Skip to content

Persist download metadata when a favorite is toggled - #210

Merged
phanan merged 1 commit into
masterfrom
fix/favorite-persist-download-metadata
Aug 6, 2026
Merged

Persist download metadata when a favorite is toggled#210
phanan merged 1 commit into
masterfrom
fix/favorite-persist-download-metadata

Conversation

@phanan

@phanan phanan commented Aug 6, 2026

Copy link
Copy Markdown
Member

Downloaded songs sometimes show the wrong favorite state, visible on the Now Playing sheet.

Cause

A downloaded song carries its own copy of the metadata on disk. DownloadProvider._collectDownloads() deserializes that copy at launch and feeds it through syncWithVault, so it becomes the vault's version of the song.

Two paths write liked:

  • InteractionProvider._like / _unlike — the Now Playing star. Calls persistMetadataIfNeeded.
  • FavoriteProvider.toggleOne / unlike — the action sheet, and the Favorites screen. Did not.

#199 added the persist to the first path only. So favoriting a downloaded song from the action sheet updated it in memory but left the on-disk copy stale; the next launch restored the old value, and the sheet showed the wrong star until some server fetch happened to cover that song. Offline — the case downloads exist for — nothing ever did.

Song.toJson does serialize liked, and DownloadSyncProvider does compare it, so the metadata format was never the problem; only one of its two writers was missing.

Fix

FavoriteProvider takes a DownloadProvider and persists after a successful like/unlike, mirroring InteractionProvider. Persisting after the request, not before, keeps a rolled-back optimistic update from being written.

Tests

Both paths assert the re-persist, and both failure paths assert it does not happen when the request fails and the toggle is rolled back.

Note

fix/downloaded-song-liked-status is a stale local branch covering earlier work on this bug; everything in it landed via #199 and it can be deleted.

Summary by CodeRabbit

  • Bug Fixes
    • Favoriting or unfavoriting a playable item now keeps its downloaded metadata synchronized.
    • Metadata is only saved after successful favorite actions, preventing updates when requests fail.
  • Tests
    • Added coverage for metadata persistence during successful like and unlike operations.
    • Added validation that failed requests do not alter downloaded metadata.

A downloaded song keeps its own copy of the metadata on disk, which
_collectDownloads() restores into the vault at launch. Two paths write
`liked` — InteractionProvider behind the Now Playing star, and FavoriteProvider
behind the action sheet — but #199 only taught the former to re-write that copy.

Favorite a downloaded song from the action sheet and the on-disk `liked` stayed
stale, so the next launch restored the old value and the Now Playing sheet
showed the wrong star until a server fetch happened to cover that song. Offline,
nothing ever did.
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 45276ca2-a23e-45ad-b094-f6a454c9fe09

📥 Commits

Reviewing files that changed from the base of the PR and between f6770cd and 65e348c.

📒 Files selected for processing (6)
  • lib/main.dart
  • lib/providers/favorite_provider.dart
  • test/providers/favorite_provider_test.dart
  • test/providers/favorite_provider_test.mocks.dart
  • test/ui/widgets/now_playing/favorite_button_test.dart
  • test/ui/widgets/now_playing/favorite_button_test.mocks.dart

📝 Walkthrough

Walkthrough

Changes

Favorite metadata synchronization

Layer / File(s) Summary
Favorite persistence flow
lib/providers/favorite_provider.dart, lib/main.dart
FavoriteProvider now requires DownloadProvider. Successful like and unlike requests persist playable metadata through persistMetadataIfNeeded. Application wiring passes the shared DownloadProvider.
FavoriteProvider validation
test/providers/favorite_provider_test.dart, test/providers/favorite_provider_test.mocks.dart
Tests verify metadata persistence after successful like and unlike requests. Failure tests verify that unsuccessful requests do not persist metadata.
Favorite button test wiring
test/ui/widgets/now_playing/favorite_button_test.dart, test/ui/widgets/now_playing/favorite_button_test.mocks.dart
Favorite button tests inject a mocked DownloadProvider through a shared FavoriteProvider factory.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • koel/player#130: Adds the download metadata persistence API used by this change.
  • koel/player#175: Adds related persistMetadataIfNeeded calls for favorite-state synchronization.
  • koel/player#199: Modifies FavoriteProvider like and unlike behavior and tests.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes persisting download metadata when a favorite changes, which is the main purpose of the pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/favorite-persist-download-metadata

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@phanan
phanan merged commit 5de4efc into master Aug 6, 2026
1 check passed
@phanan
phanan deleted the fix/favorite-persist-download-metadata branch August 6, 2026 20:14
@phanan phanan mentioned this pull request Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant