// Чтение хранилища в браузере — три пути ввода, все → RawNote[]. // Содержимое заметок остаётся в браузере (приватность-моат). import type { RawNote } from "./types"; const SKIP = ["/.obsidian/", "/.trash/", "/.git/"]; function isMd(path: string): boolean { return path.toLowerCase().endsWith(".md") && !SKIP.some((s) => path.includes(s)); } /* eslint-disable @typescript-eslint/no-explicit-any */ export function supportsFSA(): boolean { return typeof window !== "undefined" && "showDirectoryPicker" in window; } // 1. File System Access API (Chromium: Chrome/Edge/Brave) export async function readViaFSA(): Promise { const dir: any = await (window as any).showDirectoryPicker(); const notes: RawNote[] = []; async function walk(handle: any, prefix: string): Promise { for await (const [name, h] of handle.entries()) { const path = prefix + "/" + name; if (h.kind === "directory") { if (name.startsWith(".")) continue; await walk(h, path); } else if (isMd(path)) { const file: File = await h.getFile(); notes.push({ name, text: await file.text(), ctime: file.lastModified, mtime: file.lastModified }); } } } await walk(dir, ""); return notes; } // 2. (Safari / Firefox) export async function readViaInput(files: FileList): Promise { const notes: RawNote[] = []; for (const file of Array.from(files)) { const path = (file as any).webkitRelativePath || file.name; if (!isMd(path)) continue; notes.push({ name: file.name, text: await file.text(), ctime: file.lastModified, mtime: file.lastModified }); } return notes; } // 3. drag-drop папки (webkitGetAsEntry) export async function readViaDrop(items: DataTransferItemList): Promise { const notes: RawNote[] = []; const roots: any[] = []; for (const item of Array.from(items)) { const entry = (item as any).webkitGetAsEntry?.(); if (entry) roots.push(entry); } async function readEntry(entry: any, prefix: string): Promise { const path = prefix + "/" + entry.name; if (entry.isDirectory) { if (entry.name.startsWith(".")) return; const reader = entry.createReader(); const children: any[] = await new Promise((resolve) => { const all: any[] = []; const readBatch = () => reader.readEntries((batch: any[]) => { if (!batch.length) return resolve(all); all.push(...batch); readBatch(); }); readBatch(); }); for (const c of children) await readEntry(c, path); } else if (isMd(path)) { const file: File = await new Promise((resolve, reject) => entry.file(resolve, reject)); notes.push({ name: entry.name, text: await file.text(), ctime: file.lastModified, mtime: file.lastModified }); } } for (const e of roots) await readEntry(e, ""); return notes; }