@netless/window-manager 1.0.0-canary.9 → 1.0.1

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.
Files changed (132) hide show
  1. package/LICENSE.txt +21 -0
  2. package/README.md +90 -64
  3. package/README.zh-cn.md +224 -0
  4. package/dist/index.d.ts +1133 -40
  5. package/dist/index.js +62 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/{index.es.js → index.mjs} +7954 -5445
  8. package/dist/index.mjs.map +1 -0
  9. package/dist/style.css +1 -1
  10. package/docs/advanced.md +55 -55
  11. package/docs/api.md +126 -113
  12. package/docs/app-context.md +248 -209
  13. package/docs/basic.md +25 -26
  14. package/docs/camera.md +21 -21
  15. package/docs/cn/advanced.md +137 -0
  16. package/docs/cn/api.md +311 -0
  17. package/docs/cn/app-context.md +369 -0
  18. package/docs/cn/basic.md +64 -0
  19. package/docs/cn/camera.md +53 -0
  20. package/docs/cn/concept.md +9 -0
  21. package/docs/cn/custom-max-bar.md +31 -0
  22. package/docs/cn/develop-app.md +94 -0
  23. package/docs/cn/export-pdf.md +48 -0
  24. package/docs/cn/migrate.md +60 -0
  25. package/docs/cn/replay.md +40 -0
  26. package/docs/concept.md +6 -5
  27. package/docs/custom-max-bar.md +31 -0
  28. package/docs/develop-app.md +22 -19
  29. package/docs/export-pdf.md +48 -0
  30. package/docs/migrate.md +25 -27
  31. package/docs/quickstart.md +50 -0
  32. package/docs/replay.md +20 -20
  33. package/package.json +32 -22
  34. package/src/App/AppContext.ts +105 -73
  35. package/src/App/AppPageStateImpl.ts +6 -25
  36. package/src/App/AppProxy.ts +41 -166
  37. package/src/App/MagixEvent/index.ts +38 -38
  38. package/src/App/Storage/StorageEvent.ts +13 -13
  39. package/src/App/Storage/index.ts +269 -245
  40. package/src/App/Storage/typings.ts +4 -2
  41. package/src/App/Storage/utils.ts +3 -3
  42. package/src/App/index.ts +0 -1
  43. package/src/AppListener.ts +8 -8
  44. package/src/AppManager.ts +88 -77
  45. package/src/AttributesDelegate.ts +42 -22
  46. package/src/BoxEmitter.ts +12 -6
  47. package/src/BoxManager.ts +128 -108
  48. package/src/ContainerResizeObserver.ts +75 -0
  49. package/src/Cursor/Cursor.svelte +16 -5
  50. package/src/Cursor/Cursor.svelte.d.ts +21 -0
  51. package/src/Cursor/Cursor.ts +77 -13
  52. package/src/Cursor/icons.ts +6 -0
  53. package/src/Cursor/icons2.ts +66 -0
  54. package/src/Cursor/index.ts +127 -26
  55. package/src/Helper.ts +94 -14
  56. package/src/InternalEmitter.ts +2 -7
  57. package/src/Page/index.ts +1 -1
  58. package/src/PageState.ts +6 -5
  59. package/src/ReconnectRefresher.ts +9 -4
  60. package/src/RedoUndo.ts +3 -3
  61. package/src/Register/index.ts +22 -17
  62. package/src/Register/loader.ts +26 -22
  63. package/src/Register/storage.ts +13 -13
  64. package/src/Utils/Common.ts +18 -14
  65. package/src/Utils/Reactive.ts +26 -25
  66. package/src/Utils/RoomHacker.ts +4 -4
  67. package/src/Utils/error.ts +0 -1
  68. package/src/View/IframeBridge.ts +680 -0
  69. package/src/View/MainView.ts +127 -53
  70. package/src/callback.ts +21 -1
  71. package/src/constants.ts +0 -2
  72. package/src/image/pencil-eraser-1.svg +3 -0
  73. package/src/image/pencil-eraser-2.svg +3 -0
  74. package/src/image/pencil-eraser-3.svg +3 -0
  75. package/src/index.ts +220 -83
  76. package/src/style.css +27 -10
  77. package/src/typings.ts +20 -10
  78. package/.prettierignore +0 -7
  79. package/.prettierrc.json +0 -9
  80. package/CHANGELOG.md +0 -196
  81. package/__mocks__/white-web-sdk.ts +0 -50
  82. package/dist/App/AppContext.d.ts +0 -76
  83. package/dist/App/AppPageStateImpl.d.ts +0 -21
  84. package/dist/App/AppProxy.d.ts +0 -86
  85. package/dist/App/AppViewSync.d.ts +0 -11
  86. package/dist/App/MagixEvent/index.d.ts +0 -29
  87. package/dist/App/Storage/StorageEvent.d.ts +0 -8
  88. package/dist/App/Storage/index.d.ts +0 -39
  89. package/dist/App/Storage/typings.d.ts +0 -22
  90. package/dist/App/Storage/utils.d.ts +0 -5
  91. package/dist/App/WhiteboardView.d.ts +0 -22
  92. package/dist/App/index.d.ts +0 -3
  93. package/dist/AppListener.d.ts +0 -21
  94. package/dist/AppManager.d.ts +0 -107
  95. package/dist/AttributesDelegate.d.ts +0 -80
  96. package/dist/BoxEmitter.d.ts +0 -34
  97. package/dist/BoxManager.d.ts +0 -99
  98. package/dist/BuiltinApps.d.ts +0 -5
  99. package/dist/Cursor/Cursor.d.ts +0 -39
  100. package/dist/Cursor/icons.d.ts +0 -3
  101. package/dist/Cursor/index.d.ts +0 -46
  102. package/dist/Helper.d.ts +0 -17
  103. package/dist/InternalEmitter.d.ts +0 -39
  104. package/dist/Page/PageController.d.ts +0 -21
  105. package/dist/Page/index.d.ts +0 -3
  106. package/dist/PageState.d.ts +0 -9
  107. package/dist/ReconnectRefresher.d.ts +0 -24
  108. package/dist/RedoUndo.d.ts +0 -18
  109. package/dist/Register/index.d.ts +0 -28
  110. package/dist/Register/loader.d.ts +0 -4
  111. package/dist/Register/storage.d.ts +0 -8
  112. package/dist/Utils/AppCreateQueue.d.ts +0 -15
  113. package/dist/Utils/Common.d.ts +0 -23
  114. package/dist/Utils/Reactive.d.ts +0 -6
  115. package/dist/Utils/RoomHacker.d.ts +0 -3
  116. package/dist/Utils/error.d.ts +0 -27
  117. package/dist/Utils/log.d.ts +0 -1
  118. package/dist/View/CameraSynchronizer.d.ts +0 -16
  119. package/dist/View/MainView.d.ts +0 -47
  120. package/dist/View/ViewManager.d.ts +0 -13
  121. package/dist/callback.d.ts +0 -24
  122. package/dist/constants.d.ts +0 -49
  123. package/dist/index.cjs.js +0 -46
  124. package/dist/index.umd.js +0 -46
  125. package/dist/typings.d.ts +0 -82
  126. package/jest.config.js +0 -27
  127. package/pnpm-lock.yaml +0 -6302
  128. package/src/App/AppViewSync.ts +0 -68
  129. package/src/App/WhiteboardView.ts +0 -83
  130. package/src/View/CameraSynchronizer.ts +0 -56
  131. package/vite.config.js +0 -51
  132. /package/docs/{qickstart.md → cn/quickstart.md} +0 -0
