Some checks failed
Host-Based Deploy (Java 21 Fix) / build-and-run (push) Has been cancelled
265 lines
14 KiB
JavaScript
265 lines
14 KiB
JavaScript
(function () {
|
|
const path = window.location.pathname;
|
|
const I = window.IC || function() { return ''; };
|
|
|
|
const groups = [
|
|
{
|
|
label: 'Vanilla Game',
|
|
icon: I('VANILLA'),
|
|
items: [
|
|
{ href: '/games/vanilla/neuvanilla.html', icon: I('PLAY_NEW'), label: 'Neue Session', id: 'navVanillaNeu' },
|
|
{ href: '#', icon: I('WAITING'), label: 'Aktive Session', id: 'navVanillaAktiv' },
|
|
{ href: '/games/vanilla/vanillaingame.html', icon: I('PLAY_ACTIVE'), label: 'Im Spiel', id: 'navVanillaImSpiel' },
|
|
{ href: '/games/common/aufgaben.html', icon: I('CHECK'), label: 'Aufgaben' },
|
|
{ href: '/games/common/toys.html', icon: I('TOYS'), label: 'Toys' },
|
|
{ href: '/games/chastity/entdecken.html', icon: I('DISCOVER'), label: 'Entdecken' },
|
|
]
|
|
},
|
|
{
|
|
label: 'BDSM Game',
|
|
icon: I('BDSM'),
|
|
items: [
|
|
{ href: '/games/bdsm/neubdsm.html', icon: I('PLAY_NEW'), label: 'Neue Session', id: 'navBdsmNeu' },
|
|
{ href: '#', icon: I('WAITING'), label: 'Aktive Session', id: 'navBdsmAktiv' },
|
|
{ href: '/games/bdsm/bdsmingame.html', icon: I('PLAY_ACTIVE'), label: 'Im Spiel', id: 'navBdsmImSpiel' },
|
|
{ href: '/games/common/aufgaben.html?mode=bdsm', icon: I('CHECK'), label: 'Aufgaben' },
|
|
{ href: '/games/common/toys.html', icon: I('TOYS'), label: 'Toys' },
|
|
{ href: '/games/chastity/entdecken.html', icon: I('DISCOVER'), label: 'Entdecken' },
|
|
]
|
|
},
|
|
{
|
|
label: 'Chastity Game',
|
|
icon: I('CHASTITY'),
|
|
items: [
|
|
{ href: '/games/chastity/neulock.html', icon: I('NEW_LOCK'), label: 'Neues Lock', id: 'navChastityNeu' },
|
|
{ href: '#', icon: I('ACTIVE_LOCK'), label: 'Aktives Lock', id: 'navChastityAktiv' },
|
|
{ href: '/games/chastity/communityvotes.html', icon: I('VOTES'), label: 'Community Votes' },
|
|
{ href: '/games/chastity/meine-locks.html', icon: I('LOCK'), label: 'Meine Vorlagen' },
|
|
{ href: '/games/chastity/entdecken-vorlagen.html', icon: I('DISCOVER'), label: 'Entdecken' },
|
|
{ href: '/games/chastity/keyholder-finden.html', icon: I('FRIENDS'), label: 'Keyholder finden' },
|
|
{ href: '/games/chastity/keyholder.html', icon: I('KEY'), label: 'Keyholder' },
|
|
{ href: '/games/chastity/unlock-history.html', icon: I('HISTORY'), label: 'Code-Historie' },
|
|
]
|
|
},
|
|
];
|
|
|
|
|
|
// ── Community-Links (immer sichtbar, oberhalb der Spiele) ──
|
|
const socialLinks = [
|
|
{ href: '/userhome.html', icon: I('HOME') || '⌂', label: 'Home', badgeId: null },
|
|
{ href: '/community/feed.html', icon: I('FEED'), label: 'Feed', badgeId: null },
|
|
{ href: '/community/freunde.html', icon: I('FRIENDS'), label: 'Freunde', badgeId: 'socialFriendsBadge'},
|
|
{ href: '/community/nachrichten.html', icon: I('MESSAGES'), label: 'Nachrichten', badgeId: null },
|
|
{ href: '/community/benachrichtigungen.html', icon: I('NOTIFICATIONS'), label: 'Benachrichtigungen', badgeId: null },
|
|
{ href: '/community/gruppen.html', icon: I('GROUPS'), label: 'Gruppen', badgeId: 'socialGruppenBadge'},
|
|
{ href: '/games/common/einladungen.html', icon: I('INVITATIONS'), label: 'Einladungen', badgeId: null },
|
|
];
|
|
const socialNav = socialLinks.map(({ href, icon, label, badgeId }) => {
|
|
const cls = path === href ? ' class="active"' : '';
|
|
const badge = badgeId ? `<span class="social-badge" id="${badgeId}" style="display:none;"></span>` : '';
|
|
return `<li><a href="${href}"${cls}><span class="icon">${icon}</span> ${label}${badge}</a></li>`;
|
|
}).join('');
|
|
|
|
const datingActive = path === '/dating.html';
|
|
const datingCls = datingActive ? ' class="active"' : '';
|
|
const datingItem = `<li id="navDating"><a href="/konto/einstellungen.html#sec-dating"${datingCls}><span class="icon">${I('DATING') || '♥'}</span> Dating</a></li>`;
|
|
|
|
const fullHref = path + window.location.search;
|
|
const nav = groups.map(({ label, icon, items }) => {
|
|
const isOpen = items.some(item => item.href === path || item.href === fullHref);
|
|
const openCls = isOpen ? ' open' : '';
|
|
const subItems = items.map(({ href, icon: iIcon, label: iLabel, id: iId }) => {
|
|
const cls = (href === path || href === fullHref) ? ' class="active"' : '';
|
|
const idAt = iId ? ` id="${iId}"` : '';
|
|
return `<li${idAt}><a href="${href}"${cls}><span class="icon">${iIcon}</span> ${iLabel}</a></li>`;
|
|
}).join('');
|
|
return `
|
|
<li class="sidebar-group${openCls}">
|
|
<a class="sidebar-group-toggle"><span class="icon">${icon}</span> ${label}<span class="sidebar-arrow">${I('ARROW')}</span></a>
|
|
<ul class="sidebar-sub">
|
|
${subItems}
|
|
</ul>
|
|
</li>`;
|
|
}).join('');
|
|
|
|
const adminCls = path === '/admin/admin.html' ? ' class="active"' : '';
|
|
const adminItem = `<li id="navAdminLink" style="display:none"><a href="/admin/admin.html"${adminCls}><span class="icon">${I('ADMIN') || '⚙'}</span> Administration</a></li>`;
|
|
|
|
const footerLinks = [
|
|
{ href: '/help/kontakt.html', icon: '✉️', label: 'Kontakt & Feedback' },
|
|
{ href: '/help/impressum.html', icon: '📄', label: 'Impressum' },
|
|
];
|
|
const footerNav = footerLinks.map(({ href, icon, label }) => {
|
|
const cls = path === href ? ' class="active"' : '';
|
|
return `<li><a href="${href}"${cls}><span class="icon">${icon}</span> ${label}</a></li>`;
|
|
}).join('');
|
|
|
|
document.body.insertAdjacentHTML('afterbegin', `
|
|
<div class="sidebar-overlay" id="sidebarOverlay"></div>
|
|
<button class="burger" id="burgerBtn" aria-label="Menü öffnen">
|
|
<span class="burger-icon"><span></span><span></span><span></span></span>
|
|
</button>
|
|
<div class="sidebar-wrapper" id="sidebar">
|
|
<aside class="sidebar">
|
|
<div class="sidebar-scroll-area">
|
|
<ul>
|
|
${socialNav}
|
|
<li><hr style="border:none;border-top:1px solid var(--color-secondary);margin:0.4rem 1rem;"></li>
|
|
${datingItem}
|
|
<li><hr style="border:none;border-top:1px solid var(--color-secondary);margin:0.4rem 1rem;"></li>
|
|
${nav}
|
|
<li><hr style="border:none;border-top:1px solid var(--color-secondary);margin:0.4rem 1rem;" id="navAdminDivider" style="display:none"></li>
|
|
${adminItem}
|
|
</ul>
|
|
</div>
|
|
</aside>
|
|
<div class="sidebar-footer">
|
|
<ul>${footerNav}</ul>
|
|
</div>
|
|
</div>
|
|
`);
|
|
|
|
// Sidebar und .main in einen zentrierten App-Wrapper verschieben
|
|
const appWrapper = document.createElement('div');
|
|
appWrapper.className = 'app-wrapper';
|
|
const sidebarEl = document.getElementById('sidebar');
|
|
const mainEl = document.querySelector('.main');
|
|
document.body.insertBefore(appWrapper, sidebarEl);
|
|
appWrapper.appendChild(sidebarEl);
|
|
if (mainEl) appWrapper.appendChild(mainEl);
|
|
|
|
// Group toggle
|
|
document.querySelectorAll('.sidebar-group-toggle').forEach(toggle => {
|
|
toggle.addEventListener('click', e => {
|
|
e.preventDefault();
|
|
toggle.closest('.sidebar-group').classList.toggle('open');
|
|
});
|
|
});
|
|
|
|
// "Im Spiel" und "Aktive Session" standardmäßig ausblenden; wird nach Session-Check ggf. wieder eingeblendet
|
|
const navNeu = document.getElementById('navBdsmNeu');
|
|
const navAktiv = document.getElementById('navBdsmAktiv');
|
|
const navImSpiel = document.getElementById('navBdsmImSpiel');
|
|
const navCAktiv = document.getElementById('navChastityAktiv');
|
|
const navVNeu = document.getElementById('navVanillaNeu');
|
|
const navVAktiv = document.getElementById('navVanillaAktiv');
|
|
const navVImSpiel = document.getElementById('navVanillaImSpiel');
|
|
if (navAktiv) navAktiv.style.display = 'none';
|
|
if (navImSpiel) navImSpiel.style.display = 'none';
|
|
if (navCAktiv) navCAktiv.style.display = 'none';
|
|
if (navVAktiv) navVAktiv.style.display = 'none';
|
|
if (navVImSpiel) navVImSpiel.style.display = 'none';
|
|
|
|
// Session-Status prüfen
|
|
fetch('/login/me')
|
|
.then(r => r.ok ? r.json() : null)
|
|
.then(async user => {
|
|
if (!user) return;
|
|
|
|
// BDSM Session-Status
|
|
try {
|
|
const aktivRes = await fetch('/bdsm/einladung/meine-aktive');
|
|
if (aktivRes.ok) {
|
|
const aktiv = await aktivRes.json();
|
|
if (navNeu) navNeu.style.display = 'none';
|
|
if (navImSpiel) navImSpiel.style.display = 'none';
|
|
if (navAktiv) {
|
|
navAktiv.style.display = '';
|
|
navAktiv.querySelector('a').href = aktiv.sessionId ? '/games/bdsm/bdsmingame.html' : '/games/bdsm/neubdsm.html';
|
|
}
|
|
} else {
|
|
const sessionRes = await fetch(`/bdsm?userId=${user.userId}`);
|
|
const hasSession = sessionRes.status === 200;
|
|
if (navNeu) navNeu.style.display = hasSession ? 'none' : '';
|
|
if (navImSpiel) navImSpiel.style.display = hasSession ? '' : 'none';
|
|
}
|
|
} catch (_) {}
|
|
|
|
// Vanilla Session-Status
|
|
try {
|
|
const vAktivRes = await fetch('/vanilla/einladung/meine-aktive');
|
|
if (vAktivRes.ok) {
|
|
const vAktiv = await vAktivRes.json();
|
|
if (navVNeu) navVNeu.style.display = 'none';
|
|
if (navVImSpiel) navVImSpiel.style.display = 'none';
|
|
if (navVAktiv) {
|
|
navVAktiv.style.display = '';
|
|
navVAktiv.querySelector('a').href = vAktiv.sessionId ? '/games/vanilla/vanillaingame.html' : '/games/vanilla/neuvanilla.html';
|
|
}
|
|
} else {
|
|
const vSessionRes = await fetch(`/vanilla?userId=${user.userId}`);
|
|
const vHasSession = vSessionRes.status === 200;
|
|
if (navVNeu) navVNeu.style.display = vHasSession ? 'none' : '';
|
|
if (navVImSpiel) navVImSpiel.style.display = vHasSession ? '' : 'none';
|
|
}
|
|
} catch (_) {}
|
|
|
|
// Chastity Lock-Status
|
|
try {
|
|
const lockRes = await fetch('/keyholder/mylock');
|
|
if (lockRes.ok) {
|
|
const lockData = await lockRes.json();
|
|
if (navCAktiv) {
|
|
navCAktiv.style.display = '';
|
|
navCAktiv.querySelector('a').href = '/games/chastity/activelock.html?lockId=' + lockData.lockId;
|
|
}
|
|
}
|
|
} catch (_) {}
|
|
|
|
// Dating-Link
|
|
const navDating = document.getElementById('navDating');
|
|
if (navDating) {
|
|
navDating.querySelector('a').href = user.datingAktiv
|
|
? '/dating.html'
|
|
: '/konto/einstellungen.html#sec-dating';
|
|
}
|
|
|
|
// Admin-Link
|
|
if (user.admin) {
|
|
const navAdminLink = document.getElementById('navAdminLink');
|
|
const navAdminDivider = document.getElementById('navAdminDivider');
|
|
if (navAdminLink) navAdminLink.style.display = '';
|
|
if (navAdminDivider) navAdminDivider.style.display = '';
|
|
}
|
|
})
|
|
.catch(() => {});
|
|
|
|
const sidebar = document.getElementById('sidebar');
|
|
const burgerBtn = document.getElementById('burgerBtn');
|
|
const overlay = document.getElementById('sidebarOverlay');
|
|
|
|
function openMenu() {
|
|
sidebar.classList.add('open');
|
|
overlay.classList.add('visible');
|
|
burgerBtn.classList.add('open');
|
|
burgerBtn.setAttribute('aria-label', 'Menü schließen');
|
|
}
|
|
|
|
function closeMenu() {
|
|
sidebar.classList.remove('open');
|
|
overlay.classList.remove('visible');
|
|
burgerBtn.classList.remove('open');
|
|
burgerBtn.setAttribute('aria-label', 'Menü öffnen');
|
|
}
|
|
|
|
burgerBtn.addEventListener('click', () =>
|
|
sidebar.classList.contains('open') ? closeMenu() : openMenu()
|
|
);
|
|
overlay.addEventListener('click', closeMenu);
|
|
sidebar.querySelectorAll('a:not(.sidebar-group-toggle)').forEach(l =>
|
|
l.addEventListener('click', () => {
|
|
if (window.innerWidth <= (parseInt(getComputedStyle(document.documentElement).getPropertyValue('--breakpoint-mobile').trim()) || 768))
|
|
closeMenu();
|
|
})
|
|
);
|
|
|
|
// Topbar und Social-Sidebar nachladen
|
|
function loadScript(src) {
|
|
const s = document.createElement('script');
|
|
s.src = src;
|
|
document.head.appendChild(s);
|
|
}
|
|
loadScript('/js/topbar.js');
|
|
loadScript('/js/social-sidebar.js');
|
|
})();
|