From 076634432c01a16a88128b18def08327e933b334 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Sat, 15 Jun 2024 18:24:43 +0800 Subject: [PATCH] Add placeholder view when queue is empty within queue view Signed-off-by: Claudio Cambra --- Harmony/Player/PlayerQueueView.swift | 144 ++++++++++++++------------- 1 file changed, 76 insertions(+), 68 deletions(-) diff --git a/Harmony/Player/PlayerQueueView.swift b/Harmony/Player/PlayerQueueView.swift index f42e1fa..7d87e29 100644 --- a/Harmony/Player/PlayerQueueView.swift +++ b/Harmony/Player/PlayerQueueView.swift @@ -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 } } }