@netless/window-manager 1.0.0-canary.0 → 1.0.0-canary.11

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 (49) hide show
  1. package/__mocks__/white-web-sdk.ts +10 -1
  2. package/dist/App/AppContext.d.ts +16 -15
  3. package/dist/App/AppPageStateImpl.d.ts +6 -2
  4. package/dist/App/AppProxy.d.ts +26 -4
  5. package/dist/App/AppViewSync.d.ts +11 -0
  6. package/dist/App/WhiteboardView.d.ts +24 -0
  7. package/dist/App/index.d.ts +1 -0
  8. package/dist/AppManager.d.ts +5 -3
  9. package/dist/AttributesDelegate.d.ts +6 -14
  10. package/dist/BoxManager.d.ts +4 -3
  11. package/dist/Helper.d.ts +12 -2
  12. package/dist/InternalEmitter.d.ts +4 -0
  13. package/dist/Page/PageController.d.ts +1 -0
  14. package/dist/ReconnectRefresher.d.ts +1 -1
  15. package/dist/Utils/Common.d.ts +1 -0
  16. package/dist/View/CameraSynchronizer.d.ts +7 -7
  17. package/dist/View/MainView.d.ts +0 -1
  18. package/dist/constants.d.ts +1 -0
  19. package/dist/index.cjs.js +12 -12
  20. package/dist/index.d.ts +6 -3
  21. package/dist/index.es.js +722 -652
  22. package/dist/index.umd.js +12 -12
  23. package/dist/style.css +1 -1
  24. package/dist/typings.d.ts +4 -0
  25. package/docs/app-context.md +98 -64
  26. package/docs/develop-app.md +2 -5
  27. package/package.json +3 -2
  28. package/pnpm-lock.yaml +11 -5
  29. package/src/App/AppContext.ts +71 -74
  30. package/src/App/AppPageStateImpl.ts +25 -6
  31. package/src/App/AppProxy.ts +206 -26
  32. package/src/App/AppViewSync.ts +73 -0
  33. package/src/App/Storage/index.ts +4 -4
  34. package/src/App/WhiteboardView.ts +89 -0
  35. package/src/App/index.ts +1 -0
  36. package/src/AppManager.ts +32 -23
  37. package/src/AttributesDelegate.ts +14 -17
  38. package/src/BoxManager.ts +14 -9
  39. package/src/Helper.ts +10 -1
  40. package/src/InternalEmitter.ts +4 -0
  41. package/src/Page/PageController.ts +1 -0
  42. package/src/ReconnectRefresher.ts +1 -0
  43. package/src/Utils/Common.ts +6 -0
  44. package/src/View/CameraSynchronizer.ts +32 -27
  45. package/src/View/MainView.ts +24 -41
  46. package/src/constants.ts +2 -0
  47. package/src/index.ts +20 -5
  48. package/src/style.css +9 -0
  49. package/src/typings.ts +4 -0
@@ -1,32 +1,32 @@
1
1
  import { AnimationMode } from "white-web-sdk";
2
- import { delay, throttle } from "lodash";
2
+ import { debounce, delay, throttle } from "lodash";
3
3
  import type { TeleBoxRect } from "@netless/telebox-insider";
4
- import type { Camera, View, Size } from "white-web-sdk";
5
- import type { MainViewSize } from "../AttributesDelegate";
4
+ import type { Camera, View } from "white-web-sdk";
5
+ import type { ISize } from "../AttributesDelegate";
6
6
 
7
7
  export type SaveCamera = (camera: Camera) => void;
8
8
 
