iOS 1.0.9: Add to Playlist sheet

Replaces the chain of dialogs (each waited ~450 ms for the last to close)
with one sheet: Plex | Stem tabs, inline new-playlist name field, playlist
rows with art, and mix chips for stem playlists. One "Add to Playlist…"
menu entry now covers both kinds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
cdnutterandClaude Opus 5.5 committed 2026-10-20 10:28:25 -07:00
1 parent 790f8a35a2
commit eb541b9a16
4 files changed
+218 -43

No files matched your search

+4 -41
View File
@@ -17,7 +17,6 @@ struct MediaMenu {
a.append(SheetAction("Remove Download", icon: "trash", destructive: true) { g.downloads.remove([t]) })
}
a.append(SheetAction("Add to Playlist…", icon: "text.badge.plus") { addToPlaylist([t]) })
a.append(SheetAction("Add to Stem Playlist…", icon: "slider.horizontal.3") { addToStemPlaylist([t]) })
if t.partFile != nil, g.stems.index.size > 0, g.stems.find(t) == nil { a.append(stemNow { [t] }) }
if allowGoTo, let k = t.albumKey {
a.append(SheetAction("Go to Album", icon: "square.stack") {
@@ -129,8 +128,7 @@ struct MediaMenu {
overlays.confirm("Remove Download?", "“\(title)” will no longer be available offline.", "Remove") { g.downloads.remove(downloaded) }
})
}
a.append(SheetAction("Add to Playlist…", icon: "text.badge.plus") { withTracks(load) { addToPlaylist($0, skip: playlistKey) } })
a.append(SheetAction("Add to Stem Playlist…", icon: "slider.horizontal.3") { withTracks(load) { addToStemPlaylist($0) } })
a.append(SheetAction("Add to Playlist…", icon: "text.badge.plus") { withTracks(load) { addToPlaylist($0, skip: playlistKey, title: title) } })
if !stemmed { a.append(stemNow(load)) }
return a + extra
}
@@ -173,32 +171,9 @@ struct MediaMenu {
}
}
func addToPlaylist(_ tracks: [Track], skip: String? = nil) {
Task {
let lists: [Playlist]
do { lists = try await g.plex.playlists().filter { !$0.smart && $0.ratingKey != skip } } catch {
overlays.hud("Couldn't load playlists", "exclamationmark.triangle")
return
}
let keys = tracks.map(\.ratingKey).filter { !$0.hasPrefix("stem:") }
if keys.isEmpty {
overlays.hud("These songs aren't in Plex, so they can't go in a playlist", "info.circle")
return
}
let plex = g.plex
overlays.actions("Add \(songs(keys.count)) to Playlist", [SheetAction("New Playlist…") { newPlaylist(tracks) }] + lists.map { pl in
SheetAction(pl.title) {
Task {
do {
try await plex.addToPlaylist(pl.ratingKey, trackKeys: keys)
overlays.hud("Added to \(pl.title)")
} catch {
overlays.hud("Couldn't add: \(error.localizedDescription)", "exclamationmark.triangle")
}
}
}
})
}
/// Plex or stem playlist, picked in one sheet.
func addToPlaylist(_ tracks: [Track], skip: String? = nil, title: String = "") {
overlays.addToPlaylist(tracks, title: title, skip: skip)
}
/// Picks the mix the songs get in a stem playlist: what's playing now, the song's saved mix, or a preset.
@@ -221,18 +196,6 @@ struct MediaMenu {
overlays.actions("Choose a Mix", acts)
}
func addToStemPlaylist(_ tracks: [Track]) {
let lists = g.stemPlaylists
overlays.actions("Add \(songs(tracks.count)) to Stem Playlist", [SheetAction("New Stem Playlist…") { newStemPlaylist(tracks) }] + lists.lists.map { pl in
SheetAction(pl.title) {
chooseMix(tracks) { m in
lists.add(pl.id, tracks: tracks, mix: m)
overlays.hud("Added to \(pl.title)")
}
}
})
}
func newStemPlaylist(_ tracks: [Track] = [], onCreated: @escaping (StemPlaylist) -> Void = { _ in }) {
let lists = g.stemPlaylists
overlays.prompt("New Stem Playlist", "Every song in it plays with the mix you pick.", "Create", placeholder: "Playlist name") { name in