@netless/window-manager 1.0.0-canary.5 → 1.0.0-canary.52

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 (95) hide show
  1. package/README.md +30 -6
  2. package/dist/index.cjs.js +12477 -34
  3. package/dist/index.es.js +6842 -10498
  4. package/dist/index.umd.js +12485 -46
  5. package/dist/{App → src/App}/AppContext.d.ts +12 -7
  6. package/dist/{App → src/App}/AppPageStateImpl.d.ts +0 -0
  7. package/dist/{App → src/App}/AppProxy.d.ts +29 -11
  8. package/dist/{App → src/App}/MagixEvent/index.d.ts +0 -0
  9. package/dist/{App → src/App}/Storage/StorageEvent.d.ts +0 -0
  10. package/dist/{App → src/App}/Storage/index.d.ts +0 -0
  11. package/dist/{App → src/App}/Storage/typings.d.ts +0 -0
  12. package/dist/{App → src/App}/Storage/utils.d.ts +0 -0
  13. package/dist/src/App/WhiteboardView.d.ts +27 -0
  14. package/dist/{App → src/App}/index.d.ts +1 -0
  15. package/dist/src/App/type.d.ts +21 -0
  16. package/dist/{AppListener.d.ts → src/AppListener.d.ts} +2 -2
  17. package/dist/{AppManager.d.ts → src/AppManager.d.ts} +6 -5
  18. package/dist/{AttributesDelegate.d.ts → src/AttributesDelegate.d.ts} +5 -2
  19. package/dist/{BoxEmitter.d.ts → src/BoxEmitter.d.ts} +0 -0
  20. package/dist/{BoxManager.d.ts → src/BoxManager.d.ts} +12 -6
  21. package/dist/{BuiltinApps.d.ts → src/BuiltinApps.d.ts} +3 -0
  22. package/dist/{Cursor → src/Cursor}/Cursor.d.ts +0 -0
  23. package/dist/{Cursor → src/Cursor}/icons.d.ts +0 -0
  24. package/dist/{Cursor → src/Cursor}/index.d.ts +3 -3
  25. package/dist/{Helper.d.ts → src/Helper.d.ts} +4 -8
  26. package/dist/{InternalEmitter.d.ts → src/InternalEmitter.d.ts} +3 -4
  27. package/dist/{Page → src/Page}/PageController.d.ts +2 -1
  28. package/dist/{Page → src/Page}/index.d.ts +0 -0
  29. package/dist/{PageState.d.ts → src/PageState.d.ts} +0 -0
  30. package/dist/{ReconnectRefresher.d.ts → src/ReconnectRefresher.d.ts} +0 -0
  31. package/dist/{RedoUndo.d.ts → src/RedoUndo.d.ts} +0 -0
  32. package/dist/{Register → src/Register}/index.d.ts +4 -2
  33. package/dist/{Register → src/Register}/loader.d.ts +1 -1
  34. package/dist/src/Register/storage.d.ts +11 -0
  35. package/dist/{Utils → src/Utils}/AppCreateQueue.d.ts +0 -0
  36. package/dist/{Utils → src/Utils}/Common.d.ts +0 -0
  37. package/dist/{Utils → src/Utils}/Reactive.d.ts +0 -0
  38. package/dist/{Utils → src/Utils}/RoomHacker.d.ts +0 -0
  39. package/dist/{Utils → src/Utils}/error.d.ts +1 -1
  40. package/dist/{Utils → src/Utils}/log.d.ts +0 -0
  41. package/dist/src/View/CameraSynchronizer.d.ts +19 -0
  42. package/dist/{View → src/View}/MainView.d.ts +18 -7
  43. package/dist/{View → src/View}/ViewManager.d.ts +0 -0
  44. package/dist/src/View/ViewSync.d.ts +29 -0
  45. package/dist/{callback.d.ts → src/callback.d.ts} +10 -1
  46. package/dist/{constants.d.ts → src/constants.d.ts} +10 -5
  47. package/dist/src/image.d.ts +19 -0
  48. package/dist/{index.d.ts → src/index.d.ts} +49 -14
  49. package/dist/src/shim.d.ts +11 -0
  50. package/dist/{typings.d.ts → src/typings.d.ts} +12 -3
  51. package/dist/style.css +795 -1
  52. package/docs/app-context.md +155 -27
  53. package/docs/mirgrate-to-1.0.md +68 -0
  54. package/package.json +23 -19
  55. package/playwright.config.ts +29 -0
  56. package/pnpm-lock.yaml +3078 -4412
  57. package/src/App/AppContext.ts +62 -29
  58. package/src/App/AppProxy.ts +235 -113
  59. package/src/App/WhiteboardView.ts +34 -12
  60. package/src/App/index.ts +1 -0
  61. package/src/App/type.ts +22 -0
  62. package/src/AppListener.ts +30 -21
  63. package/src/AppManager.ts +68 -45
  64. package/src/AttributesDelegate.ts +6 -3
  65. package/src/BoxManager.ts +76 -38
  66. package/src/BuiltinApps.ts +9 -8
  67. package/src/Cursor/Cursor.ts +7 -3
  68. package/src/Cursor/index.ts +7 -8
  69. package/src/Helper.ts +25 -7
  70. package/src/InternalEmitter.ts +3 -4
  71. package/src/Page/PageController.ts +2 -1
  72. package/src/PageState.ts +1 -1
  73. package/src/ReconnectRefresher.ts +6 -2
  74. package/src/Register/index.ts +36 -14
  75. package/src/Register/loader.ts +20 -9
  76. package/src/Register/storage.ts +26 -5
  77. package/src/Utils/Common.ts +3 -0
  78. package/src/Utils/Reactive.ts +27 -26
  79. package/src/Utils/RoomHacker.ts +3 -0
  80. package/src/Utils/error.ts +2 -2
  81. package/src/View/CameraSynchronizer.ts +41 -38
  82. package/src/View/MainView.ts +117 -76
  83. package/src/View/ViewSync.ts +123 -6
  84. package/src/callback.ts +6 -1
  85. package/src/constants.ts +8 -3
  86. package/src/index.ts +201 -63
  87. package/src/style.css +3 -46
  88. package/src/typings.ts +14 -3
  89. package/vite.config.js +12 -7
  90. package/dist/App/AppViewSync.d.ts +0 -11
  91. package/dist/App/WhiteboardView.d.ts +0 -21
  92. package/dist/Register/storage.d.ts +0 -8
  93. package/dist/View/CameraSynchronizer.d.ts +0 -17
  94. package/dist/View/ViewSync.d.ts +0 -7
  95. package/src/App/AppViewSync.ts +0 -69
