@netless/window-manager 0.4.18 → 0.4.21

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 (49) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +9 -3
  3. package/dist/{AppContext.d.ts → App/AppContext.d.ts} +12 -6
  4. package/dist/App/AppPageStateImpl.d.ts +17 -0
  5. package/dist/{AppProxy.d.ts → App/AppProxy.d.ts} +15 -7
  6. package/dist/App/Storage/index.d.ts +1 -1
  7. package/dist/App/index.d.ts +2 -0
  8. package/dist/AppListener.d.ts +1 -0
  9. package/dist/AppManager.d.ts +5 -2
  10. package/dist/Page/PageController.d.ts +15 -0
  11. package/dist/Page/index.d.ts +1 -0
  12. package/dist/PageState.d.ts +1 -4
  13. package/dist/ReconnectRefresher.d.ts +2 -0
  14. package/dist/RedoUndo.d.ts +1 -1
  15. package/dist/Utils/AppCreateQueue.d.ts +1 -1
  16. package/dist/Utils/Common.d.ts +1 -1
  17. package/dist/callback.d.ts +1 -1
  18. package/dist/constants.d.ts +2 -1
  19. package/dist/index.d.ts +7 -8
  20. package/dist/index.es.js +15446 -5
  21. package/dist/index.es.js.map +1 -1
  22. package/dist/index.umd.js +46 -41
  23. package/dist/index.umd.js.map +1 -1
  24. package/dist/style.css +1 -1
  25. package/dist/typings.d.ts +5 -2
  26. package/docs/api.md +8 -0
  27. package/docs/app-context.md +46 -1
  28. package/docs/develop-app.md +4 -0
  29. package/jest.config.js +27 -0
  30. package/package.json +11 -3
  31. package/pnpm-lock.yaml +8176 -0
  32. package/src/{AppContext.ts → App/AppContext.ts} +49 -7
  33. package/src/App/AppPageStateImpl.ts +49 -0
  34. package/src/{AppProxy.ts → App/AppProxy.ts} +57 -15
  35. package/src/App/Storage/index.ts +1 -1
  36. package/src/App/index.ts +2 -0
  37. package/src/AppListener.ts +8 -0
  38. package/src/AppManager.ts +27 -16
  39. package/src/Page/PageController.ts +18 -0
  40. package/src/Page/index.ts +1 -0
  41. package/src/PageState.ts +2 -6
  42. package/src/ReconnectRefresher.ts +13 -1
  43. package/src/RedoUndo.ts +1 -1
  44. package/src/Utils/AppCreateQueue.ts +3 -3
  45. package/src/Utils/Common.ts +2 -2
  46. package/src/callback.ts +1 -1
  47. package/src/constants.ts +1 -0
  48. package/src/index.ts +21 -9
  49. package/src/typings.ts +5 -2
@@ -1,5 +1,6 @@
1
- import { BoxNotCreatedError } from "./Utils/error";
2
- import { Storage } from "./App/Storage";
1
+ import { BoxNotCreatedError } from "../Utils/error";
2
+ import { putScenes } from "../Utils/Common";
3
+ import { Storage } from "./Storage";
3
4
  import {
4
5
  autorun,
5
6
  listenDisposed,
@@ -17,17 +18,20 @@ import type {
17
18
  } from "white-web-sdk";
18
19
  import type { ReadonlyTeleBox } from "@netless/telebox-insider";
19
20
  import type Emittery from "emittery";
20
- import type { BoxManager } from "./BoxManager";
21
- import type { AppEmitterEvent } from "./index";
22
- import type { AppManager } from "./AppManager";
21
+ import type { BoxManager } from "../BoxManager";
22
+ import type { AppEmitterEvent } from "../index";
23
+ import type { AppManager } from "../AppManager";
23
24
  import type { AppProxy } from "./AppProxy";
24
25
  import type {
25
26
  MagixEventAddListener,
26
27
  MagixEventDispatcher,
27
28
  MagixEventRemoveListener,
28
- } from "./App/MagixEvent";
29
+ } from "./MagixEvent";
30
+ import type { AddPageParams, PageController, PageState } from "../Page";
29
31
 
