Commit Graph
3137 Commits
Author SHA1 Message Date
zarzet 8fd574f010 refactor(rewind): split the listening rewind screen and move its providers
The two Rewind providers move to lib/providers and are re-exported from the
screen so existing imports keep working. Story, slides and widgets become
part files of the screen library. No behavior change.
2026-10-18 22:40:10 +07:00
zarzet 77c8639df2 refactor(lyrics): split player_lyrics.dart into line-style and word-sweep parts
The word-sweep painter and the line style helpers are self-contained, so
they move into part files of the same library. No behavior change.
2026-10-18 22:40:10 +07:00
zarzet 237690cd89 refactor(metadata): move editor form primitives into a widgets file
Options group, quick-select button, switch field, selection field and
section card become public StatelessWidgets in metadata_editor_fields.dart
with unchanged build bodies; State fields they read (color scheme, fetching
flag) are now constructor parameters.
2026-10-18 22:39:31 +07:00
zarzet 714bec6aaf refactor(metadata): split the edit sheet into cover and auto-fill parts
Cover editor members and auto-fill members move to extensions in part
files; bodies are unchanged except setState goes through a _setState
forwarder, as in the other State part files.
2026-10-18 22:39:31 +07:00
zarzet 77377f6b67 refactor(metadata): one option picker for provider and cover size
The provider and cover-size pickers shared the sheet shell and row layout.
Both now go through _showEditorOptionPicker<T>; per-picker differences
(label ellipsis, which context supplies the check icon theme) stay as
parameters.
2026-10-18 22:39:31 +07:00
zarzet 1c7146f906 refactor(home): split the home tab build into sliver-group builders
The 440 line build method now computes shared state once and composes one
private builder per sliver group (header, intro, search bar, filters, recent
access, home sections, explore, explore skeleton, search results). Conditions,
order, keys and provider watches are unchanged.
2026-10-18 22:32:15 +07:00
zarzet bdb2e636e9 refactor(home): move extension collection screens into their own library
ExtensionAlbumScreen, ExtensionPlaylistScreen and ExtensionArtistScreen and
their exclusive helpers lived in home_tab_widgets.dart, a part of the home tab
library. They now live in extension_collection_screens.dart, re-exported from
home_tab.dart so existing importers keep working. artist_screen.dart and
clickable_metadata.dart import the new library directly instead of home_tab.
2026-10-18 22:32:15 +07:00
zarzet 4009855ba5 refactor(library): build the filter sheet from the sort-mode table
The filter sheet moves into its own part. The sort chips now iterate
_librarySortModes with _sortLabel (same modes, labels and order), and the
source, quality and metadata groups use value/label tables since their chips
differ only in value and label.
2026-10-18 22:26:54 +07:00
zarzet 96568f720a refactor(library): move queue download labels, dialogs and sliver grid out of queue_tab.dart
Pure moves: download label helpers and the download dialogs become parts of
the queue_tab library, and the animated sliver grid becomes a public widget
in lib/widgets since it uses no private state.
2026-10-18 22:26:54 +07:00
zarzet 23c6621552 refactor(bridge): move platform_bridge helpers into part files
Top-level helpers and secondary classes (codec isolates, cache entries,
event and SAF models, the native worker job state and the NDJSON scan
file) move verbatim into part files grouped by concern. The
PlatformBridge class body is unchanged apart from three region comments
over groups that were already contiguous.

platform_bridge.dart was one 2900-line file mixing eight concerns; the
static class cannot be split without changing its type, so this moves
what can move mechanically and leaves the class intact for call sites
and the channel mocks in tests.
2026-10-18 22:24:10 +07:00
zarzet 2debaa5363 refactor(providers): remove the unused Deezer catalogue search
DeezerClient::search_all was reachable only through
Backend::search_deezer, which had no production caller: no UniFFI
export, platform channel or extension API wraps it, and no built-in
Deezer catalogue search is planned. Remove the chain together with the
items that existed only for it: the core search result types, the Deezer
search page types and their API error wrappers, the cached Search value,
and the latency test that exercised the search fan-out.

