diff --git a/src/pages/install/App.tsx b/src/pages/install/App.tsx index 80587b3ec..e103ae8f0 100644 --- a/src/pages/install/App.tsx +++ b/src/pages/install/App.tsx @@ -442,6 +442,11 @@ function App() { } } + async function onWatchFileError() { + // e.g. NotFoundError + setWatchFile(false); + } + const memoWatchFile = useMemo(() => { return `${watchFile}.${scriptInfo?.uuid}.${localFileHandle?.name}`; }, [watchFile, scriptInfo, localFileHandle]); @@ -458,6 +463,7 @@ function App() { uuid, fileName, setCode: onWatchFileCodeChanged, + onFileError: onWatchFileError, }; // 进行监听 startFileTrack(handle, ftInfo); diff --git a/src/pkg/utils/file-tracker.ts b/src/pkg/utils/file-tracker.ts index 8ec813603..246533dac 100644 --- a/src/pkg/utils/file-tracker.ts +++ b/src/pkg/utils/file-tracker.ts @@ -5,30 +5,64 @@ export type FTInfo = { fileName: string; setCode(code: string, hideInfo?: boolean): void; lastModified?: number; + onFileError(): void; +}; + +const getHandleRecord = async (root: FileSystemFileHandle, observer: FileSystemObserverInstance) => { + for (const [fileHandle, ftInfo, fileObserver] of handleRecords) { + if (fileObserver !== observer) continue; + try { + const isSame = await root.isSameEntry(fileHandle); + if (isSame) { + return ftInfo; + } + } catch (e) { + // 捕捉非预期错误 + console.warn(e); + } + } + return null; }; const callback = async (records: FileSystemChangeRecord[], observer: FileSystemObserverInstance) => { - for (const record of records) { - const { root, type } = record; - if (!(root instanceof FileSystemFileHandle) || type !== "modified") continue; - for (const [fileHandle, ftInfo, fileObserver] of handleRecords) { - if (fileObserver !== observer) continue; + try { + for (const record of records) { + const { root, type } = record; + if (!(root instanceof FileSystemFileHandle)) continue; + // 只要 FileSystemObserver 侦测到档案改变,就试一下找记录和读档 + const ftInfo = await getHandleRecord(root, observer); + // 如没有记录则忽略 + if (!ftInfo) continue; + let file: File | null = null; try { - const isSame = await root.isSameEntry(fileHandle); - if (!isSame) continue; - // 调用安装 - const file = await root.getFile(); - // 避免重复更新 - if (ftInfo.lastModified === file.lastModified) continue; - ftInfo.lastModified = file.lastModified; - const code = await file.text(); - if (code && typeof code === "string") { - ftInfo.setCode(code, false); + const fRead = await root.getFile(); + if (fRead && fRead.lastModified > 0 && fRead.size > 0) { + // 有档案内容读取权限,排除空档案 + file = fRead; } } catch (e) { + // 档案改名或删掉时,或会被此捕捉(预期报错) console.warn(e); + unmountFileTrack(root); + ftInfo.onFileError(); + } + // 如读档失败则忽略 + if (!file) continue; + // 如成功读档但显示为失败,则重新 observe + if (type === "errored") { + observer.observe(root); + } + // 以 lastModified 判断避免重复更新 + if (ftInfo.lastModified === file.lastModified) continue; + ftInfo.lastModified = file.lastModified; + const code = await file.text(); + if (code && typeof code === "string") { + ftInfo.setCode(code, false); } } + } catch (e) { + // 捕捉非预期错误 + console.warn(e); } }; @@ -49,6 +83,7 @@ export const unmountFileTrack = async (fileHandle: FileSystemFileHandle) => { } } } catch (e) { + // 捕捉非预期错误 console.warn(e); } return false;