What
The Park screen now drives two always-on TimelineView(.periodic(from: .now, by: 1)):
MeterHero — the countdown, its progress bar, and the state evaluation;
detailsCard — the "Parked for h:mm:ss" line.
Both tick every second for as long as the screen is open, and the hero's tick re-evaluates MeterState and re-renders a ProgressView. The elapsed timer predates the redesign; the hero is new, so the screen now does roughly twice the per-second work it used to.
Why it may matter here specifically
This is a screen people leave open while walking back to a car — outdoors, on cellular, often on a phone that has been out all day. It is close to the worst case for an always-on 1 Hz redraw.
What has not been established
Nothing has been measured. This is a flagged concern, not a demonstrated defect:
- no Instruments trace of the Park screen idling with a meter set;
- no comparison against the pre-redesign single timer;
- no check of what Low Power Mode should do.
AGENTS.md requires Reduce Motion support. A per-second numeric update is arguably not "motion", but a continuously animating progress bar is closer to the line, and the question has not been asked.
Suggested approach
Measure first. If it is negligible, close this with the number and stop worrying about it. If it is not:
- one
TimelineView for the whole screen instead of two;
- drop to
.periodic(by: 60) once the remaining time is over an hour, where seconds carry no information;
- consider
@Environment(\.accessibilityReduceMotion) for the progress bar's animation only, never for the countdown itself — suppressing the number would remove information rather than motion.
Acceptance
Resolution plan
- Verified: 2026-08-25T04:51:19Z against
main@04a6cd5e808720983471ee9595fd40bc94e1f0fe (commit time 2026-08-25T00:53:29Z).
- Source basis: Original issue body, all 0 comment(s), current default-branch tree, referenced pull-request states, and the protected top-90 dossier revalidated without modifying it.
- Disposition: Code or verification work - not complete on the verified default branch.
- Outcome: Park screen redraws at 1 Hz whenever it is open, with no low-power or Reduce Motion consideration
Current evidence and corrected premise
Verdict — NOT_STARTED. Two exact sites confirmed.
ParkNudge/UI/Park/ParkView.swift:
:162 TimelineView(.periodic(from: .now, by: 1)) { context in
:319 TimelineView(.periodic(from: .now, by: 1)) { context in
Two independent 1 Hz timelines in one screen. Each rebuilds its subtree every second for as long as
the view is on screen, regardless of whether anything visible changed, whether the device is in Low
Power Mode, or whether the user has asked for Reduce Motion.
P2 · accessibility, area: ios, priority:p2, revenue:r3 · Canonical source: origin/main
All 0 issue comment(s) were read. There are no comments.
Verified source paths on this head:
AGENTS.md
ParkNudge/UI/Park/ParkView.swift
ParkNudgeTests/MeterStateTests.swift
Resolution steps
Exact fix
- Drop the cadence when seconds are not visible. If the label reads "2h 14m", a 1 Hz tick is
~119 wasted rebuilds per minute. Use .periodic(by: 1) only while the remaining time is under a
minute (or whatever threshold makes the seconds digit meaningful); otherwise by: 60. This alone
removes almost all of the cost.
- Honour Low Power Mode —
ProcessInfo.processInfo.isLowPowerModeEnabled, and observe
.NSProcessInfoPowerStateDidChange so it reacts rather than sampling once at launch.
- Honour Reduce Motion —
@Environment(\.accessibilityReduceMotion). Where the timeline drives
an animation rather than a text update, this should stop it entirely, not slow it.
- Collapse the two timelines into one if both drive the same clock. Two independent periodic
sources in one view means two rebuild storms with no shared phase.
Keep the countdown correct — recompute from a stored expiry Date, never by decrementing a
counter, so a slower tick or a missed one cannot drift.
Tests and acceptance
Test / proof
ParkNudgeTests/MeterStateTests.swift already tests the state transitions; extend the same seam
with a test that the chosen tick interval is 60 when remaining time is large and 1 when small.
Battery behaviour itself is not unit-testable — verify by observing that the view body evaluates at
the expected cadence (a counter incremented in the timeline closure under test).
Gate — the repo's unit scheme
- For every listed
xcodebuild argv, submit the equivalent focused job through the shared fleet-build gate after iOS capacity admission; do not run xcodebuild directly.
Dependencies and stop gates
Out of scope — #29's meter hero states; general animation policy elsewhere in the app
- Do not close this issue until every acceptance item is mapped to exact merged-head evidence.
Next AI first action
Drop the cadence when seconds are not visible.** If the label reads "2h 14m", a 1 Hz tick is
What
The Park screen now drives two always-on
TimelineView(.periodic(from: .now, by: 1)):MeterHero— the countdown, its progress bar, and the state evaluation;detailsCard— the "Parked for h:mm:ss" line.Both tick every second for as long as the screen is open, and the hero's tick re-evaluates
MeterStateand re-renders aProgressView. The elapsed timer predates the redesign; the hero is new, so the screen now does roughly twice the per-second work it used to.Why it may matter here specifically
This is a screen people leave open while walking back to a car — outdoors, on cellular, often on a phone that has been out all day. It is close to the worst case for an always-on 1 Hz redraw.
What has not been established
Nothing has been measured. This is a flagged concern, not a demonstrated defect:
AGENTS.mdrequires Reduce Motion support. A per-second numeric update is arguably not "motion", but a continuously animating progress bar is closer to the line, and the question has not been asked.Suggested approach
Measure first. If it is negligible, close this with the number and stop worrying about it. If it is not:
TimelineViewfor the whole screen instead of two;.periodic(by: 60)once the remaining time is over an hour, where seconds carry no information;@Environment(\.accessibilityReduceMotion)for the progress bar's animation only, never for the countdown itself — suppressing the number would remove information rather than motion.Acceptance
Resolution plan
main@04a6cd5e808720983471ee9595fd40bc94e1f0fe(commit time 2026-08-25T00:53:29Z).Current evidence and corrected premise
Verdict — NOT_STARTED. Two exact sites confirmed.
ParkNudge/UI/Park/ParkView.swift:Two independent 1 Hz timelines in one screen. Each rebuilds its subtree every second for as long as
the view is on screen, regardless of whether anything visible changed, whether the device is in Low
Power Mode, or whether the user has asked for Reduce Motion.
P2 ·
accessibility, area: ios, priority:p2, revenue:r3· Canonical source:origin/mainAll 0 issue comment(s) were read. There are no comments.
Verified source paths on this head:
AGENTS.mdParkNudge/UI/Park/ParkView.swiftParkNudgeTests/MeterStateTests.swiftResolution steps
Exact fix
~119 wasted rebuilds per minute. Use
.periodic(by: 1)only while the remaining time is under aminute (or whatever threshold makes the seconds digit meaningful); otherwise
by: 60. This aloneremoves almost all of the cost.
ProcessInfo.processInfo.isLowPowerModeEnabled, and observe.NSProcessInfoPowerStateDidChangeso it reacts rather than sampling once at launch.@Environment(\.accessibilityReduceMotion). Where the timeline drivesan animation rather than a text update, this should stop it entirely, not slow it.
sources in one view means two rebuild storms with no shared phase.
Keep the countdown correct — recompute from a stored expiry
Date, never by decrementing acounter, so a slower tick or a missed one cannot drift.
Tests and acceptance
Test / proof
ParkNudgeTests/MeterStateTests.swiftalready tests the state transitions; extend the same seamwith a test that the chosen tick interval is 60 when remaining time is large and 1 when small.
Battery behaviour itself is not unit-testable — verify by observing that the view body evaluates at
the expected cadence (a counter incremented in the timeline closure under test).
Gate — the repo's unit scheme
xcodebuildargv, submit the equivalent focused job through the shared fleet-build gate after iOS capacity admission; do not runxcodebuilddirectly.Dependencies and stop gates
Out of scope — #29's meter hero states; general animation policy elsewhere in the app
Next AI first action
Drop the cadence when seconds are not visible.** If the label reads "2h 14m", a 1 Hz tick is