refactor
Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
4f46304a5b
commit
4190c95b84
@ -64,7 +64,7 @@ struct ClockSettingsView: View {
|
|||||||
SettingsNavigationRow(
|
SettingsNavigationRow(
|
||||||
title: String(localized: "settings.debug.icon_generator.title", defaultValue: "Icon Generator"),
|
title: String(localized: "settings.debug.icon_generator.title", defaultValue: "Icon Generator"),
|
||||||
subtitle: String(localized: "settings.debug.icon_generator.subtitle", defaultValue: "Generate and save app icon"),
|
subtitle: String(localized: "settings.debug.icon_generator.subtitle", defaultValue: "Generate and save app icon"),
|
||||||
backgroundColor: AppSurface.primary
|
backgroundColor: .clear
|
||||||
) {
|
) {
|
||||||
IconGeneratorView(config: .noiseClock, appName: "TheNoiseClock")
|
IconGeneratorView(config: .noiseClock, appName: "TheNoiseClock")
|
||||||
}
|
}
|
||||||
@ -72,7 +72,7 @@ struct ClockSettingsView: View {
|
|||||||
SettingsNavigationRow(
|
SettingsNavigationRow(
|
||||||
title: String(localized: "settings.debug.branding_preview.title", defaultValue: "Branding Preview"),
|
title: String(localized: "settings.debug.branding_preview.title", defaultValue: "Branding Preview"),
|
||||||
subtitle: String(localized: "settings.debug.branding_preview.subtitle", defaultValue: "Preview icon and launch screen"),
|
subtitle: String(localized: "settings.debug.branding_preview.subtitle", defaultValue: "Preview icon and launch screen"),
|
||||||
backgroundColor: AppSurface.primary
|
backgroundColor: .clear
|
||||||
) {
|
) {
|
||||||
BrandingPreviewView(
|
BrandingPreviewView(
|
||||||
iconConfig: .noiseClock,
|
iconConfig: .noiseClock,
|
||||||
@ -82,12 +82,12 @@ struct ClockSettingsView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let onResetOnboarding {
|
if let onResetOnboarding {
|
||||||
Divider()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.background(AppBorder.subtle)
|
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
onResetOnboarding()
|
onResetOnboarding()
|
||||||
} label: {
|
} label: {
|
||||||
|
SettingsCardRow(verticalPadding: Design.Spacing.medium) {
|
||||||
HStack {
|
HStack {
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.xxSmall) {
|
VStack(alignment: .leading, spacing: Design.Spacing.xxSmall) {
|
||||||
Text(String(localized: "settings.debug.reset_onboarding.title", defaultValue: "Reset Onboarding"))
|
Text(String(localized: "settings.debug.reset_onboarding.title", defaultValue: "Reset Onboarding"))
|
||||||
@ -101,8 +101,7 @@ struct ClockSettingsView: View {
|
|||||||
Image(systemName: "arrow.counterclockwise")
|
Image(systemName: "arrow.counterclockwise")
|
||||||
.foregroundStyle(AppAccent.primary)
|
.foregroundStyle(AppAccent.primary)
|
||||||
}
|
}
|
||||||
.padding(Design.Spacing.medium)
|
}
|
||||||
.background(AppSurface.primary)
|
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,10 +34,7 @@ struct AdvancedAppearanceSection: View {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
SettingsToggle(
|
SettingsToggle(
|
||||||
title: String(localized: "settings.advanced_appearance.randomize_color.title", defaultValue: "Randomize Color"),
|
title: String(localized: "settings.advanced_appearance.randomize_color.title", defaultValue: "Randomize Color"),
|
||||||
@ -46,10 +43,7 @@ struct AdvancedAppearanceSection: View {
|
|||||||
accentColor: AppAccent.primary
|
accentColor: AppAccent.primary
|
||||||
)
|
)
|
||||||
|
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
SettingsSlider(
|
SettingsSlider(
|
||||||
title: String(localized: "settings.advanced_appearance.glow.title", defaultValue: "Glow"),
|
title: String(localized: "settings.advanced_appearance.glow.title", defaultValue: "Glow"),
|
||||||
@ -61,10 +55,7 @@ struct AdvancedAppearanceSection: View {
|
|||||||
accentColor: AppAccent.primary
|
accentColor: AppAccent.primary
|
||||||
)
|
)
|
||||||
|
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
SettingsSlider(
|
SettingsSlider(
|
||||||
title: String(localized: "settings.advanced_appearance.clock_opacity.title", defaultValue: "Clock Opacity"),
|
title: String(localized: "settings.advanced_appearance.clock_opacity.title", defaultValue: "Clock Opacity"),
|
||||||
|
|||||||
@ -30,24 +30,18 @@ struct AdvancedDisplaySection: View {
|
|||||||
.accessibilityIdentifier("settings.keepAwake.toggle")
|
.accessibilityIdentifier("settings.keepAwake.toggle")
|
||||||
|
|
||||||
if style.autoBrightness {
|
if style.autoBrightness {
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
HStack {
|
SettingsLabelValueRow(
|
||||||
Text(String(localized: "settings.advanced_display.current_brightness", defaultValue: "Current Brightness"))
|
title: String(localized: "settings.advanced_display.current_brightness", defaultValue: "Current Brightness"),
|
||||||
.font(.subheadline.weight(.medium))
|
verticalPadding: Design.Spacing.medium
|
||||||
.foregroundStyle(AppTextColors.primary)
|
) {
|
||||||
Spacer()
|
|
||||||
Text(style.effectiveBrightness, format: .percent.precision(.fractionLength(0)))
|
Text(style.effectiveBrightness, format: .percent.precision(.fractionLength(0)))
|
||||||
.font(.subheadline)
|
.font(.subheadline)
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
.foregroundStyle(AppTextColors.secondary)
|
||||||
.contentTransition(.numericText())
|
.contentTransition(.numericText())
|
||||||
.animation(.snappy(duration: 0.3), value: style.effectiveBrightness)
|
.animation(.snappy(duration: 0.3), value: style.effectiveBrightness)
|
||||||
}
|
}
|
||||||
.padding(.vertical, Design.Spacing.medium)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,33 +46,27 @@ struct BasicAppearanceSection: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if style.selectedColorTheme == "Custom" {
|
if style.selectedColorTheme == "Custom" {
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
|
SettingsCardRow {
|
||||||
ColorPicker(
|
ColorPicker(
|
||||||
String(localized: "settings.colors.digit_color", defaultValue: "Digit Color"),
|
String(localized: "settings.colors.digit_color", defaultValue: "Digit Color"),
|
||||||
selection: $digitColor,
|
selection: $digitColor,
|
||||||
supportsOpacity: false
|
supportsOpacity: false
|
||||||
)
|
)
|
||||||
.foregroundStyle(AppTextColors.primary)
|
.foregroundStyle(AppTextColors.primary)
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
}
|
||||||
.padding(.vertical, Design.Spacing.small)
|
|
||||||
|
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
|
SettingsCardRow {
|
||||||
ColorPicker(
|
ColorPicker(
|
||||||
String(localized: "settings.colors.background_color", defaultValue: "Background Color"),
|
String(localized: "settings.colors.background_color", defaultValue: "Background Color"),
|
||||||
selection: $backgroundColor,
|
selection: $backgroundColor,
|
||||||
supportsOpacity: true
|
supportsOpacity: true
|
||||||
)
|
)
|
||||||
.foregroundStyle(AppTextColors.primary)
|
.foregroundStyle(AppTextColors.primary)
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
}
|
||||||
.padding(.vertical, Design.Spacing.small)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,10 +28,7 @@ struct BasicDisplaySection: View {
|
|||||||
accentColor: AppAccent.primary
|
accentColor: AppAccent.primary
|
||||||
)
|
)
|
||||||
|
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
SettingsToggle(
|
SettingsToggle(
|
||||||
title: String(localized: "settings.display.show_seconds.title", defaultValue: "Show Seconds"),
|
title: String(localized: "settings.display.show_seconds.title", defaultValue: "Show Seconds"),
|
||||||
@ -41,10 +38,7 @@ struct BasicDisplaySection: View {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if !style.use24Hour {
|
if !style.use24Hour {
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
SettingsToggle(
|
SettingsToggle(
|
||||||
title: String(localized: "settings.display.show_ampm.title", defaultValue: "Show AM/PM"),
|
title: String(localized: "settings.display.show_ampm.title", defaultValue: "Show AM/PM"),
|
||||||
@ -54,10 +48,7 @@ struct BasicDisplaySection: View {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
SettingsToggle(
|
SettingsToggle(
|
||||||
title: String(localized: "settings.display.auto_brightness.title", defaultValue: "Auto Brightness"),
|
title: String(localized: "settings.display.auto_brightness.title", defaultValue: "Auto Brightness"),
|
||||||
@ -67,10 +58,7 @@ struct BasicDisplaySection: View {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if UIDevice.current.orientation.isPortrait || UIDevice.current.orientation == .unknown {
|
if UIDevice.current.orientation.isPortrait || UIDevice.current.orientation == .unknown {
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
SettingsToggle(
|
SettingsToggle(
|
||||||
title: String(localized: "settings.display.horizontal_mode.title", defaultValue: "Horizontal Mode"),
|
title: String(localized: "settings.display.horizontal_mode.title", defaultValue: "Horizontal Mode"),
|
||||||
|
|||||||
@ -62,10 +62,7 @@ struct FontSection: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
// Font Weight
|
// Font Weight
|
||||||
SettingsNavigationRow(
|
SettingsNavigationRow(
|
||||||
@ -82,10 +79,7 @@ struct FontSection: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if style.fontFamily == .system {
|
if style.fontFamily == .system {
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
// Font Design
|
// Font Design
|
||||||
SettingsNavigationRow(
|
SettingsNavigationRow(
|
||||||
@ -102,20 +96,15 @@ struct FontSection: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
HStack {
|
SettingsLabelValueRow(
|
||||||
Text(String(localized: "settings.font.preview.title", defaultValue: "Preview")).styled(.subheadingEmphasis)
|
title: String(localized: "settings.font.preview.title", defaultValue: "Preview")
|
||||||
Spacer()
|
) {
|
||||||
Text(String(localized: "settings.font.preview.sample_time", defaultValue: "12:34"))
|
Text(String(localized: "settings.font.preview.sample_time", defaultValue: "12:34"))
|
||||||
.font(FontUtils.createFont(name: style.fontFamily, weight: style.fontWeight, design: style.fontDesign, size: 24))
|
.font(FontUtils.createFont(name: style.fontFamily, weight: style.fontWeight, design: style.fontDesign, size: 24))
|
||||||
.foregroundStyle(AppTextColors.primary)
|
.foregroundStyle(AppTextColors.primary)
|
||||||
}
|
}
|
||||||
.padding(.vertical, Design.Spacing.small)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,10 +28,7 @@ struct NightModeSection: View {
|
|||||||
accentColor: AppAccent.primary
|
accentColor: AppAccent.primary
|
||||||
)
|
)
|
||||||
|
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
SettingsToggle(
|
SettingsToggle(
|
||||||
title: String(localized: "settings.night_mode.auto.title", defaultValue: "Auto Night Mode"),
|
title: String(localized: "settings.night_mode.auto.title", defaultValue: "Auto Night Mode"),
|
||||||
@ -41,10 +38,7 @@ struct NightModeSection: View {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if style.autoNightMode {
|
if style.autoNightMode {
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
SettingsSlider(
|
SettingsSlider(
|
||||||
title: String(localized: "settings.night_mode.light_threshold.title", defaultValue: "Light Threshold"),
|
title: String(localized: "settings.night_mode.light_threshold.title", defaultValue: "Light Threshold"),
|
||||||
@ -57,10 +51,7 @@ struct NightModeSection: View {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
SettingsToggle(
|
SettingsToggle(
|
||||||
title: String(localized: "settings.night_mode.scheduled.title", defaultValue: "Scheduled Night Mode"),
|
title: String(localized: "settings.night_mode.scheduled.title", defaultValue: "Scheduled Night Mode"),
|
||||||
@ -70,43 +61,29 @@ struct NightModeSection: View {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if style.scheduledNightMode {
|
if style.scheduledNightMode {
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
HStack {
|
SettingsLabelValueRow(
|
||||||
Text(String(localized: "settings.night_mode.start_time", defaultValue: "Start Time"))
|
title: String(localized: "settings.night_mode.start_time", defaultValue: "Start Time"),
|
||||||
.font(.subheadline.weight(.medium))
|
verticalPadding: Design.Spacing.medium
|
||||||
.foregroundStyle(AppTextColors.primary)
|
) {
|
||||||
Spacer()
|
SettingsTimePicker(timeString: $style.nightModeStartTime, accentColor: AppAccent.primary)
|
||||||
TimePickerView(timeString: $style.nightModeStartTime)
|
|
||||||
}
|
}
|
||||||
.padding(.vertical, Design.Spacing.medium)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
HStack {
|
SettingsLabelValueRow(
|
||||||
Text(String(localized: "settings.night_mode.end_time", defaultValue: "End Time"))
|
title: String(localized: "settings.night_mode.end_time", defaultValue: "End Time"),
|
||||||
.font(.subheadline.weight(.medium))
|
verticalPadding: Design.Spacing.medium
|
||||||
.foregroundStyle(AppTextColors.primary)
|
) {
|
||||||
Spacer()
|
SettingsTimePicker(timeString: $style.nightModeEndTime, accentColor: AppAccent.primary)
|
||||||
TimePickerView(timeString: $style.nightModeEndTime)
|
|
||||||
}
|
}
|
||||||
.padding(.vertical, Design.Spacing.medium)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if style.isNightModeActive {
|
if style.isNightModeActive {
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
|
SettingsCardRow {
|
||||||
HStack(spacing: Design.Spacing.xSmall) {
|
HStack(spacing: Design.Spacing.xSmall) {
|
||||||
Image(systemName: "moon.fill")
|
Image(systemName: "moon.fill")
|
||||||
.foregroundStyle(AppStatus.error)
|
.foregroundStyle(AppStatus.error)
|
||||||
@ -115,8 +92,7 @@ struct NightModeSection: View {
|
|||||||
.foregroundStyle(AppStatus.error)
|
.foregroundStyle(AppStatus.error)
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
.padding(.vertical, Design.Spacing.small)
|
}
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,10 +30,7 @@ struct OverlaySection: View {
|
|||||||
accentColor: AppAccent.primary
|
accentColor: AppAccent.primary
|
||||||
)
|
)
|
||||||
|
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
SettingsToggle(
|
SettingsToggle(
|
||||||
title: String(localized: "settings.overlays.date.title", defaultValue: "Date"),
|
title: String(localized: "settings.overlays.date.title", defaultValue: "Date"),
|
||||||
@ -42,10 +39,7 @@ struct OverlaySection: View {
|
|||||||
accentColor: AppAccent.primary
|
accentColor: AppAccent.primary
|
||||||
)
|
)
|
||||||
|
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
SettingsToggle(
|
SettingsToggle(
|
||||||
title: String(localized: "settings.overlays.next_alarm.title", defaultValue: "Next Alarm"),
|
title: String(localized: "settings.overlays.next_alarm.title", defaultValue: "Next Alarm"),
|
||||||
@ -54,10 +48,7 @@ struct OverlaySection: View {
|
|||||||
accentColor: AppAccent.primary
|
accentColor: AppAccent.primary
|
||||||
)
|
)
|
||||||
|
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
SettingsToggle(
|
SettingsToggle(
|
||||||
title: String(localized: "settings.overlays.noise_controls.title", defaultValue: "Noise Controls"),
|
title: String(localized: "settings.overlays.noise_controls.title", defaultValue: "Noise Controls"),
|
||||||
@ -67,10 +58,7 @@ struct OverlaySection: View {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if style.showDate {
|
if style.showDate {
|
||||||
Rectangle()
|
SettingsDivider(color: AppBorder.subtle)
|
||||||
.fill(AppBorder.subtle)
|
|
||||||
.frame(height: 1)
|
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
|
||||||
|
|
||||||
SettingsNavigationRow(
|
SettingsNavigationRow(
|
||||||
title: String(localized: "settings.overlays.date_format.title", defaultValue: "Date Format"),
|
title: String(localized: "settings.overlays.date_format.title", defaultValue: "Date Format"),
|
||||||
|
|||||||
@ -1,57 +0,0 @@
|
|||||||
//
|
|
||||||
// TimePickerView.swift
|
|
||||||
// TheNoiseClock
|
|
||||||
//
|
|
||||||
// Created by Matt Bruce on 9/7/25.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
import Bedrock
|
|
||||||
|
|
||||||
struct TimePickerView: View {
|
|
||||||
@Binding var timeString: String
|
|
||||||
@State private var selectedTime = Date()
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
DatePicker("", selection: $selectedTime, displayedComponents: .hourAndMinute)
|
|
||||||
.labelsHidden()
|
|
||||||
.tint(AppAccent.primary)
|
|
||||||
.onAppear {
|
|
||||||
updateSelectedTimeFromString()
|
|
||||||
}
|
|
||||||
.onChange(of: selectedTime) { _, newTime in
|
|
||||||
updateStringFromTime(newTime)
|
|
||||||
}
|
|
||||||
.onChange(of: timeString) { _, _ in
|
|
||||||
updateSelectedTimeFromString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func updateSelectedTimeFromString() {
|
|
||||||
let components = timeString.split(separator: ":")
|
|
||||||
guard components.count == 2,
|
|
||||||
let hour = Int(components[0]),
|
|
||||||
let minute = Int(components[1]) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let calendar = Calendar.current
|
|
||||||
let now = Date()
|
|
||||||
let dateComponents = calendar.dateComponents([.year, .month, .day], from: now)
|
|
||||||
|
|
||||||
var newComponents = dateComponents
|
|
||||||
newComponents.hour = hour
|
|
||||||
newComponents.minute = minute
|
|
||||||
|
|
||||||
if let newDate = calendar.date(from: newComponents) {
|
|
||||||
selectedTime = newDate
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func updateStringFromTime(_ time: Date) {
|
|
||||||
let calendar = Calendar.current
|
|
||||||
let hour = calendar.component(.hour, from: time)
|
|
||||||
let minute = calendar.component(.minute, from: time)
|
|
||||||
timeString = String(format: "%02d:%02d", hour, minute)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,9 +1,6 @@
|
|||||||
{
|
{
|
||||||
"sourceLanguage" : "en",
|
"sourceLanguage" : "en",
|
||||||
"strings" : {
|
"strings" : {
|
||||||
"" : {
|
|
||||||
|
|
||||||
},
|
|
||||||
"alarm_intent.error.alarm_not_found" : {
|
"alarm_intent.error.alarm_not_found" : {
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"en" : {
|
"en" : {
|
||||||
|
|||||||
@ -1,83 +0,0 @@
|
|||||||
//
|
|
||||||
// SettingsSelectionView.swift
|
|
||||||
// TheNoiseClock
|
|
||||||
//
|
|
||||||
// Created by Matt Bruce on 9/8/25.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
import Bedrock
|
|
||||||
|
|
||||||
/// A reusable selection view for settings that navigates to a new screen.
|
|
||||||
struct SettingsSelectionView<T: Hashable>: View {
|
|
||||||
@Binding var selection: T
|
|
||||||
let options: [T]
|
|
||||||
let title: String
|
|
||||||
let toString: (T) -> String
|
|
||||||
|
|
||||||
@Environment(\.dismiss) private var dismiss
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
ZStack {
|
|
||||||
AppSurface.primary.ignoresSafeArea()
|
|
||||||
|
|
||||||
ScrollView {
|
|
||||||
VStack(spacing: Design.Spacing.medium) {
|
|
||||||
SettingsSectionHeader(
|
|
||||||
title: title,
|
|
||||||
systemImage: "checklist",
|
|
||||||
accentColor: AppAccent.primary
|
|
||||||
)
|
|
||||||
|
|
||||||
SettingsCard(backgroundColor: AppSurface.card, borderColor: AppBorder.subtle) {
|
|
||||||
VStack(spacing: 0) {
|
|
||||||
ForEach(options, id: \.self) { option in
|
|
||||||
Button(action: {
|
|
||||||
selection = option
|
|
||||||
dismiss()
|
|
||||||
}) {
|
|
||||||
HStack {
|
|
||||||
Text(toString(option))
|
|
||||||
.typography(.body)
|
|
||||||
.foregroundStyle(AppTextColors.primary)
|
|
||||||
Spacer()
|
|
||||||
if selection == option {
|
|
||||||
Image(systemName: "checkmark")
|
|
||||||
.foregroundStyle(AppAccent.primary)
|
|
||||||
.font(.body.bold())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding(Design.Spacing.medium)
|
|
||||||
.background(Color.clear)
|
|
||||||
}
|
|
||||||
.buttonStyle(.plain)
|
|
||||||
|
|
||||||
if option != options.last {
|
|
||||||
Divider()
|
|
||||||
.background(AppBorder.subtle)
|
|
||||||
.padding(.horizontal, Design.Spacing.medium)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding(.horizontal, Design.Spacing.large)
|
|
||||||
.padding(.top, Design.Spacing.large)
|
|
||||||
.padding(.bottom, Design.Spacing.xxxLarge)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.navigationTitle(title)
|
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#Preview {
|
|
||||||
NavigationStack {
|
|
||||||
SettingsSelectionView(
|
|
||||||
selection: .constant("Option 1"),
|
|
||||||
options: ["Option 1", "Option 2", "Option 3"],
|
|
||||||
title: "Test Selection",
|
|
||||||
toString: { $0 }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user