@netless/window-manager 1.0.0-canary.52 → 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 +389 -445
  2. package/dist/index.es.js +434 -490
  3. package/dist/index.umd.js +389 -446
  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 +4 -3
  9. package/dist/src/View/ScrollMode.d.ts +32 -0
  10. package/dist/src/View/ViewSync.d.ts +4 -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 +35 -23
  27. package/src/View/MainView.ts +1 -0
  28. package/src/View/ScrollMode.ts +229 -0
  29. package/src/View/ViewSync.ts +31 -18
  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/dist/index.cjs.js CHANGED
@@ -36,8 +36,9 @@ var Emittery = require("emittery");
36
36
  var lodash = require("lodash");
37
37
  var whiteWebSdk = require("white-web-sdk");
38
38
  var uuid = require("uuid");
39
- var sideEffectManager = require("side-effect-manager");
39
+ var syncedStore = require("@netless/synced-store");
40
40
  var valueEnhancer = require("value-enhancer");
41
+ var sideEffectManager = require("side-effect-manager");
41
42
  var resizeObserver = require("@juggle/resize-observer");
42
43
  function _interopDefaultLegacy(e) {
43
44
  return e && typeof e === "object" && "default" in e ? e : { "default": e };
@@ -102,6 +103,8 @@ const ROOT_DIR = "/";
102
103
  const INIT_DIR = "/init";
103
104
  const SETUP_APP_DELAY = 50;
104
105
  const MAX_PAGE_SIZE = 500;
106
+ const SCROLL_MODE_BASE_WIDTH = 1600;
107
+ const SCROLL_MODE_BASE_HEIGHT = SCROLL_MODE_BASE_WIDTH * 3;
105
108
  const callbacks = new Emittery__default["default"]();
106
109
  class AppCreateQueue {
107
110
  constructor() {
@@ -522,66 +525,6 @@ const isRootDirPage = (scenePath) => {
522
525
  }, 0);
523
526
  return delimiterCount === 1;
524
527
  };
525
- class CameraSynchronizer {
526
- constructor(saveCamera) {
527
- this.saveCamera = saveCamera;
528
- this.setRect = (rect) => {
529
- this.rect = rect;
530
- if (this.remoteCamera && this.remoteSize) {
531
- this.onRemoteUpdate(this.remoteCamera, this.remoteSize);
532
- }
533
- };
534
- this.onRemoteUpdate = lodash.throttle((camera, size) => {
535
- this.remoteCamera = camera;
536
- this.remoteSize = size;
537
- if (this.remoteSize && this.rect) {
538
- const nextScale = camera.scale * computedMinScale(size, this.rect);
539
- const config = {
540
- scale: nextScale
541
- };
542
- if (camera.centerX !== null) {
543
- config.centerX = camera.centerX;
544
- }
545
- if (camera.centerY !== null) {
546
- config.centerY = camera.centerY;
547
- }
548
- this.moveCamera(config);
549
- }
550
- }, 10);
551
- }
552
- setView(view) {
553
- this.view = view;
554
- }
555
- onRemoteSizeUpdate(size) {
556
- var _a;
557
- this.remoteSize = size;
558
- const needMoveCamera = !lodash.isEqual(lodash.pick(this.rect, ["width", "height"]), lodash.pick(size, ["width", "height"]));
559
- if (this.rect && this.remoteCamera && needMoveCamera) {
560
- if (!this.view)
561
- return;
562
- const currentCamera = this.view.camera;
563
- (_a = this.view) == null ? void 0 : _a.moveCameraToContain({
564
- width: size.width,
565
- height: size.height,
566
- originX: currentCamera.centerX - size.width / 2,
567
- originY: currentCamera.centerY - size.height / 2
568
- });
569
- }
570
- }
571
- onLocalCameraUpdate(camera) {
572
- this.saveCamera(camera);
573
- this.remoteCamera = camera;
574
- }
575
- moveCamera(camera) {
576
- var _a;
577
- (_a = this.view) == null ? void 0 : _a.moveCamera(__spreadProps(__spreadValues({}, camera), { animationMode: whiteWebSdk.AnimationMode.Immediately }));
578
- }
579
- }
580
- const computedMinScale = (remoteSize, currentSize) => {
581
- const wScale = currentSize.width / remoteSize.width;
582
- const hScale = currentSize.height / remoteSize.height;
583
- return Math.min(wScale, hScale);
584
- };
585
528
  class AppListeners {
586
529
  constructor(manager) {
587
530
  this.manager = manager;
@@ -682,16 +625,7 @@ class AppListeners {
682
625
  }
683
626
  };
684
627
  this.moveCameraHandler = (payload) => {
685
- var _a;
686
- const cameraPayload = payload;
687
- if (payload.scale) {
688
- const remoteSize = this.manager.mainViewProxy.size$.value;
689
- const currentSize = (_a = this.manager.boxManager) == null ? void 0 : _a.stageRect;
690
- if (remoteSize && currentSize) {
691
- cameraPayload.scale = payload.scale * computedMinScale(remoteSize, currentSize);
692
- }
693
- }
694
- this.manager.mainView.moveCamera(cameraPayload);
628
+ this.manager.mainView.moveCamera(payload);
695
629
  };
696
630
  this.moveCameraToContainHandler = (payload) => {
697
631
  this.manager.mainView.moveCameraToContain(payload);
@@ -759,292 +693,6 @@ class BindContainerRoomPhaseInvalidError extends Error {
759
693
  this.message = "[WindowManager]: room phase only Connected can be bindContainer";
760
694
  }
761
695
  }
762
- const onObjectByEvent = (event) => {
763
- return (object, func) => {
764
- if (object === void 0)
765
- return;
766
- if (whiteWebSdk.listenUpdated) {
767
- const listener = (events) => {
768
- const kinds = events.map((e) => e.kind);
769
- if (kinds.includes(event)) {
770
- func();
771
- }
772
- };
773
- whiteWebSdk.listenUpdated(object, listener);
774
- func();
775
- return () => whiteWebSdk.unlistenUpdated(object, listener);
776
- } else {
777
- return whiteWebSdk.reaction(() => object, () => {
778
- func();
779
- }, {
780
- fireImmediately: true
781
- });
782
- }
783
- };
784
- };
785
- const safeListenPropsUpdated = (getProps, callback, onDestroyed) => {
786
- let disposeListenUpdated = null;
787
- const disposeReaction = whiteWebSdk.reaction(getProps, () => {
788
- if (disposeListenUpdated) {
789
- disposeListenUpdated();
790
- disposeListenUpdated = null;
791
- }
792
- const props = getProps();
793
- if (lodash.isObject(props)) {
794
- disposeListenUpdated = () => whiteWebSdk.unlistenUpdated(props, callback);
795
- whiteWebSdk.listenUpdated(props, callback);
796
- } else {
797
- onDestroyed == null ? void 0 : onDestroyed(props);
798
- }
799
- }, { fireImmediately: true });
800
- return () => {
801
- disposeListenUpdated == null ? void 0 : disposeListenUpdated();
802
- disposeReaction();
803
- };
804
- };
805
- const onObjectRemoved = onObjectByEvent(whiteWebSdk.UpdateEventKind.Removed);
806
- onObjectByEvent(whiteWebSdk.UpdateEventKind.Inserted);
807
- const plainObjectKeys = Object.keys;
808
- function isRef(e) {
809
- return Boolean(lodash.has(e, "__isRef"));
810
- }
811
- function makeRef(v) {
812
- return { k: sideEffectManager.genUID(), v, __isRef: true };
813
- }
814
- class StorageEvent {
815
- constructor() {
816
- this.listeners = /* @__PURE__ */ new Set();
817
- }
818
- get length() {
819
- return this.listeners.size;
820
- }
821
- dispatch(message) {
822
- this.listeners.forEach((callback) => callback(message));
823
- }
824
- addListener(listener) {
825
- this.listeners.add(listener);
826
- }
827
- removeListener(listener) {
828
- this.listeners.delete(listener);
829
- }
830
- }
831
- const STORAGE_NS = "_WM-STORAGE_";
832
- class Storage {
833
- constructor(context, id, defaultState) {
834
- this._sideEffect = new sideEffectManager.SideEffectManager();
835
- this._destroyed = false;
836
- this._refMap = /* @__PURE__ */ new WeakMap();
837
- this._lastValue = /* @__PURE__ */ new Map();
838
- this.onStateChanged = new StorageEvent();
839
- if (defaultState && !lodash.isObject(defaultState)) {
840
- throw new Error(`Default state for Storage ${id} is not an object.`);
841
- }
842
- this._context = context;
843
- this.id = id || null;
844
- this._state = {};
845
- const rawState = this._getRawState(this._state);
846
- if (this._context.isWritable) {
847
- if (this.id === null) {
848
- if (context.isAddApp && defaultState) {
849
- this.setState(defaultState);
850
- }
851
- } else {
852
- if (rawState === this._state || !lodash.isObject(rawState)) {
853
- if (!lodash.get(this._context.getAttributes(), [STORAGE_NS])) {
854
- this._context.updateAttributes([STORAGE_NS], {});
855
- }
856
- this._context.updateAttributes([STORAGE_NS, this.id], this._state);
857
- if (defaultState) {
858
- this.setState(defaultState);
859
- }
860
- }
861
- }
862
- }
863
- plainObjectKeys(rawState).forEach((key) => {
864
- if (this.id === null && key === STORAGE_NS) {
865
- return;
866
- }
867
- try {
868
- const rawValue = lodash.isObject(rawState[key]) ? JSON.parse(JSON.stringify(rawState[key])) : rawState[key];
869
- if (isRef(rawValue)) {
870
- this._state[key] = rawValue.v;
871
- if (lodash.isObject(rawValue.v)) {
872
- this._refMap.set(rawValue.v, rawValue);
873
- }
874
- } else {
875
- this._state[key] = rawValue;
876
- }
877
- } catch (e) {
878
- console.error(e);
879
- }
880
- });
881
- this._sideEffect.addDisposer(safeListenPropsUpdated(() => this.id === null ? context.getAttributes() : lodash.get(context.getAttributes(), [STORAGE_NS, this.id]), this._updateProperties.bind(this), this.destroy.bind(this)));
882
- }
883
- get state() {
884
- if (this._destroyed) {
885
- console.warn(`Accessing state on destroyed Storage "${this.id}"`);
886
- }
887
- return this._state;
888
- }
889
- addStateChangedListener(handler) {
890
- this.onStateChanged.addListener(handler);
891
- return () => this.onStateChanged.removeListener(handler);
892
- }
893
- ensureState(state) {
894
- return this.setState(plainObjectKeys(state).reduce((payload, key) => {
895
- if (!lodash.has(this._state, key)) {
896
- payload[key] = state[key];
897
- }
898
- return payload;
899
- }, {}));
900
- }
901
- setState(state) {
902
- if (this._destroyed) {
903
- console.error(new Error(`Cannot call setState on destroyed Storage "${this.id}".`));
904
- return;
905
- }
906
- if (!this._context.isWritable) {
907
- console.error(new Error(`Cannot setState on Storage "${this.id}" without writable access`), state);
908
- return;
909
- }
910
- const keys = plainObjectKeys(state);
911
- if (keys.length > 0) {
912
- keys.forEach((key) => {
913
- const value = state[key];
914
- if (value === this._state[key]) {
915
- return;
916
- }
917
- if (value === void 0) {
918
- this._lastValue.set(key, this._state[key]);
919
- delete this._state[key];
920
- this._setRawState(key, value);
921
- } else {
922
- this._lastValue.set(key, this._state[key]);
923
- this._state[key] = value;
924
- let payload = value;
925
- if (lodash.isObject(value)) {
926
- let refValue = this._refMap.get(value);
927
- if (!refValue) {
928
- refValue = makeRef(value);
929
- this._refMap.set(value, refValue);
930
- }
931
- payload = refValue;
932
- }
933
- this._setRawState(key, payload);
934
- }
935
- });
936
- }
937
- }
938
- emptyStorage() {
939
- if (lodash.size(this._state) <= 0) {
940
- return;
941
- }
942
- if (this._destroyed) {
943
- console.error(new Error(`Cannot empty destroyed Storage "${this.id}".`));
944
- return;
945
- }
946
- if (!this._context.isWritable) {
947
- console.error(new Error(`Cannot empty Storage "${this.id}" without writable access.`));
948
- return;
949
- }
950
- this.setState(lodash.mapValues(this._state, lodash.noop));
951
- }
952
- deleteStorage() {
953
- if (this.id === null) {
954
- throw new Error(`Cannot delete main Storage`);
955
- }
956
- if (!this._context.isWritable) {
957
- console.error(new Error(`Cannot delete Storage "${this.id}" without writable access.`));
958
- return;
959
- }
960
- this.destroy();
961
- this._context.updateAttributes([STORAGE_NS, this.id], void 0);
962
- }
963
- get destroyed() {
964
- return this._destroyed;
965
- }
966
- destroy() {
967
- this._destroyed = true;
968
- this._sideEffect.flushAll();
969
- }
970
- _getRawState(defaultValue) {
971
- var _a;
972
- if (this.id === null) {
973
- return (_a = this._context.getAttributes()) != null ? _a : defaultValue;
974
- } else {
975
- return lodash.get(this._context.getAttributes(), [STORAGE_NS, this.id], defaultValue);
976
- }
977
- }
978
- _setRawState(key, value) {
979
- if (this.id === null) {
980
- if (key === STORAGE_NS) {
981
- throw new Error(`Cannot set attribute internal filed "${STORAGE_NS}"`);
982
- }
983
- return this._context.updateAttributes([key], value);
984
- } else {
985
- return this._context.updateAttributes([STORAGE_NS, this.id, key], value);
986
- }
987
- }
988
- _updateProperties(actions) {
989
- var _a;
990
- if (this._destroyed) {
991
- console.error(new Error(`Cannot call _updateProperties on destroyed Storage "${this.id}".`));
992
- return;
993
- }
994
- if (actions.length > 0) {
995
- const diffs = {};
996
- for (let i = 0; i < actions.length; i++) {
997
- try {
998
- const action = actions[i];
999
- const key = action.key;
1000
- if (this.id === null && key === STORAGE_NS) {
1001
- continue;
1002
- }
1003
- const value = lodash.isObject(action.value) ? JSON.parse(JSON.stringify(action.value)) : action.value;
1004
- let oldValue;
1005
- if (this._lastValue.has(key)) {
1006
- oldValue = this._lastValue.get(key);
1007
- this._lastValue.delete(key);
1008
- }
1009
- switch (action.kind) {
1010
- case 2: {
1011
- if (lodash.has(this._state, key)) {
1012
- oldValue = this._state[key];
1013
- delete this._state[key];
1014
- }
1015
- diffs[key] = { oldValue };
1016
- break;
1017
- }
1018
- default: {
1019
- let newValue = value;
1020
- if (isRef(value)) {
1021
- const { k: k2, v } = value;
1022
- const curValue = this._state[key];
1023
- if (lodash.isObject(curValue) && ((_a = this._refMap.get(curValue)) == null ? void 0 : _a.k) === k2) {
1024
- newValue = curValue;
1025
- } else {
1026
- newValue = v;
1027
- if (lodash.isObject(v)) {
1028
- this._refMap.set(v, value);
1029
- }
1030
- }
1031
- }
1032
- if (newValue !== this._state[key]) {
1033
- oldValue = this._state[key];
1034
- this._state[key] = newValue;
1035
- }
1036
- diffs[key] = { newValue, oldValue };
1037
- break;
1038
- }
1039
- }
1040
- } catch (e) {
1041
- console.error(e);
1042
- }
1043
- }
1044
- this.onStateChanged.dispatch(diffs);
1045
- }
1046
- }
1047
- }
1048
696
  class WhiteBoardView {
1049
697
  constructor(view, appContext, appProxy, ensureSize) {
1050
698
  this.view = view;
@@ -1073,11 +721,12 @@ class WhiteBoardView {
1073
721
  const scenePath = this.appProxy.scenePath;
1074
722
  if (!scenePath)
1075
723
  return;
724
+ const scenes = Array.isArray(scene) ? scene : [scene || {}];
1076
725
  if (after) {
1077
726
  const nextIndex = this.pageState.index + 1;
1078
- putScenes(this.appContext.room, scenePath, [scene || {}], nextIndex);
727
+ putScenes(this.appContext.room, scenePath, scenes, nextIndex);
1079
728
  } else {
1080
- putScenes(this.appContext.room, scenePath, [scene || {}]);
729
+ putScenes(this.appContext.room, scenePath, scenes);
1081
730
  }
1082
731
  };
1083
732
  this.removePage = async (index2) => {
@@ -1277,10 +926,20 @@ class AppContext {
1277
926
  this.getAppOptions = () => {
1278
927
  return typeof this.appOptions === "function" ? this.appOptions() : this.appOptions;
1279
928
  };
1280
- this.createStorage = (storeId, defaultState) => {
1281
- const storage = new Storage(this, storeId, defaultState);
929
+ this.createStorage = (namespace, defaultState) => {
930
+ const isWritable$ = new valueEnhancer.Val(this.isWritable);
931
+ const plugin$ = new valueEnhancer.Val(this.manager.windowManger);
932
+ const storage = new syncedStore.Storage({
933
+ plugin$,
934
+ isWritable$,
935
+ namespace,
936
+ defaultState
937
+ });
938
+ this.emitter.on("writableChange", (writable) => {
939
+ isWritable$.setValue(writable);
940
+ });
1282
941
  this.emitter.on("destroy", () => {
1283
- storage.destroy();
942
+ storage.disconnect();
1284
943
  });
1285
944
  return storage;
1286
945
  };
@@ -1343,7 +1002,7 @@ class AppContext {
1343
1002
  }
1344
1003
  get storage() {
1345
1004
  if (!this._storage) {
1346
- this._storage = new Storage(this);
1005
+ this._storage = this.createStorage(this.appId, this.getAttributes());
1347
1006
  }
1348
1007
  return this._storage;
1349
1008
  }
@@ -1401,6 +1060,77 @@ class AppPageStateImpl {
1401
1060
  (_a = this.sceneNode) == null ? void 0 : _a.dispose();
1402
1061
  }
1403
1062
  }
1063
+ class CameraSynchronizer {
1064
+ constructor(saveCamera) {
1065
+ this.saveCamera = saveCamera;
1066
+ this.scale = 1;
1067
+ this.setRect = (rect, updateCamera = true) => {
1068
+ this.rect = rect;
1069
+ if (this.remoteCamera && this.remoteSize && updateCamera) {
1070
+ this.onRemoteUpdate(this.remoteCamera, this.remoteSize);
1071
+ }
1072
+ };
1073
+ this.onRemoteUpdate = lodash.throttle((camera, size) => {
1074
+ this.remoteCamera = camera;
1075
+ this.remoteSize = size;
1076
+ if (this.remoteSize && this.rect) {
1077
+ requestAnimationFrame(() => {
1078
+ this.moveCameraToContian(size);
1079
+ this.moveCamera(camera);
1080
+ });
1081
+ }
1082
+ }, 32);
1083
+ }
1084
+ setView(view) {
1085
+ this.view = view;
1086
+ }
1087
+ onRemoteSizeUpdate(size) {
1088
+ var _a;
1089
+ this.remoteSize = size;
1090
+ const needMoveCamera = !lodash.isEqual(lodash.pick(this.rect, ["width", "height"]), lodash.pick(size, ["width", "height"]));
1091
+ if (this.rect && this.remoteCamera && needMoveCamera) {
1092
+ if (!this.view)
1093
+ return;
1094
+ const currentCamera = this.view.camera;
1095
+ (_a = this.view) == null ? void 0 : _a.moveCameraToContain({
1096
+ width: size.width,
1097
+ height: size.height,
1098
+ originX: currentCamera.centerX - size.width / 2,
1099
+ originY: currentCamera.centerY - size.height / 2
1100
+ });
1101
+ }
1102
+ }
1103
+ onLocalCameraUpdate(camera) {
1104
+ this.saveCamera(camera);
1105
+ this.remoteCamera = camera;
1106
+ }
1107
+ moveCameraToContian(size) {
1108
+ if (!lodash.isEmpty(size) && this.view) {
1109
+ this.view.moveCameraToContain({
1110
+ width: size.width,
1111
+ height: size.height,
1112
+ originX: -size.width / 2,
1113
+ originY: -size.height / 2,
1114
+ animationMode: whiteWebSdk.AnimationMode.Immediately
1115
+ });
1116
+ this.scale = this.view.camera.scale;
1117
+ }
1118
+ }
1119
+ moveCamera(camera) {
1120
+ if (!lodash.isEmpty(camera) && this.view && camera.centerX && camera.centerY) {
1121
+ if (lodash.isEqual(camera, this.view.camera))
1122
+ return;
1123
+ const { centerX, centerY, scale: scale2 } = camera;
1124
+ const needScale = scale2 * (this.scale || 1);
1125
+ this.view.moveCamera({
1126
+ centerX,
1127
+ centerY,
1128
+ scale: needScale,
1129
+ animationMode: whiteWebSdk.AnimationMode.Immediately
1130
+ });
1131
+ }
1132
+ }
1133
+ }
1404
1134
  class ViewSync {
1405
1135
  constructor(context) {
1406
1136
  this.context = context;
@@ -1418,8 +1148,9 @@ class ViewSync {
1418
1148
  };
1419
1149
  this.subscribeView = () => {
1420
1150
  return this.context.view$.subscribe((view) => {
1151
+ var _a;
1421
1152
  const currentCamera = this.context.camera$.value;
1422
- if (currentCamera && this.context.size$.value) {
1153
+ if (currentCamera && this.context.size$.value && ((_a = this.needRecoverCamera$) == null ? void 0 : _a.value)) {
1423
1154
  view == null ? void 0 : view.moveCamera({
1424
1155
  scale: 1,
1425
1156
  animationMode: whiteWebSdk.AnimationMode.Immediately
@@ -1441,7 +1172,7 @@ class ViewSync {
1441
1172
  };
1442
1173
  this.subscribeSize = () => {
1443
1174
  return this.context.size$.subscribe((size) => {
1444
- if (size) {
1175
+ if (size && this.isBroadcastMode) {
1445
1176
  this.synchronizer.onRemoteSizeUpdate(size);
1446
1177
  }
1447
1178
  });
@@ -1449,7 +1180,7 @@ class ViewSync {
1449
1180
  this.subscribeStageRect = () => {
1450
1181
  return this.context.stageRect$.subscribe((rect) => {
1451
1182
  if (rect) {
1452
- this.synchronizer.setRect(rect);
1183
+ this.synchronizer.setRect(rect, this.isBroadcastMode);
1453
1184
  }
1454
1185
  });
1455
1186
  };
@@ -1466,10 +1197,15 @@ class ViewSync {
1466
1197
  this.onCameraUpdatedByDevice = (camera) => {
1467
1198
  if (!camera)
1468
1199
  return;
1469
- if (this.context.size$.value && this.context.stageRect$.value) {
1470
- const diffScale = computedMinScale(this.context.size$.value, this.context.stageRect$.value);
1471
- const remoteScale = camera.scale / diffScale;
1472
- this.synchronizer.onLocalCameraUpdate(__spreadProps(__spreadValues({}, camera), { scale: remoteScale, id: this.context.uid }));
1200
+ if (!this.isBroadcastMode)
1201
+ return;
1202
+ const { size$, stageRect$, view$ } = this.context;
1203
+ if (size$.value && stageRect$.value && view$.value) {
1204
+ this.synchronizer.onLocalCameraUpdate(__spreadProps(__spreadValues({}, camera), { id: this.context.uid }));
1205
+ const newSize = __spreadProps(__spreadValues({}, view$.value.size), { id: this.context.uid });
1206
+ if (!lodash.isEqual(size$.value, newSize)) {
1207
+ this.context.storeSize(newSize);
1208
+ }
1473
1209
  }
1474
1210
  };
1475
1211
  this.synchronizer = this.createSynchronizer();
@@ -1480,14 +1216,22 @@ class ViewSync {
1480
1216
  this.subscribeSize(),
1481
1217
  this.subscribeStageRect()
1482
1218
  ]);
1219
+ if (context.viewMode$) {
1220
+ this.needRecoverCamera$ = valueEnhancer.derive(context.viewMode$, (mode) => mode !== "scroll");
1221
+ }
1483
1222
  const camera$size$ = valueEnhancer.combine([this.context.camera$, this.context.size$]);
1484
1223
  camera$size$.reaction(([camera, size]) => {
1485
- if (camera && size) {
1224
+ var _a;
1225
+ if (camera && size && ((_a = this.needRecoverCamera$) == null ? void 0 : _a.value)) {
1486
1226
  this.synchronizer.onRemoteUpdate(camera, size);
1487
1227
  camera$size$.destroy();
1488
1228
  }
1489
1229
  });
1490
1230
  }
1231
+ get isBroadcastMode() {
1232
+ var _a;
1233
+ return ((_a = this.context.viewMode$) == null ? void 0 : _a.value) === whiteWebSdk.ViewMode.Broadcaster;
1234
+ }
1491
1235
  destroy() {
1492
1236
  this.sem.flushAll();
1493
1237
  }
@@ -2559,6 +2303,51 @@ class MainViewProxy {
2559
2303
  this.sideEffectManager.flushAll();
2560
2304
  }
2561
2305
  }
2306
+ const onObjectByEvent = (event) => {
2307
+ return (object, func) => {
2308
+ if (object === void 0)
2309
+ return;
2310
+ if (whiteWebSdk.listenUpdated) {
2311
+ const listener = (events) => {
2312
+ const kinds = events.map((e) => e.kind);
2313
+ if (kinds.includes(event)) {
2314
+ func();
2315
+ }
2316
+ };
2317
+ whiteWebSdk.listenUpdated(object, listener);
2318
+ func();
2319
+ return () => whiteWebSdk.unlistenUpdated(object, listener);
2320
+ } else {
2321
+ return whiteWebSdk.reaction(() => object, () => {
2322
+ func();
2323
+ }, {
2324
+ fireImmediately: true
2325
+ });
2326
+ }
2327
+ };
2328
+ };
2329
+ const safeListenPropsUpdated = (getProps, callback, onDestroyed) => {
2330
+ let disposeListenUpdated = null;
2331
+ const disposeReaction = whiteWebSdk.reaction(getProps, () => {
2332
+ if (disposeListenUpdated) {
2333
+ disposeListenUpdated();
2334
+ disposeListenUpdated = null;
2335
+ }
2336
+ const props = getProps();
2337
+ if (lodash.isObject(props)) {
2338
+ disposeListenUpdated = () => whiteWebSdk.unlistenUpdated(props, callback);
2339
+ whiteWebSdk.listenUpdated(props, callback);
2340
+ } else {
2341
+ onDestroyed == null ? void 0 : onDestroyed(props);
2342
+ }
2343
+ }, { fireImmediately: true });
2344
+ return () => {
2345
+ disposeListenUpdated == null ? void 0 : disposeListenUpdated();
2346
+ disposeReaction();
2347
+ };
2348
+ };
2349
+ const onObjectRemoved = onObjectByEvent(whiteWebSdk.UpdateEventKind.Removed);
2350
+ onObjectByEvent(whiteWebSdk.UpdateEventKind.Inserted);
2562
2351
  class RedoUndo {
2563
2352
  constructor(context) {
2564
2353
  this.context = context;
@@ -2618,24 +2407,181 @@ class RedoUndo {
2618
2407
  this.disposePrevFocusViewRedoUndoListeners(this.context.focus());
2619
2408
  }
2620
2409
  }
2410
+ const createScrollStorage = (manager) => {
2411
+ return new syncedStore.Storage({
2412
+ plugin$: new valueEnhancer.Val(manager.windowManger),
2413
+ isWritable$: manager.isWritable$,
2414
+ namespace: "scrollStorage",
2415
+ defaultState: { scrollTop: 0 }
2416
+ });
2417
+ };
2418
+ function clamp$2(x2, min, max) {
2419
+ return x2 < min ? min : x2 > max ? max : x2;
2420
+ }
2421
+ class ScrollMode {
2422
+ constructor(manager) {
2423
+ var _a;
2424
+ this.manager = manager;
2425
+ this.sideEffect = new sideEffectManager.SideEffectManager();
2426
+ this.baseWidth = SCROLL_MODE_BASE_WIDTH;
2427
+ this.baseHeight = SCROLL_MODE_BASE_HEIGHT;
2428
+ this.initScroll = () => {
2429
+ const halfWbHeight = this._size$.value.height / 2 / this._scale$.value;
2430
+ const scrollTop = this._scrollTop$.value;
2431
+ this._scrollTop$.setValue(clamp$2(scrollTop, halfWbHeight, this.baseHeight - halfWbHeight) - 0.01);
2432
+ };
2433
+ this.getWhiteboardElement = (root) => {
2434
+ const className = ".netless-window-manager-main-view";
2435
+ return root && root.querySelector(className);
2436
+ };
2437
+ this.onWheel = (ev) => {
2438
+ var _a2;
2439
+ const target = ev.target;
2440
+ if (this.manager.canOperate && ((_a2 = this._whiteboard$.value) == null ? void 0 : _a2.contains(target))) {
2441
+ ev.preventDefault();
2442
+ ev.stopPropagation();
2443
+ const dy = ev.deltaY || 0;
2444
+ const { width } = this._size$.value;
2445
+ if (dy && width > 0) {
2446
+ const halfWbHeight = this._size$.value.height / 2 / this._scale$.value;
2447
+ const scrollTop = this._scrollTop$.value + dy / this._scale$.value;
2448
+ this.scrollStorage.setState({
2449
+ scrollTop: clamp$2(scrollTop, halfWbHeight, this.baseHeight - halfWbHeight)
2450
+ });
2451
+ callbacks.emit("userScroll");
2452
+ }
2453
+ }
2454
+ };
2455
+ this._root$ = new valueEnhancer.Val(null);
2456
+ this._mainView$ = new valueEnhancer.Val(this.manager.mainView);
2457
+ this._mainView$.value.disableCameraTransform = true;
2458
+ if ((_a = manager.scrollBaseSize$) == null ? void 0 : _a.value) {
2459
+ this.baseWidth = manager.scrollBaseSize$.value.width;
2460
+ this.baseHeight = manager.scrollBaseSize$.value.height;
2461
+ }
2462
+ this.scrollStorage = createScrollStorage(manager);
2463
+ const scrollTop$ = new valueEnhancer.Val(this.scrollStorage.state.scrollTop);
2464
+ this._scrollTop$ = scrollTop$;
2465
+ this.sideEffect.push(this.scrollStorage.on("stateChanged", () => {
2466
+ this._scrollTop$.setValue(this.scrollStorage.state.scrollTop);
2467
+ }));
2468
+ const size$ = new valueEnhancer.Val({ width: 0, height: 0 }, { compare: (a, b2) => a.width === b2.width && a.height === b2.height });
2469
+ this._size$ = size$;
2470
+ this.sideEffect.add(() => {
2471
+ const onSizeUpdated = size$.setValue.bind(size$);
2472
+ onSizeUpdated(this._mainView$.value.size);
2473
+ this._mainView$.value.callbacks.on("onSizeUpdated", onSizeUpdated);
2474
+ return () => this._mainView$.value.callbacks.off("onSizeUpdated", onSizeUpdated);
2475
+ });
2476
+ this.sideEffect.add(() => {
2477
+ const onCameraUpdated = (camera) => {
2478
+ const halfWbHeight = size$.value.height / 2 / scale$.value;
2479
+ const scrollTop = camera.centerY;
2480
+ this.scrollStorage.setState({
2481
+ scrollTop: clamp$2(scrollTop, halfWbHeight, this.baseHeight - halfWbHeight)
2482
+ });
2483
+ callbacks.emit("userScroll");
2484
+ };
2485
+ this._mainView$.value.callbacks.on("onCameraUpdatedByDevice", onCameraUpdated);
2486
+ return () => this._mainView$.value.callbacks.off("onCameraUpdatedByDevice", onCameraUpdated);
2487
+ });
2488
+ const scale$ = valueEnhancer.derive(size$, (size) => size.width / this.baseWidth);
2489
+ this._scale$ = scale$;
2490
+ const page$ = new valueEnhancer.Val(0);
2491
+ this.sideEffect.push(valueEnhancer.combine([scrollTop$, size$, scale$]).subscribe(([scrollTop, size, scale2]) => {
2492
+ if (scale2 > 0) {
2493
+ const wbHeight = size.height / scale2;
2494
+ page$.setValue(Math.max(scrollTop / wbHeight - 0.5, 0));
2495
+ }
2496
+ }));
2497
+ this._page$ = page$;
2498
+ this.sideEffect.push(valueEnhancer.combine([scrollTop$, scale$]).subscribe(([scrollTop, scale2]) => {
2499
+ this.updateBound(scrollTop, size$.value, scale2);
2500
+ }));
2501
+ this.sideEffect.push(size$.reaction(() => {
2502
+ this.updateScroll(scrollTop$.value);
2503
+ }));
2504
+ const whiteboard$ = valueEnhancer.derive(this._root$, this.getWhiteboardElement);
2505
+ this._whiteboard$ = whiteboard$;
2506
+ this.sideEffect.push(whiteboard$.reaction((el) => {
2507
+ if (el == null ? void 0 : el.parentElement) {
2508
+ this.sideEffect.addEventListener(el.parentElement, "wheel", this.onWheel, { capture: true, passive: false }, "wheel");
2509
+ }
2510
+ }));
2511
+ this.sideEffect.push(scale$.reaction((scale2) => {
2512
+ if (scale2 > 0) {
2513
+ this.sideEffect.flush("initScroll");
2514
+ this.sideEffect.setTimeout(this.initScroll, 0);
2515
+ }
2516
+ }), "initScroll");
2517
+ const maxScrollPage$ = valueEnhancer.combine([this._size$, this._scale$], ([size, scale2]) => {
2518
+ const halfWbHeight = size.height / 2 / scale2;
2519
+ return (this.baseHeight - halfWbHeight) / halfWbHeight / 2 - 0.51;
2520
+ });
2521
+ this.scrollState$ = valueEnhancer.combine([this._scrollTop$, this._page$, maxScrollPage$], ([scrollTop, page, maxScrollPage]) => {
2522
+ return {
2523
+ scrollTop,
2524
+ page,
2525
+ maxScrollPage
2526
+ };
2527
+ });
2528
+ this.updateScroll(scrollTop$.value);
2529
+ this.sideEffect.push(this.scrollState$.subscribe((state) => callbacks.emit("scrollStateChange", state)));
2530
+ }
2531
+ setRoot(root) {
2532
+ this._root$.setValue(root);
2533
+ }
2534
+ updateScroll(scrollTop) {
2535
+ this._mainView$.value.moveCamera({
2536
+ centerY: scrollTop,
2537
+ animationMode: whiteWebSdk.AnimationMode.Immediately
2538
+ });
2539
+ }
2540
+ updateBound(scrollTop, { height }, scale2) {
2541
+ if (scale2 > 0) {
2542
+ this._mainView$.value.moveCameraToContain({
2543
+ originX: 0,
2544
+ originY: scrollTop - height / scale2 / 2,
2545
+ width: this.baseWidth,
2546
+ height: height / scale2,
2547
+ animationMode: whiteWebSdk.AnimationMode.Immediately
2548
+ });
2549
+ this._mainView$.value.setCameraBound({
2550
+ damping: 1,
2551
+ maxContentMode: () => scale2,
2552
+ minContentMode: () => scale2,
2553
+ centerX: this.baseWidth / 2,
2554
+ centerY: this.baseHeight / 2,
2555
+ width: this.baseWidth,
2556
+ height: this.baseHeight
2557
+ });
2558
+ }
2559
+ }
2560
+ dispose() {
2561
+ this.sideEffect.flushAll();
2562
+ }
2563
+ }
2621
2564
  class AppManager {
2622
2565
  constructor(windowManger) {
2566
+ var _a;
2623
2567
  this.windowManger = windowManger;
2624
2568
  this.appProxies = /* @__PURE__ */ new Map();
2625
2569
  this.appStatus = /* @__PURE__ */ new Map();
2626
2570
  this.store = store;
2627
2571
  this.isReplay = this.windowManger.isReplay;
2628
2572
  this.mainViewScenesLength = 0;
2573
+ this.scrollBaseSize$ = new valueEnhancer.Val(null);
2629
2574
  this.callbacksNode = null;
2630
2575
  this.appCreateQueue = new AppCreateQueue();
2631
2576
  this.sceneIndex$ = new valueEnhancer.Val(void 0);
2632
2577
  this.focused$ = new valueEnhancer.Val(void 0);
2633
2578
  this.members$ = new valueEnhancer.Val([]);
2579
+ this.isWritable$ = new valueEnhancer.Val(Boolean((_a = this.room) == null ? void 0 : _a.isWritable));
2634
2580
  this.sideEffectManager = new sideEffectManager.SideEffectManager();
2635
2581
  this.sceneState = null;
2636
2582
  this.rootDirRemoving = false;
2637
2583
  this.onRemoveScenes = async (params) => {
2638
- var _a, _b;
2584
+ var _a2, _b;
2639
2585
  const { scenePath } = params;
2640
2586
  if (scenePath === ROOT_DIR) {
2641
2587
  await this.onRootDirRemoved();
@@ -2644,7 +2590,7 @@ class AppManager {
2644
2590
  }
2645
2591
  if (isRootDirPage(scenePath)) {
2646
2592
  let nextIndex = this.mainView.focusSceneIndex || 0;
2647
- let sceneName = (_a = this.callbacksNode) == null ? void 0 : _a.scenes[nextIndex];
2593
+ let sceneName = (_a2 = this.callbacksNode) == null ? void 0 : _a2.scenes[nextIndex];
2648
2594
  if (!sceneName) {
2649
2595
  nextIndex = 0;
2650
2596
  sceneName = (_b = this.callbacksNode) == null ? void 0 : _b.scenes[nextIndex];
@@ -2695,11 +2641,11 @@ class AppManager {
2695
2641
  }
2696
2642
  };
2697
2643
  this.removeSceneByIndex = async (index2) => {
2698
- var _a;
2644
+ var _a2;
2699
2645
  const nextIndex = calculateNextIndex(index2, this.windowManger.pageState);
2700
2646
  this.setSceneIndexWithoutSync(nextIndex);
2701
2647
  this.dispatchInternalEvent(Events.SetAppFocusIndex, { type: "main", index: nextIndex });
2702
- const scene = (_a = this.callbacksNode) == null ? void 0 : _a.scenes[index2];
2648
+ const scene = (_a2 = this.callbacksNode) == null ? void 0 : _a2.scenes[index2];
2703
2649
  setTimeout(() => {
2704
2650
  if (scene) {
2705
2651
  removeScenes(this.room, `${ROOT_DIR}${scene}`, index2);
@@ -2717,8 +2663,8 @@ class AppManager {
2717
2663
  });
2718
2664
  };
2719
2665
  this.setSceneIndexWithoutSync = (index2) => {
2720
- var _a;
2721
- const sceneName = (_a = this.callbacksNode) == null ? void 0 : _a.scenes[index2];
2666
+ var _a2;
2667
+ const sceneName = (_a2 = this.callbacksNode) == null ? void 0 : _a2.scenes[index2];
2722
2668
  if (sceneName) {
2723
2669
  this.mainViewProxy.setFocusScenePath(`${ROOT_DIR}${sceneName}`);
2724
2670
  }
@@ -2789,8 +2735,8 @@ class AppManager {
2789
2735
  });
2790
2736
  };
2791
2737
  this.addAppCloseListener = () => {
2792
- var _a;
2793
- (_a = this.refresher) == null ? void 0 : _a.add("appsClose", () => {
2738
+ var _a2;
2739
+ (_a2 = this.refresher) == null ? void 0 : _a2.add("appsClose", () => {
2794
2740
  return onObjectRemoved(this.attributes.apps, () => {
2795
2741
  this.onAppDelete(this.attributes.apps);
2796
2742
  });
@@ -2807,13 +2753,13 @@ class AppManager {
2807
2753
  }
2808
2754
  };
2809
2755
  this.onFocusChange = (focused) => {
2810
- var _a;
2756
+ var _a2;
2811
2757
  if (this.focused$.value !== focused) {
2812
2758
  callbacks.emit("focusedChange", focused);
2813
2759
  emitter.emit("focusedChange", { focused, prev: this.focused$.value });
2814
2760
  this.focused$.setValue(focused);
2815
2761
  if (focused !== void 0) {
2816
- (_a = this.boxManager) == null ? void 0 : _a.focusBox({ appId: focused });
2762
+ (_a2 = this.boxManager) == null ? void 0 : _a2.focusBox({ appId: focused });
2817
2763
  setTimeout(() => {
2818
2764
  const appProxy = this.appProxies.get(focused);
2819
2765
  if (appProxy) {
@@ -2839,14 +2785,14 @@ class AppManager {
2839
2785
  });
2840
2786
  };
2841
2787
  this.onMinimized = (minimized) => {
2842
- var _a, _b;
2843
- if (((_a = this.boxManager) == null ? void 0 : _a.minimized) !== minimized) {
2788
+ var _a2, _b;
2789
+ if (((_a2 = this.boxManager) == null ? void 0 : _a2.minimized) !== minimized) {
2844
2790
  if (minimized === true) {
2845
2791
  (_b = this.boxManager) == null ? void 0 : _b.blurAllBox();
2846
2792
  }
2847
2793
  setTimeout(() => {
2848
- var _a2;
2849
- (_a2 = this.boxManager) == null ? void 0 : _a2.setMinimized(Boolean(minimized));
2794
+ var _a3;
2795
+ (_a3 = this.boxManager) == null ? void 0 : _a3.setMinimized(Boolean(minimized));
2850
2796
  }, 0);
2851
2797
  }
2852
2798
  };
@@ -2886,11 +2832,11 @@ class AppManager {
2886
2832
  }
2887
2833
  };
2888
2834
  this.displayerWritableListener = (isReadonly) => {
2889
- var _a, _b;
2835
+ var _a2, _b;
2890
2836
  const isWritable = !isReadonly;
2891
2837
  const isManualWritable = this.windowManger.readonly === void 0 || !this.windowManger.readonly;
2892
2838
  if (this.windowManger.readonly === void 0) {
2893
- (_a = this.boxManager) == null ? void 0 : _a.setReadonly(isReadonly);
2839
+ (_a2 = this.boxManager) == null ? void 0 : _a2.setReadonly(isReadonly);
2894
2840
  } else {
2895
2841
  (_b = this.boxManager) == null ? void 0 : _b.setReadonly(!(isWritable && isManualWritable));
2896
2842
  }
@@ -2903,6 +2849,7 @@ class AppManager {
2903
2849
  }
2904
2850
  }
2905
2851
  emitter.emit("writableChange", isWritable);
2852
+ this.isWritable$.setValue(isWritable);
2906
2853
  };
2907
2854
  this.updateSceneIndex = () => {
2908
2855
  const scenePath = this.store.getMainViewScenePath();
@@ -2935,10 +2882,10 @@ class AppManager {
2935
2882
  this.refresher.setContext({ emitter });
2936
2883
  this.sideEffectManager.add(() => {
2937
2884
  return () => {
2938
- var _a, _b, _c;
2885
+ var _a2, _b, _c;
2939
2886
  this.appCreateQueue.destroy();
2940
2887
  this.mainViewProxy.destroy();
2941
- (_a = this.refresher) == null ? void 0 : _a.destroy();
2888
+ (_a2 = this.refresher) == null ? void 0 : _a2.destroy();
2942
2889
  this.viewManager.destroy();
2943
2890
  (_b = this.boxManager) == null ? void 0 : _b.destroy();
2944
2891
  (_c = this.callbacksNode) == null ? void 0 : _c.dispose();
@@ -2957,6 +2904,16 @@ class AppManager {
2957
2904
  this.safeUpdateAttributes([Fields.Registered, payload.kind], payload);
2958
2905
  });
2959
2906
  this.members$.setValue(serializeRoomMembers(this.displayer.state.roomMembers));
2907
+ emitter.on("mainViewMounted", () => {
2908
+ this.windowManger.viewMode$.subscribe((viewMode) => {
2909
+ const playground = this.windowManger.playground$.value;
2910
+ if (viewMode === "scroll" && playground) {
2911
+ const scrollMode = new ScrollMode(this);
2912
+ this.scrollMode = scrollMode;
2913
+ scrollMode.setRoot(playground);
2914
+ }
2915
+ });
2916
+ });
2960
2917
  }
2961
2918
  async onRootDirRemoved(needClose = true) {
2962
2919
  await this.setMainViewScenePath(INIT_DIR);
@@ -3128,6 +3085,7 @@ class AppManager {
3128
3085
  bindMainView(divElement, disableCameraTransform) {
3129
3086
  const mainView = this.mainViewProxy.view;
3130
3087
  mainView.disableCameraTransform = disableCameraTransform;
3088
+ console.log("bindMainView", mainView.disableCameraTransform);
3131
3089
  wait(30).then(() => {
3132
3090
  mainView.divElement = divElement;
3133
3091
  emitter.emit("mainViewMounted");
@@ -6894,7 +6852,7 @@ class CursorManager {
6894
6852
  this.initCursorInstance = (uid) => {
6895
6853
  let cursorInstance = this.cursorInstances.get(uid);
6896
6854
  if (!cursorInstance) {
6897
- cursorInstance = new Cursor(this.manager, uid, this, WindowManager.playground);
6855
+ cursorInstance = new Cursor(this.manager, uid, this, this.playground$.value);
6898
6856
  this.cursorInstances.set(uid, cursorInstance);
6899
6857
  }
6900
6858
  return cursorInstance;
@@ -6937,7 +6895,7 @@ class CursorManager {
6937
6895
  this.hideCursor(this.manager.uid);
6938
6896
  };
6939
6897
  this.roomMembers = (_a = this.manager.room) == null ? void 0 : _a.state.roomMembers;
6940
- const playground = WindowManager.playground;
6898
+ const playground = this.playground$.value;
6941
6899
  if (playground) {
6942
6900
  this.setupWrapper(playground);
6943
6901
  }
@@ -6951,6 +6909,9 @@ class CursorManager {
6951
6909
  this.applianceIcons = __spreadValues(__spreadValues({}, ApplianceMap), applianceIcons);
6952
6910
  }
6953
6911
  }
6912
+ get playground$() {
6913
+ return this.manager.windowManger.playground$;
6914
+ }
6954
6915
  canMoveCursor(member) {
6955
6916
  const isLaserPointer = (member == null ? void 0 : member.memberState.currentApplianceName) === whiteWebSdk.ApplianceNames.laserPointer;
6956
6917
  return this.enableCursor || isLaserPointer;
@@ -11688,70 +11649,35 @@ const reconnectRefresher = new ReconnectRefresher({ emitter });
11688
11649
  const _WindowManager = class extends whiteWebSdk.InvisiblePlugin {
11689
11650
  constructor(context) {
11690
11651
  super(context);
11691
- this.version = "1.0.0-canary.52";
11692
- this.dependencies = { "dependencies": { "@juggle/resize-observer": "^3.3.1", "@netless/telebox-insider": "1.0.0-alpha.37", "emittery": "^0.11.0", "lodash": "^4.17.21", "p-retry": "^4.6.2", "side-effect-manager": "^1.1.1", "uuid": "^7.0.3", "value-enhancer": "^1.3.2" }, "peerDependencies": { "white-web-sdk": "^2.16.0" }, "devDependencies": { "@netless/app-docs-viewer": "^0.3.3", "@netless/app-plyr": "0.2.2", "@playwright/test": "^1.23.2", "@rollup/plugin-commonjs": "^20.0.0", "@rollup/plugin-node-resolve": "^13.0.4", "@rollup/plugin-url": "^6.1.0", "@sveltejs/vite-plugin-svelte": "^1.0.0-next.49", "@tsconfig/svelte": "^2.0.1", "@types/debug": "^4.1.7", "@types/lodash": "^4.14.182", "@types/lodash-es": "^4.17.6", "@types/node": "^18.0.3", "@types/uuid": "^8.3.4", "@typescript-eslint/eslint-plugin": "^4.30.0", "@typescript-eslint/parser": "^4.30.0", "@vitest/ui": "^0.14.2", "cypress": "^8.7.0", "dotenv": "^10.0.0", "eslint": "^7.32.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-svelte3": "^3.2.0", "jsdom": "^19.0.0", "less": "^4.1.3", "prettier": "^2.3.2", "prettier-plugin-svelte": "^2.4.0", "rollup-plugin-analyzer": "^4.0.0", "rollup-plugin-styles": "^3.14.1", "svelte": "^3.42.4", "typescript": "^4.5.5", "vite": "^2.5.3", "vite-plugin-dts": "^1.2.1", "vitest": "^0.18.0", "white-web-sdk": "2.16.26" } };
11652
+ this.version = "1.0.0-canary.54";
11653
+ this.dependencies = { "dependencies": { "@juggle/resize-observer": "^3.3.1", "@netless/synced-store": "^2.0.7", "@netless/telebox-insider": "1.0.0-alpha.37", "emittery": "^0.11.0", "lodash": "^4.17.21", "p-retry": "^4.6.2", "side-effect-manager": "^1.2.1", "uuid": "^7.0.3", "value-enhancer": "^1.3.2" }, "peerDependencies": { "white-web-sdk": "^2.16.0" }, "devDependencies": { "@netless/app-docs-viewer": "^0.3.3", "@netless/app-plyr": "0.2.2", "@playwright/test": "^1.23.2", "@rollup/plugin-commonjs": "^20.0.0", "@rollup/plugin-node-resolve": "^13.0.4", "@rollup/plugin-url": "^6.1.0", "@sveltejs/vite-plugin-svelte": "^1.0.0-next.49", "@tsconfig/svelte": "^2.0.1", "@types/debug": "^4.1.7", "@types/lodash": "^4.14.182", "@types/lodash-es": "^4.17.6", "@types/node": "^18.0.3", "@types/uuid": "^8.3.4", "@typescript-eslint/eslint-plugin": "^4.30.0", "@typescript-eslint/parser": "^4.30.0", "@vitest/ui": "^0.14.2", "cypress": "^8.7.0", "dotenv": "^10.0.0", "eslint": "^7.32.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-svelte3": "^3.2.0", "jsdom": "^19.0.0", "less": "^4.1.3", "prettier": "^2.3.2", "prettier-plugin-svelte": "^2.4.0", "rollup-plugin-analyzer": "^4.0.0", "rollup-plugin-styles": "^3.14.1", "svelte": "^3.42.4", "typescript": "^4.5.5", "vite": "^2.5.3", "vite-plugin-dts": "^1.2.1", "vitest": "^0.18.0", "white-web-sdk": "^2.16.35" } };
11693
11654
  this.emitter = callbacks;
11694
11655
  this.viewMode = whiteWebSdk.ViewMode.Broadcaster;
11695
11656
  this.viewMode$ = new valueEnhancer.Val(whiteWebSdk.ViewMode.Broadcaster);
11657
+ this.playground$ = new valueEnhancer.Val(void 0);
11696
11658
  this.isReplay = whiteWebSdk.isPlayer(this.displayer);
11697
- this.cameraUpdating = 0;
11698
- this.nextCamera = null;
11699
11659
  this.containerSizeRatio = _WindowManager.containerSizeRatio;
11700
11660
  this.moveCamera = (camera) => {
11701
11661
  var _a;
11662
+ const pureCamera = lodash.omit(camera, ["animationMode"]);
11702
11663
  const mainViewCamera = __spreadValues({}, this.mainView.camera);
11703
- const nextCamera = __spreadValues(__spreadValues({}, mainViewCamera), camera);
11704
- if (lodash.isEqual(nextCamera, mainViewCamera))
11664
+ if (lodash.isEqual(__spreadValues(__spreadValues({}, mainViewCamera), pureCamera), mainViewCamera))
11705
11665
  return;
11706
- if (!this.appManager)
11707
- return;
11708
- if (camera.animationMode === whiteWebSdk.AnimationMode.Immediately) {
11709
- this.appManager.mainViewProxy.storeCamera(__spreadValues({
11710
- id: this.appManager.uid
11711
- }, nextCamera));
11712
- } else {
11713
- const remoteCamera = this.appManager.mainViewProxy.size$.value;
11714
- const currentSize = (_a = this.boxManager) == null ? void 0 : _a.stageRect;
11715
- let nextScale;
11716
- if (camera.scale && remoteCamera && currentSize) {
11717
- nextScale = camera.scale * computedMinScale(remoteCamera, currentSize);
11718
- }
11719
- if (nextScale) {
11720
- this.mainView.moveCamera(__spreadProps(__spreadValues({}, camera), {
11721
- scale: nextScale
11722
- }));
11723
- } else {
11724
- this.mainView.moveCamera(camera);
11725
- }
11726
- this.appManager.dispatchInternalEvent(Events.MoveCamera, camera);
11727
- this.mainView.callbacks.off("onCameraUpdated", this.onCameraUpdated);
11728
- clearTimeout(this.cameraUpdating);
11729
- this.cameraUpdating = 0;
11730
- this.mainView.callbacks.on("onCameraUpdated", this.onCameraUpdated);
11731
- if (nextScale) {
11732
- this.nextCamera = nextCamera;
11733
- }
11734
- }
11735
- };
11736
- this.onCameraUpdated = () => {
11737
- if (this.cameraUpdating) {
11738
- clearTimeout(this.cameraUpdating);
11739
- this.cameraUpdating = 0;
11740
- }
11741
- this.cameraUpdating = setTimeout(() => {
11742
- this.mainView.callbacks.off("onCameraUpdated", this.onCameraUpdated);
11743
- clearTimeout(this.cameraUpdating);
11744
- this.cameraUpdating = 0;
11745
- if (!this.appManager || !this.nextCamera)
11746
- return;
11747
- this.appManager.mainViewProxy.storeCamera(__spreadValues({
11748
- id: this.appManager.uid
11749
- }, this.nextCamera));
11750
- this.nextCamera = null;
11751
- }, 50);
11666
+ this.debouncedStoreCamera();
11667
+ this.mainView.moveCamera(camera);
11668
+ (_a = this.appManager) == null ? void 0 : _a.dispatchInternalEvent(Events.MoveCamera, camera);
11669
+ };
11670
+ this.debouncedStoreCamera = () => {
11671
+ const storeCamera = lodash.debounce(() => {
11672
+ var _a, _b;
11673
+ (_a = this.appManager) == null ? void 0 : _a.mainViewProxy.storeCurrentCamera();
11674
+ (_b = this.appManager) == null ? void 0 : _b.mainViewProxy.storeCurrentSize();
11675
+ this.mainView.callbacks.off("onCameraUpdated", storeCamera);
11676
+ }, 200);
11677
+ this.mainView.callbacks.on("onCameraUpdated", storeCamera);
11752
11678
  };
11753
11679
  _WindowManager.displayer = context.displayer;
11754
- window.NETLESS_DEPS = { "dependencies": { "@juggle/resize-observer": "^3.3.1", "@netless/telebox-insider": "1.0.0-alpha.37", "emittery": "^0.11.0", "lodash": "^4.17.21", "p-retry": "^4.6.2", "side-effect-manager": "^1.1.1", "uuid": "^7.0.3", "value-enhancer": "^1.3.2" }, "peerDependencies": { "white-web-sdk": "^2.16.0" }, "devDependencies": { "@netless/app-docs-viewer": "^0.3.3", "@netless/app-plyr": "0.2.2", "@playwright/test": "^1.23.2", "@rollup/plugin-commonjs": "^20.0.0", "@rollup/plugin-node-resolve": "^13.0.4", "@rollup/plugin-url": "^6.1.0", "@sveltejs/vite-plugin-svelte": "^1.0.0-next.49", "@tsconfig/svelte": "^2.0.1", "@types/debug": "^4.1.7", "@types/lodash": "^4.14.182", "@types/lodash-es": "^4.17.6", "@types/node": "^18.0.3", "@types/uuid": "^8.3.4", "@typescript-eslint/eslint-plugin": "^4.30.0", "@typescript-eslint/parser": "^4.30.0", "@vitest/ui": "^0.14.2", "cypress": "^8.7.0", "dotenv": "^10.0.0", "eslint": "^7.32.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-svelte3": "^3.2.0", "jsdom": "^19.0.0", "less": "^4.1.3", "prettier": "^2.3.2", "prettier-plugin-svelte": "^2.4.0", "rollup-plugin-analyzer": "^4.0.0", "rollup-plugin-styles": "^3.14.1", "svelte": "^3.42.4", "typescript": "^4.5.5", "vite": "^2.5.3", "vite-plugin-dts": "^1.2.1", "vitest": "^0.18.0", "white-web-sdk": "2.16.26" } };
11680
+ window.NETLESS_DEPS = { "dependencies": { "@juggle/resize-observer": "^3.3.1", "@netless/synced-store": "^2.0.7", "@netless/telebox-insider": "1.0.0-alpha.37", "emittery": "^0.11.0", "lodash": "^4.17.21", "p-retry": "^4.6.2", "side-effect-manager": "^1.2.1", "uuid": "^7.0.3", "value-enhancer": "^1.3.2" }, "peerDependencies": { "white-web-sdk": "^2.16.0" }, "devDependencies": { "@netless/app-docs-viewer": "^0.3.3", "@netless/app-plyr": "0.2.2", "@playwright/test": "^1.23.2", "@rollup/plugin-commonjs": "^20.0.0", "@rollup/plugin-node-resolve": "^13.0.4", "@rollup/plugin-url": "^6.1.0", "@sveltejs/vite-plugin-svelte": "^1.0.0-next.49", "@tsconfig/svelte": "^2.0.1", "@types/debug": "^4.1.7", "@types/lodash": "^4.14.182", "@types/lodash-es": "^4.17.6", "@types/node": "^18.0.3", "@types/uuid": "^8.3.4", "@typescript-eslint/eslint-plugin": "^4.30.0", "@typescript-eslint/parser": "^4.30.0", "@vitest/ui": "^0.14.2", "cypress": "^8.7.0", "dotenv": "^10.0.0", "eslint": "^7.32.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-svelte3": "^3.2.0", "jsdom": "^19.0.0", "less": "^4.1.3", "prettier": "^2.3.2", "prettier-plugin-svelte": "^2.4.0", "rollup-plugin-analyzer": "^4.0.0", "rollup-plugin-styles": "^3.14.1", "svelte": "^3.42.4", "typescript": "^4.5.5", "vite": "^2.5.3", "vite-plugin-dts": "^1.2.1", "vitest": "^0.18.0", "white-web-sdk": "^2.16.35" } };
11755
11681
  }
11756
11682
  static async mount(params) {
11757
11683
  var _a;
@@ -11798,6 +11724,9 @@ const _WindowManager = class extends whiteWebSdk.InvisiblePlugin {
11798
11724
  }
11799
11725
  manager.containerSizeRatio = _WindowManager.containerSizeRatio;
11800
11726
  await manager.ensureAttributes();
11727
+ if (params.viewMode) {
11728
+ manager.viewMode$.setValue(params.viewMode);
11729
+ }
11801
11730
  manager.appManager = new AppManager(manager);
11802
11731
  manager._pageState = new PageStateImpl(manager.appManager);
11803
11732
  manager.cursorManager = new CursorManager(manager.appManager, Boolean(cursor), params.applianceIcons);
@@ -11815,6 +11744,9 @@ const _WindowManager = class extends whiteWebSdk.InvisiblePlugin {
11815
11744
  if (params.container) {
11816
11745
  manager.bindContainer(params.container);
11817
11746
  }
11747
+ if (params.scrollModeWidth && params.scrollModeHeight) {
11748
+ manager.appManager.scrollBaseSize$.setValue({ width: params.scrollModeWidth, height: params.scrollModeHeight });
11749
+ }
11818
11750
  replaceRoomFunction(room, manager);
11819
11751
  emitter.emit("onCreated");
11820
11752
  _WindowManager.isCreated = true;
@@ -11883,6 +11815,7 @@ const _WindowManager = class extends whiteWebSdk.InvisiblePlugin {
11883
11815
  this.bindMainView(mainViewElement, params.disableCameraTransform);
11884
11816
  if (_WindowManager.playground) {
11885
11817
  (_b = this.cursorManager) == null ? void 0 : _b.setupWrapper(_WindowManager.playground);
11818
+ this.playground$.setValue(_WindowManager.playground);
11886
11819
  }
11887
11820
  }
11888
11821
  }
@@ -12098,10 +12031,11 @@ const _WindowManager = class extends whiteWebSdk.InvisiblePlugin {
12098
12031
  if (mode === whiteWebSdk.ViewMode.Broadcaster) {
12099
12032
  if (this.canOperate) {
12100
12033
  mainViewProxy == null ? void 0 : mainViewProxy.storeCurrentCamera();
12034
+ mainViewProxy == null ? void 0 : mainViewProxy.storeCurrentSize();
12101
12035
  }
12102
12036
  mainViewProxy == null ? void 0 : mainViewProxy.start();
12103
12037
  }
12104
- if (mode === whiteWebSdk.ViewMode.Freedom) {
12038
+ if (mode === whiteWebSdk.ViewMode.Freedom || mode === "scroll") {
12105
12039
  mainViewProxy == null ? void 0 : mainViewProxy.stop();
12106
12040
  }
12107
12041
  this.viewMode = mode;
@@ -12252,6 +12186,10 @@ const _WindowManager = class extends whiteWebSdk.InvisiblePlugin {
12252
12186
  throw new AppManagerNotInitError();
12253
12187
  }
12254
12188
  }
12189
+ get scrollState() {
12190
+ var _a, _b;
12191
+ return (_b = (_a = this.appManager) == null ? void 0 : _a.scrollMode) == null ? void 0 : _b.scrollState$.value;
12192
+ }
12255
12193
  get teleboxManager() {
12256
12194
  if (!this.boxManager) {
12257
12195
  throw new BoxManagerNotInitializeError();
@@ -12270,6 +12208,12 @@ const _WindowManager = class extends whiteWebSdk.InvisiblePlugin {
12270
12208
  var _a;
12271
12209
  return (_a = this.appManager) == null ? void 0 : _a.closeApp(appId);
12272
12210
  }
12211
+ moveCameraToContain(rectangle) {
12212
+ var _a;
12213
+ this.debouncedStoreCamera();
12214
+ this.mainView.moveCameraToContain(rectangle);
12215
+ (_a = this.appManager) == null ? void 0 : _a.dispatchInternalEvent(Events.MoveCameraToContain, rectangle);
12216
+ }
12273
12217
  convertToPointInWorld(point) {
12274
12218
  return this.mainView.convertToPointInWorld(point);
12275
12219
  }