Weiter an der Oberfläche getüftelt
Some checks failed
Host-Based Deploy (Java 21 Fix) / build-and-run (push) Has been cancelled
Some checks failed
Host-Based Deploy (Java 21 Fix) / build-and-run (push) Has been cancelled
This commit is contained in:
243
src/main/resources/static/js/section-nav.js
Normal file
243
src/main/resources/static/js/section-nav.js
Normal file
@@ -0,0 +1,243 @@
|
||||
(function () {
|
||||
const path = window.location.pathname;
|
||||
const search = window.location.search;
|
||||
const I = window.IC || function () { return ''; };
|
||||
|
||||
// ── Bereichs-Definitionen ────────────────────────────────────────────────
|
||||
const SECTIONS = {
|
||||
social: {
|
||||
prefixes: ['/community/'],
|
||||
exclude: [
|
||||
'/community/nachrichten.html',
|
||||
'/community/benachrichtigungen.html',
|
||||
'/community/einladungen.html',
|
||||
],
|
||||
items: [
|
||||
{ href: '/community/feed.html', icon: 'FEED', label: 'Feed' },
|
||||
{ href: '/community/freunde.html', icon: 'FRIENDS', label: 'Freunde' },
|
||||
{ href: '/community/gruppen.html', icon: 'GROUPS', label: 'Gruppen' },
|
||||
{ href: '/community/locations.html', icon: 'LOCATION', label: 'Locations' },
|
||||
{ href: '/community/events.html', icon: 'EVENT', label: 'Veranstaltungen' },
|
||||
],
|
||||
},
|
||||
dating: {
|
||||
prefixes: ['/dating/'],
|
||||
items: [
|
||||
{ href: '/dating/dating.html', icon: 'DATING', label: 'Dating', id: 'snavDatingLink' },
|
||||
{ href: '/dating/besucher.html', icon: '', label: 'Besucher' },
|
||||
{ href: '/dating/likes.html', icon: '', label: 'Likes' },
|
||||
{ href: '/dating/matches.html', icon: '', label: 'Matches' },
|
||||
],
|
||||
},
|
||||
vanilla: {
|
||||
prefixes: ['/games/vanilla/'],
|
||||
items: [
|
||||
{ href: '/games/vanilla/neuvanilla.html', icon: 'PLAY_NEW', label: 'Neue Session', id: 'snavVanillaNeu' },
|
||||
{ href: '#', icon: 'WAITING', label: 'Aktive Session', id: 'snavVanillaAktiv', hidden: true },
|
||||
{ href: '/games/vanilla/vanillaingame.html', icon: 'PLAY_ACTIVE', label: 'Im Spiel', id: 'snavVanillaImSpiel', hidden: true },
|
||||
{ href: '/games/vanilla/aufgaben.html', icon: 'CHECK', label: 'Aufgaben' },
|
||||
{ href: '/games/vanilla/toys.html', icon: 'TOYS', label: 'Toys' },
|
||||
{ href: '/games/vanilla/entdecken.html', icon: 'DISCOVER', label: 'Entdecken' },
|
||||
],
|
||||
},
|
||||
bdsm: {
|
||||
prefixes: ['/games/bdsm/'],
|
||||
items: [
|
||||
{ href: '/games/bdsm/neubdsm.html', icon: 'PLAY_NEW', label: 'Neue Session', id: 'snavBdsmNeu' },
|
||||
{ href: '#', icon: 'WAITING', label: 'Aktive Session', id: 'snavBdsmAktiv', hidden: true },
|
||||
{ href: '/games/bdsm/bdsmingame.html', icon: 'PLAY_ACTIVE', label: 'Im Spiel', id: 'snavBdsmImSpiel', hidden: true },
|
||||
{ href: '/games/bdsm/aufgaben.html', icon: 'CHECK', label: 'Aufgaben' },
|
||||
{ href: '/games/bdsm/toys.html', icon: 'TOYS', label: 'Toys' },
|
||||
{ href: '/games/bdsm/entdecken.html', icon: 'DISCOVER', label: 'Entdecken' },
|
||||
],
|
||||
},
|
||||
chastity: {
|
||||
prefixes: ['/games/chastity/'],
|
||||
items: [
|
||||
{ href: '/games/chastity/neulock.html', icon: 'NEW_LOCK', label: 'Neues Lock', id: 'snavChastityNeu' },
|
||||
{ href: '#', icon: 'ACTIVE_LOCK', label: 'Aktives Lock', id: 'snavChastityAktiv', hidden: true },
|
||||
{ href: '/games/chastity/communityvotes.html', icon: 'VOTES', label: 'Community Votes' },
|
||||
{ href: '/games/chastity/meine-locks.html', icon: 'LOCK', label: 'Meine Vorlagen' },
|
||||
{ href: '/games/chastity/entdecken-vorlagen.html', icon: 'DISCOVER', label: 'Entdecken' },
|
||||
{ href: '/games/chastity/keyholder-finden.html', icon: 'FRIENDS', label: 'Keyholder finden' },
|
||||
{ href: '/games/chastity/keyholder.html', icon: 'KEY', label: 'Keyholder' },
|
||||
{ href: '/games/chastity/unlock-history.html', icon: 'HISTORY', label: 'Code-Historie' },
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
// ── Aktiven Bereich ermitteln ────────────────────────────────────────────
|
||||
const sectionKey = Object.keys(SECTIONS).find(k => {
|
||||
const s = SECTIONS[k];
|
||||
if (!s.prefixes.some(p => path.startsWith(p))) return false;
|
||||
if (s.exclude && s.exclude.includes(path)) return false;
|
||||
return true;
|
||||
});
|
||||
if (!sectionKey) return;
|
||||
const section = SECTIONS[sectionKey];
|
||||
|
||||
// ── CSS ──────────────────────────────────────────────────────────────────
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
.section-nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.15rem;
|
||||
flex-wrap: wrap;
|
||||
padding: 0 0 0.6rem 0;
|
||||
}
|
||||
.section-nav-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
padding: 0.3rem 0.75rem;
|
||||
border-radius: 7px;
|
||||
text-decoration: none;
|
||||
color: var(--color-muted);
|
||||
font-size: 0.85rem;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
transition: background 0.12s, color 0.12s;
|
||||
}
|
||||
.section-nav-link:hover {
|
||||
background: var(--color-secondary);
|
||||
color: var(--color-text);
|
||||
}
|
||||
.section-nav-link.active {
|
||||
color: var(--color-primary);
|
||||
background: rgba(var(--color-primary-rgb, 233,69,96), 0.09);
|
||||
font-weight: 600;
|
||||
}
|
||||
.section-nav-icon {
|
||||
font-size: 0.9rem;
|
||||
line-height: 1;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.section-nav--icons-only .section-nav-label { display: none; }
|
||||
.section-nav--icons-only .section-nav-link { gap: 0; padding: 0.3rem 0.55rem; }
|
||||
.section-nav-sep {
|
||||
border: none;
|
||||
border-top: 1px solid var(--color-secondary);
|
||||
margin: 0 0 1.25rem 0;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
// ── Aktiv-Erkennung ──────────────────────────────────────────────────────
|
||||
function isActive(item) {
|
||||
if (item.href === '#') return false;
|
||||
const [itemPath, itemQuery] = item.href.split('?');
|
||||
if (itemQuery) return path === itemPath && search === '?' + itemQuery;
|
||||
return path === itemPath;
|
||||
}
|
||||
|
||||
// ── Nav bauen ────────────────────────────────────────────────────────────
|
||||
const navEl = document.createElement('nav');
|
||||
navEl.className = 'section-nav';
|
||||
|
||||
section.items.forEach(item => {
|
||||
const a = document.createElement('a');
|
||||
a.href = item.href;
|
||||
a.className = 'section-nav-link' + (isActive(item) ? ' active' : '');
|
||||
if (item.id) a.id = item.id;
|
||||
if (item.hidden) a.style.display = 'none';
|
||||
a.title = item.label;
|
||||
if (item.icon) a.innerHTML += `<span class="section-nav-icon">${I(item.icon) || ''}</span>`;
|
||||
a.innerHTML += `<span class="section-nav-label">${item.label}</span>`;
|
||||
navEl.appendChild(a);
|
||||
});
|
||||
|
||||
const sep = document.createElement('hr');
|
||||
sep.className = 'section-nav-sep';
|
||||
|
||||
// ── Einfügen in .main ────────────────────────────────────────────────────
|
||||
function checkOverflow() {
|
||||
// Immer zuerst Labels einblenden und ohne wrap messen —
|
||||
// so gibt es keine Feedback-Schleife durch Größenänderung nach dem Umschalten
|
||||
navEl.classList.remove('section-nav--icons-only');
|
||||
navEl.style.flexWrap = 'nowrap';
|
||||
const overflows = navEl.scrollWidth > navEl.clientWidth;
|
||||
navEl.style.flexWrap = '';
|
||||
if (overflows) navEl.classList.add('section-nav--icons-only');
|
||||
}
|
||||
|
||||
function inject() {
|
||||
const main = document.querySelector('.main');
|
||||
if (!main) { setTimeout(inject, 30); return; }
|
||||
main.insertBefore(sep, main.firstChild);
|
||||
main.insertBefore(navEl, sep);
|
||||
loadDynamic();
|
||||
// Overflow-Erkennung beim Laden und bei Größenänderung
|
||||
requestAnimationFrame(checkOverflow);
|
||||
new ResizeObserver(checkOverflow).observe(navEl);
|
||||
}
|
||||
inject();
|
||||
|
||||
// ── Dynamische Elemente (analog nav.js) ──────────────────────────────────
|
||||
function hide(id) { const el = document.getElementById(id); if (el) el.style.display = 'none'; }
|
||||
function show(id) { const el = document.getElementById(id); if (el) el.style.display = ''; }
|
||||
function setHref(id, h) { const el = document.getElementById(id); if (el) el.href = h; }
|
||||
|
||||
async function loadDynamic() {
|
||||
try {
|
||||
const res = await fetch('/login/me');
|
||||
if (!res.ok) return;
|
||||
const user = await res.json();
|
||||
if (!user) return;
|
||||
|
||||
// Dating-Link
|
||||
const datingLink = document.getElementById('snavDatingLink');
|
||||
if (datingLink) {
|
||||
datingLink.href = user.datingAktiv
|
||||
? '/dating/dating.html'
|
||||
: '/konto/einstellungen.html#sec-dating';
|
||||
}
|
||||
|
||||
// BDSM
|
||||
if (sectionKey === 'bdsm') {
|
||||
try {
|
||||
const r = await fetch('/bdsm/einladung/meine-aktive');
|
||||
if (r.ok) {
|
||||
const aktiv = await r.json();
|
||||
hide('snavBdsmNeu'); hide('snavBdsmImSpiel');
|
||||
show('snavBdsmAktiv');
|
||||
setHref('snavBdsmAktiv', aktiv.sessionId ? '/games/bdsm/bdsmingame.html' : '/games/bdsm/neubdsm.html');
|
||||
} else {
|
||||
const sr = await fetch(`/bdsm?userId=${user.userId}`);
|
||||
if (sr.status === 200) { hide('snavBdsmNeu'); show('snavBdsmImSpiel'); }
|
||||
else show('snavBdsmNeu');
|
||||
}
|
||||
} catch (_) { show('snavBdsmNeu'); }
|
||||
}
|
||||
|
||||
// Vanilla
|
||||
if (sectionKey === 'vanilla') {
|
||||
try {
|
||||
const r = await fetch('/vanilla/einladung/meine-aktive');
|
||||
if (r.ok) {
|
||||
const aktiv = await r.json();
|
||||
hide('snavVanillaNeu'); hide('snavVanillaImSpiel');
|
||||
show('snavVanillaAktiv');
|
||||
setHref('snavVanillaAktiv', aktiv.sessionId ? '/games/vanilla/vanillaingame.html' : '/games/vanilla/neuvanilla.html');
|
||||
} else {
|
||||
const sr = await fetch(`/vanilla?userId=${user.userId}`);
|
||||
if (sr.status === 200) { hide('snavVanillaNeu'); show('snavVanillaImSpiel'); }
|
||||
else show('snavVanillaNeu');
|
||||
}
|
||||
} catch (_) { show('snavVanillaNeu'); }
|
||||
}
|
||||
|
||||
// Chastity
|
||||
if (sectionKey === 'chastity') {
|
||||
try {
|
||||
const r = await fetch('/keyholder/mylock');
|
||||
if (r.ok) {
|
||||
const lock = await r.json();
|
||||
show('snavChastityAktiv');
|
||||
setHref('snavChastityAktiv', '/games/chastity/activelock.html?lockId=' + lock.lockId);
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user