@netless/window-manager 0.4.15 → 0.4.18

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netless/window-manager",
3
- "version": "0.4.15",
3
+ "version": "0.4.18",
4
4
  "description": "",
5
5
  "main": "dist/index.es.js",
6
6
  "module": "dist/index.es.js",
@@ -99,6 +99,8 @@ export class AppListeners {
99
99
  };
100
100
 
101
101
  private rootDirRemovedHandler = () => {
102
- this.manager.onRootDirRemoved();
103
- };
102
+ this.manager.createRootDirScenesCallback();
103
+ this.manager.mainViewProxy.rebind();
104
+ emitter.emit("rootDirRemoved");
105
+ }
104
106
  }
package/src/AppManager.ts CHANGED
@@ -59,6 +59,8 @@ export class AppManager {
59
59
 
60
60
  public sceneState: SceneState | null = null;
61
61
 
62
+ public rootDirRemoving = false;
63
+
62
64
  constructor(public windowManger: WindowManager) {
63
65
  this.displayer = windowManger.displayer;
64
66
  this.store.setContext({
@@ -106,10 +108,10 @@ export class AppManager {
106
108
  });
107
109
  }
108
110
 
109
- private onRemoveScenes = (scenePath: string) => {
111
+ private onRemoveScenes = async (scenePath: string) => {
110
112
  // 如果移除根目录就把 scenePath 设置为初始值
111
113
  if (scenePath === ROOT_DIR) {
112
- this.onRootDirRemoved();
114
+ await this.onRootDirRemoved();
113
115
  this.dispatchInternalEvent(Events.RootDirRemoved);
114
116
  return;
115
117
  }
@@ -127,19 +129,19 @@ export class AppManager {
127
129
  * 根目录被删除时所有的 scene 都会被删除.
128
130
  * 所以需要关掉所有开启了 view 的 app
129
131
  */
130
- public onRootDirRemoved() {
132
+ public async onRootDirRemoved(needClose = true) {
131
133
  this.setMainViewScenePath(INIT_DIR);
132
134
  this.createRootDirScenesCallback();
133
-
134
- this.appProxies.forEach(appProxy => {
135
+
136
+ for (const [id, appProxy] of this.appProxies.entries()) {
135
137
  if (appProxy.view) {
136
- this.closeApp(appProxy.id);
138
+ await this.closeApp(id, needClose);
137
139
  }
138
- });
140
+ }
139
141
  // 删除了根目录的 scenes 之后 mainview 需要重新绑定, 否则主白板会不能渲染
140
142
  this.mainViewProxy.rebind();
141
-
142
143
  emitter.emit("rootDirRemoved");
144
+ this.updateRootDirRemoving(false);
143
145
  }
144
146
 
145
147
  private onReadonlyChanged = () => {
@@ -159,7 +161,7 @@ export class AppManager {
159
161
  });
160
162
  };
161
163
 
162
- private createRootDirScenesCallback = () => {
164
+ public createRootDirScenesCallback = () => {
163
165
  let isRecreate = false;
164
166
  if (this.callbacksNode) {
165
167
  this.callbacksNode.dispose();
@@ -361,14 +363,13 @@ export class AppManager {
361
363
  for (const { id } of orderBy(appsWithCreatedAt, "createdAt", "asc")) {
362
364
  if (!this.appProxies.has(id) && !this.appStatus.has(id)) {
363
365
  const app = apps[id];
364
-
365
- this.appStatus.set(id, AppStatus.StartCreate);
366
366
  try {
367
367
  const appAttributes = this.attributes[id];
368
368
  if (!appAttributes) {
369
369
  throw new Error("appAttributes is undefined");
370
370
  }
371
371
  this.appCreateQueue.push(() => {
372
+ this.appStatus.set(id, AppStatus.StartCreate);
372
373
  return this.baseInsertApp(
373
374
  {
374
375
  kind: app.kind,
@@ -505,10 +506,10 @@ export class AppManager {
505
506
  }
506
507
  }
507
508
 
508
- public async closeApp(appId: string) {
509
+ public async closeApp(appId: string, needClose = true) {
509
510
  const appProxy = this.appProxies.get(appId);
510
511
  if (appProxy) {
511
- appProxy.destroy(true, true, false);
512
+ appProxy.destroy(true, needClose, false);
512
513
  }
513
514
  }
514
515
 
@@ -728,6 +729,10 @@ export class AppManager {
728
729
  });
729
730
  }
730
731
 
732
+ public updateRootDirRemoving = (removing: boolean) => {
733
+ this.rootDirRemoving = removing;
734
+ }
735
+
731
736
  public dispatchInternalEvent(event: Events, payload?: any) {
732
737
  this.safeDispatchMagixEvent(MagixEventName, {
733
738
  eventName: event,
package/src/AppProxy.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import Emittery from "emittery";
2
- import { AppAttributes, AppEvents, Events } from "./constants";
2
+ import { AppAttributes, AppEvents, Events, SETUP_APP_DELAY } from "./constants";
3
3
  import { AppContext } from "./AppContext";
4
4
  import { appRegister } from "./Register";
5
5
  import { autorun } from "white-web-sdk";
@@ -168,7 +168,7 @@ export class AppProxy {
168
168
  appRegister.notifyApp(this.kind, "created", { appId, result });
169
169
  this.afterSetupApp(boxInitState);
170
170
  this.fixMobileSize();
171
- }, 50);
171
+ }, SETUP_APP_DELAY);
172
172
  });
173
173
  this.boxManager?.createBox({
174
174
  appId: appId,
@@ -27,4 +27,4 @@ export type EmitterEvent = {
27
27
  };
28
28
 
29
29
  export type EmitterType = Emittery<EmitterEvent>;
30
- export const emitter: EmitterType = new Emittery();
30
+ export const emitter: EmitterType = new Emittery();
@@ -1,5 +1,6 @@
1
1
  import { callbacks } from "../callback";
2
2
  import type { AppProxy } from "../AppProxy";
3
+ import { SETUP_APP_DELAY } from "../constants";
3
4
 
4
5
  export type Invoker = () => Promise<AppProxy | undefined>;
5
6
 
@@ -60,11 +61,18 @@ export class AppCreateQueue {
60
61
 
61
62
  public emitReady() {
62
63
  if (!this.isEmit) {
63
- callbacks.emit("ready");
64
+ setTimeout(() => {
65
+ callbacks.emit("ready");
66
+ }, SETUP_APP_DELAY);
64
67
  }
65
68
  this.isEmit = true;
66
69
  }
67
70
 
71
+ public empty() {
72
+ this.list = [];
73
+ this.clear();
74
+ }
75
+
68
76
  public destroy() {
69
77
  if (this.timer) {
70
78
  this.clear();
@@ -1,12 +1,12 @@
1
1
  import { appRegister } from "../Register";
2
2
  import { debounce } from "lodash";
3
3
  import { emitter } from "../InternalEmitter";
4
+ import { ROOT_DIR } from "../constants";
4
5
  import { ScenePathType } from "white-web-sdk";
5
6
  import { v4 } from "uuid";
6
7
  import type { PublicEvent } from "../callback";
7
- import type { Displayer, ViewVisionMode, Room, View } from "white-web-sdk";
8
+ import type { Displayer, ViewVisionMode, Room, View , SceneDefinition} from "white-web-sdk";
8
9
  import type Emittery from "emittery";
9
- import { ROOT_DIR } from "../constants";
10
10
 
11
11
  export const genAppId = async (kind: string) => {
12
12
  const impl = await appRegister.appClasses.get(kind)?.();
@@ -104,6 +104,9 @@ 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);
109
+ }
107
110
 
108
111
  export const isValidScenePath = (scenePath: string) => {
109
112
  return scenePath.startsWith("/");
@@ -2,6 +2,7 @@ import { emitter } from "../InternalEmitter";
2
2
  import { isPlayer } from "white-web-sdk";
3
3
  import type { WindowManager } from "../index";
4
4
  import type { Camera, Room, Player, PlayerSeekingResult } from "white-web-sdk";
5
+ import { ROOT_DIR } from "../constants";
5
6
 
6
7
  // 修改多窗口状态下一些失效的方法实现到 manager 的 mainview 上, 降低迁移成本
7
8
  export const replaceRoomFunction = (room: Room | Player, manager: WindowManager) => {
@@ -54,13 +55,16 @@ export const replaceRoomFunction = (room: Room | Player, manager: WindowManager)
54
55
  room.lockImage = (...args) => manager.lockImage(...args);
55
56
  room.lockImages = (...args) => manager.lockImages(...args);
56
57
 
57
- delegateRemoveScenes(room);
58
+ delegateRemoveScenes(room, manager);
58
59
  }
59
60
  };
60
61
 
61
- const delegateRemoveScenes = (room: Room) => {
62
+ const delegateRemoveScenes = (room: Room, manager: WindowManager) => {
62
63
  const originRemoveScenes = room.removeScenes;
63
64
  room.removeScenes = (scenePath: string) => {
65
+ if (scenePath === ROOT_DIR) {
66
+ manager.appManager?.updateRootDirRemoving(true);
67
+ }
64
68
  const result = originRemoveScenes.call(room, scenePath);
65
69
  emitter.emit("removeScenes", scenePath);
66
70
  return result;
@@ -23,6 +23,7 @@ export class MainViewProxy {
23
23
  this.moveCameraSizeByAttributes();
24
24
  emitter.once("mainViewMounted").then(() => {
25
25
  setTimeout(() => {
26
+ this.addMainViewListener();
26
27
  this.start();
27
28
  if (!this.mainViewCamera || !this.mainViewSize) {
28
29
  this.setCameraAndSize();
@@ -54,7 +55,6 @@ export class MainViewProxy {
54
55
  public start() {
55
56
  if (this.started) return;
56
57
  this.sizeChangeHandler(this.mainViewSize);
57
- this.addMainViewListener();
58
58
  this.addCameraListener();
59
59
  this.manager.refresher?.add(Fields.MainViewCamera, this.cameraReaction);
60
60
  this.started = true;
@@ -116,9 +116,11 @@ export class MainViewProxy {
116
116
  const disableCameraTransform = this.mainView.disableCameraTransform;
117
117
  this.stop();
118
118
  this.mainView.release();
119
+ this.removeMainViewListener();
119
120
  this.mainView = this.createMainView();
120
121
  this.mainView.disableCameraTransform = disableCameraTransform;
121
122
  this.mainView.divElement = divElement;
123
+ this.addMainViewListener();
122
124
  this.start();
123
125
  }
124
126
 
@@ -204,7 +206,6 @@ export class MainViewProxy {
204
206
  }
205
207
 
206
208
  public stop() {
207
- this.removeMainViewListener();
208
209
  this.removeCameraListener();
209
210
  this.manager.refresher?.remove(Fields.MainViewCamera);
210
211
  this.manager.refresher?.remove(Fields.MainViewSize);
@@ -212,6 +213,7 @@ export class MainViewProxy {
212
213
  }
213
214
 
214
215
  public destroy() {
216
+ this.removeMainViewListener();
215
217
  this.stop();
216
218
  this.sideEffectManager.flushAll();
217
219
  }
package/src/constants.ts CHANGED
@@ -51,3 +51,5 @@ export const DEFAULT_CONTAINER_RATIO = 9 / 16;
51
51
 
52
52
  export const ROOT_DIR = "/";
53
53
  export const INIT_DIR = "/init";
54
+
55
+ export const SETUP_APP_DELAY = 50;
package/src/index.ts CHANGED
@@ -25,6 +25,7 @@ import {
25
25
  ensureValidScenePath,
26
26
  entireScenes,
27
27
  isValidScenePath,
28
+ putScenes,
28
29
  wait,
29
30
  } from "./Utils/Common";
30
31
  import type { TELE_BOX_STATE, BoxManager } from "./BoxManager";
@@ -387,6 +388,28 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
387
388
  * 创建一个 app 至白板
388
389
  */
389
390
  public async addApp<T = any>(params: AddAppParams<T>): Promise<string | undefined> {
391
+ if (this.appManager) {
392
+ // 移除根目录时需要做一些异步的释放操作 addApp 需要等待释放完成才可以继续添加
393
+ if (this.appManager.rootDirRemoving) {
394
+ return new Promise((resolve, reject) => {
395
+ emitter.once("rootDirRemoved").then(async () => {
396
+ try {
397
+ const appId = await this._addApp(params);
398
+ resolve(appId);
399
+ } catch (error) {
400
+ reject(error.message);
401
+ }
402
+ });
403
+ });
404
+ } else {
405
+ return this._addApp(params);
406
+ }
407
+ } else {
408
+ throw new AppManagerNotInitError();
409
+ }
410
+ }
411
+
412
+ private async _addApp<T = any>(params: AddAppParams<T>): Promise<string | undefined> {
390
413
  if (this.appManager) {
391
414
  if (!params.kind || typeof params.kind !== "string") {
392
415
  throw new ParamsInvalidError();
@@ -438,16 +461,16 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
438
461
  if (this.isDynamicPPT(scenes)) {
439
462
  isDynamicPPT = true;
440
463
  if (!entireScenes(this.displayer)[scenePath]) {
441
- this.room?.putScenes(scenePath, scenes);
464
+ putScenes(this.room, scenePath, scenes);
442
465
  }
443
466
  } else {
444
467
  if (!entireScenes(this.displayer)[scenePath]) {
445
- this.room?.putScenes(scenePath, [{ name: scenes[0].name }]);
468
+ putScenes(this.room, scenePath, [{ name: scenes[0].name }]);
446
469
  }
447
470
  }
448
471
  }
449
472
  if (scenePath && scenes === undefined) {
450
- this.room?.putScenes(scenePath, [{}]);
473
+ putScenes(this.room, scenePath, [{}]);
451
474
  }
452
475
  }
453
476
  return isDynamicPPT;
package/.eslintignore DELETED
@@ -1,4 +0,0 @@
1
- node_modules/
2
- dist/
3
- public/
4
- test/
package/.eslintrc.js DELETED
@@ -1,28 +0,0 @@
1
- /** @type {import("eslint").Linter.Config */
2
- const config = {
3
- root: true,
4
- env: {
5
- browser: true,
6
- },
7
- parser: "@typescript-eslint/parser",
8
- plugins: ["svelte3", "@typescript-eslint"],
9
- extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
10
- rules: {
11
- "@typescript-eslint/consistent-type-imports": ["warn"],
12
- "@typescript-eslint/no-empty-interface": "off",
13
- "@typescript-eslint/no-explicit-any": "off",
14
- "@typescript-eslint/explicit-module-boundary-types": "off",
15
- },
16
- overrides: [
17
- {
18
- files: ["*.svelte"],
19
- processor: "svelte3/svelte3",
20
- },
21
- ],
22
- settings: {
23
- "svelte3/typescript": true,
24
- },
25
- };
26
-
27
- // eslint-disable-next-line no-undef
28
- module.exports = config;
@@ -1,7 +0,0 @@
1
- <component name="InspectionProjectProfileManager">
2
- <profile version="1.0">
3
- <option name="myName" value="Project Default" />
4
- <inspection_tool class="ES6UnusedImports" enabled="false" level="WARNING" enabled_by_default="false" />
5
- <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
6
- </profile>
7
- </component>
package/.idea/modules.xml DELETED
@@ -1,8 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="ProjectModuleManager">
4
- <modules>
5
- <module fileurl="file://$PROJECT_DIR$/.idea/window-manager.iml" filepath="$PROJECT_DIR$/.idea/window-manager.iml" />
6
- </modules>
7
- </component>
8
- </project>
package/.idea/vcs.xml DELETED
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="VcsDirectoryMappings">
4
- <mapping directory="$PROJECT_DIR$" vcs="Git" />
5
- </component>
6
- </project>
@@ -1,12 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <module type="WEB_MODULE" version="4">
3
- <component name="NewModuleRootManager">
4
- <content url="file://$MODULE_DIR$">
5
- <excludeFolder url="file://$MODULE_DIR$/temp" />
6
- <excludeFolder url="file://$MODULE_DIR$/.tmp" />
7
- <excludeFolder url="file://$MODULE_DIR$/tmp" />
8
- </content>
9
- <orderEntry type="inheritedJdk" />
10
- <orderEntry type="sourceFolder" forTests="false" />
11
- </component>
12
- </module>
@@ -1,22 +0,0 @@
1
- {
2
- "cSpell.words": [
3
- "autorun",
4
- "Contian",
5
- "Dexie",
6
- "Displayer",
7
- "Emittery",
8
- "esbuild",
9
- "loadjs",
10
- "localforge",
11
- "Magix",
12
- "mainview",
13
- "minheight",
14
- "minwidth",
15
- "predev",
16
- "SCENEPATH",
17
- "sveltejs",
18
- "telebox",
19
- "titlebar",
20
- "vite"
21
- ]
22
- }