@netless/window-manager 1.0.0-canary.13 → 1.0.0-canary.16
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/dist/App/AppContext.d.ts +1 -3
- package/dist/App/AppProxy.d.ts +3 -2
- package/dist/App/WhiteboardView.d.ts +4 -4
- package/dist/AppManager.d.ts +2 -2
- package/dist/BoxManager.d.ts +1 -0
- package/dist/View/MainView.d.ts +13 -6
- package/dist/View/ViewSync.d.ts +24 -0
- package/dist/index.cjs.js +10 -10
- package/dist/index.d.ts +2 -0
- package/dist/index.es.js +181 -114
- package/dist/index.umd.js +12 -12
- package/dist/style.css +1 -1
- package/package.json +2 -2
- package/pnpm-lock.yaml +4 -4
- package/src/App/AppContext.ts +7 -8
- package/src/App/AppProxy.ts +21 -12
- package/src/App/WhiteboardView.ts +21 -10
- package/src/AppManager.ts +9 -8
- package/src/BoxManager.ts +4 -0
- package/src/PageState.ts +1 -1
- package/src/View/CameraSynchronizer.ts +8 -6
- package/src/View/MainView.ts +86 -52
- package/src/View/ViewSync.ts +121 -0
- package/src/index.ts +10 -5
- package/src/style.css +0 -1
- package/dist/App/AppViewSync.d.ts +0 -11
- package/src/App/AppViewSync.ts +0 -73
@@ -1,5 +1,5 @@
|
|
1
1
|
import { AnimationMode } from "white-web-sdk";
|
2
|
-
import { debounce, delay, throttle } from "lodash";
|
2
|
+
import { debounce, delay, isEqual, pick, throttle } from "lodash";
|
3
3
|
import type { TeleBoxRect } from "@netless/telebox-insider";
|
4
4
|
import type { Camera, View } from "white-web-sdk";
|
5
5
|
import type { ISize } from "../AttributesDelegate";
|
@@ -37,7 +37,6 @@ export class CameraSynchronizer {
|
|
37
37
|
scale = this.rect.height / size.height;
|
38
38
|
}
|
39
39
|
const nextScale = camera.scale * scale;
|
40
|
-
|
41
40
|
const moveCamera = () => {
|
42
41
|
this.view?.moveCamera({
|
43
42
|
centerX: camera.centerX,
|
@@ -46,26 +45,29 @@ export class CameraSynchronizer {
|
|
46
45
|
animationMode: AnimationMode.Immediately,
|
47
46
|
});
|
48
47
|
}
|
49
|
-
moveCamera();
|
48
|
+
moveCamera();
|
50
49
|
// TODO 直接调用 moveCamera 依然会出现 camera 错误的情况,这里暂时加一个 delay 保证 camera 是对的, 后续需要 SDK 进行修改
|
51
50
|
delay(moveCamera, 50);
|
52
51
|
}
|
53
52
|
}, 10);
|
54
53
|
|
55
54
|
public onRemoteSizeUpdate(size: ISize) {
|
56
|
-
|
57
|
-
|
55
|
+
this.remoteSize = size;
|
56
|
+
const needMoveCamera = !isEqual(pick(this.rect, ["width", "height"]), pick(size, ["width", "height"]));
|
57
|
+
if (this.rect && this.remoteCamera && needMoveCamera) {
|
58
|
+
const scale = this.rect.width / size.width;
|
59
|
+
const nextScale = this.remoteCamera.scale * scale;
|
58
60
|
const moveCamera = () => {
|
59
61
|
this.view?.moveCamera({
|
60
62
|
scale: nextScale,
|
61
63
|
animationMode: AnimationMode.Immediately,
|
62
64
|
})
|
63
65
|
};
|
66
|
+
moveCamera();
|
64
67
|
delay(moveCamera, 50);
|
65
68
|
}
|
66
69
|
}
|
67
70
|
|
68
|
-
|
69
71
|
public onLocalCameraUpdate(camera: Camera) {
|
70
72
|
this.saveCamera(camera);
|
71
73
|
this.remoteCamera = camera;
|
package/src/View/MainView.ts
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
import { callbacks } from "../callback";
|
2
|
-
import { CameraSynchronizer } from "./CameraSynchronizer";
|
3
2
|
import { createView } from "./ViewManager";
|
4
3
|
import { debounce, get, isEqual } from "lodash";
|
5
4
|
import { emitter } from "../InternalEmitter";
|
6
5
|
import { Events } from "../constants";
|
7
6
|
import { Fields } from "../AttributesDelegate";
|
8
|
-
import { reaction } from "white-web-sdk";
|
7
|
+
import { reaction, toJS } from "white-web-sdk";
|
9
8
|
import { releaseView, setViewFocusScenePath } from "../Utils/Common";
|
10
9
|
import { SideEffectManager } from "side-effect-manager";
|
11
|
-
import
|
10
|
+
import { Val } from "value-enhancer";
|
11
|
+
import { ViewSync } from "./ViewSync";
|
12
|
+
import type { ICamera, ISize } from "../AttributesDelegate";
|
13
|
+
import type { Size, View } from "white-web-sdk";
|
12
14
|
import type { AppManager } from "../AppManager";
|
13
15
|
|
14
16
|
export class MainViewProxy {
|
@@ -16,16 +18,17 @@ export class MainViewProxy {
|
|
16
18
|
private mainViewIsAddListener = false;
|
17
19
|
private mainView: View;
|
18
20
|
private store = this.manager.store;
|
19
|
-
private synchronizer: CameraSynchronizer;
|
20
21
|
|
21
22
|
private sideEffectManager = new SideEffectManager();
|
22
23
|
|
24
|
+
public camera$ = new Val<ICamera | undefined>(undefined);
|
25
|
+
public size$ = new Val<ISize | undefined>(undefined);
|
26
|
+
public view$ = new Val<View | undefined>(undefined);
|
27
|
+
|
28
|
+
public viewSync?: ViewSync;
|
29
|
+
|
23
30
|
constructor(private manager: AppManager) {
|
24
|
-
this.synchronizer = new CameraSynchronizer(camera =>
|
25
|
-
this.store.setMainViewCamera({ ...camera, id: this.manager.uid })
|
26
|
-
);
|
27
31
|
this.mainView = this.createMainView();
|
28
|
-
this.moveCameraSizeByAttributes();
|
29
32
|
emitter.once("mainViewMounted").then(() => {
|
30
33
|
this.addMainViewListener();
|
31
34
|
this.start();
|
@@ -33,20 +36,28 @@ export class MainViewProxy {
|
|
33
36
|
this.startListenWritableChange();
|
34
37
|
});
|
35
38
|
this.sideEffectManager.add(() => [
|
36
|
-
emitter.on("containerSizeRatioUpdate", this.onUpdateContainerSizeRatio),
|
37
39
|
emitter.on("startReconnect", () => {
|
38
40
|
releaseView(this.mainView);
|
39
41
|
}),
|
40
|
-
emitter.on("playgroundSizeChange", rect => {
|
41
|
-
this.synchronizer.setRect(rect);
|
42
|
-
})
|
43
42
|
]);
|
44
|
-
|
45
|
-
if (rect) {
|
46
|
-
this.synchronizer.setRect(rect);
|
47
|
-
}
|
43
|
+
this.createViewSync();
|
48
44
|
}
|
49
45
|
|
46
|
+
public createViewSync = () => {
|
47
|
+
if (this.manager.boxManager && !this.viewSync) {
|
48
|
+
this.viewSync = new ViewSync({
|
49
|
+
uid: this.manager.uid,
|
50
|
+
view$: this.view$,
|
51
|
+
camera$: this.camera$,
|
52
|
+
size$: this.size$,
|
53
|
+
stageRect$: this.manager.boxManager?.stageRect$,
|
54
|
+
viewMode$: this.manager.windowManger.viewMode$,
|
55
|
+
storeCamera: this.storeCamera,
|
56
|
+
storeSize: this.storeSize,
|
57
|
+
});
|
58
|
+
}
|
59
|
+
};
|
60
|
+
|
50
61
|
private startListenWritableChange = () => {
|
51
62
|
this.sideEffectManager.add(() =>
|
52
63
|
emitter.on("writableChange", isWritable => {
|
@@ -60,7 +71,18 @@ export class MainViewProxy {
|
|
60
71
|
public ensureCameraAndSize() {
|
61
72
|
if (!this.mainViewCamera || !this.mainViewSize) {
|
62
73
|
this.manager.dispatchInternalEvent(Events.InitMainViewCamera);
|
63
|
-
this.
|
74
|
+
this.storeCamera({
|
75
|
+
id: this.manager.uid,
|
76
|
+
...this.view.camera
|
77
|
+
});
|
78
|
+
const stageRect = this.manager.boxManager?.stageRect;
|
79
|
+
if (stageRect && !this.mainViewSize) {
|
80
|
+
this.storeSize({
|
81
|
+
id: this.manager.uid,
|
82
|
+
width: stageRect.width,
|
83
|
+
height: stageRect.height
|
84
|
+
});
|
85
|
+
}
|
64
86
|
}
|
65
87
|
}
|
66
88
|
|
@@ -76,10 +98,6 @@ export class MainViewProxy {
|
|
76
98
|
return get(this.view, ["didRelease"]);
|
77
99
|
}
|
78
100
|
|
79
|
-
private moveCameraSizeByAttributes() {
|
80
|
-
this.synchronizer.onRemoteUpdate(this.mainViewCamera, this.mainViewSize);
|
81
|
-
}
|
82
|
-
|
83
101
|
public start() {
|
84
102
|
if (this.started) return;
|
85
103
|
this.addCameraListener();
|
@@ -89,34 +107,64 @@ export class MainViewProxy {
|
|
89
107
|
|
90
108
|
public addCameraReaction = () => {
|
91
109
|
this.manager.refresher.add(Fields.MainViewCamera, this.cameraReaction);
|
110
|
+
this.manager.refresher.add(Fields.MainViewSize, this.sizeReaction);
|
92
111
|
};
|
93
112
|
|
94
|
-
public
|
95
|
-
const
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
113
|
+
public storeCurrentCamera = () => {
|
114
|
+
const iCamera = this.view.camera;
|
115
|
+
this.storeCamera({
|
116
|
+
id: this.manager.uid,
|
117
|
+
...iCamera
|
118
|
+
});
|
119
|
+
}
|
120
|
+
|
121
|
+
public storeCurrentSize = () => {
|
122
|
+
const rect = this.manager.boxManager?.stageRect;
|
123
|
+
if (rect) {
|
124
|
+
this.storeSize({
|
125
|
+
id: this.manager.uid,
|
126
|
+
width: rect.width,
|
127
|
+
height: rect.height
|
128
|
+
});
|
100
129
|
}
|
101
130
|
}
|
102
131
|
|
132
|
+
public storeCamera = (camera: ICamera) => {
|
133
|
+
this.store.setMainViewCamera(camera);
|
134
|
+
};
|
135
|
+
|
136
|
+
public storeSize = (size: ISize) => {
|
137
|
+
this.store.setMainViewSize(size);
|
138
|
+
};
|
139
|
+
|
103
140
|
private cameraReaction = () => {
|
104
141
|
return reaction(
|
105
142
|
() => this.mainViewCamera,
|
106
143
|
camera => {
|
107
|
-
if (camera
|
108
|
-
|
144
|
+
if (camera) {
|
145
|
+
const rawCamera = toJS(camera);
|
146
|
+
if (!isEqual(rawCamera, this.camera$.value)) {
|
147
|
+
this.camera$.setValue(rawCamera);
|
148
|
+
}
|
109
149
|
}
|
110
150
|
},
|
111
151
|
{ fireImmediately: true }
|
112
152
|
);
|
113
153
|
};
|
114
154
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
155
|
+
private sizeReaction = () => {
|
156
|
+
return reaction(
|
157
|
+
() => this.mainViewSize,
|
158
|
+
size => {
|
159
|
+
if (size) {
|
160
|
+
const rawSize = toJS(size);
|
161
|
+
if (!isEqual(rawSize, this.size$.value)) {
|
162
|
+
this.size$.setValue(rawSize);
|
163
|
+
}
|
164
|
+
}
|
165
|
+
},
|
166
|
+
{ fireImmediately: true }
|
167
|
+
);
|
120
168
|
};
|
121
169
|
|
122
170
|
public get view(): View {
|
@@ -133,7 +181,7 @@ export class MainViewProxy {
|
|
133
181
|
if (mainViewScenePath) {
|
134
182
|
setViewFocusScenePath(mainView, mainViewScenePath);
|
135
183
|
}
|
136
|
-
this.
|
184
|
+
this.view$.setValue(mainView);
|
137
185
|
return mainView;
|
138
186
|
}
|
139
187
|
|
@@ -165,21 +213,6 @@ export class MainViewProxy {
|
|
165
213
|
this.start();
|
166
214
|
}
|
167
215
|
|
168
|
-
private onCameraUpdatedByDevice = (camera: Camera) => {
|
169
|
-
this.synchronizer.onLocalCameraUpdate(camera);
|
170
|
-
const size = this.getStageSize();
|
171
|
-
if (size && !isEqual(size, this.mainViewSize)) {
|
172
|
-
this.setMainViewSize(size);
|
173
|
-
}
|
174
|
-
};
|
175
|
-
|
176
|
-
private getStageSize(): Size | undefined {
|
177
|
-
const stage = this.manager.boxManager?.stageRect;
|
178
|
-
if (stage) {
|
179
|
-
return { width: stage.width, height: stage.height };
|
180
|
-
}
|
181
|
-
}
|
182
|
-
|
183
216
|
public addMainViewListener(): void {
|
184
217
|
if (this.mainViewIsAddListener) return;
|
185
218
|
if (this.view.divElement) {
|
@@ -212,13 +245,11 @@ export class MainViewProxy {
|
|
212
245
|
}, 50);
|
213
246
|
|
214
247
|
private addCameraListener() {
|
215
|
-
this.view.callbacks.on("onCameraUpdatedByDevice", this.onCameraUpdatedByDevice);
|
216
248
|
this.view.callbacks.on("onCameraUpdated", this.onCameraOrSizeUpdated);
|
217
249
|
this.view.callbacks.on("onSizeUpdated", this.onCameraOrSizeUpdated);
|
218
250
|
}
|
219
251
|
|
220
252
|
private removeCameraListener() {
|
221
|
-
this.view.callbacks.off("onCameraUpdatedByDevice", this.onCameraUpdatedByDevice);
|
222
253
|
this.view.callbacks.off("onCameraUpdated", this.onCameraOrSizeUpdated);
|
223
254
|
this.view.callbacks.off("onSizeUpdated", this.onCameraOrSizeUpdated);
|
224
255
|
}
|
@@ -235,6 +266,9 @@ export class MainViewProxy {
|
|
235
266
|
}
|
236
267
|
|
237
268
|
public destroy() {
|
269
|
+
this.camera$.destroy();
|
270
|
+
this.size$.destroy();
|
271
|
+
this.view$.destroy();
|
238
272
|
this.removeMainViewListener();
|
239
273
|
this.stop();
|
240
274
|
this.sideEffectManager.flushAll();
|
@@ -0,0 +1,121 @@
|
|
1
|
+
import { AnimationMode, ViewMode } from "white-web-sdk";
|
2
|
+
import { CameraSynchronizer } from "./CameraSynchronizer";
|
3
|
+
import { combine } from "value-enhancer";
|
4
|
+
import { isEqual } from "lodash";
|
5
|
+
import { SideEffectManager } from "side-effect-manager";
|
6
|
+
import type { Camera, View } from "white-web-sdk";
|
7
|
+
import type { Val, ReadonlyVal } from "value-enhancer";
|
8
|
+
import type { ICamera, ISize } from "../AttributesDelegate";
|
9
|
+
import type { TeleBoxRect } from "@netless/telebox-insider";
|
10
|
+
|
11
|
+
export type ViewSyncContext = {
|
12
|
+
uid: string;
|
13
|
+
// 远端 camera
|
14
|
+
camera$: Val<ICamera | undefined, boolean>;
|
15
|
+
// 远端 size
|
16
|
+
size$: Val<ISize | undefined>;
|
17
|
+
|
18
|
+
stageRect$: ReadonlyVal<TeleBoxRect>;
|
19
|
+
|
20
|
+
viewMode$?: Val<ViewMode>;
|
21
|
+
|
22
|
+
storeCamera: (camera: ICamera) => void;
|
23
|
+
|
24
|
+
storeSize: (size: ISize) => void;
|
25
|
+
|
26
|
+
view$: Val<View | undefined>;
|
27
|
+
};
|
28
|
+
|
29
|
+
export class ViewSync {
|
30
|
+
private sem = new SideEffectManager();
|
31
|
+
private synchronizer: CameraSynchronizer;
|
32
|
+
|
33
|
+
constructor(private context: ViewSyncContext) {
|
34
|
+
this.synchronizer = new CameraSynchronizer((camera: Camera) => {
|
35
|
+
const iCamera = {
|
36
|
+
id: this.context.uid,
|
37
|
+
...camera,
|
38
|
+
}
|
39
|
+
this.context.camera$.setValue(iCamera, true);
|
40
|
+
const notStoreCamera = this.context.viewMode$ && this.context.viewMode$.value === ViewMode.Freedom;
|
41
|
+
if (notStoreCamera) {
|
42
|
+
return;
|
43
|
+
} else {
|
44
|
+
this.context.storeCamera(iCamera);
|
45
|
+
}
|
46
|
+
});
|
47
|
+
this.bindView(this.context.view$.value);
|
48
|
+
this.sem.add(() =>
|
49
|
+
this.context.view$.subscribe(view => {
|
50
|
+
const currentCamera = this.context.camera$.value;
|
51
|
+
if (currentCamera && this.context.size$.value) {
|
52
|
+
view?.moveCamera({
|
53
|
+
scale: 1,
|
54
|
+
animationMode: AnimationMode.Immediately,
|
55
|
+
});
|
56
|
+
this.synchronizer.onRemoteUpdate(currentCamera, this.context.size$.value);
|
57
|
+
}
|
58
|
+
|
59
|
+
this.bindView(view);
|
60
|
+
})
|
61
|
+
);
|
62
|
+
this.sem.add(() =>
|
63
|
+
this.context.camera$.subscribe((camera, skipUpdate) => {
|
64
|
+
const size = this.context.size$.value;
|
65
|
+
if (camera && size && !skipUpdate) {
|
66
|
+
this.synchronizer.onRemoteUpdate(camera, size);
|
67
|
+
}
|
68
|
+
})
|
69
|
+
);
|
70
|
+
this.sem.add(() =>
|
71
|
+
this.context.size$.subscribe(size => {
|
72
|
+
if (size) {
|
73
|
+
this.synchronizer.onRemoteSizeUpdate(size);
|
74
|
+
}
|
75
|
+
})
|
76
|
+
);
|
77
|
+
if (this.context.stageRect$.value) {
|
78
|
+
this.synchronizer.setRect(this.context.stageRect$.value);
|
79
|
+
this.sem.add(() =>
|
80
|
+
this.context.stageRect$.subscribe(rect => {
|
81
|
+
if (rect) {
|
82
|
+
this.synchronizer.setRect(rect);
|
83
|
+
}
|
84
|
+
})
|
85
|
+
);
|
86
|
+
}
|
87
|
+
const camera$size$ = combine([this.context.camera$, this.context.size$]);
|
88
|
+
camera$size$.subscribe(([camera, size]) => {
|
89
|
+
if (camera && size) {
|
90
|
+
this.synchronizer.onRemoteUpdate(camera, size);
|
91
|
+
camera$size$.destroy();
|
92
|
+
}
|
93
|
+
});
|
94
|
+
}
|
95
|
+
|
96
|
+
public bindView = (view?: View) => {
|
97
|
+
if (!view) return;
|
98
|
+
this.synchronizer.setView(view);
|
99
|
+
this.sem.flush("view");
|
100
|
+
this.sem.add(() => {
|
101
|
+
view.callbacks.on("onCameraUpdatedByDevice", this.onCameraUpdatedByDevice);
|
102
|
+
return () =>
|
103
|
+
view.callbacks.off("onCameraUpdatedByDevice", this.onCameraUpdatedByDevice);
|
104
|
+
}, "view");
|
105
|
+
};
|
106
|
+
|
107
|
+
private onCameraUpdatedByDevice = (camera: Camera) => {
|
108
|
+
this.synchronizer.onLocalCameraUpdate(camera);
|
109
|
+
const stage = this.context.stageRect$.value;
|
110
|
+
if (stage) {
|
111
|
+
const size = { width: stage.width, height: stage.height, id: this.context.uid };
|
112
|
+
if (!isEqual(size, this.context.size$.value)) {
|
113
|
+
this.context.storeSize(size);
|
114
|
+
}
|
115
|
+
}
|
116
|
+
};
|
117
|
+
|
118
|
+
public destroy() {
|
119
|
+
this.sem.flushAll();
|
120
|
+
}
|
121
|
+
}
|
package/src/index.ts
CHANGED
@@ -54,6 +54,7 @@ import type { PublicEvent } from "./callback";
|
|
54
54
|
import type Emittery from "emittery";
|
55
55
|
import type { PageController, AddPageParams, PageState } from "./Page";
|
56
56
|
import { boxEmitter } from "./BoxEmitter";
|
57
|
+
import { Val } from "value-enhancer";
|
57
58
|
|
58
59
|
export type WindowMangerAttributes = {
|
59
60
|
modelValue?: string;
|
@@ -162,6 +163,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
162
163
|
public appManager?: AppManager;
|
163
164
|
public cursorManager?: CursorManager;
|
164
165
|
public viewMode = ViewMode.Broadcaster;
|
166
|
+
public viewMode$ = new Val<ViewMode>(ViewMode.Broadcaster);
|
165
167
|
public isReplay = isPlayer(this.displayer);
|
166
168
|
private _pageState?: PageStateImpl;
|
167
169
|
|
@@ -592,16 +594,19 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
592
594
|
* 设置 ViewMode
|
593
595
|
*/
|
594
596
|
public setViewMode(mode: ViewMode): void {
|
597
|
+
log("setViewMode", mode);
|
598
|
+
const mainViewProxy = this.appManager?.mainViewProxy;
|
595
599
|
if (mode === ViewMode.Broadcaster) {
|
596
600
|
if (this.canOperate) {
|
597
|
-
|
601
|
+
mainViewProxy?.storeCurrentCamera();
|
598
602
|
}
|
599
|
-
|
603
|
+
mainViewProxy?.start();
|
600
604
|
}
|
601
605
|
if (mode === ViewMode.Freedom) {
|
602
|
-
|
606
|
+
mainViewProxy?.stop();
|
603
607
|
}
|
604
608
|
this.viewMode = mode;
|
609
|
+
this.viewMode$.setValue(mode);
|
605
610
|
}
|
606
611
|
|
607
612
|
public setBoxState(boxState: TeleBoxState): void {
|
@@ -764,7 +769,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
764
769
|
this.mainView.moveCamera(camera);
|
765
770
|
this.appManager?.dispatchInternalEvent(Events.MoveCamera, camera);
|
766
771
|
setTimeout(() => {
|
767
|
-
this.appManager?.mainViewProxy.
|
772
|
+
this.appManager?.mainViewProxy.storeCurrentCamera();
|
768
773
|
}, 500);
|
769
774
|
}
|
770
775
|
|
@@ -777,7 +782,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
777
782
|
this.mainView.moveCameraToContain(rectangle);
|
778
783
|
this.appManager?.dispatchInternalEvent(Events.MoveCameraToContain, rectangle);
|
779
784
|
setTimeout(() => {
|
780
|
-
this.appManager?.mainViewProxy.
|
785
|
+
this.appManager?.mainViewProxy.storeCurrentCamera();
|
781
786
|
}, 500);
|
782
787
|
}
|
783
788
|
|
package/src/style.css
CHANGED
@@ -1,11 +0,0 @@
|
|
1
|
-
import type { View } from "white-web-sdk";
|
2
|
-
import type { AppProxy } from "./AppProxy";
|
3
|
-
export declare class AppViewSync {
|
4
|
-
private appProxy;
|
5
|
-
private sem;
|
6
|
-
private synchronizer;
|
7
|
-
constructor(appProxy: AppProxy);
|
8
|
-
bindView: (view?: View | undefined) => void;
|
9
|
-
private onCameraUpdatedByDevice;
|
10
|
-
destroy(): void;
|
11
|
-
}
|
package/src/App/AppViewSync.ts
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
import { CameraSynchronizer } from "../View/CameraSynchronizer";
|
2
|
-
import { SideEffectManager } from "side-effect-manager";
|
3
|
-
import type { Camera, View } from "white-web-sdk";
|
4
|
-
import type { AppProxy } from "./AppProxy";
|
5
|
-
import { isEqual } from "lodash";
|
6
|
-
import { combine } from "value-enhancer";
|
7
|
-
|
8
|
-
export class AppViewSync {
|
9
|
-
private sem = new SideEffectManager();
|
10
|
-
private synchronizer: CameraSynchronizer;
|
11
|
-
|
12
|
-
constructor(private appProxy: AppProxy) {
|
13
|
-
this.synchronizer = new CameraSynchronizer((camera: Camera) => {
|
14
|
-
this.appProxy.storeCamera({
|
15
|
-
id: this.appProxy.uid,
|
16
|
-
...camera,
|
17
|
-
});
|
18
|
-
});
|
19
|
-
this.bindView(appProxy.view);
|
20
|
-
this.sem.add(() => this.appProxy.camera$.subscribe(camera => {
|
21
|
-
const size = this.appProxy.size$.value;
|
22
|
-
if (camera && size) {
|
23
|
-
this.synchronizer.onRemoteUpdate(camera, size);
|
24
|
-
}
|
25
|
-
}));
|
26
|
-
this.sem.add(() => this.appProxy.size$.subscribe(size => {
|
27
|
-
if (size) {
|
28
|
-
this.synchronizer.onRemoteSizeUpdate(size);
|
29
|
-
}
|
30
|
-
}));
|
31
|
-
const box = this.appProxy.box;
|
32
|
-
if (box && box.contentStageRect) {
|
33
|
-
this.synchronizer.setRect(box.contentStageRect);
|
34
|
-
this.sem.add(() =>
|
35
|
-
box._contentStageRect$.subscribe(rect => {
|
36
|
-
if (rect) {
|
37
|
-
this.synchronizer.setRect(rect);
|
38
|
-
}
|
39
|
-
}),
|
40
|
-
);
|
41
|
-
}
|
42
|
-
this.sem.add(() => combine([this.appProxy.camera$, this.appProxy.size$]).subscribe(([camera, size]) => {
|
43
|
-
if (camera && size) {
|
44
|
-
this.synchronizer.onRemoteUpdate(camera, size);
|
45
|
-
}
|
46
|
-
}));
|
47
|
-
}
|
48
|
-
|
49
|
-
public bindView = (view?: View) => {
|
50
|
-
if (!view) return;
|
51
|
-
this.synchronizer.setView(view);
|
52
|
-
this.sem.add(() => {
|
53
|
-
view.callbacks.on("onCameraUpdatedByDevice", this.onCameraUpdatedByDevice);
|
54
|
-
return () =>
|
55
|
-
view.callbacks.off("onCameraUpdatedByDevice", this.onCameraUpdatedByDevice);
|
56
|
-
});
|
57
|
-
};
|
58
|
-
|
59
|
-
private onCameraUpdatedByDevice = (camera: Camera) => {
|
60
|
-
this.synchronizer.onLocalCameraUpdate(camera);
|
61
|
-
const stage = this.appProxy.box?.contentStageRect;
|
62
|
-
if (stage) {
|
63
|
-
const size = { width: stage.width, height: stage.height, id: this.appProxy.uid };
|
64
|
-
if (!isEqual(size, this.appProxy.size$.value)) {
|
65
|
-
this.appProxy.storeSize(size);
|
66
|
-
}
|
67
|
-
}
|
68
|
-
};
|
69
|
-
|
70
|
-
public destroy() {
|
71
|
-
this.sem.flushAll();
|
72
|
-
}
|
73
|
-
}
|