@netless/window-manager 0.4.0-canary.0 → 0.4.0-canary.12

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 (65) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/App/MagixEvent/index.d.ts +28 -0
  3. package/dist/App/Storage/StorageEvent.d.ts +8 -0
  4. package/dist/App/Storage/index.d.ts +38 -0
  5. package/dist/App/Storage/typings.d.ts +21 -0
  6. package/dist/App/Storage/utils.d.ts +5 -0
  7. package/dist/AppContext.d.ts +40 -16
  8. package/dist/AppListener.d.ts +1 -1
  9. package/dist/AppManager.d.ts +8 -7
  10. package/dist/AppProxy.d.ts +4 -4
  11. package/dist/Base/Context.d.ts +0 -1
  12. package/dist/BoxManager.d.ts +1 -0
  13. package/dist/BuiltinApps.d.ts +6 -0
  14. package/dist/ContainerResizeObserver.d.ts +10 -0
  15. package/dist/Cursor/Cursor.d.ts +2 -3
  16. package/dist/Cursor/index.d.ts +7 -4
  17. package/dist/Helper.d.ts +6 -0
  18. package/dist/ReconnectRefresher.d.ts +8 -3
  19. package/dist/Utils/Common.d.ts +3 -1
  20. package/dist/Utils/Reactive.d.ts +1 -1
  21. package/dist/{MainView.d.ts → View/MainView.d.ts} +3 -4
  22. package/dist/View/ViewManager.d.ts +13 -0
  23. package/dist/constants.d.ts +3 -7
  24. package/dist/index.d.ts +14 -14
  25. package/dist/index.es.js +1 -1
  26. package/dist/index.es.js.map +1 -1
  27. package/dist/index.umd.js +1 -1
  28. package/dist/index.umd.js.map +1 -1
  29. package/dist/style.css +1 -1
  30. package/dist/typings.d.ts +3 -2
  31. package/package.json +7 -5
  32. package/src/App/MagixEvent/index.ts +66 -0
  33. package/src/App/Storage/StorageEvent.ts +21 -0
  34. package/src/App/Storage/index.ts +284 -0
  35. package/src/App/Storage/typings.ts +21 -0
  36. package/src/App/Storage/utils.ts +17 -0
  37. package/src/AppContext.ts +61 -19
  38. package/src/AppListener.ts +9 -8
  39. package/src/AppManager.ts +71 -36
  40. package/src/AppProxy.ts +39 -48
  41. package/src/Base/Context.ts +0 -4
  42. package/src/BoxManager.ts +9 -8
  43. package/src/BuiltinApps.ts +24 -0
  44. package/src/ContainerResizeObserver.ts +62 -0
  45. package/src/Cursor/Cursor.ts +23 -34
  46. package/src/Cursor/index.ts +70 -41
  47. package/src/Helper.ts +30 -0
  48. package/src/ReconnectRefresher.ts +15 -4
  49. package/src/Utils/Common.ts +35 -13
  50. package/src/Utils/Reactive.ts +9 -3
  51. package/src/Utils/RoomHacker.ts +15 -0
  52. package/src/{MainView.ts → View/MainView.ts} +19 -27
  53. package/src/View/ViewManager.ts +53 -0
  54. package/src/constants.ts +2 -3
  55. package/src/index.ts +81 -117
  56. package/src/shim.d.ts +4 -0
  57. package/src/style.css +6 -0
  58. package/src/typings.ts +3 -2
  59. package/vite.config.js +4 -1
  60. package/dist/Utils/CameraStore.d.ts +0 -15
  61. package/dist/ViewManager.d.ts +0 -29
  62. package/dist/sdk.d.ts +0 -14
  63. package/src/Utils/CameraStore.ts +0 -72
  64. package/src/sdk.ts +0 -39
  65. package/src/viewManager.ts +0 -177
package/src/AppContext.ts CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  unlistenDisposed,
7
7
  unlistenUpdated,
8
8
  toJS
9
- } from 'white-web-sdk';
9
+ } from 'white-web-sdk';
10
10
  import { BoxNotCreatedError } from './Utils/error';
11
11
  import type { Room, SceneDefinition, View } from "white-web-sdk";
12
12
  import type { ReadonlyTeleBox } from "@netless/telebox-insider";
@@ -15,9 +15,11 @@ import type { BoxManager } from "./BoxManager";
15
15
  import type { AppEmitterEvent } from "./index";
16
16
  import type { AppManager } from "./AppManager";
17
17
  import type { AppProxy } from "./AppProxy";
