返回 DeepSeek-Reasonix
lazyGuestView.ts
根目录 / desktop / electron / src / main / browser / lazyGuestView.ts
1 import type { Rectangle, MouseInputEvent } from "electron";
2 import type { GuestPage, GuestView, GuestViewEvents, GuestViewFactory } from "./guestView.js";
3 import type { BrowserViewport } from "./viewport.js";
4 import type { RecoveredTab } from "./recoveryStore.js";
5 import { browserFailure } from "./errors.js";
6
7 // A restored logical tab has no WebContents until explicit UI or granted access.
8 export class LazyGuestView implements GuestView {
9 private live: GuestView | null = null;
10 private events?: GuestViewEvents;
11 private bounds?: Rectangle;
12 private visible = false;
13 private destroyed = false;
14 private loading: Promise<void> | null = null;
15 private viewport: BrowserViewport | null;
16 readonly page: GuestPage;
17 constructor(private readonly factory: GuestViewFactory, private readonly partition: string, private readonly restored: RecoveredTab) {
18 this.viewport = restored.viewport;
19 this.page = new Proxy({} as GuestPage, { get: (_target, key) => {
20 if (key === "loadURL") return (url: string) => { this.loading = this.materialize().page.loadURL(url); return this.loading; };
21 if (this.live) {
22 const value = Reflect.get(this.live.page, key);
23 return typeof value === "function" ? value.bind(this.live.page) : value;
24 }
25 if (key === "id") return -1;
26 if (key === "getURL") return () => restored.url;
27 if (key === "getTitle") return () => restored.title;
28 if (key === "isDestroyed") return () => this.destroyed;
29 if (key === "isLoading") return () => false;
30 if (key === "getZoomFactor") return () => 1;
31 if (key === "navigationHistory") return { canGoBack: () => false, canGoForward: () => false, goBack() {}, goForward() {} };
32 throw browserFailure("page_not_ready", "restored page has not been loaded");
33 } });
34 }
35 isPlaceholder(): boolean { return this.live === null; }
36 private materialize(): GuestView {
37 if (this.destroyed) throw browserFailure("stale_document", "restored tab was closed");
38 if (!this.live) {
39 this.live = this.factory.create(this.partition);
40 if (this.events) this.live.bind(this.events);
41 if (this.bounds) this.live.setBounds(this.bounds);
42 this.live.setViewport?.(this.viewport);
43 this.live.setVisible(this.visible);
44 }
45 return this.live;
46 }
47 ensureLoaded(): Promise<void> {
48 if (this.restored.fileReference && !this.live) return Promise.reject(browserFailure("page_not_ready", "local preview needs fresh file authorization; use Reopen preview"));
49 if (this.live) return this.loading ?? Promise.resolve();
50 if (!this.loading) this.loading = this.materialize().page.loadURL(this.restored.url);
51 return this.loading;
52 }
53 bind(events: GuestViewEvents): void { this.events = events; this.live?.bind(events); }
54 setBounds(bounds: Rectangle): void { this.bounds = bounds; this.live?.setBounds(bounds); }
55 setVisible(visible: boolean): void { this.visible = visible; this.live?.setVisible(visible); }
56 setViewport(viewport: BrowserViewport | null): void { this.viewport = viewport; this.live?.setViewport?.(viewport); }
57 inputScale(): number { return this.live?.inputScale?.() ?? 1; }
58 capturePixelRatio(): number { return this.live?.capturePixelRatio?.() ?? 1; }
59 presentForUser(): void { this.live?.presentForUser?.(); }
60 prepareObservation(): () => void { return this.materialize().prepareObservation?.() ?? (() => {}); }
61 async sendMouseInput(event: MouseInputEvent, verify?: () => void): Promise<void> { const view = this.materialize(); if (view.sendMouseInput) await view.sendMouseInput(event, verify); else { verify?.(); view.page.sendInputEvent(event); } }
62 captureSurfaceSize(): { width: number; height: number } { return this.live?.captureSurfaceSize?.() ?? this.bounds ?? { width: 1280, height: 720 }; }
63 get diagnostics() { return this.live?.diagnostics; }
64 async prepareCapture(signal: AbortSignal, recording = false): Promise<() => void> { return await this.materialize().prepareCapture?.(signal, recording) ?? (() => {}); }
65 destroy(): void { this.destroyed = true; this.live?.destroy(); }
66 }
67
67 lines TYPESCRIPT