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

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 +6839 -10495
  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 +66 -43
  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 +116 -75
  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/index.ts CHANGED
@@ -2,21 +2,20 @@ 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 { createBoxManager } from "./BoxManager";
7
7
  import { CursorManager } from "./Cursor";
8
8
  import { DEFAULT_CONTAINER_RATIO, Events, INIT_DIR, ROOT_DIR } from "./constants";
9
9
  import { emitter } from "./InternalEmitter";
10
10
  import { Fields } from "./AttributesDelegate";
11
11
  import { initDb } from "./Register/storage";
12
- import { InvisiblePlugin, isPlayer, isRoom, RoomPhase, ViewMode } from "white-web-sdk";
13
- import { isEqual, isNull, isObject, omit, isNumber } from "lodash";
12
+ import { AnimationMode, InvisiblePlugin, isPlayer, isRoom, RoomPhase, ViewMode } from "white-web-sdk";
13
+ import { isEqual, isNull, isObject, isNumber } from "lodash";
14
14
  import { log } from "./Utils/log";
15
15
  import { PageStateImpl } from "./PageState";
16
16
  import { ReconnectRefresher } from "./ReconnectRefresher";
17
17
  import { replaceRoomFunction } from "./Utils/RoomHacker";
18
18
  import { setupBuiltin } from "./BuiltinApps";
19
- import "video.js/dist/video-js.css";
20
19
  import "./style.css";
21
20
  import "@netless/telebox-insider/dist/style.css";
22
21
  import {
@@ -27,6 +26,8 @@ import {
27
26
  putScenes,
28
27
  wait,
29
28
  } from "./Utils/Common";
29
+ import { boxEmitter } from "./BoxEmitter";
30
+ import { Val } from "value-enhancer";
30
31
  import type { TELE_BOX_STATE, BoxManager } from "./BoxManager";
31
32
  import * as Errors from "./Utils/error";
32
33
  import type { Apps, Position , ICamera, ISize } from "./AttributesDelegate";
@@ -37,23 +38,22 @@ import type {
37
38
  Room,
38
39
  InvisiblePluginContext,
39
40
  Camera,
40
- AnimationMode,
41
41
  CameraBound,
42
42
  Point,
43
- Rectangle,
44
43
  CameraState,
45
44
  Player,
46
45
  ImageInformation,
47
46
  SceneState,
47
+ Size
48
48
  } from "white-web-sdk";
49
49
  import type { AppListeners } from "./AppListener";
50
50
  import type { ApplianceIcons, NetlessApp, RegisterParams } from "./typings";
51
- import type { TeleBoxColorScheme, TeleBoxState } from "@netless/telebox-insider";
51
+ import type { TeleBoxColorScheme, TeleBoxFullscreen, TeleBoxManager, TeleBoxManagerThemeConfig, TeleBoxState } from "@netless/telebox-insider";
52
52
  import type { AppProxy } from "./App";
53
53
  import type { PublicEvent } from "./callback";
54
54
  import type Emittery from "emittery";
55
55
  import type { PageController, AddPageParams, PageState } from "./Page";
56
- import { boxEmitter } from "./BoxEmitter";
56
+ import { computedMinScale } from "./View/CameraSynchronizer";
57
57
 
58
58
  export type WindowMangerAttributes = {
59
59
  modelValue?: string;
@@ -106,6 +106,7 @@ export type AppSyncAttributes = {
106
106
  createdAt?: number;
107
107
  camera?: ICamera;
108
108
  size?: ISize;
109
+ setup: boolean;
109
110
  };
110
111
 
111
112
  export type AppInitState = {
@@ -120,6 +121,11 @@ export type AppInitState = {
120
121
  sceneIndex?: number;
121
122
  boxState?: TeleBoxState; // 兼容旧版 telebox
122
123
  zIndex?: number;
124
+ visible?: boolean;
125
+ stageRatio?: number;
126
+ resizable?: boolean;
127
+ draggable?: boolean;
128
+ ratio?: number;
123
129
  };
124
130
 
125
131
  export type CursorMovePayload = { uid: string; state?: "leave"; position: Position };
@@ -129,8 +135,6 @@ export type MountParams = {
129
135
  container?: HTMLElement;
130
136
  /** 白板高宽比例, 默认为 9 / 16 */
131
137
  containerSizeRatio?: number;
132
- /** 显示 PS 透明背景,默认 true */
133
- chessboard?: boolean;
134
138
  collectorContainer?: HTMLElement;
135
139
  collectorStyles?: Partial<CSSStyleDeclaration>;
136
140
  overwriteStyles?: string;
@@ -138,7 +142,18 @@ export type MountParams = {
138
142
  debug?: boolean;
139
143
  disableCameraTransform?: boolean;
140
144
  prefersColorScheme?: TeleBoxColorScheme;
145
+ /** @deprecated */
146
+ chessboard?: boolean;
141
147
  applianceIcons?: ApplianceIcons;
148
+ containerStyle?: string;
149
+ stageStyle?: string;
150
+ fullscreen?: TeleBoxFullscreen;
151
+ /** Custom `style` attribute value for content area of all boxes. Can be overwritten by box. */
152
+ defaultBoxBodyStyle?: string | null;
153
+ /** Custom `style` attribute value for stage area of all boxes. Can be overwritten by box. */
154
+ defaultBoxStageStyle?: string | null;
155
+ /** Theme variable */
156
+ theme?: TeleBoxManagerThemeConfig;
142
157
  };
143
158
 
144
159
  export const reconnectRefresher = new ReconnectRefresher({ emitter });
@@ -151,6 +166,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
151
166
  public static debug = false;
152
167
  public static containerSizeRatio = DEFAULT_CONTAINER_RATIO;
153
168
  private static isCreated = false;
169
+ public static registry = appRegister;
154
170
 
155
171
  public version = __APP_VERSION__;
156
172
  public dependencies = __APP_DEPENDENCIES__;
@@ -162,12 +178,16 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
162
178
  public appManager?: AppManager;
163
179
  public cursorManager?: CursorManager;
164
180
  public viewMode = ViewMode.Broadcaster;
181
+ public viewMode$ = new Val<ViewMode>(ViewMode.Broadcaster);
165
182
  public isReplay = isPlayer(this.displayer);
166
183
  private _pageState?: PageStateImpl;
167
184
 
168
185
  private boxManager?: BoxManager;
169
186
  private static params?: MountParams;
170
187
 
188
+ private cameraUpdating = 0;
189
+ private nextCamera: Camera | null = null;
190
+
171
191
  public containerSizeRatio = WindowManager.containerSizeRatio;
172
192
 
173
193
  constructor(context: InvisiblePluginContext) {
@@ -179,14 +199,13 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
179
199
  public static async mount(params: MountParams): Promise<WindowManager> {
180
200
  const room = params.room;
181
201
  WindowManager.container = params.container;
182
- const containerSizeRatio = params.containerSizeRatio;
183
202
  const debug = params.debug;
184
-
185
203
  const cursor = params.cursor;
186
204
  WindowManager.params = params;
187
205
  WindowManager.displayer = params.room;
188
- checkVersion();
189
206
  let manager: WindowManager | undefined = undefined;
207
+
208
+ checkVersion();
190
209
  if (isRoom(room)) {
191
210
  if (room.phase !== RoomPhase.Connected) {
192
211
  throw new Error("[WindowManager]: Room only Connected can be mount");
@@ -225,22 +244,25 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
225
244
  throw new Error("[WindowManager]: create manager failed");
226
245
  }
227
246
 
228
- if (containerSizeRatio) {
229
- WindowManager.containerSizeRatio = containerSizeRatio;
247
+ if (params.containerSizeRatio) {
248
+ WindowManager.containerSizeRatio = params.containerSizeRatio;
230
249
  }
250
+ manager.containerSizeRatio = WindowManager.containerSizeRatio;
231
251
  await manager.ensureAttributes();
232
252
 
233
253
  manager.appManager = new AppManager(manager);
234
254
  manager._pageState = new PageStateImpl(manager.appManager);
235
255
  manager.cursorManager = new CursorManager(manager.appManager, Boolean(cursor), params.applianceIcons);
236
- if (containerSizeRatio) {
237
- manager.containerSizeRatio = containerSizeRatio;
238
- }
256
+
239
257
  manager.boxManager = createBoxManager(manager, callbacks, emitter, boxEmitter, {
240
258
  collectorContainer: params.collectorContainer,
241
259
  collectorStyles: params.collectorStyles,
242
260
  prefersColorScheme: params.prefersColorScheme,
243
- stageRatio: params.containerSizeRatio,
261
+ stageRatio: WindowManager.containerSizeRatio,
262
+ containerStyle: params.containerStyle,
263
+ stageStyle: params.stageStyle,
264
+ fullscreen: params.fullscreen,
265
+ theme: params.theme,
244
266
  });
245
267
  manager.appManager?.setBoxManager(manager.boxManager);
246
268
  if (params.container) {
@@ -251,7 +273,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
251
273
  emitter.emit("onCreated");
252
274
  WindowManager.isCreated = true;
253
275
  try {
254
- await initDb();
276
+ await initDb(appRegister);
255
277
  } catch (error) {
256
278
  console.warn("[WindowManager]: indexedDB open failed");
257
279
  console.log(error);
@@ -259,8 +281,8 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
259
281
  return manager;
260
282
  }
261
283
 
262
- private static async initManager(room: Room): Promise<WindowManager> {
263
- let manager = room.getInvisiblePlugin(WindowManager.kind) as WindowManager;
284
+ private static async initManager(room: Room): Promise<WindowManager | undefined> {
285
+ let manager = room.getInvisiblePlugin(WindowManager.kind) as WindowManager | undefined;
264
286
  if (!manager) {
265
287
  if (isRoom(room)) {
266
288
  if (room.isWritable === false) {
@@ -269,18 +291,12 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
269
291
  } catch (error) {
270
292
  throw new Error("[WindowManger]: room must be switched to be writable");
271
293
  }
272
- manager = (await room.createInvisiblePlugin(
273
- WindowManager,
274
- {}
275
- )) as WindowManager;
276
- manager.ensureAttributes();
294
+ manager = await createInvisiblePlugin(room);
295
+ manager?.ensureAttributes();
277
296
  await wait(500);
278
297
  await room.setWritable(false);
279
298
  } else {
280
- manager = (await room.createInvisiblePlugin(
281
- WindowManager,
282
- {}
283
- )) as WindowManager;
299
+ manager = await createInvisiblePlugin(room);
284
300
  }
285
301
  }
286
302
  }
@@ -289,12 +305,13 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
289
305
 
290
306
  private static initContainer(
291
307
  container: HTMLElement,
308
+ target: HTMLElement,
292
309
  overwriteStyles: string | undefined
293
310
  ) {
294
311
  if (!WindowManager.container) {
295
312
  WindowManager.container = container;
296
313
  }
297
- const { playground, mainViewElement } = setupWrapper(container);
314
+ const { playground, mainViewElement } = setupWrapper(container, target);
298
315
  WindowManager.playground = playground;
299
316
  if (overwriteStyles) {
300
317
  const style = document.createElement("style");
@@ -317,10 +334,12 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
317
334
  container.appendChild(WindowManager.container.firstChild);
318
335
  }
319
336
  } else {
320
- if (WindowManager.params) {
337
+ const teleboxContainer = this.boxManager?.teleBoxManager.$stage;
338
+ if (WindowManager.params && teleboxContainer) {
321
339
  const params = WindowManager.params;
322
340
  const mainViewElement = WindowManager.initContainer(
323
341
  container,
342
+ teleboxContainer,
324
343
  params.overwriteStyles
325
344
  );
326
345
  if (this.boxManager && WindowManager.playground) {
@@ -330,6 +349,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
330
349
  if (WindowManager.playground) {
331
350
  this.cursorManager?.setupWrapper(WindowManager.playground);
332
351
  }
352
+
333
353
  }
334
354
  }
335
355
  emitter.emit("updateManagerRect");
@@ -504,15 +524,28 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
504
524
  }
505
525
  }
506
526
 
527
+ public async jumpPage(index: number): Promise<boolean> {
528
+ if (!this.appManager) {
529
+ return false;
530
+ }
531
+ if (index < 0 || index >= this.pageState.length) {
532
+ console.warn(`[WindowManager]: index ${index} out of range`);
533
+ return false;
534
+ }
535
+ await this.appManager.setMainViewSceneIndex(index);
536
+ return true;
537
+ }
538
+
507
539
  public async addPage(params?: AddPageParams): Promise<void> {
508
540
  if (this.appManager) {
509
541
  const after = params?.after;
510
- const scene = params?.scene;
542
+ const scene = params?.scene || {};
543
+ const scenes = Array.isArray(scene) ? scene : [scene];
511
544
  if (after) {
512
545
  const nextIndex = this.mainViewSceneIndex + 1;
513
- this.room.putScenes(ROOT_DIR, [scene || {}], nextIndex);
546
+ this.room.putScenes(ROOT_DIR, scenes, nextIndex);
514
547
  } else {
515
- this.room.putScenes(ROOT_DIR, [scene || {}]);
548
+ this.room.putScenes(ROOT_DIR, scenes);
516
549
  }
517
550
  }
518
551
  }
@@ -580,16 +613,19 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
580
613
  * 设置 ViewMode
581
614
  */
582
615
  public setViewMode(mode: ViewMode): void {
616
+ log("setViewMode", mode);
617
+ const mainViewProxy = this.appManager?.mainViewProxy;
583
618
  if (mode === ViewMode.Broadcaster) {
584
619
  if (this.canOperate) {
585
- this.appManager?.mainViewProxy.setCameraAndSize();
620
+ mainViewProxy?.storeCurrentCamera();
586
621
  }
587
- this.appManager?.mainViewProxy.start();
622
+ mainViewProxy?.start();
588
623
  }
589
624
  if (mode === ViewMode.Freedom) {
590
- this.appManager?.mainViewProxy.stop();
625
+ mainViewProxy?.stop();
591
626
  }
592
627
  this.viewMode = mode;
628
+ this.viewMode$.setValue(mode);
593
629
  }
594
630
 
595
631
  public setBoxState(boxState: TeleBoxState): void {
@@ -637,6 +673,22 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
637
673
  }
638
674
  }
639
675
 
676
+ public get baseCamera() {
677
+ if (this.appManager) {
678
+ return this.appManager.mainViewProxy.camera$.value;
679
+ } else {
680
+ throw new Errors.AppManagerNotInitError();
681
+ }
682
+ }
683
+
684
+ public get baseSize() {
685
+ if (this.appManager) {
686
+ return this.appManager.mainViewProxy.size$.value;
687
+ } else {
688
+ throw new Errors.AppManagerNotInitError();
689
+ }
690
+ }
691
+
640
692
  public get cameraState(): CameraState {
641
693
  if (this.appManager) {
642
694
  return this.appManager.mainViewProxy.cameraState;
@@ -669,6 +721,14 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
669
721
  }
670
722
  }
671
723
 
724
+ public get fullscreen(): TeleBoxFullscreen | undefined {
725
+ if (this.appManager) {
726
+ return this.appManager.boxManager?.teleBoxManager.fullscreen;
727
+ } else {
728
+ throw new Errors.AppManagerNotInitError();
729
+ }
730
+ }
731
+
672
732
  public get focused(): string | undefined {
673
733
  return this.attributes.focus;
674
734
  }
@@ -722,6 +782,13 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
722
782
  }
723
783
  }
724
784
 
785
+ public get teleboxManager(): TeleBoxManager {
786
+ if (!this.boxManager) {
787
+ throw new Errors.BoxManagerNotInitializeError();
788
+ }
789
+ return this.boxManager.teleBoxManager;
790
+ }
791
+
725
792
  /**
726
793
  * 查询所有的 App
727
794
  */
@@ -743,30 +810,58 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
743
810
  return this.appManager?.closeApp(appId);
744
811
  }
745
812
 
746
- public moveCamera(
747
- camera: Partial<Camera> & { animationMode?: AnimationMode | undefined }
748
- ): void {
749
- const pureCamera = omit(camera, ["animationMode"]);
813
+ public moveCamera = (camera: Partial<Camera> & { animationMode?: AnimationMode } ): void => {
750
814
  const mainViewCamera = { ...this.mainView.camera };
751
- if (isEqual({ ...mainViewCamera, ...pureCamera }, mainViewCamera)) return;
752
- this.mainView.moveCamera(camera);
753
- this.appManager?.dispatchInternalEvent(Events.MoveCamera, camera);
754
- setTimeout(() => {
755
- this.appManager?.mainViewProxy.setCameraAndSize();
756
- }, 500);
757
- }
815
+ const nextCamera = { ...mainViewCamera, ...camera };
816
+ if (isEqual(nextCamera, mainViewCamera)) return;
817
+ if (!this.appManager) return;
818
+ if (camera.animationMode === AnimationMode.Immediately) {
819
+ this.appManager.mainViewProxy.storeCamera({
820
+ id: this.appManager.uid,
821
+ ...nextCamera
822
+ });
823
+ } else {
824
+ const remoteCamera = this.appManager.mainViewProxy.size$.value;
825
+ const currentSize = this.boxManager?.stageRect;
826
+ let nextScale;
827
+ if (camera.scale && remoteCamera && currentSize) {
828
+ nextScale = camera.scale * computedMinScale(remoteCamera, currentSize);
829
+ }
830
+ if (nextScale) {
831
+ this.mainView.moveCamera({
832
+ ...camera,
833
+ scale: nextScale,
834
+ });
835
+ } else {
836
+ this.mainView.moveCamera(camera);
837
+ }
838
+ this.appManager.dispatchInternalEvent(Events.MoveCamera, camera);
839
+ this.mainView.callbacks.off("onCameraUpdated", this.onCameraUpdated);
840
+ clearTimeout(this.cameraUpdating);
841
+ this.cameraUpdating = 0;
842
+ this.mainView.callbacks.on("onCameraUpdated", this.onCameraUpdated);
843
+ if (nextScale) {
844
+ this.nextCamera = nextCamera;
845
+ }
846
+ }
847
+ };
758
848
 
759
- public moveCameraToContain(
760
- rectangle: Rectangle &
761
- Readonly<{
762
- animationMode?: AnimationMode;
763
- }>
764
- ): void {
765
- this.mainView.moveCameraToContain(rectangle);
766
- this.appManager?.dispatchInternalEvent(Events.MoveCameraToContain, rectangle);
767
- setTimeout(() => {
768
- this.appManager?.mainViewProxy.setCameraAndSize();
769
- }, 500);
849
+ private onCameraUpdated = () => {
850
+ if (this.cameraUpdating) {
851
+ clearTimeout(this.cameraUpdating);
852
+ this.cameraUpdating = 0;
853
+ }
854
+ this.cameraUpdating = setTimeout(() => {
855
+ this.mainView.callbacks.off("onCameraUpdated", this.onCameraUpdated);
856
+ clearTimeout(this.cameraUpdating);
857
+ this.cameraUpdating = 0;
858
+ if (!this.appManager || !this.nextCamera) return;
859
+ this.appManager.mainViewProxy.storeCamera({
860
+ id: this.appManager.uid,
861
+ ...this.nextCamera
862
+ });
863
+ this.nextCamera = null;
864
+ }, 50);
770
865
  }
771
866
 
772
867
  public convertToPointInWorld(point: Point): Point {
@@ -835,6 +930,10 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
835
930
  this.appManager?.boxManager?.setPrefersColorScheme(scheme);
836
931
  }
837
932
 
933
+ public setFullscreen(fullscreen: TeleBoxFullscreen): void {
934
+ this.appManager?.boxManager?.teleBoxManager.setFullscreen(fullscreen);
935
+ }
936
+
838
937
  public cleanCurrentScene(): void {
839
938
  this.focusedView?.cleanCurrentScene();
840
939
  }
@@ -894,7 +993,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
894
993
  if (WindowManager.container) {
895
994
  this.bindContainer(WindowManager.container);
896
995
  }
897
- this.appManager?.refresher?.refresh();
996
+ this.appManager?.refresher.refresh();
898
997
  }
899
998
 
900
999
  public setContainerSizeRatio(ratio: number) {
@@ -906,6 +1005,44 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
906
1005
  emitter.emit("containerSizeRatioUpdate", ratio);
907
1006
  }
908
1007
 
1008
+ public setContainerStyle(style: string) {
1009
+ this.boxManager?.teleBoxManager.setContainerStyle(style);
1010
+ }
1011
+
1012
+ public setStageStyle(style: string) {
1013
+ this.boxManager?.teleBoxManager.setStageStyle(style);
1014
+ }
1015
+
1016
+ public setBaseSize(size: Size) {
1017
+ this.appManager?.mainViewProxy.setMainViewSize(size);
1018
+ setTimeout(() => {
1019
+ if (!this.appManager || !this.appManager.mainViewProxy.camera$.value) return;
1020
+ this.appManager.mainViewProxy.storeCamera({
1021
+ ...this.appManager.mainViewProxy.camera$.value,
1022
+ id: this.appManager.uid,
1023
+ scale: 1
1024
+ });
1025
+ }, 500);
1026
+ }
1027
+
1028
+ public createPPTHandler() {
1029
+ return {
1030
+ onPageJumpTo: (_pptUUID: string, index: number) => {
1031
+ this.appManager?.focusApp?.appContext?.whiteBoardView?.jumpPage(index);
1032
+ },
1033
+ onPageToNext: () => {
1034
+ if (this.focused) {
1035
+ this.appManager?.focusApp?.appContext?.whiteBoardView?.nextPage();
1036
+ }
1037
+ },
1038
+ onPageToPrev: () => {
1039
+ if (this.focused) {
1040
+ this.appManager?.focusApp?.appContext?.whiteBoardView?.prevPage();
1041
+ }
1042
+ }
1043
+ }
1044
+ }
1045
+
909
1046
  private isDynamicPPT(scenes: SceneDefinition[]) {
910
1047
  const sceneSrc = scenes[0]?.ppt?.src;
911
1048
  return sceneSrc?.startsWith("pptx://");
@@ -939,5 +1076,6 @@ setupBuiltin();
939
1076
 
940
1077
  export * from "./typings";
941
1078
 
942
- export { BuiltinApps } from "./BuiltinApps";
1079
+ export { BuiltinApps, BuiltinAppsMap } from "./BuiltinApps";
943
1080
  export type { PublicEvent } from "./callback";
1081
+ export type { Member } from "./Helper";
package/src/style.css CHANGED
@@ -7,48 +7,9 @@
7
7
  user-select: none;
8
8
  }
9
9
 
10
- .netless-window-manager-sizer {
11
- position: absolute;
12
- top: 0;
13
- left: 0;
14
- width: 100%;
15
- height: 100%;
16
- z-index: 1;
17
- overflow: hidden;
18
- display: flex;
19
- }
20
-
21
- .netless-window-manager-sizer-horizontal {
22
- flex-direction: column;
23
- }
24
-
25
- .netless-window-manager-sizer::before,
26
- .netless-window-manager-sizer::after {
27
- flex: 1;
28
- content: "";
29
- display: block;
30
- }
31
-
32
- .netless-window-manager-chess-sizer::before,
33
- .netless-window-manager-chess-sizer::after {
34
- background-image: linear-gradient(45deg, #b0b0b0 25%, transparent 25%),
35
- linear-gradient(-45deg, #b0b0b0 25%, transparent 25%),
36
- linear-gradient(45deg, transparent 75%, #b0b0b0 75%),
37
- linear-gradient(-45deg, transparent 75%, #b0b0b0 75%);
38
- background-color: #fff;
39
- background-size: 20px 20px;
40
- background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
41
- }
42
-
43
- .netless-window-manager-wrapper {
44
- position: relative;
45
- z-index: 1;
46
- width: 100%;
47
- height: 100%;
48
- overflow: hidden;
49
- }
50
10
 
51
11
  .netless-window-manager-main-view {
12
+ position: absolute;
52
13
  width: 100%;
53
14
  height: 100%;
54
15
  }
@@ -122,7 +83,7 @@
122
83
  left: 0;
123
84
  top: 0;
124
85
  will-change: transform;
125
- transition: transform 0.1s;
86
+ transition: transform 0.12s;
126
87
  transform-origin: 0 0;
127
88
  user-select: none;
128
89
  }
@@ -180,10 +141,6 @@
180
141
  }
181
142
 
182
143
  .window-manager-view-wrapper {
183
- z-index: 5000;
184
- width: 100%;
185
- height: 100%;
186
144
  position: absolute;
187
- left: 0;
188
- top: 0;
145
+ z-index: 10;
189
146
  }
package/src/typings.ts CHANGED
@@ -11,7 +11,7 @@ import type {
11
11
  View,
12
12
  } from "white-web-sdk";
13
13
  import type { AppContext } from "./App";
14
- import type { ReadonlyTeleBox, TeleBoxRect } from "@netless/telebox-insider";
14
+ import type { ReadonlyTeleBox, TeleBoxRect, TeleBoxFullscreen } from "@netless/telebox-insider";
15
15
  import type { PageState } from "./Page";
16
16
  import type { Member } from "./Helper";
17
17
 
@@ -30,6 +30,9 @@ export interface NetlessApp<Attributes = any, MagixEventPayloads = any, AppOptio
30
30
 
31
31
  /** App only single instance. */
32
32
  singleton?: boolean;
33
+
34
+ /** App box enableShadowDom. Default true */
35
+ enableShadowDOM?: boolean;
33
36
  };
34
37
  setup: (context: AppContext<Attributes, MagixEventPayloads, AppOptions>) => SetupResult;
35
38
  }
@@ -69,22 +72,30 @@ export type RegisterEvents<SetupResult = any> = {
69
72
 
70
73
  export type RegisterParams<AppOptions = any, SetupResult = any, Attributes = any> = {
71
74
  kind: string;
72
- src: NetlessApp<Attributes, SetupResult> | string | (() => Promise<NetlessApp<Attributes, SetupResult>>);
75
+ src:
76
+ | NetlessApp<Attributes, SetupResult>
77
+ | string
78
+ | (() => Promise<NetlessApp<Attributes, SetupResult>>)
79
+ | (() => Promise<{ default: NetlessApp<Attributes, SetupResult> }>);
73
80
  appOptions?: AppOptions | (() => AppOptions);
74
81
  addHooks?: (emitter: Emittery<RegisterEvents<SetupResult>>) => void;
75
82
  /** dynamic load app package name */
76
83
  name?: string;
84
+ contentStyles?: string;
77
85
  };
78
86
 
79
87
  export type AppListenerKeys = keyof AppEmitterEvent;
80
88
 
81
89
  export type ApplianceIcons = Partial<Record<ApplianceNames, string>>;
82
90
 
91
+ export type Writeable<T> = { -readonly [P in keyof T]: T[P] };
92
+
83
93
  export type { AppContext } from "./App/AppContext";
84
94
  export type { WhiteBoardView } from "./App";
85
- export type { ReadonlyTeleBox, TeleBoxRect };
95
+ export type { ReadonlyTeleBox, TeleBoxRect, TeleBoxFullscreen };
86
96
  export type { SceneState, SceneDefinition, View, AnimationMode, Displayer, Room, Player };
87
97
  export type { Storage, StorageStateChangedEvent, StorageStateChangedListener } from "./App/Storage";
88
98
  export * from "./Page";
89
99
  export * from "./Utils/error";
90
100
  export type { Member } from "./Helper";
101
+ export type { TeleBoxManager, TeleBoxManagerQueryConfig } from "@netless/telebox-insider";
package/vite.config.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import path from "path";
2
+ import dts from 'vite-plugin-dts'
2
3
  import { defineConfig } from 'vitest/config'
3
4
  import { svelte } from "@sveltejs/vite-plugin-svelte";
4
5
  import { dependencies, peerDependencies, version, devDependencies } from "./package.json"
5
6
  import { omit } from "lodash";
6
7
 
7
- export default defineConfig(({ mode }) => {
8
- const isProd = mode === "production";
8
+ export default defineConfig(() => {
9
+ // const isProd = mode === "production";
9
10
 
10
11
  return {
11
12
  test: {
@@ -14,7 +15,9 @@ export default defineConfig(({ mode }) => {
14
15
  inline: [
15
16
  "@juggle/resize-observer"
16
17
  ]
17
- }
18
+ },
19
+ setupFiles: "./test/setup.ts",
20
+ include: ["test/**/*.test.ts"],
18
21
  },
19
22
  define: {
20
23
  __APP_VERSION__: JSON.stringify(version),
@@ -28,7 +31,8 @@ export default defineConfig(({ mode }) => {
28
31
  experimental: {
29
32
  useVitePreprocess: true,
30
33
  },
31
- })
34
+ }),
35
+ dts()
32
36
  ],
33
37
  build: {
34
38
  lib: {
@@ -36,7 +40,8 @@ export default defineConfig(({ mode }) => {
36
40
  entry: path.resolve(__dirname, "src/index.ts"),
37
41
  formats: ["es", "umd", "cjs"],
38
42
  name: "WindowManager",
39
- fileName: "index"
43
+ fileName: "index",
44
+
40
45
  },
41
46
  outDir: "dist",
42
47
  rollupOptions: {
@@ -45,7 +50,7 @@ export default defineConfig(({ mode }) => {
45
50
  ...peerDependencies,
46
51
  }),
47
52
  },
48
- minify: isProd,
53
+ minify: false
49
54
  },
50
55
  };
51
- });
56
+ })