general: testing and simplifying
This commit is contained in:
@@ -76,6 +76,10 @@ class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject {
|
|||||||
.sink { [weak self] smartMode in
|
.sink { [weak self] smartMode in
|
||||||
self?.idleService?.updateThreshold(minutes: smartMode.idleThresholdMinutes)
|
self?.idleService?.updateThreshold(minutes: smartMode.idleThresholdMinutes)
|
||||||
self?.usageTrackingService?.updateResetThreshold(minutes: smartMode.usageResetAfterMinutes)
|
self?.usageTrackingService?.updateResetThreshold(minutes: smartMode.usageResetAfterMinutes)
|
||||||
|
|
||||||
|
// Force state check when settings change to apply immediately
|
||||||
|
self?.fullscreenService?.forceUpdate()
|
||||||
|
self?.idleService?.forceUpdate()
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ enum EyeTrackingConstants {
|
|||||||
// MARK: - Face Pose Thresholds
|
// MARK: - Face Pose Thresholds
|
||||||
/// Maximum yaw (left/right head turn) in radians before considering user looking away
|
/// Maximum yaw (left/right head turn) in radians before considering user looking away
|
||||||
/// 0.20 radians ≈ 11.5 degrees (Tightened from 0.35)
|
/// 0.20 radians ≈ 11.5 degrees (Tightened from 0.35)
|
||||||
static let yawThreshold: Double = 0.20
|
static let yawThreshold: Double = 0.1
|
||||||
|
|
||||||
/// Pitch threshold for looking UP (above screen).
|
/// Pitch threshold for looking UP (above screen).
|
||||||
/// Since camera is at top, looking at screen is negative pitch.
|
/// Since camera is at top, looking at screen is negative pitch.
|
||||||
@@ -29,7 +29,7 @@ enum EyeTrackingConstants {
|
|||||||
|
|
||||||
/// Pitch threshold for looking DOWN (at keyboard/lap).
|
/// Pitch threshold for looking DOWN (at keyboard/lap).
|
||||||
/// Values < -0.45 imply looking too far down.
|
/// Values < -0.45 imply looking too far down.
|
||||||
static let pitchDownThreshold: Double = -0.45
|
static let pitchDownThreshold: Double = -0.2
|
||||||
|
|
||||||
// MARK: - Pupil Tracking Thresholds
|
// MARK: - Pupil Tracking Thresholds
|
||||||
/// Minimum horizontal pupil ratio (0.0 = right edge, 1.0 = left edge)
|
/// Minimum horizontal pupil ratio (0.0 = right edge, 1.0 = left edge)
|
||||||
|
|||||||
@@ -24,10 +24,6 @@ class EyeTrackingService: NSObject, ObservableObject {
|
|||||||
label: "com.gaze.videoDataOutput", qos: .userInitiated)
|
label: "com.gaze.videoDataOutput", qos: .userInitiated)
|
||||||
private var _previewLayer: AVCaptureVideoPreviewLayer?
|
private var _previewLayer: AVCaptureVideoPreviewLayer?
|
||||||
|
|
||||||
// Logging throttle
|
|
||||||
private var lastLogTime: Date = .distantPast
|
|
||||||
private let logInterval: TimeInterval = EyeTrackingConstants.logInterval
|
|
||||||
|
|
||||||
var previewLayer: AVCaptureVideoPreviewLayer? {
|
var previewLayer: AVCaptureVideoPreviewLayer? {
|
||||||
guard let session = captureSession else {
|
guard let session = captureSession else {
|
||||||
_previewLayer = nil
|
_previewLayer = nil
|
||||||
@@ -190,7 +186,9 @@ class EyeTrackingService: NSObject, ObservableObject {
|
|||||||
// - Camera at top = looking at screen is negative pitch
|
// - Camera at top = looking at screen is negative pitch
|
||||||
// - Looking above screen (straight ahead) is ~0 or positive -> Look Away
|
// - Looking above screen (straight ahead) is ~0 or positive -> Look Away
|
||||||
// - Looking at keyboard/lap is very negative -> Look Away
|
// - Looking at keyboard/lap is very negative -> Look Away
|
||||||
let pitchLookingAway = pitch > EyeTrackingConstants.pitchUpThreshold || pitch < EyeTrackingConstants.pitchDownThreshold
|
let pitchLookingAway =
|
||||||
|
pitch > EyeTrackingConstants.pitchUpThreshold
|
||||||
|
|| pitch < EyeTrackingConstants.pitchDownThreshold
|
||||||
|
|
||||||
let poseLookingAway = abs(yaw) > yawThreshold || pitchLookingAway
|
let poseLookingAway = abs(yaw) > yawThreshold || pitchLookingAway
|
||||||
|
|
||||||
|
|||||||
@@ -18,73 +18,6 @@ struct SettingsWindowView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
if #available(macOS 15.0, *) {
|
|
||||||
TabView(selection: $selectedSection) {
|
|
||||||
Tab(
|
|
||||||
SettingsSection.general.title,
|
|
||||||
systemImage: SettingsSection.general.iconName,
|
|
||||||
value: SettingsSection.general
|
|
||||||
) {
|
|
||||||
GeneralSetupView(
|
|
||||||
settingsManager: settingsManager,
|
|
||||||
isOnboarding: false
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Tab(
|
|
||||||
SettingsSection.lookAway.title,
|
|
||||||
systemImage: SettingsSection.lookAway.iconName,
|
|
||||||
value: SettingsSection.lookAway
|
|
||||||
) {
|
|
||||||
LookAwaySetupView(settingsManager: settingsManager)
|
|
||||||
}
|
|
||||||
|
|
||||||
Tab(
|
|
||||||
SettingsSection.blink.title, systemImage: SettingsSection.blink.iconName,
|
|
||||||
value: SettingsSection.blink
|
|
||||||
) {
|
|
||||||
BlinkSetupView(settingsManager: settingsManager)
|
|
||||||
}
|
|
||||||
|
|
||||||
Tab(
|
|
||||||
SettingsSection.posture.title,
|
|
||||||
systemImage: SettingsSection.posture.iconName,
|
|
||||||
value: SettingsSection.posture
|
|
||||||
) {
|
|
||||||
PostureSetupView(settingsManager: settingsManager)
|
|
||||||
}
|
|
||||||
|
|
||||||
Tab(
|
|
||||||
SettingsSection.userTimers.title,
|
|
||||||
systemImage: SettingsSection.userTimers.iconName,
|
|
||||||
value: SettingsSection.userTimers
|
|
||||||
) {
|
|
||||||
UserTimersView(
|
|
||||||
userTimers: Binding(
|
|
||||||
get: { settingsManager.settings.userTimers },
|
|
||||||
set: { settingsManager.settings.userTimers = $0 }
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Tab(
|
|
||||||
SettingsSection.enforceMode.title,
|
|
||||||
systemImage: SettingsSection.enforceMode.iconName,
|
|
||||||
value: SettingsSection.enforceMode
|
|
||||||
) {
|
|
||||||
EnforceModeSetupView(settingsManager: settingsManager)
|
|
||||||
}
|
|
||||||
|
|
||||||
Tab(
|
|
||||||
SettingsSection.smartMode.title,
|
|
||||||
systemImage: SettingsSection.smartMode.iconName,
|
|
||||||
value: SettingsSection.smartMode
|
|
||||||
) {
|
|
||||||
SmartModeSetupView(settingsManager: settingsManager)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.tabViewStyle(.sidebarAdaptable)
|
|
||||||
} else {
|
|
||||||
// Fallback for macOS 14 and earlier - use a consistent sidebar approach without collapse button
|
|
||||||
NavigationSplitView {
|
NavigationSplitView {
|
||||||
List(SettingsSection.allCases, selection: $selectedSection) { section in
|
List(SettingsSection.allCases, selection: $selectedSection) { section in
|
||||||
NavigationLink(value: section) {
|
NavigationLink(value: section) {
|
||||||
@@ -96,9 +29,7 @@ struct SettingsWindowView: View {
|
|||||||
} detail: {
|
} detail: {
|
||||||
detailView(for: selectedSection)
|
detailView(for: selectedSection)
|
||||||
}
|
}
|
||||||
// Disable the ability to collapse the sidebar by explicitly setting a fixed width
|
|
||||||
.navigationSplitViewColumnWidth(min: 200, ideal: 250, max: 300)
|
.navigationSplitViewColumnWidth(min: 200, ideal: 250, max: 300)
|
||||||
}
|
|
||||||
|
|
||||||
Divider()
|
Divider()
|
||||||
|
|
||||||
@@ -178,18 +109,29 @@ struct SettingsWindowView: View {
|
|||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
private func retriggerOnboarding() {
|
private func retriggerOnboarding() {
|
||||||
// Close settings window first
|
// Get AppDelegate reference first
|
||||||
|
guard let appDelegate = NSApplication.shared.delegate as? AppDelegate else { return }
|
||||||
|
|
||||||
|
// Step 1: Close any existing onboarding window
|
||||||
|
if let onboardingWindow = NSApplication.shared.windows.first(where: {
|
||||||
|
$0.identifier == WindowIdentifiers.onboarding
|
||||||
|
}) {
|
||||||
|
onboardingWindow.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: Close settings window
|
||||||
closeWindow()
|
closeWindow()
|
||||||
|
|
||||||
// Get AppDelegate and open onboarding
|
// Step 3: Reset onboarding state with a delay to ensure settings window is closed
|
||||||
if let appDelegate = NSApplication.shared.delegate as? AppDelegate {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
|
||||||
// Reset onboarding state so it shows as fresh
|
self.settingsManager.settings.hasCompletedOnboarding = false
|
||||||
settingsManager.settings.hasCompletedOnboarding = false
|
|
||||||
|
|
||||||
// Open onboarding window
|
// Step 4: Open onboarding window with another delay to ensure state is saved
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
|
||||||
appDelegate.openOnboarding()
|
appDelegate.openOnboarding()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user