Remove the never-called checkAvailability chain end to end (Dart bridge +
provider, Android/iOS MethodChannel handlers, Go exports) and stop restoring
its persistent lookup cache on every cold start; the legacy prefs key is
cleared on next cache reset.
Delete dead Go: romaji.go (test-only), the no-op pre-warm chain
(PreWarmTrackCache/PreWarmCache/…), retired Download stubs, and a batch of
exports with no Dart/Kotlin/Swift/Go caller. Kept GetTrackCacheSize/
ClearTrackIDCache (Settings cache screen), SetAllowedDownloadDirs and
Clear/GetItemProgress (live test seams).
Dedup: single updateFlacVorbis + replaceFlacPictures helper behind the six
FLAC tag writers; merge byte-identical extractCommentFrame/extractLyricsFrame
into extractLangTextFrame.
go build/vet + 237 go tests, flutter analyze + tests green.
- sharedTransport ResponseHeaderTimeout 45s -> 120s: downloads ride
this transport and some providers prepare files server-side before
the first byte; the stall watchdog still bounds dead transfers
- uTLS pool: a request that fails on a pooled (possibly silently
dead) connection now re-dials once when the body is repeatable,
matching the old dial-per-request reliability
- cover singleflight completes via defer with a default error so a
panicking fetch can never strand waiters in (nil, nil) or leave a
permanent in-flight entry
Stability:
- transient timeouts no longer classified as ISP blocking; they fall
through to retry backoff (hard blocks - DNS/RST/cert - still abort)
- connectivity change now closes idle Go connections in every network
mode (debounced), so pooled sockets from the old interface are not
reused after a wifi/cellular handoff
- download body reads get a 60s stall watchdog that cancels and
surfaces a retryable network error instead of hanging; distinct
from user cancellation
- ResponseHeaderTimeout 45s on all transports; IdleConnTimeout 90->60s;
dial timeout 30->10s; retry backoff gains full jitter; Retry-After
honored on 5xx and Deezer 429
Data usage / speed:
- cover downloads deduplicated with singleflight plus a 24MB/15min
in-memory cache keyed by final URL (album batches fetched the same
1800px cover once per track before)
- song.link availability cached (30min positive / 5min negative)
in front of the 9-req/min rate limiter
- uTLS Cloudflare path now pools one HTTP/2 connection per host with
a shared TLS session cache instead of a full handshake per request
Deezer artist track-count N+1 kept: counts feed the discography
download UI and are already amortized by the artist TTL cache.
Delete the entire Qobuz downloader implementation (qobuz.go, qobuz_test.go)
including all API clients, search, metadata, download, and track matching
code. Empty the builtInProviderRegistry now that all built-in providers are
retired. Remove Qobuz-specific exports (SearchQobuzAll, GetQobuzMetadata,
ParseQobuzURLExport) and the downloadWithBuiltInQobuz adapter. Stub out
PreWarmTrackCache and cache management since no built-in providers remain.
Move qobuz cover upgrade regex to cover.go. Update Dart screens, providers,
and localization strings for the provider-agnostic UI.
Add set/get/clear store registry URL method channel handlers on Android,
iOS, and Go backend so users can configure a custom extension repository.
Store tab now shows a setup screen when no registry URL is configured,
with a cleaner layout (removed redundant description and helper text)
and visible TextField borders for dark theme.
Minor comment and formatting cleanups across several files.
- Add PopScope with canPop:true to all settings pages for predictive back gesture support
- Change settings navigation to use PageRouteBuilder instead of MaterialPageRoute
- Add album folder structure setting (artist_album vs album_only)
- Fix extension search result parsing to handle both array and object formats
- Update CHANGELOG
Fixes back gesture freeze issue on OnePlus and other Android 13+ devices with gesture navigation