@netless/window-manager 1.0.0-canary.7 → 1.0.0-canary.71

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.
Files changed (112) hide show
  1. package/README.md +30 -6
  2. package/dist/index.js +13625 -0
  3. package/dist/index.mjs +13622 -0
  4. package/dist/index.umd.js +13620 -46
  5. package/dist/{App → src/App}/AppContext.d.ts +16 -14
  6. package/dist/{App → src/App}/AppPageStateImpl.d.ts +0 -0
  7. package/dist/{App → src/App}/AppProxy.d.ts +30 -11
  8. package/dist/{App → src/App}/MagixEvent/index.d.ts +0 -0
  9. package/dist/src/App/WhiteboardView.d.ts +27 -0
  10. package/dist/{App → src/App}/index.d.ts +1 -0
  11. package/dist/src/App/type.d.ts +21 -0
  12. package/dist/{AppListener.d.ts → src/AppListener.d.ts} +2 -2
  13. package/dist/{AppManager.d.ts → src/AppManager.d.ts} +12 -7
  14. package/dist/{AttributesDelegate.d.ts → src/AttributesDelegate.d.ts} +5 -2
  15. package/dist/{BoxEmitter.d.ts → src/BoxEmitter.d.ts} +0 -0
  16. package/dist/{BoxManager.d.ts → src/BoxManager.d.ts} +12 -6
  17. package/dist/{BuiltinApps.d.ts → src/BuiltinApps.d.ts} +3 -0
  18. package/dist/{Cursor → src/Cursor}/Cursor.d.ts +0 -0
  19. package/dist/{Cursor → src/Cursor}/icons.d.ts +0 -0
  20. package/dist/{Cursor → src/Cursor}/index.d.ts +4 -3
  21. package/dist/{Helper.d.ts → src/Helper.d.ts} +4 -8
  22. package/dist/{InternalEmitter.d.ts → src/InternalEmitter.d.ts} +1 -4
  23. package/dist/{Page → src/Page}/PageController.d.ts +3 -1
  24. package/dist/{Page → src/Page}/index.d.ts +0 -0
  25. package/dist/{PageState.d.ts → src/PageState.d.ts} +1 -0
  26. package/dist/{ReconnectRefresher.d.ts → src/ReconnectRefresher.d.ts} +0 -0
  27. package/dist/{RedoUndo.d.ts → src/RedoUndo.d.ts} +0 -0
  28. package/dist/{Register → src/Register}/index.d.ts +4 -2
  29. package/dist/{Register → src/Register}/loader.d.ts +1 -1
  30. package/dist/src/Register/storage.d.ts +11 -0
  31. package/dist/{Utils → src/Utils}/AppCreateQueue.d.ts +0 -0
  32. package/dist/{Utils → src/Utils}/Common.d.ts +0 -0
  33. package/dist/{Utils → src/Utils}/Reactive.d.ts +1 -1
  34. package/dist/{Utils → src/Utils}/RoomHacker.d.ts +0 -0
  35. package/dist/{Utils → src/Utils}/error.d.ts +4 -1
  36. package/dist/{Utils → src/Utils}/log.d.ts +0 -0
  37. package/dist/src/View/CameraSynchronizer.d.ts +21 -0
  38. package/dist/{View → src/View}/MainView.d.ts +25 -7
  39. package/dist/src/View/ScrollMode.d.ts +32 -0
  40. package/dist/{View → src/View}/ViewManager.d.ts +0 -0
  41. package/dist/src/View/ViewSync.d.ts +32 -0
  42. package/dist/{callback.d.ts → src/callback.d.ts} +12 -1
  43. package/dist/{constants.d.ts → src/constants.d.ts} +12 -5
  44. package/dist/src/image.d.ts +19 -0
  45. package/dist/{index.d.ts → src/index.d.ts} +63 -17
  46. package/dist/src/shim.d.ts +11 -0
  47. package/dist/src/storage.d.ts +7 -0
  48. package/dist/{typings.d.ts → src/typings.d.ts} +21 -8
  49. package/dist/style.css +810 -1
  50. package/docs/api.md +10 -0
  51. package/docs/app-context.md +155 -27
  52. package/docs/mirgrate-to-1.0.md +68 -0
  53. package/package.json +27 -22
  54. package/playwright.config.ts +29 -0
  55. package/src/App/AppContext.ts +81 -46
  56. package/src/App/AppPageStateImpl.ts +3 -0
  57. package/src/App/AppProxy.ts +249 -141
  58. package/src/App/WhiteboardView.ts +37 -14
  59. package/src/App/index.ts +1 -0
  60. package/src/App/type.ts +22 -0
  61. package/src/AppListener.ts +27 -21
  62. package/src/AppManager.ts +96 -50
  63. package/src/AttributesDelegate.ts +6 -3
  64. package/src/BoxManager.ts +76 -38
  65. package/src/BuiltinApps.ts +9 -8
  66. package/src/Cursor/Cursor.svelte +6 -2
  67. package/src/Cursor/Cursor.ts +15 -4
  68. package/src/Cursor/icons.ts +6 -0
  69. package/src/Cursor/index.ts +16 -11
  70. package/src/Helper.ts +25 -7
  71. package/src/InternalEmitter.ts +1 -4
  72. package/src/Page/PageController.ts +3 -1
  73. package/src/PageState.ts +8 -1
  74. package/src/ReconnectRefresher.ts +7 -3
  75. package/src/Register/index.ts +36 -14
  76. package/src/Register/loader.ts +20 -9
  77. package/src/Register/storage.ts +26 -5
  78. package/src/Utils/Common.ts +3 -0
  79. package/src/Utils/Reactive.ts +29 -27
  80. package/src/Utils/RoomHacker.ts +3 -0
  81. package/src/Utils/error.ts +6 -2
  82. package/src/View/CameraSynchronizer.ts +55 -36
  83. package/src/View/MainView.ts +163 -77
  84. package/src/View/ScrollMode.ts +240 -0
  85. package/src/View/ViewSync.ts +138 -6
  86. package/src/callback.ts +8 -1
  87. package/src/constants.ts +11 -3
  88. package/src/image/pencil-eraser-1.svg +3 -0
  89. package/src/image/pencil-eraser-2.svg +3 -0
  90. package/src/image/pencil-eraser-3.svg +3 -0
  91. package/src/index.ts +197 -60
  92. package/src/storage.ts +15 -0
  93. package/src/style.css +18 -47
  94. package/src/typings.ts +24 -7
  95. package/vite.config.js +12 -7
  96. package/dist/App/AppViewSync.d.ts +0 -11
  97. package/dist/App/Storage/StorageEvent.d.ts +0 -8
  98. package/dist/App/Storage/index.d.ts +0 -39
  99. package/dist/App/Storage/typings.d.ts +0 -22
  100. package/dist/App/Storage/utils.d.ts +0 -5
  101. package/dist/App/WhiteboardView.d.ts +0 -21
  102. package/dist/Register/storage.d.ts +0 -8
  103. package/dist/View/CameraSynchronizer.d.ts +0 -17
  104. package/dist/View/ViewSync.d.ts +0 -7
  105. package/dist/index.cjs.js +0 -46
  106. package/dist/index.es.js +0 -16161
  107. package/pnpm-lock.yaml +0 -6302
  108. package/src/App/AppViewSync.ts +0 -68
  109. package/src/App/Storage/StorageEvent.ts +0 -21
  110. package/src/App/Storage/index.ts +0 -295
  111. package/src/App/Storage/typings.ts +0 -23
  112. package/src/App/Storage/utils.ts +0 -17
