feat: better clarity for disabled reminders, continued prev commit work
This commit is contained in:
1
Gaze/Animations/ring.json
Normal file
1
Gaze/Animations/ring.json
Normal 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": [] }
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
Reference in New Issue
Block a user