diff --git a/surfsense_web/components/tool-ui/audio.tsx b/surfsense_web/components/tool-ui/audio.tsx index acf6054fb..0bda81bb8 100644 --- a/surfsense_web/components/tool-ui/audio.tsx +++ b/surfsense_web/components/tool-ui/audio.tsx @@ -27,6 +27,7 @@ function formatTime(seconds: number): string { export function Audio({ id, src, title, description, artwork, durationMs, className }: AudioProps) { const audioRef = useRef(null); + const downloadControllerRef = useRef(null); const [isPlaying, setIsPlaying] = useState(false); const [currentTime, setCurrentTime] = useState(0); const [duration, setDuration] = useState(durationMs ? durationMs / 1000 : 0); @@ -84,8 +85,12 @@ export function Audio({ id, src, title, description, artwork, durationMs, classN // Handle download const handleDownload = useCallback(async () => { + downloadControllerRef.current?.abort(); + const controller = new AbortController(); + downloadControllerRef.current = controller; + try { - const response = await fetch(src); + const response = await fetch(src, { signal: controller.signal }); const blob = await response.blob(); const url = window.URL.createObjectURL(blob); const a = document.createElement("a"); @@ -96,10 +101,16 @@ export function Audio({ id, src, title, description, artwork, durationMs, classN document.body.removeChild(a); window.URL.revokeObjectURL(url); } catch (err) { + if (err instanceof DOMException && err.name === "AbortError") return; console.error("Error downloading audio:", err); } }, [src, title]); + // Abort in-flight download on unmount + useEffect(() => { + return () => downloadControllerRef.current?.abort(); + }, []); + // Set up audio event listeners useEffect(() => { const audio = audioRef.current;