bit smoother
This commit is contained in:
@@ -28,10 +28,10 @@ final class EnforceModeCalibrationService: ObservableObject {
|
|||||||
|
|
||||||
private var countdownTimer: Timer?
|
private var countdownTimer: Timer?
|
||||||
private var sampleTimer: Timer?
|
private var sampleTimer: Timer?
|
||||||
private let countdownDuration: TimeInterval = 1.0
|
private let countdownDuration: TimeInterval = 0.8
|
||||||
private let preCountdownPause: TimeInterval = 0.5
|
private let preCountdownPause: TimeInterval = 0.8
|
||||||
private let sampleInterval: TimeInterval = 0.1
|
private let sampleInterval: TimeInterval = 0.02
|
||||||
private let samplesPerTarget = 12
|
private let samplesPerTarget = 20
|
||||||
private var windowController: NSWindowController?
|
private var windowController: NSWindowController?
|
||||||
|
|
||||||
func start() {
|
func start() {
|
||||||
@@ -89,6 +89,7 @@ final class EnforceModeCalibrationService: ObservableObject {
|
|||||||
switch currentStep {
|
switch currentStep {
|
||||||
case .eyeBox:
|
case .eyeBox:
|
||||||
currentStep = .targets
|
currentStep = .targets
|
||||||
|
// Start countdown immediately when transitioning to targets to avoid first point duplication
|
||||||
startCountdown()
|
startCountdown()
|
||||||
case .targets:
|
case .targets:
|
||||||
if targetIndex < targets.count - 1 {
|
if targetIndex < targets.count - 1 {
|
||||||
@@ -135,13 +136,17 @@ final class EnforceModeCalibrationService: ObservableObject {
|
|||||||
guard let self else { return }
|
guard let self else { return }
|
||||||
Task { @MainActor in
|
Task { @MainActor in
|
||||||
let elapsed = Date().timeIntervalSince(startTime)
|
let elapsed = Date().timeIntervalSince(startTime)
|
||||||
let countdownElapsed = max(0, elapsed - self.preCountdownPause)
|
// Pause before starting the countdown
|
||||||
if elapsed < self.preCountdownPause {
|
if elapsed < self.preCountdownPause {
|
||||||
self.countdownProgress = 1.0
|
self.countdownProgress = 1.0
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start the actual countdown after pause
|
||||||
|
let countdownElapsed = elapsed - self.preCountdownPause
|
||||||
let remaining = max(0, self.countdownDuration - countdownElapsed)
|
let remaining = max(0, self.countdownDuration - countdownElapsed)
|
||||||
self.countdownProgress = remaining / self.countdownDuration
|
self.countdownProgress = remaining / self.countdownDuration
|
||||||
|
|
||||||
if remaining <= 0 {
|
if remaining <= 0 {
|
||||||
self.stopCountdown()
|
self.stopCountdown()
|
||||||
self.startSampleCollection()
|
self.startSampleCollection()
|
||||||
@@ -153,7 +158,8 @@ final class EnforceModeCalibrationService: ObservableObject {
|
|||||||
private func stopCountdown() {
|
private func stopCountdown() {
|
||||||
countdownTimer?.invalidate()
|
countdownTimer?.invalidate()
|
||||||
countdownTimer = nil
|
countdownTimer = nil
|
||||||
countdownProgress = 1.0
|
// Only reset to 1.0 when actually stopping, not during transitions
|
||||||
|
// countdownProgress = 1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
private func startSampleCollection() {
|
private func startSampleCollection() {
|
||||||
|
|||||||
@@ -31,48 +31,47 @@ struct EnforceModeCalibrationOverlayView: View {
|
|||||||
|
|
||||||
private var eyeBoxStep: some View {
|
private var eyeBoxStep: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
VStack(spacing: 16) {
|
VStack(spacing: 20) {
|
||||||
Text("Adjust Eye Box")
|
VStack(spacing: 16) {
|
||||||
.font(.title2)
|
Text("Adjust Eye Box")
|
||||||
.foregroundStyle(.white)
|
.font(.title2)
|
||||||
|
.foregroundStyle(.white)
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
"Use the sliders to fit the boxes around your eyes. It need not be perfect."
|
"Use the sliders to fit the boxes around your eyes. It need not be perfect."
|
||||||
)
|
)
|
||||||
.font(.callout)
|
.font(.callout)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
.foregroundStyle(.white.opacity(0.8))
|
|
||||||
}
|
|
||||||
.padding(.horizontal, 40)
|
|
||||||
.padding(.top, 40)
|
|
||||||
.frame(maxWidth: 520)
|
|
||||||
.frame(maxWidth: .infinity, alignment: .top)
|
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 12) {
|
|
||||||
Text("Width")
|
|
||||||
.font(.caption)
|
|
||||||
.foregroundStyle(.white.opacity(0.8))
|
.foregroundStyle(.white.opacity(0.8))
|
||||||
Slider(
|
}
|
||||||
value: $settingsManager.settings.enforceModeEyeBoxWidthFactor,
|
.padding(.horizontal, 40)
|
||||||
in: 0.12...0.25
|
.frame(maxWidth: 520)
|
||||||
)
|
.frame(maxWidth: .infinity, alignment: .top)
|
||||||
|
|
||||||
Text("Height")
|
VStack(alignment: .leading, spacing: 12) {
|
||||||
.font(.caption)
|
Text("Width")
|
||||||
.foregroundStyle(.white.opacity(0.8))
|
.font(.caption)
|
||||||
Slider(
|
.foregroundStyle(.white.opacity(0.8))
|
||||||
value: $settingsManager.settings.enforceModeEyeBoxHeightFactor,
|
Slider(
|
||||||
in: 0.01...0.10
|
value: $settingsManager.settings.enforceModeEyeBoxWidthFactor,
|
||||||
)
|
in: 0.12...0.25
|
||||||
}
|
)
|
||||||
.padding(16)
|
|
||||||
.background(.black.opacity(0.3))
|
Text("Height")
|
||||||
.clipShape(RoundedRectangle(cornerRadius: 12))
|
.font(.caption)
|
||||||
.frame(maxWidth: 420)
|
.foregroundStyle(.white.opacity(0.8))
|
||||||
.frame(maxHeight: .infinity, alignment: .center)
|
Slider(
|
||||||
|
value: $settingsManager.settings.enforceModeEyeBoxHeightFactor,
|
||||||
|
in: 0.01...0.10
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.padding(16)
|
||||||
|
.background(.black.opacity(0.3))
|
||||||
|
.clipShape(RoundedRectangle(cornerRadius: 12))
|
||||||
|
.frame(maxWidth: 420)
|
||||||
|
|
||||||
VStack {
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
HStack(spacing: 12) {
|
HStack(spacing: 12) {
|
||||||
Button("Cancel") {
|
Button("Cancel") {
|
||||||
calibrationService.dismissOverlay()
|
calibrationService.dismissOverlay()
|
||||||
@@ -85,8 +84,8 @@ struct EnforceModeCalibrationOverlayView: View {
|
|||||||
}
|
}
|
||||||
.buttonStyle(.borderedProminent)
|
.buttonStyle(.borderedProminent)
|
||||||
}
|
}
|
||||||
|
.padding(.bottom, 40)
|
||||||
}
|
}
|
||||||
.padding(.bottom, 40)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +129,7 @@ struct EnforceModeCalibrationOverlayView: View {
|
|||||||
Text("Calibration Complete")
|
Text("Calibration Complete")
|
||||||
.font(.title2)
|
.font(.title2)
|
||||||
.foregroundStyle(.white)
|
.foregroundStyle(.white)
|
||||||
Text("You can close this window and start testing.")
|
Text("Enforce Mode is ready to use.")
|
||||||
.font(.callout)
|
.font(.callout)
|
||||||
.foregroundStyle(.white.opacity(0.8))
|
.foregroundStyle(.white.opacity(0.8))
|
||||||
|
|
||||||
@@ -163,6 +162,7 @@ struct EnforceModeCalibrationOverlayView: View {
|
|||||||
.animation(.linear(duration: 0.02), value: calibrationService.countdownProgress)
|
.animation(.linear(duration: 0.02), value: calibrationService.countdownProgress)
|
||||||
}
|
}
|
||||||
.position(center)
|
.position(center)
|
||||||
|
.animation(.easeInOut(duration: 0.3), value: center)
|
||||||
}
|
}
|
||||||
.ignoresSafeArea()
|
.ignoresSafeArea()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user