Skip to content

Commit

Permalink
Add placeholder view when queue is empty within queue view
Browse files Browse the repository at this point in the history
Signed-off-by: Claudio Cambra <[email protected]>
  • Loading branch information
claucambra committed Jun 15, 2024
1 parent b16c82d commit 0766344
Showing 1 changed file with 76 additions and 68 deletions.
144 changes: 76 additions & 68 deletions Harmony/Player/PlayerQueueView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,86 +17,94 @@ struct PlayerQueueView: View {
private let currentSongSectionId = "current-song-section"

var body: some View {
ScrollViewReader { proxy in
List(selection: $selection) {
#if os(macOS) // TODO: iPadOS?
if !queue.pastSongs.isEmpty {
Section {
ForEach(queue.pastSongs) { song in
PlayerQueueListItemView(song: song, isCurrentSong: false)
.listRowBackground(rowBackground)
}
.onDelete(perform: { indexSet in queue.removePastSongs(indexSet) })
} header: {
HStack {
Text("Previously played")
Spacer()
Button {
queue.clearPastSongs()
} label: {
Label("Clear played songs", systemImage: "trash.fill")
if queue.results?.isEmpty ?? true {
Label("Queue is empty", systemImage: "music.note.list")
.font(.title)
.foregroundColor(.secondary)
.padding()
} else {
ScrollViewReader { proxy in
List(selection: $selection) {
#if os(macOS) // TODO: iPadOS?
if !queue.pastSongs.isEmpty {
Section {
ForEach(queue.pastSongs) { song in
PlayerQueueListItemView(song: song, isCurrentSong: false)
.listRowBackground(rowBackground)
}
.onDelete(perform: { indexSet in queue.removePastSongs(indexSet) })
} header: {
HStack {
Text("Previously played")
Spacer()
Button {
queue.clearPastSongs()
} label: {
Label("Clear played songs", systemImage: "trash.fill")
}
.buttonStyle(.borderless)
.labelStyle(.iconOnly)
}
.buttonStyle(.borderless)
.labelStyle(.iconOnly)
}
}
}
#endif
if let currentSong = queue.currentSong {
Section("Currently playing") {
PlayerQueueListItemView(song: currentSong, isCurrentSong: true)
.listRowBackground(rowBackground)
}
.id(currentSongSectionId)
}
if !queue.playNextSongs.isEmpty {
Section("Playing next") {
ForEach(queue.playNextSongs) { song in
PlayerQueueListItemView(song: song, isCurrentSong: false)
#endif
if let currentSong = queue.currentSong {
Section("Currently playing") {
PlayerQueueListItemView(song: currentSong, isCurrentSong: true)
.listRowBackground(rowBackground)
}
.onDelete(perform: { indexSet in queue.removePlayNextSongs(indexSet) })
.id(currentSongSectionId)
}
}
if !queue.futureSongs.isEmpty {
Section {
ForEach(queue.futureSongs) { song in
PlayerQueueListItemView(song: song, isCurrentSong: false)
.listRowBackground(rowBackground)
.onAppear {
queue.loadNextPageIfNeeded(song: song)
}
if !queue.playNextSongs.isEmpty {
Section("Playing next") {
ForEach(queue.playNextSongs) { song in
PlayerQueueListItemView(song: song, isCurrentSong: false)
.listRowBackground(rowBackground)
}
.onDelete(perform: { indexSet in queue.removePlayNextSongs(indexSet) })
}
.onDelete(perform: { indexSet in queue.removeFutureSongs(indexSet) })
} header: {
HStack {
Text("Upcoming songs")
Spacer()
Button {
queue.clearSongsAfterCurrent()
} label: {
Label("Clear upcoming songs", systemImage: "trash.fill")
}
if !queue.futureSongs.isEmpty {
Section {
ForEach(queue.futureSongs) { song in
PlayerQueueListItemView(song: song, isCurrentSong: false)
.listRowBackground(rowBackground)
.onAppear {
queue.loadNextPageIfNeeded(song: song)
}
}
.onDelete(perform: { indexSet in queue.removeFutureSongs(indexSet) })
} header: {
HStack {
Text("Upcoming songs")
Spacer()
Button {
queue.clearSongsAfterCurrent()
} label: {
Label("Clear upcoming songs", systemImage: "trash.fill")
}
.buttonStyle(.borderless)
.labelStyle(.iconOnly)
}
.buttonStyle(.borderless)
.labelStyle(.iconOnly)
}
}
}
}
.contextMenu { _ in
// TODO: Add a context menu
} primaryAction: {
$0.forEach {
// HACK: This is a workaround for the fact that we can't get the section for a
// given item, so we need to call the generic method to check each subqueue
// rather than calling the playSongFromXXX for the specific subqueue. Slow!
playerController.playSongFromQueues(instanceId: $0)
.contextMenu { _ in
// TODO: Add a context menu
} primaryAction: {
$0.forEach {
// HACK: This is a workaround for the fact that we can't get the section for
// a given item, so we need to call the generic method to check each
// subqueue rather than calling the playSongFromXXX for the specific
// subqueue. Slow!
playerController.playSongFromQueues(instanceId: $0)
}
}
.onChange(of: queue.currentSong) {
#if os(macOS) // TODO: iPadOS?
proxy.scrollTo(currentSongSectionId, anchor: .top)
#endif
}
}
.onChange(of: queue.currentSong) {
#if os(macOS) // TODO: iPadOS?
proxy.scrollTo(currentSongSectionId, anchor: .top)
#endif
}
}
}
Expand Down

0 comments on commit 0766344

Please sign in to comment.