mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
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:
56 files changed
+23645
No files matched your search
@@ -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),
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user