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.
150 lines
3.4 KiB
150 lines
3.4 KiB
//
|
|
// Countdown+Extension.swift
|
|
// LeCountdown
|
|
//
|
|
// Created by Laurent Morvillier on 25/01/2023.
|
|
//
|
|
|
|
import Foundation
|
|
import SwiftUI
|
|
import CoreData
|
|
|
|
|
|
extension AbstractSoundTimer {
|
|
|
|
var sounds: Set<Sound> {
|
|
if let soundList {
|
|
return Set(soundList.enumItems())
|
|
}
|
|
return []
|
|
}
|
|
|
|
func setSounds(_ sounds: Set<Sound>) {
|
|
self.soundList = sounds.stringRepresentation
|
|
}
|
|
|
|
var coolSound: Sound {
|
|
var sounds = self.sounds
|
|
|
|
// remove last played sound if the playlist has at least 3 sounds
|
|
if sounds.count > 2,
|
|
let lastSoundId = Preferences.lastSelectedSound[self.stringId],
|
|
let lastSound = Sound(rawValue: lastSoundId) {
|
|
sounds.remove(lastSound)
|
|
}
|
|
|
|
if let random = sounds.randomElement() {
|
|
Preferences.lastSelectedSound[self.stringId] = random.id
|
|
return random
|
|
}
|
|
|
|
return Sound.default
|
|
}
|
|
|
|
var soundName: String {
|
|
return self.coolSound.soundName
|
|
}
|
|
|
|
}
|
|
|
|
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 = "Running"
|
|
stopwatch.activity = activity
|
|
return stopwatch
|
|
}
|
|
|
|
}
|
|
|
|
extension Record {
|
|
|
|
var count: Double { return 1.0 }
|
|
|
|
public override func didChangeValue(forKey key: String) {
|
|
super.didChangeValue(forKey: key)
|
|
|
|
switch key {
|
|
case "start", "end":
|
|
self.preCompute()
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
|
|
func preCompute() {
|
|
if let start {
|
|
self.year = Int16(start.year)
|
|
self.month = Int16(start.month)
|
|
if let end {
|
|
self.duration = end.timeIntervalSince(start)
|
|
}
|
|
}
|
|
}
|
|
|
|
var formattedDay: String {
|
|
if let start {
|
|
return start.formatted(date: .abbreviated, time: .omitted)
|
|
}
|
|
return ""
|
|
}
|
|
|
|
var details: String {
|
|
if let start, let end {
|
|
return "\(start.formatted()) - \(end.formatted())"
|
|
} 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)) ?? "--"
|
|
}
|
|
|
|
}
|
|
|
|
extension CustomSound : Localized {
|
|
|
|
var localizedString: String {
|
|
return self.text ?? ""
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// 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 Sequence where Element : RawRepresentable<Int> {
|
|
|
|
var stringRepresentation: String {
|
|
let ids = self.compactMap { formatter.string(from: NSNumber(value: $0.rawValue)) }
|
|
return ids.joined(separator: separator)
|
|
}
|
|
|
|
}
|
|
|