PlaylistUploadButton.swift 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import SwiftUI
  2. /// Upload button for playlist headers — visible only when playlist has local tracks and Chad Music is configured.
  3. /// Shows uploaded/total count (e.g., "↑ 2/9").
  4. struct PlaylistUploadButton: View {
  5. let playlist: Playlist
  6. @State private var uploadService = UploadService.shared
  7. private var localTracks: [Track] {
  8. playlist.sortedEntries.compactMap(\.track).filter { !$0.isCloud && !$0.filePath.isEmpty }
  9. }
  10. private var uploadedCount: Int {
  11. localTracks.filter { $0.uploadState == .uploaded }.count
  12. }
  13. private var uploadingCount: Int {
  14. localTracks.filter { $0.uploadState == .uploading }.count
  15. }
  16. var body: some View {
  17. let local = localTracks
  18. if !local.isEmpty && ChadMusicAPIClient.shared.isConfigured {
  19. Button {
  20. handleTap(local)
  21. } label: {
  22. Label(buttonLabel(local), systemImage: "arrow.up.circle")
  23. }
  24. .help(helpText(local))
  25. }
  26. }
  27. private func buttonLabel(_ local: [Track]) -> String {
  28. "↑ \(uploadedCount)/\(local.count)"
  29. }
  30. private func helpText(_ local: [Track]) -> String {
  31. let total = local.count
  32. if uploadedCount == total {
  33. return "All local tracks uploaded to cloud"
  34. }
  35. if uploadingCount > 0 {
  36. return "Uploading... tap to cancel"
  37. }
  38. return "Upload \(total - uploadedCount) local tracks to cloud"
  39. }
  40. private func handleTap(_ local: [Track]) {
  41. if uploadingCount > 0 {
  42. uploadService.cancel()
  43. } else if uploadedCount < local.count {
  44. let eligible = local.filter { $0.uploadState != .uploaded }
  45. uploadService.uploadBatch(tracks: eligible, apiClient: ChadMusicAPIClient.shared)
  46. }
  47. }
  48. }