Skip to content

fix(ios): keep the lock screen Live Activity moving on the always-on display - #171

Merged
ififi2017 merged 1 commit into
mainfrom
fix/ios-aod-live-activity
Sep 10, 2026
Merged

fix(ios): keep the lock screen Live Activity moving on the always-on display#171
ififi2017 merged 1 commit into
mainfrom
fix/ios-aod-live-activity

Conversation

@ififi2017

Copy link
Copy Markdown
Owner

What the user saw

The off-work countdown froze on the dimmed lock screen. A 15 minute countdown showed "14 minutes" and stayed there until the phone was picked up.

Why

Two parts of the lock-screen card were drawn from timeline.date, which only changes when iOS wakes the widget extension for another frame. The always-on display does not do that — the update schedule's own comment already says the boundaries are best-effort redraw requests and the extension can be suspended across all of them.

The countdown. It switched to a hand-computed "N minutes" string the moment isLuminanceReduced turned true, so it froze at whatever minute the screen dimmed on (ceil is why 13:xx read as 14). Text(timerInterval:) is animated by the render server while the extension sleeps, so the card now uses it in both states. Coarsening the digits on a dimmed screen is the system's call, and it already makes it — that is what the surrounding comment about a "coarse localized duration" was recording.

The progress bar. The work countdown's bar was a hand-drawn Capsule whose width came from activityProgressValue(_:at:), so it stayed frozen even after the digits moved again. It cannot simply become one ProgressView(timerInterval:) across the shift: that would count the lunch gap as worked time, against the effective-segment rule. It is now one bar per effective segment, each filling over its own interval and sized by its share of the effective duration. During lunch no bar advances, which is the same arithmetic projectedProgress does. The focus card already drew itself this way.

Checks

  • npm run build:ios-native-rules, npm run check:ios
  • xcodebuild -scheme App -destination 'platform=iOS Simulator,name=iPhone 17 Pro' build — succeeded, no warnings; OffWorkWidgets.swift recompiled in the widget target

Not verified

Always-on display cannot be reproduced in the simulator, and per the repo's rule simulator visual QA was not requested. This needs a device with the screen dimmed: leave a shift running, let the display dim, and confirm the digits keep counting and the bar keeps filling. The one visual change worth a look on device is the seam the per-segment bars leave at the lunch boundary.

🤖 Generated with Claude Code

…display

The off-work countdown froze on the dimmed lock screen: a 15 minute
countdown sat at "14 minutes" until the phone was picked up again.

Two things on that card were drawn from `timeline.date` — a value that
only changes when iOS wakes the widget extension for another frame. The
always-on display does not do that, which the schedule's own comment
already says: the boundaries are best-effort redraw requests and the
extension can be suspended across all of them.

The countdown was the visible half. It switched to a hand-computed
"N minutes" string as soon as `isLuminanceReduced` turned true, so it
froze at whatever minute the screen dimmed on. `Text(timerInterval:)` is
animated by the render server with the extension asleep, so the card now
keeps it in both states; coarsening the digits on a dimmed screen is the
system's call to make, and it already makes it.

The work countdown's progress bar was the other half, and it stayed
frozen while the digits moved. It cannot become one
`ProgressView(timerInterval:)` across the shift, because that would count
the lunch gap as worked time. It is now one bar per effective segment,
each filling over its own interval and sized by its share of the
effective duration — the same arithmetic `projectedProgress` does, drawn
by the render server instead of by us. The focus card already worked this
way.

Built for the simulator; both targets compile clean. Always-on behaviour
cannot be reproduced in the simulator, so this needs a device with the
screen dimmed to confirm.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
off-work-30 Ready Ready Preview Sep 10, 2026 11:18am UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant