@netless/window-manager 1.0.13-beta.1 → 1.0.13-test.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netless/window-manager",
3
- "version": "1.0.13-beta.1",
3
+ "version": "1.0.13-test.10",
4
4
  "description": "Multi-window mode for Netless Whiteboard",
5
5
  "author": "l1shen <lishen1635@gmail.com> (https://github.com/l1shen)",
6
6
  "license": "MIT",
@@ -47,17 +47,10 @@ export class AppListeners {
47
47
  break;
48
48
  }
49
49
  case Events.SetMainViewScenePath: {
50
+ console.log("[window-manager] mainMagixEventListener " + JSON.stringify(data.payload));
50
51
  this.setMainViewScenePathHandler(data.payload);
51
52
  break;
52
53
  }
53
- // case Events.MoveCamera: {
54
- // this.moveCameraHandler(data.payload);
55
- // break;
56
- // }
57
- // case Events.MoveCameraToContain: {
58
- // this.moveCameraToContainHandler(data.payload);
59
- // break;
60
- // }
61
54
  case Events.CursorMove: {
62
55
  this.cursorMoveHandler(data.payload);
63
56
  break;
@@ -102,17 +95,6 @@ export class AppListeners {
102
95
  callbacks.emit("mainViewScenePathChange", nextScenePath);
103
96
  };
104
97
 
105
- // private moveCameraHandler = (
106
- // payload: Camera & { animationMode?: AnimationMode | undefined }
107
- // ) => {
108
- // if (isEqual(omit(payload, ["animationMode"]), { ...this.manager.mainView.camera })) return;
109
- // this.manager.mainView.moveCamera(payload);
110
- // };
111
-
112
- // private moveCameraToContainHandler = (payload: any) => {
113
- // this.manager.mainView.moveCameraToContain(payload);
114
- // };
115
-
116
98
  private cursorMoveHandler = (payload: any) => {
117
99
  internalEmitter.emit("cursorMove", payload);
118
100
  };
package/src/AppManager.ts CHANGED
@@ -146,6 +146,7 @@ export class AppManager {
146
146
  const { scenePath } = params;
147
147
  // 如果移除根目录就把 scenePath 设置为初始值
148
148
  if (scenePath === ROOT_DIR) {
149
+ console.log("[window-manager] onRemoveScenes ROOT_DIR");
149
150
  await this.onRootDirRemoved();
150
151
  this.dispatchInternalEvent(Events.RootDirRemoved);
151
152
  return;
@@ -158,6 +159,7 @@ export class AppManager {
158
159
  sceneName = this.callbacksNode?.scenes[nextIndex];
159
160
  }
160
161
  if (sceneName) {
162
+ console.log("[window-manager] onRemoveScenes setMainViewScenePath" + `${ROOT_DIR}${sceneName}`);
161
163
  this.setMainViewScenePath(`${ROOT_DIR}${sceneName}`);
162
164
  }
163
165
  await this.setMainViewSceneIndex(nextIndex);
@@ -709,6 +711,30 @@ export class AppManager {
709
711
  }
710
712
  internalEmitter.emit("mainViewMounted");
711
713
  callbacks.emit("onMainViewMounted", mainView);
714
+ const hasRoot = this.hasRoot(mainView.divElement);
715
+ const rect = this.getRectByDivElement(mainView.divElement);
716
+ console.log("[window-manager] bindMainView hasRoot" + hasRoot + JSON.stringify(rect) +
717
+ window.outerHeight + window.outerWidth,
718
+ window.visualViewport?.width ?? "null", window.visualViewport?.height ?? "null",
719
+ window.visualViewport?.offsetLeft ?? "null", window.visualViewport?.offsetTop ?? "null",
720
+ );
721
+ }
722
+
723
+ private hasRoot(divElement: HTMLDivElement){
724
+ let current = divElement;
725
+ while (current) {
726
+ if (current.parentElement === document.body) {
727
+ return true;
728
+ }
729
+ current = current.parentElement as HTMLDivElement;
730
+ }
731
+ return false;
732
+ }
733
+
734
+ private getRectByDivElement(divElement: HTMLDivElement){
735
+ // 获取当前divElement的矩形区域
736
+ const rect = divElement.getBoundingClientRect();
737
+ return rect;
712
738
  }
713
739
 
714
740
  public setMainViewFocusPath(scenePath?: string) {
@@ -840,6 +866,7 @@ export class AppManager {
840
866
  throw new Error(`[WindowManager]: ${scenePath} not valid scene`);
841
867
  } else if (scenePathType === ScenePathType.Page) {
842
868
  await this._setMainViewScenePath(scenePath);
869
+
843
870
  } else if (scenePathType === ScenePathType.Dir) {
844
871
  const validScenePath = makeValidScenePath(this.displayer, scenePath);
845
872
  if (validScenePath) {
@@ -852,6 +879,7 @@ export class AppManager {
852
879
  private async _setMainViewScenePath(scenePath: string) {
853
880
  const success = this.setMainViewFocusPath(scenePath);
854
881
  if (success) {
882
+ console.log("[window-manager] _setMainViewScenePath ", scenePath);
855
883
  this.safeSetAttributes({ _mainScenePath: scenePath });
856
884
  this.store.setMainViewFocusPath(this.mainView);
857
885
  this.updateSceneIndex();
@@ -868,6 +896,7 @@ export class AppManager {
868
896
  const pageName = scenePath.replace(sceneDir, "").replace("/", "");
869
897
  const index = scenes.findIndex(scene => scene.name === pageName);
870
898
  if (isInteger(index) && index >= 0) {
899
+ console.log("[window-manager] updateSceneIndex ", index);
871
900
  this.safeSetAttributes({ _mainSceneIndex: index });
872
901
  }
873
902
  }
@@ -893,6 +922,7 @@ export class AppManager {
893
922
  }
894
923
 
895
924
  private dispatchSetMainViewScenePath(scenePath: string): void {
925
+ console.log("[window-manager] dispatchSetMainViewScenePath ", JSON.stringify(scenePath));
896
926
  this.dispatchInternalEvent(Events.SetMainViewScenePath, { nextScenePath: scenePath });
897
927
  callbacks.emit("mainViewScenePathChange", scenePath);
898
928
  // 兼容 15 的 SDK, 需要 room 的当前 ScenePath
@@ -973,3 +1003,4 @@ export class AppManager {
973
1003
  this._resolveTimer = undefined;
974
1004
  }
975
1005
  }
1006
+
@@ -7,6 +7,7 @@ import type { Cursor } from "./Cursor/Cursor";
7
7
  import { getExtendClass } from "./Utils/extendClass";
8
8
  import type { ExtendClass } from "./Utils/extendClass";
9
9
  import type { NotMinimizedBoxState, TeleBoxState } from "@netless/telebox-insider";
10
+ import { LocalConsole } from "./Utils/log";
10
11
 
11
12
  export enum Fields {
12
13
  Apps = "apps",
@@ -54,6 +55,7 @@ export type ISize = Size & { id: string };
54
55
 
55
56
  export class AttributesDelegate {
56
57
  static readonly kind = "AttributesDelegate";
58
+ private setMainViewCameraConsole = new LocalConsole("setMainViewCamera", 50);
57
59
  constructor(private context: StoreContext) {}
58
60
 
59
61
  public setContext(context: StoreContext) {
@@ -194,10 +196,12 @@ export class AttributesDelegate {
194
196
  }
195
197
 
196
198
  public setMainViewScenePath(scenePath: string) {
199
+ console.log("[window-manager] setMainViewScenePath ", scenePath);
197
200
  this.context.safeSetAttributes({ _mainScenePath: scenePath });
198
201
  }
199
202
 
200
203
  public setMainViewSceneIndex(index: number) {
204
+ console.log("[window-manager] setMainViewSceneIndex ", index);
201
205
  this.context.safeSetAttributes({ _mainSceneIndex: index });
202
206
  }
203
207
 
@@ -210,16 +214,19 @@ export class AttributesDelegate {
210
214
  }
211
215
 
212
216
  public setMainViewCamera(camera: ICamera) {
217
+ this.setMainViewCameraConsole.log(JSON.stringify(camera));
213
218
  this.context.safeSetAttributes({ [Fields.MainViewCamera]: { ...camera } });
214
219
  }
215
220
 
216
221
  public setMainViewSize(size: ISize) {
217
222
  if (size.width === 0 || size.height === 0) return;
223
+ console.log("[window-manager] setMainViewSize ", JSON.stringify(size));
218
224
  this.context.safeSetAttributes({ [Fields.MainViewSize]: { ...size } });
219
225
  }
220
226
 
221
227
  public setMainViewCameraAndSize(camera: ICamera, size: ISize) {
222
228
  if (size.width === 0 || size.height === 0) return;
229
+ console.log("[window-manager] setMainViewCameraAndSize ", JSON.stringify(camera), JSON.stringify(size));
223
230
  this.context.safeSetAttributes({
224
231
  [Fields.MainViewCamera]: { ...camera },
225
232
  [Fields.MainViewSize]: { ...size },
package/src/BoxManager.ts CHANGED
@@ -420,6 +420,7 @@ export class BoxManager {
420
420
  const rect = this.mainView.divElement?.getBoundingClientRect();
421
421
  if (rect && rect.width > 0 && rect.height > 0) {
422
422
  const containerRect = { x: 0, y: 0, width: rect.width, height: rect.height };
423
+ console.log("[window-manager] updateManagerRect" + JSON.stringify(containerRect) + "mainView" + this.mainView.size);
423
424
  this.teleBoxManager.setContainerRect(containerRect);
424
425
  this.context.notifyContainerRectUpdate(this.teleBoxManager.containerRect);
425
426
  }
@@ -28,18 +28,21 @@ export class ContainerResizeObserver {
28
28
  sizer: HTMLElement,
29
29
  wrapper: HTMLDivElement
30
30
  ) {
31
+ console.log(`[window-manager] observePlaygroundSize ${JSON.stringify(container.getBoundingClientRect())}, ${JSON.stringify(sizer.getBoundingClientRect())}, ${JSON.stringify(wrapper.getBoundingClientRect())}`);
31
32
  this.updateSizer(container.getBoundingClientRect(), sizer, wrapper);
32
33
 
33
34
  this.containerResizeObserver = new ResizeObserver(entries => {
34
35
  const containerRect = entries[0]?.contentRect;
35
36
  if (containerRect) {
36
37
  this.updateSizer(containerRect, sizer, wrapper);
38
+ console.log(`[window-manager] containerResizeObserver ${JSON.stringify(containerRect)}`);
37
39
  this.emitter.emit("playgroundSizeChange", containerRect);
38
40
  }
39
41
  });
40
42
 
41
43
  this.disposer = this.emitter.on("containerSizeRatioUpdate", () => {
42
44
  const containerRect = container.getBoundingClientRect();
45
+ console.log(`[window-manager] containerSizeRatioUpdate ${JSON.stringify(containerRect)}`);
43
46
  this.updateSizer(containerRect, sizer, wrapper);
44
47
  this.emitter.emit("playgroundSizeChange", containerRect);
45
48
  });
@@ -62,6 +65,8 @@ export class ContainerResizeObserver {
62
65
  }
63
66
  wrapper.style.width = `${width}px`;
64
67
  wrapper.style.height = `${height}px`;
68
+ wrapper.style.backgroundColor = 'green';
69
+ console.log(`[window-manager] updateSizer ${JSON.stringify({ width, height })} ${wrapper.style.width} ${wrapper.style.height} ${JSON.stringify(wrapper.getBoundingClientRect())}`);
65
70
  }
66
71
  }
67
72
 
@@ -34,6 +34,7 @@ export const setScenePath = (room: Room | undefined, scenePath: string) => {
34
34
  if (room && room.isWritable) {
35
35
  if (room.state.sceneState.scenePath !== scenePath) {
36
36
  const nextScenePath = scenePath === "/" ? "" : scenePath;
37
+ console.log("[window-manager] real setScenePath for current room ", nextScenePath);
37
38
  room.setScenePath(nextScenePath);
38
39
  }
39
40
  }
@@ -33,7 +33,14 @@ export const replaceRoomFunction = (room: Room | Player, manager: WindowManager)
33
33
  return manager.canRedoSteps;
34
34
  },
35
35
  });
36
-
36
+ const _scalePptToFit = room.scalePptToFit;
37
+ room.scalePptToFit = (...args) => {
38
+ _scalePptToFit.call(room, ...args);
39
+ if (manager.appManager?.mainViewProxy) {
40
+ console.log("[window-manager] scalePptToFit " + JSON.stringify(args));
41
+ manager.appManager.mainViewProxy.setCameraAndSize();
42
+ }
43
+ };
37
44
  room.moveCamera = (camera: Camera) => manager.moveCamera(camera);
38
45
  room.moveCameraToContain = (...args) => manager.moveCameraToContain(...args);
39
46
  room.convertToPointInWorld = (...args) => manager.mainView.convertToPointInWorld(...args);
package/src/Utils/log.ts CHANGED
@@ -5,3 +5,40 @@ export const log = (...args: any[]): void => {
5
5
  console.log(`[WindowManager]:`, ...args);
6
6
  }
7
7
  };
8
+
9
+ /**
10
+ * 按 `[window-manager][tagName]` 前缀输出。
11
+ * 若传入 `debounceTime`(毫秒):窗口内多次 `log` 不立即输出,只在连续停止调用满 `debounceTime` 后输出**最后一次**的参数(尾部 debounce)。
12
+ */
13
+ export class LocalConsole {
14
+ private pendingArgs: unknown[] | null = null;
15
+ private flushTimer: ReturnType<typeof setTimeout> | null = null;
16
+
17
+ constructor(
18
+ private readonly name: string,
19
+ private readonly debounceTime?: number,
20
+ ) {}
21
+
22
+ private flush(): void {
23
+ this.flushTimer = null;
24
+ const args = this.pendingArgs;
25
+ this.pendingArgs = null;
26
+ if (args === null) {
27
+ return;
28
+ }
29
+ console.log(`[window-manager][${this.name}]: ${args.join(", ")}`);
30
+ }
31
+
32
+ log(...args: unknown[]): void {
33
+ const ms = this.debounceTime;
34
+ if (ms != null && ms > 0) {
35
+ this.pendingArgs = args;
36
+ if (this.flushTimer != null) {
37
+ clearTimeout(this.flushTimer);
38
+ }
39
+ this.flushTimer = setTimeout(() => this.flush(), ms);
40
+ return;
41
+ }
42
+ console.log(`[window-manager][${this.name}]: ${args.join(", ")}`);
43
+ }
44
+ }
@@ -9,7 +9,9 @@ import { SideEffectManager } from "side-effect-manager";
9
9
  import type { Camera, Room, Size, View } from "white-web-sdk";
10
10
  import type { AppManager } from "../AppManager";
11
11
  import { Events } from "../constants";
12
+ import { LocalConsole } from "../Utils/log";
12
13
 
14
+ (window as any).___local_log = (window as any).___local_log || new Set();
13
15
  export class MainViewProxy {
14
16
  /** Refresh the view's camera in an interval of 1.5s. */
15
17
  public polling = false;
@@ -23,6 +25,8 @@ export class MainViewProxy {
23
25
 
24
26
  private sideEffectManager = new SideEffectManager();
25
27
 
28
+ private playgroundSizeChangeListenerLocalConsole = new LocalConsole("playgroundSizeChangeListener", 30);
29
+
26
30
  constructor(private manager: AppManager) {
27
31
  this.mainView = this.createMainView();
28
32
  this.moveCameraSizeByAttributes();
@@ -33,6 +37,15 @@ export class MainViewProxy {
33
37
  this.startListenWritableChange();
34
38
  });
35
39
  const playgroundSizeChangeListener = () => {
40
+ this.playgroundSizeChangeListenerLocalConsole.log(
41
+ JSON.stringify(this.mainView.camera),
42
+ JSON.stringify(this.mainView.size),
43
+ JSON.stringify(this.mainViewSize),
44
+ JSON.stringify(this.mainViewCamera),
45
+ window.outerHeight, window.outerWidth,
46
+ window.visualViewport?.width ?? "null", window.visualViewport?.height ?? "null",
47
+ window.visualViewport?.offsetLeft ?? "null", window.visualViewport?.offsetTop ?? "null",
48
+ );
36
49
  this.sizeChangeHandler(this.mainViewSize);
37
50
  };
38
51
  this.sideEffectManager.add(() => {
@@ -97,6 +110,7 @@ export class MainViewProxy {
97
110
  }
98
111
 
99
112
  public start() {
113
+ console.log("[window-manager] start " + JSON.stringify(this.mainViewSize));
100
114
  this.sizeChangeHandler(this.mainViewSize);
101
115
  if (this.started) return;
102
116
  this.addCameraListener();
@@ -120,6 +134,7 @@ export class MainViewProxy {
120
134
  () => this.mainViewCamera,
121
135
  camera => {
122
136
  if (camera && camera.id !== this.manager.uid) {
137
+ console.log("[window-manager] cameraReaction " + JSON.stringify(camera) + JSON.stringify(this.mainViewSize));
123
138
  this.moveCameraToContian(this.mainViewSize);
124
139
  this.moveCamera(camera);
125
140
  }
@@ -132,12 +147,15 @@ export class MainViewProxy {
132
147
  if (size) {
133
148
  this.moveCameraToContian(size);
134
149
  this.moveCamera(this.mainViewCamera);
150
+ console.log("[window-manager] sizeChangeHandler current size and camera" + JSON.stringify(size) + JSON.stringify(this.mainViewCamera) +
151
+ JSON.stringify(this.mainView.camera) + JSON.stringify(this.mainView.size));
135
152
  }
136
153
  this.ensureMainViewSize();
137
154
  }, 30);
138
155
 
139
156
  public onUpdateContainerSizeRatio = () => {
140
157
  const size = this.store.getMainViewSize();
158
+ console.log("[window-manager] onUpdateContainerSizeRatio " + JSON.stringify(size));
141
159
  this.sizeChangeHandler(size);
142
160
  };
143
161
 
@@ -242,6 +260,7 @@ export class MainViewProxy {
242
260
 
243
261
  private _syncMainViewTimer = 0;
244
262
  private onCameraOrSizeUpdated = () => {
263
+ console.log("[window-manager] onCameraOrSizeUpdated " + JSON.stringify(this.cameraState));
245
264
  callbacks.emit("cameraStateChange", this.cameraState);
246
265
  // sdk >= 2.16.43 的 syncMainView() 可以写入当前 main view 的 camera, 以修复复制粘贴元素的位置
247
266
  // 注意到这个操作会发送信令,应当避免频繁调用
@@ -266,6 +285,7 @@ export class MainViewProxy {
266
285
 
267
286
  private syncMainView = (room: Room) => {
268
287
  if (room.isWritable) {
288
+ console.log("[window-manager] syncMainView ");
269
289
  room.syncMainView(this.mainView);
270
290
  }
271
291
  };
package/src/index.ts CHANGED
@@ -253,6 +253,14 @@ export class WindowManager
253
253
  super(context);
254
254
  WindowManager.displayer = context.displayer;
255
255
  (window as any).NETLESS_DEPS = __APP_DEPENDENCIES__;
256
+ this.visibleStateListener();
257
+ document.addEventListener("visibilitychange", this.visibleStateListener);
258
+ this.emitter.on('mainViewScenePathChange', this.onMainViewScenePathChangeHandler)
259
+ }
260
+
261
+
262
+ private visibleStateListener = () => {
263
+ console.log("[window-manager] visibleStateListener isVisible:" + !document.hidden);
256
264
  }
257
265
 
258
266
  public static onCreate(manager: WindowManager) {
@@ -386,10 +394,27 @@ export class WindowManager
386
394
  console.warn("[WindowManager]: indexedDB open failed");
387
395
  console.log(error);
388
396
  }
389
-
397
+ manager.emitter.on('mainViewScenePathChange', manager.onMainViewScenePathChangeHandler)
390
398
  return manager;
391
399
  }
392
400
 
401
+ public onMainViewScenePathChangeHandler = (scenePath: string) => {
402
+ const mainViewElement = this.mainView.divElement;
403
+ if (mainViewElement) {
404
+ const backgroundImage = mainViewElement.querySelector('.background img');
405
+ if (backgroundImage) {
406
+ // todo 获取到 back ground image 的 rect情况以及css情况是否可见
407
+ const backgroundImageRect = backgroundImage?.getBoundingClientRect();
408
+ const backgroundImageCSS = window.getComputedStyle(backgroundImage);
409
+ const backgroundImageVisible = backgroundImageRect?.width > 0 && backgroundImageRect?.height > 0 && backgroundImageCSS.display !== 'none';
410
+ console.log("[window-manager] backgroundImageVisible" + backgroundImageVisible);
411
+ return;
412
+ }
413
+ console.log("[window-manager] onMainViewScenePathChange" + scenePath + 'backgroundImageVisible is not found');
414
+ }
415
+ console.log("[window-manager] onMainViewScenePathChange" + scenePath + 'mainViewElement is not found');
416
+ }
417
+
393
418
  private static initManager(room: Room): Promise<WindowManager | undefined> {
394
419
  return createInvisiblePlugin(room);
395
420
  }
@@ -1011,7 +1036,6 @@ export class WindowManager
1011
1036
  const mainViewCamera = { ...this.mainView.camera };
1012
1037
  if (isEqual({ ...mainViewCamera, ...pureCamera }, mainViewCamera)) return;
1013
1038
  this.mainView.moveCamera(camera);
1014
- // this.appManager?.dispatchInternalEvent(Events.MoveCamera, camera);
1015
1039
  setTimeout(() => {
1016
1040
  this.appManager?.mainViewProxy.setCameraAndSize();
1017
1041
  }, 500);
@@ -1023,8 +1047,8 @@ export class WindowManager
1023
1047
  animationMode?: AnimationMode;
1024
1048
  }>
1025
1049
  ): void {
1050
+ console.log("[window-manager] moveCameraToContain" + JSON.stringify(rectangle));
1026
1051
  this.mainView.moveCameraToContain(rectangle);
1027
- // this.appManager?.dispatchInternalEvent(Events.MoveCameraToContain, rectangle);
1028
1052
  setTimeout(() => {
1029
1053
  this.appManager?.mainViewProxy.setCameraAndSize();
1030
1054
  }, 500);
@@ -1059,6 +1083,8 @@ export class WindowManager
1059
1083
  WindowManager.playground.parentNode?.removeChild(WindowManager.playground);
1060
1084
  }
1061
1085
  WindowManager.params = undefined;
1086
+ document.removeEventListener("visibilitychange", this.visibleStateListener);
1087
+ this.emitter.off('mainViewScenePathChange', this.onMainViewScenePathChangeHandler);
1062
1088
  this._iframeBridge?.destroy();
1063
1089
  this._iframeBridge = undefined;
1064
1090
  log("Destroyed");