The Search cache bucket stays because the coalesced Deezer lookups use
it. The shared error context helper moves into the deezer module now
that search.rs is gone. searchDeezerByISRC is a separate, live method
and is untouched.
2026-10-18 22:22:57 +07:00
zarzet d60baee4a7 refactor(rust): restrict test-only functions
check_from_deezer and the lyrics cache_size accessor are only called by
unit tests in their own crate, so compile them only for tests and narrow
them to the crate.

call_download is only used by the extensions integration tests, which
can only reach public items; the download manager goes through
call_download_provider. Keep it public but hide it from the docs.

RequestLease::wait_cancelled stays public: the extensions crate's unit
tests call it across the crate boundary and a later coalescer change is
expected to use it.
2026-10-18 22:22:57 +07:00
zarzet ef5fa1cb46 perf(lyrics): compile credit regexes once
with_credits runs for every parse_lyrics data job and compiled up to
seven regexes per call. Hoist them into LazyLock statics next to the
other lyrics patterns, with the same pattern text, so each is compiled
once per process. Every other regex in the workspace is already static.

storage_failure also lowercased the error message once per probe on the
download failure path; lowercase it once and reuse it.
2026-10-18 22:22:57 +07:00
zarzet 5dbf9e6c29 refactor(network): drop the ignored insecure_tls parameter inside Rust
NetworkService::set_network_compatibility_options ignored the
insecure_tls flag by design because TLS verification is never disabled.
Remove the parameter from the network service and the extension
environment so the dead flag no longer travels through internal layers.

