Fixes and improvements

release
Laurent 3 years ago
parent 0fcd80153d
commit 9f0438a6b6
  1. 1
      LeCountdown/AppDelegate.swift
  2. 24
      LeCountdown/CountdownScheduler.swift
  3. 4
      LeCountdown/LeCountdownApp.swift
  4. 12
      LeCountdown/Model/Model+Extensions.swift
  5. 2
      LeCountdown/Utils/PropertyWrappers.swift
  6. 31
      LeCountdown/Views/RecordsView.swift

@ -30,6 +30,7 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
completionHandler([.banner, .sound]) completionHandler([.banner, .sound])
AppEnvironment.sun.endCountdown(countdownId: notification.request.identifier) AppEnvironment.sun.endCountdown(countdownId: notification.request.identifier)
} }
} }

@ -27,12 +27,14 @@ class CountdownScheduler {
content.title = NSLocalizedString("It's time!", comment: "") content.title = NSLocalizedString("It's time!", comment: "")
let duration = countdown.duration let duration = countdown.duration
let minutes = duration / 60.0 let body: String
if let name = countdown.activity?.name {
let minutesLabel = minutes > 1 ? NSLocalizedString("minutes", comment: "") : NSLocalizedString("minute", comment: "") body = NSLocalizedString("Time's up for \(name)!", comment: "")
let isOrAre = minutes > 1 ? NSLocalizedString("are", comment: "") : NSLocalizedString("is", comment: "") } else {
body = NSLocalizedString("Your \(duration.minuteSecond) countdown is over!", comment: "")
}
content.body = NSLocalizedString("The \(minutes) \(minutesLabel) \(isOrAre) over!", comment: "") content.body = body
content.sound = UNNotificationSound.defaultCritical content.sound = UNNotificationSound.defaultCritical
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: duration, repeats: false) let trigger = UNTimeIntervalNotificationTrigger(timeInterval: duration, repeats: false)
@ -81,13 +83,17 @@ class AppEnvironment : ObservableObject {
} }
func startCountdown(_ date: Date, countdown: Countdown) { func startCountdown(_ date: Date, countdown: Countdown) {
let dateInterval = DateInterval(start: Date(), end: date) DispatchQueue.main.async {
self.notificationDates[countdown.stringId] = dateInterval let dateInterval = DateInterval(start: Date(), end: date)
self.notificationDates[countdown.stringId] = dateInterval
}
} }
func endCountdown(countdownId: String) { func endCountdown(countdownId: String) {
self._recordActivityIfPossible(countdownId: countdownId) DispatchQueue.main.async {
self.notificationDates.removeValue(forKey: countdownId) self._recordActivityIfPossible(countdownId: countdownId)
self.notificationDates.removeValue(forKey: countdownId)
}
} }
func cleanup() { func cleanup() {

@ -26,9 +26,7 @@ struct LeCountdownApp: App {
} }
fileprivate func _willEnterForegroundNotification() { fileprivate func _willEnterForegroundNotification() {
DispatchQueue.main.async { AppEnvironment.sun.cleanup()
AppEnvironment.sun.cleanup()
}
} }
} }

@ -10,7 +10,6 @@ import SwiftUI
extension Countdown { extension Countdown {
var name: String? { var name: String? {
return self.activity?.name return self.activity?.name
} }
@ -28,3 +27,14 @@ extension Record {
} }
} }
extension Activity {
fileprivate static var formatter: NumberFormatter = NumberFormatter()
var recordCount: String {
let count: Int = self.records?.count ?? 0
return Activity.formatter.string(from: NSNumber(value: count)) ?? "--"
}
}

@ -8,7 +8,7 @@
import Foundation import Foundation
@propertyWrapper @propertyWrapper
struct UserDefault<T: Codable> { struct UserDefault<T : Codable> {
let key: String let key: String
let defaultValue: T let defaultValue: T

@ -14,27 +14,36 @@ struct RecordsView: View {
animation: .default) animation: .default)
private var records: FetchedResults<Record> private var records: FetchedResults<Record>
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Activity.name, ascending: true)],
predicate: NSPredicate(format: "records.@count > 0"), animation: .default)
private var activities: FetchedResults<Activity>
var body: some View { var body: some View {
if records.isEmpty { Group {
Text("You don't have any recorded activity yet") if records.isEmpty {
} else { Text("You don't have any recorded activity yet")
List { } else {
ForEach(records) { record in List {
HStack { ForEach(activities) { activity in
Text(record.activity?.name ?? "no activity") HStack {
Spacer() Text(activity.name ?? "no activity")
Text(record.details) Spacer()
Text(activity.recordCount)
}
} }
} }
} }
} }.navigationTitle("Activities")
} }
} }
struct RecordsView_Previews: PreviewProvider { struct RecordsView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
RecordsView().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext) NavigationStack {
RecordsView().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
}
} }
} }

Loading…
Cancel
Save