package/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 netless
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,214 +1,240 @@
1
1
  # WindowManager
2
2
 
3
- - 目录
4
- - [概念](docs/concept.md)
3
+ [中文](./README.zh-cn.md)
4
+
5
+ `WindowManager` is a window management system based on `white-web-sdk` `InvisiblePlugin` implementation.
6
+
7
+ This application provides the following.
8
+
9
+ 1. provides `NetlessApp` plug-in `API` system
10
+ 2. support `APP` to open as a window
11
+ 3. support application synchronization in each end
12
+ 4. cursor synchronization
13
+ 5. view angle following
14
+
15
+ ## Content list
16
+ - [Install](#Install)
17
+ - [QuickStart](#QuickStart)
18
+ - [concept](docs/concept.md)
5
19
  - [references](docs/api.md)
6
- - [从白板迁移](docs/migrate.md)
7
- - [回放](docs/replay.md)
8
- - [进阶使用](docs/advanced.md)
9
- - [视角跟随](docs/advanced.md#view-mode)
10
- - [开发自定义 APP](docs/develop-app.md)
11
- ## MainView
20
+ - [migration from whiteboard](docs/migrate.md)
21
+ - [replay](docs/replay.md)
22
+ - [advanced use](docs/advanced.md)
23
+ - [view-follow](docs/advanced.md#view-mode)
24
+ - [Develop custom APP](docs/develop-app.md)
25
+ - [Export PDF](docs/export-pdf.md)
12
26
 
13
- `MainView` 也就是主白板, 是垫在所有窗口下面的主白板
27
+ ## Install
14
28
 
15
- 因为多窗口的原因,所以抽象出来一个主白板, 并且把以前部分对 `room` 的操作, 迁移到对 `mainView` 操作
29
+ pnpm
30
+ ```sh
31
+ $ pnpm install @netless/window-manager
32
+ ```
33
+ yarn
34
+ ```sh
35
+ $ yarn install @netless/window-manager
36
+ ```
16
37
 
17
- ### 快速开始
38
+ ## QuickStart
18
39
 
19
40
  ```javascript
20
- import { WhiteWebSdk } from "white-web-sdk";
41
+ import { White-WebSdk } from "white-web-sdk";
21
42
  import { WindowManager, BuiltinApps } from "@netless/window-manager";
22
43
  import "@netless/window-manager/dist/style.css";
23
44
 
24
45
  const sdk = new WhiteWebSdk({
25
46
  appIdentifier: "appIdentifier",
26
- useMobXState: true // 请确保打开这个选项
47
+ useMobXState: true // make sure this option is turned on
27
48
  });
28
49
 
29
50
  sdk.joinRoom({
30
51
  uuid: "room uuid",
31
52
  roomToken: "room token",
32
53
  invisiblePlugins: [WindowManager],
33
- useMultiViews: true, // 多窗口必须用开启 useMultiViews
34
- disableMagixEventDispatchLimit: true, // 请确保打开这个选项
54
+ useMultiViews: true, // Multi-window must be enabled with useMultiViews
55
+ disableMagixEventDispatchLimit: true, // Make sure this option is turned on
35
56
  }).then(async room => {
36
57
  const manager = await WindowManager.mount(
37
58
  room,
38
59
  container
39
- // 完整配置见下方
60
+ // See below for full configuration
40
61
  );
41
62
  });
42
63
  ```
43
64
 
44
- [mount 完整参数](docs/api.md#mount)
65
+ [mount full parameter](docs/api.md#mount)
45
66
 
67
+ > ``containerSizeRatio`` In order to ensure that the window is displayed at different resolutions, the whiteboard can only be synchronized in the same scale area
68
+
69
+
70
+ ## MainView
71
+
72
+ `MainView`, the main whiteboard, is the main whiteboard that sits underneath all windows.
73
+
74
+ Because of the multiple windows, we abstracted out a main whiteboard, and migrated some of the previous operations on `room` to `mainView` operations
46
75
 
47
- > `containerSizeRatio` 为了保证窗口在不同分辨率下显示效果, 白板在相同的比例区域才能进行同步
48
76
 
49
- > `chessboard` 当挂载的区域不完全符合比例时, 白板会在挂载的 dom 中划分一个符合比例的区域出来, 此时多出来的部分会默认显示为棋盘透明背景
50
77
 
51
78
  ### `collector`
52
79
 
53
- > `collector` 就是窗口最小化时的图标, 默认大小 `width: 40px;` `height: 40px;`
80
+ > `collector` is the icon when the window is minimized, default size `width: 40px;` `height: 40px;`
54
81
 
55
82
 
56
- ### 光标同步
83
+ ### Cursor synchronization
57
84
 
58
- > 原本的 `SDK` 中的 `cursorAdapter` 在多窗口中不可用, 如需要光标同步功能需要在 `manager` 中开启 `cursor` 选项
85
+ > The original `cursorAdapter` in `SDK` is not available in multi-window, if you need cursor synchronization, you need to enable `cursor` option in `manager`.
59
86
 
60
87
  ```typescript
61
88
  sdk.joinRoom({
62
- // cursorAdapter: cursorAdapter, 原本开启 sdk 中的 cursorAdapter 需要关闭
89
+ // cursorAdapter: cursorAdapter, the original cursorAdapter in sdk needs to be turned off
63
90
  userPayload: {
64
- userId: "用户 id",
65
- cursorName: "光标名称",
66
- avatar: "用户头像链接",
91
+ nickName: "cursor name",
92
+ avatar: "User avatar link",
67
93
  },
68
94
  });
69
95
 
70
96
  WindowManager.mount({
71
- cursor: true, // 开启光标同步
97
+ cursor: true, // turn on cursor synchronization
72
98
  });
73
99
  ```
74
100
 
75
101
  ## APP
76
102
 
77
- 静态和动态 PPT 是作为 `App` 插入到白板, 并持久化到白板中
103
+ Static and dynamic PPTs are inserted into the whiteboard as `App`, and persisted to the whiteboard
78
104
 
79
- `App` 或会在页面刷新时自动创建出来, 不需要重复插入
105
+ `App` may be created automatically when the page is refreshed, no need to insert it repeatedly
80
106
 
81
- 如果 `App` 需要 `scenePath` 时,那么一个 `scenePath` 只能同时打开一个,要求为 `App` 实例唯一
107
+ If the `App` requires a `scenePath`, then a `scenePath` can only be opened at the same time, requiring a unique `App` instance
82
108
 
83
- ### 添加静态/动态 PPT 到白板上
109
+ ### Add static/dynamic PPT to whiteboard
84
110
 
85
111
  ```javascript
86
112
  const appId = await manager.addApp({
87
113
  kind: BuiltinApps.DocsViewer,
88
114
  options: {
89
115
  scenePath: "/docs-viewer",
90
- title: "docs1", // 可选
91
- scenes: [], // SceneDefinition[] 静态/动态 Scene 数据
116
+ title: "docs1", // optional
117
+ scenes: [], // SceneDefinition[] Static/Dynamic Scene data
92
118
  },
93
119
  });
94
120
  ```
95
121
 
96
- ### 添加音视频到白板
122
+ ### Add audio and video to the whiteboard
97
123
 
98
124
  ```javascript
99
125
  const appId = await manager.addApp({
100
126
  kind: BuiltinApps.MediaPlayer,
101
127
  options: {
102
- title: "test.mp3", // 可选
128
+ title: "test.mp3", // optional
103
129
  },
104
130
  attributes: {
105
- src: "xxxx", // 音视频 url
131
+ src: "xxxx", // audio/video url
106
132
  },
107
133
  });
108
134
  ```
109
135
 
110
- ### 设置跟随模式
136
+ ### Set follow mode
111
137
 
112
- 只有广播端也就是老师需要设置跟随模式, 其他端的主白板都会跟随广播端的视角
138
+ Only the broadcast side, i.e. the teacher, needs to set the follow mode, the other side of the main whiteboard will follow the view of the broadcast side
113
139
 
114
- > 注意 `manager` `setViewMode` 不能和 `room.setViewMode` 同时使用
140
+ > Note that `manager`'s `setViewMode` cannot be used at the same time as `room.setViewMode`.
115
141
 
116
142
  ```javascript
117
- manager.setViewMode("broadcaster"); // 开启跟随模式
118
- manager.setViewMode("freedom"); // 关闭跟随模式
143
+ manager.setViewMode("broadcaster"); // turn on follow mode
144
+ manager.setViewMode("freedom"); // turn off follow mode
119
145
  ```
120
146
 
121
- 获取当前的 `broadcaster` ID
147
+ Get the current `broadcaster` ID
122
148
  ```javascript
123
149
  manager.broadcaster
124
150
  ```
125
151
 
126
- ### 设置所有 `app` `readonly`
152
+ ### Set `readonly` for all `app`s
127
153
 
128
154
  ```javascript
129
- manager.setReadonly(true); // 所有窗口变成 readonly 状态
130
- manager.setReadonly(false); // 解锁设置的 readonly, 注意如果当前白板的 isWritable false 以白板的状态为最高优先级
155
+ manager.setReadonly(true); // all windows become readonly
156
+ manager.setReadonly(false); // unlock the readonly setting, note that if the current whiteboard isWritable is false, the whiteboard's state is the highest priority
131
157
  ```
132
158
 
133
- ### 切换 `mainView` 为可写状态
159
+ ### Toggle `mainView` to writable state
134
160
 
135
161
  ```javascript
136
162
  manager.switchMainViewToWriter();
137
163
  ```
138
164
 
139
- ### 切换 `mainView` `scenePath`
165
+ ### Switch `mainView` `scenePath`
140
166
 
141
- 切换主白板的 `ScenePath` 并把主白板设置为可写状态
167
+ Switch the `ScenePath` of the main whiteboard and set the main whiteboard to writable state
142
168
 
143
169
  ```javascript
144
170
  manager.setMainViewScenePath(scenePath);
145
171
  ```
146
172
 
147
- ### 切换 `mainView` `sceneIndex`
173
+ ### toggle `mainView` `sceneIndex`
148
174
 
149
- 切换主白板的 `SceneIndex` 并把主白板设置为可写状态
175
+ Toggles the `SceneIndex` of the main whiteboard and sets the main whiteboard to writable state
150
176
 
151
177
  ```javascript
152
178
  manager.setMainViewSceneIndex(sceneIndex);
153
179
  ```
154
180
 
155
- ### 获取 `mainView` `scenePath`
181
+ ### Get the `mainView` `scenePath`
156
182
 
157
183
  ```javascript
158
184
  manager.getMainViewScenePath();
159
185
  ```
160
186
 
161
- ### 获取 `mainView` `sceneIndex`
187
+ ### Get `mainView` `sceneIndex`
162
188
 
163
189
  ```javascript
164
190
  manager.getMainViewSceneIndex();
165
191
  ```
166
192
 
167
- ### 监听 `mainView` `mode`
193
+ ### Listen to the `mainView` `mode`
168
194
 
169
195
  ```javascript
170
196
  manager.emitter.on("mainViewModeChange", mode => {
171
- // mode 类型为 ViewVisionMode
197
+ // mode type is ViewVisionMode
172
198
  });
173
199
  ```
174
200
 
175
- ### 监听窗口最大化最小化
201
+ ### Listening for window maximization and minimization
176
202
 
177
203
  ```javascript
178
204
  manager.emitter.on("boxStateChange", state => {
179
205
  if (state === "maximized") {
180
- // 最大化
206
+ // maximize
181
207
  }
182
208
  if (state === "minimized") {
183
- // 最小化
209
+ // minimized
184
210
  }
185
211
  if (state === "normal") {
186
- // 恢复正常
212
+ // return to normal
187
213
  }
188
214
  });
189
215
  ```
190
216
 
191
- ### 监听 `broadcaster` 变化
217
+ ### Listening for `broadcaster` changes
192
218
  ```javascript
193
219
  manager.emitter.on("broadcastChange", id => {
194
- // broadcast id 进行了改变
220
+ // broadcast id changed
195
221
  })
196
222
 
197
223
  ```
198
224
 
199
- ### 关闭 `App`
225
+ ### Close the `App`
200
226
 
201
227
  ```javascript
202
228
  manager.closeApp(appId);
203
229
  ```
204
230
 
205
- ## 手动销毁 `WindowManager`
231
+ ## Manually destroy `WindowManager`
206
232
 
207
233
  ```javascript
208
234
  manager.destroy();
209
235
  ```
210
236
 
211
- ## 开发流程
237
+ ## Development process
212
238
 
213
239
  ```bash
214
240
  pnpm install
@@ -220,4 +246,4 @@ cd example
220
246
  pnpm install
221
247
 
222
248
  pnpm dev
223
- ```
249
+ ```
@@ -0,0 +1,224 @@
1
+ # WindowManager
2
+
3
+ - 目录
4
+ - [概念](docs/concept.md)
5
+ - [references](docs/api.md)
6
+ - [从白板迁移](docs/migrate.md)
7
+ - [回放](docs/replay.md)
8
+ - [进阶使用](docs/advanced.md)
9
+ - [视角跟随](docs/advanced.md#view-mode)
10
+ - [开发自定义 APP](docs/develop-app.md)
11
+ - [导出 PDF](docs/export-pdf.md)
12
+ - [Changelog](./CHANGELOG.md)
13
+ ## MainView
14
+
15
+ `MainView` 也就是主白板, 是垫在所有窗口下面的主白板
16
+
17
+ 因为多窗口的原因,所以抽象出来一个主白板, 并且把以前部分对 `room` 的操作, 迁移到对 `mainView` 操作
18
+
19
+ ### 快速开始
20
+
21
+ ```javascript
22
+ import { WhiteWebSdk } from "white-web-sdk";
23
+ import { WindowManager, BuiltinApps } from "@netless/window-manager";
24
+ import "@netless/window-manager/dist/style.css";
25
+
26
+ const sdk = new WhiteWebSdk({
27
+ appIdentifier: "appIdentifier",
28
+ useMobXState: true // 请确保打开这个选项
29
+ });
30
+
31
+ sdk.joinRoom({
32
+ uuid: "room uuid",
33
+ roomToken: "room token",
34
+ invisiblePlugins: [WindowManager],
35
+ useMultiViews: true, // 多窗口必须用开启 useMultiViews
36
+ disableMagixEventDispatchLimit: true, // 请确保打开这个选项
37
+ }).then(async room => {
38
+ const manager = await WindowManager.mount(
39
+ room,
40
+ container
41
+ // 完整配置见下方
42
+ );
43
+ });
44
+ ```
45
+
46
+ [mount 完整参数](docs/api.md#mount)
47
+
48
+
49
+ > `containerSizeRatio` 为了保证窗口在不同分辨率下显示效果, 白板在相同的比例区域才能进行同步
50
+
51
+ > `chessboard` 当挂载的区域不完全符合比例时, 白板会在挂载的 dom 中划分一个符合比例的区域出来, 此时多出来的部分会默认显示为棋盘透明背景
52
+
53
+ ### `collector`
54
+
55
+ > `collector` 就是窗口最小化时的图标, 默认大小 `width: 40px;` `height: 40px;`
56
+
57
+
58
+ ### 光标同步
59
+
60
+ > 原本的 `SDK` 中的 `cursorAdapter` 在多窗口中不可用, 如需要光标同步功能需要在 `manager` 中开启 `cursor` 选项
61
+
62
+ ```typescript
63
+ sdk.joinRoom({
64
+ // cursorAdapter: cursorAdapter, 原本开启 sdk 中的 cursorAdapter 需要关闭
65
+ userPayload: {
66
+ nickName: "光标名称",
67
+ avatar: "用户头像链接",
68
+ },
69
+ });
70
+
71
+ WindowManager.mount({
72
+ cursor: true, // 开启光标同步
73
+ });
74
+ ```
75
+
76
+ ## APP
77
+
78
+ 静态和动态 PPT 是作为 `App` 插入到白板, 并持久化到白板中
79
+
80
+ `App` 或会在页面刷新时自动创建出来, 不需要重复插入
81
+
82
+ 如果 `App` 需要 `scenePath` 时,那么一个 `scenePath` 只能同时打开一个,要求为 `App` 实例唯一
83
+
84
+ ### 添加静态/动态 PPT 到白板上
85
+
86
+ ```javascript
87
+ const appId = await manager.addApp({
88
+ kind: BuiltinApps.DocsViewer,
89
+ options: {
90
+ scenePath: "/docs-viewer",
91
+ title: "docs1", // 可选
92
+ scenes: [], // SceneDefinition[] 静态/动态 Scene 数据
93
+ },
94
+ });
95
+ ```
96
+
97
+ ### 添加音视频到白板
98
+
99
+ ```javascript
100
+ const appId = await manager.addApp({
101
+ kind: BuiltinApps.MediaPlayer,
102
+ options: {
103
+ title: "test.mp3", // 可选
104
+ },
105
+ attributes: {
106
+ src: "xxxx", // 音视频 url
107
+ },
108
+ });
109
+ ```
110
+
111
+ ### 设置跟随模式
112
+
113
+ 只有广播端也就是老师需要设置跟随模式, 其他端的主白板都会跟随广播端的视角
114
+
115
+ > 注意 `manager` 的 `setViewMode` 不能和 `room.setViewMode` 同时使用
116
+
117
+ ```javascript
118
+ manager.setViewMode("broadcaster"); // 开启跟随模式
119
+ manager.setViewMode("freedom"); // 关闭跟随模式
120
+ ```
121
+
122
+ 获取当前的 `broadcaster` ID
123
+ ```javascript
124
+ manager.broadcaster
125
+ ```
126
+
127
+ ### 设置所有 `app` 的 `readonly`
128
+
129
+ ```javascript
130
+ manager.setReadonly(true); // 所有窗口变成 readonly 状态
131
+ manager.setReadonly(false); // 解锁设置的 readonly, 注意如果当前白板的 isWritable 为 false 以白板的状态为最高优先级
132
+ ```
133
+
134
+ ### 切换 `mainView` 为可写状态
135
+
136
+ ```javascript
137
+ manager.switchMainViewToWriter();
138
+ ```
139
+
140
+ ### 切换 `mainView` `scenePath`
141
+
142
+ 切换主白板的 `ScenePath` 并把主白板设置为可写状态
143
+
144
+ ```javascript
145
+ manager.setMainViewScenePath(scenePath);
146
+ ```
147
+
148
+ ### 切换 `mainView` `sceneIndex`
149
+
150
+ 切换主白板的 `SceneIndex` 并把主白板设置为可写状态
151
+
152
+ ```javascript
153
+ manager.setMainViewSceneIndex(sceneIndex);
154
+ ```
155
+
156
+ ### 获取 `mainView` `scenePath`
157
+
158
+ ```javascript
159
+ manager.getMainViewScenePath();
160
+ ```
161
+
162
+ ### 获取 `mainView` `sceneIndex`
163
+
164
+ ```javascript
165
+ manager.getMainViewSceneIndex();
166
+ ```
167
+
168
+ ### 监听 `mainView` 的 `mode`
169
+
170
+ ```javascript
171
+ manager.emitter.on("mainViewModeChange", mode => {
172
+ // mode 类型为 ViewVisionMode
173
+ });
174
+ ```
175
+
176
+ ### 监听窗口最大化最小化
177
+
178
+ ```javascript
179
+ manager.emitter.on("boxStateChange", state => {
180
+ if (state === "maximized") {
181
+ // 最大化
182
+ }
183
+ if (state === "minimized") {
184
+ // 最小化
185
+ }
186
+ if (state === "normal") {
187
+ // 恢复正常
188
+ }
189
+ });
190
+ ```
191
+
192
+ ### 监听 `broadcaster` 变化
193
+ ```javascript
194
+ manager.emitter.on("broadcastChange", id => {
195
+ // broadcast id 进行了改变
196
+ })
197
+
198
+ ```
199
+
200
+ ### 关闭 `App`
201
+
202
+ ```javascript
203
+ manager.closeApp(appId);
204
+ ```
205
+
206
+ ## 手动销毁 `WindowManager`
207
+
208
+ ```javascript
209
+ manager.destroy();
210
+ ```
211
+
212
+ ## 开发流程
213
+
214
+ ```bash
215
+ pnpm install
216
+
217
+ pnpm build
218
+
219
+ cd example
220
+
221
+ pnpm install
222
+
223
+ pnpm dev
224
+ ```