// server and channel management async function loadServers() { try { const res = await fetch(`${API_URL}/servers`, { headers: { 'Authorization': `Bearer ${token}` } }); if (res.ok) { servers = await res.json(); // seed lastSeen timestamps so we don't mark existing messages as unread servers.forEach(s => { s.channels.forEach(ch => { const key = conversationKey('c', ch.id); if (!lastSeen[key]) lastSeen[key] = Date.now(); }); }); renderServers(); if (servers.length > 0) { selectServer(servers[0].id); } // Update Service Worker with channels list for background notifications updateServiceWorkerChannels(); } } catch (error) { console.error('Error loading servers:', error); } } function renderServers() { const bar = document.getElementById('servers-bar'); bar.querySelectorAll('.server-icon').forEach(n => n.remove()); servers.forEach(s => { const icon = document.createElement('div'); icon.className = 'server-icon'; icon.textContent = s.name.charAt(0).toUpperCase(); icon.onclick = () => selectServer(s.id); bar.insertBefore(icon, document.getElementById('create-server-btn')); }); } function addChannelButton() { const list = document.getElementById('channels-list'); let btn = document.getElementById('create-channel-btn'); if (!btn) { btn = document.createElement('div'); btn.id = 'create-channel-btn'; btn.className = 'channel create-channel-btn'; btn.textContent = '+ create channel'; btn.onclick = async () => { const name = prompt('Channel name:'); if (!name) return; const res = await fetch(`${API_URL}/servers/${currentServerId}/channels`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ name }) }); if (res.ok) { const newch = await res.json(); const srv = servers.find(s=>s.id===currentServerId); srv.channels.push(newch); selectServer(currentServerId); } else { const err = await res.json(); alert(err.error || 'failed'); } }; list.prepend(btn); } } function selectServer(id) { currentServerId = id; const srv = servers.find(s => s.id === id); document.querySelector('.server-name').textContent = srv.name; const list = document.getElementById('channels-list'); list.innerHTML = ''; addChannelButton(); srv.channels.forEach(ch => { const el = document.createElement('div'); el.className = 'channel'; el.textContent = '# ' + ch.name; // badge const count = unreadCounts[conversationKey('c', ch.id)]; if (count) { const badge = document.createElement('span'); badge.className = 'unread-badge'; badge.textContent = count; el.appendChild(badge); } el.onclick = () => selectChannel(ch.id, ch.name); list.appendChild(el); }); if (srv.channels.length>0) selectChannel(srv.channels[0].id, srv.channels[0].name); messageInput.value = ''; } function selectChannel(id, name) { currentChannelId = id; headerTitle.textContent = `#${name}`; // clear current messages when switching channels to avoid mixed history if (messagesContainer) messagesContainer.innerHTML = ''; lastFetchedTs = null; isAtBottom = true; // reset scroll state for new conversation currentDMUserId = null; loadChannel(id); document.querySelectorAll('.channel').forEach(ch => ch.classList.remove('active')); const el = [...document.querySelectorAll('.channel')].find(n=>n.textContent.includes(name)); if(el) el.classList.add('active'); messageInput.value = ''; } function selectGlobalChat() { currentDMUserId = null; headerTitle.textContent = 'Глобальный чат'; if (messagesContainer) messagesContainer.innerHTML = ''; lastFetchedTs = null; isAtBottom = true; // reset scroll state for new conversation currentChannelId = null; loadGlobalChat(); document.querySelectorAll('.channel').forEach(ch => ch.classList.remove('active')); document.querySelector('[data-channel="global"]').classList.add('active'); messageInput.value = ''; } function initServerListeners() { const btn = document.getElementById('create-server-btn'); if (btn) { btn.addEventListener('click', async () => { const name = prompt('Server name:'); if (!name) return; const res = await fetch(`${API_URL}/servers`, { method: 'POST', headers: { 'Content-Type':'application/json', 'Authorization':`Bearer ${token}` }, body: JSON.stringify({name}) }); if (res.ok) { loadServers(); } else { const err = await res.json(); alert(err.error || 'failed'); } }); } }