Skip to content

Watch complications on WidgetKit, with migration from ClockKit - #2562

Draft
jeremybarnum wants to merge 5 commits into
LoopKit:next-devfrom
jeremybarnum:complications/stock-widgetkit
Draft

jeremybarnum wants to merge 5 commits into
LoopKit:next-devfrom
jeremybarnum:complications/stock-widgetkit

Conversation

@jeremybarnum

Copy link
Copy Markdown

Watch complications on WidgetKit, with migration from ClockKit. No Sport Mode code; branched from next-dev.

Current watchOS no longer takes new ClockKit complications, and ClockKit is deprecated. This moves Loop's two watch complications, "Loop Status" and "Glucose Graph", to a WidgetKit extension, at parity with today:

  • A widget extension, "Loop Complications" ($(MAIN_APP_BUNDLE_IDENTIFIER).LoopWatch.Complications), sharing an app group with the watch app. On every context update the watch app publishes a ComplicationSnapshot to the app group, formatted with the same formatters and localized strings the ClockKit templates use, so the extension links nothing of Loop's.
  • The same two complications: Loop Status (inline, corner, circular): the reading and its trend, the loop's freshness colour, and the same inline line as today ("106↗ 108 8:47 PM"). Glucose Graph (rectangular): the reading over the chart of recent and predicted glucose, drawn by the existing ComplicationChartManager and handed to the widget as an image.
  • Reloads only when something shown changed, at most every five minutes, and only Loop's own kinds (WidgetKit budgets reloads per widget). The timeline carries the moments the reading goes stale and the loop's colour turns, so those need no reload.
  • Migration: a ClockKit widgetMigrator moves faces showing the old complications to the new ones when the app updates. The two ClockKit descriptors share the identifier "glucosegraph", so the migrator tells them apart by family.
  • Tests: ComplicationSnapshotTests (what shows at each moment, the change moments, the reload throttle).

Open items

  • A test on a real watch of the migration (old ClockKit complication on a face → install → still there) before the ClockKit timeline code is deleted.
  • The duplicate "glucosegraph" identifier in the two ClockKit descriptors looks like a slip.
  • Browser build / fastlane need the new extension's bundle ID and app group.
  • The first device install needs Xcode signed in (new bundle ID and app group).

Related: the Sport Mode "Loop Glance" complication builds on this (linked below).

🤖 Generated with Claude Code

Jeremy Barnum and others added 3 commits October 4, 2026 10:09
ClockKit is deprecated and current watchOS no longer offers new ClockKit complications. This adds a
watchOS widget extension, Loop Complications, carrying the same two complications the app offers today:

- Loop Status (inline, corner, circular): the reading and its trend, the loop's freshness colour,
  the stock inline line ("106↗ 108 8:47 PM").
- Glucose Graph (rectangular): the reading over the chart of recent and predicted glucose, drawn by the
  existing ComplicationChartManager and handed to the widget as an image.

The watch app publishes a ComplicationSnapshot to the shared app group on every context update,
formatted with the same formatters and localized strings the ClockKit templates use, so the extension
links nothing of Loop's. Reloads are requested only when something shown changed and at most every five
minutes (WidgetKit budgets them); the timeline carries the moments the reading goes stale and the loop's
colour turns, so those need no reload.

ComplicationController gains a ClockKit widget migrator, so faces showing the old complications move to
the new ones when the app updates. The two ClockKit descriptors share the identifier "glucosegraph", so
the migrator tells them apart by family.

The watch app gains an entitlements file with the app group and an AppGroupIdentifier key. Builds that
create their identifiers outside Xcode (e.g. the browser build) will need the new extension identifier
and the app group on the watch identifier.

Tests: ComplicationSnapshotTests in LoopTests — what shows at each moment, the change moments, the
reload throttle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WidgetKit budgets reloads per widget, so the publisher reloads LoopStatus and GlucoseGraph by kind
rather than every timeline the app has. ComplicationReloadThrottle takes any Equatable snapshot, so a
second publisher can keep its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Jeremy Barnum and others added 2 commits October 13, 2026 22:00
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
EJM0 added a commit to EJM0/Trio that referenced this pull request Oct 20, 2026
…s for glucose, IOB and COB

Sensor:
- New setting Watch Reads the Sensor (Apple Watch › Sensor, on by default). The phone sends the
  CGM's export with the watch state (without its time, so an unchanged sensor leaves the state
  unchanged) and the range and color scheme it colors readings by; the watch persists both.
- Outside a session the watch keeps the same G7 manager untethered mode uses: it starts and
  stops with the setting, a new sensor rebuilds it, and a session start or end keeps it. Its
  readings show on the watch until the phone's copy arrives, colored as the phone colors them.
- The hint lists what goes without it: glucose only from the phone, far fewer complication
  updates, and untethered mode starting without readings.

Complications, after kristinkand/Trio 73c64f2 and LoopKit/Loop#2562/#2563:
- The watch app writes a snapshot to the Trio app group; the watch app and the complication get
  the app group entitlement.
- Glucose: circular as Trio's bubble in the loop ring with the reading's time, corner, inline,
  and rectangular with IOB in insulin blue, COB in orange, the reading's time and 3 hours over
  the target range. New: Insulin on Board, Carbs on Board, and both together.
- Ages, the ring's color and staleness advance from timeline entries. In the background the
  watch reloads at most once per 300 s window; the phone's complication transfer wakes the
  watch at most every 28 minutes.

Co-Authored-By: Kristin Kandschur <kristin.kandschur@proton.me>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant