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 などの環境分け)

アーキテクチャ / パッケージ

  • 本アプリの依存関係図です。

%%{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への画面遷移の例
    • 一覧 ViewListTileがタップされるとオーナー名とリポジトリ名を表示したい内容に更新して詳細ページに画面遷移します。詳細画面が開くと詳細 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

GitHub

View Github