From bfc20cf91d2192c4341c1679b0054a410231a406 Mon Sep 17 00:00:00 2001 From: Avinash Kumar Deepak Date: Fri, 20 Mar 2026 21:04:47 +0530 Subject: [PATCH] fix: fail gracefully for unsupported file system APIs --- src/component/fileBrowser.jsx | 50 +++++++++++++++----------- src/component/modals/FileEdit.jsx | 11 ++++-- src/toolbarActions/toolbarFunctions.js | 14 +++++--- 3 files changed, 47 insertions(+), 28 deletions(-) diff --git a/src/component/fileBrowser.jsx b/src/component/fileBrowser.jsx index 5b80004..e0d57c6 100644 --- a/src/component/fileBrowser.jsx +++ b/src/component/fileBrowser.jsx @@ -94,28 +94,34 @@ const LocalFileBrowser = ({ superState, dispatcher }) => { }; const newFeature = async () => { - const dirHandle = await window.showDirectoryPicker(); - let state = []; - // eslint-disable-next-line no-restricted-syntax - for await (const [key, value] of dirHandle.entries()) { - if (value.kind === 'file') { - const fileData = await value.getFile(); - state = state.concat([{ - key: `${dirHandle.name}/${key}`, - modified: fileData.lastModified, - size: fileData.size, - fileObj: fileData, - fileHandle: value, - }]); - } else if (value.kind === 'directory') { - const res = await handleFileInDirs(dirHandle.name, value); - state = state.concat(res); + try { + const dirHandle = await window.showDirectoryPicker(); + let state = []; + // eslint-disable-next-line no-restricted-syntax + for await (const [key, value] of dirHandle.entries()) { + if (value.kind === 'file') { + const fileData = await value.getFile(); + state = state.concat([{ + key: `${dirHandle.name}/${key}`, + modified: fileData.lastModified, + size: fileData.size, + fileObj: fileData, + fileHandle: value, + }]); + } else if (value.kind === 'directory') { + const res = await handleFileInDirs(dirHandle.name, value); + state = state.concat(res); + } + } + setFileState([]); + setFileState(state); + dispatcher({ type: T.SET_DIR_NAME, payload: state[0].key.split('/')[0] }); + dispatcher({ type: T.SET_FILE_STATE, payload: state }); + } catch (error) { + if (error.name !== 'AbortError') { + toast.info('Switch to Edge/Chrome!'); } } - setFileState([]); - setFileState(state); - dispatcher({ type: T.SET_DIR_NAME, payload: state[0].key.split('/')[0] }); - dispatcher({ type: T.SET_FILE_STATE, payload: state }); }; const newFeatureFile = async () => { @@ -161,6 +167,10 @@ const LocalFileBrowser = ({ superState, dispatcher }) => { onChange={(e) => { const { files } = e.target; if (files && files.length > 0) { + if (!files[0].webkitRelativePath) { + toast.info('Switch to Edge/Chrome!'); + return; + } tempFilesRef.current = files; const folderName = files[0].webkitRelativePath.split('/')[0]; setPendingFolderName(folderName); diff --git a/src/component/modals/FileEdit.jsx b/src/component/modals/FileEdit.jsx index 4789297..5f4c22b 100644 --- a/src/component/modals/FileEdit.jsx +++ b/src/component/modals/FileEdit.jsx @@ -16,7 +16,7 @@ const FileEditModal = ({ superState, dispatcher }) => { const [showFilenameModal, setShowFilenameModal] = useState(false); useEffect(() => { - if (navigator.userAgent.indexOf('Edg') !== -1 || navigator.userAgent.indexOf('Chrome') !== -1) { + if ('showSaveFilePicker' in window) { setDirButton(true); } }, []); @@ -28,11 +28,16 @@ const FileEditModal = ({ superState, dispatcher }) => { }; async function submit() { - if (superState.fileHandle) { + if (!superState.fileHandle || !superState.fileHandle.createWritable) { + toast.warn('Switch to Edge/Chrome!'); + dispatcher({ type: T.EDIT_TEXTFILE, payload: { show: false } }); + return; + } + try { const stream = await superState.fileHandle.createWritable(); await stream.write(codeStuff); await stream.close(); - } else { + } catch (error) { toast.warn('Switch to Edge/Chrome!'); } dispatcher({ type: T.EDIT_TEXTFILE, payload: { show: false } }); diff --git a/src/toolbarActions/toolbarFunctions.js b/src/toolbarActions/toolbarFunctions.js index e83e481..721b106 100644 --- a/src/toolbarActions/toolbarFunctions.js +++ b/src/toolbarActions/toolbarFunctions.js @@ -85,11 +85,15 @@ const saveAction = (state) => { async function saveGraphMLFile(state) { if (state.curGraphInstance) { const graph = state.graphs[state.curGraphIndex]; - if (graph.fileHandle) { - const stream = await graph.fileHandle.createWritable(); - await stream.write(getGraphFun(state).saveToFolder()); - await stream.close(); - toast.success('File saved Successfully'); + if (graph.fileHandle && graph.fileHandle.createWritable) { + try { + const stream = await graph.fileHandle.createWritable(); + await stream.write(getGraphFun(state).saveToFolder()); + await stream.close(); + toast.success('File saved Successfully'); + } catch (error) { + getGraphFun(state).saveWithoutFileHandle(); + } } else if (!graph.fileHandle) { getGraphFun(state).saveWithoutFileHandle(); } else {