Made a hacky userscript that seems to be working (for my use case), posting if anyone else might want it. (It’s probably full of bugs)
The changes it makes are: hides thumbnails, runs multiple uploads simultaneously, prompts before closing the window, and (untested - edit: sorry, retries don’t work reliably, I actually had to delete the “disabled” attribute from the button using right-click→Inspect to retry in one case) tries to automatically retry failed uploads.
Thanks again all for your pointers!
// ==UserScript==
// @name CAA upload faster
// @description CAA upload faster
// @version 2025-7-19
// @license GPL-2+ https://github.com/metabrainz/musicbrainz-server/blob/master/COPYING.md
// @namespace https://
// @match https://musicbrainz.org/release/*/add-cover-art
// @match https://*.musicbrainz.org/release/*/add-cover-art
// @grant none
// ==/UserScript==
(function() {
'use strict';
// https://tickets.metabrainz.org/browse/MBS-12524
const removePreviews = function() {
document.querySelectorAll('.uploader-preview-image').forEach(e => e.remove());
window.setTimeout(removePreviews, 1000);
}
removePreviews();
MB.Art.file_data_uri = function (file) {
var deferred = $.Deferred();
window.setTimeout(deferred.resolve(''), 100);
return deferred.promise();
};
MB.Art.add_art_submit = function (gid, upvm) {
var pos = parseInt($(`#id-add-cover-art\\.position`).val(), 10);
$('.add-files.row').hide();
$(`#cover-art-position-row`).hide();
$('#content')[0].scrollIntoView();
$(`#add-cover-art-submit`).prop('disabled', true);
var queue = MB.Art.process_upload_queue(gid, upvm, pos);
executePromisesWithDelay(queue)
.done(function () {
window.location.href =
`/release/${gid}/cover-art`;
})
.fail(function () {
$(`#add-cover-art-submit`).prop('disabled', false);
});
};
// Prevent accidentally closing tab, from https://stackoverflow.com/a/10311375
window.onbeforeunload = function (e) {
e = e || window.event;
// For IE and Firefox prior to version 4
if (e) {
e.returnValue = 'Sure?';
}
// For Safari
return 'Sure?';
};
// This function is modified by Microsoft Copilot (sigh...) based loosely on https://github.com/metabrainz/musicbrainz-server/blob/fb0b86872f180e740360bd63d5efd1d99c8e604d/root/static/scripts/edit/MB/Art.js#L631
function executePromisesWithDelay(promises) {
var deferred = $.Deferred();
var results = [];
var pendingCount = promises.length;
var delay = 10000; // Delay in milliseconds
function executePromise(index) {
if (index >= promises.length) return;
setTimeout(() => {
promises[index]()
.then(
(result) => {
results[index] = result; // Store the result
if (--pendingCount === 0) {
deferred.resolve(results);
}
},
() => {
// Retry the failed promise
promises[index]().then((result) => {
results[index] = result;
if (--pendingCount === 0) {
deferred.resolve(results);
}
});
});
// Start the next promise execution after delay
executePromise(index + 1);
}, index * delay);
}
executePromise(0); // Start executing promises
return deferred.promise();
}
})();