add saf directory display fix

This commit is contained in:
m
2026-09-10 23:08:17 +02:00
parent 367073ed89
commit 76ed3aa66b
9 changed files with 323 additions and 51 deletions
+9
View File
@@ -98,6 +98,15 @@ export async function closeDatabase(): Promise<void> {
opening = null;
}
export async function checkpointDatabase(): Promise<void> {
try {
const db = await getDatabase();
await db.execAsync('PRAGMA wal_checkpoint(TRUNCATE)');
} catch {
// Best-effort : ne jamais faire échouer la sync sur un checkpoint.
}
}
export async function withTransaction<T>(
work: (db: SQLiteDatabase) => Promise<T>,
): Promise<T> {
+6 -1
View File
@@ -1,4 +1,9 @@
export { getDatabase, closeDatabase, withTransaction } from './client';
export {
getDatabase,
closeDatabase,
withTransaction,
checkpointDatabase,
} from './client';
export { migrateDatabase, type Migration, type MigrationDb } from './migrations';
export * from './repositories';
export type { AccessCheck, AccessSource } from './repositories/permissions';
+8
View File
@@ -6,6 +6,14 @@ import type {
FolderInfo,
PickDirectoryOptions,
} from './safDirectory.types';
import { __setSafWalkImpl, yieldToMainThread } from './safWalk';
export { listFoldersChunked, yieldToMainThread, DEFAULT_WALK_BUDGET_MS } from './safWalk';
__setSafWalkImpl({
list: listDirectory,
info: getFolderInfo,
yield: yieldToMainThread,
});
export async function pickDirectory(initialUri?: string): Promise<Folder | null> {
try {
+69
View File
@@ -0,0 +1,69 @@
import type {
DirectoryEntry,
Folder,
FolderInfo,
PickDirectoryOptions,
} from './safDirectory.types';
export async function yieldToMainThread(): Promise<void> {
await new Promise<void>((resolve) => setTimeout(resolve, 0));
}
export const DEFAULT_WALK_BUDGET_MS = 16;
export type SafWalkImpl = {
list: (uri: string) => DirectoryEntry[];
info: (uri: string) => FolderInfo;
yield: () => Promise<void>;
};
let walkImpl: SafWalkImpl | null = null;
export function __setSafWalkImpl(impl: SafWalkImpl): void {
walkImpl = impl;
}
export function __setSafWalkForTests(impl: Partial<SafWalkImpl>): () => void {
const previous = walkImpl;
walkImpl = { ...previous, ...impl } as SafWalkImpl;
return () => {
walkImpl = previous;
};
}
export async function listFoldersChunked(
directoryUri: string,
options: PickDirectoryOptions = {},
budgetMs = DEFAULT_WALK_BUDGET_MS,
): Promise<Folder[]> {
const impl = walkImpl;
if (!impl) throw new Error('SafWalkImpl not configured');
const { recursive = false, includeRoot = false } = options;
const result: Folder[] = [];
if (includeRoot) {
result.push({ ...impl.info(directoryUri), isDirectory: true });
}
if (!recursive) {
for (const entry of impl.list(directoryUri)) {
if (entry.isDirectory) result.push(entry);
}
return result;
}
let lastYield = Date.now();
const visit = async (uri: string) => {
if (Date.now() - lastYield >= budgetMs) {
lastYield = Date.now();
await impl.yield();
}
for (const entry of impl.list(uri)) {
if (entry.isDirectory) {
result.push(entry);
await visit(entry.uri);
}
}
};
await visit(directoryUri);
return result;
}