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

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.
@@ -191,7 +191,6 @@ export class AppProxy implements PageRemoveService {
191
191
  const result = await app.setup(context);
192
192
  this.appResult = result;
193
193
  appRegister.notifyApp(this.kind, "created", { appId, result });
194
- this.afterSetupApp(boxInitState);
195
194
  this.fixMobileSize();
196
195
  }, SETUP_APP_DELAY);
197
196
  });
@@ -225,14 +224,6 @@ export class AppProxy implements PageRemoveService {
225
224
  }
226
225
  }
227
226
 
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
227
  public async onSeek(time: number) {
237
228
  this.appEmitter.emit("seek", time).catch(err => {
238
229
  console.log(`[WindowManager]: emit seek error: ${err.message}`);
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() {
@@ -199,7 +215,7 @@ export class BoxManager {
199
215
  let { minwidth = MIN_WIDTH, minheight = MIN_HEIGHT } = params.app.config ?? {};
200
216
  const { width, height } = params.app.config ?? {};
201
217
  const title = params.options?.title || params.appId;
202
- const rect = this.teleBoxManager.containerRect;
218
+ const rect = this.teleBoxManager.rootRect;
203
219
 
204
220
  if (minwidth > 1) {
205
221
  minwidth = minwidth / rect.width;
@@ -221,34 +237,13 @@ export class BoxManager {
221
237
  this.context.emitter.emit(`${params.appId}${Events.WindowCreated}` as any);
222
238
  }
223
239
 
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
240
  public setupBoxManager(
240
241
  createTeleBoxManagerConfig?: CreateTeleBoxManagerConfig
241
242
  ): TeleBoxManager {
242
- const root = WindowManager.wrapper ? WindowManager.wrapper : document.body;
243
- const rect = root.getBoundingClientRect();
243
+ const root = WindowManager.playground;
244
244
  const initManagerState: TeleBoxManagerConfig = {
245
+ stageRatio: 3 / 4,
245
246
  root: root,
246
- containerRect: {
247
- x: 0,
248
- y: 0,
249
- width: rect.width,
250
- height: rect.height,
251
- },
252
247
  fence: false,
253
248
  prefersColorScheme: createTeleBoxManagerConfig?.prefersColorScheme,
254
249
  };
@@ -258,20 +253,16 @@ export class BoxManager {
258
253
  this.teleBoxManager.destroy();
259
254
  }
260
255
  this.teleBoxManager = manager;
261
- const container = createTeleBoxManagerConfig?.collectorContainer || WindowManager.wrapper;
256
+ const container = createTeleBoxManagerConfig?.collectorContainer;
262
257
  if (container) {
263
- this.setCollectorContainer(container);
258
+ this.teleBoxManager.collector.set$collector(container);
259
+ }
260
+ if (createTeleBoxManagerConfig?.collectorStyles) {
261
+ this.teleBoxManager.collector.setStyles(createTeleBoxManagerConfig.collectorStyles);
264
262
  }
265
263
  return manager;
266
264
  }
267
265
 
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
266
  public getBox(appId: string): ReadonlyTeleBox | undefined {
276
267
  return this.teleBoxManager.queryOne({ id: appId });
277
268
  }
@@ -324,15 +315,6 @@ export class BoxManager {
324
315
  }
325
316
  }
326
317
 
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
318
  public moveBox({ appId, x, y }: MoveBoxParams): void {
337
319
  this.teleBoxManager.update(appId, { x, y }, true);
338
320
  }
@@ -404,7 +386,12 @@ export class BoxManager {
404
386
  this.teleBoxManager.update(id, { zIndex }, skipUpdate);
405
387
  }
406
388
 
389
+ public setRoot(root: HTMLElement) {
390
+ this.teleBoxManager._root$.setValue(root);
391
+ }
392
+
407
393
  public destroy() {
394
+ this.sideEffectManager.flushAll();
408
395
  this.teleBoxManager.destroy();
409
396
  }
410
397
  }
@@ -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
5
  import type { Room } 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 = () => {
@@ -1,9 +1,11 @@
1
1
  import Emittery from "emittery";
2
+ import type { TeleBoxRect } from "@netless/telebox-insider";
2
3
  import type { AppInitState, CursorMovePayload } from "./index";
3
4
 
4
5
  export type RemoveSceneParams = {
5
- scenePath: string, index?: number
6
- }
6
+ scenePath: string;
7
+ index?: number;
8
+ };
7
9
 
8
10
  export type EmitterEvent = {
9
11
  onCreated: undefined;
@@ -14,14 +16,14 @@ export type EmitterEvent = {
14
16
  mainViewMounted: undefined;
15
17
  observerIdChange: number;
16
18
  boxStateChange: string;
17
- playgroundSizeChange: DOMRect;
19
+ playgroundSizeChange: TeleBoxRect;
18
20
  startReconnect: undefined;
19
21
  onReconnected: undefined;
20
22
  removeScenes: RemoveSceneParams;
21
23
  cursorMove: CursorMovePayload;
22
24
  updateManagerRect: undefined;
23
25
  focusedChange: { focused: string | undefined; prev: string | undefined };
24
- rootDirRemoved: undefined; // 根目录整个被删除
26
+ rootDirRemoved: undefined; // 根目录整个被删除
25
27
  rootDirSceneRemoved: string; // 根目录下的场景被删除
26
28
  setReadonly: boolean;
27
29
  changePageState: undefined;
@@ -0,0 +1,67 @@
1
+ import { AnimationMode } from "white-web-sdk";
2
+ import { delay, throttle } from "lodash";
3
+ import type { TeleBoxRect } from "@netless/telebox-insider";
4
+ import type { Camera, View, Size } from "white-web-sdk";
5
+ import type { MainViewSize } from "../AttributesDelegate";
6
+
7
+ export type SaveCamera = (camera: Camera) => void;
8
+
9
+ export class CameraSynchronizer {
10
+ protected remoteCamera?: Camera;
11
+ protected remoteSize?: MainViewSize;
12
+ protected rect?: TeleBoxRect;
13
+ protected view?: View;
14
+
15
+ constructor(protected saveCamera: SaveCamera) {}
16
+
17
+ public setRect(rect: TeleBoxRect) {
18
+ this.rect = rect;
19
+ if (this.remoteCamera && this.remoteSize) {
20
+ this.onRemoteUpdate(this.remoteCamera, this.remoteSize);
21
+ }
22
+ }
23
+
24
+ public setView(view: View) {
25
+ this.view = view;
26
+ }
27
+
28
+ // 远端 Camera 或者 size 更新
29
+ public onRemoteUpdate = throttle((camera: Camera, size: MainViewSize) => {
30
+ this.remoteCamera = camera;
31
+ this.remoteSize = size;
32
+ if (this.remoteSize && this.rect) {
33
+ let scale: number;
34
+ if (size.width < size.height) {
35
+ scale = this.rect.width / size.width;
36
+ } else {
37
+ scale = this.rect.height / size.height;
38
+ }
39
+ const nextScale = camera.scale * scale;
40
+ const moveCamera = () => this.view?.moveCamera({
41
+ centerX: camera.centerX,
42
+ centerY: camera.centerY,
43
+ scale: nextScale,
44
+ animationMode: AnimationMode.Immediately,
45
+ });
46
+ // TODO 直接调用 moveCamera 依然会出现 camera 错误的情况,这里暂时加一个 delay 保证 camera 是对的, 后续需要 SDK 进行修改
47
+ delay(moveCamera, 10);
48
+ }
49
+ }, 50);
50
+
51
+
52
+ public onLocalCameraUpdate(camera: Camera) {
53
+ this.saveCamera(camera);
54
+ }
55
+
56
+ // 本地 Size 更新, 先匹配 camera 到新的 size 然后再发送 camera 数据到远端
57
+ public onLocalSizeUpdate(size: Size) {
58
+ if (this.rect && this.view) {
59
+ const scale = this.rect.width / size.width;
60
+ const nextScale = this.view.camera.scale * scale;
61
+ this.view.moveCamera({
62
+ scale: nextScale,
63
+ animationMode: AnimationMode.Immediately
64
+ });
65
+ }
66
+ }
67
+ }
@@ -1,25 +1,29 @@
1
- import { AnimationMode, reaction } from "white-web-sdk";
1
+ import { reaction } from "white-web-sdk";
2
2
  import { callbacks } from "../callback";
3
3
  import { createView } from "./ViewManager";
4
- import { debounce, get, isEmpty, isEqual } from "lodash";
4
+ import { debounce, get, isEqual } from "lodash";
5
5
  import { emitter } from "../InternalEmitter";
6
+ import { Events } from "../constants";
6
7
  import { Fields } from "../AttributesDelegate";
7
8
  import { setViewFocusScenePath } from "../Utils/Common";
8
9
  import { SideEffectManager } from "side-effect-manager";
9
10
  import type { Camera, Size, View } from "white-web-sdk";
10
11
  import type { AppManager } from "../AppManager";
11
- import { Events } from "../constants";
12
+ import { CameraSynchronizer } from "./CameraSynchronizer";
12
13
 
13
14
  export class MainViewProxy {
14
- private scale?: number;
15
15
  private started = false;
16
16
  private mainViewIsAddListener = false;
17
17
  private mainView: View;
18
18
  private store = this.manager.store;
19
+ private synchronizer: CameraSynchronizer;
19
20
 
20
21
  private sideEffectManager = new SideEffectManager();
21
22
 
22
23
  constructor(private manager: AppManager) {
24
+ this.synchronizer = new CameraSynchronizer(
25
+ camera => this.store.setMainViewCamera({ ...camera, id: this.manager.uid })
26
+ );
23
27
  this.mainView = this.createMainView();
24
28
  this.moveCameraSizeByAttributes();
25
29
  emitter.once("mainViewMounted").then(() => {
@@ -28,18 +32,24 @@ export class MainViewProxy {
28
32
  this.ensureCameraAndSize();
29
33
  this.startListenWritableChange();
30
34
  });
31
- const playgroundSizeChangeListener = () => {
32
- this.sizeChangeHandler(this.mainViewSize);
33
- };
34
- this.sideEffectManager.add(() => {
35
- return emitter.on("playgroundSizeChange", playgroundSizeChangeListener);
36
- });
37
35
  this.sideEffectManager.add(() => {
38
36
  return emitter.on("containerSizeRatioUpdate", this.onUpdateContainerSizeRatio);
39
37
  });
40
38
  this.sideEffectManager.add(() => {
41
39
  return emitter.on("startReconnect", () => {
42
- this.mainView.release();
40
+ if (!(this.mainView as any).didRelease) {
41
+ this.mainView.release();
42
+ }
43
+ });
44
+ });
45
+ const rect = this.manager.boxManager?.teleBoxManager.stageRect;
46
+ if (rect) {
47
+ this.synchronizer.setRect(rect);
48
+ }
49
+ this.sideEffectManager.add(() => {
50
+ return emitter.on("playgroundSizeChange", rect => {
51
+ this.synchronizer.setRect(rect);
52
+ this.synchronizer.onLocalSizeUpdate(rect);
43
53
  });
44
54
  });
45
55
  }
@@ -52,7 +62,7 @@ export class MainViewProxy {
52
62
  }
53
63
  });
54
64
  });
55
- }
65
+ };
56
66
 
57
67
  public ensureCameraAndSize() {
58
68
  if (!this.mainViewCamera || !this.mainViewSize) {
@@ -74,8 +84,7 @@ export class MainViewProxy {
74
84
  }
75
85
 
76
86
  private moveCameraSizeByAttributes() {
77
- this.moveCameraToContian(this.mainViewSize);
78
- this.moveCamera(this.mainViewCamera);
87
+ this.synchronizer.onRemoteUpdate(this.mainViewCamera, this.mainViewSize);
79
88
  }
80
89
 
81
90
  public start() {
@@ -91,9 +100,12 @@ export class MainViewProxy {
91
100
  };
92
101
 
93
102
  public setCameraAndSize(): void {
94
- const camera = { ...this.mainView.camera, id: this.manager.uid };
95
- const size = { ...this.mainView.size, id: this.manager.uid };
96
- this.store.setMainViewCameraAndSize(camera, size);
103
+ const stageSize = this.getStageSize();
104
+ if (stageSize) {
105
+ const camera = { ...this.mainView.camera, id: this.manager.uid };
106
+ const size = { ...stageSize, id: this.manager.uid };
107
+ this.store.setMainViewCameraAndSize(camera, size);
108
+ }
97
109
  }
98
110
 
99
111
  private cameraReaction = () => {
@@ -101,8 +113,7 @@ export class MainViewProxy {
101
113
  () => this.mainViewCamera,
102
114
  camera => {
103
115
  if (camera && camera.id !== this.manager.uid) {
104
- this.moveCameraToContian(this.mainViewSize);
105
- this.moveCamera(camera);
116
+ this.synchronizer.onRemoteUpdate(camera, this.mainViewSize);
106
117
  }
107
118
  },
108
119
  { fireImmediately: true }
@@ -111,8 +122,7 @@ export class MainViewProxy {
111
122
 
112
123
  public sizeChangeHandler = debounce((size: Size) => {
113
124
  if (size) {
114
- this.moveCameraToContian(size);
115
- this.moveCamera(this.mainViewCamera);
125
+ this.synchronizer.onLocalSizeUpdate(size);
116
126
  }
117
127
  }, 30);
118
128
 
@@ -122,7 +132,7 @@ export class MainViewProxy {
122
132
  if (size.id === this.manager.uid) {
123
133
  this.setCameraAndSize();
124
134
  }
125
- }
135
+ };
126
136
 
127
137
  public get view(): View {
128
138
  return this.mainView;
@@ -138,6 +148,7 @@ export class MainViewProxy {
138
148
  if (mainViewScenePath) {
139
149
  setViewFocusScenePath(mainView, mainViewScenePath);
140
150
  }
151
+ this.synchronizer.setView(mainView);
141
152
  return mainView;
142
153
  }
143
154
 
@@ -172,12 +183,20 @@ export class MainViewProxy {
172
183
  }
173
184
 
174
185
  private onCameraUpdatedByDevice = (camera: Camera) => {
175
- this.store.setMainViewCamera({ ...camera, id: this.manager.uid });
176
- if (!isEqual(this.mainViewSize, { ...this.mainView.size, id: this.manager.uid })) {
177
- this.setMainViewSize(this.view.size);
186
+ this.synchronizer.onLocalCameraUpdate(camera);
187
+ const size = this.getStageSize();
188
+ if (size && !isEqual(size, this.mainViewSize)) {
189
+ this.setMainViewSize(size);
178
190
  }
179
191
  };
180
192
 
193
+ private getStageSize(): Size | undefined {
194
+ const stage = this.manager.boxManager?.teleBoxManager.stageRect;
195
+ if (stage) {
196
+ return { width: stage.width, height: stage.height };
197
+ }
198
+ }
199
+
181
200
  public addMainViewListener(): void {
182
201
  if (this.mainViewIsAddListener) return;
183
202
  if (this.view.divElement) {
@@ -205,7 +224,7 @@ export class MainViewProxy {
205
224
  this.manager.boxManager?.blurAllBox();
206
225
  }
207
226
 
208
- public setMainViewSize = debounce(size => {
227
+ public setMainViewSize = debounce((size: Size) => {
209
228
  this.store.setMainViewSize({ ...size, id: this.manager.uid });
210
229
  }, 50);
211
230
 
@@ -225,33 +244,6 @@ export class MainViewProxy {
225
244
  callbacks.emit("cameraStateChange", this.cameraState);
226
245
  };
227
246
 
228
- public moveCameraToContian(size: Size): void {
229
- if (!isEmpty(size)) {
230
- this.view.moveCameraToContain({
231
- width: size.width,
232
- height: size.height,
233
- originX: -size.width / 2,
234
- originY: -size.height / 2,
235
- animationMode: AnimationMode.Immediately,
236
- });
237
- this.scale = this.view.camera.scale;
238
- }
239
- }
240
-
241
- public moveCamera(camera: Camera): void {
242
- if (!isEmpty(camera)) {
243
- if (isEqual(camera, this.view.camera)) return;
244
- const { centerX, centerY, scale } = camera;
245
- const needScale = scale * (this.scale || 1);
246
- this.view.moveCamera({
247
- centerX: centerX,
248
- centerY: centerY,
249
- scale: needScale,
250
- animationMode: AnimationMode.Immediately,
251
- });
252
- }
253
- }
254
-
255
247
  public stop() {
256
248
  this.removeCameraListener();
257
249
  this.manager.refresher?.remove(Fields.MainViewCamera);