Skip to content

Conversation

deluan
Copy link
Member

@deluan deluan commented May 28, 2025

Add Love and Rating functionality to playlist tracks

This PR implements rating and love/star functionality for tracks when viewed in playlists.

Changes Made

Backend:

  • Added GET /api/playlist/{id}/tracks/{id} endpoint for fetching individual playlist tracks
  • Fixed SQL queries in playlist_track_repository.go to properly qualify column names and return playlist track objects instead of media files
  • Added getPlaylistTrack handler function with proper middleware setup

Frontend:

  • Modified RatingField and useRating to use mediaFileId when available (for playlist tracks) instead of the playlist track ID
  • Updated useToggleLove with similar logic to target the underlying media file for star/unstar operations
  • Added rating column to playlist songs view and enabled love functionality in context menus
  • Both rating and love hooks now refresh both the playlist track and underlying song data to keep the UI in sync

Testing:

  • Added comprehensive test suites for useRating and useToggleLove covering playlist track scenarios
  • Tests verify correct ID targeting, dual refresh behavior, and backward compatibility

Technical Details

The core issue was that playlist tracks are references to media files, so rating/starring operations need to target the mediaFileId rather than the playlist track ID itself. The solution maintains backward compatibility by falling back to record.id when mediaFileId is not present.

When refreshing data after rating/starring playlist tracks, both the playlist view and the song library are updated to ensure consistency across the UI.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @deluan, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

Summary of Changes

Hello! Gemini or gemini-code-assist here, providing a summary of this pull request.

This PR implements the ability to rate and 'love' (star) tracks directly from the playlist view. The core challenge addressed is ensuring that these actions target the underlying media file associated with the playlist track, rather than the playlist track entry itself, while maintaining backward compatibility for resources without a mediaFileId. The changes involve updates to the backend API to fetch individual playlist tracks, modifications to frontend hooks (useRating, useToggleLove) to correctly identify the target ID and refresh relevant data, and UI updates to display ratings and enable the love functionality in the playlist view.

Highlights

  • Backend API: Adds a new GET /api/playlist/{id}/tracks/{id} endpoint to fetch a specific track within a playlist.
  • Database Queries: Corrects SQL queries in playlist_track_repository.go to properly qualify column names and return the PlaylistTrack object instead of the nested MediaFile.
  • Frontend Rating Logic: Updates the useRating hook and RatingField component to use the mediaFileId for rating actions when available, falling back to the record's own ID.
  • Frontend Love Logic: Updates the useToggleLove hook to use the mediaFileId for star/unstar actions when available, falling back to the record's own ID.
  • Data Refresh Strategy: Modifies the useRating and useToggleLove hooks to refresh both the playlist track and the underlying song data after a rating or love action on a playlist track, ensuring UI consistency.
  • Playlist UI: Adds a rating column to the playlist songs view and enables the love/star functionality in the context menu for playlist tracks.
  • Testing: Adds comprehensive test suites for the updated useRating and useToggleLove hooks, specifically covering playlist track scenarios and the dual refresh behavior.

Changelog

Click here to see the changelog
  • persistence/playlist_track_repository.go
    • Corrected the Read method's SQL query to qualify the id column with playlist_tracks.id (line 102).
    • Changed the return value of the Read method from trk.PlaylistTrack.MediaFile to trk.PlaylistTrack (line 105).
  • server/nativeapi/native_api.go
    • Added a new GET route / within the playlist track ID route (r.Route("/{id}")) to handle fetching individual playlist tracks (lines 147-149).
  • server/nativeapi/playlists.go
    • Implemented the getPlaylistTrack handler function, including middleware to extract the playlistId from the URL and construct the correct repository (lines 48-62).
  • ui/src/common/RatingField.jsx
    • Modified the handleRating callback to use record.mediaFileId as the target ID for the rate function, falling back to record.id (line 41).
    • Updated the name prop of the Rating component to also use record.mediaFileId or record.id (line 50).
    • Added record.mediaFileId and record.id to the dependency array of the handleRating useCallback hook (line 44).
  • ui/src/common/useRating.jsx
    • Updated the refreshRating function to check for record.mediaFileId (line 21).
    • If mediaFileId is present, it now fetches both the 'song' resource using mediaFileId and the 'playlistTrack' resource using record.id and playlistId filter (lines 23-29).
    • If mediaFileId is not present, it falls back to fetching only the original resource using record.id (lines 42-53).
    • Added record.mediaFileId, record.id, record.playlistId, and resource to the dependency array of the refreshRating useCallback hook (line 55).
  • ui/src/common/useRating.test.js
    • Added a new test file useRating.test.js to provide comprehensive test coverage for the useRating hook.
    • Includes tests for basic rating functionality, handling zero rating, and specific scenarios for playlist tracks (refreshing both resources, using playlist_id filter) and non-playlist resources.
    • Also includes tests simulating component integration scenarios for ID fallback.
  • ui/src/common/useToggleLove.jsx
    • Updated the refreshRecord function to fetch both the original resource (with playlistId filter if applicable) and the 'song' resource using mediaFileId if mediaFileId is present (lines 20-32).
    • Added record.mediaFileId, record.id, record.playlistId, and resource to the dependency array of the refreshRecord useCallback hook (line 39).
    • Modified the toggleLove function to use record.mediaFileId as the target ID for the star/unstar API calls, falling back to record.id (line 43).
  • ui/src/common/useToggleLove.test.js
    • Added a new test file useToggleLove.test.js to provide comprehensive test coverage for the useToggleLove hook.
    • Includes tests for using mediaFileId, falling back to id, calling unstar, and specific scenarios for playlist tracks (refreshing both resources, using playlist_id filter) and non-playlist resources.
  • ui/src/playlist/PlaylistSongs.jsx
    • Imported RatingField (line 29) and config (line 35).
    • Added a new CSS class ratingField and updated the hover styles to make it visible on hover (lines 79-81, 71-73).
    • Added a rating column definition using RatingField, conditionally rendered based on config.enableStarRating (lines 164-171).
    • Added classes.ratingField to the dependency array of the useMemo hook for column definitions (line 173).
    • Added rating to the default selected fields for the playlist track resource (line 185).
    • Enabled the love functionality in the SongContextMenu by setting showLove={true} (line 225).
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.


