diff --git a/src/App.tsx b/src/App.tsx index 647829a..12bd593 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -44,13 +44,17 @@ const getScheduledQueueIds = () => { type AudioContextConstructor = typeof AudioContext; -const playCompletionChime = () => { +const playCompletionChime = async () => { const AudioCtor = window.AudioContext || (window as Window & { webkitAudioContext?: AudioContextConstructor }).webkitAudioContext; if (!AudioCtor) return; const context = new AudioCtor(); + if (context.state === 'suspended') { + await context.resume(); + } + const oscillator = context.createOscillator(); const gain = context.createGain(); oscillator.type = 'sine'; @@ -551,11 +555,9 @@ function App() { if (event.payload.status !== 'completed' && event.payload.status !== 'failed') return; const settings = useSettingsStore.getState(); if (event.payload.status === 'completed' && settings.playCompletionSound) { - try { - playCompletionChime(); - } catch (error) { + playCompletionChime().catch(error => { console.error('Completion sound failed:', error); - } + }); } if (!settings.showNotifications) return; diff --git a/src/components/AddDownloadsModal.tsx b/src/components/AddDownloadsModal.tsx index 917a2d5..544a648 100644 --- a/src/components/AddDownloadsModal.tsx +++ b/src/components/AddDownloadsModal.tsx @@ -37,6 +37,16 @@ const formatBytes = (bytes: number) => { return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]; }; +const isCrossHostRedirect = (sourceUrl: string, downloadUrl: string) => { + try { + const sourceHost = new URL(sourceUrl).hostname; + const downloadHost = new URL(downloadUrl).hostname; + return downloadHost !== sourceHost && !downloadHost.endsWith(`.${sourceHost}`); + } catch { + return false; + } +}; + export const AddDownloadsModal = () => { const { addToast } = useToast(); const { @@ -85,6 +95,7 @@ export const AddDownloadsModal = () => { const [checksumValue, setChecksumValue] = useState(''); const [headers, setHeaders] = useState(''); const [cookies, setCookies] = useState(''); + const cookiesFromExtensionRef = useRef(false); const [mirrors, setMirrors] = useState(''); useEffect(() => { @@ -111,6 +122,7 @@ export const AddDownloadsModal = () => { pendingAddHeaders ].filter(Boolean).join('\n')); setCookies(pendingAddCookies); + cookiesFromExtensionRef.current = Boolean(pendingAddCookies?.trim()); setMirrors(''); setIsQueueMenuOpen(false); setIsSubmitting(false); @@ -251,6 +263,11 @@ export const AddDownloadsModal = () => { headers: headers?.trim() || null, cookies: cookies?.trim() || null }); + const nextDownloadUrl = meta.url || row.sourceUrl; + if (cookiesFromExtensionRef.current && isCrossHostRedirect(row.sourceUrl, nextDownloadUrl)) { + setCookies(''); + cookiesFromExtensionRef.current = false; + } setParsedItems(current => updateRowIfCurrent( current, row.id, @@ -258,7 +275,7 @@ export const AddDownloadsModal = () => { row.generation, currentRow => ({ ...currentRow, - downloadUrl: meta.url || currentRow.downloadUrl, + downloadUrl: nextDownloadUrl || currentRow.downloadUrl, file: canonicalizeDownloadFileName( current.length === 1 && pendingAddFilename ? pendingAddFilename @@ -1008,7 +1025,17 @@ export const AddDownloadsModal = () => {
- setCookies(e.target.value)} placeholder="name=value; other=value" className="add-download-control w-full px-3 py-1.5 text-xs font-mono" aria-label="Cookies" /> + { + cookiesFromExtensionRef.current = false; + setCookies(e.target.value); + }} + placeholder="name=value; other=value" + className="add-download-control w-full px-3 py-1.5 text-xs font-mono" + aria-label="Cookies" + />
diff --git a/src/components/SettingsView.tsx b/src/components/SettingsView.tsx index 5c946ed..3f3d5d3 100644 --- a/src/components/SettingsView.tsx +++ b/src/components/SettingsView.tsx @@ -639,8 +639,8 @@ runEngineChecks(false);