summaryrefslogtreecommitdiff
path: root/ext/js/media/audio-downloader.js
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2022-08-20 11:17:24 -0400
committerGitHub <noreply@github.com>2022-08-20 11:17:24 -0400
commit310303ca1a123a77f9bd116af4dc64ad9c3256c5 (patch)
treeaf8bad0ec544625970a5f2a4613fff27773b162c /ext/js/media/audio-downloader.js
parent02483a45b1b7fb0654b3f37571b92400b76734a5 (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/audio-downloader.js')
-rw-r--r--ext/js/media/audio-downloader.js32
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');