iOS: stem playlist refresh and covers, download queue page, reorderable Library, whole-library radio
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7c8dfb54ca
commit
a4c870251c
18 files changed
+514
-30
No files matched your search
@@ -15,10 +15,12 @@ struct StemPlaylist: Codable, Hashable, Identifiable {
|
||||
var items: [StemPlaylistItem] = []
|
||||
var created = Date()
|
||||
var updated = Date()
|
||||
/// Cover picked by the user; nil follows the first song.
|
||||
var artThumb: String?
|
||||
|
||||
var tracks: [Track] { items.map(\.track) }
|
||||
var mixes: [[String: StemSetting]] { items.map(\.mix) }
|
||||
var thumb: String? { items.lazy.compactMap(\.track.thumb).first }
|
||||
var thumb: String? { artThumb ?? items.lazy.compactMap(\.track.thumb).first }
|
||||
var durationMs: Int64 { items.reduce(0) { $0 + $1.track.durationMs } }
|
||||
}
|
||||
|
||||
@@ -51,6 +53,32 @@ final class StemPlaylists {
|
||||
edit(id) { $0.items += tracks.map { StemPlaylistItem(track: $0, mix: MixPresets.normalized(mix)) } }
|
||||
}
|
||||
|
||||
func setArt(_ id: String, _ thumb: String?) { edit(id) { $0.artThumb = thumb } }
|
||||
|
||||
/// Re-reads every song from the library so renamed, retagged or re-added songs match again.
|
||||
/// Keeps each item's uid and mix, and leaves songs the library can't find as they are.
|
||||
/// Returns true when anything changed.
|
||||
@discardableResult
|
||||
func refresh(albumTracks: (String) async throws -> [Track]) async -> Bool {
|
||||
var fresh: [String: [Track]] = [:]
|
||||
for key in Set(lists.flatMap { $0.items.compactMap(\.track.albumKey) }) {
|
||||
if let t = try? await albumTracks(key) { fresh[key] = t }
|
||||
}
|
||||
var changed = false
|
||||
for li in lists.indices {
|
||||
for ii in lists[li].items.indices {
|
||||
let old = lists[li].items[ii].track
|
||||
guard let key = old.albumKey, let pool = fresh[key] else { continue }
|
||||
guard var new = pool.first(where: { $0.ratingKey == old.ratingKey })
|
||||
?? pool.first(where: { $0.title == old.title && $0.artist == old.artist }) else { continue }
|
||||
if new.stemKey == nil { new.stemKey = old.stemKey }
|
||||
if new != old { lists[li].items[ii].track = new; changed = true }
|
||||
}
|
||||
}
|
||||
if changed { save() }
|
||||
return changed
|
||||
}
|
||||
|
||||
func setItems(_ id: String, _ items: [StemPlaylistItem]) { edit(id) { $0.items = items } }
|
||||
func remove(_ id: String, item: String) { edit(id) { $0.items.removeAll { $0.uid == item } } }
|
||||
func setMix(_ id: String, item: String, _ mix: [String: StemSetting]) {
|
||||
|
||||
Reference in new issue
Block a user