9
9
  export class CameraSynchronizer {
10
- protected remoteCamera?: Camera;
11
- protected remoteSize?: MainViewSize;
10
+ public remoteCamera?: Camera;
11
+ public remoteSize?: ISize;
12
12
  protected rect?: TeleBoxRect;
13
13
  protected view?: View;
14
14
 
15
15
  constructor(protected saveCamera: SaveCamera) {}
16
16
 
17
- public setRect(rect: TeleBoxRect) {
17
+ public setRect = debounce((rect: TeleBoxRect) => {
18
18
  this.rect = rect;
19
19
  if (this.remoteCamera && this.remoteSize) {
20
20
  this.onRemoteUpdate(this.remoteCamera, this.remoteSize);
21
21
  }
22
- }
22
+ }, 50);
23
23
 
24
24
  public setView(view: View) {
25
25
  this.view = view;
26
26
  }
27
27
 
28
28
  // 远端 Camera 或者 size 更新
29
- public onRemoteUpdate = throttle((camera: Camera, size: MainViewSize) => {
29
+ public onRemoteUpdate = throttle((camera: Camera, size: ISize) => {
30
30
  this.remoteCamera = camera;
31
31
  this.remoteSize = size;
32
32
  if (this.remoteSize && this.rect) {
@@ -37,31 +37,36 @@ export class CameraSynchronizer {
37
37
  scale = this.rect.height / size.height;
38
38
  }
39
39
  const nextScale = camera.scale * scale;
40
- const moveCamera = () => this.view?.moveCamera({
41
- centerX: camera.centerX,
42
- centerY: camera.centerY,
43
- scale: nextScale,
44
- animationMode: AnimationMode.Immediately,
45
- });
40
+
41
+ const moveCamera = () => {
42
+ this.view?.moveCamera({
43
+ centerX: camera.centerX,
44
+ centerY: camera.centerY,
45
+ scale: nextScale,
46
+ animationMode: AnimationMode.Immediately,
47
+ });
48
+ }
46
49
  // TODO 直接调用 moveCamera 依然会出现 camera 错误的情况,这里暂时加一个 delay 保证 camera 是对的, 后续需要 SDK 进行修改
47
- delay(moveCamera, 10);
50
+ delay(moveCamera, 50);
48
51
  }
49
52
  }, 50);
50
53
 
54
+ public onRemoteSizeUpdate(size: ISize) {
55
+ if (this.rect) {
56
+ const nextScale = this.rect.width / size.width;
57
+ const moveCamera = () => {
58
+ this.view?.moveCamera({
59
+ scale: nextScale,
60
+ animationMode: AnimationMode.Immediately,
61
+ })
62
+ };
63
+ delay(moveCamera, 50);
64
+ }
65
+ }
66
+
51
67
 
52
68
  public onLocalCameraUpdate(camera: Camera) {
53
69
  this.saveCamera(camera);
54
- }
55
-
56
- // 本地 Size 更新, 先匹配 camera 到新的 size 然后再发送 camera 数据到远端
57
- public onLocalSizeUpdate(size: Size) {
58
- if (this.rect && this.view) {
59
- const scale = this.rect.width / size.width;
60
- const nextScale = this.view.camera.scale * scale;
61
- this.view.moveCamera({
62
- scale: nextScale,
63
- animationMode: AnimationMode.Immediately
64
- });
65
- }
70
+ this.remoteCamera = camera;
66
71
  }
67
72
  }
@@ -1,15 +1,15 @@
1
- import { reaction } from "white-web-sdk";
2
1
  import { callbacks } from "../callback";
2
+ import { CameraSynchronizer } from "./CameraSynchronizer";
3
3
  import { createView } from "./ViewManager";
4
4
  import { debounce, get, isEqual } from "lodash";
5
5
  import { emitter } from "../InternalEmitter";
6
6
  import { Events } from "../constants";
7
7
  import { Fields } from "../AttributesDelegate";
8
- import { setViewFocusScenePath } from "../Utils/Common";
8
+ import { reaction } from "white-web-sdk";
9
+ import { releaseView, setViewFocusScenePath } from "../Utils/Common";
9
10
  import { SideEffectManager } from "side-effect-manager";
10
11
  import type { Camera, Size, View } from "white-web-sdk";
11
12
  import type { AppManager } from "../AppManager";
12
- import { CameraSynchronizer } from "./CameraSynchronizer";
13
13
 
14
14
  export class MainViewProxy {
15
15
  private started = false;
@@ -21,8 +21,8 @@ export class MainViewProxy {
21
21
  private sideEffectManager = new SideEffectManager();
22
22
 
23
23
  constructor(private manager: AppManager) {
24
- this.synchronizer = new CameraSynchronizer(
25
- camera => this.store.setMainViewCamera({ ...camera, id: this.manager.uid })
24
+ this.synchronizer = new CameraSynchronizer(camera =>
25
+ this.store.setMainViewCamera({ ...camera, id: this.manager.uid })
26
26
  );
27
27
  this.mainView = this.createMainView();
28
28
  this.moveCameraSizeByAttributes();
@@ -32,36 +32,29 @@ export class MainViewProxy {
32
32
  this.ensureCameraAndSize();
33
33
  this.startListenWritableChange();
34
34
  });
35
- this.sideEffectManager.add(() => {
36
- return emitter.on("containerSizeRatioUpdate", this.onUpdateContainerSizeRatio);
37
- });
38
- this.sideEffectManager.add(() => {
39
- return emitter.on("startReconnect", () => {
40
- if (!(this.mainView as any).didRelease) {
41
- this.mainView.release();
42
- }
43
- });
44
- });
45
- const rect = this.manager.boxManager?.teleBoxManager.stageRect;
35
+ this.sideEffectManager.add(() => [
36
+ emitter.on("containerSizeRatioUpdate", this.onUpdateContainerSizeRatio),
37
+ emitter.on("startReconnect", () => {
38
+ releaseView(this.mainView);
39
+ }),
40
+ emitter.on("playgroundSizeChange", rect => {
41
+ this.synchronizer.setRect(rect);
42
+ })
43
+ ]);
44
+ const rect = this.manager.boxManager?.stageRect;
46
45
  if (rect) {
47
46
  this.synchronizer.setRect(rect);
48
47
  }
49
- this.sideEffectManager.add(() => {
50
- return emitter.on("playgroundSizeChange", rect => {
51
- this.synchronizer.setRect(rect);
52
- this.synchronizer.onLocalSizeUpdate(rect);
53
- });
54
- });
55
48
  }
56
49
 
57
50
  private startListenWritableChange = () => {
58
- this.sideEffectManager.add(() => {
59
- return emitter.on("writableChange", isWritable => {
51
+ this.sideEffectManager.add(() =>
52
+ emitter.on("writableChange", isWritable => {
60
53
  if (isWritable) {
61
54
  this.ensureCameraAndSize();
62
55
  }
63
- });
64
- });
56
+ })
57
+ );
65
58
  };
66
59
 
67
60
  public ensureCameraAndSize() {
@@ -89,14 +82,13 @@ export class MainViewProxy {
89
82
 
90
83
  public start() {
91
84
  if (this.started) return;
92
- this.sizeChangeHandler(this.mainViewSize);
93
85
  this.addCameraListener();
94
86
  this.addCameraReaction();
95
87
  this.started = true;
96
88
  }
97
89
 
98
90
  public addCameraReaction = () => {
99
- this.manager.refresher?.add(Fields.MainViewCamera, this.cameraReaction);
91
+ this.manager.refresher.add(Fields.MainViewCamera, this.cameraReaction);
100
92
  };
101
93
 
102
94
  public setCameraAndSize(): void {
@@ -120,15 +112,8 @@ export class MainViewProxy {
120
112
  );
121
113
  };
122
114
 
123
- public sizeChangeHandler = debounce((size: Size) => {
124
- if (size) {
125
- this.synchronizer.onLocalSizeUpdate(size);
126
- }
127
- }, 30);
128
-
129
115
  public onUpdateContainerSizeRatio = () => {
130
116
  const size = this.store.getMainViewSize();
131
- this.sizeChangeHandler(size);
132
117
  if (size.id === this.manager.uid) {
133
118
  this.setCameraAndSize();
134
119
  }
@@ -171,9 +156,7 @@ export class MainViewProxy {
171
156
  const divElement = this.mainView.divElement;
172
157
  const disableCameraTransform = this.mainView.disableCameraTransform;
173
158
  this.stop();
174
- if (!this.didRelease) {
175
- this.mainView.release();
176
- }
159
+ releaseView(this.mainView);
177
160
  this.removeMainViewListener();
178
161
  this.mainView = this.createMainView();
179
162
  this.mainView.disableCameraTransform = disableCameraTransform;
@@ -191,7 +174,7 @@ export class MainViewProxy {
191
174
  };
192
175
 
193
176
  private getStageSize(): Size | undefined {
194
- const stage = this.manager.boxManager?.teleBoxManager.stageRect;
177
+ const stage = this.manager.boxManager?.stageRect;
195
178
  if (stage) {
196
179
  return { width: stage.width, height: stage.height };
197
180
  }
@@ -246,8 +229,8 @@ export class MainViewProxy {
246
229
 
247
230
  public stop() {
248
231
  this.removeCameraListener();
249
- this.manager.refresher?.remove(Fields.MainViewCamera);
250
- this.manager.refresher?.remove(Fields.MainViewSize);
232
+ this.manager.refresher.remove(Fields.MainViewCamera);
233
+ this.manager.refresher.remove(Fields.MainViewSize);
251
234
  this.started = false;
252
235
  }
253
236
 
package/src/constants.ts CHANGED
@@ -57,3 +57,5 @@ export const ROOT_DIR = "/";
57
57
  export const INIT_DIR = "/init";
58
58
 
59
59
  export const SETUP_APP_DELAY = 50;
60
+
61
+ export const MAX_PAGE_SIZE = 500;
package/src/index.ts CHANGED
@@ -29,7 +29,7 @@ import {
29
29
  } from "./Utils/Common";
30
30
  import type { TELE_BOX_STATE, BoxManager } from "./BoxManager";
31
31
  import * as Errors from "./Utils/error";
32
- import type { Apps, Position } from "./AttributesDelegate";
32
+ import type { Apps, Position , ICamera, ISize } from "./AttributesDelegate";
33
33
  import type {
34
34
  Displayer,
35
35
  SceneDefinition,
@@ -104,6 +104,8 @@ export type AppSyncAttributes = {
104
104
  isDynamicPPT?: boolean;
105
105
  fullPath?: string;
106
106
  createdAt?: number;
107
+ camera?: ICamera;
108
+ size?: ISize;
107
109
  };
108
110
 
109
111
  export type AppInitState = {
@@ -127,8 +129,8 @@ export type MountParams = {
127
129
  container?: HTMLElement;
128
130
  /** 白板高宽比例, 默认为 9 / 16 */
129
131
  containerSizeRatio?: number;
130
- /** 显示 PS 透明背景,默认 true */
131
- chessboard?: boolean;
132
+ /** 是否高亮显示同步区域, 默认为 true */
133
+ highlightStage?: boolean;
132
134
  collectorContainer?: HTMLElement;
133
135
  collectorStyles?: Partial<CSSStyleDeclaration>;
134
136
  overwriteStyles?: string;
@@ -238,7 +240,8 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
238
240
  collectorContainer: params.collectorContainer,
239
241
  collectorStyles: params.collectorStyles,
240
242
  prefersColorScheme: params.prefersColorScheme,
241
- stageRatio: params.containerSizeRatio,
243
+ stageRatio: containerSizeRatio,
244
+ highlightStage: params.highlightStage
242
245
  });
243
246
  manager.appManager?.setBoxManager(manager.boxManager);
244
247
  if (params.container) {
@@ -340,7 +343,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
340
343
 
341
344
  public bindCollectorContainer(container: HTMLElement) {
342
345
  if (WindowManager.isCreated && this.boxManager) {
343
- this.boxManager.teleBoxManager.collector.set$collector(container)
346
+ this.boxManager.setCollector(container);
344
347
  } else {
345
348
  if (WindowManager.params) {
346
349
  WindowManager.params.collectorContainer = container;
@@ -502,6 +505,18 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
502
505
  }
503
506
  }
504
507
 
508
+ public async jumpPage(index: number): Promise<boolean> {
509
+ if (!this.appManager) {
510
+ return false;
511
+ }
512
+ if (index < 0 || index >= this.pageState.length) {
513
+ console.warn(`[WindowManager]: index ${index} out of range`);
514
+ return false;
515
+ }
516
+ await this.appManager.setMainViewSceneIndex(index);
517
+ return true;
518
+ }
519
+
505
520
  public async addPage(params?: AddPageParams): Promise<void> {
506
521
  if (this.appManager) {
507
522
  const after = params?.after;
package/src/style.css CHANGED
@@ -178,3 +178,12 @@
178
178
  right: 10px;
179
179
  bottom: 15px;
180
180
  }
181
+
182
+ .window-manager-view-wrapper {
183
+ z-index: 5000;
184
+ width: 100%;
185
+ height: 100%;
186
+ position: absolute;
187
+ left: 0;
188
+ top: 0;
189
+ }
package/src/typings.ts CHANGED
@@ -13,6 +13,7 @@ import type {
13
13
  import type { AppContext } from "./App";
14
14
  import type { ReadonlyTeleBox, TeleBoxRect } from "@netless/telebox-insider";
15
15
  import type { PageState } from "./Page";
16
+ import type { Member } from "./Helper";
16
17
 
17
18
  export interface NetlessApp<Attributes = any, MagixEventPayloads = any, AppOptions = any, SetupResult = any> {
18
19
  kind: string;
@@ -53,6 +54,7 @@ export type AppEmitterEvent<T = any> = {
53
54
  reconnected: void;
54
55
  seek: number;
55
56
  pageStateChange: PageState,
57
+ roomMembersChange: Member[];
56
58
  };
57
59
 
58
60
  export type RegisterEventData = {
@@ -79,8 +81,10 @@ export type AppListenerKeys = keyof AppEmitterEvent;
79
81
  export type ApplianceIcons = Partial<Record<ApplianceNames, string>>;
80
82
 
81
83
  export type { AppContext } from "./App/AppContext";
84
+ export type { WhiteBoardView } from "./App";
82
85
  export type { ReadonlyTeleBox, TeleBoxRect };
83
86
  export type { SceneState, SceneDefinition, View, AnimationMode, Displayer, Room, Player };
84
87
  export type { Storage, StorageStateChangedEvent, StorageStateChangedListener } from "./App/Storage";
85
88
  export * from "./Page";
86
89
  export * from "./Utils/error";
90
+ export type { Member } from "./Helper";