From 3b018ee0810a80d72c70708f32f88b9a6a3537f7 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Fri, 19 Apr 2024 00:45:50 +0800 Subject: [PATCH 1/4] Refactor and fix archive link bug (#30535) Regression of #29920 Fixes: #30569 Also this is a rewriting to eliminate the remaining jQuery usages from code. Co-authored-by: Giteabot --- web_src/js/features/repo-common.js | 54 ++++++++++++------------------ web_src/js/utils/dom.js | 4 +++ 2 files changed, 26 insertions(+), 32 deletions(-) diff --git a/web_src/js/features/repo-common.js b/web_src/js/features/repo-common.js index b750addb07a2c..88aa93d8508c6 100644 --- a/web_src/js/features/repo-common.js +++ b/web_src/js/features/repo-common.js @@ -1,45 +1,35 @@ import $ from 'jquery'; -import {hideElem, showElem} from '../utils/dom.js'; +import {hideElem, queryElems, showElem} from '../utils/dom.js'; import {POST} from '../modules/fetch.js'; +import {showErrorToast} from '../modules/toast.js'; +import {sleep} from '../utils.js'; -async function getArchive($target, url, first) { - const dropdownBtn = $target[0].closest('.ui.dropdown.button') ?? $target[0].closest('.ui.dropdown.btn'); - +async function onDownloadArchive(e) { + e.preventDefault(); + // there are many places using the "archive-link", eg: the dropdown on the repo code page, the release list + const el = e.target.closest('a.archive-link[href]'); + const targetLoading = el.closest('.ui.dropdown') ?? el; + targetLoading.classList.add('is-loading', 'loading-icon-2px'); try { - dropdownBtn.classList.add('is-loading'); - const response = await POST(url); - if (response.status === 200) { - const data = await response.json(); - if (!data) { - // XXX Shouldn't happen? - dropdownBtn.classList.remove('is-loading'); - return; - } + for (let tryCount = 0; ;tryCount++) { + const response = await POST(el.href); + if (!response.ok) throw new Error(`Invalid server response: ${response.status}`); - if (!data.complete) { - // Wait for only three quarters of a second initially, in case it's - // quickly archived. - setTimeout(() => { - getArchive($target, url, false); - }, first ? 750 : 2000); - } else { - // We don't need to continue checking. - dropdownBtn.classList.remove('is-loading'); - window.location.href = url; - } + const data = await response.json(); + if (data.complete) break; + await sleep(Math.min((tryCount + 1) * 750, 2000)); } - } catch { - dropdownBtn.classList.remove('is-loading'); + window.location.href = el.href; // the archive is ready, start real downloading + } catch (e) { + console.error(e); + showErrorToast(`Failed to download the archive: ${e}`, {duration: 2500}); + } finally { + targetLoading.classList.remove('is-loading', 'loading-icon-2px'); } } export function initRepoArchiveLinks() { - $('.archive-link').on('click', function (event) { - event.preventDefault(); - const url = this.getAttribute('href'); - if (!url) return; - getArchive($(event.target), url, true); - }); + queryElems('a.archive-link[href]', (el) => el.addEventListener('click', onDownloadArchive)); } export function initRepoCloneLink() { diff --git a/web_src/js/utils/dom.js b/web_src/js/utils/dom.js index 59c455e2ab483..1ac77430826ac 100644 --- a/web_src/js/utils/dom.js +++ b/web_src/js/utils/dom.js @@ -55,6 +55,10 @@ export function queryElemSiblings(el, selector) { return Array.from(el.parentNode.children).filter((child) => child !== el && child.matches(selector)); } +export function queryElems(selector, fn) { + return applyElemsCallback(document.querySelectorAll(selector), fn); +} + export function onDomReady(cb) { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', cb); From a8941e03c5f55c33a8e6d5c04b053c435c072036 Mon Sep 17 00:00:00 2001 From: silverwind Date: Fri, 19 Apr 2024 09:37:45 +0200 Subject: [PATCH 2/4] Update web_src/js/features/repo-common.js --- web_src/js/features/repo-common.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web_src/js/features/repo-common.js b/web_src/js/features/repo-common.js index 88aa93d8508c6..67390b12b1e3f 100644 --- a/web_src/js/features/repo-common.js +++ b/web_src/js/features/repo-common.js @@ -29,7 +29,9 @@ async function onDownloadArchive(e) { } export function initRepoArchiveLinks() { - queryElems('a.archive-link[href]', (el) => el.addEventListener('click', onDownloadArchive)); + for (const el of document.querySelectorAll('a.archive-link[href]') { + el.addEventListener('click', onDownloadArchive); + } } export function initRepoCloneLink() { From 845133d89a260edd7cf23f20eec6b6b99b57c72a Mon Sep 17 00:00:00 2001 From: silverwind Date: Fri, 19 Apr 2024 09:37:51 +0200 Subject: [PATCH 3/4] Update web_src/js/utils/dom.js --- web_src/js/utils/dom.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/web_src/js/utils/dom.js b/web_src/js/utils/dom.js index 1ac77430826ac..59c455e2ab483 100644 --- a/web_src/js/utils/dom.js +++ b/web_src/js/utils/dom.js @@ -55,10 +55,6 @@ export function queryElemSiblings(el, selector) { return Array.from(el.parentNode.children).filter((child) => child !== el && child.matches(selector)); } -export function queryElems(selector, fn) { - return applyElemsCallback(document.querySelectorAll(selector), fn); -} - export function onDomReady(cb) { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', cb); From 62507e692782364735f920bc863e8033b0047720 Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 21 Apr 2024 21:57:53 +0200 Subject: [PATCH 4/4] fixes --- web_src/js/features/repo-common.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web_src/js/features/repo-common.js b/web_src/js/features/repo-common.js index 67390b12b1e3f..65d4e08069ae0 100644 --- a/web_src/js/features/repo-common.js +++ b/web_src/js/features/repo-common.js @@ -1,5 +1,5 @@ import $ from 'jquery'; -import {hideElem, queryElems, showElem} from '../utils/dom.js'; +import {hideElem, showElem} from '../utils/dom.js'; import {POST} from '../modules/fetch.js'; import {showErrorToast} from '../modules/toast.js'; import {sleep} from '../utils.js'; @@ -9,7 +9,7 @@ async function onDownloadArchive(e) { // there are many places using the "archive-link", eg: the dropdown on the repo code page, the release list const el = e.target.closest('a.archive-link[href]'); const targetLoading = el.closest('.ui.dropdown') ?? el; - targetLoading.classList.add('is-loading', 'loading-icon-2px'); + targetLoading.classList.add('is-loading', 'small-loading-icon'); try { for (let tryCount = 0; ;tryCount++) { const response = await POST(el.href); @@ -24,12 +24,12 @@ async function onDownloadArchive(e) { console.error(e); showErrorToast(`Failed to download the archive: ${e}`, {duration: 2500}); } finally { - targetLoading.classList.remove('is-loading', 'loading-icon-2px'); + targetLoading.classList.remove('is-loading', 'small-loading-icon'); } } export function initRepoArchiveLinks() { - for (const el of document.querySelectorAll('a.archive-link[href]') { + for (const el of document.querySelectorAll('a.archive-link[href]')) { el.addEventListener('click', onDownloadArchive); } }