Skip to content

feat: 逃走者が写真を撮ったら鬼に通知する - #128

Merged
sana-sagegami merged 3 commits into
mainfrom
120-feature/photo-taken-notification
Sep 28, 2026
Merged

sana-sagegami merged 3 commits into
mainfrom
120-feature/photo-taken-notification

Conversation

@rinyaaa

@rinyaaa rinyaaa commented Sep 27, 2026

Copy link
Copy Markdown
Collaborator

背景 / 目的

Closes #120

9/24のプレイテストで「鬼側に写真撮ったよの通知が来なかった」と報告があった。鬼は写真を撮らないが、全員の写真を見られる。ところが、逃走者が写真を撮ったことを鬼に知らせる機能はそもそも無かった。

また、「足元の写真を撮ってください」という撮影タイミングの通知は役割を問わず出していた。鬼は撮影しないので、鬼には不要な通知だった。ユーザーと相談し、鬼には撮影の通知を出し、撮影タイミングの通知は出さないことにした。

変更内容

  • photo_taken_notifications.dart(新規)
    • usePhotoTakenNotifications: 写真の一覧を監視し、自分が鬼なら、新しく増えた他人の写真を端末通知とSnackBarで知らせる
    • 最初に受け取った一覧は基準にするだけで通知しない。途中参加やアプリの再起動で、過去の写真をまとめて通知しないため
    • 判定は純粋関数 photosToNotify、本文は photoTakenMessage(例: 「たろうさん、はなこさんが足元の写真を撮りました」)
  • local_notifications.dart: showPhotoTakenNotification を追加。チャンネルとIDは撮影タイミングの通知と分けた。同じIDで出すので、続けて撮られると最新の内容に置き換わる
  • photo_capture_controller.dart: notifyWhenDue 引数を追加し、鬼には撮影タイミングの通知を出さない。途中で鬼になった場合も、タイマーが発火した時点の役割に従う
  • game_page.dart: 上記の配線

動作確認

  • flutter test: 全件成功
  • flutter analyze: エラー・警告なし
  • 追加したテスト
    • photosToNotify: 最初の一覧では通知しない、鬼には新しい他人の写真を通知する、複数枚まとめて通知する、自分の写真・逃走者・役割不明では通知しない
    • フックの配線: 鬼なら通知とSnackBarが出る、逃走者なら何も出ない
    • 撮影タイミングの通知: 鬼には出さない、タイマーの途中で鬼になっても出さない
    • 撮影の通知と撮影タイミングの通知は別のIDで出す
  • 実機での確認: 未実施。鬼の端末で、画面OFF中にも逃走者の撮影の通知が届くかを確認したい

スクリーンショット / 動画

変更前 変更後
未撮影 未撮影

レビューで見てほしいところ

  • 通知はゲーム画面が開いている間(バックグラウンド含む)だけ届く。アプリのプロセスが終了していると届かない。RTDBの購読に頼っているため
  • 写真の拡大表示など別の画面を上に開いているときは、SnackBarは出さず端末通知だけ出す

影響範囲・注意点

  • 通知(新しいチャンネル「写真の撮影の通知」が増える)
  • RTDBのデータ構造の変更なし

🤖 Generated with Claude Code

- 鬼のとき、新しく撮られた他人の写真があれば端末通知とSnackBarで
  知らせる(usePhotoTakenNotifications)。最初に受け取った一覧は基準に
  するだけで通知しない
- 鬼は撮影しないので、撮影タイミングの通知は鬼には出さない。途中で
  鬼になった場合も、タイマー発火時点の役割に従う

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 42 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: a732ea34-7db7-4514-b447-e3d1e1968dc7

📥 Commits

Reviewing files that changed from the base of the PR and between c00c4ac and 36350a7.

📒 Files selected for processing (7)
  • lib/core/utils/local_notifications.dart
  • lib/features/room/photo_taken_notifications.dart
  • lib/features/room/view/game_page.dart
  • lib/features/room/view_model/photo_capture_controller.dart
  • test/core/utils/local_notifications_test.dart
  • test/features/room/photo_taken_notifications_test.dart
  • test/features/room/view_model/photo_capture_controller_test.dart

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.

@rinyaaa

rinyaaa commented Sep 27, 2026

Copy link
Copy Markdown
Collaborator Author

@claude review

@claude

claude Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Claude finished @rinyaaa's task in 2m 29s —— View job


レビュー

  • コンテキストの収集(diff・変更ファイルの確認)
  • 依頼内容の把握(コードレビュー)
  • 各ファイルのレビュー
  • レビュー結果の投稿

全体的によく設計・テストされたPRです。既存の useLeftUserNotifications / useDemonChangeNotifications と同じ形(ref.listen + useRefでのスナップショット比較、ModalRoute.of(context)?.isCurrentガード)に揃っていて、hooks/Riverpodの使い分けもAGENTS.mdの基準通りです。ロジック(photosToNotify/photoTakenMessage/shouldNotifyPhotoCaptureDue)を純粋関数に切り出してユニットテストしている点も良いです。

指摘は軽微なものです。

lib/features/room/photo_taken_notifications.dart

  • 39-44行目: latestUsers.value = ref.watch(roomStreamProvider(roomId)).value?.users ?? latestUsers.value; は build のたびに実行されますが、ref.watch を hook 関数の中で直接呼ぶ形は少し見通しにくいです。実害はなさそうです(GamePage側でも同じproviderをwatchしているはずなので二重コストにはならない)が、「なぜref.readではなくref.watch+useRefで持つのか」のコメントは既にあり、意図は追えました。
  • コメント通り「最初に受け取った一覧は基準にするだけ」で問題ありませんが、GamePageがpushReplacementなどで一瞬複数マウントされる場面(useLeftUserNotificationsのコメントで言及されているケース)では、新しいインスタンス側のpreviousIdsがまたnullから始まるため、直前に一方のインスタンスで見た写真を「初めて見た」として扱う可能性があります。実際には端末通知は同じID(_photoTakenNotificationId)で上書きされるだけなので大きな実害はなさそうですが、念のため確認しておくと安心です。

lib/features/room/view_model/photo_capture_controller.dart

  • notifyWhenDueRef の使い方(タイマー発火時点の最新値を見る)は、テストの「タイマーの途中で通知しない指定に変わったら、発火時点の指定に従う」でしっかり検証されていて良い実装です。

全体

  • photoTakenMessageの「同じ人は1回だけ」の実装(Setでdedup)はLinkedHashSetの挿入順保持に依存していますが、DartのSetリテラルの仕様上安全です。
  • docs/rtdb-schema.mdの変更は無く、PR本文の記載通りRTDB構造への影響もありません。
  • テストはphotosToNotifyの境界(最初の一覧・自分の写真・逃走者・役割不明)をきちんと網羅しており、実装との対応が取れています。

大きな懸念事項はありませんでした。上記はどちらも軽微な指摘で、マージをブロックするものではないと思います。

@rinyaaa

rinyaaa commented Sep 27, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 27, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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.

Copilot review overview

🟡 Changes recommended

Unresolved notification correctness issues remain, along with a documentation nit.

Review effort: Lite
Findings: 2 Medium severity

Open (2)
What changed in this PR

Adds notifications to demons when fugitives take photos, while suppressing photo-timing notifications for demons.

Changes:

  • Added photo monitoring with local notifications and SnackBars.
  • Added separate notification channel and ID.
  • Added role-aware timing notifications and tests.
File Description Review notes
test/​features/​room/​view_model/​photo_capture_controller_test.dart Tests role-aware timing notifications —
test/​features/​room/​photo_taken_notifications_test.dart Tests photo notification behavior —
test/​core/​utils/​local_notifications_test.dart Tests notification ID separation —
lib/​features/​room/​view/​game_page.dart Wires notification behavior into gameplay —
lib/​features/​room/​view_model/​photo_capture_controller.dart Controls timing notifications by role —
lib/​features/​room/​photo_taken_notifications.dart Detects and displays photo events Three moderate issues remain around duplicate names, cached initial state, and role-state synchronization.
lib/​core/​utils/​local_notifications.dart Adds photo-taken notification support Documentation nit: reference the actual capture notification channel name.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +42 to +44
String photoTakenMessage(List<String> displayNames) {
final names = <String>{for (final name in displayNames) '$nameさん'};
return '${names.join('、')}が足元の写真を撮りました';
Comment on lines +67 to +69
ref.listen(photosStreamProvider(roomId), (prev, next) {
final photos = next.value;
if (photos == null) return;
rinyaaa and others added 2 commits September 27, 2026 19:46
Copilotのレビュー指摘への対応。
- 通知の本文で重複を除く単位を名前からuidに変えた。同じ名前の別人が
  1人にまとまっていた
- 写真の一覧がすでに読み込まれた状態で画面が開くと、ref.listenはその値
  では呼ばれず、次に増えた写真が基準扱いになって通知が漏れていた。
  読み込み済みの一覧を先に基準にする
- 役割はbuild時点の値ではなく、写真が届いた時点の最新のルームから読む

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sana-sagegami
sana-sagegami merged commit 408f526 into main Sep 28, 2026
4 checks passed
@sana-sagegami
sana-sagegami deleted the 120-feature/photo-taken-notification branch September 28, 2026 10:12
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