@netless/window-manager 1.0.0-canary.6 → 1.0.0-canary.61

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 (111) hide show
  1. package/README.md +30 -6
  2. package/dist/index.js +13539 -0
  3. package/dist/index.mjs +13536 -0
  4. package/dist/index.umd.js +13534 -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} +11 -6
  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 +2 -1
  24. package/dist/{Page → src/Page}/index.d.ts +0 -0
  25. package/dist/{PageState.d.ts → src/PageState.d.ts} +0 -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 +1 -1
  36. package/dist/{Utils → src/Utils}/log.d.ts +0 -0
  37. package/dist/src/View/CameraSynchronizer.d.ts +20 -0
  38. package/dist/{View → src/View}/MainView.d.ts +18 -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} +13 -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} +66 -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} +18 -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/pnpm-lock.yaml +3141 -4483
  56. package/src/App/AppContext.ts +81 -46
  57. package/src/App/AppProxy.ts +249 -139
  58. package/src/App/WhiteboardView.ts +38 -14
  59. package/src/App/index.ts +1 -0
  60. package/src/App/type.ts +22 -0
  61. package/src/AppListener.ts +21 -21
  62. package/src/AppManager.ts +84 -43
  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 +16 -5
  68. package/src/Cursor/icons.ts +6 -0
  69. package/src/Cursor/index.ts +13 -10
  70. package/src/Helper.ts +25 -7
  71. package/src/InternalEmitter.ts +1 -4
  72. package/src/Page/PageController.ts +2 -1
  73. package/src/PageState.ts +1 -1
  74. package/src/ReconnectRefresher.ts +6 -2
  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 +2 -2
  82. package/src/View/CameraSynchronizer.ts +52 -37
  83. package/src/View/MainView.ts +118 -76
  84. package/src/View/ScrollMode.ts +239 -0
  85. package/src/View/ViewSync.ts +139 -6
  86. package/src/callback.ts +9 -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 +202 -58
  92. package/src/storage.ts +15 -0
  93. package/src/style.css +18 -47
  94. package/src/typings.ts +21 -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 -16159
  107. package/src/App/AppViewSync.ts +0 -68
  108. package/src/App/Storage/StorageEvent.ts +0 -21
  109. package/src/App/Storage/index.ts +0 -295
  110. package/src/App/Storage/typings.ts +0 -23
  111. package/src/App/Storage/utils.ts +0 -17
@@ -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,12 @@ export class AppListeners {
141
133
  }
142
134
  }
143
135
  }
136
+
137
+ private moveCameraHandler = (payload: Camera) => {
138
+ this.manager.mainView.moveCamera(payload);
139
+ }
140
+
141
+ private moveCameraToContainHandler = (payload: Rectangle & { animationMode?: AnimationMode }) => {
142
+ this.manager.mainView.moveCameraToContain(payload);
143
+ }
144
144
  }
package/src/AppManager.ts CHANGED
@@ -18,6 +18,7 @@ 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,7 +40,7 @@ import type {
38
40
  ScenesCallbacksNode,
39
41
  SceneState,
40
42
  RoomState,
41
- } from "white-web-sdk";
43
+ Size} from "white-web-sdk";
42
44
  import type { AddAppParams, BaseInsertParams, TeleBoxRect } from "./index";
