@netless/window-manager 1.0.0-canary.5 → 1.0.0-canary.50
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 +30 -6
- package/dist/index.cjs.js +12477 -34
- package/dist/index.es.js +6839 -10495
- package/dist/index.umd.js +12485 -46
- package/dist/{App → src/App}/AppContext.d.ts +12 -7
- package/dist/{App → src/App}/AppPageStateImpl.d.ts +0 -0
- package/dist/{App → src/App}/AppProxy.d.ts +29 -11
- package/dist/{App → src/App}/MagixEvent/index.d.ts +0 -0
- package/dist/{App → src/App}/Storage/StorageEvent.d.ts +0 -0
- package/dist/{App → src/App}/Storage/index.d.ts +0 -0
- package/dist/{App → src/App}/Storage/typings.d.ts +0 -0
- package/dist/{App → src/App}/Storage/utils.d.ts +0 -0
- package/dist/src/App/WhiteboardView.d.ts +27 -0
- package/dist/{App → src/App}/index.d.ts +1 -0
- package/dist/src/App/type.d.ts +21 -0
- package/dist/{AppListener.d.ts → src/AppListener.d.ts} +2 -2
- package/dist/{AppManager.d.ts → src/AppManager.d.ts} +6 -5
- package/dist/{AttributesDelegate.d.ts → src/AttributesDelegate.d.ts} +5 -2
- package/dist/{BoxEmitter.d.ts → src/BoxEmitter.d.ts} +0 -0
- package/dist/{BoxManager.d.ts → src/BoxManager.d.ts} +12 -6
- package/dist/{BuiltinApps.d.ts → src/BuiltinApps.d.ts} +3 -0
- package/dist/{Cursor → src/Cursor}/Cursor.d.ts +0 -0
- package/dist/{Cursor → src/Cursor}/icons.d.ts +0 -0
- package/dist/{Cursor → src/Cursor}/index.d.ts +3 -3
- package/dist/{Helper.d.ts → src/Helper.d.ts} +4 -8
- package/dist/{InternalEmitter.d.ts → src/InternalEmitter.d.ts} +3 -4
- package/dist/{Page → src/Page}/PageController.d.ts +2 -1
- package/dist/{Page → src/Page}/index.d.ts +0 -0
- package/dist/{PageState.d.ts → src/PageState.d.ts} +0 -0
- package/dist/{ReconnectRefresher.d.ts → src/ReconnectRefresher.d.ts} +0 -0
- package/dist/{RedoUndo.d.ts → src/RedoUndo.d.ts} +0 -0
- package/dist/{Register → src/Register}/index.d.ts +4 -2
- package/dist/{Register → src/Register}/loader.d.ts +1 -1
- package/dist/src/Register/storage.d.ts +11 -0
- package/dist/{Utils → src/Utils}/AppCreateQueue.d.ts +0 -0
- package/dist/{Utils → src/Utils}/Common.d.ts +0 -0
- package/dist/{Utils → src/Utils}/Reactive.d.ts +0 -0
- package/dist/{Utils → src/Utils}/RoomHacker.d.ts +0 -0
- package/dist/{Utils → src/Utils}/error.d.ts +1 -1
- package/dist/{Utils → src/Utils}/log.d.ts +0 -0
- package/dist/src/View/CameraSynchronizer.d.ts +19 -0
- package/dist/{View → src/View}/MainView.d.ts +18 -7
- package/dist/{View → src/View}/ViewManager.d.ts +0 -0
- package/dist/src/View/ViewSync.d.ts +29 -0
- package/dist/{callback.d.ts → src/callback.d.ts} +10 -1
- package/dist/{constants.d.ts → src/constants.d.ts} +10 -5
- package/dist/src/image.d.ts +19 -0
- package/dist/{index.d.ts → src/index.d.ts} +49 -14
- package/dist/src/shim.d.ts +11 -0
- package/dist/{typings.d.ts → src/typings.d.ts} +12 -3
- package/dist/style.css +795 -1
- package/docs/app-context.md +155 -27
- package/docs/mirgrate-to-1.0.md +68 -0
- package/package.json +23 -19
- package/playwright.config.ts +29 -0
- package/pnpm-lock.yaml +3078 -4412
- package/src/App/AppContext.ts +62 -29
- package/src/App/AppProxy.ts +235 -113
- package/src/App/WhiteboardView.ts +34 -12
- package/src/App/index.ts +1 -0
- package/src/App/type.ts +22 -0
- package/src/AppListener.ts +30 -21
- package/src/AppManager.ts +66 -43
- package/src/AttributesDelegate.ts +6 -3
- package/src/BoxManager.ts +76 -38
- package/src/BuiltinApps.ts +9 -8
- package/src/Cursor/Cursor.ts +7 -3
- package/src/Cursor/index.ts +7 -8
- package/src/Helper.ts +25 -7
- package/src/InternalEmitter.ts +3 -4
- package/src/Page/PageController.ts +2 -1
- package/src/PageState.ts +1 -1
- package/src/ReconnectRefresher.ts +6 -2
- package/src/Register/index.ts +36 -14
- package/src/Register/loader.ts +20 -9
- package/src/Register/storage.ts +26 -5
- package/src/Utils/Common.ts +3 -0
- package/src/Utils/Reactive.ts +27 -26
- package/src/Utils/RoomHacker.ts +3 -0
- package/src/Utils/error.ts +2 -2
- package/src/View/CameraSynchronizer.ts +41 -38
- package/src/View/MainView.ts +116 -75
- package/src/View/ViewSync.ts +123 -6
- package/src/callback.ts +6 -1
- package/src/constants.ts +8 -3
- package/src/index.ts +201 -63
- package/src/style.css +3 -46
- package/src/typings.ts +14 -3
- package/vite.config.js +12 -7
- package/dist/App/AppViewSync.d.ts +0 -11
- package/dist/App/WhiteboardView.d.ts +0 -21
- package/dist/Register/storage.d.ts +0 -8
- package/dist/View/CameraSynchronizer.d.ts +0 -17
- package/dist/View/ViewSync.d.ts +0 -7
- package/src/App/AppViewSync.ts +0 -69
package/src/Register/loader.ts
CHANGED
@@ -1,19 +1,20 @@
|
|
1
1
|
import { callbacks } from "../callback";
|
2
2
|
import { getItem, setItem } from "./storage";
|
3
3
|
import type { NetlessApp } from "../typings";
|
4
|
+
import { appRegister } from ".";
|
4
5
|
|
5
6
|
const Prefix = "NetlessApp";
|
6
7
|
|
7
8
|
const TIMEOUT = 10000; // 下载 script 10 秒超时
|
8
9
|
|
9
|
-
export const getScript = async (url: string): Promise<string> => {
|
10
|
-
const item = await getItem(
|
10
|
+
export const getScript = async (kind: string, url: string): Promise<string> => {
|
11
|
+
const item = await getItem(kind);
|
11
12
|
if (item) {
|
12
13
|
return item.sourceCode;
|
13
14
|
} else {
|
14
15
|
const result = await fetchWithTimeout(url, { timeout: TIMEOUT });
|
15
16
|
const text = await result.text();
|
16
|
-
await setItem(url, text);
|
17
|
+
await setItem(kind, url, text);
|
17
18
|
return text;
|
18
19
|
}
|
19
20
|
};
|
@@ -28,6 +29,15 @@ export const executeScript = (text: string, appName: string): NetlessApp => {
|
|
28
29
|
return result;
|
29
30
|
};
|
30
31
|
|
32
|
+
const emitSuccess = (kind: string, url: string) => {
|
33
|
+
callbacks.emit("loadApp", { kind, status: "success" });
|
34
|
+
appRegister.downloaded.set(kind, url);
|
35
|
+
};
|
36
|
+
|
37
|
+
const emitFailed = (kind: string, reason: string) => {
|
38
|
+
callbacks.emit("loadApp", { kind, status: "failed", reason, });
|
39
|
+
};
|
40
|
+
|
31
41
|
export const loadApp = async (
|
32
42
|
url: string,
|
33
43
|
key: string,
|
@@ -36,14 +46,14 @@ export const loadApp = async (
|
|
36
46
|
const appName = name || Prefix + key;
|
37
47
|
callbacks.emit("loadApp", { kind: key, status: "start" });
|
38
48
|
try {
|
39
|
-
const text = await getScript(url);
|
49
|
+
const text = await getScript(key, url);
|
40
50
|
if (!text || text.length === 0) {
|
41
|
-
|
51
|
+
emitFailed(key, "script is empty");
|
42
52
|
return;
|
43
53
|
}
|
44
54
|
try {
|
45
55
|
const result = executeScript(text, appName);
|
46
|
-
|
56
|
+
emitSuccess(key, url);
|
47
57
|
return result;
|
48
58
|
} catch (error: any) {
|
49
59
|
if (error.message.includes("Can only have one anonymous define call per script file")) {
|
@@ -54,16 +64,17 @@ export const loadApp = async (
|
|
54
64
|
delete define.amd;
|
55
65
|
}
|
56
66
|
const result = executeScript(text, appName);
|
57
|
-
|
67
|
+
emitSuccess(key, url);
|
58
68
|
return result;
|
59
69
|
}
|
60
|
-
|
70
|
+
emitFailed(key, error.message);
|
61
71
|
}
|
62
72
|
} catch (error: any) {
|
63
|
-
|
73
|
+
emitFailed(key, error.message);
|
64
74
|
}
|
65
75
|
};
|
66
76
|
|
77
|
+
|
67
78
|
async function fetchWithTimeout(resource: string, options: RequestInit & { timeout: number }) {
|
68
79
|
const { timeout = 10000 } = options;
|
69
80
|
|
package/src/Register/storage.ts
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
import type { AppRegister } from "./index";
|
2
|
+
|
1
3
|
const DatabaseName = "__WindowManagerAppCache";
|
2
4
|
|
3
5
|
let db: IDBDatabase;
|
@@ -5,21 +7,26 @@ let store: IDBObjectStore;
|
|
5
7
|
|
6
8
|
export type Item = {
|
7
9
|
kind: string;
|
10
|
+
url: string;
|
8
11
|
sourceCode: string;
|
9
12
|
}
|
10
13
|
|
11
|
-
export const initDb = async () => {
|
14
|
+
export const initDb = async (appRegister: AppRegister) => {
|
12
15
|
db = await createDb();
|
16
|
+
const items = await queryAll(db);
|
17
|
+
items.forEach(item => {
|
18
|
+
appRegister.downloaded.set(item.kind, item.url);
|
19
|
+
});
|
13
20
|
}
|
14
21
|
|
15
|
-
export const setItem = (
|
22
|
+
export const setItem = (kind: string, url: string, val: any) => {
|
16
23
|
if (!db) return;
|
17
|
-
return addRecord(db, { kind
|
24
|
+
return addRecord(db, { kind, url, sourceCode: val })
|
18
25
|
};
|
19
26
|
|
20
|
-
export const getItem = async (
|
27
|
+
export const getItem = async (kind: string): Promise<Item | null> => {
|
21
28
|
if (!db) return null;
|
22
|
-
return await query(db,
|
29
|
+
return await query(db, kind);
|
23
30
|
};
|
24
31
|
|
25
32
|
export const removeItem = (key: string) => {
|
@@ -27,6 +34,11 @@ export const removeItem = (key: string) => {
|
|
27
34
|
return deleteRecord(db, key);
|
28
35
|
};
|
29
36
|
|
37
|
+
export const getAll = () => {
|
38
|
+
if (!db) return;
|
39
|
+
return queryAll(db);
|
40
|
+
}
|
41
|
+
|
30
42
|
function createDb(): Promise<IDBDatabase> {
|
31
43
|
return new Promise((resolve, reject) => {
|
32
44
|
const request = indexedDB.open(DatabaseName, 2);
|
@@ -64,6 +76,15 @@ function query<T>(db: IDBDatabase, val: string): Promise<T | null> {
|
|
64
76
|
})
|
65
77
|
}
|
66
78
|
|
79
|
+
function queryAll(db: IDBDatabase): Promise<Item[]> {
|
80
|
+
return new Promise((resolve, reject) => {
|
81
|
+
const index = db.transaction(["apps"]).objectStore("apps").index("kind");
|
82
|
+
const request = index.getAll();
|
83
|
+
request.onerror = e => reject(e);
|
84
|
+
request.onsuccess = () => resolve(request.result);
|
85
|
+
});
|
86
|
+
}
|
87
|
+
|
67
88
|
function addRecord(db: IDBDatabase, payload: any): Promise<void> {
|
68
89
|
return new Promise((resolve, reject) => {
|
69
90
|
const request = db.transaction(["apps"], "readwrite").objectStore("apps").add(payload);
|
package/src/Utils/Common.ts
CHANGED
@@ -17,6 +17,9 @@ export const genAppId = async (kind: string) => {
|
|
17
17
|
};
|
18
18
|
|
19
19
|
export const setViewFocusScenePath = (view: View, focusScenePath: string) => {
|
20
|
+
if ((view as any).didRelease) {
|
21
|
+
return;
|
22
|
+
}
|
20
23
|
if (view.focusScenePath !== focusScenePath) {
|
21
24
|
view.focusScenePath = focusScenePath;
|
22
25
|
return view;
|
package/src/Utils/Reactive.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
import { listenUpdated, unlistenUpdated, reaction, UpdateEventKind } from "white-web-sdk";
|
2
|
-
import type { AkkoObjectUpdatedProperty , AkkoObjectUpdatedListener } from "white-web-sdk";
|
3
1
|
import { isObject } from "lodash";
|
2
|
+
import { listenUpdated, reaction, unlistenUpdated, UpdateEventKind } from "white-web-sdk";
|
3
|
+
import type { AkkoObjectUpdatedProperty, AkkoObjectUpdatedListener } from "white-web-sdk";
|
4
4
|
|
5
5
|
// 兼容 13 和 14 版本 SDK
|
6
6
|
export const onObjectByEvent = (event: UpdateEventKind) => {
|
@@ -12,7 +12,7 @@ export const onObjectByEvent = (event: UpdateEventKind) => {
|
|
12
12
|
if (kinds.includes(event)) {
|
13
13
|
func();
|
14
14
|
}
|
15
|
-
}
|
15
|
+
};
|
16
16
|
listenUpdated(object, listener);
|
17
17
|
func();
|
18
18
|
return () => unlistenUpdated(object, listener);
|
@@ -21,43 +21,44 @@ export const onObjectByEvent = (event: UpdateEventKind) => {
|
|
21
21
|
() => object,
|
22
22
|
() => {
|
23
23
|
func();
|
24
|
-
},
|
24
|
+
},
|
25
|
+
{
|
25
26
|
fireImmediately: true,
|
26
27
|
}
|
27
|
-
)
|
28
|
+
);
|
28
29
|
}
|
29
|
-
}
|
30
|
-
}
|
30
|
+
};
|
31
|
+
};
|
31
32
|
|
32
33
|
export const safeListenPropsUpdated = <T>(
|
33
34
|
getProps: () => T,
|
34
35
|
callback: AkkoObjectUpdatedListener<T>,
|
35
36
|
onDestroyed?: (props: unknown) => void
|
36
|
-
|
37
|
+
) => {
|
37
38
|
let disposeListenUpdated: (() => void) | null = null;
|
38
39
|
const disposeReaction = reaction(
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
40
|
+
getProps,
|
41
|
+
() => {
|
42
|
+
if (disposeListenUpdated) {
|
43
|
+
disposeListenUpdated();
|
44
|
+
disposeListenUpdated = null;
|
45
|
+
}
|
46
|
+
const props = getProps();
|
47
|
+
if (isObject(props)) {
|
48
|
+
disposeListenUpdated = () => unlistenUpdated(props, callback);
|
49
|
+
listenUpdated(props, callback);
|
50
|
+
} else {
|
51
|
+
onDestroyed?.(props);
|
52
|
+
}
|
53
|
+
},
|
54
|
+
{ fireImmediately: true }
|
54
55
|
);
|
55
56
|
|
56
57
|
return () => {
|
57
|
-
|
58
|
-
|
58
|
+
disposeListenUpdated?.();
|
59
|
+
disposeReaction();
|
59
60
|
};
|
60
|
-
}
|
61
|
+
};
|
61
62
|
|
62
63
|
export const onObjectRemoved = onObjectByEvent(UpdateEventKind.Removed);
|
63
64
|
export const onObjectInserted = onObjectByEvent(UpdateEventKind.Inserted);
|
package/src/Utils/RoomHacker.ts
CHANGED
@@ -56,6 +56,9 @@ export const replaceRoomFunction = (room: Room | Player, manager: WindowManager)
|
|
56
56
|
room.lockImages = (...args) => manager.lockImages(...args);
|
57
57
|
|
58
58
|
delegateRemoveScenes(room, manager);
|
59
|
+
if (!(room as any).dynamicPpt.slideStateAdapter.pptHandler) {
|
60
|
+
(room as any).dynamicPpt.slideStateAdapter.pptHandler = manager.createPPTHandler();
|
61
|
+
}
|
59
62
|
}
|
60
63
|
};
|
61
64
|
|
package/src/Utils/error.ts
CHANGED
@@ -31,8 +31,8 @@ export class InvalidScenePath extends Error {
|
|
31
31
|
override message = `[WindowManager]: ScenePath should start with "/"`;
|
32
32
|
}
|
33
33
|
|
34
|
-
export class
|
35
|
-
override message = "[WindowManager]: boxManager
|
34
|
+
export class BoxManagerNotInitializeError extends Error {
|
35
|
+
override message = "[WindowManager]: boxManager need initialize";
|
36
36
|
}
|
37
37
|
|
38
38
|
export class BindContainerRoomPhaseInvalidError extends Error {
|
@@ -1,20 +1,20 @@
|
|
1
1
|
import { AnimationMode } from "white-web-sdk";
|
2
|
-
import {
|
2
|
+
import { isEqual, pick, throttle } from "lodash";
|
3
3
|
import type { TeleBoxRect } from "@netless/telebox-insider";
|
4
4
|
import type { Camera, View, Size } from "white-web-sdk";
|
5
|
-
import type { ISize } from "../AttributesDelegate";
|
5
|
+
import type { ICamera, ISize } from "../AttributesDelegate";
|
6
6
|
|
7
|
-
export type SaveCamera = (camera:
|
7
|
+
export type SaveCamera = (camera: ICamera) => void;
|
8
8
|
|
9
9
|
export class CameraSynchronizer {
|
10
|
-
|
11
|
-
|
10
|
+
public remoteCamera?: ICamera;
|
11
|
+
public remoteSize?: ISize;
|
12
12
|
protected rect?: TeleBoxRect;
|
13
13
|
protected view?: View;
|
14
14
|
|
15
15
|
constructor(protected saveCamera: SaveCamera) {}
|
16
16
|
|
17
|
-
public setRect(rect: TeleBoxRect) {
|
17
|
+
public setRect = (rect: TeleBoxRect) => {
|
18
18
|
this.rect = rect;
|
19
19
|
if (this.remoteCamera && this.remoteSize) {
|
20
20
|
this.onRemoteUpdate(this.remoteCamera, this.remoteSize);
|
@@ -26,48 +26,51 @@ export class CameraSynchronizer {
|
|
26
26
|
}
|
27
27
|
|
28
28
|
// 远端 Camera 或者 size 更新
|
29
|
-
public onRemoteUpdate = throttle((camera:
|
29
|
+
public onRemoteUpdate = throttle((camera: ICamera, size: ISize) => {
|
30
30
|
this.remoteCamera = camera;
|
31
31
|
this.remoteSize = size;
|
32
32
|
if (this.remoteSize && this.rect) {
|
33
|
-
|
34
|
-
|
35
|
-
scale = this.rect.width / size.width;
|
36
|
-
} else {
|
37
|
-
scale = this.rect.height / size.height;
|
38
|
-
}
|
39
|
-
const nextScale = camera.scale * scale;
|
40
|
-
const moveCamera = () => this.view?.moveCamera({
|
41
|
-
centerX: camera.centerX,
|
42
|
-
centerY: camera.centerY,
|
33
|
+
const nextScale = camera.scale * computedMinScale(size, this.rect);
|
34
|
+
const config: Partial<Camera> = {
|
43
35
|
scale: nextScale,
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
36
|
+
}
|
37
|
+
if (camera.centerX !== null) {
|
38
|
+
config.centerX = camera.centerX;
|
39
|
+
}
|
40
|
+
if (camera.centerY !== null) {
|
41
|
+
config.centerY = camera.centerY;
|
42
|
+
}
|
43
|
+
this.moveCamera(config);
|
48
44
|
}
|
49
|
-
},
|
45
|
+
}, 10);
|
50
46
|
|
47
|
+
public onRemoteSizeUpdate(size: ISize) {
|
48
|
+
this.remoteSize = size;
|
49
|
+
const needMoveCamera = !isEqual(pick(this.rect, ["width", "height"]), pick(size, ["width", "height"]));
|
50
|
+
if (this.rect && this.remoteCamera && needMoveCamera) {
|
51
|
+
if (!this.view) return;
|
52
|
+
const currentCamera = this.view.camera;
|
53
|
+
this.view?.moveCameraToContain({
|
54
|
+
width: size.width,
|
55
|
+
height: size.height,
|
56
|
+
originX: currentCamera.centerX - (size.width / 2),
|
57
|
+
originY: currentCamera.centerY - (size.height / 2),
|
58
|
+
});
|
59
|
+
}
|
60
|
+
}
|
51
61
|
|
52
|
-
public onLocalCameraUpdate(camera:
|
62
|
+
public onLocalCameraUpdate(camera: ICamera) {
|
53
63
|
this.saveCamera(camera);
|
54
64
|
this.remoteCamera = camera;
|
55
65
|
}
|
56
66
|
|
57
|
-
|
58
|
-
|
59
|
-
if (this.rect && this.view) {
|
60
|
-
let scale: number;
|
61
|
-
if (size.width < size.height) {
|
62
|
-
scale = this.rect.width / size.width;
|
63
|
-
} else {
|
64
|
-
scale = this.rect.height / size.height;
|
65
|
-
}
|
66
|
-
const nextScale = this.view.camera.scale / scale;
|
67
|
-
this.view.moveCamera({
|
68
|
-
scale: nextScale,
|
69
|
-
animationMode: AnimationMode.Immediately
|
70
|
-
});
|
71
|
-
}
|
67
|
+
private moveCamera(camera: Partial<Camera>) {
|
68
|
+
this.view?.moveCamera({ ...camera, animationMode: AnimationMode.Immediately });
|
72
69
|
}
|
73
70
|
}
|
71
|
+
|
72
|
+
export const computedMinScale = (remoteSize: Size, currentSize: Size) => {
|
73
|
+
const wScale = currentSize.width / remoteSize.width;
|
74
|
+
const hScale = currentSize.height / remoteSize.height;
|
75
|
+
return Math.min(wScale, hScale);
|
76
|
+
}
|