Skip to content

Conversation

@zacaj
Copy link
Contributor

@zacaj zacaj commented Nov 7, 2025

Description

Adds a rated_at column to the annotation table to record when a song was rated.

Adds a display of the rating date/time to the <RatingField> component via title tooltip just to make it a bit more useful. Since I was in there I also added a similar tooltip to the Star/Loved component for consistency- lmk if you'd prefer one/both of these removed or in their own PR

Some thoughts/questions while coding this:

  1. along with/instead of the tooltip to display the date, would it make more sense to add it to the Get Info popup? I noticed that the Starred At is also not displayed here (and neither is the actual rating or Started/Loved field), but it might make sense?
  2. although opensubsonic doesn't have a 'rated at' field (yet), is it acceptable for opensubsonic implementations to provide extra fields in the responses like this, or would that be frowned upon? if it's acceptable I can add it to the subsonic api code too
  3. docs- should I add this new field to the Smart Playlists page in the docs repo? whats the process for that- should I make the PR there in parallel, or wait for this one to be merged?

Related Issues

Fixes #4653

Type of Change

  • Bug fix
  • New feature
  • Documentation update
  • Refactor
  • Other (please describe):

Checklist

Please review and check all that apply:

  • My code follows the project’s coding style
  • I have tested the changes locally
  • I have added or updated documentation as needed
    • see note 3 above
  • I have added tests that prove my fix/feature works (or explain why not)
    • didn't see any tests for similar functionality (eg, starred_at), so assuming this falls below the 'worth testing' threshold
  • All existing and new tests pass

How to Test

  1. Start navidrome- migration should run to add column
  2. In navidrome web ui or a client, edit the rating of a song
  3. Observe in DB and web ui tooltip that date/time is now saved for that song

Screenshots / Demos (if applicable)

image

Additional Notes

I coded this in a dev container; not sure how much those are used/tested but I had two issues which may be problems with the dev container or may just be something with my computer:

  1. Even after running make setup, I couldn't compile the taglib wrapper .cpp file due to it not finding the header files. Adding -I /usr/include/taglib to the #cgo linux line fixed this.
  2. configuration_test.go (and thus, the pre-push hook) failed because the ND_MUSICFOLDER env var in the devcontainer.json file was overriding the musicFolder field being tested by the config files. In the end I worked around this by disabling the env var functionality completely but this is probably a bug with the test not using isolated environment vars? or would be good to at least change the test to use a lesser-used config setting instead of one that is used universally
  3. The dev container settings specify prettier as the default formatter for javascript, but not for .jsx files, so by default it wasn't formatting most of my changes at all until I manually ran npm run prettier (also, the instructions from make lintall don't mention that you need to run it inside the ui/ folder).

Signed-off-by: zacaj <zacaj@zacaj.com>
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @zacaj, 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!

This pull request introduces the ability to track and display the exact time a user rates a song. It involves a database migration to add a new timestamp column, updates to the data model and persistence layer to store this information, and front-end changes to visualize these timestamps as tooltips in the user interface, enhancing the user's ability to see when they last interacted with a song's rating or 'loved' status.

Highlights

  • Database Schema Update: A new rated_at column has been added to the annotation table to store the timestamp when a song was rated.
  • Backend Logic Enhancement: The backend now records the current timestamp in the rated_at field whenever a song's rating is updated.
  • UI Tooltip Display: The UI has been updated to display the rated_at timestamp as a tooltip on the <RatingField> component. For consistency, a similar tooltip showing starredAt has been added to the LoveButton component.
  • Smart Playlist Integration: The new rated_at field is now available for use in smart playlist criteria under the name daterated.
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 by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

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 pull request 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 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. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

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.

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.

ALTER TABLE annotation ADD COLUMN rated_at datetime;
-- +goose StatementEnd

-- +goose Down
Copy link
Contributor Author

Choose a reason for hiding this comment

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

note- didn't add any Down to remove the column since it shouldn't cause any issues if it's still there while code is downgraded and didn't want to risk losing data if a db somehow got migrated down and then back up again

@@ -0,0 +1,7 @@
-- +goose Up
-- +goose StatementBegin
ALTER TABLE annotation ADD COLUMN rated_at datetime;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Column is nullable for backwards compatibility- if you prefer to default to the current timestamp during migration in order to keep the column non-nullable lmk.

