@netless/window-manager 1.0.0-canary.19 → 1.0.0-canary.21

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netless/window-manager",
3
- "version": "1.0.0-canary.19",
3
+ "version": "1.0.0-canary.21",
4
4
  "description": "",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.es.js",
@@ -9,7 +9,7 @@ import { boxEmitter } from "../BoxEmitter";
9
9
  import { BoxManagerNotFoundError } from "../Utils/error";
10
10
  import { calculateNextIndex } from "../Page";
11
11
  import { combine, Val, ValManager } from "value-enhancer";
12
- import { debounce, get, isEqual } from "lodash";
12
+ import { debounce, get, isEqual, isUndefined, omitBy } from "lodash";
13
13
  import { emitter } from "../InternalEmitter";
14
14
  import { Fields } from "../AttributesDelegate";
15
15
  import { log } from "../Utils/log";
@@ -25,7 +25,6 @@ import {
25
25
  } from "../Utils/Common";
26
26
  import type {
27
27
  AppEmitterEvent,
28
- AppInitState,
29
28
  BaseInsertParams,
30
29
  setAppOptions,
31
30
  AppListenerKeys,
@@ -35,6 +34,7 @@ import type { AppManager } from "../AppManager";
35
34
  import type { NetlessApp } from "../typings";
36
35
  import type { ReadonlyTeleBox, TeleBoxRect } from "@netless/telebox-insider";
37
36
  import type { PageRemoveService, PageState } from "../Page";
37
+ import type { AppState } from "./type";
38
38
 
39
39
  export type AppEmitter = Emittery<AppEmitterEvent>;
40
40
 
@@ -151,6 +151,62 @@ export class AppProxy implements PageRemoveService {
151
151
  this.sideEffectManager.add(() =>
152
152
  emitter.on("memberStateChange", this.onMemberStateChange)
153
153
  );
154
+ this.box$.subscribe(box => {
155
+ if (!box) return;
156
+ this.sideEffectManager.add(() => [
157
+ createValSync(
158
+ () => this.appAttributes?.state.visible,
159
+ box._visible$,
160
+ ),
161
+ createValSync(
162
+ () => this.appAttributes?.state.ratio,
163
+ box._ratio$,
164
+ ),
165
+ createValSync(
166
+ () => this.appAttributes?.state.stageRatio,
167
+ box._stageRatio$,
168
+ ),
169
+ createValSync(
170
+ () => this.appAttributes?.state.draggable,
171
+ box._draggable$,
172
+ ),
173
+ createValSync(
174
+ () => this.appAttributes?.state.resizable,
175
+ box._resizable$,
176
+ ),
177
+ box._visible$.reaction((visible, skipUpdate) => {
178
+ if (skipUpdate) {
179
+ return;
180
+ }
181
+ this.store.updateAppState(this.id, AppAttributes.Visible, visible);
182
+ }),
183
+ box._ratio$.reaction((ratio, skipUpdate) => {
184
+ console.log("ratio change", ratio, skipUpdate);
185
+ if (skipUpdate) {
186
+ return;
187
+ }
188
+ this.store.updateAppState(this.id, AppAttributes.Ratio, ratio);
189
+ }),
190
+ box._stageRatio$.reaction((stageRatio, skipUpdate) => {
191
+ if (skipUpdate) {
192
+ return;
193
+ }
194
+ this.store.updateAppState(this.id, AppAttributes.StageRatio, stageRatio);
195
+ }),
196
+ box._draggable$.reaction((draggable, skipUpdate) => {
197
+ if (skipUpdate) {
198
+ return;
199
+ }
200
+ this.store.updateAppState(this.id, AppAttributes.Draggable, draggable);
201
+ }),
202
+ box._resizable$.reaction((resizable, skipUpdate) => {
203
+ if (skipUpdate) {
204
+ return;
205
+ }
206
+ this.store.updateAppState(this.id, AppAttributes.Resizable, resizable);
207
+ }),
208
+ ])
209
+ });
154
210
  }
155
211
 
156
212
  public fireMemberStateChange = () => {
@@ -301,7 +357,7 @@ export class AppProxy implements PageRemoveService {
301
357
  this.appContext = context;
302
358
  try {
303
359
  emitter.once(`${appId}${Events.WindowCreated}` as any).then(async () => {
304
- let boxInitState: AppInitState | undefined;
360
+ let boxInitState: AppState | undefined;
305
361
  if (!skipUpdate) {
306
362
  boxInitState = this.getAppInitState(appId);
307
363
  this.boxManager?.updateBoxState(boxInitState);
@@ -327,6 +383,11 @@ export class AppProxy implements PageRemoveService {
327
383
  this.box$.setValue(box);
328
384
  if (this.isAddApp && this.box) {
329
385
  this.store.updateAppState(appId, AppAttributes.ZIndex, this.box.zIndex);
386
+ this.store.updateAppState(appId, AppAttributes.Visible, this.box.visible);
387
+ this.store.updateAppState(appId, AppAttributes.Ratio, this.box.ratio);
388
+ this.store.updateAppState(appId, AppAttributes.StageRatio, this.box.stageRatio);
389
+ this.store.updateAppState(appId, AppAttributes.Draggable, this.box.draggable);
390
+ this.store.updateAppState(appId, AppAttributes.Resizable, this.box.resizable);
330
391
  this.boxManager.focusBox({ appId }, false);
331
392
  }
332
393
  } catch (error: any) {
@@ -391,30 +452,18 @@ export class AppProxy implements PageRemoveService {
391
452
  }
392
453
  }
393
454
 
394
- public getAppInitState = (id: string) => {
455
+ public getAppInitState = (id: string): AppState | undefined => {
395
456
  const attrs = this.store.getAppState(id);
396
457
  if (!attrs) return;
397
- const position = attrs?.[AppAttributes.Position];
398
458
  const focus = this.store.focus;
399
- const size = attrs?.[AppAttributes.Size];
400
- const sceneIndex = attrs?.[AppAttributes.SceneIndex];
401
459
  const maximized = this.attributes?.["maximized"];
402
460
  const minimized = this.attributes?.["minimized"];
403
- const zIndex = attrs?.zIndex;
404
- let payload = { maximized, minimized, zIndex } as AppInitState;
405
- if (position) {
406
- payload = { ...payload, id: id, x: position.x, y: position.y };
407
- }
461
+ let payload = { maximized, minimized, id } as AppState;
462
+ const state = omitBy(attrs, isUndefined);
408
463
  if (focus === id) {
409
464
  payload = { ...payload, focus: true };
410
465
  }
411
- if (size) {
412
- payload = { ...payload, width: size.width, height: size.height };
413
- }
414
- if (sceneIndex) {
415
- payload = { ...payload, sceneIndex };
416
- }
417
- return payload;
466
+ return Object.assign(payload, state);;
418
467
  };
419
468
 
420
469
  public emitAppSceneStateChange(sceneState: SceneState) {
@@ -686,3 +735,16 @@ export class AppProxy implements PageRemoveService {
686
735
  return this.destroy(true, true, false);
687
736
  }
688
737
  }
738
+
739
+
740
+ const createValSync = (expr: any, Val: Val): (() => void) => {
741
+ return reaction(
742
+ expr,
743
+ val => {
744
+ if (Val.value !== val && val !== undefined) {
745
+ Val.setValue(val, true);
746
+ }
747
+ },
748
+ { fireImmediately: true }
749
+ );
750
+ };
package/src/App/index.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from "./AppProxy";
2
2
  export * from "./AppContext";
3
3
  export * from "./WhiteboardView";
4
+ export * from "./type";
@@ -0,0 +1,22 @@
1
+
2
+ export type AppState = {
3
+ id: string;
4
+ focus?: boolean;
5
+ SceneIndex?: number;
6
+ draggable?: boolean;
7
+ position?: {
8
+ x: number;
9
+ y: number;
10
+ }
11
+ ratio?: number;
12
+ resizable?: boolean;
13
+ size?: {
14
+ width: number;
15
+ height: number;
16
+ }
17
+ stageRatio?: number;
18
+ visible?: boolean;
19
+ zIndex?: number;
20
+ maximized: boolean | null;
21
+ minimized: boolean | null;
22
+ }
package/src/AppManager.ts CHANGED
@@ -30,6 +30,7 @@ import {
30
30
  removeScenes,
31
31
  setScenePath,
32
32
  setViewFocusScenePath,
33
+ wait,
33
34
  } from "./Utils/Common";
34
35
  import type { ReconnectRefresher } from "./ReconnectRefresher";
35
36
  import type { BoxManager } from "./BoxManager";
@@ -568,7 +569,10 @@ export class AppManager {
568
569
  public bindMainView(divElement: HTMLDivElement, disableCameraTransform: boolean) {
569
570
  const mainView = this.mainViewProxy.view;
570
571
  mainView.disableCameraTransform = disableCameraTransform;
571
- mainView.divElement = divElement;
572
+ // 延迟挂载 mainView dom, 避免因为同步 camera 的闪动
573
+ wait(30).then(() => {
574
+ mainView.divElement = divElement;
575
+ });
572
576
  if (!mainView.focusScenePath) {
573
577
  this.setMainViewFocusPath();
574
578
  }
package/src/BoxManager.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import { AppAttributes, Events, MIN_HEIGHT, MIN_WIDTH } from "./constants";
2
2
  import { debounce } from "lodash";
3
+ import { SideEffectManager } from "side-effect-manager";
3
4
  import { TELE_BOX_STATE, TeleBoxManager } from "@netless/telebox-insider";
4
5
  import { WindowManager } from "./index";
5
6
  import type { BoxEmitterType } from "./BoxEmitter";
6
- import type { AddAppOptions, AppInitState } from "./index";
7
+ import type { AddAppOptions } from "./index";
7
8
  import type {
8
9
  TeleBoxManagerUpdateConfig,
9
10
  TeleBoxManagerCreateConfig,
@@ -18,7 +19,7 @@ import type { NetlessApp } from "./typings";
18
19
  import type { View } from "white-web-sdk";
19
20
  import type { CallbacksType } from "./callback";
20
21
  import type { EmitterType } from "./InternalEmitter";
21
- import { SideEffectManager } from "side-effect-manager";
22
+ import type { AppState } from "./App/type";
22
23
 
23
24
  export { TELE_BOX_STATE };
24
25
 
@@ -294,17 +295,17 @@ export class BoxManager {
294
295
  return this.teleBoxManager.topBox;
295
296
  }
296
297
 
297
- public updateBoxState(state?: AppInitState): void {
298
+ public updateBoxState(state?: AppState): void {
298
299
  if (!state) return;
299
300
  const box = this.getBox(state.id);
300
301
  if (box) {
301
302
  this.teleBoxManager.update(
302
303
  box.id,
303
304
  {
304
- x: state.x,
305
- y: state.y,
306
- width: state.width || 0.5,
307
- height: state.height || 0.5,
305
+ x: state.position?.x,
306
+ y: state.position?.y,
307
+ width: state.size?.width || 0.5,
308
+ height: state.size?.height || 0.5,
308
309
  zIndex: state.zIndex,
309
310
  },
310
311
  true
@@ -23,7 +23,6 @@ export type MoveCursorParams = {
23
23
  };
24
24
 
25
25
  export class CursorManager {
26
- public containerRect?: DOMRect;
27
26
  public wrapperRect?: DOMRect;
28
27
  public cursorInstances: Map<string, Cursor> = new Map();
29
28
  public roomMembers?: readonly RoomMember[];
@@ -168,7 +167,6 @@ export class CursorManager {
168
167
  };
169
168
 
170
169
  public updateContainerRect() {
171
- this.containerRect = WindowManager.container?.getBoundingClientRect();
172
170
  this.wrapperRect = WindowManager.playground?.getBoundingClientRect();
173
171
  }
174
172
 
@@ -1,6 +1,6 @@
1
1
  import Emittery from "emittery";
2
2
  import type { TeleBoxRect } from "@netless/telebox-insider";
3
- import type { AppInitState, CursorMovePayload } from "./index";
3
+ import type { CursorMovePayload } from "./index";
4
4
  import type { Member } from "./Helper";
5
5
  import type { MemberState } from "white-web-sdk";
6
6
 
@@ -11,7 +11,6 @@ export type RemoveSceneParams = {
11
11
 
12
12
  export type EmitterEvent = {
13
13
  onCreated: undefined;
14
- InitReplay: AppInitState;
15
14
  error: Error;
16
15
  seekStart: undefined;
17
16
  seek: number;
@@ -1,6 +1,6 @@
1
- import { listenUpdated, unlistenUpdated, reaction, UpdateEventKind } from "white-web-sdk";
2
- import type { AkkoObjectUpdatedProperty , AkkoObjectUpdatedListener } from "white-web-sdk";
3
1
  import { isObject } from "lodash";
2
+ import { listenUpdated, reaction, unlistenUpdated, UpdateEventKind } from "white-web-sdk";
3
+ import type { AkkoObjectUpdatedProperty, AkkoObjectUpdatedListener } from "white-web-sdk";
4
4
 
5
5
  // 兼容 13 和 14 版本 SDK
6
6
  export const onObjectByEvent = (event: UpdateEventKind) => {
@@ -12,7 +12,7 @@ export const onObjectByEvent = (event: UpdateEventKind) => {
12
12
  if (kinds.includes(event)) {
13
13
  func();
14
14
  }
15
- }
15
+ };
16
16
  listenUpdated(object, listener);
17
17
  func();
18
18
  return () => unlistenUpdated(object, listener);
@@ -21,43 +21,44 @@ export const onObjectByEvent = (event: UpdateEventKind) => {
21
21
  () => object,
22
22
  () => {
23
23
  func();
24
- }, {
24
+ },
25
+ {
25
26
  fireImmediately: true,
26
27
  }
27
- )
28
+ );
28
29
  }
29
- }
30
- }
30
+ };
31
+ };
31
32
 
32
33
  export const safeListenPropsUpdated = <T>(
33
34
  getProps: () => T,
34
35
  callback: AkkoObjectUpdatedListener<T>,
35
36
  onDestroyed?: (props: unknown) => void
36
- ) => {
37
+ ) => {
37
38
  let disposeListenUpdated: (() => void) | null = null;
38
39
  const disposeReaction = reaction(
39
- getProps,
40
- () => {
41
- if (disposeListenUpdated) {
42
- disposeListenUpdated();
43
- disposeListenUpdated = null;
44
- }
45
- const props = getProps();
46
- if (isObject(props)) {
47
- disposeListenUpdated = () => unlistenUpdated(props, callback);
48
- listenUpdated(props, callback);
49
- } else {
50
- onDestroyed?.(props);
51
- }
52
- },
53
- { fireImmediately: true }
40
+ getProps,
41
+ () => {
42
+ if (disposeListenUpdated) {
43
+ disposeListenUpdated();
44
+ disposeListenUpdated = null;
45
+ }
46
+ const props = getProps();
47
+ if (isObject(props)) {
48
+ disposeListenUpdated = () => unlistenUpdated(props, callback);
49
+ listenUpdated(props, callback);
50
+ } else {
51
+ onDestroyed?.(props);
52
+ }
53
+ },
54
+ { fireImmediately: true }
54
55
  );
55
56
 
56
57
  return () => {
57
- disposeListenUpdated?.();
58
- disposeReaction();
58
+ disposeListenUpdated?.();
59
+ disposeReaction();
59
60
  };
60
- }
61
+ };
61
62
 
62
63
  export const onObjectRemoved = onObjectByEvent(UpdateEventKind.Removed);
63
64
  export const onObjectInserted = onObjectByEvent(UpdateEventKind.Inserted);
@@ -1,4 +1,4 @@
1
- import { AnimationMode, ViewMode } from "white-web-sdk";
1
+ import { AnimationMode, toJS, ViewMode } from "white-web-sdk";
2
2
  import { CameraSynchronizer } from "./CameraSynchronizer";
3
3
  import { combine } from "value-enhancer";
4
4
  import { isEqual } from "lodash";
@@ -42,7 +42,7 @@ export class ViewSync {
42
42
  }
43
43
  });
44
44
  this.bindView(this.context.view$.value);
45
- this.sem.add(() =>
45
+ this.sem.add(() => [
46
46
  this.context.view$.subscribe(view => {
47
47
  const currentCamera = this.context.camera$.value;
48
48
  if (currentCamera && this.context.size$.value) {
@@ -54,30 +54,24 @@ export class ViewSync {
54
54
  }
55
55
 
56
56
  this.bindView(view);
57
- })
58
- );
59
- this.sem.add(() =>
57
+ }),
60
58
  this.context.camera$.subscribe((camera, skipUpdate) => {
61
59
  const size = this.context.size$.value;
62
60
  if (camera && size && !skipUpdate) {
63
61
  this.synchronizer.onRemoteUpdate(camera, size);
64
62
  }
65
- })
66
- );
67
- this.sem.add(() =>
63
+ }),
68
64
  this.context.size$.subscribe(size => {
69
65
  if (size) {
70
66
  this.synchronizer.onRemoteSizeUpdate(size);
71
67
  }
72
- })
73
- );
74
- this.sem.add(() =>
68
+ }),
75
69
  this.context.stageRect$.reaction(rect => {
76
70
  if (rect) {
77
71
  this.synchronizer.setRect(rect);
78
72
  }
79
73
  })
80
- );
74
+ ]);
81
75
  const camera$size$ = combine([this.context.camera$, this.context.size$]);
82
76
  camera$size$.reaction(([camera, size]) => {
83
77
  if (camera && size) {
@@ -99,7 +93,7 @@ export class ViewSync {
99
93
  };
100
94
 
101
95
  private onCameraUpdatedByDevice = (camera: Camera) => {
102
- this.synchronizer.onLocalCameraUpdate(Object.assign(camera, { id: this.context.uid }));
96
+ this.synchronizer.onLocalCameraUpdate(Object.assign(toJS(camera), { id: this.context.uid }));
103
97
  const stage = this.context.stageRect$.value;
104
98
  if (stage) {
105
99
  const size = { width: stage.width, height: stage.height, id: this.context.uid };
package/src/constants.ts CHANGED
@@ -5,7 +5,6 @@ export enum Events {
5
5
  AppBoxStateChange = "AppBoxStateChange",
6
6
  GetAttributes = "GetAttributes",
7
7
  UpdateWindowManagerWrapper = "UpdateWindowManagerWrapper",
8
- InitReplay = "InitReplay",
9
8
  WindowCreated = "WindowCreated",
10
9
  SetMainViewScenePath = "SetMainViewScenePath",
11
10
  SetMainViewSceneIndex = "SetMainViewSceneIndex",
@@ -27,6 +26,11 @@ export enum AppAttributes {
27
26
  Position = "position",
28
27
  SceneIndex = "SceneIndex",
29
28
  ZIndex = "zIndex",
29
+ Visible = "visible",
30
+ Ratio = "ratio",
31
+ StageRatio = "stageRatio",
32
+ Draggable = "draggable",
33
+ Resizable = "resizable",
30
34
  }
31
35
 
32
36
  export enum AppEvents {
package/src/index.ts CHANGED
@@ -121,6 +121,11 @@ export type AppInitState = {
121
121
  sceneIndex?: number;
122
122
  boxState?: TeleBoxState; // 兼容旧版 telebox
123
123
  zIndex?: number;
124
+ visible?: boolean;
125
+ stageRatio?: number;
126
+ resizable?: boolean;
127
+ draggable?: boolean;
128
+ ratio?: number;
124
129
  };
125
130
 
126
131
  export type CursorMovePayload = { uid: string; state?: "leave"; position: Position };