|
|
|
|
@ -82,7 +82,6 @@ struct LiveTimerView: View { |
|
|
|
|
struct LiveStopwatchView: View { |
|
|
|
|
|
|
|
|
|
@Environment(\.managedObjectContext) private var viewContext |
|
|
|
|
@EnvironmentObject var conductor: Conductor |
|
|
|
|
|
|
|
|
|
@State var stopwatch: Stopwatch |
|
|
|
|
|
|
|
|
|
@ -138,7 +137,7 @@ struct LiveStopwatchView: View { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _dismiss() { |
|
|
|
|
conductor.removeLiveTimer(id: self.stopwatch.stringId) |
|
|
|
|
Conductor.maestro.removeLiveTimer(id: self.stopwatch.stringId) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _formattedDuration(date: Date) -> String { |
|
|
|
|
@ -154,19 +153,21 @@ struct LiveStopwatchView: View { |
|
|
|
|
struct LiveCountdownView: View { |
|
|
|
|
|
|
|
|
|
@Environment(\.managedObjectContext) private var viewContext |
|
|
|
|
@EnvironmentObject var conductor: Conductor |
|
|
|
|
|
|
|
|
|
@State var countdown: Countdown |
|
|
|
|
var date: Date |
|
|
|
|
|
|
|
|
|
@State var showConfirmationPopup: Bool = false |
|
|
|
|
|
|
|
|
|
var body: some View { |
|
|
|
|
|
|
|
|
|
TimelineView(.periodic(from: self.date, by: 0.01)) { context in |
|
|
|
|
|
|
|
|
|
let cancelled = Conductor.maestro.isCountdownCancelled(self.countdown) |
|
|
|
|
|
|
|
|
|
HStack { |
|
|
|
|
|
|
|
|
|
let running = self.date > context.date |
|
|
|
|
let cancelled = self.conductor.cancelledCountdowns.contains(where: { $0 == self.countdown.stringId }) |
|
|
|
|
|
|
|
|
|
VStack(alignment: .leading) { |
|
|
|
|
|
|
|
|
|
@ -197,26 +198,71 @@ struct LiveCountdownView: View { |
|
|
|
|
} |
|
|
|
|
.contentShape(Rectangle()) |
|
|
|
|
.onTapGesture { |
|
|
|
|
self._actionHandler() |
|
|
|
|
|
|
|
|
|
if Conductor.maestro.isCountdownCancelled(self.countdown) { |
|
|
|
|
self._dismiss() |
|
|
|
|
} else { |
|
|
|
|
self.showConfirmationPopup = true |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
.frame(height: liveViewSize) |
|
|
|
|
.monospaced() |
|
|
|
|
.fullScreenCover(isPresented: self.$showConfirmationPopup) { |
|
|
|
|
|
|
|
|
|
ZStack { |
|
|
|
|
Color.black.opacity(0.1) |
|
|
|
|
.edgesIgnoringSafeArea(.all) |
|
|
|
|
|
|
|
|
|
let name = self.countdown.displayName |
|
|
|
|
|
|
|
|
|
Button(String(format: NSLocalizedString("Cancel %@", comment: ""), name)) { |
|
|
|
|
self._cancelCountdown() |
|
|
|
|
self.showConfirmationPopup = false |
|
|
|
|
} |
|
|
|
|
.padding() |
|
|
|
|
.foregroundColor(.white) |
|
|
|
|
.background(Color.accentColor) |
|
|
|
|
.cornerRadius(8.0) |
|
|
|
|
.font(.title) |
|
|
|
|
|
|
|
|
|
// Button { |
|
|
|
|
// self._actionHandler() |
|
|
|
|
// self.showConfirmationPopup = false |
|
|
|
|
// } label: { |
|
|
|
|
// Image(systemName: "xmark.circle") |
|
|
|
|
// .font(.system(size: 48.0)).foregroundColor(.accentColor) |
|
|
|
|
// } |
|
|
|
|
}.onTapGesture { |
|
|
|
|
self.showConfirmationPopup = false |
|
|
|
|
} |
|
|
|
|
.background(BackgroundBlurView()) |
|
|
|
|
|
|
|
|
|
// VStack { |
|
|
|
|
// Button { |
|
|
|
|
// self._actionHandler() |
|
|
|
|
// self.showConfirmationPopup = false |
|
|
|
|
// } label: { |
|
|
|
|
// Image(systemName: "xmark.circle") |
|
|
|
|
// .font(.title).foregroundColor(.accentColor) |
|
|
|
|
// } |
|
|
|
|
// }.background(BlurView()) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _actionHandler() { |
|
|
|
|
|
|
|
|
|
FileLogger.log("countdown _actionHandler") |
|
|
|
|
withAnimation { |
|
|
|
|
if conductor.currentCountdowns[self.countdown.stringId] != nil { |
|
|
|
|
if Conductor.maestro.currentCountdowns[self.countdown.stringId] != nil { |
|
|
|
|
self._cancelCountdown() |
|
|
|
|
} else { |
|
|
|
|
self._dismiss() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _dismiss() { |
|
|
|
|
conductor.removeLiveTimer(id: self.countdown.stringId) |
|
|
|
|
withAnimation { |
|
|
|
|
Conductor.maestro.removeLiveTimer(id: self.countdown.stringId) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _formattedDuration(date: Date) -> String { |
|
|
|
|
@ -225,12 +271,23 @@ struct LiveCountdownView: View { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _cancelCountdown() { |
|
|
|
|
Conductor.maestro.cancelCountdown(id: self.countdown.stringId) |
|
|
|
|
withAnimation { |
|
|
|
|
Conductor.maestro.cancelCountdown(id: self.countdown.stringId) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
struct BackgroundBlurView: UIViewRepresentable { |
|
|
|
|
func makeUIView(context: Context) -> UIView { |
|
|
|
|
let view = UIVisualEffectView(effect: UIBlurEffect(style: .light)) |
|
|
|
|
DispatchQueue.main.async { |
|
|
|
|
view.superview?.superview?.backgroundColor = .clear |
|
|
|
|
} |
|
|
|
|
return view |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func updateUIView(_ uiView: UIView, context: Context) {} |
|
|
|
|
} |
|
|
|
|
struct LiveTimerView_Previews: PreviewProvider { |
|
|
|
|
|
|
|
|
|
static var previews: some View { |
|
|
|
|
|