Skip to content

深夜(0:00-2:00)の服用記録に当日分まで記録された旨の注意ダイアログを表示#1821

Merged
bannzai merged 13 commits into
mainfrom
fix-issue-dialog
Jul 14, 2026
Merged

深夜(0:00-2:00)の服用記録に当日分まで記録された旨の注意ダイアログを表示#1821
bannzai merged 13 commits into
mainfrom
fix-issue-dialog

Conversation

@bannzai

@bannzai bannzai commented Jul 12, 2026

Copy link
Copy Markdown
Owner

Abstract

深夜0:00〜2:00にアプリ上で服用記録(「飲んだ」ボタン・ピルシートの番号タップ)をした場合に、当日分まで服用記録されたことを知らせる注意ダイアログを表示する。

  • 文言: 「ご注意ください。7/12分の服用記録までされました。7/12である本日12:00の通知はお手元に届きません。間違いの場合は、服用を取り消してください」(日付・通知時刻は動的)
  • 「服用の取り消し方法を見る」ボタンでFAQ「服用済みのピルを未服用状態に戻したい」( https://pilll.notion.site/63c3436e63ea4ba8a1407be40cb5f0e5 ) を開く
  • 表示頻度は30日に1回まで。「閉じる」押下時に表示日時をSharedPreferences(double / millisecondsSinceEpoch)へ保存し、次回以降の判定に使う
  • 2回目以降の表示(doubleキーが保存済み)では「二度と表示しない」ボタンを表示。押下でBooleanフラグを保存し、以降は表示しない
  • ダイアログはボタン以外(背景タップ)では閉じない(barrierDismissible: false)。「閉じる」で確実に表示記録を残すため

表示条件の詳細

midnightTakenWarningDialogDisplayMode で判定:

  1. 記録操作時刻が0:00〜1:59であること(2:00以降は対象外)
  2. 当日分まで服用記録されたこと。過去のピル番号タップで過去分のみ記録した場合は、当日の通知は届くため表示しない
  3. 記録時点でまだ届いていない当日の通知が1件以上あること。通知時刻が0:00〜2:00内(例: 1:00)に設定されているユーザーがその時刻より後(例: 1:30)に記録した場合、通知は既に届いており「届きません」が成立しないため表示しない。本文に列挙する通知時刻も未到達分のみ
  4. 「二度と表示しない」が未押下であること
  5. 前回表示から30日以上経過していること(初回は無条件)

なお通知時刻の未設定は ReminderTime.minimumCount = 1 が保存時にバリデーションされるため通常発生しないが、条件3が空リストも自然に吸収する。

実装

  • 服用記録(takePill)の完了を待たずにダイアログを表示する(「飲んだ」ボタン)。ピルシートの番号タップは服用記録されないケース(休薬中・未来のピル等)があるため、記録結果を待って実際に記録された場合のみ表示判定する
  • ダイアログに必要な SettingRecordPageBodyRecordPageButtonTakenButton とconstructorで受け渡す
  • 過去シート画面(before_pill_sheet_group_history)は onTap: () {} で服用記録できないため対象外

Why

明朝0時〜2時に服用するユーザーが、日を跨いでいないと勘違いして「飲んだ」を押すと当日分まで服用記録される。例えば7/11 0:10の記録でユーザーは7/10分のつもりだが、実際は7/11分まで記録され、7/11当日の通知が届かず「設定した時刻に通知が来ない」という問い合わせが発生している。その対策として、記録直後に注意を促し服用取消のFAQへ誘導する。

Links

スクリーンショット

シミュレータでの動作確認(検証用に時刻・表示頻度条件を一時無効化したビルドで撮影。コードは復元済み)。

初回表示 2回目以降(「二度と表示しない」あり) 番号タップ・通知時刻フィルタ
  • 左・中央: 「飲んだ」ボタン経由。初回は「二度と表示しない」なし、2回目以降はあり(※初期実装ビルドでの撮影のため通知時刻が11:00, 12:00と全件表示されている)
  • 右: ピルシートの番号タップ経由。11:55の記録で、既に届いた11:00が除外され未到達の12:00のみ表示されている
  • このほか「二度と表示しない」押下後に再度服用記録してもダイアログが表示されないこと、服用記録自体が正常に完了することを確認済み

Checked

  • Analyticsのログを入れたか(midnight_taken_warning_faq / midnight_taken_warning_close / midnight_taken_warning_never_show_again、表示時の logScreenView
  • 境界値に対してのUnitTestを書いた(記録時刻0:00/1:59/2:00/23:59、30日間隔の前日/29日後/30日後/年跨ぎ、通知時刻の未到達判定、当日分記録の有無)
  • パターン分岐が発生するWidgetに対してWidgetTestを書いた(「二度と表示しない」ボタンの出し分け、本文の日付・通知時刻表示)

セッション再開

cd /Users/bannzai/worktrees/bannzai/Pilll/fix-issue-dialog
claude --resume 9b6ce426-d0fa-4947-a03f-cfded3be9b7c

Summary by CodeRabbit

  • 新機能
    • 深夜(0:00〜2:00)に「服用済み」記録を行うと、当日の通知(未到達分)に関する注意ダイアログが表示されます。
    • 服用日({takenDate})と未到達の通知時刻(複数可)を本文に反映し、「戻し方」案内を表示します。
    • 「今後表示しない」で次回以降の表示を制御できます。
  • 改善
    • 表示は、記録時刻・通知設定・前回表示からの経過に基づき、必要な場合にのみ実行されます。

bannzai added 5 commits July 12, 2026 13:00
日を跨いだことに気づかず服用記録をすると当日分まで記録され、
当日の通知が届かなくなる問い合わせへの対策。

- 表示は30日に1回まで。「閉じる」押下時にSharedPreferencesへ記録
- 2回目以降の表示では「二度と表示しない」ボタンを出す
- 当日分まで記録された場合のみ対象(過去のピル番号タップは対象外)
- 本文の通知時刻は記録時点でまだ届いていない当日の通知のみ列挙し、
  1件もなければ表示しない(通知時刻が0:00-2:00内のユーザーを考慮)
- 服用取り消し方法のFAQリンク付き
- 飲んだボタン: 服用記録の完了(await)を待たずに表示する
- ピルシートの番号タップ: 服用記録されないケースがあるため、
  実際に記録された場合のみ表示判定する
- ダイアログに必要なsettingはRecordPageBody -> RecordPageButton -> TakenButton
  とconstructorで受け渡す
- 表示判定: 記録操作時刻(0:00/1:59/2:00/23:59)の境界値、
  当日分まで記録されたかどうか、通知時刻の未到達判定、
  30日間隔(前日/29日後/30日後/年跨ぎ)の境界値
- Widget: 初回と2回目以降の「二度と表示しない」ボタンの出し分け、
  本文の日付・通知時刻表示
- 既存のRecordPageButtonテストにsetting引数を追加
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

深夜の服用記録に対する注意ダイアログを追加し、通知時刻・表示履歴・非表示設定に基づく表示判定、記録ボタンへの統合、ローカライズ、関連テストを実装した。

Changes

深夜服用記録の注意表示

Layer / File(s) Summary
表示判定とダイアログ実装
lib/features/record/components/button/midnight_taken_warning_dialog.dart, lib/utils/shared_preference/keys.dart, lib/l10n/app_*.arb
通知時刻、服用日時、SharedPreferencesの状態から表示可否を判定し、服用日・未到達通知時刻を含むダイアログと各操作を追加した。
服用記録フローへの統合
lib/features/record/components/button/record_page_button.dart, lib/features/record/components/button/taken_button.dart, lib/features/record/components/pill_sheet/record_page_pill_sheet.dart, lib/features/record/page.dart
Settingを記録ボタンへ渡し、服用記録処理中に必要な場合のみ注意ダイアログを表示するよう変更した。
表示判定と統合のテスト
test/features/record/components/button/midnight_taken_warning_dialog_test.dart, test/features/record/components/button/record_page_button_test.dart, test/features/record/record_page_button_state_test.dart
未到達通知時刻、表示条件、ダイアログ本文とボタン表示、およびSetting追加後の既存ボタンテストを検証した。

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant RecordPageBody
  participant RecordPageButton
  participant TakenButton
  participant takePill
  participant showMidnightTakenWarningDialogIfNeeded
  participant SharedPreferences
  RecordPageBody->>RecordPageButton: Setting を渡して構築
  RecordPageButton->>TakenButton: Setting を渡す
  TakenButton->>takePill: 服用記録を開始
  TakenButton->>showMidnightTakenWarningDialogIfNeeded: 記録日時と服用日を渡す
  showMidnightTakenWarningDialogIfNeeded->>SharedPreferences: 表示履歴と非表示設定を参照
  showMidnightTakenWarningDialogIfNeeded-->>TakenButton: 条件を満たす場合に表示
  TakenButton->>takePill: 記録処理の完了を待機
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 深夜の服用記録時に注意ダイアログを表示する変更内容を概ね正しく要約しています。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-issue-dialog

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 6

🧹 Nitpick comments (1)
test/features/record/components/button/midnight_taken_warning_dialog_test.dart (1)

273-342: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Widgetテストのgroup名を規約に合わせてください。

MidnightTakenWarningDialog のgroup名は #MidnightTakenWarningDialog のように # で始めてください。

コーディングガイドラインの「Widget TestsはWidget classごとに整理し、group名を#で始める」に基づく指摘です。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@test/features/record/components/button/midnight_taken_warning_dialog_test.dart`
around lines 273 - 342, Update the widget test group declaration for
MidnightTakenWarningDialog to use the required “#MidnightTakenWarningDialog”
naming convention, leaving the contained tests unchanged.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/features/record/components/button/midnight_taken_warning_dialog.dart`:
- Around line 192-200: Update the midnight warning dialog flow so the timestamp
keyed by DoubleKey.midnightTakenWarningDialogLastShownDateTime is persisted when
the dialog is shown, rather than only in the close button’s onPressed callback.
Remove the close-time-only persistence while preserving analytics logging and
navigation behavior.
- Around line 87-100:
直列化されていない判定から表示開始までの処理を、対象のダイアログ表示関数で共有ロックまたは表示中フラグを使って保護してください。MidnightTakenWarningDialogDisplayMode.none
の判定後から showDialog
の開始までを同時実行できないようにし、重複呼び出し時は後続処理を中止してください。表示開始後は必ずガードを解放し、context.mounted が false
の場合も解除されるようにしてください。
- Around line 45-60: Update midnightTakenWarningDialogDisplayMode to accept and
check the reminder-enabled flag before evaluating remaining reminder times.
Return MidnightTakenWarningDialogDisplayMode.none when reminders are disabled,
while preserving the existing behavior for enabled reminders.
- Around line 179-185: Update the FAQ button’s onPressed handler to await the
Future<bool> returned by launchUrl in the midnight warning dialog, and notify
the user when it returns false because the FAQ cannot be opened. Preserve the
existing analytics event and URL.

In `@lib/features/record/components/button/taken_button.dart`:
- Around line 58-72: Update the takePill flow in the button handler so it awaits
successful completion before calling showMidnightTakenWarningDialogIfNeeded.
Remove the fire-and-forget invocation, preserve the existing takenDate and
arguments, and ensure the dialog is not shown when takePill fails.

In
`@test/features/record/components/button/midnight_taken_warning_dialog_test.dart`:
- Around line 175-270: Extend the SharedPreferences tests for
midnightTakenWarningDialogDisplayMode with leap-year boundary cases covering
dates around February 29, 2024, where 29 elapsed days returns none and 30
elapsed days returns repeated. Add equivalent 29-day and 30-day boundary cases
in non-leap-year 2025, preserving the existing setup and assertions.

---

Nitpick comments:
In
`@test/features/record/components/button/midnight_taken_warning_dialog_test.dart`:
- Around line 273-342: Update the widget test group declaration for
MidnightTakenWarningDialog to use the required “#MidnightTakenWarningDialog”
naming convention, leaving the contained tests unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4fdc837f-bb74-4e09-bfea-4a375cab7289

📥 Commits

Reviewing files that changed from the base of the PR and between b9ff433 and f1b96e5.

📒 Files selected for processing (11)
  • lib/features/record/components/button/midnight_taken_warning_dialog.dart
  • lib/features/record/components/button/record_page_button.dart
  • lib/features/record/components/button/taken_button.dart
  • lib/features/record/components/pill_sheet/record_page_pill_sheet.dart
  • lib/features/record/page.dart
  • lib/l10n/app_en.arb
  • lib/l10n/app_ja.arb
  • lib/utils/shared_preference/keys.dart
  • test/features/record/components/button/midnight_taken_warning_dialog_test.dart
  • test/features/record/components/button/record_page_button_test.dart
  • test/features/record/record_page_button_state_test.dart

Comment thread lib/features/record/components/button/midnight_taken_warning_dialog.dart Outdated
Comment thread lib/features/record/components/button/midnight_taken_warning_dialog.dart Outdated
Comment thread lib/features/record/components/button/taken_button.dart

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f1b96e5546

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/features/record/components/button/midnight_taken_warning_dialog.dart Outdated
Comment thread lib/features/record/components/button/taken_button.dart
import 'package:url_launcher/url_launcher.dart';

/// 深夜(0:00-2:00)服用記録の注意ダイアログの表示要否
enum MidnightTakenWarningDialogDisplayMode {

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

わざわざenumを用意する必要なさそう。不要な中間表現は使わない

bannzai added 4 commits July 14, 2026 14:38
TakenButton / RecordPageButton / RecordPageBody はhooksを使用していないため、
hooks-and-consumer-widget.md の規約に従い ConsumerWidget にする
- hooksを使用していないため ConsumerWidget にする
- 1回しか参照しない updatedPillSheetGroup を条件式にインライン化
- 1回しか参照しない sharedPreferences をインライン化
- getBool の ?? false に「未保存は未押下として扱う」根拠コメントを追加
表示要否と「二度と表示しない」ボタンの出し分けを1つのenumに
まとめる中間表現は不要なため、それぞれ直接導出する形にする。

- 表示要否: shouldShowMidnightTakenWarningDialog (bool)
- ボタンの出し分け: 表示日時キー(double)の保存有無をそのまま参照

@coderabbitai coderabbitai Bot 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.

♻️ Duplicate comments (2)
lib/features/record/components/button/midnight_taken_warning_dialog.dart (1)

74-94: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

通知OFF時はこの警告を出さないように考慮してください。

以前のレビューでも指摘されていましたが、setting.isOnReminderfalse の場合でも、保存済みの通知時刻が setting.reminderTimes に残っていると「通知が届かない」と誤って案内されてしまいます。通知が無効な場合は警告をスキップするよう、isOnReminder を判定に含めてください。

💡 修正案
  void showMidnightTakenWarningDialogIfNeeded({
    required BuildContext context,
    required DateTime takenDate,
    required DateTime recordedAt,
    required Setting setting,
  }) async {
    final sharedPreferences = await SharedPreferences.getInstance();
+   final activeReminderTimes = setting.isOnReminder ? setting.reminderTimes : <ReminderTime>[];
    if (!shouldShowMidnightTakenWarningDialog(
      sharedPreferences: sharedPreferences,
      takenDate: takenDate,
      recordedAt: recordedAt,
-     reminderTimes: setting.reminderTimes,
+     reminderTimes: activeReminderTimes,
    )) {
      return;
    }

    if (context.mounted) {
      analytics.logScreenView(screenName: 'MidnightTakenWarningDialog');
      showDialog(
        context: context,
        // 「閉じる」でSharedPreferencesに表示記録を残すため、ボタン以外で閉じられないようにする
        barrierDismissible: false,
        builder: (context) => MidnightTakenWarningDialog(
          takenDate: takenDate,
-         reminderTimes: midnightTakenWarningRemainingReminderTimes(reminderTimes: setting.reminderTimes, recordedAt: recordedAt),
+         reminderTimes: midnightTakenWarningRemainingReminderTimes(reminderTimes: activeReminderTimes, recordedAt: recordedAt),
          // 2回目以降(過去に「閉じる」で表示日時が保存済み)の表示でのみ「二度と表示しない」を出す
          showsNeverShowAgainButton: sharedPreferences.containsKey(DoubleKey.midnightTakenWarningDialogLastShownDateTime),
        ),
      );
    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/record/components/button/midnight_taken_warning_dialog.dart`
around lines 74 - 94, 通知が無効な場合に警告ダイアログを表示しないよう、MidnightTakenWarningDialog の表示判定で
setting.isOnReminder を確認してください。setting.isOnReminder が false の場合は
shouldShowMidnightTakenWarningDialog の呼び出し前に return し、既存の有効時の判定と表示処理は維持してください。
test/features/record/components/button/midnight_taken_warning_dialog_test.dart (1)

255-270: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

うるう年の境界値テストを追加してください。

以前のレビューでも指摘されていましたが、30日経過の判定に対して、うるう年(2024年2月29日を含む)と平年(2025年)の境界値テストが不足しています。コーディングガイドラインに従い、日付の境界値テストとしてうるう年のケースを網羅してください。

💡 テスト追加案
      test("年をまたいでも前回表示から30日未満の場合は表示しない", () async {
        SharedPreferences.setMockInitialValues({
          DoubleKey.midnightTakenWarningDialogLastShownDateTime:
              DateTime(2026, 12, 31, 0, 30).millisecondsSinceEpoch.toDouble(),
        });
        expect(
          shouldShowMidnightTakenWarningDialog(
            sharedPreferences: await SharedPreferences.getInstance(),
            takenDate: DateTime(2027, 1, 1, 0, 10),
            recordedAt: DateTime(2027, 1, 1, 0, 10),
            reminderTimes: reminderTimes,
          ),
          false,
        );
      });
+
+     test("うるう年(2月29日を含む)で前回表示から29日後の場合は表示しない", () async {
+       SharedPreferences.setMockInitialValues({
+         DoubleKey.midnightTakenWarningDialogLastShownDateTime:
+             DateTime(2024, 2, 1, 0, 30).millisecondsSinceEpoch.toDouble(),
+       });
+       expect(
+         shouldShowMidnightTakenWarningDialog(
+           sharedPreferences: await SharedPreferences.getInstance(),
+           takenDate: DateTime(2024, 3, 1, 0, 10), // 2月29日があるので29日後
+           recordedAt: DateTime(2024, 3, 1, 0, 10),
+           reminderTimes: reminderTimes,
+         ),
+         false,
+       );
+     });
+
+     test("うるう年(2月29日を含む)で前回表示から30日後の場合は表示する", () async {
+       SharedPreferences.setMockInitialValues({
+         DoubleKey.midnightTakenWarningDialogLastShownDateTime:
+             DateTime(2024, 1, 31, 0, 30).millisecondsSinceEpoch.toDouble(),
+       });
+       expect(
+         shouldShowMidnightTakenWarningDialog(
+           sharedPreferences: await SharedPreferences.getInstance(),
+           takenDate: DateTime(2024, 3, 1, 0, 10), // 2月29日があるので30日後
+           recordedAt: DateTime(2024, 3, 1, 0, 10),
+           reminderTimes: reminderTimes,
+         ),
+         true,
+       );
+     });
+
+     test("平年(2月28日まで)で前回表示から29日後の場合は表示しない", () async {
+       SharedPreferences.setMockInitialValues({
+         DoubleKey.midnightTakenWarningDialogLastShownDateTime:
+             DateTime(2025, 2, 1, 0, 30).millisecondsSinceEpoch.toDouble(),
+       });
+       expect(
+         shouldShowMidnightTakenWarningDialog(
+           sharedPreferences: await SharedPreferences.getInstance(),
+           takenDate: DateTime(2025, 3, 2, 0, 10), // 2月は28日までなので29日後
+           recordedAt: DateTime(2025, 3, 2, 0, 10),
+           reminderTimes: reminderTimes,
+         ),
+         false,
+       );
+     });
    });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@test/features/record/components/button/midnight_taken_warning_dialog_test.dart`
around lines 255 - 270, Extend the tests around
shouldShowMidnightTakenWarningDialog with leap-year boundary cases covering
February 29, 2024 and the corresponding non-leap-year boundary in 2025. Verify
both sides of the 30-day threshold, including dates just before and at/after the
threshold, while preserving the existing cross-year coverage and expected
display behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@lib/features/record/components/button/midnight_taken_warning_dialog.dart`:
- Around line 74-94: 通知が無効な場合に警告ダイアログを表示しないよう、MidnightTakenWarningDialog の表示判定で
setting.isOnReminder を確認してください。setting.isOnReminder が false の場合は
shouldShowMidnightTakenWarningDialog の呼び出し前に return し、既存の有効時の判定と表示処理は維持してください。

In
`@test/features/record/components/button/midnight_taken_warning_dialog_test.dart`:
- Around line 255-270: Extend the tests around
shouldShowMidnightTakenWarningDialog with leap-year boundary cases covering
February 29, 2024 and the corresponding non-leap-year boundary in 2025. Verify
both sides of the 30-day threshold, including dates just before and at/after the
threshold, while preserving the existing cross-year coverage and expected
display behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 21c63fac-9deb-4f6c-9d68-274a9e9696ab

📥 Commits

Reviewing files that changed from the base of the PR and between f1b96e5 and 808d267.

📒 Files selected for processing (6)
  • lib/features/record/components/button/midnight_taken_warning_dialog.dart
  • lib/features/record/components/button/record_page_button.dart
  • lib/features/record/components/button/taken_button.dart
  • lib/features/record/components/pill_sheet/record_page_pill_sheet.dart
  • lib/features/record/page.dart
  • test/features/record/components/button/midnight_taken_warning_dialog_test.dart
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/features/record/components/button/taken_button.dart
  • lib/features/record/components/button/record_page_button.dart

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 808d267393

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/features/record/components/button/midnight_taken_warning_dialog.dart Outdated
@bannzai

bannzai commented Jul 14, 2026

Copy link
Copy Markdown
Owner Author

