177 lines
5.1 KiB
Swift
177 lines
5.1 KiB
Swift
// ── Watch Content View ────────────────────────────────────────
|
|
// Main navigation for watchOS — timeline + quick timer
|
|
|
|
import SwiftUI
|
|
|
|
struct WatchContentView: View {
|
|
@EnvironmentObject var store: WatchTimerStore
|
|
|
|
var body: some View {
|
|
NavigationStack {
|
|
if store.timers.isEmpty {
|
|
emptyState
|
|
} else {
|
|
timerList
|
|
}
|
|
}
|
|
.onAppear {
|
|
store.loadFromSharedData()
|
|
}
|
|
}
|
|
|
|
// MARK: - Timer List
|
|
|
|
private var timerList: some View {
|
|
List {
|
|
// Next up section
|
|
if let next = store.nextFiringTimer {
|
|
Section {
|
|
NavigationLink {
|
|
WatchTimerDetailView(timer: next)
|
|
} label: {
|
|
WatchNextUpCard(timer: next, now: store.now)
|
|
}
|
|
.listRowBackground(urgencyColor(next.urgency).opacity(0.15))
|
|
} header: {
|
|
Text("NEXT UP")
|
|
.font(.system(size: 10, weight: .semibold))
|
|
}
|
|
}
|
|
|
|
// Quick timer
|
|
Section {
|
|
NavigationLink {
|
|
WatchQuickTimerView()
|
|
} label: {
|
|
Label("Quick Timer", systemImage: "plus.circle.fill")
|
|
.foregroundStyle(.blue)
|
|
}
|
|
}
|
|
|
|
// All active timers
|
|
if store.activeTimers.count > 1 {
|
|
Section {
|
|
ForEach(store.activeTimers.filter { $0.id != store.nextFiringTimer?.id }) { timer in
|
|
NavigationLink {
|
|
WatchTimerDetailView(timer: timer)
|
|
} label: {
|
|
WatchTimerRow(timer: timer, now: store.now)
|
|
}
|
|
}
|
|
} header: {
|
|
Text("UPCOMING")
|
|
.font(.system(size: 10, weight: .semibold))
|
|
}
|
|
}
|
|
}
|
|
.navigationTitle("ChronoMind")
|
|
}
|
|
|
|
// MARK: - Empty State
|
|
|
|
private var emptyState: some View {
|
|
VStack(spacing: 12) {
|
|
Image(systemName: "clock")
|
|
.font(.system(size: 36))
|
|
.foregroundStyle(.secondary)
|
|
|
|
Text("No Timers")
|
|
.font(.system(size: 16, weight: .semibold))
|
|
|
|
NavigationLink {
|
|
WatchQuickTimerView()
|
|
} label: {
|
|
Label("Create Timer", systemImage: "plus")
|
|
}
|
|
.buttonStyle(.borderedProminent)
|
|
.tint(.blue)
|
|
}
|
|
.navigationTitle("ChronoMind")
|
|
}
|
|
|
|
private func urgencyColor(_ urgency: UrgencyLevel) -> Color {
|
|
switch urgency {
|
|
case .critical: return .red
|
|
case .important: return .orange
|
|
case .standard: return .yellow
|
|
case .gentle: return .green
|
|
case .passive: return .blue
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Next Up Card
|
|
|
|
struct WatchNextUpCard: View {
|
|
let timer: TimerSnapshot
|
|
let now: Date
|
|
|
|
var body: some View {
|
|
VStack(alignment: .leading, spacing: 4) {
|
|
Text(timer.label)
|
|
.font(.system(size: 14, weight: .semibold))
|
|
.lineLimit(1)
|
|
|
|
Text(timer.targetTime, style: .timer)
|
|
.font(.system(size: 24, weight: .bold, design: .monospaced))
|
|
.foregroundStyle(urgencyColor(timer.urgency))
|
|
|
|
Text(formatTime(timer.targetTime))
|
|
.font(.system(size: 11))
|
|
.foregroundStyle(.secondary)
|
|
}
|
|
.padding(.vertical, 4)
|
|
}
|
|
|
|
private func urgencyColor(_ urgency: UrgencyLevel) -> Color {
|
|
switch urgency {
|
|
case .critical: return .red
|
|
case .important: return .orange
|
|
case .standard: return .yellow
|
|
case .gentle: return .green
|
|
case .passive: return .blue
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Timer Row
|
|
|
|
struct WatchTimerRow: View {
|
|
let timer: TimerSnapshot
|
|
let now: Date
|
|
|
|
var body: some View {
|
|
HStack {
|
|
Circle()
|
|
.fill(urgencyColor(timer.urgency))
|
|
.frame(width: 6, height: 6)
|
|
|
|
VStack(alignment: .leading, spacing: 2) {
|
|
Text(timer.label)
|
|
.font(.system(size: 13, weight: .medium))
|
|
.lineLimit(1)
|
|
Text(formatTime(timer.targetTime))
|
|
.font(.system(size: 11))
|
|
.foregroundStyle(.secondary)
|
|
}
|
|
|
|
Spacer()
|
|
|
|
Text(timer.targetTime, style: .timer)
|
|
.font(.system(size: 13, weight: .semibold, design: .monospaced))
|
|
.foregroundStyle(urgencyColor(timer.urgency))
|
|
.multilineTextAlignment(.trailing)
|
|
}
|
|
}
|
|
|
|
private func urgencyColor(_ urgency: UrgencyLevel) -> Color {
|
|
switch urgency {
|
|
case .critical: return .red
|
|
case .important: return .orange
|
|
case .standard: return .yellow
|
|
case .gentle: return .green
|
|
case .passive: return .blue
|
|
}
|
|
}
|
|
}
|