@netless/window-manager 1.0.0-canary.0 → 1.0.0-canary.11
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 +4 -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 +722 -652
- 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 +14 -9
- 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 +24 -41
- package/src/constants.ts +2 -0
- package/src/index.ts +20 -5
- package/src/style.css +9 -0
- package/src/typings.ts +4 -0
package/src/App/AppContext.ts
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
import { BoxNotCreatedError } from "../Utils/error";
|
2
|
-
import { putScenes } from "../Utils/Common";
|
3
2
|
import { Storage } from "./Storage";
|
4
3
|
import {
|
5
4
|
autorun,
|
@@ -19,7 +18,7 @@ import type {
|
|
19
18
|
import type { ReadonlyTeleBox } from "@netless/telebox-insider";
|
20
19
|
import type Emittery from "emittery";
|
21
20
|
import type { BoxManager } from "../BoxManager";
|
22
|
-
import type { AppEmitterEvent } from "../index";
|
21
|
+
import type { AppEmitterEvent, Member } from "../index";
|
23
22
|
import type { AppManager } from "../AppManager";
|
24
23
|
import type { AppProxy } from "./AppProxy";
|
25
24
|
import type {
|
@@ -27,11 +26,12 @@ import type {
|
|
27
26
|
MagixEventDispatcher,
|
28
27
|
MagixEventRemoveListener,
|
29
28
|
} from "./MagixEvent";
|
30
|
-
import
|
29
|
+
import { WhiteBoardView } from "./WhiteboardView";
|
30
|
+
import { findMemberByUid } from "../Helper";
|
31
|
+
import { MAX_PAGE_SIZE } from "../constants";
|
32
|
+
import { isNumber } from "lodash";
|
31
33
|
|
32
|
-
export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOptions = any>
|
33
|
-
implements PageController
|
34
|
-
{
|
34
|
+
export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOptions = any> {
|
35
35
|
public readonly emitter: Emittery<AppEmitterEvent<TAttributes>>;
|
36
36
|
public readonly mobxUtils = {
|
37
37
|
autorun,
|
@@ -48,6 +48,8 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
|
|
48
48
|
private store = this.manager.store;
|
49
49
|
public readonly isAddApp: boolean;
|
50
50
|
public readonly isReplay = this.manager.isReplay;
|
51
|
+
private whiteBoardView?: WhiteBoardView;
|
52
|
+
public _viewWrapper?: HTMLElement;
|
51
53
|
|
52
54
|
constructor(
|
53
55
|
private manager: AppManager,
|
@@ -60,9 +62,13 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
|
|
60
62
|
this.isAddApp = appProxy.isAddApp;
|
61
63
|
}
|
62
64
|
|
63
|
-
public
|
65
|
+
public get displayer() {
|
64
66
|
return this.manager.displayer;
|
65
|
-
}
|
67
|
+
}
|
68
|
+
|
69
|
+
public get destroyed() {
|
70
|
+
return this.appProxy.status === "destroyed";
|
71
|
+
}
|
66
72
|
|
67
73
|
/** @deprecated Use context.storage.state instead. */
|
68
74
|
public getAttributes = (): TAttributes | undefined => {
|
@@ -78,32 +84,58 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
|
|
78
84
|
}
|
79
85
|
};
|
80
86
|
|
81
|
-
public
|
87
|
+
public get view(): View | undefined {
|
82
88
|
return this.appProxy.view;
|
83
89
|
};
|
84
90
|
|
85
|
-
public
|
86
|
-
|
87
|
-
|
88
|
-
view.divElement = dom as HTMLDivElement;
|
89
|
-
setTimeout(() => {
|
90
|
-
// 渲染需要时间,延迟 refresh
|
91
|
-
this.getRoom()?.refreshViewSize();
|
92
|
-
}, 1000);
|
91
|
+
public createWhiteBoardView = (size?: number): WhiteBoardView => {
|
92
|
+
if (this.whiteBoardView) {
|
93
|
+
return this.whiteBoardView;
|
93
94
|
}
|
94
|
-
|
95
|
+
let view = this.view;
|
96
|
+
if (!view) {
|
97
|
+
view = this.appProxy.createAppDir();
|
98
|
+
}
|
99
|
+
const viewWrapper = document.createElement("div");
|
100
|
+
this._viewWrapper = viewWrapper;
|
101
|
+
viewWrapper.className = "window-manager-view-wrapper";
|
102
|
+
this.box.$content.parentElement?.appendChild(viewWrapper);
|
103
|
+
const removeViewWrapper = () => {
|
104
|
+
this.box.$content.parentElement?.removeChild(viewWrapper);
|
105
|
+
this._viewWrapper = undefined;
|
106
|
+
}
|
107
|
+
view.divElement = viewWrapper;
|
108
|
+
this.appProxy.fireMemberStateChange();
|
109
|
+
if (this.isAddApp) {
|
110
|
+
this.ensurePageSize(size);
|
111
|
+
}
|
112
|
+
this.whiteBoardView = new WhiteBoardView(view, this, this.appProxy, removeViewWrapper, this.ensurePageSize);
|
113
|
+
return this.whiteBoardView;
|
114
|
+
}
|
115
|
+
|
116
|
+
private ensurePageSize = (size?: number) => {
|
117
|
+
if (!isNumber(size)) return;
|
118
|
+
if (!this.appProxy.scenePath) return;
|
119
|
+
if (this.appProxy.pageState.length >= size) return;
|
120
|
+
if (size <= 0 || size >= MAX_PAGE_SIZE) {
|
121
|
+
throw Error(`[WindowManager]: size ${size} muse be in range [1, ${MAX_PAGE_SIZE}]`);
|
122
|
+
}
|
123
|
+
const needInsert = size - this.appProxy.pageState.length;
|
124
|
+
const scenes = new Array(needInsert).fill({});
|
125
|
+
this.room?.putScenes(this.appProxy.scenePath, scenes);
|
126
|
+
}
|
95
127
|
|
96
128
|
public getInitScenePath = () => {
|
97
129
|
return this.manager.getAppInitPath(this.appId);
|
98
130
|
};
|
99
131
|
|
100
132
|
/** Get App writable status. */
|
101
|
-
public
|
102
|
-
return this.manager.canOperate;
|
133
|
+
public get isWritable(): boolean {
|
134
|
+
return this.manager.canOperate && !this.destroyed;
|
103
135
|
};
|
104
136
|
|
105
137
|
/** Get the App Window UI box. */
|
106
|
-
public
|
138
|
+
public get box(): ReadonlyTeleBox {
|
107
139
|
const box = this.boxManager.getBox(this.appId);
|
108
140
|
if (box) {
|
109
141
|
return box;
|
@@ -112,10 +144,25 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
|
|
112
144
|
}
|
113
145
|
};
|
114
146
|
|
115
|
-
public
|
147
|
+
public get room(): Room | undefined {
|
116
148
|
return this.manager.room;
|
117
149
|
};
|
118
150
|
|
151
|
+
public get members() {
|
152
|
+
return this.manager.members;
|
153
|
+
}
|
154
|
+
|
155
|
+
public get memberState(): Member {
|
156
|
+
const self = findMemberByUid(this.room, this.manager.uid);
|
157
|
+
if (!self) {
|
158
|
+
throw new Error(`Member ${this.manager.uid} not found.`);
|
159
|
+
}
|
160
|
+
return {
|
161
|
+
uid: this.manager.uid,
|
162
|
+
...self,
|
163
|
+
}
|
164
|
+
}
|
165
|
+
|
119
166
|
/** @deprecated Use context.storage.setState instead. */
|
120
167
|
public setAttributes = (attributes: TAttributes) => {
|
121
168
|
this.manager.safeSetAttributes({ [this.appId]: attributes });
|
@@ -128,11 +175,12 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
|
|
128
175
|
}
|
129
176
|
};
|
130
177
|
|
178
|
+
/** @deprecated Use Pages api instead. */
|
131
179
|
public setScenePath = async (scenePath: string): Promise<void> => {
|
132
180
|
if (!this.appProxy.box) return;
|
133
181
|
this.appProxy.setFullPath(scenePath);
|
134
182
|
// 兼容 15 版本 SDK 的切页
|
135
|
-
this.
|
183
|
+
this.room?.setScenePath(scenePath);
|
136
184
|
};
|
137
185
|
|
138
186
|
/** Get the local App options. */
|
@@ -196,55 +244,4 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
|
|
196
244
|
public removeMagixEventListener = this.manager.displayer.removeMagixEventListener.bind(
|
197
245
|
this.manager.displayer
|
198
246
|
) as MagixEventRemoveListener<TMagixEventPayloads>;
|
199
|
-
|
200
|
-
/** PageController */
|
201
|
-
public nextPage = async (): Promise<boolean> => {
|
202
|
-
const nextIndex = this.pageState.index + 1;
|
203
|
-
if (nextIndex > this.pageState.length - 1) {
|
204
|
-
console.warn("[WindowManager] nextPage: index out of range");
|
205
|
-
return false;
|
206
|
-
}
|
207
|
-
this.appProxy.setSceneIndex(nextIndex);
|
208
|
-
return true;
|
209
|
-
};
|
210
|
-
|
211
|
-
public prevPage = async (): Promise<boolean> => {
|
212
|
-
const nextIndex = this.pageState.index - 1;
|
213
|
-
if (nextIndex < 0) {
|
214
|
-
console.warn("[WindowManager] prevPage: index out of range");
|
215
|
-
return false;
|
216
|
-
}
|
217
|
-
this.appProxy.setSceneIndex(nextIndex);
|
218
|
-
return true;
|
219
|
-
};
|
220
|
-
|
221
|
-
public addPage = async (params?: AddPageParams) => {
|
222
|
-
const after = params?.after;
|
223
|
-
const scene = params?.scene;
|
224
|
-
const scenePath = this.appProxy.scenePath;
|
225
|
-
if (!scenePath) return;
|
226
|
-
if (after) {
|
227
|
-
const nextIndex = this.pageState.index + 1;
|
228
|
-
putScenes(this.manager.room, scenePath, [scene || {}], nextIndex);
|
229
|
-
} else {
|
230
|
-
putScenes(this.manager.room, scenePath, [scene || {}]);
|
231
|
-
}
|
232
|
-
};
|
233
|
-
|
234
|
-
public removePage = async (index?: number): Promise<boolean> => {
|
235
|
-
const needRemoveIndex = index === undefined ? this.pageState.index : index;
|
236
|
-
if (this.pageState.length === 1) {
|
237
|
-
console.warn(`[WindowManager]: can not remove the last page`);
|
238
|
-
return false;
|
239
|
-
}
|
240
|
-
if (needRemoveIndex < 0 || needRemoveIndex >= this.pageState.length) {
|
241
|
-
console.warn(`[WindowManager]: page index ${index} out of range`);
|
242
|
-
return false;
|
243
|
-
}
|
244
|
-
return this.appProxy.removeSceneByIndex(needRemoveIndex);;
|
245
|
-
}
|
246
|
-
|
247
|
-
public get pageState(): PageState {
|
248
|
-
return this.appProxy.pageState;
|
249
|
-
}
|
250
247
|
}
|
@@ -9,11 +9,15 @@ export type AppPageStateParams = {
|
|
9
9
|
};
|
10
10
|
|
11
11
|
export class AppPageStateImpl {
|
12
|
-
|
12
|
+
public sceneNode: ScenesCallbacksNode | null = null;
|
13
|
+
private scenePath?: string;
|
14
|
+
private view?: View;
|
13
15
|
|
14
16
|
constructor(private params: AppPageStateParams) {
|
15
17
|
const { displayer, scenePath } = this.params;
|
18
|
+
this.view = this.params.view;
|
16
19
|
if (scenePath) {
|
20
|
+
this.scenePath = scenePath;
|
17
21
|
this.sceneNode = displayer.createScenesCallback(scenePath, {
|
18
22
|
onAddScene: this.onSceneChange,
|
19
23
|
onRemoveScene: this.onSceneChange,
|
@@ -21,24 +25,39 @@ export class AppPageStateImpl {
|
|
21
25
|
}
|
22
26
|
}
|
23
27
|
|
24
|
-
|
25
|
-
this.
|
28
|
+
public createSceneNode = (scenePath: string) => {
|
29
|
+
this.scenePath = scenePath;
|
30
|
+
if (this.sceneNode) {
|
31
|
+
this.sceneNode.dispose();
|
32
|
+
}
|
33
|
+
this.sceneNode = this.params.displayer.createScenesCallback(scenePath, {
|
34
|
+
onAddScene: this.onSceneChange,
|
35
|
+
onRemoveScene: this.onSceneChange,
|
36
|
+
});
|
37
|
+
return this.sceneNode;
|
38
|
+
}
|
39
|
+
|
40
|
+
public setView(view: View) {
|
41
|
+
this.view = view;
|
42
|
+
}
|
43
|
+
|
44
|
+
private onSceneChange = () => {
|
26
45
|
this.params.notifyPageStateChange();
|
27
46
|
};
|
28
47
|
|
29
48
|
public getFullPath(index: number) {
|
30
49
|
const scenes = this.sceneNode?.scenes;
|
31
|
-
if (this.
|
50
|
+
if (this.scenePath && scenes) {
|
32
51
|
const name = scenes[index];
|
33
52
|
if (name) {
|
34
|
-
return `${this.
|
53
|
+
return `${this.scenePath}/${name}`;
|
35
54
|
}
|
36
55
|
}
|
37
56
|
}
|
38
57
|
|
39
58
|
public toObject(): PageState {
|
40
59
|
return {
|
41
|
-
index: this.
|
60
|
+
index: this.view?.focusSceneIndex || 0,
|
42
61
|
length: this.sceneNode?.scenes.length || 0,
|
43
62
|
};
|
44
63
|
}
|
package/src/App/AppProxy.ts
CHANGED
@@ -3,15 +3,22 @@ import { AppAttributes, AppEvents, Events, SETUP_APP_DELAY } from "../constants"
|
|
3
3
|
import { AppContext } from "./AppContext";
|
4
4
|
import { AppPageStateImpl } from "./AppPageStateImpl";
|
5
5
|
import { appRegister } from "../Register";
|
6
|
-
import {
|
6
|
+
import { AppViewSync } from "./AppViewSync";
|
7
|
+
import { autorun, reaction, toJS } from "white-web-sdk";
|
8
|
+
import { boxEmitter } from "../BoxEmitter";
|
7
9
|
import { BoxManagerNotFoundError } from "../Utils/error";
|
10
|
+
import { calculateNextIndex } from "../Page";
|
11
|
+
import { combine, Val, ValManager } from "value-enhancer";
|
8
12
|
import { debounce, get } from "lodash";
|
9
13
|
import { emitter } from "../InternalEmitter";
|
10
14
|
import { Fields } from "../AttributesDelegate";
|
11
15
|
import { log } from "../Utils/log";
|
16
|
+
import { SideEffectManager } from "side-effect-manager";
|
17
|
+
import type { ICamera, ISize } from "../AttributesDelegate";
|
12
18
|
import {
|
13
19
|
entireScenes,
|
14
20
|
getScenePath,
|
21
|
+
putScenes,
|
15
22
|
removeScenes,
|
16
23
|
setScenePath,
|
17
24
|
setViewFocusScenePath,
|
@@ -23,13 +30,11 @@ import type {
|
|
23
30
|
setAppOptions,
|
24
31
|
AppListenerKeys,
|
25
32
|
} from "../index";
|
26
|
-
import type { SceneState, View, SceneDefinition } from "white-web-sdk";
|
33
|
+
import type { SceneState, View, SceneDefinition, Camera , MemberState} from "white-web-sdk";
|
27
34
|
import type { AppManager } from "../AppManager";
|
28
35
|
import type { NetlessApp } from "../typings";
|
29
|
-
import type { ReadonlyTeleBox } from "@netless/telebox-insider";
|
36
|
+
import type { ReadonlyTeleBox, TeleBoxRect } from "@netless/telebox-insider";
|
30
37
|
import type { PageRemoveService, PageState } from "../Page";
|
31
|
-
import { calculateNextIndex } from "../Page";
|
32
|
-
import { boxEmitter } from "../BoxEmitter";
|
33
38
|
|
34
39
|
export type AppEmitter = Emittery<AppEmitterEvent>;
|
35
40
|
|
@@ -37,6 +42,7 @@ export class AppProxy implements PageRemoveService {
|
|
37
42
|
public kind: string;
|
38
43
|
public id: string;
|
39
44
|
public scenePath?: string;
|
45
|
+
private appScenePath: string;
|
40
46
|
public appEmitter: AppEmitter;
|
41
47
|
public scenes?: SceneDefinition[];
|
42
48
|
|
@@ -45,16 +51,27 @@ export class AppProxy implements PageRemoveService {
|
|
45
51
|
private appProxies = this.manager.appProxies;
|
46
52
|
private viewManager = this.manager.viewManager;
|
47
53
|
private store = this.manager.store;
|
54
|
+
public uid = this.manager.uid;
|
48
55
|
|
49
56
|
public isAddApp: boolean;
|
50
|
-
|
57
|
+
public status: "normal" | "destroyed" = "normal";
|
51
58
|
private stateKey: string;
|
52
|
-
|
53
|
-
private _prevFullPath: string | undefined;
|
59
|
+
public _pageState: AppPageStateImpl;
|
54
60
|
|
55
61
|
public appResult?: NetlessApp<any>;
|
56
62
|
public appContext?: AppContext<any, any>;
|
57
63
|
|
64
|
+
private sideEffectManager = new SideEffectManager();
|
65
|
+
private valManager = new ValManager();
|
66
|
+
|
67
|
+
private fullPath$ = this.valManager.attach(new Val<string | undefined>(undefined));
|
68
|
+
private appViewSync?: AppViewSync;
|
69
|
+
|
70
|
+
public camera$ = this.valManager.attach(new Val<ICamera | undefined>(undefined));
|
71
|
+
public size$ = this.valManager.attach(new Val<ISize | undefined>(undefined));
|
72
|
+
public box$ = this.valManager.attach(new Val<ReadonlyTeleBox | undefined>(undefined));
|
73
|
+
public view$ = this.valManager.attach(new Val<View | undefined>(undefined));
|
74
|
+
|
58
75
|
constructor(
|
59
76
|
private params: BaseInsertParams,
|
60
77
|
private manager: AppManager,
|
@@ -63,6 +80,7 @@ export class AppProxy implements PageRemoveService {
|
|
63
80
|
) {
|
64
81
|
this.kind = params.kind;
|
65
82
|
this.id = appId;
|
83
|
+
this.appScenePath = `/${this.id}-app-dir`;
|
66
84
|
this.stateKey = `${this.id}_state`;
|
67
85
|
this.appProxies.set(this.id, this);
|
68
86
|
this.appEmitter = new Emittery();
|
@@ -75,12 +93,109 @@ export class AppProxy implements PageRemoveService {
|
|
75
93
|
// 只有传入了 scenePath 的 App 才会创建 View
|
76
94
|
this.createView();
|
77
95
|
}
|
96
|
+
if (!this.scenePath) {
|
97
|
+
this.scenePath = this.appScenePath;
|
98
|
+
}
|
78
99
|
this._pageState = new AppPageStateImpl({
|
79
100
|
displayer: this.manager.displayer,
|
80
101
|
scenePath: this.scenePath,
|
81
102
|
view: this.view,
|
82
103
|
notifyPageStateChange: this.notifyPageStateChange,
|
83
104
|
});
|
105
|
+
this.sideEffectManager.add(() => () => this._pageState.destroy());
|
106
|
+
this.sideEffectManager.add(() =>
|
107
|
+
emitter.on("roomMembersChange", members => {
|
108
|
+
this.appEmitter.emit("roomMembersChange", members);
|
109
|
+
})
|
110
|
+
);
|
111
|
+
this.camera$.setValue(toJS(this.appAttributes.camera));
|
112
|
+
this.size$.setValue(toJS(this.appAttributes.size));
|
113
|
+
this.addCameraReaction();
|
114
|
+
this.addSizeReaction();
|
115
|
+
this.sideEffectManager.add(() =>
|
116
|
+
combine([this.box$, this.view$]).subscribe(([box, view]) => {
|
117
|
+
if (box && view) {
|
118
|
+
if (!this.camera$.value) {
|
119
|
+
this.storeCamera({
|
120
|
+
centerX: 0,
|
121
|
+
centerY: 0,
|
122
|
+
scale: 1,
|
123
|
+
id: this.uid,
|
124
|
+
});
|
125
|
+
this.camera$.setValue(toJS(this.appAttributes.camera));
|
126
|
+
}
|
127
|
+
if (!this.size$.value && box.contentStageRect) {
|
128
|
+
const initialRect = this.computedInitialRect(box.contentStageRect);
|
129
|
+
const width = initialRect?.width || box.contentStageRect.width;
|
130
|
+
const height = initialRect?.height || box.contentStageRect.height;
|
131
|
+
this.storeSize({
|
132
|
+
id: this.uid,
|
133
|
+
width,
|
134
|
+
height,
|
135
|
+
});
|
136
|
+
this.size$.setValue(toJS(this.appAttributes.size));
|
137
|
+
}
|
138
|
+
this.appViewSync = new AppViewSync(this);
|
139
|
+
this.sideEffectManager.add(() => () => this.appViewSync?.destroy());
|
140
|
+
}
|
141
|
+
})
|
142
|
+
);
|
143
|
+
this.sideEffectManager.add(() =>
|
144
|
+
emitter.on("memberStateChange", this.onMemberStateChange)
|
145
|
+
);
|
146
|
+
}
|
147
|
+
|
148
|
+
public fireMemberStateChange = () => {
|
149
|
+
if (this.manager.room) {
|
150
|
+
this.onMemberStateChange(this.manager.room.state.memberState);
|
151
|
+
}
|
152
|
+
}
|
153
|
+
|
154
|
+
private onMemberStateChange = (memberState: MemberState) => {
|
155
|
+
// clicker 教具把事件穿透给下层
|
156
|
+
const needPointerEventsNone = memberState.currentApplianceName === "clicker";
|
157
|
+
if (needPointerEventsNone) {
|
158
|
+
if (this.appContext?._viewWrapper) {
|
159
|
+
this.appContext._viewWrapper.style.pointerEvents = "none";
|
160
|
+
}
|
161
|
+
} else {
|
162
|
+
if (this.appContext?._viewWrapper) {
|
163
|
+
this.appContext._viewWrapper.style.pointerEvents = "auto";
|
164
|
+
}
|
165
|
+
}
|
166
|
+
}
|
167
|
+
|
168
|
+
private computedInitialRect = (boxRect: TeleBoxRect) => {
|
169
|
+
const managerRect = this.manager.boxManager?.stageRect;
|
170
|
+
if (managerRect) {
|
171
|
+
const { width, height } = managerRect;
|
172
|
+
const boxRatio = boxRect.height / boxRect.width;
|
173
|
+
if (height < 480) {
|
174
|
+
return {
|
175
|
+
width: 480 / boxRatio,
|
176
|
+
height: 480,
|
177
|
+
};
|
178
|
+
} else {
|
179
|
+
return {
|
180
|
+
width: width * 0.65,
|
181
|
+
height: height * 0.65,
|
182
|
+
};
|
183
|
+
}
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
187
|
+
public createAppDir() {
|
188
|
+
const scenePath = this.scenePath || this.appScenePath;
|
189
|
+
const sceneNode = this._pageState.createSceneNode(scenePath);
|
190
|
+
if (!sceneNode) {
|
191
|
+
putScenes(this.manager.room, scenePath, [{ name: "1" }]);
|
192
|
+
this._pageState.createSceneNode(scenePath);
|
193
|
+
this.setSceneIndex(0);
|
194
|
+
}
|
195
|
+
this.scenes = entireScenes(this.manager.displayer)[scenePath];
|
196
|
+
const view = this.createView();
|
197
|
+
this._pageState.setView(view);
|
198
|
+
return view;
|
84
199
|
}
|
85
200
|
|
86
201
|
private initScenes() {
|
@@ -96,7 +211,7 @@ export class AppProxy implements PageRemoveService {
|
|
96
211
|
}
|
97
212
|
|
98
213
|
public get view(): View | undefined {
|
99
|
-
return this.
|
214
|
+
return this.view$.value;
|
100
215
|
}
|
101
216
|
|
102
217
|
public get viewIndex(): number | undefined {
|
@@ -131,7 +246,7 @@ export class AppProxy implements PageRemoveService {
|
|
131
246
|
}
|
132
247
|
|
133
248
|
public setFullPath(path: string) {
|
134
|
-
this.
|
249
|
+
this.store.updateAppAttributes(this.id, Fields.FullPath, path);
|
135
250
|
}
|
136
251
|
|
137
252
|
public async baseInsertApp(skipUpdate = false): Promise<{ appId: string; app: NetlessApp }> {
|
@@ -160,7 +275,7 @@ export class AppProxy implements PageRemoveService {
|
|
160
275
|
}
|
161
276
|
|
162
277
|
public get box(): ReadonlyTeleBox | undefined {
|
163
|
-
return this.
|
278
|
+
return this.box$.value;
|
164
279
|
}
|
165
280
|
|
166
281
|
private async setupApp(
|
@@ -194,13 +309,14 @@ export class AppProxy implements PageRemoveService {
|
|
194
309
|
this.fixMobileSize();
|
195
310
|
}, SETUP_APP_DELAY);
|
196
311
|
});
|
197
|
-
this.boxManager?.createBox({
|
312
|
+
const box = this.boxManager?.createBox({
|
198
313
|
appId: appId,
|
199
314
|
app,
|
200
315
|
options,
|
201
316
|
canOperate: this.manager.canOperate,
|
202
317
|
smartPosition: this.isAddApp,
|
203
318
|
});
|
319
|
+
this.box$.setValue(box);
|
204
320
|
if (this.isAddApp && this.box) {
|
205
321
|
this.store.updateAppState(appId, AppAttributes.ZIndex, this.box.zIndex);
|
206
322
|
this.boxManager.focusBox({ appId }, false);
|
@@ -345,7 +461,7 @@ export class AppProxy implements PageRemoveService {
|
|
345
461
|
}
|
346
462
|
|
347
463
|
private appAttributesUpdateListener = (appId: string) => {
|
348
|
-
this.manager.refresher
|
464
|
+
this.manager.refresher.add(appId, () => {
|
349
465
|
return autorun(() => {
|
350
466
|
const attrs = this.manager.attributes[appId];
|
351
467
|
if (attrs) {
|
@@ -353,7 +469,7 @@ export class AppProxy implements PageRemoveService {
|
|
353
469
|
}
|
354
470
|
});
|
355
471
|
});
|
356
|
-
this.manager.refresher
|
472
|
+
this.manager.refresher.add(this.stateKey, () => {
|
357
473
|
return autorun(() => {
|
358
474
|
const appState = this.appAttributes?.state;
|
359
475
|
if (appState?.zIndex > 0 && appState.zIndex !== this.box?.zIndex) {
|
@@ -361,13 +477,13 @@ export class AppProxy implements PageRemoveService {
|
|
361
477
|
}
|
362
478
|
});
|
363
479
|
});
|
364
|
-
this.manager.refresher
|
480
|
+
this.manager.refresher.add(`${appId}-fullPath`, () => {
|
365
481
|
return autorun(() => {
|
366
482
|
const fullPath = this.appAttributes?.fullPath;
|
367
483
|
this.setFocusScenePathHandler(fullPath);
|
368
|
-
if (this.
|
484
|
+
if (this.fullPath$.value !== fullPath) {
|
369
485
|
this.notifyPageStateChange();
|
370
|
-
this.
|
486
|
+
this.fullPath$.setValue(fullPath);
|
371
487
|
}
|
372
488
|
});
|
373
489
|
});
|
@@ -395,14 +511,17 @@ export class AppProxy implements PageRemoveService {
|
|
395
511
|
return fullPath;
|
396
512
|
}
|
397
513
|
|
398
|
-
private
|
399
|
-
const view =
|
514
|
+
private createView(): View {
|
515
|
+
const view = this.viewManager.createView(this.id);
|
516
|
+
this.view$.setValue(view);
|
400
517
|
this.setViewFocusScenePath();
|
401
518
|
return view;
|
402
519
|
}
|
403
520
|
|
404
521
|
public notifyPageStateChange = debounce(() => {
|
405
|
-
|
522
|
+
if (this.pageState) {
|
523
|
+
this.appEmitter.emit("pageStateChange", this.pageState);
|
524
|
+
}
|
406
525
|
}, 50);
|
407
526
|
|
408
527
|
public get pageState(): PageState {
|
@@ -412,7 +531,7 @@ export class AppProxy implements PageRemoveService {
|
|
412
531
|
// PageRemoveService
|
413
532
|
public async removeSceneByIndex(index: number) {
|
414
533
|
const scenePath = this._pageState.getFullPath(index);
|
415
|
-
if (scenePath) {
|
534
|
+
if (scenePath && this.pageState) {
|
416
535
|
const nextIndex = calculateNextIndex(index, this.pageState);
|
417
536
|
// 只修改 focus path 不修改 FullPath
|
418
537
|
this.setSceneIndexWithoutSync(nextIndex);
|
@@ -448,6 +567,31 @@ export class AppProxy implements PageRemoveService {
|
|
448
567
|
}
|
449
568
|
}
|
450
569
|
|
570
|
+
public storeCamera = (camera: ICamera) => {
|
571
|
+
this.store.updateAppAttributes(this.id, Fields.Camera, camera);
|
572
|
+
};
|
573
|
+
|
574
|
+
public storeSize = (size: ISize) => {
|
575
|
+
this.store.updateAppAttributes(this.id, Fields.Size, size);
|
576
|
+
};
|
577
|
+
|
578
|
+
public updateSize = (width: number, height: number) => {
|
579
|
+
const iSize = {
|
580
|
+
id: this.manager.uid,
|
581
|
+
width, height
|
582
|
+
}
|
583
|
+
this.store.updateAppAttributes(this.id, Fields.Size, iSize);
|
584
|
+
this.size$.setValue(iSize);
|
585
|
+
}
|
586
|
+
|
587
|
+
public moveCamera = (camera: Camera) => {
|
588
|
+
if (!this.camera$.value) {
|
589
|
+
return;
|
590
|
+
}
|
591
|
+
const nextCamera = { ...this.camera$.value, ...camera };
|
592
|
+
this.storeCamera(nextCamera);
|
593
|
+
};
|
594
|
+
|
451
595
|
public async destroy(
|
452
596
|
needCloseBox: boolean,
|
453
597
|
cleanAttrs: boolean,
|
@@ -463,6 +607,7 @@ export class AppProxy implements PageRemoveService {
|
|
463
607
|
console.error("[WindowManager]: notifyApp error", error.message, error.stack);
|
464
608
|
}
|
465
609
|
this.appEmitter.clearListeners();
|
610
|
+
this.sideEffectManager.flushAll();
|
466
611
|
emitter.emit(`destroy-${this.id}` as any, { error });
|
467
612
|
if (needCloseBox) {
|
468
613
|
this.boxManager?.closeBox(this.id, skipUpdate);
|
@@ -474,14 +619,49 @@ export class AppProxy implements PageRemoveService {
|
|
474
619
|
}
|
475
620
|
}
|
476
621
|
this.appProxies.delete(this.id);
|
477
|
-
this._pageState.destroy();
|
478
622
|
|
479
623
|
this.viewManager.destroyView(this.id);
|
480
624
|
this.manager.appStatus.delete(this.id);
|
481
|
-
this.manager.refresher
|
482
|
-
this.manager.refresher
|
483
|
-
this.manager.refresher
|
484
|
-
this.
|
625
|
+
this.manager.refresher.remove(this.id);
|
626
|
+
this.manager.refresher.remove(this.stateKey);
|
627
|
+
this.manager.refresher.remove(`${this.id}-fullPath`);
|
628
|
+
this.valManager.destroy();
|
629
|
+
}
|
630
|
+
|
631
|
+
private addCameraReaction = () => {
|
632
|
+
this.sideEffectManager.add(() =>
|
633
|
+
this.manager.refresher.add(`${this.id}-camera`, () =>
|
634
|
+
reaction(
|
635
|
+
() => this.appAttributes?.camera,
|
636
|
+
camera => {
|
637
|
+
if (camera && camera.id !== this.uid) {
|
638
|
+
const rawCamera = toJS(camera);
|
639
|
+
if (rawCamera !== this.camera$.value) {
|
640
|
+
this.camera$.setValue(rawCamera);
|
641
|
+
}
|
642
|
+
}
|
643
|
+
}
|
644
|
+
)
|
645
|
+
)
|
646
|
+
, "camera");
|
647
|
+
}
|
648
|
+
|
649
|
+
private addSizeReaction = () => {
|
650
|
+
this.sideEffectManager.add(() =>
|
651
|
+
this.manager.refresher.add(`${this.id}-size`, () =>
|
652
|
+
reaction(
|
653
|
+
() => this.appAttributes?.size,
|
654
|
+
size => {
|
655
|
+
if (size && size.id !== this.uid) {
|
656
|
+
const rawSize = toJS(size);
|
657
|
+
if (this.size$.value !== rawSize) {
|
658
|
+
this.size$.setValue(rawSize);
|
659
|
+
}
|
660
|
+
}
|
661
|
+
}
|
662
|
+
)
|
663
|
+
)
|
664
|
+
, "size");
|
485
665
|
}
|
486
666
|
|
487
667
|
public close(): Promise<void> {
|