@netless/window-manager 1.0.0-canary.6 → 1.0.0-canary.60

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 (111) hide show
  1. package/README.md +30 -6
  2. package/dist/index.js +13539 -0
  3. package/dist/index.mjs +13536 -0
  4. package/dist/index.umd.js +13534 -46
  5. package/dist/{App → src/App}/AppContext.d.ts +16 -14
  6. package/dist/{App → src/App}/AppPageStateImpl.d.ts +0 -0
  7. package/dist/{App → src/App}/AppProxy.d.ts +30 -11
  8. package/dist/{App → src/App}/MagixEvent/index.d.ts +0 -0
  9. package/dist/src/App/WhiteboardView.d.ts +27 -0
  10. package/dist/{App → src/App}/index.d.ts +1 -0
  11. package/dist/src/App/type.d.ts +21 -0
  12. package/dist/{AppListener.d.ts → src/AppListener.d.ts} +2 -2
  13. package/dist/{AppManager.d.ts → src/AppManager.d.ts} +11 -6
  14. package/dist/{AttributesDelegate.d.ts → src/AttributesDelegate.d.ts} +5 -2
  15. package/dist/{BoxEmitter.d.ts → src/BoxEmitter.d.ts} +0 -0
  16. package/dist/{BoxManager.d.ts → src/BoxManager.d.ts} +12 -6
  17. package/dist/{BuiltinApps.d.ts → src/BuiltinApps.d.ts} +3 -0
  18. package/dist/{Cursor → src/Cursor}/Cursor.d.ts +0 -0
  19. package/dist/{Cursor → src/Cursor}/icons.d.ts +0 -0
  20. package/dist/{Cursor → src/Cursor}/index.d.ts +4 -3
  21. package/dist/{Helper.d.ts → src/Helper.d.ts} +4 -8
  22. package/dist/{InternalEmitter.d.ts → src/InternalEmitter.d.ts} +1 -4
  23. package/dist/{Page → src/Page}/PageController.d.ts +2 -1
  24. package/dist/{Page → src/Page}/index.d.ts +0 -0
  25. package/dist/{PageState.d.ts → src/PageState.d.ts} +0 -0
  26. package/dist/{ReconnectRefresher.d.ts → src/ReconnectRefresher.d.ts} +0 -0
  27. package/dist/{RedoUndo.d.ts → src/RedoUndo.d.ts} +0 -0
  28. package/dist/{Register → src/Register}/index.d.ts +4 -2
  29. package/dist/{Register → src/Register}/loader.d.ts +1 -1
  30. package/dist/src/Register/storage.d.ts +11 -0
  31. package/dist/{Utils → src/Utils}/AppCreateQueue.d.ts +0 -0
  32. package/dist/{Utils → src/Utils}/Common.d.ts +0 -0
  33. package/dist/{Utils → src/Utils}/Reactive.d.ts +1 -1
  34. package/dist/{Utils → src/Utils}/RoomHacker.d.ts +0 -0
  35. package/dist/{Utils → src/Utils}/error.d.ts +1 -1
  36. package/dist/{Utils → src/Utils}/log.d.ts +0 -0
  37. package/dist/src/View/CameraSynchronizer.d.ts +20 -0
  38. package/dist/{View → src/View}/MainView.d.ts +18 -7
  39. package/dist/src/View/ScrollMode.d.ts +32 -0
  40. package/dist/{View → src/View}/ViewManager.d.ts +0 -0
  41. package/dist/src/View/ViewSync.d.ts +32 -0
  42. package/dist/{callback.d.ts → src/callback.d.ts} +13 -1
  43. package/dist/{constants.d.ts → src/constants.d.ts} +12 -5
  44. package/dist/src/image.d.ts +19 -0
  45. package/dist/{index.d.ts → src/index.d.ts} +66 -17
  46. package/dist/src/shim.d.ts +11 -0
  47. package/dist/src/storage.d.ts +7 -0
  48. package/dist/{typings.d.ts → src/typings.d.ts} +18 -8
  49. package/dist/style.css +810 -1
  50. package/docs/api.md +10 -0
  51. package/docs/app-context.md +155 -27
  52. package/docs/mirgrate-to-1.0.md +68 -0
  53. package/package.json +27 -22
  54. package/playwright.config.ts +29 -0
  55. package/pnpm-lock.yaml +3141 -4483
  56. package/src/App/AppContext.ts +81 -46
  57. package/src/App/AppProxy.ts +249 -139
  58. package/src/App/WhiteboardView.ts +38 -14
  59. package/src/App/index.ts +1 -0
  60. package/src/App/type.ts +22 -0
  61. package/src/AppListener.ts +21 -21
  62. package/src/AppManager.ts +84 -43
  63. package/src/AttributesDelegate.ts +6 -3
  64. package/src/BoxManager.ts +76 -38
  65. package/src/BuiltinApps.ts +9 -8
  66. package/src/Cursor/Cursor.svelte +6 -2
  67. package/src/Cursor/Cursor.ts +16 -5
  68. package/src/Cursor/icons.ts +6 -0
  69. package/src/Cursor/index.ts +13 -10
  70. package/src/Helper.ts +25 -7
  71. package/src/InternalEmitter.ts +1 -4
  72. package/src/Page/PageController.ts +2 -1
  73. package/src/PageState.ts +1 -1
  74. package/src/ReconnectRefresher.ts +6 -2
  75. package/src/Register/index.ts +36 -14
  76. package/src/Register/loader.ts +20 -9
  77. package/src/Register/storage.ts +26 -5
  78. package/src/Utils/Common.ts +3 -0
  79. package/src/Utils/Reactive.ts +29 -27
  80. package/src/Utils/RoomHacker.ts +3 -0
  81. package/src/Utils/error.ts +2 -2
  82. package/src/View/CameraSynchronizer.ts +52 -37
  83. package/src/View/MainView.ts +118 -76
  84. package/src/View/ScrollMode.ts +239 -0
  85. package/src/View/ViewSync.ts +139 -6
  86. package/src/callback.ts +9 -1
  87. package/src/constants.ts +11 -3
  88. package/src/image/pencil-eraser-1.svg +3 -0
  89. package/src/image/pencil-eraser-2.svg +3 -0
  90. package/src/image/pencil-eraser-3.svg +3 -0
  91. package/src/index.ts +202 -58
  92. package/src/storage.ts +15 -0
  93. package/src/style.css +18 -47
  94. package/src/typings.ts +21 -7
  95. package/vite.config.js +12 -7
  96. package/dist/App/AppViewSync.d.ts +0 -11
  97. package/dist/App/Storage/StorageEvent.d.ts +0 -8
  98. package/dist/App/Storage/index.d.ts +0 -39
  99. package/dist/App/Storage/typings.d.ts +0 -22
  100. package/dist/App/Storage/utils.d.ts +0 -5
  101. package/dist/App/WhiteboardView.d.ts +0 -21
  102. package/dist/Register/storage.d.ts +0 -8
  103. package/dist/View/CameraSynchronizer.d.ts +0 -17
  104. package/dist/View/ViewSync.d.ts +0 -7
  105. package/dist/index.cjs.js +0 -46
  106. package/dist/index.es.js +0 -16159
  107. package/src/App/AppViewSync.ts +0 -68
  108. package/src/App/Storage/StorageEvent.ts +0 -21
  109. package/src/App/Storage/index.ts +0 -295
  110. package/src/App/Storage/typings.ts +0 -23
  111. package/src/App/Storage/utils.ts +0 -17
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
+ }
@@ -15,12 +15,16 @@
15
15
  export let color: string;
