@netless/window-manager 0.4.0-canary.1 → 0.4.0-canary.13

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 (64) hide show
  1. package/dist/App/MagixEvent/index.d.ts +29 -0
  2. package/dist/App/Storage/StorageEvent.d.ts +8 -0
  3. package/dist/App/Storage/index.d.ts +38 -0
  4. package/dist/App/Storage/typings.d.ts +21 -0
  5. package/dist/App/Storage/utils.d.ts +5 -0
  6. package/dist/AppContext.d.ts +40 -16
  7. package/dist/AppListener.d.ts +0 -1
  8. package/dist/AppManager.d.ts +8 -7
  9. package/dist/AppProxy.d.ts +3 -3
  10. package/dist/Base/Context.d.ts +0 -1
  11. package/dist/BoxManager.d.ts +1 -0
  12. package/dist/BuiltinApps.d.ts +6 -0
  13. package/dist/ContainerResizeObserver.d.ts +10 -0
  14. package/dist/Cursor/Cursor.d.ts +2 -3
  15. package/dist/Cursor/index.d.ts +7 -4
  16. package/dist/Helper.d.ts +6 -0
  17. package/dist/ReconnectRefresher.d.ts +5 -2
  18. package/dist/Utils/Common.d.ts +3 -1
  19. package/dist/Utils/Reactive.d.ts +1 -1
  20. package/dist/{MainView.d.ts → View/MainView.d.ts} +2 -4
  21. package/dist/View/ViewManager.d.ts +13 -0
  22. package/dist/constants.d.ts +1 -6
  23. package/dist/index.d.ts +14 -13
  24. package/dist/index.es.js +1 -1
  25. package/dist/index.es.js.map +1 -1
  26. package/dist/index.umd.js +1 -1
  27. package/dist/index.umd.js.map +1 -1
  28. package/dist/style.css +1 -1
  29. package/dist/typings.d.ts +3 -2
  30. package/package.json +6 -5
  31. package/src/App/MagixEvent/index.ts +68 -0
  32. package/src/App/Storage/StorageEvent.ts +21 -0
  33. package/src/App/Storage/index.ts +284 -0
  34. package/src/App/Storage/typings.ts +21 -0
  35. package/src/App/Storage/utils.ts +17 -0
  36. package/src/AppContext.ts +65 -20
  37. package/src/AppListener.ts +1 -8
  38. package/src/AppManager.ts +68 -35
  39. package/src/AppProxy.ts +37 -46
  40. package/src/Base/Context.ts +0 -4
  41. package/src/BoxManager.ts +9 -7
  42. package/src/BuiltinApps.ts +24 -0
  43. package/src/ContainerResizeObserver.ts +62 -0
  44. package/src/Cursor/Cursor.ts +23 -34
  45. package/src/Cursor/index.ts +70 -41
  46. package/src/Helper.ts +30 -0
  47. package/src/ReconnectRefresher.ts +13 -5
  48. package/src/Utils/Common.ts +35 -13
  49. package/src/Utils/Reactive.ts +9 -3
  50. package/src/Utils/RoomHacker.ts +16 -0
  51. package/src/{MainView.ts → View/MainView.ts} +9 -25
  52. package/src/View/ViewManager.ts +53 -0
  53. package/src/constants.ts +1 -3
  54. package/src/index.ts +47 -86
  55. package/src/shim.d.ts +4 -0
  56. package/src/style.css +6 -0
  57. package/src/typings.ts +3 -2
  58. package/vite.config.js +4 -1
  59. package/dist/Utils/CameraStore.d.ts +0 -15
  60. package/dist/ViewManager.d.ts +0 -29
  61. package/dist/sdk.d.ts +0 -14
  62. package/src/Utils/CameraStore.ts +0 -72
  63. package/src/sdk.ts +0 -39
  64. package/src/viewManager.ts +0 -177
package/src/AppContext.ts CHANGED
@@ -6,18 +6,20 @@ 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
- import type { Room, SceneDefinition, View } from "white-web-sdk";
11
+ import type { Room, SceneDefinition, View, EventListener as WhiteEventListener } from "white-web-sdk";
12
12
  import type { ReadonlyTeleBox } from "@netless/telebox-insider";
13
13
  import type Emittery from "emittery";
14
14
  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,44 @@ 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> = (event, handler, options) => {
162
+ this.manager.displayer.addMagixEventListener(event, handler as WhiteEventListener, options);
163
+ return () => this.manager.displayer.removeMagixEventListener(event, handler as WhiteEventListener);
164
+ }
165
+
166
+ /** Remove a Magix event listener. */
167
+ public removeMagixEventListener = this.manager.displayer.removeMagixEventListener.bind(this.manager.displayer) as MagixEventRemoveListener<TMagixEventPayloads>
123
168
  }
