@netless/window-manager 1.0.0-canary.15 → 1.0.0-canary.18
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 +2 -4
- package/dist/App/AppProxy.d.ts +1 -1
- package/dist/App/WhiteboardView.d.ts +1 -3
- 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 +7 -0
- package/dist/index.es.js +216 -128
- 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 +3 -10
- package/src/App/AppProxy.ts +28 -16
- package/src/App/WhiteboardView.ts +0 -7
- package/src/AppManager.ts +1 -1
- package/src/BoxManager.ts +4 -0
- package/src/ReconnectRefresher.ts +1 -1
- package/src/Utils/RoomHacker.ts +3 -0
- package/src/View/CameraSynchronizer.ts +7 -5
- package/src/View/MainView.ts +95 -53
- package/src/View/ViewSync.ts +119 -0
- package/src/index.ts +28 -5
- package/src/style.css +0 -1
- package/dist/App/AppViewSync.d.ts +0 -11
- package/src/App/AppViewSync.ts +0 -73
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";
|
9
|
-
import { releaseView, setViewFocusScenePath } from "../Utils/Common";
|
7
|
+
import { reaction, toJS } from "white-web-sdk";
|
8
|
+
import { releaseView, setScenePath, 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,36 @@ 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
|
-
|
46
|
-
|
47
|
-
|
43
|
+
this.createViewSync();
|
44
|
+
this.sideEffectManager.add(() => emitter.on("focusedChange", ({ focused }) => {
|
45
|
+
if (focused === undefined) {
|
46
|
+
const scenePath = this.store.getMainViewScenePath();
|
47
|
+
if (scenePath) {
|
48
|
+
setScenePath(this.manager.room, scenePath);
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}));
|
48
52
|
}
|
49
53
|
|
54
|
+
public createViewSync = () => {
|
55
|
+
if (this.manager.boxManager && !this.viewSync) {
|
56
|
+
this.viewSync = new ViewSync({
|
57
|
+
uid: this.manager.uid,
|
58
|
+
view$: this.view$,
|
59
|
+
camera$: this.camera$,
|
60
|
+
size$: this.size$,
|
61
|
+
stageRect$: this.manager.boxManager?.stageRect$,
|
62
|
+
viewMode$: this.manager.windowManger.viewMode$,
|
63
|
+
storeCamera: this.storeCamera,
|
64
|
+
storeSize: this.storeSize,
|
65
|
+
});
|
66
|
+
}
|
67
|
+
};
|
68
|
+
|
50
69
|
private startListenWritableChange = () => {
|
51
70
|
this.sideEffectManager.add(() =>
|
52
71
|
emitter.on("writableChange", isWritable => {
|
@@ -60,7 +79,18 @@ export class MainViewProxy {
|
|
60
79
|
public ensureCameraAndSize() {
|
61
80
|
if (!this.mainViewCamera || !this.mainViewSize) {
|
62
81
|
this.manager.dispatchInternalEvent(Events.InitMainViewCamera);
|
63
|
-
this.
|
82
|
+
this.storeCamera({
|
83
|
+
id: this.manager.uid,
|
84
|
+
...this.view.camera
|
85
|
+
});
|
86
|
+
const stageRect = this.manager.boxManager?.stageRect;
|
87
|
+
if (stageRect && !this.mainViewSize) {
|
88
|
+
this.storeSize({
|
89
|
+
id: this.manager.uid,
|
90
|
+
width: stageRect.width,
|
91
|
+
height: stageRect.height
|
92
|
+
});
|
93
|
+
}
|
64
94
|
}
|
65
95
|
}
|
66
96
|
|
@@ -76,10 +106,6 @@ export class MainViewProxy {
|
|
76
106
|
return get(this.view, ["didRelease"]);
|
77
107
|
}
|
78
108
|
|
79
|
-
private moveCameraSizeByAttributes() {
|
80
|
-
this.synchronizer.onRemoteUpdate(this.mainViewCamera, this.mainViewSize);
|
81
|
-
}
|
82
|
-
|
83
109
|
public start() {
|
84
110
|
if (this.started) return;
|
85
111
|
this.addCameraListener();
|
@@ -89,34 +115,64 @@ export class MainViewProxy {
|
|
89
115
|
|
90
116
|
public addCameraReaction = () => {
|
91
117
|
this.manager.refresher.add(Fields.MainViewCamera, this.cameraReaction);
|
118
|
+
this.manager.refresher.add(Fields.MainViewSize, this.sizeReaction);
|
92
119
|
};
|
93
120
|
|
94
|
-
public
|
95
|
-
const
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
121
|
+
public storeCurrentCamera = () => {
|
122
|
+
const iCamera = this.view.camera;
|
123
|
+
this.storeCamera({
|
124
|
+
id: this.manager.uid,
|
125
|
+
...iCamera
|
126
|
+
});
|
127
|
+
}
|
128
|
+
|
129
|
+
public storeCurrentSize = () => {
|
130
|
+
const rect = this.manager.boxManager?.stageRect;
|
131
|
+
if (rect) {
|
132
|
+
this.storeSize({
|
133
|
+
id: this.manager.uid,
|
134
|
+
width: rect.width,
|
135
|
+
height: rect.height
|
136
|
+
});
|
100
137
|
}
|
101
138
|
}
|
102
139
|
|
140
|
+
public storeCamera = (camera: ICamera) => {
|
141
|
+
this.store.setMainViewCamera(camera);
|
142
|
+
};
|
143
|
+
|
144
|
+
public storeSize = (size: ISize) => {
|
145
|
+
this.store.setMainViewSize(size);
|
146
|
+
};
|
147
|
+
|
103
148
|
private cameraReaction = () => {
|
104
149
|
return reaction(
|
105
150
|
() => this.mainViewCamera,
|
106
151
|
camera => {
|
107
|
-
if (camera
|
108
|
-
|
152
|
+
if (camera) {
|
153
|
+
const rawCamera = toJS(camera);
|
154
|
+
if (!isEqual(rawCamera, this.camera$.value)) {
|
155
|
+
this.camera$.setValue(rawCamera);
|
156
|
+
}
|
109
157
|
}
|
110
158
|
},
|
111
159
|
{ fireImmediately: true }
|
112
160
|
);
|
113
161
|
};
|
114
162
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
163
|
+
private sizeReaction = () => {
|
164
|
+
return reaction(
|
165
|
+
() => this.mainViewSize,
|
166
|
+
size => {
|
167
|
+
if (size) {
|
168
|
+
const rawSize = toJS(size);
|
169
|
+
if (!isEqual(rawSize, this.size$.value)) {
|
170
|
+
this.size$.setValue(rawSize);
|
171
|
+
}
|
172
|
+
}
|
173
|
+
},
|
174
|
+
{ fireImmediately: true }
|
175
|
+
);
|
120
176
|
};
|
121
177
|
|
122
178
|
public get view(): View {
|
@@ -133,7 +189,7 @@ export class MainViewProxy {
|
|
133
189
|
if (mainViewScenePath) {
|
134
190
|
setViewFocusScenePath(mainView, mainViewScenePath);
|
135
191
|
}
|
136
|
-
this.
|
192
|
+
this.view$.setValue(mainView);
|
137
193
|
return mainView;
|
138
194
|
}
|
139
195
|
|
@@ -165,21 +221,6 @@ export class MainViewProxy {
|
|
165
221
|
this.start();
|
166
222
|
}
|
167
223
|
|
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
224
|
public addMainViewListener(): void {
|
184
225
|
if (this.mainViewIsAddListener) return;
|
185
226
|
if (this.view.divElement) {
|
@@ -212,13 +253,11 @@ export class MainViewProxy {
|
|
212
253
|
}, 50);
|
213
254
|
|
214
255
|
private addCameraListener() {
|
215
|
-
this.view.callbacks.on("onCameraUpdatedByDevice", this.onCameraUpdatedByDevice);
|
216
256
|
this.view.callbacks.on("onCameraUpdated", this.onCameraOrSizeUpdated);
|
217
257
|
this.view.callbacks.on("onSizeUpdated", this.onCameraOrSizeUpdated);
|
218
258
|
}
|
219
259
|
|
220
260
|
private removeCameraListener() {
|
221
|
-
this.view.callbacks.off("onCameraUpdatedByDevice", this.onCameraUpdatedByDevice);
|
222
261
|
this.view.callbacks.off("onCameraUpdated", this.onCameraOrSizeUpdated);
|
223
262
|
this.view.callbacks.off("onSizeUpdated", this.onCameraOrSizeUpdated);
|
224
263
|
}
|
@@ -235,6 +274,9 @@ export class MainViewProxy {
|
|
235
274
|
}
|
236
275
|
|
237
276
|
public destroy() {
|
277
|
+
this.camera$.destroy();
|
278
|
+
this.size$.destroy();
|
279
|
+
this.view$.destroy();
|
238
280
|
this.removeMainViewListener();
|
239
281
|
this.stop();
|
240
282
|
this.sideEffectManager.flushAll();
|
@@ -0,0 +1,119 @@
|
|
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 =
|
41
|
+
this.context.viewMode$ && this.context.viewMode$.value === ViewMode.Freedom;
|
42
|
+
if (notStoreCamera) {
|
43
|
+
return;
|
44
|
+
} else {
|
45
|
+
this.context.storeCamera(iCamera);
|
46
|
+
}
|
47
|
+
});
|
48
|
+
this.bindView(this.context.view$.value);
|
49
|
+
this.sem.add(() =>
|
50
|
+
this.context.view$.subscribe(view => {
|
51
|
+
const currentCamera = this.context.camera$.value;
|
52
|
+
if (currentCamera && this.context.size$.value) {
|
53
|
+
view?.moveCamera({
|
54
|
+
scale: 1,
|
55
|
+
animationMode: AnimationMode.Immediately,
|
56
|
+
});
|
57
|
+
this.synchronizer.onRemoteUpdate(currentCamera, this.context.size$.value);
|
58
|
+
}
|
59
|
+
|
60
|
+
this.bindView(view);
|
61
|
+
})
|
62
|
+
);
|
63
|
+
this.sem.add(() =>
|
64
|
+
this.context.camera$.subscribe((camera, skipUpdate) => {
|
65
|
+
const size = this.context.size$.value;
|
66
|
+
if (camera && size && !skipUpdate) {
|
67
|
+
this.synchronizer.onRemoteUpdate(camera, size);
|
68
|
+
}
|
69
|
+
})
|
70
|
+
);
|
71
|
+
this.sem.add(() =>
|
72
|
+
this.context.size$.subscribe(size => {
|
73
|
+
if (size) {
|
74
|
+
this.synchronizer.onRemoteSizeUpdate(size);
|
75
|
+
}
|
76
|
+
})
|
77
|
+
);
|
78
|
+
this.sem.add(() =>
|
79
|
+
this.context.stageRect$.reaction(rect => {
|
80
|
+
if (rect) {
|
81
|
+
this.synchronizer.setRect(rect);
|
82
|
+
}
|
83
|
+
})
|
84
|
+
);
|
85
|
+
const camera$size$ = combine([this.context.camera$, this.context.size$]);
|
86
|
+
camera$size$.reaction(([camera, size]) => {
|
87
|
+
if (camera && size) {
|
88
|
+
this.synchronizer.onRemoteUpdate(camera, size);
|
89
|
+
camera$size$.destroy();
|
90
|
+
}
|
91
|
+
});
|
92
|
+
}
|
93
|
+
|
94
|
+
public bindView = (view?: View) => {
|
95
|
+
if (!view) return;
|
96
|
+
this.synchronizer.setView(view);
|
97
|
+
this.sem.flush("view");
|
98
|
+
this.sem.add(() => {
|
99
|
+
view.callbacks.on("onCameraUpdatedByDevice", this.onCameraUpdatedByDevice);
|
100
|
+
return () =>
|
101
|
+
view.callbacks.off("onCameraUpdatedByDevice", this.onCameraUpdatedByDevice);
|
102
|
+
}, "view");
|
103
|
+
};
|
104
|
+
|
105
|
+
private onCameraUpdatedByDevice = (camera: Camera) => {
|
106
|
+
this.synchronizer.onLocalCameraUpdate(camera);
|
107
|
+
const stage = this.context.stageRect$.value;
|
108
|
+
if (stage) {
|
109
|
+
const size = { width: stage.width, height: stage.height, id: this.context.uid };
|
110
|
+
if (!isEqual(size, this.context.size$.value)) {
|
111
|
+
this.context.storeSize(size);
|
112
|
+
}
|
113
|
+
}
|
114
|
+
};
|
115
|
+
|
116
|
+
public destroy() {
|
117
|
+
this.sem.flushAll();
|
118
|
+
}
|
119
|
+
}
|
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
|
|
@@ -918,6 +923,24 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
918
923
|
emitter.emit("containerSizeRatioUpdate", ratio);
|
919
924
|
}
|
920
925
|
|
926
|
+
public createPPTHandler() {
|
927
|
+
return {
|
928
|
+
onPageJumpTo: (_pptUUID: string, index: number) => {
|
929
|
+
this.appManager?.focusApp?.appContext?.whiteBoardView?.jumpPage(index);
|
930
|
+
},
|
931
|
+
onPageToNext: () => {
|
932
|
+
if (this.focused) {
|
933
|
+
this.appManager?.focusApp?.appContext?.whiteBoardView?.nextPage();
|
934
|
+
}
|
935
|
+
},
|
936
|
+
onPageToPrev: () => {
|
937
|
+
if (this.focused) {
|
938
|
+
this.appManager?.focusApp?.appContext?.whiteBoardView?.prevPage();
|
939
|
+
}
|
940
|
+
}
|
941
|
+
}
|
942
|
+
}
|
943
|
+
|
921
944
|
private isDynamicPPT(scenes: SceneDefinition[]) {
|
922
945
|
const sceneSrc = scenes[0]?.ppt?.src;
|
923
946
|
return sceneSrc?.startsWith("pptx://");
|
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
|
-
}
|