From 0b82fe49ee870702ef38ea6b8f55213e7073a597 Mon Sep 17 00:00:00 2001 From: Dariusz L Date: Tue, 4 Aug 2026 21:02:43 +0200 Subject: [PATCH] fix(frontend): preserve model size across search result shapes --- tests/test_downloads_tab_workflow_route.mjs | 34 +++++++++++++++++++ web/resolver/search/search_panel.js | 36 +++++++++++++++++++-- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/tests/test_downloads_tab_workflow_route.mjs b/tests/test_downloads_tab_workflow_route.mjs index 2147f4c..59a6b6c 100644 --- a/tests/test_downloads_tab_workflow_route.mjs +++ b/tests/test_downloads_tab_workflow_route.mjs @@ -5829,6 +5829,40 @@ test('search result table exposes linked local hash targets for exact matches', assert.match(html, />Exact<\/span>/); }); +test('CivitAI hash search renders sizeKB when byte size is unavailable', () => { + const formatSearchResultSize = eval(`(${extractMethod(searchPanelMethodsSource, 'formatSearchResultSize')})`); + const dialog = { + formatBytes(value) { + const units = ['B', 'KB', 'MB', 'GB']; + let index = 0; + let number = Number(value); + while (number >= 1024 && index < units.length - 1) { + number /= 1024; + index += 1; + } + return `${Number(number.toFixed(1))} ${units[index]}`; + }, + }; + + assert.equal( + formatSearchResultSize.call(dialog, { + source: 'civitai', + match_type: 'hash', + size: null, + sizeKB: 12021353.90625, + }), + '11.5 GB' + ); + assert.equal( + formatSearchResultSize.call(dialog, { + source: 'civitai', + size: null, + files: [{ name: 'zImageTurbo_turbo.safetensors', sizeKB: 12021353.90625 }], + }), + '11.5 GB' + ); +}); + test('search result refreshes preserve keyed progress and result DOM', () => { const displaySearchResults = extractMethod(resolveDownloadMethodsSource, 'displaySearchResults'); const patchSearchResultsContainer = extractMethod( diff --git a/web/resolver/search/search_panel.js b/web/resolver/search/search_panel.js index eff2652..885dc86 100644 --- a/web/resolver/search/search_panel.js +++ b/web/resolver/search/search_panel.js @@ -1509,9 +1509,39 @@ export const searchPanelMethods = { }, formatSearchResultSize(result = {}) { - if (result.size === 0) return '0 B'; - if (!result.size) return ''; - return typeof result.size === 'number' ? this.formatBytes(result.size) : String(result.size); + const candidates = [result]; + const nestedCandidates = [ + result.file_info, + result.fileInfo, + result.selected_file, + result.selectedFile, + ]; + const files = Array.isArray(result.files) ? result.files : []; + candidates.push( + ...nestedCandidates.filter(candidate => candidate && typeof candidate === 'object'), + ...files.filter(candidate => candidate && typeof candidate === 'object') + ); + + for (const candidate of candidates) { + const directSize = candidate.size + ?? candidate.size_bytes + ?? candidate.sizeBytes + ?? candidate.file_size + ?? candidate.fileSize + ?? candidate.bytes; + if (directSize === 0) return '0 B'; + if (directSize !== undefined && directSize !== null && directSize !== '') { + return typeof directSize === 'number' ? this.formatBytes(directSize) : String(directSize); + } + + const sizeKb = candidate.sizeKB ?? candidate.size_kb; + if (sizeKb !== undefined && sizeKb !== null && sizeKb !== '') { + const sizeBytes = Number(sizeKb) * 1024; + if (Number.isFinite(sizeBytes)) return this.formatBytes(sizeBytes); + } + } + + return ''; }, getSearchResultMatchDisplay(result = {}, fallbackLabel = 'Match', fallbackClass = 'neutral', hashLabel = '') {