Files
Deepwave/app
christopherandClaude Sonnet 5 4c116eb84f Phase 6: Playlists, local-first with server sync
Adds user-created playlists synced to/from Navidrome, using the same
Room-plus-WorkManager outbox pattern Phase 5 established for downloads:
every read/write goes through Room first (fully offline-capable), and
mutations mark a PENDING_CREATE/UPDATE/DELETE syncState that
PlaylistSyncWorker later pushes to the server, then pulls the server's
current playlists back down to reconcile.

New Subsonic endpoints: getPlaylists, getPlaylist, createPlaylist,
updatePlaylist, deletePlaylist. Track-list updates are computed as an
add/remove diff against a freshly-fetched remote track list
(computePlaylistSyncDelta, unit tested in isolation since a wrong
index here deletes the wrong track server-side, not just a local
glitch) rather than replaying individual UI actions - simpler, and
self-correcting if a previous push partially failed. Conflict
handling is last-write-wins at the whole-playlist level: pushPending()
always runs before pullRemote(), so a playlist with local changes
queued keeps them as the source of truth for that sync pass.

UI: the bottom-nav Library tab now switches between Playlists and
Artists (Spotify's own convention), a playlist detail screen
(play/download-all/remove-track/delete), and an "add to playlist"
entry point wired into AlbumDetailScreen's track rows - a bottom sheet
listing existing playlists plus inline playlist creation.

Verified on-device against the real Navidrome server: creating a
playlist assigns a real server id and reaches SYNCED; adding and
removing a track push the expected updatePlaylist add/remove diff
(confirmed via the actual HTTP requests) and both directions
reconcile correctly; deleting a playlist issues a real
server-side deletePlaylist; creating a playlist entirely offline
stays queued (WorkManager correctly blocks the sync job on the
CONNECTIVITY constraint, confirmed via dumpsys jobscheduler) and
syncs automatically the moment connectivity returns, with no crash
and no user action needed.

Bumped DeepwaveDatabase to version 2 for the new playlist tables,
using the same fallbackToDestructiveMigration already in place since
Phase 5 - this drops and recreates the whole database, including
Phase 5's downloaded_tracks table, so previously-downloaded tracks'
files remain on disk but drop out of the app's tracking until
re-downloaded. Expected given the documented "schema isn't stable
yet" tradeoff, not a regression, but worth knowing before installing
this build over an existing one with real downloads.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-17 14:59:17 -04:00
..