@netless/window-manager 1.0.0-canary.53 → 1.0.0-canary.54

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 (44) hide show
  1. package/dist/index.cjs.js +381 -444
  2. package/dist/index.es.js +427 -490
  3. package/dist/index.umd.js +381 -445
  4. package/dist/src/App/AppContext.d.ts +8 -8
  5. package/dist/src/AppManager.d.ts +5 -1
  6. package/dist/src/Cursor/index.d.ts +1 -0
  7. package/dist/src/Utils/Reactive.d.ts +1 -1
  8. package/dist/src/View/CameraSynchronizer.d.ts +3 -2
  9. package/dist/src/View/ScrollMode.d.ts +32 -0
  10. package/dist/src/View/ViewSync.d.ts +3 -2
  11. package/dist/src/callback.d.ts +3 -0
  12. package/dist/src/constants.d.ts +2 -0
  13. package/dist/src/index.d.ts +21 -11
  14. package/dist/src/storage.d.ts +7 -0
  15. package/dist/src/typings.d.ts +5 -4
  16. package/dist/style.css +2 -1
  17. package/docs/api.md +10 -0
  18. package/package.json +4 -3
  19. package/pnpm-lock.yaml +28 -73
  20. package/src/App/AppContext.ts +19 -8
  21. package/src/App/WhiteboardView.ts +4 -2
  22. package/src/AppListener.ts +1 -10
  23. package/src/AppManager.ts +19 -1
  24. package/src/Cursor/index.ts +6 -2
  25. package/src/Utils/Reactive.ts +2 -1
  26. package/src/View/CameraSynchronizer.ts +33 -22
  27. package/src/View/MainView.ts +1 -0
  28. package/src/View/ScrollMode.ts +229 -0
  29. package/src/View/ViewSync.ts +24 -16
  30. package/src/callback.ts +3 -0
  31. package/src/constants.ts +3 -0
  32. package/src/index.ts +56 -63
  33. package/src/storage.ts +15 -0
  34. package/src/style.css +1 -1
  35. package/src/typings.ts +6 -3
  36. package/vite.config.js +1 -1
  37. package/dist/src/App/Storage/StorageEvent.d.ts +0 -8
  38. package/dist/src/App/Storage/index.d.ts +0 -39
  39. package/dist/src/App/Storage/typings.d.ts +0 -22
  40. package/dist/src/App/Storage/utils.d.ts +0 -5
  41. package/src/App/Storage/StorageEvent.ts +0 -21
  42. package/src/App/Storage/index.ts +0 -295
  43. package/src/App/Storage/typings.ts +0 -23
  44. package/src/App/Storage/utils.ts +0 -17
package/src/index.ts CHANGED
@@ -9,8 +9,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 { AnimationMode, InvisiblePlugin, isPlayer, isRoom, RoomPhase, ViewMode } from "white-web-sdk";
13
- import { isEqual, isNull, isObject, isNumber } from "lodash";
12
+ import { InvisiblePlugin, isPlayer, isRoom, RoomPhase, ViewMode } from "white-web-sdk";
13
+ import { isEqual, isNull, isObject, isNumber, omit, debounce } from "lodash";
14
14
  import { log } from "./Utils/log";
15
15
  import { PageStateImpl } from "./PageState";
16
16
  import { ReconnectRefresher } from "./ReconnectRefresher";
@@ -44,22 +44,25 @@ import type {
44
44
  Player,
45
45
  ImageInformation,
46
46
  SceneState,
47
- Size
47
+ Size,
48
+ AnimationMode,
49
+ Rectangle,
48
50
  } from "white-web-sdk";
49
51
  import type { AppListeners } from "./AppListener";
50
- import type { ApplianceIcons, NetlessApp, RegisterParams } from "./typings";
52
+ import type { ApplianceIcons, ManagerViewMode, NetlessApp, RegisterParams } from "./typings";
51
53
  import type { TeleBoxColorScheme, TeleBoxFullscreen, TeleBoxManager, TeleBoxManagerThemeConfig, TeleBoxState } from "@netless/telebox-insider";
