// // PodcastsView.swift // Mobile Music Assistant // // Created by Sven Hanold on 08.04.26. // import SwiftUI struct PodcastsView: View { @Environment(MAService.self) private var service @State private var errorMessage: String? @State private var showError = false private var podcasts: [MAPodcast] { service.libraryManager.podcasts } private var isLoading: Bool { service.libraryManager.isLoadingPodcasts } var body: some View { Group { if isLoading && podcasts.isEmpty { ProgressView() } else if podcasts.isEmpty { ContentUnavailableView( "No Podcasts", systemImage: "mic.fill", description: Text("Your library doesn't contain any podcasts yet.") ) } else { List { ForEach(podcasts) { podcast in NavigationLink(value: podcast) { PodcastRow(podcast: podcast) } } } .listStyle(.plain) } } .refreshable { await loadPodcasts() } .task { await loadPodcasts(refresh: !podcasts.isEmpty) } .alert("Error", isPresented: $showError) { Button("OK", role: .cancel) { } } message: { if let errorMessage { Text(errorMessage) } } } private func loadPodcasts(refresh: Bool = true) async { do { try await service.libraryManager.loadPodcasts(refresh: refresh) } catch { errorMessage = error.localizedDescription showError = true } } } // MARK: - Podcast Row struct PodcastRow: View { @Environment(MAService.self) private var service let podcast: MAPodcast var body: some View { HStack(spacing: 12) { CachedAsyncImage(url: service.imageProxyURL(path: podcast.imageUrl, provider: podcast.imageProvider, size: 128)) { image in image .resizable() .aspectRatio(contentMode: .fill) } placeholder: { RoundedRectangle(cornerRadius: 8) .fill(Color.gray.opacity(0.2)) .overlay { Image(systemName: "mic.fill") .font(.title2) .foregroundStyle(.secondary) } } .frame(width: 64, height: 64) .clipShape(RoundedRectangle(cornerRadius: 8)) .overlay(alignment: .bottomTrailing) { if service.libraryManager.isFavorite(uri: podcast.uri) { Image(systemName: "heart.fill") .font(.system(size: 10)) .foregroundStyle(.red) .padding(3) } } VStack(alignment: .leading, spacing: 4) { Text(podcast.name) .font(.headline) .lineLimit(2) if let publisher = podcast.publisher { Text(publisher) .font(.caption) .foregroundStyle(.secondary) .lineLimit(1) } if let total = podcast.totalEpisodes { Text("\(total) episodes") .font(.caption2) .foregroundStyle(.tertiary) } } Spacer() } .padding(.vertical, 4) } } #Preview { NavigationStack { PodcastsView() .environment(MAService()) } }