Some checks failed
Host-Based Deploy (Java 21 Fix) / build-and-run (push) Has been cancelled
466 lines
24 KiB
JavaScript
466 lines
24 KiB
JavaScript
(function () {
|
|
if (document.querySelector('.topbar')) return;
|
|
|
|
function esc(s) {
|
|
return String(s ?? '')
|
|
.replace(/&/g, '&').replace(/</g, '<')
|
|
.replace(/>/g, '>').replace(/"/g, '"');
|
|
}
|
|
|
|
// ── Warten bis app-wrapper existiert (sidebar.js läuft synchron davor) ──
|
|
function init() {
|
|
const appWrapper = document.querySelector('.app-wrapper');
|
|
if (!appWrapper) { setTimeout(init, 30); return; }
|
|
injectHTML(appWrapper);
|
|
loadProfile();
|
|
setupSearch();
|
|
setupOverlayButtons();
|
|
loadInitialBadges();
|
|
}
|
|
setTimeout(init, 0);
|
|
|
|
// ── HTML Struktur ──
|
|
function injectHTML(appWrapper) {
|
|
const topbar = document.createElement('div');
|
|
topbar.className = 'topbar';
|
|
topbar.id = 'topbar';
|
|
topbar.innerHTML = `
|
|
<div class="topbar-left">
|
|
<a href="/userhome.html"><img class="topbar-banner" src="/img/banner.png" alt="xXx Sphere"></a>
|
|
</div>
|
|
<div class="topbar-search-wrap">
|
|
<span class="topbar-search-icon">${IC('SEARCH')}</span>
|
|
<input type="text" id="topbarSearchInput" placeholder="Suchen…" autocomplete="off" spellcheck="false">
|
|
<div class="topbar-search-overlay" id="topbarSearchOverlay"></div>
|
|
</div>
|
|
<div class="topbar-right">
|
|
<button class="topbar-btn" id="topbarMsgBtn" title="Nachrichten">
|
|
${IC('MESSAGES')}
|
|
<span class="topbar-badge" id="topbarMsgBadge"></span>
|
|
</button>
|
|
<button class="topbar-btn" id="topbarNotifBtn" title="Benachrichtigungen">
|
|
${IC('NOTIFICATIONS')}
|
|
<span class="topbar-badge" id="topbarNotifBadge"></span>
|
|
</button>
|
|
<button class="topbar-btn" id="topbarInvBtn" title="Einladungen">
|
|
${IC('INVITATIONS')}
|
|
<span class="topbar-badge" id="topbarInvBadge"></span>
|
|
</button>
|
|
<button class="topbar-btn topbar-profile-btn" id="topbarProfileBtn">
|
|
<span class="topbar-avatar-placeholder" id="topbarAvatarWrap">${IC('PROFILE')}</span>
|
|
<span class="topbar-username" id="topbarUsername">…</span>
|
|
</button>
|
|
</div>`;
|
|
appWrapper.insertAdjacentElement('beforebegin', topbar);
|
|
|
|
// Panel-Overlays am Ende von body einfügen
|
|
document.body.insertAdjacentHTML('beforeend', `
|
|
<div class="topbar-panel" id="topbarMsgPanel">
|
|
<div class="topbar-panel-header">
|
|
<span>${IC('MESSAGES')} Nachrichten</span>
|
|
<button class="topbar-panel-close" onclick="window.__topbarCloseAll()">✕</button>
|
|
</div>
|
|
<div class="topbar-panel-body" id="topbarMsgBody"></div>
|
|
<div class="topbar-panel-footer"><a href="/community/nachrichten.html">Alle Nachrichten →</a></div>
|
|
</div>
|
|
|
|
<div class="topbar-panel" id="topbarNotifPanel">
|
|
<div class="topbar-panel-header">
|
|
<span>${IC('NOTIFICATIONS')} Benachrichtigungen</span>
|
|
<button class="topbar-panel-close" onclick="window.__topbarCloseAll()">✕</button>
|
|
</div>
|
|
<div class="topbar-panel-body" id="topbarNotifBody"></div>
|
|
<div class="topbar-panel-footer"><a href="/community/benachrichtigungen.html">Alle anzeigen →</a></div>
|
|
</div>
|
|
|
|
<div class="topbar-panel" id="topbarInvPanel">
|
|
<div class="topbar-panel-header">
|
|
<span>${IC('INVITATIONS')} Einladungen</span>
|
|
<button class="topbar-panel-close" onclick="window.__topbarCloseAll()">✕</button>
|
|
</div>
|
|
<div class="topbar-panel-body" id="topbarInvBody"></div>
|
|
<div class="topbar-panel-footer"><a href="/games/common/einladungen.html">Alle anzeigen →</a></div>
|
|
</div>
|
|
|
|
<div class="topbar-panel" id="topbarProfilePanel">
|
|
<div class="topbar-panel-header">
|
|
<span>Konto</span>
|
|
<button class="topbar-panel-close" onclick="window.__topbarCloseAll()">✕</button>
|
|
</div>
|
|
<div class="topbar-panel-body topbar-profile-body">
|
|
<div class="topbar-profile-card">
|
|
<span id="topbarPanelAvatarWrap" style="font-size:2.5rem;line-height:1;">${IC('PROFILE')}</span>
|
|
<div>
|
|
<div id="topbarPanelName" style="font-weight:700;font-size:1rem;"></div>
|
|
</div>
|
|
</div>
|
|
<hr style="border:none;border-top:1px solid var(--color-secondary);margin:0;">
|
|
<nav class="topbar-profile-nav">
|
|
<a id="topbarProfileLink" href="/community/benutzer.html" class="topbar-profile-link">
|
|
<span>${IC('PROFILE')}</span> Mein Profil
|
|
</a>
|
|
<a href="/konto/einstellungen.html" class="topbar-profile-link">
|
|
<span>${IC('SETTINGS')}</span> Einstellungen
|
|
</a>
|
|
<a href="/help/overview.html" class="topbar-profile-link">
|
|
<span>${IC('HELP')}</span> Hilfe
|
|
</a>
|
|
<hr style="border:none;border-top:1px solid var(--color-secondary);margin:0;">
|
|
<a href="/login/logout" class="topbar-profile-link topbar-profile-link--danger">
|
|
<span>${IC('LOGOUT')}</span> Abmelden
|
|
</a>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
`);
|
|
}
|
|
|
|
function IC(key) { return window.IC ? window.IC(key) : (window.ICONS?.[key]?.value || ''); }
|
|
|
|
// ── Profil laden ──
|
|
function loadProfile() {
|
|
fetch('/login/me')
|
|
.then(r => r.ok ? r.json() : null)
|
|
.then(user => {
|
|
if (!user) return;
|
|
const nameEl = document.getElementById('topbarUsername');
|
|
if (nameEl) nameEl.textContent = user.name;
|
|
|
|
const avatarWrap = document.getElementById('topbarAvatarWrap');
|
|
if (avatarWrap && user.profilePicture) {
|
|
avatarWrap.innerHTML = `<img src="data:image/png;base64,${user.profilePicture}" class="topbar-avatar" alt="">`;
|
|
}
|
|
const panelName = document.getElementById('topbarPanelName');
|
|
if (panelName) panelName.textContent = user.name;
|
|
|
|
const panelAvatar = document.getElementById('topbarPanelAvatarWrap');
|
|
if (panelAvatar && user.profilePicture) {
|
|
panelAvatar.innerHTML = `<img src="data:image/png;base64,${user.profilePicture}" style="width:3rem;height:3rem;border-radius:50%;object-fit:cover;" alt="">`;
|
|
}
|
|
const profileLink = document.getElementById('topbarProfileLink');
|
|
if (profileLink && user.userId) profileLink.href = '/community/benutzer.html?userId=' + user.userId;
|
|
})
|
|
.catch(() => {});
|
|
}
|
|
|
|
// ── Suche ──
|
|
function setupSearch() {
|
|
const input = document.getElementById('topbarSearchInput');
|
|
const overlay = document.getElementById('topbarSearchOverlay');
|
|
if (!input || !overlay) return;
|
|
|
|
let timer;
|
|
input.addEventListener('input', () => {
|
|
clearTimeout(timer);
|
|
const q = input.value.trim();
|
|
if (q.length < 2) { overlay.innerHTML = ''; overlay.classList.remove('open'); return; }
|
|
overlay.innerHTML = '<div class="topbar-search-hint">Suche…</div>';
|
|
overlay.classList.add('open');
|
|
timer = setTimeout(() => doSearch(q, overlay), 300);
|
|
});
|
|
|
|
document.addEventListener('click', e => {
|
|
if (!e.target.closest('.topbar-search-wrap')) {
|
|
overlay.classList.remove('open');
|
|
}
|
|
});
|
|
}
|
|
|
|
async function doSearch(q, overlay) {
|
|
try {
|
|
const tagQuery = q.startsWith('#') ? q.slice(1) : q;
|
|
const [searchRes, gruppenRes, hashtagRes] = await Promise.all([
|
|
fetch('/search?q=' + encodeURIComponent(q) + '&limit=3'),
|
|
fetch('/gruppen/search?q=' + encodeURIComponent(q)),
|
|
fetch('/hashtags/suggest?q=' + encodeURIComponent(tagQuery) + '&limit=4')
|
|
]);
|
|
|
|
const data = searchRes.ok ? await searchRes.json() : {};
|
|
const gruppen = gruppenRes.ok ? await gruppenRes.json() : [];
|
|
const hashtags = hashtagRes.ok ? await hashtagRes.json() : [];
|
|
|
|
const { users = [], locations = [], events = [] } = data;
|
|
const gruppenSlice = gruppen.slice(0, 3);
|
|
|
|
let html = '';
|
|
|
|
if (!users.length && !locations.length && !events.length && !gruppenSlice.length && !hashtags.length) {
|
|
html += '<div class="topbar-search-hint">Keine Ergebnisse.</div>';
|
|
}
|
|
|
|
if (users.length) {
|
|
html += `<div class="topbar-search-section">Personen</div>`;
|
|
html += users.map(u => {
|
|
const av = u.profilePicture
|
|
? `<img src="data:image/png;base64,${esc(u.profilePicture)}" class="topbar-search-avatar" alt="">`
|
|
: `<span class="topbar-search-avatar topbar-search-avatar--placeholder">${IC('PROFILE')}</span>`;
|
|
return `<a href="/community/benutzer.html?userId=${esc(u.userId)}" class="topbar-search-result">
|
|
${av}<span>${esc(u.name)}</span></a>`;
|
|
}).join('');
|
|
}
|
|
|
|
if (locations.length) {
|
|
html += `<div class="topbar-search-section">Locations</div>`;
|
|
html += locations.map(l => {
|
|
const av = l.profilePicture
|
|
? `<img src="data:image/png;base64,${esc(l.profilePicture)}" class="topbar-search-avatar" alt="">`
|
|
: `<span class="topbar-search-avatar topbar-search-avatar--placeholder">📍</span>`;
|
|
return `<a href="/community/location-detail.html?id=${esc(l.locationId)}" class="topbar-search-result">
|
|
${av}<span>${esc(l.name)}</span></a>`;
|
|
}).join('');
|
|
}
|
|
|
|
if (events.length) {
|
|
html += `<div class="topbar-search-section">Veranstaltungen</div>`;
|
|
html += events.map(e => {
|
|
const av = e.imageData
|
|
? `<img src="${esc(e.imageData)}" class="topbar-search-avatar" alt="">`
|
|
: `<span class="topbar-search-avatar topbar-search-avatar--placeholder">🗓</span>`;
|
|
return `<a href="/community/event-detail.html?eventId=${esc(e.eventId)}" class="topbar-search-result">
|
|
${av}<span>${esc(e.title)}</span></a>`;
|
|
}).join('');
|
|
}
|
|
|
|
if (gruppenSlice.length) {
|
|
html += `<div class="topbar-search-section">Gruppen</div>`;
|
|
html += gruppenSlice.map(g => {
|
|
const av = g.bild
|
|
? `<img src="data:image/jpeg;base64,${esc(g.bild)}" class="topbar-search-avatar" alt="">`
|
|
: `<span class="topbar-search-avatar topbar-search-avatar--placeholder">👥</span>`;
|
|
return `<a href="/community/gruppe.html?gruppeId=${esc(g.gruppeId)}" class="topbar-search-result">
|
|
${av}<span>${esc(g.name)}</span></a>`;
|
|
}).join('');
|
|
}
|
|
|
|
if (hashtags.length) {
|
|
html += `<div class="topbar-search-section">Hashtags</div>`;
|
|
html += `<div style="display:flex;flex-wrap:wrap;gap:0.4rem;padding:0.4rem 0.75rem;">`;
|
|
html += hashtags.map(tag =>
|
|
`<a href="/community/feed.html?tag=${encodeURIComponent(tag)}" style="display:inline-block;padding:0.25rem 0.65rem;background:var(--color-secondary);border-radius:14px;font-size:0.82rem;font-weight:600;color:var(--color-primary);text-decoration:none;">#${esc(tag)}</a>`
|
|
).join('');
|
|
html += `</div>`;
|
|
}
|
|
|
|
html += `<a href="/search.html?q=${encodeURIComponent(q)}" class="topbar-search-all">Alle Ergebnisse anzeigen →</a>`;
|
|
overlay.innerHTML = html;
|
|
} catch (e) {
|
|
overlay.innerHTML = '<div class="topbar-search-hint">Fehler bei der Suche.</div>';
|
|
}
|
|
}
|
|
|
|
// ── Panel-Overlays ──
|
|
let _activePanel = null;
|
|
|
|
function positionPanel(panel, btn) {
|
|
const topbar = document.getElementById('topbar');
|
|
const tRect = topbar ? topbar.getBoundingClientRect() : btn.getBoundingClientRect();
|
|
panel.style.top = tRect.bottom + 'px';
|
|
panel.style.right = Math.max(4, window.innerWidth - tRect.right) + 'px';
|
|
panel.style.left = 'auto';
|
|
}
|
|
|
|
function openPanel(panelId, btnId, loadFn) {
|
|
const panel = document.getElementById(panelId);
|
|
const btn = document.getElementById(btnId);
|
|
if (!panel || !btn) return;
|
|
if (_activePanel === panel && panel.classList.contains('open')) {
|
|
closeAllPanels(); return;
|
|
}
|
|
if (window.__navClose) window.__navClose();
|
|
closeAllPanels();
|
|
positionPanel(panel, btn);
|
|
panel.classList.add('open');
|
|
_activePanel = panel;
|
|
if (loadFn) loadFn();
|
|
}
|
|
|
|
function closeAllPanels() {
|
|
document.querySelectorAll('.topbar-panel.open').forEach(p => p.classList.remove('open'));
|
|
_activePanel = null;
|
|
}
|
|
|
|
window.__topbarCloseAll = closeAllPanels;
|
|
|
|
document.addEventListener('click', e => {
|
|
if (!e.target.closest('.topbar-panel') && !e.target.closest('.topbar-btn'))
|
|
closeAllPanels();
|
|
});
|
|
document.addEventListener('keydown', e => { if (e.key === 'Escape') closeAllPanels(); });
|
|
|
|
function setupOverlayButtons() {
|
|
const msgBtn = document.getElementById('topbarMsgBtn');
|
|
const notifBtn = document.getElementById('topbarNotifBtn');
|
|
const invBtn = document.getElementById('topbarInvBtn');
|
|
const profileBtn = document.getElementById('topbarProfileBtn');
|
|
if (msgBtn) msgBtn.addEventListener('click', e => { e.stopPropagation(); openPanel('topbarMsgPanel', 'topbarMsgBtn', loadMessages); });
|
|
if (notifBtn) notifBtn.addEventListener('click', e => { e.stopPropagation(); openPanel('topbarNotifPanel', 'topbarNotifBtn', loadNotifications); });
|
|
if (invBtn) invBtn.addEventListener('click', e => { e.stopPropagation(); openPanel('topbarInvPanel', 'topbarInvBtn', loadInvitations); });
|
|
if (profileBtn) profileBtn.addEventListener('click', e => { e.stopPropagation(); openPanel('topbarProfilePanel', 'topbarProfileBtn', null); });
|
|
}
|
|
|
|
// ── Nachrichten ──
|
|
async function loadMessages() {
|
|
const body = document.getElementById('topbarMsgBody');
|
|
if (!body) return;
|
|
body.innerHTML = '<div class="topbar-panel-hint">Wird geladen…</div>';
|
|
try {
|
|
const res = await fetch('/social/messages');
|
|
if (!res.ok) { body.innerHTML = '<div class="topbar-panel-hint">Keine Nachrichten.</div>'; return; }
|
|
const convos = await res.json();
|
|
if (!convos.length) { body.innerHTML = '<div class="topbar-panel-hint">Noch keine Nachrichten.</div>'; return; }
|
|
body.innerHTML = convos.slice(0, 7).map(c => {
|
|
const av = c.partner?.profilePicture
|
|
? `<img src="data:image/png;base64,${esc(c.partner.profilePicture)}" class="topbar-item-avatar" alt="">`
|
|
: `<span class="topbar-item-avatar topbar-item-avatar--placeholder">${IC('PROFILE')}</span>`;
|
|
const bold = c.unreadCount > 0 ? 'font-weight:700;' : '';
|
|
const badge = c.unreadCount > 0
|
|
? `<span class="topbar-item-badge">${c.unreadCount > 99 ? '99+' : c.unreadCount}</span>` : '';
|
|
return `<a href="/community/nachrichten.html?userId=${esc(c.partner?.userId)}" class="topbar-panel-item">
|
|
${av}
|
|
<div class="topbar-panel-item-body">
|
|
<div style="${bold}font-size:0.88rem;">${esc(c.partner?.name || '')}</div>
|
|
<div class="topbar-panel-item-sub">${esc(c.lastMessage?.text || '')}</div>
|
|
</div>
|
|
${badge}
|
|
</a>`;
|
|
}).join('');
|
|
} catch (e) { body.innerHTML = '<div class="topbar-panel-hint">Fehler beim Laden.</div>'; }
|
|
}
|
|
|
|
// ── Benachrichtigungen ──
|
|
async function loadNotifications() {
|
|
const body = document.getElementById('topbarNotifBody');
|
|
if (!body) return;
|
|
body.innerHTML = '<div class="topbar-panel-hint">Wird geladen…</div>';
|
|
try {
|
|
const res = await fetch('/notifications');
|
|
if (!res.ok) { body.innerHTML = '<div class="topbar-panel-hint">Keine Benachrichtigungen.</div>'; return; }
|
|
const unread = (await res.json()).filter(n => !n.read);
|
|
if (!unread.length) { body.innerHTML = '<div class="topbar-panel-hint">Keine neuen Benachrichtigungen.</div>'; return; }
|
|
body.innerHTML = '';
|
|
unread.forEach(n => {
|
|
const el = document.createElement('div');
|
|
const tag = n.targetUrl ? 'a' : 'div';
|
|
const href = n.targetUrl ? `href="${esc(n.targetUrl)}"` : '';
|
|
const av = n.senderAvatar
|
|
? `<img src="data:image/png;base64,${esc(n.senderAvatar)}" class="topbar-item-avatar" alt="">`
|
|
: `<span class="topbar-item-avatar topbar-item-avatar--placeholder">${IC('PROFILE')}</span>`;
|
|
el.innerHTML = `<${tag} ${href} class="topbar-panel-item topbar-notif-item${n.read ? '' : ' topbar-notif-item--unread'}">
|
|
${av}
|
|
<div class="topbar-panel-item-body">
|
|
<div style="font-size:0.85rem;line-height:1.4;">${esc(n.text)}</div>
|
|
<div class="topbar-panel-item-sub">${n.sentAt ? new Date(n.sentAt).toLocaleString('de-DE',{dateStyle:'short',timeStyle:'short'}) : ''}</div>
|
|
</div>
|
|
</${tag}>`;
|
|
body.appendChild(el.firstElementChild);
|
|
});
|
|
// Alle als gelesen markieren
|
|
fetch('/notifications/read-all', { method: 'POST' }).then(() => setTopbarBadge('notif', 0)).catch(() => {});
|
|
} catch (e) { body.innerHTML = '<div class="topbar-panel-hint">Fehler beim Laden.</div>'; }
|
|
}
|
|
|
|
window.__topbarMarkNotifRead = async function (id) {
|
|
try {
|
|
await fetch('/notifications/' + id + '/read', { method: 'POST' });
|
|
const el = document.querySelector(`.topbar-notif-item--unread[onclick*="${id}"]`);
|
|
if (el) el.classList.remove('topbar-notif-item--unread');
|
|
const r = await fetch('/notifications/unread/count');
|
|
if (r.ok) setTopbarBadge('notif', await r.json());
|
|
} catch (e) {}
|
|
};
|
|
|
|
window.__topbarMarkAllRead = async function () {
|
|
try {
|
|
await fetch('/notifications/read-all', { method: 'POST' });
|
|
setTopbarBadge('notif', 0);
|
|
loadNotifications();
|
|
} catch (e) {}
|
|
};
|
|
|
|
// ── Einladungen ──
|
|
async function loadInvitations() {
|
|
const body = document.getElementById('topbarInvBody');
|
|
if (!body) return;
|
|
body.innerHTML = '<div class="topbar-panel-hint">Wird geladen…</div>';
|
|
try {
|
|
const [lr, kr, br, vr] = await Promise.all([
|
|
fetch('/lockee/invitations/mine'),
|
|
fetch('/keyholder/invitations/mine'),
|
|
fetch('/bdsm/einladung/pending'),
|
|
fetch('/vanilla/einladung/pending')
|
|
]);
|
|
const lockee = lr.ok ? await lr.json() : [];
|
|
const kh = kr.ok ? await kr.json() : [];
|
|
const bdsm = br.ok ? await br.json() : [];
|
|
const vanilla = vr.ok ? await vr.json() : [];
|
|
const all = [
|
|
...lockee.map(i => ({ ...i, _type: 'lockee' })),
|
|
...kh.map(i => ({ ...i, _type: 'keyholder' })),
|
|
...bdsm.map(i => ({ ...i, _type: 'bdsm' })),
|
|
...vanilla.map(i => ({ ...i, _type: 'vanilla' }))
|
|
];
|
|
if (!all.length) { body.innerHTML = '<div class="topbar-panel-hint">Keine offenen Einladungen.</div>'; return; }
|
|
body.innerHTML = '';
|
|
all.forEach(inv => body.appendChild(buildInvCard(inv)));
|
|
} catch (e) { body.innerHTML = '<div class="topbar-panel-hint">Fehler beim Laden.</div>'; }
|
|
}
|
|
|
|
function buildInvCard(inv) {
|
|
let typeIcon, typeName, line;
|
|
|
|
if (inv._type === 'lockee') {
|
|
typeIcon = IC('LOCK'); typeName = 'Lockee-Einladung'; line = inv.lockName || 'Lock';
|
|
} else if (inv._type === 'keyholder') {
|
|
typeIcon = IC('KEY'); typeName = 'Keyholder-Einladung'; line = inv.lockName || 'Lock';
|
|
} else if (inv._type === 'vanilla') {
|
|
typeIcon = IC('INVITATIONS'); typeName = 'Vanilla Game'; line = inv.inviterName || 'Einladung';
|
|
} else {
|
|
typeIcon = IC('BDSM'); typeName = 'BDSM Game'; line = inv.senderName || 'Einladung';
|
|
}
|
|
|
|
const senderPic = inv.senderAvatar || inv.lockOwnerAvatar || inv.inviterAvatar;
|
|
const av = senderPic
|
|
? `<img src="data:image/png;base64,${esc(senderPic)}" class="topbar-item-avatar" alt="">`
|
|
: `<span class="topbar-item-avatar topbar-item-avatar--placeholder">${IC('PROFILE')}</span>`;
|
|
|
|
const div = document.createElement('div');
|
|
div.className = 'topbar-panel-item topbar-inv-card';
|
|
div.style.cursor = 'pointer';
|
|
div.innerHTML = `${av}
|
|
<div class="topbar-panel-item-body">
|
|
<div class="topbar-panel-item-sub">${typeIcon} ${typeName}</div>
|
|
<div style="font-weight:600;font-size:0.88rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">${esc(line)}</div>
|
|
</div>`;
|
|
div.addEventListener('click', () => { window.location.href = '/games/common/einladungen.html'; });
|
|
return div;
|
|
}
|
|
|
|
// ── Badge-Verwaltung ──
|
|
function setTopbarBadge(type, count) {
|
|
const map = { msg: 'topbarMsgBadge', notif: 'topbarNotifBadge', inv: 'topbarInvBadge' };
|
|
const el = document.getElementById(map[type]);
|
|
if (!el) return;
|
|
el.textContent = count > 99 ? '99+' : count;
|
|
el.style.display = count > 0 ? 'inline-block' : 'none';
|
|
}
|
|
|
|
// Für social-sidebar.js zugänglich
|
|
window.__topbarSetBadge = setTopbarBadge;
|
|
|
|
function reloadInvBadge() {
|
|
Promise.all([
|
|
fetch('/lockee/invitations/mine/count').then(r => r.ok ? r.json() : 0).catch(() => 0),
|
|
fetch('/keyholder/invitations/mine/count').then(r => r.ok ? r.json() : 0).catch(() => 0),
|
|
fetch('/bdsm/einladung/pending/count').then(r => r.ok ? r.json() : 0).catch(() => 0),
|
|
fetch('/vanilla/einladung/pending/count').then(r => r.ok ? r.json() : 0).catch(() => 0)
|
|
]).then(([l, k, b, v]) => setTopbarBadge('inv', l + k + b + v)).catch(() => {});
|
|
}
|
|
window.__topbarReloadInvBadge = reloadInvBadge;
|
|
|
|
function loadInitialBadges() {
|
|
fetch('/social/messages/unread/count').then(r => r.ok ? r.json() : 0).then(n => setTopbarBadge('msg', n)).catch(() => {});
|
|
fetch('/notifications/unread/count').then(r => r.ok ? r.json() : 0).then(n => setTopbarBadge('notif', n)).catch(() => {});
|
|
reloadInvBadge();
|
|
}
|
|
})();
|