@netless/window-manager 0.4.7 → 0.4.9-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/CHANGELOG.md +5 -0
- package/README.md +1 -0
- package/dist/AppContext.d.ts +4 -4
- package/dist/AppManager.d.ts +12 -9
- package/dist/BoxManager.d.ts +4 -3
- package/dist/ContainerResizeObserver.d.ts +1 -1
- package/dist/Helper.d.ts +2 -0
- package/dist/InternalEmitter.d.ts +41 -0
- package/dist/ReconnectRefresher.d.ts +1 -1
- package/dist/RedoUndo.d.ts +18 -0
- package/dist/Utils/AppCreateQueue.d.ts +2 -0
- package/dist/Utils/Common.d.ts +1 -1
- package/dist/View/MainView.d.ts +1 -0
- package/dist/callback.d.ts +21 -0
- package/dist/index.d.ts +5 -52
- 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/dist/style.css +1 -1
- package/docs/advanced.md +13 -0
- package/docs/api.md +15 -1
- package/docs/develop-app.md +50 -0
- package/package.json +3 -3
- package/src/AppContext.ts +51 -33
- package/src/AppListener.ts +2 -1
- package/src/AppManager.ts +90 -82
- package/src/AppProxy.ts +8 -4
- package/src/BoxManager.ts +7 -13
- package/src/ContainerResizeObserver.ts +1 -1
- package/src/Cursor/Cursor.ts +2 -1
- package/src/Cursor/index.ts +4 -2
- package/src/Helper.ts +6 -0
- package/src/InternalEmitter.ts +27 -0
- package/src/ReconnectRefresher.ts +1 -1
- package/src/RedoUndo.ts +88 -0
- package/src/Register/index.ts +1 -0
- package/src/Register/loader.ts +1 -1
- package/src/Utils/AppCreateQueue.ts +10 -0
- package/src/Utils/Common.ts +2 -2
- package/src/Utils/RoomHacker.ts +3 -3
- package/src/View/MainView.ts +13 -1
- package/src/callback.ts +23 -0
- package/src/index.ts +23 -57
package/src/AppManager.ts
CHANGED
@@ -4,13 +4,18 @@ import { AppListeners } from "./AppListener";
|
|
4
4
|
import { AppProxy } from "./AppProxy";
|
5
5
|
import { appRegister } from "./Register";
|
6
6
|
import { autorun, isPlayer, isRoom, ScenePathType } from "white-web-sdk";
|
7
|
-
import { callbacks
|
7
|
+
import { callbacks } from "./callback";
|
8
|
+
import { emitter } from "./InternalEmitter";
|
8
9
|
import { get, isInteger, orderBy } from "lodash";
|
9
10
|
import { log } from "./Utils/log";
|
10
11
|
import { MainViewProxy } from "./View/MainView";
|
11
12
|
import { onObjectRemoved, safeListenPropsUpdated } from "./Utils/Reactive";
|
13
|
+
import { reconnectRefresher, WindowManager } from "./index";
|
14
|
+
import { RedoUndo } from "./RedoUndo";
|
15
|
+
import { SideEffectManager } from "side-effect-manager";
|
12
16
|
import { store } from "./AttributesDelegate";
|
13
17
|
import { ViewManager } from "./View/ViewManager";
|
18
|
+
import type { EmitterEvent } from "./InternalEmitter";
|
14
19
|
import {
|
15
20
|
entireScenes,
|
16
21
|
genAppId,
|
@@ -21,9 +26,14 @@ import {
|
|
21
26
|
} from "./Utils/Common";
|
22
27
|
import type { ReconnectRefresher } from "./ReconnectRefresher";
|
23
28
|
import type { BoxManager } from "./BoxManager";
|
24
|
-
import type {
|
25
|
-
|
26
|
-
|
29
|
+
import type {
|
30
|
+
Displayer,
|
31
|
+
DisplayerState,
|
32
|
+
Room,
|
33
|
+
ScenesCallbacksNode,
|
34
|
+
SceneState,
|
35
|
+
} from "white-web-sdk";
|
36
|
+
import type { AddAppParams, BaseInsertParams, TeleBoxRect } from "./index";
|
27
37
|
export class AppManager {
|
28
38
|
public displayer: Displayer;
|
29
39
|
public viewManager: ViewManager;
|
@@ -43,6 +53,10 @@ export class AppManager {
|
|
43
53
|
private callbacksNode: ScenesCallbacksNode | null = null;
|
44
54
|
private appCreateQueue = new AppCreateQueue();
|
45
55
|
|
56
|
+
private sideEffectManager = new SideEffectManager();
|
57
|
+
|
58
|
+
public sceneState: SceneState | null = null;
|
59
|
+
|
46
60
|
constructor(public windowManger: WindowManager) {
|
47
61
|
this.displayer = windowManger.displayer;
|
48
62
|
this.store.setContext({
|
@@ -50,6 +64,7 @@ export class AppManager {
|
|
50
64
|
safeSetAttributes: attributes => this.safeSetAttributes(attributes),
|
51
65
|
safeUpdateAttributes: (keys, val) => this.safeUpdateAttributes(keys, val),
|
52
66
|
});
|
67
|
+
|
53
68
|
this.mainViewProxy = new MainViewProxy(this);
|
54
69
|
this.viewManager = new ViewManager(this.displayer);
|
55
70
|
this.appListeners = new AppListeners(this);
|
@@ -60,6 +75,17 @@ export class AppManager {
|
|
60
75
|
this.refresher.setRoom(this.room);
|
61
76
|
this.refresher.setContext({ emitter });
|
62
77
|
|
78
|
+
this.sideEffectManager.add(() => {
|
79
|
+
return () => {
|
80
|
+
this.appCreateQueue.destroy();
|
81
|
+
this.mainViewProxy.destroy();
|
82
|
+
this.refresher?.destroy();
|
83
|
+
this.viewManager.destroy();
|
84
|
+
this.boxManager?.destroy();
|
85
|
+
this.callbacksNode?.dispose();
|
86
|
+
};
|
87
|
+
});
|
88
|
+
|
63
89
|
emitter.once("onCreated").then(() => this.onCreated());
|
64
90
|
emitter.on("onReconnected", () => this.onReconnected());
|
65
91
|
if (isPlayer(this.displayer)) {
|
@@ -75,6 +101,8 @@ export class AppManager {
|
|
75
101
|
if (scenePath === ROOT_DIR) {
|
76
102
|
this.setMainViewScenePath(ROOT_DIR);
|
77
103
|
this.createRootDirScenesCallback();
|
104
|
+
this.onRootDirRemoved();
|
105
|
+
emitter.emit("rootDirRemoved");
|
78
106
|
return;
|
79
107
|
}
|
80
108
|
const mainViewScenePath = this.store.getMainViewScenePath();
|
@@ -87,6 +115,20 @@ export class AppManager {
|
|
87
115
|
this.createRootDirScenesCallback();
|
88
116
|
}
|
89
117
|
|
118
|
+
/**
|
119
|
+
* 根目录被删除时所有的 scene 都会被删除.
|
120
|
+
* 所以需要关掉所有开启了 view 的 app
|
121
|
+
*/
|
122
|
+
private onRootDirRemoved() {
|
123
|
+
this.appProxies.forEach(appProxy => {
|
124
|
+
if (appProxy.view) {
|
125
|
+
this.closeApp(appProxy.id);
|
126
|
+
}
|
127
|
+
});
|
128
|
+
// 删除了根目录的 scenes 之后 mainview 需要重新绑定, 否则主白板会不能渲染
|
129
|
+
this.mainViewProxy.rebind();
|
130
|
+
}
|
131
|
+
|
90
132
|
private createRootDirScenesCallback = () => {
|
91
133
|
let isRecreate = false;
|
92
134
|
if (this.callbacksNode) {
|
@@ -94,22 +136,39 @@ export class AppManager {
|
|
94
136
|
isRecreate = true;
|
95
137
|
}
|
96
138
|
this.callbacksNode = this.displayer.createScenesCallback(ROOT_DIR, {
|
97
|
-
onAddScene:
|
98
|
-
|
99
|
-
callbacks.emit("mainViewScenesLengthChange", this.mainViewScenesLength);
|
100
|
-
},
|
101
|
-
onRemoveScene: scenesCallback => {
|
102
|
-
this.mainViewScenesLength = scenesCallback.scenes.length;
|
103
|
-
callbacks.emit("mainViewScenesLengthChange", this.mainViewScenesLength);
|
104
|
-
},
|
139
|
+
onAddScene: this.onSceneChange,
|
140
|
+
onRemoveScene: this.onSceneChange,
|
105
141
|
});
|
106
142
|
if (this.callbacksNode) {
|
143
|
+
this.updateSceneState(this.callbacksNode);
|
107
144
|
this.mainViewScenesLength = this.callbacksNode.scenes.length;
|
108
145
|
if (isRecreate) {
|
109
146
|
callbacks.emit("mainViewScenesLengthChange", this.callbacksNode.scenes.length);
|
110
147
|
}
|
111
148
|
}
|
112
|
-
}
|
149
|
+
};
|
150
|
+
|
151
|
+
private onSceneChange = (node: ScenesCallbacksNode) => {
|
152
|
+
this.mainViewScenesLength = node.scenes.length;
|
153
|
+
this.updateSceneState(node);
|
154
|
+
callbacks.emit("mainViewScenesLengthChange", this.mainViewScenesLength);
|
155
|
+
};
|
156
|
+
|
157
|
+
private updateSceneState = (node: ScenesCallbacksNode) => {
|
158
|
+
const currentIndex = this.store.getMainViewSceneIndex() || 0;
|
159
|
+
const sceneName = node.scenes[currentIndex];
|
160
|
+
this.sceneState = {
|
161
|
+
scenePath: `${ROOT_DIR}${sceneName}`,
|
162
|
+
contextPath: node.path,
|
163
|
+
index: currentIndex,
|
164
|
+
scenes: node.scenes.map(scene => {
|
165
|
+
return {
|
166
|
+
name: scene,
|
167
|
+
};
|
168
|
+
}),
|
169
|
+
sceneName: sceneName,
|
170
|
+
};
|
171
|
+
};
|
113
172
|
|
114
173
|
private get eventName() {
|
115
174
|
return isRoom(this.displayer) ? "onRoomStateChanged" : "onPlayerStateChanged";
|
@@ -152,7 +211,7 @@ export class AppManager {
|
|
152
211
|
|
153
212
|
private async onCreated() {
|
154
213
|
await this.attributesUpdateCallback(this.attributes.apps);
|
155
|
-
|
214
|
+
emitter.emit("updateManagerRect");
|
156
215
|
emitter.onAny(this.boxEventListener);
|
157
216
|
this.refresher?.add("apps", () => {
|
158
217
|
return safeListenPropsUpdated(
|
@@ -191,6 +250,9 @@ export class AppManager {
|
|
191
250
|
const mainSceneIndex = get(this.attributes, "_mainSceneIndex");
|
192
251
|
if (mainSceneIndex !== undefined && this._prevSceneIndex !== mainSceneIndex) {
|
193
252
|
callbacks.emit("mainViewSceneIndexChange", mainSceneIndex);
|
253
|
+
if (this.callbacksNode) {
|
254
|
+
this.updateSceneState(this.callbacksNode);
|
255
|
+
}
|
194
256
|
this._prevSceneIndex = mainSceneIndex;
|
195
257
|
}
|
196
258
|
});
|
@@ -200,10 +262,7 @@ export class AppManager {
|
|
200
262
|
const focused = get(this.attributes, "focus");
|
201
263
|
if (this._prevFocused !== focused) {
|
202
264
|
callbacks.emit("focusedChange", focused);
|
203
|
-
|
204
|
-
setTimeout(() => {
|
205
|
-
this.addRedoUndoListeners(focused);
|
206
|
-
}, 0);
|
265
|
+
emitter.emit("focusedChange", { focused, prev: this._prevFocused });
|
207
266
|
this._prevFocused = focused;
|
208
267
|
if (focused !== undefined) {
|
209
268
|
this.boxManager?.focusBox({ appId: focused });
|
@@ -229,59 +288,16 @@ export class AppManager {
|
|
229
288
|
this.displayerWritableListener(!this.room?.isWritable);
|
230
289
|
this.displayer.callbacks.on("onEnableWriteNowChanged", this.displayerWritableListener);
|
231
290
|
this._prevFocused = this.attributes.focus;
|
232
|
-
this.addRedoUndoListeners(this.attributes.focus);
|
233
|
-
}
|
234
|
-
|
235
|
-
private disposePrevFocusViewRedoUndoListeners = (prevFocused: string | undefined) => {
|
236
|
-
if (prevFocused === undefined) {
|
237
|
-
this.mainView.callbacks.off("onCanRedoStepsUpdate", this.onCanRedoStepsUpdate);
|
238
|
-
this.mainView.callbacks.off("onCanUndoStepsUpdate", this.onCanRedoStepsUpdate);
|
239
|
-
} else {
|
240
|
-
const appProxy = this.appProxies.get(prevFocused);
|
241
|
-
if (appProxy) {
|
242
|
-
appProxy.view?.callbacks.off("onCanRedoStepsUpdate", this.onCanRedoStepsUpdate);
|
243
|
-
appProxy.view?.callbacks.off("onCanUndoStepsUpdate", this.onCanUndoStepsUpdate);
|
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
291
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
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
|
-
};
|
292
|
+
this.sideEffectManager.add(() => {
|
293
|
+
const redoUndo = new RedoUndo({
|
294
|
+
mainView: () => this.mainViewProxy.view,
|
295
|
+
focus: () => this.attributes.focus,
|
296
|
+
getAppProxy: id => this.appProxies.get(id),
|
297
|
+
});
|
298
|
+
return () => redoUndo.destroy();
|
299
|
+
});
|
300
|
+
}
|
285
301
|
|
286
302
|
/**
|
287
303
|
* 插件更新 attributes 时的回调
|
@@ -292,6 +308,9 @@ export class AppManager {
|
|
292
308
|
public async attributesUpdateCallback(apps: any) {
|
293
309
|
if (apps && WindowManager.container) {
|
294
310
|
const appIds = Object.keys(apps);
|
311
|
+
if (appIds.length === 0) {
|
312
|
+
this.appCreateQueue.emitReady();
|
313
|
+
}
|
295
314
|
const appsWithCreatedAt = appIds.map(appId => {
|
296
315
|
return {
|
297
316
|
id: appId,
|
@@ -637,11 +656,6 @@ export class AppManager {
|
|
637
656
|
});
|
638
657
|
}
|
639
658
|
|
640
|
-
public findMemberByUid = (uid: string) => {
|
641
|
-
const roomMembers = this.room?.state.roomMembers;
|
642
|
-
return roomMembers?.find(member => member.payload?.uid === uid);
|
643
|
-
};
|
644
|
-
|
645
659
|
public destroy() {
|
646
660
|
this.displayer.callbacks.off(this.eventName, this.displayerStateListener);
|
647
661
|
this.displayer.callbacks.off("onEnableWriteNowChanged", this.displayerWritableListener);
|
@@ -653,14 +667,8 @@ export class AppManager {
|
|
653
667
|
appProxy.destroy(true, false, true);
|
654
668
|
});
|
655
669
|
}
|
656
|
-
this.viewManager.destroy();
|
657
|
-
this.boxManager?.destroy();
|
658
|
-
this.refresher?.destroy();
|
659
|
-
this.mainViewProxy.destroy();
|
660
670
|
callbacks.clearListeners();
|
661
|
-
this.
|
662
|
-
this.appCreateQueue.destroy();
|
663
|
-
this.disposePrevFocusViewRedoUndoListeners(this._prevFocused);
|
671
|
+
this.sideEffectManager.flushAll();
|
664
672
|
this._prevFocused = undefined;
|
665
673
|
this._prevSceneIndex = undefined;
|
666
674
|
}
|
package/src/AppProxy.ts
CHANGED
@@ -5,7 +5,7 @@ import { appRegister } from "./Register";
|
|
5
5
|
import { autorun } from "white-web-sdk";
|
6
6
|
import { BoxManagerNotFoundError } from "./Utils/error";
|
7
7
|
import { debounce, get } from "lodash";
|
8
|
-
import { emitter } from "./
|
8
|
+
import { emitter } from "./InternalEmitter";
|
9
9
|
import { Fields } from "./AttributesDelegate";
|
10
10
|
import { entireScenes, getScenePath, removeScenes, setScenePath, setViewFocusScenePath } from "./Utils/Common";
|
11
11
|
import { log } from "./Utils/log";
|
@@ -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,12 +1,8 @@
|
|
1
1
|
import { AppAttributes, Events, MIN_HEIGHT, MIN_WIDTH } from "./constants";
|
2
2
|
import { debounce } from "lodash";
|
3
|
-
import {
|
4
|
-
import {
|
5
|
-
|
6
|
-
TeleBoxCollector,
|
7
|
-
TeleBoxManager,
|
8
|
-
} from "@netless/telebox-insider";
|
9
|
-
import type { AddAppOptions, AppInitState, EmitterType, CallbacksType } from "./index";
|
3
|
+
import { TELE_BOX_STATE, TeleBoxCollector, TeleBoxManager } from "@netless/telebox-insider";
|
4
|
+
import { WindowManager } from "./index";
|
5
|
+
import type { AddAppOptions, AppInitState } from "./index";
|
10
6
|
import type {
|
11
7
|
TeleBoxManagerUpdateConfig,
|
12
8
|
TeleBoxManagerCreateConfig,
|
@@ -19,6 +15,8 @@ import type {
|
|
19
15
|
import type Emittery from "emittery";
|
20
16
|
import type { NetlessApp } from "./typings";
|
21
17
|
import type { View } from "white-web-sdk";
|
18
|
+
import type { CallbacksType } from "./callback";
|
19
|
+
import type { EmitterType } from "./InternalEmitter";
|
22
20
|
|
23
21
|
export { TELE_BOX_STATE };
|
24
22
|
|
@@ -156,13 +154,10 @@ export class BoxManager {
|
|
156
154
|
this.teleBoxManager.events.on("z_index", box => {
|
157
155
|
this.context.updateAppState(box.id, AppAttributes.ZIndex, box.zIndex);
|
158
156
|
});
|
159
|
-
emitter.on("playgroundSizeChange", this.
|
157
|
+
emitter.on("playgroundSizeChange", () => this.updateManagerRect());
|
158
|
+
emitter.on("updateManagerRect", () => this.updateManagerRect());
|
160
159
|
}
|
161
160
|
|
162
|
-
private playgroundSizeChangeListener = () => {
|
163
|
-
this.updateManagerRect();
|
164
|
-
};
|
165
|
-
|
166
161
|
private get mainView() {
|
167
162
|
return this.context.getMainView();
|
168
163
|
}
|
@@ -406,7 +401,6 @@ export class BoxManager {
|
|
406
401
|
}
|
407
402
|
|
408
403
|
public destroy() {
|
409
|
-
emitter.off("playgroundSizeChange", this.playgroundSizeChangeListener);
|
410
404
|
this.teleBoxManager.destroy();
|
411
405
|
}
|
412
406
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { ResizeObserver as ResizeObserverPolyfill } from "@juggle/resize-observer";
|
2
2
|
import { WindowManager } from "./index";
|
3
|
-
import type { EmitterType } from "./
|
3
|
+
import type { EmitterType } from "./InternalEmitter";
|
4
4
|
|
5
5
|
const ResizeObserver = window.ResizeObserver || ResizeObserverPolyfill;
|
6
6
|
|
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/Cursor/index.ts
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
import { ApplianceNames } from "white-web-sdk";
|
2
2
|
import { Cursor } from "./Cursor";
|
3
3
|
import { CursorState, Events } from "../constants";
|
4
|
-
import { emitter
|
4
|
+
import { emitter } from "../InternalEmitter";
|
5
5
|
import { SideEffectManager } from "side-effect-manager";
|
6
6
|
import { throttle } from "lodash";
|
7
|
+
import { WindowManager } from "../index";
|
7
8
|
import type { CursorMovePayload } from "../index";
|
8
9
|
import type { PositionType } from "../AttributesDelegate";
|
9
10
|
import type { Point, RoomMember, View } from "white-web-sdk";
|
@@ -65,7 +66,8 @@ export class CursorManager {
|
|
65
66
|
};
|
66
67
|
|
67
68
|
private canMoveCursor(member: RoomMember | undefined) {
|
68
|
-
const isLaserPointer =
|
69
|
+
const isLaserPointer =
|
70
|
+
member?.memberState.currentApplianceName === ApplianceNames.laserPointer;
|
69
71
|
// 激光笔教具在不开启光标的情况下也要显示
|
70
72
|
return this.enableCursor || isLaserPointer;
|
71
73
|
}
|
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
|
+
};
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import Emittery from "emittery";
|
2
|
+
import type { AppInitState, CursorMovePayload } from "./index";
|
3
|
+
|
4
|
+
|
5
|
+
export type EmitterEvent = {
|
6
|
+
onCreated: undefined;
|
7
|
+
InitReplay: AppInitState;
|
8
|
+
move: { appId: string; x: number; y: number };
|
9
|
+
focus: { appId: string };
|
10
|
+
close: { appId: string };
|
11
|
+
resize: { appId: string; width: number; height: number; x?: number; y?: number };
|
12
|
+
error: Error;
|
13
|
+
seek: number;
|
14
|
+
mainViewMounted: undefined;
|
15
|
+
observerIdChange: number;
|
16
|
+
boxStateChange: string;
|
17
|
+
playgroundSizeChange: DOMRect;
|
18
|
+
onReconnected: void;
|
19
|
+
removeScenes: string;
|
20
|
+
cursorMove: CursorMovePayload;
|
21
|
+
updateManagerRect: undefined;
|
22
|
+
focusedChange: { focused: string | undefined; prev: string | undefined };
|
23
|
+
rootDirRemoved: undefined;
|
24
|
+
};
|
25
|
+
|
26
|
+
export type EmitterType = Emittery<EmitterEvent>;
|
27
|
+
export const emitter: EmitterType = new Emittery();
|
@@ -2,7 +2,7 @@ import { debounce, isFunction } from "lodash";
|
|
2
2
|
import { log } from "./Utils/log";
|
3
3
|
import { RoomPhase } from "white-web-sdk";
|
4
4
|
import type { Room } from "white-web-sdk";
|
5
|
-
import type { EmitterType } from "./
|
5
|
+
import type { EmitterType } from "./InternalEmitter";
|
6
6
|
|
7
7
|
export type ReconnectRefresherContext = {
|
8
8
|
emitter: EmitterType;
|
package/src/RedoUndo.ts
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
import { callbacks } from "./callback";
|
2
|
+
import { emitter } from "./InternalEmitter";
|
3
|
+
import type { View } from "white-web-sdk";
|
4
|
+
import type { AppProxy } from "./AppProxy";
|
5
|
+
|
6
|
+
export type RedoUndoContext = {
|
7
|
+
mainView: () => View;
|
8
|
+
focus: () => string | undefined;
|
9
|
+
getAppProxy: (id: string) => AppProxy | undefined;
|
10
|
+
};
|
11
|
+
|
12
|
+
export class RedoUndo {
|
13
|
+
constructor(private context: RedoUndoContext) {
|
14
|
+
emitter.on("focusedChange", changed => {
|
15
|
+
this.disposePrevFocusViewRedoUndoListeners(changed.prev);
|
16
|
+
setTimeout(() => {
|
17
|
+
this.addRedoUndoListeners(changed.focused);
|
18
|
+
}, 0);
|
19
|
+
});
|
20
|
+
emitter.on("rootDirRemoved", () => {
|
21
|
+
this.disposePrevFocusViewRedoUndoListeners(context.focus());
|
22
|
+
this.addRedoUndoListeners(context.focus());
|
23
|
+
});
|
24
|
+
this.addRedoUndoListeners(context.focus());
|
25
|
+
}
|
26
|
+
|
27
|
+
private addRedoUndoListeners = (focused: string | undefined) => {
|
28
|
+
if (focused === undefined) {
|
29
|
+
this.addViewCallbacks(
|
30
|
+
this.context.mainView(),
|
31
|
+
this.onCanRedoStepsUpdate,
|
32
|
+
this.onCanUndoStepsUpdate
|
33
|
+
);
|
34
|
+
} else {
|
35
|
+
const focusApp = this.context.getAppProxy(focused);
|
36
|
+
if (focusApp && focusApp.view) {
|
37
|
+
this.addViewCallbacks(
|
38
|
+
focusApp.view,
|
39
|
+
this.onCanRedoStepsUpdate,
|
40
|
+
this.onCanUndoStepsUpdate
|
41
|
+
);
|
42
|
+
}
|
43
|
+
}
|
44
|
+
};
|
45
|
+
|
46
|
+
private addViewCallbacks = (
|
47
|
+
view: View,
|
48
|
+
redoListener: (steps: number) => void,
|
49
|
+
undoListener: (steps: number) => void
|
50
|
+
) => {
|
51
|
+
redoListener(view.canRedoSteps);
|
52
|
+
undoListener(view.canUndoSteps);
|
53
|
+
view.callbacks.on("onCanRedoStepsUpdate", redoListener);
|
54
|
+
view.callbacks.on("onCanUndoStepsUpdate", undoListener);
|
55
|
+
};
|
56
|
+
|
57
|
+
private disposeViewCallbacks = (view: View) => {
|
58
|
+
view.callbacks.off("onCanRedoStepsUpdate", this.onCanRedoStepsUpdate);
|
59
|
+
view.callbacks.off("onCanUndoStepsUpdate", this.onCanUndoStepsUpdate);
|
60
|
+
};
|
61
|
+
|
62
|
+
private onCanRedoStepsUpdate = (steps: number) => {
|
63
|
+
callbacks.emit("canRedoStepsChange", steps);
|
64
|
+
};
|
65
|
+
|
66
|
+
private onCanUndoStepsUpdate = (steps: number) => {
|
67
|
+
callbacks.emit("canUndoStepsChange", steps);
|
68
|
+
};
|
69
|
+
|
70
|
+
private disposePrevFocusViewRedoUndoListeners = (prevFocused: string | undefined) => {
|
71
|
+
let view: View | undefined = undefined;
|
72
|
+
if (prevFocused === undefined) {
|
73
|
+
view = this.context.mainView();
|
74
|
+
} else {
|
75
|
+
const appProxy = this.context.getAppProxy(prevFocused);
|
76
|
+
if (appProxy && appProxy.view) {
|
77
|
+
view = appProxy.view;
|
78
|
+
}
|
79
|
+
}
|
80
|
+
if (view) {
|
81
|
+
this.disposeViewCallbacks(view);
|
82
|
+
}
|
83
|
+
};
|
84
|
+
|
85
|
+
public destroy() {
|
86
|
+
this.disposePrevFocusViewRedoUndoListeners(this.context.focus());
|
87
|
+
}
|
88
|
+
}
|
package/src/Register/index.ts
CHANGED
@@ -15,6 +15,7 @@ class AppRegister {
|
|
15
15
|
public appClasses: Map<string, () => Promise<NetlessApp>> = new Map();
|
16
16
|
|
17
17
|
public async register(params: RegisterParams): Promise<void> {
|
18
|
+
this.appClassesCache.delete(params.kind);
|
18
19
|
this.registered.set(params.kind, params);
|
19
20
|
|
20
21
|
const srcOrAppOrFunction = params.src;
|
package/src/Register/loader.ts
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import { callbacks } from "../callback";
|
1
2
|
import type { AppProxy } from "../AppProxy";
|
2
3
|
|
3
4
|
export type Invoker = () => Promise<AppProxy | undefined>;
|
@@ -6,6 +7,7 @@ export class AppCreateQueue {
|
|
6
7
|
private list: Invoker[] = [];
|
7
8
|
private currentInvoker: Invoker | undefined;
|
8
9
|
private timer: number | undefined;
|
10
|
+
public isEmit = false;
|
9
11
|
|
10
12
|
private initInterval() {
|
11
13
|
return setInterval(() => {
|
@@ -37,6 +39,7 @@ export class AppCreateQueue {
|
|
37
39
|
this.currentInvoker = undefined;
|
38
40
|
if (this.list.length === 0) {
|
39
41
|
clearInterval(this.timer);
|
42
|
+
this.emitReady();
|
40
43
|
}
|
41
44
|
})
|
42
45
|
.catch(error => {
|
@@ -46,6 +49,13 @@ export class AppCreateQueue {
|
|
46
49
|
}
|
47
50
|
}
|
48
51
|
|
52
|
+
public emitReady() {
|
53
|
+
if (!this.isEmit) {
|
54
|
+
callbacks.emit("ready");
|
55
|
+
}
|
56
|
+
this.isEmit = true;
|
57
|
+
}
|
58
|
+
|
49
59
|
public destroy() {
|
50
60
|
if (this.timer) {
|
51
61
|
clearInterval(this.timer);
|
package/src/Utils/Common.ts
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
import { appRegister } from "../Register";
|
2
2
|
import { debounce } from "lodash";
|
3
|
-
import { emitter } from "../
|
3
|
+
import { emitter } from "../InternalEmitter";
|
4
4
|
import { ScenePathType } from "white-web-sdk";
|
5
5
|
import { v4 } from "uuid";
|
6
|
-
import type { PublicEvent } from "../
|
6
|
+
import type { PublicEvent } from "../callback";
|
7
7
|
import type { Displayer, ViewVisionMode, Room, View } from "white-web-sdk";
|
8
8
|
import type Emittery from "emittery";
|
9
9
|
import { ROOT_DIR } from "../constants";
|
package/src/Utils/RoomHacker.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { emitter } from "../
|
1
|
+
import { emitter } from "../InternalEmitter";
|
2
2
|
import { isPlayer } from "white-web-sdk";
|
3
3
|
import type { WindowManager } from "../index";
|
4
4
|
import type { Camera, Room, Player, PlayerSeekingResult } from "white-web-sdk";
|
@@ -23,13 +23,13 @@ export const replaceRoomFunction = (room: Room | Player, manager: WindowManager)
|
|
23
23
|
|
24
24
|
Object.defineProperty(room, "canUndoSteps", {
|
25
25
|
get() {
|
26
|
-
return manager.
|
26
|
+
return manager.canUndoSteps;
|
27
27
|
},
|
28
28
|
});
|
29
29
|
|
30
30
|
Object.defineProperty(room, "canRedoSteps", {
|
31
31
|
get() {
|
32
|
-
return manager.
|
32
|
+
return manager.canRedoSteps;
|
33
33
|
},
|
34
34
|
});
|
35
35
|
|
package/src/View/MainView.ts
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
import { AnimationMode, reaction } from "white-web-sdk";
|
2
|
-
import { callbacks
|
2
|
+
import { callbacks } from "../callback";
|
3
3
|
import { createView } from "./ViewManager";
|
4
4
|
import { debounce, isEmpty, isEqual } from "lodash";
|
5
|
+
import { emitter } from "../InternalEmitter";
|
5
6
|
import { Fields } from "../AttributesDelegate";
|
6
7
|
import { setViewFocusScenePath } from "../Utils/Common";
|
7
8
|
import { SideEffectManager } from "side-effect-manager";
|
@@ -110,6 +111,17 @@ export class MainViewProxy {
|
|
110
111
|
}
|
111
112
|
}
|
112
113
|
|
114
|
+
public rebind(): void {
|
115
|
+
const divElement = this.mainView.divElement;
|
116
|
+
const disableCameraTransform = this.mainView.disableCameraTransform;
|
117
|
+
this.stop();
|
118
|
+
this.mainView.release();
|
119
|
+
this.mainView = this.createMainView();
|
120
|
+
this.mainView.disableCameraTransform = disableCameraTransform;
|
121
|
+
this.mainView.divElement = divElement;
|
122
|
+
this.start();
|
123
|
+
}
|
124
|
+
|
113
125
|
private onCameraUpdatedByDevice = (camera: Camera) => {
|
114
126
|
this.store.setMainViewCamera({ ...camera, id: this.manager.uid });
|
115
127
|
if (!isEqual(this.mainViewSize, { ...this.mainView.size, id: this.manager.uid })) {
|