@netless/window-manager 0.4.32 → 1.0.0-canary.2

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 (42) hide show
  1. package/dist/App/AppContext.d.ts +14 -15
  2. package/dist/App/AppPageStateImpl.d.ts +6 -2
  3. package/dist/App/AppProxy.d.ts +5 -2
  4. package/dist/App/WhiteBoardView.d.ts +16 -0
  5. package/dist/App/index.d.ts +1 -0
  6. package/dist/AppManager.d.ts +2 -0
  7. package/dist/BoxManager.d.ts +7 -5
  8. package/dist/Helper.d.ts +12 -4
  9. package/dist/InternalEmitter.d.ts +4 -1
  10. package/dist/View/CameraSynchronizer.d.ts +17 -0
  11. package/dist/View/MainView.d.ts +4 -5
  12. package/dist/constants.d.ts +1 -0
  13. package/dist/index.cjs.js +21 -22
  14. package/dist/index.d.ts +0 -2
  15. package/dist/index.es.js +2186 -1970
  16. package/dist/index.umd.js +21 -22
  17. package/dist/style.css +1 -1
  18. package/dist/typings.d.ts +4 -0
  19. package/package.json +4 -3
  20. package/pnpm-lock.yaml +86 -97
  21. package/src/App/AppContext.ts +58 -73
  22. package/src/App/AppPageStateImpl.ts +25 -6
  23. package/src/App/AppProxy.ts +39 -15
  24. package/src/App/Storage/index.ts +4 -4
  25. package/src/App/WhiteBoardView.ts +68 -0
  26. package/src/App/index.ts +1 -0
  27. package/src/AppManager.ts +9 -1
  28. package/src/BoxManager.ts +102 -107
  29. package/src/Cursor/index.ts +5 -5
  30. package/src/Helper.ts +12 -16
  31. package/src/InternalEmitter.ts +8 -4
  32. package/src/View/CameraSynchronizer.ts +67 -0
  33. package/src/View/MainView.ts +45 -53
  34. package/src/constants.ts +2 -0
  35. package/src/index.ts +13 -33
  36. package/src/typings.ts +4 -0
  37. package/vite.config.js +0 -1
  38. package/dist/ContainerResizeObserver.d.ts +0 -11
  39. package/dist/index.cjs.js.map +0 -1
  40. package/dist/index.es.js.map +0 -1
  41. package/dist/index.umd.js.map +0 -1
  42. package/src/ContainerResizeObserver.ts +0 -73
