@netless/window-manager 0.4.7 → 0.4.8-canary.0
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/AppManager.d.ts +8 -8
- package/dist/BoxManager.d.ts +1 -2
- package/dist/Helper.d.ts +2 -0
- package/dist/RedoUndo.d.ts +18 -0
- package/dist/View/MainView.d.ts +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.es.js +5 -5
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +5 -5
- package/dist/index.umd.js.map +1 -1
- package/package.json +2 -2
- package/src/AppManager.ts +46 -71
- package/src/AppProxy.ts +7 -3
- package/src/BoxManager.ts +4 -12
- package/src/Cursor/Cursor.ts +2 -1
- package/src/Helper.ts +6 -0
- package/src/RedoUndo.ts +87 -0
- package/src/View/MainView.ts +11 -0
- package/src/index.ts +4 -1
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@netless/window-manager",
|
3
|
-
"version": "0.4.
|
3
|
+
"version": "0.4.8-canary.0",
|
4
4
|
"description": "",
|
5
5
|
"main": "dist/index.es.js",
|
6
6
|
"module": "dist/index.es.js",
|
@@ -54,7 +54,7 @@
|
|
54
54
|
"rollup-plugin-analyzer": "^4.0.0",
|
55
55
|
"rollup-plugin-styles": "^3.14.1",
|
56
56
|
"svelte": "^3.42.4",
|
57
|
-
"typescript": "^4.
|
57
|
+
"typescript": "^4.5.5",
|
58
58
|
"vite": "^2.5.3",
|
59
59
|
"white-web-sdk": "2.16.10"
|
60
60
|
}
|
package/src/AppManager.ts
CHANGED
@@ -9,6 +9,8 @@ import { get, isInteger, orderBy } from "lodash";
|
|
9
9
|
import { log } from "./Utils/log";
|
10
10
|
import { MainViewProxy } from "./View/MainView";
|
11
11
|
import { onObjectRemoved, safeListenPropsUpdated } from "./Utils/Reactive";
|
12
|
+
import { RedoUndo } from "./RedoUndo";
|
13
|
+
import { SideEffectManager } from "side-effect-manager";
|
12
14
|
import { store } from "./AttributesDelegate";
|
13
15
|
import { ViewManager } from "./View/ViewManager";
|
14
16
|
import {
|
@@ -21,7 +23,7 @@ import {
|
|
21
23
|
} from "./Utils/Common";
|
22
24
|
import type { ReconnectRefresher } from "./ReconnectRefresher";
|
23
25
|
import type { BoxManager } from "./BoxManager";
|
24
|
-
import type { Displayer, DisplayerState, Room, ScenesCallbacksNode
|
26
|
+
import type { Displayer, DisplayerState, Room, ScenesCallbacksNode } from "white-web-sdk";
|
25
27
|
import type { AddAppParams, BaseInsertParams, TeleBoxRect, EmitterEvent } from "./index";
|
26
28
|
|
27
29
|
export class AppManager {
|
@@ -43,6 +45,8 @@ export class AppManager {
|
|
43
45
|
private callbacksNode: ScenesCallbacksNode | null = null;
|
44
46
|
private appCreateQueue = new AppCreateQueue();
|
45
47
|
|
48
|
+
private sideEffectManager = new SideEffectManager();
|
49
|
+
|
46
50
|
constructor(public windowManger: WindowManager) {
|
47
51
|
this.displayer = windowManger.displayer;
|
48
52
|
this.store.setContext({
|
@@ -50,6 +54,7 @@ export class AppManager {
|
|
50
54
|
safeSetAttributes: attributes => this.safeSetAttributes(attributes),
|
51
55
|
safeUpdateAttributes: (keys, val) => this.safeUpdateAttributes(keys, val),
|
52
56
|
});
|
57
|
+
|
53
58
|
this.mainViewProxy = new MainViewProxy(this);
|
54
59
|
this.viewManager = new ViewManager(this.displayer);
|
55
60
|
this.appListeners = new AppListeners(this);
|
@@ -60,6 +65,17 @@ export class AppManager {
|
|
60
65
|
this.refresher.setRoom(this.room);
|
61
66
|
this.refresher.setContext({ emitter });
|
62
67
|
|
68
|
+
this.sideEffectManager.add(() => {
|
69
|
+
return () => {
|
70
|
+
this.appCreateQueue.destroy();
|
71
|
+
this.mainViewProxy.destroy();
|
72
|
+
this.refresher?.destroy();
|
73
|
+
this.viewManager.destroy();
|
74
|
+
this.boxManager?.destroy();
|
75
|
+
this.callbacksNode?.dispose();
|
76
|
+
};
|
77
|
+
});
|
78
|
+
|
63
79
|
emitter.once("onCreated").then(() => this.onCreated());
|
64
80
|
emitter.on("onReconnected", () => this.onReconnected());
|
65
81
|
if (isPlayer(this.displayer)) {
|
@@ -75,6 +91,8 @@ export class AppManager {
|
|
75
91
|
if (scenePath === ROOT_DIR) {
|
76
92
|
this.setMainViewScenePath(ROOT_DIR);
|
77
93
|
this.createRootDirScenesCallback();
|
94
|
+
this.onRootDirRemoved();
|
95
|
+
emitter.emit("rootDirRemoved");
|
78
96
|
return;
|
79
97
|
}
|
80
98
|
const mainViewScenePath = this.store.getMainViewScenePath();
|
@@ -87,6 +105,20 @@ export class AppManager {
|
|
87
105
|
this.createRootDirScenesCallback();
|
88
106
|
}
|
89
107
|
|
108
|
+
/**
|
109
|
+
* 根目录被删除时所有的 scene 都会被删除.
|
110
|
+
* 所以需要关掉所有开启了 view 的 app
|
111
|
+
*/
|
112
|
+
private onRootDirRemoved() {
|
113
|
+
this.appProxies.forEach(appProxy => {
|
114
|
+
if (appProxy.view) {
|
115
|
+
this.closeApp(appProxy.id);
|
116
|
+
}
|
117
|
+
});
|
118
|
+
// 删除了根目录的 scenes 之后 mainview 需要重新绑定, 否则主白板会不能渲染
|
119
|
+
this.mainViewProxy.rebind();
|
120
|
+
}
|
121
|
+
|
90
122
|
private createRootDirScenesCallback = () => {
|
91
123
|
let isRecreate = false;
|
92
124
|
if (this.callbacksNode) {
|
@@ -109,7 +141,7 @@ export class AppManager {
|
|
109
141
|
callbacks.emit("mainViewScenesLengthChange", this.callbacksNode.scenes.length);
|
110
142
|
}
|
111
143
|
}
|
112
|
-
}
|
144
|
+
};
|
113
145
|
|
114
146
|
private get eventName() {
|
115
147
|
return isRoom(this.displayer) ? "onRoomStateChanged" : "onPlayerStateChanged";
|
@@ -152,7 +184,7 @@ export class AppManager {
|
|
152
184
|
|
153
185
|
private async onCreated() {
|
154
186
|
await this.attributesUpdateCallback(this.attributes.apps);
|
155
|
-
|
187
|
+
emitter.emit("updateManagerRect");
|
156
188
|
emitter.onAny(this.boxEventListener);
|
157
189
|
this.refresher?.add("apps", () => {
|
158
190
|
return safeListenPropsUpdated(
|
@@ -200,10 +232,7 @@ export class AppManager {
|
|
200
232
|
const focused = get(this.attributes, "focus");
|
201
233
|
if (this._prevFocused !== focused) {
|
202
234
|
callbacks.emit("focusedChange", focused);
|
203
|
-
|
204
|
-
setTimeout(() => {
|
205
|
-
this.addRedoUndoListeners(focused);
|
206
|
-
}, 0);
|
235
|
+
emitter.emit("focusedChange", { focused, prev: this._prevFocused });
|
207
236
|
this._prevFocused = focused;
|
208
237
|
if (focused !== undefined) {
|
209
238
|
this.boxManager?.focusBox({ appId: focused });
|
@@ -229,59 +258,16 @@ export class AppManager {
|
|
229
258
|
this.displayerWritableListener(!this.room?.isWritable);
|
230
259
|
this.displayer.callbacks.on("onEnableWriteNowChanged", this.displayerWritableListener);
|
231
260
|
this._prevFocused = this.attributes.focus;
|
232
|
-
this.addRedoUndoListeners(this.attributes.focus);
|
233
|
-
}
|
234
261
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
}
|
245
|
-
}
|
246
|
-
};
|
247
|
-
|
248
|
-
private addRedoUndoListeners = (focused: string | undefined) => {
|
249
|
-
if (focused === undefined) {
|
250
|
-
this.addViewCallbacks(
|
251
|
-
this.mainView,
|
252
|
-
this.onCanRedoStepsUpdate,
|
253
|
-
this.onCanUndoStepsUpdate
|
254
|
-
);
|
255
|
-
} else {
|
256
|
-
const focusApp = this.appProxies.get(focused);
|
257
|
-
if (focusApp && focusApp.view) {
|
258
|
-
this.addViewCallbacks(
|
259
|
-
focusApp.view,
|
260
|
-
this.onCanRedoStepsUpdate,
|
261
|
-
this.onCanUndoStepsUpdate
|
262
|
-
);
|
263
|
-
}
|
264
|
-
}
|
265
|
-
};
|
266
|
-
|
267
|
-
private addViewCallbacks = (
|
268
|
-
view: View,
|
269
|
-
redoListener: (steps: number) => void,
|
270
|
-
undoListener: (steps: number) => void
|
271
|
-
) => {
|
272
|
-
redoListener(view.canRedoSteps);
|
273
|
-
undoListener(view.canUndoSteps);
|
274
|
-
view.callbacks.on("onCanRedoStepsUpdate", redoListener);
|
275
|
-
view.callbacks.on("onCanUndoStepsUpdate", undoListener);
|
276
|
-
};
|
277
|
-
|
278
|
-
private onCanRedoStepsUpdate = (steps: number) => {
|
279
|
-
callbacks.emit("canRedoStepsChange", steps);
|
280
|
-
};
|
281
|
-
|
282
|
-
private onCanUndoStepsUpdate = (steps: number) => {
|
283
|
-
callbacks.emit("canUndoStepsChange", steps);
|
284
|
-
};
|
262
|
+
this.sideEffectManager.add(() => {
|
263
|
+
const redoUndo = new RedoUndo({
|
264
|
+
mainView: () => this.mainViewProxy.view,
|
265
|
+
focus: () => this.attributes.focus,
|
266
|
+
getAppProxy: id => this.appProxies.get(id),
|
267
|
+
});
|
268
|
+
return () => redoUndo.destroy();
|
269
|
+
});
|
270
|
+
}
|
285
271
|
|
286
272
|
/**
|
287
273
|
* 插件更新 attributes 时的回调
|
@@ -637,11 +623,6 @@ export class AppManager {
|
|
637
623
|
});
|
638
624
|
}
|
639
625
|
|
640
|
-
public findMemberByUid = (uid: string) => {
|
641
|
-
const roomMembers = this.room?.state.roomMembers;
|
642
|
-
return roomMembers?.find(member => member.payload?.uid === uid);
|
643
|
-
};
|
644
|
-
|
645
626
|
public destroy() {
|
646
627
|
this.displayer.callbacks.off(this.eventName, this.displayerStateListener);
|
647
628
|
this.displayer.callbacks.off("onEnableWriteNowChanged", this.displayerWritableListener);
|
@@ -653,14 +634,8 @@ export class AppManager {
|
|
653
634
|
appProxy.destroy(true, false, true);
|
654
635
|
});
|
655
636
|
}
|
656
|
-
this.viewManager.destroy();
|
657
|
-
this.boxManager?.destroy();
|
658
|
-
this.refresher?.destroy();
|
659
|
-
this.mainViewProxy.destroy();
|
660
637
|
callbacks.clearListeners();
|
661
|
-
this.
|
662
|
-
this.appCreateQueue.destroy();
|
663
|
-
this.disposePrevFocusViewRedoUndoListeners(this._prevFocused);
|
638
|
+
this.sideEffectManager.flushAll();
|
664
639
|
this._prevFocused = undefined;
|
665
640
|
this._prevSceneIndex = undefined;
|
666
641
|
}
|
package/src/AppProxy.ts
CHANGED
@@ -127,7 +127,7 @@ export class AppProxy {
|
|
127
127
|
} else {
|
128
128
|
throw new Error(`[WindowManager]: app load failed ${params.kind} ${params.src}`);
|
129
129
|
}
|
130
|
-
|
130
|
+
emitter.emit("updateManagerRect")
|
131
131
|
return {
|
132
132
|
appId: this.id,
|
133
133
|
app: appImpl,
|
@@ -363,8 +363,12 @@ export class AppProxy {
|
|
363
363
|
) {
|
364
364
|
if (this.status === "destroyed") return;
|
365
365
|
this.status = "destroyed";
|
366
|
-
|
367
|
-
|
366
|
+
try {
|
367
|
+
await appRegister.notifyApp(this.kind, "destroy", { appId: this.id });
|
368
|
+
await this.appEmitter.emit("destroy", { error });
|
369
|
+
} catch (error) {
|
370
|
+
console.error("[WindowManager]: notifyApp error", error.message, error.stack);
|
371
|
+
}
|
368
372
|
this.appEmitter.clearListeners();
|
369
373
|
emitter.emit(`destroy-${this.id}` as any, { error });
|
370
374
|
if (needCloseBox) {
|
package/src/BoxManager.ts
CHANGED
@@ -1,11 +1,7 @@
|
|
1
1
|
import { AppAttributes, Events, MIN_HEIGHT, MIN_WIDTH } from "./constants";
|
2
2
|
import { debounce } from "lodash";
|
3
|
-
import {
|
4
|
-
import {
|
5
|
-
TELE_BOX_STATE,
|
6
|
-
TeleBoxCollector,
|
7
|
-
TeleBoxManager,
|
8
|
-
} from "@netless/telebox-insider";
|
3
|
+
import { TELE_BOX_STATE, TeleBoxCollector, TeleBoxManager } from "@netless/telebox-insider";
|
4
|
+
import { WindowManager } from "./index";
|
9
5
|
import type { AddAppOptions, AppInitState, EmitterType, CallbacksType } from "./index";
|
10
6
|
import type {
|
11
7
|
TeleBoxManagerUpdateConfig,
|
@@ -156,13 +152,10 @@ export class BoxManager {
|
|
156
152
|
this.teleBoxManager.events.on("z_index", box => {
|
157
153
|
this.context.updateAppState(box.id, AppAttributes.ZIndex, box.zIndex);
|
158
154
|
});
|
159
|
-
emitter.on("playgroundSizeChange", this.
|
155
|
+
emitter.on("playgroundSizeChange", () => this.updateManagerRect());
|
156
|
+
emitter.on("updateManagerRect", () => this.updateManagerRect());
|
160
157
|
}
|
161
158
|
|
162
|
-
private playgroundSizeChangeListener = () => {
|
163
|
-
this.updateManagerRect();
|
164
|
-
};
|
165
|
-
|
166
159
|
private get mainView() {
|
167
160
|
return this.context.getMainView();
|
168
161
|
}
|
@@ -406,7 +399,6 @@ export class BoxManager {
|
|
406
399
|
}
|
407
400
|
|
408
401
|
public destroy() {
|
409
|
-
emitter.off("playgroundSizeChange", this.playgroundSizeChangeListener);
|
410
402
|
this.teleBoxManager.destroy();
|
411
403
|
}
|
412
404
|
}
|
package/src/Cursor/Cursor.ts
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import App from "./Cursor.svelte";
|
2
2
|
import { ApplianceMap } from "./icons";
|
3
3
|
import { ApplianceNames } from "white-web-sdk";
|
4
|
+
import { findMemberByUid } from "../Helper";
|
4
5
|
import { omit } from "lodash";
|
5
6
|
import type { Position } from "../AttributesDelegate";
|
6
7
|
import type { RoomMember } from "white-web-sdk";
|
@@ -164,7 +165,7 @@ export class Cursor {
|
|
164
165
|
}
|
165
166
|
|
166
167
|
public updateMember() {
|
167
|
-
this.member = this.manager.
|
168
|
+
this.member = findMemberByUid(this.manager.room, this.memberId);
|
168
169
|
this.updateComponent();
|
169
170
|
return this.member;
|
170
171
|
}
|
package/src/Helper.ts
CHANGED
@@ -3,6 +3,7 @@ import { REQUIRE_VERSION } from "./constants";
|
|
3
3
|
import { WhiteVersion } from "white-web-sdk";
|
4
4
|
import { WhiteWebSDKInvalidError } from "./Utils/error";
|
5
5
|
import { WindowManager } from "./index";
|
6
|
+
import type { Room } from "white-web-sdk";
|
6
7
|
|
7
8
|
export const setupWrapper = (
|
8
9
|
root: HTMLElement
|
@@ -39,3 +40,8 @@ export const checkVersion = () => {
|
|
39
40
|
throw new WhiteWebSDKInvalidError(REQUIRE_VERSION);
|
40
41
|
}
|
41
42
|
};
|
43
|
+
|
44
|
+
export const findMemberByUid = (room: Room | undefined, uid: string) => {
|
45
|
+
const roomMembers = room?.state.roomMembers;
|
46
|
+
return roomMembers?.find(member => member.payload?.uid === uid);
|
47
|
+
};
|
package/src/RedoUndo.ts
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
import { callbacks, emitter } from "./index";
|
2
|
+
import type { View } from "white-web-sdk";
|
3
|
+
import type { AppProxy } from "./AppProxy";
|
4
|
+
|
5
|
+
export type RedoUndoContext = {
|
6
|
+
mainView: () => View;
|
7
|
+
focus: () => string | undefined;
|
8
|
+
getAppProxy: (id: string) => AppProxy | undefined;
|
9
|
+
};
|
10
|
+
|
11
|
+
export class RedoUndo {
|
12
|
+
constructor(private context: RedoUndoContext) {
|
13
|
+
emitter.on("focusedChange", changed => {
|
14
|
+
this.disposePrevFocusViewRedoUndoListeners(changed.prev);
|
15
|
+
setTimeout(() => {
|
16
|
+
this.addRedoUndoListeners(changed.focused);
|
17
|
+
}, 0);
|
18
|
+
});
|
19
|
+
emitter.on("rootDirRemoved", () => {
|
20
|
+
this.disposePrevFocusViewRedoUndoListeners(context.focus());
|
21
|
+
this.addRedoUndoListeners(context.focus());
|
22
|
+
});
|
23
|
+
this.addRedoUndoListeners(context.focus());
|
24
|
+
}
|
25
|
+
|
26
|
+
private addRedoUndoListeners = (focused: string | undefined) => {
|
27
|
+
if (focused === undefined) {
|
28
|
+
this.addViewCallbacks(
|
29
|
+
this.context.mainView(),
|
30
|
+
this.onCanRedoStepsUpdate,
|
31
|
+
this.onCanUndoStepsUpdate
|
32
|
+
);
|
33
|
+
} else {
|
34
|
+
const focusApp = this.context.getAppProxy(focused);
|
35
|
+
if (focusApp && focusApp.view) {
|
36
|
+
this.addViewCallbacks(
|
37
|
+
focusApp.view,
|
38
|
+
this.onCanRedoStepsUpdate,
|
39
|
+
this.onCanUndoStepsUpdate
|
40
|
+
);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
};
|
44
|
+
|
45
|
+
private addViewCallbacks = (
|
46
|
+
view: View,
|
47
|
+
redoListener: (steps: number) => void,
|
48
|
+
undoListener: (steps: number) => void
|
49
|
+
) => {
|
50
|
+
redoListener(view.canRedoSteps);
|
51
|
+
undoListener(view.canUndoSteps);
|
52
|
+
view.callbacks.on("onCanRedoStepsUpdate", redoListener);
|
53
|
+
view.callbacks.on("onCanUndoStepsUpdate", undoListener);
|
54
|
+
};
|
55
|
+
|
56
|
+
private disposeViewCallbacks = (view: View) => {
|
57
|
+
view.callbacks.off("onCanRedoStepsUpdate", this.onCanRedoStepsUpdate);
|
58
|
+
view.callbacks.off("onCanUndoStepsUpdate", this.onCanUndoStepsUpdate);
|
59
|
+
};
|
60
|
+
|
61
|
+
private onCanRedoStepsUpdate = (steps: number) => {
|
62
|
+
callbacks.emit("canRedoStepsChange", steps);
|
63
|
+
};
|
64
|
+
|
65
|
+
private onCanUndoStepsUpdate = (steps: number) => {
|
66
|
+
callbacks.emit("canUndoStepsChange", steps);
|
67
|
+
};
|
68
|
+
|
69
|
+
private disposePrevFocusViewRedoUndoListeners = (prevFocused: string | undefined) => {
|
70
|
+
let view: View | undefined = undefined;
|
71
|
+
if (prevFocused === undefined) {
|
72
|
+
view = this.context.mainView();
|
73
|
+
} else {
|
74
|
+
const appProxy = this.context.getAppProxy(prevFocused);
|
75
|
+
if (appProxy && appProxy.view) {
|
76
|
+
view = appProxy.view;
|
77
|
+
}
|
78
|
+
}
|
79
|
+
if (view) {
|
80
|
+
this.disposeViewCallbacks(view);
|
81
|
+
}
|
82
|
+
};
|
83
|
+
|
84
|
+
public destroy() {
|
85
|
+
this.disposePrevFocusViewRedoUndoListeners(this.context.focus());
|
86
|
+
}
|
87
|
+
}
|
package/src/View/MainView.ts
CHANGED
@@ -110,6 +110,17 @@ export class MainViewProxy {
|
|
110
110
|
}
|
111
111
|
}
|
112
112
|
|
113
|
+
public rebind(): void {
|
114
|
+
const divElement = this.mainView.divElement;
|
115
|
+
const disableCameraTransform = this.mainView.disableCameraTransform;
|
116
|
+
this.stop();
|
117
|
+
this.mainView.release();
|
118
|
+
this.mainView = this.createMainView();
|
119
|
+
this.mainView.disableCameraTransform = disableCameraTransform;
|
120
|
+
this.mainView.divElement = divElement;
|
121
|
+
this.start();
|
122
|
+
}
|
123
|
+
|
113
124
|
private onCameraUpdatedByDevice = (camera: Camera) => {
|
114
125
|
this.store.setMainViewCamera({ ...camera, id: this.manager.uid });
|
115
126
|
if (!isEqual(this.mainViewSize, { ...this.mainView.size, id: this.manager.uid })) {
|
package/src/index.ts
CHANGED
@@ -138,6 +138,9 @@ export type EmitterEvent = {
|
|
138
138
|
onReconnected: void;
|
139
139
|
removeScenes: string;
|
140
140
|
cursorMove: CursorMovePayload;
|
141
|
+
updateManagerRect: undefined;
|
142
|
+
focusedChange: { focused: string | undefined, prev: string | undefined };
|
143
|
+
rootDirRemoved: undefined;
|
141
144
|
};
|
142
145
|
|
143
146
|
export type EmitterType = Emittery<EmitterEvent>;
|
@@ -374,7 +377,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
|
|
374
377
|
}
|
375
378
|
}
|
376
379
|
}
|
377
|
-
|
380
|
+
emitter.emit("updateManagerRect");
|
378
381
|
this.appManager?.refresh();
|
379
382
|
this.appManager?.resetMaximized();
|
380
383
|
this.appManager?.resetMinimized();
|