@netless/window-manager 1.0.18 → 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.
@@ -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 { LocalConsole } from "./Utils/log";
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(private emitter: EmitterType) {}
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(emitter);
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
@@ -57,3 +57,7 @@ export const ROOT_DIR = "/";
57
57
  export const INIT_DIR = "/init";
58
58
 
59
59
  export const SETUP_APP_DELAY = 50;
60
+
61
+ export const BOX_SIZE_SETTLE_DELAY = 650;
62
+
63
+ export const CONTAINER_STATE_LOG_DEBOUNCE = 1000;
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
 
package/src/typings.ts CHANGED
@@ -59,6 +59,8 @@ export type AppEmitterEvent<T = any> = {
59
59
  seek: number;
60
60
  pageStateChange: PageState;
61
61
  boxStatusChange: { appId: string; status: TeleBoxState };
62
+ /** Actual app content size in CSS pixels after the box layout is applied. */
63
+ boxSizeChange: { appId: string; width: number; height: number };
62
64
  };
63
65
 
64
66
  export type RegisterEventData = {