Skip to content

Widget: Fix widgets freezing at initial state after first render#561

Merged
d4rken merged 1 commit into
mainfrom
fix/widget-update-after-initial-render
Apr 30, 2026
Merged

Widget: Fix widgets freezing at initial state after first render#561
d4rken merged 1 commit into
mainfrom
fix/widget-update-after-initial-render

Conversation

@d4rken

@d4rken d4rken commented Apr 30, 2026

Copy link
Copy Markdown
Member

What changed

Fixed a bug where the home-screen widgets stopped updating after the first time they appeared. Battery levels, in-ear status, ANC mode, and charging state would freeze at whatever they were when the widget started, even though the rest of the app (notification, popup, settings screen) reflected the correct values.

Technical Context

  • Root cause: Glance only calls GlanceAppWidget.provideGlance() once per widget session — at mount, after process death, or on widget reconfiguration. Subsequent update() / updateAll() calls send an UpdateGlanceState event to the existing session, which only triggers a recomposition of the already-running provideContent { } block. A previous refactor moved data reads (device, isPro, profileLabel) out of the composition into one-time captures at the top of provideGlance. The composition then read those captured local variables — not Compose State — so recompositions produced the same RemoteViews every time.
  • Fix: subscribe to a widgetDeviceFlow(profileId) flow inside provideContent via collectAsState. The flow is pre-deduped by WidgetDeviceKey, so the composition only recomposes on state changes that actually affect rendering — not on every BLE advertisement.
  • WidgetManager rewritten to call widget.update(context, id) per resolved GlanceId rather than widget.updateAll(context), with a fallback to platform AppWidgetManager.getAppWidgetIds(...) when Glance returns no IDs (defensive against the edge case where Glance's internal map is empty but platform widget instances exist).
  • Bonus PodDevice fix: isLeftInEar/isRightInEar now resolve when AAP reports both pods in the same placement and primaryPod is unresolved — previously returned null in that ambiguous case, blanking the widget's wear indicators.

Glance only calls provideGlance() once per widget session; subsequent update() calls recompose the existing composition without re-running provideGlance. The previous capture-once approach left widgets frozen at initial state because the composition had no reactive State to read.

Subscribe to a widgetDeviceFlow(profileId) inside provideContent that pre-filters by WidgetDeviceKey, so the composition recomposes on visible state changes without firing on every BLE advertisement. Replace updateAll() with explicit per-GlanceId update() calls in WidgetManager, with a platform-id fallback when Glance returns no IDs.
@d4rken d4rken merged commit b952aff into main Apr 30, 2026
10 checks passed
@d4rken d4rken deleted the fix/widget-update-after-initial-render branch April 30, 2026 14:45
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