コーディング規約チェックと修正

.claude/rules 全6ファイルと全プロジェクト共通規約に対して本PRの差分を照合し、違反を修正した。

準拠済みだった項目

  • analytics: コールバック先頭で logEvent、イベント名40文字以内、閉じる系の操作も記録、表示時の logScreenView
  • coding-conventions: 引数の {required}、Firestore変更は TakePill(callクラスProvider)経由、Entityフィールド名の省略なし
  • testing: find.text(L.xxx) でのマッチなし(byType と動的値の textContaining のみ)、シナリオベースのWidgetTest

修正した項目

  1. hooksを使っていないWidgetをConsumerWidgetに変更(hooks-and-consumer-widget.md)
    TakenButton / RecordPageButton / RecordPagePillSheet / RecordPageBodyuse* 呼び出しがないため ConsumerWidget にした。RecordPageuseAutomaticKeepAlive を使用しているため HookConsumerWidget のまま
  2. 1回しか参照しない一時変数をインライン化
    showMidnightTakenWarningDialogIfNeededsharedPreferences(後のenum廃止で2回参照となり変数として復活)、ピル番号タップ経路の updatedPillSheetGroup
  3. デフォルト値への選定根拠コメント追加
    getBool(...) ?? false に「キーは押下時にのみ保存されるため未保存は未押下として扱う」を明記
  4. MidnightTakenWarningDialogDisplayMode enumを廃止
    表示要否と「二度と表示しない」ボタンの出し分けを1つのenumにまとめる中間表現をやめ、それぞれ直接導出する形にした
    • 表示要否: shouldShowMidnightTakenWarningDialog (bool)
    • ボタンの出し分け: 表示日時キー(double)の保存有無(containsKey)をそのまま参照

