import SwiftUI struct PreferencesView: View { private enum Tab: CaseIterable { case monitor, notifications, alerts var title: String { switch self { case .monitor: return "Monitor" case .notifications: return "Notifications" case .alerts: return "Alerts" } } var icon: String { switch self { case .monitor: return "waveform.path.ecg" case .notifications: return "bell.badge" case .alerts: return "exclamationmark.triangle" } } } @AppStorage("pingInterval") private var storedPingInterval: Int = 10 @AppStorage("refreshInterval") private var storedRefreshInterval: Int = 60 @AppStorage("showIntervalIndicator") private var showIntervalIndicator: Bool = true @State private var pingIntervalSlider: Double = 10 @State private var refreshIntervalSlider: Double = 60 @State private var selection: Tab = .monitor private let minimumInterval: Double = 10 private let maximumPingInterval: Double = 600 private let maximumRefreshInterval: Double = 600 var body: some View { HStack(spacing: 0) { sidebar Divider() ScrollView { detailContent(for: selection) .frame(maxWidth: .infinity, alignment: .leading) .padding() } .frame(minWidth: 360, maxWidth: .infinity, maxHeight: .infinity) } .frame(minWidth: 560, minHeight: 360) .onAppear { pingIntervalSlider = Double(storedPingInterval) refreshIntervalSlider = Double(storedRefreshInterval) } .onChange(of: pingIntervalSlider) { _, newValue in storedPingInterval = Int(newValue) } .onChange(of: refreshIntervalSlider) { _, newValue in storedRefreshInterval = Int(newValue) } } private var sidebar: some View { VStack(alignment: .leading, spacing: 12) { Text("Preferences") .font(.headline) .padding(.bottom, 8) ForEach(Tab.allCases, id: \.self) { tab in Button { selection = tab } label: { HStack(spacing: 10) { Image(systemName: tab.icon) .frame(width: 20) Text(tab.title) Spacer() } .padding(.vertical, 8) .padding(.horizontal, 6) .background( RoundedRectangle(cornerRadius: 10, style: .continuous) .fill(selection == tab ? Color.accentColor.opacity(0.25) : Color.clear) ) } .buttonStyle(.plain) } Spacer() } .padding() .frame(width: 180, alignment: .top) } @ViewBuilder private func detailContent(for tab: Tab) -> some View { VStack(alignment: .leading, spacing: 12) { Text(tab.title) .font(.title2) .padding(.bottom, 12) switch tab { case .monitor: MonitorPreferencesView( pingIntervalSlider: $pingIntervalSlider, refreshIntervalSlider: $refreshIntervalSlider, showIntervalIndicator: $showIntervalIndicator, minimumInterval: minimumInterval, maximumPingInterval: maximumPingInterval, maximumRefreshInterval: maximumRefreshInterval, pingChanged: handlePingSliderEditing(_:), refreshChanged: handleRefreshSliderEditing(_:) ) case .notifications: NotificationsPreferencesView() case .alerts: AlertsPreferencesView() } } } private func handlePingSliderEditing(_ editing: Bool) { if !editing { storedPingInterval = Int(pingIntervalSlider) } } private func handleRefreshSliderEditing(_ editing: Bool) { if !editing { storedRefreshInterval = Int(refreshIntervalSlider) } } } private struct MonitorPreferencesView: View { @Binding var pingIntervalSlider: Double @Binding var refreshIntervalSlider: Double @Binding var showIntervalIndicator: Bool let minimumInterval: Double let maximumPingInterval: Double let maximumRefreshInterval: Double let pingChanged: (Bool) -> Void let refreshChanged: (Bool) -> Void var body: some View { VStack(alignment: .leading, spacing: 18) { Group { Text("Ping interval") .font(.headline) Slider( value: $pingIntervalSlider, in: minimumInterval...maximumPingInterval, step: 5 ) { Text("Ping interval") } minimumValueLabel: { Text("\(Int(minimumInterval))s") .font(.caption) .foregroundColor(.secondary) } maximumValueLabel: { Text("\(Int(maximumPingInterval))s") .font(.caption) .foregroundColor(.secondary) } onEditingChanged: { editing in pingChanged(editing) } Text("Current: \(Int(pingIntervalSlider)) seconds") .font(.caption) .foregroundColor(.secondary) } Group { Text("Refresh interval") .font(.headline) Slider( value: $refreshIntervalSlider, in: minimumInterval...maximumRefreshInterval, step: 5 ) { Text("Refresh interval") } minimumValueLabel: { Text("\(Int(minimumInterval))s") .font(.caption) .foregroundColor(.secondary) } maximumValueLabel: { Text("\(Int(maximumRefreshInterval))s") .font(.caption) .foregroundColor(.secondary) } onEditingChanged: { editing in refreshChanged(editing) } Text("Current: \(Int(refreshIntervalSlider)) seconds") .font(.caption) .foregroundColor(.secondary) } Divider() Toggle("Show interval indicator", isOn: $showIntervalIndicator) .toggleStyle(.switch) Spacer() } .frame(maxWidth: .infinity, alignment: .leading) } } private struct NotificationsPreferencesView: View { var body: some View { VStack(alignment: .leading, spacing: 12) { Text("Notifications") .font(.headline) .padding(.bottom) Text("Configure notification behavior here.") .foregroundColor(.secondary) Spacer() } .frame(maxWidth: .infinity, alignment: .leading) .padding() } } private struct AlertsPreferencesView: View { var body: some View { VStack(alignment: .leading, spacing: 12) { Text("Alerts") .font(.headline) .padding(.bottom) Text("Configure alert thresholds and behavior.") .foregroundColor(.secondary) Spacer() } .frame(maxWidth: .infinity, alignment: .leading) .padding() } } #Preview { PreferencesView() }