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.
 
 

84 lines
2.3 KiB

import { DiaryEntry, EntryIndex } from '@/types/entry';
import { File, Directory, Paths } from 'expo-file-system';
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) {
const tmp = new File(file.parentDirectory, `${file.name}.tmp`, file.type);
if (tmp.exists) tmp.delete();
tmp.create();
tmp.write(text);
if (file.exists) file.delete();
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();
}