From 44a8f40a2781b3b060fb58435efda241176a4c76 Mon Sep 17 00:00:00 2001 From: Michael Freno Date: Fri, 30 Jan 2026 01:09:08 -0500 Subject: [PATCH] cleaning up concurrency warnings --- Gaze/Models/PauseReason.swift | 2 + Gaze/Protocols/EnforceModeProviding.swift | 1 - Gaze/Protocols/SettingsProviding.swift | 2 - Gaze/Protocols/SmartModeProviding.swift | 2 - Gaze/Protocols/TimerEngineProviding.swift | 1 - .../CalibrationFlowController.swift | 1 - .../Calibration/CalibratorService.swift | 5 +- Gaze/Services/EnforceModeService.swift | 7 +-- .../EyeTracking/CameraSessionManager.swift | 2 - .../EyeTracking/EyeTrackingService.swift | 24 +++++----- Gaze/Services/EyeTracking/PupilDetector.swift | 28 +++++------ Gaze/Services/LoggingManager.swift | 46 ++++++++++++------- Gaze/Services/MenuBarItemLocator.swift | 1 - .../ScreenCapturePermissionManager.swift | 2 - Gaze/Services/ServiceContainer.swift | 1 - .../Settings/CameraAccessService.swift | 1 - Gaze/Services/Settings/SettingsManager.swift | 1 - .../System/FullscreenDetectionService.swift | 5 +- .../System/IdleMonitoringService.swift | 14 ++---- Gaze/Services/System/SystemSleepManager.swift | 1 - .../Timer/ReminderTriggerService.swift | 1 - .../Services/Timer/SmartModeCoordinator.swift | 9 +--- Gaze/Services/Timer/TimerEngine.swift | 7 +-- Gaze/Services/Timer/TimerScheduler.swift | 1 - Gaze/Services/Timer/TimerStateManager.swift | 1 - Gaze/Services/UpdateManager.swift | 9 +--- 26 files changed, 72 insertions(+), 103 deletions(-) diff --git a/Gaze/Models/PauseReason.swift b/Gaze/Models/PauseReason.swift index 8d1c5fe..d473644 100644 --- a/Gaze/Models/PauseReason.swift +++ b/Gaze/Models/PauseReason.swift @@ -13,3 +13,5 @@ enum PauseReason: Codable, Equatable, Hashable { case idle case system } + +extension PauseReason: Sendable {} diff --git a/Gaze/Protocols/EnforceModeProviding.swift b/Gaze/Protocols/EnforceModeProviding.swift index 8e05e79..377b8fa 100644 --- a/Gaze/Protocols/EnforceModeProviding.swift +++ b/Gaze/Protocols/EnforceModeProviding.swift @@ -9,7 +9,6 @@ import Combine import Foundation /// Protocol that defines the interface for enforce mode functionality. -@MainActor protocol EnforceModeProviding: AnyObject, ObservableObject { /// Whether enforce mode is currently enabled var isEnforceModeEnabled: Bool { get } diff --git a/Gaze/Protocols/SettingsProviding.swift b/Gaze/Protocols/SettingsProviding.swift index fbf926a..8a8c30a 100644 --- a/Gaze/Protocols/SettingsProviding.swift +++ b/Gaze/Protocols/SettingsProviding.swift @@ -6,14 +6,12 @@ import Combine import Foundation -@MainActor protocol TimerSettingsProviding { func allTimerSettings() -> [TimerType: (enabled: Bool, intervalMinutes: Int)] func isTimerEnabled(for type: TimerType) -> Bool func timerIntervalMinutes(for type: TimerType) -> Int } -@MainActor protocol SettingsProviding: AnyObject, Observable, TimerSettingsProviding { var settings: AppSettings { get set } var settingsPublisher: AnyPublisher { get } diff --git a/Gaze/Protocols/SmartModeProviding.swift b/Gaze/Protocols/SmartModeProviding.swift index 57de3f9..b9e444c 100644 --- a/Gaze/Protocols/SmartModeProviding.swift +++ b/Gaze/Protocols/SmartModeProviding.swift @@ -9,7 +9,6 @@ import Combine import Foundation /// Protocol for fullscreen detection functionality -@MainActor protocol FullscreenDetectionProviding: AnyObject, ObservableObject { /// Whether a fullscreen app is currently active var isFullscreenActive: Bool { get } @@ -22,7 +21,6 @@ protocol FullscreenDetectionProviding: AnyObject, ObservableObject { } /// Protocol for idle monitoring functionality -@MainActor protocol IdleMonitoringProviding: AnyObject, ObservableObject { /// Whether the user is currently idle var isIdle: Bool { get } diff --git a/Gaze/Protocols/TimerEngineProviding.swift b/Gaze/Protocols/TimerEngineProviding.swift index d7ba5ab..9e1aaad 100644 --- a/Gaze/Protocols/TimerEngineProviding.swift +++ b/Gaze/Protocols/TimerEngineProviding.swift @@ -10,7 +10,6 @@ import Foundation /// Protocol that defines the interface for timer engine functionality. /// This abstraction allows for dependency injection and easy mocking in tests. -@MainActor protocol TimerEngineProviding: AnyObject, ObservableObject { /// Current timer states for all active timers var timerStates: [TimerIdentifier: TimerState] { get } diff --git a/Gaze/Services/Calibration/CalibrationFlowController.swift b/Gaze/Services/Calibration/CalibrationFlowController.swift index 356f94f..b66cd00 100644 --- a/Gaze/Services/Calibration/CalibrationFlowController.swift +++ b/Gaze/Services/Calibration/CalibrationFlowController.swift @@ -8,7 +8,6 @@ import Combine import Foundation -@MainActor final class CalibrationFlowController: ObservableObject { @Published private(set) var currentStep: CalibrationStep? @Published private(set) var currentStepIndex = 0 diff --git a/Gaze/Services/Calibration/CalibratorService.swift b/Gaze/Services/Calibration/CalibratorService.swift index 0bc1a89..c3f6612 100644 --- a/Gaze/Services/Calibration/CalibratorService.swift +++ b/Gaze/Services/Calibration/CalibratorService.swift @@ -10,7 +10,6 @@ import Foundation import AppKit import SwiftUI -@MainActor final class CalibratorService: ObservableObject { static let shared = CalibratorService() @@ -280,8 +279,8 @@ final class CalibratorService: ObservableObject { rightVertical: Double? = nil, faceWidthRatio: Double = 0 ) { - Task { @MainActor in - collectSample( + Task { [weak self] in + self?.collectSample( leftRatio: leftRatio, rightRatio: rightRatio, leftVertical: leftVertical, diff --git a/Gaze/Services/EnforceModeService.swift b/Gaze/Services/EnforceModeService.swift index 72e29f3..f992e49 100644 --- a/Gaze/Services/EnforceModeService.swift +++ b/Gaze/Services/EnforceModeService.swift @@ -14,7 +14,6 @@ enum ComplianceResult { case faceNotDetected } -@MainActor class EnforceModeService: ObservableObject { static let shared = EnforceModeService() @@ -224,10 +223,8 @@ class EnforceModeService: ObservableObject { private func startFaceDetectionTimer() { stopFaceDetectionTimer() - faceDetectionTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in - Task { @MainActor [weak self] in - self?.checkFaceDetectionTimeout() - } + faceDetectionTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in + self?.checkFaceDetectionTimeout() } } diff --git a/Gaze/Services/EyeTracking/CameraSessionManager.swift b/Gaze/Services/EyeTracking/CameraSessionManager.swift index 252193f..6598709 100644 --- a/Gaze/Services/EyeTracking/CameraSessionManager.swift +++ b/Gaze/Services/EyeTracking/CameraSessionManager.swift @@ -45,7 +45,6 @@ final class CameraSessionManager: NSObject, ObservableObject { return layer } - @MainActor func start() async throws { guard !isRunning else { return } @@ -63,7 +62,6 @@ final class CameraSessionManager: NSObject, ObservableObject { isRunning = true } - @MainActor func stop() { captureSession?.stopRunning() captureSession = nil diff --git a/Gaze/Services/EyeTracking/EyeTrackingService.swift b/Gaze/Services/EyeTracking/EyeTrackingService.swift index 12a9141..624ddbc 100644 --- a/Gaze/Services/EyeTracking/EyeTrackingService.swift +++ b/Gaze/Services/EyeTracking/EyeTrackingService.swift @@ -10,7 +10,6 @@ import AVFoundation import Combine import Foundation -@MainActor class EyeTrackingService: NSObject, ObservableObject { static let shared = EyeTrackingService() @@ -100,18 +99,22 @@ class EyeTrackingService: NSObject, ObservableObject { } try await cameraManager.start() - isEyeTrackingActive = true + await MainActor.run { + self.isEyeTrackingActive = true + } print("✓ Eye tracking active") } func stopEyeTracking() { cameraManager.stop() - isEyeTrackingActive = false - isEyesClosed = false - userLookingAtScreen = true - faceDetected = false - debugAdapter.clear() - syncDebugState() + Task { @MainActor in + isEyeTrackingActive = false + isEyesClosed = false + userLookingAtScreen = true + faceDetected = false + debugAdapter.clear() + syncDebugState() + } } private func syncDebugState() { @@ -134,7 +137,6 @@ class EyeTrackingService: NSObject, ObservableObject { debugImageSize = debugAdapter.imageSize } - @MainActor private func updateGazeConfiguration() { let configuration = GazeDetector.Configuration( thresholds: CalibrationState.shared.thresholds, @@ -184,7 +186,8 @@ extension EyeTrackingService: CameraSessionDelegate { } } - Task { @MainActor in + Task { @MainActor [weak self] in + guard let self else { return } self.faceDetected = result.faceDetected self.isEyesClosed = result.isEyesClosed self.userLookingAtScreen = result.userLookingAtScreen @@ -220,7 +223,6 @@ enum EyeTrackingError: Error, LocalizedError { // MARK: - Debug State Adapter -@MainActor final class EyeDebugStateAdapter { var leftPupilRatio: Double? var rightPupilRatio: Double? diff --git a/Gaze/Services/EyeTracking/PupilDetector.swift b/Gaze/Services/EyeTracking/PupilDetector.swift index c91d036..700d870 100644 --- a/Gaze/Services/EyeTracking/PupilDetector.swift +++ b/Gaze/Services/EyeTracking/PupilDetector.swift @@ -92,19 +92,19 @@ enum GazeDirection: String, Sendable, CaseIterable { } /// Calibration state for adaptive thresholding (matches Python Calibration class) -final class PupilCalibration: @unchecked Sendable { +final class PupilCalibration: Sendable { private let lock = NSLock() private let targetFrames = 20 private var thresholdsLeft: [Int] = [] private var thresholdsRight: [Int] = [] - nonisolated var isComplete: Bool { + var isComplete: Bool { lock.lock() defer { lock.unlock() } return thresholdsLeft.count >= targetFrames && thresholdsRight.count >= targetFrames } - nonisolated func threshold(forSide side: Int) -> Int { + func threshold(forSide side: Int) -> Int { lock.lock() defer { lock.unlock() } let thresholds = side == 0 ? thresholdsLeft : thresholdsRight @@ -113,7 +113,7 @@ final class PupilCalibration: @unchecked Sendable { return thresholds.reduce(0, +) / thresholds.count } - nonisolated func evaluate(eyeData: UnsafePointer, width: Int, height: Int, side: Int) { + func evaluate(eyeData: UnsafePointer, width: Int, height: Int, side: Int) { let bestThreshold = findBestThreshold(eyeData: eyeData, width: width, height: height) lock.lock() defer { lock.unlock() } @@ -124,7 +124,7 @@ final class PupilCalibration: @unchecked Sendable { } } - private nonisolated func findBestThreshold( + private func findBestThreshold( eyeData: UnsafePointer, width: Int, height: Int ) -> Int { let averageIrisSize = 0.48 @@ -154,7 +154,7 @@ final class PupilCalibration: @unchecked Sendable { return bestThreshold } - private nonisolated static func irisSize(data: UnsafePointer, width: Int, height: Int) + private static func irisSize(data: UnsafePointer, width: Int, height: Int) -> Double { let margin = 5 @@ -177,7 +177,7 @@ final class PupilCalibration: @unchecked Sendable { return totalCount > 0 ? Double(blackCount) / Double(totalCount) : 0 } - nonisolated func reset() { + func reset() { lock.lock() defer { lock.unlock() } thresholdsLeft.removeAll() @@ -245,34 +245,34 @@ final class PupilDetector: @unchecked Sendable { nonisolated(unsafe) static var debugRightEyeRegion: EyeRegion? nonisolated(unsafe) static var debugImageSize: CGSize? - nonisolated(unsafe) static let calibration = PupilCalibration() + nonisolated static let calibration = PupilCalibration() // MARK: - Convenience Properties - private nonisolated static var debugImageCounter: Int { + private nonisolated(unsafe) static var debugImageCounter: Int { get { _debugImageCounter } set { _debugImageCounter = newValue } } - private nonisolated static var frameCounter: Int { + private nonisolated(unsafe) static var frameCounter: Int { get { _frameCounter } set { _frameCounter = newValue } } - private nonisolated static var lastPupilPositions: (left: PupilPosition?, right: PupilPosition?) + private nonisolated(unsafe) static var lastPupilPositions: (left: PupilPosition?, right: PupilPosition?) { get { _lastPupilPositions } set { _lastPupilPositions = newValue } } - private nonisolated static var metrics: PupilDetectorMetrics { + private nonisolated(unsafe) static var metrics: PupilDetectorMetrics { get { _metrics } set { _metrics = newValue } } // MARK: - Precomputed Tables - private nonisolated(unsafe) static let spatialWeightsLUT: [[Float]] = { + private nonisolated static let spatialWeightsLUT: [[Float]] = { let d = 10 let radius = d / 2 let sigmaSpace: Float = 15.0 @@ -287,7 +287,7 @@ final class PupilDetector: @unchecked Sendable { return weights }() - private nonisolated(unsafe) static let colorWeightsLUT: [Float] = { + private nonisolated static let colorWeightsLUT: [Float] = { let sigmaColor: Float = 15.0 var lut = [Float](repeating: 0, count: 256) for diff in 0..<256 { diff --git a/Gaze/Services/LoggingManager.swift b/Gaze/Services/LoggingManager.swift index c595c9f..5440595 100644 --- a/Gaze/Services/LoggingManager.swift +++ b/Gaze/Services/LoggingManager.swift @@ -8,20 +8,23 @@ import Foundation import os.log -#if DEBUG - let isLoggingEnabled = true -#else - let isLoggingEnabled = false -#endif +nonisolated private let loggingSubsystem = "com.mikefreno.Gaze" +nonisolated private let isLoggingEnabled: Bool = { + #if DEBUG + return true + #else + return false + #endif +}() /// A centralized logging manager that provides structured, subsystem-aware logging /// for the Gaze application to ensure logs are captured by the run script. -final class LoggingManager { +final class LoggingManager: @unchecked Sendable { static let shared = LoggingManager() // MARK: - Private Properties - private let subsystem = "com.mikefreno.Gaze" + private let subsystem = loggingSubsystem // MARK: - Public Loggers @@ -84,30 +87,39 @@ final class LoggingManager { } /// Log an info message using the shared LoggingManager -public func logInfo(_ message: String, category: String = "General") { - LoggingManager.shared.info(message, category: category) +nonisolated public func logInfo(_ message: String, category: String = "General") { + guard isLoggingEnabled else { return } + let logger = Logger(subsystem: loggingSubsystem, category: category) + logger.info("\(message, privacy: .public)") } /// Log a debug message using the shared LoggingManager -public func logDebug(_ message: String, category: String = "General") { - LoggingManager.shared.debug(message, category: category) +nonisolated public func logDebug(_ message: String, category: String = "General") { + guard isLoggingEnabled else { return } + let logger = Logger(subsystem: loggingSubsystem, category: category) + logger.debug("\(message, privacy: .public)") } /// Log an error message using the shared LoggingManager -public func logError(_ message: String, category: String = "General") { - LoggingManager.shared.error(message, category: category) +nonisolated public func logError(_ message: String, category: String = "General") { + guard isLoggingEnabled else { return } + let logger = Logger(subsystem: loggingSubsystem, category: category) + logger.error("\(message, privacy: .public)") } /// Log a warning message using the shared LoggingManager -public func logWarning(_ message: String, category: String = "General") { - LoggingManager.shared.warning(message, category: category) +nonisolated public func logWarning(_ message: String, category: String = "General") { + guard isLoggingEnabled else { return } + let logger = Logger(subsystem: loggingSubsystem, category: category) + logger.warning("\(message, privacy: .public)") } // MARK: - Additional Helper Functions /// Log a verbose message (only enabled in DEBUG builds) -public func logVerbose(_ message: String, category: String = "General") { +nonisolated public func logVerbose(_ message: String, category: String = "General") { #if DEBUG - LoggingManager.shared.debug(message, category: category) + let logger = Logger(subsystem: loggingSubsystem, category: category) + logger.debug("\(message, privacy: .public)") #endif } diff --git a/Gaze/Services/MenuBarItemLocator.swift b/Gaze/Services/MenuBarItemLocator.swift index c54ef5e..a088563 100644 --- a/Gaze/Services/MenuBarItemLocator.swift +++ b/Gaze/Services/MenuBarItemLocator.swift @@ -12,7 +12,6 @@ struct MenuBarLocationResult { let frame: CGRect } -@MainActor final class MenuBarItemLocator { static let shared = MenuBarItemLocator() diff --git a/Gaze/Services/Permissions/ScreenCapturePermissionManager.swift b/Gaze/Services/Permissions/ScreenCapturePermissionManager.swift index 75b8c3c..827e467 100644 --- a/Gaze/Services/Permissions/ScreenCapturePermissionManager.swift +++ b/Gaze/Services/Permissions/ScreenCapturePermissionManager.swift @@ -21,7 +21,6 @@ public enum ScreenCaptureAuthorizationStatus: Equatable { } } -@MainActor protocol ScreenCapturePermissionManaging: AnyObject { var authorizationStatus: ScreenCaptureAuthorizationStatus { get } var authorizationStatusPublisher: AnyPublisher { get } @@ -31,7 +30,6 @@ protocol ScreenCapturePermissionManaging: AnyObject { func openSystemSettings() } -@MainActor final class ScreenCapturePermissionManager: ObservableObject, ScreenCapturePermissionManaging { static let shared = ScreenCapturePermissionManager() diff --git a/Gaze/Services/ServiceContainer.swift b/Gaze/Services/ServiceContainer.swift index 7873f30..c9a86c2 100644 --- a/Gaze/Services/ServiceContainer.swift +++ b/Gaze/Services/ServiceContainer.swift @@ -8,7 +8,6 @@ import Foundation /// A simple dependency injection container for managing service instances. -@MainActor final class ServiceContainer { /// Shared instance for production use diff --git a/Gaze/Services/Settings/CameraAccessService.swift b/Gaze/Services/Settings/CameraAccessService.swift index b8cc9f0..6f8023f 100644 --- a/Gaze/Services/Settings/CameraAccessService.swift +++ b/Gaze/Services/Settings/CameraAccessService.swift @@ -8,7 +8,6 @@ import AVFoundation import Combine -@MainActor class CameraAccessService: ObservableObject { static let shared = CameraAccessService() diff --git a/Gaze/Services/Settings/SettingsManager.swift b/Gaze/Services/Settings/SettingsManager.swift index fcf4ec3..75baac4 100644 --- a/Gaze/Services/Settings/SettingsManager.swift +++ b/Gaze/Services/Settings/SettingsManager.swift @@ -9,7 +9,6 @@ import Combine import Foundation import Observation -@MainActor @Observable final class SettingsManager { static let shared = SettingsManager() diff --git a/Gaze/Services/System/FullscreenDetectionService.swift b/Gaze/Services/System/FullscreenDetectionService.swift index 554eb64..9ba4481 100644 --- a/Gaze/Services/System/FullscreenDetectionService.swift +++ b/Gaze/Services/System/FullscreenDetectionService.swift @@ -62,7 +62,6 @@ struct SystemFullscreenEnvironmentProvider: FullscreenEnvironmentProviding { } } -@MainActor final class FullscreenDetectionService: ObservableObject { @Published private(set) var isFullscreenActive = false @@ -113,9 +112,7 @@ final class FullscreenDetectionService: ObservableObject { let notificationCenter = workspace.notificationCenter let stateChangeHandler: (Notification) -> Void = { [weak self] _ in - Task { @MainActor in - self?.checkFullscreenState() - } + self?.checkFullscreenState() } let notifications: [(NSNotification.Name, Any?)] = [ diff --git a/Gaze/Services/System/IdleMonitoringService.swift b/Gaze/Services/System/IdleMonitoringService.swift index 705472d..413e0a0 100644 --- a/Gaze/Services/System/IdleMonitoringService.swift +++ b/Gaze/Services/System/IdleMonitoringService.swift @@ -9,7 +9,6 @@ import AppKit import Combine import Foundation -@MainActor class IdleMonitoringService: ObservableObject { @Published private(set) var isIdle = false @Published private(set) var idleTimeSeconds: TimeInterval = 0 @@ -34,9 +33,7 @@ class IdleMonitoringService: ObservableObject { private func startMonitoring() { timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in guard let self = self else { return } - Task { @MainActor in - self.checkIdleState() - } + self.checkIdleState() } } @@ -82,7 +79,6 @@ struct UsageStatistics: Codable { } } -@MainActor class UsageTrackingService: ObservableObject { @Published private(set) var statistics: UsageStatistics @@ -120,9 +116,7 @@ class UsageTrackingService: ObservableObject { idleService.$isIdle .sink { [weak self] isIdle in - Task { @MainActor in - self?.updateTracking(isIdle: isIdle) - } + self?.updateTracking(isIdle: isIdle) } .store(in: &cancellables) } @@ -135,9 +129,7 @@ class UsageTrackingService: ObservableObject { private func startTracking() { Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in guard let self = self else { return } - Task { @MainActor in - self.tick() - } + self.tick() } } diff --git a/Gaze/Services/System/SystemSleepManager.swift b/Gaze/Services/System/SystemSleepManager.swift index 1087fb8..3a6998e 100644 --- a/Gaze/Services/System/SystemSleepManager.swift +++ b/Gaze/Services/System/SystemSleepManager.swift @@ -8,7 +8,6 @@ import AppKit import Foundation -@MainActor final class SystemSleepManager { private let settingsManager: any SettingsProviding private weak var timerEngine: (any TimerEngineProviding)? diff --git a/Gaze/Services/Timer/ReminderTriggerService.swift b/Gaze/Services/Timer/ReminderTriggerService.swift index 6f8ba42..a5d1c3e 100644 --- a/Gaze/Services/Timer/ReminderTriggerService.swift +++ b/Gaze/Services/Timer/ReminderTriggerService.swift @@ -7,7 +7,6 @@ import Foundation -@MainActor final class ReminderTriggerService { private let settingsProvider: any SettingsProviding private let enforceModeService: EnforceModeService? diff --git a/Gaze/Services/Timer/SmartModeCoordinator.swift b/Gaze/Services/Timer/SmartModeCoordinator.swift index 61f34f3..9634019 100644 --- a/Gaze/Services/Timer/SmartModeCoordinator.swift +++ b/Gaze/Services/Timer/SmartModeCoordinator.swift @@ -13,7 +13,6 @@ protocol SmartModeCoordinatorDelegate: AnyObject { func smartModeDidRequestResumeAll(_ coordinator: SmartModeCoordinator, reason: PauseReason) } -@MainActor final class SmartModeCoordinator { weak var delegate: SmartModeCoordinatorDelegate? @@ -35,17 +34,13 @@ final class SmartModeCoordinator { fullscreenService?.$isFullscreenActive .sink { [weak self] isFullscreen in - Task { @MainActor in - self?.handleFullscreenChange(isFullscreen: isFullscreen) - } + self?.handleFullscreenChange(isFullscreen: isFullscreen) } .store(in: &cancellables) idleService?.$isIdle .sink { [weak self] isIdle in - Task { @MainActor in - self?.handleIdleChange(isIdle: isIdle) - } + self?.handleIdleChange(isIdle: isIdle) } .store(in: &cancellables) } diff --git a/Gaze/Services/Timer/TimerEngine.swift b/Gaze/Services/Timer/TimerEngine.swift index fa59f6d..7cb0aa1 100644 --- a/Gaze/Services/Timer/TimerEngine.swift +++ b/Gaze/Services/Timer/TimerEngine.swift @@ -8,7 +8,6 @@ import Combine import Foundation -@MainActor class TimerEngine: ObservableObject { @Published var timerStates: [TimerIdentifier: TimerState] = [:] @Published var activeReminder: ReminderEvent? @@ -47,9 +46,7 @@ class TimerEngine: ObservableObject { ) self.configurationHelper = TimerConfigurationHelper(settingsProvider: settingsManager) - Task { @MainActor in - enforceModeService?.setTimerEngine(self) - } + enforceModeService?.setTimerEngine(self) scheduler.delegate = self smartModeCoordinator.delegate = self @@ -175,7 +172,7 @@ class TimerEngine: ObservableObject { for: identifier, secondsRemaining: updatedState.remainingSeconds ) { - Task { @MainActor in + Task { await reminderService.prepareEnforceMode( secondsRemaining: updatedState.remainingSeconds) } diff --git a/Gaze/Services/Timer/TimerScheduler.swift b/Gaze/Services/Timer/TimerScheduler.swift index 0376bac..b9ec98c 100644 --- a/Gaze/Services/Timer/TimerScheduler.swift +++ b/Gaze/Services/Timer/TimerScheduler.swift @@ -12,7 +12,6 @@ protocol TimerSchedulerDelegate: AnyObject { func schedulerDidTick(_ scheduler: TimerScheduler) } -@MainActor final class TimerScheduler { weak var delegate: TimerSchedulerDelegate? diff --git a/Gaze/Services/Timer/TimerStateManager.swift b/Gaze/Services/Timer/TimerStateManager.swift index 02672e3..6b141a6 100644 --- a/Gaze/Services/Timer/TimerStateManager.swift +++ b/Gaze/Services/Timer/TimerStateManager.swift @@ -8,7 +8,6 @@ import Combine import Foundation -@MainActor final class TimerStateManager: ObservableObject { @Published private(set) var timerStates: [TimerIdentifier: TimerState] = [:] @Published private(set) var activeReminder: ReminderEvent? diff --git a/Gaze/Services/UpdateManager.swift b/Gaze/Services/UpdateManager.swift index 591c534..43724aa 100644 --- a/Gaze/Services/UpdateManager.swift +++ b/Gaze/Services/UpdateManager.swift @@ -12,7 +12,6 @@ import Foundation import Sparkle #endif -@MainActor class UpdateManager: NSObject, ObservableObject { static let shared = UpdateManager() @@ -49,9 +48,7 @@ class UpdateManager: NSObject, ObservableObject { options: [.new, .initial] ) { [weak self] _, change in guard let self = self, let newValue = change.newValue else { return } - Task { @MainActor in - self.automaticallyChecksForUpdates = newValue - } + self.automaticallyChecksForUpdates = newValue } lastCheckDateObservation = updater.observe( @@ -59,9 +56,7 @@ class UpdateManager: NSObject, ObservableObject { options: [.new, .initial] ) { [weak self] _, change in guard let self = self else { return } - Task { @MainActor in - self.lastUpdateCheckDate = change.newValue ?? nil - } + self.lastUpdateCheckDate = change.newValue ?? nil } } #endif