Keep the order of the playlist when adding new songs. Also allow adding a song more than once
This commit is contained in:
@@ -121,20 +121,50 @@ func (r *playlistRepository) fromModel(p *model.Playlist) playlist {
|
|||||||
return pls
|
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 {
|
func (r *playlistRepository) loadTracks(p *model.Playlist) model.MediaFiles {
|
||||||
mfRepo := NewMediaFileRepository(r.ctx, r.ormer)
|
if len(p.Tracks) == 0 {
|
||||||
var ids []string
|
return nil
|
||||||
for _, t := range p.Tracks {
|
|
||||||
ids = append(ids, t.ID)
|
|
||||||
}
|
}
|
||||||
idsFilter := Eq{"id": ids}
|
|
||||||
|
// 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)
|
||||||
|
trackMap := map[string]model.MediaFile{}
|
||||||
|
for i := range chunks {
|
||||||
|
idsFilter := Eq{"id": chunks[i]}
|
||||||
tracks, err := mfRepo.GetAll(model.QueryOptions{Filters: idsFilter})
|
tracks, err := mfRepo.GetAll(model.QueryOptions{Filters: idsFilter})
|
||||||
if err == nil {
|
if err != nil {
|
||||||
return tracks
|
|
||||||
} else {
|
|
||||||
log.Error(r.ctx, "Could not load playlist's tracks", "playlistName", p.Name, "playlistId", p.ID, err)
|
log.Error(r.ctx, "Could not load playlist's tracks", "playlistName", p.Name, "playlistId", p.ID, err)
|
||||||
}
|
}
|
||||||
return nil
|
for _, t := range tracks {
|
||||||
|
trackMap[t.ID] = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 newTracks
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ model.PlaylistRepository = (*playlistRepository)(nil)
|
var _ model.PlaylistRepository = (*playlistRepository)(nil)
|
||||||
|
|||||||
@@ -63,11 +63,20 @@ var _ = Describe("PlaylistRepository", func() {
|
|||||||
Describe("Put/Exists/Delete", func() {
|
Describe("Put/Exists/Delete", func() {
|
||||||
var newPls model.Playlist
|
var newPls model.Playlist
|
||||||
BeforeEach(func() {
|
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() {
|
It("saves the playlist to the DB", func() {
|
||||||
Expect(repo.Put(&newPls)).To(BeNil())
|
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() {
|
It("returns the newly created playlist", func() {
|
||||||
Expect(repo.Exists("22")).To(BeTrue())
|
Expect(repo.Exists("22")).To(BeTrue())
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user