@netless/window-manager 0.4.31 → 0.4.34

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/dist/typings.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type Emittery from "emittery";
2
- import type { AnimationMode, Displayer, DisplayerState, Player, Room, SceneDefinition, SceneState, View } from "white-web-sdk";
2
+ import type { AnimationMode, ApplianceNames, Displayer, DisplayerState, Player, Room, SceneDefinition, SceneState, View } from "white-web-sdk";
3
3
  import type { AppContext } from "./App";
4
4
  import type { ReadonlyTeleBox, TeleBoxRect } from "@netless/telebox-insider";
5
5
  import type { PageState } from "./Page";
@@ -69,6 +69,7 @@ export declare type RegisterParams<AppOptions = any, SetupResult = any, Attribut
69
69
  name?: string;
70
70
  };
71
71
  export declare type AppListenerKeys = keyof AppEmitterEvent;
72
+ export declare type ApplianceIcons = Partial<Record<ApplianceNames, string>>;
72
73
  export type { AppContext } from "./App/AppContext";
73
74
  export type { ReadonlyTeleBox, TeleBoxRect };
74
75
  export type { SceneState, SceneDefinition, View, AnimationMode, Displayer, Room, Player };
package/docs/api.md CHANGED
@@ -64,7 +64,7 @@ const manager = await WindowManager.mount(
64
64
  | disableCameraTransform | [optional] boolean | | 禁用主白板的相机移动 |
65
65
  | prefersColorScheme | [optional] string | light | auto, light, dark |
66
66
  | debug | [optional] boolean | false | 打印日志信息
67
-
67
+ | applianceIcons | [optional] {ApplianceNames, string} | | 配置光标使用的教具图片 |
68
68
 
69
69
  <h3 id="register">WindowManager.register</h3>
70
70
 
@@ -1,10 +1,11 @@
1
1
  ## AppContext
2
2
 
3
- - [api](#api)
3
+ - [api](#api)
4
4
  - [view](#view)
5
5
  - [page](#page)
6
6
  - [storage](#storage)
7
- - [events](#events)
7
+ - [events](#events)
8
+ - [Advanced](#Advanced)
8
9
 
9
10
  <h2 id="api">API</h2>
10
11
 
@@ -16,6 +17,12 @@
16
17
  const appId = context.appId;
17
18
  ```
18
19
 
20
+ - **context.isReplay**
21
+
22
+ 类型: `boolean`
23
+
24
+ 当前是否回放模式
25
+
19
26
  - **context.getDisplayer()**
20
27
 
21
28
  在默认情况下 `Displayer` 为白板的 `room` 实例
@@ -32,10 +39,10 @@
32
39
 
33
40
  - **context.getIsWritable()**
34
41
 
35
- 获取当前状态是否可写
42
+ 获取当前状态是否可写\
43
+ 可以通过监听 `writableChange` 事件获取可写状态的改变
36
44
 
37
45
  ```ts
38
- // isWritable === (room.isWritable && box.readonly)
39
46
  const isWritable = context.getIsWritable();
40
47
  ```
41
48
 
@@ -50,46 +57,31 @@
50
57
  box.$footer;
51
58
  ```
52
59
 
53
- <h3 id="view">View</h3>
54
-
55
- `view` 可以理解为一块白板,可以从 `context` 中拿到这个实例并挂载到 `Dom` 中
56
-
57
- - **context.getView()**
60
+ <h3 id="view">挂载白板</h3>
58
61
 
59
- 获取 `view` 实例
60
-
61
- ```ts
62
- const view = context.getView();
63
- ```
62
+ 当应用想要一个可以涂画的白板,可以使用以下接口
64
63
 
65
64
  - **context.mountView()**
66
65
 
67
- 挂载 view 到指定 dom
66
+ 挂载白板到指定 dom
68
67
 
69
68
  ```ts
70
69
  context.mountView(element);
71
70
  ```
72
71
 
73
- - **context.getScenes()**
74
-
75
- `scenes` 在 `addApp` 时传入 `scenePath` 会由 `WindowManager` 创建
76
-
77
- ```ts
78
- const scenes = context.getScenes();
79
- ```
80
-
81
- - **context.setScenePath()**
82
-
83
- 切换当前 `view` 到指定的 `scenePath`
84
-
85
- ```ts
86
- context.setScenePath("/page/2");
87
- ```
88
-
72
+ **注意** 在调用 `manager` 的 `addApp` 时必须填写 `scenePath` 才可以使用 `view`
73
+ ```ts
74
+ manager.addApp({
75
+ kind: "xxx",
76
+ options: { // 可选配置
77
+ scenePath: "/example-path"
78
+ }
79
+ })
80
+ ```
89
81
 
90
82
  <h3 id="page">Page</h3>
91
83
 
92
- `Page` 是封装后 `scenes` 的一些概念
84
+ 白板有多页的概念, 可以通过以下接口添加,切换,以及删除
93
85
 
94
86
  - **context.addPage()**
95
87
 
@@ -116,10 +108,19 @@
116
108
  ```ts
117
109
  context.prevPage();
118
110
  ```
111
+ - **context.removePage()**
112
+
113
+ 删除一页
114
+
115
+ ```ts
116
+ context.removePage() // 默认删除当前页
117
+ context.removePage(1) // 也可以指定 index 删除
118
+ ```
119
119
 
120
120
  - **context.pageState**
121
121
 
122
- 获取当前所在的 `index` 和一共有多少页
122
+ 获取当前所在的 `index` 和一共有多少页\
123
+ 当想要监听 `pageState` 的变化时, 可以监听 `pageStateChange` 事件获取最新的 `pageState`
123
124
 
124
125
  ```ts
125
126
  context.pageState;
@@ -141,17 +142,97 @@
141
142
  context.storage
142
143
  ```
143
144
 
144
- - **createStorage()**
145
+ - **context.createStorage(namespace)**
145
146
 
146
147
  同时你也可以创建多个 `storage` 实例
148
+
149
+ 返回: `Storage<State>`
147
150
 
148
151
  ```ts
149
- const defaultState = { count: 0 } // 可选
150
- const storage = context.createStorage("store1", defaultState);
152
+ type State = { count: number };
153
+ const defaultState = { count: 0 };
154
+ const storage = context.createStorage<State>("store1", defaultState);
151
155
  ```
152
156
 
157
+ - **storage.state**
158
+
159
+ 类型: `State`\
160
+ 默认值: `defaultState`
161
+
162
+ 在所有客户端之间同步的状态,调用 `storage.setState()` 来改变它。
163
+
164
+ - **storage.ensureState(partialState)**
165
+
166
+ 确保 `storage.state` 包含某些初始值,类似于执行了:
167
+
168
+ ```js
169
+ // 这段代码不能直接运行,因为 app.state 是只读的
170
+ storage.state = { ...partialState, ...storage.state };
171
+ ```
153
172
 
173
+ **partialState**
154
174
 
175
+ 类型: `Partial<State>`
176
+
177
+ ```js
178
+ storage.state; // { a: 1 }
179
+ storage.ensureState({ a: 0, b: 0 });
180
+ storage.state; // { a: 1, b: 0 }
181
+ ```
182
+
183
+ - **storage.setState(partialState)**
184
+
185
+ 和 React 的 `setState` 类似,更新 `storage.state` 并同步到所有客户端。
186
+
187
+ 当设置某个字段为 `undefined` 时,它会被从 `storage.state` 里删除。
188
+
189
+ > - 状态同步所需的时间和网络状态与数据大小有关,建议只在 state 里存储必须的数据。
190
+
191
+ **partialState**
192
+
193
+ 类型: `Partial<State>`
194
+
195
+ ```js
196
+ storage.state; //=> { count: 0, a: 1 }
197
+ storage.setState({ count: storage.state.count + 1, b: 2 });
198
+ storage.state; //=> { count: 1, a: 1, b: 2 }
199
+ ```
200
+
201
+ - **storage.addStateChangedListener(listener)**
202
+
203
+ 它在有人调用 `storage.setState()` 后触发 (包含当前 `storage`)
204
+
205
+ 返回: `() => void`
206
+
207
+ ```js
208
+ const disposer = storage.addStateChangedListener(diff => {
209
+ console.log("state changed", diff.oldValue, diff.newValue);
210
+ disposer(); // remove listener by calling disposer
211
+ });
212
+ ```
213
+
214
+ - **context.dispatchMagixEvent(event, payload)**
215
+
216
+ 向其他客户端广播事件消息
217
+
218
+ ```js
219
+ context.dispatchMagixEvent("click", { data: "data" });
220
+ ```
221
+
222
+ - **context.addMagixEventListener(event, listener)**
223
+
224
+ 当接收来自其他客户端的消息时(当其他客户端调用'context.dispatchMagixEvent()`时), 它会被触发
225
+
226
+ 返回: `() => void` a disposer function.
227
+
228
+ ```js
229
+ const disposer = context.addMagixEventListener("click", ({ payload }) => {
230
+ console.log(payload.data);
231
+ disposer();
232
+ });
233
+
234
+ context.dispatchMagixEvent("click", { data: "data" });
235
+ ```
155
236
 
156
237
  <h2 id="events">events</h2>
157
238
 
@@ -203,3 +284,13 @@
203
284
  // { index: 0, length: 1 }
204
285
  });
205
286
  ```
287
+
288
+ <h2 id="Advanced">Advanced</h2>
289
+
290
+ - **context.getView()**
291
+
292
+ 获取 `view` 实例
293
+
294
+ ```ts
295
+ const view = context.getView();
296
+ ```
@@ -49,7 +49,7 @@ const Counter: NetlessApp<{ count: number }> = {
49
49
  countDom.innerText = storage.state.count.toString();
50
50
  $content.appendChild(countDom);
51
51
 
52
- // state 变化回调
52
+ // 监听 state 变化回调
53
53
  storage.addStateChangedListener(diff => {
54
54
  if (diff.count) {
55
55
  // diff 会给出 newValue 和 oldValue
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netless/window-manager",
3
- "version": "0.4.31",
3
+ "version": "0.4.34",
4
4
  "description": "",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.es.js",
@@ -204,6 +204,10 @@ export class AppProxy implements PageRemoveService {
204
204
  });
205
205
  if (this.isAddApp && this.box) {
206
206
  this.store.updateAppState(appId, AppAttributes.ZIndex, this.box.zIndex);
207
+ this.store.updateAppState(appId, AppAttributes.Size, {
208
+ width: this.box.intrinsicWidth,
209
+ height: this.box.intrinsicHeight
210
+ });
207
211
  this.boxManager.focusBox({ appId }, false);
208
212
  }
209
213
  } catch (error: any) {
package/src/AppManager.ts CHANGED
@@ -785,6 +785,7 @@ export class AppManager {
785
785
  }
786
786
 
787
787
  public async onReconnected() {
788
+ this.attributesUpdateCallback(this.attributes.apps);
788
789
  const appProxies = Array.from(this.appProxies.values());
789
790
  const reconnected = appProxies.map(appProxy => {
790
791
  return appProxy.onReconnected();
@@ -1,5 +1,4 @@
1
1
  import App from "./Cursor.svelte";
2
- import { ApplianceMap } from "./icons";
3
2
  import { ApplianceNames } from "white-web-sdk";
4
3
  import { findMemberByUid } from "../Helper";
5
4
  import { omit } from "lodash";
@@ -159,8 +158,9 @@ export class Cursor {
159
158
 
160
159
  private getIcon() {
161
160
  if (this.member) {
162
- const applianceSrc = ApplianceMap[this.memberApplianceName || ApplianceNames.shape];
163
- return applianceSrc || ApplianceMap[ApplianceNames.shape];
161
+ const icons = this.cursorManager.applianceIcons;
162
+ const applianceSrc = icons[this.memberApplianceName || ApplianceNames.shape];
163
+ return applianceSrc || icons[ApplianceNames.shape];
164
164
  }
165
165
  }
166
166
 
@@ -5,10 +5,11 @@ import { emitter } from "../InternalEmitter";
5
5
  import { SideEffectManager } from "side-effect-manager";
6
6
  import { throttle } from "lodash";
7
7
  import { WindowManager } from "../index";
8
- import type { CursorMovePayload } from "../index";
8
+ import type { CursorMovePayload , ApplianceIcons} from "../index";
9
9
  import type { PositionType } from "../AttributesDelegate";
10
10
  import type { Point, RoomMember, View } from "white-web-sdk";
11
11
  import type { AppManager } from "../AppManager";
12
+ import { ApplianceMap } from "./icons";
12
13
 
13
14
  export type EventType = {
14
15
  type: PositionType;
@@ -20,6 +21,7 @@ export type MoveCursorParams = {
20
21
  x: number;
21
22
  y: number;
22
23
  };
24
+
23
25
  export class CursorManager {
24
26
  public containerRect?: DOMRect;
25
27
  public wrapperRect?: DOMRect;
@@ -28,8 +30,9 @@ export class CursorManager {
28
30
  private mainViewElement?: HTMLDivElement;
29
31
  private sideEffectManager = new SideEffectManager();
30
32
  private store = this.manager.store;
33
+ public applianceIcons: ApplianceIcons = ApplianceMap;
31
34
 
32
- constructor(private manager: AppManager, private enableCursor: boolean) {
35
+ constructor(private manager: AppManager, private enableCursor: boolean, applianceIcons?: ApplianceIcons) {
33
36
  this.roomMembers = this.manager.room?.state.roomMembers;
34
37
  const wrapper = WindowManager.wrapper;
35
38
  if (wrapper) {
@@ -42,6 +45,9 @@ export class CursorManager {
42
45
  this.sideEffectManager.add(() => {
43
46
  return emitter.on("playgroundSizeChange", () => this.updateContainerRect());
44
47
  });
48
+ if (applianceIcons) {
49
+ this.applianceIcons = { ...ApplianceMap, ...applianceIcons };
50
+ }
45
51
  }
46
52
 
47
53
  private onCursorMove = (payload: CursorMovePayload) => {
package/src/Helper.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { getVersionNumber } from "./Utils/Common";
1
+ import { getVersionNumber, wait } from "./Utils/Common";
2
+ import { log } from "./Utils/log";
2
3
  import { REQUIRE_VERSION } from "./constants";
3
4
  import { WhiteVersion } from "white-web-sdk";
4
5
  import { WhiteWebSDKInvalidError } from "./Utils/error";
@@ -45,3 +46,18 @@ export const findMemberByUid = (room: Room | undefined, uid: string) => {
45
46
  const roomMembers = room?.state.roomMembers;
46
47
  return roomMembers?.find(member => member.payload?.uid === uid);
47
48
  };
49
+
50
+ export const createInvisiblePlugin = async (room: Room) => {
51
+ try {
52
+ const manager = (await room.createInvisiblePlugin(WindowManager, {})) as WindowManager;
53
+ return manager;
54
+ } catch (error) {
55
+ // 如果有两个用户同时调用 WindowManager.mount 有概率出现这个错误
56
+ if (error.message === `invisible plugin "WindowManager" exits`) {
57
+ await wait(200);
58
+ return room.getInvisiblePlugin(WindowManager.kind) as WindowManager;
59
+ } else {
60
+ log("createInvisiblePlugin failed", error);
61
+ }
62
+ }
63
+ };
@@ -4,6 +4,7 @@ import { RoomPhase } from "white-web-sdk";
4
4
  import type { Room } from "white-web-sdk";
5
5
  import type { EmitterType } from "./InternalEmitter";
6
6
  import { EnsureReconnectEvent } from "./constants";
7
+ import { wait } from "./Utils/Common";
7
8
 
8
9
  export type ReconnectRefresherContext = {
9
10
  emitter: EmitterType;
@@ -41,19 +42,24 @@ export class ReconnectRefresher {
41
42
  this.ctx = ctx;
42
43
  }
43
44
 
44
- private onPhaseChanged = (phase: RoomPhase) => {
45
+ private onPhaseChanged = async (phase: RoomPhase) => {
45
46
  if (phase === RoomPhase.Reconnecting) {
46
47
  this.ctx.emitter.emit("startReconnect");
47
48
  }
48
49
  if (phase === RoomPhase.Connected && this.phase === RoomPhase.Reconnecting) {
49
- this.room?.dispatchMagixEvent(EnsureReconnectEvent, {});
50
+ if (this.room?.isWritable) {
51
+ this.room?.dispatchMagixEvent(EnsureReconnectEvent, {});
52
+ } else {
53
+ await wait(500);
54
+ this.onReconnected();
55
+ }
50
56
  }
51
57
  this.phase = phase;
52
58
  };
53
59
 
54
60
  private onReconnected = debounce(() => {
55
61
  this._onReconnected();
56
- }, 3000);
62
+ }, 1000);
57
63
 
58
64
  private _onReconnected = () => {
59
65
  log("onReconnected refresh reactors");
package/src/index.ts CHANGED
@@ -2,7 +2,7 @@ import pRetry from "p-retry";
2
2
  import { AppManager } from "./AppManager";
3
3
  import { appRegister } from "./Register";
4
4
  import { callbacks } from "./callback";
5
- import { checkVersion, setupWrapper } from "./Helper";
5
+ import { checkVersion, createInvisiblePlugin, setupWrapper } from "./Helper";
6
6
  import { ContainerResizeObserver } from "./ContainerResizeObserver";
7
7
  import { createBoxManager } from "./BoxManager";
8
8
  import { CursorManager } from "./Cursor";
@@ -29,13 +29,7 @@ import {
29
29
  wait,
30
30
  } from "./Utils/Common";
31
31
  import type { TELE_BOX_STATE, BoxManager } from "./BoxManager";
32
- import {
33
- AppCreateError,
34
- AppManagerNotInitError,
35
- BindContainerRoomPhaseInvalidError,
36
- InvalidScenePath,
37
- ParamsInvalidError,
38
- } from "./Utils/error";
32
+ import * as Errors from "./Utils/error";
39
33
  import type { Apps, Position } from "./AttributesDelegate";
40
34
  import type {
41
35
  Displayer,
@@ -54,7 +48,7 @@ import type {
54
48
  SceneState,
55
49
  } from "white-web-sdk";
56
50
  import type { AppListeners } from "./AppListener";
57
- import type { NetlessApp, RegisterParams } from "./typings";
51
+ import type { ApplianceIcons, NetlessApp, RegisterParams } from "./typings";
58
52
  import type { TeleBoxColorScheme, TeleBoxState } from "@netless/telebox-insider";
59
53
  import type { AppProxy } from "./App";
60
54
  import type { PublicEvent } from "./callback";
@@ -143,6 +137,7 @@ export type MountParams = {
143
137
  debug?: boolean;
144
138
  disableCameraTransform?: boolean;
145
139
  prefersColorScheme?: TeleBoxColorScheme;
140
+ applianceIcons?: ApplianceIcons;
146
141
  };
147
142
 
148
143
  export const reconnectRefresher = new ReconnectRefresher({ emitter });
@@ -238,7 +233,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
238
233
 
239
234
  manager.appManager = new AppManager(manager);
240
235
  manager._pageState = new PageStateImpl(manager.appManager);
241
- manager.cursorManager = new CursorManager(manager.appManager, Boolean(cursor));
236
+ manager.cursorManager = new CursorManager(manager.appManager, Boolean(cursor), params.applianceIcons);
242
237
  if (containerSizeRatio) {
243
238
  manager.containerSizeRatio = containerSizeRatio;
244
239
  }
@@ -259,8 +254,8 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
259
254
  return manager;
260
255
  }
261
256
 
262
- private static async initManager(room: Room): Promise<WindowManager> {
263
- let manager = room.getInvisiblePlugin(WindowManager.kind) as WindowManager;
257
+ private static async initManager(room: Room): Promise<WindowManager | undefined> {
258
+ let manager = room.getInvisiblePlugin(WindowManager.kind) as WindowManager | undefined;
264
259
  if (!manager) {
265
260
  if (isRoom(room)) {
266
261
  if (room.isWritable === false) {
@@ -269,18 +264,12 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
269
264
  } catch (error) {
270
265
  throw new Error("[WindowManger]: room must be switched to be writable");
271
266
  }
272
- manager = (await room.createInvisiblePlugin(
273
- WindowManager,
274
- {}
275
- )) as WindowManager;
276
- manager.ensureAttributes();
267
+ manager = await createInvisiblePlugin(room);
268
+ manager?.ensureAttributes();
277
269
  await wait(500);
278
270
  await room.setWritable(false);
279
271
  } else {
280
- manager = (await room.createInvisiblePlugin(
281
- WindowManager,
282
- {}
283
- )) as WindowManager;
272
+ manager = await createInvisiblePlugin(room);
284
273
  }
285
274
  }
286
275
  }
@@ -322,7 +311,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
322
311
 
323
312
  public bindContainer(container: HTMLElement) {
324
313
  if (isRoom(this.displayer) && this.room.phase !== RoomPhase.Connected) {
325
- throw new BindContainerRoomPhaseInvalidError();
314
+ throw new Errors.BindContainerRoomPhaseInvalidError();
326
315
  }
327
316
  if (WindowManager.isCreated && WindowManager.container) {
328
317
  if (WindowManager.container.firstChild) {
@@ -408,19 +397,19 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
408
397
  return this._addApp(params);
409
398
  }
410
399
  } else {
411
- throw new AppManagerNotInitError();
400
+ throw new Errors.AppManagerNotInitError();
412
401
  }
413
402
  }
414
403
 
415
404
  private async _addApp<T = any>(params: AddAppParams<T>): Promise<string | undefined> {
416
405
  if (this.appManager) {
417
406
  if (!params.kind || typeof params.kind !== "string") {
418
- throw new ParamsInvalidError();
407
+ throw new Errors.ParamsInvalidError();
419
408
  }
420
409
  const appImpl = await appRegister.appClasses.get(params.kind)?.();
421
410
  if (appImpl && appImpl.config?.singleton) {
422
411
  if (this.appManager.appProxies.has(params.kind)) {
423
- throw new AppCreateError();
412
+ throw new Errors.AppCreateError();
424
413
  }
425
414
  }
426
415
  const isDynamicPPT = this.setupScenePath(params, this.appManager);
@@ -433,7 +422,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
433
422
  const appId = await this.appManager.addApp(params, Boolean(isDynamicPPT));
434
423
  return appId;
435
424
  } else {
436
- throw new AppManagerNotInitError();
425
+ throw new Errors.AppManagerNotInitError();
437
426
  }
438
427
  }
439
428
 
@@ -443,7 +432,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
443
432
  const { scenePath, scenes } = params.options;
444
433
  if (scenePath) {
445
434
  if (!isValidScenePath(scenePath)) {
446
- throw new InvalidScenePath();
435
+ throw new Errors.InvalidScenePath();
447
436
  }
448
437
  const apps = Object.keys(this.apps || {});
449
438
  for (const appId of apps) {
@@ -646,7 +635,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
646
635
  if (this.appManager) {
647
636
  return this.appManager.mainViewProxy.view;
648
637
  } else {
649
- throw new AppManagerNotInitError();
638
+ throw new Errors.AppManagerNotInitError();
650
639
  }
651
640
  }
652
641
 
@@ -654,7 +643,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
654
643
  if (this.appManager) {
655
644
  return this.appManager.mainViewProxy.view.camera;
656
645
  } else {
657
- throw new AppManagerNotInitError();
646
+ throw new Errors.AppManagerNotInitError();
658
647
  }
659
648
  }
660
649
 
@@ -662,7 +651,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
662
651
  if (this.appManager) {
663
652
  return this.appManager.mainViewProxy.cameraState;
664
653
  } else {
665
- throw new AppManagerNotInitError();
654
+ throw new Errors.AppManagerNotInitError();
666
655
  }
667
656
  }
668
657
 
@@ -674,7 +663,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
674
663
  if (this.appManager) {
675
664
  return this.appManager.boxManager?.boxState;
676
665
  } else {
677
- throw new AppManagerNotInitError();
666
+ throw new Errors.AppManagerNotInitError();
678
667
  }
679
668
  }
680
669
 
@@ -686,7 +675,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
686
675
  if (this.appManager) {
687
676
  return this.appManager.boxManager?.prefersColorScheme;
688
677
  } else {
689
- throw new AppManagerNotInitError();
678
+ throw new Errors.AppManagerNotInitError();
690
679
  }
691
680
  }
692
681
 
@@ -706,7 +695,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
706
695
  if (this.appManager) {
707
696
  return this.appManager?.getMainViewSceneDir();
708
697
  } else {
709
- throw new AppManagerNotInitError();
698
+ throw new Errors.AppManagerNotInitError();
710
699
  }
711
700
  }
712
701
 
@@ -731,7 +720,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
731
720
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
732
721
  return this.appManager.sceneState!;
733
722
  } else {
734
- throw new AppManagerNotInitError();
723
+ throw new Errors.AppManagerNotInitError();
735
724
  }
736
725
  }
737
726
 
@@ -739,7 +728,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
739
728
  if (this._pageState) {
740
729
  return this._pageState.toObject();
741
730
  } else {
742
- throw new AppManagerNotInitError();
731
+ throw new Errors.AppManagerNotInitError();
743
732
  }
744
733
  }
745
734
 
package/src/typings.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type Emittery from "emittery";
2
2
  import type {
3
3
  AnimationMode,
4
+ ApplianceNames,
4
5
  Displayer,
5
6
  DisplayerState,
6
7
  Player,
@@ -75,6 +76,8 @@ export type RegisterParams<AppOptions = any, SetupResult = any, Attributes = any
75
76
 
76
77
  export type AppListenerKeys = keyof AppEmitterEvent;
77
78
 
79
+ export type ApplianceIcons = Partial<Record<ApplianceNames, string>>;
80
+
78
81
  export type { AppContext } from "./App/AppContext";
79
82
  export type { ReadonlyTeleBox, TeleBoxRect };
80
83
  export type { SceneState, SceneDefinition, View, AnimationMode, Displayer, Room, Player };