@vibes.diy/base 14.3.45 → 14.3.47
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/components/FilesPanelView.d.ts +19 -1
- package/components/FilesPanelView.js +52 -2
- package/components/FilesPanelView.js.map +1 -1
- package/components/HandlePickerMenu.d.ts +1 -0
- package/components/HandlePickerMenu.js.map +1 -1
- package/components/ImgGen.d.ts +5 -1
- package/components/ImgGen.js +23 -5
- package/components/ImgGen.js.map +1 -1
- package/components/NotificationDetailView.d.ts +15 -0
- package/components/NotificationDetailView.js +41 -3
- package/components/NotificationDetailView.js.map +1 -1
- package/components/ViewerTagView.d.ts +5 -1
- package/components/ViewerTagView.js +58 -12
- package/components/ViewerTagView.js.map +1 -1
- package/components/vibe-menu/cards/ShareAppDrill.d.ts +21 -0
- package/components/vibe-menu/cards/ShareAppDrill.js +162 -0
- package/components/vibe-menu/cards/ShareAppDrill.js.map +1 -0
- package/components/vibe-menu/cards/ShareCard.js +4 -4
- package/components/vibe-menu/cards/ShareCard.js.map +1 -1
- package/components/vibe-menu/cards/ShareDrills.d.ts +2 -2
- package/components/vibe-menu/cards/ShareDrills.js +5 -0
- package/components/vibe-menu/cards/ShareDrills.js.map +1 -1
- package/components/vibe-menu/cards/ShareLinkRows.d.ts +3 -2
- package/components/vibe-menu/cards/ShareLinkRows.js +5 -3
- package/components/vibe-menu/cards/ShareLinkRows.js.map +1 -1
- package/components/vibe-menu/cards/share-card.styles.d.ts +1 -1
- package/components/vibe-menu/cards/share-card.styles.js +22 -0
- package/components/vibe-menu/cards/share-card.styles.js.map +1 -1
- package/components/vibe-menu/cards/share-copy.d.ts +5 -3
- package/components/vibe-menu/cards/share-copy.js +7 -6
- package/components/vibe-menu/cards/share-copy.js.map +1 -1
- package/components/vibe-menu/index.d.ts +2 -0
- package/components/vibe-menu/index.js +2 -0
- package/components/vibe-menu/index.js.map +1 -1
- package/components/vibe-menu/menu-state.d.ts +1 -1
- package/components/vibe-menu/menu-state.js +1 -0
- package/components/vibe-menu/menu-state.js.map +1 -1
- package/components/vibe-menu/parts/Glyph.d.ts +1 -1
- package/components/vibe-menu/parts/Glyph.js +5 -1
- package/components/vibe-menu/parts/Glyph.js.map +1 -1
- package/components/vibe-menu/share-fixtures.d.ts +3 -1
- package/components/vibe-menu/share-fixtures.js +11 -0
- package/components/vibe-menu/share-fixtures.js.map +1 -1
- package/components/vibe-menu/share-image.d.ts +17 -0
- package/components/vibe-menu/share-image.js +194 -0
- package/components/vibe-menu/share-image.js.map +1 -0
- package/components/vibe-menu/slices.d.ts +11 -0
- package/components/vibe-menu/slices.js.map +1 -1
- package/hooks/img-gen/local-pictures.d.ts +10 -0
- package/hooks/img-gen/local-pictures.js +31 -0
- package/hooks/img-gen/local-pictures.js.map +1 -0
- package/hooks/img-gen/picture-bytes.d.ts +54 -0
- package/hooks/img-gen/picture-bytes.js +312 -0
- package/hooks/img-gen/picture-bytes.js.map +1 -0
- package/hooks/img-gen/use-img-gen.d.ts +9 -1
- package/hooks/img-gen/use-img-gen.js +109 -8
- package/hooks/img-gen/use-img-gen.js.map +1 -1
- package/hooks/img-gen/use-picture-src.d.ts +13 -0
- package/hooks/img-gen/use-picture-src.js +94 -0
- package/hooks/img-gen/use-picture-src.js.map +1 -0
- package/package.json +5 -4
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import { exception2Result } from "@adviser/cement";
|
|
2
|
+
import { type } from "arktype";
|
|
3
|
+
import { FILES_ASSET_STATE_HEADER, FILES_UPLOAD_ID_HEADER, KEEPABLE_ASSET_STATES } from "@vibes.diy/vibe-types";
|
|
4
|
+
import { vibe } from "@vibes.diy/vibe-runtime";
|
|
5
|
+
function defaultWarn(event, fields) {
|
|
6
|
+
vibe.log("warn", event, fields);
|
|
7
|
+
}
|
|
8
|
+
const RASTER_IMAGE_TYPES = ["image/png", "image/jpeg", "image/webp", "image/gif", "image/avif", "image/bmp"];
|
|
9
|
+
export function isRasterImageType(mime) {
|
|
10
|
+
return RASTER_IMAGE_TYPES.includes(mime.split(";")[0].trim().toLowerCase());
|
|
11
|
+
}
|
|
12
|
+
const DEFAULT_MEMORY_BYTES = 48 * 1024 * 1024;
|
|
13
|
+
const DEFAULT_LOCAL_LOOKUP_MS = 1500;
|
|
14
|
+
class MemoryTier {
|
|
15
|
+
max;
|
|
16
|
+
entries = new Map();
|
|
17
|
+
total = 0;
|
|
18
|
+
constructor(max) {
|
|
19
|
+
this.max = max;
|
|
20
|
+
}
|
|
21
|
+
get(id) {
|
|
22
|
+
const b = this.entries.get(id);
|
|
23
|
+
if (b === undefined)
|
|
24
|
+
return undefined;
|
|
25
|
+
this.entries.delete(id);
|
|
26
|
+
this.entries.set(id, b);
|
|
27
|
+
return b;
|
|
28
|
+
}
|
|
29
|
+
delete(id) {
|
|
30
|
+
const b = this.entries.get(id);
|
|
31
|
+
if (b === undefined)
|
|
32
|
+
return;
|
|
33
|
+
this.entries.delete(id);
|
|
34
|
+
this.total -= b.size;
|
|
35
|
+
}
|
|
36
|
+
set(id, b) {
|
|
37
|
+
const prior = this.entries.get(id);
|
|
38
|
+
if (prior !== undefined) {
|
|
39
|
+
this.total -= prior.size;
|
|
40
|
+
this.entries.delete(id);
|
|
41
|
+
}
|
|
42
|
+
if (b.size > this.max)
|
|
43
|
+
return;
|
|
44
|
+
this.entries.set(id, b);
|
|
45
|
+
this.total += b.size;
|
|
46
|
+
for (const [oldId, old] of this.entries) {
|
|
47
|
+
if (this.total <= this.max)
|
|
48
|
+
break;
|
|
49
|
+
this.entries.delete(oldId);
|
|
50
|
+
this.total -= old.size;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const TIMED_OUT = Symbol("timed-out");
|
|
55
|
+
function withinMs(p, ms) {
|
|
56
|
+
return new Promise((resolve, reject) => {
|
|
57
|
+
const timer = setTimeout(() => resolve(TIMED_OUT), ms);
|
|
58
|
+
p.then((v) => {
|
|
59
|
+
clearTimeout(timer);
|
|
60
|
+
resolve(v);
|
|
61
|
+
}, (e) => {
|
|
62
|
+
clearTimeout(timer);
|
|
63
|
+
reject(e);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
export function createPictureStore(opts) {
|
|
68
|
+
const fetcher = opts.fetcher ?? defaultFetch;
|
|
69
|
+
const warn = opts.warn ?? defaultWarn;
|
|
70
|
+
const memory = new MemoryTier(opts.memoryBytes ?? DEFAULT_MEMORY_BYTES);
|
|
71
|
+
const lookupMs = opts.localLookupMs ?? DEFAULT_LOCAL_LOOKUP_MS;
|
|
72
|
+
const filesPrefix = `${opts.assetOrigin}/_files/`;
|
|
73
|
+
const inFlight = new Map();
|
|
74
|
+
const notKeepable = new Map();
|
|
75
|
+
const unconfirmed = new Set();
|
|
76
|
+
const confirmInFlight = new Map();
|
|
77
|
+
async function keep(uploadId, blob) {
|
|
78
|
+
if (isRasterImageType(blob.type) === false) {
|
|
79
|
+
warn("picture-bytes-not-raster", { uploadId, type: blob.type });
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
memory.set(uploadId, blob);
|
|
83
|
+
const rPut = await exception2Result(() => opts.bytes.put(uploadId, blob));
|
|
84
|
+
if (rPut.isErr())
|
|
85
|
+
warn("picture-bytes-put-failed", { uploadId, message: rPut.Err().message });
|
|
86
|
+
}
|
|
87
|
+
async function seed(uploadId, blob) {
|
|
88
|
+
if (isRasterImageType(blob.type) === false) {
|
|
89
|
+
warn("picture-bytes-not-raster", { uploadId, type: blob.type });
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
memory.set(uploadId, blob);
|
|
93
|
+
unconfirmed.add(uploadId);
|
|
94
|
+
}
|
|
95
|
+
function dropUnconfirmed(uploadId) {
|
|
96
|
+
if (unconfirmed.delete(uploadId))
|
|
97
|
+
memory.delete(uploadId);
|
|
98
|
+
}
|
|
99
|
+
function judge(uploadId, res, type) {
|
|
100
|
+
const servedUpload = res.headers.get(FILES_UPLOAD_ID_HEADER);
|
|
101
|
+
const state = res.headers.get(FILES_ASSET_STATE_HEADER);
|
|
102
|
+
const named = servedUpload === uploadId;
|
|
103
|
+
const rasterOk = type === undefined ? true : isRasterImageType(type);
|
|
104
|
+
return { named, keepable: named && state !== null && KEEPABLE_ASSET_STATES.includes(state) && rasterOk };
|
|
105
|
+
}
|
|
106
|
+
async function headConfirm(uploadId, url) {
|
|
107
|
+
if (unconfirmed.has(uploadId) === false)
|
|
108
|
+
return "none";
|
|
109
|
+
if (url.startsWith(filesPrefix) === false)
|
|
110
|
+
return "unknown";
|
|
111
|
+
const rRes = await exception2Result(() => fetcher(url, { method: "HEAD", credentials: "include" }));
|
|
112
|
+
if (rRes.isErr()) {
|
|
113
|
+
warn("picture-bytes-confirm-failed", { uploadId, message: rRes.Err().message });
|
|
114
|
+
return "unknown";
|
|
115
|
+
}
|
|
116
|
+
const res = rRes.Ok();
|
|
117
|
+
if (res.ok === false)
|
|
118
|
+
return "unknown";
|
|
119
|
+
const seeded = memory.get(uploadId);
|
|
120
|
+
const verdict = judge(uploadId, res, seeded?.type);
|
|
121
|
+
if (verdict.keepable === false || seeded === undefined) {
|
|
122
|
+
dropUnconfirmed(uploadId);
|
|
123
|
+
return "dropped";
|
|
124
|
+
}
|
|
125
|
+
unconfirmed.delete(uploadId);
|
|
126
|
+
await keep(uploadId, seeded);
|
|
127
|
+
return "kept";
|
|
128
|
+
}
|
|
129
|
+
function confirm(ref) {
|
|
130
|
+
const pending = confirmInFlight.get(ref.uploadId);
|
|
131
|
+
if (pending !== undefined)
|
|
132
|
+
return pending;
|
|
133
|
+
const p = headConfirm(ref.uploadId, ref.url).finally(() => confirmInFlight.delete(ref.uploadId));
|
|
134
|
+
confirmInFlight.set(ref.uploadId, p);
|
|
135
|
+
return p;
|
|
136
|
+
}
|
|
137
|
+
async function lookup(uploadId) {
|
|
138
|
+
const hot = memory.get(uploadId);
|
|
139
|
+
if (hot !== undefined)
|
|
140
|
+
return hot;
|
|
141
|
+
const rStored = await exception2Result(() => withinMs(opts.bytes.get(uploadId), lookupMs));
|
|
142
|
+
if (rStored.isErr()) {
|
|
143
|
+
warn("picture-bytes-get-failed", { uploadId, message: rStored.Err().message });
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
const stored = rStored.Ok();
|
|
147
|
+
if (stored === TIMED_OUT) {
|
|
148
|
+
warn("picture-bytes-get-slow", { uploadId, ms: lookupMs });
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
151
|
+
if (stored === undefined)
|
|
152
|
+
return undefined;
|
|
153
|
+
if (isRasterImageType(stored.type) === false)
|
|
154
|
+
return undefined;
|
|
155
|
+
memory.set(uploadId, stored);
|
|
156
|
+
return stored;
|
|
157
|
+
}
|
|
158
|
+
async function download(uploadId, url) {
|
|
159
|
+
if (url.startsWith(filesPrefix) === false)
|
|
160
|
+
return { outcome: "unavailable" };
|
|
161
|
+
const rRes = await exception2Result(() => fetcher(url, { credentials: "include" }));
|
|
162
|
+
if (rRes.isErr()) {
|
|
163
|
+
warn("picture-bytes-fetch-failed", { uploadId, message: rRes.Err().message });
|
|
164
|
+
return { outcome: "unavailable" };
|
|
165
|
+
}
|
|
166
|
+
const res = rRes.Ok();
|
|
167
|
+
if (res.ok === false) {
|
|
168
|
+
warn("picture-bytes-fetch-status", { uploadId, status: res.status });
|
|
169
|
+
return { outcome: "unavailable" };
|
|
170
|
+
}
|
|
171
|
+
const servedUpload = res.headers.get(FILES_UPLOAD_ID_HEADER);
|
|
172
|
+
if (servedUpload !== null && servedUpload !== uploadId) {
|
|
173
|
+
warn("picture-bytes-other-upload", { uploadId, servedUpload });
|
|
174
|
+
dropUnconfirmed(uploadId);
|
|
175
|
+
return { outcome: "other-upload" };
|
|
176
|
+
}
|
|
177
|
+
const rBlob = await exception2Result(() => res.blob());
|
|
178
|
+
if (rBlob.isErr()) {
|
|
179
|
+
warn("picture-bytes-body-failed", { uploadId, message: rBlob.Err().message });
|
|
180
|
+
return { outcome: "unavailable" };
|
|
181
|
+
}
|
|
182
|
+
const blob = rBlob.Ok();
|
|
183
|
+
const verdict = judge(uploadId, res, blob.type);
|
|
184
|
+
if (verdict.keepable === false) {
|
|
185
|
+
notKeepable.set(uploadId, verdict.named);
|
|
186
|
+
dropUnconfirmed(uploadId);
|
|
187
|
+
return { outcome: "not-kept", blob, confirmed: verdict.named };
|
|
188
|
+
}
|
|
189
|
+
unconfirmed.delete(uploadId);
|
|
190
|
+
await keep(uploadId, blob);
|
|
191
|
+
return { outcome: "kept", blob };
|
|
192
|
+
}
|
|
193
|
+
function fill(ref) {
|
|
194
|
+
const pending = inFlight.get(ref.uploadId);
|
|
195
|
+
if (pending !== undefined)
|
|
196
|
+
return pending;
|
|
197
|
+
const known = notKeepable.get(ref.uploadId);
|
|
198
|
+
if (known !== undefined)
|
|
199
|
+
return Promise.resolve({ outcome: "known-not-keepable", confirmed: known });
|
|
200
|
+
const p = download(ref.uploadId, ref.url).finally(() => inFlight.delete(ref.uploadId));
|
|
201
|
+
inFlight.set(ref.uploadId, p);
|
|
202
|
+
return p;
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
peek: (uploadId) => memory.get(uploadId),
|
|
206
|
+
lookup,
|
|
207
|
+
fill,
|
|
208
|
+
seed,
|
|
209
|
+
isUnconfirmed: (uploadId) => unconfirmed.has(uploadId),
|
|
210
|
+
confirm,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
function defaultFetch(input, init) {
|
|
214
|
+
return fetch(input, init);
|
|
215
|
+
}
|
|
216
|
+
export const PICTURE_BYTES_DB = "vibes-picture-bytes";
|
|
217
|
+
const BYTES = "bytes";
|
|
218
|
+
const META = "meta";
|
|
219
|
+
const DEFAULT_MAX_BYTES = 160 * 1024 * 1024;
|
|
220
|
+
const bytesRow = type({ buf: type.instanceOf(ArrayBuffer), type: "string" });
|
|
221
|
+
const metaRow = type({ uploadId: "string", size: "number", lastUsed: "number" });
|
|
222
|
+
const metaRowId = type({ uploadId: "string" });
|
|
223
|
+
function req(r) {
|
|
224
|
+
return new Promise((resolve, reject) => {
|
|
225
|
+
r.onsuccess = () => resolve(r.result);
|
|
226
|
+
r.onerror = () => reject(r.error ?? new Error("indexeddb request failed"));
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
function done(tx) {
|
|
230
|
+
return new Promise((resolve, reject) => {
|
|
231
|
+
tx.oncomplete = () => resolve();
|
|
232
|
+
tx.onerror = () => reject(tx.error ?? new Error("indexeddb transaction failed"));
|
|
233
|
+
tx.onabort = () => reject(tx.error ?? new Error("indexeddb transaction aborted"));
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
export function idbPictureBytes(opts = {}) {
|
|
237
|
+
const factory = opts.indexedDB ?? (typeof indexedDB === "undefined" ? undefined : indexedDB);
|
|
238
|
+
const maxBytes = opts.maxBytes ?? DEFAULT_MAX_BYTES;
|
|
239
|
+
const now = opts.now ?? Date.now;
|
|
240
|
+
let dbp;
|
|
241
|
+
function open() {
|
|
242
|
+
if (factory === undefined)
|
|
243
|
+
return Promise.reject(new Error("indexedDB unavailable"));
|
|
244
|
+
if (dbp === undefined) {
|
|
245
|
+
const r = factory.open(opts.dbName ?? PICTURE_BYTES_DB, 1);
|
|
246
|
+
r.onupgradeneeded = () => {
|
|
247
|
+
const db = r.result;
|
|
248
|
+
if (db.objectStoreNames.contains(BYTES) === false)
|
|
249
|
+
db.createObjectStore(BYTES);
|
|
250
|
+
if (db.objectStoreNames.contains(META) === false)
|
|
251
|
+
db.createObjectStore(META, { keyPath: "uploadId" });
|
|
252
|
+
};
|
|
253
|
+
const opening = req(r);
|
|
254
|
+
dbp = opening;
|
|
255
|
+
opening.then(undefined, forgetFailedOpen);
|
|
256
|
+
}
|
|
257
|
+
return dbp;
|
|
258
|
+
}
|
|
259
|
+
function forgetFailedOpen() {
|
|
260
|
+
dbp = undefined;
|
|
261
|
+
}
|
|
262
|
+
async function get(uploadId) {
|
|
263
|
+
const db = await open();
|
|
264
|
+
const tx = db.transaction([BYTES, META], "readwrite");
|
|
265
|
+
const row = bytesRow(await req(tx.objectStore(BYTES).get(uploadId)));
|
|
266
|
+
if (row instanceof type.errors) {
|
|
267
|
+
await done(tx);
|
|
268
|
+
return undefined;
|
|
269
|
+
}
|
|
270
|
+
tx.objectStore(META).put({ uploadId, size: row.buf.byteLength, lastUsed: now() });
|
|
271
|
+
await done(tx);
|
|
272
|
+
return new Blob([row.buf], { type: row.type });
|
|
273
|
+
}
|
|
274
|
+
async function put(uploadId, blob) {
|
|
275
|
+
if (blob.size > maxBytes)
|
|
276
|
+
return;
|
|
277
|
+
const buf = await blob.arrayBuffer();
|
|
278
|
+
const db = await open();
|
|
279
|
+
const tx = db.transaction([BYTES, META], "readwrite");
|
|
280
|
+
const bytes = tx.objectStore(BYTES);
|
|
281
|
+
const meta = tx.objectStore(META);
|
|
282
|
+
bytes.put({ buf, type: blob.type }, uploadId);
|
|
283
|
+
meta.put({ uploadId, size: buf.byteLength, lastUsed: now() });
|
|
284
|
+
const rows = [];
|
|
285
|
+
for (const raw of await req(meta.getAll())) {
|
|
286
|
+
const m = metaRow(raw);
|
|
287
|
+
if (m instanceof type.errors) {
|
|
288
|
+
const id = metaRowId(raw);
|
|
289
|
+
if (id instanceof type.errors === false) {
|
|
290
|
+
bytes.delete(id.uploadId);
|
|
291
|
+
meta.delete(id.uploadId);
|
|
292
|
+
}
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
rows.push(m);
|
|
296
|
+
}
|
|
297
|
+
rows.sort((a, b) => a.lastUsed - b.lastUsed);
|
|
298
|
+
let total = rows.reduce((n, m) => n + m.size, 0);
|
|
299
|
+
for (const m of rows) {
|
|
300
|
+
if (total <= maxBytes)
|
|
301
|
+
break;
|
|
302
|
+
if (m.uploadId === uploadId)
|
|
303
|
+
continue;
|
|
304
|
+
bytes.delete(m.uploadId);
|
|
305
|
+
meta.delete(m.uploadId);
|
|
306
|
+
total -= m.size;
|
|
307
|
+
}
|
|
308
|
+
await done(tx);
|
|
309
|
+
}
|
|
310
|
+
return { get, put };
|
|
311
|
+
}
|
|
312
|
+
//# sourceMappingURL=picture-bytes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"picture-bytes.js","sourceRoot":"","sources":["../../../jsr/hooks/img-gen/picture-bytes.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,8 @@ export type UseFireproofHook = typeof useFireproof;
|
|
|
3
3
|
export type UseVibeContextHook = typeof useVibeContext;
|
|
4
4
|
import type { ImgGenRequestOptions, ImgGenResult, UseImgGenOptions, UseImgGenResult } from "@vibes.diy/vibe-types";
|
|
5
5
|
import { Result } from "@adviser/cement";
|
|
6
|
+
import { type LocalFileUrl } from "./local-pictures.js";
|
|
7
|
+
import type { PictureStore } from "./picture-bytes.js";
|
|
6
8
|
export declare function __setImgGenProbeDeadlineMsForTests(ms: number | undefined): void;
|
|
7
9
|
export declare function __setImgGenCommitReprobeDelaysMsForTests(ms: readonly number[] | undefined): void;
|
|
8
10
|
interface InjectedDeps {
|
|
@@ -10,7 +12,13 @@ interface InjectedDeps {
|
|
|
10
12
|
imgGen?: (prompt: string, opts?: ImgGenRequestOptions) => Promise<Result<ImgGenResult>>;
|
|
11
13
|
confirmedMediaProbe?: ConfirmedMediaProbe | null;
|
|
12
14
|
useFireproof?: UseFireproofHook;
|
|
15
|
+
localFileUrl?: LocalFileUrl | null;
|
|
16
|
+
pictures?: PictureStore | null;
|
|
13
17
|
useVibeContext?: UseVibeContextHook;
|
|
14
18
|
}
|
|
15
|
-
export
|
|
19
|
+
export interface UseImgGenDisplayResult extends UseImgGenResult {
|
|
20
|
+
readonly mintedUrls: ReadonlySet<string>;
|
|
21
|
+
readonly reportUnavailable: (uploadId: string) => void;
|
|
22
|
+
}
|
|
23
|
+
export declare function useImgGen(opts: Partial<UseImgGenOptions> & InjectedDeps): UseImgGenDisplayResult;
|
|
16
24
|
export {};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { useState, useEffect, useMemo, useRef } from "react";
|
|
1
|
+
import { useState, useEffect, useMemo, useRef, useCallback } from "react";
|
|
2
2
|
import { useFireproof, imgGen as defaultImgGen, confirmedMediaProbe as defaultConfirmedMediaProbe, useVibeContext, getRegisteredVibeApi, vibe, decorateFiles, IMG_GEN_SOURCE_UNUSABLE, } from "@vibes.diy/vibe-runtime";
|
|
3
3
|
import { IMG_GEN_CANCELLED, IMG_GEN_NEEDS_TAP, IMG_GEN_UNREACHABLE, IMG_GEN_UNREACHABLE_MESSAGE, buildMediaPointerDoc, buildMediaVersionDoc, mediaDbName, mediaPointerDocId, mediaVersionDocId, } from "@vibes.diy/vibe-types";
|
|
4
4
|
import { exception2Result, Result } from "@adviser/cement";
|
|
5
|
+
import { type } from "arktype";
|
|
6
|
+
import { registeredLocalFileUrl, registeredPictureStore } from "./local-pictures.js";
|
|
5
7
|
const PROMPT_KEY = "p1";
|
|
6
8
|
function isValidVersionDoc(d) {
|
|
7
9
|
if (d.type !== "version")
|
|
@@ -40,6 +42,41 @@ function withLocalPreviews(doc, previews) {
|
|
|
40
42
|
}
|
|
41
43
|
return changed ? { ...doc, _files: files } : doc;
|
|
42
44
|
}
|
|
45
|
+
function withLocalUrls(doc, localUrls) {
|
|
46
|
+
const minted = new Set();
|
|
47
|
+
if (doc === null || localUrls.size === 0 || doc._files === undefined)
|
|
48
|
+
return { doc, minted };
|
|
49
|
+
const files = {};
|
|
50
|
+
for (const [key, f] of Object.entries(doc._files)) {
|
|
51
|
+
const url = f.url === undefined && f.uploadId !== undefined ? localUrls.get(localUrlKey(key, f.uploadId)) : undefined;
|
|
52
|
+
if (url !== undefined) {
|
|
53
|
+
files[key] = { ...f, url };
|
|
54
|
+
minted.add(url);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
files[key] = f;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return minted.size > 0 ? { doc: decorateFiles({ ...doc, _files: files }), minted } : { doc, minted };
|
|
61
|
+
}
|
|
62
|
+
function localUrlKey(fileKey, uploadId) {
|
|
63
|
+
return `${fileKey}\u0000${uploadId}`;
|
|
64
|
+
}
|
|
65
|
+
const localRow = type({ _id: "string", _files: "Record<string, unknown>" });
|
|
66
|
+
const localFileEntry = type({ uploadId: "string > 0", "url?": "unknown" });
|
|
67
|
+
function noteLocalUrls(args) {
|
|
68
|
+
for (const raw of args.docs) {
|
|
69
|
+
const d = localRow(raw);
|
|
70
|
+
if (d instanceof type.errors)
|
|
71
|
+
continue;
|
|
72
|
+
for (const [key, rawEntry] of Object.entries(d._files)) {
|
|
73
|
+
const f = localFileEntry(rawEntry);
|
|
74
|
+
if (f instanceof type.errors || f.url !== undefined)
|
|
75
|
+
continue;
|
|
76
|
+
args.into.set(localUrlKey(key, f.uploadId), args.mint({ dbName: args.dbName, docId: d._id, key, uploadId: f.uploadId }));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
43
80
|
function synthesizeMediaDocument(hostDocId, versionDocs, pointer) {
|
|
44
81
|
const versions = versionDocs.map((vd) => {
|
|
45
82
|
const fileKey = Object.keys(vd._files)[0];
|
|
@@ -182,7 +219,9 @@ async function readBackFromServer(args) {
|
|
|
182
219
|
const IMG_GEN_MAX_REKEEPS = 3;
|
|
183
220
|
const IMG_GEN_UNKEPT_MESSAGE = "This picture wasn't saved — another device added a version at the same moment. Please try again.";
|
|
184
221
|
export function useImgGen(opts) {
|
|
185
|
-
const { prompt, _id, database = "ImgGen", skip = false, generationId, inputImage, model, imgGen = defaultImgGen, temporaryDraft = getRegisteredVibeApi()?.temporaryData === true, confirmedMediaProbe = defaultConfirmedMediaProbe, useFireproof: useFireproofImpl = useFireproof, useVibeContext: useVibeContextImpl = useVibeContext, tapGenerationId, } = opts;
|
|
222
|
+
const { prompt, _id, database = "ImgGen", skip = false, generationId, inputImage, model, imgGen = defaultImgGen, temporaryDraft = getRegisteredVibeApi()?.temporaryData === true, confirmedMediaProbe = defaultConfirmedMediaProbe, useFireproof: useFireproofImpl = useFireproof, useVibeContext: useVibeContextImpl = useVibeContext, tapGenerationId, localFileUrl: localFileUrlOpt = registeredLocalFileUrl(), pictures: picturesOpt = registeredPictureStore(), } = opts;
|
|
223
|
+
const mintLocal = temporaryDraft || localFileUrlOpt === null ? undefined : localFileUrlOpt;
|
|
224
|
+
const pictures = picturesOpt ?? undefined;
|
|
186
225
|
const [loading, setLoading] = useState(false);
|
|
187
226
|
const [progress, setProgress] = useState(0);
|
|
188
227
|
const [error, setError] = useState(null);
|
|
@@ -222,6 +261,9 @@ export function useImgGen(opts) {
|
|
|
222
261
|
unmountSignalRef.current = ac.signal;
|
|
223
262
|
return () => ac.abort();
|
|
224
263
|
}, []);
|
|
264
|
+
const localUrlsRef = useRef(new Map());
|
|
265
|
+
const retryDisplayReadBackRef = useRef(null);
|
|
266
|
+
const seededRef = useRef(new Set());
|
|
225
267
|
const previewUrlsRef = useRef(new Map());
|
|
226
268
|
useEffect(() => {
|
|
227
269
|
const previews = previewUrlsRef.current;
|
|
@@ -282,6 +324,9 @@ export function useImgGen(opts) {
|
|
|
282
324
|
const hostDocId = _id;
|
|
283
325
|
async function loadMediaDocs() {
|
|
284
326
|
const res = await mediaDb.query("hostDocId", { key: hostDocId });
|
|
327
|
+
if (mintLocal !== undefined) {
|
|
328
|
+
noteLocalUrls({ docs: res.docs, dbName: mediaDbName(dbName), mint: mintLocal, into: localUrlsRef.current });
|
|
329
|
+
}
|
|
285
330
|
return res.docs;
|
|
286
331
|
}
|
|
287
332
|
let readStartedPending = false;
|
|
@@ -302,9 +347,14 @@ export function useImgGen(opts) {
|
|
|
302
347
|
tapSpentRef.current = generationId;
|
|
303
348
|
return;
|
|
304
349
|
}
|
|
305
|
-
|
|
350
|
+
const localLegacy = rLegacy.isOk() ? rLegacy.Ok() : null;
|
|
351
|
+
if (mintLocal !== undefined && localLegacy !== null) {
|
|
352
|
+
noteLocalUrls({ docs: [localLegacy], dbName, mint: mintLocal, into: localUrlsRef.current });
|
|
353
|
+
}
|
|
354
|
+
await decide(rMediaDocs.Ok(), localLegacy, false);
|
|
306
355
|
}
|
|
307
356
|
async function readBackForDisplay(shown, fileKey, localDocs, legacyDoc) {
|
|
357
|
+
const ourVersionId = sortVersionDocs(localDocs).find((vd) => vd._files[fileKey]?.uploadId === shown._files?.[fileKey]?.uploadId)?._id;
|
|
308
358
|
const uploadId = shown._files?.[fileKey]?.uploadId;
|
|
309
359
|
if (confirmedMediaProbe === undefined || confirmedMediaProbe === null)
|
|
310
360
|
return;
|
|
@@ -333,8 +383,17 @@ export function useImgGen(opts) {
|
|
|
333
383
|
logEvent: "imggen-display-probe-failed",
|
|
334
384
|
examine: (probedDocs, probedLegacy) => {
|
|
335
385
|
const probedVersions = sortVersionDocs(probedDocs);
|
|
336
|
-
if (holdsUpload(probedVersions, uploadId, true) === false)
|
|
386
|
+
if (holdsUpload(probedVersions, uploadId, true) === false) {
|
|
387
|
+
const taken = ourVersionId !== undefined &&
|
|
388
|
+
probedVersions.some((vd) => vd._id === ourVersionId && holdsUpload([vd], uploadId, false) === false);
|
|
389
|
+
if (taken) {
|
|
390
|
+
vibe.log("warn", "imggen-version-unkept", { docId: hostDocId, dbName, uploadId, lane: "display" });
|
|
391
|
+
setError(new Error(IMG_GEN_UNKEPT_MESSAGE));
|
|
392
|
+
setPending(false);
|
|
393
|
+
return { done: true, value: true };
|
|
394
|
+
}
|
|
337
395
|
return { done: false };
|
|
396
|
+
}
|
|
338
397
|
const composed = composeDocument({
|
|
339
398
|
hostDocId,
|
|
340
399
|
versionDocs: probedVersions,
|
|
@@ -389,12 +448,24 @@ export function useImgGen(opts) {
|
|
|
389
448
|
currentVer?.id &&
|
|
390
449
|
existingDoc._files?.[currentVer.id]) {
|
|
391
450
|
const urlPending = existingDoc._files[currentVer.id]?.url === undefined;
|
|
392
|
-
|
|
451
|
+
const currentUpload = existingDoc._files[currentVer.id]?.uploadId;
|
|
452
|
+
const shownLocally = urlPending && currentUpload !== undefined && localUrlsRef.current.has(localUrlKey(currentVer.id, currentUpload));
|
|
453
|
+
setPending(urlPending && shownLocally === false);
|
|
393
454
|
setDocument(existingDoc);
|
|
394
455
|
setNeedsTap(false);
|
|
395
456
|
if (urlPending) {
|
|
396
457
|
currentGenRef.current = null;
|
|
397
|
-
|
|
458
|
+
if (shownLocally === false)
|
|
459
|
+
await readBackForDisplay(existingDoc, currentVer.id, mediaDocs, legacyDoc);
|
|
460
|
+
else if (currentUpload !== undefined) {
|
|
461
|
+
const fileKey = currentVer.id;
|
|
462
|
+
const restart = () => {
|
|
463
|
+
displayReadBackRef.current = null;
|
|
464
|
+
void readBackForDisplay(existingDoc, fileKey, mediaDocs, legacyDoc);
|
|
465
|
+
};
|
|
466
|
+
retryDisplayReadBackRef.current = { uploadId: currentUpload, run: restart };
|
|
467
|
+
void readBackForDisplay(existingDoc, fileKey, mediaDocs, legacyDoc);
|
|
468
|
+
}
|
|
398
469
|
}
|
|
399
470
|
else {
|
|
400
471
|
const committed = committedGenRef.current;
|
|
@@ -513,7 +584,7 @@ export function useImgGen(opts) {
|
|
|
513
584
|
if (earlyPreviewRef.current !== null)
|
|
514
585
|
return;
|
|
515
586
|
const url = URL.createObjectURL(blob);
|
|
516
|
-
earlyPreviewRef.current = { genKey, url };
|
|
587
|
+
earlyPreviewRef.current = { genKey, url, blob };
|
|
517
588
|
setPreviewUrl(url);
|
|
518
589
|
},
|
|
519
590
|
}));
|
|
@@ -561,6 +632,11 @@ export function useImgGen(opts) {
|
|
|
561
632
|
else if (file.preview instanceof Blob && previewUrlsRef.current.has(file.uploadId) === false) {
|
|
562
633
|
previewUrlsRef.current.set(file.uploadId, URL.createObjectURL(file.preview));
|
|
563
634
|
}
|
|
635
|
+
const ownBytes = early?.blob ?? (file.preview instanceof Blob ? file.preview : undefined);
|
|
636
|
+
if (ownBytes !== undefined && pictures !== undefined) {
|
|
637
|
+
void pictures.seed(file.uploadId, ownBytes);
|
|
638
|
+
seededRef.current.add(file.uploadId);
|
|
639
|
+
}
|
|
564
640
|
const rRun = await exception2Result(async () => {
|
|
565
641
|
setProgress(90);
|
|
566
642
|
const showCommitted = async (uploadId, clientWrite) => {
|
|
@@ -832,12 +908,35 @@ export function useImgGen(opts) {
|
|
|
832
908
|
model,
|
|
833
909
|
imgGen,
|
|
834
910
|
confirmedMediaProbe,
|
|
911
|
+
mintLocal,
|
|
912
|
+
pictures,
|
|
835
913
|
mediaFromCache,
|
|
836
914
|
hostFromCache,
|
|
837
915
|
deferTick,
|
|
838
916
|
arrivalTick,
|
|
839
917
|
]);
|
|
840
|
-
const displayed = useMemo(() => withLocalPreviews(document, previewUrlsRef.current), [document]);
|
|
918
|
+
const { doc: displayed, minted: mintedUrls } = useMemo(() => withLocalUrls(withLocalPreviews(document, previewUrlsRef.current), localUrlsRef.current), [document]);
|
|
919
|
+
useEffect(() => {
|
|
920
|
+
if (pictures === undefined || seededRef.current.size === 0 || document?._files === undefined)
|
|
921
|
+
return;
|
|
922
|
+
for (const [key, f] of Object.entries(document._files)) {
|
|
923
|
+
const uploadId = f.uploadId;
|
|
924
|
+
if (uploadId === undefined || seededRef.current.has(uploadId) === false)
|
|
925
|
+
continue;
|
|
926
|
+
const url = f.url ?? localUrlsRef.current.get(localUrlKey(key, uploadId));
|
|
927
|
+
if (url === undefined)
|
|
928
|
+
continue;
|
|
929
|
+
void pictures.confirm({ uploadId, url }).then((answer) => {
|
|
930
|
+
if (answer !== "unknown")
|
|
931
|
+
seededRef.current.delete(uploadId);
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
}, [document, pictures]);
|
|
935
|
+
const reportUnavailable = useCallback((uploadId) => {
|
|
936
|
+
const retry = retryDisplayReadBackRef.current;
|
|
937
|
+
if (retry !== null && retry.uploadId === uploadId)
|
|
938
|
+
retry.run();
|
|
939
|
+
}, []);
|
|
841
940
|
const previewSettled = previewUrl !== undefined && (error !== null || Object.values(displayed?._files ?? {}).some((f) => f.url === previewUrl));
|
|
842
941
|
useEffect(() => {
|
|
843
942
|
if (previewSettled)
|
|
@@ -851,6 +950,8 @@ export function useImgGen(opts) {
|
|
|
851
950
|
pending,
|
|
852
951
|
needsTap,
|
|
853
952
|
...(previewUrl !== undefined ? { previewUrl } : {}),
|
|
953
|
+
mintedUrls,
|
|
954
|
+
reportUnavailable,
|
|
854
955
|
};
|
|
855
956
|
}
|
|
856
957
|
//# sourceMappingURL=use-img-gen.js.map
|