codecov

GitHub 搜索

利用 GitHub API 搜索 GitHub 仓库的应用。实现了株式会社 yumemi 的 Flutter 工程师代码检查的要求。

通过这款应用,旨在确立自己最合适的架构,并将其作为参考代码。

⚠️ 注意 此应用为了使用 `GitHub API`,其配置是将 GitHub 的 `访问令牌` 硬编码在应用内部。如果公开此应用,可能会导致恶意者窃取 `访问令牌` 并滥用,请避免公开。当然,在本地构建和运行是没有问题的。

github_search_0 1 0_demo

应用功能

  • 简洁的 UI / UX
    • GitHub 仓库搜索及详情显示
    • 支持无限滚动
  • 使用 go_router 进行新的路由管理
  • 使用 http 实现 REST API
  • 多语言支持(日语/英语)
  • 支持自定义字体
  • 使用 mockito 进行单元/组件测试
  • 使用 flutter_launcher_icons 设置应用图标
  • 使用 flutter_native_splash 设置启动画面
  • 通过 GitHub Actions 进行自动化测试和构建
  • 支持的平台
    • iOS / Android / Web / macOS / Windows

未来支持计划

不支持的功能

  • Firebase 集成
  • Flavor 支持(开发/预生产/生产等环境划分)

架构 / 软件包

CODE_WITH_ANDREA

  • 这是本应用依赖关系图。

%%{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;
  • 列表视图更新示例
    • 列表视图的依赖关系为:列表视图列表视图状态列表视图控制器搜索字符串。当用户更改搜索字符串并执行搜索时,会更新搜索字符串。然后,依赖于搜索字符串列表视图控制器会更新,将搜索字符串提供给仓库仓库执行仓库搜索,并根据结果更新列表视图状态。然后,依赖于列表视图状态列表视图会重新构建并重绘。
  • 导航到详情视图的示例
    • 当点击列表视图ListTile时,会更新要显示的所有者名称和仓库名称并导航到详情页面。当详情页面打开时,会构建详情视图并创建详情视图控制器详情视图控制器所有者名称和仓库名称提供给仓库仓库执行仓库获取,并根据结果更新详情视图状态。然后,依赖于详情视图状态详情视图会重新构建并重绘。

文件夹结构

文件夹名 说明
/ assets 访问assets的自动生成工具类
/ config 应用程序、定义值、环境变量
/ entities 模型层的文件,用作仓库的返回值实体,演示层使用的实体(带有 `_data` 后缀)
/ localizations 语言文件(`arb` 文件),由 `flutter gen-l10n` 生成的类
/ presentation / pages 演示层的文件,屏幕 Widget
/ presentation / widgets 演示层的文件,组件 Widget、控制器、状态
/ repositories 数据层的文件,仓库、数据源,数据源在子目录中管理
/ utils 扩展功能、日志等实用类

环境

版本
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 版本
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 [访问令牌] 必须 请将 GitHub 个人访问令牌 设置为值。
-s [搜索字符串的初始值] 可选 请设置您喜欢的字符串。如果不指定,则设置为空字符串。
-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。
    • 当创建或更新 Pull Request 时,或者当 `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

查看 Github