From 5dd30f7a1d6c5d6c489e3c1fa36893d00dcf1688 Mon Sep 17 00:00:00 2001 From: Ludwig <62896243+ludwig-pro@users.noreply.github.com> Date: Tue, 17 Feb 2026 11:03:48 +0100 Subject: [PATCH 1/3] fix(ios): add missing monospacedDigit to relative timer text Adds .monospacedDigit() modifier to relative style timer text and static zero text to ensure consistent digit width rendering across all timer display modes. The other timer text views already had this modifier applied. --- ios/ui/Views/VoltraTimer.swift | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/ios/ui/Views/VoltraTimer.swift b/ios/ui/Views/VoltraTimer.swift index 27b7903c..c78adee2 100644 --- a/ios/ui/Views/VoltraTimer.swift +++ b/ios/ui/Views/VoltraTimer.swift @@ -13,12 +13,12 @@ public struct VoltraTimer: VoltraView { // Stopwatch support: if counting up (not down) and we have a start time // but no end time or duration, treat it as an open-ended stopwatch. if !countsDown(params: params), - let startAtMs = params.startAtMs, - params.endAtMs == nil, - params.durationMs == nil + let startAtMs = params.startAtMs, + params.endAtMs == nil, + params.durationMs == nil { let start = Date(timeIntervalSince1970: startAtMs / 1000) - return start ... Date.distantFuture + return start...Date.distantFuture } return VoltraProgressDriver.resolveRange( @@ -28,7 +28,9 @@ public struct VoltraTimer: VoltraView { ) } - private func resolvedEndDate(params: TimerParameters) -> Date? { progressRange(params: params)?.upperBound } + private func resolvedEndDate(params: TimerParameters) -> Date? { + progressRange(params: params)?.upperBound + } private func countsDown(params: TimerParameters) -> Bool { (params.direction.lowercased()) != "up" @@ -45,7 +47,8 @@ public struct VoltraTimer: VoltraView { private func textTemplates(params: TimerParameters) -> TextTemplates? { guard let raw = params.textTemplates, - let data = raw.data(using: .utf8) else { return nil } + let data = raw.data(using: .utf8) + else { return nil } return try? JSONDecoder().decode(TextTemplates.self, from: data) } @@ -87,7 +90,7 @@ public struct VoltraTimer: VoltraView { if style == "relative" { let targetDate = isCountDown ? range.upperBound : range.lowerBound - Text(targetDate, style: .relative) + Text(targetDate, style: .relative).monospacedDigit() } else { // Live Activities require Text(timerInterval:...) for automatic updates Text(timerInterval: range, countsDown: isCountDown, showsHours: showHours) @@ -98,7 +101,7 @@ public struct VoltraTimer: VoltraView { @ViewBuilder private func staticZeroText(style: String, showHours: Bool) -> some View { if style == "relative" { - Text("0s") + Text("0s").monospacedDigit() } else { Text(showHours ? "0:00:00" : "0:00") .monospacedDigit() @@ -106,7 +109,9 @@ public struct VoltraTimer: VoltraView { } @ViewBuilder - private func renderTemplate(template: String, @ViewBuilder timeView: @escaping () -> T) -> some View { + private func renderTemplate(template: String, @ViewBuilder timeView: @escaping () -> T) + -> some View + { let placeholder = "{time}" let segments = template.components(separatedBy: placeholder) From ccd28c7082240539d7c51184b46808888e1c7a66 Mon Sep 17 00:00:00 2001 From: Szymon Chmal Date: Mon, 9 Mar 2026 09:00:10 +0100 Subject: [PATCH 2/3] chore: add changeset --- .changeset/timer-monospaced-digit-fix.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/timer-monospaced-digit-fix.md diff --git a/.changeset/timer-monospaced-digit-fix.md b/.changeset/timer-monospaced-digit-fix.md new file mode 100644 index 00000000..4346c7ee --- /dev/null +++ b/.changeset/timer-monospaced-digit-fix.md @@ -0,0 +1,5 @@ +--- +'voltra': patch +--- + +Fix timer digits shifting during countdown and stopwatch in relative mode. From 5e77d0d84cdd3c2145fe64e66cc8538eb8e0d01f Mon Sep 17 00:00:00 2001 From: Szymon Chmal Date: Mon, 9 Mar 2026 09:00:53 +0100 Subject: [PATCH 3/3] chore: reformat --- ios/ui/Views/VoltraTimer.swift | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/ios/ui/Views/VoltraTimer.swift b/ios/ui/Views/VoltraTimer.swift index c78adee2..cc2924d6 100644 --- a/ios/ui/Views/VoltraTimer.swift +++ b/ios/ui/Views/VoltraTimer.swift @@ -13,12 +13,12 @@ public struct VoltraTimer: VoltraView { // Stopwatch support: if counting up (not down) and we have a start time // but no end time or duration, treat it as an open-ended stopwatch. if !countsDown(params: params), - let startAtMs = params.startAtMs, - params.endAtMs == nil, - params.durationMs == nil + let startAtMs = params.startAtMs, + params.endAtMs == nil, + params.durationMs == nil { let start = Date(timeIntervalSince1970: startAtMs / 1000) - return start...Date.distantFuture + return start ... Date.distantFuture } return VoltraProgressDriver.resolveRange( @@ -47,7 +47,7 @@ public struct VoltraTimer: VoltraView { private func textTemplates(params: TimerParameters) -> TextTemplates? { guard let raw = params.textTemplates, - let data = raw.data(using: .utf8) + let data = raw.data(using: .utf8) else { return nil } return try? JSONDecoder().decode(TextTemplates.self, from: data) } @@ -129,9 +129,3 @@ public struct VoltraTimer: VoltraView { } } } - -// MARK: - Formatters - -extension VoltraTimer { - // Formatters are no longer needed for live updates but kept if we need static fallbacks. -}