@@ -0,0 +1,22 @@
1
+
2
+ export type AppState = {
3
+ id: string;
4
+ focus?: boolean;
5
+ SceneIndex?: number;
6
+ draggable?: boolean;
7
+ position?: {
8
+ x: number;
9
+ y: number;
10
+ }
11
+ ratio?: number;
12
+ resizable?: boolean;
13
+ size?: {
14
+ width: number;
15
+ height: number;
16
+ }
17
+ stageRatio?: number;
18
+ visible?: boolean;
19
+ zIndex?: number;
20
+ maximized: boolean | null;
21
+ minimized: boolean | null;
22
+ }
@@ -1,9 +1,8 @@
1
1
  import { callbacks } from "./callback";
2
2
  import { emitter } from "./InternalEmitter";
3
3
  import { Events, MagixEventName } from "./constants";
4
- import { isEqual, omit } from "lodash";
5
4
  import { setViewFocusScenePath } from "./Utils/Common";
6
- import type { AnimationMode, Camera, Event } from "white-web-sdk";
5
+ import type { AnimationMode, Camera, Event, Rectangle } from "white-web-sdk";
7
6
  import type { AppManager } from "./AppManager";
8
7
  import type { TeleBoxState } from "@netless/telebox-insider";
9
8
 
@@ -50,14 +49,6 @@ export class AppListeners {
50
49
  this.setMainViewScenePathHandler(data.payload);
51
50
  break;
52
51
  }
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
52
  case Events.CursorMove: {
62
53
  this.cursorMoveHandler(data.payload);
63
54
  break;
@@ -78,6 +69,18 @@ export class AppListeners {
78
69
  this.setAppFocusViewIndexHandler(data.payload);
79
70
  break;
80
71
  }
72
+ case Events.InvokeAttributesUpdateCallback: {
73
+ this.manager.attributesUpdateCallback(this.manager.attributes.apps);
74
+ break;
75
+ }
76
+ case Events.MoveCamera: {
77
+ this.moveCameraHandler(data.payload);
78
+ break;
79
+ }
80
+ case Events.MoveCameraToContain: {
81
+ this.moveCameraToContainHandler(data.payload);
82
+ break;
83
+ }
81
84
  default:
82
85
  break;
83
86
  }