The UniFFI method keeps its signature: Kotlin and Swift still pass the
flag, and the mobile binding accepts and ignores it until the binding
and channel cleanup lands separately.
2026-10-18 22:22:57 +07:00
zarzet 6879df4917 refactor(services): clarify misleading names and drop a no-op rethrow
Remove the try/catch that only rethrew in the library scan helper, rename
the history loader that schedules a microtask, and fix two comments.
2026-10-18 22:12:29 +07:00
zarzet 019257541b refactor(logging): rename Go-era log names to native
The log buffer polls the native backend, so isFromGo, the Go log polling
methods and their private state now use native names. Comments that still
described the backend as Go are reworded. No string literals changed.
2026-10-18 22:12:29 +07:00
zarzet 4887172926 refactor(services): mark test-only members and privatize file-local ones
Annotate members that only tests call with @visibleForTesting and make
helpers used only inside their own file private.
2026-10-18 22:12:29 +07:00
zarzet ec1b84e6de refactor(services): remove members with no caller
Delete Dart members that have no reference in lib, test or integration_test:
unused player configuration helpers and event streams, two PlatformBridge
wrappers, database and export helpers, the unused global logger and the
now pointless 'hide log' imports.
2026-10-18 22:12:29 +07:00
zarzet e41e6ec432 test: share one FixedSettingsNotifier across tests
Replace 16 private SettingsNotifier fakes that only returned a fixed AppSettings with test/support/fixed_settings.dart. Mornye owner WIP tests and bespoke fakes are untouched.
2026-10-18 22:08:02 +07:00
zarzet 77c149eb20 test: skip the automix renderer test when ffmpeg is missing
Mirror the other ffmpeg-backed tests: skip instead of failing with a ProcessException on hosts without ffmpeg.
2026-10-18 22:08:02 +07:00
zarzet 25ad8b3c71 test: poll for cover eviction instead of asserting after one event-loop turn
Cover eviction deletes files without awaiting, so asserting right after one event-loop turn was timing dependent. Poll with a bounded timeout instead.
2026-10-18 22:08:02 +07:00
zarzet f8f911c920 chore(analysis): analyze hand-written l10n files and correct the lint comment
Only the generated app_localizations*.dart files need excluding; l10n.dart
and supported_locales.dart are hand-written. The unreachable_from_main
comment now states what the lint actually checks.
2026-10-18 22:07:18 +07:00
zarzet 7cef0700cc test: split models_and_utils_test by domain and isolate source contracts
The grab-bag file mixed model tests with tests that pin literal source
text across Dart, Kotlin and Swift. The contracts now live in
source_contracts_test.dart with a header explaining that they must be
updated, never deleted, when code moves. The remaining groups moved
verbatim into domain files.
2026-10-18 22:07:17 +07:00
zarzet db85ef0547 docs(rust): mark the Unicode case table as frozen and generated
The table is pinned to Unicode 15.0.0 for matching parity and its generator
is no longer in the repository. Say so in the header and mark the file as
generated for linguist.
2026-10-18 22:02:52 +07:00
zarzet 43f7257d3d docs(rust): say that Go is the retired backend in crate docs
Rust is the only backend and routes the app on Android and iOS. Rewrite
the migration-era crate, script and comment wording that implied Go still
runs, and note in each crate doc that Go mentions describe the retired
backend whose observable behavior remains a compatibility contract.
2026-10-18 22:02:52 +07:00
zarzet 5254760bbd build(rust): drop unused direct dependencies and centralize pins
Remove tokio from spotiflac-extensions and thiserror and the direct hyper
entry from spotiflac-network (hyper stays resolved through hyper-util).
Move roxmltree, rusqlite and libc into workspace.dependencies. libc already
resolves to 0.2.190, so the workspace pin uses that exact version. No
resolved version or enabled feature changes.
2026-10-18 22:02:35 +07:00
zarzet 95a8802e42 docs(contributing): name every third_party fork and scope the ffmpeg override
The boundaries table left out the two audioplayers forks and the encrypted
Discord SDK, and the test prerequisites implied SPOTIFLAC_TEST_FFMPEG applies
to every ffmpeg test when only the automix renderer test reads it.
2026-10-18 22:02:15 +07:00
zarzet 9063104799 chore: retire Go-era config and rename SMB fixture servers
Drop the gomod renovate rule, the stray em dash in crowdin.yml and the migration wording in check_rust_backend.sh. Rename the SMB fixture servers so test_*.py discovery no longer implies unit tests, and describe supported_locales.dart as hand-maintained since its generator never existed.
2026-10-18 22:01:32 +07:00
zarzet 3e86ca14e6 docs(contributing): match the repository (l10n, gradle, ffmpeg, test layers)
Generated l10n sources are gitignored, there is no Gradle wrapper, some tests need ffmpeg, and the test layers and boundary directories were undocumented.
2026-10-18 22:01:32 +07:00
zarzet 4c78f476d3 ci: run the Android Rust build once and cache Cargo
The rust job rebuilt the Android libraries that the android job already builds through Gradle. Drop it, cache Cargo for the rust, rust-ios and android jobs, widen the rust path filter to the fixtures the Rust tests read, default workflow tokens to contents: read, and delete the inert auto-tag workflow.
2026-10-18 22:01:32 +07:00
zarzet 0539a12f99 ci: add a dart format gate and fix the one drifted test file
Format drift was unchecked in CI. Add the gate before analyze and include integration_test in the documented format commands.
2026-10-18 22:01:32 +07:00
zarzet acbc614f42 perf(library): build DateFormat and RegExp once instead of per row
The month-year DateFormat was rebuilt for every loaded row and every
fast-scroller drag label; it is now cached per locale tag. Constant-pattern
RegExp objects built per call (or per word) are now static or top-level.
2026-10-18 21:56:46 +07:00
zarzet 0810ee7847 refactor(library): drop unread QueueTab page parameters and fast-scroller callbacks
Nothing read parentPageController, parentPageIndex or nextPageIndex, and the
Library tab root watched showExtensionStore only to compute them, so toggling
that setting rebuilt the tab for nothing. No caller passed the fast scroller
onDragStart/onDragEnd callbacks.
2026-10-18 21:54:05 +07:00
zarzet 68c739dfa1 fix(equalizer): keep headroom and limiter choices when applying a preset
Applying a preset replaced every setting, so built-in presets silently
turned automatic headroom, the limiter and the compressor back on and
reset balance. Presets now carry only the curve, preamp, bass and treble.
The active preset is matched on the same fields, so it no longer shows as
Custom once headroom is off.
2026-10-18 20:58:36 +07:00
zarzet d63d95db63 fix(lyrics): restore QQ Music search after the desktop CGI broke
The desktop search CGI now answers HTTP 500 for every query, so QQ Music
never reached its lyrics. Search through the suggestion box instead, rank
title and artist matches, and check the length of the best few through
the song detail CGI so a live or remixed cut is skipped. The lyrics CGI
is unchanged and still answers.
2026-10-18 20:50:36 +07:00
zarzet 52ef41f156 docs(readme): describe the lyrics providers and online search
Explain the default provider order and Search online in the FAQ, mention
SpotiFLAC-Mobile Lyrics in the Lyrics feature, and credit lrc.red,
LyricsPlus and BetterLyrics.
2026-10-18 19:24:39 +07:00
zarzet dbee3d56cb feat(player): search lyrics online for files without them
The empty lyrics page offers Search online, which asks the enabled lyrics
providers in their configured order. The result is shown in the player
only and never written to the file; a late result is dropped after the
track changes, and a miss says so.
2026-10-18 19:24:39 +07:00
zarzet 56ad01ec2c feat(lyrics): add lrc.red and BetterLyrics, split SpotiFLAC-Mobile Lyrics
Add two keyless providers that serve Apple Music TTML: lrc.red, matched by
recording, and BetterLyrics, which answers songs it has already cached.
TTML is read into the first-party Apple line structure, so vocal sides,
backing groups, word timing, translations and romanization share one eLRC
formatter. The XML depth guard moves to core so both readers use it.

