Split the enhanced search dropdown into distinct Albums and Singles & EPs sections using the album_type field. Changed the zero-tracks error from a cryptic red error toast to a clear warning message. Fixed the loading text to show the actual music source name instead of hardcoded "Spotify".
Automatically clear completed downloads from slskd after batch completion, matching the cleanup behavior already present in the frontend. Adds a 5-minute periodic sweep as a safety net when no batches are actively running.
When clicking a partially-complete album on the Library page, the wishlist modal now shows which tracks are owned (dimmed with checkmark) and which are missing (orange border). Ownership data lazy-loads after the modal opens to avoid blocking the UI, using a batch DB query for speed. Also fixes albums like DAMN. showing "14/15" when all available tracks are owned — the frontend now trusts the backend's "completed" status instead of doing raw track count math against potentially inaccurate Spotify metadata.
Replace blocking DB matching in the Library artist detail view with a two-phase render pattern. The page now renders album cards instantly from Spotify/Itunes data , then streams per-release ownership results via SSE that update cards one-by-one.
Update version to 1.6 in sidebar and API. Add changelog for local import, enhanced tagging, mobile layout, and performance improvements. Fix track popularity field access for upcoming Spotify API changes (February 2026).
Added an Import feature that lets users process local audio files through the existing post-processing pipeline (metadata enrichment, cover art, lyrics, library organization). Files are placed in a configurable Staging folder and imported via two modes: Album mode (search/match files to a Spotify tracklist) and Singles mode (select individual files for processing). Includes auto-suggested albums based on staging folder contents and real-time per-track progress tracking.
- Add global discovery_match_cache table to cache successful track matches
(title+artist+provider -> matched result) across all discovery sources
- Cache check before API search in YouTube, ListenBrainz, Tidal, and Beatport
discovery workers; cache write after high-confidence matches
- Re-discovering playlists or overlapping tracks across sources skips API lookups
- Fix Spotify tab sidebar forcing 2-column grid on mobile via inline JS styles
- Add mobile responsive styles for Spotify playlist cards (stack layout vertically)
Enrich downloaded audio files with external identifiers and improved genre metadata in a single post-processing write. During metadata enhancement, the app now looks up the MusicBrainz recording and artist MBIDs, retrieves the ISRC and MusicBrainz genres from a follow-up detail lookup, merges them with Spotify's artist-level genres (deduplicated, capped at 5), and embeds everything alongside the Spotify/iTunes track, artist, and album IDs. All MusicBrainz API calls are serialized through the existing global rate limiter, making concurrent download workers safe without needing to pause the background worker. Includes a database migration adding Spotify/iTunes ID columns to the library tables.
Add optional post-download audio fingerprint verification using AcoustID.
Downloads are verified against expected track/artist using fuzzy string
matching on AcoustID results. Mismatched files are quarantined and
automatically added to the wishlist for retry.
- AcoustID verification with title/artist fuzzy matching (not MBID comparison)
- Quarantine system with JSON metadata sidecars for failed verifications
- fpcalc binary auto-download for Windows, macOS (universal), and Linux
- MusicBrainz enrichment worker with live status UI and track badges
- Settings page AcoustID section with real-fingerprint connection test
- Source reuse for album downloads to keep tracks from same Soulseek user
- Enhanced search queries for better track matching
- Bug fixes: wishlist tracking, album splitting, regex & handling, log rotation
MusicBrainz library enrichment with real-time
status monitoring and manual control.
Features:
- Status icon button in dashboard header with glassmorphic design
- Animated loading spinner during active enrichment
- Hover tooltip showing:
- Worker status (Running/Paused/Idle)
- Currently processing item
- Artist matching progress with percentage
- Click-to-toggle pause/resume functionality
- Auto-polling every 2 seconds for live updates
Backend Changes:
- Added GET /api/musicbrainz/status endpoint
- Added POST /api/musicbrainz/pause endpoint
- Added POST /api/musicbrainz/resume endpoint
- Worker tracks current_item for UI display
- get_stats() returns enhanced status data
Frontend Changes:
- New MusicBrainz button component with tooltip
- Premium CSS styling with animations
- JavaScript polling and state management
- Positioned tooltip below button with centered arrow
Files Modified:
- web_server.py: API endpoints and worker initialization
- core/musicbrainz_worker.py: current_item tracking
- webui/index.html: Button and tooltip structure
- webui/static/style.css: Complete styling (240 lines)
- webui/static/script.js: Polling and interaction logic (115 lines)
- Files downloaded from different soulseek sources carried conflicting MusicBrainz Release IDs and disc number tags that were never overwritten during metadata enhancement, causing Navidrome/Plex to split a single album into multiple entries even when folder structure and album name were identical
- disc_number is now written to file metadata (sourced from Spotify/iTunes API), overwriting stale tags from soulseek sources
- MusicBrainz IDs are now stripped during metadata enhancement so media servers group by album name + artist instead of mismatched release IDs
- The verification worker now applies _resolve_album_group() for album name consistency with the stream processor path
- Fixed source reuse retry logic: used_sources is no longer reset between retries, so a source that errors during transfer is skipped on retry and the system falls through to a normal search instead of retrying the same failing source 3 times
Added per-context-key threading lock in _post_process_matched_download to serialize access when both the Stream Processor and Verification Worker attempt to process the same downloaded file. Previously, both threads would race to move the source file via shutil.move, causing FileNotFoundError for the loser. The lock ensures the first thread completes the move before the second enters, where existing protection checks detect the file was already transferred and return early.
- Single-worker mode for album batches (sequential downloads enable clean source reuse)
- Browse API integration to list files in a source's directory
- Failed source tracking per-batch to avoid retrying broken sources
- Graduated quality scoring for upload speed, queue length, and free slots
- Track number fallback fix (uses Spotify track number instead of hardcoded 1)
- Duplicate completion guard to prevent double-decrement of active worker count
- Dedicated logging for source reuse and post-processing diagnostics
When downloading an album/EP, perform a single album-level search on Soulseek to find a user with the complete album folder before falling back to per-track search. This improves album completion rates and ensures consistent quality across tracks.
Add a /callback Flask route (port 8008) that handles Spotify OAuth token exchange, mirroring the existing HTTPServer handler on port 8888. This allows users behind a reverse proxy to point their Spotify redirect_uri at the main app.
Root cause: When album downloads completed, the frontend immediately closed
the modal and called /api/playlists/cleanup_batch, which deleted the batch
from memory. The wishlist processing thread (submitted to executor) would
then try to access the batch and fail silently because it was already deleted.
This explains why:
- Wishlist auto-processing worked (different timing/3-second delay)
- Manual "Add to Wishlist" button worked (different code path, before downloads)
- Album modal failed tracks didn't get added (race condition)
The fix prevents batch cleanup until wishlist processing completes:
Backend (web_server.py):
1. Mark wishlist_processing_started=True when submitting processing job
2. Mark wishlist_processing_complete=True when processing finishes
3. Block cleanup endpoint if processing in progress (return 202)
Frontend (script.js):
4. Handle 202 response and retry cleanup after 2-second delay
This eliminates the race condition while maintaining async processing and
ensuring all failed/cancelled tracks are properly added to the wishlist.
Issue: Tracks marked as failed or cancelled in the download missing tracks modal
were not being automatically added to the wishlist on completion, despite manual
"Add to Wishlist" button working correctly. Modal completed silently without
mentioning wishlist.
Root cause: Line 549 in web_server.py was calling _on_download_completed() with
wrong parameters - missing batch_id. This caused the completion handler to look
up wrong batch, return early, and never process failed tracks to wishlist.
The bug affected downloads that complete via monitor detection (YouTube, Soulseek)
since the monitor loop calls this function when it detects completed transfers.
Fix: Added missing batch_id parameter to _on_download_completed() call on line 549.
Changed:
_on_download_completed(task_id, success=True)
To:
_on_download_completed(batch_id, task_id, success=True)
Tested: Automatic wishlist addition now works correctly for failed/cancelled tracks.
Frontend: treat discover_album_ playlists as Album Downloads to ensure proper folder structure for Recent Releases.
Backend: inject explicit album context into Wishlist download tasks to force Artist/Album/ grouping instead of flat file handling.
Library page was using album data from discography listing while Artists page used track.album from API. With iTunes, these could have different track counts, causing different album_type classifications.
- Updated handleAddToWishlist to use track.album data like Artists page does
- Added album_type copying to owned releases in merge_discography_data
- Display "Apple Music" instead of "Spotify" in UI when iTunes is active source
- Enhanced connection test messages to indicate Spotify config/auth status
- Fixed similar artists requiring Spotify re-scan when Spotify becomes available
- Fixed hero slider buttons failing for iTunes-only artists
- Updated activity feed items to show correct source name dynamically
When Spotify is enabled after populating similar artists with only iTunes IDs, the freshness check now detects missing Spotify IDs and triggers a refetch. This fixes the Discover page not showing data when switching from iTunes-only mode.
- Add similar artists fetching to web UI scan loop
- Add database migration for UNIQUE constraint on similar_artists table - Add source-agnostic /api/discover/album endpoint for iTunes support
- Fix NOT NULL constraint on discovery_recent_albums blocking iTunes albums
- Add fallback to watchlist artists when no similar artists exist
- Add /api/discover/refresh and /api/discover/diagnose endpoints
- Add retry logic with exponential backoff for iTunes API calls
- Ensure cache_discovery_recent_albums runs even when pool population skips
- Fix platform detection to include is_listenbrainz_playlist check when generating fix buttons
- Update openDiscoveryFixModal to check both listenbrainzPlaylistStates and youtubePlaylistStates
- Update searchDiscoveryFix to detect discovery_source and use appropriate search API
- Add /api/itunes/search_tracks endpoint for manual track search when using iTunes source
- Update selectDiscoveryFixTrack state lookup to include ListenBrainz
Fix button now works correctly for all platforms (YouTube, ListenBrainz, Tidal, Beatport) with both Spotify
and iTunes discovery sources.
- Update _search_spotify_for_tidal_track to accept use_spotify and itunes_client parameters for dual-source
support
- Update _run_tidal_discovery_worker to check is_spotify_authenticated() and fall back to iTunes when Spotify
unavailable
- Update _run_beatport_discovery_worker with same iTunes fallback pattern
- Add discovery_source field to state and results for frontend awareness
- Activity messages now indicate which provider (SPOTIFY/ITUNES) completed discovery
All four discovery modals (YouTube, ListenBrainz, Tidal, Beatport) now support the dual-source architecture:
Spotify preferred, iTunes fallback.
Implement dual-source architecture where iTunes serves as always-available
primary source and Spotify as preferred source when authenticated.
- Make watchlist scans provider-aware (manual and auto paths)
- Update discovery pool population to process both sources
- Update recent albums caching for both sources
- Create source-specific curated playlists (Fresh Tape, Archives)
- Add on-the-fly iTunes ID resolution for similar artists
- Add iTunes ID check to similar artists freshness validation
- Fix sqlite3.Row compatibility in personalized playlists
- Fix iTunes ISO 8601 date format parsing
- Update API endpoints to serve source-appropriate data
This ensures the app remains fully functional if Spotify becomes
unavailable (rate limits, auth issues, bans) by seamlessly falling
back to iTunes data that has been building in parallel.
Implements lazy loading of artist images in search results, artist pages, and similar artist bubbles to improve performance and user experience. Updates the iTunes client to prefer explicit album versions and deduplicate albums accordingly. Adds a new API endpoint to fetch artist images, and updates frontend logic to asynchronously fetch and display images where missing.
Adds iTunes fallback to SpotifyClient for search and metadata when Spotify is not authenticated. Updates album type logic to distinguish EPs, singles, and albums more accurately. Refactors watchlist database methods to support both Spotify and iTunes artist IDs. Improves deduplication and normalization of album names from iTunes. Updates web server and frontend to use new album type logic and support both ID types. Adds artist bubble snapshot example data.
Introduces iTunes artist ID support to WatchlistArtist and database schema, enabling proactive backfilling of missing provider IDs (Spotify/iTunes) for watchlist artists. Updates WatchlistScanner to use MetadataService for provider-agnostic scanning and ID matching, and modifies web_server to support scans with either provider. Includes new database migration and update methods for iTunes and Spotify artist IDs.
Changed stuck flag detection for wishlist and watchlist auto-processing from 2 hours to 15 minutes for faster recovery. Updated log messages and related logic to reflect the new timeout and display stuck duration in minutes. Also updated wishlist stats to use the improved stuck detection function.
Added backend support for reporting current auto-processing state and cycle in the wishlist stats API. Updated frontend to detect and handle auto-processing start, close modals, and notify users, as well as improved countdown timer updates and conflict handling when starting manual processing.
Refactored wishlist and watchlist auto-processing scheduling to use atomic timer updates and retry logic, preventing stuck timers and improving reliability. Removed excessive debug logging and improved error handling throughout related functions. Added checks to prevent concurrent wishlist processing and ensured timer state is managed consistently.
Added logic to remove duplicate tracks based on their Spotify track ID during both the sanitization and category filtering steps in get_wishlist_tracks(). This ensures the frontend receives a deduplicated list and improves data consistency. A warning is printed if duplicates are found and removed during sanitization.
Enhanced wishlist and watchlist processing to deduplicate tracks during both sanitization and filtering, preventing duplicate downloads and processing. Added explicit resets of next run timer variables to ensure accurate scheduling after each cycle. Updated countdown timer display in the UI to show '0s' when timer reaches zero instead of hiding it.
Introduces new filters for live versions, remixes, acoustic versions, and compilation albums to the watchlist artist configuration. Updates the database schema, backend API, and web UI to support these options, allowing users to customize which content types are included for each artist in their watchlist.
Standardizes the use of extract_filename() for context keys to ensure consistent lookup and storage across download and post-processing flows. Increases fuzzy match thresholds in file search to reduce false positives. Adds per-file threading locks to prevent concurrent metadata writes, improving thread safety during metadata enhancement.
Introduced _sanitize_context_values to clean all string values in the context dictionary before applying path templates. This prevents unsafe characters (like '/') in metadata (e.g., artist names) from creating unintended path components during template substitution.
Adds a check for the presence of 'load_config' in config_manager. If not found, uses a fallback method to support older settings.py files, improving compatibility with legacy Docker volumes.
Bump version to 1.3 and update the version info modal to highlight the new YouTube download engine, Docker and system reliability fixes, and general improvements. Update the web UI to display v1.3 and apply minor formatting and accessibility improvements throughout index.html.
Updated _find_downloaded_file to resolve download paths for Docker environments, ensuring compatibility with host-mounted directories. Also updated README to clarify YouTube integration and sources.
Enhanced the Tidal authentication page to provide clearer, step-by-step instructions for users accessing the app remotely or via Docker. The new flow helps users update the callback URL as needed, improving the authentication experience in non-localhost environments.
Adds critical fixes to reschedule timers after stuck flag recovery for wishlist and watchlist processes, preventing deadlocks and ensuring continuity. Refines album classification by prioritizing Spotify's album_type over track count heuristics, and ensures album_type is included in API responses. Updates frontend logic to pass and use fresh album/artist context for discover_album modals, improving metadata accuracy and display.
Replaces the timer-based automatic watchlist scanning with a background heartbeat thread for improved reliability and robust retry logic. The new system handles scheduling, conflict detection, and error recovery, while UI countdown updates are decoupled from actual scheduling.
Refines album/single classification in get_wishlist_stats by considering explicit 'album' type for short multi-track releases. Also updates openDownloadModalForRecentAlbum to include total_tracks and album_type in album data for more accurate processing.
Replaces the previous daisy-chained timer logic for automatic wishlist processing with a robust background heartbeat thread. This ensures reliable scheduling, simplifies stopping/starting, and improves error handling. UI countdown updates remain compatible with existing call sites.
Introduces a reload_config method to SpotifyClient and refactors ConfigManager to support reloading configuration from a file. Updates web_server.py to use the new config loading mechanism, ensuring configuration is loaded into the existing singleton instance and SpotifyClient is properly re-initialized after settings changes.
Changed Docker volume mapping from './database' to './data' in README-Docker.md for SQLite files. Updated web_server.py to support config path override via SOULSYNC_CONFIG_PATH environment variable, improving Docker compatibility.
Updated the normalize_title function to remove unicode accents using NFD normalization and filtering non-spacing marks. This enhances title comparison by handling accented characters more robustly.
Adjusts matching weights for YouTube sources to rely more on title and duration, adds a shutdown callback to the YouTube client to prevent new downloads during shutdown, and enhances post-processing to reliably resolve actual YouTube file paths. Improves error handling for file removal, ensures no new batch downloads start during shutdown, and refines download monitoring to trigger post-processing on completed YouTube downloads. Also increases YouTube download retries and improves logging for debugging.
Enhanced download status and post-processing logic to properly handle YouTube downloads alongside Soulseek transfers. Improved file organization for simple downloads, moving singles without album info directly to the Transfer root. Added a new generic Spotify search API endpoint. Updated frontend logic to correctly display YouTube download titles and results, and improved filename parsing for YouTube tracks.
Enhances streaming logic to better support YouTube as a download source, including improved filename handling, fuzzy file matching, and search query generation. Updates format checks in the frontend to skip them for YouTube (always MP3). Refactors backend to use a unified download status API for both Soulseek and YouTube, and improves service test messaging based on the active download mode.
Introduces a DownloadOrchestrator class to route downloads between Soulseek and YouTube based on user-configurable modes (Soulseek only, YouTube only, Hybrid with fallback). Updates web server and UI to support new download source settings, including hybrid mode options and YouTube confidence threshold. Refactors YouTube client for thread-safe download management and bot detection bypass. Ensures quality filtering is skipped for YouTube results and improves file matching and post-processing logic for YouTube downloads.
Introduces the $year variable for album, single, and playlist path templates, allowing users to include the release year in file organization. Updates the backend to extract and provide the year, adjusts the web UI to document the new variable, and updates validation logic to recognize $year as valid in templates.
Wrapped calls to schedule_next_wishlist_processing in try/except blocks to prevent timer thread termination if scheduling fails. This improves robustness and ensures continuity of automatic wishlist processing cycles even in the event of scheduling errors.
Increases Spotify search result limits for artists and albums. Adds dynamic glow effects to artist, album, and track cards in the UI using image-based colors. Significantly upgrades the CSS for enhanced dropdowns, cards, and lists with a premium, vibrant, and responsive design.
Bumps SoulSync version to 1.2, introducing a unified multi-source search system, a major overhaul of the matching engine for improved accuracy, and significant wishlist and quality-of-life improvements. Updates version info and UI elements to reflect the new release and its features.
Introduces a backend API endpoint and frontend logic to allow users to stream individual tracks directly from enhanced search results. Updates the UI to include a play button for each track, adjusts the search mode toggle to default to enhanced search, and refines related styles for improved user experience.
Implements a persistent search bubble system for tracking album and track downloads in enhanced search. Adds backend API endpoints for saving and hydrating search bubble snapshots, frontend state management for search download bubbles, UI for displaying and managing active/completed downloads, and associated styles for search bubble cards. This enables users to resume and manage search downloads across page refreshes.
Increased the number of tracks returned by enhanced search from 10 to 20. Updated CSS for enhanced search sections and artist cards to improve visual appearance, spacing, and responsiveness, including larger artist images, new backgrounds, and better layout for various screen sizes.
Implements an enhanced search endpoint in the backend that unifies Spotify and local database results, returning categorized artists, albums, and tracks. Updates the frontend with a new dropdown overlay for live search, debounced input, categorized result rendering, and direct integration with the main results area for album/track selection. Adds new CSS for the dropdown and result cards, and updates the Track dataclass to include image URLs for richer UI display.
Introduces a search mode toggle in the downloads UI, allowing users to switch between basic and enhanced search modes. Adds new HTML structure, JavaScript logic, and CSS styles for the enhanced search interface (currently placeholder functionality). In the backend, implements a retry system for file discovery after download completion to handle race conditions, with cleanup of stale retry attempts to prevent memory leaks.
Introduces an optional 'limit' query parameter to the /api/wishlist/tracks endpoint for improved performance when fetching tracks. Updates the frontend to use this parameter, limiting requests to 50 tracks per category when fetching album and single covers.
Eliminates hardcoded source prefixes (e.g., [Tidal], [YouTube], [Beatport], [ListenBrainz]) from playlist names in both backend and frontend code. Source detection is now handled via virtualPlaylistId prefixes, improving consistency and simplifying playlist name handling throughout the application.
Adds robust track-to-track matching for album and single downloads, enabling enhanced metadata enrichment using Spotify data. Updates both backend and frontend to support matching Soulseek tracks to Spotify tracks, sending full Spotify track objects for improved organization and post-processing. Simplifies context handling for simple downloads and removes legacy flags, ensuring more accurate and consistent metadata for matched downloads.
Adds detection for remote access during Spotify authentication and provides step-by-step instructions for users connecting remotely, including guidance on modifying the callback URL. Enhances user experience with styled HTML and a copy-to-clipboard button for the host IP.
Introduces a template-based file organization system for downloads, allowing users to define custom folder and filename structures for albums, singles, and playlists. Updates the backend, config example, web UI, and client-side validation to support template editing, resetting, and error checking. Improves consistency in file placement and metadata handling across all download modes.
Enhanced handling of artist data to support both string and object formats across the database, sync service, and web server. The sync process now preserves full album and artist objects for tracks, enabling wishlist additions with album cover art. The frontend and API were updated to use the full artist objects, and the UI now formats artist names correctly.
Introduces API endpoints and UI elements to view and change the application's log level from the web interface. Log level changes are applied immediately and persisted in the database. Updates backend logic, logging utilities, and frontend scripts to support this feature.
Introduces backend API endpoints to remove individual tracks or all tracks from an album in the wishlist. Updates the frontend to display delete buttons for tracks and albums, with confirmation modals before removal, and styles these new UI elements for clarity and usability.
Introduces backend and frontend functionality to list and select Jellyfin music libraries. Adds API endpoints, updates the client logic, and provides a UI selector for users to choose their preferred Jellyfin music library.
Implements automatic cleanup of completed, errored, or cancelled batches after 5 minutes to prevent stale state. Adds stuck task detection for 'searching' and 'post_processing' states, forcing failure or completion if tasks exceed time thresholds. Updates batch completion logic to track completion timestamps and handle orphaned tasks more robustly. Also improves wishlist auto-processing timer management.
Adds support for sending specific track IDs from the frontend to the backend when starting wishlist missing downloads. This ensures only the tracks currently visible to the user are processed, preventing race conditions if the wishlist changes between modal open and analysis start. Category filtering remains for backward compatibility.
When an artist is added to the watchlist, their image is now fetched from Spotify and cached in the database immediately if available. This improves user experience by ensuring artist images are present without requiring a separate fetch.
Added logic to both automatic and manual wishlist processing to check for and remove tracks that already exist in the library before initiating downloads. This prevents unnecessary bandwidth usage and keeps the wishlist up to date.
Improves handling of concurrent wishlist and watchlist operations by moving scheduling outside the lock and using flags to avoid deadlocks. This change ensures that scheduling the next wishlist processing does not occur while holding the lock, reducing risk of deadlock and improving code clarity.
Introduces timestamp-based stuck-flag detection and auto-recovery for both wishlist auto-processing and watchlist auto-scanning, preventing indefinite blocking if a process crashes. Refactors watchlist auto-scanning to use a timer-based system (mirroring wishlist), adds smart mutual exclusion between wishlist and watchlist automation, and ensures flags are always reset on completion or error. Improves startup diagnostics to recover stuck flags, and enhances logging and scheduling for both automation systems.
Implements manual track matching (discovery fix modal) for YouTube, Tidal, and Beatport platforms, allowing users to search and select Spotify tracks for unmatched results. Adds backend endpoints and frontend logic for updating matches, improves conversion of discovery results for sync/download, and updates Dockerfile/entrypoint for dynamic PUID/PGID/UMASK support. Includes a new DOCKER_PERMISSIONS.md guide.
Introduces backend scraping and API endpoint for Beatport genre Top 10 and Hype Top 10 tracks, with 1-hour caching. Updates frontend to load and display these lists in the genre browser modal, matching main page structure and click handling for chart discovery.
Introduces a new API endpoint to scrape tracks from multiple Beatport release URLs and integrates hero slider click handling on the rebuild page. The frontend now extracts release URLs from the hero slider and fetches track data using the new backend endpoint, improving rebuild page functionality.
Redirect URIs for Spotify and Tidal OAuth are now configurable via the web UI and settings. Updated backend clients to use the configured redirect URI if provided, improving flexibility for deployments with custom callback URLs.
Wishlist tracks are now sorted by artist and track name for consistent display. The database query for wishlist tracks now orders by date_added instead of randomly. Added logic to remove completed tracks from the wishlist during failed track processing. Updated docker-compose.yml to mount the H: drive for transfer folders.
Added helper functions to resolve Windows paths for Docker containers and to extract filenames in a cross-platform manner. Updated usage throughout web_server.py and soulseek_client.py to ensure correct path mapping and filename handling. Modified docker-compose.yml to use named volumes and mount the E: drive for better Docker compatibility.
Updated Soulseek client, web server, and docker-compose.yml to better handle service URLs when running inside Docker containers. Localhost URLs are now resolved to host.docker.internal, and Docker-specific volume mounts and extra_hosts are configured for improved interoperability between container and host services.
Introduces web server routes and UI buttons for initiating Spotify and Tidal OAuth authentication flows, with dedicated callback servers for token exchange. Updates Docker ports for OAuth callbacks and refines PKCE handling for Tidal. Improves user experience by allowing authentication directly from the web UI.
Introduces Docker deployment files (.dockerignore, Dockerfile, docker-compose.yml, docker-setup.sh, requirements-webui.txt, and README-Docker.md) for SoulSync WebUI. Refactors core/database_update_worker.py and core/media_scan_manager.py to support headless operation without PyQt6, enabling signal/callback compatibility for both GUI and non-GUI environments. Removes logs/app.log file.
Bumped version to 1.0 and updated all version references and changelog details to reflect the major release. SoulSync now features a fully rebuilt web-based UI, Docker container support, enhanced music management, and significant performance improvements.
Introduces a metadata updater backend in web_server.py, including API endpoints for starting, stopping, and checking status, and a threaded worker for updating artist metadata from Spotify. Updates script.js to add UI controls, polling, and progress display for the metadata updater, with logic to hide the tool when Jellyfin is the active server.
Introduces activity item logging for settings saves, connection tests, auto-detects, authentication flows, searches, batch cancellations, and discovery operations in web_server.py. Updates dashboard connection test API and UI to use a new endpoint and function, ensuring user actions are tracked and surfaced in the activity feed.
Introduces a global activity feed system with API endpoints for recent activities and toasts, and integrates activity tracking for key backend events (downloads, syncs, database updates, etc.). Updates the dashboard frontend to periodically fetch and display activity feed items and show toasts for recent actions. Improves error logging and reduces noise for expected 404s in Soulseek client. Adds related CSS for activity feed separators.
Introduces a new /api/system/stats endpoint in web_server.py to provide system statistics such as uptime, memory usage, download speed, and sync counts. Enhances the dashboard in script.js to periodically fetch and display service connection status and system stats, including response times for Spotify, media server, and Soulseek.
Introduces a watchlist system for tracking artists, including backend API endpoints for managing the watchlist and scanning for new releases. Updates the frontend to allow users to add/remove artists to/from the watchlist from both artist cards and detail pages, view and scan their watchlist via a modal, and see real-time scan progress. Adds related styles for watchlist UI components.
Introduces backend logic to automatically remove tracks from the wishlist if they already exist in the database after downloads or database updates. Adds a new API endpoint and frontend button for manual wishlist cleanup, allowing users to remove already-owned tracks from the wishlist. Enhances reliability and user experience by keeping the wishlist up-to-date.
Sanitizes wishlist track data for consistent backend/frontend handling, enhances wishlist process state reporting for better UI sync, and refactors frontend modal logic to prevent auto-show conflicts and ensure user-driven visibility. Also improves polling and rehydration to keep frontend state in sync with server-side auto-processing.
Introduces a new atomic cancel system (V2) for download tasks, ensuring single-step cancellation with proper worker slot management and backend-driven state. Updates both backend (web_server.py) and frontend (script.js) to support V2 cancel API, persistent cancel state, and improved UI handling for cancelling tasks, eliminating race conditions and dual state management.
Introduces backend API endpoints and frontend logic to persist and restore artist download bubble state across page refreshes. Snapshots are saved and hydrated with live download status, ensuring continuity of user progress and UI state. Includes debounce logic for efficient snapshot saving and automatic cleanup of outdated or invalid snapshots.
Refactored download monitor to handle error and timeout retries directly and consistently, removing legacy retry methods. Improved batch completion logic to ensure batches are only marked complete when all tasks are truly finished, preventing premature completion. Updated client-side polling to never stop automatically, using exponential backoff on failures, and fixed worker counting to exclude post-processing tasks. Enhanced post-processing and verification workflows to avoid double completion callbacks and ensure proper task state transitions.
Introduces a new post-processing workflow in web_server.py that verifies file existence and integrity before marking download tasks as completed. Updates status handling to include a 'post_processing' state and reflects this in the frontend UI, ensuring users see accurate progress and preventing premature completion status for downloads.
Adds server-side validation and healing for download batch worker counts to prevent ghost workers and orphaned tasks, including periodic batch state checks and recovery logic. Enhances thread safety with batch-specific locks and improves error handling in worker slot management. On the frontend, implements exponential backoff for polling failures, validates server responses, and logs worker count discrepancies for better debugging and UI consistency.
Introduces backend API and frontend integration for downloading missing tracks from artist albums and singles. Adds artist download bubbles, management modal, and related state/UI logic to script.js, with supporting styles in style.css. Also refactors some type hints in web_server.py for consistency.