From 4b3a1f99c91572e54caf6d00b6e68bc9efc5b5a7 Mon Sep 17 00:00:00 2001 From: Michael Freno Date: Thu, 8 Jan 2026 16:43:34 -0500 Subject: [PATCH] general: conform reminder pages --- Gaze/Views/Components/InfoBox.swift | 43 +++++++ Gaze/Views/Onboarding/BlinkSetupView.swift | 56 ++++++--- Gaze/Views/Onboarding/LookAwaySetupView.swift | 108 +++++++++--------- Gaze/Views/Onboarding/PostureSetupView.swift | 56 ++++++--- 4 files changed, 179 insertions(+), 84 deletions(-) create mode 100644 Gaze/Views/Components/InfoBox.swift diff --git a/Gaze/Views/Components/InfoBox.swift b/Gaze/Views/Components/InfoBox.swift new file mode 100644 index 0000000..859ea26 --- /dev/null +++ b/Gaze/Views/Components/InfoBox.swift @@ -0,0 +1,43 @@ +// +// InfoBox.swift +// Gaze +// +// Created by Mike Freno on 1/8/26. +// + +import SwiftUI + +struct InfoBox: View { + let text: String + let url: String? + + var body: some View { + HStack(spacing: 12) { + if let url = url, let urlObj = URL(string: url) { + Button(action: { + #if os(iOS) + UIApplication.shared.open(urlObj) + #elseif os(macOS) + NSWorkspace.shared.open(urlObj) + #endif + }) { + Image(systemName: "info.circle") + .foregroundColor(.white) + }.buttonStyle(.plain) + } else { + Image(systemName: "info.circle") + .foregroundColor(.white) + } + Text(text) + .font(.headline) + .foregroundColor(.white) + } + .padding() + .glassEffect(.regular.tint(.blue), in: .rect(cornerRadius: 8)) + } +} + +#Preview { + InfoBox(text: "This is an informational message that provides helpful context to the user.", url: "https://www.healthline.com/health/eye-health/20-20-20-rule") + .padding() +} \ No newline at end of file diff --git a/Gaze/Views/Onboarding/BlinkSetupView.swift b/Gaze/Views/Onboarding/BlinkSetupView.swift index a9efbb6..960dc15 100644 --- a/Gaze/Views/Onboarding/BlinkSetupView.swift +++ b/Gaze/Views/Onboarding/BlinkSetupView.swift @@ -10,36 +10,62 @@ import SwiftUI struct BlinkSetupView: View { @Binding var enabled: Bool @Binding var intervalMinutes: Int - + var body: some View { VStack(spacing: 30) { Image(systemName: "eye.circle") .font(.system(size: 60)) .foregroundColor(.green) - + Text("Blink Reminder") .font(.system(size: 28, weight: .bold)) - + Text("Keep your eyes hydrated") .font(.title3) .foregroundColor(.secondary) - + + // InfoBox with link functionality + HStack(spacing: 12) { + Button(action: { + if let url = URL( + string: "https://www.healthline.com/health/eye-health/eye-strain#symptoms") + { + #if os(iOS) + UIApplication.shared.open(url) + #elseif os(macOS) + NSWorkspace.shared.open(url) + #endif + } + }) { + Image(systemName: "info.circle") + .foregroundColor(.white) + }.buttonStyle(.plain) + Text( + "We blink much less when focusing on screens. Regular blink reminders help prevent dry eyes" + ) + .font(.headline) + .foregroundColor(.white) + } + .padding() + .glassEffect(.regular.tint(.blue), in: .rect(cornerRadius: 8)) + VStack(alignment: .leading, spacing: 20) { Toggle("Enable Blink Reminders", isOn: $enabled) .font(.headline) - + if enabled { VStack(alignment: .leading, spacing: 12) { Text("Remind me every:") .font(.subheadline) .foregroundColor(.secondary) - + HStack { - Slider(value: Binding( - get: { Double(intervalMinutes) }, - set: { intervalMinutes = Int($0) } - ), in: 1...15, step: 1) - + Slider( + value: Binding( + get: { Double(intervalMinutes) }, + set: { intervalMinutes = Int($0) } + ), in: 1...15, step: 1) + Text("\(intervalMinutes) min") .frame(width: 60, alignment: .trailing) .monospacedDigit() @@ -49,9 +75,11 @@ struct BlinkSetupView: View { } .padding() .glassEffect(.regular, in: .rect(cornerRadius: 12)) - - InfoBox(text: "We blink much less when focusing on screens. Regular blink reminders help prevent dry eyes") - + + Text( + "You will be subtly reminded every \(intervalMinutes) minutes to blink" + ) + Spacer() } .frame(width: 600, height: 450) diff --git a/Gaze/Views/Onboarding/LookAwaySetupView.swift b/Gaze/Views/Onboarding/LookAwaySetupView.swift index d3780d6..55175be 100644 --- a/Gaze/Views/Onboarding/LookAwaySetupView.swift +++ b/Gaze/Views/Onboarding/LookAwaySetupView.swift @@ -6,59 +6,83 @@ // import SwiftUI + #if os(iOS) -import UIKit -#elseif os(macOS) -import AppKit + import UIKit +#else + import AppKit #endif struct LookAwaySetupView: View { @Binding var enabled: Bool @Binding var intervalMinutes: Int @Binding var countdownSeconds: Int - + var body: some View { VStack(spacing: 30) { Image(systemName: "eye.fill") .font(.system(size: 60)) .foregroundColor(.blue) - + Text("Look Away Reminder") .font(.system(size: 28, weight: .bold)) - - InfoBox(text: "Suggested: 20-20-20 rule") - + + // InfoBox with link functionality + HStack(spacing: 12) { + Button(action: { + if let url = URL( + string: "https://www.healthline.com/health/eye-health/20-20-20-rule") + { + #if os(iOS) + UIApplication.shared.open(url) + #elseif os(macOS) + NSWorkspace.shared.open(url) + #endif + } + }) { + Image(systemName: "info.circle") + .foregroundColor(.white) + }.buttonStyle(.plain) + Text("Suggested: 20-20-20 rule") + .font(.headline) + .foregroundColor(.white) + } + .padding() + .glassEffect(.regular.tint(.blue), in: .rect(cornerRadius: 8)) + VStack(alignment: .leading, spacing: 20) { Toggle("Enable Look Away Reminders", isOn: $enabled) .font(.headline) - + if enabled { VStack(alignment: .leading, spacing: 12) { Text("Remind me every:") .font(.subheadline) .foregroundColor(.secondary) - + HStack { - Slider(value: Binding( - get: { Double(intervalMinutes) }, - set: { intervalMinutes = Int($0) } - ), in: 5...60, step: 5) - + Slider( + value: Binding( + get: { Double(intervalMinutes) }, + set: { intervalMinutes = Int($0) } + ), in: 5...60, step: 5) + Text("\(intervalMinutes) min") .frame(width: 60, alignment: .trailing) .monospacedDigit() } - - Text("Look away for:") + + Text("Look away for:") .font(.subheadline) .foregroundColor(.secondary) - + HStack { - Slider(value: Binding( - get: { Double(countdownSeconds) }, - set: { countdownSeconds = Int($0) } - ), in: 10...30, step: 5) - + Slider( + value: Binding( + get: { Double(countdownSeconds) }, + set: { countdownSeconds = Int($0) } + ), in: 10...30, step: 5) + Text("\(countdownSeconds) sec") .frame(width: 60, alignment: .trailing) .monospacedDigit() @@ -68,9 +92,11 @@ 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") - + + Text( + "You will be reminded every \(intervalMinutes) minutes to look in the distance for \(countdownSeconds) seconds" + ) + Spacer() } .frame(width: 600, height: 450) @@ -79,32 +105,6 @@ struct LookAwaySetupView: View { } } -struct InfoBox: View { - let text: String - - var body: some View { - HStack(spacing: 12) { - Button(action: { - if let url = URL(string: "https://www.healthline.com/health/eye-health/20-20-20-rule") { - #if os(iOS) - UIApplication.shared.open(url) - #elseif os(macOS) - NSWorkspace.shared.open(url) - #endif - } - }) { - Image(systemName: "info.circle") - .foregroundColor(.white) - }.buttonStyle(.plain) - Text(text) - .font(.headline) - .foregroundColor(.white) - } - .padding() - .glassEffect(.regular.tint(.blue), in: .rect(cornerRadius: 8)) - } -} - #Preview("Look Away Setup View") { LookAwaySetupView( enabled: .constant(true), @@ -113,7 +113,3 @@ struct InfoBox: View { ) } -#Preview("Info Box") { - InfoBox(text: "This is an informational message that provides helpful context to the user.") - .padding() -} diff --git a/Gaze/Views/Onboarding/PostureSetupView.swift b/Gaze/Views/Onboarding/PostureSetupView.swift index 9a96fcd..e39eb9e 100644 --- a/Gaze/Views/Onboarding/PostureSetupView.swift +++ b/Gaze/Views/Onboarding/PostureSetupView.swift @@ -10,36 +10,62 @@ import SwiftUI struct PostureSetupView: View { @Binding var enabled: Bool @Binding var intervalMinutes: Int - + var body: some View { VStack(spacing: 30) { Image(systemName: "figure.stand") .font(.system(size: 60)) .foregroundColor(.orange) - + Text("Posture Reminder") .font(.system(size: 28, weight: .bold)) - + Text("Maintain proper ergonomics") .font(.title3) .foregroundColor(.secondary) - + + // InfoBox with link functionality + HStack(spacing: 12) { + Button(action: { + if let url = URL( + string: "https://www.healthline.com/health/ergonomic-workspace") + { + #if os(iOS) + UIApplication.shared.open(url) + #elseif os(macOS) + NSWorkspace.shared.open(url) + #endif + } + }) { + Image(systemName: "info.circle") + .foregroundColor(.white) + }.buttonStyle(.plain) + Text( + "Regular posture checks help prevent back and neck pain from prolonged sitting" + ) + .font(.headline) + .foregroundColor(.white) + } + .padding() + .glassEffect(.regular.tint(.blue), in: .rect(cornerRadius: 8)) + VStack(alignment: .leading, spacing: 20) { Toggle("Enable Posture Reminders", isOn: $enabled) .font(.headline) - + if enabled { VStack(alignment: .leading, spacing: 12) { Text("Remind me every:") .font(.subheadline) .foregroundColor(.secondary) - + HStack { - Slider(value: Binding( - get: { Double(intervalMinutes) }, - set: { intervalMinutes = Int($0) } - ), in: 15...60, step: 5) - + Slider( + value: Binding( + get: { Double(intervalMinutes) }, + set: { intervalMinutes = Int($0) } + ), in: 15...60, step: 5) + Text("\(intervalMinutes) min") .frame(width: 60, alignment: .trailing) .monospacedDigit() @@ -49,9 +75,11 @@ struct PostureSetupView: View { } .padding() .glassEffect(.regular, in: .rect(cornerRadius: 12)) - - InfoBox(text: "Regular posture checks help prevent back and neck pain from prolonged sitting") - + + Text( + "You will be subtly reminded every \(intervalMinutes) minutes to check your posture" + ) + Spacer() } .frame(width: 600, height: 450)