diff --git a/TheNoiseClock/Views/Clock/ClockSettingsView.swift b/TheNoiseClock/Views/Clock/ClockSettingsView.swift index e89cb38..1b7a566 100644 --- a/TheNoiseClock/Views/Clock/ClockSettingsView.swift +++ b/TheNoiseClock/Views/Clock/ClockSettingsView.swift @@ -16,6 +16,7 @@ struct ClockSettingsView: View { @State private var digitColor: Color = .white @State private var backgroundColor: Color = .black + @State private var showAdvancedSettings = false // MARK: - Init init(style: ClockStyle, onCommit: @escaping (ClockStyle) -> Void) { @@ -27,17 +28,38 @@ struct ClockSettingsView: View { var body: some View { NavigationView { Form { - TimeFormatSection(style: $style) - FontSection(style: $style) - AppearanceSection( + // BASIC SETTINGS - Most commonly used + BasicAppearanceSection( style: $style, digitColor: $digitColor, backgroundColor: $backgroundColor, onCommit: onCommit ) - NightModeSection(style: $style) - DisplaySection(style: $style) - OverlaySection(style: $style) + + BasicDisplaySection(style: $style) + + // ADVANCED SETTINGS - Toggle to show/hide + if showAdvancedSettings { + AdvancedAppearanceSection( + style: $style, + digitColor: $digitColor, + backgroundColor: $backgroundColor, + onCommit: onCommit + ) + + FontSection(style: $style) + + NightModeSection(style: $style) + + OverlaySection(style: $style) + + AdvancedDisplaySection(style: $style) + } + + // TOGGLE FOR ADVANCED SETTINGS + Section { + Toggle("Show Advanced Settings", isOn: $showAdvancedSettings) + } } .navigationTitle("Clock Settings") .navigationBarTitleDisplayMode(.inline) @@ -53,6 +75,156 @@ struct ClockSettingsView: View { } // MARK: - Supporting Views + +// MARK: - Basic Settings Sections +private struct BasicAppearanceSection: View { + @Binding var style: ClockStyle + @Binding var digitColor: Color + @Binding var backgroundColor: Color + let onCommit: (ClockStyle) -> Void + + var body: some View { + Section(header: Text("Colors"), footer: Text("Choose your favorite color theme or create a custom look.")) { + // Color Theme Picker + Picker("Color Theme", selection: $style.selectedColorTheme) { + ForEach(ClockStyle.availableColorThemes(), id: \.0) { theme in + HStack { + Circle() + .fill(themeColor(for: theme.0)) + .frame(width: 20, height: 20) + Text(theme.1) + } + .tag(theme.0) + } + } + .pickerStyle(.menu) + .onChange(of: style.selectedColorTheme) { _, newTheme in + if newTheme != "Custom" { + style.applyColorTheme(newTheme) + digitColor = Color(hex: style.digitColorHex) ?? .white + backgroundColor = Color(hex: style.backgroundHex) ?? .black + } + } + + // Custom color pickers (only show if Custom is selected) + if style.selectedColorTheme == "Custom" { + ColorPicker("Digit Color", selection: $digitColor, supportsOpacity: false) + ColorPicker("Background Color", selection: $backgroundColor, supportsOpacity: true) + } + } + .onChange(of: backgroundColor) { _, newValue in + style.backgroundHex = newValue.toHex() ?? AppConstants.Defaults.backgroundColorHex + style.selectedColorTheme = "Custom" + style.clearColorCache() + } + .onChange(of: digitColor) { _, newValue in + style.digitColorHex = newValue.toHex() ?? AppConstants.Defaults.digitColorHex + style.selectedColorTheme = "Custom" + style.clearColorCache() + } + } + + /// Get the color for a theme + private func themeColor(for theme: String) -> Color { + switch theme { + case "Custom": + return .gray + case "Red": + return .red + case "Orange": + return .orange + case "Yellow": + return .yellow + case "Green": + return .green + case "Blue": + return .blue + case "Purple": + return .purple + case "Pink": + return .pink + case "White": + return .white + default: + return .gray + } + } +} + +private struct BasicDisplaySection: View { + @Binding var style: ClockStyle + + var body: some View { + Section(header: Text("Display"), footer: Text("Basic display settings for your clock.")) { + Toggle("24‑Hour Format", isOn: $style.use24Hour) + Toggle("Show Seconds", isOn: $style.showSeconds) + Toggle("Auto Brightness", isOn: $style.autoBrightness) + } + } +} + +// MARK: - Advanced Settings Sections +private struct AdvancedAppearanceSection: View { + @Binding var style: ClockStyle + @Binding var digitColor: Color + @Binding var backgroundColor: Color + let onCommit: (ClockStyle) -> Void + + var body: some View { + Section(header: Text("Advanced Appearance"), footer: Text("Fine-tune the visual appearance of your clock.")) { + Toggle("Randomize Color (every minute)", isOn: $style.randomizeColor) + + Toggle("Stretched (auto-fit)", isOn: $style.stretched) + + if !style.stretched { + HStack { + Text("Size") + Slider(value: $style.digitScale, in: 0.0...1.0) + Text("\(Int((min(max(style.digitScale, 0.0), 1.0)) * 100))%") + .frame(width: 50, alignment: .trailing) + } + } + + HStack { + Text("Glow") + Slider(value: $style.glowIntensity, in: 0...1) + Text("\(Int(style.glowIntensity * 100))%") + .frame(width: 50, alignment: .trailing) + } + + HStack { + Text("Clock Opacity") + Slider(value: $style.clockOpacity, in: 0.0...1.0) + Text("\(Int(style.clockOpacity * 100))%") + .frame(width: 50, alignment: .trailing) + } + } + } +} + +private struct AdvancedDisplaySection: View { + @Binding var style: ClockStyle + + var body: some View { + Section(header: Text("Advanced Display"), footer: Text("Advanced display and system integration settings.")) { + Toggle("Keep Awake in Display Mode", isOn: $style.keepAwake) + + if style.autoBrightness { + HStack { + Text("Current Brightness") + Spacer() + Text("\(Int(style.effectiveBrightness * 100))%") + .foregroundColor(.secondary) + } + } + } + + Section(header: Text("Focus Modes"), footer: Text("Control how the app behaves when Focus modes (Do Not Disturb) are active.")) { + Toggle("Respect Focus Modes", isOn: $style.respectFocusModes) + } + } +} + private struct FontSection: View { @Binding var style: ClockStyle @@ -104,113 +276,6 @@ private struct FontSection: View { } } -private struct TimeFormatSection: View { - @Binding var style: ClockStyle - - var body: some View { - Section(header: Text("Time")) { - Toggle("24‑Hour", isOn: $style.use24Hour) - Toggle("Show Seconds", isOn: $style.showSeconds) - } - } -} - -private struct AppearanceSection: View { - @Binding var style: ClockStyle - @Binding var digitColor: Color - @Binding var backgroundColor: Color - let onCommit: (ClockStyle) -> Void - - var body: some View { - Section(header: Text("Appearance")) { - // Color Theme Picker - Picker("Color Theme", selection: $style.selectedColorTheme) { - ForEach(ClockStyle.availableColorThemes(), id: \.0) { theme in - HStack { - Circle() - .fill(themeColor(for: theme.0)) - .frame(width: 20, height: 20) - Text(theme.1) - } - .tag(theme.0) - } - } - .pickerStyle(.menu) - .onChange(of: style.selectedColorTheme) { _, newTheme in - if newTheme != "Custom" { - style.applyColorTheme(newTheme) - digitColor = Color(hex: style.digitColorHex) ?? .white - backgroundColor = Color(hex: style.backgroundHex) ?? .black - } - } - - ColorPicker("Background Color", selection: $backgroundColor, supportsOpacity: true) - ColorPicker("Digit Color", selection: $digitColor, supportsOpacity: false) - Toggle("Randomize Color (every minute)", isOn: $style.randomizeColor) - - Toggle("Stretched (auto-fit)", isOn: $style.stretched) - - if !style.stretched { - HStack { - Text("Size") - Slider(value: $style.digitScale, in: 0.0...1.0) - Text("\(Int((min(max(style.digitScale, 0.0), 1.0)) * 100))%") - .frame(width: 50, alignment: .trailing) - } - } - - HStack { - Text("Glow") - Slider(value: $style.glowIntensity, in: 0...1) - Text("\(Int(style.glowIntensity * 100))%") - .frame(width: 50, alignment: .trailing) - } - - HStack { - Text("Clock Opacity") - Slider(value: $style.clockOpacity, in: 0.0...1.0) - Text("\(Int(style.clockOpacity * 100))%") - .frame(width: 50, alignment: .trailing) - } - } - .onChange(of: backgroundColor) { _, newValue in - style.backgroundHex = newValue.toHex() ?? AppConstants.Defaults.backgroundColorHex - style.selectedColorTheme = "Custom" - style.clearColorCache() - } - .onChange(of: digitColor) { _, newValue in - style.digitColorHex = newValue.toHex() ?? AppConstants.Defaults.digitColorHex - style.selectedColorTheme = "Custom" - style.clearColorCache() - } - } - - /// Get the color for a theme - private func themeColor(for theme: String) -> Color { - switch theme { - case "Custom": - return .gray - case "Red": - return .red - case "Orange": - return .orange - case "Yellow": - return .yellow - case "Green": - return .green - case "Blue": - return .blue - case "Purple": - return .purple - case "Pink": - return .pink - case "White": - return .white - default: - return .gray - } - } -} private struct NightModeSection: View { @Binding var style: ClockStyle @@ -289,32 +354,6 @@ private struct OverlaySection: View { } } -private struct DisplaySection: View { - @Binding var style: ClockStyle - - var body: some View { - Section(header: Text("Display"), footer: Text("Keep the screen awake when in full-screen display mode. This prevents the device from sleeping while viewing the clock.")) { - Toggle("Keep Awake in Display Mode", isOn: $style.keepAwake) - } - - Section(header: Text("Auto Brightness"), footer: Text("Automatically adjust display brightness based on color theme and ambient light. Works with all color themes and night mode.")) { - Toggle("Auto Brightness", isOn: $style.autoBrightness) - - if style.autoBrightness { - HStack { - Text("Current Brightness") - Spacer() - Text("\(Int(style.effectiveBrightness * 100))%") - .foregroundColor(.secondary) - } - } - } - - Section(header: Text("Focus Modes"), footer: Text("Control how the app behaves when Focus modes (Do Not Disturb) are active. When enabled, audio may be paused during Focus mode.")) { - Toggle("Respect Focus Modes", isOn: $style.respectFocusModes) - } - } -} private struct TimePickerView: View { @Binding var timeString: String