From 63dde81b97dd593ac6e7a8e75e2a158eb4e097f5 Mon Sep 17 00:00:00 2001 From: Michael Freno Date: Fri, 9 Jan 2026 13:13:07 -0500 Subject: [PATCH] feat: better clarity for disabled reminders, continued prev commit work --- Gaze/Animations/ring.json | 1 + Gaze/Models/AnimationAsset.swift | 1 + Gaze/Models/AppSettings.swift | 23 ++++++++++++++++ Gaze/Views/MenuBar/MenuBarContentView.swift | 2 +- Gaze/Views/Onboarding/BlinkSetupView.swift | 16 +++++++++--- Gaze/Views/Onboarding/CompletionView.swift | 9 +++++++ Gaze/Views/Onboarding/LookAwaySetupView.swift | 18 ++++++++++--- Gaze/Views/Onboarding/PostureSetupView.swift | 16 +++++++++--- Gaze/Views/Onboarding/WelcomeView.swift | 26 ++++++++++++++++--- Gaze/Views/Reminders/BlinkReminderView.swift | 2 ++ 10 files changed, 99 insertions(+), 15 deletions(-) create mode 100644 Gaze/Animations/ring.json diff --git a/Gaze/Animations/ring.json b/Gaze/Animations/ring.json new file mode 100644 index 0000000..0f135a3 --- /dev/null +++ b/Gaze/Animations/ring.json @@ -0,0 +1 @@ +{ "v": "5.7.4", "fr": 30, "ip": 0, "op": 60, "w": 200, "h": 200, "nm": "Ring Animation", "ddd": 0, "assets": [], "date": "2026-01-09T00:00:00Z", "layers": [ { "ddd": 0, "ind": 1, "ty": 4, "nm": "Ring", "sr": 1, "ks": { "o": { "a": 0, "k": 100 }, "r": { "a": 1, "k": [ { "t": 0, "s": [0], "e": [360] }, { "t": 30, "s": [360], "e": [0] } ] }, "p": { "a": 0, "k": [100, 100, 0] }, "a": { "a": 0, "k": [0, 0, 0] }, "s": { "a": 0, "k": [100, 100, 100] } }, "ao": 0, "shapes": [ { "ty": "gr", "it": [ { "ty": "el", "p": { "a": 0, "k": [0, 0] }, "s": { "a": 0, "k": [80, 80] }, "nm": "Ring Ellipse" }, { "ty": "st", "c": { "a": 0, "k": [0.9, 0.3, 0.1, 1] }, "o": { "a": 0, "k": 100 }, "w": { "a": 0, "k": 6 }, "lc": 1, "lj": 2, "nm": "Stroke" }, { "ty": "tr", "p": { "a": 0, "k": [0, 0] }, "a": { "a": 0, "k": [0, 0] }, "s": { "a": 0, "k": [100, 100] }, "r": { "a": 0, "k": 0 }, "o": { "a": 0, "k": 100 } } ], "nm": "Ring Shape" } ], "ip": 0, "op": 60, "st": 0, "bm": 0 } ], "markers": [] } diff --git a/Gaze/Models/AnimationAsset.swift b/Gaze/Models/AnimationAsset.swift index 5c89b7a..3020f5c 100644 --- a/Gaze/Models/AnimationAsset.swift +++ b/Gaze/Models/AnimationAsset.swift @@ -11,6 +11,7 @@ enum AnimationAsset: String { case blink = "blink" case lookAway = "look-away" case posture = "posture" + case ring = "ring" var fileName: String { return self.rawValue diff --git a/Gaze/Models/AppSettings.swift b/Gaze/Models/AppSettings.swift index 52f1301..4744165 100644 --- a/Gaze/Models/AppSettings.swift +++ b/Gaze/Models/AppSettings.swift @@ -28,6 +28,29 @@ struct AppSettings: Codable, Equatable { var launchAtLogin: Bool var playSounds: Bool + init( + lookAwayTimer: TimerConfiguration = TimerConfiguration(enabled: true, intervalSeconds: 20 * 60), + lookAwayCountdownSeconds: Int = 20, + blinkTimer: TimerConfiguration = TimerConfiguration(enabled: false, intervalSeconds: 7 * 60), + postureTimer: TimerConfiguration = TimerConfiguration(enabled: true, intervalSeconds: 30 * 60), + userTimers: [UserTimer] = [], + subtleReminderSizePercentage: Double = 5.0, + hasCompletedOnboarding: Bool = false, + launchAtLogin: Bool = false, + playSounds: Bool = true + ) { + self.lookAwayTimer = lookAwayTimer + self.lookAwayCountdownSeconds = lookAwayCountdownSeconds + self.blinkTimer = blinkTimer + self.postureTimer = postureTimer + self.userTimers = userTimers + // Clamp the subtle reminder size to valid range (2-35%) + self.subtleReminderSizePercentage = max(2.0, min(35.0, subtleReminderSizePercentage)) + self.hasCompletedOnboarding = hasCompletedOnboarding + self.launchAtLogin = launchAtLogin + self.playSounds = playSounds + } + static var defaults: AppSettings { AppSettings( lookAwayTimer: TimerConfiguration(enabled: true, intervalSeconds: 20 * 60), diff --git a/Gaze/Views/MenuBar/MenuBarContentView.swift b/Gaze/Views/MenuBar/MenuBarContentView.swift index 5d159a7..719b9c1 100644 --- a/Gaze/Views/MenuBar/MenuBarContentView.swift +++ b/Gaze/Views/MenuBar/MenuBarContentView.swift @@ -30,7 +30,7 @@ struct MenuBarHoverButtonStyle: ButtonStyle { func makeBody(configuration: Configuration) -> some View { configuration.label .glassEffect( - isHovered ? .regular.tint(.accentColor).interactive() : .regular, + isHovered ? .regular.tint(.accentColor.opacity(0.5)).interactive() : .regular, in: .rect(cornerRadius: 6) ) .contentShape(Rectangle()) diff --git a/Gaze/Views/Onboarding/BlinkSetupView.swift b/Gaze/Views/Onboarding/BlinkSetupView.swift index a4d4f55..005c9a4 100644 --- a/Gaze/Views/Onboarding/BlinkSetupView.swift +++ b/Gaze/Views/Onboarding/BlinkSetupView.swift @@ -76,9 +76,19 @@ struct BlinkSetupView: View { .padding() .glassEffect(.regular, in: .rect(cornerRadius: 12)) - Text( - "You will be subtly reminded every \(intervalMinutes) minutes to blink" - ) + if enabled { + Text( + "You will be subtly reminded every \(intervalMinutes) minutes to blink" + ) + .font(.subheadline) + .foregroundColor(.secondary) + } else { + Text( + "Blink reminders are currently disabled." + ) + .font(.caption) + .foregroundColor(.secondary) + } Spacer() } diff --git a/Gaze/Views/Onboarding/CompletionView.swift b/Gaze/Views/Onboarding/CompletionView.swift index e36e6da..b7d4b5f 100644 --- a/Gaze/Views/Onboarding/CompletionView.swift +++ b/Gaze/Views/Onboarding/CompletionView.swift @@ -56,6 +56,15 @@ struct CompletionView: View { .font(.subheadline) } .padding(.horizontal) + + HStack(spacing: 16) { + Image(systemName: "plus.circle") + .foregroundColor(.accentColor) + .frame(width: 30) + Text("Create custom timers in Settings for additional reminders") + .font(.subheadline) + } + .padding(.horizontal) } .padding() .glassEffect(.regular, in: .rect(cornerRadius: 12)) diff --git a/Gaze/Views/Onboarding/LookAwaySetupView.swift b/Gaze/Views/Onboarding/LookAwaySetupView.swift index 0740633..406b0aa 100644 --- a/Gaze/Views/Onboarding/LookAwaySetupView.swift +++ b/Gaze/Views/Onboarding/LookAwaySetupView.swift @@ -93,9 +93,20 @@ struct LookAwaySetupView: View { .padding() .glassEffect(.regular, in: .rect(cornerRadius: 12)) - Text( - "You will be reminded every \(intervalMinutes) minutes to look in the distance for \(countdownSeconds) seconds" - ) + if enabled { + Text( + "You will be reminded every \(intervalMinutes) minutes to look in the distance for \(countdownSeconds) seconds" + ) + .font(.subheadline) + .foregroundColor(.secondary) + .multilineTextAlignment(.center) + } else { + Text( + "Look away reminders are currently disabled." + ) + .font(.caption) + .foregroundColor(.secondary) + } Spacer() } @@ -112,4 +123,3 @@ struct LookAwaySetupView: View { countdownSeconds: .constant(20) ) } - diff --git a/Gaze/Views/Onboarding/PostureSetupView.swift b/Gaze/Views/Onboarding/PostureSetupView.swift index 34d33f4..b6a51a2 100644 --- a/Gaze/Views/Onboarding/PostureSetupView.swift +++ b/Gaze/Views/Onboarding/PostureSetupView.swift @@ -76,9 +76,19 @@ struct PostureSetupView: View { .padding() .glassEffect(.regular, in: .rect(cornerRadius: 12)) - Text( - "You will be subtly reminded every \(intervalMinutes) minutes to check your posture" - ) + if enabled { + Text( + "You will be subtly reminded every \(intervalMinutes) minutes to check your posture" + ) + .font(.subheadline) + .foregroundColor(.secondary) + } else { + Text( + "Posture reminders are currently disabled." + ) + .font(.caption) + .foregroundColor(.secondary) + } Spacer() } diff --git a/Gaze/Views/Onboarding/WelcomeView.swift b/Gaze/Views/Onboarding/WelcomeView.swift index a0f27e5..acb3ed7 100644 --- a/Gaze/Views/Onboarding/WelcomeView.swift +++ b/Gaze/Views/Onboarding/WelcomeView.swift @@ -24,9 +24,18 @@ struct WelcomeView: View { .foregroundColor(.secondary) VStack(alignment: .leading, spacing: 16) { - FeatureRow(icon: "eye.circle", title: "Reduce Eye Strain", description: "Regular breaks help prevent digital eye strain") - FeatureRow(icon: "eye.trianglebadge.exclamationmark", title: "Remember to Blink", description: "We blink less when focused on screens") - FeatureRow(icon: "figure.stand", title: "Maintain Good Posture", description: "Gentle reminders to sit up straight") + FeatureRow( + icon: "eye.trianglebadge.exclamationmark", title: "Reduce Eye Strain", + description: "Regular breaks help prevent digital eye strain") + FeatureRow( + icon: "eye.circle", title: "Remember to Blink", + description: "We blink less when focused on screens") + FeatureRow( + icon: "figure.stand", title: "Maintain Good Posture", + description: "Gentle reminders to sit up straight") + FeatureRow( + icon: "plus.circle", title: "Custom Timers", + description: "Create your own timers for specific needs") } .padding() .glassEffect(.regular, in: .rect(cornerRadius: 12)) @@ -44,11 +53,20 @@ struct FeatureRow: View { let title: String let description: String + private var iconColor: Color { + switch icon { + case "eye.trianglebadge.exclamationmark": return .accentColor + case "eye.circle": return .green + case "figure.stand": return .orange + default: return .primary + } + } + var body: some View { HStack(alignment: .top, spacing: 16) { Image(systemName: icon) .font(.title2) - .foregroundColor(.accentColor) + .foregroundColor(iconColor) .frame(width: 30) VStack(alignment: .leading, spacing: 4) { diff --git a/Gaze/Views/Reminders/BlinkReminderView.swift b/Gaze/Views/Reminders/BlinkReminderView.swift index 800e2ad..e6c64e9 100644 --- a/Gaze/Views/Reminders/BlinkReminderView.swift +++ b/Gaze/Views/Reminders/BlinkReminderView.swift @@ -17,6 +17,8 @@ struct BlinkReminderView: View { private let screenHeight = NSScreen.main?.frame.height ?? 800 private let screenWidth = NSScreen.main?.frame.width ?? 1200 + // For now, we'll use hardcoded size but leave framework for configuration + // In a real implementation, this would be passed in from SettingsManager var body: some View { VStack { LottieView(