From 1ab7e521670d86c0741eb30ad24cbe689d2497f1 Mon Sep 17 00:00:00 2001 From: Gronod Date: Tue, 19 May 2026 23:56:05 +0100 Subject: [PATCH] Use index-based unique identifiers for download client selection to prevent cross-selection --- public/app.js | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/public/app.js b/public/app.js index fbddca6..b7d2dc0 100644 --- a/public/app.js +++ b/public/app.js @@ -386,7 +386,9 @@ function renderDownloads() { // Filter downloads by selected clients let filteredDownloads = downloads; if (selectedDownloadClients.length > 0) { - filteredDownloads = downloads.filter(d => selectedDownloadClients.includes(d.instanceId)); + // Map indices to instanceIds + const selectedInstanceIds = selectedDownloadClients.map(idx => downloadClients[idx]?.id).filter(Boolean); + filteredDownloads = downloads.filter(d => selectedInstanceIds.includes(d.instanceId)); } // Sort downloads by client order (matching the order in downloadClients) @@ -1109,7 +1111,7 @@ function initDownloadClientFilter() { if (selectAllBtn) { selectAllBtn.addEventListener('click', (e) => { e.stopPropagation(); - selectedDownloadClients = downloadClients.map(c => c.id); + selectedDownloadClients = downloadClients.map((_, idx) => idx); localStorage.setItem('sofarr-download-clients', JSON.stringify(selectedDownloadClients)); updateDownloadClientFilter(); renderDownloads(); @@ -1139,6 +1141,19 @@ function updateDownloadClientFilter() { return; } + // Migrate old client.id values to indices + if (selectedDownloadClients.length > 0 && typeof selectedDownloadClients[0] === 'string') { + const migratedIndices = []; + selectedDownloadClients.forEach(clientId => { + const index = downloadClients.findIndex(c => c.id === clientId); + if (index !== -1) { + migratedIndices.push(index); + } + }); + selectedDownloadClients = migratedIndices; + localStorage.setItem('sofarr-download-clients', JSON.stringify(selectedDownloadClients)); + } + // Add checkboxes for each download client downloadClients.forEach((client, index) => { const option = document.createElement('div'); @@ -1148,13 +1163,13 @@ function updateDownloadClientFilter() { const checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.className = 'download-client-checkbox'; - checkbox.value = client.id; - checkbox.checked = selectedDownloadClients.includes(client.id); + checkbox.value = index; // Use index as unique identifier + checkbox.checked = selectedDownloadClients.includes(index); checkbox.id = checkboxId; // Toggle selection when checkbox changes checkbox.addEventListener('change', (e) => { - toggleClientSelection(client.id, e.target.checked); + toggleClientSelection(index, e.target.checked); }); const label = document.createElement('label'); @@ -1197,7 +1212,7 @@ function updateSelectedCountDisplay() { if (selectedDownloadClients.length === 0) { selectedText.textContent = 'All clients'; } else if (selectedDownloadClients.length === 1) { - const client = downloadClients.find(c => c.id === selectedDownloadClients[0]); + const client = downloadClients[selectedDownloadClients[0]]; selectedText.textContent = client ? client.name : '1 selected'; } else { selectedText.textContent = `${selectedDownloadClients.length} selected`;