52
54
  import type { AppProxy } from "./App";
53
55
  import type { PublicEvent } from "./callback";
54
56
  import type Emittery from "emittery";
55
57
  import type { PageController, AddPageParams, PageState } from "./Page";
56
- import { computedMinScale } from "./View/CameraSynchronizer";
58
+ import type { ScrollState } from "./View/ScrollMode";
57
59
 
58
60
  export type WindowMangerAttributes = {
59
61
  modelValue?: string;
60
62
  boxState: TELE_BOX_STATE;
61
63
  maximized?: boolean;
62
64
  minimized?: boolean;
65
+ scrollTop?: number;
63
66
  [key: string]: any;
64
67
  };
65
68
 
@@ -154,11 +157,16 @@ export type MountParams = {
154
157
  defaultBoxStageStyle?: string | null;
155
158
  /** Theme variable */
156
159
  theme?: TeleBoxManagerThemeConfig;
160
+ /** ScrollMode BaseWidth */
161
+ scrollModeWidth?: number;
162
+ /** ScrollMode BaseHeight */
163
+ scrollModeHeight?: number;
164
+ viewMode?: ManagerViewMode;
157
165
  };
158
166
 
159
167
  export const reconnectRefresher = new ReconnectRefresher({ emitter });
160
168
 
161
- export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> implements PageController {
169
+ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes, any> implements PageController {
162
170
  public static kind = "WindowManager";
163
171
  public static displayer: Displayer;
164
172
  public static playground?: HTMLElement;
@@ -177,17 +185,15 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
177
185
  public emitter: Emittery<PublicEvent> = callbacks;
178
186
  public appManager?: AppManager;
179
187
  public cursorManager?: CursorManager;
180
- public viewMode = ViewMode.Broadcaster;
181
- public viewMode$ = new Val<ViewMode>(ViewMode.Broadcaster);
188
+ public viewMode: ManagerViewMode = ViewMode.Broadcaster;
189
+ public viewMode$ = new Val<ManagerViewMode>(ViewMode.Broadcaster);
190
+ public playground$ = new Val<HTMLElement | undefined>(undefined);
182
191
  public isReplay = isPlayer(this.displayer);
183
192
  private _pageState?: PageStateImpl;
184
193
 
185
194
  private boxManager?: BoxManager;
186
195
  private static params?: MountParams;
187
196
 
188
- private cameraUpdating = 0;
189
- private nextCamera: Camera | null = null;
190
-
191
197
  public containerSizeRatio = WindowManager.containerSizeRatio;
192
198
 
193
199
  constructor(context: InvisiblePluginContext) {
@@ -249,7 +255,9 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
249
255
  }
250
256
  manager.containerSizeRatio = WindowManager.containerSizeRatio;
251
257
  await manager.ensureAttributes();
252
-
258
+ if (params.viewMode) {
259
+ manager.viewMode$.setValue(params.viewMode);
260
+ }
253
261
  manager.appManager = new AppManager(manager);
254
262
  manager._pageState = new PageStateImpl(manager.appManager);
255
263
  manager.cursorManager = new CursorManager(manager.appManager, Boolean(cursor), params.applianceIcons);
@@ -269,6 +277,10 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
269
277
  manager.bindContainer(params.container);
270
278
  }
271
279
 
280
+ if (params.scrollModeWidth && params.scrollModeHeight) {
281
+ manager.appManager.scrollBaseSize$.setValue({ width: params.scrollModeWidth, height: params.scrollModeHeight });
282
+ }
283
+
272
284
  replaceRoomFunction(room, manager);
273
285
  emitter.emit("onCreated");
274
286
  WindowManager.isCreated = true;
@@ -348,6 +360,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
348
360
  this.bindMainView(mainViewElement, params.disableCameraTransform);
349
361
  if (WindowManager.playground) {
350
362
  this.cursorManager?.setupWrapper(WindowManager.playground);
363
+ this.playground$.setValue(WindowManager.playground);
351
364
  }
352
365
 
353
366
  }
