- Header: no SSO chip ("Sign in again" only on expiry), state dot on the
session chip, LIVE as a dot, ⋯ menu for text size/notifications/fullscreen,
Panels badge for waiting sessions and alerts.
- Session switcher on the chip; bare URL reattaches the last session; + New
opens the panel form with project folders.
- Notifications when other sessions start waiting; alerts polled with the
panels closed; one tab polls for all tabs over BroadcastChannel.
- Sidebar: context bar per session instead of the Context panel; compact
Repo/CI with "Ask Claude to fix CI"; legible labels.
- Phone: key bar, drawer with backdrop, visualViewport-aware layout, DOM
renderer on touch, compact connection dot.
- devdesk-notify-matrix: one Matrix message per wait that lasts
DEVDESK_MATRIX_DELAY seconds with nobody attached.
Closes #8
Closes #13
Closes #14
Closes #15
Closes #16
Closes #17
Closes #28
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
32 lines
941 B
JavaScript
32 lines
941 B
JavaScript
// One tab polls for every open DevDesk tab (devdesk#8): whoever fetches the
|
|
// session list or the alerts broadcasts the result, and a tab that heard a fresh
|
|
// result recently skips its own poll. Each poll costs a ttyd client and a PTY.
|
|
|
|
const channel = typeof BroadcastChannel === 'function' ? new BroadcastChannel('devdesk') : null;
|
|
const heard = new Map();
|
|
const handlers = new Map();
|
|
|
|
channel?.addEventListener('message', (event) => {
|
|
const { key, data } = event.data ?? {};
|
|
const handler = handlers.get(key);
|
|
if (!handler) return;
|
|
heard.set(key, Date.now());
|
|
handler(data);
|
|
});
|
|
|
|
export function onShared(key, handler) {
|
|
handlers.set(key, handler);
|
|
}
|
|
|
|
export function share(key, data) {
|
|
try {
|
|
channel?.postMessage({ key, data });
|
|
} catch {
|
|
// Not cloneable or channel closed: the other tabs just poll themselves.
|
|
}
|
|
}
|
|
|
|
export function heardWithin(key, ms) {
|
|
return Date.now() - (heard.get(key) ?? 0) < ms;
|
|
}
|