blastoise/ios/BlastoisePing/BlastoisePing/ContentView.swift

127 lines
3.8 KiB
Swift

import SwiftUI
struct ContentView: View {
@StateObject private var model = AppModel()
@State private var username = ""
@State private var password = ""
@State private var selectedTab: MainTab = .rooms
var body: some View {
NavigationStack {
ZStack {
Theme.background.ignoresSafeArea()
if model.authState == .signedIn {
mainApp
} else {
AuthView(
model: model,
username: $username,
password: $password
)
}
}
.navigationTitle("Blastoise")
.toolbarColorScheme(.dark, for: .navigationBar)
.toolbarBackground(Theme.background, for: .navigationBar)
.toolbarBackground(.visible, for: .navigationBar)
.font(Theme.bodyFont)
.buttonBorderShape(.roundedRectangle(radius: Theme.corner))
}
.onChange(of: model.authState) { _, authState in
if authState == .signedIn {
password = ""
}
}
}
private var mainApp: some View {
ScrollView {
VStack(spacing: 14) {
HeaderView(model: model)
PlayerDeckView(model: model)
tabStrip
selectedPanel
DebugFooterView(model: model)
}
.padding(.horizontal, 14)
.padding(.bottom, 18)
}
}
private var tabStrip: some View {
HStack(spacing: 8) {
ForEach(MainTab.allCases) { tab in
Button {
selectedTab = tab
if tab == .library {
Task { await model.loadLibraryIfNeeded() }
} else if tab == .playlists {
Task { await model.loadPlaylistsIfNeeded() }
}
} label: {
Label(tab.title, systemImage: tab.icon)
.labelStyle(.iconOnly)
.frame(width: 44, height: 40)
.background(selectedTab == tab ? Theme.accent : Theme.panel2)
.foregroundStyle(selectedTab == tab ? Theme.background : Theme.text)
.clipShape(RoundedRectangle(cornerRadius: Theme.corner))
}
.accessibilityLabel(tab.title)
}
}
.frame(maxWidth: .infinity, alignment: .leading)
}
@ViewBuilder
private var selectedPanel: some View {
switch selectedTab {
case .rooms:
RoomsPanel(model: model)
case .queue:
QueuePanel(model: model)
case .people:
PeoplePanel(model: model)
case .library:
LibraryPanel(model: model)
case .playlists:
PlaylistsPanel(model: model)
case .debug:
DebugPanel(model: model)
}
}
}
private enum MainTab: String, CaseIterable, Identifiable {
case rooms
case queue
case people
case library
case playlists
case debug
var id: String { rawValue }
var title: String {
switch self {
case .rooms: return "Rooms"
case .queue: return "Queue"
case .people: return "People"
case .library: return "Library"
case .playlists: return "Lists"
case .debug: return "Debug"
}
}
var icon: String {
switch self {
case .rooms: return "radio"
case .queue: return "list.bullet"
case .people: return "person.2"
case .library: return "music.note.list"
case .playlists: return "rectangle.stack"
case .debug: return "waveform.path.ecg"
}
}
}