@neta-art/cohub 12.2.0 → 12.4.0
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 +87 -3
- package/dist/board/editor/context.d.ts +2 -0
- package/dist/board/editor/document.d.ts +3 -1
- package/dist/board/editor/document.js +8 -6
- package/dist/board/editor/editor.d.ts +7 -3
- package/dist/board/editor/editor.js +8 -1
- package/dist/board/editor/index.d.ts +3 -3
- package/dist/board/editor/index.js +2 -2
- package/dist/board/editor/interaction.d.ts +23 -2
- package/dist/board/editor/interaction.js +99 -5
- package/dist/board/editor/query.d.ts +1 -1
- package/dist/board/editor/query.js +3 -7
- package/dist/board/editor/selection.js +13 -1
- package/dist/board/editor/tool.d.ts +4 -1
- package/dist/board/editor/tool.js +6 -1
- package/dist/board/model/asset-key.d.ts +9 -1
- package/dist/board/model/asset-key.js +27 -7
- package/dist/board/model/index.d.ts +5 -5
- package/dist/board/model/index.js +4 -4
- package/dist/board/model/items/create.js +1 -1
- package/dist/board/model/items/definition.d.ts +9 -1
- package/dist/board/model/items/index.d.ts +2 -2
- package/dist/board/model/items/registry.d.ts +2 -1
- package/dist/board/model/items/registry.js +1 -0
- package/dist/board/model/text-metrics.d.ts +21 -1
- package/dist/board/model/text-metrics.js +24 -1
- package/dist/board/model/themes.d.ts +49 -42
- package/dist/board/model/themes.js +49 -44
- package/dist/board/render/index.d.ts +8 -6
- package/dist/board/render/index.js +7 -5
- package/dist/board/render/labels.d.ts +15 -0
- package/dist/board/render/labels.js +14 -0
- package/dist/board/render/lod.d.ts +9 -1
- package/dist/board/render/lod.js +7 -1
- package/dist/board/render/media-interaction.d.ts +5 -2
- package/dist/board/render/media-interaction.js +14 -2
- package/dist/board/render/renderers/arrow-card-renderer.js +7 -5
- package/dist/board/render/renderers/board-renderer-registry.d.ts +12 -1
- package/dist/board/render/renderers/board-renderer-registry.js +9 -4
- package/dist/board/render/renderers/far-plate.d.ts +4 -1
- package/dist/board/render/renderers/far-plate.js +5 -1
- package/dist/board/render/renderers/file-card-renderer.js +44 -24
- package/dist/board/render/renderers/frame-card-renderer.js +9 -3
- package/dist/board/render/renderers/image-card-renderer.js +2 -2
- package/dist/board/render/renderers/model-card-renderer.js +2 -2
- package/dist/board/render/renderers/task-card-renderer.js +2 -2
- package/dist/board/render/renderers/video-card-renderer.js +2 -2
- package/dist/board/render/style.d.ts +1 -0
- package/dist/board/render/style.js +3 -1
- package/dist/board/render/text-edit.d.ts +32 -0
- package/dist/board/render/text-edit.js +134 -0
- package/dist/board/render/text-fit.d.ts +1 -3
- package/dist/board/render/text-fit.js +4 -43
- package/dist/board/render/text-measurement.d.ts +12 -2
- package/dist/board/render/text-measurement.js +55 -10
- package/dist/board/replica/index.d.ts +4 -2
- package/dist/board/replica/index.js +34 -21
- package/dist/board/replica/indexeddb.d.ts +16 -0
- package/dist/board/replica/indexeddb.js +155 -0
- package/dist/board/stage/assets.d.ts +16 -4
- package/dist/board/stage/assets.js +155 -30
- package/dist/board/stage/bench.d.ts +35 -0
- package/dist/board/stage/bench.js +153 -0
- package/dist/board/stage/device.d.ts +41 -0
- package/dist/board/stage/device.js +62 -0
- package/dist/board/stage/frame-budget.d.ts +19 -0
- package/dist/board/stage/frame-budget.js +69 -0
- package/dist/board/stage/idle.d.ts +4 -0
- package/dist/board/stage/idle.js +26 -0
- package/dist/board/stage/index.d.ts +9 -5
- package/dist/board/stage/index.js +5 -2
- package/dist/board/stage/presses.d.ts +21 -0
- package/dist/board/stage/presses.js +66 -0
- package/dist/board/stage/scene.d.ts +4 -0
- package/dist/board/stage/scene.js +45 -13
- package/dist/board/stage/stage.d.ts +21 -2
- package/dist/board/stage/stage.js +309 -89
- package/dist/board/stage/texture-pool.d.ts +6 -4
- package/dist/board/stage/texture-pool.js +42 -8
- package/dist/board/stage/views.d.ts +1 -1
- package/dist/board/stage/views.js +2 -2
- package/dist/chunks/environment.d.ts +6 -0
- package/dist/chunks/http.d.ts +9 -1
- package/dist/chunks/http.js +791 -4
- package/dist/index.d.ts +52 -1
- package/dist/index.js +65 -733
- package/dist/protocol/dist/board-model.d.ts +15 -1
- package/dist/protocol/dist/board-model.js +12 -2
- package/dist/protocol/dist/board-schema.d.ts +2 -1
- package/dist/protocol/dist/board-schema.js +4 -1
- package/dist/protocol/dist/core/media.js +4 -0
- package/dist/protocol/dist/index.d.ts +2 -2
- package/package.json +2 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BoardDelta, BoardDocument, BoardPatch } from "../../protocol/dist/board-model.js";
|
|
2
2
|
import { BoardApplyResult, BoardPlaybackSnapshot, BoardReadResult } from "../../protocol/dist/board.js";
|
|
3
3
|
import "../../protocol/dist/index.js";
|
|
4
|
+
import { BoardReplicaDatabaseOptions, BoardReplicaScope, clearBoardReplicaStorage, createIndexedDbBoardReplicaStorage } from "./indexeddb.js";
|
|
4
5
|
//#region src/board/replica/index.d.ts
|
|
5
6
|
type BoardPendingPatch = {
|
|
6
7
|
mutationId: string;
|
|
@@ -27,6 +28,7 @@ type BoardRemote = {
|
|
|
27
28
|
playback: BoardPlaybackSnapshot | null;
|
|
28
29
|
};
|
|
29
30
|
}) => void;
|
|
31
|
+
resync?: () => void;
|
|
30
32
|
}): () => void;
|
|
31
33
|
};
|
|
32
34
|
type BoardReplicaStorage = {
|
|
@@ -62,9 +64,9 @@ declare function createBoardReplica(options: BoardReplicaOptions): {
|
|
|
62
64
|
receive: (payload: BoardChangedPayload) => void;
|
|
63
65
|
receivePlayback: (next: BoardPlaybackSnapshot | null) => void;
|
|
64
66
|
refresh: () => Promise<void>;
|
|
65
|
-
retry()
|
|
67
|
+
retry: () => Promise<void>;
|
|
66
68
|
dispose(): void;
|
|
67
69
|
};
|
|
68
70
|
type BoardReplica = ReturnType<typeof createBoardReplica>;
|
|
69
71
|
//#endregion
|
|
70
|
-
export { BoardChangedPayload, BoardPendingPatch, BoardRemote, BoardReplica, BoardReplicaOptions, BoardReplicaState, BoardReplicaStorage, createBoardReplica };
|
|
72
|
+
export { BoardChangedPayload, BoardPendingPatch, BoardRemote, BoardReplica, type BoardReplicaDatabaseOptions, BoardReplicaOptions, type BoardReplicaScope, BoardReplicaState, BoardReplicaStorage, clearBoardReplicaStorage, createBoardReplica, createIndexedDbBoardReplicaStorage };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { applyBoardDelta, applyBoardPatchToDocument, parseBoardDocument } from "../../protocol/dist/board-patch.js";
|
|
2
2
|
import { createBoardEntityId } from "../model/items/id.js";
|
|
3
3
|
import { shareBoardDocument } from "../model/document-share.js";
|
|
4
|
+
import { clearBoardReplicaStorage, createIndexedDbBoardReplicaStorage } from "./indexeddb.js";
|
|
4
5
|
//#region src/board/replica/index.ts
|
|
5
6
|
function memoryStorage() {
|
|
6
7
|
return {
|
|
@@ -47,6 +48,7 @@ function createBoardReplica(options) {
|
|
|
47
48
|
let retryTimer = null;
|
|
48
49
|
let retryDelay = RETRY_BASE_MS;
|
|
49
50
|
let disposed = false;
|
|
51
|
+
let restored = false;
|
|
50
52
|
let unpersisted = null;
|
|
51
53
|
let persistTimer = null;
|
|
52
54
|
function subscribeRemote() {
|
|
@@ -54,7 +56,8 @@ function createBoardReplica(options) {
|
|
|
54
56
|
try {
|
|
55
57
|
return remote.subscribe({
|
|
56
58
|
changed: (event) => receive(event.payload),
|
|
57
|
-
playback: (event) => receivePlayback(event.payload.playback)
|
|
59
|
+
playback: (event) => receivePlayback(event.payload.playback),
|
|
60
|
+
resync: () => void retry()
|
|
58
61
|
});
|
|
59
62
|
} catch {
|
|
60
63
|
return null;
|
|
@@ -157,7 +160,7 @@ function createBoardReplica(options) {
|
|
|
157
160
|
retryDelay = Math.min(RETRY_MAX_MS, retryDelay * 2);
|
|
158
161
|
}
|
|
159
162
|
async function flush() {
|
|
160
|
-
if (sending || disposed || !loaded) return;
|
|
163
|
+
if (sending || disposed || !loaded || !restored) return;
|
|
161
164
|
sending = true;
|
|
162
165
|
try {
|
|
163
166
|
while (pending.length && !disposed) {
|
|
@@ -217,6 +220,30 @@ function createBoardReplica(options) {
|
|
|
217
220
|
}
|
|
218
221
|
emit();
|
|
219
222
|
}
|
|
223
|
+
function retry() {
|
|
224
|
+
if (disposed) return Promise.resolve();
|
|
225
|
+
if (retryTimer) clearTimeout(retryTimer);
|
|
226
|
+
retryTimer = null;
|
|
227
|
+
retryDelay = RETRY_BASE_MS;
|
|
228
|
+
readError = null;
|
|
229
|
+
writeError = null;
|
|
230
|
+
emit();
|
|
231
|
+
return refresh().then(flush);
|
|
232
|
+
}
|
|
233
|
+
function onOnline() {
|
|
234
|
+
if (pending.length || readError || writeError) retry();
|
|
235
|
+
}
|
|
236
|
+
async function restore() {
|
|
237
|
+
const [cached, stored] = await Promise.all([storage.readDocument().catch(() => null), storage.listPending().catch(() => [])]);
|
|
238
|
+
if (disposed) return;
|
|
239
|
+
const known = new Set(stored.map((entry) => entry.mutationId));
|
|
240
|
+
pending = [...stored, ...pending.filter((entry) => !known.has(entry.mutationId))];
|
|
241
|
+
restored = true;
|
|
242
|
+
const parsed = cached && !server ? parseBoardDocument(cached.document) : null;
|
|
243
|
+
if (cached && parsed?.ok) adoptServer(parsed.document, cached.version, false);
|
|
244
|
+
else recompute();
|
|
245
|
+
emit();
|
|
246
|
+
}
|
|
220
247
|
function receivePlayback(next) {
|
|
221
248
|
playbackRevision += 1;
|
|
222
249
|
playback = next;
|
|
@@ -232,15 +259,8 @@ function createBoardReplica(options) {
|
|
|
232
259
|
},
|
|
233
260
|
async start() {
|
|
234
261
|
unsubscribeRemote ??= subscribeRemote();
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
pending = stored;
|
|
238
|
-
if (cached && !server) {
|
|
239
|
-
const parsed = parseBoardDocument(cached.document);
|
|
240
|
-
if (parsed.ok) adoptServer(parsed.document, cached.version, false);
|
|
241
|
-
}
|
|
242
|
-
emit();
|
|
243
|
-
await refresh();
|
|
262
|
+
globalThis.addEventListener?.("online", onOnline);
|
|
263
|
+
await Promise.all([restore(), refresh()]);
|
|
244
264
|
await flush();
|
|
245
265
|
},
|
|
246
266
|
apply(patch) {
|
|
@@ -256,17 +276,10 @@ function createBoardReplica(options) {
|
|
|
256
276
|
receive,
|
|
257
277
|
receivePlayback,
|
|
258
278
|
refresh,
|
|
259
|
-
retry
|
|
260
|
-
if (retryTimer) clearTimeout(retryTimer);
|
|
261
|
-
retryTimer = null;
|
|
262
|
-
retryDelay = RETRY_BASE_MS;
|
|
263
|
-
readError = null;
|
|
264
|
-
writeError = null;
|
|
265
|
-
emit();
|
|
266
|
-
return refresh().then(flush);
|
|
267
|
-
},
|
|
279
|
+
retry,
|
|
268
280
|
dispose() {
|
|
269
281
|
disposed = true;
|
|
282
|
+
globalThis.removeEventListener?.("online", onOnline);
|
|
270
283
|
unsubscribeRemote?.();
|
|
271
284
|
unsubscribeRemote = null;
|
|
272
285
|
listeners.clear();
|
|
@@ -276,4 +289,4 @@ function createBoardReplica(options) {
|
|
|
276
289
|
};
|
|
277
290
|
}
|
|
278
291
|
//#endregion
|
|
279
|
-
export { createBoardReplica };
|
|
292
|
+
export { clearBoardReplicaStorage, createBoardReplica, createIndexedDbBoardReplicaStorage };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BoardReplicaStorage } from "./index.js";
|
|
2
|
+
//#region src/board/replica/indexeddb.d.ts
|
|
3
|
+
type BoardReplicaScope = {
|
|
4
|
+
userKey: string;
|
|
5
|
+
spaceId: string;
|
|
6
|
+
boardId: string;
|
|
7
|
+
};
|
|
8
|
+
type BoardReplicaDatabaseOptions = {
|
|
9
|
+
database?: string;
|
|
10
|
+
};
|
|
11
|
+
declare function createIndexedDbBoardReplicaStorage(scope: BoardReplicaScope, options?: BoardReplicaDatabaseOptions): BoardReplicaStorage;
|
|
12
|
+
declare function clearBoardReplicaStorage(options?: BoardReplicaDatabaseOptions & {
|
|
13
|
+
userKey?: string;
|
|
14
|
+
}): Promise<void>;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { BoardReplicaDatabaseOptions, BoardReplicaScope, clearBoardReplicaStorage, createIndexedDbBoardReplicaStorage };
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
//#region src/board/replica/indexeddb.ts
|
|
2
|
+
const DATABASE = "cohub-board";
|
|
3
|
+
const VERSION = 1;
|
|
4
|
+
const OPEN_TIMEOUT_MS = 3e3;
|
|
5
|
+
const connections = /* @__PURE__ */ new Map();
|
|
6
|
+
function open(name) {
|
|
7
|
+
const existing = connections.get(name);
|
|
8
|
+
if (existing) return existing;
|
|
9
|
+
const opening = new Promise((resolve, reject) => {
|
|
10
|
+
const factory = globalThis.indexedDB;
|
|
11
|
+
if (!factory) {
|
|
12
|
+
reject(/* @__PURE__ */ new Error("IndexedDB is unavailable."));
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
let late = false;
|
|
16
|
+
const timer = setTimeout(() => {
|
|
17
|
+
late = true;
|
|
18
|
+
reject(/* @__PURE__ */ new Error("IndexedDB did not open in time."));
|
|
19
|
+
}, OPEN_TIMEOUT_MS);
|
|
20
|
+
const request = factory.open(name, VERSION);
|
|
21
|
+
request.onupgradeneeded = () => {
|
|
22
|
+
const db = request.result;
|
|
23
|
+
db.createObjectStore("documents", { keyPath: "board" }).createIndex("user", "userKey");
|
|
24
|
+
const pending = db.createObjectStore("pending", { keyPath: ["board", "mutationId"] });
|
|
25
|
+
pending.createIndex("board", "board");
|
|
26
|
+
pending.createIndex("user", "userKey");
|
|
27
|
+
};
|
|
28
|
+
request.onsuccess = () => {
|
|
29
|
+
clearTimeout(timer);
|
|
30
|
+
const db = request.result;
|
|
31
|
+
if (late) {
|
|
32
|
+
db.close();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const forget = () => {
|
|
36
|
+
if (connections.get(name) === opening) connections.delete(name);
|
|
37
|
+
};
|
|
38
|
+
db.onversionchange = () => {
|
|
39
|
+
db.close();
|
|
40
|
+
forget();
|
|
41
|
+
};
|
|
42
|
+
db.onclose = forget;
|
|
43
|
+
resolve(db);
|
|
44
|
+
};
|
|
45
|
+
request.onerror = () => {
|
|
46
|
+
clearTimeout(timer);
|
|
47
|
+
reject(request.error ?? /* @__PURE__ */ new Error("IndexedDB failed to open."));
|
|
48
|
+
};
|
|
49
|
+
});
|
|
50
|
+
connections.set(name, opening);
|
|
51
|
+
opening.catch(() => {
|
|
52
|
+
if (connections.get(name) === opening) connections.delete(name);
|
|
53
|
+
});
|
|
54
|
+
return opening;
|
|
55
|
+
}
|
|
56
|
+
async function transact(name, stores, mode, work, retry = true) {
|
|
57
|
+
const db = await open(name);
|
|
58
|
+
let tx;
|
|
59
|
+
try {
|
|
60
|
+
tx = db.transaction(stores, mode);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
if (!retry) throw error;
|
|
63
|
+
db.close();
|
|
64
|
+
connections.delete(name);
|
|
65
|
+
return transact(name, stores, mode, work, false);
|
|
66
|
+
}
|
|
67
|
+
return new Promise((resolve, reject) => {
|
|
68
|
+
const result = work(tx);
|
|
69
|
+
tx.oncomplete = () => resolve(result());
|
|
70
|
+
tx.onerror = () => reject(tx.error ?? /* @__PURE__ */ new Error("IndexedDB transaction failed."));
|
|
71
|
+
tx.onabort = () => reject(tx.error ?? /* @__PURE__ */ new Error("IndexedDB transaction aborted."));
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function deleteByIndex(store, index, key) {
|
|
75
|
+
const request = store.index(index).openKeyCursor(IDBKeyRange.only(key));
|
|
76
|
+
request.onsuccess = () => {
|
|
77
|
+
const cursor = request.result;
|
|
78
|
+
if (!cursor) return;
|
|
79
|
+
store.delete(cursor.primaryKey);
|
|
80
|
+
cursor.continue();
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
let lastOrder = 0;
|
|
84
|
+
function createIndexedDbBoardReplicaStorage(scope, options = {}) {
|
|
85
|
+
const name = options.database ?? DATABASE;
|
|
86
|
+
const board = JSON.stringify([
|
|
87
|
+
scope.userKey,
|
|
88
|
+
scope.spaceId,
|
|
89
|
+
scope.boardId
|
|
90
|
+
]);
|
|
91
|
+
return {
|
|
92
|
+
listPending: () => transact(name, ["pending"], "readonly", (tx) => {
|
|
93
|
+
const request = tx.objectStore("pending").index("board").getAll(IDBKeyRange.only(board));
|
|
94
|
+
return () => request.result.sort((a, b) => a.order - b.order).map(({ mutationId, patch }) => ({
|
|
95
|
+
mutationId,
|
|
96
|
+
patch
|
|
97
|
+
}));
|
|
98
|
+
}),
|
|
99
|
+
putPending: ({ mutationId, patch }) => transact(name, ["pending"], "readwrite", (tx) => {
|
|
100
|
+
lastOrder = Math.max(Date.now(), lastOrder + 1);
|
|
101
|
+
const record = {
|
|
102
|
+
board,
|
|
103
|
+
mutationId,
|
|
104
|
+
userKey: scope.userKey,
|
|
105
|
+
order: lastOrder,
|
|
106
|
+
patch
|
|
107
|
+
};
|
|
108
|
+
tx.objectStore("pending").put(record);
|
|
109
|
+
return () => void 0;
|
|
110
|
+
}),
|
|
111
|
+
deletePending: (mutationId) => transact(name, ["pending"], "readwrite", (tx) => {
|
|
112
|
+
tx.objectStore("pending").delete([board, mutationId]);
|
|
113
|
+
return () => void 0;
|
|
114
|
+
}),
|
|
115
|
+
readDocument: () => transact(name, ["documents"], "readonly", (tx) => {
|
|
116
|
+
const request = tx.objectStore("documents").get(board);
|
|
117
|
+
return () => {
|
|
118
|
+
const record = request.result;
|
|
119
|
+
return record ? {
|
|
120
|
+
version: record.version,
|
|
121
|
+
document: record.document
|
|
122
|
+
} : null;
|
|
123
|
+
};
|
|
124
|
+
}),
|
|
125
|
+
writeDocument: (version, document) => transact(name, ["documents"], "readwrite", (tx) => {
|
|
126
|
+
const store = tx.objectStore("documents");
|
|
127
|
+
const request = store.get(board);
|
|
128
|
+
request.onsuccess = () => {
|
|
129
|
+
const current = request.result;
|
|
130
|
+
if (current && current.version > version) return;
|
|
131
|
+
const record = {
|
|
132
|
+
board,
|
|
133
|
+
userKey: scope.userKey,
|
|
134
|
+
version,
|
|
135
|
+
document
|
|
136
|
+
};
|
|
137
|
+
store.put(record);
|
|
138
|
+
};
|
|
139
|
+
return () => void 0;
|
|
140
|
+
})
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
async function clearBoardReplicaStorage(options = {}) {
|
|
144
|
+
const { userKey } = options;
|
|
145
|
+
await transact(options.database ?? DATABASE, ["documents", "pending"], "readwrite", (tx) => {
|
|
146
|
+
for (const name of ["documents", "pending"]) {
|
|
147
|
+
const store = tx.objectStore(name);
|
|
148
|
+
if (userKey === void 0) store.clear();
|
|
149
|
+
else deleteByIndex(store, "user", userKey);
|
|
150
|
+
}
|
|
151
|
+
return () => void 0;
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
//#endregion
|
|
155
|
+
export { clearBoardReplicaStorage, createIndexedDbBoardReplicaStorage };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ModelFormat } from "../../protocol/dist/fs/mime.js";
|
|
2
2
|
import { BoardSceneItem } from "../model/scene.js";
|
|
3
|
-
import { BoardAssetMedia } from "../model/asset-key.js";
|
|
3
|
+
import { BoardAssetMedia, BoardAssetRef } from "../model/asset-key.js";
|
|
4
4
|
import { BoardAssetUrlOptions } from "../model/media-playback.js";
|
|
5
5
|
import "../model/index.js";
|
|
6
6
|
import { LruBudget } from "./lru.js";
|
|
@@ -25,6 +25,7 @@ type BoardModelPreviews = {
|
|
|
25
25
|
type BoardAssetManager = {
|
|
26
26
|
assetKey: (item: BoardSceneItem) => string | null;
|
|
27
27
|
invalidatePath: (path: string) => void;
|
|
28
|
+
invalidateItemAssets: () => void;
|
|
28
29
|
requestItem: (item: BoardSceneItem, edge?: number) => void;
|
|
29
30
|
/** World point used to prioritize queued loads. */
|
|
30
31
|
focus: (point: {
|
|
@@ -33,25 +34,35 @@ type BoardAssetManager = {
|
|
|
33
34
|
} | null) => void;
|
|
34
35
|
getTexture: (key: string) => Texture | null;
|
|
35
36
|
getNaturalSize: (key: string) => Size | null;
|
|
37
|
+
getTone: (key: string) => number | null;
|
|
36
38
|
hasError: (key: string) => boolean;
|
|
37
39
|
acquire: (key: string) => void;
|
|
38
40
|
release: (key: string) => void;
|
|
41
|
+
prefetch?: (requests: readonly BoardAssetPrefetch[]) => void;
|
|
39
42
|
withTextures: <T>(items: BoardSceneItem[], use: (textures: Map<string, Texture>) => T | Promise<T>, options?: {
|
|
40
43
|
timeoutMs?: number;
|
|
41
44
|
edge?: (item: BoardSceneItem) => number;
|
|
42
45
|
}) => Promise<T>;
|
|
43
|
-
subscribe: (listener: (key: string) => void) => () => void;
|
|
44
|
-
/** Current texture and cooling-cache usage. */
|
|
46
|
+
subscribe: (listener: (key: string, change: BoardAssetChange) => void) => () => void;
|
|
45
47
|
stats: () => {
|
|
46
48
|
textures: number;
|
|
47
49
|
cooling: number;
|
|
48
50
|
bytes: number;
|
|
51
|
+
loading?: number;
|
|
52
|
+
prefetching?: number;
|
|
49
53
|
};
|
|
50
54
|
destroy: () => void;
|
|
51
55
|
};
|
|
56
|
+
type BoardAssetPrefetch = {
|
|
57
|
+
item: BoardSceneItem;
|
|
58
|
+
edge: number;
|
|
59
|
+
};
|
|
60
|
+
type BoardAssetChange = "texture" | "tone";
|
|
52
61
|
type BoardAssetManagerOptions = {
|
|
53
62
|
/** Resolve a Space file path to a URL a texture can load from; null when unavailable. */
|
|
54
63
|
resolveFileUrl: (path: string, options?: BoardAssetUrlOptions) => Promise<string | null>;
|
|
64
|
+
/** undefined keeps the built-in rule, null shows none; cached until `invalidateItemAssets`. */
|
|
65
|
+
itemAsset?: (item: BoardSceneItem) => BoardAssetRef | null | undefined;
|
|
55
66
|
concurrency?: number;
|
|
56
67
|
videoConcurrency?: number;
|
|
57
68
|
loadVideoPreviews?: boolean;
|
|
@@ -62,8 +73,9 @@ type BoardAssetManagerOptions = {
|
|
|
62
73
|
unloadTexture?: (url: string, texture: Texture | null, media: BoardAssetMedia) => Promise<void>;
|
|
63
74
|
/** An unshared copy of an image texture at `edge`; null keeps evicting outright. */
|
|
64
75
|
shrinkTexture?: (texture: Texture, edge: number) => Promise<Texture | null>;
|
|
76
|
+
readTone?: ((texture: Texture) => Promise<number | null>) | null;
|
|
65
77
|
now?: () => number;
|
|
66
78
|
};
|
|
67
79
|
declare function createBoardAssetManager(options: BoardAssetManagerOptions): BoardAssetManager;
|
|
68
80
|
//#endregion
|
|
69
|
-
export { BoardAssetManager, BoardAssetManagerOptions, BoardModelPreviewRequest, BoardModelPreviews, createBoardAssetManager };
|
|
81
|
+
export { BoardAssetChange, BoardAssetManager, BoardAssetManagerOptions, BoardAssetPrefetch, BoardModelPreviewRequest, BoardModelPreviews, createBoardAssetManager };
|