@@ -102,17 +105,6 @@ export class AppListeners {
102
105
  callbacks.emit("mainViewScenePathChange", nextScenePath);
103
106
  };
104
107
 
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
108
  private cursorMoveHandler = (payload: any) => {
117
109
  emitter.emit("cursorMove", payload);
118
110
  };
@@ -141,4 +133,18 @@ export class AppListeners {
141
133
  }
142
134
  }
143
135
  }
136
+
137
+ private moveCameraHandler = (payload: Camera) => {
138
+ const size$ = this.manager.mainViewProxy.size$;
139
+ if (size$.value) {
140
+ const size = this.manager.mainView.size;
141
+ const diff = Math.max(size.height / size$.value.height, size.width / size$.value.width);
142
+ const nextCamera = { ...payload, scale: payload.scale * diff };
143
+ this.manager.mainView.moveCamera(nextCamera);
144
+ }
145
+ }
146
+
147
+ private moveCameraToContainHandler = (payload: Rectangle & { animationMode?: AnimationMode }) => {
148
+ this.manager.mainView.moveCameraToContain(payload);
149
+ }
144
150
  }
package/src/AppManager.ts CHANGED
@@ -3,7 +3,7 @@ import { AppCreateQueue } from "./Utils/AppCreateQueue";
3
3
  import { AppListeners } from "./AppListener";
4
4
  import { AppProxy } from "./App";
5
5
  import { appRegister } from "./Register";
6
- import { autorun, isPlayer, isRoom, ScenePathType, toJS } from "white-web-sdk";
6
+ import { autorun, isPlayer, isRoom, ScenePathType, toJS, UpdateEventKind } from "white-web-sdk";
7
7
  import { boxEmitter } from "./BoxEmitter";
8
8
  import { calculateNextIndex } from "./Page";
9
9
  import { callbacks } from "./callback";