<span
onClick={(e) => stopPropagation(e)}
title={
record.ratedAt ? new Date(record.ratedAt).toLocaleString() : undefined
Copy link
Contributor Author

Choose a reason for hiding this comment

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

should this have any of the logic in DateField.jsx regarding ignoring '0001-01-01T00:00:00Z' or passing in a locale/etc to toLocaleString() ?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, it should ignore empty dates (0001-01-01T00:00:00Z). We don't need to pass a locate unless you add tests for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added check for empty dates to each component

is there any like, util file that'd be a good place to maybe pull out the date check (and/or formatting) logic for easier consistency?

Copy link
Member

Choose a reason for hiding this comment

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

We do have a ui/src/utils folder for this type of utility functions

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ah, I was looking for a file called utils, not a folder, doh.

Would you like me to move all three cases of the empty date check here, probably in validations.js, as part of this PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added

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 introduces a rated_at field to track when songs are rated, with changes across the database, backend, and UI. The implementation is mostly solid, but I have a few suggestions. My main feedback concerns the database migration, which is missing its Down implementation for rollbacks. I also suggest refining the logic for when rated_at is set to improve data semantics and the user experience of the new tooltips. A similar point is raised for the starred_at tooltip for consistency.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @zacaj, 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!

This pull request introduces a new feature that tracks and displays the exact time a song was rated. It adds a rated_at timestamp to the database and backend model, making this information available for querying and display. The user interface has been enhanced with tooltips on both the rating and "loved" buttons, providing users with immediate visual feedback on when they last interacted with a song's rating or "loved" status. This improves the overall user experience by offering more detailed historical context for their music interactions.

Highlights

  • New rated_at field: A rated_at column has been added to the annotation database table to store the timestamp when a song was rated.
  • Go model update: The Annotations struct in the Go backend now includes a RatedAt field to represent this new timestamp.
  • Smart Playlist integration: The new rated_at field is now queryable via the daterated criteria for Smart Playlists.
  • Automatic timestamping: The rated_at field is automatically populated with the current time whenever a song's rating is updated.
  • UI Tooltips: A tooltip displaying the rated_at timestamp has been added to the <RatingField> component in the UI.
  • Consistency for 'Loved': For consistency, a similar tooltip showing starredAt has been added to the <LoveButton> component.
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 by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

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 pull request 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 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. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

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.

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 introduces a rated_at timestamp to track when a song's rating is set. The changes are well-integrated across the database, backend, and frontend, including a new tooltip to display this information. For consistency, a similar tooltip has been added for the 'starred' timestamp. The overall implementation is solid, but I have one important suggestion regarding the database migration to ensure it can be safely rolled back.

Copy link
Member

@deluan deluan left a comment

Choose a reason for hiding this comment

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

LGTM, but check my comment below. I know the annotations feature does not have any tests atm, so it is fine to not have added them. Unless you feel compelled to write some tests for it :)

<span
onClick={(e) => stopPropagation(e)}
title={
record.ratedAt ? new Date(record.ratedAt).toLocaleString() : undefined
Copy link
Member

Choose a reason for hiding this comment

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

Yes, it should ignore empty dates (0001-01-01T00:00:00Z). We don't need to pass a locate unless you add tests for it.

zacaj and others added 4 commits November 10, 2025 16:58
Signed-off-by: zacaj <zacaj@zacaj.com>
Added comprehensive tests for isDateSet and urlValidate functions in
ui/src/utils/validations.test.js covering falsy values, Go zero date handling,
valid date strings, Date objects, and edge cases.

Added rated_at sort mapping to album, artist, and mediafile repositories,
following the same pattern as starred_at (sorting by rating first, then by
timestamp). This enables proper sorting by rating date in the UI.
@deluan deluan merged commit 3294bca into navidrome:master Nov 25, 2025
16 checks passed
@deluan
Copy link
Member

deluan commented Nov 25, 2025

Thanks! Can you also create a PR for the documentation website for the new Smart Playlist field? Thanks!

@zacaj
Copy link
Contributor Author

zacaj commented Nov 25, 2025

Thanks! Can you also create a PR for the documentation website for the new Smart Playlist field? Thanks!

navidrome/website#241

@zacaj zacaj deleted the rating-date/4653 branch November 25, 2025 15:50
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.

2 participants