diff options
author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2022-08-20 11:17:24 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-20 11:17:24 -0400 |
commit | 310303ca1a123a77f9bd116af4dc64ad9c3256c5 (patch) | |
tree | af8bad0ec544625970a5f2a4613fff27773b162c /ext/js/media | |
parent | 02483a45b1b7fb0654b3f37571b92400b76734a5 (diff) |
Audio download timeout (#2187)
* Add support for an idle timeout when downloading audio
* Update eslint rules
* Pass idleTimeout to the downloader from DisplayAnki
* Add anki.downloadTimeout setting
* Update tests
* Assign _audioDownloadIdleTimeout using settings
* Show info about cancelled downloads
* Handle Firefox bug
* Improve audio errors
* Refactor
* Move functions to RequestBuilder
Diffstat (limited to 'ext/js/media')
-rw-r--r-- | ext/js/media/audio-downloader.js | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/ext/js/media/audio-downloader.js b/ext/js/media/audio-downloader.js index 0991d14d..4142e3f4 100644 --- a/ext/js/media/audio-downloader.js +++ b/ext/js/media/audio-downloader.js @@ -18,6 +18,7 @@ /* global * JsonSchema * NativeSimpleDOMParser + * RequestBuilder * SimpleDOMParser * StringUtil */ @@ -50,7 +51,7 @@ class AudioDownloader { return []; } - async downloadTermAudio(sources, preferredAudioIndex, term, reading) { + async downloadTermAudio(sources, preferredAudioIndex, term, reading, idleTimeout) { const errors = []; for (const source of sources) { let infoList = await this.getTermAudioInfoList(source, term, reading); @@ -61,7 +62,7 @@ class AudioDownloader { switch (info.type) { case 'url': try { - return await this._downloadAudioFromUrl(info.url, source.type); + return await this._downloadAudioFromUrl(info.url, source.type, idleTimeout); } catch (e) { errors.push(e); } @@ -241,21 +242,42 @@ class AudioDownloader { return url.replace(/\{([^}]*)\}/g, (m0, m1) => (Object.prototype.hasOwnProperty.call(data, m1) ? `${data[m1]}` : m0)); } - async _downloadAudioFromUrl(url, sourceType) { + async _downloadAudioFromUrl(url, sourceType, idleTimeout) { + let signal; + let onProgress = null; + let idleTimer = null; + if (typeof idleTimeout === 'number') { + const abortController = new AbortController(); + ({signal} = abortController); + const onIdleTimeout = () => { + abortController.abort('Idle timeout'); + }; + onProgress = (done) => { + clearTimeout(idleTimer); + idleTimer = done ? null : setTimeout(onIdleTimeout, idleTimeout); + }; + idleTimer = setTimeout(onIdleTimeout, idleTimeout); + } + const response = await this._requestBuilder.fetchAnonymous(url, { method: 'GET', mode: 'cors', cache: 'default', credentials: 'omit', redirect: 'follow', - referrerPolicy: 'no-referrer' + referrerPolicy: 'no-referrer', + signal }); if (!response.ok) { throw new Error(`Invalid response: ${response.status}`); } - const arrayBuffer = await response.arrayBuffer(); + const arrayBuffer = await RequestBuilder.readFetchResponseArrayBuffer(response, onProgress); + + if (idleTimer !== null) { + clearTimeout(idleTimer); + } if (!await this._isAudioBinaryValid(arrayBuffer, sourceType)) { throw new Error('Could not retrieve audio'); |