@netless/window-manager 0.4.0-canary.2 → 0.4.0-canary.23
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/.idea/inspectionProfiles/Project_Default.xml +7 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/.idea/window-manager.iml +12 -0
- package/.vscode/settings.json +1 -0
- package/CHANGELOG.md +29 -1
- package/README.md +1 -0
- package/dist/App/MagixEvent/index.d.ts +29 -0
- package/dist/App/Storage/StorageEvent.d.ts +8 -0
- package/dist/App/Storage/index.d.ts +39 -0
- package/dist/App/Storage/typings.d.ts +22 -0
- package/dist/App/Storage/utils.d.ts +5 -0
- package/dist/AppContext.d.ts +40 -16
- package/dist/AppListener.d.ts +1 -1
- package/dist/AppManager.d.ts +15 -11
- package/dist/AppProxy.d.ts +7 -6
- package/dist/AttributesDelegate.d.ts +2 -2
- package/dist/BoxManager.d.ts +6 -3
- package/dist/BuiltinApps.d.ts +5 -0
- package/dist/ContainerResizeObserver.d.ts +10 -0
- package/dist/Cursor/Cursor.d.ts +8 -11
- package/dist/Cursor/index.d.ts +5 -16
- package/dist/Helper.d.ts +6 -0
- package/dist/ReconnectRefresher.d.ts +0 -1
- package/dist/Register/storage.d.ts +5 -1
- package/dist/Utils/Common.d.ts +7 -2
- package/dist/Utils/Reactive.d.ts +1 -1
- package/dist/Utils/RoomHacker.d.ts +1 -1
- package/dist/{MainView.d.ts → View/MainView.d.ts} +5 -6
- package/dist/View/ViewManager.d.ts +13 -0
- package/dist/constants.d.ts +3 -7
- package/dist/index.d.ts +25 -10
- package/dist/index.es.js +41 -1
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +41 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/style.css +1 -1
- package/dist/typings.d.ts +3 -2
- package/docs/api.md +36 -6
- package/docs/concept.md +9 -0
- package/package.json +7 -6
- package/src/App/MagixEvent/index.ts +68 -0
- package/src/App/Storage/StorageEvent.ts +21 -0
- package/src/App/Storage/index.ts +289 -0
- package/src/App/Storage/typings.ts +23 -0
- package/src/App/Storage/utils.ts +17 -0
- package/src/AppContext.ts +66 -24
- package/src/AppListener.ts +15 -14
- package/src/AppManager.ts +146 -63
- package/src/AppProxy.ts +52 -53
- package/src/AttributesDelegate.ts +2 -2
- package/src/BoxManager.ts +40 -24
- package/src/BuiltinApps.ts +23 -0
- package/src/ContainerResizeObserver.ts +62 -0
- package/src/Cursor/Cursor.ts +22 -36
- package/src/Cursor/index.ts +39 -139
- package/src/Helper.ts +30 -0
- package/src/ReconnectRefresher.ts +0 -5
- package/src/Register/index.ts +25 -16
- package/src/Register/loader.ts +2 -2
- package/src/Register/storage.ts +6 -1
- package/src/Utils/Common.ts +66 -13
- package/src/Utils/Reactive.ts +9 -3
- package/src/Utils/RoomHacker.ts +42 -13
- package/src/{MainView.ts → View/MainView.ts} +25 -36
- package/src/View/ViewManager.ts +52 -0
- package/src/constants.ts +3 -4
- package/src/index.ts +96 -72
- package/src/shim.d.ts +5 -0
- package/src/style.css +7 -1
- package/src/typings.ts +3 -2
- package/vite.config.js +8 -2
- package/dist/Base/Context.d.ts +0 -13
- package/dist/Base/index.d.ts +0 -7
- package/dist/Utils/CameraStore.d.ts +0 -15
- package/dist/ViewManager.d.ts +0 -29
- package/dist/sdk.d.ts +0 -14
- package/src/Base/Context.ts +0 -49
- package/src/Base/index.ts +0 -10
- package/src/Utils/CameraStore.ts +0 -72
- package/src/sdk.ts +0 -39
- package/src/viewManager.ts +0 -177
package/src/AppProxy.ts
CHANGED
@@ -2,17 +2,13 @@ import Emittery from "emittery";
|
|
2
2
|
import { AppAttributes, AppEvents, Events } from "./constants";
|
3
3
|
import { AppContext } from "./AppContext";
|
4
4
|
import { appRegister } from "./Register";
|
5
|
-
import { autorun
|
6
|
-
import {
|
5
|
+
import { autorun } from "white-web-sdk";
|
6
|
+
import { BoxManagerNotFoundError } from "./Utils/error";
|
7
|
+
import { debounce, get } from "lodash";
|
8
|
+
import { emitter } from "./index";
|
7
9
|
import { Fields } from "./AttributesDelegate";
|
8
|
-
import {
|
10
|
+
import { getScenePath, removeScenes, setScenePath, setViewFocusScenePath } from "./Utils/Common";
|
9
11
|
import { log } from "./Utils/log";
|
10
|
-
import {
|
11
|
-
notifyMainViewModeChange,
|
12
|
-
setScenePath,
|
13
|
-
setViewFocusScenePath,
|
14
|
-
setViewMode,
|
15
|
-
} from "./Utils/Common";
|
16
12
|
import type {
|
17
13
|
AppEmitterEvent,
|
18
14
|
AppInitState,
|
@@ -24,10 +20,9 @@ import type { SceneState, View, SceneDefinition } from "white-web-sdk";
|
|
24
20
|
import type { AppManager } from "./AppManager";
|
25
21
|
import type { NetlessApp } from "./typings";
|
26
22
|
import type { ReadonlyTeleBox } from "@netless/telebox-insider";
|
27
|
-
import { Base } from "./Base";
|
28
|
-
import { BoxManagerNotFoundError } from "./Utils/error";
|
29
23
|
|
30
|
-
export class AppProxy
|
24
|
+
export class AppProxy {
|
25
|
+
public kind: string;
|
31
26
|
public id: string;
|
32
27
|
public scenePath?: string;
|
33
28
|
public appEmitter: Emittery<AppEmitterEvent>;
|
@@ -37,8 +32,8 @@ export class AppProxy extends Base {
|
|
37
32
|
private boxManager = this.manager.boxManager;
|
38
33
|
private appProxies = this.manager.appProxies;
|
39
34
|
private viewManager = this.manager.viewManager;
|
40
|
-
private
|
41
|
-
|
35
|
+
private store = this.manager.store;
|
36
|
+
|
42
37
|
public isAddApp: boolean;
|
43
38
|
private status: "normal" | "destroyed" = "normal";
|
44
39
|
private stateKey: string;
|
@@ -47,11 +42,10 @@ export class AppProxy extends Base {
|
|
47
42
|
|
48
43
|
constructor(
|
49
44
|
private params: BaseInsertParams,
|
50
|
-
manager: AppManager,
|
45
|
+
private manager: AppManager,
|
51
46
|
appId: string,
|
52
47
|
isAddApp: boolean
|
53
48
|
) {
|
54
|
-
super(manager);
|
55
49
|
this.kind = params.kind;
|
56
50
|
this.id = appId;
|
57
51
|
this.stateKey = `${this.id}_state`;
|
@@ -98,18 +92,24 @@ export class AppProxy extends Base {
|
|
98
92
|
|
99
93
|
public getFullScenePath(): string | undefined {
|
100
94
|
if (this.scenePath) {
|
101
|
-
return get(this.appAttributes, [Fields.FullPath], this.
|
95
|
+
return get(this.appAttributes, [Fields.FullPath], this.getFullScenePathFromScenes());
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
private getFullScenePathFromScenes() {
|
100
|
+
const sceneIndex = get(this.appAttributes, ["state", "SceneIndex"], 0);
|
101
|
+
const fullPath = getScenePath(this.manager.room, this.scenePath, sceneIndex);
|
102
|
+
if (fullPath) {
|
103
|
+
this.setFullPath(fullPath);
|
102
104
|
}
|
105
|
+
return fullPath;
|
103
106
|
}
|
104
107
|
|
105
108
|
public setFullPath(path: string) {
|
106
109
|
this.manager.safeUpdateAttributes(["apps", this.id, Fields.FullPath], path);
|
107
110
|
}
|
108
111
|
|
109
|
-
public async baseInsertApp(
|
110
|
-
skipUpdate = false,
|
111
|
-
focus?: boolean
|
112
|
-
): Promise<{ appId: string; app: NetlessApp }> {
|
112
|
+
public async baseInsertApp(skipUpdate = false): Promise<{ appId: string; app: NetlessApp }> {
|
113
113
|
const params = this.params;
|
114
114
|
if (!params.kind) {
|
115
115
|
throw new Error("[WindowManager]: kind require");
|
@@ -117,14 +117,17 @@ export class AppProxy extends Base {
|
|
117
117
|
const appImpl = await appRegister.appClasses.get(params.kind)?.();
|
118
118
|
const appParams = appRegister.registered.get(params.kind);
|
119
119
|
if (appImpl) {
|
120
|
-
await this.setupApp(
|
120
|
+
await this.setupApp(
|
121
|
+
this.id,
|
122
|
+
skipUpdate,
|
123
|
+
appImpl,
|
124
|
+
params.options,
|
125
|
+
appParams?.appOptions
|
126
|
+
);
|
121
127
|
} else {
|
122
128
|
throw new Error(`[WindowManager]: app load failed ${params.kind} ${params.src}`);
|
123
129
|
}
|
124
|
-
this.
|
125
|
-
if (focus) {
|
126
|
-
this.focusApp();
|
127
|
-
}
|
130
|
+
this.boxManager?.updateManagerRect();
|
128
131
|
return {
|
129
132
|
appId: this.id,
|
130
133
|
app: appImpl,
|
@@ -133,7 +136,6 @@ export class AppProxy extends Base {
|
|
133
136
|
|
134
137
|
private focusApp() {
|
135
138
|
this.focusBox();
|
136
|
-
this.context.switchAppToWriter(this.id);
|
137
139
|
this.store.setMainViewFocusPath(this.manager.mainView);
|
138
140
|
}
|
139
141
|
|
@@ -184,6 +186,11 @@ export class AppProxy extends Base {
|
|
184
186
|
canOperate: this.manager.canOperate,
|
185
187
|
smartPosition: this.isAddApp,
|
186
188
|
});
|
189
|
+
if (this.isAddApp && this.box) {
|
190
|
+
this.store.updateAppState(appId, AppAttributes.ZIndex, this.box.zIndex);
|
191
|
+
this.store.setAppFocus(appId, true);
|
192
|
+
this.focusBox();
|
193
|
+
}
|
187
194
|
} catch (error: any) {
|
188
195
|
console.error(error);
|
189
196
|
throw new Error(`[WindowManager]: app setup error: ${error.message}`);
|
@@ -205,9 +212,6 @@ export class AppProxy extends Base {
|
|
205
212
|
|
206
213
|
private afterSetupApp(boxInitState: AppInitState | undefined): void {
|
207
214
|
if (boxInitState) {
|
208
|
-
if (boxInitState.focus && this.scenePath) {
|
209
|
-
this.context.switchAppToWriter(this.id);
|
210
|
-
}
|
211
215
|
if (!boxInitState?.x || !boxInitState.y) {
|
212
216
|
this.boxManager?.setBoxInitState(this.id);
|
213
217
|
}
|
@@ -226,29 +230,10 @@ export class AppProxy extends Base {
|
|
226
230
|
await this.destroy(true, false, true);
|
227
231
|
const params = this.params;
|
228
232
|
const appProxy = new AppProxy(params, this.manager, this.id, this.isAddApp);
|
229
|
-
await appProxy.baseInsertApp(true
|
233
|
+
await appProxy.baseInsertApp(true);
|
230
234
|
this.boxManager?.updateBoxState(currentAppState);
|
231
235
|
}
|
232
236
|
|
233
|
-
public switchToWritable() {
|
234
|
-
appRegister.notifyApp(this.kind, "focus", { appId: this.id });
|
235
|
-
this.cameraStore.switchView(this.id, this.view, () => {
|
236
|
-
if (this.view) {
|
237
|
-
if (this.view.mode === ViewVisionMode.Writable) return;
|
238
|
-
try {
|
239
|
-
if (this.manager.mainView.mode === ViewVisionMode.Writable) {
|
240
|
-
this.store.setMainViewFocusPath(this.manager.mainView);
|
241
|
-
notifyMainViewModeChange(callbacks, ViewVisionMode.Freedom);
|
242
|
-
setViewMode(this.manager.mainView, ViewVisionMode.Freedom);
|
243
|
-
}
|
244
|
-
setViewMode(this.view, ViewVisionMode.Writable);
|
245
|
-
} catch (error) {
|
246
|
-
log("switch view failed", error);
|
247
|
-
}
|
248
|
-
}
|
249
|
-
});
|
250
|
-
}
|
251
|
-
|
252
237
|
public getAppInitState = (id: string) => {
|
253
238
|
const attrs = this.store.getAppState(id);
|
254
239
|
if (!attrs) return;
|
@@ -337,7 +322,7 @@ export class AppProxy extends Base {
|
|
337
322
|
}
|
338
323
|
});
|
339
324
|
});
|
340
|
-
this.manager.refresher?.add(this.stateKey,() => {
|
325
|
+
this.manager.refresher?.add(this.stateKey, () => {
|
341
326
|
return autorun(() => {
|
342
327
|
const appState = this.appAttributes?.state;
|
343
328
|
if (appState?.zIndex > 0 && appState.zIndex !== this.box?.zIndex) {
|
@@ -345,8 +330,20 @@ export class AppProxy extends Base {
|
|
345
330
|
}
|
346
331
|
});
|
347
332
|
});
|
333
|
+
this.manager.refresher?.add(`${appId}-fullPath`, () => {
|
334
|
+
return autorun(() => {
|
335
|
+
const fullPath = this.appAttributes?.fullPath;
|
336
|
+
this.setFocusScenePathHandler(fullPath);
|
337
|
+
});
|
338
|
+
});
|
348
339
|
};
|
349
340
|
|
341
|
+
private setFocusScenePathHandler = debounce((fullPath: string | undefined) => {
|
342
|
+
if (this.view && fullPath && fullPath !== this.view?.focusScenePath) {
|
343
|
+
setViewFocusScenePath(this.view, fullPath);
|
344
|
+
}
|
345
|
+
}, 50);
|
346
|
+
|
350
347
|
public setScenePath(): void {
|
351
348
|
if (!this.manager.canOperate) return;
|
352
349
|
const fullScenePath = this.getFullScenePath();
|
@@ -364,7 +361,6 @@ export class AppProxy extends Base {
|
|
364
361
|
|
365
362
|
private async createView(): Promise<View> {
|
366
363
|
const view = await this.viewManager.createView(this.id);
|
367
|
-
this.cameraStore.register(this.id, view);
|
368
364
|
this.setViewFocusScenePath();
|
369
365
|
return view;
|
370
366
|
}
|
@@ -386,14 +382,17 @@ export class AppProxy extends Base {
|
|
386
382
|
}
|
387
383
|
if (cleanAttrs) {
|
388
384
|
this.store.cleanAppAttributes(this.id);
|
385
|
+
if (this.scenePath) {
|
386
|
+
removeScenes(this.manager.room, this.scenePath);
|
387
|
+
}
|
389
388
|
}
|
390
389
|
this.appProxies.delete(this.id);
|
391
|
-
this.cameraStore.unregister(this.id, this.view);
|
392
390
|
|
393
391
|
this.viewManager.destroyView(this.id);
|
394
392
|
this.manager.appStatus.delete(this.id);
|
395
393
|
this.manager.refresher?.remove(this.id);
|
396
394
|
this.manager.refresher?.remove(this.stateKey);
|
395
|
+
this.manager.refresher?.remove(`${this.id}-fullPath`);
|
397
396
|
}
|
398
397
|
|
399
398
|
public close(): Promise<void> {
|
@@ -123,7 +123,7 @@ export class AttributesDelegate {
|
|
123
123
|
return this.getAppAttributes(id)?.options?.scenePath;
|
124
124
|
}
|
125
125
|
|
126
|
-
public getMainViewScenePath() {
|
126
|
+
public getMainViewScenePath(): string | undefined {
|
127
127
|
return this.attributes["_mainScenePath"];
|
128
128
|
}
|
129
129
|
|
@@ -159,7 +159,7 @@ export class AttributesDelegate {
|
|
159
159
|
this.context.safeSetAttributes({ [Fields.MainViewSize]: { ...size } });
|
160
160
|
}
|
161
161
|
|
162
|
-
public setAppFocus(appId: string, focus: boolean) {
|
162
|
+
public setAppFocus = (appId: string, focus: boolean) => {
|
163
163
|
if (focus) {
|
164
164
|
this.context.safeSetAttributes({ [Fields.Focus]: appId });
|
165
165
|
} else {
|
package/src/BoxManager.ts
CHANGED
@@ -1,12 +1,11 @@
|
|
1
|
-
import { AppAttributes,
|
2
|
-
import { debounce
|
1
|
+
import { AppAttributes, Events, MIN_HEIGHT, MIN_WIDTH } from "./constants";
|
2
|
+
import { debounce } from "lodash";
|
3
|
+
import { emitter, WindowManager } from "./index";
|
3
4
|
import {
|
4
|
-
TELE_BOX_MANAGER_EVENT,
|
5
5
|
TELE_BOX_STATE,
|
6
6
|
TeleBoxCollector,
|
7
7
|
TeleBoxManager,
|
8
8
|
} from "@netless/telebox-insider";
|
9
|
-
import { WindowManager } from "./index";
|
10
9
|
import type { AddAppOptions, AppInitState, EmitterType, CallbacksType } from "./index";
|
11
10
|
import type {
|
12
11
|
TeleBoxManagerUpdateConfig,
|
@@ -15,6 +14,7 @@ import type {
|
|
15
14
|
TeleBoxManagerConfig,
|
16
15
|
TeleBoxColorScheme,
|
17
16
|
TeleBoxRect,
|
17
|
+
TeleBoxConfig,
|
18
18
|
} from "@netless/telebox-insider";
|
19
19
|
import type Emittery from "emittery";
|
20
20
|
import type { NetlessApp } from "./typings";
|
@@ -57,6 +57,7 @@ export type BoxManagerContext = {
|
|
57
57
|
canOperate: () => boolean;
|
58
58
|
notifyContainerRectUpdate: (rect: TeleBoxRect) => void;
|
59
59
|
cleanFocus: () => void;
|
60
|
+
setAppFocus: (appId: string) => void;
|
60
61
|
};
|
61
62
|
|
62
63
|
export const createBoxManager = (
|
@@ -74,6 +75,7 @@ export const createBoxManager = (
|
|
74
75
|
notifyContainerRectUpdate: (rect: TeleBoxRect) =>
|
75
76
|
manager.appManager?.notifyContainerRectUpdate(rect),
|
76
77
|
cleanFocus: () => manager.appManager?.store.cleanFocus(),
|
78
|
+
setAppFocus: (appId: string) => manager.appManager?.store.setAppFocus(appId, true),
|
77
79
|
callbacks,
|
78
80
|
emitter,
|
79
81
|
},
|
@@ -90,17 +92,32 @@ export class BoxManager {
|
|
90
92
|
) {
|
91
93
|
const { emitter, callbacks } = context;
|
92
94
|
this.teleBoxManager = this.setupBoxManager(createTeleBoxManagerConfig);
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
95
|
+
|
96
|
+
// 使用 _xxx$.reaction 订阅修改的值, 不管有没有 skipUpdate, 修改值都会触发回调
|
97
|
+
this.teleBoxManager._state$.reaction(state => {
|
98
|
+
callbacks.emit("boxStateChange", state);
|
99
|
+
emitter.emit("boxStateChange", state);
|
100
|
+
});
|
101
|
+
|
102
|
+
this.teleBoxManager._darkMode$.reaction(darkMode => {
|
103
|
+
callbacks.emit("darkModeChange", darkMode);
|
98
104
|
});
|
105
|
+
this.teleBoxManager._prefersColorScheme$.reaction(colorScheme => {
|
106
|
+
callbacks.emit("prefersColorSchemeChange", colorScheme);
|
107
|
+
});
|
108
|
+
|
109
|
+
// events.on 的值则会根据 skipUpdate 来决定是否触发回调
|
99
110
|
this.teleBoxManager.events.on("minimized", minimized => {
|
100
111
|
this.context.safeSetAttributes({ minimized });
|
101
112
|
if (minimized) {
|
102
113
|
this.context.cleanFocus();
|
103
114
|
this.blurAllBox();
|
115
|
+
} else {
|
116
|
+
const topBox = this.getTopBox();
|
117
|
+
if (topBox) {
|
118
|
+
this.context.setAppFocus(topBox.id);
|
119
|
+
this.focusBox({ appId: topBox.id }, false);
|
120
|
+
}
|
104
121
|
}
|
105
122
|
});
|
106
123
|
this.teleBoxManager.events.on("maximized", maximized => {
|
@@ -136,17 +153,16 @@ export class BoxManager {
|
|
136
153
|
}
|
137
154
|
}
|
138
155
|
});
|
139
|
-
this.teleBoxManager.events.on("dark_mode", darkMode => {
|
140
|
-
callbacks.emit("darkModeChange", darkMode);
|
141
|
-
});
|
142
|
-
this.teleBoxManager.events.on("prefers_color_scheme", colorScheme => {
|
143
|
-
callbacks.emit("prefersColorSchemeChange", colorScheme);
|
144
|
-
});
|
145
156
|
this.teleBoxManager.events.on("z_index", box => {
|
146
157
|
this.context.updateAppState(box.id, AppAttributes.ZIndex, box.zIndex);
|
147
158
|
});
|
159
|
+
emitter.on("playgroundSizeChange", this.playgroundSizeChangeListener);
|
148
160
|
}
|
149
161
|
|
162
|
+
private playgroundSizeChangeListener = () => {
|
163
|
+
this.updateManagerRect();
|
164
|
+
};
|
165
|
+
|
150
166
|
private get mainView() {
|
151
167
|
return this.context.getMainView();
|
152
168
|
}
|
@@ -251,12 +267,8 @@ export class BoxManager {
|
|
251
267
|
}
|
252
268
|
|
253
269
|
public setCollectorContainer(container: HTMLElement) {
|
254
|
-
const styles = {
|
255
|
-
...DEFAULT_COLLECTOR_STYLE,
|
256
|
-
...this.createTeleBoxManagerConfig?.collectorStyles,
|
257
|
-
};
|
258
270
|
const collector = new TeleBoxCollector({
|
259
|
-
styles
|
271
|
+
styles: this.createTeleBoxManagerConfig?.collectorStyles,
|
260
272
|
}).mount(container);
|
261
273
|
this.teleBoxManager.setCollector(collector);
|
262
274
|
}
|
@@ -280,8 +292,7 @@ export class BoxManager {
|
|
280
292
|
}
|
281
293
|
|
282
294
|
public getTopBox(): ReadonlyTeleBox | undefined {
|
283
|
-
|
284
|
-
return maxBy(boxes, "zIndex");
|
295
|
+
return this.teleBoxManager.topBox;
|
285
296
|
}
|
286
297
|
|
287
298
|
public updateBoxState(state?: AppInitState): void {
|
@@ -358,9 +369,9 @@ export class BoxManager {
|
|
358
369
|
this.teleBoxManager.updateAll(config);
|
359
370
|
}
|
360
371
|
|
361
|
-
public setMaximized(maximized: boolean) {
|
372
|
+
public setMaximized(maximized: boolean, skipUpdate = true): void {
|
362
373
|
if (maximized !== this.maximized) {
|
363
|
-
this.teleBoxManager.setMaximized(maximized,
|
374
|
+
this.teleBoxManager.setMaximized(maximized, skipUpdate);
|
364
375
|
}
|
365
376
|
}
|
366
377
|
|
@@ -378,6 +389,10 @@ export class BoxManager {
|
|
378
389
|
}
|
379
390
|
}
|
380
391
|
|
392
|
+
public updateBox(id: string, payload: TeleBoxConfig, skipUpdate = true): void {
|
393
|
+
this.teleBoxManager.update(id, payload, skipUpdate);
|
394
|
+
}
|
395
|
+
|
381
396
|
public setReadonly(readonly: boolean) {
|
382
397
|
this.teleBoxManager.setReadonly(readonly);
|
383
398
|
}
|
@@ -391,6 +406,7 @@ export class BoxManager {
|
|
391
406
|
}
|
392
407
|
|
393
408
|
public destroy() {
|
409
|
+
emitter.off("playgroundSizeChange", this.playgroundSizeChangeListener);
|
394
410
|
this.teleBoxManager.destroy();
|
395
411
|
}
|
396
412
|
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import AppDocsViewer from "@netless/app-docs-viewer";
|
2
|
+
import AppMediaPlayer, { setOptions } from "@netless/app-media-player";
|
3
|
+
import { WindowManager } from "./index";
|
4
|
+
|
5
|
+
export const setupBuiltin = () => {
|
6
|
+
if (WindowManager.debug) {
|
7
|
+
setOptions({ verbose: true });
|
8
|
+
}
|
9
|
+
|
10
|
+
WindowManager.register({
|
11
|
+
kind: AppDocsViewer.kind,
|
12
|
+
src: AppDocsViewer,
|
13
|
+
});
|
14
|
+
WindowManager.register({
|
15
|
+
kind: AppMediaPlayer.kind,
|
16
|
+
src: AppMediaPlayer,
|
17
|
+
});
|
18
|
+
};
|
19
|
+
|
20
|
+
export const BuiltinApps = {
|
21
|
+
DocsViewer: AppDocsViewer.kind as string,
|
22
|
+
MediaPlayer: AppMediaPlayer.kind as string,
|
23
|
+
};
|
@@ -0,0 +1,62 @@
|
|
1
|
+
import { ResizeObserver as ResizeObserverPolyfill } from "@juggle/resize-observer";
|
2
|
+
import { WindowManager } from "./index";
|
3
|
+
import type { EmitterType} from "./index";
|
4
|
+
|
5
|
+
const ResizeObserver = window.ResizeObserver || ResizeObserverPolyfill;
|
6
|
+
|
7
|
+
export class ContainerResizeObserver {
|
8
|
+
private containerResizeObserver?: ResizeObserver;
|
9
|
+
|
10
|
+
constructor(private emitter: EmitterType) {}
|
11
|
+
|
12
|
+
public static create(
|
13
|
+
container: HTMLElement,
|
14
|
+
sizer: HTMLElement,
|
15
|
+
wrapper: HTMLDivElement,
|
16
|
+
emitter: EmitterType,
|
17
|
+
) {
|
18
|
+
const containerResizeObserver = new ContainerResizeObserver(emitter);
|
19
|
+
containerResizeObserver.observePlaygroundSize(container, sizer, wrapper);
|
20
|
+
return containerResizeObserver;
|
21
|
+
}
|
22
|
+
|
23
|
+
public observePlaygroundSize(
|
24
|
+
container: HTMLElement,
|
25
|
+
sizer: HTMLElement,
|
26
|
+
wrapper: HTMLDivElement
|
27
|
+
) {
|
28
|
+
this.updateSizer(container.getBoundingClientRect(), sizer, wrapper);
|
29
|
+
|
30
|
+
this.containerResizeObserver = new ResizeObserver(entries => {
|
31
|
+
const containerRect = entries[0]?.contentRect;
|
32
|
+
if (containerRect) {
|
33
|
+
this.updateSizer(containerRect, sizer, wrapper);
|
34
|
+
this.emitter.emit("playgroundSizeChange", containerRect)
|
35
|
+
}
|
36
|
+
});
|
37
|
+
|
38
|
+
this.containerResizeObserver.observe(container);
|
39
|
+
}
|
40
|
+
|
41
|
+
private updateSizer(
|
42
|
+
{ width, height }: DOMRectReadOnly,
|
43
|
+
sizer: HTMLElement,
|
44
|
+
wrapper: HTMLDivElement
|
45
|
+
) {
|
46
|
+
if (width && height) {
|
47
|
+
if (height / width > WindowManager.containerSizeRatio) {
|
48
|
+
height = width * WindowManager.containerSizeRatio;
|
49
|
+
sizer.classList.toggle("netless-window-manager-sizer-horizontal", true);
|
50
|
+
} else {
|
51
|
+
width = height / WindowManager.containerSizeRatio;
|
52
|
+
sizer.classList.toggle("netless-window-manager-sizer-horizontal", false);
|
53
|
+
}
|
54
|
+
wrapper.style.width = `${width}px`;
|
55
|
+
wrapper.style.height = `${height}px`;
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
public disconnect() {
|
60
|
+
this.containerResizeObserver?.disconnect();
|
61
|
+
}
|
62
|
+
}
|
package/src/Cursor/Cursor.ts
CHANGED
@@ -1,42 +1,34 @@
|
|
1
|
-
import App from
|
2
|
-
import { ApplianceMap } from
|
3
|
-
import { ApplianceNames } from
|
4
|
-
import {
|
5
|
-
import {
|
6
|
-
import { get, omit } from 'lodash';
|
7
|
-
import type { Position } from '../AttributesDelegate';
|
1
|
+
import App from "./Cursor.svelte";
|
2
|
+
import { ApplianceMap } from "./icons";
|
3
|
+
import { ApplianceNames } from "white-web-sdk";
|
4
|
+
import { omit } from "lodash";
|
5
|
+
import type { Position } from "../AttributesDelegate";
|
8
6
|
import type { RoomMember } from "white-web-sdk";
|
9
7
|
import type { CursorManager } from "./index";
|
10
8
|
import type { SvelteComponent } from "svelte";
|
11
|
-
import {
|
12
|
-
import type { AppManager } from '../AppManager';
|
9
|
+
import type { AppManager } from "../AppManager";
|
13
10
|
|
14
11
|
export type Payload = {
|
15
|
-
[key: string]: any
|
16
|
-
}
|
17
|
-
|
12
|
+
[key: string]: any;
|
13
|
+
};
|
18
14
|
|
19
|
-
export class Cursor
|
15
|
+
export class Cursor {
|
20
16
|
private member?: RoomMember;
|
21
17
|
private timer?: number;
|
22
18
|
private component?: SvelteComponent;
|
23
19
|
|
24
20
|
constructor(
|
25
|
-
manager: AppManager,
|
26
|
-
addCursorChangeListener: (uid: string, callback: (position: Position, state: CursorState) => void) => void,
|
27
|
-
private cursors: any,
|
21
|
+
private manager: AppManager,
|
28
22
|
private memberId: string,
|
29
23
|
private cursorManager: CursorManager,
|
30
|
-
private wrapper?: HTMLElement
|
24
|
+
private wrapper?: HTMLElement
|
31
25
|
) {
|
32
|
-
super(manager);
|
33
26
|
this.setMember();
|
34
27
|
this.createCursor();
|
35
|
-
addCursorChangeListener(this.memberId, this.onCursorChange);
|
36
28
|
this.autoHidden();
|
37
29
|
}
|
38
30
|
|
39
|
-
|
31
|
+
public move = (position: Position) => {
|
40
32
|
if (position.type === "main") {
|
41
33
|
const rect = this.cursorManager.wrapperRect;
|
42
34
|
if (this.component && rect) {
|
@@ -45,7 +37,6 @@ export class Cursor extends Base {
|
|
45
37
|
}
|
46
38
|
} else {
|
47
39
|
const focusView = this.cursorManager.focusView;
|
48
|
-
// TODO 可以存一个当前 focusView 的 Rect 这样只有 focus 切换的时候才调用 getBoundingClientRect
|
49
40
|
const viewRect = focusView?.divElement?.getBoundingClientRect();
|
50
41
|
const viewCamera = focusView?.camera;
|
51
42
|
if (focusView && viewRect && viewCamera && this.component) {
|
@@ -53,10 +44,11 @@ export class Cursor extends Base {
|
|
53
44
|
this.moveCursor(position, viewRect, focusView);
|
54
45
|
}
|
55
46
|
}
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
47
|
+
};
|
48
|
+
|
49
|
+
public leave = () => {
|
50
|
+
this.hide();
|
51
|
+
};
|
60
52
|
|
61
53
|
private moveCursor(cursor: Position, rect: DOMRect, view: any) {
|
62
54
|
const { x, y, type } = cursor;
|
@@ -124,21 +116,12 @@ export class Cursor extends Base {
|
|
124
116
|
}
|
125
117
|
}
|
126
118
|
|
127
|
-
public get cursorState(): CursorState | undefined {
|
128
|
-
return get(this.cursors, [this.memberId, Fields.CursorState]);
|
129
|
-
}
|
130
|
-
|
131
|
-
public get cursorPosition(): Position | undefined {
|
132
|
-
return get(this.cursors, [this.memberId, Fields.Position]);
|
133
|
-
}
|
134
|
-
|
135
119
|
private autoHidden() {
|
136
120
|
if (this.timer) {
|
137
121
|
clearTimeout(this.timer);
|
138
122
|
}
|
139
123
|
this.timer = window.setTimeout(() => {
|
140
124
|
this.hide();
|
141
|
-
this.store.updateCursorState(this.memberId, CursorState.Leave);
|
142
125
|
}, 1000 * 10); // 10 秒钟自动隐藏
|
143
126
|
}
|
144
127
|
|
@@ -176,7 +159,7 @@ export class Cursor extends Base {
|
|
176
159
|
}
|
177
160
|
|
178
161
|
public setMember() {
|
179
|
-
this.member = this.
|
162
|
+
this.member = this.manager.findMemberByUid(this.memberId);
|
180
163
|
this.updateComponent();
|
181
164
|
}
|
182
165
|
|
@@ -188,13 +171,16 @@ export class Cursor extends Base {
|
|
188
171
|
if (this.component) {
|
189
172
|
this.component.$destroy();
|
190
173
|
}
|
191
|
-
this.manager.refresher?.remove(this.memberId);
|
192
174
|
this.cursorManager.cursorInstances.delete(this.memberId);
|
175
|
+
if (this.timer) {
|
176
|
+
clearTimeout(this.timer);
|
177
|
+
}
|
193
178
|
}
|
194
179
|
|
195
180
|
public hide() {
|
196
181
|
if (this.component) {
|
197
182
|
this.component.$set({ visible: false });
|
183
|
+
this.destroy();
|
198
184
|
}
|
199
185
|
}
|
200
186
|
}
|