velody/apps/apple/VelodyiPhone/Sources/iPhoneLibraryView.swift

88 lines
3.1 KiB
Swift

import SwiftUI
struct iPhoneLibraryView: View {
@State private var viewModel = iPhoneLibraryViewModel()
var body: some View {
NavigationStack {
List {
Section("Remote tracks: \(viewModel.remoteTracks.count)") {
ForEach(viewModel.remoteTracks) { track in
VStack(alignment: .leading, spacing: 6) {
Text(track.title)
.font(.headline)
Text(track.artist)
.foregroundStyle(.secondary)
Text("Duration: \(track.durationText)")
.font(.subheadline)
.foregroundStyle(.secondary)
Text("Remote track ID: \(track.remoteTrackID)")
.font(.caption)
.foregroundStyle(.tertiary)
.textSelection(.enabled)
}
.padding(.vertical, 4)
}
}
}
.overlay {
overlayView
}
.navigationTitle("Velody")
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button("Sync Remote Library") {
Task {
await viewModel.refreshSync()
}
}
.disabled(viewModel.state == .loading)
}
}
.safeAreaInset(edge: .bottom) {
Text(viewModel.syncStatus)
.font(.footnote)
.foregroundStyle(.secondary)
.padding()
.frame(maxWidth: .infinity, alignment: .leading)
.background(.ultraThinMaterial)
}
}
.task {
await viewModel.loadIfNeeded()
}
}
@ViewBuilder
private var overlayView: some View {
switch viewModel.state {
case .idle:
if viewModel.remoteTracks.isEmpty {
ContentUnavailableView(
"No Remote Library Yet",
systemImage: "music.note.list",
description: Text("Tap Sync Remote Library to fetch metadata from the backend.")
)
}
case .loading:
ProgressView("Syncing remote library...")
case .success:
EmptyView()
case .empty:
ContentUnavailableView(
"Empty Remote Library",
systemImage: "music.note.list",
description: Text("The backend returned no remote tracks for this iPhone.")
)
case .networkError(let message):
if viewModel.remoteTracks.isEmpty {
ContentUnavailableView(
"Network Error",
systemImage: "wifi.exclamationmark",
description: Text(message)
)
}
}
}
}