SpotiFLAC-Mobile Lyrics becomes its own provider instead of a fallback
inside Apple Music. New defaults are Apple Music, lrc.red, SpotiFLAC-Mobile
Lyrics, LyricsPlus and LRCLIB. Migration 13 moves untouched defaults to the
new list and keeps the former fallback right after Apple Music in custom
orders. Replace the dead LyricsPlus Workers mirror.
2026-10-18 19:24:31 +07:00
zarzet 16cae16562 docs(readme): redesign banner, sections and showcase
Replace the banner with animated light and dark SVGs built from M3
Expressive shapes, give every section heading a shaped icon, and swap the
four screenshots for a themed showcase of Home, Library, Now Playing and
Equalizer. Rewrite the FAQ for the current app and trim API Credits to a
single line of services the app still uses.
2026-10-18 18:45:57 +07:00
zarzet 0d496acc99 docs(readme): show the redesigned Home screen 2026-10-18 18:10:17 +07:00
zarzet 67a346c15b feat(home): greet in the header and gather listening shortcuts
Without a feed, the Material Home now greets in its header with a
prompt picked once per launch, keeps import and paste out of the
resting search field, and fills the page with Continue listening,
player shortcuts, Recently added tracks from the whole Library and the
most played tracks of the last four weeks.
2026-10-18 18:08:13 +07:00
zarzet 96dc66f34f docs(readme): refresh screenshots, badges and feature table
Replace the old screenshots with Home, Library, Now Playing and
Equalizer captures, add the Featured on FMHY badge, redraw the release,
Crowdin and Telegram badges as Material Expressive light and dark
images, and replace the Extensions section with a two-column feature
table using colored shape icons.
2026-10-18 18:05:41 +07:00
zarzet 2ede99bef8 fix(player): restore the lighter full-screen cover scrim
Shade the app bar lightly and ease it out so white icons stay legible
without darkening the top of the cover.
2026-10-18 12:41:28 +07:00
zarzet 7c0b275f9f feat(onboarding): introduce the 5.2 release tour 2026-10-18 04:09:16 +07:00
zarzet 66d480dbdc fix(storage): retain legacy Android cipher migration support 2026-10-18 04:09:16 +07:00
zarzet 080df889d0 fix(library): recover missing local album artwork from audio 2026-10-18 04:09:15 +07:00
zarzet 02e67cf3d3 feat(library): add adaptive icons to collection tabs 2026-10-18 03:11:54 +07:00
zarzet 759079517c fix(library): restore bit depth as the default quality badge 2026-10-18 03:11:54 +07:00
zarzet 9b622f941c chore(settings): clarify beta features and playback information 2026-10-18 03:11:44 +07:00
zarzet 4cee16e9e8 feat(home): localize greetings and address profile names 2026-10-18 03:11:44 +07:00