@netless/window-manager 0.4.0-canary.23 → 0.4.0-canary.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/api.md CHANGED
@@ -136,6 +136,7 @@ manager.setBoxState("normal") // boxState: normal | maximized | minimized
136
136
  | ------------------ | ------- | ------- | ----------------- |
137
137
  | mainView | View | | 主白板 |
138
138
  | mainViewSceneIndex | number | | 当前主白板的 SceneIndex |
139
+ | mainViewScenesLength | number | | mainView 的 scenes 长度 |
139
140
  | boxState | string | | 当前窗口状态 |
140
141
  | darkMode | boolean | | 黑夜模式 |
141
142
  | prefersColorScheme | string | | 颜色主题 |
@@ -158,3 +159,4 @@ manager.callbacks.on(events, listener)
158
159
  | prefersColorSchemeChange | string | | auto,light,dark |
159
160
  | cameraStateChange | CameraState | | |
160
161
  | focusedChange | string, undefined | | 当前 focus 的 appId,主白板时为 undefined |
162
+ | mainViewScenesLengthChange | number | | mainView scenes 添加或删除时触发 |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netless/window-manager",
3
- "version": "0.4.0-canary.23",
3
+ "version": "0.4.0-canary.24",
4
4
  "description": "",
5
5
  "main": "dist/index.es.js",
6
6
  "module": "dist/index.es.js",
package/src/AppManager.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import pRetry from "p-retry";
2
- import { AppAttributes, AppStatus, Events, MagixEventName } from "./constants";
2
+ import { AppAttributes, AppStatus, Events, MagixEventName, ROOT_DIR } from "./constants";
3
3
  import { AppListeners } from "./AppListener";
4
4
  import { AppProxy } from "./AppProxy";
5
5
  import { autorun, isPlayer, isRoom, ScenePathType } from "white-web-sdk";
@@ -20,7 +20,7 @@ import { store } from "./AttributesDelegate";
20
20
  import { ViewManager } from "./View/ViewManager";
21
21
  import type { ReconnectRefresher } from "./ReconnectRefresher";
22
22
  import type { BoxManager } from "./BoxManager";
23
- import type { Displayer, DisplayerState, Room } from "white-web-sdk";
23
+ import type { Displayer, DisplayerState, Room , ScenesCallbacksNode } from "white-web-sdk";
24
24
  import type { AddAppParams, BaseInsertParams, TeleBoxRect, EmitterEvent } from "./index";
25
25
  import { appRegister } from "./Register";
26
26
 
@@ -33,12 +33,14 @@ export class AppManager {
33
33
  public mainViewProxy: MainViewProxy;
34
34
  public refresher?: ReconnectRefresher;
35
35
  public isReplay = this.windowManger.isReplay;
36
+ public mainViewScenesLength = 0;
36
37
 
37
38
  private appListeners: AppListeners;
38
39
  public boxManager?: BoxManager;
39
40
 
40
41
  private _prevSceneIndex: number | undefined;
41
42
  private _prevFocused: string | undefined;
43
+ private callbacksNode: ScenesCallbacksNode | null;
42
44
 
43
45
  constructor(public windowManger: WindowManager) {
44
46
  this.displayer = windowManger.displayer;
@@ -69,17 +71,30 @@ export class AppManager {
69
71
  });
70
72
  }
71
73
  emitter.on("removeScenes", scenePath => {
72
- if (scenePath === "/") {
73
- this.setMainViewScenePath("/");
74
+ if (scenePath === ROOT_DIR) {
75
+ this.setMainViewScenePath(ROOT_DIR);
74
76
  return;
75
77
  }
76
78
  const mainViewScenePath = this.store.getMainViewScenePath();
77
79
  if (this.room && mainViewScenePath) {
78
80
  if (mainViewScenePath === scenePath) {
79
- this.setMainViewScenePath("/");
81
+ this.setMainViewScenePath(ROOT_DIR);
80
82
  }
81
83
  }
82
84
  });
85
+ this.callbacksNode = this.displayer.createScenesCallback(ROOT_DIR, {
86
+ onAddScene: (scenesCallback) => {
87
+ this.mainViewScenesLength = scenesCallback.scenes.length;
88
+ callbacks.emit("mainViewScenesLengthChange", this.mainViewScenesLength);
89
+ },
90
+ onRemoveScene: (scenesCallback) => {
91
+ this.mainViewScenesLength = scenesCallback.scenes.length;
92
+ callbacks.emit("mainViewScenesLengthChange", this.mainViewScenesLength);
93
+ },
94
+ });
95
+ if (this.callbacksNode) {
96
+ this.mainViewScenesLength = this.callbacksNode.scenes.length;
97
+ }
83
98
  }
84
99
 
85
100
  private get eventName() {
@@ -111,6 +126,15 @@ export class AppManager {
111
126
  public get uid() {
112
127
  return this.room?.uid || "";
113
128
  }
129
+
130
+ public getMainViewSceneDir() {
131
+ const scenePath = this.store.getMainViewScenePath();
132
+ if (scenePath) {
133
+ return parseSceneDir(scenePath);
134
+ } else {
135
+ throw new Error("[WindowManager]: mainViewSceneDir not found");
136
+ }
137
+ }
114
138
 
115
139
  private async onCreated() {
116
140
  await this.attributesUpdateCallback(this.attributes.apps);
@@ -385,6 +409,10 @@ export class AppManager {
385
409
  public async setMainViewScenePath(scenePath: string) {
386
410
  if (this.room) {
387
411
  const scenePathType = this.displayer.scenePathType(scenePath);
412
+ const sceneDir = parseSceneDir(scenePath);
413
+ if (sceneDir !== ROOT_DIR) {
414
+ throw new Error(`[WindowManager]: main view scenePath must in root dir "/"`);
415
+ }
388
416
  if (scenePathType === ScenePathType.None) {
389
417
  throw new Error(`[WindowManager]: ${scenePath} not valid scene`);
390
418
  } else if (scenePathType === ScenePathType.Page) {
@@ -554,6 +582,7 @@ export class AppManager {
554
582
  this.refresher?.destroy();
555
583
  this.mainViewProxy.destroy();
556
584
  callbacks.clearListeners();
585
+ this.callbacksNode?.dispose();
557
586
  this._prevSceneIndex = undefined;
558
587
  }
559
588
  }
package/src/AppProxy.ts CHANGED
@@ -7,7 +7,7 @@ import { BoxManagerNotFoundError } from "./Utils/error";
7
7
  import { debounce, get } from "lodash";
8
8
  import { emitter } from "./index";
9
9
  import { Fields } from "./AttributesDelegate";
10
- import { getScenePath, removeScenes, setScenePath, setViewFocusScenePath } from "./Utils/Common";
10
+ import { entireScenes, getScenePath, removeScenes, setScenePath, setViewFocusScenePath } from "./Utils/Common";
11
11
  import { log } from "./Utils/log";
12
12
  import type {
13
13
  AppEmitterEvent,
@@ -67,7 +67,7 @@ export class AppProxy {
67
67
  if (options) {
68
68
  this.scenePath = options.scenePath;
69
69
  if (this.appAttributes?.isDynamicPPT && this.scenePath) {
70
- this.scenes = this.manager.displayer.entireScenes()[this.scenePath];
70
+ this.scenes = entireScenes(this.manager.displayer)[this.scenePath];
71
71
  } else {
72
72
  this.scenes = options.scenes;
73
73
  }
@@ -134,19 +134,10 @@ export class AppProxy {
134
134
  };
135
135
  }
136
136
 
137
- private focusApp() {
138
- this.focusBox();
139
- this.store.setMainViewFocusPath(this.manager.mainView);
140
- }
141
-
142
137
  public get box(): ReadonlyTeleBox | undefined {
143
138
  return this.boxManager?.getBox(this.id);
144
139
  }
145
140
 
146
- public focusBox() {
147
- this.boxManager?.focusBox({ appId: this.id });
148
- }
149
-
150
141
  private async setupApp(
151
142
  appId: string,
152
143
  skipUpdate: boolean,
@@ -188,8 +179,7 @@ export class AppProxy {
188
179
  });
189
180
  if (this.isAddApp && this.box) {
190
181
  this.store.updateAppState(appId, AppAttributes.ZIndex, this.box.zIndex);
191
- this.store.setAppFocus(appId, true);
192
- this.focusBox();
182
+ this.boxManager.focusBox({ appId }, false);
193
183
  }
194
184
  } catch (error: any) {
195
185
  console.error(error);
@@ -1,11 +1,13 @@
1
1
  import { appRegister } from "../Register";
2
- import { debounce } from "lodash";
2
+ import { debounce, memoize } from "lodash";
3
3
  import { emitter } from "../index";
4
4
  import { ScenePathType } from "white-web-sdk";
5
5
  import { v4 } from "uuid";
6
6
  import type { PublicEvent } from "../index";
7
7
  import type { Displayer, ViewVisionMode, Room, View } from "white-web-sdk";
8
8
  import type Emittery from "emittery";
9
+ import { log } from "./log";
10
+ import { ROOT_DIR } from "../constants";
9
11
 
10
12
  export const genAppId = async (kind: string) => {
11
13
  const impl = await appRegister.appClasses.get(kind)?.();
@@ -91,7 +93,7 @@ export const makeValidScenePath = (displayer: Displayer, scenePath: string, inde
91
93
  const scene = scenes[index];
92
94
  if (!scene) return;
93
95
  const firstSceneName = scene.name;
94
- if (scenePath === "/") {
96
+ if (scenePath === ROOT_DIR) {
95
97
  return `/${firstSceneName}`;
96
98
  } else {
97
99
  return `${scenePath}/${firstSceneName}`;
@@ -99,9 +101,16 @@ export const makeValidScenePath = (displayer: Displayer, scenePath: string, inde
99
101
  };
100
102
 
101
103
  export const entireScenes = (displayer: Displayer) => {
102
- return displayer.entireScenes();
104
+ // 缓存 entireScenes 结果, 避免频繁调用
105
+ const cacheKey = Math.round(Date.now() / 1000);
106
+ return invokeEntireScenes(cacheKey, displayer);
103
107
  };
104
108
 
109
+ const invokeEntireScenes = memoize((cacheKey: number, displayer: Displayer) => {
110
+ log("invokeEntireScenes", cacheKey);
111
+ return displayer.entireScenes();
112
+ });
113
+
105
114
  export const isValidScenePath = (scenePath: string) => {
106
115
  return scenePath.startsWith("/");
107
116
  };
package/src/constants.ts CHANGED
@@ -46,3 +46,5 @@ export const MIN_HEIGHT = 340 / 720;
46
46
  export const SET_SCENEPATH_DELAY = 100; // 设置 scenePath 的延迟事件
47
47
 
48
48
  export const DEFAULT_CONTAINER_RATIO = 9 / 16;
49
+
50
+ export const ROOT_DIR = "/";
package/src/index.ts CHANGED
@@ -19,9 +19,9 @@ import "@netless/telebox-insider/dist/style.css";
19
19
  import {
20
20
  addEmitterOnceListener,
21
21
  ensureValidScenePath,
22
+ entireScenes,
22
23
  getVersionNumber,
23
24
  isValidScenePath,
24
- parseSceneDir,
25
25
  wait,
26
26
  } from "./Utils/Common";
27
27
  import type { TELE_BOX_STATE, BoxManager } from "./BoxManager";
@@ -157,6 +157,7 @@ export type PublicEvent = {
157
157
  mainViewScenePathChange: string;
158
158
  mainViewSceneIndexChange: number;
159
159
  focusedChange: string | undefined;
160
+ mainViewScenesLengthChange: number;
160
161
  };
161
162
 
162
163
  export type MountParams = {
@@ -447,11 +448,11 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
447
448
  if (scenePath && scenes && scenes.length > 0) {
448
449
  if (this.isDynamicPPT(scenes)) {
449
450
  isDynamicPPT = true;
450
- if (!this.displayer.entireScenes()[scenePath]) {
451
+ if (!entireScenes(this.displayer)[scenePath]) {
451
452
  this.room?.putScenes(scenePath, scenes);
452
453
  }
453
454
  } else {
454
- if (!this.displayer.entireScenes()[scenePath]) {
455
+ if (!entireScenes(this.displayer)[scenePath]) {
455
456
  this.room?.putScenes(scenePath, [{ name: scenes[0].name }]);
456
457
  }
457
458
  }
@@ -618,11 +619,10 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
618
619
  }
619
620
 
620
621
  public get mainViewSceneDir(): string {
621
- const scenePath = this.appManager?.store.getMainViewScenePath();
622
- if (scenePath) {
623
- return parseSceneDir(scenePath);
622
+ if (this.appManager) {
623
+ return this.appManager?.getMainViewSceneDir();
624
624
  } else {
625
- throw new Error("[WindowManager]: mainViewSceneDir not found");
625
+ throw new AppManagerNotInitError();
626
626
  }
627
627
  }
628
628
 
@@ -630,6 +630,10 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
630
630
  return this.boxManager?.getTopBox()?.id;
631
631
  }
632
632
 
633
+ public get mainViewScenesLength(): number {
634
+ return this.appManager?.mainViewScenesLength || 0;
635
+ }
636
+
633
637
  /**
634
638
  * 查询所有的 App
635
639
  */