@@ -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;
@@ -65,16 +61,13 @@ export class AppListeners {
65
61
  this.manager.room?.refreshViewSize();
66
62
  };
67
63
 
68
- private switchViewsToFreedomHandler = () => {
69
- this.manager.viewManager.freedomAllViews();
70
- };
71
-
72
64
  private boxStateChangeHandler = (state: TeleBoxState) => {
73
65
  callbacks.emit("boxStateChange", state);
74
66
  }
75
67
 
76
68
  private setMainViewScenePathHandler = ({ nextScenePath }: { nextScenePath: string }) => {
77
69
  setViewFocusScenePath(this.manager.mainView, nextScenePath);
70
+ callbacks.emit("mainViewScenePathChange", nextScenePath);
78
71
  }
79
72
 
80
73
  private moveCameraToContainHandler = (payload: any) => {
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,6 +29,9 @@ 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({
@@ -37,19 +39,18 @@ export class AppManager {
37
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, {
48
- notifyReconnected: () => this.notifyReconnected(),
49
- });
48
+ this.refresher = reconnectRefresher;
49
+ this.refresher.setRoom(this.room);
50
+ this.refresher.setContext({ emitter });
50
51
 
51
52
  emitter.once("onCreated").then(() => this.onCreated());
52
-
53
+ emitter.on("onReconnected", () => this.onReconnected());
53
54
  if (isPlayer(this.displayer)) {
54
55
  emitter.on("seek", time => {
55
56
  this.appProxies.forEach(appProxy => {
@@ -97,6 +98,24 @@ export class AppManager {
97
98
  }
98
99
  });
99
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
+ })
100
119
  if (!this.attributes.apps || Object.keys(this.attributes.apps).length === 0) {
101
120
  const mainScenePath = this.store.getMainViewScenePath();
102
121
  if (!mainScenePath) return;
@@ -107,6 +126,7 @@ export class AppManager {
107
126
  }
108
127
  this.displayerWritableListener(!this.room?.isWritable);
109
128
  this.displayer.callbacks.on("onEnableWriteNowChanged", this.displayerWritableListener);
129
+ this._prevFocused = this.attributes.focus;
110
130
  }
111
131
 
112
132
  /**
@@ -187,15 +207,18 @@ export class AppManager {
187
207
  mainView.disableCameraTransform = disableCameraTransform;
188
208
  mainView.divElement = divElement;
189
209
  if (!mainView.focusScenePath) {
190
- this.store.setMainViewFocusPath(mainView);
191
- }
192
- if (this.store.focus === undefined && mainView.mode !== ViewVisionMode.Writable) {
193
- this.viewManager.switchMainViewToWriter();
210
+ this.setMainViewFocusPath();
194
211
  }
195
- this.mainViewProxy.addMainViewListener();
196
212
  emitter.emit("mainViewMounted");
197
213
  }
198
214
 
215
+ public setMainViewFocusPath() {
216
+ const scenePath = this.store.getMainViewScenePath();
217
+ if (scenePath) {
218
+ setViewFocusScenePath(this.mainView, scenePath);
219
+ }
220
+ }
221
+
199
222
  public async addApp(params: AddAppParams, isDynamicPPT: boolean): Promise<string | undefined> {
200
223
  log("addApp", params);
201
224
  const { appId, needFocus } = await this.beforeAddApp(params, isDynamicPPT);
@@ -281,7 +304,7 @@ export class AppManager {
281
304
  emitter.emit("observerIdChange", this.displayer.observerId);
282
305
  };
283
306
 
284
- private displayerWritableListener = (isReadonly: boolean) => {
307
+ public displayerWritableListener = (isReadonly: boolean) => {
285
308
  const isWritable = !isReadonly;
286
309
  const isManualWritable =
287
310
  this.windowManger.readonly === undefined || this.windowManger.readonly === false;
@@ -294,10 +317,10 @@ export class AppManager {
294
317
  appProxy.emitAppIsWritableChange();
295
318
  });
296
319
  if (isWritable === true) {
297
- if (!this.store.focus) {
298
- this.mainViewProxy.switchViewModeToWriter();
299
- }
300
320
  this.mainView.disableCameraTransform = false;
321
+ if (this.room && this.room.disableSerialization === true) {
322
+ this.room.disableSerialization = false;
323
+ }
301
324
  } else {
302
325
  this.mainView.disableCameraTransform = true;
303
326
  }
@@ -346,15 +369,16 @@ export class AppManager {
346
369
  await this._setMainViewScenePath(scenePath);
347
370
  } else if (scenePathType === ScenePathType.Dir) {
348
371
  const validScenePath = makeValidScenePath(this.displayer, scenePath);
349
- await this._setMainViewScenePath(validScenePath);
372
+ if (validScenePath) {
373
+ await this._setMainViewScenePath(validScenePath);
374
+ }
350
375
  }
351
376
  }
352
377
  }
353
378
 
354
379
  private async _setMainViewScenePath(scenePath: string) {
355
380
  this.safeSetAttributes({ _mainScenePath: scenePath });
356
- await this.viewManager.switchMainViewToWriter();
357
- setScenePath(this.room, scenePath);
381
+ this.setMainViewFocusPath();
358
382
  this.store.setMainViewFocusPath(this.mainView);
359
383
  this.dispatchInternalEvent(Events.SetMainViewScenePath, { nextScenePath: scenePath });
360
384
  }
@@ -362,12 +386,20 @@ export class AppManager {
362
386
  public async setMainViewSceneIndex(index: number) {
363
387
  if (this.room) {
364
388
  this.safeSetAttributes({ _mainSceneIndex: index });
365
- await this.viewManager.switchMainViewToWriter();
366
- this.room.setSceneIndex(index);
367
- const nextScenePath = this.room.state.sceneState.scenePath;
368
- this.store.setMainViewScenePath(nextScenePath);
369
- this.store.setMainViewFocusPath(this.mainView);
370
- 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
+ }
371
403
  }
372
404
  }
373
405
 
@@ -433,7 +465,7 @@ export class AppManager {
433
465
  }
434
466
  }
435
467
 
436
- public async notifyReconnected() {
468
+ public async onReconnected() {
437
469
  const appProxies = Array.from(this.appProxies.values());
438
470
  const reconnected = appProxies.map(appProxy => {
439
471
  return appProxy.onReconnected();
@@ -470,5 +502,6 @@ export class AppManager {
470
502
  this.refresher?.destroy();
471
503
  this.mainViewProxy.destroy();
472
504
  callbacks.clearListeners();
505
+ this._prevSceneIndex = undefined;
473
506
  }
474
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,7 +32,6 @@ 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";
@@ -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
 
@@ -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,
@@ -145,6 +145,11 @@ export class BoxManager {
145
145
  this.teleBoxManager.events.on("z_index", box => {
146
146
  this.context.updateAppState(box.id, AppAttributes.ZIndex, box.zIndex);
147
147
  });
148
+ emitter.on("playgroundSizeChange", this.playgroundSizeChangeListener);
149
+ }
150
+
151
+ private playgroundSizeChangeListener = () => {
152
+ this.updateManagerRect();
148
153
  }
149
154
 
150
155
  private get mainView() {
@@ -251,12 +256,8 @@ export class BoxManager {
251
256
  }
252
257
 
253
258
  public setCollectorContainer(container: HTMLElement) {
254
- const styles = {
255
- ...DEFAULT_COLLECTOR_STYLE,
256
- ...this.createTeleBoxManagerConfig?.collectorStyles,
257
- };
258
259
  const collector = new TeleBoxCollector({
259
- styles
260
+ styles: this.createTeleBoxManagerConfig?.collectorStyles,
260
261
  }).mount(container);
261
262
  this.teleBoxManager.setCollector(collector);
262
263
  }
@@ -391,6 +392,7 @@ export class BoxManager {
391
392
  }
392
393
 
393
394
  public destroy() {
395
+ emitter.off("playgroundSizeChange", this.playgroundSizeChangeListener);
394
396
  this.teleBoxManager.destroy();
395
397
  }
396
398
  }
@@ -0,0 +1,24 @@
1
+ import AppDocsViewer from "@netless/app-docs-viewer";
2
+ import AppMediaPlayer, { setOptions } from "@netless/app-media-player";
3
+ import { WindowManager } from "./index";
4
+ import "@netless/app-docs-viewer/dist/style.css";
5
+
6
+ export const setupBuiltin = () => {
7
+ if (WindowManager.debug) {
8
+ setOptions({ verbose: true });
9
+ }
10
+
11
+ WindowManager.register({
12
+ kind: AppDocsViewer.kind,
13
+ src: AppDocsViewer,
14
+ });
15
+ WindowManager.register({
16
+ kind: AppMediaPlayer.kind,
17
+ src: AppMediaPlayer,
18
+ });
19
+ };
20
+
21
+ export const BuiltinApps = {
22
+ DocsViewer: AppDocsViewer.kind as string,
23
+ MediaPlayer: AppMediaPlayer.kind as string,
24
+ };