30
- export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOptions = any> {
32
+ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOptions = any>
33
+ implements PageController
34
+ {
31
35
  public readonly emitter: Emittery<AppEmitterEvent<TAttributes>>;
32
36
  public readonly mobxUtils = {
33
37
  autorun,
@@ -192,4 +196,42 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
192
196
  public removeMagixEventListener = this.manager.displayer.removeMagixEventListener.bind(
193
197
  this.manager.displayer
194
198
  ) as MagixEventRemoveListener<TMagixEventPayloads>;
199
+
200
+ /** PageController */
201
+ public nextPage = async (): Promise<boolean> => {
202
+ const nextIndex = this.pageState.index + 1;
203
+ if (nextIndex > this.pageState.length - 1) {
204
+ console.warn("[WindowManager] nextPage: index out of range");
205
+ return false;
206
+ }
207
+ this.appProxy.setSceneIndex(nextIndex);
208
+ return true;
209
+ };
210
+
211
+ public prevPage = async (): Promise<boolean> => {
212
+ const nextIndex = this.pageState.index - 1;
213
+ if (nextIndex < 0) {
214
+ console.warn("[WindowManager] prevPage: index out of range");
215
+ return false;
216
+ }
217
+ this.appProxy.setSceneIndex(nextIndex);
218
+ return true;
219
+ };
220
+
221
+ public addPage = async (params?: AddPageParams) => {
222
+ const after = params?.after;
223
+ const scene = params?.scene;
224
+ const scenePath = this.appProxy.scenePath;
225
+ if (!scenePath) return;
226
+ if (after) {
227
+ const nextIndex = this.pageState.index + 1;
228
+ putScenes(this.manager.room, scenePath, [scene || {}], nextIndex);
229
+ } else {
230
+ putScenes(this.manager.room, scenePath, [scene || {}]);
231
+ }
232
+ };
233
+
234
+ public get pageState(): PageState {
235
+ return this.appProxy.pageState;
236
+ }
195
237
  }
@@ -0,0 +1,49 @@
1
+ import type { Displayer, ScenesCallbacksNode, View } from "white-web-sdk";
2
+ import type { PageState } from "../Page";
3
+
4
+ export type AppPageStateParams = {
5
+ displayer: Displayer;
6
+ scenePath: string | undefined;
7
+ view: View | undefined;
8
+ notifyPageStateChange: () => void;
9
+ };
10
+
11
+ export class AppPageStateImpl {
12
+ private sceneNode: ScenesCallbacksNode | null = null;
13
+
14
+ constructor(private params: AppPageStateParams) {
15
+ const { displayer, scenePath } = this.params;
16
+ if (scenePath) {
17
+ this.sceneNode = displayer.createScenesCallback(scenePath, {
18
+ onAddScene: this.onSceneChange,
19
+ onRemoveScene: this.onSceneChange,
20
+ });
21
+ }
22
+ }
23
+
24
+ private onSceneChange = (node: ScenesCallbacksNode) => {
25
+ this.sceneNode = node;
26
+ this.params.notifyPageStateChange();
27
+ };
28
+
29
+ public getFullPath(index: number) {
30
+ const scenes = this.sceneNode?.scenes;
31
+ if (this.params.scenePath && scenes) {
32
+ const name = scenes[index];
33
+ if (name) {
34
+ return `${this.params.scenePath}/${name}`;
35
+ }
36
+ }
37
+ }
38
+
39
+ public toObject(): PageState {
40
+ return {
41
+ index: this.params.view?.focusSceneIndex || 0,
42
+ length: this.sceneNode?.scenes.length || 0,
43
+ };
44
+ }
45
+
46
+ public destroy() {
47
+ this.sceneNode?.dispose();
48
+ }
49
+ }
@@ -1,31 +1,41 @@
1
1
  import Emittery from "emittery";
2
- import { AppAttributes, AppEvents, Events, SETUP_APP_DELAY } from "./constants";
2
+ import { AppAttributes, AppEvents, Events, SETUP_APP_DELAY } from "../constants";
3
3
  import { AppContext } from "./AppContext";
4
- import { appRegister } from "./Register";
4
+ import { AppPageStateImpl } from "./AppPageStateImpl";
5
+ import { appRegister } from "../Register";
5
6
  import { autorun } from "white-web-sdk";
6
- import { BoxManagerNotFoundError } from "./Utils/error";
7
+ import { BoxManagerNotFoundError } from "../Utils/error";
7
8
  import { debounce, get } from "lodash";
8
- import { emitter } from "./InternalEmitter";
9
- import { Fields } from "./AttributesDelegate";
10
- import { entireScenes, getScenePath, removeScenes, setScenePath, setViewFocusScenePath } from "./Utils/Common";
11
- import { log } from "./Utils/log";
9
+ import { emitter } from "../InternalEmitter";
10
+ import { Fields } from "../AttributesDelegate";
11
+ import { log } from "../Utils/log";
12
+ import {
13
+ entireScenes,
14
+ getScenePath,
15
+ removeScenes,
16
+ setScenePath,
17
+ setViewFocusScenePath,
18
+ } from "../Utils/Common";
12
19
  import type {
13
20
  AppEmitterEvent,
14
21
  AppInitState,
15
22
  BaseInsertParams,
16
23
  setAppOptions,
17
24
  AppListenerKeys,
18
- } from "./index";
25
+ } from "../index";
19
26
  import type { SceneState, View, SceneDefinition } from "white-web-sdk";
20
- import type { AppManager } from "./AppManager";
21
- import type { NetlessApp } from "./typings";
27
+ import type { AppManager } from "../AppManager";
28
+ import type { NetlessApp } from "../typings";
22
29
  import type { ReadonlyTeleBox } from "@netless/telebox-insider";
30
+ import type { PageState } from "../Page";
31
+
32
+ export type AppEmitter = Emittery<AppEmitterEvent>;
23
33
 
24
34
  export class AppProxy {
25
35
  public kind: string;
26
36
  public id: string;
27
37
  public scenePath?: string;
28
- public appEmitter: Emittery<AppEmitterEvent>;
38
+ public appEmitter: AppEmitter;
29
39
  public scenes?: SceneDefinition[];
30
40
 
31
41
  private appListener: any;
@@ -37,8 +47,10 @@ export class AppProxy {
37
47
  public isAddApp: boolean;
38
48
  private status: "normal" | "destroyed" = "normal";
39
49
  private stateKey: string;
40
- private appResult?: NetlessApp<any>;
41
- private appContext?: AppContext<any, any>;
50
+ private _pageState: AppPageStateImpl;
51
+
52
+ public appResult?: NetlessApp<any>;
53
+ public appContext?: AppContext<any, any>;
42
54
 
43
55
  constructor(
44
56
  private params: BaseInsertParams,
@@ -60,6 +72,12 @@ export class AppProxy {
60
72
  // 只有传入了 scenePath 的 App 才会创建 View
61
73
  this.createView();
62
74
  }
75
+ this._pageState = new AppPageStateImpl({
76
+ displayer: this.manager.displayer,
77
+ scenePath: this.scenePath,
78
+ view: this.view,
79
+ notifyPageStateChange: this.notifyPageStateChange,
80
+ });
63
81
  }
64
82
 
65
83
  private initScenes() {
@@ -78,6 +96,10 @@ export class AppProxy {
78
96
  return this.manager.viewManager.getView(this.id);
79
97
  }
80
98
 
99
+ public get viewIndex(): number | undefined {
100
+ return this.view?.focusSceneIndex;
101
+ }
102
+
81
103
  public get isWritable(): boolean {
82
104
  return this.manager.canOperate && !this.box?.readonly;
83
105
  }
@@ -127,7 +149,7 @@ export class AppProxy {
127
149
  } else {
128
150
  throw new Error(`[WindowManager]: app load failed ${params.kind} ${params.src}`);
129
151
  }
130
- emitter.emit("updateManagerRect")
152
+ emitter.emit("updateManagerRect");
131
153
  return {
132
154
  appId: this.id,
133
155
  app: appImpl,
@@ -210,7 +232,7 @@ export class AppProxy {
210
232
 
211
233
  public async onSeek(time: number) {
212
234
  this.appEmitter.emit("seek", time).catch(err => {
213
- console.log(`[WindowManager]: emit seek error: ${err.message}`)
235
+ console.log(`[WindowManager]: emit seek error: ${err.message}`);
214
236
  });
215
237
  const boxInitState = this.getAppInitState(this.id);
216
238
  this.boxManager?.updateBoxState(boxInitState);
@@ -326,6 +348,7 @@ export class AppProxy {
326
348
  return autorun(() => {
327
349
  const fullPath = this.appAttributes?.fullPath;
328
350
  this.setFocusScenePathHandler(fullPath);
351
+ this.notifyPageStateChange();
329
352
  });
330
353
  });
331
354
  };
@@ -358,6 +381,24 @@ export class AppProxy {
358
381
  return view;
359
382
  }
360
383
 
384
+ public notifyPageStateChange = () => {
385
+ this.appEmitter.emit("pageStateChange", this.pageState);
386
+ };
387
+
388
+ public get pageState(): PageState {
389
+ return this._pageState.toObject();
390
+ }
391
+
392
+ public setSceneIndex(index: number) {
393
+ if (this.view) {
394
+ this.view.focusSceneIndex = index;
395
+ const fullPath = this._pageState.getFullPath(index);
396
+ if (fullPath) {
397
+ this.setFullPath(fullPath);
398
+ }
399
+ }
400
+ }
401
+
361
402
  public async destroy(
362
403
  needCloseBox: boolean,
363
404
  cleanAttrs: boolean,
@@ -384,6 +425,7 @@ export class AppProxy {
384
425
  }
385
426
  }
386
427
  this.appProxies.delete(this.id);
428
+ this._pageState.destroy();
387
429
 
388
430
  this.viewManager.destroyView(this.id);
389
431
  this.manager.appStatus.delete(this.id);
@@ -1,7 +1,7 @@
1
1
  import type { AkkoObjectUpdatedProperty } from "white-web-sdk";
2
2
  import { get, has, mapValues, isObject, size, noop } from "lodash";
3
3
  import { SideEffectManager } from "side-effect-manager";
4
- import type { AppContext } from "../../AppContext";
4
+ import type { AppContext } from "../AppContext";
5
5
  import { safeListenPropsUpdated } from "../../Utils/Reactive";
6
6
  import { isRef, makeRef, plainObjectKeys } from "./utils";
7
7
  import type { Diff, MaybeRefValue, RefValue, StorageStateChangedEvent, StorageStateChangedListener, StorageStateChangedListenerDisposer } from "./typings";
@@ -0,0 +1,2 @@
1
+ export * from "./AppProxy";
2
+ export * from "./AppContext";
@@ -59,6 +59,10 @@ export class AppListeners {
59
59
  this.rootDirRemovedHandler();
60
60
  break;
61
61
  }
62
+ case Events.Refresh: {
63
+ this.refreshHandler();
64
+ break;
65
+ }
62
66
  default:
63
67
  break;
64
68
  }
@@ -103,4 +107,8 @@ export class AppListeners {
103
107
  this.manager.mainViewProxy.rebind();
104
108
  emitter.emit("rootDirRemoved");
105
109
  }
110
+
111
+ private refreshHandler = () => {
112
+ this.manager.windowManger._refresh();
113
+ }
106
114
  }
package/src/AppManager.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  import { AppAttributes, AppStatus, Events, INIT_DIR, MagixEventName, ROOT_DIR } from "./constants";
2
2
  import { AppCreateQueue } from "./Utils/AppCreateQueue";
3
3
  import { AppListeners } from "./AppListener";
4
- import { AppProxy } from "./AppProxy";
4
+ 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
8
  import { emitter } from "./InternalEmitter";
9
9
  import { Fields, store } from "./AttributesDelegate";
10
- import { get, isInteger, orderBy } from "lodash";
10
+ import { debounce, 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";
@@ -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);
@@ -342,13 +351,15 @@ export class AppManager {
342
351
  }
343
352
  }
344
353
 
354
+ public attributesUpdateCallback = debounce((apps: any) => this._attributesUpdateCallback(apps), 100);
355
+
345
356
  /**
346
357
  * 插件更新 attributes 时的回调
347
358
  *
348
359
  * @param {*} attributes
349
360
  * @memberof WindowManager
350
361
  */
351
- public async attributesUpdateCallback(apps: any) {
362
+ public async _attributesUpdateCallback(apps: any) {
352
363
  if (apps && WindowManager.container) {
353
364
  const appIds = Object.keys(apps);
354
365
  if (appIds.length === 0) {
@@ -0,0 +1,18 @@
1
+ import type { SceneDefinition } from "white-web-sdk";
2
+
3
+ export type AddPageParams = {
4
+ after?: boolean;
5
+ scene?: SceneDefinition;
6
+ };
7
+
8
+ export type PageState = {
9
+ index: number;
10
+ length: number;
11
+ };
12
+
13
+ export interface PageController {
14
+ nextPage: () => Promise<boolean>;
15
+ prevPage: () => Promise<boolean>;
16
+ addPage: (params?: AddPageParams) => Promise<void>;
17
+ pageState: PageState;
18
+ }
@@ -0,0 +1 @@
1
+ export * from "./PageController";
package/src/PageState.ts CHANGED
@@ -1,11 +1,7 @@
1
- import type { AppManager } from "./AppManager";
2
1
  import { callbacks } from "./callback";
3
2
  import { emitter } from "./InternalEmitter";
4
-
5
- export type PageState = {
6
- index: number;
7
- length: number;
8
- };
3
+ import type { AppManager } from "./AppManager";
4
+ import type { PageState } from "./Page";
9
5
 
10
6
  export class PageStateImpl {
11
7
  constructor(private manager: AppManager) {
@@ -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());
package/src/RedoUndo.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { callbacks } from "./callback";
2
2
  import { emitter } from "./InternalEmitter";
3
3
  import type { View } from "white-web-sdk";
4
- import type { AppProxy } from "./AppProxy";
4
+ import type { AppProxy } from "./App";
5
5
 
6
6
  export type RedoUndoContext = {
7
7
  mainView: () => View;
@@ -1,6 +1,6 @@
1
1
  import { callbacks } from "../callback";
2
- import type { AppProxy } from "../AppProxy";
3
2
  import { SETUP_APP_DELAY } from "../constants";
3
+ import type { AppProxy } from "../App";
4
4
 
5
5
  export type Invoker = () => Promise<AppProxy | undefined>;
6
6
 
@@ -52,12 +52,12 @@ export class AppCreateQueue {
52
52
  this.clear();
53
53
  this.emitReady();
54
54
  }
55
- }
55
+ };
56
56
 
57
57
  private clear = () => {
58
58
  clearInterval(this.timer);
59
59
  this.timer = undefined;
60
- }
60
+ };
61
61
 
62
62
  public emitReady() {
63
63
  if (!this.isEmit) {
@@ -104,8 +104,8 @@ export const entireScenes = (displayer: Displayer) => {
104
104
  return displayer.entireScenes();
105
105
  };
106
106
 
107
- export const putScenes = (room: Room | undefined, path: string, scenes: SceneDefinition[]) => {
108
- return room?.putScenes(path, scenes);
107
+ export const putScenes = (room: Room | undefined, path: string, scenes: SceneDefinition[], index?: number) => {
108
+ return room?.putScenes(path, scenes, index);
109
109
  }
110
110
 
111
111
  export const isValidScenePath = (scenePath: string) => {
package/src/callback.ts CHANGED
@@ -2,7 +2,7 @@ import Emittery from "emittery";
2
2
  import type { TeleBoxColorScheme, TELE_BOX_STATE } from "@netless/telebox-insider";
3
3
  import type { CameraState, SceneState, ViewVisionMode } from "white-web-sdk";
4
4
  import type { LoadAppEvent } from "./Register";
5
- import type { PageState } from "./PageState";
5
+ import type { PageState } from "./Page";
6
6
 
7
7
  export type PublicEvent = {
8
8
  mainViewModeChange: ViewVisionMode;
package/src/constants.ts CHANGED
@@ -14,6 +14,7 @@ export enum Events {
14
14
  MoveCameraToContain = "MoveCameraToContain",
15
15
  CursorMove = "CursorMove",
16
16
  RootDirRemoved = "RootDirRemoved",
17
+ Refresh = "Refresh",
17
18
  }
18
19
 
19
20
  export const MagixEventName = "__WindowManger";
package/src/index.ts CHANGED
@@ -55,10 +55,10 @@ import type {
55
55
  import type { AppListeners } from "./AppListener";
56
56
  import type { NetlessApp, RegisterParams } from "./typings";
57
57
  import type { TeleBoxColorScheme, TeleBoxState } from "@netless/telebox-insider";
58
- import type { AppProxy } from "./AppProxy";
59
- import type { PublicEvent } from "./Callback";
58
+ import type { AppProxy } from "./App";
59
+ import type { PublicEvent } from "./callback";
60
60
  import type Emittery from "emittery";
61
- import type { PageState } from "./PageState";
61
+ import type { PageController, AddPageParams, PageState } from "./Page";
62
62
 
63
63
  export type WindowMangerAttributes = {
64
64
  modelValue?: string;
@@ -145,12 +145,7 @@ export type MountParams = {
145
145
 
146
146
  export const reconnectRefresher = new ReconnectRefresher({ emitter });
147
147
 
148
- export type AddPageParams = {
149
- after?: boolean;
150
- scene?: SceneDefinition;
151
- };
152
-
153
- export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
148
+ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> implements PageController {
154
149
  public static kind = "WindowManager";
155
150
  public static displayer: Displayer;
156
151
  public static wrapper?: HTMLElement;
@@ -337,6 +332,9 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
337
332
  params.chessboard,
338
333
  params.overwriteStyles
339
334
  );
335
+ if (this.boxManager) {
336
+ this.boxManager.destroy();
337
+ }
340
338
  const boxManager = createBoxManager(this, callbacks, emitter, {
341
339
  collectorContainer: params.collectorContainer,
342
340
  collectorStyles: params.collectorStyles,
@@ -881,6 +879,20 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
881
879
  return this.focusedView?.lockImages(locked);
882
880
  }
883
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
+
884
896
  private isDynamicPPT(scenes: SceneDefinition[]) {
885
897
  const sceneSrc = scenes[0]?.ppt?.src;
886
898
  return sceneSrc?.startsWith("pptx://");
package/src/typings.ts CHANGED
@@ -9,8 +9,9 @@ import type {
9
9
  SceneState,
10
10
  View,
11
11
  } from "white-web-sdk";
12
- import type { AppContext } from "./AppContext";
12
+ import type { AppContext } from "./App";
13
13
  import type { ReadonlyTeleBox, TeleBoxRect } from "@netless/telebox-insider";
14
+ import type { PageState } from "./Page";
14
15
 
15
16
  export interface NetlessApp<Attributes = any, MagixEventPayloads = any, AppOptions = any, SetupResult = any> {
16
17
  kind: string;
@@ -50,6 +51,7 @@ export type AppEmitterEvent<T = any> = {
50
51
  focus: boolean;
51
52
  reconnected: void;
52
53
  seek: number;
54
+ pageStateChange: PageState,
53
55
  };
54
56
 
55
57
  export type RegisterEventData = {
@@ -73,7 +75,8 @@ export type RegisterParams<AppOptions = any, SetupResult = any, Attributes = any
73
75
 
74
76
  export type AppListenerKeys = keyof AppEmitterEvent;
75
77
 
76
- export type { AppContext } from "./AppContext";
78
+ export type { AppContext } from "./App/AppContext";
77
79
  export type { ReadonlyTeleBox, TeleBoxRect };
78
80
  export type { SceneState, SceneDefinition, View, AnimationMode, Displayer, Room, Player };
79
81
  export type { Storage, StorageStateChangedEvent, StorageStateChangedListener } from "./App/Storage";
82
+ export * from "./Page";