mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-04 04:57:37 +03:00
Keep the order of the playlist when adding new songs. Also allow adding a song more than once
This commit is contained in:
parent
e476a5f6f1
commit
4b1c76e307
2 changed files with 50 additions and 11 deletions
|
@ -121,20 +121,50 @@ func (r *playlistRepository) fromModel(p *model.Playlist) playlist {
|
|||
return pls
|
||||
}
|
||||
|
||||
// TODO: Introduce a relation table for Playlist <-> MediaFiles, and rewrite this method in pure SQL
|
||||
func (r *playlistRepository) loadTracks(p *model.Playlist) model.MediaFiles {
|
||||
if len(p.Tracks) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Collect all ids
|
||||
ids := make([]string, len(p.Tracks))
|
||||
for i, t := range p.Tracks {
|
||||
ids[i] = t.ID
|
||||
}
|
||||
|
||||
// Break the list in chunks, up to 50 items, to avoid hitting SQLITE_MAX_FUNCTION_ARG limit
|
||||
const chunkSize = 50
|
||||
var chunks [][]string
|
||||
for i := 0; i < len(ids); i += chunkSize {
|
||||
end := i + chunkSize
|
||||
if end > len(ids) {
|
||||
end = len(ids)
|
||||
}
|
||||
|
||||
chunks = append(chunks, ids[i:end])
|
||||
}
|
||||
|
||||
// Query each chunk of media_file ids and store results in a map
|
||||
mfRepo := NewMediaFileRepository(r.ctx, r.ormer)
|
||||
var ids []string
|
||||
for _, t := range p.Tracks {
|
||||
ids = append(ids, t.ID)
|
||||
trackMap := map[string]model.MediaFile{}
|
||||
for i := range chunks {
|
||||
idsFilter := Eq{"id": chunks[i]}
|
||||
tracks, err := mfRepo.GetAll(model.QueryOptions{Filters: idsFilter})
|
||||
if err != nil {
|
||||
log.Error(r.ctx, "Could not load playlist's tracks", "playlistName", p.Name, "playlistId", p.ID, err)
|
||||
}
|
||||
for _, t := range tracks {
|
||||
trackMap[t.ID] = t
|
||||
}
|
||||
}
|
||||
idsFilter := Eq{"id": ids}
|
||||
tracks, err := mfRepo.GetAll(model.QueryOptions{Filters: idsFilter})
|
||||
if err == nil {
|
||||
return tracks
|
||||
} else {
|
||||
log.Error(r.ctx, "Could not load playlist's tracks", "playlistName", p.Name, "playlistId", p.ID, err)
|
||||
|
||||
// Create a new list of tracks with the same order as the original
|
||||
newTracks := make(model.MediaFiles, len(p.Tracks))
|
||||
for i, t := range p.Tracks {
|
||||
newTracks[i] = trackMap[t.ID]
|
||||
}
|
||||
return nil
|
||||
return newTracks
|
||||
}
|
||||
|
||||
var _ model.PlaylistRepository = (*playlistRepository)(nil)
|
||||
|
|
|
@ -63,11 +63,20 @@ var _ = Describe("PlaylistRepository", func() {
|
|||
Describe("Put/Exists/Delete", func() {
|
||||
var newPls model.Playlist
|
||||
BeforeEach(func() {
|
||||
newPls = model.Playlist{ID: "22", Name: "Great!", Tracks: model.MediaFiles{{ID: "4"}}}
|
||||
newPls = model.Playlist{ID: "22", Name: "Great!", Tracks: model.MediaFiles{{ID: "4"}, {ID: "3"}}}
|
||||
})
|
||||
It("saves the playlist to the DB", func() {
|
||||
Expect(repo.Put(&newPls)).To(BeNil())
|
||||
})
|
||||
It("adds repeated songs to a playlist and keeps the order", func() {
|
||||
newPls.Tracks = append(newPls.Tracks, model.MediaFile{ID: "4"})
|
||||
Expect(repo.Put(&newPls)).To(BeNil())
|
||||
saved, _ := repo.Get("22")
|
||||
Expect(saved.Tracks).To(HaveLen(3))
|
||||
Expect(saved.Tracks[0].ID).To(Equal("4"))
|
||||
Expect(saved.Tracks[1].ID).To(Equal("3"))
|
||||
Expect(saved.Tracks[2].ID).To(Equal("4"))
|
||||
})
|
||||
It("returns the newly created playlist", func() {
|
||||
Expect(repo.Exists("22")).To(BeTrue())
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue