@netless/window-manager 0.4.0-canary.28 → 0.4.0-canary.31
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 +7 -2
- package/dist/Cursor/Cursor.d.ts +2 -1
- package/dist/Cursor/index.d.ts +2 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.es.js +5 -5
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +5 -5
- package/dist/index.umd.js.map +1 -1
- package/docs/api.md +31 -9
- package/docs/replay.md +40 -0
- package/package.json +2 -2
- package/src/AppContext.ts +4 -1
- package/src/AppManager.ts +60 -2
- 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/Utils/RoomHacker.ts +1 -1
- package/src/image/laser-pointer-cursor.svg +17 -0
- package/src/index.ts +39 -4
package/docs/api.md
CHANGED
@@ -12,6 +12,8 @@
|
|
12
12
|
- [`setMainViewSceneIndex`](#setMainViewSceneIndex)
|
13
13
|
- [`setBoxState`](#setBoxState)
|
14
14
|
- [`cleanCurrentScene`](#cleanCurrentScene)
|
15
|
+
- [`redo`](#redo)
|
16
|
+
- [`undo`](#undo)
|
15
17
|
- [实例属性](#prototypes)
|
16
18
|
- [事件回调](#events)
|
17
19
|
|
@@ -137,19 +139,37 @@ manager.setBoxState("normal") // boxState: normal | maximized | minimized
|
|
137
139
|
manager.cleanCurrentScene()
|
138
140
|
```
|
139
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
|
+
|
140
158
|
<br>
|
141
159
|
|
142
160
|
<h2 id="prototypes">实例属性</h2>
|
143
161
|
|
144
|
-
| name | type | default | desc
|
145
|
-
| ------------------ | ------- | ------- | -----------------
|
146
|
-
| mainView | View | | 主白板
|
147
|
-
| mainViewSceneIndex | number | | 当前主白板的 SceneIndex
|
162
|
+
| name | type | default | desc |
|
163
|
+
| ------------------ | ------- | ------- | ----------------- |
|
164
|
+
| mainView | View | | 主白板 |
|
165
|
+
| mainViewSceneIndex | number | | 当前主白板的 SceneIndex |
|
148
166
|
| mainViewScenesLength | number | | mainView 的 scenes 长度 |
|
149
|
-
| boxState | string | | 当前窗口状态
|
150
|
-
| darkMode | boolean | | 黑夜模式
|
151
|
-
| prefersColorScheme | string | | 颜色主题
|
152
|
-
| 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 可以撤销的步数 |
|
153
173
|
|
154
174
|
<br>
|
155
175
|
|
@@ -168,4 +188,6 @@ manager.callbacks.on(events, listener)
|
|
168
188
|
| prefersColorSchemeChange | string | | auto,light,dark |
|
169
189
|
| cameraStateChange | CameraState | | |
|
170
190
|
| focusedChange | string, undefined | | 当前 focus 的 appId,主白板时为 undefined |
|
171
|
-
| 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.31",
|
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
|
*
|
@@ -591,6 +647,8 @@ export class AppManager {
|
|
591
647
|
callbacks.clearListeners();
|
592
648
|
this.callbacksNode?.dispose();
|
593
649
|
this.appCreateQueue.destroy();
|
650
|
+
this.disposePrevFocusViewRedoUndoListeners(this._prevFocused);
|
651
|
+
this._prevFocused = undefined;
|
594
652
|
this._prevSceneIndex = undefined;
|
595
653
|
}
|
596
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/Utils/RoomHacker.ts
CHANGED
@@ -43,7 +43,7 @@ export const replaceRoomFunction = (room: Room | Player, manager: WindowManager)
|
|
43
43
|
room.setMemberState = (...args) => manager.mainView.setMemberState(...args);
|
44
44
|
room.redo = () => manager.mainView.redo();
|
45
45
|
room.undo = () => manager.mainView.undo();
|
46
|
-
room.cleanCurrentScene = () => manager.
|
46
|
+
room.cleanCurrentScene = () => manager.cleanCurrentScene();
|
47
47
|
delegateRemoveScenes(room);
|
48
48
|
}
|
49
49
|
};
|
@@ -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
@@ -150,6 +150,8 @@ export type PublicEvent = {
|
|
150
150
|
mainViewSceneIndexChange: number;
|
151
151
|
focusedChange: string | undefined;
|
152
152
|
mainViewScenesLengthChange: number;
|
153
|
+
canRedoStepsChange: number;
|
154
|
+
canUndoStepsChange: number;
|
153
155
|
};
|
154
156
|
|
155
157
|
export type MountParams = {
|
@@ -261,10 +263,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
|
|
261
263
|
await manager.ensureAttributes();
|
262
264
|
|
263
265
|
manager.appManager = new AppManager(manager);
|
264
|
-
|
265
|
-
if (cursor) {
|
266
|
-
manager.cursorManager = new CursorManager(manager.appManager);
|
267
|
-
}
|
266
|
+
manager.cursorManager = new CursorManager(manager.appManager, Boolean(cursor));
|
268
267
|
|
269
268
|
if (params.container) {
|
270
269
|
manager.bindContainer(params.container);
|
@@ -632,6 +631,24 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
|
|
632
631
|
return this.appManager?.mainViewScenesLength || 0;
|
633
632
|
}
|
634
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
|
+
|
635
652
|
/**
|
636
653
|
* 查询所有的 App
|
637
654
|
*/
|
@@ -749,6 +766,24 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
|
|
749
766
|
}
|
750
767
|
}
|
751
768
|
|
769
|
+
public redo(): void {
|
770
|
+
const focused = this.focused;
|
771
|
+
if (focused) {
|
772
|
+
this.appManager?.focusApp?.view?.redo();
|
773
|
+
} else {
|
774
|
+
this.mainView.redo();
|
775
|
+
}
|
776
|
+
}
|
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
|
+
|
752
787
|
private isDynamicPPT(scenes: SceneDefinition[]) {
|
753
788
|
const sceneSrc = scenes[0]?.ppt?.src;
|
754
789
|
return sceneSrc?.startsWith("pptx://");
|