import { resolveToolbarActive } from '../router.js'; import { state, authService } from '../state.js'; import { openAuthRequiredModal } from '../services/auth-required-modal.js'; import { SHINE_CONNECTIONS_LOGO_SRC } from './shine-logo.js'; // iconImg — путь к неоновой PNG (если есть, рисуем картинку вместо эмодзи); glow — цвет доп.свечения // активной/нажатой вкладки (var --tab-glow); hero — «герой»-вкладка (крупнее/ярче, всегда светится). // Пока подключена только «Связи»; остальные 4 — эмодзи до подготовки ассетов (имена подставлю). const ITEMS = [ { pageId: 'messages-list', label: 'Личные', icon: '💬', iconImg: '/assets/icon_lichnye.png', glow: 'rgba(0, 229, 255, .6)' }, { pageId: 'channels-list', label: 'Каналы', icon: '📢', iconImg: '/assets/icon_kanaly.png', glow: 'rgba(0, 229, 255, .6)' }, { pageId: 'network-view', label: 'Связи', icon: '🕸', iconImg: SHINE_CONNECTIONS_LOGO_SRC, glow: 'rgba(0, 229, 255, .6)', hero: true }, { pageId: 'notifications-view', label: 'Уведомления', icon: '🔔', iconImg: '/assets/icon_uvedomleniya.png', glow: 'rgba(0, 229, 255, .6)' }, { pageId: 'profile-view', label: 'Профиль', icon: '👤', iconImg: '/assets/icon_profil.png', glow: 'rgba(0, 229, 255, .6)' }, ]; function iconHtml(item) { return item.iconImg ? `` : `${item.icon}`; } function normalizeCounters(payload = {}) { const notifications = payload?.notifications || {}; const notificationTotal = Math.max(0, Number(payload?.notificationsUnreadCount ?? ( Number(notifications.replies || 0) + Number(notifications.connections || 0) + Number(notifications.events || 0) )) || 0); return { dmUnreadCount: Math.max(0, Number(payload?.dmUnreadCount || 0) || 0), channelsUnreadCount: Math.max(0, Number(payload?.channelsUnreadCount || 0) || 0), notificationsUnreadCount: notificationTotal, notifications: { replies: Math.max(0, Number(notifications.replies ?? payload?.notificationRepliesUnreadCount ?? 0) || 0), connections: Math.max(0, Number(notifications.connections ?? payload?.notificationConnectionsUnreadCount ?? 0) || 0), events: Math.max(0, Number(notifications.events ?? payload?.notificationEventsUnreadCount ?? 0) || 0), }, }; } function setCounterState(payload = {}) { state.userCounters = normalizeCounters(payload); state.notificationUnreadTotal = state.userCounters.notificationsUnreadCount; } function renderBadge(btn, count, ariaLabel, extraClass = '') { if (!btn) return; let badge = btn.querySelector('.toolbar-unread-badge'); if (count <= 0) { badge?.remove(); return; } if (!badge) { badge = document.createElement('span'); badge.className = `toolbar-unread-badge${extraClass ? ` ${extraClass}` : ''}`; btn.append(badge); } badge.textContent = count > 99 ? '99+' : String(count); badge.setAttribute('aria-label', `${ariaLabel}: ${count}`); } function applyCountersToMountedToolbars() { const c = normalizeCounters(state.userCounters); document.querySelectorAll('.toolbar').forEach((toolbar) => { renderBadge(toolbar.querySelector('[data-toolbar-page="messages-list"]'), c.dmUnreadCount, 'Непрочитанных личных сообщений'); renderBadge(toolbar.querySelector('[data-toolbar-page="channels-list"]'), c.channelsUnreadCount, 'Непрочитанных сообщений в каналах'); renderBadge(toolbar.querySelector('[data-toolbar-page="notifications-view"]'), c.notificationsUnreadCount, 'Новых уведомлений', 'notification-toolbar-badge'); }); } let countersPushBound = false; function ensureCountersPushBound() { if (countersPushBound) return; countersPushBound = true; authService.onEvent('UserCountersChanged', (event) => { setCounterState(event?.payload || {}); applyCountersToMountedToolbars(); }); } async function refreshUserCounters() { if (!state.session.isAuthorized) return; try { setCounterState(await authService.getUserCounters()); applyCountersToMountedToolbars(); } catch { // Keep the last known counters; realtime push or the next refresh can recover. } } function navigateWithGuestRules(pageId, navigate) { if (state.session.isAuthorized) { navigate(pageId); return; } if (pageId === 'messages-list') { openAuthRequiredModal({ title: 'Личные сообщения недоступны', text: 'Вы не авторизованы. Для личных сообщений сначала войдите в систему.', }); return; } if (pageId === 'profile-view') { openAuthRequiredModal({ title: 'Профиль недоступен', text: 'Вы не авторизованы. Для профиля сначала войдите в систему.', }); return; } if (pageId === 'notifications-view') { openAuthRequiredModal({ title: 'Уведомления недоступны', text: 'Вы не авторизованы. Для уведомлений сначала войдите в систему.', }); return; } navigate(pageId); } export function renderToolbar(currentPageId, navigate) { const root = document.createElement('nav'); root.className = 'toolbar'; const active = resolveToolbarActive(currentPageId); ensureCountersPushBound(); const counters = normalizeCounters(state.userCounters); ITEMS.forEach((item) => { const btn = document.createElement('button'); const isProfile = item.pageId === 'profile-view'; const isMessages = item.pageId === 'messages-list'; const isNetwork = item.pageId === 'network-view'; const isNotifications = item.pageId === 'notifications-view'; btn.dataset.toolbarPage = item.pageId; btn.className = `toolbar-btn${item.pageId === active ? ' active' : ''}${isProfile ? ' toolbar-btn-profile' : ''}${isMessages ? ' toolbar-btn-messages' : ''}${isNetwork ? ' toolbar-btn-network' : ''}${item.hero ? ' toolbar-btn-hero' : ''}`; if (isProfile) { btn.innerHTML = ` ${iconHtml(item)} ${item.label} `; } else if (isNetwork) { btn.innerHTML = `${iconHtml(item)}${item.label}`; btn.setAttribute('aria-label', item.label); btn.title = item.label; } else { btn.innerHTML = `${iconHtml(item)}${item.label}`; } if (isMessages) renderBadge(btn, counters.dmUnreadCount, 'Непрочитанных личных сообщений'); if (item.pageId === 'channels-list') renderBadge(btn, counters.channelsUnreadCount, 'Непрочитанных сообщений в каналах'); if (isNotifications) renderBadge(btn, counters.notificationsUnreadCount, 'Новых уведомлений', 'notification-toolbar-badge'); if (item.pageId === 'channels-list') { btn.addEventListener('click', () => navigate('channels-list')); } else { btn.addEventListener('click', () => navigateWithGuestRules(item.pageId, navigate)); } root.append(btn); }); if (state.session.isAuthorized) void refreshUserCounters(); return root; }