AlbumDownloadButton.swift 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import SwiftUI
  2. /// Download button for album headers — shows aggregate download state across all tracks.
  3. /// States: "Download All" / "3 of 12" / "Downloaded" / "5 remaining"
  4. struct AlbumDownloadButton: View {
  5. let tracks: [Track]
  6. let apiClient: ChadMusicAPIClient
  7. @State private var downloadManager = DownloadManager.shared
  8. private var cloudTracks: [Track] {
  9. tracks.filter { $0.isCloud }
  10. }
  11. private var downloadedCount: Int {
  12. cloudTracks.filter { $0.downloadState == .downloaded }.count
  13. }
  14. private var downloadingCount: Int {
  15. cloudTracks.filter { $0.downloadState == .downloading }.count
  16. }
  17. var body: some View {
  18. if !cloudTracks.isEmpty {
  19. Button {
  20. handleTap()
  21. } label: {
  22. Label(buttonLabel, systemImage: buttonIcon)
  23. .font(.caption)
  24. }
  25. .buttonStyle(.plain)
  26. .foregroundStyle(.secondary)
  27. .fixedSize()
  28. }
  29. }
  30. private var buttonLabel: String {
  31. let total = cloudTracks.count
  32. if downloadedCount == total {
  33. return "Downloaded"
  34. }
  35. if downloadingCount > 0 {
  36. return "\(downloadedCount + downloadingCount) of \(total)"
  37. }
  38. if downloadedCount > 0 {
  39. return "\(total - downloadedCount) remaining"
  40. }
  41. return "Download All"
  42. }
  43. private var buttonIcon: String {
  44. if downloadedCount == cloudTracks.count {
  45. return "checkmark.circle.fill"
  46. }
  47. if downloadingCount > 0 {
  48. return "arrow.down.circle"
  49. }
  50. return "arrow.down.circle"
  51. }
  52. private func handleTap() {
  53. let total = cloudTracks.count
  54. if downloadedCount == total {
  55. return // All downloaded
  56. }
  57. if downloadingCount > 0 {
  58. // Cancel all active
  59. downloadManager.cancelBatch(tracks: cloudTracks)
  60. } else {
  61. // Download remaining
  62. downloadManager.downloadBatch(tracks: cloudTracks, apiClient: apiClient)
  63. }
  64. }
  65. }