Go Router移行方針ドキュメントの追加#593
Conversation
Co-Authored-By: Kanta Oikawa <iam@kantacky.com>
Original prompt from Kanta
|
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
kantacky
left a comment
There was a problem hiding this comment.
レビュー(方針ドキュメント)
全体の構成・段階的移行(Phase 分割)・主要論点の洗い出しはよくできており、AGENTS.md の「大規模一括リファクタを避け段階的に移行」の方針とも整合しています。現状分析もおおむね正確(MaterialApp.home → RootScreen/FirebaseAnalyticsObserver、IndexedStack+タブ別 Navigator、ガード分岐、navigatorKeys+popUntil、PopScope+maybePop、BusTimetableScreen のオブジェクト渡し、go_router 未導入 — いずれも実コードと一致)です。
マージ前に補強したい点を、設計に関わるものと表記の不一致に分けて挙げます。
重要な論点(設計に関わるもの)
1. 動的タブ切り替え(学食 ↔ 科目検索)と StatefulShellRoute.indexedStack の相性(最重要)
StatefulShellRoute.indexedStack は構築時にブランチ数が固定で、実行時にブランチを追加・削除できません。現状は isFunchEnabled で同一スロットの TabItem.funch ↔ TabItem.subject を入れ替えています(apps/dotto/lib/feature/root/root_viewmodel.dart:22-29)。13 節は「条件分岐でブランチ構築 or redirect」とありますが、ここが本移行の最大の難所です。
- 案A: 両タブを含む固定ブランチを定義し、
NavigationBar側で表示制御 - 案B:
isFunchEnabled変化時に router を作り直す(→ ナビゲーション状態リセットの副作用に注意)
どちらを採るかを Phase 1 で必ずプロトタイプ検証する旨を明記したいです(PR 本文チェックリストでも未確認項目)。
2. GoRouter を ref.watch する Provider にする際の再生成問題
3〜4 節で「GoRouter を Riverpod Provider にして ref 経由で状態参照」とありますが、ref.watch した状態が変わるたびに Provider が再評価され GoRouter インスタンスごと作り直されると、ナビゲーションスタックがリセットされます。ルーター本体は安定させ、状態変化は refreshListenable(Listenable 化した Notifier)で通知するのが定石です。この注意の追記を推奨します。
3. Analytics Observer と StatefulShellRoute の組み合わせ
10 節は「FirebaseAnalyticsObserver を GoRouter.observers に設定」とありますが、StatefulShellRoute ではタブ内の遷移は各ブランチの Navigator を通るため、トップレベルの observers だけではタブ配下の画面遷移が Analytics に記録されない可能性があります。各 StatefulShellBranch 側にも observer を付与する必要がある点を明記したいです。
4. ディープリンクのネイティブ設定
11 節「app_links は不要になる」は概ね正しいですが、現状の app_links は listen のみで実質何もしていません(root_viewmodel.dart:43-48)。go_router に移しても iOS(Associated Domains / Universal Links)・Android(intent-filter)のネイティブ設定は別途必要です。「パス定義だけで機能する」は誤解を招くので一言補足を。
軽微な指摘(表記ゆれ・実コードとの不一致)
- パスのベースが不正確: ドキュメントは
lib/routing/・pubspec.yaml・app.dart表記ですが、本リポジトリは melos 構成で実体はapps/dotto/lib/...・apps/dotto/pubspec.yamlです。冒頭で「パスはapps/dotto/基準」と注記を。 /course/web_pdf_viewer→/course/pdfの暗黙リネーム: 現状分析の表は/course/web_pdf_viewer(実コード一致、course_screen.dart:75等)ですが、2 節の構造図では/course/pdfになっています。リネームするなら「意図的に改名」と明記、しないなら統一を。/subjectと/subjectsの混在: タブ表は/subject、科目詳細表は/subjects/:id。実コードは/subjects/...(複数形、search_subject_screen.dart:131)かつ講義経由は/course/subjects/:id。同一画面が複数パスから到達するので、移行後のパス設計を意図的に決めて統一を。- 過去問 PDF ルートが実コードと不一致&既にバグ: ドキュメントは
/subjects/:id/past_exam/:pastExamId。実コードは/subjects/$pastExamId/past_exams/$filename(subject_detail_past_exam_screen.dart:58)で、コード側にも「正しくは/subjects/${subjectId}/past_exams/${pastExamId}にすべき」という TODO が残っています。移行の好機なので正しい想定パスを明記しておくと良いです。 - タブ単体ルート(
/course/funch等): 現状は明示定義ではなく'/${tab.name}'で動的生成(root_screen.dart:286)。実装イメージとしては問題ありませんが補足があると親切です。 - go_router バージョン:
^15.1.2指定。並行 PR #592 で Flutter 3.44.0 / Dart 3.12.0 へ上げているので、対応バージョンの確認を一言。
方針ドキュメントとしての完成度は高く、上記(特に 1〜3)を追記いただければ実装フェーズに安心して進めると思います。
Generated by Claude Code
|
@devinai |
Co-Authored-By: Kanta Oikawa <iam@kantacky.com>
|
レビューありがとうございます。全指摘事項を反映しました(dcd9b58)。 重要な論点(設計に関わるもの)
軽微な指摘(表記ゆれ・実コードとの不一致)
|
Co-Authored-By: Kanta Oikawa <iam@kantacky.com>
Summary
現在
Navigator(命令型ナビゲーション)で実装されているルーティングをgo_router(宣言型ナビゲーション)に置き換えるための移行方針ドキュメント(docs/go_router_migration_plan.md)を追加。ドキュメントには以下を含む:
StatefulShellRoute.indexedStackによるタブナビゲーション)GoRouterProvider の安定性(refreshListenableパターン)StatefulShellBranchごとの Analytics Observer 設定/subjects複数形、過去問ルート修正等)Review & Testing Checklist for Human
extraパラメータで渡しているオブジェクト(BusTrip等)のディープリンク時の復元方針が適切か確認Notes
Link to Devin session: https://app.devin.ai/sessions/0a58a02cf73d4939ac841d293329810b
Requested by: @kantacky