16
16
  export let cursorTagBackgroundColor: string;
17
17
  export let opacity: number;
18
+ export let pencilEraserSize: number;
18
19
 
19
20
  $: hasName = !isEmpty(cursorName);
20
21
  $: hasTagName = !isEmpty(tagName);
21
22
  $: hasAvatar = !isEmpty(avatar);
22
23
  $: display = visible ? "initial" : "none";
23
24
  $: isLaserPointer = appliance === ApplianceNames.laserPointer;
25
+ $: isLaserPointerPencilEraser = isLaserPointer || appliance === ApplianceNames.pencilEraser;
26
+ $: offset = isLaserPointerPencilEraser ? "netless-window-manager-laserPointer-pencilEraser-offset" : "";
27
+ $: pencilEraserSize3ImageOffset = pencilEraserSize === 3 ? "netless-window-manager-pencilEraser-3-offset" : "";
24
28
 
25
29
  const computedAvatarStyle = () => {
26
30
  return Object.entries({
@@ -40,7 +44,7 @@
40
44
  style="transform: translateX({x}px) translateY({y}px);display: {display}"
41
45
  >
42
46
  {#if !isLaserPointer}
43
- <div class="netless-window-manager-cursor-name">
47
+ <div class="netless-window-manager-cursor-name {offset} {pencilEraserSize3ImageOffset}">
44
48
  <div
45
49
  class={theme}
46
50
  style="background-color: {backgroundColor};color: {color};opacity: {opacity}"
@@ -63,6 +67,6 @@
63
67
  </div>
64
68
  {/if}
65
69
  <div class="cursor-image-wrapper">
66
- <img class="netless-window-manager-cursor-{appliance}-image" {src} alt={appliance} />
70
+ <img class="netless-window-manager-cursor-{appliance}-image {pencilEraserSize3ImageOffset}" {src} alt={appliance} />
67
71
  </div>
68
72
  </div>
@@ -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 });
@@ -153,14 +157,21 @@ export class Cursor {
153
157
  cursorTagBackgroundColor: this.memberCursorTagBackgroundColor,
154
158
  opacity: this.memberOpacity,
155
159
  tagName: this.memberTagName,
160
+ pencilEraserSize: this.member?.memberState.pencilEraserSize,
156
161
  };
157
162
  }
158
163
 
159
164
  private getIcon() {
160
165
  if (this.member) {
161
166
  const icons = this.cursorManager.applianceIcons;
162
- const applianceSrc = icons[this.memberApplianceName || ApplianceNames.shape];
163
- return applianceSrc || icons[ApplianceNames.shape];
167
+ let applianceSrc = icons[ApplianceNames.shape];
168
+ if (this.memberApplianceName === ApplianceNames.pencilEraser) {
169
+ const size = this.member?.memberState.pencilEraserSize || 1;
170
+ applianceSrc = icons[`${this.memberApplianceName}${size}`];
171
+ } else {
172
+ applianceSrc = icons[this.memberApplianceName || ApplianceNames.shape];
173
+ }
174
+ return applianceSrc;
164
175
  }
165
176
  }
166
177
 
@@ -5,6 +5,9 @@ import eraser from "../image/eraser-cursor.png";
5
5
  import shape from "../image/shape-cursor.svg";
6
6
  import text from "../image/text-cursor.svg";
7
7
  import laser from "../image/laser-pointer-cursor.svg";
8
+ import pencilEraser1 from "../image/pencil-eraser-1.svg";
9
+ import pencilEraser2 from "../image/pencil-eraser-2.svg";
10
+ import pencilEraser3 from "../image/pencil-eraser-3.svg";
8
11
 
9
12
  export const ApplianceMap: {
10
13
  [key: string]: string;
@@ -15,4 +18,7 @@ export const ApplianceMap: {
15
18
  [ApplianceNames.shape]: shape,
16
19
  [ApplianceNames.text]: text,
17
20
  [ApplianceNames.laserPointer]: laser,
21
+ ["pencilEraser1"]: pencilEraser1,
22
+ ["pencilEraser2"]: pencilEraser2,
23
+ ["pencilEraser3"]: pencilEraser3,
18
24
  };
@@ -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;
@@ -32,9 +32,13 @@ export class CursorManager {
32
32
  private store = this.manager.store;
33
33
  public applianceIcons: ApplianceIcons = ApplianceMap;
34
34
 
35
+ public get playground$() {
36
+ return this.manager.windowManger.playground$;
37
+ }
38
+
35
39
  constructor(private manager: AppManager, private enableCursor: boolean, applianceIcons?: ApplianceIcons) {
36
40
  this.roomMembers = this.manager.room?.state.roomMembers;
37
- const playground = WindowManager.playground;
41
+ const playground = this.playground$.value;
38
42
  if (playground) {
39
43
  this.setupWrapper(playground);
40
44
  }
@@ -65,7 +69,7 @@ export class CursorManager {
65
69
  private initCursorInstance = (uid: string) => {
66
70
  let cursorInstance = this.cursorInstances.get(uid);
67
71
  if (!cursorInstance) {
68
- cursorInstance = new Cursor(this.manager, uid, this, WindowManager.playground);
72
+ cursorInstance = new Cursor(this.manager, uid, this, this.playground$.value);
69
73
  this.cursorInstances.set(uid, cursorInstance);
70
74
  }
71
75
  return cursorInstance;
@@ -89,8 +93,7 @@ export class CursorManager {
89
93
  wrapper.removeEventListener("pointerleave", this.mouseLeaveListener);
90
94
  };
91
95
  });
92
-
93
- this.wrapperRect = wrapper.getBoundingClientRect();
96
+ this.updateContainerRect();
94
97
  }
95
98
 
96
99
  public setMainViewDivElement(div: HTMLDivElement) {
@@ -110,7 +113,7 @@ export class CursorManager {
110
113
  if (!event.isPrimary) return;
111
114
  }
112
115
  this.updateCursor(this.getType(event), event.clientX, event.clientY);
113
- }, 16);
116
+ }, 48);
114
117
 
