Updated API calls and Library View
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
//
|
||||
// RadiosView.swift
|
||||
// Mobile Music Assistant
|
||||
//
|
||||
// Created by Sven Hanold on 26.03.26.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct RadiosView: View {
|
||||
@Environment(MAService.self) private var service
|
||||
|
||||
@State private var radios: [MAMediaItem] = []
|
||||
@State private var isLoading = true
|
||||
@State private var errorMessage: String?
|
||||
@State private var showError = false
|
||||
@State private var showPlayerPicker = false
|
||||
@State private var selectedRadio: MAMediaItem?
|
||||
|
||||
private var players: [MAPlayer] {
|
||||
Array(service.playerManager.players.values).sorted { $0.name < $1.name }
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
List(radios) { radio in
|
||||
RadioRow(radio: radio, service: service)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
selectedRadio = radio
|
||||
showPlayerPicker = true
|
||||
}
|
||||
.listRowSeparator(.visible)
|
||||
}
|
||||
.listStyle(.plain)
|
||||
.overlay {
|
||||
if isLoading {
|
||||
ProgressView()
|
||||
} else if radios.isEmpty && errorMessage == nil {
|
||||
ContentUnavailableView(
|
||||
"No Radio Stations",
|
||||
systemImage: "antenna.radiowaves.left.and.right",
|
||||
description: Text("No radio stations found in your library.")
|
||||
)
|
||||
}
|
||||
}
|
||||
.task {
|
||||
await loadRadios()
|
||||
}
|
||||
.refreshable {
|
||||
await loadRadios()
|
||||
}
|
||||
.alert("Error", isPresented: $showError) {
|
||||
Button("OK", role: .cancel) { }
|
||||
} message: {
|
||||
if let errorMessage { Text(errorMessage) }
|
||||
}
|
||||
.sheet(isPresented: $showPlayerPicker) {
|
||||
if let radio = selectedRadio {
|
||||
PlayerPickerView(players: players) { player in
|
||||
Task { await playRadio(radio, on: player) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func loadRadios() async {
|
||||
isLoading = true
|
||||
errorMessage = nil
|
||||
do {
|
||||
radios = try await service.getRadios()
|
||||
isLoading = false
|
||||
} catch {
|
||||
errorMessage = error.localizedDescription
|
||||
showError = true
|
||||
isLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
private func playRadio(_ radio: MAMediaItem, on player: MAPlayer) async {
|
||||
do {
|
||||
try await service.playerManager.playMedia(playerId: player.playerId, uri: radio.uri)
|
||||
} catch {
|
||||
errorMessage = error.localizedDescription
|
||||
showError = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Radio Row
|
||||
|
||||
private struct RadioRow: View {
|
||||
let radio: MAMediaItem
|
||||
let service: MAService
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 12) {
|
||||
if let imageUrl = radio.imageUrl {
|
||||
CachedAsyncImage(url: service.imageProxyURL(path: imageUrl, size: 128)) { image in
|
||||
image.resizable().aspectRatio(contentMode: .fill)
|
||||
} placeholder: {
|
||||
RoundedRectangle(cornerRadius: 8).fill(Color.gray.opacity(0.2))
|
||||
}
|
||||
.frame(width: 50, height: 50)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 8))
|
||||
} else {
|
||||
RoundedRectangle(cornerRadius: 8)
|
||||
.fill(Color.gray.opacity(0.2))
|
||||
.frame(width: 50, height: 50)
|
||||
.overlay {
|
||||
Image(systemName: "antenna.radiowaves.left.and.right")
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
|
||||
Text(radio.name)
|
||||
.font(.body)
|
||||
.lineLimit(2)
|
||||
|
||||
Spacer()
|
||||
|
||||
Image(systemName: "play.circle")
|
||||
.font(.title2)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
.padding(.vertical, 4)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
NavigationStack {
|
||||
RadiosView()
|
||||
.environment(MAService())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user