diff --git a/core/playlists.go b/core/playlists.go index 5fc1af3ad..4e13ba1f7 100644 --- a/core/playlists.go +++ b/core/playlists.go @@ -11,6 +11,7 @@ import ( "os" "path/filepath" "strings" + "time" "github.com/navidrome/navidrome/log" "github.com/navidrome/navidrome/model" @@ -156,6 +157,7 @@ func (s *playlists) updatePlaylist(ctx context.Context, newPls *model.Playlist) newPls.Comment = pls.Comment newPls.Owner = pls.Owner newPls.Public = pls.Public + newPls.EvaluatedAt = time.Time{} } else { log.Info(ctx, "Adding synced playlist", "playlist", newPls.Name, "path", newPls.Path, "owner", owner) newPls.Owner = owner diff --git a/core/playlists_test.go b/core/playlists_test.go index 9eb5c3388..ab5d76831 100644 --- a/core/playlists_test.go +++ b/core/playlists_test.go @@ -81,10 +81,10 @@ type mockedPlaylist struct { model.PlaylistRepository } -func (r *mockedPlaylist) FindByPath(path string) (*model.Playlist, error) { +func (r *mockedPlaylist) FindByPath(string) (*model.Playlist, error) { return nil, model.ErrNotFound } -func (r *mockedPlaylist) Put(pls *model.Playlist) error { +func (r *mockedPlaylist) Put(*model.Playlist) error { return nil } diff --git a/persistence/playlist_repository.go b/persistence/playlist_repository.go index 16608539b..8a16027ea 100644 --- a/persistence/playlist_repository.go +++ b/persistence/playlist_repository.go @@ -3,6 +3,7 @@ package persistence import ( "context" "encoding/json" + "strconv" "strings" "time" @@ -99,7 +100,11 @@ func (r *playlistRepository) Put(p *model.Playlist) error { } p.ID = id - // Only update tracks if they are specified + if p.IsSmartPlaylist() { + r.refreshSmartPlaylist(p) + return nil + } + // Only update tracks if they were specified if tracks == nil { return nil } @@ -300,18 +305,24 @@ func (r *playlistRepository) updateStats(playlistId string) error { } func (r *playlistRepository) loadTracks(pls *model.Playlist) error { - tracksQuery := Select().From("playlist_tracks"). + tracksQuery := Select().From("media_file f"). LeftJoin("annotation on ("+ - "annotation.item_id = media_file_id"+ + "annotation.item_id = f.id"+ " AND annotation.item_type = 'media_file'"+ " AND annotation.user_id = '"+userId(r.ctx)+"')"). Columns("starred", "starred_at", "play_count", "play_date", "rating", "f.*"). - Join("media_file f on f.id = media_file_id"). - Where(Eq{"playlist_id": pls.ID}).OrderBy("playlist_tracks.id") + Join("playlist_tracks t on t.media_file_id = f.id"). + Where(Eq{"playlist_id": pls.ID}).OrderBy("t.id") err := r.queryAll(tracksQuery, &pls.Tracks) if err != nil { log.Error(r.ctx, "Error loading playlist tracks", "playlist", pls.Name, "id", pls.ID, err) } + // Fix Track attributes + for i, t := range pls.Tracks { + pls.Tracks[i].ID = strconv.Itoa(i + 1) // (must be the position of the track in the list) + pls.Tracks[i].PlaylistID = pls.ID + pls.Tracks[i].MediaFileID = t.MediaFile.ID + } return err } diff --git a/persistence/playlist_repository_test.go b/persistence/playlist_repository_test.go index 832f34bdc..833aa0230 100644 --- a/persistence/playlist_repository_test.go +++ b/persistence/playlist_repository_test.go @@ -58,6 +58,15 @@ var _ = Describe("PlaylistRepository", func() { pls, err := repo.GetWithTracks(plsBest.ID) Expect(err).To(BeNil()) Expect(pls.Name).To(Equal(plsBest.Name)) + Expect(pls.Tracks).To(HaveLen(2)) + Expect(pls.Tracks[0].ID).To(Equal("1")) + Expect(pls.Tracks[0].PlaylistID).To(Equal(plsBest.ID)) + Expect(pls.Tracks[0].MediaFileID).To(Equal(songDayInALife.ID)) + Expect(pls.Tracks[0].MediaFile.ID).To(Equal(songDayInALife.ID)) + Expect(pls.Tracks[1].ID).To(Equal("2")) + Expect(pls.Tracks[1].PlaylistID).To(Equal(plsBest.ID)) + Expect(pls.Tracks[1].MediaFileID).To(Equal(songRadioactivity.ID)) + Expect(pls.Tracks[1].MediaFile.ID).To(Equal(songRadioactivity.ID)) mfs := pls.MediaFiles() Expect(mfs).To(HaveLen(2)) Expect(mfs[0].ID).To(Equal(songDayInALife.ID)) @@ -78,9 +87,9 @@ var _ = Describe("PlaylistRepository", func() { Expect(repo.Put(&newPls)).To(BeNil()) saved, _ := repo.GetWithTracks(newPls.ID) Expect(saved.Tracks).To(HaveLen(3)) - Expect(saved.Tracks[0].ID).To(Equal("1004")) - Expect(saved.Tracks[1].ID).To(Equal("1003")) - Expect(saved.Tracks[2].ID).To(Equal("1004")) + Expect(saved.Tracks[0].MediaFileID).To(Equal("1004")) + Expect(saved.Tracks[1].MediaFileID).To(Equal("1003")) + Expect(saved.Tracks[2].MediaFileID).To(Equal("1004")) By("returns the newly created playlist") Expect(repo.Exists(newPls.ID)).To(BeTrue()) diff --git a/persistence/playlist_track_repository.go b/persistence/playlist_track_repository.go index 220837880..96889c535 100644 --- a/persistence/playlist_track_repository.go +++ b/persistence/playlist_track_repository.go @@ -25,9 +25,12 @@ func (r *playlistRepository) Tracks(playlistId string) model.PlaylistTrackReposi p.sortMappings = map[string]string{ "id": "playlist_tracks.id", } - _, err := r.GetWithTracks(playlistId) + pls, err := r.Get(playlistId) if err != nil { - log.Error(r.ctx, "Failed to load tracks of smart playlist", "playlistId", playlistId, err) + return nil + } + if pls.IsSmartPlaylist() { + r.refreshSmartPlaylist(pls) } return p }