なお TakenButtonupdatedPillSheetGroupFuture は1回参照だが、服用記録を先に開始してから完了を待たずにダイアログを表示するという実行順序のために必要な変数のため維持(理由はコード上にコメント済み)。

検証

  • flutter analyze エラー・警告0件
  • 全テストスイート1514件パス(ConsumerWidget化・enum廃止を含む状態で実行)
  • シミュレータでリファクタ後の動作を再確認(検証用に時刻・表示済み条件の一時無効化と未到達通知時刻23:00の一時追加を行ったビルドで撮影。検証後にコードを復元し、作業ツリーがクリーンなことを確認済み)
「飲んだ」ボタン経由 ピルシートの番号タップ経由
  • 15時台の記録操作に対して、既に届いた11:00, 12:00の通知が除外され、未到達の23:00のみ本文に表示されている(midnightTakenWarningRemainingReminderTimes の実動作)
  • 表示日時キーが保存済みのため「二度と表示しない」ボタンが表示されている(enum廃止後の containsKey による出し分け)
  • 「閉じる」でダイアログが閉じ、服用記録自体も正常に完了することを両経路で確認

Comment thread lib/features/record/components/pill_sheet/record_page_pill_sheet.dart Outdated
bannzai added 4 commits July 14, 2026 15:42
複数の記録経路(飲んだボタン・ピルシートの番号タップ)が短時間に呼んだ場合、
表示記録の保存前に両方が表示可能と判定して二重表示され得るため、
表示中フラグでガードする。フラグはダイアログが閉じたら必ず解除し、
解除後の再表示は「閉じる」で保存される表示記録の30日条件で防がれる
setting.isOnReminderがfalseの場合、LocalNotificationService.runが早期returnして
当日の通知は元々送信されないため、「通知が届きません」という注意自体が成立しない。
判定関数にはreminderTimesではなくSettingを渡す形に変更
await式をif条件に直接埋め込むとインデントが崩れて読みづらいため、
一時変数に代入してから判定する
setting.isOnNotifyInNotTakenDurationがfalseで当日が偽薬/休薬期間
(ピル番号がdosingPeriod超)の場合、RegisterReminderLocalNotification.runは
その日の通知登録をスキップするため当日の通知は元々予定されていない。
判定にactivePillSheetを渡し、該当日は表示対象から外す

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/features/record/components/button/midnight_taken_warning_dialog.dart`:
- Around line 91-113: Update the midnight warning dialog flow around showDialog
to persist DoubleKey.midnightTakenWarningDialogLastShownDateTime when the dialog
is displayed, before awaiting its dismissal. In the FAQ link handler, await
launchUrl and show the existing error guidance when it returns false instead of
ignoring the result.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fdaec9f1-e8f0-4ea4-a459-c38c6f6250fc

📥 Commits

Reviewing files that changed from the base of the PR and between 808d267 and 45596ce.

📒 Files selected for processing (4)
  • lib/features/record/components/button/midnight_taken_warning_dialog.dart
  • lib/features/record/components/button/taken_button.dart
  • lib/features/record/components/pill_sheet/record_page_pill_sheet.dart
  • test/features/record/components/button/midnight_taken_warning_dialog_test.dart
🚧 Files skipped from review as they are similar to previous changes (3)
  • lib/features/record/components/button/taken_button.dart
  • lib/features/record/components/pill_sheet/record_page_pill_sheet.dart
  • test/features/record/components/button/midnight_taken_warning_dialog_test.dart

@bannzai bannzai merged commit 0f9ddc5 into main Jul 14, 2026
6 checks passed
@bannzai bannzai deleted the fix-issue-dialog branch July 14, 2026 07:37
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