import { useState } from "react"; import { Button } from "@/components/ui/button"; import { useFileConnections } from "@/store/file-connection"; import { toast } from "sonner"; import { upsertLanguageTranslations } from "@/lib/db"; import { flattenValues } from "@/lib/i18n-structure"; import { RefreshCw } from "lucide-react"; type Props = { projectId: string; onSynced: () => void | Promise; disabled?: boolean; }; async function ensureReadPermission(handle: FileSystemFileHandle): Promise { try { // @ts-expect-error - queryPermission/requestPermission exist in supporting browsers const q = await handle.queryPermission?.({ mode: "read" }); if (q === "granted") return true; // @ts-expect-error - requestPermission exist in supporting browsers const r = await handle.requestPermission?.({ mode: "read" }); return r === "granted"; } catch { try { // Fallback: try to read once; if it throws, we treat as no permission const f = await handle.getFile(); // Touch the file object so TS doesn't complain about unused variable if (!f) return false; return true; } catch { return false; } } } export function SyncFromFilesButton({ projectId, onSynced, disabled }: Props) { const [syncing, setSyncing] = useState(false); const connSnap = useFileConnections(projectId); const hasConnections = Object.keys(connSnap.connections).length > 0; async function handleSync() { if (!projectId) return; if (!hasConnections) { toast.info("没有已连接的语言"); return; } setSyncing(true); try { const entries = Object.entries(connSnap.connections); const results = await Promise.allSettled( entries.map(async ([lang, conn]) => { const canRead = await ensureReadPermission(conn.handle); if (!canRead) throw new Error(`${lang}: 无读取权限`); const file = await conn.handle.getFile(); const text = await file.text(); let json: unknown; try { json = JSON.parse(text); } catch { throw new Error(`${lang}: JSON 解析失败`); } const values = flattenValues(json); await upsertLanguageTranslations(projectId, lang, values); return lang; }) ); const failed: string[] = []; let success = 0; for (const r of results) { if (r.status === "fulfilled") success += 1; else failed.push((r.reason as Error)?.message || "未知语言"); } if (failed.length === 0) { toast.success(`同步完成(${success})`); } else if (success === 0) { toast.error(`全部失败(${failed.length}):${failed.join(",")}`); } else { toast.warning(`部分成功(成功 ${success},失败 ${failed.length}):${failed.join(",")}`); } } finally { setSyncing(false); await onSynced?.(); } } return ( ); }