@@ -373,7 +386,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
373
386
  /**
374
387
  * 注册插件
375
388
  */
376
- public static register<AppOptions = any, SetupResult = any, Attributes = any>(
389
+ public static register<AppOptions = any, SetupResult = any, Attributes extends Record<string, any> = any>(
377
390
  params: RegisterParams<AppOptions, SetupResult, Attributes>
378
391
  ): Promise<void> {
379
392
  return appRegister.register(params);
@@ -612,16 +625,17 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
612
625
  /**
613
626
  * 设置 ViewMode
614
627
  */
615
- public setViewMode(mode: ViewMode): void {
628
+ public setViewMode(mode: ManagerViewMode): void {
616
629
  log("setViewMode", mode);
617
630
  const mainViewProxy = this.appManager?.mainViewProxy;
618
631
  if (mode === ViewMode.Broadcaster) {
619
632
  if (this.canOperate) {
620
633
  mainViewProxy?.storeCurrentCamera();
634
+ mainViewProxy?.storeCurrentSize();
621
635
  }
622
636
  mainViewProxy?.start();
623
637
  }
624
- if (mode === ViewMode.Freedom) {
638
+ if (mode === ViewMode.Freedom || mode === "scroll") {
625
639
  mainViewProxy?.stop();
626
640
  }
627
641
  this.viewMode = mode;
@@ -782,6 +796,10 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
782
796
  }
783
797
  }
784
798
 
799
+ public get scrollState(): ScrollState | undefined {
800
+ return this.appManager?.scrollMode?.scrollState$.value;
801
+ }
802
+
785
803
  public get teleboxManager(): TeleBoxManager {
786
804
  if (!this.boxManager) {
787
805
  throw new Errors.BoxManagerNotInitializeError();
@@ -811,57 +829,32 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
811
829
  }
812
830
 
813
831
  public moveCamera = (camera: Partial<Camera> & { animationMode?: AnimationMode } ): void => {
832
+ const pureCamera = omit(camera, ["animationMode"]);
814
833
  const mainViewCamera = { ...this.mainView.camera };
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
- }
834
+ if (isEqual({ ...mainViewCamera, ...pureCamera }, mainViewCamera)) return;
835
+ this.debouncedStoreCamera();
836
+ this.mainView.moveCamera(camera);
837
+ this.appManager?.dispatchInternalEvent(Events.MoveCamera, camera);
847
838
  };
848
839
 
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);
840
+ public moveCameraToContain(
841
+ rectangle: Rectangle &
842
+ Readonly<{
843
+ animationMode?: AnimationMode;
844
+ }>
845
+ ): void {
846
+ this.debouncedStoreCamera();
847
+ this.mainView.moveCameraToContain(rectangle);
848
+ this.appManager?.dispatchInternalEvent(Events.MoveCameraToContain, rectangle);
849
+ }
850
+
851
+ private debouncedStoreCamera = () => {
852
+ const storeCamera = debounce(() => {
853
+ this.appManager?.mainViewProxy.storeCurrentCamera();
854
+ this.appManager?.mainViewProxy.storeCurrentSize();
855
+ this.mainView.callbacks.off("onCameraUpdated", storeCamera);
856
+ }, 200);
857
+ this.mainView.callbacks.on("onCameraUpdated", storeCamera);
865
858
  }
866
859
 
867
860
  public convertToPointInWorld(point: Point): Point {
package/src/storage.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { Storage } from "@netless/synced-store";
2
+ import { Val } from "value-enhancer";
3
+ import type { AppManager } from "./AppManager";
4
+
5
+ export type ScrollStorageState = { scrollTop: number }
6
+ export type ScrollStorage = Storage<ScrollStorageState>;
7
+
8
+ export const createScrollStorage = (manager: AppManager) => {
9
+ return new Storage<ScrollStorageState>({
10
+ plugin$: new Val(manager.windowManger),
11
+ isWritable$: manager.isWritable$,
12
+ namespace: "scrollStorage",
13
+ defaultState: { scrollTop: 0 }
14
+ });
15
+ };
package/src/style.css CHANGED
@@ -143,4 +143,4 @@
143
143
  .window-manager-view-wrapper {
144
144
  position: absolute;
145
145
  z-index: 10;
146
- }
146
+ }
package/src/typings.ts CHANGED
@@ -9,13 +9,14 @@ import type {
9
9
  SceneDefinition,
10
10
  SceneState,
11
11
  View,
12
+ ViewMode,
12
13
  } from "white-web-sdk";
13
14
  import type { AppContext } from "./App";
14
15
  import type { ReadonlyTeleBox, TeleBoxRect, TeleBoxFullscreen } from "@netless/telebox-insider";
15
16
  import type { PageState } from "./Page";
16
17
  import type { Member } from "./Helper";
17
18
 
18
- export interface NetlessApp<Attributes = any, MagixEventPayloads = any, AppOptions = any, SetupResult = any> {
19
+ export interface NetlessApp<Attributes extends Record<string, any> = any, MagixEventPayloads = any, AppOptions = any, SetupResult = any> {
19
20
  kind: string;
20
21
  config?: {
21
22
  /** Box width relative to whiteboard. 0~1. Default 0.5. */
@@ -70,7 +71,7 @@ export type RegisterEvents<SetupResult = any> = {
70
71
  focus: RegisterEventData;
71
72
  };
72
73
 
73
- export type RegisterParams<AppOptions = any, SetupResult = any, Attributes = any> = {
74
+ export type RegisterParams<AppOptions = any, SetupResult = any, Attributes extends Record<string, any> = any> = {
74
75
  kind: string;
75
76
  src:
76
77
  | NetlessApp<Attributes, SetupResult>
@@ -90,12 +91,14 @@ export type ApplianceIcons = Partial<Record<ApplianceNames, string>>;
90
91
 
91
92
  export type Writeable<T> = { -readonly [P in keyof T]: T[P] };
92
93
 
94
+ export type ManagerViewMode = `${ViewMode}` | "scroll";
95
+
93
96
  export type { AppContext } from "./App/AppContext";
94
97
  export type { WhiteBoardView } from "./App";
95
98
  export type { ReadonlyTeleBox, TeleBoxRect, TeleBoxFullscreen };
96
99
  export type { SceneState, SceneDefinition, View, AnimationMode, Displayer, Room, Player };
97
- export type { Storage, StorageStateChangedEvent, StorageStateChangedListener } from "./App/Storage";
98
100
  export * from "./Page";
99
101
  export * from "./Utils/error";
100
102
  export type { Member } from "./Helper";
101
103
  export type { TeleBoxManager, TeleBoxManagerQueryConfig } from "@netless/telebox-insider";
104
+ export type { Storage, StorageConfig } from "@netless/synced-store";
package/vite.config.js CHANGED
@@ -32,7 +32,7 @@ export default defineConfig(() => {
32
32
  useVitePreprocess: true,
33
33
  },
34
34
  }),
35
- dts()
35
+ dts(),
36
36
  ],
37
37
  build: {
38
38
  lib: {
@@ -1,8 +0,0 @@
1
- export declare type StorageEventListener<T> = (event: T) => void;
2
- export declare class StorageEvent<TMessage> {
3
- listeners: Set<StorageEventListener<TMessage>>;
4
- get length(): number;
5
- dispatch(message: TMessage): void;
6
- addListener(listener: StorageEventListener<TMessage>): void;
7
- removeListener(listener: StorageEventListener<TMessage>): void;
8
- }
@@ -1,39 +0,0 @@
1
- import type { AppContext } from "../AppContext";
2
- import type { Diff, StorageStateChangedListener, StorageStateChangedListenerDisposer } from "./typings";
3
- import { StorageEvent } from "./StorageEvent";
4
- export * from './typings';
5
- export declare const STORAGE_NS = "_WM-STORAGE_";
6
- export declare class Storage<TState extends Record<string, any> = any> implements Storage<TState> {
7
- readonly id: string | null;
8
- private readonly _context;
9
- private readonly _sideEffect;
10
- private _state;
11
- private _destroyed;
12
- private _refMap;
13
- /**
14
- * `setState` alters local state immediately before sending to server. This will cache the old value for onStateChanged diffing.
15
- */
16
- private _lastValue;
17
- constructor(context: AppContext, id?: string, defaultState?: TState);
18
- get state(): Readonly<TState>;
19
- readonly onStateChanged: StorageEvent<Diff<TState>>;
20
- addStateChangedListener(handler: StorageStateChangedListener<TState>): StorageStateChangedListenerDisposer;
21
- ensureState(state: Partial<TState>): void;
22
- setState(state: Partial<TState>): void;
23
- /**
24
- * Empty storage data.
25
- */
26
- emptyStorage(): void;
27
- /**
28
- * Delete storage index with all of its data and destroy the Storage instance.
29
- */
30
- deleteStorage(): void;
31
- get destroyed(): boolean;
32
- /**
33
- * Destroy the Storage instance. The data will be kept.
34
- */
35
- destroy(): void;
36
- private _getRawState;
37
- private _setRawState;
38
- private _updateProperties;
39
- }
@@ -1,22 +0,0 @@
1
- import type { StorageEventListener } from "./StorageEvent";
2
- export declare type RefValue<TValue = any> = {
3
- k: string;
4
- v: TValue;
5
- __isRef: true;
6
- };
7
- export declare type ExtractRawValue<TValue> = TValue extends RefValue<infer TRefValue> ? TRefValue : TValue;
8
- export declare type AutoRefValue<TValue> = RefValue<ExtractRawValue<TValue>>;
9
- export declare type MaybeRefValue<TValue> = TValue | AutoRefValue<TValue>;
10
- export declare type DiffOne<T> = {
11
- oldValue?: T;
12
- newValue?: T;
13
- };
14
- export declare type Diff<T> = {
15
- [K in keyof T]?: DiffOne<T[K]>;
16
- };
17
- export declare type StorageOnSetStatePayload<TState = unknown> = {
18
- [K in keyof TState]?: MaybeRefValue<TState[K]>;
19
- };
20
- export declare type StorageStateChangedEvent<TState = any> = Diff<TState>;
21
- export declare type StorageStateChangedListener<TState = any> = StorageEventListener<StorageStateChangedEvent<TState>>;
22
- export declare type StorageStateChangedListenerDisposer = () => void;
@@ -1,5 +0,0 @@
1
- import type { AutoRefValue, RefValue } from "./typings";
2
- export declare const plainObjectKeys: <T>(o: T) => Extract<keyof T, string>[];
3
- export declare function isRef<TValue = unknown>(e: unknown): e is RefValue<TValue>;
4
- export declare function makeRef<TValue>(v: TValue): RefValue<TValue>;
5
- export declare function makeAutoRef<TValue>(v: TValue): AutoRefValue<TValue>;
@@ -1,21 +0,0 @@
1
- export type StorageEventListener<T> = (event: T) => void;
2
-
3
- export class StorageEvent<TMessage> {
4
- listeners = new Set<StorageEventListener<TMessage>>();
5
-
6
- get length(): number {
7
- return this.listeners.size;
8
- }
9
-
10
- dispatch(message: TMessage): void {
11
- this.listeners.forEach(callback => callback(message));
12
- }
13
-
14
- addListener(listener: StorageEventListener<TMessage>): void {
15
- this.listeners.add(listener);
16
- }
17
-
18
- removeListener(listener: StorageEventListener<TMessage>): void {
19
- this.listeners.delete(listener);
20
- }
21
- }