@@ -12,12 +12,13 @@ import { emitter } from "./InternalEmitter";
12
12
  import { Fields, store } from "./AttributesDelegate";
13
13
  import { log } from "./Utils/log";
14
14
  import { MainViewProxy } from "./View/MainView";
15
- import { onObjectRemoved, safeListenPropsUpdated } from "./Utils/Reactive";
15
+ import { safeListenPropsUpdated } from "./Utils/Reactive";
16
16
  import { reconnectRefresher, WindowManager } from "./index";
17
17
  import { RedoUndo } from "./RedoUndo";
18
18
  import { serializeRoomMembers } from "./Helper";
19
19
  import { SideEffectManager } from "side-effect-manager";
20
20
  import { ViewManager } from "./View/ViewManager";
21
+ import { Val } from "value-enhancer";
21
22
  import type { SyncRegisterAppPayload } from "./Register";
22
23
  import type { RemoveSceneParams } from "./InternalEmitter";
23
24
  import {
@@ -29,6 +30,7 @@ import {
29
30
  removeScenes,
30
31
  setScenePath,
31
32
  setViewFocusScenePath,
33
+ wait,
32
34
  } from "./Utils/Common";
33
35
  import type { ReconnectRefresher } from "./ReconnectRefresher";
34
36
  import type { BoxManager } from "./BoxManager";
@@ -38,6 +40,7 @@ import type {
38
40
  ScenesCallbacksNode,
39
41
  SceneState,
40
42
  RoomState,
43
+ Size,
41
44
  } from "white-web-sdk";
42
45
  import type { AddAppParams, BaseInsertParams, TeleBoxRect } from "./index";
43
46
  import type {
@@ -48,6 +51,7 @@ import type {
48
51
  BoxStateChangePayload,
49
52
  } from "./BoxEmitter";
50
53
  import type { Member } from "./Helper";
54
+ import { ScrollMode } from "./View/ScrollMode";
51
55
 
52
56
  export class AppManager {
53
57
  public displayer: Displayer;
@@ -62,11 +66,15 @@ export class AppManager {
62
66
 
63
67
  private appListeners: AppListeners;
64
68
  public boxManager?: BoxManager;
69
+ public scrollMode?: ScrollMode;
70
+ public scrollBaseSize$ = new Val<Size | null>(null);
65
71
 
66
- private _prevSceneIndex: number | undefined;
67
- private _prevFocused: string | undefined;
68
- private callbacksNode: ScenesCallbacksNode | null = null;
72
+ public callbacksNode: ScenesCallbacksNode | null = null;
69
73
  private appCreateQueue = new AppCreateQueue();
74
+ private sceneIndex$ = new Val<number | undefined>(undefined);
75
+ private focused$ = new Val<string | undefined>(undefined);
76
+ public members$ = new Val<Member[]>([]);
77
+ public isWritable$ = new Val<boolean>(Boolean(this.room?.isWritable));
70
78
 
71
79
  private sideEffectManager = new SideEffectManager();
72
80
 
@@ -119,6 +127,21 @@ export class AppManager {
119
127
  appRegister.setSyncRegisterApp(payload => {
120
128
  this.safeUpdateAttributes([Fields.Registered, payload.kind], payload);
121
129
  });
130
+ this.members$.setValue(serializeRoomMembers(this.displayer.state.roomMembers));
131
+
132
+ emitter.on("mainViewMounted", () => {
133
+ this.windowManger.viewMode$.subscribe(viewMode => {
134
+ const playground = this.windowManger.playground$.value;
135
+ if (viewMode === "scroll" && playground) {
136
+ const scrollMode = new ScrollMode(this);
137
+ this.scrollMode = scrollMode;
138
+ scrollMode.setRoot(playground);
139
+ } else {
140
+ this.scrollMode?.dispose();
141
+ this.scrollMode = undefined;
142
+ }
143
+ });
144
+ });
122
145
  }
123
146
 
124
147
  private onRemoveScenes = async (params: RemoveSceneParams) => {
@@ -137,7 +160,7 @@ export class AppManager {
137
160
  sceneName = this.callbacksNode?.scenes[nextIndex];
138
161
  }
139
162
  if (sceneName) {
140
- this.setMainViewScenePath(`${ROOT_DIR}${sceneName}`);
163
+ await this.setMainViewScenePath(`${ROOT_DIR}${sceneName}`);
141
164
  }
142
165
  await this.setMainViewSceneIndex(nextIndex);
143
166
  } else {
@@ -152,7 +175,7 @@ export class AppManager {
152
175
  * 所以需要关掉所有开启了 view 的 app
153
176
  */
154
177
  public async onRootDirRemoved(needClose = true) {
155
- this.setMainViewScenePath(INIT_DIR);
178
+ await this.setMainViewScenePath(INIT_DIR);
156
179
  this.createRootDirScenesCallback();
157
180
 
158
181
  for (const [id, appProxy] of this.appProxies.entries()) {
@@ -160,9 +183,9 @@ export class AppManager {
160
183
  await this.closeApp(id, needClose);
161
184
  }
162
185
  }
163
- // 删除了根目录的 scenes 之后 mainview 需要重新绑定, 否则主白板会不能渲染
186
+ // 删除了根目录的 scenes 之后 main-view 需要重新绑定, 否则主白板会不能渲染
164
187
  this.mainViewProxy.rebind();
165
- emitter.emit("rootDirRemoved");
188
+ await emitter.emit("rootDirRemoved");
166
189
  this.updateRootDirRemoving(false);
167
190
  }
168
191
 
@@ -300,10 +323,6 @@ export class AppManager {
300
323
  return this.room?.uid || "";
301
324
  }
302
325
 
303
- public get members(): Member[] {
304
- return serializeRoomMembers(this.displayer.state.roomMembers);
305
- }
306
-
307
326
  public getMainViewSceneDir() {
308
327
  const scenePath = this.store.getMainViewScenePath();
309
328
  if (scenePath) {
@@ -324,31 +343,31 @@ export class AppManager {
324
343
 
325
344
  this.addAppsChangeListener();
326
345
  this.addAppCloseListener();
327
- this.refresher?.add("maximized", () => {
346
+ this.refresher.add("maximized", () => {
328
347
  return autorun(() => {
329
348
  const maximized = this.attributes.maximized;
330
349
  this.boxManager?.setMaximized(Boolean(maximized));
331
350
  });
332
351
  });
333
- this.refresher?.add("minimized", () => {
352
+ this.refresher.add("minimized", () => {
334
353
  return autorun(() => {
335
354
  const minimized = this.attributes.minimized;
336
355
  this.onMinimized(minimized);
337
356
  });
338
357
  });
339
- this.refresher?.add("mainViewIndex", () => {
358
+ this.refresher.add("mainViewIndex", () => {
340
359
  return autorun(() => {
341
360
  const mainSceneIndex = get(this.attributes, "_mainSceneIndex");
342
361
  this.onMainViewIndexChange(mainSceneIndex);
343
362
  });
344
363
  });
345
- this.refresher?.add("focusedChange", () => {
364
+ this.refresher.add("focusedChange", () => {
346
365
  return autorun(() => {
347
366
  const focused = get(this.attributes, "focus");
348
367
  this.onFocusChange(focused);
349
368
  });
350
369
  });
351
- this.refresher?.add("registeredChange", () => {
370
+ this.refresher.add("registeredChange", () => {
352
371
  return autorun(() => {
353
372
  const registered = get(this.attributes, Fields.Registered);
354
373
  this.onRegisteredChange(registered);
@@ -361,7 +380,7 @@ export class AppManager {
361
380
  }
362
381
  this.displayerWritableListener(!this.room?.isWritable);
363
382
  this.displayer.callbacks.on("onEnableWriteNowChanged", this.displayerWritableListener);
364
- this._prevFocused = this.attributes.focus;
383
+ this.focused$.setValue(this.attributes.focus);
365
384
 
366
385
  this.sideEffectManager.add(() => {
367
386
  const redoUndo = new RedoUndo({
@@ -376,8 +395,8 @@ export class AppManager {
376
395
  private onBoxMove = (payload: BoxMovePayload) => {
377
396
  this.dispatchInternalEvent(Events.AppMove, payload);
378
397
  this.store.updateAppState(payload.appId, AppAttributes.Position, {
379
- x: payload.x,
380
- y: payload.y,
398
+ x: payload.x || 0,
399
+ y: payload.y || 0,
381
400
  });
382
401
  };
383
402
 
@@ -407,7 +426,7 @@ export class AppManager {
407
426
  };
408
427
 
409
428
  public addAppsChangeListener = () => {
410
- this.refresher?.add("apps", () => {
429
+ this.refresher.add("apps", () => {
411
430
  return safeListenPropsUpdated(
412
431
  () => this.attributes.apps,
413
432
  () => {
@@ -419,34 +438,40 @@ export class AppManager {
419
438
 
420
439
  public addAppCloseListener = () => {
421
440
  this.refresher?.add("appsClose", () => {
422
- return onObjectRemoved(this.attributes.apps, () => {
423
- this.onAppDelete(this.attributes.apps);
424
- });
441
+ return safeListenPropsUpdated(
442
+ () => this.attributes.apps,
443
+ events => {
444
+ if (events.some(e => e.kind === UpdateEventKind.Removed)) {
445
+ this.onAppDelete(this.attributes.apps);
446
+ }
447
+ }
448
+ );
425
449
  });
426
450
  };
427
451
 
428
452
  private onMainViewIndexChange = (index: number) => {
429
- if (index !== undefined && this._prevSceneIndex !== index) {
453
+ if (index !== undefined && this.sceneIndex$.value !== index) {
430
454
  callbacks.emit("mainViewSceneIndexChange", index);
431
455
  emitter.emit("changePageState");
432
456
  if (this.callbacksNode) {
433
457
  this.updateSceneState(this.callbacksNode);
434
458
  }
435
- this._prevSceneIndex = index;
459
+ this.sceneIndex$.setValue(index);
436
460
  }
437
461
  };
438
462
 
439
463
  private onFocusChange = (focused: string | undefined) => {
440
- if (this._prevFocused !== focused) {
464
+ if (this.focused$.value !== focused) {
441
465
  callbacks.emit("focusedChange", focused);
442
- emitter.emit("focusedChange", { focused, prev: this._prevFocused });
443
- this._prevFocused = focused;
466
+ emitter.emit("focusedChange", { focused, prev: this.focused$.value });
467
+ this.focused$.setValue(focused);
444
468
  if (focused !== undefined) {
445
469
  this.boxManager?.focusBox({ appId: focused });
446
470
  // 确保 focus 修改的时候, appProxy 已经创建
447
471
  setTimeout(() => {
448
472
  const appProxy = this.appProxies.get(focused);
449
473
  if (appProxy) {
474
+ appProxy.onFocus();
450
475
  appRegister.notifyApp(appProxy.kind, "focus", { appId: focused });
451
476
  }
452
477
  }, 0);
@@ -460,9 +485,9 @@ export class AppManager {
460
485
  );
461
486
 
462
487
  /**
463
- * 插件更新 attributes 时的回调
488
+ * 插件更新 apps 时的回调
464
489
  *
465
- * @param {*} attributes
490
+ * @param {*} apps
466
491
  * @memberof WindowManager
467
492
  */
468
493
  public async _attributesUpdateCallback(apps: any) {
@@ -471,14 +496,28 @@ export class AppManager {
471
496
  if (appIds.length === 0) {
472
497
  this.appCreateQueue.emitReady();
473
498
  }
474
- const appsWithCreatedAt = appIds.map(appId => {
475
- return {
476
- id: appId,
477
- createdAt: apps[appId].createdAt,
478
- };
499
+ let appsWithCreatedAt = appIds.map(appId => {
500
+ // 兼容 1.0 之前创建的应用
501
+ if (apps[appId].setup === true || apps[appId].setup === undefined) {
502
+ return {
503
+ id: appId,
504
+ createdAt: apps[appId].createdAt,
505
+ };
506
+ } else {
507
+ return {};
508
+ }
479
509
  });
510
+ // 兼容 1.0 之前版本的回放, 回放时直接过判断 setup 直接创建 app
511
+ if (this.isReplay) {
512
+ appsWithCreatedAt = appIds.map(appId => {
513
+ return {
514
+ id: appId,
515
+ createdAt: apps[appId].createdAt,
516
+ };
517
+ });
518
+ }
480
519
  for (const { id } of orderBy(appsWithCreatedAt, "createdAt", "asc")) {
481
- if (!this.appProxies.has(id) && !this.appStatus.has(id)) {
520
+ if (id && !this.appProxies.has(id) && !this.appStatus.has(id)) {
482
521
  const app = apps[id];
483
522
  try {
484
523
  const appAttributes = this.attributes[id];
@@ -536,6 +575,7 @@ export class AppManager {
536
575
 
537
576
  public setBoxManager(boxManager: BoxManager) {
538
577
  this.boxManager = boxManager;
578
+ this.mainViewProxy.createViewSync();
539
579
  }
540
580
 
541
581
  public resetMaximized() {
@@ -565,11 +605,14 @@ export class AppManager {
565
605
  public bindMainView(divElement: HTMLDivElement, disableCameraTransform: boolean) {
566
606
  const mainView = this.mainViewProxy.view;
567
607
  mainView.disableCameraTransform = disableCameraTransform;
568
- mainView.divElement = divElement;
608
+ // 延迟挂载 mainView dom, 避免因为同步 camera 的闪动
609
+ wait(30).then(() => {
610
+ mainView.divElement = divElement;
611
+ emitter.emit("mainViewMounted");
612
+ });
569
613
  if (!mainView.focusScenePath) {
570
614
  this.setMainViewFocusPath();
571
615
  }
572
- emitter.emit("mainViewMounted");
573
616
  }
574
617
 
575
618
  public setMainViewFocusPath(scenePath?: string) {
@@ -589,6 +632,7 @@ export class AppManager {
589
632
 
590
633
  public async addApp(params: AddAppParams, isDynamicPPT: boolean): Promise<string | undefined> {
591
634
  log("addApp", params);
635
+ // 初始化 app 的属性创建
592
636
  const { appId, needFocus } = await this.beforeAddApp(params, isDynamicPPT);
593
637
  const appProxy = await this.baseInsertApp(params, appId, true, needFocus);
594
638
  this.afterAddApp(appProxy);
@@ -600,6 +644,7 @@ export class AppManager {
600
644
  this.appStatus.set(appId, AppStatus.StartCreate);
601
645
  const attrs = params.attributes ?? {};
602
646
  this.safeUpdateAttributes([appId], attrs);
647
+ // 初始化的时候时需要一些异步的工作, 完成后其他端才可以创建
603
648
  this.store.setupAppAttributes(params, appId, isDynamicPPT);
604
649
  const needFocus = !this.boxManager?.minimized;
605
650
  if (needFocus) {
@@ -613,8 +658,8 @@ export class AppManager {
613
658
  const box = appProxy.box;
614
659
  boxEmitter.emit("move", {
615
660
  appId: appProxy.id,
616
- x: box?.intrinsicX,
617
- y: box?.intrinsicY,
661
+ x: box.intrinsicX || 0,
662
+ y: box.intrinsicY || 0,
618
663
  });
619
664
  this.store.updateAppState(appProxy.id, AppAttributes.ZIndex, box.zIndex);
620
665
  }
@@ -666,7 +711,7 @@ export class AppManager {
666
711
  appProxy.appEmitter.emit("roomStateChange", state);
667
712
  });
668
713
  if (state.roomMembers) {
669
- emitter.emit("roomMembersChange", this.members);
714
+ this.members$.setValue(serializeRoomMembers(state.roomMembers));
670
715
  }
671
716
  emitter.emit("observerIdChange", this.displayer.observerId);
672
717
  if (state.memberState) {
@@ -677,7 +722,7 @@ export class AppManager {
677
722
  public displayerWritableListener = (isReadonly: boolean) => {
678
723
  const isWritable = !isReadonly;
679
724
  const isManualWritable =
680
- this.windowManger.readonly === undefined || this.windowManger.readonly === false;
725
+ this.windowManger.readonly === undefined || !this.windowManger.readonly;
681
726
  if (this.windowManger.readonly === undefined) {
682
727
  this.boxManager?.setReadonly(isReadonly);
683
728
  } else {
@@ -686,15 +731,13 @@ export class AppManager {
686
731
  this.appProxies.forEach(appProxy => {
687
732
  appProxy.emitAppIsWritableChange();
688
733
  });
689
- if (isWritable === true) {
690
- this.mainView.disableCameraTransform = false;
734
+ if (isWritable) {
691
735
  if (this.room && this.room.disableSerialization === true) {
692
736
  this.room.disableSerialization = false;
693
737
  }
694
- } else {
695
- this.mainView.disableCameraTransform = true;
696
738
  }
697
739
  emitter.emit("writableChange", isWritable);
740
+ this.isWritable$.setValue(isWritable);
698
741
  };
699
742
 
700
743
  public safeSetAttributes(attributes: any) {
@@ -796,6 +839,7 @@ export class AppManager {
796
839
  }
797
840
 
798
841
  public async onReconnected() {
842
+ this.attributesUpdateCallback(this.attributes.apps);
799
843
  const appProxies = Array.from(this.appProxies.values());
800
844
  const reconnected = appProxies.map(appProxy => {
801
845
  return appProxy.onReconnected();
@@ -834,7 +878,9 @@ export class AppManager {
834
878
  }
835
879
  callbacks.clearListeners();
836
880
  this.sideEffectManager.flushAll();
837
- this._prevFocused = undefined;
838
- this._prevSceneIndex = undefined;
881
+ this.sceneIndex$.destroy();
882
+ this.focused$.destroy();
883
+ this.members$.destroy();
884
+ this.scrollMode?.dispose();
839
885
  }
840
886
  }
@@ -2,7 +2,7 @@ import { AppAttributes } from "./constants";
2
2
  import { get, pick } from "lodash";
3
3
  import { setViewFocusScenePath } from "./Utils/Common";
4
4
  import type { AddAppParams, AppSyncAttributes } from "./index";
5
- import type { Camera, Size, View } from "white-web-sdk";
5
+ import type { Size, View } from "white-web-sdk";
6
6
  import type { Cursor } from "./Cursor/Cursor";
7
7
 
8
8
  export enum Fields {
@@ -41,8 +41,11 @@ export type StoreContext = {
41
41
  safeSetAttributes: (attributes: any) => void;
42
42
  }
43
43
 
44
- export type ICamera = Camera & {
44
+ export type ICamera = & {
45
45
  id: string; // room uid
46
+ centerX: number | null,
47
+ centerY: number | null,
48
+ scale: number
46
49
  };
47
50
 
48
51
  export type ISize = Size & {
@@ -95,7 +98,7 @@ export class AttributesDelegate {
95
98
  attrNames.push("scenes");
96
99
  }
97
100
  const options = pick(params.options, attrNames);
98
- const attrs: AppSyncAttributes = { kind: params.kind, options, isDynamicPPT };
101
+ const attrs: AppSyncAttributes = { kind: params.kind, options, isDynamicPPT, setup: false };
99
102
  if (typeof params.src === "string") {
100
103
  attrs.src = params.src;
101
104
  }