18
+ import { Storage } from './App/Storage';
19
+ import type { MagixEventAddListener, MagixEventDispatcher, MagixEventRemoveListener } from './App/MagixEvent';
18
20
 
19
- export class AppContext<TAttrs extends Record<string, any>, AppOptions = any> {
20
- public readonly emitter: Emittery<AppEmitterEvent<TAttrs>>;
21
+ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOptions = any> {
22
+ public readonly emitter: Emittery<AppEmitterEvent<TAttributes>>;
21
23
  public readonly mobxUtils = {
22
24
  autorun,
23
25
  reaction,
@@ -39,21 +41,22 @@ export class AppContext<TAttrs extends Record<string, any>, AppOptions = any> {
39
41
  private boxManager: BoxManager,
40
42
  public appId: string,
41
43
  private appProxy: AppProxy,
42
- private appOptions?: AppOptions | (() => AppOptions),
44
+ private appOptions?: TAppOptions | (() => TAppOptions),
43
45
  ) {
44
46
  this.emitter = appProxy.appEmitter;
45
47
  this.isAddApp = appProxy.isAddApp;
46
48
  }
47
49
 
48
- public getDisplayer() {
50
+ public getDisplayer = () => {
49
51
  return this.manager.displayer;
50
52
  }
51
53
 
52
- public getAttributes(): TAttrs | undefined {
54
+ /** @deprecated Use context.storage.state instead. */
55
+ public getAttributes = (): TAttributes | undefined => {
53
56
  return this.appProxy.attributes;
54
57
  }
55
58
 
56
- public getScenes(): SceneDefinition[] | undefined {
59
+ public getScenes = (): SceneDefinition[] | undefined => {
57
60
  const appAttr = this.store.getAppAttributes(this.appId);
58
61
  if (appAttr?.isDynamicPPT) {
59
62
  const appProxy = this.manager.appProxies.get(this.appId);
@@ -65,19 +68,21 @@ export class AppContext<TAttrs extends Record<string, any>, AppOptions = any> {
65
68
  }
66
69
  }
67
70
 
68
- public getView(): View | undefined {
71
+ public getView = (): View | undefined => {
69
72
  return this.appProxy.view;
70
73
  }
71
74
 
72
- public getInitScenePath() {
75
+ public getInitScenePath = () => {
73
76
  return this.manager.getAppInitPath(this.appId);
74
77
  }
75
78
 
76
- public getIsWritable(): boolean {
79
+ /** Get App writable status. */
80
+ public getIsWritable = (): boolean => {
77
81
  return this.manager.canOperate;
78
82
  }
79
83
 
80
- public getBox(): ReadonlyTeleBox {
84
+ /** Get the App Window UI box. */
85
+ public getBox = (): ReadonlyTeleBox => {
81
86
  const box = this.boxManager.getBox(this.appId);
82
87
  if (box) {
83
88
  return box;
@@ -86,27 +91,30 @@ export class AppContext<TAttrs extends Record<string, any>, AppOptions = any> {
86
91
  }
87
92
  }
88
93
 
89
- public getRoom(): Room | undefined {
94
+ public getRoom = (): Room | undefined => {
90
95
  return this.manager.room;
91
96
  }
92
97
 
93
- public setAttributes(attributes: TAttrs) {
98
+ /** @deprecated Use context.storage.setState instead. */
99
+ public setAttributes = (attributes: TAttributes) => {
94
100
  this.manager.safeSetAttributes({ [this.appId]: attributes });
95
101
  }
96
102
 
97
- public updateAttributes(keys: string[], value: any) {
103
+ /** @deprecated Use context.storage.setState instead. */
104
+ public updateAttributes = (keys: string[], value: any) => {
98
105
  if (this.manager.attributes[this.appId]) {
99
106
  this.manager.safeUpdateAttributes([this.appId, ...keys], value);
100
107
  }
101
108
  }
102
109
 
103
- public async setScenePath(scenePath: string): Promise<void> {
110
+ public setScenePath = async (scenePath: string): Promise<void> => {
104
111
  if (!this.appProxy.box) return;
105
112
  this.appProxy.setFullPath(scenePath);
106
- this.appProxy.context.switchAppToWriter(this.appId);
113
+ // 兼容 15 版本 SDK 的切页
114
+ this.getRoom()?.setScenePath(scenePath);
107
115
  }
108
116
 
109
- public mountView(dom: HTMLDivElement): void {
117
+ public mountView = (dom: HTMLDivElement): void => {
110
118
  const view = this.getView();
111
119
  if (view) {
112
120
  view.divElement = dom;
@@ -117,7 +125,41 @@ export class AppContext<TAttrs extends Record<string, any>, AppOptions = any> {
117
125
  }
118
126
  }
119
127
 
120
- public getAppOptions(): AppOptions | undefined {
121
- return typeof this.appOptions === 'function' ? (this.appOptions as () => AppOptions)() : this.appOptions
128
+ /** Get the local App options. */
129
+ public getAppOptions = (): TAppOptions | undefined => {
130
+ return typeof this.appOptions === 'function' ? (this.appOptions as () => TAppOptions)() : this.appOptions
122
131
  }
132
+
133
+ private _storage?: Storage<TAttributes>
134
+
135
+ /** Main Storage for attributes. */
136
+ public get storage(): Storage<TAttributes> {
137
+ if (!this._storage) {
138
+ this._storage = new Storage(this);
139
+ }
140
+ return this._storage;
141
+ }
142
+
143
+ /**
144
+ * Create separated storages for flexible state management.
145
+ * @param storeId Namespace for the storage. Storages of the same namespace share the same data.
146
+ * @param defaultState Default state for initial storage creation.
147
+ * @returns
148
+ */
149
+ public createStorage = <TState>(storeId: string, defaultState?: TState): Storage<TState> => {
150
+ const storage = new Storage(this, storeId, defaultState);
151
+ this.emitter.on("destroy", () => {
152
+ storage.destroy();
153
+ });
154
+ return storage;
155
+ }
156
+
157
+ /** Dispatch events to other clients (and self). */
158
+ public dispatchMagixEvent: MagixEventDispatcher<TMagixEventPayloads> = (this.manager.displayer as Room).dispatchMagixEvent.bind(this.manager.displayer)
159
+
160
+ /** Listen to events from others clients (and self messages). */
161
+ public addMagixEventListener: MagixEventAddListener<TMagixEventPayloads> = this.manager.displayer.addMagixEventListener.bind(this.manager.displayer)
162
+
163
+ /** Remove a Magix event listener. */
164
+ public removeMagixEventListener = this.manager.displayer.removeMagixEventListener.bind(this.manager.displayer) as MagixEventRemoveListener<TMagixEventPayloads>
123
165
  }
@@ -34,10 +34,6 @@ export class AppListeners {
34
34
  this.appResizeHandler(data.payload);
35
35
  break;
36
36
  }
37
- case Events.SwitchViewsToFreedom: {
38
- this.switchViewsToFreedomHandler();
39
- break;
40
- }
41
37
  case Events.AppBoxStateChange: {
42
38
  this.boxStateChangeHandler(data.payload);
43
39
  break;
@@ -46,6 +42,10 @@ export class AppListeners {
46
42
  this.setMainViewScenePathHandler(data.payload);
47
43
  break;
48
44
  }
45
+ case Events.MoveCameraToContain: {
46
+ this.moveCameraToContainHandler(data.payload);
47
+ break;
48
+ }
49
49
  default:
50
50
  break;
51
51
  }
@@ -61,15 +61,16 @@ export class AppListeners {
61
61
  this.manager.room?.refreshViewSize();
62
62
  };
63
63
 
64
- private switchViewsToFreedomHandler = () => {
65
- this.manager.viewManager.freedomAllViews();
66
- };
67
-
68
64
  private boxStateChangeHandler = (state: TeleBoxState) => {
69
65
  callbacks.emit("boxStateChange", state);
70
66
  }
71
67
 
72
68
  private setMainViewScenePathHandler = ({ nextScenePath }: { nextScenePath: string }) => {
73
69
  setViewFocusScenePath(this.manager.mainView, nextScenePath);
70
+ callbacks.emit("mainViewScenePathChange", nextScenePath);
71
+ }
72
+
73
+ private moveCameraToContainHandler = (payload: any) => {
74
+ this.manager.mainView.moveCameraToContain(payload);
74
75
  }
75
76
  }
package/src/AppManager.ts CHANGED
@@ -1,24 +1,23 @@
1
1
  import pRetry from "p-retry";
2
- import { sortBy } from "lodash";
3
2
  import { AppAttributes, AppStatus, Events, MagixEventName } from "./constants";
4
3
  import { AppListeners } from "./AppListener";
5
4
  import { AppProxy } from "./AppProxy";
6
- import { store } from "./AttributesDelegate";
7
- import { autorun, isPlayer, isRoom, ScenePathType, ViewVisionMode } from "white-web-sdk";
8
- import { callbacks, emitter, WindowManager } from "./index";
9
- import { CameraStore } from "./Utils/CameraStore";
10
- import { genAppId, makeValidScenePath, setScenePath } from "./Utils/Common";
5
+ import { autorun, isPlayer, isRoom, ScenePathType } from "white-web-sdk";
6
+ import { callbacks, emitter, WindowManager, reconnectRefresher } from "./index";
7
+ import { genAppId, makeValidScenePath, setScenePath, setViewFocusScenePath } from "./Utils/Common";
11
8
  import { log } from "./Utils/log";
12
- import { MainViewProxy } from "./MainView";
9
+ import { MainViewProxy } from "./View/MainView";
13
10
  import { onObjectRemoved, safeListenPropsUpdated } from "./Utils/Reactive";
14
- import { ReconnectRefresher } from "./ReconnectRefresher";
15
- import { ViewManager } from "./ViewManager";
11
+ import { get, sortBy } from "lodash";
12
+ import { store } from "./AttributesDelegate";
13
+ import { ViewManager } from "./View/ViewManager";
14
+ import type { ReconnectRefresher } from "./ReconnectRefresher";
16
15
  import type { BoxManager } from "./BoxManager";
17
16
  import type { Displayer, DisplayerState, Room } from "white-web-sdk";
18
17
  import type { AddAppParams, BaseInsertParams, TeleBoxRect, EmitterEvent } from "./index";
18
+
19
19
  export class AppManager {
20
20
  public displayer: Displayer;
21
- public cameraStore: CameraStore;
22
21
  public viewManager: ViewManager;
23
22
  public appProxies: Map<string, AppProxy> = new Map();
24
23
  public appStatus: Map<string, AppStatus> = new Map();
@@ -30,24 +29,28 @@ export class AppManager {
30
29
  private appListeners: AppListeners;
31
30
  public boxManager?: BoxManager;
32
31
 
32
+ private _prevSceneIndex: number | undefined;
33
+ private _prevFocused: string | undefined;
34
+
33
35
  constructor(public windowManger: WindowManager) {
34
36
  this.displayer = windowManger.displayer;
35
37
  this.store.setContext({
36
38
  getAttributes: () => this.attributes,
37
- safeSetAttributes: (attributes) => this.safeSetAttributes(attributes),
39
+ safeSetAttributes: attributes => this.safeSetAttributes(attributes),
38
40
  safeUpdateAttributes: (keys, val) => this.safeUpdateAttributes(keys, val),
39
41
  });
40
- this.cameraStore = new CameraStore();
41
42
  this.mainViewProxy = new MainViewProxy(this);
42
- this.viewManager = new ViewManager(this);
43
+ this.viewManager = new ViewManager(this.displayer);
43
44
  this.appListeners = new AppListeners(this);
44
45
  this.displayer.callbacks.on(this.eventName, this.displayerStateListener);
45
46
  this.appListeners.addListeners();
46
47
 
47
- this.refresher = new ReconnectRefresher(this.room, this);
48
+ this.refresher = reconnectRefresher;
49
+ this.refresher.setRoom(this.room);
50
+ this.refresher.setContext({ emitter });
48
51
 
49
52
  emitter.once("onCreated").then(() => this.onCreated());
50
-
53
+ emitter.on("onReconnected", () => this.onReconnected());
51
54
  if (isPlayer(this.displayer)) {
52
55
  emitter.on("seek", time => {
53
56
  this.appProxies.forEach(appProxy => {
@@ -95,6 +98,24 @@ export class AppManager {
95
98
  }
96
99
  });
97
100
  });
101
+ this.refresher?.add("mainViewIndex", () => {
102
+ return autorun(() => {
103
+ const mainSceneIndex = get(this.attributes, "_mainSceneIndex");
104
+ if (mainSceneIndex !== undefined && this._prevSceneIndex !== mainSceneIndex) {
105
+ callbacks.emit("mainViewSceneIndexChange", mainSceneIndex);
106
+ this._prevSceneIndex = mainSceneIndex;
107
+ }
108
+ });
109
+ });
110
+ this.refresher?.add("focusedChange", () => {
111
+ return autorun(() => {
112
+ const focused = get(this.attributes, "focus");
113
+ if (this._prevFocused !== focused) {
114
+ callbacks.emit("focusedChange", focused);
115
+ this._prevFocused = focused;
116
+ }
117
+ });
118
+ })
98
119
  if (!this.attributes.apps || Object.keys(this.attributes.apps).length === 0) {
99
120
  const mainScenePath = this.store.getMainViewScenePath();
100
121
  if (!mainScenePath) return;
@@ -105,6 +126,7 @@ export class AppManager {
105
126
  }
106
127
  this.displayerWritableListener(!this.room?.isWritable);
107
128
  this.displayer.callbacks.on("onEnableWriteNowChanged", this.displayerWritableListener);
129
+ this._prevFocused = this.attributes.focus;
108
130
  }
109
131
 
110
132
  /**
@@ -116,11 +138,11 @@ export class AppManager {
116
138
  public async attributesUpdateCallback(apps: any) {
117
139
  if (apps && WindowManager.container) {
118
140
  const appIds = Object.keys(apps);
119
- const appsWithCreatedAt = appIds.map(appId => {
141
+ const appsWithCreatedAt = appIds.map(appId => {
120
142
  return {
121
143
  id: appId,
122
144
  createdAt: apps[appId].createdAt,
123
- }
145
+ };
124
146
  });
125
147
  for (const { id } of sortBy(appsWithCreatedAt, "createdAt")) {
126
148
  if (!this.appProxies.has(id) && !this.appStatus.has(id)) {
@@ -185,15 +207,18 @@ export class AppManager {
185
207
  mainView.disableCameraTransform = disableCameraTransform;
186
208
  mainView.divElement = divElement;
187
209
  if (!mainView.focusScenePath) {
188
- this.store.setMainViewFocusPath(mainView);
189
- }
190
- if (this.store.focus === undefined && mainView.mode !== ViewVisionMode.Writable) {
191
- this.viewManager.switchMainViewToWriter();
210
+ this.setMainViewFocusPath();
192
211
  }
193
- this.mainViewProxy.addMainViewListener();
194
212
  emitter.emit("mainViewMounted");
195
213
  }
196
214
 
215
+ public setMainViewFocusPath() {
216
+ const scenePath = this.store.getMainViewScenePath();
217
+ if (scenePath) {
218
+ setViewFocusScenePath(this.mainView, scenePath);
219
+ }
220
+ }
221
+
197
222
  public async addApp(params: AddAppParams, isDynamicPPT: boolean): Promise<string | undefined> {
198
223
  log("addApp", params);
199
224
  const { appId, needFocus } = await this.beforeAddApp(params, isDynamicPPT);
@@ -279,7 +304,7 @@ export class AppManager {
279
304
  emitter.emit("observerIdChange", this.displayer.observerId);
280
305
  };
281
306
 
282
- private displayerWritableListener = (isReadonly: boolean) => {
307
+ public displayerWritableListener = (isReadonly: boolean) => {
283
308
  const isWritable = !isReadonly;
284
309
  const isManualWritable =
285
310
  this.windowManger.readonly === undefined || this.windowManger.readonly === false;
@@ -292,10 +317,10 @@ export class AppManager {
292
317
  appProxy.emitAppIsWritableChange();
293
318
  });
294
319
  if (isWritable === true) {
295
- if (!this.store.focus) {
296
- this.mainViewProxy.switchViewModeToWriter();
297
- }
298
320
  this.mainView.disableCameraTransform = false;
321
+ if (this.room && this.room.disableSerialization === true) {
322
+ this.room.disableSerialization = false;
323
+ }
299
324
  } else {
300
325
  this.mainView.disableCameraTransform = true;
301
326
  }
@@ -344,15 +369,16 @@ export class AppManager {
344
369
  await this._setMainViewScenePath(scenePath);
345
370
  } else if (scenePathType === ScenePathType.Dir) {
346
371
  const validScenePath = makeValidScenePath(this.displayer, scenePath);
347
- await this._setMainViewScenePath(validScenePath);
372
+ if (validScenePath) {
373
+ await this._setMainViewScenePath(validScenePath);
374
+ }
348
375
  }
349
376
  }
350
377
  }
351
378
 
352
379
  private async _setMainViewScenePath(scenePath: string) {
353
380
  this.safeSetAttributes({ _mainScenePath: scenePath });
354
- await this.viewManager.switchMainViewToWriter();
355
- setScenePath(this.room, scenePath);
381
+ this.setMainViewFocusPath();
356
382
  this.store.setMainViewFocusPath(this.mainView);
357
383
  this.dispatchInternalEvent(Events.SetMainViewScenePath, { nextScenePath: scenePath });
358
384
  }
@@ -360,12 +386,20 @@ export class AppManager {
360
386
  public async setMainViewSceneIndex(index: number) {
361
387
  if (this.room) {
362
388
  this.safeSetAttributes({ _mainSceneIndex: index });
363
- await this.viewManager.switchMainViewToWriter();
364
- this.room.setSceneIndex(index);
365
- const nextScenePath = this.room.state.sceneState.scenePath;
366
- this.store.setMainViewScenePath(nextScenePath);
367
- this.store.setMainViewFocusPath(this.mainView);
368
- this.dispatchInternalEvent(Events.SetMainViewScenePath, { nextScenePath });
389
+ const mainViewScenePath = this.store.getMainViewScenePath() as string;
390
+ if (mainViewScenePath) {
391
+ const sceneList = mainViewScenePath.split("/");
392
+ sceneList.pop();
393
+ let sceneDir = sceneList.join("/");
394
+ if (sceneDir === "") {
395
+ sceneDir = "/";
396
+ }
397
+ const scenePath = makeValidScenePath(this.displayer, sceneDir, index);
398
+ if (scenePath) {
399
+ this.store.setMainViewScenePath(scenePath);
400
+ this.setMainViewFocusPath();
401
+ }
402
+ }
369
403
  }
370
404
  }
371
405
 
@@ -431,7 +465,7 @@ export class AppManager {
431
465
  }
432
466
  }
433
467
 
434
- public async notifyReconnected() {
468
+ public async onReconnected() {
435
469
  const appProxies = Array.from(this.appProxies.values());
436
470
  const reconnected = appProxies.map(appProxy => {
437
471
  return appProxy.onReconnected();
@@ -468,5 +502,6 @@ export class AppManager {
468
502
  this.refresher?.destroy();
469
503
  this.mainViewProxy.destroy();
470
504
  callbacks.clearListeners();
505
+ this._prevSceneIndex = undefined;
471
506
  }
472
507
  }
package/src/AppProxy.ts CHANGED
@@ -2,17 +2,12 @@ import Emittery from "emittery";
2
2
  import { AppAttributes, AppEvents, Events } from "./constants";
3
3
  import { AppContext } from "./AppContext";
4
4
  import { appRegister } from "./Register";
5
- import { autorun, ViewVisionMode } from "white-web-sdk";
6
- import { callbacks, emitter } from "./index";
5
+ import { autorun } from "white-web-sdk";
6
+ import { emitter } from "./index";
7
7
  import { Fields } from "./AttributesDelegate";
8
- import { get } from "lodash";
8
+ import { debounce, get } from "lodash";
9
9
  import { log } from "./Utils/log";
10
- import {
11
- notifyMainViewModeChange,
12
- setScenePath,
13
- setViewFocusScenePath,
14
- setViewMode,
15
- } from "./Utils/Common";
10
+ import { setScenePath, setViewFocusScenePath, getScenePath } from "./Utils/Common";
16
11
  import type {
17
12
  AppEmitterEvent,
18
13
  AppInitState,
@@ -37,12 +32,11 @@ export class AppProxy extends Base {
37
32
  private boxManager = this.manager.boxManager;
38
33
  private appProxies = this.manager.appProxies;
39
34
  private viewManager = this.manager.viewManager;
40
- private cameraStore = this.manager.cameraStore;
41
35
  private kind: string;
42
36
  public isAddApp: boolean;
43
37
  private status: "normal" | "destroyed" = "normal";
44
38
  private stateKey: string;
45
- private setupResult?: any;
39
+ private appResult?: NetlessApp<any>;
46
40
  private appContext?: AppContext<any, any>;
47
41
 
48
42
  constructor(
@@ -98,18 +92,24 @@ export class AppProxy extends Base {
98
92
 
99
93
  public getFullScenePath(): string | undefined {
100
94
  if (this.scenePath) {
101
- return get(this.appAttributes, [Fields.FullPath], this.scenePath);
95
+ return get(this.appAttributes, [Fields.FullPath], this.getFullScenePathFromScenes());
102
96
  }
103
97
  }
104
98
 
99
+ private getFullScenePathFromScenes() {
100
+ const sceneIndex = get(this.appAttributes, ["state", "SceneIndex"], 0);
101
+ const fullPath = getScenePath(this.manager.room, this.scenePath, sceneIndex);
102
+ if (fullPath) {
103
+ this.setFullPath(fullPath);
104
+ }
105
+ return fullPath;
106
+ }
107
+
105
108
  public setFullPath(path: string) {
106
109
  this.manager.safeUpdateAttributes(["apps", this.id, Fields.FullPath], path);
107
110
  }
108
111
 
109
- public async baseInsertApp(
110
- skipUpdate = false,
111
- focus?: boolean
112
- ): Promise<{ appId: string; app: NetlessApp }> {
112
+ public async baseInsertApp(skipUpdate = false): Promise<{ appId: string; app: NetlessApp }> {
113
113
  const params = this.params;
114
114
  if (!params.kind) {
115
115
  throw new Error("[WindowManager]: kind require");
@@ -117,14 +117,17 @@ export class AppProxy extends Base {
117
117
  const appImpl = await appRegister.appClasses.get(params.kind)?.();
118
118
  const appParams = appRegister.registered.get(params.kind);
119
119
  if (appImpl) {
120
- await this.setupApp(this.id, skipUpdate, appImpl, params.options, appParams?.appOptions);
120
+ await this.setupApp(
121
+ this.id,
122
+ skipUpdate,
123
+ appImpl,
124
+ params.options,
125
+ appParams?.appOptions
126
+ );
121
127
  } else {
122
128
  throw new Error(`[WindowManager]: app load failed ${params.kind} ${params.src}`);
123
129
  }
124
130
  this.context.updateManagerRect();
125
- if (focus) {
126
- this.focusApp();
127
- }
128
131
  return {
129
132
  appId: this.id,
130
133
  app: appImpl,
@@ -133,7 +136,6 @@ export class AppProxy extends Base {
133
136
 
134
137
  private focusApp() {
135
138
  this.focusBox();
136
- this.context.switchAppToWriter(this.id);
137
139
  this.store.setMainViewFocusPath(this.manager.mainView);
138
140
  }
139
141
 
@@ -171,7 +173,7 @@ export class AppProxy extends Base {
171
173
  setTimeout(async () => {
172
174
  // 延迟执行 setup, 防止初始化的属性没有更新成功
173
175
  const result = await app.setup(context);
174
- this.setupResult = result;
176
+ this.appResult = result;
175
177
  appRegister.notifyApp(app.kind, "created", { appId, result });
176
178
  this.afterSetupApp(boxInitState);
177
179
  this.fixMobileSize();
@@ -205,9 +207,6 @@ export class AppProxy extends Base {
205
207
 
206
208
  private afterSetupApp(boxInitState: AppInitState | undefined): void {
207
209
  if (boxInitState) {
208
- if (boxInitState.focus && this.scenePath) {
209
- this.context.switchAppToWriter(this.id);
210
- }
211
210
  if (!boxInitState?.x || !boxInitState.y) {
212
211
  this.boxManager?.setBoxInitState(this.id);
213
212
  }
@@ -226,29 +225,10 @@ export class AppProxy extends Base {
226
225
  await this.destroy(true, false, true);
227
226
  const params = this.params;
228
227
  const appProxy = new AppProxy(params, this.manager, this.id, this.isAddApp);
229
- await appProxy.baseInsertApp(true, this.store.focus === this.id);
228
+ await appProxy.baseInsertApp(true);
230
229
  this.boxManager?.updateBoxState(currentAppState);
231
230
  }
232
231
 
233
- public switchToWritable() {
234
- appRegister.notifyApp(this.kind, "focus", { appId: this.id });
235
- this.cameraStore.switchView(this.id, this.view, () => {
236
- if (this.view) {
237
- if (this.view.mode === ViewVisionMode.Writable) return;
238
- try {
239
- if (this.manager.mainView.mode === ViewVisionMode.Writable) {
240
- this.store.setMainViewFocusPath(this.manager.mainView);
241
- notifyMainViewModeChange(callbacks, ViewVisionMode.Freedom);
242
- setViewMode(this.manager.mainView, ViewVisionMode.Freedom);
243
- }
244
- setViewMode(this.view, ViewVisionMode.Writable);
245
- } catch (error) {
246
- log("switch view failed", error);
247
- }
248
- }
249
- });
250
- }
251
-
252
232
  public getAppInitState = (id: string) => {
253
233
  const attrs = this.store.getAppState(id);
254
234
  if (!attrs) return;
@@ -337,7 +317,7 @@ export class AppProxy extends Base {
337
317
  }
338
318
  });
339
319
  });
340
- this.manager.refresher?.add(this.stateKey,() => {
320
+ this.manager.refresher?.add(this.stateKey, () => {
341
321
  return autorun(() => {
342
322
  const appState = this.appAttributes?.state;
343
323
  if (appState?.zIndex > 0 && appState.zIndex !== this.box?.zIndex) {
@@ -345,8 +325,20 @@ export class AppProxy extends Base {
345
325
  }
346
326
  });
347
327
  });
328
+ this.manager.refresher?.add(`${appId}-fullPath`, () => {
329
+ return autorun(() => {
330
+ const fullPath = this.appAttributes.fullPath;
331
+ this.setFocusScenePathHandler(fullPath);
332
+ });
333
+ });
348
334
  };
349
335
 
336
+ private setFocusScenePathHandler = debounce((fullPath: string | undefined) => {
337
+ if (this.view && fullPath && fullPath !== this.view?.focusScenePath) {
338
+ setViewFocusScenePath(this.view, fullPath);
339
+ }
340
+ }, 50);
341
+
350
342
  public setScenePath(): void {
351
343
  if (!this.manager.canOperate) return;
352
344
  const fullScenePath = this.getFullScenePath();
@@ -364,7 +356,6 @@ export class AppProxy extends Base {
364
356
 
365
357
  private async createView(): Promise<View> {
366
358
  const view = await this.viewManager.createView(this.id);
367
- this.cameraStore.register(this.id, view);
368
359
  this.setViewFocusScenePath();
369
360
  return view;
370
361
  }
@@ -388,12 +379,12 @@ export class AppProxy extends Base {
388
379
  this.store.cleanAppAttributes(this.id);
389
380
  }
390
381
  this.appProxies.delete(this.id);
391
- this.cameraStore.unregister(this.id, this.view);
392
382
 
393
383
  this.viewManager.destroyView(this.id);
394
384
  this.manager.appStatus.delete(this.id);
395
385
  this.manager.refresher?.remove(this.id);
396
386
  this.manager.refresher?.remove(this.stateKey);
387
+ this.manager.refresher?.remove(`${this.id}-fullPath`);
397
388
  }
398
389
 
399
390
  public close(): Promise<void> {
@@ -33,10 +33,6 @@ export class Context {
33
33
  public blurFocusBox() {
34
34
  this.manager.boxManager?.blurAllBox();
35
35
  }
36
-
37
- public switchAppToWriter(id: string) {
38
- this.manager.viewManager.switchAppToWriter(id);
39
- }
40
36
  }
41
37
 
42
38
  let context: Context;
package/src/BoxManager.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { AppAttributes, DEFAULT_COLLECTOR_STYLE, Events, MIN_HEIGHT, MIN_WIDTH } from "./constants";
1
+ import { AppAttributes, Events, MIN_HEIGHT, MIN_WIDTH } from "./constants";
2
2
  import { debounce, maxBy } from "lodash";
3
3
  import {
4
4
  TELE_BOX_MANAGER_EVENT,
@@ -6,7 +6,7 @@ import {
6
6
  TeleBoxCollector,
7
7
  TeleBoxManager,
8
8
  } from "@netless/telebox-insider";
9
- import { WindowManager } from "./index";
9
+ import { emitter, WindowManager } from "./index";
10
10
  import type { AddAppOptions, AppInitState, EmitterType, CallbacksType } from "./index";
11
11
  import type {
12
12
  TeleBoxManagerUpdateConfig,
@@ -143,9 +143,13 @@ export class BoxManager {
143
143
  callbacks.emit("prefersColorSchemeChange", colorScheme);
144
144
  });
145
145
  this.teleBoxManager.events.on("z_index", box => {
146
- console.log("on z_index", box.id, box.zIndex);
147
146
  this.context.updateAppState(box.id, AppAttributes.ZIndex, box.zIndex);
148
147
  });
148
+ emitter.on("playgroundSizeChange", this.playgroundSizeChangeListener);
149
+ }
150
+
151
+ private playgroundSizeChangeListener = () => {
152
+ this.updateManagerRect();
149
153
  }
150
154
 
151
155
  private get mainView() {
@@ -252,12 +256,8 @@ export class BoxManager {
252
256
  }
253
257
 
254
258
  public setCollectorContainer(container: HTMLElement) {
255
- const styles = {
256
- ...DEFAULT_COLLECTOR_STYLE,
257
- ...this.createTeleBoxManagerConfig?.collectorStyles,
258
- };
259
259
  const collector = new TeleBoxCollector({
260
- styles
260
+ styles: this.createTeleBoxManagerConfig?.collectorStyles,
261
261
  }).mount(container);
262
262
  this.teleBoxManager.setCollector(collector);
263
263
  }
@@ -392,6 +392,7 @@ export class BoxManager {
392
392
  }
393
393
 
394
394
  public destroy() {
395
+ emitter.off("playgroundSizeChange", this.playgroundSizeChangeListener);
395
396
  this.teleBoxManager.destroy();
396
397
  }
397
398
  }