A Flutter application that searches the GitHub repository using the GitHub API
GitHub Search
GitHub API を利用して GitHub のリポジトリを検索するアプリです。株式会社ゆめみのFlutterエンジニアコードチェックの要件を満たすよう実装しています。
本アプリを通して自分なりの最適なアーキテクチャを確立し、リファレンスコードにすることを目的にしています。
⚠️ 注意 このアプリは
GitHub API
を利用するために GitHub のアクセストークン
をアプリの内部でハードコーディングして保持する構成になっています。このアプリを公開すると悪意のある者にアクセストークン
を抜き取られ悪用される恐れがありますのでお控え下さい。もちろん、手元でビルドして動かすことは問題ありません。
アプリの機能
- シンプルな UI / UX
- GitHub リポジトリの検索と詳細表示
- 無限スクロール対応
- go_router を使った新しいルーティング
- http を使った REST API の実装
- 多言語対応(日本語/英語)
- カスタムフォント対応
- mockito を使った Unit / Widget テスト
- flutter_launcher_icons を使ったアプリアイコン
- flutter_native_splash を使ったスプラッシュ画面
- GitHub Actions による自動テストと自動ビルド
- サポートするプラットフォーム
- iOS / Android / Web / macOS / Windows
今後対応予定
- hive or shared_preferences の利用
- Integration テスト
- テーマ対応
- ダークモード対応
- よりよい UI / UX
対応しないこと
- Firebase 連携
- Flavor 対応(develop / staging / production などの環境分け)
アーキテクチャ / パッケージ
- flutter_riverpod + state_notifier + freezed + go_router
- CODE WITH ANDREA の下記アーキテクチャを参考にしています。本アプリでは、Application Layer は省略しています。
- 本アプリの依存関係図です。
%%{init:{'theme':'base','themeVariables':{'primaryColor':'#f0f0f0','primaryTextColor':'#2f2f2f', 'lineColor':'#2f2f2f','textColor':'#2f2f2f','fontSize':'16px','nodeBorder':'0px'}}}%% graph TD subgraph プレゼンテーション層 IndexPage(一覧ページ<br>StatelessWidget) --> SearchTextField(検索テキストフィールド<br>ConsumerWidget) IndexPage --> ListView(一覧 View<br>ConsumerWidget) SearchTextField --> SearchText([検索文字列<br>String]) ListView --> ListViewState([一覧 View 状態<br>State]) ListViewState --> ListViewController(一覧 View コントローラ<br>StateNotifier) ListViewController --> SearchText ViewPage(詳細ページ<br>StatelessWidget) --> DetailView(詳細 View<br>ConsumerWidget) DetailView --> DetailViewState([詳細 View 状態<br>State]) DetailViewState --> DetailViewController(詳細 View コントローラ<br>StateNotifier) DetailViewController --> ViewParameter([オーナー名とリポジトリ名<br>Equatable]) end subgraph データ層 ListViewController --> RepoRepository(リポジトリ用リポジトリ) DetailViewController ---> RepoRepository RepoRepository --> GitHubRepoRepository(GitHub 向けリポジトリ用リポジトリ) subgraph DTO GitHubRepoRepository --> GitHubHttpClient(GitHub 向け HTTP クライアント) GitHubRepoRepository --> GitHubApiDef(GitHub API 定義) end subgraph データソース GitHubHttpClient --> GitHubApi(GitHub API) end end subgraph 環境変数 SearchText --> EnvSearchText{{検索文字列初期値<br>String}} GitHubHttpClient ---> EnvAccessToken{{アクセストークン<br>String}} end classDef widget fill:#4063DD, color:#ffffff; classDef controller fill:#4063DD, color:#ffffff; classDef state fill:#BDB5F4, color:#ffffff; classDef repository fill:#437C40, color:#ffffff; classDef env fill:#7c7d7c, color:#ffffff; class IndexPage,ViewPage,ListView,SearchTextField,DetailView widget; class ListViewController,DetailViewController controller; class SearchText,ListViewState,DetailViewState,ViewParameter state; class RepoRepository,GitHubRepoRepository,GitHubHttpClient,GitHubApiDef,GitHubApi repository; class EnvSearchText,EnvAccessToken env;
一覧 View
が更新される例一覧 View
の依存関係は、一覧 View
→一覧 View 状態
→一覧 View コントローラ
→検索文字列
となっています。ユーザが検索文字列を変更し検索を実行した場合、検索文字列
が更新されます。すると検索文字列
に依存している一覧 View コントローラ
が更新され、リポジトリ用リポジトリ
に検索文字列
を与えてリポジトリの検索を実行し、その結果をもとに一覧 View 状態
を更新します。すると一覧 View 状態
に依存している一覧 View
がリビルドされて再描画されます。
詳細 View
への画面遷移の例一覧 View
のListTile
がタップされるとオーナー名とリポジトリ名
を表示したい内容に更新して詳細ページ
に画面遷移します。詳細画面
が開くと詳細 View
がビルドされ、詳細 View コントローラ
も作成されます。詳細 View コントローラ
はオーナー名とリポジトリ名
をリポジトリ用リポジトリ
に与えてリポジトリの取得を実行し、その結果をもとに詳細 View 状態
を更新します。すると詳細 View 状態
に依存している詳細 View
がリビルドされて再描画されます。
フォルダ構成
フォルダ名 | 説明 |
---|---|
/ assets |
assets にアクセスする自動生成されるユーティリティクラス |
/ config |
アプリケーション、定義値、環境変数 |
/ entities |
モデル層のファイルリポジトリの戻り値に使うエンティティプレゼンテーション層で使うエンティティ(_data suffix がつく) |
/ localizations |
言語ファイル(arb ファイル)、flutter gen-l10n で生成されるクラス |
/ presentation / pages |
プレゼンテーション層のファイル画面Widget |
/ presentation / widgets |
プレゼンテーション層のファイル部品Widget、Controller、State |
/ repositories |
データ層のファイルリポジトリ、データソースデータソースはサブディレクトリで管理 |
/ utils |
拡張機能、ロガーなど便利クラス |
環境
Version | |
---|---|
Xcode | 13.3 |
Android Studio | Bumblebee 2021.1.1 Patch 2 |
Flutter | 2.10.3 |
Swift | 5.6 |
Kotlin | 1.6.10 |
Chrome | 99 |
対象 OSバージョン
OS Version | |
---|---|
iOS | 9.0 ~ 15.4 |
Android | 8.0 ~ 13 |
ビルド方法
- カレントディレクトリで下記コマンドを実行してください。
bin/flutter_env
は引数で与えられた環境変数を基にビルドに必要なlib/config/env.dart
を作成してくれます。- 作成された
lib/config/env.dart
を直接編集しても大丈夫です。
bin/flutter_env -g [アクセストークン] -s [検索文字列の初期値]
パラメータ名 | 説明 | |
---|---|---|
-g [アクセストークン] |
Must |
値には GitHub 個人アクセストークン を設定してください。 |
-s [検索文字列の初期値] |
Optional |
好きな文字列を設定してください。指定しない場合は空文字が設定されます。 |
-h |
ヘルプを表示します。 |
- Configurations を選択してビルドしてください
Configurations 名 | 説明 |
---|---|
app |
アプリ(iOS / Android)向け |
web |
Web 向け |
コードの自動生成
arb
ファイルを変更した場合やfreezed
を使ったdart
ファイルを変更した場合は下記コマンドを実行してください。
bin/flutter_gen
テスト
- ローカルでテストを行うためには事前に次のライブラリをインストールしてください。
# lcov のインストール
brew install lcov
# dart_dot_reporter のインストール
flutter pub global activate dart_dot_reporter
- ローカルでテストを行う場合は下記コマンドを実行してください。
- 静的解析 => テスト => カバレッジの結果を表示 を行います。
bin/flutter_test
API ドキュメント
-
API ドキュメント で公開しています。
-
ローカルで生成する場合は下記コマンドを実行してください。
bin/dartdoc
CI
- GitHub Actions を利用して CI を構築しています。
- プルリクエストが作成や更新された時、もしくは
main
またはdevelop
ブランチにpush
されたときに CI が発火します。
- プルリクエストが作成や更新された時、もしくは
%%{init:{'theme':'base','themeVariables':{'primaryColor':'#f0f0f0','primaryTextColor':'#2f2f2f', 'lineColor':'#2f2f2f','textColor':'#2f2f2f','fontSize':'16px','nodeBorder':'0px'}}}%% flowchart LR Start((開始)) --> Analyze(静的解析) subgraph テスト Analyze --> Test(単体テスト) Test --> UploadCoverage(Codecovに結果を送信) end subgraph ビルド UploadCoverage --> BuildAndroid(Androidビルド) UploadCoverage --> BuildiOS(iOSビルド) UploadCoverage --> BuildWeb(Webビルド) UploadCoverage --> BuildMacOS(macOSビルド) UploadCoverage --> BuildWindows(Windowsビルド) UploadCoverage --> CreateApiDoc(APIドキュメント作成) CreateApiDoc --> DeployGitHubPages(GitHubPagesにデプロイ) end subgraph レポート BuildAndroid ---> NotifySlack(Slackに結果を送信) BuildiOS ---> NotifySlack BuildWeb ---> NotifySlack BuildMacOS ---> NotifySlack BuildWindows ---> NotifySlack DeployGitHubPages --> NotifySlack end NotifySlack --> End((終了)) classDef anchor fill:#4063DD, color:#ffffff; classDef testJob fill:#4063DD, color:#ffffff; classDef buildJob fill:#d32f2f, color:#ffffff; classDef reportJob fill:#437C40, color:#ffffff; %% class Start,End anchor; class Analyze,Test,UploadCoverage testJob; class BuildAndroid,BuildiOS,BuildWeb,BuildMacOS,BuildWindows,CreateApiDoc,DeployGitHubPages buildJob; class NotifySlack reportJob;
ライセンス
MIT