feat(frontend): surfaces live web (workstate live, background, inbox, reconnect) (#13)

Lot F5 du chantier server/client mode : le client web consomme les frames
event.domain (B7) pour animer ses surfaces live.

- webLive.ts : consommation du flux event.domain (workstate, background,
  inbox).
- useLiveReconnect.ts : reconnexion du flux live.
- wsLiveClient.ts / index.ts : câblage du transport live.
- WebWorkspace.tsx : surfaces live branchées.
- Tests : WebWorkspaceLive.test.tsx, wsLiveClientReconnect.test.ts,
  WebApp.test.tsx.

Validé : frontend 753 tests verts, desktop non régressé.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-15 23:37:02 +02:00
parent 1bc5217dbc
commit dd1d083a1a
8 changed files with 457 additions and 112 deletions

View File

@ -0,0 +1,28 @@
/**
* Web live-connection accessor — ticket #13, lot F5.
*
* The web gateways share a single {@link WsLiveClient} (created in
* `createHttpWsGateways`). The live surfaces (workstate / background /
* notifications) need to know when that socket **reconnects** after an outage so
* they can re-synchronise their read-models (events emitted while disconnected
* were missed). The `SystemGateway` port intentionally does not expose transport
* connection state, so — rather than leak it through the port — the web client is
* registered here as a module singleton and consumed only by the web feature
* (`useLiveReconnect`). Desktop never registers a client, so this is inert there.
*
* Lives in `src/adapters/**`; touches no `@tauri-apps/api`.
*/
import type { WsLiveClient } from "./wsLiveClient";
let liveClient: WsLiveClient | null = null;
/** Registers the shared web live client (called by `createHttpWsGateways`). */
export function setWebLiveClient(client: WsLiveClient | null): void {
liveClient = client;
}
/** Returns the shared web live client, or `null` outside web transport. */
export function getWebLiveClient(): WsLiveClient | null {
return liveClient;
}