feat(messages): auto-open/flash dock on incoming + persist dock across reload

The live-message push now carries both parties, so an incoming message opens
that conversation's dock window if it's closed, or flashes it once if it's
already open (expanded or minimised, without disturbing the minimised state) —
only for messages from someone else, never your own echo.

Dock state (open windows + minimised state) is persisted per user, so a reload
restores exactly what was open, minimised, or closed.
This commit is contained in:
npeter83 2026-06-25 22:46:54 +02:00
parent 3fd71cd316
commit 8392037e5f
4 changed files with 110 additions and 23 deletions

View file

@ -2,9 +2,15 @@
// to all of a user's open tabs when a message is stored; subscribers react (e.g. refetch the
// thread + conversations). Auto-reconnects with backoff; a low-frequency poll elsewhere is the
// safety net if the socket is down.
import type { Message } from "./api";
import type { Message, MessageUser } from "./api";
type Handler = (msg: Message) => void;
// A pushed message plus both parties, so the dock can open/flash the right window.
export interface IncomingMessage {
message: Message;
from?: MessageUser;
to?: MessageUser;
}
type Handler = (e: IncomingMessage) => void;
const handlers = new Set<Handler>();
let ws: WebSocket | null = null;
@ -31,7 +37,8 @@ function open() {
try {
const data = JSON.parse(ev.data);
if (data?.type === "message" && data.message) {
for (const h of handlers) h(data.message as Message);
const e: IncomingMessage = { message: data.message as Message, from: data.from, to: data.to };
for (const h of handlers) h(e);
}
} catch {
/* ignore malformed frames */