You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
3.8 KiB
171 lines
3.8 KiB
//
|
|
// Countdown+Extension.swift
|
|
// LeCountdown
|
|
//
|
|
// Created by Laurent Morvillier on 25/01/2023.
|
|
//
|
|
|
|
import Foundation
|
|
import SwiftUI
|
|
import CoreData
|
|
|
|
enum TimerError: Error {
|
|
case notificationAuthorizationMissing
|
|
}
|
|
|
|
extension AbstractTimer {
|
|
|
|
var displayName: String {
|
|
return self.name ?? self.coolpic.emoji
|
|
}
|
|
|
|
var name: String? {
|
|
return self.activity?.name
|
|
}
|
|
|
|
var url: URL {
|
|
if let url = URL(string: self.stringId) {
|
|
return url
|
|
} else {
|
|
fatalError("Can't produce url with \(self.stringId)")
|
|
}
|
|
}
|
|
|
|
var coolpic: CoolPic {
|
|
if let image, let coolpic = CoolPic(rawValue: image) {
|
|
return coolpic
|
|
}
|
|
return CoolPic.allCases[0]
|
|
}
|
|
|
|
var imageName: String {
|
|
return self.coolpic.rawValue
|
|
}
|
|
|
|
}
|
|
|
|
extension AbstractSoundTimer {
|
|
|
|
var sounds: [Sound] {
|
|
if let soundList {
|
|
return soundList.enumItems()
|
|
}
|
|
return []
|
|
}
|
|
|
|
var playlists: [Playlist] {
|
|
if let playlistList {
|
|
return playlistList.enumItems()
|
|
}
|
|
return []
|
|
}
|
|
|
|
func setSounds(_ sounds: [Sound]) {
|
|
self.soundList = sounds.stringRepresentation
|
|
}
|
|
|
|
func setPlaylists(_ playlists: [Playlist]) {
|
|
self.playlistList = playlists.stringRepresentation
|
|
}
|
|
|
|
var coolSound: Sound {
|
|
var allSounds: [Sound] = []
|
|
allSounds.append(contentsOf: self.sounds)
|
|
allSounds.append(contentsOf: self.playlists.reduce([], { $0 + $1.sounds }))
|
|
return allSounds.randomElement() ?? Sound.allCases[0]
|
|
}
|
|
|
|
var soundName: String {
|
|
return self.coolSound.soundName
|
|
}
|
|
|
|
}
|
|
|
|
extension Countdown {
|
|
|
|
static func fake(context: NSManagedObjectContext) -> Countdown {
|
|
let cd = Countdown(context: context)
|
|
cd.duration = 4 * 60.0
|
|
let activity = Activity(context: context)
|
|
activity.name = "Tea"
|
|
cd.activity = activity
|
|
return cd
|
|
}
|
|
|
|
}
|
|
|
|
extension Alarm {
|
|
|
|
static func fake(context: NSManagedObjectContext) -> Alarm {
|
|
let alarm = Alarm(context: context)
|
|
alarm.fireDate = Date()
|
|
let activity = Activity(context: context)
|
|
activity.name = "Wakeup"
|
|
alarm.activity = activity
|
|
return alarm
|
|
}
|
|
|
|
}
|
|
|
|
extension Stopwatch {
|
|
|
|
var coolSound: Sound? {
|
|
return Sound(rawValue: Int(self.sound)) ?? nil
|
|
}
|
|
|
|
static func fake(context: NSManagedObjectContext) -> Stopwatch {
|
|
let stopwatch = Stopwatch(context: context)
|
|
let activity = Activity(context: context)
|
|
activity.name = "Run"
|
|
stopwatch.activity = activity
|
|
return stopwatch
|
|
}
|
|
|
|
}
|
|
|
|
extension Record {
|
|
|
|
var details: String {
|
|
if let start, let end {
|
|
return "\(start) - \(end)"
|
|
} else {
|
|
return "no details"
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
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)) ?? "--"
|
|
}
|
|
|
|
}
|
|
|
|
// MARK: - Storage convenience
|
|
|
|
fileprivate let separator = "|"
|
|
fileprivate let formatter: NumberFormatter = NumberFormatter()
|
|
|
|
extension String {
|
|
|
|
func enumItems<T : RawRepresentable<Int>>() -> [T] {
|
|
let ids: [String] = self.components(separatedBy: separator)
|
|
let intIds: [Int] = ids.compactMap { formatter.number(from: $0)?.intValue }
|
|
return intIds.compactMap { T(rawValue: $0) }
|
|
}
|
|
|
|
}
|
|
|
|
extension Array where Element : RawRepresentable<Int> {
|
|
|
|
var stringRepresentation: String {
|
|
let ids = self.compactMap { formatter.string(from: NSNumber(value: $0.rawValue)) }
|
|
return ids.joined(separator: separator)
|
|
}
|
|
|
|
}
|
|
|