diff --git a/public/app.js b/public/app.js index d39ee3e..ab54520 100644 --- a/public/app.js +++ b/public/app.js @@ -192,12 +192,12 @@ const updateMap = async (peers) => { const loc = await fetchLocation(peer.ip); if (loc) { const marker = L.circleMarker([loc.lat, loc.lon], { - radius: 5, + radius: 10, fillColor: "#4ade80", - color: "#fff", - weight: 1, - opacity: 1, - fillOpacity: 0.8 + color: "transparent", + weight: 0, + opacity: 0, + fillOpacity: 0.15 }).addTo(map); marker.bindPopup(`Node ${peer.id.slice(-8)}
${loc.city}, ${loc.country}`); @@ -220,11 +220,29 @@ terminalToggle.addEventListener('click', (e) => { toggleChat(); }); +// Initialize chat state from localStorage +const initChatState = () => { + const isCollapsed = localStorage.getItem('chatCollapsed') === 'true'; + if (isCollapsed) { + terminal.classList.add('collapsed'); + terminalToggle.innerText = '▲'; + document.body.classList.remove('chat-active'); + document.body.classList.add('chat-collapsed'); + } else { + terminal.classList.remove('collapsed'); + terminalToggle.innerText = '▼'; + document.body.classList.add('chat-active'); + document.body.classList.remove('chat-collapsed'); + } +}; + const toggleChat = () => { terminal.classList.toggle('collapsed'); const isCollapsed = terminal.classList.contains('collapsed'); terminalToggle.innerText = isCollapsed ? '▲' : '▼'; + localStorage.setItem('chatCollapsed', isCollapsed); + if (isCollapsed) { document.body.classList.remove('chat-active'); document.body.classList.add('chat-collapsed'); @@ -328,10 +346,11 @@ evtSource.onmessage = (event) => { if (data.chatEnabled) { terminal.classList.remove('hidden'); - if (terminal.classList.contains('collapsed')) { - document.body.classList.add('chat-collapsed'); - } else { - document.body.classList.add('chat-active'); + + // Only initialize state once when chat becomes enabled + if (!terminal.dataset.initialized) { + initChatState(); + terminal.dataset.initialized = 'true'; } } else { terminal.classList.add('hidden'); diff --git a/public/style.css b/public/style.css index 3339dc1..dae9a2c 100644 --- a/public/style.css +++ b/public/style.css @@ -25,8 +25,26 @@ body.chat-collapsed { .count { font-size: 8rem; font-weight: bold; color: #4ade80; transition: color 0.2s; visibility: hidden; } .count.loaded { visibility: visible; } .label { font-size: 1.5rem; color: #9ca3af; margin-top: 1rem; } -.footer { margin-top: 2rem; font-size: 0.9rem; color: #4b5563; } -.debug { font-size: 0.8rem; color: #4b5563; margin-top: 1rem; } +.footer { + margin: 2rem auto 0; + font-size: 0.9rem; + color: #4b5563; + background: rgba(0, 0, 0, 0.6); + padding: 2px 8px; + border-radius: 4px; + display: block; + width: fit-content; +} +.debug { + font-size: 0.8rem; + color: #4b5563; + margin: 1rem auto 0; + background: rgba(0, 0, 0, 0.6); + padding: 5px 10px; + border-radius: 4px; + display: block; + width: fit-content; +} .debug-link { color: #4b5563; border-bottom: 1px dotted #4b5563; cursor: pointer; } .debug-link:hover { color: #9ca3af; } a { color: #4b5563; text-decoration: none; border-bottom: 1px dotted #4b5563; } @@ -58,9 +76,10 @@ a { color: #4b5563; text-decoration: none; border-bottom: 1px dotted #4b5563; } position: relative; } .modal-content.map-content { - max-width: 800px; - width: 90%; - height: 80vh; + max-width: 1000px; + width: 100%; + height: 500px; + max-height: 80vh; padding: 0; overflow: hidden; display: flex; @@ -80,17 +99,19 @@ a { color: #4b5563; text-decoration: none; border-bottom: 1px dotted #4b5563; } text-transform: uppercase; letter-spacing: 1px; } + .close-btn { position: absolute; top: 1.5rem; right: 1.5rem; background: none; border: none; - color: #333; + color: #9ca3af; font-size: 1.2rem; cursor: pointer; + z-index: 1001; } -.close-btn:hover { color: #666; } +.close-btn:hover { color: #fff; } .stat-row { display: flex; justify-content: space-between;