@netless/window-manager 0.4.20 → 0.4.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/api.md CHANGED
@@ -27,6 +27,7 @@
27
27
  - [`nextPage`](#nextPage)
28
28
  - [`prevPage`](#prevPage)
29
29
  - [`addPage`](#addPage)
30
+ - [`refresh`](#refresh)
30
31
  - [实例属性](#prototypes)
31
32
  - [事件回调](#events)
32
33
 
@@ -212,6 +213,13 @@ manager.addPage({ after: true }) // 在当前页后添加一页
212
213
  manager.addPage({ scene: { name: "page2" } }) // 传入 page 信息
213
214
  ```
214
215
 
216
+ <h3 id="refresh">refresh</h3>
217
+
218
+ > 刷新 `manager` 的内部状态, 用于从其他房间 `copy` `attributes`
219
+
220
+ ```ts
221
+ manager.refresh()
222
+ ```
215
223
 
216
224
  <br>
217
225
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netless/window-manager",
3
- "version": "0.4.20",
3
+ "version": "0.4.23",
4
4
  "description": "",
5
5
  "main": "dist/index.es.js",
6
6
  "module": "dist/index.es.js",
@@ -59,6 +59,14 @@ export class AppListeners {
59
59
  this.rootDirRemovedHandler();
60
60
  break;
61
61
  }
62
+ case Events.Refresh: {
63
+ this.refreshHandler();
64
+ break;
65
+ }
66
+ case Events.InitMainViewCamera: {
67
+ this.initMainViewCameraHandler();
68
+ break;
69
+ }
62
70
  default:
63
71
  break;
64
72
  }
@@ -103,4 +111,12 @@ export class AppListeners {
103
111
  this.manager.mainViewProxy.rebind();
104
112
  emitter.emit("rootDirRemoved");
105
113
  }
114
+
115
+ private refreshHandler = () => {
116
+ this.manager.windowManger._refresh();
117
+ }
118
+
119
+ private initMainViewCameraHandler = () => {
120
+ this.manager.mainViewProxy.addCameraReaction();
121
+ }
106
122
  }
package/src/AppManager.ts CHANGED
@@ -5,9 +5,9 @@ import { AppProxy } from "./App";
5
5
  import { appRegister } from "./Register";
6
6
  import { autorun, isPlayer, isRoom, ScenePathType } from "white-web-sdk";
7
7
  import { callbacks } from "./callback";
8
+ import { debounce, get, isInteger, orderBy } from "lodash";
8
9
  import { emitter } from "./InternalEmitter";
9
10
  import { Fields, store } from "./AttributesDelegate";
10
- import { get, isInteger, orderBy } from "lodash";
11
11
  import { log } from "./Utils/log";
12
12
  import { MainViewProxy } from "./View/MainView";
13
13
  import { onObjectRemoved, safeListenPropsUpdated } from "./Utils/Reactive";
@@ -132,7 +132,7 @@ export class AppManager {
132
132
  public async onRootDirRemoved(needClose = true) {
133
133
  this.setMainViewScenePath(INIT_DIR);
134
134
  this.createRootDirScenesCallback();
135
-
135
+
136
136
  for (const [id, appProxy] of this.appProxies.entries()) {
137
137
  if (appProxy.view) {
138
138
  await this.closeApp(id, needClose);
@@ -251,19 +251,9 @@ export class AppManager {
251
251
  await this.attributesUpdateCallback(this.attributes.apps);
252
252
  emitter.emit("updateManagerRect");
253
253
  emitter.onAny(this.boxEventListener);
254
- this.refresher?.add("apps", () => {
255
- return safeListenPropsUpdated(
256
- () => this.attributes.apps,
257
- () => {
258
- this.attributesUpdateCallback(this.attributes.apps);
259
- }
260
- );
261
- });
262
- this.refresher?.add("appsClose", () => {
263
- return onObjectRemoved(this.attributes.apps, () => {
264
- this.onAppDelete(this.attributes.apps);
265
- });
266
- });
254
+
255
+ this.addAppsChangeListener();
256
+ this.addAppCloseListener();
267
257
  this.refresher?.add("maximized", () => {
268
258
  return autorun(() => {
269
259
  const maximized = this.attributes.maximized;
@@ -313,6 +303,25 @@ export class AppManager {
313
303
  });
314
304
  }
315
305
 
306
+ public addAppsChangeListener = () => {
307
+ this.refresher?.add("apps", () => {
308
+ return safeListenPropsUpdated(
309
+ () => this.attributes.apps,
310
+ () => {
311
+ this.attributesUpdateCallback(this.attributes.apps);
312
+ }
313
+ );
314
+ });
315
+ };
316
+
317
+ public addAppCloseListener = () => {
318
+ this.refresher?.add("appsClose", () => {
319
+ return onObjectRemoved(this.attributes.apps, () => {
320
+ this.onAppDelete(this.attributes.apps);
321
+ });
322
+ });
323
+ };
324
+
316
325
  private onMainViewIndexChange = (index: number) => {
317
326
  if (index !== undefined && this._prevSceneIndex !== index) {
318
327
  callbacks.emit("mainViewSceneIndexChange", index);
@@ -322,7 +331,7 @@ export class AppManager {
322
331
  }
323
332
  this._prevSceneIndex = index;
324
333
  }
325
- }
334
+ };
326
335
 
327
336
  private onFocusChange = (focused: string | undefined) => {
328
337
  if (this._prevFocused !== focused) {
@@ -340,7 +349,12 @@ export class AppManager {
340
349
  }, 0);
341
350
  }
342
351
  }
343
- }
352
+ };
353
+
354
+ public attributesUpdateCallback = debounce(
355
+ (apps: any) => this._attributesUpdateCallback(apps),
356
+ 100
357
+ );
344
358
 
345
359
  /**
346
360
  * 插件更新 attributes 时的回调
@@ -348,7 +362,7 @@ export class AppManager {
348
362
  * @param {*} attributes
349
363
  * @memberof WindowManager
350
364
  */
351
- public async attributesUpdateCallback(apps: any) {
365
+ public async _attributesUpdateCallback(apps: any) {
352
366
  if (apps && WindowManager.container) {
353
367
  const appIds = Object.keys(apps);
354
368
  if (appIds.length === 0) {
@@ -571,6 +585,7 @@ export class AppManager {
571
585
  } else {
572
586
  this.mainView.disableCameraTransform = true;
573
587
  }
588
+ emitter.emit("writableChange", isWritable);
574
589
  };
575
590
 
576
591
  public safeSetAttributes(attributes: any) {
@@ -731,7 +746,7 @@ export class AppManager {
731
746
 
732
747
  public updateRootDirRemoving = (removing: boolean) => {
733
748
  this.rootDirRemoving = removing;
734
- }
749
+ };
735
750
 
736
751
  public dispatchInternalEvent(event: Events, payload?: any) {
737
752
  this.safeDispatchMagixEvent(MagixEventName, {
@@ -38,6 +38,11 @@ export type StoreContext = {
38
38
  safeUpdateAttributes: (keys: string[], value: any) => void;
39
39
  safeSetAttributes: (attributes: any) => void;
40
40
  }
41
+
42
+ export type ICamera = Camera & { id: string };
43
+
44
+ export type ISize = Size & { id: string };
45
+
41
46
  export class AttributesDelegate {
42
47
 
43
48
  constructor(private context: StoreContext) {}
@@ -152,14 +157,21 @@ export class AttributesDelegate {
152
157
  return get(this.attributes, [Fields.MainViewSize]);
153
158
  }
154
159
 
155
- public setMainViewCamera(camera: (Camera & { id: string }) | undefined) {
160
+ public setMainViewCamera(camera: ICamera) {
156
161
  this.context.safeSetAttributes({ [Fields.MainViewCamera]: { ...camera } });
157
162
  }
158
163
 
159
- public setMainViewSize(size: (Size & { id: string }) | undefined) {
164
+ public setMainViewSize(size: ISize) {
160
165
  this.context.safeSetAttributes({ [Fields.MainViewSize]: { ...size } });
161
166
  }
162
167
 
168
+ public setMainViewCameraAndSize(camera: ICamera, size: ISize) {
169
+ this.context.safeSetAttributes({
170
+ [Fields.MainViewCamera]: { ...camera },
171
+ [Fields.MainViewSize]: { ...size },
172
+ });
173
+ }
174
+
163
175
  public setAppFocus = (appId: string, focus: boolean) => {
164
176
  if (focus) {
165
177
  this.context.safeSetAttributes({ [Fields.Focus]: appId });
@@ -24,6 +24,7 @@ export type EmitterEvent = {
24
24
  rootDirRemoved: undefined;
25
25
  setReadonly: boolean;
26
26
  changePageState: undefined;
27
+ writableChange: boolean;
27
28
  };
28
29
 
29
30
  export type EmitterType = Emittery<EmitterEvent>;
@@ -36,6 +36,10 @@ export class ReconnectRefresher {
36
36
  };
37
37
 
38
38
  private onReconnected = debounce(() => {
39
+ this._onReconnected();
40
+ }, 3000);
41
+
42
+ private _onReconnected = () => {
39
43
  log("onReconnected refresh reactors");
40
44
  this.releaseDisposers();
41
45
  this.reactors.forEach((func, id) => {
@@ -44,7 +48,7 @@ export class ReconnectRefresher {
44
48
  }
45
49
  });
46
50
  this.ctx.emitter.emit("onReconnected", undefined);
47
- }, 3000);
51
+ }
48
52
 
49
53
  private releaseDisposers() {
50
54
  this.disposers.forEach(disposer => {
@@ -55,7 +59,15 @@ export class ReconnectRefresher {
55
59
  this.disposers.clear();
56
60
  }
57
61
 
62
+ public refresh() {
63
+ this._onReconnected();
64
+ }
65
+
58
66
  public add(id: string, func: any) {
67
+ const disposer = this.disposers.get(id);
68
+ if (disposer && isFunction(disposer)) {
69
+ disposer();
70
+ }
59
71
  if (isFunction(func)) {
60
72
  this.reactors.set(id, func);
61
73
  this.disposers.set(id, func());
@@ -8,6 +8,7 @@ import { setViewFocusScenePath } from "../Utils/Common";
8
8
  import { SideEffectManager } from "side-effect-manager";
9
9
  import type { Camera, Size, View } from "white-web-sdk";
10
10
  import type { AppManager } from "../AppManager";
11
+ import { Events } from "../constants";
11
12
 
12
13
  export class MainViewProxy {
13
14
  private scale?: number;
@@ -22,13 +23,10 @@ export class MainViewProxy {
22
23
  this.mainView = this.createMainView();
23
24
  this.moveCameraSizeByAttributes();
24
25
  emitter.once("mainViewMounted").then(() => {
25
- setTimeout(() => {
26
- this.addMainViewListener();
27
- this.start();
28
- if (!this.mainViewCamera || !this.mainViewSize) {
29
- this.setCameraAndSize();
30
- }
31
- }, 200); // 等待 mainView 挂载完毕再进行监听,否则会触发不必要的 onSizeUpdated
26
+ this.addMainViewListener();
27
+ this.start();
28
+ this.ensureCameraAndSize();
29
+ this.startListenWritableChange();
32
30
  });
33
31
  const playgroundSizeChangeListener = () => {
34
32
  this.sizeChangeHandler(this.mainViewSize);
@@ -39,6 +37,23 @@ export class MainViewProxy {
39
37
  });
40
38
  }
41
39
 
40
+ private startListenWritableChange = () => {
41
+ this.sideEffectManager.add(() => {
42
+ return emitter.on("writableChange", isWritable => {
43
+ if (isWritable) {
44
+ this.ensureCameraAndSize();
45
+ }
46
+ });
47
+ });
48
+ }
49
+
50
+ public ensureCameraAndSize() {
51
+ if (!this.mainViewCamera || !this.mainViewSize) {
52
+ this.manager.dispatchInternalEvent(Events.InitMainViewCamera);
53
+ this.setCameraAndSize();
54
+ }
55
+ }
56
+
42
57
  private get mainViewCamera() {
43
58
  return this.store.getMainViewCamera();
44
59
  }
@@ -56,13 +71,18 @@ export class MainViewProxy {
56
71
  if (this.started) return;
57
72
  this.sizeChangeHandler(this.mainViewSize);
58
73
  this.addCameraListener();
59
- this.manager.refresher?.add(Fields.MainViewCamera, this.cameraReaction);
74
+ this.addCameraReaction();
60
75
  this.started = true;
61
76
  }
62
77
 
78
+ public addCameraReaction = () => {
79
+ this.manager.refresher?.add(Fields.MainViewCamera, this.cameraReaction);
80
+ };
81
+
63
82
  public setCameraAndSize(): void {
64
- this.store.setMainViewCamera({ ...this.mainView.camera, id: this.manager.uid });
65
- this.store.setMainViewSize({ ...this.mainView.size, id: this.manager.uid });
83
+ const camera = { ...this.mainView.camera, id: this.manager.uid };
84
+ const size = { ...this.mainView.size, id: this.manager.uid };
85
+ this.store.setMainViewCameraAndSize(camera, size);
66
86
  }
67
87
 
68
88
  private cameraReaction = () => {
@@ -74,9 +94,7 @@ export class MainViewProxy {
74
94
  this.moveCamera(camera);
75
95
  }
76
96
  },
77
- {
78
- fireImmediately: true,
79
- }
97
+ { fireImmediately: true }
80
98
  );
81
99
  };
82
100
 
package/src/constants.ts CHANGED
@@ -14,6 +14,8 @@ export enum Events {
14
14
  MoveCameraToContain = "MoveCameraToContain",
15
15
  CursorMove = "CursorMove",
16
16
  RootDirRemoved = "RootDirRemoved",
17
+ Refresh = "Refresh",
18
+ InitMainViewCamera = "InitMainViewCamera",
17
19
  }
18
20
 
19
21
  export const MagixEventName = "__WindowManger";
package/src/index.ts CHANGED
@@ -332,6 +332,9 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
332
332
  params.chessboard,
333
333
  params.overwriteStyles
334
334
  );
335
+ if (this.boxManager) {
336
+ this.boxManager.destroy();
337
+ }
335
338
  const boxManager = createBoxManager(this, callbacks, emitter, {
336
339
  collectorContainer: params.collectorContainer,
337
340
  collectorStyles: params.collectorStyles,
@@ -876,6 +879,20 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
876
879
  return this.focusedView?.lockImages(locked);
877
880
  }
878
881
 
882
+ public refresh() {
883
+ this._refresh();
884
+ this.appManager?.dispatchInternalEvent(Events.Refresh);
885
+ }
886
+
887
+ /** @inner */
888
+ public _refresh() {
889
+ this.appManager?.mainViewProxy.rebind();
890
+ if (WindowManager.container) {
891
+ this.bindContainer(WindowManager.container);
892
+ }
893
+ this.appManager?.refresher?.refresh();
894
+ }
895
+
879
896
  private isDynamicPPT(scenes: SceneDefinition[]) {
880
897
  const sceneSrc = scenes[0]?.ppt?.src;
881
898
  return sceneSrc?.startsWith("pptx://");