You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
2.4 KiB
93 lines
2.4 KiB
import { File, Directory, Paths } from 'expo-file-system';
|
|
import { DiaryEntry, EntryIndex } from '@/types/entry';
|
|
|
|
const JSON_MIMETYPE = 'application/json';
|
|
const JPG_MIMETYPE = 'image/jpeg';
|
|
const ROOT = new Directory(Paths.document, 'diary');
|
|
const ENTRIES_DIR = ROOT.createDirectory('entries');
|
|
const IMAGE_DIR = ROOT.createDirectory('images');
|
|
export const INDEX_FILE = ROOT.createFile('entries.json', JSON_MIMETYPE);
|
|
export const INDEX_BAK = ROOT.createFile('entries.json.bak', JSON_MIMETYPE);
|
|
|
|
export function ensureDirs() {
|
|
if (!ROOT.exists) ROOT.create();
|
|
if (!ENTRIES_DIR.exists) ENTRIES_DIR.create();
|
|
if (!IMAGE_DIR.exists) IMAGE_DIR.create();
|
|
}
|
|
|
|
export function writeTextAtomic(file: File, text: string) {
|
|
try {
|
|
if (!file.parentDirectory.exists) file.parentDirectory.create();
|
|
} catch {}
|
|
|
|
const tmp = new File(file.parentDirectory, `${file.name}.tmp`);
|
|
|
|
try {
|
|
tmp.delete();
|
|
} catch {}
|
|
tmp.create();
|
|
tmp.write(text);
|
|
|
|
try {
|
|
file.delete();
|
|
} catch {}
|
|
tmp.move(file);
|
|
}
|
|
|
|
export function readJsonSafe<T>(file: File, fallback?: T): T | undefined {
|
|
try {
|
|
if (!file.exists) return fallback;
|
|
const raw = file.textSync();
|
|
return JSON.parse(raw) as T;
|
|
} catch (e) {
|
|
console.warn(`[FILEIO_READ] ${e}`);
|
|
|
|
return fallback;
|
|
}
|
|
}
|
|
|
|
export function writeIndexAtomic(index: EntryIndex) {
|
|
ensureDirs();
|
|
if (INDEX_FILE.exists) {
|
|
if (INDEX_BAK.exists) INDEX_BAK.delete();
|
|
|
|
INDEX_FILE.copy(INDEX_BAK);
|
|
}
|
|
|
|
try {
|
|
writeTextAtomic(INDEX_FILE, JSON.stringify(index));
|
|
} catch (e) {
|
|
console.warn(`[FILEIO_WRITE] ${e}`);
|
|
|
|
if (INDEX_BAK.exists) {
|
|
if (INDEX_FILE.exists) INDEX_FILE.delete();
|
|
|
|
INDEX_BAK.copy(INDEX_FILE);
|
|
}
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
export function entryFile(id: string) {
|
|
return ENTRIES_DIR.createFile(`${id}.json`, JSON_MIMETYPE);
|
|
}
|
|
|
|
export function imageFile(id: string) {
|
|
return IMAGE_DIR.createFile(`${id}.jpg`, JPG_MIMETYPE);
|
|
}
|
|
|
|
export function readEntry(id: string) {
|
|
return readJsonSafe<DiaryEntry>(entryFile(id));
|
|
}
|
|
|
|
export function writeEntryAtomic(entry: DiaryEntry) {
|
|
writeTextAtomic(entryFile(entry.id), JSON.stringify(entry));
|
|
}
|
|
|
|
export function deleteEntryFile(id: string) {
|
|
const e = entryFile(id);
|
|
if (e.exists) e.delete();
|
|
|
|
const img = imageFile(id);
|
|
if (img.exists) img.delete();
|
|
}
|
|
|