Playlist tunes flow,
Now rate and love each song,
Stars shine on the list.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively implements the Love and Rating functionality for playlist tracks by correctly targeting the underlying media files. The backend changes for the new endpoint and SQL query adjustments are clear, and the frontend hooks (useRating, useToggleLove) have been updated logically to support this, including the dual refresh mechanism for UI consistency.

The addition of comprehensive test suites for useRating and useToggleLove is a significant contribution and greatly enhances confidence in these changes. Well done on that!

I've identified a couple of high-severity issues related to error handling and loading state management in the React hooks, and one medium-severity suggestion for improving dependency arrays. Addressing these will further improve the robustness of the new functionality.

Summary of Findings

  • Error Handling in useRating Hook: The refreshRating function within useRating.jsx does not properly handle errors from its internal data fetching promises, potentially leaving the loading state as true indefinitely if a refresh fails after a rating action.
  • Error Handling in useToggleLove Hook: The refreshRecord function within useToggleLove.jsx lacks a .catch() block for its Promise.all call. This can lead to unhandled errors and the loading state not being reset if a refresh operation fails after a love/unlove action.
  • Dependency Array Specificity in useRating: The useCallback for refreshRating in useRating.jsx could use a more specific dependency array to avoid unnecessary recreations of the callback, potentially improving performance and maintainability.

Merge Readiness

The pull request introduces valuable functionality and is generally well-implemented, especially with the inclusion of thorough tests. However, there are a couple of high-severity issues related to error handling in the React hooks (useRating and useToggleLove) that could lead to inconsistent UI states (e.g., stuck loading indicators).

I recommend addressing these high-severity issues before merging to ensure the robustness of the new features. Once these are resolved, the PR should be in good shape. As an AI, I am not authorized to approve pull requests; please ensure further review and approval from authorized team members.

@deluan deluan requested a review from Copilot May 28, 2025 17:03
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Adds love/star and rating functionality to playlist tracks by targeting the underlying media file and keeping both playlist and song views in sync, plus a new backend endpoint for fetching individual playlist-track entries.

  • UI
    • Shows a rating column when enabled and toggles love in the playlist context menu
    • Hooks (useToggleLove, useRating) now use mediaFileId and refresh both playlist-track and song data
  • Backend
    • New GET /api/playlist/{id}/tracks/{id} endpoint with getPlaylistTrack handler
    • Fixed repository to qualify playlist_tracks.id and return the playlist-track entity instead of the media file

Reviewed Changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.

Show a summary per file
File Description
ui/src/playlist/PlaylistSongs.jsx Imported/enabled RatingField, updated styles & columns list
ui/src/common/useToggleLove.jsx Refactored refresh to handle mediaFileId, dual data refresh
ui/src/common/useRating.jsx Updated refreshRating to reload both song & playlist-track
server/nativeapi/playlists.go Added getPlaylistTrack middleware handler
persistence/playlist_track_repository.go Qualified playlist_tracks.id, return PlaylistTrack object
Comments suppressed due to low confidence (2)

server/nativeapi/playlists.go:48

  • New getPlaylistTrack endpoint is added without any tests. Add unit or integration tests to verify correct middleware wiring, parameter handling, and response payload.
func getPlaylistTrack(ds model.DataStore) http.HandlerFunc {

ui/src/playlist/PlaylistSongs.jsx:185

  • Including 'rating' in useSelectedFields for the 'playlistTrack' resource will cause an API error since playlistTrack objects do not have a 'rating' field. Consider removing 'rating' here or mapping the joined media file's rating into the playlistTrack DTO.
'rating',

@deluan deluan marked this pull request as draft May 29, 2025 19:53
deluan added 3 commits June 4, 2025 20:29
Signed-off-by: Deluan <deluan@navidrome.org>
Signed-off-by: Deluan <deluan@navidrome.org>
…ting components

Signed-off-by: Deluan <deluan@navidrome.org>
@deluan deluan force-pushed the ui-playlist-annotations branch from e3e1f31 to d1da67a Compare June 5, 2025 00:29
@deluan deluan marked this pull request as ready for review June 5, 2025 00:32
@deluan deluan merged commit 4172d23 into master Jun 5, 2025
35 checks passed
@deluan deluan deleted the ui-playlist-annotations branch June 5, 2025 00:38
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