iOS: section reorder and visibility, CarPlay downloads fix, stem playlist refresh fix

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
rootandClaude Sonnet 5.5 committed 2026-10-28 16:30:30 -07:00
1 parent 3e832e3125
commit 5b7fadb7f7
6 files changed
+122 -31

No files matched your search

+29 -3
View File
@@ -77,6 +77,8 @@ final class CarLibrary: @unchecked Sendable {
guard let (kind, key) = CarIds.split(id) else { return nil }
switch kind {
case "dl": return try await downloadsView(key)
case "dlalbum": return await songs(id, try tracksOf(id), shuffleRow: false, showArtist: false)
case "dlartist": return await songs(id, try tracksOf(id), shuffleRow: true, showArtist: false)
case "playlist", "stemplaylist": return await songs(id, try tracksOf(id), shuffleRow: true, showArtist: true)
case "album": return await songs(id, try tracksOf(id), shuffleRow: false, showArtist: false)
case "artist": return try await artistPage(key, away)
@@ -102,14 +104,36 @@ final class CarLibrary: @unchecked Sendable {
private func downloadsView(_ key: String) async throws -> [CarItem]? {
switch key {
case "playlists": return try await playlists(true, onlyDownloaded: true)
case "albums": return try await albumsFor(true).map { albumItem($0) }
case "artists": return try await artistsFor(true).map { artistItem($0) }
case "playlists": return await downloadedPlaylists()
case "albums":
return albumsOf(downloadedTracks()).sorted { $0.title.lowercased() < $1.title.lowercased() }.map { a in
CarItem(id: "dlalbum:\(a.ratingKey)", title: a.title, subtitle: a.artist, art: artOr(a.thumb, a.title), playable: false)
}
case "artists":
return (try await artistsFor(true)).map { a in
CarItem(id: "dlartist:\(a.ratingKey)", title: a.title, art: artOr(a.thumb, a.sortTitle), playable: false)
}
case "songs": return await songs(CarIds.downloads, try tracksOf(CarIds.downloads), shuffleRow: true, showArtist: true)
default: return nil
}
}
/// Local only: stem playlists with a downloaded song, plus Plex playlists if the server answers.
private func downloadedPlaylists() async -> [CarItem] {
let have = Set(downloadedTracks().map(\.ratingKey))
let stem = await MainActor.run { AppGraph.shared.stemPlaylists.lists.filter { l in l.tracks.contains { have.contains($0.ratingKey) } } }
var out = stem.map { l in
CarItem(id: "stemplaylist:\(l.id)", title: l.title, subtitle: CarTree.countLabel(l.items.count, "song", "songs"),
art: artOr(l.thumb, l.title), playable: false, group: "Stem Playlists")
}
if let all = try? await plex.playlists() {
for p in all where ((try? await plex.playlistTracks(p.ratingKey))?.contains { have.contains($0.ratingKey) } == true) {
out.append(playlistItem(p, group: "Plex Playlists"))
}
}
return out
}
private func playlists(_ away: Bool, onlyDownloaded: Bool = false) async throws -> [CarItem] {
let all = try await plex.playlists()
var shown: [Playlist] = []
@@ -204,6 +228,8 @@ final class CarLibrary: @unchecked Sendable {
case "playlist": all = try await plex.playlistTracks(key)
case "stemplaylist": all = await MainActor.run { AppGraph.shared.stemPlaylists.list(key)?.tracks ?? [] }
case "album": all = try await plex.albumTracks(key)
case "dlalbum": all = downloadedTracks().filter { $0.albumKey == key }
case "dlartist": all = downloadedTracks().filter { $0.artistKey == key }
case "artist": all = away ? downloadedTracks().filter { $0.artistKey == key } : try await plex.artistTracks(key)
case "search": all = try await searchTracks(key, away)
default: all = []