display files with cache image
This commit is contained in:
@@ -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;
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user