Post

Replies

Boosts

Views

Activity

Reply to Custom `DiscreteFormatStyle` in live activities
Ok, some of the code was wrong.. I have just updated the playground, even adding some other formatter for the purposes of checking, that would show the time as mm:ss, but the original question remains the same, and it would be about using the MatchFormatStyle in the context of live activities. import Foundation import SwiftUI import PlaygroundSupport extension Duration { struct MatchFormatStyle: DiscreteFormatStyle, Sendable { let periodLength: Int let overtime: Int func format(_ value: Duration) -> String { let (seconds, _): (Int64, Int64) = value.components let current: Int = ((periodLength + overtime) * 60 + Int(seconds)) / 60 if current > periodLength { return "\(periodLength)' (+\(current - periodLength))" } else { return "\(current)'" } } func discreteInput(before input: Duration) -> Duration? { let (seconds, _): (Int64, Int64) = input.components return Duration(secondsComponent: (seconds / 60) * 60, attosecondsComponent: .zero) } func discreteInput(after input: Duration) -> Duration? { let (seconds, _): (Int64, Int64) = input.components return Duration(secondsComponent: (seconds / 60 - 1) * 60, attosecondsComponent: .zero) } } } extension FormatStyle where Self == Duration.MatchFormatStyle { static func matchTime(currentTime: Int, periodLength: Int) -> Duration.MatchFormatStyle { return Duration.MatchFormatStyle(periodLength: periodLength, overtime: max(currentTime - periodLength, .zero)) } } extension Duration { struct MatchSecondsFormatStyle: DiscreteFormatStyle, Sendable { let periodLength: Int let overtime: Int func format(_ value: Duration) -> String { let (seconds, _): (Int64, Int64) = value.components let current: Int = (periodLength + overtime) * 60 + Int(seconds) return "\(String(format: "%02d", current / 60)):\(String(format: "%02d", current % 60))" } func discreteInput(before input: Duration) -> Duration? { let (seconds, _): (Int64, Int64) = input.components return Duration(secondsComponent: seconds, attosecondsComponent: .zero) } func discreteInput(after input: Duration) -> Duration? { let (seconds, _): (Int64, Int64) = input.components return Duration(secondsComponent: seconds - 1, attosecondsComponent: .zero) } } } extension FormatStyle where Self == Duration.MatchSecondsFormatStyle { static func matchSecondsTime(currentTime: Int, periodLength: Int) -> Duration.MatchSecondsFormatStyle { return Duration.MatchSecondsFormatStyle(periodLength: periodLength, overtime: max(currentTime - periodLength, .zero)) } } extension TimeDataSource<Date> { static func matchDuration(for currentTime: Int, periodLength: Int) -> TimeDataSource<Duration> { let minutesAhead: Double = Double(max(periodLength - currentTime, .zero)) return TimeDataSource<Date>.durationOffset(to: Date.now.addingTimeInterval(minutesAhead * 60)) } } struct FooView: View { let currentTime: Int = 45 let periodLength: Int = 45 var body: some View { Text( TimeDataSource<Date>.matchDuration(for: currentTime, periodLength: periodLength), format: .matchTime(currentTime: currentTime, periodLength: periodLength) ) .frame(width: 400, height: 200) .font(.system(size: 50)) Text( TimeDataSource<Date>.matchDuration(for: currentTime, periodLength: periodLength), format: .matchSecondsTime(currentTime: currentTime, periodLength: periodLength) ) .frame(width: 400, height: 200) .font(.system(size: 50)) } } // Present the view controller in the Live View window PlaygroundPage.current.setLiveView(FooView())
Topic: App & System Services SubTopic: General Tags:
Feb ’25