// ── Settings View ────────────────────────────────────────────── // Preferences, categories, sounds, about import SwiftUI struct SettingsView: View { @EnvironmentObject var store: TimerStore @EnvironmentObject var notificationManager: CMNotificationManager @AppStorage("cm_defaultUrgency") private var defaultUrgency = "standard" @AppStorage("cm_defaultCascade") private var defaultCascade = "standard" @AppStorage("cm_hapticEnabled") private var hapticEnabled = true @AppStorage("cm_soundEnabled") private var soundEnabled = true var body: some View { NavigationStack { ZStack { CMColors.bg.ignoresSafeArea() List { // Notifications Section { HStack { Label("Notifications", systemImage: "bell.fill") .foregroundStyle(CMColors.text) Spacer() if notificationManager.isAuthorized { Text("Enabled") .font(CMFonts.body(size: 13)) .foregroundStyle(CMColors.success) } else { Button("Enable") { Task { await notificationManager.requestPermission() } } .font(CMFonts.body(size: 13, weight: .semibold)) .foregroundStyle(CMColors.accent) } } Toggle(isOn: $hapticEnabled) { Label("Haptic Feedback", systemImage: "iphone.radiowaves.left.and.right") .foregroundStyle(CMColors.text) } .tint(CMColors.accent) Toggle(isOn: $soundEnabled) { Label("Sound", systemImage: "speaker.wave.2.fill") .foregroundStyle(CMColors.text) } .tint(CMColors.accent) } header: { Text("Notifications & Feedback") .foregroundStyle(CMColors.textMuted) } .listRowBackground(CMColors.surface) // Defaults Section { Picker(selection: $defaultUrgency) { ForEach(UrgencyLevel.allCases) { level in HStack { Circle() .fill(CMColors.urgencyColor(level)) .frame(width: 8, height: 8) Text(getUrgencyConfig(level).label) } .tag(level.rawValue) } } label: { Label("Default Urgency", systemImage: "exclamationmark.triangle.fill") .foregroundStyle(CMColors.text) } Picker(selection: $defaultCascade) { ForEach(CascadePreset.allCases.filter { $0 != .custom }) { preset in Text(preset.label).tag(preset.rawValue) } } label: { Label("Default Cascade", systemImage: "arrow.down.forward.and.arrow.up.backward") .foregroundStyle(CMColors.text) } } header: { Text("Defaults") .foregroundStyle(CMColors.textMuted) } .listRowBackground(CMColors.surface) // Data Section { HStack { Label("Total Timers", systemImage: "number") .foregroundStyle(CMColors.text) Spacer() Text("\(store.timers.count)") .font(CMFonts.mono(size: 14)) .foregroundStyle(CMColors.textSecondary) } Button { store.timers.removeAll { [.completed, .dismissed].contains($0.state) } } label: { Label("Clear History", systemImage: "trash") .foregroundStyle(CMColors.error) } Button { store.timers.removeAll() CMNotificationManager.shared.removeAllNotifications() } label: { Label("Delete All Timers", systemImage: "trash.fill") .foregroundStyle(CMColors.error) } } header: { Text("Data") .foregroundStyle(CMColors.textMuted) } .listRowBackground(CMColors.surface) // About Section { HStack { Label("Version", systemImage: "info.circle") .foregroundStyle(CMColors.text) Spacer() Text("1.0.0 (Phase 3)") .font(CMFonts.body(size: 13)) .foregroundStyle(CMColors.textMuted) } HStack { Label("Product ID", systemImage: "barcode") .foregroundStyle(CMColors.text) Spacer() Text("chronomind") .font(CMFonts.mono(size: 13)) .foregroundStyle(CMColors.textMuted) } Link(destination: URL(string: "https://chronomind.app/privacy")!) { Label("Privacy Policy", systemImage: "hand.raised.fill") .foregroundStyle(CMColors.text) } } header: { Text("About") .foregroundStyle(CMColors.textMuted) } .listRowBackground(CMColors.surface) } .scrollContentBackground(.hidden) .listStyle(.insetGrouped) } .navigationTitle("Settings") .navigationBarTitleDisplayMode(.inline) .toolbarBackground(CMColors.surface, for: .navigationBar) .toolbarColorScheme(.dark, for: .navigationBar) } } }