feat: better clarity for disabled reminders, continued prev commit work

This commit is contained in:
Michael Freno
2026-01-09 13:13:07 -05:00
parent b8f995b2e9
commit 63dde81b97
10 changed files with 99 additions and 15 deletions

View File

@@ -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": [] }

View File

@@ -11,6 +11,7 @@ enum AnimationAsset: String {
case blink = "blink" case blink = "blink"
case lookAway = "look-away" case lookAway = "look-away"
case posture = "posture" case posture = "posture"
case ring = "ring"
var fileName: String { var fileName: String {
return self.rawValue return self.rawValue

View File

@@ -28,6 +28,29 @@ struct AppSettings: Codable, Equatable {
var launchAtLogin: Bool var launchAtLogin: Bool
var playSounds: 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 { static var defaults: AppSettings {
AppSettings( AppSettings(
lookAwayTimer: TimerConfiguration(enabled: true, intervalSeconds: 20 * 60), lookAwayTimer: TimerConfiguration(enabled: true, intervalSeconds: 20 * 60),

View File

@@ -30,7 +30,7 @@ struct MenuBarHoverButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View { func makeBody(configuration: Configuration) -> some View {
configuration.label configuration.label
.glassEffect( .glassEffect(
isHovered ? .regular.tint(.accentColor).interactive() : .regular, isHovered ? .regular.tint(.accentColor.opacity(0.5)).interactive() : .regular,
in: .rect(cornerRadius: 6) in: .rect(cornerRadius: 6)
) )
.contentShape(Rectangle()) .contentShape(Rectangle())

View File

@@ -76,9 +76,19 @@ struct BlinkSetupView: View {
.padding() .padding()
.glassEffect(.regular, in: .rect(cornerRadius: 12)) .glassEffect(.regular, in: .rect(cornerRadius: 12))
if enabled {
Text( Text(
"You will be subtly reminded every \(intervalMinutes) minutes to blink" "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() Spacer()
} }

View File

@@ -56,6 +56,15 @@ struct CompletionView: View {
.font(.subheadline) .font(.subheadline)
} }
.padding(.horizontal) .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() .padding()
.glassEffect(.regular, in: .rect(cornerRadius: 12)) .glassEffect(.regular, in: .rect(cornerRadius: 12))

View File

@@ -93,9 +93,20 @@ struct LookAwaySetupView: View {
.padding() .padding()
.glassEffect(.regular, in: .rect(cornerRadius: 12)) .glassEffect(.regular, in: .rect(cornerRadius: 12))
if enabled {
Text( Text(
"You will be reminded every \(intervalMinutes) minutes to look in the distance for \(countdownSeconds) seconds" "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() Spacer()
} }
@@ -112,4 +123,3 @@ struct LookAwaySetupView: View {
countdownSeconds: .constant(20) countdownSeconds: .constant(20)
) )
} }

View File

@@ -76,9 +76,19 @@ struct PostureSetupView: View {
.padding() .padding()
.glassEffect(.regular, in: .rect(cornerRadius: 12)) .glassEffect(.regular, in: .rect(cornerRadius: 12))
if enabled {
Text( Text(
"You will be subtly reminded every \(intervalMinutes) minutes to check your posture" "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() Spacer()
} }

View File

@@ -24,9 +24,18 @@ struct WelcomeView: View {
.foregroundColor(.secondary) .foregroundColor(.secondary)
VStack(alignment: .leading, spacing: 16) { VStack(alignment: .leading, spacing: 16) {
FeatureRow(icon: "eye.circle", title: "Reduce Eye Strain", description: "Regular breaks help prevent digital eye strain") FeatureRow(
FeatureRow(icon: "eye.trianglebadge.exclamationmark", title: "Remember to Blink", description: "We blink less when focused on screens") icon: "eye.trianglebadge.exclamationmark", title: "Reduce Eye Strain",
FeatureRow(icon: "figure.stand", title: "Maintain Good Posture", description: "Gentle reminders to sit up straight") 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() .padding()
.glassEffect(.regular, in: .rect(cornerRadius: 12)) .glassEffect(.regular, in: .rect(cornerRadius: 12))
@@ -44,11 +53,20 @@ struct FeatureRow: View {
let title: String let title: String
let description: 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 { var body: some View {
HStack(alignment: .top, spacing: 16) { HStack(alignment: .top, spacing: 16) {
Image(systemName: icon) Image(systemName: icon)
.font(.title2) .font(.title2)
.foregroundColor(.accentColor) .foregroundColor(iconColor)
.frame(width: 30) .frame(width: 30)
VStack(alignment: .leading, spacing: 4) { VStack(alignment: .leading, spacing: 4) {

View File

@@ -17,6 +17,8 @@ struct BlinkReminderView: View {
private let screenHeight = NSScreen.main?.frame.height ?? 800 private let screenHeight = NSScreen.main?.frame.height ?? 800
private let screenWidth = NSScreen.main?.frame.width ?? 1200 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 { var body: some View {
VStack { VStack {
LottieView( LottieView(