feat: system widgets foundation + price widget#895
Conversation
# Conflicts: # CHANGELOG.md
|
some improvements like constant extractions implemented in #914 |
This comment has been minimized.
This comment has been minimized.
|
I tested on device, works as described, except it did not seem to update price for me automatically (waited ~30minutes). Only after I tapped the widget did it reload. Still don't know anything about Kotlin so won't review code. EDIT: have seen it update now |
| } | ||
|
|
||
| @Composable | ||
| private fun PriceConfigContent( |
There was a problem hiding this comment.
CLAUDE.md violation — The inner private composable must be named Content per CLAUDE.md:
ALWAYS split screen composables into parent accepting viewmodel + inner private child accepting state and callbacks
Content()
The codebase consistently uses the literal name Content for the private inner child (e.g. ContactsScreen.kt, ProfileScreen.kt). This should be renamed from PriceConfigContent to Content.
| private fun PriceConfigContent( | |
| private fun Content( |
| val type = typeName?.let { runCatching { AppWidgetType.valueOf(it) }.getOrNull() } | ||
| ?: AppWidgetType.PRICE | ||
|
|
||
| viewModel.init(appWidgetId, type) |
There was a problem hiding this comment.
Bug — viewModel.init() is called unconditionally in onCreate, which runs again on any configuration change (locale switch, font size adjustment, dark/light mode toggle) — not just rotation. At that point the widget hasn't been saved to the DataStore yet, so preferencesStore.getEntry(appWidgetId) returns null and the user's in-progress selections are silently reset to PricePreferences().
Fix: guard with savedInstanceState == null so init only runs on the first launch:
| viewModel.init(appWidgetId, type) | |
| if (savedInstanceState == null) viewModel.init(appWidgetId, type) |
This PR:
Description
Introduces the foundation for Android home screen widgets (AppWidgets) using Jetpack Glance, starting with the Price widget. The widget displays enabled trading pairs with price, change percentage, and a line chart — matching the in-app Price widget layout.
The architecture reuses the existing
PriceServicefor data fetching (via a newfetchData(period)overload) while keeping widget preferences completely independent from the in-app widget system through a dedicatedAppWidgetPreferencesStorebacked by its own DataStore file.A Glance design system (
GlanceTextStyles,GlanceColors) ports the app's typography and color tokens to Glance equivalents, and shared components (GlanceWidgetScaffold,GlanceDataRow) provide consistent widget layouts.Preview
Screen_recording_20260421_153032.webm
QA Notes