115
118
  private updateCursor(event: EventType, clientX: number, clientY: number) {
116
119
  if (this.wrapperRect && this.manager.canOperate) {
@@ -168,8 +171,8 @@ export class CursorManager {
168
171
  };
169
172
 
170
173
  public updateContainerRect() {
171
- this.containerRect = WindowManager.container?.getBoundingClientRect();
172
- this.wrapperRect = WindowManager.playground?.getBoundingClientRect();
174
+ this.wrapperRect = this.manager.boxManager?.stageRect;
175
+ this.playgroundRect = WindowManager.playground?.getBoundingClientRect();
173
176
  }
174
177
 
175
178
  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,6 @@
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";
5
4
  import type { MemberState } from "white-web-sdk";
6
5
 
7
6
  export type RemoveSceneParams = {
@@ -11,7 +10,6 @@ export type RemoveSceneParams = {
11
10
 
12
11
  export type EmitterEvent = {
13
12
  onCreated: undefined;
14
- InitReplay: AppInitState;
15
13
  error: Error;
16
14
  seekStart: undefined;
17
15
  seek: number;
@@ -31,7 +29,6 @@ export type EmitterEvent = {
31
29
  changePageState: undefined;
32
30
  writableChange: boolean;
33
31
  containerSizeRatioUpdate: number;
34
- roomMembersChange: Member[];
35
32
  memberStateChange: MemberState;
36
33
  };
37
34
 
@@ -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");