-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTimerDurationStepper.swift
107 lines (96 loc) · 3.2 KB
/
TimerDurationStepper.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
//
// TimerDurationStepper.swift
// Focal
//
// Created by Niek van de Pas on 05/01/2025.
//
import SwiftUI
struct TimerDurationStepper: View {
let settingsManager = SettingsManager.shared
var timerState: TimerState
@Binding var duration: Int // Duration in seconds
@State var oldDuration: Int
init(forTimerState timerState: TimerState, duration: Binding<Int>) {
self.timerState = timerState
self._duration = duration
self.oldDuration = duration.wrappedValue
}
func incrementStep() {
let maxDuration = getMaxDuration()
if duration + 60 <= maxDuration {
duration += 60
}
}
func decrementStep() {
let minDuration = getMinDuration()
if duration - 60 >= minDuration {
duration -= 60
}
}
func getMinDuration() -> Int {
switch timerState {
case .work:
return Constants.MIN_WORK_DURATION
case .rest:
return Constants.MIN_REST_DURATION
case .longRest:
return Constants.MIN_LONG_REST_DURATION
}
}
func getMaxDuration() -> Int {
switch timerState {
case .work:
return Constants.MAX_WORK_DURATION
case .rest:
return Constants.MAX_REST_DURATION
case .longRest:
return Constants.MAX_LONG_REST_DURATION
}
}
/// Updates the remaining time of the active timer if the duration is changed while the timer is full.
func maybeUpdateTimeRemaining() {
// Assume that when the timer full and the user changes the value,
// the duration of the timer should be changed to the new value.
// Conversely, when the timer has already decreased,
// leave the time remaining intact so as to not interfere with ongoing sessions.
let isChangingDurationForCurrentlyActiveTimer = self.timerState == TimerViewModel.shared.timerState
let timerIsFull = TimerViewModel.shared.timeRemaining == oldDuration
let durationIsLessThanTimeRemainingInTimer = duration < TimerViewModel.shared.timeRemaining
if isChangingDurationForCurrentlyActiveTimer && (timerIsFull || durationIsLessThanTimeRemainingInTimer) {
TimerViewModel.shared.timeRemaining = duration
}
oldDuration = duration
}
var body: some View {
let label = switch timerState {
case .work:
"Work:"
case .rest:
"Short break:"
case .longRest:
"Long break:"
}
Stepper {
HStack {
Text(label)
// On macOS, the text should be pushed to the right, towards the stepper, to have them aligned.
// On iOS, this isn't possible anyway, and having them left-aligned looks neater.
// #if os(macOS)
Spacer()
// #endif
Text("\(duration / 60) minutes")
}
}
onIncrement: {
incrementStep()
maybeUpdateTimeRemaining()
}
onDecrement: {
decrementStep()
maybeUpdateTimeRemaining()
}
#if os(macOS)
.frame(width: 170)
#endif
}
}