From 7cae818d2d02596b918eb33a6c468e3e561d4960 Mon Sep 17 00:00:00 2001 From: Michael Freno Date: Thu, 8 Jan 2026 21:57:31 -0500 Subject: [PATCH] general: text swap and attempt for menu item fix --- Gaze/AppDelegate.swift | 18 +++-- Gaze/Views/MenuBar/MenuBarContentView.swift | 63 ++++++++-------- .../Onboarding/OnboardingContainerView.swift | 3 +- .../Onboarding/SettingsOnboardingView.swift | 9 ++- Gaze/Views/Reminders/BlinkReminderView.swift | 71 +++++-------------- Gaze/Views/SettingsWindowView.swift | 3 +- 6 files changed, 71 insertions(+), 96 deletions(-) diff --git a/Gaze/AppDelegate.swift b/Gaze/AppDelegate.swift index cebe1a3..06dc1c4 100644 --- a/Gaze/AppDelegate.swift +++ b/Gaze/AppDelegate.swift @@ -61,10 +61,16 @@ class AppDelegate: NSObject, NSApplicationDelegate { } private func showPopover() { - let popover = NSPopover() - popover.contentSize = NSSize(width: 300, height: 400) - popover.behavior = .transient - popover.contentViewController = NSHostingController( + // Reuse existing popover or create new one + if popover == nil { + let newPopover = NSPopover() + newPopover.contentSize = NSSize(width: 300, height: 400) + newPopover.behavior = .transient + popover = newPopover + } + + // Always set fresh content + popover?.contentViewController = NSHostingController( rootView: MenuBarContentView( timerEngine: timerEngine!, settingsManager: settingsManager!, @@ -74,10 +80,8 @@ class AppDelegate: NSObject, NSApplicationDelegate { ) if let button = statusItem?.button { - popover.show(relativeTo: button.bounds, of: button, preferredEdge: .minY) + popover?.show(relativeTo: button.bounds, of: button, preferredEdge: .minY) } - - self.popover = popover } private func startTimers() { diff --git a/Gaze/Views/MenuBar/MenuBarContentView.swift b/Gaze/Views/MenuBar/MenuBarContentView.swift index 2efee63..35a214d 100644 --- a/Gaze/Views/MenuBar/MenuBarContentView.swift +++ b/Gaze/Views/MenuBar/MenuBarContentView.swift @@ -14,7 +14,8 @@ struct MenuBarButtonStyle: ButtonStyle { .background( RoundedRectangle(cornerRadius: 6) .fill( - configuration.isPressed ? Color.accentColor.opacity(0.2) : Color.gray.opacity(0.1) + configuration.isPressed + ? Color.accentColor.opacity(0.2) : Color.gray.opacity(0.1) ) .opacity(configuration.isPressed ? 1 : 0) ) @@ -28,9 +29,9 @@ struct MenuBarHoverButtonStyle: ButtonStyle { func makeBody(configuration: Configuration) -> some View { configuration.label - .background( - RoundedRectangle(cornerRadius: 6) - .fill(isHovered ? Color.accentColor.opacity(0.35) : Color.clear) + .glassEffect( + isHovered ? .regular.tint(.accentColor).interactive() : .regular, + in: .rect(cornerRadius: 6) ) .contentShape(Rectangle()) .onHover { hovering in @@ -180,23 +181,23 @@ struct TimerStatusRow: View { Spacer() #if DEBUG - if let onDevTrigger = onDevTrigger { - Button(action: onDevTrigger) { - Image(systemName: "bolt.fill") - .font(.caption) - .foregroundColor(.yellow) - .padding(6) - .background( - Circle() - .fill(isHoveredDevTrigger ? Color.yellow.opacity(0.35) : Color.clear) - ) + if let onDevTrigger = onDevTrigger { + Button(action: onDevTrigger) { + Image(systemName: "bolt.fill") + .font(.caption) + .foregroundColor(.yellow) + .padding(6) + } + .buttonStyle(.plain) + .glassEffect( + isHoveredDevTrigger ? .regular.tint(.yellow) : .regular, + in: .circle + ) + .help("Trigger \(type.displayName) reminder now (dev)") + .onHover { hovering in + isHoveredDevTrigger = hovering + } } - .buttonStyle(.plain) - .help("Trigger \(type.displayName) reminder now (dev)") - .onHover { hovering in - isHoveredDevTrigger = hovering - } - } #endif Button(action: onSkip) { @@ -204,25 +205,27 @@ struct TimerStatusRow: View { .font(.caption) .foregroundColor(.accentColor) .padding(6) - .background( - Circle() - .fill(isHoveredSkip ? Color.accentColor.opacity(0.35) : Color.clear) - ) } .buttonStyle(.plain) + .glassEffect( + isHoveredSkip ? .regular.tint(.accentColor) : .regular, + in: .circle + ) .help("Skip to next \(type.displayName) reminder") .onHover { hovering in isHoveredSkip = hovering } } + .padding(.horizontal, 8) + .padding(.vertical, 6) + .glassEffect( + isHoveredBody ? .regular.tint(.accentColor) : .regular, + in: .rect(cornerRadius: 6) + ) + .padding(.horizontal, 8) .onHover { hovering in isHoveredBody = hovering - }.background( - RoundedRectangle(cornerRadius: 6).fill( - isHoveredBody ? Color.accentColor.opacity(0.35) : Color.clear) - ) - .padding(.horizontal) - .padding(.vertical, 4) + } } private var iconColor: Color { diff --git a/Gaze/Views/Onboarding/OnboardingContainerView.swift b/Gaze/Views/Onboarding/OnboardingContainerView.swift index 013941e..e291eb8 100644 --- a/Gaze/Views/Onboarding/OnboardingContainerView.swift +++ b/Gaze/Views/Onboarding/OnboardingContainerView.swift @@ -74,7 +74,8 @@ struct OnboardingContainerView: View { } SettingsOnboardingView( - launchAtLogin: $launchAtLogin + launchAtLogin: $launchAtLogin, + isOnboarding: true ) .tag(4) .tabItem { diff --git a/Gaze/Views/Onboarding/SettingsOnboardingView.swift b/Gaze/Views/Onboarding/SettingsOnboardingView.swift index 7bdca93..44d8910 100644 --- a/Gaze/Views/Onboarding/SettingsOnboardingView.swift +++ b/Gaze/Views/Onboarding/SettingsOnboardingView.swift @@ -9,6 +9,7 @@ import SwiftUI struct SettingsOnboardingView: View { @Binding var launchAtLogin: Bool + var isOnboarding: Bool = true var body: some View { VStack(spacing: 30) { @@ -18,7 +19,7 @@ struct SettingsOnboardingView: View { .font(.system(size: 80)) .foregroundColor(.accentColor) - Text("Final Settings") + Text(isOnboarding ? "Final Settings" : "General Settings") .font(.system(size: 36, weight: .bold)) Text("Configure app preferences and support the project") @@ -135,12 +136,14 @@ struct SettingsOnboardingView: View { #Preview("Settings Onboarding - Launch Disabled") { SettingsOnboardingView( - launchAtLogin: .constant(false) + launchAtLogin: .constant(false), + isOnboarding: true ) } #Preview("Settings Onboarding - Launch Enabled") { SettingsOnboardingView( - launchAtLogin: .constant(true) + launchAtLogin: .constant(true), + isOnboarding: true ) } diff --git a/Gaze/Views/Reminders/BlinkReminderView.swift b/Gaze/Views/Reminders/BlinkReminderView.swift index 829a559..fed942d 100644 --- a/Gaze/Views/Reminders/BlinkReminderView.swift +++ b/Gaze/Views/Reminders/BlinkReminderView.swift @@ -11,9 +11,13 @@ struct BlinkReminderView: View { var onDismiss: () -> Void @State private var opacity: Double = 0 + @State private var scale: CGFloat = 0 @State private var blinkState: BlinkState = .open @State private var blinkCount = 0 + private let screenHeight = NSScreen.main?.frame.height ?? 800 + private let screenWidth = NSScreen.main?.frame.width ?? 1200 + enum BlinkState { case open case closed @@ -21,37 +25,35 @@ struct BlinkReminderView: View { var body: some View { VStack { - RoundedRectangle(cornerRadius: 20) - .fill(Color.white) - .shadow(color: .black.opacity(0.3), radius: 10, x: 0, y: 5) - .frame(width: 100, height: 100) - .overlay( - BlinkingFace(isOpen: blinkState == .open) - ) + Image(systemName: blinkState == .open ? "eye.circle" : "eye.slash.circle") + .font(.system(size: scale)) + .foregroundColor(.accentColor) + .shadow(color: .black.opacity(0.2), radius: 5, x: 0, y: 2) } .opacity(opacity) .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) - .padding(.top, NSScreen.main?.frame.height ?? 800 * 0.1) + .padding(.top, screenHeight * 0.1) .onAppear { startAnimation() } } private func startAnimation() { - // Fade in - withAnimation(.easeIn(duration: 0.3)) { + // Fade in and grow + withAnimation(.easeOut(duration: 0.3)) { opacity = 1.0 + scale = screenWidth * 0.1 } // Start blinking after fade in - DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) { performBlinks() } } private func performBlinks() { - let blinkDuration = 0.1 - let pauseBetweenBlinks = 0.5 + let blinkDuration = 0.15 + let pauseBetweenBlinks = 0.2 func blink() { // Close eyes @@ -67,7 +69,7 @@ struct BlinkReminderView: View { blinkCount += 1 - if blinkCount < 3 { + if blinkCount < 2 { // Pause before next blink DispatchQueue.main.asyncAfter(deadline: .now() + pauseBetweenBlinks) { blink() @@ -87,6 +89,7 @@ struct BlinkReminderView: View { private func fadeOut() { withAnimation(.easeOut(duration: 0.3)) { opacity = 0 + scale = screenWidth * 0.05 } DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { @@ -95,46 +98,6 @@ struct BlinkReminderView: View { } } -struct BlinkingFace: View { - let isOpen: Bool - - var body: some View { - ZStack { - // Simple face - Circle() - .fill(Color.yellow) - .frame(width: 60, height: 60) - - // Eyes - HStack(spacing: 12) { - if isOpen { - Circle() - .fill(Color.black) - .frame(width: 8, height: 8) - Circle() - .fill(Color.black) - .frame(width: 8, height: 8) - } else { - // Closed eyes (lines) - Rectangle() - .fill(Color.black) - .frame(width: 10, height: 2) - Rectangle() - .fill(Color.black) - .frame(width: 10, height: 2) - } - } - .offset(y: -8) - - // Smile - Arc(startAngle: .degrees(20), endAngle: .degrees(160), clockwise: false) - .stroke(Color.black, lineWidth: 2) - .frame(width: 30, height: 15) - .offset(y: 10) - } - } -} - #Preview("Blink Reminder") { BlinkReminderView(onDismiss: {}) .frame(width: 800, height: 600) diff --git a/Gaze/Views/SettingsWindowView.swift b/Gaze/Views/SettingsWindowView.swift index af09e1b..2696964 100644 --- a/Gaze/Views/SettingsWindowView.swift +++ b/Gaze/Views/SettingsWindowView.swift @@ -64,7 +64,8 @@ struct SettingsWindowView: View { } SettingsOnboardingView( - launchAtLogin: $launchAtLogin + launchAtLogin: $launchAtLogin, + isOnboarding: false ) .tag(3) .tabItem {