Skip to content

Go Router移行方針ドキュメントの追加#593

Draft
devin-ai-integration[bot] wants to merge 3 commits into
mainfrom
devin/1779340154-go-router-migration-plan
Draft

Go Router移行方針ドキュメントの追加#593
devin-ai-integration[bot] wants to merge 3 commits into
mainfrom
devin/1779340154-go-router-migration-plan

Conversation

@devin-ai-integration
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot commented May 21, 2026

Summary

現在 Navigator(命令型ナビゲーション)で実装されているルーティングを go_router(宣言型ナビゲーション)に置き換えるための移行方針ドキュメント(docs/go_router_migration_plan.md)を追加。

ドキュメントには以下を含む:

  • 現状のルーティング構成の分析(タブナビゲーション、全画面遷移パターン、ルート名一覧)
  • Go Router移行後のルート構造設計(StatefulShellRoute.indexedStack によるタブナビゲーション)
  • 各論点の方針(ガード処理、ダイアログ、Analytics連携、ディープリンク、オブジェクトパラメータ等)
  • 動的タブ切り替え(学食 ↔ 科目検索)の案A/B比較と推奨方針
  • GoRouter Provider の安定性(refreshListenable パターン)
  • StatefulShellBranch ごとの Analytics Observer 設定
  • ディープリンクのネイティブ設定(iOS/Android)の必要性
  • パス表記の統一方針(/subjects 複数形、過去問ルート修正等)
  • 5段階の移行手順(Phase 1〜5)

Review & Testing Checklist for Human

  • 動的タブ切り替え(13節)の案A推奨が妥当か確認。Phase 1でのプロトタイプ検証で最終決定
  • 移行後のパス設計(2節)が現在の画面遷移を網羅しているか確認
  • extra パラメータで渡しているオブジェクト(BusTrip 等)のディープリンク時の復元方針が適切か確認

Notes

  • コード変更は含まない方針ドキュメントのみのPR
  • 実際の移行はPhaseごとに別PRで段階的に実施する想定
  • go_router バージョンは PR Flutterバージョンを3.44.0にアップデート #592(Flutter/Dart アップグレード)マージ後に互換性を確認して決定

Link to Devin session: https://app.devin.ai/sessions/0a58a02cf73d4939ac841d293329810b
Requested by: @kantacky

Co-Authored-By: Kanta Oikawa <iam@kantacky.com>
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

Original prompt from Kanta

SYSTEM:
=== BEGIN THREAD HISTORY (in #times_kantacky) ===
<most_recent_message>
Kanta Oikawa (U071TQ4TLTB): @Devin
fun-dotto/appで、ルーティングは何で行われている?
</most_recent_message>
=== END THREAD HISTORY ===

Thread URL: https://furarico.slack.com/archives/C08DF8VMA8N/p1779339211327539?thread_ts=1779339211.327539&amp;cid=C08DF8VMA8N

The latest message is the one right above that tagged you. The <most_recent_message> is the message that you should use to guide your goals + task for this session, and you should use the rest of the slack thread as context.

@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Copy link
Copy Markdown
Member

@kantacky kantacky left a comment

Choose a reason for hiding this comment

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

レビュー(方針ドキュメント)

全体の構成・段階的移行(Phase 分割)・主要論点の洗い出しはよくできており、AGENTS.md の「大規模一括リファクタを避け段階的に移行」の方針とも整合しています。現状分析もおおむね正確(MaterialApp.home → RootScreenFirebaseAnalyticsObserverIndexedStack+タブ別 Navigator、ガード分岐、navigatorKeyspopUntilPopScopemaybePopBusTimetableScreen のオブジェクト渡し、go_router 未導入 — いずれも実コードと一致)です。

マージ前に補強したい点を、設計に関わるものと表記の不一致に分けて挙げます。

重要な論点(設計に関わるもの)

1. 動的タブ切り替え(学食 ↔ 科目検索)と StatefulShellRoute.indexedStack の相性(最重要)
StatefulShellRoute.indexedStack は構築時にブランチ数が固定で、実行時にブランチを追加・削除できません。現状は isFunchEnabled で同一スロットの TabItem.funchTabItem.subject を入れ替えています(apps/dotto/lib/feature/root/root_viewmodel.dart:22-29)。13 節は「条件分岐でブランチ構築 or redirect」とありますが、ここが本移行の最大の難所です。

  • 案A: 両タブを含む固定ブランチを定義し、NavigationBar 側で表示制御
  • 案B: isFunchEnabled 変化時に router を作り直す(→ ナビゲーション状態リセットの副作用に注意)

どちらを採るかを Phase 1 で必ずプロトタイプ検証する旨を明記したいです(PR 本文チェックリストでも未確認項目)。

2. GoRouterref.watch する Provider にする際の再生成問題
3〜4 節で「GoRouter を Riverpod Provider にして ref 経由で状態参照」とありますが、ref.watch した状態が変わるたびに Provider が再評価され GoRouter インスタンスごと作り直されると、ナビゲーションスタックがリセットされます。ルーター本体は安定させ、状態変化は refreshListenableListenable 化した Notifier)で通知するのが定石です。この注意の追記を推奨します。

3. Analytics Observer と StatefulShellRoute の組み合わせ
10 節は「FirebaseAnalyticsObserverGoRouter.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.yamlapp.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/$filenamesubject_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

@kantacky
Copy link
Copy Markdown
Member

@devinai
レビューコメントを修正して。

Co-Authored-By: Kanta Oikawa <iam@kantacky.com>
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

レビューありがとうございます。全指摘事項を反映しました(dcd9b58)。

重要な論点(設計に関わるもの)

  1. 動的タブ切り替え: 案A(両ブランチ固定 + NavigationBar 側制御)と案B(router 再生成)をメリット・デメリット付きで明記し、Phase 1 でのプロトタイプ検証を手順に追加しました。案Aを推奨としています。
  2. GoRouter Provider の再生成問題: refreshListenable パターンの採用方針を注意書きとして追記しました。
  3. Analytics Observer と StatefulShellBranch: 各ブランチの observers にも設定が必要な点を追記し、Phase 5 の動作確認項目にも反映しました。
  4. ディープリンクのネイティブ設定: iOS(Associated Domains)・Android(intent-filter)の設定が別途必要な旨を補足し、Phase 4 の手順にも明記しました。

軽微な指摘(表記ゆれ・実コードとの不一致)

  • パスのベース: 冒頭に「パスは apps/dotto/ 基準」の注記を追加
  • /course/pdf: /course/web_pdf_viewer に統一(現行コードに合わせ、暗黙リネームを撤回)
  • /subject vs /subjects: 移行後のパス設計で /subjects(複数形)に統一する方針を明記
  • 過去問 PDF ルート: 実コードの現状(/subjects/$pastExamId/past_exams/$filename)と既存 TODO を記載し、移行後は /subjects/:subjectId/past_exams/:pastExamId に修正する旨を明記
  • タブルートの動的生成: '/${tab.name}' による動的生成である旨の補足を追加
  • go_router バージョン: PR Flutterバージョンを3.44.0にアップデート #592 との互換性確認が必要な旨の注記を追加

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