diff --git a/web_server.py b/web_server.py index 426838c4..d2e879b4 100644 --- a/web_server.py +++ b/web_server.py @@ -37,7 +37,7 @@ _log_dir = Path(_log_path).parent logger = setup_logging(_log_level, _log_path) # App version — single source of truth for backup metadata, version-info endpoint, etc. -_SOULSYNC_BASE_VERSION = "2.40" +_SOULSYNC_BASE_VERSION = "2.41" def _build_version_string(): """Append short commit hash to version when available (e.g. 2.35+abc1234).""" @@ -22809,6 +22809,16 @@ def get_version_info(): "title": "What's New in SoulSync", "subtitle": f"Version {SOULSYNC_VERSION} — Latest Changes", "sections": [ + { + "title": "Shared Enhanced-Search Fetch Helper", + "description": "Internal refactor — the Search page and the global search widget now route through one shared fetch helper, so future source-picker work only needs wiring in one place", + "features": [ + "• New enhancedSearchFetch(query, { source, signal }) in search.js", + "• Both callers (Search page dropdown + global widget) deduplicated — single /api/enhanced-search chokepoint", + "• Accepts the source param added in 2.40, letting future UI wire a picker without touching both callers", + "• Zero UX change — pure plumbing (Phase 2 of the Search/Artists unification project)", + ], + }, { "title": "Explicit Source Selection on Enhanced Search", "description": "The /api/enhanced-search endpoint now accepts an optional `source` parameter so callers can target a single metadata source instead of always fanning out across every provider", diff --git a/webui/static/downloads.js b/webui/static/downloads.js index 3b18282f..8610caeb 100644 --- a/webui/static/downloads.js +++ b/webui/static/downloads.js @@ -5492,13 +5492,7 @@ async function _gsPerformSearch(query) { results.classList.add('visible'); try { - const res = await fetch('/api/enhanced-search', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ query }), - signal: _gsState.abortCtrl.signal, - }); - const data = await res.json(); + const data = await enhancedSearchFetch(query, { signal: _gsState.abortCtrl.signal }); _gsState.data = data; _gsState.activeSource = data.primary_source || 'spotify'; _gsState.sources = {}; diff --git a/webui/static/helper.js b/webui/static/helper.js index b3687b05..eff92aec 100644 --- a/webui/static/helper.js +++ b/webui/static/helper.js @@ -3599,6 +3599,11 @@ function closeHelperSearch() { // ═══════════════════════════════════════════════════════════════════════════ const WHATS_NEW = { + '2.41': [ + // --- April 22, 2026 (late night) --- + { date: 'April 22, 2026 (late night)' }, + { title: 'Shared Enhanced-Search Fetch Helper', desc: 'Internal refactor — the Search page dropdown and the global search widget now route through one shared enhancedSearchFetch helper in search.js, so both callers hit /api/enhanced-search through a single chokepoint. Zero UX change, but it means the upcoming source picker (Phase 3) only needs wiring in one place instead of two. Also lets both surfaces accept the source parameter added in 2.40 (Phase 2 of the Search/Artists unification project)', page: 'downloads' }, + ], '2.40': [ // --- April 22, 2026 (late) --- { date: 'April 22, 2026 (late)' }, diff --git a/webui/static/search.js b/webui/static/search.js index 2931d91b..cbf19504 100644 --- a/webui/static/search.js +++ b/webui/static/search.js @@ -1,6 +1,22 @@ // SEARCH FUNCTIONALITY // =============================== +// Shared enhanced-search fetch used by the Search page and the global widget. +// Pass source to restrict results to a single metadata provider; omit or pass +// null/'auto' to let the backend fan out across all configured sources. +async function enhancedSearchFetch(query, { source = null, signal = null } = {}) { + const body = { query }; + if (source && source !== 'auto') body.source = source; + const res = await fetch('/api/enhanced-search', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(body), + signal: signal || undefined, + }); + if (!res.ok) throw new Error(`Enhanced search failed: ${res.status}`); + return res.json(); +} + function initializeSearch() { // --- FIX: Corrected the element IDs to match the HTML --- const searchInput = document.getElementById('downloads-search-input'); @@ -225,16 +241,7 @@ function initializeSearchModeToggle() { _enhancedSearchData = { db_artists: [], primary_source: null, sources: {}, searchId, query }; try { - const response = await fetch('/api/enhanced-search', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ query }), - signal: abortController.signal - }); - - if (!response.ok) throw new Error('Search failed'); - - const data = await response.json(); + const data = await enhancedSearchFetch(query, { signal: abortController.signal }); console.log('Enhanced results:', data); // Store multi-source state