@netless/window-manager 0.4.11-canary.0 → 0.4.11

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/advanced.md CHANGED
@@ -4,6 +4,7 @@
4
4
  - [撤销重做](#redo-undo)
5
5
  - [清屏](#clean-current-scene)
6
6
  - [判断是否打开某种 APP](#has-kind)
7
+ - [页面控制器](#page-control)
7
8
 
8
9
 
9
10
  <h3 id="redo-undo">撤销重做</h3>
@@ -64,3 +65,26 @@ manager.emitter.on("ready", () => { // ready 事件在所有 app 创建完成后
64
65
  const hasSlide = apps.some(app => app.kind === "Slide"); // 判断已经打开的 APP 中是否有 Slide
65
66
  });
66
67
  ```
68
+
69
+ <br>
70
+
71
+ <h3 id="page-control">页面控制器</h3>
72
+
73
+ `manager` 提供了一个 `pageState` 来获取当前的 index 和总页数
74
+
75
+ ```ts
76
+ manager.pageState.index // 当前的 index
77
+ manager.pageState.length // 总页数
78
+
79
+ manager.emitter.on("pageStateChange", state => {
80
+ // 当前 index 变化和总页数变化会触发此事件
81
+ });
82
+ ```
83
+
84
+ 上一页/下一页/添加一页
85
+
86
+ ```ts
87
+ manager.nextPage()
88
+ manager.prevPage()
89
+ manager.addPage()
90
+ ```
package/docs/api.md CHANGED
@@ -229,6 +229,7 @@ manager.addPage({ scene: { name: "page2" } }) // 传入 page 信息
229
229
  | canRedoSteps | number | | 当前 focus 的 view 可以重做的步数 |
230
230
  | canRedoSteps | number | | 当前 focus 的 view 可以撤销的步数 |
231
231
  | sceneState | SceneState | | 兼容原本 SDK 的 sceneState 属性, 只对 mainView 生效 |
232
+ | pageState | PageState | | 组合 mainView 的 index 和 scenes 的修改 |
232
233
 
233
234
  <br>
234
235
 
@@ -253,6 +254,7 @@ manager.callbacks.on(events, listener)
253
254
  | loadApp | LoadAppEvent | | 加载远程APP 事件 |
254
255
  | ready | undefined | | 当所有 APP 创建完毕时触发 |
255
256
  | sceneStateChange | SceneState | | 当 sceneState 修改时触发 |
257
+ | pageStateChange | PageState | | |
256
258
 
257
259
  ```ts
258
260
  type LoadAppEvent = {
@@ -260,4 +262,11 @@ type LoadAppEvent = {
260
262
  status: "start" | "success" | "failed";
261
263
  reason?: string;
262
264
  }
265
+ ```
266
+
267
+ ```ts
268
+ type PageState = {
269
+ index: number;
270
+ length: number;
271
+ }
263
272
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netless/window-manager",
3
- "version": "0.4.11-canary.0",
3
+ "version": "0.4.11",
4
4
  "description": "",
5
5
  "main": "dist/index.es.js",
6
6
  "module": "dist/index.es.js",
package/src/AppManager.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { AppAttributes, AppStatus, Events, MagixEventName, ROOT_DIR } from "./constants";
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
4
  import { AppProxy } from "./AppProxy";
@@ -106,17 +106,20 @@ export class AppManager {
106
106
  }
107
107
 
108
108
  private onRemoveScenes = (scenePath: string) => {
109
+ // 如果移除根目录就把 scenePath 设置为初始值
109
110
  if (scenePath === ROOT_DIR) {
110
- this.setMainViewScenePath(ROOT_DIR);
111
+ this.setMainViewScenePath(INIT_DIR);
111
112
  this.createRootDirScenesCallback();
112
113
  this.onRootDirRemoved();
113
114
  emitter.emit("rootDirRemoved");
114
115
  return;
115
116
  }
117
+ // 如果移除的 path 跟 MainViewScenePath 相同就取当前目录的当前 index
116
118
  const mainViewScenePath = this.store.getMainViewScenePath();
117
119
  if (this.room && mainViewScenePath) {
118
120
  if (mainViewScenePath === scenePath) {
119
- this.setMainViewScenePath(ROOT_DIR);
121
+ const nextPath = this.callbacksNode?.scenes[this.store.getMainViewSceneIndex()];
122
+ this.setMainViewScenePath(`/${nextPath}` || INIT_DIR);
120
123
  }
121
124
  }
122
125
  };
@@ -163,7 +166,7 @@ export class AppManager {
163
166
  this.updateSceneState(this.callbacksNode);
164
167
  this.mainViewScenesLength = this.callbacksNode.scenes.length;
165
168
  if (isRecreate) {
166
- callbacks.emit("mainViewScenesLengthChange", this.callbacksNode.scenes.length);
169
+ this.emitMainViewScenesChange(this.callbacksNode.scenes.length);
167
170
  }
168
171
  }
169
172
  };
@@ -171,7 +174,12 @@ export class AppManager {
171
174
  private onSceneChange = (node: ScenesCallbacksNode) => {
172
175
  this.mainViewScenesLength = node.scenes.length;
173
176
  this.updateSceneState(node);
174
- callbacks.emit("mainViewScenesLengthChange", this.mainViewScenesLength);
177
+ this.emitMainViewScenesChange(this.mainViewScenesLength);
178
+ };
179
+
180
+ private emitMainViewScenesChange = (length: number) => {
181
+ callbacks.emit("mainViewScenesLengthChange", length);
182
+ emitter.emit("changePageState");
175
183
  };
176
184
 
177
185
  private updateSceneState = (node: ScenesCallbacksNode) => {
@@ -264,6 +272,7 @@ export class AppManager {
264
272
  const mainSceneIndex = get(this.attributes, "_mainSceneIndex");
265
273
  if (mainSceneIndex !== undefined && this._prevSceneIndex !== mainSceneIndex) {
266
274
  callbacks.emit("mainViewSceneIndexChange", mainSceneIndex);
275
+ emitter.emit("changePageState");
267
276
  if (this.callbacksNode) {
268
277
  this.updateSceneState(this.callbacksNode);
269
278
  }
@@ -300,10 +309,7 @@ export class AppManager {
300
309
  if (!this.attributes.apps || Object.keys(this.attributes.apps).length === 0) {
301
310
  const mainScenePath = this.store.getMainViewScenePath();
302
311
  if (!mainScenePath) return;
303
- const sceneState = this.displayer.state.sceneState;
304
- if (sceneState.scenePath !== mainScenePath) {
305
- setScenePath(this.room, mainScenePath);
306
- }
312
+ this.resetScenePath(mainScenePath);
307
313
  }
308
314
  this.displayerWritableListener(!this.room?.isWritable);
309
315
  this.displayer.callbacks.on("onEnableWriteNowChanged", this.displayerWritableListener);
@@ -389,7 +395,7 @@ export class AppManager {
389
395
  this.boxManager?.setMinimized(Boolean(minimized));
390
396
  }, 0);
391
397
  }
392
- }
398
+ };
393
399
 
394
400
  public refresh() {
395
401
  this.attributesUpdateCallback(this.attributes.apps);
@@ -434,6 +440,13 @@ export class AppManager {
434
440
  }
435
441
  }
436
442
 
443
+ private resetScenePath(scenePath: string) {
444
+ const sceneState = this.displayer.state.sceneState;
445
+ if (sceneState.scenePath !== scenePath) {
446
+ setScenePath(this.room, scenePath);
447
+ }
448
+ }
449
+
437
450
  public async addApp(params: AddAppParams, isDynamicPPT: boolean): Promise<string | undefined> {
438
451
  log("addApp", params);
439
452
  const { appId, needFocus } = await this.beforeAddApp(params, isDynamicPPT);
@@ -22,6 +22,7 @@ export type EmitterEvent = {
22
22
  focusedChange: { focused: string | undefined; prev: string | undefined };
23
23
  rootDirRemoved: undefined;
24
24
  setReadonly: boolean;
25
+ changePageState: undefined;
25
26
  };
26
27
 
27
28
  export type EmitterType = Emittery<EmitterEvent>;
@@ -0,0 +1,31 @@
1
+ import type { AppManager } from "./AppManager";
2
+ import { callbacks } from "./callback";
3
+ import { emitter } from "./InternalEmitter";
4
+
5
+ export type PageState = {
6
+ index: number;
7
+ length: number;
8
+ };
9
+
10
+ export class PageStateImpl {
11
+ constructor(private manager: AppManager) {
12
+ emitter.on("changePageState", () => {
13
+ callbacks.emit("pageStateChange", this.toObject());
14
+ });
15
+ }
16
+
17
+ public get index(): number {
18
+ return this.manager?.store.getMainViewSceneIndex() || 0;
19
+ }
20
+
21
+ public get length(): number {
22
+ return this.manager?.mainViewScenesLength || 0;
23
+ }
24
+
25
+ public toObject(): PageState {
26
+ return {
27
+ index: this.index,
28
+ length: this.length,
29
+ };
30
+ }
31
+ }
@@ -33,7 +33,8 @@ export const setViewSceneIndex = (view: View, index: number) => {
33
33
  export const setScenePath = (room: Room | undefined, scenePath: string) => {
34
34
  if (room && room.isWritable) {
35
35
  if (room.state.sceneState.scenePath !== scenePath) {
36
- room.setScenePath(scenePath);
36
+ const nextScenePath = scenePath === "/" ? "" : scenePath;
37
+ room.setScenePath(nextScenePath);
37
38
  }
38
39
  }
39
40
  };
package/src/callback.ts CHANGED
@@ -2,6 +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
6
 
6
7
  export type PublicEvent = {
7
8
  mainViewModeChange: ViewVisionMode;
@@ -18,6 +19,7 @@ export type PublicEvent = {
18
19
  loadApp: LoadAppEvent;
19
20
  ready: undefined; // 所有 APP 创建完毕时触发
20
21
  sceneStateChange: SceneState;
22
+ pageStateChange: PageState;
21
23
  };
22
24
 
23
25
  export type CallbacksType = Emittery<PublicEvent>;
package/src/constants.ts CHANGED
@@ -49,3 +49,4 @@ export const SET_SCENEPATH_DELAY = 100; // 设置 scenePath 的延迟事件
49
49
  export const DEFAULT_CONTAINER_RATIO = 9 / 16;
50
50
 
51
51
  export const ROOT_DIR = "/";
52
+ export const INIT_DIR = "/init";
package/src/index.ts CHANGED
@@ -6,13 +6,14 @@ import { checkVersion, setupWrapper } from "./Helper";
6
6
  import { ContainerResizeObserver } from "./ContainerResizeObserver";
7
7
  import { createBoxManager } from "./BoxManager";
8
8
  import { CursorManager } from "./Cursor";
9
- import { DEFAULT_CONTAINER_RATIO, Events, ROOT_DIR } from "./constants";
9
+ import { DEFAULT_CONTAINER_RATIO, Events, INIT_DIR, ROOT_DIR } from "./constants";
10
10
  import { emitter } from "./InternalEmitter";
11
11
  import { Fields } from "./AttributesDelegate";
12
12
  import { initDb } from "./Register/storage";
13
13
  import { InvisiblePlugin, isPlayer, isRoom, RoomPhase, ViewMode } from "white-web-sdk";
14
14
  import { isEqual, isNull, isObject, omit } from "lodash";
15
15
  import { log } from "./Utils/log";
16
+ import { PageStateImpl } from "./PageState";
16
17
  import { ReconnectRefresher } from "./ReconnectRefresher";
17
18
  import { replaceRoomFunction } from "./Utils/RoomHacker";
18
19
  import { setupBuiltin } from "./BuiltinApps";
@@ -56,6 +57,7 @@ import type { TeleBoxColorScheme, TeleBoxState } from "@netless/telebox-insider"
56
57
  import type { AppProxy } from "./AppProxy";
57
58
  import type { PublicEvent } from "./Callback";
58
59
  import type Emittery from "emittery";
60
+ import type { PageState } from "./PageState";
59
61
 
60
62
  export type WindowMangerAttributes = {
61
63
  modelValue?: string;
@@ -168,11 +170,13 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
168
170
  public cursorManager?: CursorManager;
169
171
  public viewMode = ViewMode.Broadcaster;
170
172
  public isReplay = isPlayer(this.displayer);
173
+ private _pageState?: PageStateImpl;
171
174
 
172
175
  private boxManager?: BoxManager;
173
176
  private static params?: MountParams;
174
177
 
175
178
  private containerResizeObserver?: ContainerResizeObserver;
179
+ public containerSizeRatio = WindowManager.containerSizeRatio;
176
180
 
177
181
  constructor(context: InvisiblePluginContext) {
178
182
  super(context);
@@ -235,7 +239,11 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
235
239
  await manager.ensureAttributes();
236
240
 
237
241
  manager.appManager = new AppManager(manager);
242
+ manager._pageState = new PageStateImpl(manager.appManager);
238
243
  manager.cursorManager = new CursorManager(manager.appManager, Boolean(cursor));
244
+ if (containerSizeRatio) {
245
+ manager.containerSizeRatio = containerSizeRatio;
246
+ }
239
247
 
240
248
  if (params.container) {
241
249
  manager.bindContainer(params.container);
@@ -642,7 +650,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
642
650
  }
643
651
 
644
652
  public get mainViewSceneIndex(): number {
645
- return this.appManager?.store.getMainViewSceneIndex();
653
+ return this._pageState?.index || 0;
646
654
  }
647
655
 
648
656
  public get mainViewSceneDir(): string {
@@ -658,7 +666,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
658
666
  }
659
667
 
660
668
  public get mainViewScenesLength(): number {
661
- return this.appManager?.mainViewScenesLength || 0;
669
+ return this._pageState?.length || 0;
662
670
  }
663
671
 
664
672
  public get canRedoSteps(): number {
@@ -678,6 +686,14 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
678
686
  }
679
687
  }
680
688
 
689
+ public get pageState(): PageState {
690
+ if (this._pageState) {
691
+ return this._pageState.toObject();
692
+ } else {
693
+ throw new AppManagerNotInitError();
694
+ }
695
+ }
696
+
681
697
  /**
682
698
  * 查询所有的 App
683
699
  */
@@ -858,7 +874,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
858
874
  this.safeSetAttributes({ [Fields.Cursors]: {} });
859
875
  }
860
876
  if (!this.attributes["_mainScenePath"]) {
861
- this.safeSetAttributes({ _mainScenePath: ROOT_DIR });
877
+ this.safeSetAttributes({ _mainScenePath: INIT_DIR });
862
878
  }
863
879
  if (!this.attributes["_mainSceneIndex"]) {
864
880
  this.safeSetAttributes({ _mainSceneIndex: 0 });
@@ -875,4 +891,4 @@ setupBuiltin();
875
891
  export * from "./typings";
876
892
 
877
893
  export { BuiltinApps } from "./BuiltinApps";
878
- export type { PublicEvent } from "./callback";
894
+ export type { PublicEvent } from "./callback";