wip and fix

splits
Laurent 2 years ago
parent 2871a7abaa
commit 676fb0e97b
  1. 60
      LaunchWidget/LaunchWidgetLiveActivity.swift
  2. 14
      LeCountdown/Conductor.swift
  3. 39
      LeCountdown/CountdownSequence.swift
  4. 10
      LeCountdown/Views/DialView.swift
  5. 2
      LeCountdown/Views/TimersView.swift
  6. 3
      LeCountdown/Widget/LaunchWidgetAttributes.swift

@ -29,25 +29,34 @@ struct LiveActivityView: View {
struct LaunchWidgetLiveActivity: Widget {
fileprivate let now: Date = Date()
var body: some WidgetConfiguration {
ActivityConfiguration(for: LaunchWidgetAttributes.self) { context in
// Lock screen/banner UI goes here
VStack(alignment: .leading) {
// TimelineView(.periodic(from: self.now, by: 0.1)) { _ in
if context.attributes.isTimer {
let range = Date()...context.attributes.date
Text(timerInterval: range,
pauseTime: range.lowerBound)
.font(.title)
} else {
Text(context.attributes.date, style: .timer)
// Lock screen/banner UI goes here
VStack(alignment: .leading) {
let date: Date = self._date(context: context)
let name: String = self._name(context: context)
if context.attributes.isCountdown {
let range = Date()...date
Text(timerInterval: range,
pauseTime: range.lowerBound)
.font(.title)
} else {
Text(context.attributes.date, style: .timer)
.font(.title)
}
Text(name.uppercased())
.font(.callout)
}
Text(context.attributes.name.uppercased())
.font(.callout)
}
// }
.padding()
.monospaced()
.background(Color(white: 0.1))
@ -60,10 +69,12 @@ struct LaunchWidgetLiveActivity: Widget {
DynamicIslandExpandedRegion(.leading) {
Text(context.attributes.name.uppercased())
.monospaced()
.padding(.leading, 4.0)
}
DynamicIslandExpandedRegion(.trailing) {
Text(context.attributes.date, style: .timer)
.monospaced()
.padding(.trailing, 4.0)
}
DynamicIslandExpandedRegion(.bottom) {
Button {
@ -76,7 +87,7 @@ struct LaunchWidgetLiveActivity: Widget {
Text(context.attributes.name.uppercased())
} compactTrailing: {
Group {
if context.attributes.isTimer {
if context.attributes.isCountdown {
let range = Date()...context.attributes.date
Text(timerInterval: range,
pauseTime: range.lowerBound)
@ -85,7 +96,7 @@ struct LaunchWidgetLiveActivity: Widget {
}
}.multilineTextAlignment(.trailing)
} minimal: {
if context.attributes.isTimer {
if context.attributes.isCountdown {
let range = Date()...context.attributes.date
Text(timerInterval: range,
pauseTime: range.lowerBound)
@ -100,9 +111,26 @@ struct LaunchWidgetLiveActivity: Widget {
}
}
fileprivate func _name(context: ActivityViewContext<LaunchWidgetAttributes>) -> String {
if let name = context.state.sequence?.currentStep.name {
return name
} else {
return context.attributes.name
}
}
fileprivate func _date(context: ActivityViewContext<LaunchWidgetAttributes>) -> Date {
if let date = context.state.sequence?.currentStep.interval.end {
return date
} else {
return context.attributes.date
}
}
fileprivate func _stop() {
}
}
struct LaunchWidgetLiveActivity_Previews: PreviewProvider {
@ -110,7 +138,7 @@ struct LaunchWidgetLiveActivity_Previews: PreviewProvider {
static let attributes = LaunchWidgetAttributes(
id: "",
name: "Tea",
date: Date().addingTimeInterval(3600.0), isTimer: true)
date: Date().addingTimeInterval(3600.0), isCountdown: true)
static let contentState = LaunchWidgetAttributes.ContentState(ended: false)

@ -93,8 +93,8 @@ class Conductor: ObservableObject {
fileprivate func _buildLiveTimers() {
let liveCountdowns: [LiveTimer] = self.currentCountdowns.map { id, sequence in
let currentSpan = sequence.currentSpan
return LiveTimer(id: id, name: currentSpan.label, date: currentSpan.end)
let currentStep = sequence.currentStep
return LiveTimer(id: id, name: currentStep.label, date: currentStep.end)
}
// add countdown if not present
for liveCountdown in liveCountdowns {
@ -217,6 +217,7 @@ class Conductor: ObservableObject {
// let countdownId = countdown.stringId
FileLogger.log("schedule countdown \(step.name ?? "''") at \(end)")
Logger.log("schedule countdown \(step.name ?? "''") at \(end)")
let sound = step.someSound ?? countdown.someSound ?? Sound.default
@ -300,7 +301,7 @@ class Conductor: ObservableObject {
func resumeCountdown(id: TimerID) throws {
let now = Date()
// let now = Date()
let context = PersistenceController.shared.container.viewContext
if let countdown: Countdown = context.object(stringId: id),
@ -325,7 +326,6 @@ class Conductor: ObservableObject {
// self.currentCountdowns[countdown.stringId] = CountdownSequence(steps: steps)
// TODO: RESUME
// _ = try self._scheduleSoundPlayer(countdown: countdown, in: remainingTime)
} else {
throw AppError.timerNotFound(id: id)
@ -628,12 +628,14 @@ class Conductor: ObservableObject {
fileprivate func _launchLiveActivity(timer: AbstractTimer, date: Date) {
guard let sequence = self.currentCountdowns[timer.stringId] else { return }
if #available(iOS 16.2, *) {
if ActivityAuthorizationInfo().areActivitiesEnabled {
let contentState = LaunchWidgetAttributes.ContentState(ended: false)
let attributes = LaunchWidgetAttributes(id: timer.stringId, name: timer.displayName, date: date, isTimer: timer is Countdown)
let contentState = LaunchWidgetAttributes.ContentState(ended: false, sequence: sequence)
let attributes = LaunchWidgetAttributes(id: timer.stringId, name: timer.displayName, date: date, isCountdown: timer is Countdown)
let activityContent = ActivityContent(state: contentState, staleDate: nil)
do {

@ -8,7 +8,8 @@
import Foundation
import CoreData
class CountdownSequence: Codable {
class CountdownSequence: Codable, Equatable, Hashable {
var steps: [CountdownStep]
var pauseDate: Date? = nil
@ -17,7 +18,7 @@ class CountdownSequence: Codable {
self.pauseDate = pauseDate
}
var currentSpan: CountdownStep {
var currentStep: CountdownStep {
let referenceDate = self.pauseDate ?? Date()
let current: CountdownStep? = self.steps.first { span in
return span.interval.start < referenceDate && span.interval.end > referenceDate
@ -26,7 +27,7 @@ class CountdownSequence: Codable {
}
var currentEnd: Date {
return self.currentSpan.interval.end
return self.currentStep.interval.end
}
var dateInterval: DateInterval {
@ -67,11 +68,23 @@ class CountdownSequence: Codable {
self.pauseDate = nil
}
// MARK: - Equatable / Hashable
static func == (lhs: CountdownSequence, rhs: CountdownSequence) -> Bool {
return lhs.steps == rhs.steps && lhs.pauseDate == rhs.pauseDate
}
func hash(into hasher: inout Hasher) {
hasher.combine(steps)
hasher.combine(pauseDate)
}
private static let defaultSpan = CountdownStep(interval: DateInterval(start: Date(), end: Date()), name: "none", index: 0, loopCount: 1, stepId: "")
}
class CountdownStep: Codable {
class CountdownStep: Codable, Equatable, Hashable {
var interval: DateInterval
var name: String?
var index: Int16
@ -115,4 +128,22 @@ class CountdownStep: Codable {
self.interval = DateInterval(start: start, end: end)
}
// MARK: - Equatable / Hashable
static func == (lhs: CountdownStep, rhs: CountdownStep) -> Bool {
return lhs.interval == rhs.interval
&& lhs.name == rhs.name
&& lhs.index == rhs.index
&& lhs.loopCount == rhs.loopCount
&& lhs.stepId == rhs.stepId
}
func hash(into hasher: inout Hasher) {
hasher.combine(interval)
hasher.combine(name)
hasher.combine(index)
hasher.combine(loopCount)
hasher.combine(stepId)
}
}

@ -67,10 +67,10 @@ struct DialView: View {
}
.background(self._dialBackgroundColor)
.frame(width: frameSize, height: self._height)
.frame(width: self.frameSize, height: self._height)
.cornerRadius(20.0)
}
fileprivate var _height: CGFloat {
return UIDevice.isPhoneIdiom ? 80.0 : 200.0
}
@ -94,13 +94,15 @@ struct DialView: View {
Group {
switch self.timer {
case let countdown as Countdown:
CountdownDialView(countdown: countdown, isEditing: self.isEditingBinding.wrappedValue)
CountdownDialView(countdown: countdown,
isEditing: self.isEditingBinding.wrappedValue)
.environmentObject(Conductor.maestro)
case let alarm as Alarm:
AlarmDialView(alarm: alarm)
.environmentObject(Conductor.maestro)
case let stopwatch as Stopwatch:
StopwatchDialView(stopwatch: stopwatch, isEditing: self.isEditingBinding.wrappedValue)
StopwatchDialView(stopwatch: stopwatch,
isEditing: self.isEditingBinding.wrappedValue)
.environmentObject(Conductor.maestro)
default:
Text("missing dial view")

@ -34,7 +34,7 @@ struct TimersView: View {
GeometryReader { reader in
let columns: [GridItem] = self._columns()
let width: CGFloat = reader.size.width / CGFloat(columns.count) - 5.0
let width: CGFloat = max(reader.size.width / CGFloat(columns.count) - 5.0, 0.0)
ScrollView {

@ -12,12 +12,13 @@ struct LaunchWidgetAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable {
// Dynamic stateful properties about your activity go here!
var ended: Bool
var sequence: CountdownSequence? = nil
}
// Fixed non-changing properties about your activity go here!
var id: String
var name: String
var date: Date
var isTimer: Bool
var isCountdown: Bool
}

Loading…
Cancel
Save