From 8e2f9c11c1d1fb6b033abcbd07a690e498104ae9 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 8 Sep 2025 12:53:31 -0500 Subject: [PATCH] Signed-off-by: Matt Bruce --- .../Core/Extensions/Date+Extensions.swift | 30 +++++++++++++++++-- TheNoiseClock/Models/ClockStyle.swift | 5 ++++ .../Views/Clock/ClockSettingsView.swift | 11 +++++++ .../Components/ClockOverlayContainer.swift | 3 +- .../Clock/Components/DateOverlayView.swift | 6 +++- .../Clock/Components/TopOverlayView.swift | 3 +- 6 files changed, 52 insertions(+), 6 deletions(-) diff --git a/TheNoiseClock/Core/Extensions/Date+Extensions.swift b/TheNoiseClock/Core/Extensions/Date+Extensions.swift index 9a3943a..5c19dd3 100644 --- a/TheNoiseClock/Core/Extensions/Date+Extensions.swift +++ b/TheNoiseClock/Core/Extensions/Date+Extensions.swift @@ -9,14 +9,38 @@ import Foundation extension Date { - /// Format date for display in overlay (e.g., "7 September Mon") + /// Format date for display in overlay with custom format + /// - Parameter format: Date format string (e.g., "d MMMM EEE") /// - Returns: Formatted date string - func formattedForOverlay() -> String { + func formattedForOverlay(format: String = "d MMMM EEE") -> String { let formatter = DateFormatter() - formatter.dateFormat = "d MMMM EEE" + formatter.dateFormat = format return formatter.string(from: self) } + /// Get available date format options with their display names + /// - Returns: Array of (displayName, formatString) tuples + static func availableDateFormats() -> [(String, String)] { + let today = Date() + let formatStrings = [ + "d MMMM EEE", + "MMMM d, EEE", + "EEE, MMM d", + "d MMM yyyy", + "MM/dd/yyyy", + "dd/MM/yyyy", + "yyyy-MM-dd", + "MMM d", + "MMMM d", + "EEEE, MMM d" + ] + + return formatStrings.map { formatString in + let example = today.formattedForOverlay(format: formatString) + return (example, formatString) + } + } + /// Get time components for alarm scheduling /// - Returns: DateComponents with hour and minute func timeComponents() -> DateComponents { diff --git a/TheNoiseClock/Models/ClockStyle.swift b/TheNoiseClock/Models/ClockStyle.swift index acb14d7..e01e175 100644 --- a/TheNoiseClock/Models/ClockStyle.swift +++ b/TheNoiseClock/Models/ClockStyle.swift @@ -33,6 +33,7 @@ class ClockStyle: Codable, Equatable { // MARK: - Overlay Settings var showBattery: Bool = true var showDate: Bool = true + var dateFormat: String = "d MMMM EEE" // Default: "7 September Mon" var clockOpacity: Double = AppConstants.Defaults.clockOpacity var overlayOpacity: Double = AppConstants.Defaults.overlayOpacity @@ -56,6 +57,7 @@ class ClockStyle: Codable, Equatable { case fontDesign case showBattery case showDate + case dateFormat case clockOpacity case overlayOpacity } @@ -83,6 +85,7 @@ class ClockStyle: Codable, Equatable { self.fontDesign = try container.decodeIfPresent(String.self, forKey: .fontDesign) ?? self.fontDesign self.showBattery = try container.decodeIfPresent(Bool.self, forKey: .showBattery) ?? self.showBattery self.showDate = try container.decodeIfPresent(Bool.self, forKey: .showDate) ?? self.showDate + self.dateFormat = try container.decodeIfPresent(String.self, forKey: .dateFormat) ?? self.dateFormat self.clockOpacity = try container.decodeIfPresent(Double.self, forKey: .clockOpacity) ?? self.clockOpacity self.overlayOpacity = try container.decodeIfPresent(Double.self, forKey: .overlayOpacity) ?? self.overlayOpacity @@ -105,6 +108,7 @@ class ClockStyle: Codable, Equatable { try container.encode(fontDesign, forKey: .fontDesign) try container.encode(showBattery, forKey: .showBattery) try container.encode(showDate, forKey: .showDate) + try container.encode(dateFormat, forKey: .dateFormat) try container.encode(clockOpacity, forKey: .clockOpacity) try container.encode(overlayOpacity, forKey: .overlayOpacity) } @@ -150,6 +154,7 @@ class ClockStyle: Codable, Equatable { lhs.fontDesign == rhs.fontDesign && lhs.showBattery == rhs.showBattery && lhs.showDate == rhs.showDate && + lhs.dateFormat == rhs.dateFormat && lhs.clockOpacity == rhs.clockOpacity && lhs.overlayOpacity == rhs.overlayOpacity } diff --git a/TheNoiseClock/Views/Clock/ClockSettingsView.swift b/TheNoiseClock/Views/Clock/ClockSettingsView.swift index 75dca9b..41f5fd3 100644 --- a/TheNoiseClock/Views/Clock/ClockSettingsView.swift +++ b/TheNoiseClock/Views/Clock/ClockSettingsView.swift @@ -169,6 +169,8 @@ private struct AppearanceSection: View { private struct OverlaySection: View { @Binding var style: ClockStyle + private let dateFormats = Date.availableDateFormats() + var body: some View { Section(header: Text("Overlays")) { HStack { @@ -180,6 +182,15 @@ private struct OverlaySection: View { Toggle("Battery Level", isOn: $style.showBattery) Toggle("Date", isOn: $style.showDate) + + if style.showDate { + Picker("Date Format", selection: $style.dateFormat) { + ForEach(dateFormats, id: \.1) { format in + Text(format.0).tag(format.1) + } + } + .pickerStyle(.menu) + } } } } diff --git a/TheNoiseClock/Views/Clock/Components/ClockOverlayContainer.swift b/TheNoiseClock/Views/Clock/Components/ClockOverlayContainer.swift index b328c1e..919b90c 100644 --- a/TheNoiseClock/Views/Clock/Components/ClockOverlayContainer.swift +++ b/TheNoiseClock/Views/Clock/Components/ClockOverlayContainer.swift @@ -21,7 +21,8 @@ struct ClockOverlayContainer: View { showBattery: style.showBattery, showDate: style.showDate, color: style.digitColor.opacity(UIConstants.Opacity.primary), - opacity: style.overlayOpacity + opacity: style.overlayOpacity, + dateFormat: style.dateFormat ) .padding(.top, UIConstants.Spacing.small) .padding(.horizontal, UIConstants.Spacing.large) diff --git a/TheNoiseClock/Views/Clock/Components/DateOverlayView.swift b/TheNoiseClock/Views/Clock/Components/DateOverlayView.swift index dff78d2..29a2263 100644 --- a/TheNoiseClock/Views/Clock/Components/DateOverlayView.swift +++ b/TheNoiseClock/Views/Clock/Components/DateOverlayView.swift @@ -14,6 +14,7 @@ struct DateOverlayView: View { // MARK: - Properties let color: Color let opacity: Double + let dateFormat: String @State private var dateString: String = "" @State private var minuteTimer: Timer.TimerPublisher? @@ -34,6 +35,9 @@ struct DateOverlayView: View { .onDisappear { stopMinuteUpdates() } + .onChange(of: dateFormat) { _, _ in + updateDate() + } } // MARK: - Private Methods @@ -52,6 +56,6 @@ struct DateOverlayView: View { } private func updateDate() { - dateString = Date().formattedForOverlay() + dateString = Date().formattedForOverlay(format: dateFormat) } } diff --git a/TheNoiseClock/Views/Clock/Components/TopOverlayView.swift b/TheNoiseClock/Views/Clock/Components/TopOverlayView.swift index 374fe7b..f11088f 100644 --- a/TheNoiseClock/Views/Clock/Components/TopOverlayView.swift +++ b/TheNoiseClock/Views/Clock/Components/TopOverlayView.swift @@ -15,12 +15,13 @@ struct TopOverlayView: View { let showDate: Bool let color: Color let opacity: Double + let dateFormat: String // MARK: - Body var body: some View { HStack { if showDate { - DateOverlayView(color: color, opacity: opacity) + DateOverlayView(color: color, opacity: opacity, dateFormat: dateFormat) } Spacer()