Make stopwatch work + UI

release
Laurent 3 years ago
parent 7db4aecfa4
commit 6137196be7
  1. 29
      LeCountdown/Conductor.swift
  2. 4
      LeCountdown/Model/CoreDataRequests.swift
  3. 14
      LeCountdown/TimerRouter.swift
  4. 4
      LeCountdown/Views/Alarm/AlarmDialView.swift
  5. 2
      LeCountdown/Views/ContentView.swift
  6. 5
      LeCountdown/Views/Countdown/CountdownDialView.swift
  7. 26
      LeCountdown/Views/DialView.swift
  8. 19
      LeCountdown/Views/Stopwatch/StopwatchDialView.swift

@ -16,25 +16,34 @@ class Conductor : ObservableObject {
@Published var soundPlayer: SoundPlayer? = nil @Published var soundPlayer: SoundPlayer? = nil
@UserDefault(Key.dates.rawValue, defaultValue: [:]) static var savedDates: [String : DateInterval] @UserDefault(Key.dates.rawValue, defaultValue: [:]) static var savedDates: [String : DateInterval]
@UserDefault(Key.stopwatch.rawValue, defaultValue: [:]) static var savedStopwatches: [String : Date]
init() { init() {
self.notificationDates = Conductor.savedDates self.timerDates = Conductor.savedDates
self.stopwatchIntervals = Conductor.savedStopwatches
}
@Published var timerDates: [String : DateInterval] = [:] {
didSet {
Conductor.savedDates = timerDates
}
} }
@Published var notificationDates: [String : DateInterval] = [:] { @Published var stopwatchIntervals: [String : Date] = [:] {
didSet { didSet {
Conductor.savedDates = notificationDates Conductor.savedStopwatches = stopwatchIntervals
} }
} }
enum Key : String { enum Key : String {
case dates case dates
case stopwatch
} }
func startCountdown(_ date: Date, countdown: Countdown) { func startCountdown(_ date: Date, countdown: Countdown) {
DispatchQueue.main.async { DispatchQueue.main.async {
let dateInterval = DateInterval(start: Date(), end: date) let dateInterval = DateInterval(start: Date(), end: date)
self.notificationDates[countdown.stringId] = dateInterval self.timerDates[countdown.stringId] = dateInterval
self._launchLiveActivity(countdown: countdown, endDate: date) self._launchLiveActivity(countdown: countdown, endDate: date)
} }
@ -51,7 +60,7 @@ class Conductor : ObservableObject {
self._recordActivity(countdownId: countdownId) self._recordActivity(countdownId: countdownId)
} }
if self.notificationDates.removeValue(forKey: countdownId) != nil { if self.timerDates.removeValue(forKey: countdownId) != nil {
self._endLiveActivity(countdownId: countdownId) self._endLiveActivity(countdownId: countdownId)
} }
} }
@ -59,7 +68,7 @@ class Conductor : ObservableObject {
func cleanup() { func cleanup() {
let now = Date() let now = Date()
for (key, value) in self.notificationDates { for (key, value) in self.timerDates {
if value.end < now { if value.end < now {
self.endCountdown(countdownId: key, cancel: false) self.endCountdown(countdownId: key, cancel: false)
} }
@ -69,9 +78,9 @@ class Conductor : ObservableObject {
fileprivate func _recordActivity(countdownId: String) { fileprivate func _recordActivity(countdownId: String) {
let context = PersistenceController.shared.container.viewContext let context = PersistenceController.shared.container.viewContext
if let countdown = context.object(stringId: countdownId) as? Countdown, if let countdown = context.object(stringId: countdownId) as? Countdown,
let dateInterval = self.notificationDates[countdownId] { let dateInterval = self.timerDates[countdownId] {
do { do {
try CoreDataRequests.recordActivity(countdown: countdown, dateInterval: dateInterval) try CoreDataRequests.recordActivity(timer: countdown, dateInterval: dateInterval)
} catch { } catch {
print("Could not record activity = \(error)") print("Could not record activity = \(error)")
// TODO: show error to user // TODO: show error to user
@ -145,7 +154,7 @@ class Conductor : ObservableObject {
func updateLiveActivities() { func updateLiveActivities() {
print("update live activity...") print("update live activity...")
for (countdownId, interval) in self.notificationDates { for (countdownId, interval) in self.timerDates {
if interval.end < Date() { if interval.end < Date() {
self._endLiveActivity(countdownId: countdownId) self._endLiveActivity(countdownId: countdownId)

@ -42,9 +42,9 @@ class CoreDataRequests {
return activity return activity
} }
static func recordActivity(countdown: Countdown, dateInterval: DateInterval) throws { static func recordActivity(timer: AbstractTimer, dateInterval: DateInterval) throws {
guard let activity = countdown.activity else { guard let activity = timer.activity else {
return return
} }

@ -50,7 +50,19 @@ class TimerRouter {
fileprivate static func _startStopwatch(_ stopwatch: Stopwatch, handler: @escaping (Result<Bool, Error>) -> Void) { fileprivate static func _startStopwatch(_ stopwatch: Stopwatch, handler: @escaping (Result<Bool, Error>) -> Void) {
if let start = Conductor.maestro.stopwatchIntervals[stopwatch.stringId] {
Conductor.maestro.stopwatchIntervals.removeValue(forKey: stopwatch.stringId)
do {
try CoreDataRequests.recordActivity(timer: stopwatch, dateInterval: DateInterval(start: start, end: Date()))
} catch {
handler(.failure(error))
}
} else {
Conductor.maestro.stopwatchIntervals[stopwatch.stringId] = Date()
}
} }
} }

@ -28,10 +28,6 @@ struct AlarmDialView: View {
Spacer() Spacer()
} }
.padding(24.0)
.monospaced()
.font(Font.system(size: 16.0, weight: .semibold))
.foregroundColor(Color.white)
} }
} }

@ -231,7 +231,7 @@ struct MainToolbarView: View {
fileprivate extension Countdown { fileprivate extension Countdown {
var endDate: Date? { var endDate: Date? {
return Conductor.maestro.notificationDates[self.stringId]?.end return Conductor.maestro.timerDates[self.stringId]?.end
} }
var isLive: Bool { var isLive: Bool {

@ -19,7 +19,7 @@ struct CountdownDialView: View {
VStack(alignment: .leading) { VStack(alignment: .leading) {
Text(countdown.activity?.name?.uppercased() ?? "") Text(countdown.activity?.name?.uppercased() ?? "")
// let dateInterval = DateInterval(start: Date(), end: Date()) // let dateInterval = DateInterval(start: Date(), end: Date())
if let dateInterval = conductor.notificationDates[countdown.stringId] { if let dateInterval = conductor.timerDates[countdown.stringId] {
Text(dateInterval.end, style: .timer) Text(dateInterval.end, style: .timer)
Spacer() Spacer()
HStack { HStack {
@ -40,9 +40,6 @@ struct CountdownDialView: View {
} }
Spacer() Spacer()
} }
.monospaced()
.font(Font.system(size: 16.0, weight: .semibold))
.foregroundColor(Color.white)
} }
} }

@ -47,16 +47,24 @@ struct DialView: View {
@ViewBuilder @ViewBuilder
fileprivate func _dialView(timer: AbstractTimer) -> some View { fileprivate func _dialView(timer: AbstractTimer) -> some View {
switch timer { Group {
case let countdown as Countdown: switch timer {
CountdownDialView(countdown: countdown) .environmentObject(Conductor.maestro) case let countdown as Countdown:
case let alarm as Alarm: CountdownDialView(countdown: countdown)
AlarmDialView(alarm: alarm) .environmentObject(Conductor.maestro) .environmentObject(Conductor.maestro)
case let stopwatch as Stopwatch: case let alarm as Alarm:
StopwatchDialView(stopwatch: stopwatch) .environmentObject(Conductor.maestro) AlarmDialView(alarm: alarm)
default: .environmentObject(Conductor.maestro)
Text("missing dial view") case let stopwatch as Stopwatch:
StopwatchDialView(stopwatch: stopwatch)
.environmentObject(Conductor.maestro)
default:
Text("missing dial view")
}
} }
.monospaced()
.font(Font.system(size: 16.0, weight: .semibold))
.foregroundColor(Color.white)
} }
@ViewBuilder @ViewBuilder

@ -9,22 +9,23 @@ import SwiftUI
struct StopwatchDialView: View { struct StopwatchDialView: View {
@EnvironmentObject var conductor: Conductor
@ObservedObject var stopwatch: Stopwatch @ObservedObject var stopwatch: Stopwatch
var body: some View { var body: some View {
VStack { HStack {
VStack(alignment: .leading) {
HStack {
Text(stopwatch.activity?.name?.uppercased() ?? "") Text(stopwatch.activity?.name?.uppercased() ?? "")
if let start = conductor.stopwatchIntervals[stopwatch.stringId] {
Text(start, style: .timer)
}
Spacer() Spacer()
} }
Spacer() Spacer()
} }
.padding(24.0)
.monospaced()
.font(Font.system(size: 16.0, weight: .semibold))
.foregroundColor(Color.white)
} }
} }
@ -32,5 +33,7 @@ struct StopwatchDialView: View {
struct StopwatchDialView_Previews: PreviewProvider { struct StopwatchDialView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
StopwatchDialView(stopwatch: Stopwatch.fake(context: PersistenceController.preview.container.viewContext)) StopwatchDialView(stopwatch: Stopwatch.fake(context: PersistenceController.preview.container.viewContext))
.environmentObject(Conductor.maestro)
.background(.cyan)
} }
} }

Loading…
Cancel
Save