返回 DeepSeek-Reasonix
remoteTabEvents.ts
根目录 / desktop / frontend / src / lib / remoteTabEvents.ts
1 import { desktopHost } from "./desktopHost";
2 import type { RemoteTabState, TabMeta } from "./types";
3
4 type MockRemoteTabChannel = "event" | "state";
5 const mockListeners = new Map<string, Set<(payload: unknown) => void>>();
6 const openedListeners = new Set<(meta: TabMeta) => void>();
7 const updatedListeners = new Set<(meta: TabMeta) => void>();
8
9 function hostEvents(name: string, cb: (...args: unknown[]) => void): (() => void) | null {
10 const host = desktopHost();
11 return host.kind === "none" ? null : host.events.on(name, cb);
12 }
13
14 function registerMock(tabId: string, channel: MockRemoteTabChannel, cb: (payload: unknown) => void): () => void {
15 const key = `${tabId}:${channel}`;
16 const listeners = mockListeners.get(key) ?? new Set<(payload: unknown) => void>();
17 listeners.add(cb);
18 mockListeners.set(key, listeners);
19 return () => {
20 listeners.delete(cb);
21 if (listeners.size === 0) mockListeners.delete(key);
22 };
23 }
24
25 export function onRemoteTabEvent(tabId: string, cb: (frame: unknown) => void): () => void {
26 return hostEvents(`remote-tab:${tabId}:event`, cb) ?? registerMock(tabId, "event", cb);
27 }
28
29 export function onRemoteTabState(tabId: string, cb: (state: RemoteTabState) => void): () => void {
30 return hostEvents(`remote-tab:${tabId}:state`, (payload?: unknown) => cb((payload ?? {}) as RemoteTabState))
31 ?? registerMock(tabId, "state", cb as (payload: unknown) => void);
32 }
33
34 export function onRemoteTabOpened(cb: (meta: TabMeta) => void): () => void {
35 const off = hostEvents("remote-tab:opened", (payload?: unknown) => cb((payload ?? {}) as TabMeta));
36 if (off) return off;
37 openedListeners.add(cb);
38 return () => openedListeners.delete(cb);
39 }
40
41 export function onRemoteTabUpdated(cb: (meta: TabMeta) => void): () => void {
42 const off = hostEvents("remote-tab:updated", (payload?: unknown) => cb((payload ?? {}) as TabMeta));
43 if (off) return off;
44 updatedListeners.add(cb);
45 return () => updatedListeners.delete(cb);
46 }
47
48 export function __emitMockRemoteTab(tabId: string, channel: MockRemoteTabChannel, payload: unknown): void {
49 for (const cb of mockListeners.get(`${tabId}:${channel}`) ?? []) cb(payload);
50 }
51
52 export function __emitMockRemoteTabOpened(meta: TabMeta): void {
53 for (const cb of openedListeners) cb(meta);
54 }
55
56 export function __emitMockRemoteTabUpdated(meta: TabMeta): void {
57 for (const cb of updatedListeners) cb(meta);
58 }
59
59 lines TYPESCRIPT