feat: improve compact layouts, chart readability, and medication reminders - #31
feat: improve compact layouts, chart readability, and medication reminders#31YingQiu0871 wants to merge 4 commits into
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
The Wear module debug signing references a missing keystore (build-breaking) and widget updates are triggered from the main dispatcher in MainActivity, risking UI jank/ANRs.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR improves small-width/foldable layouts, boosts chart readability, and expands medication reminders with actionable notifications, while also introducing a Wear OS tile + phone↔watch data layer integration and updating the home-screen widget implementation for broader launcher compatibility.
Changes:
- Refined UI behavior for compact screens (home concentration card auto-sizing/stacking, settings segmented shapes stabilization) and chart readability (responsive X-axis labels, GAHT target band, dose markers as stars).
- Implemented medication reminder notifications with confirm/skip actions, idempotent dose record creation, and rescheduling on reboot/app update/time changes.
- Added Wear OS module (tile UI + plan sync + one-tap dose actions) and replaced the Glance widget with a traditional RemoteViews widget.
File summaries
| File | Description |
|---|---|
| wear/src/test/java/cn/naivetomcat/hrt_tracker/wear/WearDashboardTest.kt | Adds unit coverage for Wear dashboard interpolation logic. |
| wear/src/main/res/values/strings.xml | Introduces Wear app/tile strings. |
| wear/src/main/res/drawable/tile_preview.xml | Adds Wear tile preview vector. |
| wear/src/main/res/drawable/ic_tile_medication.xml | Adds Wear tile icon vector. |
| wear/src/main/java/cn/naivetomcat/hrt_tracker/wear/WearSyncManager.kt | Requests plan sync from phone and triggers tile refresh on boot/update. |
| wear/src/main/java/cn/naivetomcat/hrt_tracker/wear/WearPlanStore.kt | Persists synced plans/dashboard on watch and provides curve positioning helpers. |
| wear/src/main/java/cn/naivetomcat/hrt_tracker/wear/WearPlanListenerService.kt | Receives synced dashboard data and updates the tile. |
| wear/src/main/java/cn/naivetomcat/hrt_tracker/wear/DoseTileService.kt | Implements the Wear tile UI and sends one-tap dose actions to the phone. |
| wear/src/main/AndroidManifest.xml | Declares Wear tile service, listener service, and boot/update receiver. |
| wear/build.gradle.kts | Adds the Wear application module build configuration and dependencies. |
| wear/.gitignore | Ignores Wear build outputs. |
| settings.gradle.kts | Includes the new :wear module. |
| gradle/libs.versions.toml | Adds Wear Tiles/ProtoLayout/Wearable/Guava coordinates. |
| app/src/test/java/cn/naivetomcat/hrt_tracker/wear/WearDataLayerTest.kt | Adds tests for wear curve sampling, plan encoding, and event mapping. |
| app/src/test/java/cn/naivetomcat/hrt_tracker/ui/components/ConcentrationChartLayoutTest.kt | Adds tests for responsive X-axis label count calculation. |
| app/src/test/java/cn/naivetomcat/hrt_tracker/reminder/ReminderDoseFactoryTest.kt | Adds tests for reminder dose-event idempotency and field mapping. |
| app/src/test/java/cn/naivetomcat/hrt_tracker/reminder/DoseCheckInMatcherTest.kt | Adds tests for reminder suppression window and evaluation timing. |
| app/src/main/res/xml/hrt_tracker_widget_info.xml | Updates widget sizing, preview, and resize behavior for the new RemoteViews widget. |
| app/src/main/res/values/strings.xml | Adds reminder/notification strings and updates curve legend + widget description. |
| app/src/main/res/values-zh-rCN/strings.xml | Mirrors the above string additions for zh-CN. |
| app/src/main/res/layout/widget_hrt_tracker.xml | Adds the new RemoteViews widget layout. |
| app/src/main/res/layout/widget_hrt_tracker_preview.xml | Removes the old widget preview layout. |
| app/src/main/res/drawable/widget_panel.xml | Adds widget panel background shape. |
| app/src/main/res/drawable/widget_button.xml | Adds widget button background shape. |
| app/src/main/res/drawable/widget_background.xml | Adds widget background shape. |
| app/src/main/java/cn/naivetomcat/hrt_tracker/widget/WidgetUtils.kt | Refactors plan-dose matching via a shared matcher helper. |
| app/src/main/java/cn/naivetomcat/hrt_tracker/widget/HRTTrackerWidgetReceiver.kt | Replaces Glance widget receiver with RemoteViews widget update + quick record actions. |
| app/src/main/java/cn/naivetomcat/hrt_tracker/widget/HRTTrackerWidgetConfigActivity.kt | Removes the old widget configuration activity. |
| app/src/main/java/cn/naivetomcat/hrt_tracker/widget/HRTTrackerWidget.kt | Removes the old Glance widget implementation. |
| app/src/main/java/cn/naivetomcat/hrt_tracker/wear/WearDataLayer.kt | Adds phone-side Wear data layer sync + action ingestion + curve sampling utilities. |
| app/src/main/java/cn/naivetomcat/hrt_tracker/viewmodel/MedicationPlanViewModel.kt | Ensures rescheduling pulls fresh plans from repository rather than StateFlow snapshot. |
| app/src/main/java/cn/naivetomcat/hrt_tracker/ui/screens/SettingsScreen.kt | Stabilizes segmented option shapes across interaction states. |
| app/src/main/java/cn/naivetomcat/hrt_tracker/ui/screens/MedicationPlansScreen.kt | Adds runtime notification permission + promoted-notification settings entry points. |
| app/src/main/java/cn/naivetomcat/hrt_tracker/ui/screens/HomeScreen.kt | Improves compact layout behavior and adds a curve legend for dose star markers. |
| app/src/main/java/cn/naivetomcat/hrt_tracker/ui/components/ConcentrationChart.kt | Adds responsive X-axis labeling, GAHT target band, and star dose markers. |
| app/src/main/java/cn/naivetomcat/hrt_tracker/reminder/ReminderRescheduleReceiver.kt | Restores alarms after reboot/update/time changes. |
| app/src/main/java/cn/naivetomcat/hrt_tracker/reminder/ReminderManager.kt | Reschedules reminders more robustly (clear stale alarms, schedule window, ±1h evaluation). |
| app/src/main/java/cn/naivetomcat/hrt_tracker/reminder/ReminderDoseFactory.kt | Creates idempotent reminder-confirmation dose events. |
| app/src/main/java/cn/naivetomcat/hrt_tracker/reminder/NotificationHelper.kt | Builds actionable reminder notifications (confirm/skip) and requests promoted ongoing where supported. |
| app/src/main/java/cn/naivetomcat/hrt_tracker/reminder/MedicationReminderReceiver.kt | Defers reminder decision to end of check-in window and reschedules next batch after delivery. |
| app/src/main/java/cn/naivetomcat/hrt_tracker/reminder/MedicationNotificationActionReceiver.kt | Handles notification actions (confirm writes dose event; skip dismisses). |
| app/src/main/java/cn/naivetomcat/hrt_tracker/reminder/DoseCheckInMatcher.kt | Adds stable plan-dose matching + reminder evaluation timing helpers. |
| app/src/main/java/cn/naivetomcat/hrt_tracker/MainActivity.kt | Triggers widget refresh and pushes dashboard updates to Wear. |
| app/src/main/AndroidManifest.xml | Adds promoted notification permission, reschedule receiver, and Wear listener service wiring. |
| app/build.gradle.kts | Removes Glance dependency and adds play-services-wearable. |
Review details
Suppressed comments (3)
app/src/main/res/layout/widget_hrt_tracker.xml:56
- This widget layout also hardcodes the target-range label ("目标 100–200") in XML. This should be a string resource (potentially parameterized) to support localization and future changes.
<TextView
android:id="@+id/widget_target_range"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:maxLines="1"
android:text="目标 100–200"
android:textColor="#FFC5CAFF"
android:textSize="10sp"
android:visibility="gone" />
app/src/main/res/layout/widget_hrt_tracker.xml:98
- The widget’s placeholder/button labels (e.g. "记录用药", "方案一") are hardcoded in XML. These should be moved to string resources to avoid hardcoding Chinese into the default locale and to keep UI copy centralized.
<TextView
android:id="@+id/widget_record_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="6dp"
android:maxLines="1"
android:text="记录用药"
android:textColor="#FFF1F1F7"
android:textSize="12sp"
android:textStyle="bold"
android:visibility="gone" />
<Button
android:id="@+id/widget_plan_one"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@drawable/widget_button"
android:gravity="center"
android:includeFontPadding="false"
android:maxLines="2"
android:minHeight="0dp"
android:minWidth="0dp"
android:padding="4dp"
android:text="方案一"
android:textAllCaps="false"
android:textColor="#FFFFFFFF"
android:textSize="11sp" />
app/src/main/java/cn/naivetomcat/hrt_tracker/widget/HRTTrackerWidgetReceiver.kt:242
- The Toast message text is hardcoded ("已记录:...") instead of coming from a string resource. This prevents localization and makes copy changes harder; prefer
context.getString(...)with a format arg.
updateAllHRTTrackerWidgets(context)
CoroutineScope(Dispatchers.Main).launch {
Toast.makeText(context, "已记录:${plan.name}", Toast.LENGTH_SHORT)
.show()
}
- Files reviewed: 45/45 changed files
- Comments generated: 4
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| signingConfigs { | ||
| getByName("debug") { | ||
| storeFile = file("../app/debugkeystore.jks") | ||
| storePassword = "DEBUG1" | ||
| keyAlias = "DEBUG" | ||
| keyPassword = "DEBUG1" | ||
| } |
| LaunchedEffect(doseEvents) { | ||
| updateAllHRTTrackerWidgets(applicationContext) | ||
| } |
| <TextView | ||
| android:layout_width="wrap_content" | ||
| android:layout_height="wrap_content" | ||
| android:maxLines="1" | ||
| android:text="当前浓度" | ||
| android:textColor="#FFE5E7FF" | ||
| android:textSize="12sp" | ||
| android:textStyle="bold" /> |
| bindPlanButton( | ||
| context = context, | ||
| views = views, | ||
| buttonId = R.id.widget_plan_one, | ||
| plan = plans.getOrNull(0), | ||
| appWidgetId = appWidgetId, | ||
| emptyText = "打开 App 添加方案" | ||
| ) | ||
| bindPlanButton( | ||
| context = context, | ||
| views = views, | ||
| buttonId = R.id.widget_plan_two, | ||
| plan = plans.getOrNull(1), | ||
| appWidgetId = appWidgetId, | ||
| emptyText = if (plans.isEmpty()) "添加用药方案" else "添加第二个方案" | ||
| ) |
|
有空时review,但是这个PR的改动好大,45个更改的文件,+2506,-1137,不保证review时效( 在此之前,有这些问题需要确认:
另外,该PR包含了多个feature和fix,并且单独项并无法看到具体的开发过程,仅有一个独立commit。这样会对review造成困难。可能后续并不会直接merge该PR,而是对其所address的问题进行单独的implementation。 |
概要
本 PR 汇总了一组针对窄屏设备、折叠屏合上模式、图表可读性及用药计划提醒的改进,并保持现有药代模型、用药数据结构与数据库结构不变。
特别适配了折叠屏设备合上后的窄屏显示模式,同时兼顾普通小屏手机和系统大字体场景;新增提醒使用 Android 标准通知组件,并在支持的系统上请求 Android 16 焦点通知(Live Updates / promoted notifications)展示资格。
更新内容
1. 首页窄屏与折叠屏合上模式适配
2. 浓度图表响应式布局
100–200 pg/mL的非针剂女性向 GAHT 目标浓度阴影,并确保纵轴始终能完整展示该范围。3. 设置页选项形状稳定
4. 用药计划提醒与通知快捷操作
根因
StateFlow读取方案。Android 兼容依据
NotificationCompat.Builder.addAction()与BroadcastReceiver模式。POST_PROMOTED_NOTIFICATIONS、setRequestPromotedOngoing(true)和系统授权状态检查;未获得 promoted 资格时由系统自然降级。RemoteViews,保留标准通知样式、公开锁屏可见性和高重要性通知渠道。验证
clean testDebugUnitTest lintDebug assembleDebug:完整干净构建通过。testDebugUnitTest:81 项单元测试全部通过。lintDebug:0 个错误。assembleDebug:Debug APK 构建成功。范围说明
dose_events数据结构。