diff --git a/webui/static/script.js b/webui/static/script.js
index 5d30baa6..8b7cdc96 100644
--- a/webui/static/script.js
+++ b/webui/static/script.js
@@ -65539,6 +65539,7 @@ async function loadRepairFindings() {
duplicate_tracks: 'Keep Best',
incomplete_album: 'Auto-Fill',
missing_lossy_copy: 'Convert',
+ acoustid_mismatch: 'Fix',
};
container.innerHTML = items.map(f => {
@@ -66096,6 +66097,11 @@ async function fixRepairFinding(id, findingType) {
fixAction = await _promptDeadFileAction();
if (!fixAction) return;
}
+ // AcoustID mismatch: retag, redownload, or delete
+ if (findingType === 'acoustid_mismatch') {
+ fixAction = await _promptAcoustidAction();
+ if (!fixAction) return;
+ }
const card = document.querySelector(`.repair-finding-card[data-id="${id}"]`);
const fixBtn = card ? card.querySelector('.repair-finding-btn.fix') : null;
@@ -66197,6 +66203,46 @@ function _promptDeadFileAction() {
});
}
+function _promptAcoustidAction() {
+ return new Promise(resolve => {
+ const overlay = document.createElement('div');
+ overlay.className = 'modal-overlay';
+ overlay.style.cssText = 'display:flex;align-items:center;justify-content:center;z-index:10000;';
+ overlay.innerHTML = `
+
+
AcoustID Mismatch
+
+ The audio fingerprint doesn't match the expected track. Choose how to fix it.
+
+
+
+ Retag
+
+
+ Re-download
+
+
+ Delete
+
+
+
+ Retag = update metadata to match actual audio • Re-download = add correct track to wishlist & delete wrong file • Delete = remove file and DB entry
+
+
+ Cancel
+
+
+ `;
+ document.body.appendChild(overlay);
+
+ overlay.querySelector('#_acid-retag').onclick = () => { overlay.remove(); resolve('retag'); };
+ overlay.querySelector('#_acid-redownload').onclick = () => { overlay.remove(); resolve('redownload'); };
+ overlay.querySelector('#_acid-delete').onclick = () => { overlay.remove(); resolve('delete'); };
+ overlay.querySelector('#_acid-cancel').onclick = () => { overlay.remove(); resolve(null); };
+ overlay.onclick = (e) => { if (e.target === overlay) { overlay.remove(); resolve(null); } };
+ });
+}
+
async function resolveRepairFinding(id) {
try {
await fetch(`/api/repair/findings/${id}/resolve`, { method: 'POST' });
@@ -66272,6 +66318,17 @@ async function bulkFixFindings() {
if (!deadFixAction) return;
}
+ // If any selected findings are AcoustID mismatches, prompt for action
+ const selectedAcoustidCards = ids.filter(id => {
+ const card = document.querySelector(`.repair-finding-card[data-id="${id}"]`);
+ return card && card.dataset.jobId === 'acoustid_scanner';
+ });
+ let acoustidFixAction = null;
+ if (selectedAcoustidCards.length > 0) {
+ acoustidFixAction = await _promptAcoustidAction();
+ if (!acoustidFixAction) return;
+ }
+
let fixed = 0, failed = 0, lastError = '';
showToast(`Fixing ${ids.length} findings...`, 'info');
@@ -66281,9 +66338,11 @@ async function bulkFixFindings() {
const card = document.querySelector(`.repair-finding-card[data-id="${id}"]`);
const isOrphan = card && card.dataset.jobId === 'orphan_file_detector';
const isDead = card && card.dataset.jobId === 'dead_file_cleaner';
+ const isAcoustid = card && card.dataset.jobId === 'acoustid_scanner';
let body = {};
if (isOrphan && orphanFixAction) body = { fix_action: orphanFixAction };
else if (isDead && deadFixAction) body = { fix_action: deadFixAction };
+ else if (isAcoustid && acoustidFixAction) body = { fix_action: acoustidFixAction };
const response = await fetch(`/api/repair/findings/${id}/fix`, {
method: 'POST',