// The (?) window: a thematic floating panel explaining what the app is, what // the status tiers mean, and a live status readout (connection + counts). Single // instance — opening again just brings it forward. import { makeDraggable } from './drag.js'; let el = null; let timer = null; const CONN_LABEL = { connecting: 'connecting…', live: 'connected', down: 'reconnecting…' }; // getStatus() -> { handle, conn, online, idle, offline, total } export function openAbout(getStatus) { if (el) { el.style.zIndex = 3000; return; } el = document.createElement('div'); el.className = 'imwin about'; el.style.left = `${Math.max(8, (window.innerWidth - 320) / 2)}px`; el.style.top = `${Math.max(8, window.innerHeight / 6)}px`; el.style.zIndex = 3000; el.innerHTML = `
❓ About Buddy List ×

An AIM-style buddy list of your Bluesky mutuals. No login — it reads your public follows & followers, then watches the Bluesky firehose (Jetstream) for what they do, in real time. 👂

Status

Set the window with “active within”. A door chime plays when a buddy flips to Online; click a buddy to open an IM log of their recent activity.

Now

—

a cee.wtf thing

`; document.body.appendChild(el); makeDraggable(el, el.querySelector('.im-tb')); el.addEventListener('mousedown', () => { el.style.zIndex = 3000; }, true); el.querySelector('.ab-x').addEventListener('click', closeAbout); const paint = () => renderStatus(getStatus()); paint(); timer = setInterval(paint, 3000); } function renderStatus(s) { const box = el?.querySelector('#ab-status'); if (!box) return; if (!s || !s.handle) { box.innerHTML = `not signed on`; return; } box.innerHTML = `
signed on as @${escAttr(s.handle)}
connection: ${CONN_LABEL[s.conn] || s.conn}
${s.online} online · ${s.idle} idle · ${s.offline} offline (of ${s.total})
`; } function escAttr(s) { return String(s).replace(/[&<>"]/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"' }[c])); } export function closeAbout() { if (timer) { clearInterval(timer); timer = null; } el?.remove(); el = null; }