- Add reference-counted cancel entries to prevent premature cleanup when multiple operations share the same itemID
- Propagate cancellation to DownloadTrack, DownloadWithFallback, DownloadWithExtensionsJSON, extension providers, and ISRC search
- Fetch album artist from MusicBrainz when missing during download and re-enrich
- Make ALBUMARTIST tag nullable to avoid writing artistName as album artist
- Add home feed 'Off' option in extension settings
- Skip deezer in download provider priority sanitization
- Move explore JSON decode/encode to compute() isolate to avoid blocking main thread
- Memoize search sort results (artists/albums/playlists/tracks) in HomeTab; invalidate on new query
- Extract _DownloadedOrRemoteCover StatefulWidget with proper embedded-cover lifecycle management
- Replace O(playlists x tracks) in-memory playlist picker check with SQL loadPlaylistPickerSummaries query
- Add FutureProvider.family (libraryPlaylistPickerSummariesProvider) invalidated on all playlist mutations
- Memoize _buildQueueHistoryStats, localPathMatchKeys, and localSingleItems in QueueTab
- Add coverCacheWidthForViewport util; apply memCacheWidth/cacheWidth based on real DPR across all album/playlist/track screens
- Convert sync file ops in TrackMetadataScreen to async; use mtime+size as validation token
- Fetch Deezer album nb_tracks in parallel via fetchAlbumTrackCounts
- Default track/disc number to 0 (unknown) instead of 1, letting the
backend use the service-provided value or skip the field entirely
- Add releaseDate to ExploreItem so explore downloads carry release info
- Pass discNumber and releaseDate from extension album/playlist tracks
- Fix isDeezer detection using service field instead of substring match
- Add _displayServiceTrackId() to properly strip prefixes for all services
- Add homeFeedProvider field to AppSettings with picker UI in extensions page
- Update explore_provider to respect user's home feed provider preference
- Add normalizeCoverReference() and normalizeRemoteHttpUrl() to filter
invalid cover URLs (no scheme, no host, protocol-relative)
- Apply cover URL normalization across all screens and providers to
prevent 'no host specified in URI' errors from Qobuz
- Propagate CoverURL from QobuzDownloadResult through Go backend so
cover art is available even when request metadata is incomplete
- Cache home feed to SharedPreferences for instant restore on app launch
- Resolve SAF tree URIs to human-readable paths (e.g. /storage/emulated/0/Music)
- Add Android 13+ per-app language support (locale_config.xml)
- Bump version to 3.5.0+73
- iOS: Auto-migrate file paths when container UUID changes after app update
- Greeting: Use device local time instead of extension response
- i18n: Fix 16 ICU plural syntax warnings in Spanish and Portuguese
- Add duration_ms field to ExploreItem model
- Parse duration_ms from spotify-web and ytmusic home feed responses
- Update _downloadExploreTrack to use item.durationMs
- Fixes track duration showing 0:00 in metadata screen after download
- Bump version to 3.2.0+63
- Add Home Feed/Explore feature with extension capabilities system
- Add pull-to-refresh on home feed (replaces refresh button)
- Add gobackend.getLocalTime() API for accurate device timezone detection
- Add YT Music Quick Picks UI with swipeable vertical format
- Fix greeting time showing wrong time due to Goja getTimezoneOffset() returning 0
- Update spotify-web and ytmusic extensions to use getLocalTime()
- Add Turkish language support
- Update CHANGELOG for v3.2.0