@@ -12,6 +12,7 @@ import { log } from "../Utils/log";
12
12
  import {
13
13
  entireScenes,
14
14
  getScenePath,
15
+ putScenes,
15
16
  removeScenes,
16
17
  setScenePath,
17
18
  setViewFocusScenePath,
@@ -30,6 +31,7 @@ import type { ReadonlyTeleBox } from "@netless/telebox-insider";
30
31
  import type { PageRemoveService, PageState } from "../Page";
31
32
  import { calculateNextIndex } from "../Page";
32
33
  import { boxEmitter } from "../BoxEmitter";
34
+ import { SideEffectManager } from "side-effect-manager";
33
35
 
34
36
  export type AppEmitter = Emittery<AppEmitterEvent>;
35
37
 
@@ -37,6 +39,7 @@ export class AppProxy implements PageRemoveService {
37
39
  public kind: string;
38
40
  public id: string;
39
41
  public scenePath?: string;
42
+ private appScenePath: string;
40
43
  public appEmitter: AppEmitter;
41
44
  public scenes?: SceneDefinition[];
42
45
 
@@ -49,12 +52,14 @@ export class AppProxy implements PageRemoveService {
49
52
  public isAddApp: boolean;
50
53
  private status: "normal" | "destroyed" = "normal";
51
54
  private stateKey: string;
52
- private _pageState: AppPageStateImpl;
55
+ public _pageState: AppPageStateImpl;
53
56
  private _prevFullPath: string | undefined;
54
57
 
55
58
  public appResult?: NetlessApp<any>;
56
59
  public appContext?: AppContext<any, any>;
57
60
 
61
+ private sideEffectManager = new SideEffectManager();
62
+
58
63
  constructor(
59
64
  private params: BaseInsertParams,
60
65
  private manager: AppManager,
@@ -63,6 +68,7 @@ export class AppProxy implements PageRemoveService {
63
68
  ) {
64
69
  this.kind = params.kind;
65
70
  this.id = appId;
71
+ this.appScenePath = `/${this.id}-app-dir`;
66
72
  this.stateKey = `${this.id}_state`;
67
73
  this.appProxies.set(this.id, this);
68
74
  this.appEmitter = new Emittery();
@@ -75,12 +81,37 @@ export class AppProxy implements PageRemoveService {
75
81
  // 只有传入了 scenePath 的 App 才会创建 View
76
82
  this.createView();
77
83
  }
84
+ if (!this.scenePath) {
85
+ this.scenePath = this.appScenePath;
86
+ }
78
87
  this._pageState = new AppPageStateImpl({
79
88
  displayer: this.manager.displayer,
80
89
  scenePath: this.scenePath,
81
90
  view: this.view,
82
91
  notifyPageStateChange: this.notifyPageStateChange,
83
92
  });
93
+ this.sideEffectManager.add(() => {
94
+ return () => this._pageState.destroy();
95
+ });
96
+ this.sideEffectManager.add(() => {
97
+ return emitter.on("roomMembersChange", members => {
98
+ this.appEmitter.emit("roomMembersChange", members);
99
+ });
100
+ });
101
+ }
102
+
103
+ public createAppDir() {
104
+ const scenePath = this.scenePath || this.appScenePath;
105
+ const sceneNode = this._pageState.createSceneNode(scenePath);
106
+ if (!sceneNode) {
107
+ putScenes(this.manager.room, scenePath, [{ name: "1" }]);
108
+ this._pageState.createSceneNode(scenePath);
109
+ this.setSceneIndex(0);
110
+ }
111
+ this.scenes = entireScenes(this.manager.displayer)[scenePath];
112
+ const view = this.createView();
113
+ this._pageState.setView(view);
114
+ return view;
84
115
  }
85
116
 
86
117
  private initScenes() {
@@ -191,7 +222,6 @@ export class AppProxy implements PageRemoveService {
191
222
  const result = await app.setup(context);
192
223
  this.appResult = result;
193
224
  appRegister.notifyApp(this.kind, "created", { appId, result });
194
- this.afterSetupApp(boxInitState);
195
225
  this.fixMobileSize();
196
226
  }, SETUP_APP_DELAY);
197
227
  });
@@ -225,14 +255,6 @@ export class AppProxy implements PageRemoveService {
225
255
  }
226
256
  }
227
257
 
228
- private afterSetupApp(boxInitState: AppInitState | undefined): void {
229
- if (boxInitState) {
230
- if (!boxInitState?.x || !boxInitState.y) {
231
- this.boxManager?.setBoxInitState(this.id);
232
- }
233
- }
234
- }
235
-
236
258
  public async onSeek(time: number) {
237
259
  this.appEmitter.emit("seek", time).catch(err => {
238
260
  console.log(`[WindowManager]: emit seek error: ${err.message}`);
@@ -404,14 +426,16 @@ export class AppProxy implements PageRemoveService {
404
426
  return fullPath;
405
427
  }
406
428
 
407
- private async createView(): Promise<View> {
408
- const view = await this.viewManager.createView(this.id);
429
+ private createView(): View {
430
+ const view = this.viewManager.createView(this.id);
409
431
  this.setViewFocusScenePath();
410
432
  return view;
411
433
  }
412
434
 
413
435
  public notifyPageStateChange = debounce(() => {
414
- this.appEmitter.emit("pageStateChange", this.pageState);
436
+ if (this.pageState) {
437
+ this.appEmitter.emit("pageStateChange", this.pageState);
438
+ }
415
439
  }, 50);
416
440
 
417
441
  public get pageState(): PageState {
@@ -421,7 +445,7 @@ export class AppProxy implements PageRemoveService {
421
445
  // PageRemoveService
422
446
  public async removeSceneByIndex(index: number) {
423
447
  const scenePath = this._pageState.getFullPath(index);
424
- if (scenePath) {
448
+ if (scenePath && this.pageState) {
425
449
  const nextIndex = calculateNextIndex(index, this.pageState);
426
450
  // 只修改 focus path 不修改 FullPath
427
451
  this.setSceneIndexWithoutSync(nextIndex);
@@ -483,7 +507,6 @@ export class AppProxy implements PageRemoveService {
483
507
  }
484
508
  }
485
509
  this.appProxies.delete(this.id);
486
- this._pageState.destroy();
487
510
 
488
511
  this.viewManager.destroyView(this.id);
489
512
  this.manager.appStatus.delete(this.id);
@@ -491,6 +514,7 @@ export class AppProxy implements PageRemoveService {
491
514
  this.manager.refresher?.remove(this.stateKey);
492
515
  this.manager.refresher?.remove(`${this.id}-fullPath`);
493
516
  this._prevFullPath = undefined;
517
+ this.sideEffectManager.flushAll();
494
518
  }
495
519
 
496
520
  public close(): Promise<void> {
@@ -37,7 +37,7 @@ export class Storage<TState extends Record<string, any> = any> implements Storag
37
37
  this._state = {} as TState;
38
38
  const rawState = this._getRawState(this._state);
39
39
 
40
- if (this._context.getIsWritable()) {
40
+ if (this._context.isWritable) {
41
41
  if (this.id === null) {
42
42
  if (context.isAddApp && defaultState) {
43
43
  this.setState(defaultState);
@@ -115,7 +115,7 @@ export class Storage<TState extends Record<string, any> = any> implements Storag
115
115
  return;
116
116
  }
117
117
 
118
- if (!this._context.getIsWritable()) {
118
+ if (!this._context.isWritable) {
119
119
  console.error(new Error(`Cannot setState on Storage "${this.id}" without writable access`), state);
120
120
  return;
121
121
  }
@@ -165,7 +165,7 @@ export class Storage<TState extends Record<string, any> = any> implements Storag
165
165
  return;
166
166
  }
167
167
 
168
- if (!this._context.getIsWritable()) {
168
+ if (!this._context.isWritable) {
169
169
  console.error(new Error(`Cannot empty Storage "${this.id}" without writable access.`));
170
170
  return;
171
171
  }
@@ -181,7 +181,7 @@ export class Storage<TState extends Record<string, any> = any> implements Storag
181
181
  throw new Error(`Cannot delete main Storage`);
182
182
  }
183
183
 
184
- if (!this._context.getIsWritable()) {
184
+ if (!this._context.isWritable) {
185
185
  console.error(new Error(`Cannot delete Storage "${this.id}" without writable access.`));
186
186
  return;
187
187
  }
@@ -0,0 +1,68 @@
1
+ import { putScenes } from "../Utils/Common";
2
+ import { Val } from "value-enhancer";
3
+
4
+ import type { ReadonlyVal } from "value-enhancer";
5
+ import type { AddPageParams, PageController, PageState } from "../Page";
6
+ import type { AppProxy } from "./AppProxy";
7
+ import type { AppContext } from "./AppContext";
8
+
9
+ export class WhiteBoardView implements PageController {
10
+ public readonly pageState$: ReadonlyVal<PageState>;
11
+
12
+ constructor(protected appContext: AppContext, protected appProxy: AppProxy) {
13
+ const pageState$ = new Val<PageState>(appProxy.pageState);
14
+ this.pageState$ = pageState$;
15
+ appProxy.appEmitter.on("pageStateChange", pageState => {
16
+ pageState$.setValue(pageState);
17
+ });
18
+ }
19
+
20
+ public get pageState() {
21
+ return this.pageState$.value;
22
+ }
23
+
24
+ public nextPage = async (): Promise<boolean> => {
25
+ const nextIndex = this.pageState.index + 1;
26
+ return this.jumpPage(nextIndex);
27
+ };
28
+
29
+ public prevPage = async (): Promise<boolean> => {
30
+ const nextIndex = this.pageState.index - 1;
31
+ return this.jumpPage(nextIndex);
32
+ };
33
+
34
+ public jumpPage = async (index: number): Promise<boolean> => {
35
+ if (index < 0 || index >= this.pageState.length) {
36
+ console.warn(`[WindowManager]: index ${index} out of range`);
37
+ return false;
38
+ }
39
+ this.appProxy.setSceneIndex(index);
40
+ return true;
41
+ };
42
+
43
+ public addPage = async (params?: AddPageParams) => {
44
+ const after = params?.after;
45
+ const scene = params?.scene;
46
+ const scenePath = this.appProxy.scenePath;
47
+ if (!scenePath) return;
48
+ if (after) {
49
+ const nextIndex = this.pageState.index + 1;
50
+ putScenes(this.appContext.room, scenePath, [scene || {}], nextIndex);
51
+ } else {
52
+ putScenes(this.appContext.room, scenePath, [scene || {}]);
53
+ }
54
+ };
55
+
56
+ public removePage = async (index?: number): Promise<boolean> => {
57
+ const needRemoveIndex = index === undefined ? this.pageState.index : index;
58
+ if (this.pageState.length === 1) {
59
+ console.warn(`[WindowManager]: can not remove the last page`);
60
+ return false;
61
+ }
62
+ if (needRemoveIndex < 0 || needRemoveIndex >= this.pageState.length) {
63
+ console.warn(`[WindowManager]: page index ${index} out of range`);
64
+ return false;
65
+ }
66
+ return this.appProxy.removeSceneByIndex(needRemoveIndex);
67
+ };
68
+ }
package/src/App/index.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from "./AppProxy";
2
2
  export * from "./AppContext";
3
+ export * from "./WhiteBoardView";
package/src/AppManager.ts CHANGED
@@ -15,6 +15,7 @@ import { MainViewProxy } from "./View/MainView";
15
15
  import { onObjectRemoved, safeListenPropsUpdated } from "./Utils/Reactive";
16
16
  import { reconnectRefresher, WindowManager } from "./index";
17
17
  import { RedoUndo } from "./RedoUndo";
18
+ import { serializeRoomMembers } from "./Helper";
18
19
  import { SideEffectManager } from "side-effect-manager";
19
20
  import { ViewManager } from "./View/ViewManager";
20
21
  import type { SyncRegisterAppPayload } from "./Register";
@@ -46,7 +47,7 @@ import type {
46
47
  BoxResizePayload,
47
48
  BoxStateChangePayload,
48
49
  } from "./BoxEmitter";
49
-
50
+ import type { Member } from "./Helper";
50
51
 
51
52
  export class AppManager {
52
53
  public displayer: Displayer;
@@ -299,6 +300,10 @@ export class AppManager {
299
300
  return this.room?.uid || "";
300
301
  }
301
302
 
303
+ public get members(): Member[] {
304
+ return serializeRoomMembers(this.displayer.state.roomMembers);
305
+ }
306
+
302
307
  public getMainViewSceneDir() {
303
308
  const scenePath = this.store.getMainViewScenePath();
304
309
  if (scenePath) {
@@ -660,6 +665,9 @@ export class AppManager {
660
665
  this.appProxies.forEach(appProxy => {
661
666
  appProxy.appEmitter.emit("roomStateChange", state);
662
667
  });
668
+ if (state.roomMembers) {
669
+ emitter.emit("roomMembersChange", this.members);
670
+ }
663
671
  emitter.emit("observerIdChange", this.displayer.observerId);
664
672
  };
665
673
 
package/src/BoxManager.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { AppAttributes, Events, MIN_HEIGHT, MIN_WIDTH } from "./constants";
2
2
  import { debounce } from "lodash";
3
- import { TELE_BOX_STATE, TeleBoxCollector, TeleBoxManager } from "@netless/telebox-insider";
3
+ import { TELE_BOX_STATE, TeleBoxManager } from "@netless/telebox-insider";
4
4
  import { WindowManager } from "./index";
5
5
  import type { BoxEmitterType } from "./BoxEmitter";
6
6
  import type { AddAppOptions, AppInitState } from "./index";
@@ -18,6 +18,7 @@ import type { NetlessApp } from "./typings";
18
18
  import type { View } from "white-web-sdk";
19
19
  import type { CallbacksType } from "./callback";
20
20
  import type { EmitterType } from "./InternalEmitter";
21
+ import { SideEffectManager } from "side-effect-manager";
21
22
 
22
23
  export { TELE_BOX_STATE };
23
24
 
@@ -45,6 +46,7 @@ export type CreateTeleBoxManagerConfig = {
45
46
  collectorContainer?: HTMLElement;
46
47
  collectorStyles?: Partial<CSSStyleDeclaration>;
47
48
  prefersColorScheme?: TeleBoxColorScheme;
49
+ stageRatio?: number;
48
50
  };
49
51
 
50
52
  export type BoxManagerContext = {
@@ -87,79 +89,93 @@ export const createBoxManager = (
87
89
 
88
90
  export class BoxManager {
89
91
  public teleBoxManager: TeleBoxManager;
92
+ protected sideEffectManager: SideEffectManager;
90
93
 
91
94
  constructor(
92
95
  private context: BoxManagerContext,
93
- private createTeleBoxManagerConfig?: CreateTeleBoxManagerConfig
96
+ createTeleBoxManagerConfig?: CreateTeleBoxManagerConfig
94
97
  ) {
98
+ this.sideEffectManager = new SideEffectManager();
95
99
  const { emitter, callbacks, boxEmitter } = context;
96
100
  this.teleBoxManager = this.setupBoxManager(createTeleBoxManagerConfig);
97
-
98
- // 使用 _xxx$.reaction 订阅修改的值, 不管有没有 skipUpdate, 修改值都会触发回调
99
- this.teleBoxManager._state$.reaction(state => {
100
- callbacks.emit("boxStateChange", state);
101
- emitter.emit("boxStateChange", state);
102
- });
103
-
104
- this.teleBoxManager._darkMode$.reaction(darkMode => {
105
- callbacks.emit("darkModeChange", darkMode);
106
- });
107
- this.teleBoxManager._prefersColorScheme$.reaction(colorScheme => {
108
- callbacks.emit("prefersColorSchemeChange", colorScheme);
109
- });
110
-
111
- // events.on 的值则会根据 skipUpdate 来决定是否触发回调
112
- this.teleBoxManager.events.on("minimized", minimized => {
113
- this.context.safeSetAttributes({ minimized });
114
- if (minimized) {
115
- this.context.cleanFocus();
116
- this.blurAllBox();
117
- } else {
118
- const topBox = this.getTopBox();
119
- if (topBox) {
120
- this.context.setAppFocus(topBox.id);
121
- this.focusBox({ appId: topBox.id }, false);
101
+ this.sideEffectManager.add(() => [
102
+ // 使用 _xxx$.reaction 订阅修改的值, 不管有没有 skipUpdate, 修改值都会触发回调
103
+ this.teleBoxManager._state$.reaction(state => {
104
+ callbacks.emit("boxStateChange", state);
105
+ emitter.emit("boxStateChange", state);
106
+ }),
107
+ this.teleBoxManager._darkMode$.reaction(darkMode => {
108
+ callbacks.emit("darkModeChange", darkMode);
109
+ }),
110
+ this.teleBoxManager._prefersColorScheme$.reaction(colorScheme => {
111
+ callbacks.emit("prefersColorSchemeChange", colorScheme);
112
+ }),
113
+ this.teleBoxManager._minimized$.reaction((minimized, skipUpdate) => {
114
+ if (skipUpdate) {
115
+ return;
122
116
  }
123
- }
124
- });
125
- this.teleBoxManager.events.on("maximized", maximized => {
126
- this.context.safeSetAttributes({ maximized });
127
- });
128
- this.teleBoxManager.events.on("removed", boxes => {
129
- boxes.forEach(box => {
130
- boxEmitter.emit("close", { appId: box.id });
131
- });
132
- });
133
- this.teleBoxManager.events.on(
134
- "intrinsic_move",
135
- debounce((box: ReadonlyTeleBox): void => {
136
- boxEmitter.emit("move", { appId: box.id, x: box.intrinsicX, y: box.intrinsicY });
137
- }, 50)
138
- );
139
- this.teleBoxManager.events.on(
140
- "intrinsic_resize",
141
- debounce((box: ReadonlyTeleBox): void => {
142
- boxEmitter.emit("resize", {
143
- appId: box.id,
144
- width: box.intrinsicWidth,
145
- height: box.intrinsicHeight,
146
- });
147
- }, 200)
148
- );
149
- this.teleBoxManager.events.on("focused", box => {
150
- if (box) {
151
- if (this.canOperate) {
152
- boxEmitter.emit("focus", { appId: box.id });
117
+ this.context.safeSetAttributes({ minimized });
118
+ if (minimized) {
119
+ this.context.cleanFocus();
120
+ this.blurAllBox();
153
121
  } else {
154
- this.teleBoxManager.blurBox(box.id);
122
+ const topBox = this.getTopBox();
123
+ if (topBox) {
124
+ this.context.setAppFocus(topBox.id);
125
+ this.focusBox({ appId: topBox.id }, false);
126
+ }
155
127
  }
156
- }
157
- });
158
- this.teleBoxManager.events.on("z_index", box => {
159
- this.context.updateAppState(box.id, AppAttributes.ZIndex, box.zIndex);
160
- });
161
- emitter.on("playgroundSizeChange", () => this.updateManagerRect());
162
- emitter.on("updateManagerRect", () => this.updateManagerRect());
128
+ }),
129
+ this.teleBoxManager._maximized$.reaction((maximized, skipUpdate) => {
130
+ if (skipUpdate) {
131
+ return;
132
+ }
133
+ this.context.safeSetAttributes({ maximized });
134
+ }),
135
+ this.teleBoxManager.events.on("removed", boxes => {
136
+ boxes.forEach(box => {
137
+ boxEmitter.emit("close", { appId: box.id });
138
+ });
139
+ }),
140
+ this.teleBoxManager.events.on(
141
+ "intrinsic_move",
142
+ debounce((box: ReadonlyTeleBox): void => {
143
+ boxEmitter.emit("move", { appId: box.id, x: box.intrinsicX, y: box.intrinsicY });
144
+ }, 50)
145
+ ),
146
+ this.teleBoxManager.events.on(
147
+ "intrinsic_resize",
148
+ debounce((box: ReadonlyTeleBox): void => {
149
+ boxEmitter.emit("resize", {
150
+ appId: box.id,
151
+ width: box.intrinsicWidth,
152
+ height: box.intrinsicHeight,
153
+ });
154
+ }, 200)
155
+ ),
156
+ this.teleBoxManager.events.on("focused", box => {
157
+ if (box) {
158
+ if (this.canOperate) {
159
+ boxEmitter.emit("focus", { appId: box.id });
160
+ } else {
161
+ this.teleBoxManager.blurBox(box.id);
162
+ }
163
+ }
164
+ }),
165
+ this.teleBoxManager.events.on("z_index", box => {
166
+ this.context.updateAppState(box.id, AppAttributes.ZIndex, box.zIndex);
167
+ }),
168
+ this.teleBoxManager._stageRect$.subscribe(stage => {
169
+ emitter.emit("playgroundSizeChange", stage);
170
+ this.context.notifyContainerRectUpdate(stage);
171
+ }),
172
+ emitter.on("writableChange", isWritable => {
173
+ this.teleBoxManager.setHighlightStage(isWritable);
174
+ }),
175
+ emitter.on("containerSizeRatioUpdate", ratio => {
176
+ this.teleBoxManager._stageRatio$.setValue(ratio);
177
+ }),
178
+ ]);
163
179
  }
164
180
 
165
181
  private get mainView() {
@@ -194,12 +210,16 @@ export class BoxManager {
194
210
  return this.teleBoxManager.boxes.length;
195
211
  }
196
212
 
213
+ public get stageRect() {
214
+ return this.teleBoxManager.stageRect;
215
+ }
216
+
197
217
  public createBox(params: CreateBoxParams): void {
198
218
  if (!this.teleBoxManager) return;
199
219
  let { minwidth = MIN_WIDTH, minheight = MIN_HEIGHT } = params.app.config ?? {};
200
220
  const { width, height } = params.app.config ?? {};
201
221
  const title = params.options?.title || params.appId;
202
- const rect = this.teleBoxManager.containerRect;
222
+ const rect = this.teleBoxManager.rootRect;
203
223
 
204
224
  if (minwidth > 1) {
205
225
  minwidth = minwidth / rect.width;
@@ -221,34 +241,13 @@ export class BoxManager {
221
241
  this.context.emitter.emit(`${params.appId}${Events.WindowCreated}` as any);
222
242
  }
223
243
 
224
- public setBoxInitState(appId: string): void {
225
- const box = this.teleBoxManager.queryOne({ id: appId });
226
- if (box) {
227
- if (box.state === TELE_BOX_STATE.Maximized) {
228
- this.context.boxEmitter.emit("resize", {
229
- appId: appId,
230
- x: box.x,
231
- y: box.y,
232
- width: box.intrinsicWidth,
233
- height: box.intrinsicHeight,
234
- });
235
- }
236
- }
237
- }
238
-
239
244
  public setupBoxManager(
240
245
  createTeleBoxManagerConfig?: CreateTeleBoxManagerConfig
241
246
  ): TeleBoxManager {
242
- const root = WindowManager.wrapper ? WindowManager.wrapper : document.body;
243
- const rect = root.getBoundingClientRect();
247
+ const root = WindowManager.playground;
244
248
  const initManagerState: TeleBoxManagerConfig = {
249
+ stageRatio: createTeleBoxManagerConfig?.stageRatio,
245
250
  root: root,
246
- containerRect: {
247
- x: 0,
248
- y: 0,
249
- width: rect.width,
250
- height: rect.height,
251
- },
252
251
  fence: false,
253
252
  prefersColorScheme: createTeleBoxManagerConfig?.prefersColorScheme,
254
253
  };
@@ -258,20 +257,16 @@ export class BoxManager {
258
257
  this.teleBoxManager.destroy();
259
258
  }
260
259
  this.teleBoxManager = manager;
261
- const container = createTeleBoxManagerConfig?.collectorContainer || WindowManager.wrapper;
260
+ const container = createTeleBoxManagerConfig?.collectorContainer;
262
261
  if (container) {
263
- this.setCollectorContainer(container);
262
+ this.teleBoxManager.collector.set$collector(container);
263
+ }
264
+ if (createTeleBoxManagerConfig?.collectorStyles) {
265
+ this.teleBoxManager.collector.setStyles(createTeleBoxManagerConfig.collectorStyles);
264
266
  }
265
267
  return manager;
266
268
  }
267
269
 
268
- public setCollectorContainer(container: HTMLElement) {
269
- const collector = new TeleBoxCollector({
270
- styles: this.createTeleBoxManagerConfig?.collectorStyles,
271
- }).mount(container);
272
- this.teleBoxManager.setCollector(collector);
273
- }
274
-
275
270
  public getBox(appId: string): ReadonlyTeleBox | undefined {
276
271
  return this.teleBoxManager.queryOne({ id: appId });
277
272
  }
@@ -324,15 +319,6 @@ export class BoxManager {
324
319
  }
325
320
  }
326
321
 
327
- public updateManagerRect(): void {
328
- const rect = this.mainView.divElement?.getBoundingClientRect();
329
- if (rect && rect.width > 0 && rect.height > 0) {
330
- const containerRect = { x: 0, y: 0, width: rect.width, height: rect.height };
331
- this.teleBoxManager.setContainerRect(containerRect);
332
- this.context.notifyContainerRectUpdate(this.teleBoxManager.containerRect);
333
- }
334
- }
335
-
336
322
  public moveBox({ appId, x, y }: MoveBoxParams): void {
337
323
  this.teleBoxManager.update(appId, { x, y }, true);
338
324
  }
@@ -404,7 +390,16 @@ export class BoxManager {
404
390
  this.teleBoxManager.update(id, { zIndex }, skipUpdate);
405
391
  }
406
392
 
393
+ public setRoot(root: HTMLElement) {
394
+ this.teleBoxManager._root$.setValue(root);
395
+ }
396
+
397
+ public setCollector(collector: HTMLElement) {
398
+ this.teleBoxManager.collector.set$collector(collector);
399
+ }
400
+
407
401
  public destroy() {
402
+ this.sideEffectManager.flushAll();
408
403
  this.teleBoxManager.destroy();
409
404
  }
410
405
  }
@@ -34,9 +34,9 @@ export class CursorManager {
34
34
 
35
35
  constructor(private manager: AppManager, private enableCursor: boolean, applianceIcons?: ApplianceIcons) {
36
36
  this.roomMembers = this.manager.room?.state.roomMembers;
37
- const wrapper = WindowManager.wrapper;
38
- if (wrapper) {
39
- this.setupWrapper(wrapper);
37
+ const playground = WindowManager.playground;
38
+ if (playground) {
39
+ this.setupWrapper(playground);
40
40
  }
41
41
  this.sideEffectManager.add(() => {
42
42
  return emitter.on("cursorMove", this.onCursorMove);
@@ -65,7 +65,7 @@ export class CursorManager {
65
65
  private initCursorInstance = (uid: string) => {
66
66
  let cursorInstance = this.cursorInstances.get(uid);
67
67
  if (!cursorInstance) {
68
- cursorInstance = new Cursor(this.manager, uid, this, WindowManager.wrapper);
68
+ cursorInstance = new Cursor(this.manager, uid, this, WindowManager.playground);
69
69
  this.cursorInstances.set(uid, cursorInstance);
70
70
  }
71
71
  return cursorInstance;
@@ -169,7 +169,7 @@ export class CursorManager {
169
169
 
170
170
  public updateContainerRect() {
171
171
  this.containerRect = WindowManager.container?.getBoundingClientRect();
172
- this.wrapperRect = WindowManager.wrapper?.getBoundingClientRect();
172
+ this.wrapperRect = WindowManager.playground?.getBoundingClientRect();
173
173
  }
174
174
 
175
175
  public deleteCursor(uid: string) {
package/src/Helper.ts CHANGED
@@ -2,36 +2,23 @@ import { getVersionNumber } from "./Utils/Common";
2
2
  import { REQUIRE_VERSION } from "./constants";
3
3
  import { WhiteVersion } from "white-web-sdk";
4
4
  import { WhiteWebSDKInvalidError } from "./Utils/error";
5
- import { WindowManager } from "./index";
6
- import type { Room } from "white-web-sdk";
5
+ import type { Room , RoomMember} from "white-web-sdk";
7
6
 
8
7
  export const setupWrapper = (
9
8
  root: HTMLElement
10
9
  ): {
11
10
  playground: HTMLDivElement;
12
- wrapper: HTMLDivElement;
13
- sizer: HTMLDivElement;
14
11
  mainViewElement: HTMLDivElement;
15
12
  } => {
16
13
  const playground = document.createElement("div");
17
14
  playground.className = "netless-window-manager-playground";
18
15
 
19
- const sizer = document.createElement("div");
20
- sizer.className = "netless-window-manager-sizer";
21
-
22
- const wrapper = document.createElement("div");
23
- wrapper.className = "netless-window-manager-wrapper";
24
-
25
16
  const mainViewElement = document.createElement("div");
26
17
  mainViewElement.className = "netless-window-manager-main-view";
27
-
28
- playground.appendChild(sizer);
29
- sizer.appendChild(wrapper);
30
- wrapper.appendChild(mainViewElement);
18
+ playground.appendChild(mainViewElement);
31
19
  root.appendChild(playground);
32
- WindowManager.wrapper = wrapper;
33
20
 
34
- return { playground, wrapper, sizer, mainViewElement };
21
+ return { playground, mainViewElement };
35
22
  };
36
23
 
37
24
  export const checkVersion = () => {
@@ -45,3 +32,12 @@ export const findMemberByUid = (room: Room | undefined, uid: string) => {
45
32
  const roomMembers = room?.state.roomMembers;
46
33
  return roomMembers?.find(member => member.payload?.uid === uid);
47
34
  };
35
+
36
+ export type Member = RoomMember & { uid: string };
37
+
38
+ export const serializeRoomMembers = (members: readonly RoomMember[]) => {
39
+ return members.map(member => ({
40
+ uid: member.payload?.uid || "",
41
+ ...member,
42
+ }));
43
+ }