parent
d0b31d2c3e
commit
04cc931ce8
@ -0,0 +1,40 @@ |
|||||||
|
// |
||||||
|
// SiriTimerView.swift |
||||||
|
// LeCountdown |
||||||
|
// |
||||||
|
// Created by Laurent Morvillier on 10/03/2023. |
||||||
|
// |
||||||
|
|
||||||
|
import SwiftUI |
||||||
|
import _AppIntents_SwiftUI |
||||||
|
|
||||||
|
struct SiriTimerView: View { |
||||||
|
|
||||||
|
var timer: AbstractTimer? = nil |
||||||
|
|
||||||
|
@State var isVisible = true |
||||||
|
|
||||||
|
var body: some View { |
||||||
|
if self.timer != nil { |
||||||
|
SiriTipView(intent: self.intent(), isVisible: self.$isVisible) |
||||||
|
.siriTipViewStyle(SiriTipViewStyle.dark).padding() |
||||||
|
} else { |
||||||
|
Text("no siri view") |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fileprivate func intent() -> StartTimerIntent { |
||||||
|
let intent = StartTimerIntent() |
||||||
|
if let timer { |
||||||
|
intent.timer = TimerIdentifierAppEntity(id: timer.stringId, displayString: timer.displayName) |
||||||
|
} |
||||||
|
return intent |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
struct SiriTimerView_Previews: PreviewProvider { |
||||||
|
static var previews: some View { |
||||||
|
SiriTimerView() |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,107 @@ |
|||||||
|
// |
||||||
|
// TimersView.swift |
||||||
|
// LeCountdown |
||||||
|
// |
||||||
|
// Created by Laurent Morvillier on 10/03/2023. |
||||||
|
// |
||||||
|
|
||||||
|
import SwiftUI |
||||||
|
|
||||||
|
struct TimersView: View { |
||||||
|
|
||||||
|
@EnvironmentObject var boringContext: BoringContext |
||||||
|
|
||||||
|
@Environment(\.managedObjectContext) private var viewContext |
||||||
|
|
||||||
|
@Binding var isEditing: Bool |
||||||
|
|
||||||
|
@FetchRequest( |
||||||
|
sortDescriptors: [NSSortDescriptor(keyPath: \AbstractTimer.order, ascending: true)], |
||||||
|
animation: .default) |
||||||
|
private var timers: FetchedResults<AbstractTimer> |
||||||
|
|
||||||
|
fileprivate let itemSpacing: CGFloat = 10.0 |
||||||
|
|
||||||
|
var body: some View { |
||||||
|
|
||||||
|
GeometryReader { reader in |
||||||
|
|
||||||
|
let columns: [GridItem] = self._columns() |
||||||
|
let width: CGFloat = reader.size.width / CGFloat(columns.count) - 15.0 |
||||||
|
let abstractTimers: [AbstractTimer] = Array(self.timers) |
||||||
|
|
||||||
|
if abstractTimers.count > 0 { |
||||||
|
|
||||||
|
ScrollView { |
||||||
|
|
||||||
|
LazyVGrid( |
||||||
|
columns: columns, |
||||||
|
spacing: itemSpacing |
||||||
|
) { |
||||||
|
|
||||||
|
ReorderableForEach(items: abstractTimers) { timer in |
||||||
|
|
||||||
|
DialView(timer: timer, isEditingBinding: self.$isEditing, frameSize: width, handler: { timer in |
||||||
|
self._handleSiriTips(timer: timer) |
||||||
|
}) |
||||||
|
.environment(\.managedObjectContext, viewContext) |
||||||
|
.environmentObject(Conductor.maestro) |
||||||
|
.environmentObject(boringContext) |
||||||
|
} moveAction: { from, to in |
||||||
|
self._reorder(from: from, to: to) |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
Text("You'll find your timers here. Start by creating them on the left screen") |
||||||
|
} |
||||||
|
}.padding(.horizontal, itemSpacing) |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
fileprivate func _reorder(from: IndexSet, to: Int) { |
||||||
|
var timers: [AbstractTimer] = Array(self.timers) |
||||||
|
timers.move(fromOffsets: from, toOffset: to) |
||||||
|
for (i, countdown) in timers.enumerated() { |
||||||
|
countdown.order = Int16(i) |
||||||
|
} |
||||||
|
do { |
||||||
|
try viewContext.save() |
||||||
|
} catch { |
||||||
|
Logger.error(error) |
||||||
|
self.boringContext.error = error |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fileprivate func _handleSiriTips(timer: AbstractTimer) { |
||||||
|
let timerId = timer.stringId |
||||||
|
if !Preferences.timerSiriTips.contains(timerId) { |
||||||
|
self.boringContext.siriTimer = timer |
||||||
|
Preferences.timerSiriTips.insert(timerId) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fileprivate func _columnCount() -> Int { |
||||||
|
#if os(iOS) |
||||||
|
if UIDevice.isPhoneIdiom { |
||||||
|
return 2 |
||||||
|
} else { |
||||||
|
return 3 |
||||||
|
} |
||||||
|
#else |
||||||
|
return 3 |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
fileprivate func _columns() -> [GridItem] { |
||||||
|
return (0..<self._columnCount()).map { _ in GridItem(spacing: 10.0) } |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
struct TimersView_Previews: PreviewProvider { |
||||||
|
static var previews: some View { |
||||||
|
TimersView(isEditing: .constant(false)) |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue