diff --git a/Gaze/AppDelegate.swift b/Gaze/AppDelegate.swift index b2ef003..c572564 100644 --- a/Gaze/AppDelegate.swift +++ b/Gaze/AppDelegate.swift @@ -14,55 +14,40 @@ class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject { @Published var timerEngine: TimerEngine? private let settingsManager: SettingsManager = .shared private var updateManager: UpdateManager? - private var reminderWindowController: NSWindowController? + private var overlayReminderWindowController: NSWindowController? + private var subtleReminderWindowController: NSWindowController? private var settingsWindowController: NSWindowController? private var cancellables = Set() private var hasStartedTimers = false func applicationDidFinishLaunching(_ notification: Notification) { - print("πŸš€ Gaze: applicationDidFinishLaunching") - // Set activation policy to hide dock icon NSApplication.shared.setActivationPolicy(.accessory) - print("βœ“ Activation policy set to accessory") timerEngine = TimerEngine(settingsManager: settingsManager) - print("βœ“ TimerEngine initialized") // Initialize update manager after onboarding is complete if settingsManager.settings.hasCompletedOnboarding { - print("βœ“ Onboarding completed, initializing UpdateManager") updateManager = UpdateManager.shared - } else { - print("ℹ️ Onboarding not completed, skipping UpdateManager") } // Detect App Store version asynchronously at launch Task { do { - print("πŸ” Detecting App Store version...") await settingsManager.detectAppStoreVersion() - print("βœ“ App Store detection complete: \(settingsManager.settings.isAppStoreVersion)") } catch { - print("⚠️ Failed to detect App Store version: \(error)") + // Handle error silently in production } } setupLifecycleObservers() - print("βœ“ Lifecycle observers set up") observeSettingsChanges() - print("βœ“ Settings change observer set up") // Start timers if onboarding is complete if settingsManager.settings.hasCompletedOnboarding { - print("▢️ Starting timers (onboarding complete)") startTimers() - } else { - print("⏸️ Timers not started (onboarding incomplete)") } - - print("βœ… Gaze: Launch complete") } func onboardingCompleted() { @@ -130,7 +115,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject { timerEngine?.$activeReminder .sink { [weak self] reminder in guard let reminder = reminder else { - self?.dismissReminder() + self?.dismissOverlayReminder() return } self?.showReminder(reminder) @@ -185,10 +170,10 @@ class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject { } } - showReminderWindow(contentView, requiresFocus: requiresFocus) + showReminderWindow(contentView, requiresFocus: requiresFocus, isOverlay: requiresFocus) } - private func showReminderWindow(_ content: AnyView, requiresFocus: Bool) { + private func showReminderWindow(_ content: AnyView, requiresFocus: Bool, isOverlay: Bool) { guard let screen = NSScreen.main else { return } let window: NSWindow @@ -229,12 +214,24 @@ class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject { window.orderFront(nil) } - reminderWindowController = windowController + // Track overlay and subtle reminders separately + if isOverlay { + overlayReminderWindowController?.close() + overlayReminderWindowController = windowController + } else { + subtleReminderWindowController?.close() + subtleReminderWindowController = windowController + } } - private func dismissReminder() { - reminderWindowController?.close() - reminderWindowController = nil + private func dismissOverlayReminder() { + overlayReminderWindowController?.close() + overlayReminderWindowController = nil + } + + private func dismissSubtleReminder() { + subtleReminderWindowController?.close() + subtleReminderWindowController = nil } // Public method to open settings window diff --git a/Gaze/GazeApp.swift b/Gaze/GazeApp.swift index d89c064..d8f7e37 100644 --- a/Gaze/GazeApp.swift +++ b/Gaze/GazeApp.swift @@ -13,18 +13,12 @@ struct GazeApp: App { @StateObject private var settingsManager = SettingsManager.shared init() { - print("πŸš€ GazeApp: init") - // Handle test launch arguments if TestingEnvironment.shouldSkipOnboarding { - print("ℹ️ Test mode: Skipping onboarding") SettingsManager.shared.settings.hasCompletedOnboarding = true } else if TestingEnvironment.shouldResetOnboarding { - print("ℹ️ Test mode: Resetting onboarding") SettingsManager.shared.settings.hasCompletedOnboarding = false } - - print("βœ“ GazeApp initialized") } var body: some Scene { diff --git a/Gaze/Services/AppStoreDetector.swift b/Gaze/Services/AppStoreDetector.swift index a6ced7c..e906b47 100644 --- a/Gaze/Services/AppStoreDetector.swift +++ b/Gaze/Services/AppStoreDetector.swift @@ -17,53 +17,38 @@ enum AppStoreDetector { /// This method is asynchronous due to the use of StoreKit's async API. static func isAppStoreVersion() async -> Bool { #if DEBUG - print("πŸ” AppStoreDetector: DEBUG build, returning false") return false #else - print("πŸ” AppStoreDetector: Checking App Store status...") if #available(macOS 15.0, *) { - print(" ℹ️ Using macOS 15+ AppTransaction API") do { let transaction = try await AppTransaction.shared - print(" βœ… AppTransaction found: This is an App Store version") return true } catch { - print(" ⚠️ AppTransaction error: \(error.localizedDescription)") - print(" β†’ Assuming NOT an App Store version") return false } } else { // Fallback for older macOS: use legacy receipt check - print(" ℹ️ Using legacy receipt check (macOS <15)") guard let receiptURL = Bundle.main.appStoreReceiptURL else { - print(" ⚠️ No receipt URL available") return false } - print(" πŸ“„ Receipt URL: \(receiptURL.path)") do { let fileExists = FileManager.default.fileExists(atPath: receiptURL.path) guard fileExists else { - print(" ⚠️ Receipt file does not exist") return false } - print(" βœ“ Receipt file exists") guard let receiptData = try? Data(contentsOf: receiptURL), receiptData.count > 2 else { - print(" ⚠️ Receipt file is empty or unreadable") return false } - print(" βœ“ Receipt data loaded (\(receiptData.count) bytes)") let bytes = [UInt8](receiptData.prefix(2)) let isValid = bytes[0] == 0x30 && bytes[1] == 0x82 - print(" \(isValid ? "βœ…" : "⚠️") Receipt validation: \(isValid)") return isValid } catch { - print(" ❌ Receipt check error: \(error.localizedDescription)") return false } } diff --git a/Gaze/Services/SettingsManager.swift b/Gaze/Services/SettingsManager.swift index 15f4d32..387b0f1 100644 --- a/Gaze/Services/SettingsManager.swift +++ b/Gaze/Services/SettingsManager.swift @@ -27,9 +27,6 @@ class SettingsManager: ObservableObject { private init() { self.settings = Self.loadSettings() - #if DEBUG - validateTimerConfigMappings() - #endif setupDebouncedSave() } @@ -49,34 +46,13 @@ class SettingsManager: ObservableObject { private static func loadSettings() -> AppSettings { guard let data = UserDefaults.standard.data(forKey: "gazeAppSettings") else { - #if DEBUG - print("ℹ️ No saved settings found, using defaults") - #endif return .defaults } do { let settings = try JSONDecoder().decode(AppSettings.self, from: data) - #if DEBUG - print("βœ… Settings loaded successfully (\(data.count) bytes)") - #endif return settings } catch { - print("⚠️ Failed to decode settings, using defaults: \(error.localizedDescription)") - if let decodingError = error as? DecodingError { - switch decodingError { - case .keyNotFound(let key, let context): - print(" Missing key: \(key.stringValue) at path: \(context.codingPath)") - case .typeMismatch(let type, let context): - print(" Type mismatch for type: \(type) at path: \(context.codingPath)") - case .valueNotFound(let type, let context): - print(" Value not found for type: \(type) at path: \(context.codingPath)") - case .dataCorrupted(let context): - print(" Data corrupted at path: \(context.codingPath)") - @unknown default: - print(" Unknown decoding error: \(decodingError)") - } - } return .defaults } } @@ -90,20 +66,7 @@ class SettingsManager: ObservableObject { encoder.outputFormatting = .prettyPrinted let data = try encoder.encode(settings) userDefaults.set(data, forKey: settingsKey) - - #if DEBUG - print("βœ… Settings saved successfully (\(data.count) bytes)") - #endif } catch { - print("❌ Failed to encode settings: \(error.localizedDescription)") - if let encodingError = error as? EncodingError { - switch encodingError { - case .invalidValue(let value, let context): - print(" Invalid value: \(value) at path: \(context.codingPath)") - default: - print(" Encoding error: \(encodingError)") - } - } } } diff --git a/Gaze/Services/UpdateManager.swift b/Gaze/Services/UpdateManager.swift index 0e8b351..0b1a785 100644 --- a/Gaze/Services/UpdateManager.swift +++ b/Gaze/Services/UpdateManager.swift @@ -40,7 +40,6 @@ class UpdateManager: NSObject, ObservableObject { ) guard let updater = updaterController?.updater else { - print("Failed to initialize Sparkle updater") return } @@ -69,12 +68,10 @@ class UpdateManager: NSObject, ObservableObject { func checkForUpdates() { #if !APPSTORE guard let updater = updaterController?.updater else { - print("Updater not initialized") return } updater.checkForUpdates() #else - print("Updates are managed by the App Store") #endif } diff --git a/Gaze/Views/Setup/GeneralSetupView.swift b/Gaze/Views/Setup/GeneralSetupView.swift index 961a49b..3b9d7a9 100644 --- a/Gaze/Views/Setup/GeneralSetupView.swift +++ b/Gaze/Views/Setup/GeneralSetupView.swift @@ -225,7 +225,7 @@ struct GeneralSetupView: View { try LaunchAtLoginManager.disable() } } catch { - print("Failed to set launch at login: \(error)") + // Failed to set launch at login - handled silently in production } }