@netless/window-manager 1.0.0-canary.1 → 1.0.0-canary.10
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/__mocks__/white-web-sdk.ts +10 -1
- package/dist/App/AppContext.d.ts +16 -15
- package/dist/App/AppPageStateImpl.d.ts +6 -2
- package/dist/App/AppProxy.d.ts +26 -4
- package/dist/App/AppViewSync.d.ts +11 -0
- package/dist/App/WhiteboardView.d.ts +24 -0
- package/dist/App/index.d.ts +1 -0
- package/dist/AppManager.d.ts +5 -3
- package/dist/AttributesDelegate.d.ts +6 -14
- package/dist/BoxManager.d.ts +2 -3
- package/dist/Helper.d.ts +12 -2
- package/dist/InternalEmitter.d.ts +4 -0
- package/dist/Page/PageController.d.ts +1 -0
- package/dist/ReconnectRefresher.d.ts +1 -1
- package/dist/Utils/Common.d.ts +1 -0
- package/dist/View/CameraSynchronizer.d.ts +7 -7
- package/dist/View/MainView.d.ts +0 -1
- package/dist/constants.d.ts +1 -0
- package/dist/index.cjs.js +12 -12
- package/dist/index.d.ts +6 -3
- package/dist/index.es.js +712 -648
- package/dist/index.umd.js +12 -12
- package/dist/style.css +1 -1
- package/dist/typings.d.ts +4 -0
- package/docs/app-context.md +98 -64
- package/docs/develop-app.md +2 -5
- package/package.json +3 -2
- package/pnpm-lock.yaml +11 -5
- package/src/App/AppContext.ts +71 -74
- package/src/App/AppPageStateImpl.ts +25 -6
- package/src/App/AppProxy.ts +206 -26
- package/src/App/AppViewSync.ts +73 -0
- package/src/App/Storage/index.ts +4 -4
- package/src/App/WhiteboardView.ts +89 -0
- package/src/App/index.ts +1 -0
- package/src/AppManager.ts +32 -23
- package/src/AttributesDelegate.ts +14 -17
- package/src/BoxManager.ts +5 -8
- package/src/Helper.ts +10 -1
- package/src/InternalEmitter.ts +4 -0
- package/src/Page/PageController.ts +1 -0
- package/src/ReconnectRefresher.ts +1 -0
- package/src/Utils/Common.ts +6 -0
- package/src/View/CameraSynchronizer.ts +32 -27
- package/src/View/MainView.ts +22 -39
- package/src/constants.ts +2 -0
- package/src/index.ts +18 -3
- package/src/style.css +9 -0
- package/src/typings.ts +4 -0
@@ -1,32 +1,32 @@
|
|
1
1
|
import { AnimationMode } from "white-web-sdk";
|
2
|
-
import { delay, throttle } from "lodash";
|
2
|
+
import { debounce, delay, throttle } from "lodash";
|
3
3
|
import type { TeleBoxRect } from "@netless/telebox-insider";
|
4
|
-
import type { Camera, View
|
5
|
-
import type {
|
4
|
+
import type { Camera, View } from "white-web-sdk";
|
5
|
+
import type { ISize } from "../AttributesDelegate";
|
6
6
|
|
7
7
|
export type SaveCamera = (camera: Camera) => void;
|
8
8
|
|
9
9
|
export class CameraSynchronizer {
|
10
|
-
|
11
|
-
|
10
|
+
public remoteCamera?: Camera;
|
11
|
+
public remoteSize?: ISize;
|
12
12
|
protected rect?: TeleBoxRect;
|
13
13
|
protected view?: View;
|
14
14
|
|
15
15
|
constructor(protected saveCamera: SaveCamera) {}
|
16
16
|
|
17
|
-
public setRect(rect: TeleBoxRect) {
|
17
|
+
public setRect = debounce((rect: TeleBoxRect) => {
|
18
18
|
this.rect = rect;
|
19
19
|
if (this.remoteCamera && this.remoteSize) {
|
20
20
|
this.onRemoteUpdate(this.remoteCamera, this.remoteSize);
|
21
21
|
}
|
22
|
-
}
|
22
|
+
}, 50);
|
23
23
|
|
24
24
|
public setView(view: View) {
|
25
25
|
this.view = view;
|
26
26
|
}
|
27
27
|
|
28
28
|
// 远端 Camera 或者 size 更新
|
29
|
-
public onRemoteUpdate = throttle((camera: Camera, size:
|
29
|
+
public onRemoteUpdate = throttle((camera: Camera, size: ISize) => {
|
30
30
|
this.remoteCamera = camera;
|
31
31
|
this.remoteSize = size;
|
32
32
|
if (this.remoteSize && this.rect) {
|
@@ -37,31 +37,36 @@ export class CameraSynchronizer {
|
|
37
37
|
scale = this.rect.height / size.height;
|
38
38
|
}
|
39
39
|
const nextScale = camera.scale * scale;
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
40
|
+
|
41
|
+
const moveCamera = () => {
|
42
|
+
this.view?.moveCamera({
|
43
|
+
centerX: camera.centerX,
|
44
|
+
centerY: camera.centerY,
|
45
|
+
scale: nextScale,
|
46
|
+
animationMode: AnimationMode.Immediately,
|
47
|
+
});
|
48
|
+
}
|
46
49
|
// TODO 直接调用 moveCamera 依然会出现 camera 错误的情况,这里暂时加一个 delay 保证 camera 是对的, 后续需要 SDK 进行修改
|
47
|
-
delay(moveCamera,
|
50
|
+
delay(moveCamera, 50);
|
48
51
|
}
|
49
52
|
}, 50);
|
50
53
|
|
54
|
+
public onRemoteSizeUpdate(size: ISize) {
|
55
|
+
if (this.rect) {
|
56
|
+
const nextScale = this.rect.width / size.width;
|
57
|
+
const moveCamera = () => {
|
58
|
+
this.view?.moveCamera({
|
59
|
+
scale: nextScale,
|
60
|
+
animationMode: AnimationMode.Immediately,
|
61
|
+
})
|
62
|
+
};
|
63
|
+
delay(moveCamera, 50);
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
51
67
|
|
52
68
|
public onLocalCameraUpdate(camera: Camera) {
|
53
69
|
this.saveCamera(camera);
|
54
|
-
|
55
|
-
|
56
|
-
// 本地 Size 更新, 先匹配 camera 到新的 size 然后再发送 camera 数据到远端
|
57
|
-
public onLocalSizeUpdate(size: Size) {
|
58
|
-
if (this.rect && this.view) {
|
59
|
-
const scale = this.rect.width / size.width;
|
60
|
-
const nextScale = this.view.camera.scale * scale;
|
61
|
-
this.view.moveCamera({
|
62
|
-
scale: nextScale,
|
63
|
-
animationMode: AnimationMode.Immediately
|
64
|
-
});
|
65
|
-
}
|
70
|
+
this.remoteCamera = camera;
|
66
71
|
}
|
67
72
|
}
|
package/src/View/MainView.ts
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
import { reaction } from "white-web-sdk";
|
2
1
|
import { callbacks } from "../callback";
|
2
|
+
import { CameraSynchronizer } from "./CameraSynchronizer";
|
3
3
|
import { createView } from "./ViewManager";
|
4
4
|
import { debounce, get, isEqual } from "lodash";
|
5
5
|
import { emitter } from "../InternalEmitter";
|
6
6
|
import { Events } from "../constants";
|
7
7
|
import { Fields } from "../AttributesDelegate";
|
8
|
-
import {
|
8
|
+
import { reaction } from "white-web-sdk";
|
9
|
+
import { releaseView, setViewFocusScenePath } from "../Utils/Common";
|
9
10
|
import { SideEffectManager } from "side-effect-manager";
|
10
11
|
import type { Camera, Size, View } from "white-web-sdk";
|
11
12
|
import type { AppManager } from "../AppManager";
|
12
|
-
import { CameraSynchronizer } from "./CameraSynchronizer";
|
13
13
|
|
14
14
|
export class MainViewProxy {
|
15
15
|
private started = false;
|
@@ -21,8 +21,8 @@ export class MainViewProxy {
|
|
21
21
|
private sideEffectManager = new SideEffectManager();
|
22
22
|
|
23
23
|
constructor(private manager: AppManager) {
|
24
|
-
this.synchronizer = new CameraSynchronizer(
|
25
|
-
|
24
|
+
this.synchronizer = new CameraSynchronizer(camera =>
|
25
|
+
this.store.setMainViewCamera({ ...camera, id: this.manager.uid })
|
26
26
|
);
|
27
27
|
this.mainView = this.createMainView();
|
28
28
|
this.moveCameraSizeByAttributes();
|
@@ -32,36 +32,29 @@ export class MainViewProxy {
|
|
32
32
|
this.ensureCameraAndSize();
|
33
33
|
this.startListenWritableChange();
|
34
34
|
});
|
35
|
-
this.sideEffectManager.add(() =>
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
});
|
35
|
+
this.sideEffectManager.add(() => [
|
36
|
+
emitter.on("containerSizeRatioUpdate", this.onUpdateContainerSizeRatio),
|
37
|
+
emitter.on("startReconnect", () => {
|
38
|
+
releaseView(this.mainView);
|
39
|
+
}),
|
40
|
+
emitter.on("playgroundSizeChange", rect => {
|
41
|
+
this.synchronizer.setRect(rect);
|
42
|
+
})
|
43
|
+
]);
|
45
44
|
const rect = this.manager.boxManager?.stageRect;
|
46
45
|
if (rect) {
|
47
46
|
this.synchronizer.setRect(rect);
|
48
47
|
}
|
49
|
-
this.sideEffectManager.add(() => {
|
50
|
-
return emitter.on("playgroundSizeChange", rect => {
|
51
|
-
this.synchronizer.setRect(rect);
|
52
|
-
this.synchronizer.onLocalSizeUpdate(rect);
|
53
|
-
});
|
54
|
-
});
|
55
48
|
}
|
56
49
|
|
57
50
|
private startListenWritableChange = () => {
|
58
|
-
this.sideEffectManager.add(() =>
|
59
|
-
|
51
|
+
this.sideEffectManager.add(() =>
|
52
|
+
emitter.on("writableChange", isWritable => {
|
60
53
|
if (isWritable) {
|
61
54
|
this.ensureCameraAndSize();
|
62
55
|
}
|
63
|
-
})
|
64
|
-
|
56
|
+
})
|
57
|
+
);
|
65
58
|
};
|
66
59
|
|
67
60
|
public ensureCameraAndSize() {
|
@@ -89,14 +82,13 @@ export class MainViewProxy {
|
|
89
82
|
|
90
83
|
public start() {
|
91
84
|
if (this.started) return;
|
92
|
-
this.sizeChangeHandler(this.mainViewSize);
|
93
85
|
this.addCameraListener();
|
94
86
|
this.addCameraReaction();
|
95
87
|
this.started = true;
|
96
88
|
}
|
97
89
|
|
98
90
|
public addCameraReaction = () => {
|
99
|
-
this.manager.refresher
|
91
|
+
this.manager.refresher.add(Fields.MainViewCamera, this.cameraReaction);
|
100
92
|
};
|
101
93
|
|
102
94
|
public setCameraAndSize(): void {
|
@@ -120,15 +112,8 @@ export class MainViewProxy {
|
|
120
112
|
);
|
121
113
|
};
|
122
114
|
|
123
|
-
public sizeChangeHandler = debounce((size: Size) => {
|
124
|
-
if (size) {
|
125
|
-
this.synchronizer.onLocalSizeUpdate(size);
|
126
|
-
}
|
127
|
-
}, 30);
|
128
|
-
|
129
115
|
public onUpdateContainerSizeRatio = () => {
|
130
116
|
const size = this.store.getMainViewSize();
|
131
|
-
this.sizeChangeHandler(size);
|
132
117
|
if (size.id === this.manager.uid) {
|
133
118
|
this.setCameraAndSize();
|
134
119
|
}
|
@@ -171,9 +156,7 @@ export class MainViewProxy {
|
|
171
156
|
const divElement = this.mainView.divElement;
|
172
157
|
const disableCameraTransform = this.mainView.disableCameraTransform;
|
173
158
|
this.stop();
|
174
|
-
|
175
|
-
this.mainView.release();
|
176
|
-
}
|
159
|
+
releaseView(this.mainView);
|
177
160
|
this.removeMainViewListener();
|
178
161
|
this.mainView = this.createMainView();
|
179
162
|
this.mainView.disableCameraTransform = disableCameraTransform;
|
@@ -246,8 +229,8 @@ export class MainViewProxy {
|
|
246
229
|
|
247
230
|
public stop() {
|
248
231
|
this.removeCameraListener();
|
249
|
-
this.manager.refresher
|
250
|
-
this.manager.refresher
|
232
|
+
this.manager.refresher.remove(Fields.MainViewCamera);
|
233
|
+
this.manager.refresher.remove(Fields.MainViewSize);
|
251
234
|
this.started = false;
|
252
235
|
}
|
253
236
|
|
package/src/constants.ts
CHANGED
package/src/index.ts
CHANGED
@@ -29,7 +29,7 @@ import {
|
|
29
29
|
} from "./Utils/Common";
|
30
30
|
import type { TELE_BOX_STATE, BoxManager } from "./BoxManager";
|
31
31
|
import * as Errors from "./Utils/error";
|
32
|
-
import type { Apps, Position } from "./AttributesDelegate";
|
32
|
+
import type { Apps, Position , ICamera, ISize } from "./AttributesDelegate";
|
33
33
|
import type {
|
34
34
|
Displayer,
|
35
35
|
SceneDefinition,
|
@@ -104,6 +104,8 @@ export type AppSyncAttributes = {
|
|
104
104
|
isDynamicPPT?: boolean;
|
105
105
|
fullPath?: string;
|
106
106
|
createdAt?: number;
|
107
|
+
camera?: ICamera;
|
108
|
+
size?: ISize;
|
107
109
|
};
|
108
110
|
|
109
111
|
export type AppInitState = {
|
@@ -127,8 +129,8 @@ export type MountParams = {
|
|
127
129
|
container?: HTMLElement;
|
128
130
|
/** 白板高宽比例, 默认为 9 / 16 */
|
129
131
|
containerSizeRatio?: number;
|
130
|
-
/**
|
131
|
-
|
132
|
+
/** 是否高亮显示同步区域, 默认为 true */
|
133
|
+
highlightStage?: boolean;
|
132
134
|
collectorContainer?: HTMLElement;
|
133
135
|
collectorStyles?: Partial<CSSStyleDeclaration>;
|
134
136
|
overwriteStyles?: string;
|
@@ -239,6 +241,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
239
241
|
collectorStyles: params.collectorStyles,
|
240
242
|
prefersColorScheme: params.prefersColorScheme,
|
241
243
|
stageRatio: params.containerSizeRatio,
|
244
|
+
highlightStage: params.highlightStage
|
242
245
|
});
|
243
246
|
manager.appManager?.setBoxManager(manager.boxManager);
|
244
247
|
if (params.container) {
|
@@ -502,6 +505,18 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
502
505
|
}
|
503
506
|
}
|
504
507
|
|
508
|
+
public async jumpPage(index: number): Promise<boolean> {
|
509
|
+
if (!this.appManager) {
|
510
|
+
return false;
|
511
|
+
}
|
512
|
+
if (index < 0 || index >= this.pageState.length) {
|
513
|
+
console.warn(`[WindowManager]: index ${index} out of range`);
|
514
|
+
return false;
|
515
|
+
}
|
516
|
+
await this.appManager.setMainViewSceneIndex(index);
|
517
|
+
return true;
|
518
|
+
}
|
519
|
+
|
505
520
|
public async addPage(params?: AddPageParams): Promise<void> {
|
506
521
|
if (this.appManager) {
|
507
522
|
const after = params?.after;
|
package/src/style.css
CHANGED
package/src/typings.ts
CHANGED
@@ -13,6 +13,7 @@ import type {
|
|
13
13
|
import type { AppContext } from "./App";
|
14
14
|
import type { ReadonlyTeleBox, TeleBoxRect } from "@netless/telebox-insider";
|
15
15
|
import type { PageState } from "./Page";
|
16
|
+
import type { Member } from "./Helper";
|
16
17
|
|
17
18
|
export interface NetlessApp<Attributes = any, MagixEventPayloads = any, AppOptions = any, SetupResult = any> {
|
18
19
|
kind: string;
|
@@ -53,6 +54,7 @@ export type AppEmitterEvent<T = any> = {
|
|
53
54
|
reconnected: void;
|
54
55
|
seek: number;
|
55
56
|
pageStateChange: PageState,
|
57
|
+
roomMembersChange: Member[];
|
56
58
|
};
|
57
59
|
|
58
60
|
export type RegisterEventData = {
|
@@ -79,8 +81,10 @@ export type AppListenerKeys = keyof AppEmitterEvent;
|
|
79
81
|
export type ApplianceIcons = Partial<Record<ApplianceNames, string>>;
|
80
82
|
|
81
83
|
export type { AppContext } from "./App/AppContext";
|
84
|
+
export type { WhiteBoardView } from "./App";
|
82
85
|
export type { ReadonlyTeleBox, TeleBoxRect };
|
83
86
|
export type { SceneState, SceneDefinition, View, AnimationMode, Displayer, Room, Player };
|
84
87
|
export type { Storage, StorageStateChangedEvent, StorageStateChangedListener } from "./App/Storage";
|
85
88
|
export * from "./Page";
|
86
89
|
export * from "./Utils/error";
|
90
|
+
export type { Member } from "./Helper";
|