Album-artist grouping for cloud libraries + trust user-installed CAs#16
Merged
Conversation
Self-hosted Navidrome/Subsonic/Jellyfin servers commonly use a private or self-signed CA. Release builds previously trusted only system CAs, so a root certificate the user imported via Android Settings was ignored and the connection was refused. Add <certificates src="user"/> to the release network security config so the app honors user-installed CAs. This is a declarative, user-controlled trust decision (the user must deliberately install the cert), not a validation bypass, and keeps F-Droid compliance intact. Fixes #7
"Group by Album Artist" was effectively ignored for Subsonic/Navidrome and Jellyfin libraries, and never decluttered the Artists tab for any source. Two problems: - Cloud sync hardcoded albumArtist = null, so the album-artist tag the Subsonic (albumArtist) and Jellyfin (AlbumArtist) APIs return was dropped and the setting could not work for cloud albums. - The preference only relabeled album entities; the Artists tab always listed every track-level artist, so featured/compilation artists cluttered it even for local libraries. Changes: - Capture the album-artist tag end to end for Navidrome and Jellyfin (API parser -> DTO -> cache entity -> unified song). - Add songs.album_artist_id, the id of the effective album artist (album_artist when present, else the primary track artist), populated at sync for local and both cloud sources. Album-artist-only names (e.g. "Various Artists") get a real artist row and are preserved by deleteOrphanedArtists. - When the toggle is on, the Artists tab and artist detail collapse onto album_artist_id. The column is preference-independent, so toggling switches queries at runtime with no re-sync. Default (toggle off) behavior is unchanged. - MIGRATION_1_2 (v1 -> v2) adds the columns with defensive PRAGMA guards and backfills album_artist_id from the existing primary artist. Closes #8
The lifecycle 2.11.0 lint rule LifecycleCurrentStateInComposition flags reading Lifecycle.currentState during composition: it is not snapshot-backed, so topIndex could read stale state and fail to recompose when an entry's lifecycle state changed on its own. Read each visible entry's started-state via the snapshot-aware currentStateAsState() instead, keyed on entry id so each per-entry observer stays bound across recompositions. The started-state filter is kept (not redundant): visibleEntries is filtered by maxLifecycle, so a mid-transition incoming entry can appear while its real state is still CREATED. Dim-overlay behavior is unchanged.
core-ktx 1.19.0 changes timing so beginPreparingSong's IO coroutine (albumArtUriString.toUri()) is awaited within the shuffle unit tests. Uri.parse returns null on the JVM stub, throwing NPE and regressing the six ShuffleFunctionalityTests. Stub android.net.Uri.parse in stubShuffledPlayback so the queue-prep path completes; assertions unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements two issues.
#7 — Allow self-signed certificates (Closes #7)
Release builds trusted only system CAs, so a root certificate the user imported via Android Settings was ignored and self-hosted Navidrome/Subsonic/Jellyfin servers with a private CA were refused.
<certificates src="user"/>to the releasenetwork_security_config.xml(debug already had it).#8 — "Sort artists by Album Artist" ignored for Subsonic/Navidrome (Closes #8)
Two problems: cloud sync hardcoded
albumArtist = null(so the SubsonicalbumArtist/ JellyfinAlbumArtisttag was dropped), and the toggle only relabeled albums — the Artists tab always listed every track-level artist, so featured/compilation artists cluttered it for every source.songs.album_artist_id— id of the effective album artist (album_artistwhen present, else the primary track artist), populated at sync for local + both cloud sources. Album-artist-only names (e.g. "Various Artists") get a real artist row and are preserved bydeleteOrphanedArtists.album_artist_id. The column is preference-independent, so toggling switches queries at runtime with no re-sync. Default (toggle off) behavior is byte-for-byte unchanged.MIGRATION_1_2(v1 → v2) adds the three columns with defensivePRAGMA table_infoguards and backfillsalbum_artist_idfrom the existing primary artist so the collapsed tab is non-empty before the next sync. Verified the migration DDL matches the exported2.jsonschema exactly.Testing
All three pre-PR checks pass (JDK 21):
:app:compileDebugKotlin✅:app:lintDebug✅:app:testDebugUnitTest✅Not done: live on-device DB upgrade test (no connected device); the schema-identity check against the exported v2 schema is the proxy.