Skip to content

feat: improve compact layouts, chart readability, and medication reminders - #31

Open
YingQiu0871 wants to merge 4 commits into
NaiveTomcat:masterfrom
YingQiu0871:agent/fix-home-responsive-layout
Open

feat: improve compact layouts, chart readability, and medication reminders#31
YingQiu0871 wants to merge 4 commits into
NaiveTomcat:masterfrom
YingQiu0871:agent/fix-home-responsive-layout

Conversation

@YingQiu0871

Copy link
Copy Markdown

概要

本 PR 汇总了一组针对窄屏设备、折叠屏合上模式、图表可读性及用药计划提醒的改进,并保持现有药代模型、用药数据结构与数据库结构不变。

特别适配了折叠屏设备合上后的窄屏显示模式,同时兼顾普通小屏手机和系统大字体场景;新增提醒使用 Android 标准通知组件,并在支持的系统上请求 Android 16 焦点通知(Live Updates / promoted notifications)展示资格。

相比已关闭的 #29:原第 3 点(给药途径按钮弹跳修复)已按维护者意见移除,恢复 M3E 预期的宽度动画行为。

更新内容

1. 首页窄屏与折叠屏合上模式适配

  • 当前浓度卡片会根据可用宽度和系统字体缩放,在横向与纵向布局间自动切换。
  • 浓度数值支持自适应字号,避免状态文本被挤压成竖向逐字显示。
  • 调整内容宽度与间距,使首页在折叠屏合上模式、窄屏手机和大字体下保持完整可读。

2. 浓度图表响应式布局

  • 根据图表可用宽度动态显示 2–6 个横轴标签。
  • 日期和时间拆分为两行,并约束首尾标签位置,避免横轴文字重叠或越界。
  • 增加 100–200 pg/mL 的非针剂女性向 GAHT 目标浓度阴影,并确保纵轴始终能完整展示该范围。
  • 将贯穿图表的粉色给药竖线改为曲线上的星形标记,减少遮挡。
  • 在“曲线说明”中增加“星形:实际给药记录”图例。

3. 设置页选项形状稳定

  • 主题模式、颜色主题和时间制式选项在选中、按下、聚焦等状态下保持相同尺寸和圆角。
  • 选中行为只改变背景色、内容颜色和单选圆点,不再改变方块形状。

4. 用药计划提醒与通知快捷操作

  • 启用的用药方案会在计划时间发送 Android 标准高优先级通知。
  • 通知提供“确认用药”和“跳过本次”两个系统 Action,无需先打开应用。
  • “确认用药”按确认时间写入现有用药记录;记录 ID 由方案和本次计划时间确定,避免重复广播生成重复记录。
  • “跳过本次”只结束当前提醒,不修改方案,也不影响后续提醒。
  • Android 13+ 在启用方案时申请通知权限,并在方案页提供权限恢复入口。
  • Android 16+ 声明 promoted notification 权限并请求焦点通知展示资格;系统不支持、用户未授权或系统判定不符合时,自动保留为普通高优先级通知。
  • 手机重启、应用更新、手动修改时间或时区后自动恢复提醒。
  • 每次提醒触发后续排下一批计划,避免长期方案在预排窗口结束后停止。
  • 编辑方案时先清理旧闹钟,避免旧时间点继续触发。

根因

  • 首页原布局依赖固定横向空间,在折叠屏合上模式、窄屏或大字体下会出现文本挤压。
  • 图表固定绘制完整时间标签,未根据实际画布宽度减少标签数量。
  • 给药时间使用贯穿图表的竖线标记,视觉干扰较强。
  • 原提醒仅发送基础通知,没有运行时权限入口、通知 Action、重启恢复和长期续排;启动时还可能从尚未订阅的空 StateFlow 读取方案。

Android 兼容依据

  • 通知快捷操作使用 Android 官方 NotificationCompat.Builder.addAction()BroadcastReceiver 模式。
  • Android 16 焦点通知使用 POST_PROMOTED_NOTIFICATIONSsetRequestPromotedOngoing(true) 和系统授权状态检查;未获得 promoted 资格时由系统自然降级。
  • 未使用自定义 RemoteViews,保留标准通知样式、公开锁屏可见性和高重要性通知渠道。

验证

  • clean testDebugUnitTest lintDebug assembleDebug:完整干净构建通过。
  • testDebugUnitTest:81 项单元测试全部通过。
  • lintDebug:0 个错误。
  • assembleDebug:Debug APK 构建成功。
  • 增加窄屏/大字体预览、横轴标签数量计算测试,以及提醒确认记录的幂等性与字段映射测试。

范围说明

  • 本 PR 不包含校准功能。
  • 不修改现有药代计算逻辑、用药记录格式或数据库结构。
  • “确认用药”复用现有 dose_events 数据结构。
  • 不包含本地临时构建配置。

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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.

Comment thread wear/build.gradle.kts
Comment on lines +13 to +19
signingConfigs {
getByName("debug") {
storeFile = file("../app/debugkeystore.jks")
storePassword = "DEBUG1"
keyAlias = "DEBUG"
keyPassword = "DEBUG1"
}
Comment on lines +92 to +94
LaunchedEffect(doseEvents) {
updateAllHRTTrackerWidgets(applicationContext)
}
Comment on lines +20 to +27
<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" />
Comment on lines +146 to +161
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 "添加第二个方案"
)
@NaiveTomcat

Copy link
Copy Markdown
Owner

有空时review,但是这个PR的改动好大,45个更改的文件,+2506,-1137,不保证review时效(

在此之前,有这些问题需要确认:

  1. 这个PR的代码改动,提交消息,PR文本内容,有多大比例是LLM写的?多少是经过人工确认的?
  2. 提交PR之前是否已经人工进行了相关单元测试和功能测试?

另外,该PR包含了多个feature和fix,并且单独项并无法看到具体的开发过程,仅有一个独立commit。这样会对review造成困难。可能后续并不会直接merge该PR,而是对其所address的问题进行单独的implementation。

@NaiveTomcat NaiveTomcat self-assigned this Aug 22, 2026
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.

3 participants