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.
LeCountdown/LeCountdown/Views/PresetsView.swift

219 lines
6.3 KiB

//
// PresetsView.swift
// LeCountdown
//
// Created by Laurent Morvillier on 13/02/2023.
//
import SwiftUI
enum PresetSection: Int, Identifiable, CaseIterable {
var id: Int { return self.rawValue }
case workout
case chill
case cooking
var presets: [Preset] {
switch self {
case .cooking: return [.softBoiled, .mediumBoiledEggs, .hardBoiledEggs]
case .workout: return [.runningSplits]
case .chill: return [.nap, .meditation]
}
}
var localizedName: String {
switch self {
case .cooking: return NSLocalizedString("Cooking", comment: "")
case .workout: return NSLocalizedString("Workout", comment: "")
case .chill: return NSLocalizedString("Chill", comment: "")
}
}
}
struct CountdownIntervalGroup {
var repeatCount: Int
var intervals: [CountdownInterval]
}
struct CountdownInterval {
var duration: TimeInterval
var sound: Sound?
}
enum Preset: Int, Identifiable, CaseIterable {
var id: Int { return self.rawValue }
case softBoiled
case mediumBoiledEggs
case hardBoiledEggs
case meditation
case nap
case runningSplits
var localizedName: String {
switch self {
case .hardBoiledEggs: return NSLocalizedString("Hard boiled eggs", comment: "")
case .softBoiled: return NSLocalizedString("Soft boiled eggs", comment: "")
case .mediumBoiledEggs: return NSLocalizedString("Medium boiled eggs", comment: "")
case .meditation: return NSLocalizedString("Meditation", comment: "")
case .nap: return NSLocalizedString("Nap", comment: "")
case .runningSplits: return NSLocalizedString("Running splits", comment: "")
}
}
var intervalGroup: CountdownIntervalGroup? {
switch self {
case .runningSplits:
let runInterval = CountdownInterval(duration: 30.0, sound: Sound.sbArpeggio_Loop_River)
let breakInterval = CountdownInterval(duration: 30.0, sound: Sound.sbLoop_ToneSD_Boavista)
return CountdownIntervalGroup(repeatCount: 8, intervals: [runInterval, breakInterval])
default:
return nil
}
}
var duration: TimeInterval {
switch self {
case .softBoiled: return 3 * 60
case .mediumBoiledEggs: return 6 * 60
case .hardBoiledEggs: return 10 * 60
case .meditation: return 15 * 60
case .nap: return 20 * 60
case .runningSplits: return 13
}
}
var formattedDuration: String {
if let group = self.intervalGroup {
let count = group.repeatCount.formatted()
let durations = group.intervals.map { $0.duration.formatted() }
let formattedIntervals = durations.joined(separator: "/")
return "\(count) * [\(formattedIntervals)]"
} else {
return self.duration.minuteSecond
}
}
var sound: Set<Sound> {
switch self {
case .softBoiled: return []
case .mediumBoiledEggs: return []
case .hardBoiledEggs: return []
case .meditation: return []
case .nap: return []
case .runningSplits: return []
}
}
var soundTitle: String {
return "Great sound"
}
}
class PresetModel : ObservableObject {
@Published var selectedPreset: Preset = Preset.hardBoiledEggs
}
struct PresetsView: View {
@Environment(\.managedObjectContext) private var viewContext
@StateObject var model: PresetModel = PresetModel()
@State var isPresented: Bool = false
var tabSelection: Binding<Int>
private let columns: [GridItem] = [
GridItem(spacing: 10.0),
GridItem(spacing: 10.0),
]
var body: some View {
VStack {
Text("You can edit the duration, sound and label before adding")
.padding()
.font(.callout)
LazyVGrid(
columns: columns,
spacing: 10.0
) {
ForEach(PresetSection.allCases) { section in
Section {
ForEach(section.presets) { preset in
Button {
self.model.selectedPreset = preset
self.isPresented = true
} label: {
TimerItemView(name: preset.localizedName, duration: preset.formattedDuration, sound: preset.soundTitle)
}
}
} header: {
HStack {
Text(section.localizedName.uppercased())
Spacer()
}
}
}
}.padding(.horizontal)
Spacer()
}
.sheet(isPresented: $isPresented, content: {
CountdownEditView(isPresented: $isPresented, preset: self.model.selectedPreset, tabSelection: self.tabSelection)
.environment(\.managedObjectContext, viewContext)
})
.navigationTitle("Presets")
}
}
struct TimerItemView: View {
var name: String
var duration: String
var sound: String
var body: some View {
HStack {
VStack(alignment: .leading) {
Text(name.uppercased()).multilineTextAlignment(.leading)
Text(duration)
Text(sound.uppercased()).foregroundColor(Color(white: 0.7))
}.padding()
Spacer()
}.background(Color(white: 0.15))
.cornerRadius(16.0)
.monospaced()
.font(Font.system(size: 16.0, weight: .semibold))
.foregroundColor(Color.white)
}
}
struct PresetsView_Previews: PreviewProvider {
static var previews: some View {
PresetsView(tabSelection: .constant(0))
}
}
struct TimerItemView_Previews: PreviewProvider {
static var previews: some View {
TimerItemView(name: "Hard boiled eggs", duration: "10:00", sound: "Stephan Bodzin").frame(width: UIScreen.main.bounds.width / 2.0)
}
}