fix(zim): stabilize uploader state to avoid cancel on tab refocus
Also improves surfacing of upload error messages
This commit is contained in:
parent
a7d05859d4
commit
fad9e30ddc
|
|
@ -16,6 +16,16 @@ export default function ZimUploader({ onUploadComplete, existingFilenames }: Zim
|
||||||
existingFilenamesRef.current = existingFilenames
|
existingFilenamesRef.current = existingFilenames
|
||||||
}, [existingFilenames])
|
}, [existingFilenames])
|
||||||
|
|
||||||
|
// Keep the latest callback in a ref so the Uppy lifecycle effect below does
|
||||||
|
// not depend on it. The parent passes a new inline function on every render,
|
||||||
|
// and if that identity were in the effect deps, a re-render mid-upload (e.g.
|
||||||
|
// a window-focus refetch) would tear down and `uppy.destroy()` the instance,
|
||||||
|
// aborting the in-flight upload.
|
||||||
|
const onUploadCompleteRef = useRef(onUploadComplete)
|
||||||
|
useEffect(() => {
|
||||||
|
onUploadCompleteRef.current = onUploadComplete
|
||||||
|
}, [onUploadComplete])
|
||||||
|
|
||||||
const [uppy] = useState(() =>
|
const [uppy] = useState(() =>
|
||||||
new Uppy({
|
new Uppy({
|
||||||
restrictions: {
|
restrictions: {
|
||||||
|
|
@ -53,9 +63,17 @@ export default function ZimUploader({ onUploadComplete, existingFilenames }: Zim
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const handleComplete = (result: { successful: Array<{ response?: { body?: { added?: number } } }> }) => {
|
const handleComplete = (result: {
|
||||||
|
successful: Array<{ response?: { body?: { added?: number } } }>
|
||||||
|
failed: Array<unknown>
|
||||||
|
}) => {
|
||||||
|
// Uppy emits `complete` even when uploads fail or are aborted. Only treat
|
||||||
|
// the run as a success when nothing failed — otherwise leave the uploader
|
||||||
|
// open so the Dashboard can surface the error instead of closing it with a
|
||||||
|
// false "Upload complete" toast.
|
||||||
|
if (result.failed.length > 0) return
|
||||||
const added = result.successful.reduce((sum, f) => sum + (f.response?.body?.added ?? 0), 0)
|
const added = result.successful.reduce((sum, f) => sum + (f.response?.body?.added ?? 0), 0)
|
||||||
onUploadComplete(added)
|
onUploadCompleteRef.current(added)
|
||||||
}
|
}
|
||||||
uppy.on('file-added', handleFileAdded)
|
uppy.on('file-added', handleFileAdded)
|
||||||
uppy.on('complete', handleComplete)
|
uppy.on('complete', handleComplete)
|
||||||
|
|
@ -64,7 +82,7 @@ export default function ZimUploader({ onUploadComplete, existingFilenames }: Zim
|
||||||
uppy.off('complete', handleComplete)
|
uppy.off('complete', handleComplete)
|
||||||
uppy.destroy()
|
uppy.destroy()
|
||||||
}
|
}
|
||||||
}, [uppy, onUploadComplete])
|
}, [uppy])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dashboard
|
<Dashboard
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ export default function ZimPage() {
|
||||||
const { data, isLoading } = useQuery<ZimFileWithMetadata[]>({
|
const { data, isLoading } = useQuery<ZimFileWithMetadata[]>({
|
||||||
queryKey: ['zim-files'],
|
queryKey: ['zim-files'],
|
||||||
queryFn: getFiles,
|
queryFn: getFiles,
|
||||||
|
refetchOnWindowFocus: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
async function getFiles() {
|
async function getFiles() {
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
"@uppy/core": "5.2.0",
|
"@uppy/core": "5.2.0",
|
||||||
"@uppy/dashboard": "5.1.0",
|
"@uppy/dashboard": "5.1.0",
|
||||||
"@uppy/react": "5.1.1",
|
"@uppy/react": "5.1.1",
|
||||||
|
"@uppy/xhr-upload": "5.2.0",
|
||||||
"@vinejs/vine": "3.0.1",
|
"@vinejs/vine": "3.0.1",
|
||||||
"@vitejs/plugin-react": "4.7.0",
|
"@vitejs/plugin-react": "4.7.0",
|
||||||
"autoprefixer": "10.5.0",
|
"autoprefixer": "10.5.0",
|
||||||
|
|
@ -4589,7 +4590,6 @@
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"license": "Apache-2.0 AND MIT",
|
"license": "Apache-2.0 AND MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
|
|
@ -4606,7 +4606,6 @@
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"license": "Apache-2.0 AND MIT",
|
"license": "Apache-2.0 AND MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
|
|
@ -4623,7 +4622,6 @@
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
|
|
@ -4716,7 +4714,6 @@
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"license": "Apache-2.0 AND MIT",
|
"license": "Apache-2.0 AND MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
|
|
@ -4733,7 +4730,6 @@
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"license": "Apache-2.0 AND MIT",
|
"license": "Apache-2.0 AND MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
|
|
@ -4750,7 +4746,6 @@
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"license": "Apache-2.0 AND MIT",
|
"license": "Apache-2.0 AND MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue