Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>

This commit is contained in:
Matt Bruce 2025-09-08 12:53:31 -05:00
parent b3615c8117
commit 8e2f9c11c1
6 changed files with 52 additions and 6 deletions

View File

@ -9,14 +9,38 @@ import Foundation
extension Date { 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 /// - Returns: Formatted date string
func formattedForOverlay() -> String { func formattedForOverlay(format: String = "d MMMM EEE") -> String {
let formatter = DateFormatter() let formatter = DateFormatter()
formatter.dateFormat = "d MMMM EEE" formatter.dateFormat = format
return formatter.string(from: self) 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 /// Get time components for alarm scheduling
/// - Returns: DateComponents with hour and minute /// - Returns: DateComponents with hour and minute
func timeComponents() -> DateComponents { func timeComponents() -> DateComponents {

View File

@ -33,6 +33,7 @@ class ClockStyle: Codable, Equatable {
// MARK: - Overlay Settings // MARK: - Overlay Settings
var showBattery: Bool = true var showBattery: Bool = true
var showDate: Bool = true var showDate: Bool = true
var dateFormat: String = "d MMMM EEE" // Default: "7 September Mon"
var clockOpacity: Double = AppConstants.Defaults.clockOpacity var clockOpacity: Double = AppConstants.Defaults.clockOpacity
var overlayOpacity: Double = AppConstants.Defaults.overlayOpacity var overlayOpacity: Double = AppConstants.Defaults.overlayOpacity
@ -56,6 +57,7 @@ class ClockStyle: Codable, Equatable {
case fontDesign case fontDesign
case showBattery case showBattery
case showDate case showDate
case dateFormat
case clockOpacity case clockOpacity
case overlayOpacity case overlayOpacity
} }
@ -83,6 +85,7 @@ class ClockStyle: Codable, Equatable {
self.fontDesign = try container.decodeIfPresent(String.self, forKey: .fontDesign) ?? self.fontDesign self.fontDesign = try container.decodeIfPresent(String.self, forKey: .fontDesign) ?? self.fontDesign
self.showBattery = try container.decodeIfPresent(Bool.self, forKey: .showBattery) ?? self.showBattery self.showBattery = try container.decodeIfPresent(Bool.self, forKey: .showBattery) ?? self.showBattery
self.showDate = try container.decodeIfPresent(Bool.self, forKey: .showDate) ?? self.showDate 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.clockOpacity = try container.decodeIfPresent(Double.self, forKey: .clockOpacity) ?? self.clockOpacity
self.overlayOpacity = try container.decodeIfPresent(Double.self, forKey: .overlayOpacity) ?? self.overlayOpacity 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(fontDesign, forKey: .fontDesign)
try container.encode(showBattery, forKey: .showBattery) try container.encode(showBattery, forKey: .showBattery)
try container.encode(showDate, forKey: .showDate) try container.encode(showDate, forKey: .showDate)
try container.encode(dateFormat, forKey: .dateFormat)
try container.encode(clockOpacity, forKey: .clockOpacity) try container.encode(clockOpacity, forKey: .clockOpacity)
try container.encode(overlayOpacity, forKey: .overlayOpacity) try container.encode(overlayOpacity, forKey: .overlayOpacity)
} }
@ -150,6 +154,7 @@ class ClockStyle: Codable, Equatable {
lhs.fontDesign == rhs.fontDesign && lhs.fontDesign == rhs.fontDesign &&
lhs.showBattery == rhs.showBattery && lhs.showBattery == rhs.showBattery &&
lhs.showDate == rhs.showDate && lhs.showDate == rhs.showDate &&
lhs.dateFormat == rhs.dateFormat &&
lhs.clockOpacity == rhs.clockOpacity && lhs.clockOpacity == rhs.clockOpacity &&
lhs.overlayOpacity == rhs.overlayOpacity lhs.overlayOpacity == rhs.overlayOpacity
} }

View File

@ -169,6 +169,8 @@ private struct AppearanceSection: View {
private struct OverlaySection: View { private struct OverlaySection: View {
@Binding var style: ClockStyle @Binding var style: ClockStyle
private let dateFormats = Date.availableDateFormats()
var body: some View { var body: some View {
Section(header: Text("Overlays")) { Section(header: Text("Overlays")) {
HStack { HStack {
@ -180,6 +182,15 @@ private struct OverlaySection: View {
Toggle("Battery Level", isOn: $style.showBattery) Toggle("Battery Level", isOn: $style.showBattery)
Toggle("Date", isOn: $style.showDate) 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)
}
} }
} }
} }

View File

@ -21,7 +21,8 @@ struct ClockOverlayContainer: View {
showBattery: style.showBattery, showBattery: style.showBattery,
showDate: style.showDate, showDate: style.showDate,
color: style.digitColor.opacity(UIConstants.Opacity.primary), color: style.digitColor.opacity(UIConstants.Opacity.primary),
opacity: style.overlayOpacity opacity: style.overlayOpacity,
dateFormat: style.dateFormat
) )
.padding(.top, UIConstants.Spacing.small) .padding(.top, UIConstants.Spacing.small)
.padding(.horizontal, UIConstants.Spacing.large) .padding(.horizontal, UIConstants.Spacing.large)

View File

@ -14,6 +14,7 @@ struct DateOverlayView: View {
// MARK: - Properties // MARK: - Properties
let color: Color let color: Color
let opacity: Double let opacity: Double
let dateFormat: String
@State private var dateString: String = "" @State private var dateString: String = ""
@State private var minuteTimer: Timer.TimerPublisher? @State private var minuteTimer: Timer.TimerPublisher?
@ -34,6 +35,9 @@ struct DateOverlayView: View {
.onDisappear { .onDisappear {
stopMinuteUpdates() stopMinuteUpdates()
} }
.onChange(of: dateFormat) { _, _ in
updateDate()
}
} }
// MARK: - Private Methods // MARK: - Private Methods
@ -52,6 +56,6 @@ struct DateOverlayView: View {
} }
private func updateDate() { private func updateDate() {
dateString = Date().formattedForOverlay() dateString = Date().formattedForOverlay(format: dateFormat)
} }
} }

View File

@ -15,12 +15,13 @@ struct TopOverlayView: View {
let showDate: Bool let showDate: Bool
let color: Color let color: Color
let opacity: Double let opacity: Double
let dateFormat: String
// MARK: - Body // MARK: - Body
var body: some View { var body: some View {
HStack { HStack {
if showDate { if showDate {
DateOverlayView(color: color, opacity: opacity) DateOverlayView(color: color, opacity: opacity, dateFormat: dateFormat)
} }
Spacer() Spacer()