wip(mobile): checkpoint the app shell and vision mockup in progress

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VVYRAqiQj9Y1V9ZfG1RcDH
This commit is contained in:
Claude committed 2026-10-18 05:27:50 +00:00
1 parent a8b7680c7a
commit e532c5efb6
56 files changed
+23645

No files matched your search

+93
View File
@@ -0,0 +1,93 @@
/** Minimal promise wrapper over the device's IndexedDB for keys and captures. */
const DB_NAME = 'gev-mobile';
const DB_VERSION = 1;
let dbp = null;
export function openDb() {
if (dbp) return dbp;
dbp = new Promise((resolve, reject) => {
if (!('indexedDB' in globalThis)) {
reject(new Error('IndexedDB is unavailable'));
return;
}
const req = indexedDB.open(DB_NAME, DB_VERSION);
req.onupgradeneeded = () => {
const db = req.result;
if (!db.objectStoreNames.contains('keys'))
db.createObjectStore('keys', { keyPath: 'id' });
if (!db.objectStoreNames.contains('captures')) {
const s = db.createObjectStore('captures', { keyPath: 'id' });
s.createIndex('seq', 'seq');
}
if (!db.objectStoreNames.contains('media'))
db.createObjectStore('media', { keyPath: 'id' });
};
req.onsuccess = () => resolve(req.result);
req.onerror = () => reject(req.error);
});
dbp.catch(() => (dbp = null));
return dbp;
}
function wrap(req) {
return new Promise((resolve, reject) => {
req.onsuccess = () => resolve(req.result);
req.onerror = () => reject(req.error);
});
}
export async function get(store, key) {
const db = await openDb();
return wrap(db.transaction(store).objectStore(store).get(key));
}
export async function put(store, value) {
const db = await openDb();
return wrap(db.transaction(store, 'readwrite').objectStore(store).put(value));
}
export async function del(store, key) {
const db = await openDb();
return wrap(
db.transaction(store, 'readwrite').objectStore(store).delete(key),
);
}
export async function all(store) {
const db = await openDb();
return wrap(db.transaction(store).objectStore(store).getAll());
}
/** Write a capture bundle and its media atomically. */
export async function putCapture(bundle, mediaBlob) {
const db = await openDb();
return new Promise((resolve, reject) => {
const tx = db.transaction(['captures', 'media'], 'readwrite');
tx.objectStore('captures').put(bundle);
tx.objectStore('media').put({ id: bundle.id, blob: mediaBlob });
tx.oncomplete = () => resolve(bundle);
tx.onerror = () => reject(tx.error);
tx.onabort = () => reject(tx.error);
});
}
export async function lastCapture() {
const db = await openDb();
return new Promise((resolve, reject) => {
const req = db
.transaction('captures')
.objectStore('captures')
.index('seq')
.openCursor(null, 'prev');
req.onsuccess = () => resolve(req.result?.value || null);
req.onerror = () => reject(req.error);
});
}
export async function captureBySeq(seq) {
const db = await openDb();
return wrap(
db.transaction('captures').objectStore('captures').index('seq').get(seq),
);
}