@netless/window-manager 1.0.0-canary.8 → 1.0.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/LICENSE.txt +21 -0
- package/README.md +90 -64
- package/README.zh-cn.md +224 -0
- package/dist/index.d.ts +1133 -39
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -0
- package/dist/{index.es.js → index.mjs} +8393 -5913
- package/dist/index.mjs.map +1 -0
- package/dist/style.css +1 -1
- package/docs/advanced.md +55 -55
- package/docs/api.md +124 -113
- package/docs/app-context.md +248 -209
- package/docs/basic.md +25 -26
- package/docs/camera.md +19 -20
- package/docs/cn/advanced.md +137 -0
- package/docs/cn/api.md +309 -0
- package/docs/cn/app-context.md +369 -0
- package/docs/cn/basic.md +64 -0
- package/docs/cn/camera.md +53 -0
- package/docs/cn/concept.md +9 -0
- package/docs/cn/custom-max-bar.md +31 -0
- package/docs/cn/develop-app.md +94 -0
- package/docs/cn/export-pdf.md +48 -0
- package/docs/cn/migrate.md +60 -0
- package/docs/cn/replay.md +40 -0
- package/docs/concept.md +6 -5
- package/docs/custom-max-bar.md +31 -0
- package/docs/develop-app.md +22 -19
- package/docs/export-pdf.md +48 -0
- package/docs/migrate.md +25 -27
- package/docs/quickstart.md +50 -0
- package/docs/replay.md +20 -20
- package/package.json +32 -22
- package/src/App/AppContext.ts +104 -71
- package/src/App/AppPageStateImpl.ts +6 -25
- package/src/App/AppProxy.ts +42 -147
- package/src/App/MagixEvent/index.ts +38 -38
- package/src/App/Storage/StorageEvent.ts +13 -13
- package/src/App/Storage/index.ts +269 -245
- package/src/App/Storage/typings.ts +4 -2
- package/src/App/Storage/utils.ts +3 -3
- package/src/App/index.ts +0 -1
- package/src/AppListener.ts +8 -8
- package/src/AppManager.ts +84 -75
- package/src/AttributesDelegate.ts +42 -22
- package/src/BoxEmitter.ts +12 -6
- package/src/BoxManager.ts +122 -106
- package/src/ContainerResizeObserver.ts +75 -0
- package/src/Cursor/Cursor.svelte +16 -5
- package/src/Cursor/Cursor.svelte.d.ts +21 -0
- package/src/Cursor/Cursor.ts +77 -13
- package/src/Cursor/icons.ts +6 -0
- package/src/Cursor/icons2.ts +66 -0
- package/src/Cursor/index.ts +127 -26
- package/src/Helper.ts +94 -14
- package/src/InternalEmitter.ts +2 -7
- package/src/Page/PageController.ts +1 -0
- package/src/Page/index.ts +1 -1
- package/src/PageState.ts +6 -5
- package/src/ReconnectRefresher.ts +9 -4
- package/src/RedoUndo.ts +3 -3
- package/src/Register/index.ts +22 -17
- package/src/Register/loader.ts +26 -22
- package/src/Register/storage.ts +13 -13
- package/src/Utils/Common.ts +18 -14
- package/src/Utils/Reactive.ts +26 -25
- package/src/Utils/RoomHacker.ts +4 -4
- package/src/Utils/error.ts +0 -1
- package/src/View/IframeBridge.ts +680 -0
- package/src/View/MainView.ts +114 -53
- package/src/callback.ts +21 -1
- package/src/constants.ts +0 -2
- package/src/image/pencil-eraser-1.svg +3 -0
- package/src/image/pencil-eraser-2.svg +3 -0
- package/src/image/pencil-eraser-3.svg +3 -0
- package/src/index.ts +224 -74
- package/src/style.css +27 -10
- package/src/typings.ts +20 -10
- package/.prettierignore +0 -7
- package/.prettierrc.json +0 -9
- package/CHANGELOG.md +0 -196
- package/__mocks__/white-web-sdk.ts +0 -50
- package/dist/App/AppContext.d.ts +0 -76
- package/dist/App/AppPageStateImpl.d.ts +0 -21
- package/dist/App/AppProxy.d.ts +0 -81
- package/dist/App/AppViewSync.d.ts +0 -11
- package/dist/App/MagixEvent/index.d.ts +0 -29
- package/dist/App/Storage/StorageEvent.d.ts +0 -8
- package/dist/App/Storage/index.d.ts +0 -39
- package/dist/App/Storage/typings.d.ts +0 -22
- package/dist/App/Storage/utils.d.ts +0 -5
- package/dist/App/WhiteboardView.d.ts +0 -22
- package/dist/App/index.d.ts +0 -3
- package/dist/AppListener.d.ts +0 -21
- package/dist/AppManager.d.ts +0 -107
- package/dist/AttributesDelegate.d.ts +0 -80
- package/dist/BoxEmitter.d.ts +0 -34
- package/dist/BoxManager.d.ts +0 -100
- package/dist/BuiltinApps.d.ts +0 -5
- package/dist/Cursor/Cursor.d.ts +0 -39
- package/dist/Cursor/icons.d.ts +0 -3
- package/dist/Cursor/index.d.ts +0 -46
- package/dist/Helper.d.ts +0 -17
- package/dist/InternalEmitter.d.ts +0 -39
- package/dist/Page/PageController.d.ts +0 -20
- package/dist/Page/index.d.ts +0 -3
- package/dist/PageState.d.ts +0 -9
- package/dist/ReconnectRefresher.d.ts +0 -24
- package/dist/RedoUndo.d.ts +0 -18
- package/dist/Register/index.d.ts +0 -28
- package/dist/Register/loader.d.ts +0 -4
- package/dist/Register/storage.d.ts +0 -8
- package/dist/Utils/AppCreateQueue.d.ts +0 -15
- package/dist/Utils/Common.d.ts +0 -23
- package/dist/Utils/Reactive.d.ts +0 -6
- package/dist/Utils/RoomHacker.d.ts +0 -3
- package/dist/Utils/error.d.ts +0 -27
- package/dist/Utils/log.d.ts +0 -1
- package/dist/View/CameraSynchronizer.d.ts +0 -17
- package/dist/View/MainView.d.ts +0 -48
- package/dist/View/ViewManager.d.ts +0 -13
- package/dist/View/ViewSync.d.ts +0 -7
- package/dist/callback.d.ts +0 -24
- package/dist/constants.d.ts +0 -49
- package/dist/index.cjs.js +0 -46
- package/dist/index.umd.js +0 -46
- package/dist/typings.d.ts +0 -82
- package/jest.config.js +0 -27
- package/pnpm-lock.yaml +0 -6302
- package/src/App/AppViewSync.ts +0 -68
- package/src/App/WhiteboardView.ts +0 -83
- package/src/View/CameraSynchronizer.ts +0 -73
- package/src/View/ViewSync.ts +0 -10
- package/vite.config.js +0 -51
- /package/docs/{qickstart.md → cn/quickstart.md} +0 -0
package/src/BoxManager.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import { AppAttributes, Events, MIN_HEIGHT, MIN_WIDTH } from "./constants";
|
2
2
|
import { debounce } from "lodash";
|
3
|
-
import { TELE_BOX_STATE, TeleBoxManager } from "@netless/telebox-insider";
|
3
|
+
import { TELE_BOX_STATE, TeleBoxCollector, TeleBoxManager } from "@netless/telebox-insider";
|
4
4
|
import { WindowManager } from "./index";
|
5
5
|
import type { BoxEmitterType } from "./BoxEmitter";
|
6
6
|
import type { AddAppOptions, AppInitState } from "./index";
|
@@ -18,7 +18,6 @@ import type { NetlessApp } from "./typings";
|
|
18
18
|
import type { View } from "white-web-sdk";
|
19
19
|
import type { CallbacksType } from "./callback";
|
20
20
|
import type { EmitterType } from "./InternalEmitter";
|
21
|
-
import { SideEffectManager } from "side-effect-manager";
|
22
21
|
|
23
22
|
export { TELE_BOX_STATE };
|
24
23
|
|
@@ -46,7 +45,6 @@ export type CreateTeleBoxManagerConfig = {
|
|
46
45
|
collectorContainer?: HTMLElement;
|
47
46
|
collectorStyles?: Partial<CSSStyleDeclaration>;
|
48
47
|
prefersColorScheme?: TeleBoxColorScheme;
|
49
|
-
stageRatio?: number;
|
50
48
|
};
|
51
49
|
|
52
50
|
export type BoxManagerContext = {
|
@@ -81,7 +79,7 @@ export const createBoxManager = (
|
|
81
79
|
setAppFocus: (appId: string) => manager.appManager?.store.setAppFocus(appId, true),
|
82
80
|
callbacks,
|
83
81
|
emitter,
|
84
|
-
boxEmitter
|
82
|
+
boxEmitter,
|
85
83
|
},
|
86
84
|
options
|
87
85
|
);
|
@@ -89,93 +87,91 @@ export const createBoxManager = (
|
|
89
87
|
|
90
88
|
export class BoxManager {
|
91
89
|
public teleBoxManager: TeleBoxManager;
|
92
|
-
protected sideEffectManager: SideEffectManager;
|
93
90
|
|
94
91
|
constructor(
|
95
92
|
private context: BoxManagerContext,
|
96
|
-
createTeleBoxManagerConfig?: CreateTeleBoxManagerConfig
|
93
|
+
private createTeleBoxManagerConfig?: CreateTeleBoxManagerConfig
|
97
94
|
) {
|
98
|
-
this.sideEffectManager = new SideEffectManager();
|
99
95
|
const { emitter, callbacks, boxEmitter } = context;
|
100
96
|
this.teleBoxManager = this.setupBoxManager(createTeleBoxManagerConfig);
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
this.
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
this.
|
130
|
-
|
131
|
-
|
97
|
+
|
98
|
+
// 使用 _xxx$.reaction 订阅修改的值, 不管有没有 skipUpdate, 修改值都会触发回调
|
99
|
+
this.teleBoxManager._state$.reaction(state => {
|
100
|
+
callbacks.emit("boxStateChange", state);
|
101
|
+
emitter.emit("boxStateChange", state);
|
102
|
+
});
|
103
|
+
|
104
|
+
this.teleBoxManager._darkMode$.reaction(darkMode => {
|
105
|
+
callbacks.emit("darkModeChange", darkMode);
|
106
|
+
});
|
107
|
+
this.teleBoxManager._prefersColorScheme$.reaction(colorScheme => {
|
108
|
+
callbacks.emit("prefersColorSchemeChange", colorScheme);
|
109
|
+
});
|
110
|
+
|
111
|
+
// ppt 在最小化后刷新恢复正常大小,拿不到正确的宽高,需要手动触发一下窗口的 resize
|
112
|
+
this.teleBoxManager._minimized$.reaction(minimized => {
|
113
|
+
if (!minimized) {
|
114
|
+
setTimeout(() => {
|
115
|
+
const offset = 0.001 * (Math.random() > 0.5 ? 1 : -1);
|
116
|
+
this.teleBoxManager.boxes.forEach(box => {
|
117
|
+
box.resize(box.intrinsicWidth + offset, box.intrinsicHeight + offset, true);
|
118
|
+
});
|
119
|
+
}, 400);
|
120
|
+
}
|
121
|
+
});
|
122
|
+
|
123
|
+
// events.on 的值则会根据 skipUpdate 来决定是否触发回调
|
124
|
+
this.teleBoxManager.events.on("minimized", minimized => {
|
125
|
+
this.context.safeSetAttributes({ minimized });
|
126
|
+
if (minimized) {
|
127
|
+
this.context.cleanFocus();
|
128
|
+
this.blurAllBox();
|
129
|
+
} else {
|
130
|
+
const topBox = this.getTopBox();
|
131
|
+
if (topBox) {
|
132
|
+
this.context.setAppFocus(topBox.id);
|
133
|
+
this.focusBox({ appId: topBox.id }, false);
|
132
134
|
}
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
135
|
+
}
|
136
|
+
});
|
137
|
+
this.teleBoxManager.events.on("maximized", maximized => {
|
138
|
+
this.context.safeSetAttributes({ maximized });
|
139
|
+
});
|
140
|
+
this.teleBoxManager.events.on("removed", boxes => {
|
141
|
+
boxes.forEach(box => {
|
142
|
+
boxEmitter.emit("close", { appId: box.id });
|
143
|
+
});
|
144
|
+
});
|
145
|
+
this.teleBoxManager.events.on(
|
146
|
+
"intrinsic_move",
|
147
|
+
debounce((box: ReadonlyTeleBox): void => {
|
148
|
+
boxEmitter.emit("move", { appId: box.id, x: box.intrinsicX, y: box.intrinsicY });
|
149
|
+
}, 50)
|
150
|
+
);
|
151
|
+
this.teleBoxManager.events.on(
|
152
|
+
"intrinsic_resize",
|
153
|
+
debounce((box: ReadonlyTeleBox): void => {
|
154
|
+
boxEmitter.emit("resize", {
|
155
|
+
appId: box.id,
|
156
|
+
width: box.intrinsicWidth,
|
157
|
+
height: box.intrinsicHeight,
|
138
158
|
});
|
139
|
-
})
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
"intrinsic_resize",
|
148
|
-
debounce((box: ReadonlyTeleBox): void => {
|
149
|
-
boxEmitter.emit("resize", {
|
150
|
-
appId: box.id,
|
151
|
-
width: box.intrinsicWidth,
|
152
|
-
height: box.intrinsicHeight,
|
153
|
-
});
|
154
|
-
}, 200)
|
155
|
-
),
|
156
|
-
this.teleBoxManager.events.on("focused", box => {
|
157
|
-
if (box) {
|
158
|
-
if (this.canOperate) {
|
159
|
-
boxEmitter.emit("focus", { appId: box.id });
|
160
|
-
} else {
|
161
|
-
this.teleBoxManager.blurBox(box.id);
|
162
|
-
}
|
159
|
+
}, 200)
|
160
|
+
);
|
161
|
+
this.teleBoxManager.events.on("focused", box => {
|
162
|
+
if (box) {
|
163
|
+
if (this.canOperate) {
|
164
|
+
boxEmitter.emit("focus", { appId: box.id });
|
165
|
+
} else {
|
166
|
+
this.teleBoxManager.blurBox(box.id);
|
163
167
|
}
|
164
|
-
}
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
}),
|
172
|
-
emitter.on("writableChange", isWritable => {
|
173
|
-
this.teleBoxManager.setHighlightStage(isWritable);
|
174
|
-
}),
|
175
|
-
emitter.on("containerSizeRatioUpdate", ratio => {
|
176
|
-
this.teleBoxManager._stageRatio$.setValue(ratio);
|
177
|
-
}),
|
178
|
-
]);
|
168
|
+
}
|
169
|
+
});
|
170
|
+
this.teleBoxManager.events.on("z_index", box => {
|
171
|
+
this.context.updateAppState(box.id, AppAttributes.ZIndex, box.zIndex);
|
172
|
+
});
|
173
|
+
emitter.on("playgroundSizeChange", () => this.updateManagerRect());
|
174
|
+
emitter.on("updateManagerRect", () => this.updateManagerRect());
|
179
175
|
}
|
180
176
|
|
181
177
|
private get mainView() {
|
@@ -210,16 +206,12 @@ export class BoxManager {
|
|
210
206
|
return this.teleBoxManager.boxes.length;
|
211
207
|
}
|
212
208
|
|
213
|
-
public
|
214
|
-
return this.teleBoxManager.stageRect;
|
215
|
-
}
|
216
|
-
|
217
|
-
public createBox(params: CreateBoxParams): ReadonlyTeleBox | undefined {
|
209
|
+
public createBox(params: CreateBoxParams): void {
|
218
210
|
if (!this.teleBoxManager) return;
|
219
211
|
let { minwidth = MIN_WIDTH, minheight = MIN_HEIGHT } = params.app.config ?? {};
|
220
212
|
const { width, height } = params.app.config ?? {};
|
221
213
|
const title = params.options?.title || params.appId;
|
222
|
-
const rect = this.teleBoxManager.
|
214
|
+
const rect = this.teleBoxManager.containerRect;
|
223
215
|
|
224
216
|
if (minwidth > 1) {
|
225
217
|
minwidth = minwidth / rect.width;
|
@@ -237,18 +229,38 @@ export class BoxManager {
|
|
237
229
|
height,
|
238
230
|
id: params.appId,
|
239
231
|
};
|
240
|
-
|
232
|
+
this.teleBoxManager.create(createBoxConfig, params.smartPosition);
|
241
233
|
this.context.emitter.emit(`${params.appId}${Events.WindowCreated}` as any);
|
242
|
-
|
234
|
+
}
|
235
|
+
|
236
|
+
public setBoxInitState(appId: string): void {
|
237
|
+
const box = this.teleBoxManager.queryOne({ id: appId });
|
238
|
+
if (box) {
|
239
|
+
if (box.state === TELE_BOX_STATE.Maximized) {
|
240
|
+
this.context.boxEmitter.emit("resize", {
|
241
|
+
appId: appId,
|
242
|
+
x: box.x,
|
243
|
+
y: box.y,
|
244
|
+
width: box.intrinsicWidth,
|
245
|
+
height: box.intrinsicHeight,
|
246
|
+
});
|
247
|
+
}
|
248
|
+
}
|
243
249
|
}
|
244
250
|
|
245
251
|
public setupBoxManager(
|
246
252
|
createTeleBoxManagerConfig?: CreateTeleBoxManagerConfig
|
247
253
|
): TeleBoxManager {
|
248
|
-
const root = WindowManager.
|
254
|
+
const root = WindowManager.wrapper ? WindowManager.wrapper : document.body;
|
255
|
+
const rect = root.getBoundingClientRect();
|
249
256
|
const initManagerState: TeleBoxManagerConfig = {
|
250
|
-
stageRatio: createTeleBoxManagerConfig?.stageRatio,
|
251
257
|
root: root,
|
258
|
+
containerRect: {
|
259
|
+
x: 0,
|
260
|
+
y: 0,
|
261
|
+
width: rect.width,
|
262
|
+
height: rect.height,
|
263
|
+
},
|
252
264
|
fence: false,
|
253
265
|
prefersColorScheme: createTeleBoxManagerConfig?.prefersColorScheme,
|
254
266
|
};
|
@@ -258,16 +270,20 @@ export class BoxManager {
|
|
258
270
|
this.teleBoxManager.destroy();
|
259
271
|
}
|
260
272
|
this.teleBoxManager = manager;
|
261
|
-
const container = createTeleBoxManagerConfig?.collectorContainer;
|
273
|
+
const container = createTeleBoxManagerConfig?.collectorContainer || WindowManager.wrapper;
|
262
274
|
if (container) {
|
263
|
-
this.
|
264
|
-
}
|
265
|
-
if (createTeleBoxManagerConfig?.collectorStyles) {
|
266
|
-
this.teleBoxManager.collector.setStyles(createTeleBoxManagerConfig.collectorStyles);
|
275
|
+
this.setCollectorContainer(container);
|
267
276
|
}
|
268
277
|
return manager;
|
269
278
|
}
|
270
279
|
|
280
|
+
public setCollectorContainer(container: HTMLElement) {
|
281
|
+
const collector = new TeleBoxCollector({
|
282
|
+
styles: this.createTeleBoxManagerConfig?.collectorStyles,
|
283
|
+
}).mount(container);
|
284
|
+
this.teleBoxManager.setCollector(collector);
|
285
|
+
}
|
286
|
+
|
271
287
|
public getBox(appId: string): ReadonlyTeleBox | undefined {
|
272
288
|
return this.teleBoxManager.queryOne({ id: appId });
|
273
289
|
}
|
@@ -320,6 +336,15 @@ export class BoxManager {
|
|
320
336
|
}
|
321
337
|
}
|
322
338
|
|
339
|
+
public updateManagerRect(): void {
|
340
|
+
const rect = this.mainView.divElement?.getBoundingClientRect();
|
341
|
+
if (rect && rect.width > 0 && rect.height > 0) {
|
342
|
+
const containerRect = { x: 0, y: 0, width: rect.width, height: rect.height };
|
343
|
+
this.teleBoxManager.setContainerRect(containerRect);
|
344
|
+
this.context.notifyContainerRectUpdate(this.teleBoxManager.containerRect);
|
345
|
+
}
|
346
|
+
}
|
347
|
+
|
323
348
|
public moveBox({ appId, x, y }: MoveBoxParams): void {
|
324
349
|
this.teleBoxManager.update(appId, { x, y }, true);
|
325
350
|
}
|
@@ -391,16 +416,7 @@ export class BoxManager {
|
|
391
416
|
this.teleBoxManager.update(id, { zIndex }, skipUpdate);
|
392
417
|
}
|
393
418
|
|
394
|
-
public setRoot(root: HTMLElement) {
|
395
|
-
this.teleBoxManager._root$.setValue(root);
|
396
|
-
}
|
397
|
-
|
398
|
-
public setCollector(collector: HTMLElement) {
|
399
|
-
this.teleBoxManager.collector.set$collector(collector);
|
400
|
-
}
|
401
|
-
|
402
419
|
public destroy() {
|
403
|
-
this.sideEffectManager.flushAll();
|
404
420
|
this.teleBoxManager.destroy();
|
405
421
|
}
|
406
422
|
}
|
@@ -0,0 +1,75 @@
|
|
1
|
+
import { ResizeObserver as ResizeObserverPolyfill } from "@juggle/resize-observer";
|
2
|
+
import { isFunction } from "lodash";
|
3
|
+
import { WindowManager } from "./index";
|
4
|
+
import type { EmitterType } from "./InternalEmitter";
|
5
|
+
import type { UnsubscribeFn } from "emittery";
|
6
|
+
|
7
|
+
const ResizeObserver = window.ResizeObserver || ResizeObserverPolyfill;
|
8
|
+
|
9
|
+
export class ContainerResizeObserver {
|
10
|
+
private containerResizeObserver?: ResizeObserver;
|
11
|
+
private disposer?: UnsubscribeFn;
|
12
|
+
|
13
|
+
constructor(private emitter: EmitterType) {}
|
14
|
+
|
15
|
+
public static create(
|
16
|
+
container: HTMLElement,
|
17
|
+
sizer: HTMLElement,
|
18
|
+
wrapper: HTMLDivElement,
|
19
|
+
emitter: EmitterType
|
20
|
+
) {
|
21
|
+
const containerResizeObserver = new ContainerResizeObserver(emitter);
|
22
|
+
containerResizeObserver.observePlaygroundSize(container, sizer, wrapper);
|
23
|
+
return containerResizeObserver;
|
24
|
+
}
|
25
|
+
|
26
|
+
public observePlaygroundSize(
|
27
|
+
container: HTMLElement,
|
28
|
+
sizer: HTMLElement,
|
29
|
+
wrapper: HTMLDivElement
|
30
|
+
) {
|
31
|
+
this.updateSizer(container.getBoundingClientRect(), sizer, wrapper);
|
32
|
+
|
33
|
+
this.containerResizeObserver = new ResizeObserver(entries => {
|
34
|
+
const containerRect = entries[0]?.contentRect;
|
35
|
+
if (containerRect) {
|
36
|
+
this.updateSizer(containerRect, sizer, wrapper);
|
37
|
+
this.emitter.emit("playgroundSizeChange", containerRect);
|
38
|
+
}
|
39
|
+
});
|
40
|
+
|
41
|
+
this.disposer = this.emitter.on("containerSizeRatioUpdate", () => {
|
42
|
+
const containerRect = container.getBoundingClientRect();
|
43
|
+
this.updateSizer(containerRect, sizer, wrapper);
|
44
|
+
this.emitter.emit("playgroundSizeChange", containerRect);
|
45
|
+
});
|
46
|
+
|
47
|
+
this.containerResizeObserver.observe(container);
|
48
|
+
}
|
49
|
+
|
50
|
+
public updateSizer(
|
51
|
+
{ width, height }: DOMRectReadOnly,
|
52
|
+
sizer: HTMLElement,
|
53
|
+
wrapper: HTMLDivElement
|
54
|
+
) {
|
55
|
+
if (width && height) {
|
56
|
+
if (height / width > WindowManager.containerSizeRatio) {
|
57
|
+
height = width * WindowManager.containerSizeRatio;
|
58
|
+
sizer.classList.toggle("netless-window-manager-sizer-horizontal", true);
|
59
|
+
} else {
|
60
|
+
width = height / WindowManager.containerSizeRatio;
|
61
|
+
sizer.classList.toggle("netless-window-manager-sizer-horizontal", false);
|
62
|
+
}
|
63
|
+
wrapper.style.width = `${width}px`;
|
64
|
+
wrapper.style.height = `${height}px`;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
public disconnect() {
|
69
|
+
this.containerResizeObserver?.disconnect();
|
70
|
+
if (isFunction(this.disposer)) {
|
71
|
+
this.disposer();
|
72
|
+
this.disposer = undefined;
|
73
|
+
}
|
74
|
+
}
|
75
|
+
}
|
package/src/Cursor/Cursor.svelte
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
import { isEmpty } from "lodash";
|
3
3
|
import { ApplianceNames } from "white-web-sdk";
|
4
4
|
|
5
|
+
export let uid: string;
|
5
6
|
export let cursorName: string;
|
6
7
|
export let tagName: string | undefined;
|
7
8
|
export let backgroundColor: string;
|
@@ -15,12 +16,17 @@
|
|
15
16
|
export let color: string;
|
16
17
|
export let cursorTagBackgroundColor: string;
|
17
18
|
export let opacity: number;
|
19
|
+
export let pencilEraserSize: number | undefined;
|
20
|
+
export let custom: boolean | undefined;
|
18
21
|
|
19
22
|
$: hasName = !isEmpty(cursorName);
|
20
23
|
$: hasTagName = !isEmpty(tagName);
|
21
24
|
$: hasAvatar = !isEmpty(avatar);
|
22
|
-
$: display = visible ? "
|
25
|
+
$: display = visible ? "" : "none";
|
23
26
|
$: isLaserPointer = appliance === ApplianceNames.laserPointer;
|
27
|
+
$: isLaserPointerPencilEraser = isLaserPointer || appliance === ApplianceNames.pencilEraser;
|
28
|
+
$: offset = isLaserPointerPencilEraser ? "netless-window-manager-laserPointer-pencilEraser-offset" : "";
|
29
|
+
$: pencilEraserSize3ImageOffset = pencilEraserSize === 3 ? "netless-window-manager-pencilEraser-3-offset" : "";
|
24
30
|
|
25
31
|
const computedAvatarStyle = () => {
|
26
32
|
return Object.entries({
|
@@ -36,11 +42,12 @@
|
|
36
42
|
</script>
|
37
43
|
|
38
44
|
<div
|
39
|
-
class="netless-window-manager-cursor-mid"
|
45
|
+
class={"netless-window-manager-cursor-mid" + (custom ? " netless-window-manager-cursor-custom" : "")}
|
40
46
|
style="transform: translateX({x}px) translateY({y}px);display: {display}"
|
41
|
-
|
47
|
+
data-cursor-uid={uid}
|
48
|
+
>
|
42
49
|
{#if !isLaserPointer}
|
43
|
-
<div class="netless-window-manager-cursor-name">
|
50
|
+
<div class="netless-window-manager-cursor-name {offset} {pencilEraserSize3ImageOffset}">
|
44
51
|
<div
|
45
52
|
class={theme}
|
46
53
|
style="background-color: {backgroundColor};color: {color};opacity: {opacity}"
|
@@ -63,6 +70,10 @@
|
|
63
70
|
</div>
|
64
71
|
{/if}
|
65
72
|
<div class="cursor-image-wrapper">
|
66
|
-
<img
|
73
|
+
<img
|
74
|
+
class="netless-window-manager-cursor-{appliance}-image {pencilEraserSize3ImageOffset}"
|
75
|
+
{src}
|
76
|
+
alt={appliance}
|
77
|
+
/>
|
67
78
|
</div>
|
68
79
|
</div>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
2
|
+
|
3
|
+
declare class Cursor extends SvelteComponentTyped<{
|
4
|
+
readonly cursorName: string;
|
5
|
+
readonly tagName?: string;
|
6
|
+
readonly backgroundColor: string;
|
7
|
+
readonly appliance: string;
|
8
|
+
readonly x: number;
|
9
|
+
readonly y: number;
|
10
|
+
readonly src?: string;
|
11
|
+
readonly visible: boolean;
|
12
|
+
readonly avatar: string;
|
13
|
+
readonly theme: string;
|
14
|
+
readonly color: string;
|
15
|
+
readonly cursorTagBackgroundColor: string;
|
16
|
+
readonly opacity: number;
|
17
|
+
readonly pencilEraserSize?: number;
|
18
|
+
readonly custom?: boolean;
|
19
|
+
}> {}
|
20
|
+
|
21
|
+
export default Cursor;
|
package/src/Cursor/Cursor.ts
CHANGED
@@ -1,12 +1,15 @@
|
|
1
|
-
import App from "./Cursor.svelte";
|
2
|
-
import { ApplianceNames } from "white-web-sdk";
|
3
|
-
import { findMemberByUid } from "../Helper";
|
4
|
-
import { omit } from "lodash";
|
5
|
-
import type { Position } from "../AttributesDelegate";
|
6
1
|
import type { RoomMember } from "white-web-sdk";
|
7
|
-
import type {
|
8
|
-
import type { SvelteComponent } from "svelte";
|
2
|
+
import type { CursorOptions } from "../index";
|
9
3
|
import type { AppManager } from "../AppManager";
|
4
|
+
import type { Position } from "../AttributesDelegate";
|
5
|
+
import type { CursorManager } from "./index";
|
6
|
+
|
7
|
+
import { omit } from "lodash";
|
8
|
+
import { ApplianceNames } from "white-web-sdk";
|
9
|
+
|
10
|
+
import { findMemberByUid } from "../Helper";
|
11
|
+
import App from "./Cursor.svelte";
|
12
|
+
import { remoteIcon } from "./icons2";
|
10
13
|
|
11
14
|
export type Payload = {
|
12
15
|
[key: string]: any;
|
@@ -15,7 +18,8 @@ export type Payload = {
|
|
15
18
|
export class Cursor {
|
16
19
|
private member?: RoomMember;
|
17
20
|
private timer?: number;
|
18
|
-
private component?:
|
21
|
+
private component?: App;
|
22
|
+
private style: CursorOptions["style"] & string = "default";
|
19
23
|
|
20
24
|
constructor(
|
21
25
|
private manager: AppManager,
|
@@ -26,6 +30,7 @@ export class Cursor {
|
|
26
30
|
this.updateMember();
|
27
31
|
this.createCursor();
|
28
32
|
this.autoHidden();
|
33
|
+
this.setStyle(cursorManager.style);
|
29
34
|
}
|
30
35
|
|
31
36
|
public move = (position: Position) => {
|
@@ -46,6 +51,16 @@ export class Cursor {
|
|
46
51
|
}
|
47
52
|
};
|
48
53
|
|
54
|
+
public setStyle = (style: typeof this.style) => {
|
55
|
+
this.style = style;
|
56
|
+
if (this.component) {
|
57
|
+
this.component.$set({
|
58
|
+
src: this.getIcon(),
|
59
|
+
custom: this.isCustomIcon(),
|
60
|
+
});
|
61
|
+
}
|
62
|
+
};
|
63
|
+
|
49
64
|
public leave = () => {
|
50
65
|
this.hide();
|
51
66
|
};
|
@@ -56,6 +71,10 @@ export class Cursor {
|
|
56
71
|
if (point) {
|
57
72
|
let translateX = point.x - 2;
|
58
73
|
let translateY = point.y - 18;
|
74
|
+
if (this.isCustomIcon()) {
|
75
|
+
translateX -= 11;
|
76
|
+
translateY += 4;
|
77
|
+
}
|
59
78
|
if (type === "app") {
|
60
79
|
const wrapperRect = this.cursorManager.wrapperRect;
|
61
80
|
if (wrapperRect) {
|
@@ -80,6 +99,11 @@ export class Cursor {
|
|
80
99
|
return `rgb(${rgb})`;
|
81
100
|
}
|
82
101
|
|
102
|
+
public get memberColorHex(): string {
|
103
|
+
const [r, g, b] = this.member?.memberState?.strokeColor || [236, 52, 85];
|
104
|
+
return ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
|
105
|
+
}
|
106
|
+
|
83
107
|
private get payload(): Payload | undefined {
|
84
108
|
return this.member?.payload;
|
85
109
|
}
|
@@ -140,11 +164,13 @@ export class Cursor {
|
|
140
164
|
|
141
165
|
private initProps() {
|
142
166
|
return {
|
167
|
+
uid: this.memberId,
|
143
168
|
x: 0,
|
144
169
|
y: 0,
|
145
170
|
appliance: this.memberApplianceName as string,
|
146
171
|
avatar: this.memberAvatar,
|
147
172
|
src: this.getIcon(),
|
173
|
+
custom: this.isCustomIcon(),
|
148
174
|
visible: false,
|
149
175
|
backgroundColor: this.memberColor,
|
150
176
|
cursorName: this.memberCursorName,
|
@@ -153,15 +179,53 @@ export class Cursor {
|
|
153
179
|
cursorTagBackgroundColor: this.memberCursorTagBackgroundColor,
|
154
180
|
opacity: this.memberOpacity,
|
155
181
|
tagName: this.memberTagName,
|
182
|
+
pencilEraserSize: this.member?.memberState.pencilEraserSize,
|
156
183
|
};
|
157
184
|
}
|
158
185
|
|
159
|
-
private getIcon() {
|
160
|
-
if (this.member)
|
161
|
-
|
162
|
-
|
163
|
-
|
186
|
+
private getIcon(): string | undefined {
|
187
|
+
if (!this.member) return;
|
188
|
+
|
189
|
+
const { memberApplianceName, memberColorHex } = this;
|
190
|
+
const { userApplianceIcons, applianceIcons } = this.cursorManager;
|
191
|
+
|
192
|
+
let iconsKey: string | undefined = this.memberApplianceName;
|
193
|
+
if (iconsKey === ApplianceNames.pencilEraser) {
|
194
|
+
iconsKey = `${iconsKey}${this.member?.memberState.pencilEraserSize || 1}`;
|
195
|
+
}
|
196
|
+
|
197
|
+
const userApplianceSrc = iconsKey && userApplianceIcons[iconsKey];
|
198
|
+
if (userApplianceSrc) return userApplianceSrc;
|
199
|
+
|
200
|
+
if (this.style === "custom" && memberApplianceName) {
|
201
|
+
const customApplianceSrc = remoteIcon(memberApplianceName, memberColorHex);
|
202
|
+
if (customApplianceSrc) return customApplianceSrc;
|
203
|
+
}
|
204
|
+
|
205
|
+
const applianceSrc = applianceIcons[iconsKey || ApplianceNames.shape];
|
206
|
+
return applianceSrc || applianceIcons[ApplianceNames.shape];
|
207
|
+
}
|
208
|
+
|
209
|
+
private isCustomIcon(): boolean {
|
210
|
+
if (!this.member) return false;
|
211
|
+
|
212
|
+
const { memberApplianceName, memberColorHex } = this;
|
213
|
+
const { userApplianceIcons } = this.cursorManager;
|
214
|
+
|
215
|
+
let iconsKey: string | undefined = this.memberApplianceName;
|
216
|
+
if (iconsKey === ApplianceNames.pencilEraser) {
|
217
|
+
iconsKey = `${iconsKey}${this.member?.memberState.pencilEraserSize || 1}`;
|
164
218
|
}
|
219
|
+
|
220
|
+
const userApplianceSrc = iconsKey && userApplianceIcons[iconsKey];
|
221
|
+
if (userApplianceSrc) return false;
|
222
|
+
|
223
|
+
if (this.style === "custom" && memberApplianceName) {
|
224
|
+
const customApplianceSrc = remoteIcon(memberApplianceName, memberColorHex);
|
225
|
+
if (customApplianceSrc) return true;
|
226
|
+
}
|
227
|
+
|
228
|
+
return false;
|
165
229
|
}
|
166
230
|
|
167
231
|
public updateMember() {
|
package/src/Cursor/icons.ts
CHANGED
@@ -5,6 +5,9 @@ import eraser from "../image/eraser-cursor.png";
|
|
5
5
|
import shape from "../image/shape-cursor.svg";
|
6
6
|
import text from "../image/text-cursor.svg";
|
7
7
|
import laser from "../image/laser-pointer-cursor.svg";
|
8
|
+
import pencilEraser1 from "../image/pencil-eraser-1.svg";
|
9
|
+
import pencilEraser2 from "../image/pencil-eraser-2.svg";
|
10
|
+
import pencilEraser3 from "../image/pencil-eraser-3.svg";
|
8
11
|
|
9
12
|
export const ApplianceMap: {
|
10
13
|
[key: string]: string;
|
@@ -15,4 +18,7 @@ export const ApplianceMap: {
|
|
15
18
|
[ApplianceNames.shape]: shape,
|
16
19
|
[ApplianceNames.text]: text,
|
17
20
|
[ApplianceNames.laserPointer]: laser,
|
21
|
+
["pencilEraser1"]: pencilEraser1,
|
22
|
+
["pencilEraser2"]: pencilEraser2,
|
23
|
+
["pencilEraser3"]: pencilEraser3,
|
18
24
|
};
|