@netless/window-manager 0.4.0-canary.27 → 0.4.0-canary.30
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 +3 -0
- package/README.md +1 -0
- package/dist/AppManager.d.ts +8 -2
- package/dist/Cursor/Cursor.d.ts +2 -1
- package/dist/Cursor/index.d.ts +2 -1
- package/dist/Helper.d.ts +1 -0
- package/dist/index.d.ts +8 -2
- 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/docs/api.md +40 -9
- package/docs/replay.md +40 -0
- package/package.json +2 -2
- package/src/AppContext.ts +4 -1
- package/src/AppManager.ts +68 -6
- package/src/ContainerResizeObserver.ts +3 -3
- package/src/Cursor/Cursor.svelte +25 -21
- package/src/Cursor/Cursor.ts +3 -2
- package/src/Cursor/icons.ts +2 -0
- package/src/Cursor/index.ts +10 -5
- package/src/Helper.ts +12 -1
- package/src/image/laser-pointer-cursor.svg +17 -0
- package/src/index.ts +52 -24
package/docs/api.md
CHANGED
@@ -11,6 +11,9 @@
|
|
11
11
|
- [`closeApp`](#closeApp)
|
12
12
|
- [`setMainViewSceneIndex`](#setMainViewSceneIndex)
|
13
13
|
- [`setBoxState`](#setBoxState)
|
14
|
+
- [`cleanCurrentScene`](#cleanCurrentScene)
|
15
|
+
- [`redo`](#redo)
|
16
|
+
- [`undo`](#undo)
|
14
17
|
- [实例属性](#prototypes)
|
15
18
|
- [事件回调](#events)
|
16
19
|
|
@@ -128,19 +131,45 @@ manager.setMainViewSceneIndex(1)
|
|
128
131
|
manager.setBoxState("normal") // boxState: normal | maximized | minimized
|
129
132
|
```
|
130
133
|
|
134
|
+
<h3 id="cleanCurrentScene">cleanCurrentScene</h3>
|
135
|
+
|
136
|
+
> 清除当前 focus 的 view 的笔迹
|
137
|
+
|
138
|
+
```ts
|
139
|
+
manager.cleanCurrentScene()
|
140
|
+
```
|
141
|
+
|
142
|
+
<h3 id="redo">redo</h3>
|
143
|
+
|
144
|
+
> 在当前 focus 的 view 上重做上一步操作
|
145
|
+
|
146
|
+
```ts
|
147
|
+
manager.redo()
|
148
|
+
```
|
149
|
+
|
150
|
+
<h3 id="undo">undo</h3>
|
151
|
+
|
152
|
+
> 在当前 focus 的 view 上撤消上一步操作
|
153
|
+
|
154
|
+
```ts
|
155
|
+
manager.undo()
|
156
|
+
```
|
157
|
+
|
131
158
|
<br>
|
132
159
|
|
133
160
|
<h2 id="prototypes">实例属性</h2>
|
134
161
|
|
135
|
-
| name | type | default | desc
|
136
|
-
| ------------------ | ------- | ------- | -----------------
|
137
|
-
| mainView | View | | 主白板
|
138
|
-
| mainViewSceneIndex | number | | 当前主白板的 SceneIndex
|
162
|
+
| name | type | default | desc |
|
163
|
+
| ------------------ | ------- | ------- | ----------------- |
|
164
|
+
| mainView | View | | 主白板 |
|
165
|
+
| mainViewSceneIndex | number | | 当前主白板的 SceneIndex |
|
139
166
|
| mainViewScenesLength | number | | mainView 的 scenes 长度 |
|
140
|
-
| boxState | string | | 当前窗口状态
|
141
|
-
| darkMode | boolean | | 黑夜模式
|
142
|
-
| prefersColorScheme | string | | 颜色主题
|
143
|
-
| focused | string |
|
167
|
+
| boxState | string | | 当前窗口状态 |
|
168
|
+
| darkMode | boolean | | 黑夜模式 |
|
169
|
+
| prefersColorScheme | string | | 颜色主题 |
|
170
|
+
| focused | string | | focus 的 app |
|
171
|
+
| canRedoSteps | number | | 当前 focus 的 view 可以重做的步数 |
|
172
|
+
| canRedoSteps | number | | 当前 focus 的 view 可以撤销的步数 |
|
144
173
|
|
145
174
|
<br>
|
146
175
|
|
@@ -159,4 +188,6 @@ manager.callbacks.on(events, listener)
|
|
159
188
|
| prefersColorSchemeChange | string | | auto,light,dark |
|
160
189
|
| cameraStateChange | CameraState | | |
|
161
190
|
| focusedChange | string, undefined | | 当前 focus 的 appId,主白板时为 undefined |
|
162
|
-
| mainViewScenesLengthChange | number | | mainView scenes 添加或删除时触发 |
|
191
|
+
| mainViewScenesLengthChange | number | | mainView scenes 添加或删除时触发 |
|
192
|
+
| canRedoStepsChange | number | | 当前 focus 的 view 可重做步数改变 |
|
193
|
+
| canUndoStepsChange | number | | 当前 focus 的 view 可撤销步数改变 |
|
package/docs/replay.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
## 回放
|
2
|
+
|
3
|
+
> 注意: 多窗口的回放只支持从创建房间开始就是多窗口的房间
|
4
|
+
|
5
|
+
> 如果是一开始作为单窗口模式使用,又转变成多窗口模式使用, 则会造成回放渲染空白
|
6
|
+
|
7
|
+
<br>
|
8
|
+
|
9
|
+
|
10
|
+
```typescript
|
11
|
+
import { WhiteWebSdk } from "white-web-sdk";
|
12
|
+
import { WindowManager, BuiltinApps } from "@netless/window-manager";
|
13
|
+
import "@netless/window-manager/dist/style.css";
|
14
|
+
|
15
|
+
const sdk = new WhiteWebSdk({
|
16
|
+
appIdentifier: "appIdentifier",
|
17
|
+
useMobXState: true // 请确保打开这个选项
|
18
|
+
});
|
19
|
+
|
20
|
+
let manager: WindowManager;
|
21
|
+
|
22
|
+
sdk.replayRoom({
|
23
|
+
uuid: "room uuid",
|
24
|
+
roomToken: "room token",
|
25
|
+
invisiblePlugins: [WindowManager],
|
26
|
+
useMultiViews: true, // 多窗口必须用开启 useMultiViews
|
27
|
+
}).then(player => {
|
28
|
+
player.callbacks.on("onPhaseChanged", async (phase) => {
|
29
|
+
if (phase === PlayerPhase.Playing) {
|
30
|
+
if (manager) return;
|
31
|
+
manager = await WindowManager.mount({
|
32
|
+
room: player,
|
33
|
+
container: document.getElementById("container")
|
34
|
+
});
|
35
|
+
}
|
36
|
+
})
|
37
|
+
});
|
38
|
+
|
39
|
+
player.play(); // WindowManager 只有在播放之后才能挂载
|
40
|
+
```
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@netless/window-manager",
|
3
|
-
"version": "0.4.0-canary.
|
3
|
+
"version": "0.4.0-canary.30",
|
4
4
|
"description": "",
|
5
5
|
"main": "dist/index.es.js",
|
6
6
|
"module": "dist/index.es.js",
|
@@ -58,6 +58,6 @@
|
|
58
58
|
"typescript": "^4.3.5",
|
59
59
|
"video.js": "^7.14.3",
|
60
60
|
"vite": "^2.5.3",
|
61
|
-
"white-web-sdk": "^2.16.
|
61
|
+
"white-web-sdk": "^2.16.4"
|
62
62
|
}
|
63
63
|
}
|
package/src/AppContext.ts
CHANGED
@@ -152,7 +152,10 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
|
|
152
152
|
}
|
153
153
|
|
154
154
|
/** Dispatch events to other clients (and self). */
|
155
|
-
public dispatchMagixEvent: MagixEventDispatcher<TMagixEventPayloads> = (
|
155
|
+
public dispatchMagixEvent: MagixEventDispatcher<TMagixEventPayloads> = (...args) => {
|
156
|
+
// can't dispatch events on replay mode
|
157
|
+
return this.manager.room?.dispatchMagixEvent(...args);
|
158
|
+
}
|
156
159
|
|
157
160
|
/** Listen to events from others clients (and self messages). */
|
158
161
|
public addMagixEventListener: MagixEventAddListener<TMagixEventPayloads> = (event, handler, options) => {
|
package/src/AppManager.ts
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import { AppAttributes, AppStatus, Events, MagixEventName, ROOT_DIR } from "./constants";
|
2
|
+
import { AppCreateQueue } from "./Utils/AppCreateQueue";
|
2
3
|
import { AppListeners } from "./AppListener";
|
3
4
|
import { AppProxy } from "./AppProxy";
|
4
5
|
import { appRegister } from "./Register";
|
@@ -20,9 +21,8 @@ import {
|
|
20
21
|
} from "./Utils/Common";
|
21
22
|
import type { ReconnectRefresher } from "./ReconnectRefresher";
|
22
23
|
import type { BoxManager } from "./BoxManager";
|
23
|
-
import type { Displayer, DisplayerState, Room, ScenesCallbacksNode } from "white-web-sdk";
|
24
|
+
import type { Displayer, DisplayerState, Room, ScenesCallbacksNode, View } from "white-web-sdk";
|
24
25
|
import type { AddAppParams, BaseInsertParams, TeleBoxRect, EmitterEvent } from "./index";
|
25
|
-
import { AppCreateQueue } from "./Utils/AppCreateQueue";
|
26
26
|
|
27
27
|
export class AppManager {
|
28
28
|
public displayer: Displayer;
|
@@ -187,6 +187,10 @@ export class AppManager {
|
|
187
187
|
const focused = get(this.attributes, "focus");
|
188
188
|
if (this._prevFocused !== focused) {
|
189
189
|
callbacks.emit("focusedChange", focused);
|
190
|
+
this.disposePrevFocusViewRedoUndoListeners(this._prevFocused);
|
191
|
+
setTimeout(() => {
|
192
|
+
this.addRedoUndoListeners(focused);
|
193
|
+
}, 0);
|
190
194
|
this._prevFocused = focused;
|
191
195
|
if (focused !== undefined) {
|
192
196
|
this.boxManager?.focusBox({ appId: focused });
|
@@ -212,8 +216,60 @@ export class AppManager {
|
|
212
216
|
this.displayerWritableListener(!this.room?.isWritable);
|
213
217
|
this.displayer.callbacks.on("onEnableWriteNowChanged", this.displayerWritableListener);
|
214
218
|
this._prevFocused = this.attributes.focus;
|
219
|
+
this.addRedoUndoListeners(this.attributes.focus);
|
215
220
|
}
|
216
221
|
|
222
|
+
private disposePrevFocusViewRedoUndoListeners = (prevFocused: string | undefined) => {
|
223
|
+
if (prevFocused === undefined) {
|
224
|
+
this.mainView.callbacks.off("onCanRedoStepsUpdate", this.onCanRedoStepsUpdate);
|
225
|
+
this.mainView.callbacks.off("onCanUndoStepsUpdate", this.onCanRedoStepsUpdate);
|
226
|
+
} else {
|
227
|
+
const appProxy = this.appProxies.get(prevFocused);
|
228
|
+
if (appProxy) {
|
229
|
+
appProxy.view?.callbacks.off("onCanRedoStepsUpdate", this.onCanRedoStepsUpdate);
|
230
|
+
appProxy.view?.callbacks.off("onCanUndoStepsUpdate", this.onCanUndoStepsUpdate);
|
231
|
+
}
|
232
|
+
}
|
233
|
+
};
|
234
|
+
|
235
|
+
private addRedoUndoListeners = (focused: string | undefined) => {
|
236
|
+
if (focused === undefined) {
|
237
|
+
this.addViewCallbacks(
|
238
|
+
this.mainView,
|
239
|
+
this.onCanRedoStepsUpdate,
|
240
|
+
this.onCanUndoStepsUpdate
|
241
|
+
);
|
242
|
+
} else {
|
243
|
+
const focusApp = this.appProxies.get(focused);
|
244
|
+
if (focusApp && focusApp.view) {
|
245
|
+
this.addViewCallbacks(
|
246
|
+
focusApp.view,
|
247
|
+
this.onCanRedoStepsUpdate,
|
248
|
+
this.onCanUndoStepsUpdate
|
249
|
+
);
|
250
|
+
}
|
251
|
+
}
|
252
|
+
};
|
253
|
+
|
254
|
+
private addViewCallbacks = (
|
255
|
+
view: View,
|
256
|
+
redoListener: (steps: number) => void,
|
257
|
+
undoListener: (steps: number) => void
|
258
|
+
) => {
|
259
|
+
redoListener(view.canRedoSteps);
|
260
|
+
undoListener(view.canUndoSteps);
|
261
|
+
view.callbacks.on("onCanRedoStepsUpdate", redoListener);
|
262
|
+
view.callbacks.on("onCanUndoStepsUpdate", undoListener);
|
263
|
+
};
|
264
|
+
|
265
|
+
private onCanRedoStepsUpdate = (steps: number) => {
|
266
|
+
callbacks.emit("canRedoStepsChange", steps);
|
267
|
+
};
|
268
|
+
|
269
|
+
private onCanUndoStepsUpdate = (steps: number) => {
|
270
|
+
callbacks.emit("canUndoStepsChange", steps);
|
271
|
+
};
|
272
|
+
|
217
273
|
/**
|
218
274
|
* 插件更新 attributes 时的回调
|
219
275
|
*
|
@@ -439,7 +495,7 @@ export class AppManager {
|
|
439
495
|
this.safeSetAttributes({ _mainScenePath: scenePath });
|
440
496
|
this.store.setMainViewFocusPath(this.mainView);
|
441
497
|
this.updateSceneIndex();
|
442
|
-
this.
|
498
|
+
this.dispatchSetMainViewScenePath(scenePath);
|
443
499
|
}
|
444
500
|
}
|
445
501
|
|
@@ -469,9 +525,7 @@ export class AppManager {
|
|
469
525
|
if (success) {
|
470
526
|
this.store.setMainViewScenePath(scenePath);
|
471
527
|
this.safeSetAttributes({ _mainSceneIndex: index });
|
472
|
-
this.
|
473
|
-
nextScenePath: scenePath,
|
474
|
-
});
|
528
|
+
this.dispatchSetMainViewScenePath(scenePath);
|
475
529
|
}
|
476
530
|
} else {
|
477
531
|
throw new Error(`[WindowManager]: ${sceneDir}: ${index} not valid index`);
|
@@ -480,6 +534,12 @@ export class AppManager {
|
|
480
534
|
}
|
481
535
|
}
|
482
536
|
|
537
|
+
private dispatchSetMainViewScenePath(scenePath: string): void {
|
538
|
+
this.dispatchInternalEvent(Events.SetMainViewScenePath, { nextScenePath: scenePath });
|
539
|
+
// 兼容 15 的 SDK, 需要 room 的当前 ScenePath
|
540
|
+
setScenePath(this.room, scenePath);
|
541
|
+
}
|
542
|
+
|
483
543
|
public getAppInitPath(appId: string): string | undefined {
|
484
544
|
const attrs = this.store.getAppAttributes(appId);
|
485
545
|
if (attrs) {
|
@@ -587,6 +647,8 @@ export class AppManager {
|
|
587
647
|
callbacks.clearListeners();
|
588
648
|
this.callbacksNode?.dispose();
|
589
649
|
this.appCreateQueue.destroy();
|
650
|
+
this.disposePrevFocusViewRedoUndoListeners(this._prevFocused);
|
651
|
+
this._prevFocused = undefined;
|
590
652
|
this._prevSceneIndex = undefined;
|
591
653
|
}
|
592
654
|
}
|
@@ -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 "./index";
|
3
|
+
import type { EmitterType } from "./index";
|
4
4
|
|
5
5
|
const ResizeObserver = window.ResizeObserver || ResizeObserverPolyfill;
|
6
6
|
|
@@ -13,7 +13,7 @@ export class ContainerResizeObserver {
|
|
13
13
|
container: HTMLElement,
|
14
14
|
sizer: HTMLElement,
|
15
15
|
wrapper: HTMLDivElement,
|
16
|
-
emitter: EmitterType
|
16
|
+
emitter: EmitterType
|
17
17
|
) {
|
18
18
|
const containerResizeObserver = new ContainerResizeObserver(emitter);
|
19
19
|
containerResizeObserver.observePlaygroundSize(container, sizer, wrapper);
|
@@ -31,7 +31,7 @@ export class ContainerResizeObserver {
|
|
31
31
|
const containerRect = entries[0]?.contentRect;
|
32
32
|
if (containerRect) {
|
33
33
|
this.updateSizer(containerRect, sizer, wrapper);
|
34
|
-
this.emitter.emit("playgroundSizeChange", containerRect)
|
34
|
+
this.emitter.emit("playgroundSizeChange", containerRect);
|
35
35
|
}
|
36
36
|
});
|
37
37
|
|
package/src/Cursor/Cursor.svelte
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
<script lang="ts">
|
2
2
|
import { isEmpty } from "lodash";
|
3
|
+
import { ApplianceNames } from "white-web-sdk";
|
3
4
|
|
4
5
|
export let cursorName: string;
|
5
6
|
export let tagName: string;
|
@@ -19,6 +20,7 @@
|
|
19
20
|
$: hasTagName = !isEmpty(tagName);
|
20
21
|
$: hasAvatar = !isEmpty(avatar);
|
21
22
|
$: display = visible ? "initial" : "none";
|
23
|
+
$: isLaserPointer = appliance === ApplianceNames.laserPointer;
|
22
24
|
|
23
25
|
const computedAvatarStyle = () => {
|
24
26
|
return Object.entries({
|
@@ -36,28 +38,30 @@
|
|
36
38
|
<div
|
37
39
|
class="netless-window-manager-cursor-mid"
|
38
40
|
style="transform: translateX({x}px) translateY({y}px);display: {display}"
|
39
|
-
>
|
40
|
-
|
41
|
-
<div
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
{
|
57
|
-
|
58
|
-
|
41
|
+
>
|
42
|
+
{#if !isLaserPointer}
|
43
|
+
<div class="netless-window-manager-cursor-name">
|
44
|
+
<div
|
45
|
+
class={theme}
|
46
|
+
style="background-color: {backgroundColor};color: {color};opacity: {opacity}"
|
47
|
+
>
|
48
|
+
{#if hasAvatar}
|
49
|
+
<img
|
50
|
+
class="netless-window-manager-cursor-selector-avatar"
|
51
|
+
style={computedAvatarStyle()}
|
52
|
+
src={avatar}
|
53
|
+
alt="avatar"
|
54
|
+
/>
|
55
|
+
{/if}
|
56
|
+
<span style="overflow: hidden;white-space: nowrap;text-overflow: ellipsis;max-width: 80px">{cursorName}</span>
|
57
|
+
{#if hasTagName}
|
58
|
+
<span class="netless-window-manager-cursor-tag-name" style="background-color: {cursorTagBackgroundColor}">
|
59
|
+
{tagName}
|
60
|
+
</span>
|
61
|
+
{/if}
|
62
|
+
</div>
|
59
63
|
</div>
|
60
|
-
|
64
|
+
{/if}
|
61
65
|
<div class="cursor-image-wrapper">
|
62
66
|
<img class="netless-window-manager-cursor-{appliance}-image" {src} alt={appliance} />
|
63
67
|
</div>
|
package/src/Cursor/Cursor.ts
CHANGED
@@ -23,7 +23,7 @@ export class Cursor {
|
|
23
23
|
private cursorManager: CursorManager,
|
24
24
|
private wrapper?: HTMLElement
|
25
25
|
) {
|
26
|
-
this.
|
26
|
+
this.updateMember();
|
27
27
|
this.createCursor();
|
28
28
|
this.autoHidden();
|
29
29
|
}
|
@@ -158,9 +158,10 @@ export class Cursor {
|
|
158
158
|
}
|
159
159
|
}
|
160
160
|
|
161
|
-
public
|
161
|
+
public updateMember() {
|
162
162
|
this.member = this.manager.findMemberByUid(this.memberId);
|
163
163
|
this.updateComponent();
|
164
|
+
return this.member;
|
164
165
|
}
|
165
166
|
|
166
167
|
private updateComponent() {
|
package/src/Cursor/icons.ts
CHANGED
@@ -4,6 +4,7 @@ import selector from "../image/selector-cursor.png";
|
|
4
4
|
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
|
+
import laser from "../image/laser-pointer-cursor.svg";
|
7
8
|
|
8
9
|
export const ApplianceMap: {
|
9
10
|
[key: string]: string;
|
@@ -13,4 +14,5 @@ export const ApplianceMap: {
|
|
13
14
|
[ApplianceNames.eraser]: eraser,
|
14
15
|
[ApplianceNames.shape]: shape,
|
15
16
|
[ApplianceNames.text]: text,
|
17
|
+
[ApplianceNames.laserPointer]: laser,
|
16
18
|
};
|
package/src/Cursor/index.ts
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
import {
|
1
|
+
import { ApplianceNames } from "white-web-sdk";
|
2
2
|
import { Cursor } from "./Cursor";
|
3
3
|
import { CursorState, Events } from "../constants";
|
4
4
|
import { emitter, WindowManager } from "../index";
|
5
5
|
import { SideEffectManager } from "side-effect-manager";
|
6
|
+
import { throttle } from "lodash";
|
6
7
|
import type { CursorMovePayload } from "../index";
|
7
8
|
import type { PositionType } from "../AttributesDelegate";
|
8
9
|
import type { Point, RoomMember, View } from "white-web-sdk";
|
@@ -27,7 +28,7 @@ export class CursorManager {
|
|
27
28
|
private sideEffectManager = new SideEffectManager();
|
28
29
|
private store = this.manager.store;
|
29
30
|
|
30
|
-
constructor(private manager: AppManager) {
|
31
|
+
constructor(private manager: AppManager, private enableCursor: boolean) {
|
31
32
|
this.roomMembers = this.manager.room?.state.roomMembers;
|
32
33
|
const wrapper = WindowManager.wrapper;
|
33
34
|
if (wrapper) {
|
@@ -42,8 +43,12 @@ export class CursorManager {
|
|
42
43
|
if (payload.state === CursorState.Leave) {
|
43
44
|
cursorInstance.leave();
|
44
45
|
} else {
|
45
|
-
cursorInstance.
|
46
|
-
|
46
|
+
const member = cursorInstance.updateMember();
|
47
|
+
const isLaserPointer =
|
48
|
+
member?.memberState.currentApplianceName === ApplianceNames.laserPointer;
|
49
|
+
if (this.enableCursor || isLaserPointer) {
|
50
|
+
cursorInstance.move(payload.position);
|
51
|
+
}
|
47
52
|
}
|
48
53
|
});
|
49
54
|
this.sideEffectManager.add(() => {
|
@@ -51,7 +56,7 @@ export class CursorManager {
|
|
51
56
|
this.updateContainerRect();
|
52
57
|
});
|
53
58
|
return unsubscribe;
|
54
|
-
})
|
59
|
+
});
|
55
60
|
}
|
56
61
|
|
57
62
|
public setupWrapper(wrapper: HTMLElement) {
|
package/src/Helper.ts
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
import { getVersionNumber } from "./Utils/Common";
|
2
|
+
import { REQUIRE_VERSION } from "./constants";
|
3
|
+
import { WhiteVersion } from "white-web-sdk";
|
4
|
+
import { WhiteWebSDKInvalidError } from "./Utils/error";
|
1
5
|
import { WindowManager } from "./index";
|
2
6
|
|
3
7
|
export const setupWrapper = (
|
@@ -27,4 +31,11 @@ export const setupWrapper = (
|
|
27
31
|
WindowManager.wrapper = wrapper;
|
28
32
|
|
29
33
|
return { playground, wrapper, sizer, mainViewElement };
|
30
|
-
};
|
34
|
+
};
|
35
|
+
|
36
|
+
export const checkVersion = () => {
|
37
|
+
const version = getVersionNumber(WhiteVersion);
|
38
|
+
if (version < getVersionNumber(REQUIRE_VERSION)) {
|
39
|
+
throw new WhiteWebSDKInvalidError(REQUIRE_VERSION);
|
40
|
+
}
|
41
|
+
};
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<svg width="28px" height="28px" viewBox="0 0 28 28" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
3
|
+
<!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
|
4
|
+
<title>编组 2</title>
|
5
|
+
<desc>Created with Sketch.</desc>
|
6
|
+
<defs>
|
7
|
+
<filter x="-120.0%" y="-120.0%" width="340.0%" height="340.0%" filterUnits="objectBoundingBox" id="filter-1">
|
8
|
+
<feGaussianBlur stdDeviation="4" in="SourceGraphic"></feGaussianBlur>
|
9
|
+
</filter>
|
10
|
+
</defs>
|
11
|
+
<g id="页面1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
12
|
+
<g id="编组-2" transform="translate(9.000000, 9.000000)" fill="#FF0100">
|
13
|
+
<circle id="椭圆形" filter="url(#filter-1)" cx="5" cy="5" r="5"></circle>
|
14
|
+
<path d="M5,8 C6.65685425,8 8,6.65685425 8,5 C8,3.34314575 6.65685425,2 5,2 C3.34314575,2 2,3.34314575 2,5 C2,6.65685425 3.34314575,8 5,8 Z M5,6.28571429 C4.28991961,6.28571429 3.71428571,5.71008039 3.71428571,5 C3.71428571,4.28991961 4.28991961,3.71428571 5,3.71428571 C5.71008039,3.71428571 6.28571429,4.28991961 6.28571429,5 C6.28571429,5.71008039 5.71008039,6.28571429 5,6.28571429 Z" id="椭圆形" fill-rule="nonzero"></path>
|
15
|
+
</g>
|
16
|
+
</g>
|
17
|
+
</svg>
|
package/src/index.ts
CHANGED
@@ -2,25 +2,25 @@ import Emittery from "emittery";
|
|
2
2
|
import pRetry from "p-retry";
|
3
3
|
import { AppManager } from "./AppManager";
|
4
4
|
import { appRegister } from "./Register";
|
5
|
+
import { checkVersion, setupWrapper } from "./Helper";
|
5
6
|
import { ContainerResizeObserver } from "./ContainerResizeObserver";
|
6
7
|
import { createBoxManager } from "./BoxManager";
|
7
8
|
import { CursorManager } from "./Cursor";
|
8
|
-
import { DEFAULT_CONTAINER_RATIO, Events
|
9
|
+
import { DEFAULT_CONTAINER_RATIO, Events } from "./constants";
|
9
10
|
import { Fields } from "./AttributesDelegate";
|
10
11
|
import { initDb } from "./Register/storage";
|
12
|
+
import { InvisiblePlugin, isPlayer, isRoom, RoomPhase, ViewMode } from "white-web-sdk";
|
11
13
|
import { isNull, isObject } from "lodash";
|
12
14
|
import { log } from "./Utils/log";
|
13
15
|
import { ReconnectRefresher } from "./ReconnectRefresher";
|
14
16
|
import { replaceRoomFunction } from "./Utils/RoomHacker";
|
15
17
|
import { setupBuiltin } from "./BuiltinApps";
|
16
|
-
import { setupWrapper } from "./Helper";
|
17
18
|
import "./style.css";
|
18
19
|
import "@netless/telebox-insider/dist/style.css";
|
19
20
|
import {
|
20
21
|
addEmitterOnceListener,
|
21
22
|
ensureValidScenePath,
|
22
23
|
entireScenes,
|
23
|
-
getVersionNumber,
|
24
24
|
isValidScenePath,
|
25
25
|
wait,
|
26
26
|
} from "./Utils/Common";
|
@@ -30,17 +30,8 @@ import {
|
|
30
30
|
AppManagerNotInitError,
|
31
31
|
InvalidScenePath,
|
32
32
|
ParamsInvalidError,
|
33
|
-
WhiteWebSDKInvalidError,
|
34
33
|
} from "./Utils/error";
|
35
34
|
import type { Apps, Position } from "./AttributesDelegate";
|
36
|
-
import {
|
37
|
-
InvisiblePlugin,
|
38
|
-
isPlayer,
|
39
|
-
isRoom,
|
40
|
-
RoomPhase,
|
41
|
-
ViewMode,
|
42
|
-
WhiteVersion,
|
43
|
-
} from "white-web-sdk";
|
44
35
|
import type {
|
45
36
|
Displayer,
|
46
37
|
SceneDefinition,
|
@@ -159,6 +150,8 @@ export type PublicEvent = {
|
|
159
150
|
mainViewSceneIndexChange: number;
|
160
151
|
focusedChange: string | undefined;
|
161
152
|
mainViewScenesLengthChange: number;
|
153
|
+
canRedoStepsChange: number;
|
154
|
+
canUndoStepsChange: number;
|
162
155
|
};
|
163
156
|
|
164
157
|
export type MountParams = {
|
@@ -224,7 +217,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
|
|
224
217
|
const cursor = params.cursor;
|
225
218
|
WindowManager.params = params;
|
226
219
|
|
227
|
-
|
220
|
+
checkVersion();
|
228
221
|
let manager: WindowManager | undefined = undefined;
|
229
222
|
if (isRoom(room)) {
|
230
223
|
if (room.phase !== RoomPhase.Connected) {
|
@@ -270,10 +263,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
|
|
270
263
|
await manager.ensureAttributes();
|
271
264
|
|
272
265
|
manager.appManager = new AppManager(manager);
|
273
|
-
|
274
|
-
if (cursor) {
|
275
|
-
manager.cursorManager = new CursorManager(manager.appManager);
|
276
|
-
}
|
266
|
+
manager.cursorManager = new CursorManager(manager.appManager, Boolean(cursor));
|
277
267
|
|
278
268
|
if (params.container) {
|
279
269
|
manager.bindContainer(params.container);
|
@@ -641,6 +631,24 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
|
|
641
631
|
return this.appManager?.mainViewScenesLength || 0;
|
642
632
|
}
|
643
633
|
|
634
|
+
public get canRedoSteps(): number {
|
635
|
+
const focused = this.focused;
|
636
|
+
if (focused) {
|
637
|
+
return this.appManager?.focusApp?.view?.canRedoSteps || 0;
|
638
|
+
} else {
|
639
|
+
return this.mainView.canRedoSteps;
|
640
|
+
}
|
641
|
+
}
|
642
|
+
|
643
|
+
public get canUndoSteps(): number {
|
644
|
+
const focused = this.focused;
|
645
|
+
if (focused) {
|
646
|
+
return this.appManager?.focusApp?.view?.canUndoSteps || 0;
|
647
|
+
} else {
|
648
|
+
return this.mainView.canUndoSteps;
|
649
|
+
}
|
650
|
+
}
|
651
|
+
|
644
652
|
/**
|
645
653
|
* 查询所有的 App
|
646
654
|
*/
|
@@ -749,18 +757,38 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
|
|
749
757
|
this.appManager?.boxManager?.setPrefersColorScheme(scheme);
|
750
758
|
}
|
751
759
|
|
752
|
-
|
753
|
-
const
|
754
|
-
|
760
|
+
public cleanCurrentScene(): void {
|
761
|
+
const focused = this.focused;
|
762
|
+
if (focused) {
|
763
|
+
this.appManager?.focusApp?.view?.cleanCurrentScene();
|
764
|
+
} else {
|
765
|
+
this.mainView.cleanCurrentScene();
|
766
|
+
}
|
755
767
|
}
|
756
768
|
|
757
|
-
|
758
|
-
const
|
759
|
-
if (
|
760
|
-
|
769
|
+
public redo(): void {
|
770
|
+
const focused = this.focused;
|
771
|
+
if (focused) {
|
772
|
+
this.appManager?.focusApp?.view?.redo();
|
773
|
+
} else {
|
774
|
+
this.mainView.redo();
|
761
775
|
}
|
762
776
|
}
|
763
777
|
|
778
|
+
public undo(): void {
|
779
|
+
const focused = this.focused;
|
780
|
+
if (focused) {
|
781
|
+
this.appManager?.focusApp?.view?.undo();
|
782
|
+
} else {
|
783
|
+
this.mainView.undo();
|
784
|
+
}
|
785
|
+
}
|
786
|
+
|
787
|
+
private isDynamicPPT(scenes: SceneDefinition[]) {
|
788
|
+
const sceneSrc = scenes[0]?.ppt?.src;
|
789
|
+
return sceneSrc?.startsWith("pptx://");
|
790
|
+
}
|
791
|
+
|
764
792
|
private async ensureAttributes() {
|
765
793
|
if (isNull(this.attributes)) {
|
766
794
|
await wait(50);
|