PlaylistDownloadButton.swift 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. import SwiftUI
  2. /// Download button for playlist headers — visible only when playlist has cloud tracks.
  3. /// Shows downloaded/total count (e.g., "↓ 2/4").
  4. struct PlaylistDownloadButton: View {
  5. let playlist: Playlist
  6. @State private var downloadManager = DownloadManager.shared
  7. private var cloudTracks: [Track] {
  8. playlist.sortedEntries.compactMap(\.track).filter(\.isCloud)
  9. }
  10. private var downloadedCount: Int {
  11. cloudTracks.filter { $0.downloadState == .downloaded }.count
  12. }
  13. private var downloadingCount: Int {
  14. cloudTracks.filter { $0.downloadState == .downloading }.count
  15. }
  16. var body: some View {
  17. let cloud = cloudTracks
  18. if !cloud.isEmpty {
  19. Button {
  20. handleTap(cloud)
  21. } label: {
  22. Label(buttonLabel(cloud), systemImage: "arrow.down.circle")
  23. }
  24. .help(helpText(cloud))
  25. }
  26. }
  27. private func buttonLabel(_ cloud: [Track]) -> String {
  28. let total = cloud.count
  29. if downloadedCount == total {
  30. return "↓ \(total)/\(total)"
  31. }
  32. return "↓ \(downloadedCount)/\(total)"
  33. }
  34. private func helpText(_ cloud: [Track]) -> String {
  35. let total = cloud.count
  36. if downloadedCount == total {
  37. return "All cloud tracks downloaded"
  38. }
  39. if downloadingCount > 0 {
  40. return "Downloading... tap to cancel"
  41. }
  42. return "Download \(total - downloadedCount) cloud tracks for offline playback"
  43. }
  44. private func handleTap(_ cloud: [Track]) {
  45. if downloadingCount > 0 {
  46. downloadManager.cancelBatch(tracks: cloud)
  47. } else if downloadedCount < cloud.count {
  48. downloadManager.downloadBatch(tracks: cloud, apiClient: ChadMusicAPIClient.shared)
  49. }
  50. }
  51. }