display files with cache image

This commit is contained in:
m
2026-07-27 23:02:09 +02:00
parent c5a959a27b
commit e8ceb99a5d
25 changed files with 814 additions and 118 deletions
+98 -34
View File
@@ -3,58 +3,113 @@ import { LocalFileEntry, SyncStatus } from '../types';
const storage = createMMKV({ id: 'vaultdrop-local-files' });
const INDEX_KEY = 'local_files_index';
const BLOB_KEY = 'local_files_v2';
const LEGACY_INDEX_KEY = 'local_files_index';
function getAllIds(): string[] {
const raw = storage.getString(INDEX_KEY);
if (!raw) return [];
return JSON.parse(raw) as string[];
interface RegistryBlob {
entries: Record<string, LocalFileEntry>;
backendIndex: Record<string, string>;
}
function setAllIds(ids: string[]) {
storage.set(INDEX_KEY, JSON.stringify(ids));
let memoryCache: RegistryBlob | null = null;
function loadBlob(): RegistryBlob {
if (memoryCache) return memoryCache;
const raw = storage.getString(BLOB_KEY);
if (raw) {
memoryCache = JSON.parse(raw) as RegistryBlob;
return memoryCache;
}
memoryCache = migrateFromLegacy();
saveBlob(memoryCache);
return memoryCache;
}
function entryKey(id: string): string {
return `local_file_${id}`;
function saveBlob(blob: RegistryBlob) {
memoryCache = blob;
storage.set(BLOB_KEY, JSON.stringify(blob));
}
function migrateFromLegacy(): RegistryBlob {
const blob: RegistryBlob = { entries: {}, backendIndex: {} };
const rawIndex = storage.getString(LEGACY_INDEX_KEY);
if (!rawIndex) return blob;
const ids: string[] = JSON.parse(rawIndex);
for (const id of ids) {
const raw = storage.getString(`local_file_${id}`);
if (!raw) continue;
const entry: LocalFileEntry = JSON.parse(raw);
blob.entries[entry.id] = entry;
if (entry.backendFileId) {
blob.backendIndex[entry.backendFileId] = entry.id;
}
}
storage.remove(LEGACY_INDEX_KEY);
for (const id of ids) {
storage.remove(`local_file_${id}`);
}
return blob;
}
export const localFileRegistry = {
register(entry: LocalFileEntry) {
storage.set(entryKey(entry.id), JSON.stringify(entry));
const ids = getAllIds();
if (!ids.includes(entry.id)) {
setAllIds([entry.id, ...ids]);
const blob = loadBlob();
blob.entries[entry.id] = entry;
if (entry.backendFileId) {
blob.backendIndex[entry.backendFileId] = entry.id;
}
saveBlob(blob);
},
registerBatch(entries: LocalFileEntry[]) {
if (entries.length === 0) return;
const blob = loadBlob();
for (const entry of entries) {
blob.entries[entry.id] = entry;
if (entry.backendFileId) {
blob.backendIndex[entry.backendFileId] = entry.id;
}
}
saveBlob(blob);
},
get(id: string): LocalFileEntry | undefined {
const raw = storage.getString(entryKey(id));
if (!raw) return undefined;
return JSON.parse(raw) as LocalFileEntry;
return loadBlob().entries[id];
},
getByBackendId(backendId: string): LocalFileEntry | undefined {
const ids = getAllIds();
for (const id of ids) {
const entry = this.get(id);
if (entry?.backendFileId === backendId) return entry;
}
return undefined;
const blob = loadBlob();
const entryId = blob.backendIndex[backendId];
if (!entryId) return undefined;
return blob.entries[entryId];
},
getAll(): LocalFileEntry[] {
const ids = getAllIds();
return ids
.map((id) => this.get(id))
.filter((e): e is LocalFileEntry => e !== undefined);
const blob = loadBlob();
return Object.values(blob.entries);
},
update(id: string, updates: Partial<LocalFileEntry>) {
const existing = this.get(id);
const blob = loadBlob();
const existing = blob.entries[id];
if (!existing) return;
if (existing.backendFileId && updates.backendFileId === undefined && updates.syncStatus === 'cloud') {
delete blob.backendIndex[existing.backendFileId];
}
const updated = { ...existing, ...updates };
storage.set(entryKey(id), JSON.stringify(updated));
blob.entries[id] = updated;
if (updated.backendFileId) {
blob.backendIndex[updated.backendFileId] = id;
}
saveBlob(blob);
},
updateSyncStatus(id: string, syncStatus: SyncStatus) {
@@ -66,17 +121,26 @@ export const localFileRegistry = {
},
remove(id: string) {
storage.remove(entryKey(id));
const ids = getAllIds().filter((i) => i !== id);
setAllIds(ids);
const blob = loadBlob();
const entry = blob.entries[id];
if (entry?.backendFileId) {
delete blob.backendIndex[entry.backendFileId];
}
delete blob.entries[id];
saveBlob(blob);
},
removeByBackendId(backendId: string) {
const entry = this.getByBackendId(backendId);
if (entry) this.remove(entry.id);
const blob = loadBlob();
const entryId = blob.backendIndex[backendId];
if (entryId) {
delete blob.entries[entryId];
delete blob.backendIndex[backendId];
saveBlob(blob);
}
},
count(): number {
return getAllIds().length;
return Object.keys(loadBlob().entries).length;
},
};