update App.tsx for embedding

This commit is contained in:
2026-06-19 14:27:27 -07:00
parent 92b7c6f06e
commit e55a825e13
+33 -6
View File
@@ -286,6 +286,20 @@ function triggerBrowserDownload(href: string, fileName: string) {
link.remove() link.remove()
} }
async function withAsyncTimeout<T>(promise: Promise<T>, timeoutMs: number, message: string): Promise<T> {
let timeoutHandle: ReturnType<typeof setTimeout> | null = null
const timeoutPromise = new Promise<T>((_, reject) => {
timeoutHandle = setTimeout(() => reject(new Error(message)), timeoutMs)
})
try {
return await Promise.race([promise, timeoutPromise])
} finally {
if (timeoutHandle) clearTimeout(timeoutHandle)
}
}
async function embedDownloadMetadata(blob: Blob, track: Track, details?: HydrusFileDetails | null, contentType?: string | null) { async function embedDownloadMetadata(blob: Blob, track: Track, details?: HydrusFileDetails | null, contentType?: string | null) {
const metadata = buildHydrusDownloadMetadata(track, details) const metadata = buildHydrusDownloadMetadata(track, details)
if (isMp3Download(track, details, contentType)) { if (isMp3Download(track, details, contentType)) {
@@ -312,7 +326,11 @@ async function embedDownloadMetadata(blob: Blob, track: Track, details?: HydrusF
if (!metadata.title && !metadata.artist && !metadata.album && !metadata.trackNumber) return { blob, note: undefined as string | undefined } if (!metadata.title && !metadata.artist && !metadata.album && !metadata.trackNumber) return { blob, note: undefined as string | undefined }
try { try {
const taggedBlob = await embedContainerAudioMetadata(blob, getTrackExtension(track, details), metadata) const taggedBlob = await withAsyncTimeout(
embedContainerAudioMetadata(blob, getTrackExtension(track, details), metadata),
15000,
'Metadata embedding timed out'
)
return { return {
blob: taggedBlob, blob: taggedBlob,
@@ -760,10 +778,19 @@ function App() {
}) })
} }
updateDownload(id, { const shouldEmbedMetadataClientSide = !isAppleMobileOrTablet
note: 'Embedding metadata...', const taggedDownload = shouldEmbedMetadataClientSide
}) ? await (async () => {
const taggedDownload = await embedDownloadMetadata(blob, track, details, response.headers.get('content-type')) updateDownload(id, {
note: 'Embedding metadata...',
})
return embedDownloadMetadata(blob, track, details, response.headers.get('content-type'))
})()
: {
blob,
note: 'iOS download: using server-provided metadata (client embedding skipped)',
}
blob = taggedDownload.blob blob = taggedDownload.blob
const downloadName = buildTrackDownloadName(track, details, response.headers.get('content-disposition')) const downloadName = buildTrackDownloadName(track, details, response.headers.get('content-disposition'))
const objectUrl = window.URL.createObjectURL(blob) const objectUrl = window.URL.createObjectURL(blob)
@@ -809,7 +836,7 @@ function App() {
delete downloadAbortControllersRef.current[id] delete downloadAbortControllersRef.current[id]
} }
})() })()
}, [downloads, updateDownload]) }, [downloads, isAppleMobileOrTablet, updateDownload])
const cancelDownload = useCallback((id: string) => { const cancelDownload = useCallback((id: string) => {
const controller = downloadAbortControllersRef.current[id] const controller = downloadAbortControllersRef.current[id]