@netless/window-manager 1.0.19 → 1.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -0
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +140 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/App/AppBoxSizeSynchronizer.ts +1 -1
- package/src/App/AppProxy.ts +40 -1
- package/src/ContainerResizeObserver.ts +134 -4
- package/src/constants.ts +4 -0
- package/src/index.ts +13 -1
package/package.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { View } from "white-web-sdk";
|
|
2
|
+
import { BOX_SIZE_SETTLE_DELAY } from "../constants";
|
|
2
3
|
|
|
3
4
|
export type AppBoxSize = { width: number; height: number };
|
|
4
5
|
export type AppBoxSizeChange = AppBoxSize & { appId: string };
|
|
@@ -15,7 +16,6 @@ type ViewWithRefreshSize = View & {
|
|
|
15
16
|
};
|
|
16
17
|
|
|
17
18
|
const BOX_SIZE_EPSILON = 0.5;
|
|
18
|
-
const BOX_SIZE_SETTLE_DELAY = 650;
|
|
19
19
|
const BOX_SIZE_CONFIRM_DELAY = 100;
|
|
20
20
|
|
|
21
21
|
const sizesEqual = (left: AppBoxSize | undefined, right: AppBoxSize): boolean =>
|
package/src/App/AppProxy.ts
CHANGED
|
@@ -36,6 +36,8 @@ import { callbacks } from "../callback";
|
|
|
36
36
|
import { getExtendClass } from "../Utils/extendClass";
|
|
37
37
|
import { AppBoxSizeSynchronizer } from "./AppBoxSizeSynchronizer";
|
|
38
38
|
|
|
39
|
+
const APP_SETUP_WATCHDOG_TIMEOUT = 10_000;
|
|
40
|
+
|
|
39
41
|
export type AppEmitter = Emittery<AppEmitterEvent>;
|
|
40
42
|
|
|
41
43
|
export class AppProxy implements PageRemoveService {
|
|
@@ -58,6 +60,7 @@ export class AppProxy implements PageRemoveService {
|
|
|
58
60
|
private _pageState: AppPageStateImpl;
|
|
59
61
|
private _prevFullPath: string | undefined;
|
|
60
62
|
private boxSizeSynchronizer: AppBoxSizeSynchronizer;
|
|
63
|
+
private setupWatchdogTimer?: ReturnType<typeof setTimeout>;
|
|
61
64
|
|
|
62
65
|
public appResult?: NetlessApp<any>;
|
|
63
66
|
public appContext?: AppContext<any, any>;
|
|
@@ -246,7 +249,9 @@ export class AppProxy implements PageRemoveService {
|
|
|
246
249
|
this.Logger.info(
|
|
247
250
|
`[WindowManager]: setup app ${this.kind}, appId: ${appId}`
|
|
248
251
|
);
|
|
249
|
-
const
|
|
252
|
+
const setupResult = await this.runAppSetup(appId, app, context);
|
|
253
|
+
if (!setupResult.succeeded) return;
|
|
254
|
+
const { result } = setupResult;
|
|
250
255
|
this.appResult = result;
|
|
251
256
|
this.scheduleBoxSizeSync();
|
|
252
257
|
appRegister.notifyApp(this.kind, "created", { appId, result });
|
|
@@ -286,6 +291,39 @@ export class AppProxy implements PageRemoveService {
|
|
|
286
291
|
}
|
|
287
292
|
}
|
|
288
293
|
|
|
294
|
+
private async runAppSetup(
|
|
295
|
+
appId: string,
|
|
296
|
+
app: NetlessApp,
|
|
297
|
+
context: AppContext<any, any>
|
|
298
|
+
): Promise<{ succeeded: true; result: any } | { succeeded: false }> {
|
|
299
|
+
this.clearSetupWatchdog();
|
|
300
|
+
this.setupWatchdogTimer = setTimeout(() => {
|
|
301
|
+
this.setupWatchdogTimer = undefined;
|
|
302
|
+
if (this.status === "destroyed") return;
|
|
303
|
+
this.Logger?.warn(
|
|
304
|
+
`[WindowManager]: hydrate timeout, stage: app setup, kind: ${this.kind}, appId: ${appId}, timeout: ${APP_SETUP_WATCHDOG_TIMEOUT}ms`
|
|
305
|
+
);
|
|
306
|
+
}, APP_SETUP_WATCHDOG_TIMEOUT);
|
|
307
|
+
try {
|
|
308
|
+
return { succeeded: true, result: await app.setup(context) };
|
|
309
|
+
} catch (error) {
|
|
310
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
311
|
+
this.Logger?.error(
|
|
312
|
+
`[WindowManager]: app setup error, kind: ${this.kind}, appId: ${appId}, status: ${this.status}, error: ${message}`
|
|
313
|
+
);
|
|
314
|
+
return { succeeded: false };
|
|
315
|
+
} finally {
|
|
316
|
+
this.clearSetupWatchdog();
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
private clearSetupWatchdog(): void {
|
|
321
|
+
if (this.setupWatchdogTimer != null) {
|
|
322
|
+
clearTimeout(this.setupWatchdogTimer);
|
|
323
|
+
this.setupWatchdogTimer = undefined;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
289
327
|
// 兼容移动端创建时会出现 PPT 不适配的问题
|
|
290
328
|
private fixMobileSize() {
|
|
291
329
|
const box = this.boxManager?.getBox(this.id);
|
|
@@ -564,6 +602,7 @@ export class AppProxy implements PageRemoveService {
|
|
|
564
602
|
) {
|
|
565
603
|
if (this.status === "destroyed") return;
|
|
566
604
|
this.status = "destroyed";
|
|
605
|
+
this.clearSetupWatchdog();
|
|
567
606
|
this.boxSizeSynchronizer.destroy();
|
|
568
607
|
try {
|
|
569
608
|
await appRegister.notifyApp(this.kind, "destroy", { appId: this.id });
|
|
@@ -2,25 +2,58 @@ import { ResizeObserver as ResizeObserverPolyfill } from "@juggle/resize-observe
|
|
|
2
2
|
import { WindowManager } from "./index";
|
|
3
3
|
import type { EmitterType } from "./InternalEmitter";
|
|
4
4
|
import type { UnsubscribeFn } from "emittery";
|
|
5
|
-
import {
|
|
5
|
+
import type { Logger } from "white-web-sdk";
|
|
6
|
+
import { CONTAINER_STATE_LOG_DEBOUNCE } from "./constants";
|
|
7
|
+
import { ArgusLog, LocalConsole } from "./Utils/log";
|
|
6
8
|
|
|
7
9
|
const ResizeObserver = window.ResizeObserver || ResizeObserverPolyfill;
|
|
8
10
|
|
|
11
|
+
export type ContainerInternalState = {
|
|
12
|
+
mainViewElement?: HTMLElement;
|
|
13
|
+
mainViewSize?: Pick<DOMRectReadOnly, "width" | "height">;
|
|
14
|
+
teleBoxContainerRect?: Pick<DOMRectReadOnly, "width" | "height">;
|
|
15
|
+
mainViewDidRelease?: boolean;
|
|
16
|
+
containerSizeRatio?: number;
|
|
17
|
+
};
|
|
18
|
+
|
|
9
19
|
export class ContainerResizeObserver {
|
|
10
20
|
private containerResizeObserver?: ResizeObserver;
|
|
11
21
|
private disposer?: UnsubscribeFn;
|
|
12
22
|
|
|
13
23
|
private updateSizerLocalConsole = new LocalConsole("updateSizer", 100);
|
|
24
|
+
private containerStateArgusLog?: ArgusLog;
|
|
25
|
+
private containerStateLogTimer?: ReturnType<typeof setTimeout>;
|
|
26
|
+
private pendingContainerState?: {
|
|
27
|
+
origin?: string;
|
|
28
|
+
observedSize?: Pick<DOMRectReadOnly, "width" | "height">;
|
|
29
|
+
};
|
|
30
|
+
private container?: HTMLElement;
|
|
31
|
+
private sizer?: HTMLElement;
|
|
32
|
+
private wrapper?: HTMLDivElement;
|
|
14
33
|
|
|
15
|
-
constructor(
|
|
34
|
+
constructor(
|
|
35
|
+
private emitter: EmitterType,
|
|
36
|
+
logger?: Logger,
|
|
37
|
+
private getInternalState?: () => ContainerInternalState
|
|
38
|
+
) {
|
|
39
|
+
if (logger) {
|
|
40
|
+
this.containerStateArgusLog = new ArgusLog(logger, "containerState");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
16
43
|
|
|
17
44
|
public static create(
|
|
18
45
|
container: HTMLElement,
|
|
19
46
|
sizer: HTMLElement,
|
|
20
47
|
wrapper: HTMLDivElement,
|
|
21
|
-
emitter: EmitterType
|
|
48
|
+
emitter: EmitterType,
|
|
49
|
+
logger?: Logger,
|
|
50
|
+
getInternalState?: () => ContainerInternalState
|
|
22
51
|
) {
|
|
23
|
-
const containerResizeObserver = new ContainerResizeObserver(
|
|
52
|
+
const containerResizeObserver = new ContainerResizeObserver(
|
|
53
|
+
emitter,
|
|
54
|
+
logger,
|
|
55
|
+
getInternalState
|
|
56
|
+
);
|
|
24
57
|
containerResizeObserver.observePlaygroundSize(container, sizer, wrapper);
|
|
25
58
|
return containerResizeObserver;
|
|
26
59
|
}
|
|
@@ -30,6 +63,9 @@ export class ContainerResizeObserver {
|
|
|
30
63
|
sizer: HTMLElement,
|
|
31
64
|
wrapper: HTMLDivElement
|
|
32
65
|
) {
|
|
66
|
+
this.container = container;
|
|
67
|
+
this.sizer = sizer;
|
|
68
|
+
this.wrapper = wrapper;
|
|
33
69
|
this.updateSizer(
|
|
34
70
|
container.getBoundingClientRect(),
|
|
35
71
|
sizer,
|
|
@@ -60,6 +96,7 @@ export class ContainerResizeObserver {
|
|
|
60
96
|
wrapper: HTMLDivElement,
|
|
61
97
|
origin?: string
|
|
62
98
|
) {
|
|
99
|
+
const observedSize = { width, height };
|
|
63
100
|
if (width && height) {
|
|
64
101
|
if (height / width > WindowManager.containerSizeRatio) {
|
|
65
102
|
height = width * WindowManager.containerSizeRatio;
|
|
@@ -82,12 +119,105 @@ export class ContainerResizeObserver {
|
|
|
82
119
|
origin,
|
|
83
120
|
});
|
|
84
121
|
}
|
|
122
|
+
this.scheduleContainerStateLog(origin, observedSize);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
public logCurrentState(origin: string): void {
|
|
126
|
+
this.scheduleContainerStateLog(origin);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private scheduleContainerStateLog(
|
|
130
|
+
origin?: string,
|
|
131
|
+
observedSize?: Pick<DOMRectReadOnly, "width" | "height">
|
|
132
|
+
): void {
|
|
133
|
+
if (!this.containerStateArgusLog || !this.container || !this.sizer || !this.wrapper) return;
|
|
134
|
+
|
|
135
|
+
this.pendingContainerState = {
|
|
136
|
+
origin,
|
|
137
|
+
observedSize: observedSize
|
|
138
|
+
? { width: observedSize.width, height: observedSize.height }
|
|
139
|
+
: undefined,
|
|
140
|
+
};
|
|
141
|
+
if (this.containerStateLogTimer != null) {
|
|
142
|
+
clearTimeout(this.containerStateLogTimer);
|
|
143
|
+
}
|
|
144
|
+
this.containerStateLogTimer = setTimeout(
|
|
145
|
+
this.flushContainerStateLog,
|
|
146
|
+
CONTAINER_STATE_LOG_DEBOUNCE
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private flushContainerStateLog = (): void => {
|
|
151
|
+
this.containerStateLogTimer = undefined;
|
|
152
|
+
const pendingState = this.pendingContainerState;
|
|
153
|
+
this.pendingContainerState = undefined;
|
|
154
|
+
if (
|
|
155
|
+
!pendingState ||
|
|
156
|
+
!this.containerStateArgusLog ||
|
|
157
|
+
!this.container ||
|
|
158
|
+
!this.sizer ||
|
|
159
|
+
!this.wrapper
|
|
160
|
+
) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const internalState = this.getInternalState?.();
|
|
165
|
+
const root = this.container.parentElement;
|
|
166
|
+
const rootRect = root?.getBoundingClientRect();
|
|
167
|
+
const playgroundRect = this.container.getBoundingClientRect();
|
|
168
|
+
const sizerRect = this.sizer.getBoundingClientRect();
|
|
169
|
+
const wrapperRect = this.wrapper.getBoundingClientRect();
|
|
170
|
+
const mainViewRect = internalState?.mainViewElement?.getBoundingClientRect();
|
|
171
|
+
const rootStyle = root ? window.getComputedStyle(root) : undefined;
|
|
172
|
+
this.containerStateArgusLog.log(
|
|
173
|
+
`origin: ${pendingState.origin || "unknown"}, connected: ${Boolean(
|
|
174
|
+
root?.isConnected
|
|
175
|
+
)}, ` +
|
|
176
|
+
`observed: ${this.formatSize(
|
|
177
|
+
pendingState.observedSize || playgroundRect
|
|
178
|
+
)}, root: ${this.formatSize(rootRect)}, playground: ${this.formatSize(
|
|
179
|
+
playgroundRect
|
|
180
|
+
)}, sizer: ${this.formatSize(sizerRect)}, wrapper: ${this.formatSize(
|
|
181
|
+
wrapperRect
|
|
182
|
+
)}, mainViewDOM: ${this.formatSize(mainViewRect)}, mainViewSize: ${this.formatSize(
|
|
183
|
+
internalState?.mainViewSize
|
|
184
|
+
)}, teleBoxRect: ${this.formatSize(
|
|
185
|
+
internalState?.teleBoxContainerRect
|
|
186
|
+
)}, didRelease: ${internalState?.mainViewDidRelease ?? "unknown"}, ratio: ${
|
|
187
|
+
internalState?.containerSizeRatio ?? "unknown"
|
|
188
|
+
}, display: ${rootStyle?.display || "unknown"}, visibility: ${
|
|
189
|
+
rootStyle?.visibility || "unknown"
|
|
190
|
+
}, clientRects: ${root?.getClientRects().length || 0}, inViewport: ${
|
|
191
|
+
rootRect
|
|
192
|
+
? rootRect.bottom > 0 &&
|
|
193
|
+
rootRect.right > 0 &&
|
|
194
|
+
rootRect.top < window.innerHeight &&
|
|
195
|
+
rootRect.left < window.innerWidth
|
|
196
|
+
: false
|
|
197
|
+
}`
|
|
198
|
+
);
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
private formatSize(rect?: Pick<DOMRectReadOnly, "width" | "height">): string {
|
|
202
|
+
if (!rect) return "unknown";
|
|
203
|
+
return `${Math.round(rect.width * 100) / 100}x${Math.round(rect.height * 100) / 100}`;
|
|
85
204
|
}
|
|
86
205
|
|
|
87
206
|
public disconnect() {
|
|
88
207
|
this.updateSizerLocalConsole.destroy();
|
|
208
|
+
if (this.containerStateLogTimer != null) {
|
|
209
|
+
clearTimeout(this.containerStateLogTimer);
|
|
210
|
+
this.containerStateLogTimer = undefined;
|
|
211
|
+
}
|
|
212
|
+
this.pendingContainerState = undefined;
|
|
213
|
+
this.containerStateArgusLog?.destroy();
|
|
214
|
+
this.containerStateArgusLog = undefined;
|
|
89
215
|
this.containerResizeObserver?.disconnect();
|
|
90
216
|
this.disposer?.();
|
|
91
217
|
this.disposer = undefined;
|
|
218
|
+
this.container = undefined;
|
|
219
|
+
this.sizer = undefined;
|
|
220
|
+
this.wrapper = undefined;
|
|
221
|
+
this.getInternalState = undefined;
|
|
92
222
|
}
|
|
93
223
|
}
|
package/src/constants.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -528,7 +528,18 @@ export class WindowManager
|
|
|
528
528
|
playground,
|
|
529
529
|
sizer,
|
|
530
530
|
wrapper,
|
|
531
|
-
internalEmitter
|
|
531
|
+
internalEmitter,
|
|
532
|
+
manager.Logger,
|
|
533
|
+
() => {
|
|
534
|
+
const mainView = manager.appManager?.mainViewProxy.view;
|
|
535
|
+
return {
|
|
536
|
+
mainViewElement: mainView?.divElement,
|
|
537
|
+
mainViewSize: mainView?.size,
|
|
538
|
+
teleBoxContainerRect: manager.boxManager?.teleBoxManager.containerRect,
|
|
539
|
+
mainViewDidRelease: Boolean((mainView as any)?.didRelease),
|
|
540
|
+
containerSizeRatio: manager.containerSizeRatio,
|
|
541
|
+
};
|
|
542
|
+
}
|
|
532
543
|
);
|
|
533
544
|
WindowManager.wrapper = wrapper;
|
|
534
545
|
WindowManager.sizer = sizer;
|
|
@@ -577,6 +588,7 @@ export class WindowManager
|
|
|
577
588
|
this.appManager?.resetMinimized();
|
|
578
589
|
this.appManager?.displayerWritableListener(!this.room.isWritable);
|
|
579
590
|
WindowManager.container = container;
|
|
591
|
+
this.containerResizeObserver?.logCurrentState("bindContainer");
|
|
580
592
|
this.extendPluginManager?.refreshContainer(container);
|
|
581
593
|
}
|
|
582
594
|
|