package/src/BoxManager.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import { AppAttributes, Events, MIN_HEIGHT, MIN_WIDTH } from "./constants";
2
2
  import { debounce } from "lodash";
3
+ import { SideEffectManager } from "side-effect-manager";
3
4
  import { TELE_BOX_STATE, TeleBoxManager } from "@netless/telebox-insider";
4
5
  import { WindowManager } from "./index";
6
+ import type { Writeable } from "./typings";
5
7
  import type { BoxEmitterType } from "./BoxEmitter";
6
- import type { AddAppOptions, AppInitState } from "./index";
8
+ import type { AddAppOptions } from "./index";
7
9
  import type {
8
10
  TeleBoxManagerUpdateConfig,
9
11
  TeleBoxManagerCreateConfig,
@@ -12,13 +14,15 @@ import type {
12
14
  TeleBoxColorScheme,
13
15
  TeleBoxRect,
14
16
  TeleBoxConfig,
17
+ TeleBoxFullscreen,
18
+ TeleBoxManagerThemeConfig,
15
19
  } from "@netless/telebox-insider";
16
20
  import type Emittery from "emittery";
17
21
  import type { NetlessApp } from "./typings";
18
22
  import type { View } from "white-web-sdk";
19
23
  import type { CallbacksType } from "./callback";
20
24
  import type { EmitterType } from "./InternalEmitter";
21
- import { SideEffectManager } from "side-effect-manager";
25
+ import type { AppState } from "./App/type";
22
26
 
23
27
  export { TELE_BOX_STATE };
24
28
 
@@ -47,11 +51,16 @@ export type CreateTeleBoxManagerConfig = {
47
51
  collectorStyles?: Partial<CSSStyleDeclaration>;
48
52
  prefersColorScheme?: TeleBoxColorScheme;
49
53
  stageRatio?: number;
54
+ containerStyle?: string;
55
+ stageStyle?: string;
56
+ fullscreen?: TeleBoxFullscreen;
57
+ defaultBoxBodyStyle?: string | null;
58
+ defaultBoxStageStyle?: string | null;
59
+ theme?: TeleBoxManagerThemeConfig;
50
60
  };
51
61
 
52
62
  export type BoxManagerContext = {
53
63
  safeSetAttributes: (attributes: any) => void;
54
- getMainView: () => View;
55
64
  updateAppState: (appId: string, field: AppAttributes, value: any) => void;
56
65
  emitter: EmitterType;
57
66
  boxEmitter: BoxEmitterType;
@@ -72,7 +81,6 @@ export const createBoxManager = (
72
81
  return new BoxManager(
73
82
  {
74
83
  safeSetAttributes: (attributes: any) => manager.safeSetAttributes(attributes),
75
- getMainView: () => manager.mainView,
76
84
  updateAppState: (...args) => manager.appManager?.store.updateAppState(...args),
77
85
  canOperate: () => manager.canOperate,
78
86
  notifyContainerRectUpdate: (rect: TeleBoxRect) =>
@@ -81,7 +89,7 @@ export const createBoxManager = (
81
89
  setAppFocus: (appId: string) => manager.appManager?.store.setAppFocus(appId, true),
82
90
  callbacks,
83
91
  emitter,
84
- boxEmitter
92
+ boxEmitter,
85
93
  },
86
94
  options
87
95
  );
@@ -100,17 +108,17 @@ export class BoxManager {
100
108
  this.teleBoxManager = this.setupBoxManager(createTeleBoxManagerConfig);
101
109
  this.sideEffectManager.add(() => [
102
110
  // 使用 _xxx$.reaction 订阅修改的值, 不管有没有 skipUpdate, 修改值都会触发回调
103
- this.teleBoxManager._state$.reaction(state => {
111
+ this.teleBoxManager.onValChanged("state", state => {
104
112
  callbacks.emit("boxStateChange", state);
105
113
  emitter.emit("boxStateChange", state);
106
114
  }),
107
- this.teleBoxManager._darkMode$.reaction(darkMode => {
115
+ this.teleBoxManager.onValChanged("darkMode", darkMode => {
108
116
  callbacks.emit("darkModeChange", darkMode);
109
117
  }),
110
- this.teleBoxManager._prefersColorScheme$.reaction(colorScheme => {
118
+ this.teleBoxManager.onValChanged("prefersColorScheme", colorScheme => {
111
119
  callbacks.emit("prefersColorSchemeChange", colorScheme);
112
120
  }),
113
- this.teleBoxManager._minimized$.reaction((minimized, skipUpdate) => {
121
+ this.teleBoxManager.onValChanged("minimized", (minimized, skipUpdate) => {
114
122
  if (skipUpdate) {
115
123
  return;
116
124
  }
@@ -126,7 +134,7 @@ export class BoxManager {
126
134
  }
127
135
  }
128
136
  }),
129
- this.teleBoxManager._maximized$.reaction((maximized, skipUpdate) => {
137
+ this.teleBoxManager.onValChanged("maximized", (maximized, skipUpdate) => {
130
138
  if (skipUpdate) {
131
139
  return;
132
140
  }
@@ -140,7 +148,11 @@ export class BoxManager {
140
148
  this.teleBoxManager.events.on(
141
149
  "intrinsic_move",
142
150
  debounce((box: ReadonlyTeleBox): void => {
143
- boxEmitter.emit("move", { appId: box.id, x: box.intrinsicX, y: box.intrinsicY });
151
+ boxEmitter.emit("move", {
152
+ appId: box.id,
153
+ x: box.intrinsicX,
154
+ y: box.intrinsicY,
155
+ });
144
156
  }, 50)
145
157
  ),
146
158
  this.teleBoxManager.events.on(
@@ -165,23 +177,15 @@ export class BoxManager {
165
177
  this.teleBoxManager.events.on("z_index", box => {
166
178
  this.context.updateAppState(box.id, AppAttributes.ZIndex, box.zIndex);
167
179
  }),
168
- this.teleBoxManager._stageRect$.subscribe(stage => {
169
- emitter.emit("playgroundSizeChange", stage);
170
- this.context.notifyContainerRectUpdate(stage);
171
- }),
172
- emitter.on("writableChange", isWritable => {
173
- this.teleBoxManager.setHighlightStage(isWritable);
174
- }),
175
180
  emitter.on("containerSizeRatioUpdate", ratio => {
176
181
  this.teleBoxManager._stageRatio$.setValue(ratio);
177
182
  }),
183
+ this.teleBoxManager._fullscreen$.reaction(fullscreen => {
184
+ callbacks.emit("fullscreenChange", fullscreen);
185
+ }),
178
186
  ]);
179
187
  }
180
188
 
181
- private get mainView() {
182
- return this.context.getMainView();
183
- }
184
-
185
189
  private get canOperate() {
186
190
  return this.context.canOperate();
187
191
  }
@@ -214,9 +218,14 @@ export class BoxManager {
214
218
  return this.teleBoxManager.stageRect;
215
219
  }
216
220
 
221
+ public get stageRect$() {
222
+ return this.teleBoxManager._stageRect$;
223
+ }
224
+
217
225
  public createBox(params: CreateBoxParams): ReadonlyTeleBox | undefined {
218
226
  if (!this.teleBoxManager) return;
219
- let { minwidth = MIN_WIDTH, minheight = MIN_HEIGHT } = params.app.config ?? {};
227
+ // eslint-disable-next-line prefer-const
228
+ let { minwidth = MIN_WIDTH, minheight = MIN_HEIGHT, enableShadowDOM = true } = params.app.config ?? {};
220
229
  const { width, height } = params.app.config ?? {};
221
230
  const title = params.options?.title || params.appId;
222
231
  const rect = this.teleBoxManager.rootRect;
@@ -236,6 +245,7 @@ export class BoxManager {
236
245
  width,
237
246
  height,
238
247
  id: params.appId,
248
+ enableShadowDOM,
239
249
  };
240
250
  const box = this.teleBoxManager.create(createBoxConfig, params.smartPosition);
241
251
  this.context.emitter.emit(`${params.appId}${Events.WindowCreated}` as any);
@@ -246,13 +256,37 @@ export class BoxManager {
246
256
  createTeleBoxManagerConfig?: CreateTeleBoxManagerConfig
247
257
  ): TeleBoxManager {
248
258
  const root = WindowManager.playground;
249
- const initManagerState: TeleBoxManagerConfig = {
259
+ const initManagerState: Writeable<TeleBoxManagerConfig> = {
250
260
  stageRatio: createTeleBoxManagerConfig?.stageRatio,
251
261
  root: root,
252
262
  fence: false,
253
263
  prefersColorScheme: createTeleBoxManagerConfig?.prefersColorScheme,
254
264
  };
255
265
 
266
+ if (createTeleBoxManagerConfig?.containerStyle) {
267
+ initManagerState.containerStyle = createTeleBoxManagerConfig.containerStyle;
268
+ }
269
+
270
+ if (createTeleBoxManagerConfig?.stageStyle) {
271
+ initManagerState.stageStyle = createTeleBoxManagerConfig.stageStyle;
272
+ }
273
+
274
+ if (createTeleBoxManagerConfig?.fullscreen) {
275
+ initManagerState.fullscreen = createTeleBoxManagerConfig.fullscreen;
276
+ }
277
+
278
+ if (createTeleBoxManagerConfig?.defaultBoxBodyStyle !== undefined) {
279
+ initManagerState.defaultBoxBodyStyle = createTeleBoxManagerConfig.defaultBoxBodyStyle;
280
+ }
281
+
282
+ if (createTeleBoxManagerConfig?.defaultBoxStageStyle !== undefined) {
283
+ initManagerState.defaultBoxStageStyle = createTeleBoxManagerConfig.defaultBoxStageStyle;
284
+ }
285
+
286
+ if (createTeleBoxManagerConfig?.theme) {
287
+ initManagerState.theme = createTeleBoxManagerConfig.theme;
288
+ }
289
+
256
290
  const manager = new TeleBoxManager(initManagerState);
257
291
  if (this.teleBoxManager) {
258
292
  this.teleBoxManager.destroy();
@@ -290,21 +324,19 @@ export class BoxManager {
290
324
  return this.teleBoxManager.topBox;
291
325
  }
292
326
 
293
- public updateBoxState(state?: AppInitState): void {
327
+ public updateBoxState(state?: AppState): void {
294
328
  if (!state) return;
295
329
  const box = this.getBox(state.id);
296
330
  if (box) {
297
- this.teleBoxManager.update(
298
- box.id,
299
- {
300
- x: state.x,
301
- y: state.y,
302
- width: state.width || 0.5,
303
- height: state.height || 0.5,
304
- zIndex: state.zIndex,
305
- },
306
- true
307
- );
331
+ if (state.size) {
332
+ box._intrinsicSize$.setValue(state.size, true);
333
+ }
334
+ if (state.position) {
335
+ box._intrinsicCoord$.setValue(state.position, true);
336
+ }
337
+ if (state.zIndex) {
338
+ box._zIndex$.setValue(state.zIndex, true);
339
+ }
308
340
  setTimeout(() => {
309
341
  if (state.focus) {
310
342
  this.teleBoxManager.focusBox(box.id, true);
@@ -321,7 +353,10 @@ export class BoxManager {
321
353
  }
322
354
 
323
355
  public moveBox({ appId, x, y }: MoveBoxParams): void {
324
- this.teleBoxManager.update(appId, { x, y }, true);
356
+ const box = this.getBox(appId);
357
+ if (box) {
358
+ box._intrinsicCoord$.setValue({ x, y }, true);
359
+ }
325
360
  }
326
361
 
327
362
  public focusBox({ appId }: AppId, skipUpdate = true): void {
@@ -329,7 +364,10 @@ export class BoxManager {
329
364
  }
330
365
 
331
366
  public resizeBox({ appId, width, height, skipUpdate }: ResizeBoxParams): void {
332
- this.teleBoxManager.update(appId, { width, height }, skipUpdate);
367
+ const box = this.getBox(appId);
368
+ if (box) {
369
+ box._intrinsicSize$.setValue({ width, height }, skipUpdate);
370
+ }
333
371
  }
334
372
 
335
373
  public setBoxMinSize(params: SetBoxMinSizeParams): void {
@@ -1,23 +1,24 @@
1
1
  import AppDocsViewer from "@netless/app-docs-viewer";
2
- import AppMediaPlayer, { setOptions } from "@netless/app-media-player";
2
+ import Plyr from "@netless/app-plyr";
3
3
  import { WindowManager } from "./index";
4
4
 
5
5
  export const setupBuiltin = () => {
6
- if (WindowManager.debug) {
7
- setOptions({ verbose: true });
8
- }
9
-
10
6
  WindowManager.register({
11
7
  kind: AppDocsViewer.kind,
12
8
  src: AppDocsViewer,
13
9
  });
14
10
  WindowManager.register({
15
- kind: AppMediaPlayer.kind,
16
- src: AppMediaPlayer,
11
+ kind: Plyr.kind,
12
+ src: Plyr,
17
13
  });
18
14
  };
19
15
 
20
16
  export const BuiltinApps = {
21
17
  DocsViewer: AppDocsViewer.kind as string,
22
- MediaPlayer: AppMediaPlayer.kind as string,
18
+ MediaPlayer: Plyr.kind as string,
23
19
  };
20
+
21
+ export const BuiltinAppsMap = {
22
+ [BuiltinApps.DocsViewer]: AppDocsViewer,
23
+ [BuiltinApps.MediaPlayer]: Plyr,
24
+ }
@@ -7,6 +7,7 @@ import type { RoomMember } from "white-web-sdk";
7
7
  import type { CursorManager } from "./index";
8
8
  import type { SvelteComponent } from "svelte";
9
9
  import type { AppManager } from "../AppManager";
10
+ import type { TeleBoxRect } from "@netless/telebox-insider";
10
11
 
11
12
  export type Payload = {
12
13
  [key: string]: any;
@@ -30,7 +31,7 @@ export class Cursor {
30
31
 
31
32
  public move = (position: Position) => {
32
33
  if (position.type === "main") {
33
- const rect = this.cursorManager.wrapperRect;
34
+ const rect = this.manager.boxManager?.stageRect;
34
35
  if (this.component && rect) {
35
36
  this.autoHidden();
36
37
  this.moveCursor(position, rect, this.manager.mainView);
@@ -50,18 +51,21 @@ export class Cursor {
50
51
  this.hide();
51
52
  };
52
53
 
53
- private moveCursor(cursor: Position, rect: DOMRect, view: any) {
54
+ private moveCursor(cursor: Position, rect: TeleBoxRect, view: any) {
54
55
  const { x, y, type } = cursor;
55
56
  const point = view?.screen.convertPointToScreen(x, y);
56
57
  if (point) {
57
58
  let translateX = point.x - 2;
58
59
  let translateY = point.y - 18;
59
60
  if (type === "app") {
60
- const wrapperRect = this.cursorManager.wrapperRect;
61
+ const wrapperRect = this.cursorManager.playgroundRect;
61
62
  if (wrapperRect) {
62
63
  translateX = translateX + rect.x - wrapperRect.x;
63
64
  translateY = translateY + rect.y - wrapperRect.y;
64
65
  }
66
+ } else {
67
+ translateX = translateX + rect.x;
68
+ translateY = translateY + rect.y;
65
69
  }
66
70
  if (point.x < 0 || point.x > rect.width || point.y < 0 || point.y > rect.height) {
67
71
  this.component?.$set({ visible: false, x: translateX, y: translateY });
@@ -5,7 +5,7 @@ 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 , ApplianceIcons} from "../index";
8
+ import type { CursorMovePayload , ApplianceIcons, TeleBoxRect } 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";
@@ -23,8 +23,8 @@ export type MoveCursorParams = {
23
23
  };
24
24
 
25
25
  export class CursorManager {
26
- public containerRect?: DOMRect;
27
- public wrapperRect?: DOMRect;
26
+ public wrapperRect?: TeleBoxRect;
27
+ public playgroundRect?: DOMRect;
28
28
  public cursorInstances: Map<string, Cursor> = new Map();
29
29
  public roomMembers?: readonly RoomMember[];
30
30
  private mainViewElement?: HTMLDivElement;
@@ -89,8 +89,7 @@ export class CursorManager {
89
89
  wrapper.removeEventListener("pointerleave", this.mouseLeaveListener);
90
90
  };
91
91
  });
92
-
93
- this.wrapperRect = wrapper.getBoundingClientRect();
92
+ this.updateContainerRect();
94
93
  }
95
94
 
96
95
  public setMainViewDivElement(div: HTMLDivElement) {
@@ -110,7 +109,7 @@ export class CursorManager {
110
109
  if (!event.isPrimary) return;
111
110
  }
112
111
  this.updateCursor(this.getType(event), event.clientX, event.clientY);
113
- }, 16);
112
+ }, 48);
114
113
 
115
114
  private updateCursor(event: EventType, clientX: number, clientY: number) {
116
115
  if (this.wrapperRect && this.manager.canOperate) {
@@ -168,8 +167,8 @@ export class CursorManager {
168
167
  };
169
168
 
170
169
  public updateContainerRect() {
171
- this.containerRect = WindowManager.container?.getBoundingClientRect();
172
- this.wrapperRect = WindowManager.playground?.getBoundingClientRect();
170
+ this.wrapperRect = this.manager.boxManager?.stageRect;
171
+ this.playgroundRect = WindowManager.playground?.getBoundingClientRect();
173
172
  }
174
173
 
175
174
  public deleteCursor(uid: string) {
package/src/Helper.ts CHANGED
@@ -1,11 +1,14 @@
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
- import { WhiteVersion } from "white-web-sdk";
4
+ import { toJS, WhiteVersion } from "white-web-sdk";
4
5
  import { WhiteWebSDKInvalidError } from "./Utils/error";
5
- import type { Room , RoomMember} from "white-web-sdk";
6
+ import { WindowManager } from "./index";
7
+ import type { Room, RoomMember } from "white-web-sdk";
6
8
 
7
9
  export const setupWrapper = (
8
- root: HTMLElement
10
+ root: HTMLElement,
11
+ target: HTMLElement
9
12
  ): {
10
13
  playground: HTMLDivElement;
11
14
  mainViewElement: HTMLDivElement;
@@ -15,7 +18,7 @@ export const setupWrapper = (
15
18
 
16
19
  const mainViewElement = document.createElement("div");
17
20
  mainViewElement.className = "netless-window-manager-main-view";
18
- playground.appendChild(mainViewElement);
21
+ target.appendChild(mainViewElement);
19
22
  root.appendChild(playground);
20
23
 
21
24
  return { playground, mainViewElement };
@@ -38,6 +41,21 @@ export type Member = RoomMember & { uid: string };
38
41
  export const serializeRoomMembers = (members: readonly RoomMember[]) => {
39
42
  return members.map(member => ({
40
43
  uid: member.payload?.uid || "",
41
- ...member,
44
+ ...toJS(member),
42
45
  }));
43
- }
46
+ };
47
+
48
+ export const createInvisiblePlugin = async (room: Room) => {
49
+ try {
50
+ const manager = (await room.createInvisiblePlugin(WindowManager, {})) as WindowManager;
51
+ return manager;
52
+ } catch (error) {
53
+ // 如果有两个用户同时调用 WindowManager.mount 有概率出现这个错误
54
+ if (error.message === `invisible plugin "WindowManager" exits`) {
55
+ await wait(200);
56
+ return room.getInvisiblePlugin(WindowManager.kind) as WindowManager;
57
+ } else {
58
+ log("createInvisiblePlugin failed", error);
59
+ }
60
+ }
61
+ };
@@ -1,7 +1,7 @@
1
1
  import Emittery from "emittery";
2
2
  import type { TeleBoxRect } from "@netless/telebox-insider";
3
- import type { AppInitState, CursorMovePayload } from "./index";
4
- import type { Member } from "./Helper";
3
+ import type { CursorMovePayload } from "./index";
4
+ import type { MemberState } from "white-web-sdk";
5
5
 
6
6
  export type RemoveSceneParams = {
7
7
  scenePath: string;
@@ -10,7 +10,6 @@ export type RemoveSceneParams = {
10
10
 
11
11
  export type EmitterEvent = {
12
12
  onCreated: undefined;
13
- InitReplay: AppInitState;
14
13
  error: Error;
15
14
  seekStart: undefined;
16
15
  seek: number;
@@ -30,7 +29,7 @@ export type EmitterEvent = {
30
29
  changePageState: undefined;
31
30
  writableChange: boolean;
32
31
  containerSizeRatioUpdate: number;
33
- roomMembersChange: Member[];
32
+ memberStateChange: MemberState;
34
33
  };
35
34
 
36
35
  export type EmitterType = Emittery<EmitterEvent>;
@@ -2,7 +2,7 @@ import type { SceneDefinition } from "white-web-sdk";
2
2
 
3
3
  export type AddPageParams = {
4
4
  after?: boolean;
5
- scene?: SceneDefinition;
5
+ scene?: SceneDefinition | SceneDefinition[];
6
6
  };
7
7
 
8
8
  export type PageState = {
@@ -13,6 +13,7 @@ export type PageState = {
13
13
  export interface PageController {
14
14
  nextPage: () => Promise<boolean>;
15
15
  prevPage: () => Promise<boolean>;
16
+ jumpPage: (index: number) => Promise<boolean>;
16
17
  addPage: (params?: AddPageParams) => Promise<void>;
17
18
  removePage: (index: number) => Promise<boolean>;
18
19
  pageState: PageState;
package/src/PageState.ts CHANGED
@@ -6,7 +6,7 @@ import type { PageState } from "./Page";
6
6
  export class PageStateImpl {
7
7
  constructor(private manager: AppManager) {
8
8
  emitter.on("changePageState", () => {
9
- callbacks.emit("pageStateChange", this.toObject());
9
+ callbacks.emit("pageStateChange", this.toObject());
10
10
  });
11
11
  }
12
12
 
@@ -46,14 +46,18 @@ export class ReconnectRefresher {
46
46
  this.ctx.emitter.emit("startReconnect");
47
47
  }
48
48
  if (phase === RoomPhase.Connected && this.phase === RoomPhase.Reconnecting) {
49
- this.room?.dispatchMagixEvent(EnsureReconnectEvent, {});
49
+ if (this.room?.isWritable) {
50
+ this.room?.dispatchMagixEvent(EnsureReconnectEvent, {});
51
+ } else {
52
+ this.onReconnected();
53
+ }
50
54
  }
51
55
  this.phase = phase;
52
56
  };
53
57
 
54
58
  private onReconnected = debounce(() => {
55
59
  this._onReconnected();
56
- }, 3000);
60
+ }, 1000);
57
61
 
58
62
  private _onReconnected = () => {
59
63
  log("onReconnected refresh reactors");
@@ -1,6 +1,7 @@
1
1
  import Emittery from "emittery";
2
2
  import { loadApp } from "./loader";
3
3
  import type { NetlessApp, RegisterEvents, RegisterParams } from "../typings";
4
+ import { removeItem } from "./storage";
4
5
 
5
6
  export type LoadAppEvent = {
6
7
  kind: string;
@@ -11,11 +12,12 @@ export type LoadAppEvent = {
11
12
  export type SyncRegisterAppPayload = { kind: string, src: string, name: string | undefined };
12
13
  export type SyncRegisterApp = (payload: SyncRegisterAppPayload) => void;
13
14
 
14
- class AppRegister {
15
+ export class AppRegister {
15
16
  public kindEmitters: Map<string, Emittery<RegisterEvents>> = new Map();
16
17
  public registered: Map<string, RegisterParams> = new Map();
17
18
  public appClassesCache: Map<string, Promise<NetlessApp>> = new Map();
18
19
  public appClasses: Map<string, () => Promise<NetlessApp>> = new Map();
20
+ public downloaded: Map<string, string> = new Map();
19
21
 
20
22
  private syncRegisterApp: SyncRegisterApp | null = null;
21
23
 
@@ -31,32 +33,39 @@ class AppRegister {
31
33
  this.appClassesCache.delete(params.kind);
32
34
  this.registered.set(params.kind, params);
33
35
 
34
- const srcOrAppOrFunction = params.src;
36
+ const paramSrc = params.src;
35
37
  let downloadApp: () => Promise<NetlessApp>;
36
38
 
37
- if (typeof srcOrAppOrFunction === "string") {
39
+ if (typeof paramSrc === "string") {
38
40
  downloadApp = async () => {
39
- let appClass = (await loadApp(srcOrAppOrFunction, params.kind, params.name)) as any;
41
+ const result = await loadApp(paramSrc, params.kind, params.name) as any;
42
+ if (result.__esModule) {
43
+ return result.default;
44
+ }
45
+ return result;
46
+ };
47
+ if (this.syncRegisterApp) {
48
+ this.syncRegisterApp({ kind: params.kind, src: paramSrc, name: params.name });
49
+ }
50
+ }
51
+ if (typeof paramSrc === "function") {
52
+ downloadApp = async () => {
53
+ let appClass = await paramSrc() as any;
40
54
  if (appClass) {
41
- if (appClass.__esModule) {
55
+ if (appClass.__esModule || appClass.default) {
42
56
  appClass = appClass.default;
43
57
  }
44
58
  return appClass;
45
59
  } else {
46
60
  throw new Error(
47
- `[WindowManager]: load remote script failed, ${srcOrAppOrFunction}`
61
+ `[WindowManager]: load remote script failed, ${paramSrc}`
48
62
  );
49
63
  }
50
64
  };
51
- if (this.syncRegisterApp) {
52
- this.syncRegisterApp({ kind: params.kind, src: srcOrAppOrFunction, name: params.name });
53
- }
54
- } else if (typeof srcOrAppOrFunction === "function") {
55
- downloadApp = srcOrAppOrFunction;
56
- } else {
57
- downloadApp = async () => srcOrAppOrFunction;
58
65
  }
59
-
66
+ if (typeof paramSrc === "object") {
67
+ downloadApp = async () => paramSrc;
68
+ }
60
69
  this.appClasses.set(params.kind, async () => {
61
70
  let app = this.appClassesCache.get(params.kind);
62
71
  if (!app) {
@@ -74,10 +83,23 @@ class AppRegister {
74
83
  }
75
84
  }
76
85
 
86
+ public downloadApp(kind: string) {
87
+ const src = this.registered.get(kind);
88
+ if (src && typeof src.src === "string") {
89
+ return loadApp(src.src, src.kind, src.name)
90
+ }
91
+ }
92
+
93
+ public async removeDownloaded(kind: string) {
94
+ await removeItem(kind);
95
+ this.downloaded.delete(kind);
96
+ }
97
+
77
98
  public unregister(kind: string) {
78
99
  this.appClasses.delete(kind);
79
100
  this.appClassesCache.delete(kind);
80
101
  this.registered.delete(kind);
102
+ this.removeDownloaded(kind);
81
103
  const kindEmitter = this.kindEmitters.get(kind);
82
104
  if (kindEmitter) {
83
105
  kindEmitter.clearListeners();