43
45
  import type {
44
46
  BoxClosePayload,
@@ -48,6 +50,7 @@ import type {
48
50
  BoxStateChangePayload,
49
51
  } from "./BoxEmitter";
50
52
  import type { Member } from "./Helper";
53
+ import { ScrollMode } from "./View/ScrollMode";
51
54
 
52
55
  export class AppManager {
53
56
  public displayer: Displayer;
@@ -62,11 +65,15 @@ export class AppManager {
62
65
 
63
66
  private appListeners: AppListeners;
64
67
  public boxManager?: BoxManager;
68
+ public scrollMode?: ScrollMode;
69
+ public scrollBaseSize$ = new Val<Size | null>(null);
65
70
 
66
- private _prevSceneIndex: number | undefined;
67
- private _prevFocused: string | undefined;
68
71
  private callbacksNode: ScenesCallbacksNode | null = null;
69
72
  private appCreateQueue = new AppCreateQueue();
73
+ private sceneIndex$ = new Val<number | undefined>(undefined);
74
+ private focused$ = new Val<string | undefined>(undefined);
75
+ public members$ = new Val<Member[]>([]);
76
+ public isWritable$ = new Val<boolean>(Boolean(this.room?.isWritable));
70
77
 
71
78
  private sideEffectManager = new SideEffectManager();
72
79
 
@@ -74,6 +81,7 @@ export class AppManager {
74
81
 
75
82
  public rootDirRemoving = false;
76
83
 
84
+
77
85
  constructor(public windowManger: WindowManager) {
78
86
  this.displayer = windowManger.displayer;
79
87
  this.store.setContext({
@@ -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: isNaN(payload.x) ? 0 : payload.x,
399
+ y: isNaN(payload.y) ? 0 : payload.y,
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
  () => {
@@ -426,27 +445,28 @@ export class AppManager {
426
445
  };
427
446
 
428
447
  private onMainViewIndexChange = (index: number) => {
429
- if (index !== undefined && this._prevSceneIndex !== index) {
448
+ if (index !== undefined && this.sceneIndex$.value !== index) {
430
449
  callbacks.emit("mainViewSceneIndexChange", index);
431
450
  emitter.emit("changePageState");
432
451
  if (this.callbacksNode) {
433
452
  this.updateSceneState(this.callbacksNode);
434
453
  }
435
- this._prevSceneIndex = index;
454
+ this.sceneIndex$.setValue(index);
436
455
  }
437
456
  };
438
457
 
439
458
  private onFocusChange = (focused: string | undefined) => {
440
- if (this._prevFocused !== focused) {
459
+ if (this.focused$.value !== focused) {
441
460
  callbacks.emit("focusedChange", focused);
442
- emitter.emit("focusedChange", { focused, prev: this._prevFocused });
443
- this._prevFocused = focused;
461
+ emitter.emit("focusedChange", { focused, prev: this.focused$.value });
462
+ this.focused$.setValue(focused);
444
463
  if (focused !== undefined) {
445
464
  this.boxManager?.focusBox({ appId: focused });
446
465
  // 确保 focus 修改的时候, appProxy 已经创建
447
466
  setTimeout(() => {
448
467
  const appProxy = this.appProxies.get(focused);
449
468
  if (appProxy) {
469
+ appProxy.onFocus();
450
470
  appRegister.notifyApp(appProxy.kind, "focus", { appId: focused });
451
471
  }
452
472
  }, 0);
@@ -460,9 +480,9 @@ export class AppManager {
460
480
  );
461
481
 
462
482
  /**
463
- * 插件更新 attributes 时的回调
483
+ * 插件更新 apps 时的回调
464
484
  *
465
- * @param {*} attributes
485
+ * @param {*} apps
466
486
  * @memberof WindowManager
467
487
  */
468
488
  public async _attributesUpdateCallback(apps: any) {
@@ -471,14 +491,28 @@ export class AppManager {
471
491
  if (appIds.length === 0) {
472
492
  this.appCreateQueue.emitReady();
473
493
  }
474
- const appsWithCreatedAt = appIds.map(appId => {
475
- return {
476
- id: appId,
477
- createdAt: apps[appId].createdAt,
478
- };
494
+ let appsWithCreatedAt = appIds.map(appId => {
495
+ // 兼容 1.0 之前创建的应用
496
+ if (apps[appId].setup === true || apps[appId].setup === undefined) {
497
+ return {
498
+ id: appId,
499
+ createdAt: apps[appId].createdAt,
500
+ };
501
+ } else {
502
+ return {};
503
+ }
479
504
  });
505
+ // 兼容 1.0 之前版本的回放, 回放时直接过判断 setup 直接创建 app
506
+ if (this.isReplay) {
507
+ appsWithCreatedAt = appIds.map(appId => {
508
+ return {
509
+ id: appId,
510
+ createdAt: apps[appId].createdAt,
511
+ };
512
+ });
513
+ }
480
514
  for (const { id } of orderBy(appsWithCreatedAt, "createdAt", "asc")) {
481
- if (!this.appProxies.has(id) && !this.appStatus.has(id)) {
515
+ if (id && !this.appProxies.has(id) && !this.appStatus.has(id)) {
482
516
  const app = apps[id];
483
517
  try {
484
518
  const appAttributes = this.attributes[id];
@@ -536,6 +570,7 @@ export class AppManager {
536
570
 
537
571
  public setBoxManager(boxManager: BoxManager) {
538
572
  this.boxManager = boxManager;
573
+ this.mainViewProxy.createViewSync();
539
574
  }
540
575
 
541
576
  public resetMaximized() {
@@ -565,11 +600,14 @@ export class AppManager {
565
600
  public bindMainView(divElement: HTMLDivElement, disableCameraTransform: boolean) {
566
601
  const mainView = this.mainViewProxy.view;
567
602
  mainView.disableCameraTransform = disableCameraTransform;
568
- mainView.divElement = divElement;
603
+ // 延迟挂载 mainView dom, 避免因为同步 camera 的闪动
604
+ wait(30).then(() => {
605
+ mainView.divElement = divElement;
606
+ emitter.emit("mainViewMounted");
607
+ });
569
608
  if (!mainView.focusScenePath) {
570
609
  this.setMainViewFocusPath();
571
610
  }
572
- emitter.emit("mainViewMounted");
573
611
  }
574
612
 
575
613
  public setMainViewFocusPath(scenePath?: string) {
@@ -589,6 +627,7 @@ export class AppManager {
589
627
 
590
628
  public async addApp(params: AddAppParams, isDynamicPPT: boolean): Promise<string | undefined> {
591
629
  log("addApp", params);
630
+ // 初始化 app 的属性创建
592
631
  const { appId, needFocus } = await this.beforeAddApp(params, isDynamicPPT);
593
632
  const appProxy = await this.baseInsertApp(params, appId, true, needFocus);
594
633
  this.afterAddApp(appProxy);
@@ -600,6 +639,7 @@ export class AppManager {
600
639
  this.appStatus.set(appId, AppStatus.StartCreate);
601
640
  const attrs = params.attributes ?? {};
602
641
  this.safeUpdateAttributes([appId], attrs);
642
+ // 初始化的时候时需要一些异步的工作, 完成后其他端才可以创建
603
643
  this.store.setupAppAttributes(params, appId, isDynamicPPT);
604
644
  const needFocus = !this.boxManager?.minimized;
605
645
  if (needFocus) {
@@ -666,7 +706,7 @@ export class AppManager {
666
706
  appProxy.appEmitter.emit("roomStateChange", state);
667
707
  });
668
708
  if (state.roomMembers) {
669
- emitter.emit("roomMembersChange", this.members);
709
+ this.members$.setValue(serializeRoomMembers(state.roomMembers));
670
710
  }
671
711
  emitter.emit("observerIdChange", this.displayer.observerId);
672
712
  if (state.memberState) {
@@ -677,7 +717,7 @@ export class AppManager {
677
717
  public displayerWritableListener = (isReadonly: boolean) => {
678
718
  const isWritable = !isReadonly;
679
719
  const isManualWritable =
680
- this.windowManger.readonly === undefined || this.windowManger.readonly === false;
720
+ this.windowManger.readonly === undefined || !this.windowManger.readonly;
681
721
  if (this.windowManger.readonly === undefined) {
682
722
  this.boxManager?.setReadonly(isReadonly);
683
723
  } else {
@@ -686,15 +726,13 @@ export class AppManager {
686
726
  this.appProxies.forEach(appProxy => {
687
727
  appProxy.emitAppIsWritableChange();
688
728
  });
689
- if (isWritable === true) {
690
- this.mainView.disableCameraTransform = false;
729
+ if (isWritable) {
691
730
  if (this.room && this.room.disableSerialization === true) {
692
731
  this.room.disableSerialization = false;
693
732
  }
694
- } else {
695
- this.mainView.disableCameraTransform = true;
696
733
  }
697
734
  emitter.emit("writableChange", isWritable);
735
+ this.isWritable$.setValue(isWritable);
698
736
  };
699
737
 
700
738
  public safeSetAttributes(attributes: any) {
@@ -796,6 +834,7 @@ export class AppManager {
796
834
  }
797
835
 
798
836
  public async onReconnected() {
837
+ this.attributesUpdateCallback(this.attributes.apps);
799
838
  const appProxies = Array.from(this.appProxies.values());
800
839
  const reconnected = appProxies.map(appProxy => {
801
840
  return appProxy.onReconnected();
@@ -834,7 +873,9 @@ export class AppManager {
834
873
  }
835
874
  callbacks.clearListeners();
836
875
  this.sideEffectManager.flushAll();
837
- this._prevFocused = undefined;
838
- this._prevSceneIndex = undefined;
876
+ this.sceneIndex$.destroy();
877
+ this.focused$.destroy();
878
+ this.members$.destroy();
879
+ this.scrollMode?.dispose();
839
880
  }
840
881
  }
@@ -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
  }