@netless/fastboard-core 0.3.6 → 1.0.0-canary.2
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/README.md +61 -0
- package/dist/index.d.ts +174 -200
- package/dist/index.js +364 -498
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +344 -440
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -8
- package/src/FastboardApp.ts +631 -0
- package/src/FastboardPlayer.ts +240 -0
- package/src/helpers.ts +57 -0
- package/src/index.ts +11 -3
- package/src/store.ts +83 -0
- package/src/typings.ts +42 -0
- package/src/behaviors/index.ts +0 -62
- package/src/impl/FastboardApp.ts +0 -637
- package/src/impl/FastboardPlayer.ts +0 -251
- package/src/impl/index.ts +0 -2
- package/src/internal.ts +0 -16
- package/src/utils/index.ts +0 -4
- package/src/utils/misc.ts +0 -49
- package/src/utils/store.ts +0 -87
- package/src/utils/uid.ts +0 -12
- package/src/utils/warn.ts +0 -11
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import type { Disposer, Readable, StartStopNotifier, Writable } from "./store";
|
|
2
|
+
import type {
|
|
3
|
+
MountParams,
|
|
4
|
+
NetlessApp,
|
|
5
|
+
Player,
|
|
6
|
+
PlayerCallbacks,
|
|
7
|
+
PlayerPhase,
|
|
8
|
+
PlayerSeekingResult,
|
|
9
|
+
PlayerState,
|
|
10
|
+
ReplayRoomParams,
|
|
11
|
+
SyncedStore,
|
|
12
|
+
WhiteWebSdkConfiguration,
|
|
13
|
+
} from "./typings";
|
|
14
|
+
|
|
15
|
+
import { WhiteWebSdk } from "white-web-sdk";
|
|
16
|
+
import { WindowManager } from "@netless/window-manager";
|
|
17
|
+
|
|
18
|
+
import { addPlayerListener, ensureOfficialPlugins } from "./helpers";
|
|
19
|
+
import { createVal } from "./store";
|
|
20
|
+
import { SyncedStorePlugin } from "@netless/synced-store";
|
|
21
|
+
|
|
22
|
+
// The inheritance is for simplifying the code, so that we can use
|
|
23
|
+
// `prop = f(this.player)` directly in its child class.
|
|
24
|
+
class FastboardPlayerStruct<TEventData> {
|
|
25
|
+
// Intensionally not class-field to prevent `__publicField` usage.
|
|
26
|
+
protected declare _disposers: Disposer[];
|
|
27
|
+
protected declare _destroyed: boolean;
|
|
28
|
+
protected _assertNotDestroyed() {
|
|
29
|
+
if (this._destroyed) {
|
|
30
|
+
throw new Error("FastboardPlayer has been destroyed");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
protected _flushAllDisposers() {
|
|
34
|
+
this._disposers.forEach(disposer => disposer());
|
|
35
|
+
this._disposers = [];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
constructor(
|
|
39
|
+
readonly sdk: WhiteWebSdk,
|
|
40
|
+
readonly player: Player,
|
|
41
|
+
readonly manager: WindowManager,
|
|
42
|
+
readonly syncedStore: SyncedStore<TEventData>
|
|
43
|
+
) {
|
|
44
|
+
this._disposers = [];
|
|
45
|
+
this._destroyed = false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** @internal */
|
|
49
|
+
protected _val<T>(init: T, start: StartStopNotifier<T>): Readable<T>;
|
|
50
|
+
/** @internal */
|
|
51
|
+
protected _val<T>(init: T, start: StartStopNotifier<T>, setter: (value: T) => void): Writable<T>;
|
|
52
|
+
protected _val<T>(init: T, start: StartStopNotifier<T>, setter?: (value: T) => void) {
|
|
53
|
+
const val = createVal(init, start, setter as (value: T) => void);
|
|
54
|
+
this._disposers.push(val.dispose.bind(val));
|
|
55
|
+
return val;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export class FastboardPlayer<TEventData = any> extends FastboardPlayerStruct<TEventData> {
|
|
60
|
+
constructor(
|
|
61
|
+
sdk: WhiteWebSdk,
|
|
62
|
+
player: Player,
|
|
63
|
+
manager: WindowManager,
|
|
64
|
+
syncedStore: SyncedStore<TEventData>
|
|
65
|
+
) {
|
|
66
|
+
super(sdk, player, manager, syncedStore);
|
|
67
|
+
|
|
68
|
+
// Guard `app.destroy()` so that network errors won't break fastboard.
|
|
69
|
+
this._disposers.push(
|
|
70
|
+
addPlayerListener(this.player, "onStoppedWithError", error => {
|
|
71
|
+
console.warn("FastboardPlayer was stopped with error.");
|
|
72
|
+
console.error(error);
|
|
73
|
+
})
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Disconnect from whiteboard room.
|
|
79
|
+
*/
|
|
80
|
+
destroy() {
|
|
81
|
+
if (this._destroyed) return;
|
|
82
|
+
this._destroyed = true;
|
|
83
|
+
this._flushAllDisposers();
|
|
84
|
+
this.manager.destroy();
|
|
85
|
+
this.player.callbacks.off();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Render this app to some DOM.
|
|
90
|
+
*/
|
|
91
|
+
bindContainer(container: HTMLElement) {
|
|
92
|
+
this._assertNotDestroyed();
|
|
93
|
+
this.manager.bindContainer(container);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Move window manager's collector to some place.
|
|
98
|
+
*/
|
|
99
|
+
bindCollector(container: HTMLElement) {
|
|
100
|
+
this._assertNotDestroyed();
|
|
101
|
+
this.manager.bindCollectorContainer(container);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Player current time in milliseconds.
|
|
106
|
+
*/
|
|
107
|
+
readonly currentTime = this._val(
|
|
108
|
+
this.player.progressTime,
|
|
109
|
+
set => addPlayerListener(this.player, "onProgressTimeChanged", set),
|
|
110
|
+
time => this.player.seekToProgressTime(time)
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Player state, like "is it playing?".
|
|
115
|
+
*/
|
|
116
|
+
readonly phase = this._val<PlayerPhase>(this.player.phase, set =>
|
|
117
|
+
addPlayerListener(this.player, "onPhaseChanged", set)
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Will become true after buffering.
|
|
122
|
+
*/
|
|
123
|
+
readonly canplay = this._val(this.player.isPlayable, set =>
|
|
124
|
+
addPlayerListener(this.player, "onIsPlayableChanged", set)
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
/** @internal */
|
|
128
|
+
private _setPlaybackRate!: (value: number) => void;
|
|
129
|
+
/**
|
|
130
|
+
* Playback speed, default `1`.
|
|
131
|
+
*/
|
|
132
|
+
readonly playbackRate = this._val(
|
|
133
|
+
this.player.playbackSpeed,
|
|
134
|
+
set => {
|
|
135
|
+
this._setPlaybackRate = set;
|
|
136
|
+
},
|
|
137
|
+
speed => this._setPlaybackRate((this.player.playbackSpeed = speed))
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Playback duration in milliseconds.
|
|
142
|
+
*/
|
|
143
|
+
readonly duration = this._val(this.player.timeDuration, _set => {});
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Get state of room at current time.
|
|
147
|
+
*/
|
|
148
|
+
readonly state = this._val<PlayerState>(this.player.state, set =>
|
|
149
|
+
addPlayerListener(this.player, "onPlayerStateChanged", () => set(this.player.state))
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Seek to some time in milliseconds.
|
|
154
|
+
*/
|
|
155
|
+
seek(timestamp: number): Promise<PlayerSeekingResult> {
|
|
156
|
+
this._assertNotDestroyed();
|
|
157
|
+
return this.player.seekToProgressTime(timestamp);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Change player state to playing.
|
|
162
|
+
*/
|
|
163
|
+
play() {
|
|
164
|
+
this.player.play();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Change player state to paused.
|
|
169
|
+
*/
|
|
170
|
+
pause() {
|
|
171
|
+
this._assertNotDestroyed();
|
|
172
|
+
this.player.pause();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Change player state to stopped.
|
|
177
|
+
*/
|
|
178
|
+
stop() {
|
|
179
|
+
this._assertNotDestroyed();
|
|
180
|
+
this.player.stop();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Set playback speed, the same as `player.playbackRate.set(x)`.
|
|
185
|
+
*/
|
|
186
|
+
setPlaybackRate(value: number) {
|
|
187
|
+
this._assertNotDestroyed();
|
|
188
|
+
this.playbackRate.set(value);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export interface FastboardReplayOptions {
|
|
193
|
+
sdkConfig: Omit<WhiteWebSdkConfiguration, "useMobXState"> & {
|
|
194
|
+
region: NonNullable<WhiteWebSdkConfiguration["region"]>;
|
|
195
|
+
};
|
|
196
|
+
replayRoom: Omit<ReplayRoomParams, "useMultiViews"> & {
|
|
197
|
+
callbacks?: Partial<PlayerCallbacks>;
|
|
198
|
+
};
|
|
199
|
+
managerConfig?: Omit<MountParams, "room">;
|
|
200
|
+
netlessApps?: NetlessApp[];
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export async function replayFastboardCore<TEventData = any>({
|
|
204
|
+
sdkConfig,
|
|
205
|
+
replayRoom: { callbacks, ...replayRoomParams },
|
|
206
|
+
managerConfig,
|
|
207
|
+
netlessApps,
|
|
208
|
+
}: FastboardReplayOptions) {
|
|
209
|
+
const sdk = new WhiteWebSdk({
|
|
210
|
+
...sdkConfig,
|
|
211
|
+
useMobXState: true,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
if (netlessApps) {
|
|
215
|
+
netlessApps.forEach(app => WindowManager.register({ kind: app.kind, src: app }));
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const player = await sdk.replayRoom(
|
|
219
|
+
{
|
|
220
|
+
...ensureOfficialPlugins(replayRoomParams),
|
|
221
|
+
useMultiViews: true,
|
|
222
|
+
},
|
|
223
|
+
callbacks
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
const syncedStore = await SyncedStorePlugin.init<TEventData>(player);
|
|
227
|
+
|
|
228
|
+
const managerPromise = WindowManager.mount({
|
|
229
|
+
cursor: true,
|
|
230
|
+
...managerConfig,
|
|
231
|
+
room: player,
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
player.play();
|
|
235
|
+
const manager = await managerPromise;
|
|
236
|
+
player.pause();
|
|
237
|
+
await player.seekToProgressTime(0);
|
|
238
|
+
|
|
239
|
+
return new FastboardPlayer<TEventData>(sdk, player, manager, syncedStore);
|
|
240
|
+
}
|
package/src/helpers.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { SyncedStorePlugin } from "@netless/synced-store";
|
|
2
|
+
import { WindowManager } from "@netless/window-manager";
|
|
3
|
+
|
|
4
|
+
import type {
|
|
5
|
+
JoinRoomParams,
|
|
6
|
+
Player,
|
|
7
|
+
PlayerCallbacks,
|
|
8
|
+
PublicEvent,
|
|
9
|
+
ReplayRoomParams,
|
|
10
|
+
Room,
|
|
11
|
+
RoomCallbacks,
|
|
12
|
+
View,
|
|
13
|
+
ViewCallbacks,
|
|
14
|
+
} from "./typings";
|
|
15
|
+
|
|
16
|
+
export function addRoomListener<K extends keyof RoomCallbacks>(
|
|
17
|
+
room: Room,
|
|
18
|
+
name: K,
|
|
19
|
+
listener: RoomCallbacks[K]
|
|
20
|
+
): () => void {
|
|
21
|
+
room.callbacks.on(name, listener);
|
|
22
|
+
return () => room.callbacks.off(name, listener);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function addPlayerListener<K extends keyof PlayerCallbacks>(
|
|
26
|
+
player: Player,
|
|
27
|
+
name: K,
|
|
28
|
+
listener: PlayerCallbacks[K]
|
|
29
|
+
): () => void {
|
|
30
|
+
player.callbacks.on(name, listener);
|
|
31
|
+
return () => player.callbacks.off(name, listener);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function addViewListener<K extends keyof ViewCallbacks>(
|
|
35
|
+
view: View,
|
|
36
|
+
name: K,
|
|
37
|
+
listener: (value: ViewCallbacks[K]) => void
|
|
38
|
+
): () => void {
|
|
39
|
+
view.callbacks.on(name, listener);
|
|
40
|
+
return () => view.callbacks.off(name, listener);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function addManagerListener<K extends keyof PublicEvent>(
|
|
44
|
+
manager: WindowManager,
|
|
45
|
+
name: K,
|
|
46
|
+
listener: (value: PublicEvent[K]) => void
|
|
47
|
+
): () => void {
|
|
48
|
+
return manager.emitter.on(name, listener);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function ensureOfficialPlugins<T extends JoinRoomParams | ReplayRoomParams>(joinRoom: T): T {
|
|
52
|
+
const plugins = new Set(joinRoom.invisiblePlugins || []);
|
|
53
|
+
plugins.add(WindowManager);
|
|
54
|
+
plugins.add(SyncedStorePlugin);
|
|
55
|
+
joinRoom.invisiblePlugins = Array.from(plugins);
|
|
56
|
+
return joinRoom;
|
|
57
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
declare const __NAME__: string;
|
|
2
|
+
declare const __VERSION__: string;
|
|
3
|
+
|
|
4
|
+
export const name = __NAME__;
|
|
5
|
+
export const version = __VERSION__;
|
|
6
|
+
|
|
7
|
+
export * from "./typings";
|
|
8
|
+
export * from "./helpers";
|
|
9
|
+
export * from "./store";
|
|
10
|
+
export * from "./FastboardApp";
|
|
11
|
+
export * from "./FastboardPlayer";
|
package/src/store.ts
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export type Subscriber<T> = (value: T) => void;
|
|
2
|
+
export type Updater<T> = (value: T) => T;
|
|
3
|
+
export type Disposer = () => void;
|
|
4
|
+
export type StartStopNotifier<T> = (set: Subscriber<T>) => Disposer | void;
|
|
5
|
+
|
|
6
|
+
export interface Readable<T> {
|
|
7
|
+
readonly value: T;
|
|
8
|
+
readonly subs: Set<Subscriber<T>>;
|
|
9
|
+
subscribe(this: Readable<T>, run: Subscriber<T>): Disposer;
|
|
10
|
+
reaction(this: Readable<T>, run: Subscriber<T>): Disposer;
|
|
11
|
+
dispose(this: Readable<T>): void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface Writable<T> extends Readable<T> {
|
|
15
|
+
set(this: Writable<T>, value: T): void;
|
|
16
|
+
update(this: Writable<T>, updater: Updater<T>): void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function is_function(x: unknown): x is () => void {
|
|
20
|
+
return typeof x === "function";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function safe_not_equal(a: unknown, b: unknown): boolean {
|
|
24
|
+
return a != a ? b == b : a !== b || ((a as boolean) && typeof a === "object") || typeof a === "function";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// This is not svelte/store.
|
|
28
|
+
class Val<T> implements Writable<T> {
|
|
29
|
+
declare value: T;
|
|
30
|
+
declare readonly subs: Set<Subscriber<T>>;
|
|
31
|
+
constructor(value: T) {
|
|
32
|
+
this.value = value;
|
|
33
|
+
this.subs = new Set();
|
|
34
|
+
}
|
|
35
|
+
subscribe(run: Subscriber<T>): Disposer {
|
|
36
|
+
this.subs.add(run);
|
|
37
|
+
run(this.value);
|
|
38
|
+
return () => this.subs.delete(run);
|
|
39
|
+
}
|
|
40
|
+
reaction(run: Subscriber<T>): Disposer {
|
|
41
|
+
this.subs.add(run);
|
|
42
|
+
return () => this.subs.delete(run);
|
|
43
|
+
}
|
|
44
|
+
set(value: T) {
|
|
45
|
+
if (safe_not_equal(this.value, value)) {
|
|
46
|
+
this.value = value;
|
|
47
|
+
this.subs.forEach(sub => sub(value));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
update(updater: Updater<T>) {
|
|
51
|
+
this.set(updater(this.value));
|
|
52
|
+
}
|
|
53
|
+
dispose() {
|
|
54
|
+
this.subs.clear();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* ```js
|
|
60
|
+
* const mediaQuery = matchMedia("(prefers-color-scheme: dark)")
|
|
61
|
+
* const isDark = createVal(mediaQuery.matches, set => {
|
|
62
|
+
* const update = () => set(mediaQuery.matches)
|
|
63
|
+
* mediaQuery.addEventListener("change", update)
|
|
64
|
+
* return () => mediaQuery.removeEventListener("change", update)
|
|
65
|
+
* });
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export function createVal<T>(init: T, start: StartStopNotifier<T>): Readable<T>;
|
|
69
|
+
export function createVal<T>(init: T, start: StartStopNotifier<T>, setter: (value: T) => void): Writable<T>;
|
|
70
|
+
export function createVal<T>(init: T, start: StartStopNotifier<T>, setter?: ((value: T) => void) | null) {
|
|
71
|
+
const val = new Val(init);
|
|
72
|
+
const stop = start(val.set.bind(val));
|
|
73
|
+
if (stop && is_function(stop)) {
|
|
74
|
+
val.dispose = function dispose() {
|
|
75
|
+
this.subs.clear();
|
|
76
|
+
stop();
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
if (setter) {
|
|
80
|
+
val.set = setter;
|
|
81
|
+
}
|
|
82
|
+
return val;
|
|
83
|
+
}
|
package/src/typings.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ApplianceNames } from "white-web-sdk";
|
|
2
|
+
|
|
3
|
+
export type { Diff, DiffOne, Storage, SyncedStore } from "@netless/synced-store";
|
|
4
|
+
export type {
|
|
5
|
+
AddPageParams,
|
|
6
|
+
MountParams,
|
|
7
|
+
NetlessApp,
|
|
8
|
+
PublicEvent,
|
|
9
|
+
WindowManager,
|
|
10
|
+
} from "@netless/window-manager";
|
|
11
|
+
export type {
|
|
12
|
+
AnimationMode,
|
|
13
|
+
ApplianceNames,
|
|
14
|
+
Camera,
|
|
15
|
+
CameraState,
|
|
16
|
+
Color,
|
|
17
|
+
ConversionResponse,
|
|
18
|
+
ConvertedFile,
|
|
19
|
+
HotKey,
|
|
20
|
+
HotKeys,
|
|
21
|
+
JoinRoomParams,
|
|
22
|
+
MemberState,
|
|
23
|
+
Player,
|
|
24
|
+
PlayerCallbacks,
|
|
25
|
+
PlayerPhase,
|
|
26
|
+
PlayerSeekingResult,
|
|
27
|
+
PlayerState,
|
|
28
|
+
Rectangle,
|
|
29
|
+
ReplayRoomParams,
|
|
30
|
+
Room,
|
|
31
|
+
RoomCallbacks,
|
|
32
|
+
RoomPhase,
|
|
33
|
+
RoomState,
|
|
34
|
+
SceneDefinition,
|
|
35
|
+
ShapeType,
|
|
36
|
+
View,
|
|
37
|
+
ViewCallbacks,
|
|
38
|
+
WhiteWebSdk,
|
|
39
|
+
WhiteWebSdkConfiguration,
|
|
40
|
+
} from "white-web-sdk";
|
|
41
|
+
|
|
42
|
+
export type Appliance = `${ApplianceNames}`;
|
package/src/behaviors/index.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import type { RegisterParams } from "@netless/window-manager";
|
|
2
|
-
import { WindowManager } from "@netless/window-manager";
|
|
3
|
-
import SlideApp, { apps, addHooks, previewSlide } from "@netless/app-slide";
|
|
4
|
-
|
|
5
|
-
export type {
|
|
6
|
-
AppOptions as SlideOptions,
|
|
7
|
-
Controller as SlideController,
|
|
8
|
-
PreviewParams,
|
|
9
|
-
SlidePreviewer,
|
|
10
|
-
} from "@netless/app-slide";
|
|
11
|
-
export { previewSlide, SlideApp, addHooks as addSlideHooks, apps as slideApps };
|
|
12
|
-
|
|
13
|
-
export interface AppsConfig {
|
|
14
|
-
[kind: string]: Omit<RegisterParams, "kind">;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const DefaultApps: AppsConfig = {
|
|
18
|
-
Monaco: {
|
|
19
|
-
src: "https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-monaco/0.1.12/dist/main.iife.js",
|
|
20
|
-
},
|
|
21
|
-
Countdown: {
|
|
22
|
-
src: "https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-countdown/0.0.2/dist/main.iife.js",
|
|
23
|
-
},
|
|
24
|
-
GeoGebra: {
|
|
25
|
-
src: "https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-geogebra/0.0.4/dist/main.iife.js",
|
|
26
|
-
appOptions: {
|
|
27
|
-
HTML5Codebase: "https://flat-storage-cn-hz.whiteboard.agora.io/GeoGebra/HTML5/5.0/web3d",
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
|
-
EmbeddedPage: {
|
|
31
|
-
src: "https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-embedded-page/0.1.1/dist/main.iife.js",
|
|
32
|
-
},
|
|
33
|
-
Plyr: {
|
|
34
|
-
src: "https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-plyr/0.1.3/dist/main.iife.js",
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
WindowManager.register({
|
|
39
|
-
kind: "Slide",
|
|
40
|
-
appOptions: { debug: false },
|
|
41
|
-
src: SlideApp,
|
|
42
|
-
addHooks,
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
for (const kind in DefaultApps) {
|
|
46
|
-
if (Object.prototype.hasOwnProperty.call(DefaultApps, kind)) {
|
|
47
|
-
const options = DefaultApps[kind];
|
|
48
|
-
WindowManager.register({ kind, ...options });
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export const register = WindowManager.register.bind(WindowManager);
|
|
53
|
-
|
|
54
|
-
declare let __NAME__: string, __VERSION__: string;
|
|
55
|
-
|
|
56
|
-
export const version = __VERSION__;
|
|
57
|
-
|
|
58
|
-
if (typeof window !== "undefined") {
|
|
59
|
-
let str = (window as { __netlessUA?: string }).__netlessUA || "";
|
|
60
|
-
str += ` ${__NAME__}@${version} `;
|
|
61
|
-
(window as { __netlessUA?: string }).__netlessUA = str;
|
|
62
|
-
}
|