Showing preview only (1,318K chars total). Download the full file or copy to clipboard to get everything.
Repository: CarGuo/gsy_github_app_flutter
Branch: master
Commit: 5917c1936240
Files: 369
Total size: 1.2 MB
Directory structure:
gitextract_kfzn5wba/
├── .fvmrc
├── .github/
│ ├── FUNDING.yml
│ └── workflows/
│ └── ci.yml
├── .gitignore
├── .metadata
├── .vscode/
│ └── settings.json
├── AGENTS.md
├── LICENSE
├── README.md
├── README_EN.md
├── RECORD.md
├── UISCENE_PLUGIN_RISK.md
├── VERSION.md
├── analysis_options.yaml
├── android/
│ ├── .gitignore
│ ├── app/
│ │ ├── build.gradle
│ │ ├── exported.gradle
│ │ └── src/
│ │ └── main/
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin/
│ │ │ └── com/
│ │ │ └── shuyu/
│ │ │ └── gsygithub/
│ │ │ └── gsygithubappflutter/
│ │ │ ├── MainActivity.kt
│ │ │ └── UpdateAlbumPlugin.kt
│ │ └── res/
│ │ ├── drawable/
│ │ │ ├── launch_background.xml
│ │ │ └── normal_background.xml
│ │ └── values/
│ │ └── styles.xml
│ ├── build.gradle
│ ├── gradle/
│ │ └── wrapper/
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
│ ├── gradle.properties
│ ├── gradlew
│ ├── gradlew.bat
│ ├── gsygithubapp-debug.jks
│ └── settings.gradle
├── devtools_options.yaml
├── docs/
│ ├── 00-overview/
│ │ └── project-map.md
│ ├── 01-architecture/
│ │ ├── app-layering.md
│ │ └── state-management-matrix.md
│ ├── 02-features/
│ │ ├── debug.md
│ │ ├── dynamic.md
│ │ ├── home.md
│ │ ├── issue.md
│ │ ├── login.md
│ │ ├── notify.md
│ │ ├── push.md
│ │ ├── release.md
│ │ ├── repos.md
│ │ ├── search.md
│ │ ├── trend.md
│ │ └── user.md
│ ├── 03-runbooks/
│ │ └── local-setup.md
│ ├── 04-quality/
│ │ ├── smoke-matrix.md
│ │ └── test-strategy.md
│ ├── 05-ai/
│ │ ├── agent-guide.md
│ │ ├── feature-playbooks/
│ │ │ ├── debug-change.md
│ │ │ ├── dynamic-change.md
│ │ │ ├── home-change.md
│ │ │ ├── issue-change.md
│ │ │ ├── notify-change.md
│ │ │ ├── push-change.md
│ │ │ ├── release-change.md
│ │ │ ├── repos-change.md
│ │ │ ├── search-change.md
│ │ │ ├── trend-change.md
│ │ │ └── user-change.md
│ │ ├── prompts/
│ │ │ ├── author-handoff.md
│ │ │ └── reviewer-system.md
│ │ ├── review-harness.md
│ │ └── task-playbooks/
│ │ ├── add-api.md
│ │ ├── add-page.md
│ │ ├── fix-bug.md
│ │ └── refactor-state.md
│ ├── 06-decisions/
│ │ ├── ADR-0001-状态管理收敛策略.md
│ │ ├── ADR-0002-新增功能默认状态方案.md
│ │ └── README.md
│ ├── CONTRIBUTING_AI.md
│ └── README.md
├── fastlane/
│ └── metadata/
│ └── android/
│ └── en-US/
│ ├── full_description.txt
│ └── short_description.txt
├── ios/
│ ├── .gitignore
│ ├── Flutter/
│ │ ├── AppFrameworkInfo.plist
│ │ ├── Debug.xcconfig
│ │ ├── Release.xcconfig
│ │ └── ephemeral/
│ │ ├── flutter_lldb_helper.py
│ │ └── flutter_lldbinit
│ ├── Podfile
│ ├── Runner/
│ │ ├── AppDelegate.swift
│ │ ├── Assets.xcassets/
│ │ │ ├── AppIcon.appiconset/
│ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ └── LaunchImage.imageset/
│ │ │ └── Contents.json
│ │ ├── Base.lproj/
│ │ │ ├── LaunchScreen.storyboard
│ │ │ └── Main.storyboard
│ │ ├── Info.plist
│ │ ├── Runner-Bridging-Header.h
│ │ └── SceneDelegate.swift
│ ├── Runner.xcodeproj/
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace/
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata/
│ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcshareddata/
│ │ └── xcschemes/
│ │ └── Runner.xcscheme
│ └── Runner.xcworkspace/
│ ├── contents.xcworkspacedata
│ └── xcshareddata/
│ └── IDEWorkspaceChecks.plist
├── l10n.yaml
├── lib/
│ ├── app.dart
│ ├── common/
│ │ ├── config/
│ │ │ └── config.dart
│ │ ├── event/
│ │ │ ├── event_bus.dart
│ │ │ ├── http_error_event.dart
│ │ │ └── index.dart
│ │ ├── local/
│ │ │ └── local_storage.dart
│ │ ├── localization/
│ │ │ ├── extension.dart
│ │ │ └── l10n/
│ │ │ ├── app_en.arb
│ │ │ ├── app_ja.arb
│ │ │ ├── app_ko.arb
│ │ │ ├── app_localizations.dart
│ │ │ ├── app_localizations_en.dart
│ │ │ ├── app_localizations_ja.dart
│ │ │ ├── app_localizations_ko.dart
│ │ │ ├── app_localizations_zh.dart
│ │ │ └── app_zh.arb
│ │ ├── logger.dart
│ │ ├── net/
│ │ │ ├── AGENTS.md
│ │ │ ├── address.dart
│ │ │ ├── api.dart
│ │ │ ├── code.dart
│ │ │ ├── graphql/
│ │ │ │ ├── client.dart
│ │ │ │ ├── repositories.dart
│ │ │ │ └── users.dart
│ │ │ ├── interceptors/
│ │ │ │ ├── error_interceptor.dart
│ │ │ │ ├── header_interceptor.dart
│ │ │ │ ├── log_interceptor.dart
│ │ │ │ ├── response_interceptor.dart
│ │ │ │ └── token_interceptor.dart
│ │ │ ├── result_data.dart
│ │ │ ├── transformer.dart
│ │ │ ├── transformer.g.dart
│ │ │ └── trending/
│ │ │ └── github_trending.dart
│ │ ├── repositories/
│ │ │ ├── data_result.dart
│ │ │ ├── event_repository.dart
│ │ │ ├── issue_repository.dart
│ │ │ ├── repos_repository.dart
│ │ │ └── user_repository.dart
│ │ ├── router/
│ │ │ └── anima_route.dart
│ │ ├── style/
│ │ │ └── gsy_style.dart
│ │ ├── toast.dart
│ │ └── utils/
│ │ ├── code_utils.dart
│ │ ├── common_utils.dart
│ │ ├── event_utils.dart
│ │ ├── html_utils.dart
│ │ └── navigator_utils.dart
│ ├── db/
│ │ ├── provider/
│ │ │ ├── event/
│ │ │ │ ├── received_event_db_provider.dart
│ │ │ │ └── user_event_db_provider.dart
│ │ │ ├── issue/
│ │ │ │ ├── issue_comment_db_provider.dart
│ │ │ │ └── issue_detail_db_provider.dart
│ │ │ ├── repos/
│ │ │ │ ├── read_history_db_provider.dart
│ │ │ │ ├── repository_branch_db_provider.dart
│ │ │ │ ├── repository_commitInfo_detail_db_provider.dart
│ │ │ │ ├── repository_commits_db_provider.dart
│ │ │ │ ├── repository_detail_db_provider.dart
│ │ │ │ ├── repository_detail_readme_db_provider.dart
│ │ │ │ ├── repository_event_db_provider.dart
│ │ │ │ ├── repository_fork_db_provider.dart
│ │ │ │ ├── repository_issue_db_provider.dart
│ │ │ │ ├── repository_pulse_db_provider.dart
│ │ │ │ ├── repository_star_db_provider.dart
│ │ │ │ ├── repository_watcher_db_provider.dart
│ │ │ │ └── trend_repository_db_provider.dart
│ │ │ └── user/
│ │ │ ├── org_member_db_provider.dart
│ │ │ ├── user_followed_db_provider.dart
│ │ │ ├── user_follower_db_provider.dart
│ │ │ ├── user_orgs_db_provider.dart
│ │ │ ├── user_repos_db_provider.dart
│ │ │ ├── user_stared_db_provider.dart
│ │ │ └── userinfo_db_provider.dart
│ │ ├── sql_manager.dart
│ │ └── sql_provider.dart
│ ├── env/
│ │ ├── AGENTS.md
│ │ ├── config_wrapper.dart
│ │ ├── dev.dart
│ │ ├── dev.g.dart
│ │ ├── env_config.dart
│ │ ├── env_config.g.dart
│ │ ├── env_json_dev.json
│ │ ├── env_json_prod.json
│ │ ├── prod.dart
│ │ └── prod.g.dart
│ ├── main.dart
│ ├── main_prod.dart
│ ├── model/
│ │ ├── branch.dart
│ │ ├── branch.g.dart
│ │ ├── commitFile.dart
│ │ ├── commitFile.g.dart
│ │ ├── commit_comment.dart
│ │ ├── commit_comment.g.dart
│ │ ├── commit_git_info.dart
│ │ ├── commit_git_info.g.dart
│ │ ├── commit_git_user.dart
│ │ ├── commit_git_user.g.dart
│ │ ├── commit_stats.dart
│ │ ├── commit_stats.g.dart
│ │ ├── commits_comparison.dart
│ │ ├── commits_comparison.g.dart
│ │ ├── common_list_datatype.dart
│ │ ├── download_source.dart
│ │ ├── download_source.g.dart
│ │ ├── event.dart
│ │ ├── event.g.dart
│ │ ├── event_payload.dart
│ │ ├── event_payload.g.dart
│ │ ├── file_model.dart
│ │ ├── file_model.g.dart
│ │ ├── issue.dart
│ │ ├── issue.g.dart
│ │ ├── issue_event.dart
│ │ ├── issue_event.g.dart
│ │ ├── license.dart
│ │ ├── license.g.dart
│ │ ├── notification.dart
│ │ ├── notification.g.dart
│ │ ├── notification_subject.dart
│ │ ├── notification_subject.g.dart
│ │ ├── push_commit.dart
│ │ ├── push_commit.g.dart
│ │ ├── push_event_commit.dart
│ │ ├── push_event_commit.g.dart
│ │ ├── release.dart
│ │ ├── release.g.dart
│ │ ├── release_asset.dart
│ │ ├── release_asset.g.dart
│ │ ├── repo_commit.dart
│ │ ├── repo_commit.g.dart
│ │ ├── repository.dart
│ │ ├── repository.g.dart
│ │ ├── repository_permissions.dart
│ │ ├── repository_permissions.g.dart
│ │ ├── repository_ql.dart
│ │ ├── search_user_ql.dart
│ │ ├── template.dart
│ │ ├── template.g.dart
│ │ ├── trending_repo_model.dart
│ │ ├── trending_repo_model.g.dart
│ │ ├── user.dart
│ │ ├── user.g.dart
│ │ ├── user_org.dart
│ │ └── user_org.g.dart
│ ├── page/
│ │ ├── AGENTS.md
│ │ ├── code_detail_page_web.dart
│ │ ├── common_list_page.dart
│ │ ├── debug/
│ │ │ ├── debug_data_page.dart
│ │ │ └── debug_label.dart
│ │ ├── dynamic/
│ │ │ ├── dynamic_bloc.dart
│ │ │ └── dynamic_page.dart
│ │ ├── error_page.dart
│ │ ├── gsy_webview.dart
│ │ ├── home/
│ │ │ ├── home_page.dart
│ │ │ └── widget/
│ │ │ └── home_drawer.dart
│ │ ├── honor_list_page.dart
│ │ ├── issue/
│ │ │ ├── issue_detail_page.dart
│ │ │ ├── issue_edit_dIalog.dart
│ │ │ └── widget/
│ │ │ ├── issue_header_item.dart
│ │ │ └── issue_item.dart
│ │ ├── login/
│ │ │ ├── login_page.dart
│ │ │ └── login_webview.dart
│ │ ├── my_page.dart
│ │ ├── notify/
│ │ │ └── notify_page.dart
│ │ ├── photoview_page.dart
│ │ ├── push/
│ │ │ ├── push_detail_page.dart
│ │ │ └── widget/
│ │ │ ├── push_coed_item.dart
│ │ │ └── push_header.dart
│ │ ├── release/
│ │ │ ├── release_page.dart
│ │ │ └── widget/
│ │ │ └── release_item.dart
│ │ ├── repos/
│ │ │ ├── provider/
│ │ │ │ ├── repos_detail_provider.dart
│ │ │ │ └── repos_network_provider.dart
│ │ │ ├── repository_detail_issue_list_page.dart
│ │ │ ├── repository_detail_page.dart
│ │ │ ├── repository_detail_readme_page.dart
│ │ │ ├── repository_file_list_page.dart
│ │ │ ├── repostory_detail_info_page.dart
│ │ │ └── widget/
│ │ │ ├── repos_header_item.dart
│ │ │ └── repos_item.dart
│ │ ├── search/
│ │ │ ├── search_bloc.dart
│ │ │ ├── search_page.dart
│ │ │ └── widget/
│ │ │ ├── gsy_search_drawer.dart
│ │ │ └── gsy_search_input_widget.dart
│ │ ├── trend/
│ │ │ ├── trend_page.dart
│ │ │ ├── trend_provider.dart
│ │ │ ├── trend_provider.g.dart
│ │ │ ├── trend_user_page.dart
│ │ │ ├── trend_user_provider.dart
│ │ │ └── trend_user_provider.g.dart
│ │ ├── user/
│ │ │ ├── base_person_provider.dart
│ │ │ ├── base_person_provider.g.dart
│ │ │ ├── base_person_state.dart
│ │ │ ├── person_page.dart
│ │ │ └── widget/
│ │ │ ├── user_header.dart
│ │ │ └── user_item.dart
│ │ ├── user_profile_page.dart
│ │ └── welcome_page.dart
│ ├── provider/
│ │ ├── app_state_provider.dart
│ │ └── app_state_provider.g.dart
│ ├── redux/
│ │ ├── gsy_state.dart
│ │ ├── login_redux.dart
│ │ ├── middleware/
│ │ │ ├── combine_epics.dart
│ │ │ ├── epic.dart
│ │ │ ├── epic_middleware.dart
│ │ │ └── epic_store.dart
│ │ └── user_redux.dart
│ ├── test/
│ │ ├── demo_app.dart
│ │ ├── demo_appbar.dart
│ │ ├── demo_bloc_page.dart
│ │ ├── demo_db.dart
│ │ ├── demo_item.dart
│ │ ├── demo_mixins.dart
│ │ ├── demo_page.dart
│ │ ├── demo_tab_page.dart
│ │ ├── demo_text_field_page.dart
│ │ ├── demo_user_store.dart
│ │ └── demo_widget.dart
│ └── widget/
│ ├── anima/
│ │ └── curves_bezier.dart
│ ├── animated_background.dart
│ ├── diff_scale_text.dart
│ ├── flutter_json_widget.dart
│ ├── gsy_bottom_action_bar.dart
│ ├── gsy_card_item.dart
│ ├── gsy_common_option_widget.dart
│ ├── gsy_event_item.dart
│ ├── gsy_flex_button.dart
│ ├── gsy_icon_text.dart
│ ├── gsy_input_widget.dart
│ ├── gsy_select_item_widget.dart
│ ├── gsy_tabbar_widget.dart
│ ├── gsy_tabs.dart
│ ├── gsy_title_bar.dart
│ ├── gsy_user_icon_widget.dart
│ ├── markdown/
│ │ ├── gsy_markdown_widget.dart
│ │ └── syntax_high_lighter.dart
│ ├── menu/
│ │ ├── flutter_radial_menu.dart
│ │ └── src/
│ │ ├── arc_progress_indicator.dart
│ │ ├── radial_menu.dart
│ │ ├── radial_menu_button.dart
│ │ ├── radial_menu_center_button.dart
│ │ └── radial_menu_item.dart
│ ├── mole_widget.dart
│ ├── never_overscroll_indicator.dart
│ ├── only_share_widget.dart
│ ├── particle/
│ │ ├── particle_model.dart
│ │ ├── particle_painter.dart
│ │ └── particle_widget.dart
│ ├── pull/
│ │ ├── custom_bouncing_scroll_physics.dart
│ │ ├── gsy_flare_mutli_pull_controller.dart
│ │ ├── gsy_flare_pull_controller.dart
│ │ ├── gsy_pull_load_widget.dart
│ │ ├── gsy_pull_new_load_widget.dart
│ │ ├── gsy_refresh_sliver.dart
│ │ └── nested/
│ │ ├── gsy_nested_pull_load_widget.dart
│ │ ├── gsy_sliver_header_delegate.dart
│ │ └── nested_refresh.dart
│ └── state/
│ └── gsy_list_state.dart
├── pubspec.yaml
├── static/
│ ├── file/
│ │ ├── Space-Demo.flr
│ │ ├── flare_flutter_logo_.flr
│ │ ├── launch.riv
│ │ ├── loading_world_now.flr
│ │ ├── rejection.json
│ │ ├── rejection2.json
│ │ ├── search.json
│ │ └── user.json
│ └── font/
│ ├── demo.css
│ ├── demo_fontclass.html
│ ├── demo_symbol.html
│ ├── demo_unicode.html
│ ├── iconfont.css
│ └── iconfont.js
└── tool/
└── ai/
└── build_review_bundle.ps1
================================================
FILE CONTENTS
================================================
================================================
FILE: .fvmrc
================================================
{
"flutter": "3.38.4"
}
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
custom: http://img.cdn.guoshuyu.cn/thanks.jpg
================================================
FILE: .github/workflows/ci.yml
================================================
name: CI
on:
push:
branches:
- master
tags:
- '*'
pull_request:
paths-ignore:
- '**/*.md'
- '**/*.txt'
- '**/*.png'
- '**/*.jpg'
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Free Disk Space
uses: jlumbroso/free-disk-space@main
with:
tool-cache: false
android: false
dotnet: true
haskell: true
large-packages: true
docker-images: true
swap-storage: true
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
with:
distribution: 'zulu'
java-version: 21
- uses: subosito/flutter-action@v1
with:
flutter-version: '3.38.4'
- name: Create config file
run: |
echo 'class NetConfig { static const CLIENT_ID = "${{ secrets.CLIENT_ID }}"; static const CLIENT_SECRET = "${{ secrets.CLIENT_SECRET }}";}' > lib/common/config/ignoreConfig.dart
- run: flutter pub get
- run: flutter build apk --release --target-platform=android-arm64 --no-shrink
apk:
name: Generate APK
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
steps:
- name: Free Disk Space
uses: jlumbroso/free-disk-space@main
with:
tool-cache: false
android: false
dotnet: true
haskell: true
large-packages: true
docker-images: true
swap-storage: true
- name: Checkout
uses: actions/checkout@v2
- name: Setup JDK
uses: actions/setup-java@v2
with:
distribution: 'zulu'
java-version: 21
- uses: subosito/flutter-action@v1
with:
flutter-version: '3.38.4'
- name: Create config file
run: |
echo 'class NetConfig { static const CLIENT_ID = "${{ secrets.CLIENT_ID }}"; static const CLIENT_SECRET = "${{ secrets.CLIENT_SECRET }}";}' > lib/common/config/ignoreConfig.dart
- run: flutter pub get
- run: flutter build apk --release --target-platform=android-arm64 --no-shrink
- name: Upload APK
uses: actions/upload-artifact@v4
with:
name: apk
path: build/app/outputs/apk/release/app-release.apk
release:
name: Release APK
needs: apk
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
steps:
- name: Free Disk Space
uses: jlumbroso/free-disk-space@main
with:
tool-cache: false
android: false
dotnet: true
haskell: true
large-packages: true
docker-images: true
swap-storage: true
- name: Download APK from build
uses: actions/download-artifact@v4
with:
name: apk
- name: Display structure of downloaded files
run: ls -R
- name: Create Release
id: create_release
uses: actions/create-release@v1.1.4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: ${{ github.ref }}
- name: Upload Release APK
id: upload_release_asset
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./app-release.apk
asset_name: app-release.apk
asset_content_type: application/zip
================================================
FILE: .gitignore
================================================
.DS_Store
.dart_tool/
.packages
.pub/
build/
.flutter-plugins
.flutter-plugins-dependencies
.gradle/
ignoreConfig.dart
flutter_export_environment.sh
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.pub-cache/
/build/
# Web related
lib/generated_plugin_registrant.dart
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Exceptions to above rules.
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
# FVM Version Cache
.fvm/
================================================
FILE: .metadata
================================================
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: 18cd7a3601bcffb36fdf2f679f763b5e827c2e8e
channel: unknown
project_type: app
================================================
FILE: .vscode/settings.json
================================================
{
"java.configuration.updateBuildConfiguration": "disabled"
}
================================================
FILE: AGENTS.md
================================================
# GSY GitHub App Flutter 协作说明
这是一个 Flutter GitHub 客户端,同时也是带有教学展示性质的示例工程。
不要假设整个仓库是单一架构风格。多种状态管理方案并存是当前设计现实,不是偶然脏代码。
## 进入仓库后先读
在进行非微小改动前,先读这些文件:
1. `README.md`
2. `docs/README.md`
3. `docs/00-overview/project-map.md`
4. `docs/01-architecture/app-layering.md`
5. `docs/01-architecture/state-management-matrix.md`
## 工作规则
- 改动尽量限制在当前功能域,不要顺手做跨模块重构。
- 非任务明确要求时,不要迁移状态管理框架。
- 优先遵循目标模块现有模式,而不是引入新的全局规范。
- 未经明确允许,不得为了满足需求擅自替换模块既有框架或状态实现,即使替换后看起来更简单。
- `*.g.dart`、多语言生成文件、env 生成文件都视为生成产物;优先重新生成,不要手改。
- 不要提交密钥。`lib/common/config/ignoreConfig.dart` 属于本地或 CI 环境材料。
## 高风险目录
- `lib/app.dart`:应用根装配、导航、全局报错、Redux 和 Riverpod 混合接线
- `lib/common/net/`:共享网络栈、拦截器、GraphQL/REST 入口
- `lib/common/repositories/`:功能数据访问边界
- `lib/env/`:构建期环境配置和生成文件
- `lib/common/localization/`:ARB 与多语言生成输出
## 建议修改策略
- 纯 UI 任务:优先只改页面或局部 widget,不碰全局状态
- API 任务:同时检查 `common/net` 与对应 `common/repositories`
- 状态任务:沿用该模块当前已有状态方案,除非任务明确要求迁移
- 配置/构建任务:同步更新 `docs/03-runbooks/` 中的操作说明
## Review 规则
- 中等以上改动默认使用独立 reviewer 上下文
- 每次非微小代码改动后,默认拉起新的 reviewer subagent 或新的干净上下文审查刚刚的修改
- author 在通过一轮新的 reviewer subagent 审查前,不应直接宣告代码任务完成
- reviewer 不应复用 author 的完整上下文历史
- 先看 `docs/05-ai/review-harness.md`
- reviewer 提示模板见 `docs/05-ai/prompts/reviewer-system.md`
- `tool/ai/build_review_bundle.ps1` 只是可选辅助,不是主流程
## 本地最小验证
按改动范围选择最小验证集合:
- `flutter pub get`
- `dart run build_runner build --delete-conflicting-outputs`
- `flutter gen-l10n`
- `flutter analyze`
- `flutter build apk --release --target-platform=android-arm64 --no-shrink`
说明:
- 改模型、env、注解生成代码时跑 `build_runner`
- 改 ARB 或本地化输入时跑 `flutter gen-l10n`
- 改 Android 构建、依赖或运行时关键路径时跑 APK 构建
## 当前已知约束
- 仓库目前没有提交进来的 `test/` 测试目录
- CI 使用 GitHub Actions,当前偏重构建成功
- 项目同时使用 Redux、Riverpod、Provider、Signals
- OAuth 登录相关流程依赖本地 `ignoreConfig.dart`
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================

[](https://github.com/CarGuo/gsy_github_app_flutter/actions)
[](https://github.com/CarGuo/GSYGithubAppFlutter/stargazers)
[](https://github.com/CarGuo/GSYGithubAppFlutter/network)
[](https://github.com/CarGuo/GSYGithubAppFlutter/issues)
[](https://github.com/CarGuo/GSYGithubAppFlutter/blob/master/LICENSE)
[](https://gitcode.com/ZuoYueLiang/gsy_github_app_flutter)
### [English Readme](https://github.com/CarGuo/GSYGithubAppFlutter/blob/master/README_EN.md)
## 一款跨平台的开源Github客户端App,提供更丰富的功能,更好体验,旨在更好的日常管理和维护个人Github,提供更好更方便的驾车体验~~Σ( ̄。 ̄ノ)ノ。项目涉及各种常用控件、网络、数据库、设计模式、主题切换、多语言、状态管理(Redux、Riverpod、Provider)等。在开发学习过程中,提供丰富的同款对比:
* ### 同款Weex版 ( https://github.com/CarGuo/GSYGithubAppWeex )
* ### 同款ReactNative版 ( https://github.com/CarGuo/GSYGithubApp )
* ### 同款Android Kotlin View版本( https://github.com/CarGuo/GSYGithubAppKotlin )
* ### 同款Android Compose版本( https://github.com/CarGuo/GSYGithubAppCompose )
* ### 简单 Flutter 独立学习项目 ( https://github.com/CarGuo/gsy_flutter_demo )
## AI 协作与贡献入口
如果你希望用 AI 或更工程化的方式参与这个仓库,建议不要只看本 README,先看下面这些文档入口:
- 总导航:`docs/CONTRIBUTING_AI.md`
- 文档索引:`docs/README.md`
- 项目地图:`docs/00-overview/project-map.md`
- 分层边界:`docs/01-architecture/app-layering.md`
- 状态管理边界:`docs/01-architecture/state-management-matrix.md`
- 手工回归矩阵:`docs/04-quality/smoke-matrix.md`
按任务类型进入:
- 修 Bug:`docs/05-ai/task-playbooks/fix-bug.md`
- 新增页面:`docs/05-ai/task-playbooks/add-page.md`
- 新增接口:`docs/05-ai/task-playbooks/add-api.md`
- 状态整理:`docs/05-ai/task-playbooks/refactor-state.md`
按功能域进入:
- 仓库详情:`docs/05-ai/feature-playbooks/repos-change.md`
- 趋势页:`docs/05-ai/feature-playbooks/trend-change.md`
- 通知页:`docs/05-ai/feature-playbooks/notify-change.md`
- Issue:`docs/05-ai/feature-playbooks/issue-change.md`
- 搜索:`docs/05-ai/feature-playbooks/search-change.md`
- 用户页:`docs/05-ai/feature-playbooks/user-change.md`
- 首页容器:`docs/05-ai/feature-playbooks/home-change.md`
- 动态页:`docs/05-ai/feature-playbooks/dynamic-change.md`
- Release:`docs/05-ai/feature-playbooks/release-change.md`
- Push 提交详情:`docs/05-ai/feature-playbooks/push-change.md`
- 调试页:`docs/05-ai/feature-playbooks/debug-change.md`
长期规则:
- 状态管理收敛策略:`docs/06-decisions/ADR-0001-状态管理收敛策略.md`
- 新增功能默认状态方案:`docs/06-decisions/ADR-0002-新增功能默认状态方案.md`
Review harness:
- author / reviewer 分离:`docs/05-ai/review-harness.md`
- reviewer prompt:`docs/05-ai/prompts/reviewer-system.md`
- review bundle 脚本(可选辅助):`tool/ai/build_review_bundle.ps1`
## 相关文章
| 公众号 | 掘金 | 知乎 | CSDN | 简书
|---------|---------|--------- |---------|---------|
| GSYTech | [点我](https://juejin.cn/user/582aca2ba22b9d006b59ae68/posts) | [点我](https://www.zhihu.com/people/carguo) | [点我](https://blog.csdn.net/ZuoYueLiang) | [点我](https://www.jianshu.com/u/6e613846e1ea)
- ### [Flutter系列文章专栏](https://juejin.cn/column/6960546078202527774)
----
- ### [Flutter 独立简单学习演示项目](https://github.com/CarGuo/gsy_flutter_demo)
- ### [Flutter 完整开发实战详解 Gitbook 预览下载](https://github.com/CarGuo/gsy_flutter_book)
- ### [所有运行问题请点击这里](https://github.com/CarGuo/gsy_github_app_flutter/issues/13)
* ### GSY老书:[《Flutter开发实战详解》](https://item.jd.com/12883054.html)上架啦:[京东](https://item.jd.com/12883054.html) / [当当](http://product.dangdang.com/28558519.html) / 电子版[京东读书](https://e.jd.com/30624414.html)和[Kindle](https://www.amazon.cn/dp/B08BHQ4TKK/ref=sr_1_5?__mk_zh_CN=亚马逊网站&keywords=flutter&qid=1593498531&s=digital-text&sr=1-5)
- ### [如果克隆太慢或者图片看不到,可尝试从码云地址下载](https://gitee.com/CarGuo/GSYGithubAppFlutter)
-----
## 须知
> **因为是偏学习展示项目,所以项目里会有各式各样的模式、库、UI等,请不要介意**
>
> 0、 全局状态管理目前有多种模式,包括 Provider、Redux、Riverpod 等
>
> 1、 TrendPage : 目前采用纯 riverpod 状态管理,演示
>
> 2、 Provider:目前在 RepositoryDetailPage 出使用
>
> 3、 Redux:目前展示了全局登陆和用户信息等上面使用。
>
> 4、 riverpod:目前用于管理全局灰度,多语言。
>
> 5、 Repos 等请求展示了 graphQL
>
> 6、 Redux:目前展示了全局登陆和用户信息等上面使用。
>
> 7、 Signals:目前用于 NotifyPage、RepositoryDetailFileListPage 页面内状态管理
>
> **列表显示有多个,其中:**
>
> 1、**gsy_pull_load_widget.dart.dart**
> `common_list_page.dart 等使用,搭配 gsy_list_state.dart 使用`
>
> 2、**gsy_pull_new_load_widget.dart.dart**
> `dynamic_page.dart 等使用,搭配 gsy_bloc_list_state.dart 使用`
> `有 iOS 和 Android 两种风格下拉风格支持`
>
> 3、**gsy_nested_pull_load_widget.dart**
> `trend_page.dart 等使用,配置sliver 效果`
## 编译运行流程
1、配置好Flutter开发环境(目前Flutter SDK 版本 **3.38**),可参阅 [【搭建环境】](https://flutterchina.club)。
2、clone代码,执行`Packages get`安装第三方包。(因为某些不可抗力原因,国内可能需要设置代理: [代理环境变量](https://flutterchina.club/setup-windows/))
>### 3、重点:你需要自己在lib/common/config/目录下 创建一个`ignoreConfig.dart`文件,然后输入你申请的Github client_id 和 client_secret。
class NetConfig {
static const CLIENT_ID = "xxxx";
static const CLIENT_SECRET = "xxxxxxxxxxx";
}
[ 注册 Github APP 传送门](https://github.com/settings/applications/new),当然,前提是你现有一个github账号(~ ̄▽ ̄)~ 。
### 4、如果使用安全登录(授权登录),那么在上述注册 Github App 的 Authorization callback URL 一栏必须填入 `gsygithubapp://authed`
<div>
<img src="http://img.cdn.guoshuyu.cn/register0.png" width="426px"/>
<img src="http://img.cdn.guoshuyu.cn/register1.jpg" width="426px"/>
</div>
### 5、运行之前请注意下
>### 1、本地 Flutter SDK 版本 3.38 ; 2、是否执行过 `flutter pub get`;3、 网络等问题参考: [如果出现登陆失败或者请求失败 ](https://github.com/CarGuo/gsy_github_app_flutter/issues/643)
### 下载
#### Apk下载链接: [Apk下载链接1 ](https://github.com/CarGuo/gsy_github_app_flutter/releases)
#### Apk下载链接: [Apk下载链接2 ](https://www.openapk.net/gsygithubappflutter/com.shuyu.gsygithub.gsygithubappflutter/)

| 类型 | 二维码 |
| ----------- | ---------------------------------------- |
| **Apk二维码** |  |
| **iOS暂无下载** | |
## 项目结构图

### 常见问题
* 如果包同步失败,一般都是因为没设置包代理,可以参考:[环境变量问题](https://github.com/CarGuo/GSYGithubAppFlutter/issues/13)
* [如果克隆太慢,可尝试码云地址下载](https://gitee.com/CarGuo/GSYGithubAppFlutter)
### 示例图片
### 示例图片


<img src="http://img.cdn.guoshuyu.cn/showapp1.jpg" width="426px"/>
<img src="http://img.cdn.guoshuyu.cn/showapp2.jpg" width="426px"/>
<img src="http://img.cdn.guoshuyu.cn/showapp3.jpg" width="426px"/>
### 框架
>当前 Flutter SDK 版本 3.38
```
用户交互 → UI层(Widget/Page) → 状态层(Redux/Provider/Riverpod) → 服务层(Repositories)
→ 网络层(Net) → GitHub API → 数据模型(Model) → 本地存储(DB) → UI更新
```
```
┌─────────────────────────────────────────────────────────────────┐
│ GSY GitHub App │
├─────────────┬───────────────┬────────────────┬─────────────────┤
│ UI Layer │ State Layer │ Service Layer │ Data Layer │
├─────────────┼───────────────┼────────────────┼─────────────────┤
│ │ │ │ │
│ ┌─────────┐│ ┌─────────┐ │ ┌─────────┐ │ ┌─────────┐ │
│ │ Pages ││ │ Redux │ │ │Repositories│ │ │ Models │ │
│ └─────────┘│ └─────────┘ │ └─────────┘ │ └─────────┘ │
│ │ │ │ │
│ ┌─────────┐│ ┌─────────┐ │ ┌─────────┐ │ ┌─────────┐ │
│ │ Widgets ││ │ Provider│ │ │Network API│ │ │Database │ │
│ └─────────┘│ └─────────┘ │ └─────────┘ │ └─────────┘ │
│ │ │ │ │
│ ┌─────────┐│ ┌─────────┐ │ │ │
│ │Common UI││ │Riverpod │ │ │ │
│ └─────────┘│ └─────────┘ │ │ │
│ │ │ │ │
│ │ ┌─────────┐ │ │ │
│ │ │ Signals │ │ │ │
│ │ └─────────┘ │ │ │
│ │ │ │ │
└─────────────┴───────────────┴────────────────┴─────────────────┘
```
```
lib/
├── main.dart # 应用入口点
├── main_prod.dart # 生产环境入口点
├── app.dart # 应用配置与路由
├── common/ # 公共功能模块
│ ├── config/ # 应用配置
│ ├── event/ # 事件总线
│ ├── local/ # 本地化
│ ├── localization/ # 多语言支持
│ ├── net/ # 网络请求
│ ├── repositories/ # 数据仓库
│ ├── router/ # 路由配置
│ ├── style/ # 样式配置
│ └── utils/ # 工具类
├── db/ # 数据库相关
│ ├── provider/ # 数据库提供者
│ ├── sql_manager.dart # SQL管理器
│ └── sql_provider.dart # SQL提供者
├── env/ # 环境配置
├── model/ # 数据模型
├── page/ # 页面
│ ├── debug/ # 调试页面
│ ├── dynamic/ # 动态页面
│ ├── home/ # 主页
│ ├── issue/ # Issue相关页面
│ ├── login/ # 登录页面
│ ├── push/ # 推送相关页面
│ ├── release/ # 发布相关页面
│ ├── repos/ # 仓库相关页面
│ ├── search/ # 搜索页面
│ ├── trend/ # 趋势页面
│ └── user/ # 用户相关页面
├── provider/ # Provider状态管理
├── redux/ # Redux状态管理
│ ├── middleware/ # Redux中间件
│ ├── gsy_state.dart # Redux状态定义
│ ├── login_redux.dart # 登录状态管理
│ └── user_redux.dart # 用户状态管理
├── test/ # 测试相关
└── widget/ # 自定义组件
├── anima/ # 动画组件
├── markdown/ # Markdown渲染组件
├── menu/ # 菜单组件
├── particle/ # 粒子效果组件
├── pull/ # 下拉刷新组件
└── state/ # 状态相关组件
```
riverpod 页面内状态管理:
```
┌───────────────────────────────────────────────────────────────────────────┐
│ Page Architecture Overview │
└───────────────────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────────────────┐
│ Global State │
│ ┌───────────────────┐ ┌────────────────────┐ ┌────────────────────┐ │
│ │ appThemeProvider │ │ appLocalProvider │ │ appGrepProvider │ │
│ │ (Theme Data) │ │ (Localization) │ │ (Grayscale Mode) │ │
│ └───────────────────┘ └────────────────────┘ └────────────────────┘ │
└───────────────────────────────────────────────────────────────────────────┘
│
┌────────────────┴────────────────┐
▼ ▼
┌─────────────────────────────────┐ ┌─────────────────────────────────────┐
│ TrendPage (Riverpod) │ │ NotifyPage (Signals) │
├─────────────────────────────────┤ ├─────────────────────────────────────┤
│ │ │ │
│┌─────────────────────────────┐ │ │┌───────────────────────────────────┐│
││ Riverpod Providers │ │ ││ Signals State ││
││┌───────────────────────────┐│ │ ││┌─────────────────────────────────┐││
│││ trendFirstProvider ││ │ │││ notifySignal (List) │││
│││ trendSecondProvider ││ │ │││ notifyIndexSignal (int) │││
││└───────────────────────────┘│ │ │││ signalPage (int) │││
│└─────────────────────────────┘ │ ││└─────────────────────────────────┘││
│ │ │└───────────────────────────────────┘│
│┌─────────────────────────────┐ │ │┌───────────────────────────────────┐│
││ Local State (StatefulWidget)│ │ ││ SignalsMixin Processing ││
││ - UI Controls │ │ ││ - createEffect() for reactions ││
││ - Filter Parameters │ │ ││ - Manages data loading ││
│└─────────────────────────────┘ │ ││ - Updates UI based on signals ││
│ │ │└───────────────────────────────────┘│
└─────────────────────────────────┘ └─────────────────────────────────────┘
│ │
└────────────────┬────────────────┘
▼
┌───────────────────────────────────────────────────────────────────────────┐
│ Data Layer │
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ ReposRepository / UserRepository │ │
│ │ ┌────────────────────────┐ ┌─────────────────────────────────┐ │ │
│ │ │ Network Request │───┬──▶│ Database Providers │ │ │
│ │ │ - API calls │ │ │ - Data caching │ │ │
│ │ └────────────────────────┘ │ └─────────────────────────────────┘ │ │
│ │ │ │ │
│ │ │ ┌─────────────────────────────────┐ │ │
│ │ └──▶│ Data Models │ │ │
│ │ │ - Structure definitions │ │ │
│ │ └─────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────────────────┐
│ UI Components │
│ ┌────────────────────┐ ┌────────────────────┐ ┌────────────────────┐ │
│ │ View Models │ │ List Items │ │ Interactive UI │ │
│ │ - Data Formatting │ │ - Item Rendering │ │ - User Actions │ │
│ └────────────────────┘ └────────────────────┘ └────────────────────┘ │
└───────────────────────────────────────────────────────────────────────────┘
```
provider 页面内状态管理:
```
+-----------------------------------------------------+
| App User Interface |
+-----------------------------------------------------+
|
v
+-----------------------------------------------------+
| RepositoryDetailPage (StatefulWidget) |
| with SingleTickerProviderStateMixin |
+-----------------------------------------------------+
|
v
+-----------------------------------------------------+
| MultiProvider |
+-----------------------------------------------------+
| |
v v
+------------------+ +-----------------------+
| ReposNetWork |<----------| ReposDetailProvider |
| Provider | | |
+---------+--------+ +-----------------------+
| |
| |
v v
+-----------------------------------------------------+
| Repository Data Services |
| (ReposRepository, IssueRepository) |
+-----------------------------------------------------+
|
v
+-----------------------------------------------------+
| Four Tab Pages (Consumers) |
+-----------------------------------------------------+
| | | |
v v v v
+----------+ +----------+ +----------+ +----------+
| Info | | Readme | | Issues | | Files |
| Page | | Page | | Page | | Page |
+----------+ +----------+ +----------+ +----------+
| | | |
| | | |
v v v v
+-----------------------------------------------------+
| GlobalKeys for Tab Access |
| (infoListKey, readmeKey, issueListKey, fileListKey) |
+-----------------------------------------------------+
```




> 更多可见:https://codewiki.google/github.com/carguo/gsy_github_app_flutter
## Star History Chart
[](https://star-history.com/#CarGuo/gsy_github_app_flutter&Date)


### LICENSE
```
CarGuo/GSYGithubAppFlutter is licensed under the
Apache License 2.0
A permissive license whose main conditions require preservation of copyright and license notices.
Contributors provide an express grant of patent rights.
Licensed works, modifications, and larger works may be distributed under different terms and without source code.
```
================================================
FILE: README_EN.md
================================================

[](https://github.com/CarGuo/gsy_github_app_flutter/actions)
[](https://github.com/CarGuo/GSYGithubAppFlutter/stargazers)
[](https://github.com/CarGuo/GSYGithubAppFlutter/network)
[](https://github.com/CarGuo/GSYGithubAppFlutter/issues)
[](https://github.com/CarGuo/GSYGithubAppFlutter/blob/master/LICENSE)
[](https://gitcode.com/ZuoYueLiang/gsy_github_app_flutter)
### [Chinese Readme](https://github.com/CarGuo/GSYGithubAppFlutter/blob/master/README.md)
## A cross-platform open source Github client App, offering richer features and better experience. Designed for better daily management and maintenance of your personal Github account, providing a more convenient driving experience~~Σ( ̄。 ̄ノ)ノ. The project involves various common widgets, networking, databases, design patterns, theme switching, multi-language support, state management (Redux, Riverpod, Provider), and more. During the development and learning process, it provides rich comparisons with equivalent implementations:
* ### Same Weex version ( https://github.com/CarGuo/GSYGithubAppWeex )
* ### Same ReactNative version ( https://github.com/CarGuo/GSYGithubApp )
* ### Same Android Kotlin View version ( https://github.com/CarGuo/GSYGithubAppKotlin )
* ### Same Android Compose version ( https://github.com/CarGuo/GSYGithubAppCompose )
* ### Simple Flutter standalone learning project ( https://github.com/CarGuo/gsy_flutter_demo )
## Related Articles
- ## [Flutter Series Articles Column](https://juejin.cn/column/6960546078202527774)
----
- ## [Flutter Simple Learning Demo Project](https://github.com/CarGuo/gsy_flutter_demo)
- ## [Flutter Complete Development Practical Detailed Gitbook Preview Download](https://github.com/CarGuo/gsy_flutter_book)
- ## [For all running issues please click here](https://github.com/CarGuo/gsy_github_app_flutter/issues/13)
* ### GSY's old book: [《Flutter Development in Action》](https://item.jd.com/12883054.html) is available: [JD.com](https://item.jd.com/12883054.html) / [Dangdang](http://product.dangdang.com/28558519.html) / E-book [JD Reading](https://e.jd.com/30624414.html) and [Kindle](https://www.amazon.cn/dp/B08BHQ4TKK/ref=sr_1_5?__mk_zh_CN=亚马逊网站&keywords=flutter&qid=1593498531&s=digital-text&sr=1-5)
- ### [If cloning is too slow or if images don't display, you can try downloading from the Gitee address](https://gitee.com/CarGuo/GSYGithubAppFlutter)
-----
## Important Notes
> **Since this is primarily a learning and demonstration project, it includes various patterns, libraries, UIs, etc. Please don't mind the diversity**
>
> 0. Global state management currently has multiple modes, including Provider, Redux, Riverpod, etc.
>
> 1. TrendPage: Currently uses pure riverpod state management for demonstration
>
> 2. Provider: Currently used in RepositoryDetailPage
>
> 3. Redux: Currently demonstrated for global login and user information.
>
> 4. riverpod: Currently used to manage global grayscale and multi-language.
>
> 5. Repos and other requests demonstrate graphQL
>
> 6. Redux: Currently demonstrated for global login and user information.
>
> 7. Signals: Currently used for in-page state management in NotifyPage, RepositoryDetailFileListPage
>
> **There are multiple list displays, including:**
>
> 1. **gsy_pull_load_widget.dart.dart**
> `Used in common_list_page.dart, etc., paired with gsy_list_state.dart`
>
> 2. **gsy_pull_new_load_widget.dart.dart**
> `Used in dynamic_page.dart, etc., paired with gsy_bloc_list_state.dart`
> `Supports both iOS and Android pull-to-refresh styles`
>
> 3. **gsy_nested_pull_load_widget.dart**
> `Used in trend_page.dart, etc., configured with sliver effect`
## Compilation and Running Process
1. Set up the Flutter development environment (current Flutter SDK version **3.38**), see [Setting up the environment](https://flutterchina.club).
2. Clone the code, run `Packages get` to install third-party packages. (Due to certain reasons beyond control, you may need to set up a proxy in China: [Proxy environment variables](https://flutterchina.club/setup-windows/))
>### 3. Important: You need to create an `ignoreConfig.dart` file in the lib/common/config/ directory yourself, and then enter your registered Github client_id and client_secret.
class NetConfig {
static const CLIENT_ID = "xxxx";
static const CLIENT_SECRET = "xxxxxxxxxxx";
}
[ Register Github APP link](https://github.com/settings/applications/new), of course, the prerequisite is that you already have a github account (~ ̄▽ ̄)~.
### 4. If using secure login (authorization login), then in the above Github App registration, the Authorization callback URL field must be filled with `gsygithubapp://authed`
<div>
<img src="http://img.cdn.guoshuyu.cn/register0.png" width="426px"/>
<img src="http://img.cdn.guoshuyu.cn/register1.jpg" width="426px"/>
</div>
### 5. Please note before running
>### 1. Local Flutter SDK version 3.38; 2. Have you executed `flutter pub get`; 3. For network and other issues, refer to: [If login fails or requests fail](https://github.com/CarGuo/gsy_github_app_flutter/issues/643)
### Download
#### APK download link: [APK download link 1](https://github.com/CarGuo/gsy_github_app_flutter/releases)
#### APK download link: [APK download link 2](https://www.openapk.net/gsygithubappflutter/com.shuyu.gsygithub.gsygithubappflutter/)

| Type | QR Code |
| ----------- | ---------------------------------------- |
| **APK QR Code** |  |
| **iOS download not available** | |
## Project Structure Diagram

### Common Issues
* If package synchronization fails, it's usually because the package proxy is not set. You can refer to: [Environment variable issues](https://github.com/CarGuo/GSYGithubAppFlutter/issues/13)
* [If cloning is too slow, you can try downloading from the Gitee address](https://gitee.com/CarGuo/GSYGithubAppFlutter)
### Example Images


<img src="http://img.cdn.guoshuyu.cn/showapp1.jpg" width="426px"/>
<img src="http://img.cdn.guoshuyu.cn/showapp2.jpg" width="426px"/>
<img src="http://img.cdn.guoshuyu.cn/showapp3.jpg" width="426px"/>
### Framework
>Current Flutter SDK version 3.38
```
User Interaction → UI Layer(Widget/Page) → State Layer(Redux/Provider/Riverpod) → Service Layer(Repositories)
→ Network Layer(Net) → GitHub API → Data Model(Model) → Local Storage(DB) → UI Update
```
```
┌─────────────────────────────────────────────────────────────────┐
│ GSY GitHub App │
├─────────────┬───────────────┬────────────────┬─────────────────┤
│ UI Layer │ State Layer │ Service Layer │ Data Layer │
├─────────────┼───────────────┼────────────────┼─────────────────┤
│ │ │ │ │
│ ┌─────────┐│ ┌─────────┐ │ ┌─────────┐ │ ┌─────────┐ │
│ │ Pages ││ │ Redux │ │ │Repositories│ │ │ Models │ │
│ └─────────┘│ └─────────┘ │ └─────────┘ │ └─────────┘ │
│ │ │ │ │
│ ┌─────────┐│ ┌─────────┐ │ ┌─────────┐ │ ┌─────────┐ │
│ │ Widgets ││ │ Provider│ │ │Network API│ │ │Database │ │
│ └─────────┘│ └─────────┘ │ └─────────┘ │ └─────────┘ │
│ │ │ │ │
│ ┌─────────┐│ ┌─────────┐ │ │ │
│ │Common UI││ │Riverpod │ │ │ │
│ └─────────┘│ └─────────┘ │ │ │
│ │ │ │ │
│ │ ┌─────────┐ │ │ │
│ │ │ Signals │ │ │ │
│ │ └─────────┘ │ │ │
│ │ │ │ │
└─────────────┴───────────────┴────────────────┴─────────────────┘
```
```
lib/
├── main.dart # Application entry point
├── main_prod.dart # Production environment entry point
├── app.dart # Application configuration and routing
├── common/ # Common functionality modules
│ ├── config/ # Application configuration
│ ├── event/ # Event bus
│ ├── local/ # Localization
│ ├── localization/ # Multi-language support
│ ├── net/ # Network requests
│ ├── repositories/ # Data repositories
│ ├── router/ # Routing configuration
│ ├── style/ # Style configuration
│ └── utils/ # Utility classes
├── db/ # Database related
│ ├── provider/ # Database providers
│ ├── sql_manager.dart # SQL manager
│ └── sql_provider.dart # SQL provider
├── env/ # Environment configuration
├── model/ # Data models
├── page/ # Pages
│ ├── debug/ # Debug pages
│ ├── dynamic/ # Dynamic pages
│ ├── home/ # Home page
│ ├── issue/ # Issue related pages
│ ├── login/ # Login page
│ ├── push/ # Push related pages
│ ├── release/ # Release related pages
│ ├── repos/ # Repository related pages
│ ├── search/ # Search page
│ ├── trend/ # Trend page
│ └── user/ # User related pages
├── provider/ # Provider state management
├── redux/ # Redux state management
│ ├── middleware/ # Redux middleware
│ ├── gsy_state.dart # Redux state definition
│ ├── login_redux.dart # Login state management
│ └── user_redux.dart # User state management
├── test/ # Test related
└── widget/ # Custom widgets
├── anima/ # Animation widgets
├── markdown/ # Markdown rendering widgets
├── menu/ # Menu widgets
├── particle/ # Particle effect widgets
├── pull/ # Pull-to-refresh widgets
└── state/ # State related widgets
```
Riverpod page state management:
```
┌───────────────────────────────────────────────────────────────────────────┐
│ Page Architecture Overview │
└───────────────────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────────────────┐
│ Global State │
│ ┌───────────────────┐ ┌────────────────────┐ ┌────────────────────┐ │
│ │ appThemeProvider │ │ appLocalProvider │ │ appGrepProvider │ │
│ │ (Theme Data) │ │ (Localization) │ │ (Grayscale Mode) │ │
│ └───────────────────┘ └────────────────────┘ └────────────────────┘ │
└───────────────────────────────────────────────────────────────────────────┘
│
┌────────────────┴────────────────┐
▼ ▼
┌─────────────────────────────────┐ ┌─────────────────────────────────────┐
│ TrendPage (Riverpod) │ │ NotifyPage (Signals) │
├─────────────────────────────────┤ ├─────────────────────────────────────┤
│ │ │ │
│┌─────────────────────────────┐ │ │┌───────────────────────────────────┐│
││ Riverpod Providers │ │ ││ Signals State ││
││┌───────────────────────────┐│ │ ││┌─────────────────────────────────┐││
│││ trendFirstProvider ││ │ │││ notifySignal (List) │││
│││ trendSecondProvider ││ │ │││ notifyIndexSignal (int) │││
││└───────────────────────────┘│ │ │││ signalPage (int) │││
│└─────────────────────────────┘ │ ││└─────────────────────────────────┘││
│ │ │└───────────────────────────────────┘│
│┌─────────────────────────────┐ │ │┌───────────────────────────────────┐│
││ Local State (StatefulWidget)│ │ ││ SignalsMixin Processing ││
││ - UI Controls │ │ ││ - createEffect() for reactions ││
││ - Filter Parameters │ │ ││ - Manages data loading ││
│└─────────────────────────────┘ │ ││ - Updates UI based on signals ││
│ │ │└───────────────────────────────────┘│
└─────────────────────────────────┘ └─────────────────────────────────────┘
│ │
└────────────────┬────────────────┘
▼
┌───────────────────────────────────────────────────────────────────────────┐
│ Data Layer │
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ ReposRepository / UserRepository │ │
│ │ ┌────────────────────────┐ ┌─────────────────────────────────┐ │ │
│ │ │ Network Request │───┬──▶│ Database Providers │ │ │
│ │ │ - API calls │ │ │ - Data caching │ │ │
│ │ └────────────────────────┘ │ └─────────────────────────────────┘ │ │
│ │ │ │ │
│ │ │ ┌─────────────────────────────────┐ │ │
│ │ └──▶│ Data Models │ │ │
│ │ │ - Structure definitions │ │ │
│ │ └─────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────────────────┐
│ UI Components │
│ ┌────────────────────┐ ┌────────────────────┐ ┌────────────────────┐ │
│ │ View Models │ │ List Items │ │ Interactive UI │ │
│ │ - Data Formatting │ │ - Item Rendering │ │ - User Actions │ │
│ └────────────────────┘ └────────────────────┘ └────────────────────┘ │
└───────────────────────────────────────────────────────────────────────────┘
```
Provider page state management:
```
+-----------------------------------------------------+
| App User Interface |
+-----------------------------------------------------+
|
v
+-----------------------------------------------------+
| RepositoryDetailPage (StatefulWidget) |
| with SingleTickerProviderStateMixin |
+-----------------------------------------------------+
|
v
+-----------------------------------------------------+
| MultiProvider |
+-----------------------------------------------------+
| |
v v
+------------------+ +-----------------------+
| ReposNetWork |<----------| ReposDetailProvider |
| Provider | | |
+---------+--------+ +-----------------------+
| |
| |
v v
+-----------------------------------------------------+
| Repository Data Services |
| (ReposRepository, IssueRepository) |
+-----------------------------------------------------+
|
v
+-----------------------------------------------------+
| Four Tab Pages (Consumers) |
+-----------------------------------------------------+
| | | |
v v v v
+----------+ +----------+ +----------+ +----------+
| Info | | Readme | | Issues | | Files |
| Page | | Page | | Page | | Page |
+----------+ +----------+ +----------+ +----------+
| | | |
| | | |
v v v v
+-----------------------------------------------------+
| GlobalKeys for Tab Access |
| (infoListKey, readmeKey, issueListKey, fileListKey) |
+-----------------------------------------------------+
```




## Star History Chart
[](https://star-history.com/#CarGuo/gsy_github_app_flutter&Date)
### LICENSE
```
CarGuo/GSYGithubAppFlutter is licensed under the
Apache License 2.0
A permissive license whose main conditions require preservation of copyright and license notices.
Contributors provide an express grant of patent rights.
Licensed works, modifications, and larger works may be distributed under different terms and without source code.
```
================================================
FILE: RECORD.md
================================================
flutter build apk --target-platform android-arm64 -t lib/main_prod.dart --no-sound-null-safety
flutter packages pub run build_runner build --delete-conflicting-outputs
dart migrate --skip-import-check
flutter run --no-sound-null-safety
https://flutter.cn/docs/development/tools/devtools/cli http://localhost:9100
sudo gem install -n /usr/local/bin cocoapods -v 1.9.3
./gradlew :app:dependencies
AS 全局匹配中文搜索 ^((?!(\*|//)).)+[\u4e00-\u9fa5]
查看 framework 支持
1.进入到framework目录下
cd /Users/.../xFramework.framework
2.输入命令
lipo -info xFramework
-tag:gralloc4
# 如何查看dill文件
我们可以通过dart sdk中的vm package提供的dump_kernel.dart打印出dill的内部结构。
```
dart bin/dump_kernel.dart /Users/kylewong/Codes/AOP/aspectd/example/aop/build/app.dill /Users/kylewong/Codes/AOP/aspectd/example/aop/build/app.dill.txt
注意bin/dump_kernel.dart需要改成自己dart sdk中的具体路径。
```
///配置多渠道
flutter run --dart-define=CHANNEL=GSY --dart-define=LANGUAGE=Dart
const CHANNEL = String.fromEnvironment('CHANNEL');
const LANGUAGE = String.fromEnvironment('LANGUAGE');
query getUserDetail($name:String!){
user(login: $name) {
login,
avatarUrl,
company,
location,
bio,
email,
bioHTML,
websiteUrl,
viewerIsFollowing,
createdAt,
repositories(first: 100) {
totalCount,
nodes {
stargazers {
totalCount
}
}
}
followers {
totalCount
}
following {
totalCount
}
starredRepositories {
totalCount
}
isViewer,
#pinnedItems {
#
#}
organizations(first: 100) {
nodes {
login,
avatarUrl,
name
}
}
}
}
query GetStars($name: String!, $owner: String!, $after: String) {
repository(name: $name, owner: $owner) {
createdAt
stargazers(first: 100, after: $after) {
edges {
node {
id
login
name
avatarUrl
__typename
}
starredAt
__typename
}
pageInfo {
startCursor
endCursor
hasNextPage
__typename↵
}
totalCount
__typename
}
__typename
}
}
xxd /Users/xxxxxxx/workspace/flutter-wrok/flutter_app_test/.dart_tool/flutter_build/bf7ed8e7e7b3e64f28f0af8a89a29ca9/app.dill
dart dump_kernel.dart /Users/xxxxxxx/workspace/flutter-wrok/flutter_app_test/.dart_tool/flutter_build/bf7ed8e7e7b3e64f28f0af8a89a29ca9/app.dill /Users/xxxxxxx/workspace/flutter-wrok/flutter_app_test/.dart_tool/flutter_build/bf7ed8e7e7b3e64f28f0af8a89a29ca9/app.dill.txt
flutter pub deps 打印依赖
m1 mac pod install fail , gem install ffi -- --enable-libffi-alloc
iconv -f gbk -t utf8 1.txt > 1_utf.txt
AS 检索匹配中文
^((?!(\*|//)).)+[\u4e00-\u9fa5]
serve --ssl-key *.key --ssl-cert *.crt
获取崩溃日志
/// 清空
adb logcat -d *:W > crash.log
/// 输出
win 平台可以
adb logcat -d *:E | Select-String "com.shuyu.gsygithub.gsygithubappflutter" > crash.log
mac 可以
adb logcat -d *:E | grep "com.shuyu.gsygithub.gsygithubappflutter" > crash.log
获取更进准
flutter build web --no-web-resources-cdn
adb shell setprop log.tag.gralloc4 SILENT
"No uri found in code block"
clear your working set as it has become corrupt
================================================
FILE: UISCENE_PLUGIN_RISK.md
================================================
# UIScene Plugin Risk Checklist
- Project: `gsy_github_app_flutter`
- Generated on: 2026-02-13
- Scope: iOS plugins listed in `.flutter-plugins-dependencies`
- Method: static source scan for Scene lifecycle compatibility signals (`FlutterSceneLifeCycleDelegate`, `addSceneDelegate`, usage of `UIApplication.keyWindow` / `windows`, and AppDelegate lifecycle hooks).
## High Risk
### 1. `url_launcher_ios 6.3.6`
- Risk level: High
- Why:
- Uses deprecated window lookup via `UIApplication.shared.keyWindow`, which is scene-unaware.
- Evidence:
- `/Users/guoshuyu/.pub-cache/hosted/pub.dev/url_launcher_ios-6.3.6/ios/url_launcher_ios/Sources/url_launcher_ios/URLLauncherPlugin.swift:22`
- Impact:
- In multi-scene/iPad multi-window mode, in-app Safari presentation may target the wrong scene or fail to present.
### 2. `flutter_inappwebview_ios 1.1.2`
- Risk level: High
- Why:
- Multiple code paths still use `keyWindow` / `UIApplication.shared.windows`, which can be incorrect under multi-scene.
- Evidence:
- `/Users/guoshuyu/.pub-cache/hosted/pub.dev/flutter_inappwebview_ios-1.1.2/ios/Classes/HeadlessInAppWebView/HeadlessInAppWebView.swift:40`
- `/Users/guoshuyu/.pub-cache/hosted/pub.dev/flutter_inappwebview_ios-1.1.2/ios/Classes/UIApplication/VisibleViewController.swift:13`
- `/Users/guoshuyu/.pub-cache/hosted/pub.dev/flutter_inappwebview_ios-1.1.2/ios/Classes/WebAuthenticationSession/WebAuthenticationSession.swift:93`
- Impact:
- Headless WebView attach point, visible view-controller resolution, and web-auth presentation anchor may bind to the wrong window/scene.
## Medium Risk
### 1. `fluttertoast 8.2.10`
- Risk level: Medium
- Why:
- Chooses UI window via `UIApplication.sharedApplication.windows` and key-window iteration.
- Evidence:
- `/Users/guoshuyu/.pub-cache/hosted/pub.dev/fluttertoast-8.2.10/ios/Classes/FluttertoastPlugin.m:130`
- Impact:
- Toast may appear on a non-active scene window or behave inconsistently in multi-window mode.
## Low Risk
### 1. `share_plus 12.0.1`
- Risk level: Low
- Why:
- Uses `connectedScenes` and `UIWindowScene.windows` for root view-controller selection on iOS 13+.
- Evidence:
- `/Users/guoshuyu/.pub-cache/hosted/pub.dev/share_plus-12.0.1/ios/share_plus/Sources/share_plus/FPPSharePlusPlugin.m:12`
- Note:
- Keeps a fallback to `keyWindow` for iOS 12 and below (acceptable for non-scene OS versions).
### 2. Other installed iOS plugins in this repo
- `connectivity_plus 6.0.5`
- `device_info_plus 10.1.2`
- `package_info_plus 8.0.2`
- `path_provider_foundation 2.5.1`
- `permission_handler_apple 9.4.7`
- `rive_common 0.4.11`
- `shared_preferences_foundation 2.5.6`
- `sqflite 2.3.3+1`
- `webview_flutter_wkwebview 3.23.5`
Risk level: Low (for UIScene lifecycle migration)
- Why:
- No direct AppDelegate lifecycle hook usage (`addApplicationDelegate` / `openURL` callbacks / `continueUserActivity`) detected in plugin runtime source paths.
## Recommended Actions
1. Upgrade first:
- `url_launcher_ios`
- `flutter_inappwebview_ios`
- `fluttertoast`
2. Run targeted iPad multi-window validation:
- `url_launcher` in-app Safari presentation
- InAppWebView / headless webview attach
- Web auth session presentation anchor
- Toast display target window
- Share sheet presentation
3. If upgrade is blocked:
- Apply local patch to resolve active `UIWindowScene` and active window/VC instead of `keyWindow`/global `windows`.
================================================
FILE: VERSION.md
================================================
### 请直接看 github release
### 1.1.9
* 修正弹出键盘的时候被挤压问题
* 修复切换主题导致长按输入框弹出异常
* 修复其他小问题。
### 1.1.8
* 修复反馈输入框遮挡问题。
* 更新部分插件,更新了 sdk 到 1.1.9
### 1.1.7
* 更新flutter SDK 到 1.1.3 版本,修复TargetSDK 28以上在9.0键盘无法弹出问题。
### 1.1.6
* flutter升级正式版1.0
### 1.1.5
* Android 代码详情使用 AndroidView 实现WebView
* 升级flutter Sdk
* 升级第三方包
### 1.1.3
* 修复详情tab切换问题。
### 1.1.2
* 增加滑动返回。
* 修复主页抽屉小屏幕无法滚动。
* 增加部分代码高亮。
* 修复搜索排序按键问题。
* 更新flutter SDK
### 1.1.1
* 更新flutter SDK 0.5.8。
* 修复一些仓库下的readme问题。
### 1.1.0
* 切换用户切换数据库。
* 多语言。
### 1.0.9
* 切换主题支持
* 问题修复
### 1.0.8
* readme图片解析优化
* readme图片增加点击查看
* 组织账号不显示活跃记录Item
* 增加用户组织显示
### 1.0.7
* 增加图片预览
* 修复未读的通知打开提示其他异常
* 增加fork仓库跳转到原仓库
* 增加仓库点击展示 issue 状态信息
* 增加个人状态信息可跳转
* 增加仓库Topic显示
* 通知中心增加侧滑点击已读
### 1.0.6
* trend修改为redux
* 增加本地阅读历史
* drawer 状态栏样式处理
* 增加个人动态提交表。
### 1.0.5
* 增加本地数据库
* 修复分享问题。
* 修改用户页面样式
* 增加用户加入github时间显示
### 1.0.4
* 修复启动页变形问题。
* 调整个人页面字体动态大小。
* 增加趋势语言,搜索语言dart选项。
* 增加前后台切换刷新动态。
* 增加触摸隐藏键盘。
* 增加点击检测版本。
* 增加 issue 使用markdown解析
* 增加 issue 输入框的快速输入按键。
* 增加 issue 关闭操作信息。
* 返回文件列表的返回键处理逻辑。
* 修复详情中存在的model转化问题。
### 1.0.1 (已发布)
* 修复loading弹出框黄线问题。
* 调整部分ui。
* 增加Release列表。
* 增加版检测。
* Issue详情页显示问题。
* 返回按键退出问题。
### 1.0.0
* 第一版完成
================================================
FILE: analysis_options.yaml
================================================
include: package:flutter_lints/flutter.yaml
analyzer:
errors:
mixin_inherits_from_not_object: ignore
plugins:
- custom_lint
linter:
rules:
non_constant_identifier_names: false
file_names: false
constant_identifier_names: false
library_private_types_in_public_api: false
library_prefixes: false
================================================
FILE: android/.gitignore
================================================
*.iml
*.class
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
GeneratedPluginRegistrant.java
.cxx/
================================================
FILE: android/app/build.gradle
================================================
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
apply from: "exported.gradle"
android {
namespace "com.shuyu.gsygithub.gsygithubappflutter"
compileSdkVersion 36
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
lint {
disable += 'InvalidPackage'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.shuyu.gsygithub.gsygithubappflutter"
minSdkVersion flutter.minSdkVersion
targetSdkVersion 35
versionCode 69
versionName "7.9.3"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
signingConfigs {
debug {
storeFile file("../gsygithubapp-debug.jks")
storePassword "123456"
keyAlias "debug"
keyPassword "123456"
}
release {
storeFile file("../gsygithubapp-debug.jks")
storePassword "123456"
keyAlias "debug"
keyPassword "123456"
}
}
buildTypes {
debug {
signingConfig signingConfigs.debug
}
release {
signingConfig signingConfigs.release
}
}
lint {
abortOnError = false
}
dependenciesInfo {
// Disables dependency metadata when building APKs.
includeInApk = false
// Disables dependency metadata when building Android App Bundles.
includeInBundle = false
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '17'
}
configurations.all {
resolutionStrategy {
///为了 https://github.com/pichillilorenzo/flutter_inappwebview/issues/2150
///force 'androidx.webkit:webkit:1.8.0'
///为了 Failed to transform appcompat-resources-1.7.0.aar
///这玩意导致的 Failed to transform appcompat-resources-1.7.0.aar Cannot invoke "String.length()" because "<parameter1>" is null 居然要升级 AGP 8.6.1 才能适配,有毒
//force "androidx.appcompat:appcompat:1.6.1"
}
}
}
flutter {
source '../..'
}
dependencies {}
// 在你的模块级别 build.gradle 文件中添加此任务
// 例如: app/build.gradle
task findSoFileOrigins {
description = "扫描项目依赖的 AAR 文件,找出 .so 文件的来源。"
group = "reporting" // 将任务归类到 "reporting" 组下
doLast {
// 用于存储 AAR 标识符及其包含的 .so 文件路径
// 键 (Key): AAR 的字符串标识符 (例如:"project :gsyVideoPlayer", "com.example.library:core:1.0.0")
// 值 (Value): 一个 Set 集合,包含该 AAR 内所有 .so 文件的路径 (字符串)
def aarSoFilesMap = [:]
def variants = null
if (project.plugins.hasPlugin('com.android.application')) {
variants = project.android.applicationVariants
} else if (project.plugins.hasPlugin('com.android.library')) {
variants = project.android.libraryVariants
} else {
project.logger.warn("警告: findSoFileOrigins 任务需要 Android 应用插件 (com.android.application) 或库插件 (com.android.library)。")
return
}
if (variants == null || variants.isEmpty()) {
project.logger.warn("警告: 未找到任何变体 (variants) 来处理。")
return
}
variants.all { variant ->
project.logger.lifecycle("正在扫描变体 '${variant.name}' 中的 AAR 依赖以查找 .so 文件...")
// 获取该变体的运行时配置 (runtime configuration)
def configuration = variant.getRuntimeConfiguration()
try {
// 配置一个构件视图 (artifact view) 来精确请求 AAR 类型的构件
def resolvedArtifactsView = configuration.incoming.artifactView { view ->
view.attributes { attributes ->
// 明确指定我们只对 artifactType 为 'aar' 的构件感兴趣
// AGP 也常用 "android-aar",如果 "aar" 效果不佳,可以尝试替换
attributes.attribute(Attribute.of("artifactType", String.class), "aar")
}
// lenient(false) 是默认行为。如果设为 true,它会尝试跳过无法解析的构件而不是让整个视图失败。
// 但如果像之前那样,是组件级别的变体选择失败 (如 gsyVideoPlayer),lenient 可能也无法解决。
// view.lenient(false)
}.artifacts // 获取 ResolvedArtifactSet
project.logger.info("对于变体 '${variant.name}',从配置 '${configuration.name}' 解析到 ${resolvedArtifactsView.artifacts.size()} 个 AAR 类型的构件。")
resolvedArtifactsView.each { resolvedArtifactResult ->
// resolvedArtifactResult 是 ResolvedArtifactResult 类型的对象
File aarFile = resolvedArtifactResult.file
// 获取组件的标识符,这能告诉我们依赖的来源
// 例如:"project :gsyVideoPlayer" 或 "com.google.android.material:material:1.7.0"
String aarIdentifier = resolvedArtifactResult.id.componentIdentifier.displayName
aarSoFilesMap.putIfAbsent(aarIdentifier, new HashSet<String>())
if (aarFile.exists() && aarFile.name.endsWith('.aar')) {
// project.logger.info("正在检查 AAR: ${aarIdentifier} (文件: ${aarFile.name})")
try {
project.zipTree(aarFile).matching {
include '**/*.so' // 匹配 AAR 中的所有 .so 文件
}.each { File soFileInZip ->
aarSoFilesMap[aarIdentifier].add(soFileInZip.path)
}
} catch (Exception e) {
project.logger.error("错误: 无法检查 AAR 文件 '${aarIdentifier}' (路径: ${aarFile.absolutePath})。原因: ${e.message}")
}
} else {
if (!aarFile.name.endsWith('.aar')) {
project.logger.debug("跳过非 AAR 文件 '${aarFile.name}' (来自: ${aarIdentifier}),其构件类型被解析为 AAR。")
} else {
project.logger.warn("警告: 来自 '${aarIdentifier}' 的 AAR 文件不存在: ${aarFile.absolutePath}")
}
}
}
} catch (Exception e) {
// 这个 catch 块会捕获解析构件视图时发生的错误
// 这可能仍然包括之前遇到的 "Could not resolve all artifacts for configuration" 错误,
// 如果问题非常根本,即使是特定的构件视图也无法克服。
project.logger.error("错误: 无法为配置 '${configuration.name}' 解析 AAR 类型的构件。" +
"这通常表明您的项目设置中存在依赖变体匹配问题," +
"特别是对于像 ':gsyVideoPlayer' 这样的项目依赖。 " +
"详细信息: ${e.message}", e) // 打印异常堆栈以获取更多信息
project.logger.error("建议: 请检查项目依赖(尤其是本地子项目如 ':gsyVideoPlayer')的构建配置," +
"确保它们能正确地发布带有标准 Android 库属性(如组件类别、构建类型,以及适用的 Kotlin 平台类型等)的变体。")
// 如果希望任务在此处停止而不是尝试其他变体,可以取消下一行的注释
// throw e
}
}
// 打印结果
if (aarSoFilesMap.isEmpty()) {
project.logger.lifecycle("\n在所有已处理变体的可解析 AAR 依赖中均未找到 .so 文件,或者依赖解析失败。")
} else {
println "\n--- AAR 依赖中的 .so 文件来源 ---"
// 按 AAR 标识符排序以获得一致的输出
aarSoFilesMap.sort { it.key }.each { aarId, soFileList ->
if (!soFileList.isEmpty()) {
println "${aarId}:" // 例如:project :gsyVideoPlayer: 或 com.some.library:core:1.0:
soFileList.sort().each { soPath -> // 对 .so 文件路径排序
println " - ${soPath}" // 例如: - jni/armeabi-v7a/libexample.so
}
}
}
println "----------------------------------"
}
project.logger.lifecycle("任务执行完毕。要再次运行此任务,请执行: ./gradlew ${project.name}:${name}")
}
}
================================================
FILE: android/app/exported.gradle
================================================
/**
* 修改 Android 12 因为 exported 的构建问题,主要用于演示
*/
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
def processManifest = output.getProcessManifestProvider().get()
processManifest.doLast { task ->
def outputDir = task.multiApkManifestOutputDirectory
File outputDirectory
if (outputDir instanceof File) {
outputDirectory = outputDir
} else {
outputDirectory = outputDir.get().asFile
}
File manifestOutFile = file("$outputDirectory/AndroidManifest.xml")
println("----------- ${manifestOutFile} ----------- ")
if (manifestOutFile.exists() && manifestOutFile.canRead() && manifestOutFile.canWrite()) {
def manifestFile = manifestOutFile
///这里第二个参数是 false ,所以 namespace 是展开的,所以下面不能用 androidSpace,而是用 nameTag
def xml = new XmlParser(false, false).parse(manifestFile)
def exportedTag = "android:exported"
def nameTag = "android:name"
///指定 space
//def androidSpace = new groovy.xml.Namespace('http://schemas.android.com/apk/res/android', 'android')
def nodes = xml.application[0].'*'.findAll {
//挑选要修改的节点,没有指定的 exported 的才需要增加
//如果 exportedTag 拿不到可以尝试 it.attribute(androidSpace.exported)
(it.name() == 'activity' || it.name() == 'receiver' || it.name() == 'service') && it.attribute(exportedTag) == null
}
///添加 exported,默认 false
nodes.each {
def isMain = false
it.each {
if (it.name() == "intent-filter") {
it.each {
if (it.name() == "action") {
//如果 nameTag 拿不到可以尝试 it.attribute(androidSpace.name)
if (it.attributes().get(nameTag) == "android.intent.action.MAIN") {
isMain = true
println("......................MAIN FOUND......................")
}
}
}
}
}
it.attributes().put(exportedTag, "${isMain}")
}
PrintWriter pw = new PrintWriter(manifestFile)
pw.write(groovy.xml.XmlUtil.serialize(xml))
pw.close()
}
}
}
}
================================================
FILE: android/app/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.shuyu.gsygithub.gsygithubappflutter">
<!-- The INTERNET permission is required for development. Specifically,
flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<queries>
<!-- If your app checks for call support -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="tel" />
</intent>
<!-- If your app checks for call support -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https" />
</intent>
</queries>
<uses-permission android:name="android.permission.INTERNET"/>
<!-- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />-->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:label="GSYGithubAppFlutter"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
android:hardwareAccelerated="true"
android:exported="true"
android:windowSoftInputMode="adjustResize">
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background" />
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<meta-data
android:name="io.flutter.embedded_views_preview"
android:value="true" />
<!-- <meta-data-->
<!-- android:name="io.flutter.embedding.android.DisableMergedPlatformUIThread"-->
<!-- android:value="true" />-->
<!-- <meta-data-->
<!-- android:name="io.flutter.embedding.android.EnableImpeller"-->
<!-- android:value="false" />-->
</application>
</manifest>
================================================
FILE: android/app/src/main/kotlin/com/shuyu/gsygithub/gsygithubappflutter/MainActivity.kt
================================================
package com.shuyu.gsygithub.gsygithubappflutter
import UpdateAlbumPlugin
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine)
flutterEngine.plugins.add(UpdateAlbumPlugin())
}
}
================================================
FILE: android/app/src/main/kotlin/com/shuyu/gsygithub/gsygithubappflutter/UpdateAlbumPlugin.kt
================================================
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.provider.MediaStore
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
class UpdateAlbumPlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
/** Channel名称 **/
private var channel: MethodChannel? = null
private var context: Context? = null
companion object {
private val sChannelName = "com.shuyu.gsygithub.gsygithubflutter/UpdateAlbumPlugin"
}
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
channel = MethodChannel(
binding.binaryMessenger, sChannelName)
context = binding.applicationContext
channel!!.setMethodCallHandler(this)
}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
channel?.setMethodCallHandler(null)
channel = null
}
override fun onMethodCall(methodCall: MethodCall, result: MethodChannel.Result) {
when (methodCall.method) {
"updateAlbum" -> {
val path: String? = methodCall.argument("path")
val name: String? = methodCall.argument("name")
try {
MediaStore.Images.Media.insertImage(context?.contentResolver, path, name, null)
} catch (e: Exception) {
e.printStackTrace()
}
// 最后通知图库更新
context?.sendBroadcast(Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://$path")))
}
}
result.success(null)
}
}
================================================
FILE: android/app/src/main/res/drawable/launch_background.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item>
</layer-list>
================================================
FILE: android/app/src/main/res/drawable/normal_background.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
</layer-list>
================================================
FILE: android/app/src/main/res/values/styles.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowEnableSplitTouch">false</item>
<item name="android:splitMotionEvents">false</item>
</style>
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">@drawable/normal_background</item>
</style>
</resources>
================================================
FILE: android/build.gradle
================================================
allprojects {
repositories {
google()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}
================================================
FILE: android/gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
================================================
FILE: android/gradle.properties
================================================
org.gradle.jvmargs=-Xmx4096M -Dfile.encoding=UTF-8
android.useAndroidX=true
#systemProp.http.proxyHost=127.0.0.1
#systemProp.http.proxyPort=7890
#systemProp.https.proxyHost=127.0.0.1
#systemProp.https.proxyPort=7890
================================================
FILE: android/gradlew
================================================
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
================================================
FILE: android/gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: android/settings.gradle
================================================
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.9.1" apply false
id "org.jetbrains.kotlin.android" version "2.1.0" apply false
}
include ":app"
================================================
FILE: devtools_options.yaml
================================================
description: This file stores settings for Dart & Flutter DevTools.
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
extensions:
================================================
FILE: docs/00-overview/project-map.md
================================================
# 项目地图
## 项目定位
`gsy_github_app_flutter` 是一个跨平台 GitHub 客户端。
它既是完整功能应用,也是偏教学展示风格的工程,因此仓库中会刻意保留多种实现方式,而不是追求所有模块都完全统一。
## 运行主链路
高层数据链路可以概括为:
`UI/Page -> 状态层 -> Repository -> 网络/数据库 -> Model -> UI 刷新`
应用入口和全局装配主要集中在:
- `lib/main.dart`
- `lib/app.dart`
这些位置负责:
- 应用启动
- 环境配置装配
- 根导航
- 多语言和主题
- 全局错误处理
- 全局状态容器接线
## 目录地图
- `lib/main.dart`:应用启动、Zone 异常兜底、环境包装
- `lib/app.dart`:`MaterialApp`、路由、Redux 根 store、Riverpod 容器、HTTP 错误监听
- `lib/common/config/`:应用配置和 OAuth 本地配置
- `lib/common/net/`:API 客户端、拦截器、GraphQL、数据转换
- `lib/common/repositories/`:功能层数据访问边界
- `lib/common/localization/`:本地化扩展、ARB、生成代码
- `lib/db/`:本地数据库 provider 和 SQL 辅助
- `lib/env/`:环境配置及其生成文件
- `lib/model/`:数据模型和序列化生成文件
- `lib/page/`:页面功能目录,如 `repos`、`issue`、`trend`、`notify`、`user`
- `lib/provider/`:Provider/Riverpod 相关共享状态
- `lib/redux/`:Redux state、reducer、middleware
- `static/`:静态资源
- `.github/workflows/`:GitHub Actions 配置
## 对协作者很重要的现实
- 项目里同时存在多种状态管理方案
- 同时使用 REST 和 GraphQL
- 生成代码是日常开发流程的一部分
- 根 README 主要承担项目介绍和运行说明,不足以替代工程地图
## AI 最容易犯错的地方
- 误以为整个项目已经统一到某一种状态管理
- 为了解决页面局部问题去改 `lib/app.dart`
- 直接手改生成文件而不是回到源输入
- 忘记 `ignoreConfig.dart` 的本地依赖
在修改共享链路前,先看架构文档和对应模块文档。
================================================
FILE: docs/01-architecture/app-layering.md
================================================
# 应用分层
## 目的
这个仓库不是严格单一架构实现,而是采用“整体分层明确、局部实现多样”的方式。
协作者不需要强行统一写法,但需要尊重已有边界,避免把局部需求扩散成全局耦合。
## 1. 入口与应用壳层
- `lib/main.dart`
- `lib/app.dart`
- `lib/env/`
职责:
- 应用启动
- 环境配置装配
- 根导航与多语言/主题
- 全局异常处理
- 全局状态容器接线
原则:
- 不要把功能业务逻辑直接塞进这里
- 除非是全局行为问题,否则尽量不要改 `lib/app.dart`
## 2. UI 层
- `lib/page/`
- 各功能目录下的局部 widget
- `lib/common/` 下复用 UI 组件
职责:
- 页面渲染
- 用户交互响应
- 将数据请求和状态变化委托给状态层或 repository
原则:
- 优先在功能目录内完成 UI 改动
- 页面不要直接承接太多网络协议细节
## 3. 状态层
- `lib/redux/`
- `lib/provider/`
- `lib/app.dart` 中接入的 Riverpod 容器
- 指定页面中的 Signals
职责:
- 维护视图状态
- 协调异步加载
- 向 UI 暴露状态变化
原则:
- 新改动优先沿用目标模块当前已有状态方案
- 不要在无关任务里做状态管理迁移
## 4. Repository 层
- `lib/common/repositories/`
职责:
- 将功能请求翻译成网络或数据库访问
- 隔离页面/状态层与具体传输实现
原则:
- 改接口时优先在 repository 边界收口
- 页面不要绕过 repository 直接铺开网络细节
## 5. 数据与传输层
- `lib/common/net/`
- `lib/db/`
- `lib/model/`
职责:
- HTTP/GraphQL 访问
- 拦截器与响应转换
- 本地持久化
- 序列化与模型转换
原则:
- 不要从页面直接复制网络调用逻辑
- 共用行为优先收敛到共享网络层或 repository
## 生成代码约束
以下内容应视为生成产物:
- `lib/model/` 下的 `*.g.dart`
- `lib/env/` 下生成文件
- `lib/common/localization/l10n/` 下生成输出
- `riverpod_annotation` 对应的 `*.g.dart`
原则:
- 优先修改源输入,再重新生成
- 非必要不要直接手改生成文件
## 改动入口建议
- 页面展示问题:先看 `lib/page/<feature>/`
- API/模型问题:看 `common/net`、`common/repositories`、`model`
- 全局主题/语言/导航问题:看 `lib/app.dart` 和共享 provider/redux
- 构建或配置问题:看 `lib/env/`、`pubspec.yaml` 和 runbook
================================================
FILE: docs/01-architecture/state-management-matrix.md
================================================
# 状态管理矩阵
## 为什么要有这份文档
这个项目刻意保留了多种状态管理方式用于展示和演进。
这对学习有价值,但也意味着协作者和 agent 很容易“按自己的偏好”误改边界。
这份文档的目的是停止猜测。
## 当前分布
### Redux
- 主要承担应用级共享状态,例如登录态和用户信息
- 根 store 在 `lib/app.dart` 中创建
- reducer 和 middleware 位于 `lib/redux/`
### Riverpod
- 用于部分全局共享状态,例如灰度模式、语言、主题
- 也用于部分功能模块,例如趋势页相关数据流
- 根容器同样在 `lib/app.dart` 中接入
### Provider
- 仍存在于部分功能模块,尤其是较早的页面链路
- 典型例子是仓库详情页的跨 tab 状态共享
### Signals
- 用于局部页面状态
- 当前通知页和部分文件列表相关页面会使用
## 工作策略
- 不要再引入第五种状态管理模式
- 无关任务里不要顺手把模块从一种方案迁到另一种方案
- 新状态优先跟随“最近的既有模式”,而不是个人习惯
- 如果一个需求同时涉及全局状态和页面局部状态,要明确边界,避免双份真相
## 评审时必问的问题
1. 这份状态是页面局部、功能局部,还是应用全局?
2. 目标模块原来已经在用哪种状态方案?
3. 这次改动是否真的需要碰 `lib/app.dart`?
4. 会不会让 Redux、Riverpod、Provider 或 Signals 之间出现重复状态源?
## 后续方向
如果将来要收敛状态管理种类,应先在 `docs/06-decisions/` 记录决策,再开始迁移。
不要让“慢慢改着改着就变了”成为默认路径。
================================================
FILE: docs/02-features/debug.md
================================================
# 调试页功能
## 相关文件
- `lib/page/debug/debug_data_page.dart`
- `lib/page/debug/debug_label.dart`
- `lib/common/net/interceptors/log_interceptor.dart`
- `lib/common/logger.dart`
## 当前实现
调试页用于查看开发过程中的:
- HTTP Response
- HTTP Request
- HTTP Error
- Talker 错误日志
并支持复制链接、复制数据、弹出 JSON 查看器。
## 数据流
调试页本身不发起业务请求,而是消费全局日志和拦截器收集到的数据。
## 状态管理
- 页面本地 tab 状态
- 数据由全局日志容器和拦截器静态列表提供
## 高风险点
- 这是辅助调试能力,不应影响线上业务路径
- 改日志结构时要同步看调试页展示
- 大量数据展示和复制逻辑集中在单页内部
## 修改建议
- 仅在需要增强调试体验时修改
- 不要把正式业务依赖绑到调试页上
- 改日志采集字段时,顺带检查调试页是否还能正确显示
================================================
FILE: docs/02-features/dynamic.md
================================================
# 动态页功能
## 相关文件
- `lib/page/dynamic/dynamic_page.dart`
- `lib/page/dynamic/dynamic_bloc.dart`
- `lib/common/repositories/repos_repository.dart`
- `lib/common/utils/event_utils.dart`
## 当前实现
动态页是首页第一个 tab,展示当前用户相关动态流。
页面支持:
- 首次加载
- 下拉刷新
- 上拉加载更多
- 生命周期恢复时自动刷新
- 事件点击跳转
## 数据流
1. 首次进入时先读数据库或本地缓存链路
2. 再触发刷新
3. 页面恢复到前台时,如果已有数据则再次触发刷新
4. 列表项点击后通过 `EventUtils` 分发跳转
## 状态管理
- 主要通过 `DynamicBloc` 管理列表数据
- 页面本地管理滚动、刷新和忽略点击状态
- 用户名来源于 Redux store
## 高风险点
- 首次加载、手动刷新、生命周期恢复刷新是三条不同入口
- `_ignoring` 会影响页面交互时机
- 数据来源和跳转逻辑分布在 bloc、repository、event utils
## 修改建议
- 列表行为问题优先看 `dynamic_page.dart`
- 数据加载与分页问题看 `dynamic_bloc.dart`
- 事件跳转问题看 `EventUtils`
================================================
FILE: docs/02-features/home.md
================================================
# 首页容器功能
## 相关文件
- `lib/page/home/home_page.dart`
- `lib/page/home/widget/home_drawer.dart`
- `lib/page/dynamic/dynamic_page.dart`
- `lib/page/trend/trend_page.dart`
- `lib/page/my_page.dart`
## 当前实现
首页不是单一业务页,而是应用主容器,负责:
- 三个主 tab 切换
- 搜索入口
- drawer 入口
- 双击 tab 回到顶部
- Android 返回键回桌面
## 数据流
首页主要负责导航和容器调度,本身不直接承接业务数据。
业务数据由各 tab 页面自己拉取。
## 状态管理
- 主要是页面容器本地状态
- 通过 `GlobalKey` 驱动各 tab 的 `scrollToTop`
## 高风险点
- 改 tab 结构会影响动态页、趋势页、我的页面联动
- 搜索入口依赖右上角控件位置计算
- 返回键行为是首页特有容器逻辑
## 修改建议
- 首页问题优先限制在容器和导航层
- 不要把某个 tab 的业务逻辑加回首页
- 改搜索入口时要验证动画起点和跳转
================================================
FILE: docs/02-features/issue.md
================================================
# Issue 功能
## 相关文件
- `lib/page/issue/issue_detail_page.dart`
- `lib/page/issue/issue_edit_dIalog.dart`
- `lib/common/repositories/issue_repository.dart`
## 当前实现
Issue 详情页同时承担:
- issue 头部信息展示
- 评论列表展示
- 回复 issue
- 编辑 issue
- 编辑/删除评论
- open/close issue
## 数据流
1. 页面刷新时先拉 issue 头部信息
2. 再拉评论列表
3. 头部和评论列表分别更新
4. 编辑、回复、删除后通过刷新重新拉取数据
## 状态管理
- 主要使用页面本地 state
- 列表部分依赖 `GSYListState`
- 数据入口集中在 `IssueRepository`
## 高风险点
- 头部信息和评论列表是两条并行数据链路
- 编辑、删除、回复之后依赖刷新回流,不是本地直接 patch
- issue 状态切换会影响头部按钮和展示状态
## 修改建议
- 评论展示问题优先改 `issue_detail_page.dart` 和 widget
- 数据或协议问题再看 `IssueRepository`
- 改编辑能力时要同时验证 reply/edit/delete/open-close 几条链路
================================================
FILE: docs/02-features/login.md
================================================
# 登录功能
## 相关文件
- `lib/page/login/login_page.dart`
- `lib/page/login/login_webview.dart`
- `lib/redux/login_redux.dart`
- `lib/common/repositories/user_repository.dart`
- `lib/common/net/address.dart`
## 当前实现
登录页同时保留了账号密码入口和 OAuth 入口,但当前用户名密码登录已被直接禁用,页面会提示 `login_deprecated`。
实际可用主链路是 OAuth 登录。
## 数据流
OAuth 登录链路:
1. `LoginPage` 点击 OAuth 按钮
2. 通过 `Address.getOAuthUrl()` 生成授权地址
3. 跳转到 `login_webview.dart`
4. 登录成功后拿到 `code`
5. 分发 Redux `OAuthAction`
6. `oauthEpic` 调用 `UserRepository.oauth`
7. 登录成功后分发 `LoginSuccessAction`
8. reducer 内跳转首页
## 状态管理
- 页面输入和交互:页面本地 state
- 登录结果与全局用户态:Redux
## 高风险点
- 不要把 OAuth 成功后的全局登录逻辑搬回页面层
- `use_build_context_synchronously` 已在现有代码中被局部忽略,修改时要注意异步后导航安全
- `ignoreConfig.dart` 缺失会直接影响 OAuth 流程
## 修改建议
- 登录页 UI 小改动:尽量只动 `lib/page/login/`
- 登录协议改动:同步检查 `login_redux.dart`、`user_repository.dart`、OAuth 地址构造
- 不要在无关任务中恢复账号密码登录链路,除非需求明确要求
================================================
FILE: docs/02-features/notify.md
================================================
# 通知功能
## 相关文件
- `lib/page/notify/notify_page.dart`
- `lib/common/repositories/user_repository.dart`
- `lib/model/notification.dart`
## 当前实现
通知页负责展示 GitHub 通知消息,并支持:
- 未读 / 参与 / 全部 三种筛选
- 下拉刷新
- 上拉加载更多
- 将单条通知标记为已读
- 全部标记为已读
## 数据流
1. 页面通过 Signals 创建通知列表、筛选索引、页码信号
2. `createEffect` 监听筛选索引和页码变化
3. 变化后触发 `loadData()`
4. `loadData()` 调用 `UserRepository.getNotifyRequest`
5. 根据返回结果刷新列表或追加列表
6. 点开 Issue 类型通知后跳转详情,并在返回时强制刷新
## 状态管理
- 该页面主要使用 Signals
- `notifySignal` 保存列表
- `notifyIndexSignal` 保存筛选状态
- `signalPage` 保存页码
## 高风险点
- `signalPage = -1` 被用作强制刷新前的中间态,改页码逻辑时不能忽略这个约定
- 列表加载、筛选切换、已读操作都依赖信号联动,改动时要验证多种入口
- 目前只对 `Issue` 类型通知做了明确跳转处理
## 修改建议
- 页面交互改动优先保持 Signals 结构稳定
- 如果扩展更多通知类型跳转,集中收口在 `_renderEventItem`
- 改分页或刷新逻辑时,必须手工验证切 tab、已读、回退刷新三条链路
================================================
FILE: docs/02-features/push.md
================================================
# Push 提交详情功能
## 相关文件
- `lib/page/push/push_detail_page.dart`
- `lib/page/push/widget/push_header.dart`
- `lib/page/push/widget/push_coed_item.dart`
- `lib/common/repositories/repos_repository.dart`
## 当前实现
Push 提交详情页负责展示一次 commit 的:
- 头部信息
- 文件变更列表
- patch 预览
- 跳回仓库详情入口
## 数据流
1. 页面刷新时请求 commit 详情
2. 拿到头部信息和文件列表
3. 点击文件项后把 patch 转成 HTML 并跳到代码详情页
## 状态管理
- 主要是页面本地 state
- 列表依赖 `GSYListState`
- 数据入口在 `ReposRepository`
## 高风险点
- 头部和文件列表来自同一 commit 详情结果
- patch 需要转换成 HTML 后再展示
- 有的入口需要显示返回仓库首页按钮
## 修改建议
- UI 展示问题优先改 `push_detail_page.dart` 和 widget
- patch 展示问题同时看 `HtmlUtils`
- commit 数据问题再看 `ReposRepository`
================================================
FILE: docs/02-features/release.md
================================================
# Release 功能
## 相关文件
- `lib/page/release/release_page.dart`
- `lib/page/release/widget/release_item.dart`
- `lib/common/repositories/repos_repository.dart`
## 当前实现
Release 页面支持查看:
- Release 列表
- Tag 列表
- 内嵌查看 release HTML 内容
- 外部打开 release 或 tag 页面
## 数据流
1. 页面根据 tab 选择 release 或 tag
2. 调 `ReposRepository.getRepositoryReleaseRequest`
3. 列表项长按可打开外部链接
4. release 项点击可在应用内查看 HTML 内容
## 状态管理
- 页面本地 state 保存当前 tab
- 列表能力基于 `GSYListState`
## 高风险点
- release 和 tag 共用一个页面,但数据语义不同
- HTML 内容和外部链接两种打开方式都要兼容
- tab 切换时会清空并重刷列表
## 修改建议
- 展示问题优先改 `release_page.dart` 和 item widget
- 数据问题再看 `ReposRepository`
- 改 tab 逻辑时要同时验证 release 和 tag 两条链路
================================================
FILE: docs/02-features/repos.md
================================================
# 仓库详情功能
## 相关文件
- `lib/page/repos/repository_detail_page.dart`
- `lib/page/repos/provider/repos_detail_provider.dart`
- `lib/page/repos/provider/repos_network_provider.dart`
- `lib/common/repositories/repos_repository.dart`
- `lib/common/repositories/issue_repository.dart`
## 当前实现
仓库详情页是一个典型的“功能复杂且跨 tab 共享状态”的模块。
页面包含:
- 信息页
- Readme 页
- Issue 列表页
- 文件列表页
它通过 `MultiProvider` 在 tab 间共享 `ReposDetailProvider` 和 `ReposNetWorkProvider`。
## 数据流
初始化主链路:
1. `RepositoryDetailPage` 创建 `ReposDetailProvider`
2. `initState` 中先拉取分支列表
3. tab 子页面通过共享 provider 请求详情、readme、issue、文件等数据
4. provider 继续委托给 `ReposRepository` 或 `IssueRepository`
分支切换链路:
1. 顶部更多菜单选择 branch
2. 更新 `currentBranch`
3. 主信息、文件列表、readme 分别触发刷新
## 状态管理
- 当前模块主要使用 Provider
- `ReposDetailProvider` 负责共享仓库详情、分支、底部按钮、当前 tab、readme 内容等状态
- `ReposNetWorkProvider` 只是对 repository 调用做一层包装,主要用于演示 provider 依赖 provider
## 高风险点
- 这是跨 tab 共享状态模块,不要把共享状态拆回单页局部变量
- `currentBranch` 会影响多个子页面数据源,改分支逻辑时要检查联动刷新
- 底部按钮依赖仓库详情状态,不要只改显示不改数据更新链路
- 该模块同时触及 repo、issue、readme、file,多点回归风险高
## 修改建议
- UI 结构改动:先停留在 `lib/page/repos/`
- 数据字段改动:同步检查 `ReposDetailProvider` 和 repository 返回模型
- 如果只是改某个 tab,不要顺手重做整个 provider 结构
================================================
FILE: docs/02-features/search.md
================================================
# 搜索功能
## 相关文件
- `lib/page/search/search_page.dart`
- `lib/page/search/search_bloc.dart`
- `lib/page/search/widget/gsy_search_drawer.dart`
- `lib/common/repositories/repos_repository.dart`
## 当前实现
搜索页支持:
- 搜仓库
- 搜用户
- 排序和过滤
- 搜索动画展开/收起
## 数据流
1. 页面输入搜索词
2. 选择仓库或用户 tab
3. drawer 选择排序、类型、语言
4. `SearchBLoC.getDataLogic` 调 `ReposRepository.searchRepositoryRequest`
5. 列表根据当前 tab 渲染仓库项或用户项
## 状态管理
- 页面主要使用本地 state
- 查询条件保存在 `SearchBLoC`
- 列表能力依赖 `GSYListState`
## 高风险点
- 搜索条件切换会触发清空列表并重新刷新
- 仓库和用户复用同一请求入口,但渲染不同
- 搜索页有自定义圆形展开/收起动画
## 修改建议
- 纯交互或动画问题优先改 `search_page.dart`
- 查询参数问题优先改 `search_bloc.dart`
- 接口或返回结构问题再看 `ReposRepository`
================================================
FILE: docs/02-features/trend.md
================================================
# 趋势功能
## 相关文件
- `lib/page/trend/trend_page.dart`
- `lib/page/trend/trend_provider.dart`
- `lib/page/trend/trend_user_page.dart`
- `lib/common/repositories/repos_repository.dart`
## 当前实现
趋势页展示热门仓库列表,并支持按时间范围和语言筛选。
它现在主要基于 Riverpod provider 获取数据,但页面内部仍保留了一些本地状态和历史兼容写法。
## 数据流
1. 页面首次进入时设置默认筛选条件
2. 触发 `trendFirstProvider`
3. `trendFirstProvider` 先请求第一阶段结果
4. `trendSecondProvider` 再等待第一阶段结果,并在需要时继续追第二阶段数据
5. 页面优先读第二阶段结果,否则回退到第一阶段结果
这里的设计重点不是“两个列表源”,而是展示先后阶段的数据请求处理方式。
## 状态管理
- 列表数据请求:Riverpod
- 筛选条件、滚动、刷新控制:页面本地 state
- 还有 `trendLoadingState`、`trendRequestedState` 这样的模块级变量
## 高风险点
- `trendLoadingState` 和 `trendRequestedState` 是模块级共享变量,改并发或刷新逻辑时要格外小心
- 首次加载和筛选切换都依赖 `didChangeDependencies`
- 页面同时用到了局部 state、Riverpod 和刷新控件,不要只改其中一段就认为链路完整
## 修改建议
- 小功能改动先只改 `trend_page.dart`
- 数据请求或缓存逻辑改动再看 `trend_provider.dart` 和 `ReposRepository`
- 如果要重构趋势页状态,先单独立决策,不要夹在普通需求里做
================================================
FILE: docs/02-features/user.md
================================================
# 用户页功能
## 相关文件
- `lib/page/user/person_page.dart`
- `lib/page/user/base_person_provider.dart`
- `lib/page/user/base_person_state.dart`
- `lib/common/repositories/user_repository.dart`
- `lib/common/repositories/event_repository.dart`
## 当前实现
用户页负责展示用户或组织的详情页,并根据用户类型展示不同内容:
- 用户信息头部
- 关注/取消关注
- 用户动态
- 组织成员
- 组织信息与荣誉数据
## 数据流
1. 刷新时先拉用户信息
2. 再根据用户类型拉用户动态或组织成员
3. 并行获取关注状态和 honor 数据
4. 头部与列表一起渲染到嵌套下拉页面
## 状态管理
- 页面主体基于 `BasePersonState`
- honor 相关使用 provider
- 页面本地 state 保存关注状态、用户信息等
## 高风险点
- 用户和组织走的列表数据源不同
- 关注状态、用户信息、动态列表是多条链路
- `BasePersonState` 和 provider 共同参与页面行为
## 修改建议
- 用户页展示问题优先改 `person_page.dart` 与 widget
- honor 或头部共享逻辑再看 `base_person_provider.dart`
- 数据源问题分别看 `UserRepository` 与 `EventRepository`
================================================
FILE: docs/03-runbooks/local-setup.md
================================================
# 本地开发环境
## 基线要求
- Flutter SDK:以仓库 README 和当前 workflow 为准
- Java:Android 构建需要
- Android 工具链:生成 APK 需要
## 首次启动
1. 安装 Flutter,并确认 `flutter doctor`
2. 运行 `flutter pub get`
3. 创建 `lib/common/config/ignoreConfig.dart`
4. 填入 GitHub OAuth 所需的 `CLIENT_ID` 和 `CLIENT_SECRET`
示例:
```dart
class NetConfig {
static const CLIENT_ID = "xxxx";
static const CLIENT_SECRET = "xxxx";
}
```
## 常用命令
```bash
flutter pub get
flutter analyze
dart run build_runner build --delete-conflicting-outputs
flutter build apk --release --target-platform=android-arm64 --no-shrink
```
## 什么时候需要重新生成
- 改模型、序列化、Riverpod 注解或 env 源文件时,跑 `build_runner`
- 改 ARB 多语言文件时,重新生成本地化输出
## 常见失败原因
- 缺少 `ignoreConfig.dart`
- Flutter 版本不匹配
- 拉包时网络或代理异常
- 手改生成文件但没同步源文件
## 当前本地验证策略
仓库目前没有提交进来的自动化测试目录,因此本地验证以静态检查、构建和手工冒烟为主:
- 跑 `flutter analyze`
- 对构建相关改动跑 APK 构建
- 在模拟器或真机上手工验证改动功能
================================================
FILE: docs/04-quality/smoke-matrix.md
================================================
# 手工回归矩阵
## 目的
仓库当前缺少自动化测试基线,因此需要一份最小可执行的手工回归矩阵。
它的目标不是覆盖全部功能,而是覆盖最容易因局部改动而回归的主链路。
## 使用方式
- 改动前:确认本次变更影响哪些功能域
- 改动后:至少执行对应功能域的基础用例
- 改共享层时:除目标功能外,额外抽查一个高频功能
## 全局基础项
每次涉及共享层或根装配时,至少验证:
1. 应用能正常启动
2. 首页或欢迎页能进入
3. 路由跳转正常
4. 多语言和主题没有明显异常
## 登录
适用改动:
- `lib/page/login/`
- `lib/redux/login_redux.dart`
- `user_repository`
- OAuth 配置或导航相关改动
基础用例:
1. 进入登录页
2. 点击 OAuth 登录按钮
3. 能正常打开登录 WebView
4. 登录完成后能回到应用并进入首页
5. 退出登录后能回到登录页
重点观察:
- WebView 跳转是否正常
- OAuth 回调后是否正确更新全局登录态
## 仓库详情
适用改动:
- `lib/page/repos/`
- `repos_repository`
- `issue_repository`
- 相关模型、网络层改动
基础用例:
1. 从列表页进入仓库详情
2. 信息页正常展示
3. Readme 页能加载
4. Issue 页能切换并加载
5. 文件列表页能切换并加载
6. 切换分支后,信息页、Readme、文件列表表现正常
重点观察:
- 跨 tab 状态是否同步
- 分支切换是否触发联动刷新
## 趋势页
适用改动:
- `lib/page/trend/`
- `ReposRepository.getTrendRequest`
- 趋势筛选、滚动、刷新相关改动
基础用例:
1. 进入趋势页
2. 首次加载能显示列表或空态
3. 切换时间筛选
4. 切换语言筛选
5. 下拉刷新
6. 点击列表项进入仓库详情并返回
重点观察:
- 首次加载与刷新是否重复触发
- 筛选切换后列表是否正确刷新
## 通知页
适用改动:
- `lib/page/notify/`
- `user_repository` 通知相关接口
- Signals 或分页刷新逻辑相关改动
基础用例:
1. 进入通知页
2. 默认列表正常加载
3. 在 未读 / 参与 / 全部 之间切换
4. 下拉刷新
5. 上拉加载更多
6. 将单条未读标记为已读
7. 执行“全部标记为已读”
8. 点击 Issue 类型通知跳转详情并返回
重点观察:
- 切 tab 时列表是否正确刷新
- 标记已读后列表是否正确更新
- 返回后是否触发强制刷新
## 共享网络层
适用改动:
- `lib/common/net/`
- `lib/common/repositories/`
- 认证、拦截器、公共响应解析
基础用例:
1. 验证登录链路
2. 验证趋势页加载
3. 验证仓库详情加载
4. 验证通知页加载
重点观察:
- 是否出现全局 toast 异常
- 是否出现统一鉴权失效
- REST 与 GraphQL 路径是否都正常
## 共享状态或根装配
适用改动:
- `lib/app.dart`
- `lib/provider/`
- `lib/redux/`
基础用例:
1. 应用启动正常
2. 首页进入正常
3. 登录态切换正常
4. 主题或语言切换正常
5. 趋势页、通知页、仓库详情页各抽查一个
## 执行原则
- 不要求每次全量回归
- 但改共享链路时,不能只测当前页面
- 如果某次改动跨越多个功能域,应把对应模块基础用例全部跑一遍
================================================
FILE: docs/04-quality/test-strategy.md
================================================
# 测试策略
## 当前现状
- 仓库目前没有提交进来的 `test/` 目录
- [pubspec.yaml](/D:/workspace/project/gsy_github_app_flutter/pubspec.yaml) 中 `flutter_test` 仍是注释状态
- 质量保障目前主要依赖手工验证和 CI 构建成功
这意味着当前工程对 AI 改动并不友好,因为“改完是否正确”缺少快速反馈。
## 近期目标
不要等完整测试体系一次性到位。
先建立一个最小可用的工程验证 harness,让 agent 和人都能知道改动是否越界。
## 近期最小基线
1. 静态检查
- `flutter analyze`
2. 生成代码一致性
- 输入变化后重新生成相关文件
3. 高价值手工冒烟
- 应用启动
- 登录入口
- 仓库详情
- 趋势页
- 通知页
4. Android 构建验证
- 对构建相关改动执行 release APK 构建
当前手工回归入口见:
- `docs/04-quality/smoke-matrix.md`
## 第一批值得补的测试
- 高频模型的序列化测试
- 应用壳层和高频页面的 widget smoke test
- repository 层的解析与适配测试
## 典型改动的完成标准
### UI 小改动
- 页面可正常渲染
- 交互没有破坏导航和状态恢复
### API 或模型改动
- 请求入口正确
- 模型解析仍正常
- 受影响页面能拿到正确数据
### 应用壳层或共享状态改动
- 应用能启动
- 主题、语言、登录态相关行为仍正确
- 根导航无明显回归
## 原则
可靠的小测试集,比覆盖面大但没人维护的测试集更有价值。
测试策略的目标不是形式完整,而是建立可执行、可复用的验证闭环。
================================================
FILE: docs/05-ai/agent-guide.md
================================================
# Agent 工作指引
## 目标
做范围清晰、容易验证、方便评审的改动。
不要把 agent 的“能改”误当成“应该改很多”。
## 编辑前先读
1. `AGENTS.md`
2. `docs/00-overview/project-map.md`
3. `docs/01-architecture/app-layering.md`
4. `docs/01-architecture/state-management-matrix.md`
5. `docs/04-quality/smoke-matrix.md`
6. `docs/06-decisions/ADR-0001-状态管理收敛策略.md`
7. 目标功能对应的 `docs/02-features/*.md`
## 任务模板
按任务类型优先参考:
- 修 Bug:`docs/05-ai/task-playbooks/fix-bug.md`
- 新增页面:`docs/05-ai/task-playbooks/add-page.md`
- 新增接口:`docs/05-ai/task-playbooks/add-api.md`
- 状态整理:`docs/05-ai/task-playbooks/refactor-state.md`
这些模板现在都内置了统一收尾步骤:
- author 完成修改和最小验证后
- 必须先拉起新的 reviewer subagent
- reviewer 独立审查后,author 才能对外汇报完成
## 功能模板
按功能域优先参考:
- 仓库详情:`docs/05-ai/feature-playbooks/repos-change.md`
- 趋势页:`docs/05-ai/feature-playbooks/trend-change.md`
- 通知页:`docs/05-ai/feature-playbooks/notify-change.md`
- Issue:`docs/05-ai/feature-playbooks/issue-change.md`
- 搜索:`docs/05-ai/feature-playbooks/search-change.md`
- 用户页:`docs/05-ai/feature-playbooks/user-change.md`
- 首页容器:`docs/05-ai/feature-playbooks/home-change.md`
- 动态页:`docs/05-ai/feature-playbooks/dynamic-change.md`
- Release:`docs/05-ai/feature-playbooks/release-change.md`
- Push 提交详情:`docs/05-ai/feature-playbooks/push-change.md`
- 调试页:`docs/05-ai/feature-playbooks/debug-change.md`
统一入口:
- `docs/CONTRIBUTING_AI.md`
## Review 分离
- review 采用 author / reviewer 分离上下文
- 每次非微小代码改动后,默认拉起新的 reviewer subagent 做审查
- 在 reviewer subagent 完成一轮审查前,不应直接向用户汇报“已完成”
- 说明见 `docs/05-ai/review-harness.md`
- reviewer 提示模板见 `docs/05-ai/prompts/reviewer-system.md`
- author 交接模板见 `docs/05-ai/prompts/author-handoff.md`
- `tool/ai/build_review_bundle.ps1` 只是可选辅助,不是主路径
## 工作规则
- 优先遵循目标模块现有模式,不主动创造新的抽象层
- 页面局部问题不要上升到根装配层
- 优先通过 repository 或共享网络边界收口,不要把传输细节散落到页面
- 需要生成的内容改源文件,不改生成输出
- 新出现的架构规则应写入 `docs/06-decisions/`,不要只留在对话或 PR 评审里
## 改动后最低报告要求
- 改了什么
- 为什么改动边界合理
- 跑了哪些命令或做了哪些手工验证
- 还剩哪些风险
================================================
FILE: docs/05-ai/feature-playbooks/debug-change.md
================================================
# 功能模板:修改调试页相关功能
## 开始前先读
1. `docs/02-features/debug.md`
2. `lib/common/net/AGENTS.md`
## 优先定位
- 调试页 UI:`lib/page/debug/debug_data_page.dart`
- 日志数据结构:`log_interceptor.dart`、`common/logger.dart`
## 修改策略
- 调试页只服务开发和诊断,不要引入业务依赖
- 改日志字段时同步检查调试页展示
- 复制和 JSON 弹窗链路都要能工作
## 最低验证
1. 调试页可打开
2. 四个 tab 可切换
3. 列表项可点击查看 JSON
4. 长按和双击复制正常
## 收尾步骤
调试页改动完成后,仍需先经过新的 reviewer subagent 审查,再对外汇报结果。
================================================
FILE: docs/05-ai/feature-playbooks/dynamic-change.md
================================================
# 功能模板:修改动态页相关功能
## 开始前先读
1. `docs/02-features/dynamic.md`
2. `docs/04-quality/smoke-matrix.md`
3. `lib/page/AGENTS.md`
## 优先定位
- 页面刷新和滚动行为:`lib/page/dynamic/dynamic_page.dart`
- 列表数据与分页:`lib/page/dynamic/dynamic_bloc.dart`
- 事件跳转:`common/utils/event_utils.dart`
## 修改策略
- 首次加载、手动刷新、恢复前台刷新都要分开验证
- 动态页依赖当前登录用户,注意 Redux 用户态
- 不要只改 bloc 不测页面恢复刷新
## 最低验证
1. 首次进入动态页
2. 下拉刷新
3. 上拉加载更多
4. 退到后台再回来,验证自动刷新
5. 点击事件项跳转
## 收尾步骤
动态页改动完成后,先拉起新的 reviewer subagent 审查首次加载、恢复刷新和事件跳转,再对外汇报。
================================================
FILE: docs/05-ai/feature-playbooks/home-change.md
================================================
# 功能模板:修改首页容器相关功能
## 开始前先读
1. `docs/02-features/home.md`
2. `docs/04-quality/smoke-matrix.md`
3. `lib/page/AGENTS.md`
## 优先定位
- tab 容器和搜索入口:`lib/page/home/home_page.dart`
- drawer:`lib/page/home/widget/home_drawer.dart`
## 修改策略
- 首页只负责容器和导航,不要承接具体业务逻辑
- 改 tab 结构时,同时验证 dynamic/trend/my 三个入口
- 改搜索入口时,要验证右上角位置计算与动画起点
## 最低验证
1. 首页可正常进入
2. 三个 tab 可切换
3. 双击 tab 可回到顶部
4. 搜索入口可打开搜索页
5. Android 返回键行为符合预期
## 收尾步骤
首页容器相关改动在完成验证后,必须先经过新的 reviewer subagent 审查。
这是容器层改动,不应由 author 自己直接宣布完成。
================================================
FILE: docs/05-ai/feature-playbooks/issue-change.md
================================================
# 功能模板:修改 Issue 相关功能
## 开始前先读
1. `docs/02-features/issue.md`
2. `docs/04-quality/smoke-matrix.md`
3. `lib/page/AGENTS.md`
## 优先定位
- 展示和交互问题:`lib/page/issue/issue_detail_page.dart`
- 数据协议问题:`lib/common/repositories/issue_repository.dart`
## 修改策略
- 头部信息和评论列表分开看,不要混成一条链路
- 编辑、删除、回复逻辑都依赖刷新回流
- 不要只改按钮显示,不改实际提交链路
## 最低验证
1. 进入 issue 详情
2. 头部正常展示
3. 评论列表正常加载
4. 回复 issue
5. 编辑 issue 或评论
6. open/close issue 后头部状态更新
## 收尾步骤
Issue 相关改动完成后,先用新的 reviewer subagent 审查评论链路和头部状态回流,再对外汇报完成。
================================================
FILE: docs/05-ai/feature-playbooks/notify-change.md
================================================
# 功能模板:修改通知页相关功能
## 适用场景
- 修改通知列表展示
- 调整未读/参与/全部筛选
- 修复刷新、分页或已读状态问题
- 扩展通知跳转行为
## 开始前先读
1. `docs/02-features/notify.md`
2. `docs/04-quality/smoke-matrix.md`
3. `lib/page/AGENTS.md`
## 先判断问题属于哪一层
### 页面与交互层
对应:
- `lib/page/notify/notify_page.dart`
适合处理:
- 列表渲染
- 滑动已读
- 顶部筛选
- 跳转行为
### 数据层
对应:
- `lib/common/repositories/user_repository.dart`
- `lib/model/notification.dart`
适合处理:
- 获取通知
- 标记已读
- 全部已读
- 通知字段解析
## 修改策略
- 优先维持 Signals 结构稳定
- 扩展通知类型跳转时,集中处理在 `_renderEventItem`
- 改分页或刷新逻辑时,必须一起验证筛选切换和返回强刷
- 未经明确允许,不得把本模块从 Signals 改成别的状态实现;这里保留 Signals 具有明确演示价值
## 常见误区
- 忽略 `signalPage = -1` 的强制刷新约定
- 只验证默认列表,不验证三个筛选 tab
- 标记已读后忘了检查列表移除或刷新逻辑
## 最低验证
1. 进入通知页
2. 默认列表加载
3. 切换 未读 / 参与 / 全部
4. 下拉刷新
5. 上拉加载更多
6. 单条标记已读
7. 全部标记已读
8. 点击 Issue 类型通知进入详情并返回
## 需要额外谨慎的情况
- 修改 Signals 触发链路
- 修改分页边界
- 修改通知详情跳转映射
## 收尾步骤
通知页改动完成后,必须先经过新的 reviewer subagent 审查。
author 不应在未做独立 review 的情况下直接宣布完成。
================================================
FILE: docs/05-ai/feature-playbooks/push-change.md
================================================
# 功能模板:修改 Push 提交详情相关功能
## 开始前先读
1. `docs/02-features/push.md`
2. `docs/04-quality/smoke-matrix.md`
3. `lib/page/AGENTS.md`
## 优先定位
- 页面与 patch 展示:`lib/page/push/push_detail_page.dart`
- patch 转 HTML:`common/utils/html_utils.dart`
- commit 数据:`ReposRepository`
## 修改策略
- 头部和文件列表来自同一请求结果
- patch 展示问题不要忽略 HTML 转换逻辑
- 改导航时要验证返回仓库详情按钮
## 最低验证
1. 进入 push 提交详情
2. 头部信息正常
3. 文件变更列表正常
4. 点击文件项进入 patch 详情
5. 返回仓库详情链路正常
## 收尾步骤
Push 提交详情改动完成后,必须先经过新的 reviewer subagent 审查 patch 展示和返回链路。
================================================
FILE: docs/05-ai/feature-playbooks/release-change.md
================================================
# 功能模板:修改 Release 相关功能
## 开始前先读
1. `docs/02-features/release.md`
2. `docs/04-quality/smoke-matrix.md`
3. `lib/page/AGENTS.md`
## 优先定位
- 页面交互与 tab:`lib/page/release/release_page.dart`
- 数据获取:`ReposRepository.getRepositoryReleaseRequest`
## 修改策略
- release 和 tag 两条链路都要测
- 内嵌 HTML 预览和外部链接打开都要测
- tab 切换后会清空并重刷列表
## 最低验证
1. 进入 release 页面
2. release 列表可加载
3. 切到 tag 列表可加载
4. 点击 release 项查看 HTML
5. 长按项可外部打开链接
## 收尾步骤
Release 页面改动完成后,先由新的 reviewer subagent 审查 release/tag 双链路,再对外汇报完成。
================================================
FILE: docs/05-ai/feature-playbooks/repos-change.md
================================================
# 功能模板:修改仓库详情相关功能
## 适用场景
- 修改仓库详情页 UI
- 调整 Readme、Issue、文件列表其中一个 tab
- 修改分支切换逻辑
- 调整仓库详情底部按钮行为
- 修复仓库详情页的联动刷新问题
## 开始前先读
1. `docs/02-features/repos.md`
2. `docs/01-architecture/state-management-matrix.md`
3. `docs/04-quality/smoke-matrix.md`
4. `lib/page/AGENTS.md`
## 先判断问题属于哪一层
### 页面壳层
对应:
- `lib/page/repos/repository_detail_page.dart`
- tab 容器、标题栏、更多菜单、浮动按钮
适合处理:
- 页面布局
- tab 切换
- 分支选择入口
- 顶部和底部操作区
### 共享状态层
对应:
- `lib/page/repos/provider/repos_detail_provider.dart`
- `lib/page/repos/provider/repos_network_provider.dart`
适合处理:
- 当前 tab
- 当前分支
- 仓库详情共享数据
- readme 内容
- 底部按钮联动
### 数据层
对应:
- `lib/common/repositories/repos_repository.dart`
- `lib/common/repositories/issue_repository.dart`
- 相关 model
适合处理:
- 请求字段
- 数据解析
- readme、issue、file 等数据源问题
## 修改策略
- 只改某一个 tab 时,优先停留在该 tab 及其直接依赖
- 涉及分支切换时,必须检查 info/readme/file 三者联动
- 涉及 issue 创建时,检查弹窗输入、提交、刷新回流
- 不要为了某个 tab 的问题重做整个 Provider 结构
## 常见误区
- 把跨 tab 共享状态拆成各页面自己的局部变量
- 只改 UI 显示,不改 provider 内状态更新
- 忽略 `currentBranch` 对多个子页的数据源影响
## 最低验证
1. 从入口进入仓库详情页
2. 信息页正常展示
3. Readme 页能加载
4. Issue 页能切换并加载
5. 文件列表页能切换并加载
6. 切换分支后,至少验证信息页、Readme、文件列表联动
## 需要额外谨慎的情况
- 修改 provider 字段定义
- 修改共享底部按钮逻辑
- 修改和 issue、readme、file 同时相关的请求入口
## 收尾步骤
仓库详情相关改动完成后,必须先经过新的 reviewer subagent 审查。
这是跨 tab、跨状态共享模块,不应由 author 直接宣布完成。
================================================
FILE: docs/05-ai/feature-playbooks/search-change.md
================================================
# 功能模板:修改搜索相关功能
## 开始前先读
1. `docs/02-features/search.md`
2. `docs/04-quality/smoke-matrix.md`
3. `lib/page/AGENTS.md`
## 优先定位
- 页面、动画、输入交互:`lib/page/search/search_page.dart`
- 搜索参数与请求:`lib/page/search/search_bloc.dart`
- 接口结果:`ReposRepository.searchRepositoryRequest`
## 修改策略
- 搜索条件变更后要清空旧列表并重刷
- 仓库搜索和用户搜索要分别验证
- 动画问题不要误伤搜索逻辑,请求问题也不要顺手改动画
## 最低验证
1. 打开搜索页
2. 输入关键字后搜索仓库
3. 切换到用户搜索
4. 改变排序或过滤条件
5. 返回首页时动画正常收起
## 收尾步骤
搜索页改动完成后,需先由新的 reviewer subagent 审查搜索参数、动画和页面生命周期处理,再对外汇报。
================================================
FILE: docs/05-ai/feature-playbooks/trend-change.md
================================================
# 功能模板:修改趋势页相关功能
## 适用场景
- 趋势页列表展示改动
- 时间和语言筛选改动
- 刷新或首次加载问题
- 趋势页跳转链路调整
## 开始前先读
1. `docs/02-features/trend.md`
2. `docs/06-decisions/ADR-0001-状态管理收敛策略.md`
3. `docs/04-quality/smoke-matrix.md`
4. `lib/page/AGENTS.md`
## 先判断问题属于哪一层
### 页面层
对应:
- `lib/page/trend/trend_page.dart`
适合处理:
- 列表渲染
- 筛选头部
- 滚动和刷新控件
- 空态、按钮、跳转
### 状态与请求层
对应:
- `lib/page/trend/trend_provider.dart`
- `lib/common/repositories/repos_repository.dart`
适合处理:
- 首次请求
- 二阶段请求
- 刷新触发逻辑
- 趋势数据获取
## 修改策略
- UI 小改动尽量停留在 `trend_page.dart`
- 请求或缓存问题再看 `trend_provider.dart`
- 不要在普通改动里重构趋势页整体状态管理
- 修改首次加载逻辑时,要同时检查 `didChangeDependencies` 和刷新流程
## 常见误区
- 忽略模块级变量 `trendLoadingState`、`trendRequestedState`
- 只测首次加载,不测切换筛选和下拉刷新
- 误把趋势页当前实现理解成纯页面局部状态
## 最低验证
1. 进入趋势页
2. 首次加载正常
3. 切换时间筛选
4. 切换语言筛选
5. 下拉刷新
6. 点击列表项进入仓库详情并返回
## 需要额外谨慎的情况
- 修改 provider 参数结构
- 修改刷新触发时机
- 修改趋势页和仓库详情页之间的跳转
## 收尾步骤
趋势页改动完成后,先拉起新的 reviewer subagent 审查刷新、筛选和状态边界,再对外汇报完成。
================================================
FILE: docs/05-ai/feature-playbooks/user-change.md
================================================
# 功能模板:修改用户页相关功能
## 开始前先读
1. `docs/02-features/user.md`
2. `docs/04-quality/smoke-matrix.md`
3. `lib/page/AGENTS.md`
## 优先定位
- 页面展示与交互:`lib/page/user/person_page.dart`
- 共享头部与 honor:`lib/page/user/base_person_provider.dart`
- 数据请求:`UserRepository` / `EventRepository`
## 修改策略
- 先判断当前展示对象是用户还是组织
- 关注状态、用户信息、列表数据是多条链路,分别验证
- 不要把组织分支和普通用户分支混在一起改
## 最低验证
1. 进入用户页
2. 头部信息正常
3. 用户动态或组织成员正常展示
4. 关注/取消关注行为正常
5. 返回链路正常
## 收尾步骤
用户页改动完成后,先用新的 reviewer subagent 审查用户分支和组织分支,再对外汇报完成。
================================================
FILE: docs/05-ai/prompts/author-handoff.md
================================================
# Author Handoff Prompt
你是 author agent。你已经完成实现,现在要把改动交给 reviewer agent。
你的任务不是解释自己为什么对,而是提供一个尽量中立、最小、可验证的 review bundle。
请输出:
1. 本次任务目标
2. 变更文件列表
3. 改动边界
4. 已运行的验证命令
5. 未覆盖的风险
6. 建议 reviewer 优先检查的功能域
约束:
- 不要输出长篇自我辩护
- 不要把“为什么我认为没问题”作为主体
- 不要省略失败过或没做的验证
- 用事实描述,不要用结论压 reviewer
================================================
FILE: docs/05-ai/prompts/reviewer-system.md
================================================
# Reviewer System Prompt
你是 reviewer agent,不是 author agent。
你的职责是独立审查当前变更,优先发现问题、风险、回归和验证缺口。
不要默认信任 author 的实现,也不要帮助 author 为改动辩护。
## 你的输入边界
你可以使用:
- 仓库代码
- review bundle
- `AGENTS.md`
- 相关功能文档和 feature playbook
- 本地验证命令输出
你不应依赖:
- author 的完整对话历史
- author 的内部推理
- “已经验证没问题”这类自证结论
## 你的优先级
1. 先找 bug 和行为回归
2. 再看边界是否越界
3. 再看验证是否足够
4. 最后才是风格和可维护性建议
## 输出要求
如果发现问题,按严重程度排序输出:
- Findings
- Open Questions
- Verification Gaps
每条 finding 尽量包含:
- 问题是什么
- 为什么会导致错误或回归
- 涉及文件
如果没有发现问题,也必须明确说明:
- 未发现明确缺陷
- 仍有哪些验证空白或残余风险
## 禁止事项
- 不要把 author 的描述当成事实
- 不要因为改动小就跳过共享边界检查
- 不要在没有证据时给出“应该没问题”式结论
================================================
FILE: docs/05-ai/review-harness.md
================================================
# Review Harness
## 目标
让代码审查尽量摆脱 author 视角,避免“作者自己解释自己为什么没问题”。
本仓库默认采用 `author agent` 和 `reviewer subagent` 分离的方式进行 AI 审查。
这更接近 OpenAI 在《Harness engineering》里强调的做法:把 review 设计成独立反馈回路,而不是同一上下文里的自我安慰式复查。
## 核心原则
1. `author` 和 `reviewer` 不共用上下文
2. `reviewer` 应使用新的 subagent 或新的干净上下文
3. `reviewer` 不读取 author 的完整对话历史
4. `reviewer` 只拿到最小必要信息:
- 任务目标
- 相关文档入口
- 变更文件
- diff
- 验证结果
5. `reviewer` 的默认职责是找问题,不是帮 author 辩护
这里最重要的不是“把 review 写成文档”,而是把 review 运行在一个新的思维上下文里。
如果 reviewer 继承了 author 的长上下文,它就很容易共享 author 的错误假设。
## 两种角色
### Author
负责:
- 理解任务
- 修改代码
- 运行最小验证
- 在需要时产出 review bundle
不负责:
- 在同一思路链路里给自己“盖章通过”
### Reviewer
负责:
- 在新的 subagent 或新的干净上下文中审查变更
- 优先寻找 bug、回归、越界改动、验证缺失
- 明确指出风险,而不是复述 author 目标
不负责:
- 继续帮 author 完成实现
- 读取 author 的内部推理过程
## 推荐流程
1. Author 完成代码和最小验证
2. 启动新的 reviewer subagent 或新的 reviewer 会话
3. Reviewer 只读取:
- `docs/05-ai/prompts/reviewer-system.md`
- 当前 diff
- 变更相关文件
- 相关功能文档
- 验证结果
4. Reviewer 输出 findings、风险、验证缺口
5. Author 根据 findings 修复
6. 必要时开启下一轮 reviewer 会话
默认流程里,review bundle 不是必需的。
如果当前环境已经能直接让新的 reviewer subagent 读取代码和 diff,那么直接这样做即可。
在这个流程完成前,author 不应直接对外宣告“任务已完成”。
对外汇报应发生在至少一轮独立 reviewer 审查之后。
## Reviewer 输入边界
Reviewer 默认可以看:
- 本仓库代码
- 当前 diff
- `AGENTS.md`
- 相关功能文档和 feature playbook
Reviewer 默认不应该看:
- author 的完整聊天历史
- author 的主观解释性长文本
- “我已经确认没问题了”这类自证语句
## 最小 review bundle
如果无法方便地把当前 diff 和验证结果直接交给 reviewer,才使用 review bundle。
bundle 至少应包含:
- 任务摘要
- 变更文件列表
- diff 统计
- 关键 diff
- 运行过的验证命令
- 对应功能域和回归建议
默认情况下,`tool/ai/build_review_bundle.ps1` 会收集“当前工作区相对 `HEAD` 的未提交变更”。
它只是一个可选辅助工具,不是主流程。
如果你要审查某个分支相对基线分支的差异,可以显式传入:
- `-BaseRef origin/master`
- 或其他明确基线
## 审查标准
Reviewer 优先关注:
1. 逻辑正确性
2. 行为回归
3. 状态边界是否被破坏
4. 是否违反仓库文档中的既有约束
5. 验证是否足够支撑本次改动
## 输出格式建议
- Findings
- Open Questions
- Verification Gaps
- Residual Risks
如果没有发现问题,也要明确说明:
- 未发现明显问题
- 仍然存在哪些验证空白
## 实操要求
- 只要是中等以上改动,默认走 reviewer 分离流程
- 改共享层、根装配、状态边界、公共网络层时,必须走 reviewer 分离流程
- reviewer 分离流程的首选实现方式是新的 subagent / 新的干净上下文
- 未经过 reviewer 分离流程的代码改动,不应以“已完成”状态对外汇报
================================================
FILE: docs/05-ai/task-playbooks/add-api.md
================================================
# 任务模板:新增接口或数据请求
## 适用场景
- 新增 REST 或 GraphQL 请求
- 扩展已有 repository 的数据读取能力
- 新增页面所需的数据接口
## 开始前先确认
1. 这是 REST 还是 GraphQL
2. 是已有 repository 的扩展,还是确实需要新的边界
3. 是否需要新增模型或更新现有模型
4. 页面是否真的需要新的接口,而不是已有接口字段未使用
## 先读哪些文档
1. `AGENTS.md`
2. `docs/01-architecture/app-layering.md`
3. 对应功能文档
4. `lib/common/net/AGENTS.md`
## 执行步骤
1. 先找最接近的现有请求入口
2. 优先在 repository 层新增或扩展能力
3. 必要时再补 `common/net` 或 `graphql/` 细节
4. 如需新模型,更新模型定义并重新生成
5. 在页面层只消费 repository 结果,不扩散传输细节
6. 若接口会被多个页面复用,避免把逻辑藏在单页内部
## 本仓库的修改顺序建议
1. `lib/common/repositories/*`
2. `lib/common/net/*` 或 `lib/common/net/graphql/*`
3. `lib/model/*`
4. 对应 `lib/page/*` 或 provider/redux 层
## 禁止事项
- 不要把接口细节直接塞进页面
- 不要先改 UI 再临时拼接网络逻辑
- 不要漏掉模型和生成代码同步
## 最低验证
- `flutter analyze`
- 若改模型或注解,执行生成命令
- 手工验证至少一个使用该接口的页面
- 若改公共网络层,按 `smoke-matrix.md` 抽查多个功能
## 输出要求
至少说明:
- 新接口加在了哪个 repository 边界
- 是否新增或更新了模型
- 是否影响共享网络层
- 验证覆盖了哪些页面
## 收尾步骤
接口或数据请求改动在完成最小验证后,必须经过新的 reviewer subagent 审查。
尤其当改动触及共享网络层、repository 边界或模型时,不应跳过这一步。
================================================
FILE: docs/05-ai/task-playbooks/add-page.md
================================================
# 任务模板:新增页面
## 适用场景
- 新增一个页面或子页面
- 新增一个现有功能下的详情页、列表页、设置页
- 需要接入已有导航和数据链路
## 开始前先确认
1. 这是独立功能页,还是已有功能下的一个子页
2. 页面需要页面局部状态、功能共享状态,还是全局状态
3. 页面数据来自已有 repository 还是需要新增接口
## 先读哪些文档
1. `AGENTS.md`
2. `docs/01-architecture/app-layering.md`
3. `docs/01-architecture/state-management-matrix.md`
4. 目标功能文档,例如 `docs/02-features/*.md`
5. `docs/06-decisions/ADR-0002-新增功能默认状态方案.md`
## 执行步骤
1. 找到最接近的现有页面作为参照
2. 先决定状态作用域:
- 页面局部:优先本地 state
- 功能局部共享:沿用当前模块既有方案
- 应用全局:复用 Redux 或 Riverpod 入口
3. 将页面放入对应功能目录,不要新建随意目录层级
4. 复用现有导航、标题栏、列表、加载和弹窗组件
5. 若页面依赖新数据,再补 repository 或 API 入口
6. 补充对应功能文档,至少记录入口、状态方案和主要数据流
## 本仓库的默认选择
- 若新增 `repos` 子页:优先跟随该模块当前 Provider 结构
- 若新增趋势页相关子页:优先跟随 Riverpod 结构
- 若只是很轻的局部页面交互:优先页面本地 state
## 禁止事项
- 不要为了新页面顺手引入新的状态管理库
- 不要直接把页面私有状态放进全局容器
- 不要复制粘贴一套新的网络调用链路绕过 repository
## 最低验证
- 页面可正常进入与返回
- 主要交互可执行
- 若依赖列表或详情数据,至少完成一次加载与刷新验证
- 若接入导航,验证入口页到新页面再返回的链路
## 输出要求
至少说明:
- 页面放在哪个功能目录
- 选择了哪种状态方案,为什么
- 是否复用了已有 repository 或新增了数据边界
- 跑了哪些验证
## 收尾步骤
新增页面完成后,author 不应直接宣布完成。
必须先使用新的 reviewer subagent 审查页面边界、状态方案和验证覆盖,再对外汇报结果。
================================================
FILE: docs/05-ai/task-playbooks/fix-bug.md
================================================
# 任务模板:修复 Bug
## 适用场景
- 页面行为异常
- 接口数据展示错误
- 刷新、分页、跳转、状态同步问题
- 某个已有功能回归
## 开始前先确认
1. Bug 属于哪个功能域
2. 问题发生在 UI、状态层、repository,还是共享网络层
3. 是否已经有稳定复现路径
## 先读哪些文档
1. `AGENTS.md`
2. `docs/00-overview/project-map.md`
3. 对应功能文档,例如 `docs/02-features/repos.md`
4. 若涉及共享层,再读:
- `docs/01-architecture/app-layering.md`
- `docs/04-quality/smoke-matrix.md`
## 执行步骤
1. 先定位最小复现路径
2. 找到最靠近问题的模块,不要一上来改全局
3. 判断问题属于:
- 页面展示错误
- 局部状态错误
- 共享状态错误
- repository/网络返回错误
4. 只在必要范围内修改
5. 回归受影响功能和相邻链路
## 本仓库的定位建议
- 登录问题:先看 `lib/page/login/` 和 `lib/redux/login_redux.dart`
- 仓库详情问题:先看 `lib/page/repos/` 与对应 provider
- 趋势页问题:先看 `lib/page/trend/`
- 通知页问题:先看 `lib/page/notify/`
- 多页面同时异常:再考虑 `lib/common/net/`、`lib/common/repositories/` 或 `lib/app.dart`
## 禁止事项
- 不要借修 bug 顺手迁移状态管理框架
- 不要为了页面问题直接修改根装配层
- 不要手改生成文件来掩盖真实问题
## 最低验证
- 按 `docs/04-quality/smoke-matrix.md` 执行该功能的基础用例
- 若动到共享层,额外抽查一个高频功能
- 若改模型或生成输入,执行相应生成命令
## 输出要求
至少说明:
- 复现路径
- 根因在哪一层
- 改动边界为什么足够小
- 跑了哪些验证
## 收尾步骤
在 author 自己完成修改和最小验证后,不应直接宣布任务完成。
必须先拉起新的 reviewer subagent 或新的干净 reviewer 上下文,对这次 bug 修复做一轮独立审查。
================================================
FILE: docs/05-ai/task-playbooks/refactor-state.md
================================================
# 任务模板:整理或重构状态
## 适用场景
- 页面状态过于分散
- 同一功能出现重复状态源
- 需要把局部状态收敛到当前模块既有状态容器
- 明确批准的小范围状态整理
## 开始前先确认
1. 这是普通需求里的顺手整理,还是明确批准的状态改造
2. 当前模块已经使用哪种状态方案
3. 改动后是否会影响多个页面、多个 tab 或全局行为
## 先读哪些文档
1. `docs/01-architecture/state-management-matrix.md`
2. `docs/06-decisions/ADR-0001-状态管理收敛策略.md`
3. `docs/06-decisions/ADR-0002-新增功能默认状态方案.md`
4. 对应功能文档
## 执行步骤
1. 画清楚当前状态的拥有者和消费者
2. 找出重复状态源和不必要的跨层传递
3. 限制整理范围,只处理目标模块
4. 保持外部行为不变
5. 回归该模块的主要交互链路
## 是否允许执行
可以直接做:
- 将页面内重复局部 state 收敛到当前页面已有状态结构
- 在同一模块内消除明显重复状态源
- 把散落在多个子 widget 的功能局部状态收回到该模块已有 provider 或局部状态容器
需要先补 ADR 再做:
- 将整个功能域从 Provider 迁移到 Riverpod
- 将 Redux 的登录/用户主链路挪到别的状态方案
- 修改 `lib/app.dart` 中的全局状态接线方式
## 禁止事项
- 不要把“状态整理”变成大规模架构迁移
- 不要在没有验证的情况下改动共享状态边界
- 不要同时调整状态方案和功能行为,除非任务明确要求
- 未经明确允许,不得把模块从既有框架/状态实现切换到另一套实现,即使你认为新实现更稳定或更容易修
## 最低验证
- 目标功能的基础回归用例
- 涉及共享状态时,额外抽查一个相邻功能
- 若动到根装配或全局共享状态,回归启动、登录态、主题/语言
## 输出要求
至少说明:
- 旧状态结构的问题是什么
- 为什么这次整理不属于架构迁移
- 改动后状态归属是否更清晰
- 跑了哪些回归
## 收尾步骤
状态整理类改动默认必须经过新的 reviewer subagent 审查后,才能对外宣告完成。
这是高 author 偏见风险任务,不允许用 author 自己的上下文直接给自己通过。
================================================
FILE: docs/06-decisions/ADR-0001-状态管理收敛策略.md
================================================
# ADR-0001 状态管理收敛策略
## 状态
已采纳
## 日期
2026-03-10
## 背景
当前项目同时使用 Redux、Riverpod、Provider、Signals。
这种并存状态来自历史演进和教学展示诉求,短期内不会也不应该通过一次重构强行统一。
问题不在于“有多种状态管理”,而在于如果没有新增规则,后续功能和 agent 改动会继续把边界变得更混乱:
- 新功能可能按个人偏好继续引入不一致方案
- 页面局部状态可能误上升为全局状态
- 全局状态可能同时在多个状态容器里重复保存
- AI 在缺少明确规则时容易用“看起来最熟的库”去实现需求
## 决策
项目接受当前多状态并存的现实,但从现在开始约束新增和演进规则:
1. 不新增第五种状态管理方案
2. 无关任务不得顺手迁移既有模块的状态管理
3. 新增状态默认按“作用域”选择,而不是按个人偏好选择
4. 涉及全局共享状态时,优先使用现有全局主路径,而不是新开一条平行状态链路
5. 任何跨模块状态管理迁移都必须先补决策记录,再执行代码改造
6. 未经明确允许,不得为了满足需求或修复问题,擅自把模块从既有框架/状态实现切换到另一套实现
## 默认选择规则
### 应用级共享状态
适用场景:
- 登录态
- 当前用户核心信息
- 全局主题、语言、灰度模式
- 会影响多个页面和全局入口的状态
默认策略:
- 优先复用当前已经承接这类职责的 Redux 或 Riverpod 入口
- 如果是“纯应用配置型共享状态”,优先贴近现有 Riverpod 方式
- 如果是历史上已经由 Redux 管理的登录/用户链路,优先延续 Redux
### 功能级共享状态
适用场景:
- 某个复杂功能模块内部多个子页面、tab、局部组件共享状态
默认策略:
- 优先沿用该模块当前已存在方案
- 对当前仓库,像 `repos` 这类跨 tab 共享状态,继续沿用模块内 Provider 结构
### 页面局部交互状态
适用场景:
- 筛选条件
- 页码
- 局部开关
- 临时 UI 控制状态
默认策略:
- 优先使用页面本地 state
- 如果模块已经明确使用 Signals 或局部 Riverpod,则跟随既有模式
## 不做的事
- 不要求立即把 Redux/Provider/Signals 全部迁到 Riverpod
- 不要求为了一致性重写成熟模块
- 不鼓励在普通需求里夹带架构收敛
- 不允许为了“更容易改”就把演示性质明确的模块偷偷改成别的状态方案
## 影响
正面影响:
- 新增功能不会继续无序扩散状态方案
- agent 更容易判断应该把状态放在哪里
- 评审时有了明确基准,而不是只看个人习惯
代价:
- 一段时间内项目仍会维持多种状态管理并存
- 部分历史模块看起来仍然不统一
## 执行规则
以下情况需要先补新 ADR,再开始迁移:
- 计划将某一整个功能域从 Provider 迁到 Riverpod
- 计划把登录和用户主链路从 Redux 挪走
- 计划修改全局状态入口,影响 `lib/app.dart`
普通需求只需遵守本 ADR,不需要额外发起架构迁移。
额外约束:
- 如果某个模块明确承担演示某种状态方案的职责,例如 `notify` 中的 Signals,用普通需求绕过这层设计同样视为越界。
================================================
FILE: docs/06-decisions/ADR-0002-新增功能默认状态方案.md
================================================
# ADR-0002 新增功能默认状态方案
## 状态
已采纳
## 日期
2026-03-10
## 背景
即使接受“当前存在多种状态管理方案”,团队和 agent 仍然需要一个面向新增功能的默认选择标准。
否则每个新页面都可能重新争论一次,或者由 AI 直接按训练偏好做决定。
## 决策
新增功能的状态管理默认按以下优先级选择:
1. 先看目标模块已有状态方案
2. 再看状态作用域是页面局部、功能局部还是应用全局
3. 只有在目标模块没有明确先例时,才使用下面的默认规则
## 默认规则
### 页面局部状态
优先选择:
- `StatefulWidget` 本地 state
- 若该模块已使用 Signals,则可继续使用 Signals
适用:
- 页码
- 筛选项
- 展开/收起
- 加载中标记
- 只影响当前页面的临时状态
### 功能局部共享状态
优先选择:
- 沿用目标功能目录已存在方案
- 如果目标功能是新建且预计会存在多 tab、多子视图共享,可优先考虑 Riverpod
适用:
- 复杂详情页
- 多 tab 共享数据
- 多个子 widget 共用一份异步加载状态
### 应用全局状态
优先选择:
- 复用现有 Redux 或 Riverpod 全局入口
适用:
- 登录态
- 当前用户核心身份信息
- 全局主题/语言/灰度模式
## 禁止事项
- 不要因为某个库“更先进”就替换当前功能模块状态方案
- 不要在一个新功能里同时引入两套新的状态来源
- 不要把页面局部交互状态直接抬升到全局
## 评审清单
新增功能提交前至少回答:
1. 这个状态为什么不放在页面本地?
2. 为什么不沿用目标模块既有模式?
3. 这个状态会影响几个页面或几个 tab?
4. 是否会和现有 Redux/Riverpod/Provider/Signals 形成重复状态源?
## 结果
这个 ADR 的目标不是追求形式统一,而是降低新增功能的状态决策成本,并减少 AI 改动的随机性。
================================================
FILE: docs/06-decisions/README.md
================================================
# 决策记录
这个目录用于保存 ADR 风格的长期决策。
凡是“以后还会反复被问到”的架构选择,不要只留在代码评审历史里。
后续适合记录的主题包括:
- 状态管理收敛策略
- CI 最小验证基线
- 生成代码工作流
- 功能目录约定
================================================
FILE: docs/CONTRIBUTING_AI.md
================================================
# AI 协作入口
这个入口页用于帮助人和 agent 快速选择正确的文档路径。
不要从根 README 直接跳进代码,先判断你当前属于哪类任务。
## 如果你要修 Bug
先读:
1. `docs/05-ai/task-playbooks/fix-bug.md`
2. 对应功能文档 `docs/02-features/*.md`
3. `docs/04-quality/smoke-matrix.md`
注意:
- 任务模板和功能模板都已经内置 reviewer subagent 收尾步骤
- author 不应跳过这一步直接宣布完成
## 如果你要新增页面
先读:
1. `docs/05-ai/task-playbooks/add-page.md`
2. `docs/06-decisions/ADR-0002-新增功能默认状态方案.md`
3. 对应功能文档 `docs/02-features/*.md`
## 如果你要新增接口
先读:
1. `docs/05-ai/task-playbooks/add-api.md`
2. `lib/common/net/AGENTS.md`
3. 对应功能文档 `docs/02-features/*.md`
## 如果你要整理状态
先读:
1. `docs/05-ai/task-playbooks/refactor-state.md`
2. `docs/06-decisions/ADR-0001-状态管理收敛策略.md`
3. `docs/01-architecture/state-management-matrix.md`
## 如果你要改仓库详情相关功能
先读:
1. `docs/05-ai/feature-playbooks/repos-change.md`
2. `docs/02-features/repos.md`
3. `docs/04-quality/smoke-matrix.md`
## 如果你要改趋势页
先读:
1. `docs/05-ai/feature-playbooks/trend-change.md`
2. `docs/02-features/trend.md`
3. `docs/04-quality/smoke-matrix.md`
## 如果你要改通知页
先读:
1. `docs/05-ai/feature-playbooks/notify-change.md`
2. `docs/02-features/notify.md`
3. `docs/04-quality/smoke-matrix.md`
## 如果你要改 Issue
先读:
1. `docs/05-ai/feature-playbooks/issue-change.md`
2. `docs/02-features/issue.md`
## 如果你要改搜索
先读:
1. `docs/05-ai/feature-playbooks/search-change.md`
2. `docs/02-features/search.md`
## 如果你要改用户页
先读:
1. `docs/05-ai/feature-playbooks/user-change.md`
2. `docs/02-features/user.md`
## 如果你要改首页容器
先读:
1. `docs/05-ai/feature-playbooks/home-change.md`
2. `docs/02-features/home.md`
## 如果你要改动态页
先读:
1. `docs/05-ai/feature-playbooks/dynamic-change.md`
2. `docs/02-features/dynamic.md`
## 如果你要改 Release
先读:
1. `docs/05-ai/feature-playbooks/release-change.md`
2. `docs/02-features/release.md`
## 如果你要改 Push 提交详情
先读:
1. `docs/05-ai/feature-playbooks/push-change.md`
2. `docs/02-features/push.md`
## 如果你要改调试页
先读:
1. `docs/05-ai/feature-playbooks/debug-change.md`
2. `docs/02-features/debug.md`
## 通用入口
无论哪类任务,默认都建议先过一遍:
1. `AGENTS.md`
2. `docs/README.md`
3. `docs/00-overview/project-map.md`
4. `docs/01-architecture/app-layering.md`
## 如果你要做 AI review
先读:
1. `docs/05-ai/review-harness.md`
2. `docs/05-ai/prompts/reviewer-system.md`
3. 如需 review bundle,再看 `tool/ai/build_review_bundle.ps1`
================================================
FILE: docs/README.md
================================================
# 文档索引
这个目录同时服务于人类协作者和代码 agent。
第一次进入仓库时,建议按顺序阅读,不要只看根 README 就直接改代码。
## 推荐阅读顺序
1. `00-overview/project-map.md`
2. `01-architecture/app-layering.md`
3. `01-architecture/state-management-matrix.md`
4. `03-runbooks/local-setup.md`
5. `04-quality/test-strategy.md`
6. `04-quality/smoke-matrix.md`
7. `05-ai/agent-guide.md`
## 目录说明
- `00-overview/`:快速理解项目和目录职责
- `01-architecture/`:分层边界、状态管理边界、生成代码与配置规则
- `02-features/`:按功能说明关键页面、数据流和高风险点
- `03-runbooks/`:本地运行和常见操作手册
- `04-quality/`:验证方式、质量门槛、测试策略
- `05-ai/`:面向 agent 的工作约束和执行方式
- `06-decisions/`:需要长期保留的架构决策记录
## 当前关键文档
- 架构边界:`01-architecture/app-layering.md`
- 状态管理边界:`01-architecture/state-management-matrix.md`
- 手工回归入口:`04-quality/smoke-matrix.md`
- 长期规则:`06-decisions/ADR-0001-状态管理收敛策略.md`
- 任务模板入口:`05-ai/task-playbooks/`
- 功能模板入口:`05-ai/feature-playbooks/`
- AI 协作导航:`CONTRIBUTING_AI.md`
## 当前目标
当前这批文档的重点不是先做“AI 功能”,而是先把仓库整理成:
- 更容易理解
- 更容易局部修改
- 更容易验证
- 更不容易让 agent 猜错边界
================================================
FILE: fastlane/metadata/android/en-US/full_description.txt
================================================
<p>The purpose of the project is to facilitate personal daily maintenance and access to Github, better immerse in the mutual base between coders, Github is your home.</p>
================================================
FILE: fastlane/metadata/android/en-US/short_description.txt
================================================
Third-party Github App
================================================
FILE: ios/.gitignore
================================================
.idea/
.vagrant/
.sconsign.dblite
.svn/
.DS_Store
*.swp
profile
DerivedData/
build/
GeneratedPluginRegistrant.h
GeneratedPluginRegistrant.m
.generated/
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
xcuserdata
*.moved-aside
*.pyc
*sync/
Icon?
.tags*
/Flutter/app.flx
/Flutter/app.zip
/Flutter/flutter_assets/
/Flutter/App.framework
/Flutter/Flutter.framework
/Flutter/Generated.xcconfig
/Flutter/Flutter.podspec
/ServiceDefinitions.json
Pods/
.symlinks/
================================================
FILE: ios/Flutter/AppFrameworkInfo.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>13.0</string>
</dict>
</plist>
================================================
FILE: ios/Flutter/Debug.xcconfig
================================================
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
================================================
FILE: ios/Flutter/Release.xcconfig
================================================
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
================================================
FILE: ios/Flutter/ephemeral/flutter_lldb_helper.py
================================================
#
# Generated file, do not edit.
#
import lldb
def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_dict):
"""Intercept NOTIFY_DEBUGGER_ABOUT_RX_PAGES and touch the pages."""
base = frame.register["x0"].GetValueAsAddress()
page_len = frame.register["x1"].GetValueAsUnsigned()
# Note: NOTIFY_DEBUGGER_ABOUT_RX_PAGES will check contents of the
# first page to see if handled it correctly. This makes diagnosing
# misconfiguration (e.g. missing breakpoint) easier.
data = bytearray(page_len)
data[0:8] = b'IHELPED!'
error = lldb.SBError()
frame.GetThread().GetProcess().WriteMemory(base, data, error)
if not error.Success():
print(f'Failed to write into {base}[+{page_len}]', error)
return
def __lldb_init_module(debugger: lldb.SBDebugger, _):
target = debugger.GetDummyTarget()
# Caveat: must use BreakpointCreateByRegEx here and not
# BreakpointCreateByName. For some reasons callback function does not
# get carried over from dummy target for the later.
bp = target.BreakpointCreateByRegex("^NOTIFY_DEBUGGER_ABOUT_RX_PAGES$")
bp.SetScriptCallbackFunction('{}.handle_new_rx_page'.format(__name__))
bp.SetAutoContinue(True)
print("-- LLDB integration loaded --")
================================================
FILE: ios/Flutter/ephemeral/flutter_lldbinit
================================================
#
# Generated file, do not edit.
#
command script import --relative-to-command-file flutter_lldb_helper.py
================================================
FILE: ios/Podfile
================================================
# Uncomment this line to define a global platform for your project
# platform :ios, '13.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end
================================================
FILE: ios/Runner/AppDelegate.swift
================================================
import UIKit
import Flutter
@main
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
func didInitializeImplicitFlutterEngine(
_ engineBridge: FlutterImplicitEngineBridge
) {
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
}
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
) -> Bool {
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
================================================
FILE: ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "40.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "60.jpg",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "58.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "87.jpg",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "80.jpg",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "logo-4.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "120.jpg",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "180.png",
"scale" : "3x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "logo2x-3.jpg",
"scale" : "1x"
},
{
"size" : "152x152",
"idiom" : "iphone",
"filename" : "152.jpg",
"scale" : "1x"
},
{
"size" : "167x167",
"idiom" : "iphone",
"filename" : "167.jpg",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "iphone",
"filename" : "76.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: ios/Runner/Assets.xcassets/Contents.json
================================================
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "iphone",
"scale" : "1x"
},
{
"idiom" : "iphone",
"filename" : "Default@3x-1.png",
"scale" : "2x"
},
{
"idiom" : "iphone",
"filename" : "Default@3x.png",
"scale" : "3x"
},
{
"idiom" : "iphone",
"subtype" : "retina4",
"scale" : "1x"
},
{
"idiom" : "iphone",
"filename" : "Default@3x-2.png",
"subtype" : "retina4",
"scale" : "2x"
},
{
"idiom" : "iphone",
"filename" : "Default@3x-4.png",
"subtype" : "retina4",
"scale" : "3x"
},
{
"idiom" : "iphone",
"subtype" : "736h",
"scale" : "3x"
},
{
"idiom" : "iphone",
"filename" : "Default@2x.png",
"subtype" : "667h",
"scale" : "2x"
},
{
"idiom" : "iphone",
"filename" : "Default@3x-3.png",
"subtype" : "2436h",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: ios/Runner/Base.lproj/LaunchScreen.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>
================================================
FILE: ios/Runner/Base.lproj/Main.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
================================================
FILE: ios/Runner/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>GSYGithubAppFlutter</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>GSYGithubAppFlutter</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>7.9.3</string> <key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSApplicationCategoryType</key>
<string></string>
<key>LSRequiresIPhoneOS</key> <true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
</dict>
<key>NSAppleMusicUsageDescription</key>
<string>Allow to get user music</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Allow to get user location in background</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>Allow to get user location</string>
<key>NSCalendarsUsageDescription</key>
<string>Allow to get user calendars</string>
<key>NSCameraUsageDescription</key>
<string>Allow user to scan QR codes using the camera</string>
<key>NSContactsUsageDescription</key>
<string>Allow to get user contacts</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Allow to get user location in background</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>Allow to get user location in background</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Allow to get user location</string>
<key>NSMotionUsageDescription</key>
<string>Allow to get user motion</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>Allow to get user speech recognition</string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>io.flutter.embedded_views_preview</key>
<true/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>
================================================
FILE: ios/Runner/Runner-Bridging-Header.h
================================================
#import "GeneratedPluginRegistrant.h"
================================================
FILE: ios/Runner/SceneDelegate.swift
================================================
import Flutter
class SceneDelegate: FlutterSceneDelegate {}
================================================
FILE: ios/Runner.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B1CF5E1D5F3697BA6D5E888 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC05E0EDBFF42659F21BDE4B /* Pods_Runner.framework */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
6B771FB42D6F90E700E9D56C /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B771FB32D6F90E700E9D56C /* SceneDelegate.swift */; };
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB31CF90195004384FC /* Generated.xcconfig */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
4B43CF9723BDED980094FB3A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4B51210C211F395A00E0C9B3 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 627667392E82CDFAE68C51AEBD0893F4;
remoteInfo = flutter_webview_plugin;
};
4B51211D211F395B00E0C9B3 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4B51210C211F395A00E0C9B3 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 6B534DBBA8DF3878886AC541E1F9B27F;
remoteInfo = connectivity;
};
4B51211F211F395B00E0C9B3 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4B51210C211F395A00E0C9B3 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = FE03FE86639A72DA4B3E03B276CF9787;
remoteInfo = device_info;
};
4B512125211F395B00E0C9B3 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4B51210C211F395A00E0C9B3 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = A01BD7926EF9CCFC9422AAE0154B021C;
remoteInfo = fluttertoast;
};
4B512127211F395B00E0C9B3 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4B51210C211F395A00E0C9B3 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 05CFA344FD05BDC7846987FC69E2968D;
remoteInfo = FMDB;
};
4B51212B211F395B00E0C9B3 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4B51210C211F395A00E0C9B3 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = F3ECC93A65C1AC7391162CC6DE987104;
remoteInfo = package_info;
};
4B51212D211F395B00E0C9B3 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4B51210C211F395A00E0C9B3 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 07082C9AE15BEF3C3E1B87A9E0002399;
remoteInfo = "Pods-Runner";
};
4B51212F211F395B00E0C9B3 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4B51210C211F395A00E0C9B3 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3980A755FA9D435ACB2BB8E062462E50;
remoteInfo = Reachability;
};
4B512131211F395B00E0C9B3 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4B51210C211F395A00E0C9B3 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = FA6117CD532A944FB87D5A01C425C052;
remoteInfo = share;
};
4B512133211F395B00E0C9B3 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4B51210C211F395A00E0C9B3 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 5AD4D046EA66405A678044C7D231DED9;
remoteInfo = shared_preferences;
};
4B512135211F395B00E0C9B3 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4B51210C211F395A00E0C9B3 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 395F12FD509BCF5B8F35276A25ED61E9;
remoteInfo = sqflite;
};
4B512137211F395B00E0C9B3 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4B51210C211F395A00E0C9B3 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 4B40ADA9AD61ADB08CA9739165A77AE5;
remoteInfo = url_launcher;
};
4B7052AA25787C7700723D25 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4B51210C211F395A00E0C9B3 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 55E0AFD333353D71ACC2207149E879D6;
remoteInfo = Toast;
};
4BDA3AD022744C9D0035B197 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4B51210C211F395A00E0C9B3 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 7571524E8933F347BDF8BA25D6AF7699;
remoteInfo = webview_flutter;
};
4BDB48EC21A2AEFF00E882C1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4B51210C211F395A00E0C9B3 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = F8B158E8230AA4D2DFAE7C847882628E;
remoteInfo = path_provider;
};
4BDB48EE21A2AEFF00E882C1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4B51210C211F395A00E0C9B3 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = FAE7273859BB129D96609B584B6F2535;
remoteInfo = permission_handler;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
4B51210C211F395A00E0C9B3 /* Pods.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Pods.xcodeproj; path = Pods/Pods.xcodeproj; sourceTree = "<group>"; };
4F13ED567330568565999636 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
593F42BD9F603A49DC922B8C /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
6B771FB32D6F90E700E9D56C /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
BC05E0EDBFF42659F21BDE4B /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
3B1CF5E1D5F3697BA6D5E888 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
4B51210D211F395A00E0C9B3 /* Products */ = {
isa = PBXGroup;
children = (
4B51211E211F395B00E0C9B3 /* connectivity.framework */,
4B512120211F395B00E0C9B3 /* device_info.framework */,
4B43CF9823BDED980094FB3A /* flutter_webview_plugin.framework */,
4B512126211F395B00E0C9B3 /* fluttertoast.framework */,
4B512128211F395B00E0C9B3 /* FMDB.framework */,
4B51212C211F395B00E0C9B3 /* package_info.framework */,
4BDB48ED21A2AEFF00E882C1 /* path_provider.framework */,
4BDB48EF21A2AEFF00E882C1 /* permission_handler.framework */,
4B51212E211F395B00E0C9B3 /* Pods_Runner.framework */,
4B512130211F395B00E0C9B3 /* Reachability.framework */,
4B512132211F395B00E0C9B3 /* share.framework */,
4B512134211F395B00E0C9B3 /* shared_preferences.framework */,
4B512136211F395B00E0C9B3 /* sqflite.framework */,
4B7052AB25787C7700723D25 /* Toast.framework */,
4B512138211F395B00E0C9B3 /* url_launcher.framework */,
4BDA3AD122744C9D0035B197 /* webview_flutter.framework */,
);
name = Products;
sourceTree = "<group>";
};
547008C5C91FE4BDD08FA652 /* Pods */ = {
isa = PBXGroup;
children = (
4B51210C211F395A00E0C9B3 /* Pods.xcodeproj */,
4F13ED567330568565999636 /* Pods-Runner.debug.xcconfig */,
593F42BD9F603A49DC922B8C /* Pods-Runner.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
547008C5C91FE4BDD08FA652 /* Pods */,
9C6818AD15B2DCD007E4DFD4 /* Frameworks */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
97C146F11CF9000F007C117D /* Supporting Files */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
6B771FB32D6F90E700E9D56C /* SceneDelegate.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
);
path = Runner;
sourceTree = "<group>";
};
97C146F11CF9000F007C117D /* Supporting Files */ = {
isa = PBXGroup;
children = (
);
name = "Supporting Files";
sourceTree = "<group>";
};
9C6818AD15B2DCD007E4DFD4 /* Frameworks */ = {
isa = PBXGroup;
children = (
BC05E0EDBFF42659F21BDE4B /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
E055B1E414155455BC367B8B /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
0CE87C2C48C36989195F6D5E /* [CP] Embed Pods Frameworks */,
24F7C8729A424760B0DE5489 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "The Chromium Authors";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
DevelopmentTeam = 8F3DX65RJ6;
LastSwiftMigration = 0910;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = 4B51210D211F395A00E0C9B3 /* Products */;
ProjectRef = 4B51210C211F395A00E0C9B3 /* Pods.xcodeproj */;
},
);
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
);
};
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
4B43CF9823BDED980094FB3A /* flutter_webview_plugin.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = flutter_webview_plugin.framework;
remoteRef = 4B43CF9723BDED980094FB3A /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
4B51211E211F395B00E0C9B3 /* connectivity.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = connectivity.framework;
remoteRef = 4B51211D211F395B00E0C9B3 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
4B512120211F395B00E0C9B3 /* device_info.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = device_info.framework;
remoteRef = 4B51211F211F395B00E0C9B3 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
4B512126211F395B00E0C9B3 /* fluttertoast.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = fluttertoast.framework;
remoteRef = 4B512125211F395B00E0C9B3 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
4B512128211F395B00E0C9B3 /* FMDB.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = FMDB.framework;
remoteRef = 4B512127211F395B00E0C9B3 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
4B51212C211F395B00E0C9B3 /* package_info.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = package_info.framework;
remoteRef = 4B51212B211F395B00E0C9B3 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
4B51212E211F395B00E0C9B3 /* Pods_Runner.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = Pods_Runner.framework;
remoteRef = 4B51212D211F395B00E0C9B3 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
4B512130211F395B00E0C9B3 /* Reachability.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = Reachability.framework;
remoteRef = 4B51212F211F395B00E0C9B3 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
4B512132211F395B00E0C9B3 /* share.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = share.framework;
remoteRef = 4B512131211F395B00E0C9B3 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
4B512134211F395B00E0C9B3 /* shared_preferences.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = shared_preferences.framework;
remoteRef = 4B512133211F395B00E0C9B3 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
4B512136211F395B00E0C9B3 /* sqflite.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = sqflite.framework;
remoteRef = 4B512135211F395B00E0C9B3 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
4B512138211F395B00E0C9B3 /* url_launcher.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = url_launcher.framework;
remoteRef = 4B512137211F395B00E0C9B3 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
4B7052AB25787C7700723D25 /* Toast.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = Toast.framework;
remoteRef = 4B7052AA25787C7700723D25 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
4BDA3AD122744C9D0035B197 /* webview_flutter.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = webview_flutter.framework;
remoteRef = 4BDA3AD022744C9D0035B197 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
4BDB48ED21A2AEFF00E882C1 /* path_provider.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = path_provider.framework;
remoteRef = 4BDB48EC21A2AEFF00E882C1 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
4BDB48EF21A2AEFF00E882C1 /* permission_handler.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = permission_handler.framework;
remoteRef = 4BDB48EE21A2AEFF00E882C1 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
0CE87C2C48C36989195F6D5E /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/OrderedSet/OrderedSet.framework",
"${BUILT_PRODUCTS_DIR}/Toast/Toast.framework",
"${BUILT_PRODUCTS_DIR}/connectivity_plus/connectivity_plus.framework",
"${BUILT_PRODUCTS_DIR}/device_info_plus/device_info_plus.framework",
"${BUILT_PRODUCTS_DIR}/flutter_inappwebview_ios/flutter_inappwebview_ios.framework",
"${BUILT_PRODUCTS_DIR}/fluttertoast/fluttertoast.framework",
"${BUILT_PRODUCTS_DIR}/package_info_plus/package_info_plus.framework",
"${BUILT_PRODUCTS_DIR}/path_provider_foundation/path_provider_foundation.framework",
"${BUILT_PRODUCTS_DIR}/rive_common/rive_common.framework",
"${BUILT_PRODUCTS_DIR}/share_plus/share_plus.framework",
"${BUILT_PRODUCTS_DIR}/shared_preferences_foundation/shared_preferences_foundation.framework",
"${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework",
"${BUILT_PRODUCTS_DIR}/url_launcher_ios/url_launcher_ios.framework",
"${BUILT_PRODUCTS_DIR}/webview_flutter_wkwebview/webview_flutter_wkwebview.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OrderedSet.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Toast.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity_plus.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/device_info_plus.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_inappwebview_ios.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fluttertoast.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/package_info_plus.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider_foundation.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/rive_common.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/share_plus.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences_foundation.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher_ios.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/webview_flutter_wkwebview.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
24F7C8729A424760B0DE5489 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/permission_handler_apple/permission_handler_apple_privacy.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/permission_handler_apple_privacy.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
showEnvVarsInLog = 0;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
E055B1E414155455BC367B8B /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
6B771FB42D6F90E700E9D56C /* SceneDelegate.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 35;
DEVELOPMENT_TEAM = 8F3DX65RJ6;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
"COCOAPODS=1",
"DISABLE_PUSH_NOTIFICATIONS=1",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.shuyu.GSYGithubAppBundle;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = 1;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 35;
DEVELOPMENT_TEAM = 8F3DX65RJ6;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
"COCOAPODS=1",
"DISABLE_PUSH_NOTIFICATIONS=1",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.shuyu.GSYGithubAppBundle;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = 1;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
================================================
FILE: ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>
================================================
FILE: ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
================================================
FILE: ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
================================================
FILE: ios/Runner.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
================================================
FILE: ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
================================================
FILE: l10n.yaml
================================================
arb-dir: lib/common/localization/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
================================================
FILE: lib/app.dart
================================================
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:gsy_github_app_flutter/common/event/http_error_event.dart';
import 'package:gsy_github_app_flutter/common/event/index.dart';
import 'package:gsy_github_app_flutter/common/localization/extension.dart';
import 'package:gsy_github_app_flutter/common/localization/l10n/app_localizations.dart';
import 'package:gsy_github_app_flutter/common/net/code.dart';
import 'package:gsy_github_app_flutter/common/toast.dart';
import 'package:gsy_github_app_flutter/model/user.dart';
import 'package:gsy_github_app_flutter/page/debug/debug_label.dart';
import 'package:gsy_github_app_flutter/page/home/home_page.dart';
import 'package:gsy_github_app_flutter/page/login/login_page.dart';
import 'package:gsy_github_app_flutter/page/photoview_page.dart';
import 'package:gsy_github_app_flutter/page/welcome_page.dart';
import 'package:gsy_github_app_flutter/provider/app_state_provider.dart';
import 'package:gsy_github_app_flutter/redux/gsy_state.dart';
import 'package:redux/redux.dart';
import 'common/utils/navigator_utils.dart';
class FlutterReduxApp extends StatefulWidget {
const FlutterReduxApp({super.key});
@override
_FlutterReduxAppState createState() => _FlutterReduxAppState();
}
class _FlutterReduxAppState extends State<FlutterReduxApp>
with HttpErrorListener {
/// 创建Store,引用 GSYState 中的 appReducer 实现 Reducer 方法
/// initialState 初始化 State
final store = Store<GSYState>(
appReducer,
///拦截器
middleware: middleware,
///初始化数据
initialState: GSYState(
userInfo: User.empty(),
login: false,
),
);
NavigatorObserver navigatorObserver = NavigatorObserver();
// Helper method to check if the locale is supported
Locale _checkSupportedLocale(Locale locale) {
// Define the supported locales
const supportedLocales = AppLocalizations.supportedLocales;
// Check if the requested locale is supported
for (final supportedLocale in supportedLocales) {
if (supportedLocale.languageCode == locale.languageCode) {
return locale;
}
}
// Fall back to English if the locale is not supported
return const Locale('en', 'US');
}
@override
void initState() {
super.initState();
Future.delayed(const Duration(seconds: 0), () {
/// 通过 with NavigatorObserver ,在这里可以获取可以往上获取到
/// MaterialApp 和 StoreProvider 的 context
/// 还可以获取到 navigator;
/// 比如在这里增加一个监听,如果 token 失效就退回登陆页。
navigatorObserver.navigator!.context;
navigatorObserver.navigator;
});
}
@override
Widget build(BuildContext context) {
/// 使用 riverpod 做部分状态共享
/// 这里是为了展示使用 riverpod 的能力所以使用了多种状态管理
return UncontrolledProviderScope(
container: globalContainer,
child: Consumer(
builder: (BuildContext context, WidgetRef ref, Widget? child) {
final (greyApp, appLocale, themeData) = ref.watch(appStateProvider);
// Make sure the locale is supported or fall back to a default one
final effectiveLocale = _checkSupportedLocale(appLocale);
/// 使用 flutter_redux 做部分状态共享
/// 通过 StoreProvider 应用 store
/// 这里是为了展示使用 flutter_redux 的能力所以使用了多种状态管理
return StoreProvider(
store: store,
child: StoreBuilder<GSYState>(builder: (context, store) {
Widget app = MaterialApp(
navigatorKey: navKey,
///多语言实现代理
localizationsDelegates:
AppLocalizations.localizationsDelegates,
supportedLocales: [effectiveLocale],
locale: effectiveLocale,
theme: themeData,
navigatorObservers: [navigatorObserver],
///命名式路由
/// "/" 和 MaterialApp 的 home 参数一个效果
///⚠️ 这里的 name调用,里面 pageContainer 方法有一个 MediaQuery.of(context).copyWith(textScaleFactor: 1),
///⚠️ 而这里的 context 用的是 WidgetBuilder 的 context ~
///⚠️ 所以 MediaQuery.of(context) 这个 InheritedWidget 就把这个 context “登记”到了 Element 的内部静态 _map 里。
///⚠️ 所以键盘弹出来的时候,触发了顶层的 MediaQueryData 发生变化,自然就触发了“登记”过的 context 的变化
///⚠️ 比如 LoginPage 、HomePage ····
///⚠️ 所以比如你在 搜索页面 键盘弹出时,下面的 HomePage.sName 对应的 WidgetBuilder 会被触发
///⚠️ 这个是我故意的,如果不需要,可以去掉 pageContainer 或者不要用这里的 context
routes: {
WelcomePage.sName: (context) {
DebugLabel.showDebugLabel(context);
return const WelcomePage();
},
HomePage.sName: (context) {
return NavigatorUtils.pageContainer(
const HomePage(), context);
},
LoginPage.sName: (context) {
return NavigatorUtils.pageContainer(
const LoginPage(), context);
},
///使用 ModalRoute.of(context).settings.arguments; 获取参数
PhotoViewPage.sName: (context) {
return const PhotoViewPage();
},
});
if (greyApp) {
///mode one
app = ColorFiltered(
colorFilter: const ColorFilter.mode(
Colors.grey, BlendMode.saturation),
child: app);
///mode two
// app = ColorFiltered(
// colorFilter: greyscale,
// child: app);
}
return app;
}),
);
},
),
);
}
}
mixin HttpErrorListener on State<FlutterReduxApp> {
StreamSubscription? stream;
GlobalKey<NavigatorState> navKey = GlobalKey();
@override
void initState() {
super.initState();
///Stream演示event bus
stream = eventBus.on<HttpErrorEvent>().listen((event) {
errorHandleFunction(event.code, event.message);
});
}
@override
void dispose() {
super.dispose();
if (stream != null) {
stream!.cancel();
stream = null;
}
}
///网络错误提醒
errorHandleFunction(int? code, message) {
var context = navKey.currentContext!;
switch (code) {
case Code.NETWORK_ERROR:
showToast(context.l10n.network_error);
break;
case 401:
showToast(context.l10n.network_error_401);
break;
case 403:
showToast(context.l10n.network_error_403);
break;
case 404:
showToast(context.l10n.network_error_404);
break;
case 422:
showToast(context.l10n.network_error_422);
break;
case Code.NETWORK_TIMEOUT:
//超时
showToast(context.l10n.network_error_timeout);
break;
case Code.GITHUB_API_REFUSED:
//Github API 异常
showToast(context.l10n.github_refused);
break;
default:
showToast("${context.l10n.network_error_unknown} $message");
break;
}
}
}
================================================
FILE: lib/common/config/config.dart
================================================
class Config {
// Private constructor to prevent instantiation
Config._();
static bool? DEBUG = true;
static const PAGE_SIZE = 20;
/// //////////////////////////////////////常量////////////////////////////////////// ///
stat
gitextract_kfzn5wba/
├── .fvmrc
├── .github/
│ ├── FUNDING.yml
│ └── workflows/
│ └── ci.yml
├── .gitignore
├── .metadata
├── .vscode/
│ └── settings.json
├── AGENTS.md
├── LICENSE
├── README.md
├── README_EN.md
├── RECORD.md
├── UISCENE_PLUGIN_RISK.md
├── VERSION.md
├── analysis_options.yaml
├── android/
│ ├── .gitignore
│ ├── app/
│ │ ├── build.gradle
│ │ ├── exported.gradle
│ │ └── src/
│ │ └── main/
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin/
│ │ │ └── com/
│ │ │ └── shuyu/
│ │ │ └── gsygithub/
│ │ │ └── gsygithubappflutter/
│ │ │ ├── MainActivity.kt
│ │ │ └── UpdateAlbumPlugin.kt
│ │ └── res/
│ │ ├── drawable/
│ │ │ ├── launch_background.xml
│ │ │ └── normal_background.xml
│ │ └── values/
│ │ └── styles.xml
│ ├── build.gradle
│ ├── gradle/
│ │ └── wrapper/
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
│ ├── gradle.properties
│ ├── gradlew
│ ├── gradlew.bat
│ ├── gsygithubapp-debug.jks
│ └── settings.gradle
├── devtools_options.yaml
├── docs/
│ ├── 00-overview/
│ │ └── project-map.md
│ ├── 01-architecture/
│ │ ├── app-layering.md
│ │ └── state-management-matrix.md
│ ├── 02-features/
│ │ ├── debug.md
│ │ ├── dynamic.md
│ │ ├── home.md
│ │ ├── issue.md
│ │ ├── login.md
│ │ ├── notify.md
│ │ ├── push.md
│ │ ├── release.md
│ │ ├── repos.md
│ │ ├── search.md
│ │ ├── trend.md
│ │ └── user.md
│ ├── 03-runbooks/
│ │ └── local-setup.md
│ ├── 04-quality/
│ │ ├── smoke-matrix.md
│ │ └── test-strategy.md
│ ├── 05-ai/
│ │ ├── agent-guide.md
│ │ ├── feature-playbooks/
│ │ │ ├── debug-change.md
│ │ │ ├── dynamic-change.md
│ │ │ ├── home-change.md
│ │ │ ├── issue-change.md
│ │ │ ├── notify-change.md
│ │ │ ├── push-change.md
│ │ │ ├── release-change.md
│ │ │ ├── repos-change.md
│ │ │ ├── search-change.md
│ │ │ ├── trend-change.md
│ │ │ └── user-change.md
│ │ ├── prompts/
│ │ │ ├── author-handoff.md
│ │ │ └── reviewer-system.md
│ │ ├── review-harness.md
│ │ └── task-playbooks/
│ │ ├── add-api.md
│ │ ├── add-page.md
│ │ ├── fix-bug.md
│ │ └── refactor-state.md
│ ├── 06-decisions/
│ │ ├── ADR-0001-状态管理收敛策略.md
│ │ ├── ADR-0002-新增功能默认状态方案.md
│ │ └── README.md
│ ├── CONTRIBUTING_AI.md
│ └── README.md
├── fastlane/
│ └── metadata/
│ └── android/
│ └── en-US/
│ ├── full_description.txt
│ └── short_description.txt
├── ios/
│ ├── .gitignore
│ ├── Flutter/
│ │ ├── AppFrameworkInfo.plist
│ │ ├── Debug.xcconfig
│ │ ├── Release.xcconfig
│ │ └── ephemeral/
│ │ ├── flutter_lldb_helper.py
│ │ └── flutter_lldbinit
│ ├── Podfile
│ ├── Runner/
│ │ ├── AppDelegate.swift
│ │ ├── Assets.xcassets/
│ │ │ ├── AppIcon.appiconset/
│ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ └── LaunchImage.imageset/
│ │ │ └── Contents.json
│ │ ├── Base.lproj/
│ │ │ ├── LaunchScreen.storyboard
│ │ │ └── Main.storyboard
│ │ ├── Info.plist
│ │ ├── Runner-Bridging-Header.h
│ │ └── SceneDelegate.swift
│ ├── Runner.xcodeproj/
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace/
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata/
│ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcshareddata/
│ │ └── xcschemes/
│ │ └── Runner.xcscheme
│ └── Runner.xcworkspace/
│ ├── contents.xcworkspacedata
│ └── xcshareddata/
│ └── IDEWorkspaceChecks.plist
├── l10n.yaml
├── lib/
│ ├── app.dart
│ ├── common/
│ │ ├── config/
│ │ │ └── config.dart
│ │ ├── event/
│ │ │ ├── event_bus.dart
│ │ │ ├── http_error_event.dart
│ │ │ └── index.dart
│ │ ├── local/
│ │ │ └── local_storage.dart
│ │ ├── localization/
│ │ │ ├── extension.dart
│ │ │ └── l10n/
│ │ │ ├── app_en.arb
│ │ │ ├── app_ja.arb
│ │ │ ├── app_ko.arb
│ │ │ ├── app_localizations.dart
│ │ │ ├── app_localizations_en.dart
│ │ │ ├── app_localizations_ja.dart
│ │ │ ├── app_localizations_ko.dart
│ │ │ ├── app_localizations_zh.dart
│ │ │ └── app_zh.arb
│ │ ├── logger.dart
│ │ ├── net/
│ │ │ ├── AGENTS.md
│ │ │ ├── address.dart
│ │ │ ├── api.dart
│ │ │ ├── code.dart
│ │ │ ├── graphql/
│ │ │ │ ├── client.dart
│ │ │ │ ├── repositories.dart
│ │ │ │ └── users.dart
│ │ │ ├── interceptors/
│ │ │ │ ├── error_interceptor.dart
│ │ │ │ ├── header_interceptor.dart
│ │ │ │ ├── log_interceptor.dart
│ │ │ │ ├── response_interceptor.dart
│ │ │ │ └── token_interceptor.dart
│ │ │ ├── result_data.dart
│ │ │ ├── transformer.dart
│ │ │ ├── transformer.g.dart
│ │ │ └── trending/
│ │ │ └── github_trending.dart
│ │ ├── repositories/
│ │ │ ├── data_result.dart
│ │ │ ├── event_repository.dart
│ │ │ ├── issue_repository.dart
│ │ │ ├── repos_repository.dart
│ │ │ └── user_repository.dart
│ │ ├── router/
│ │ │ └── anima_route.dart
│ │ ├── style/
│ │ │ └── gsy_style.dart
│ │ ├── toast.dart
│ │ └── utils/
│ │ ├── code_utils.dart
│ │ ├── common_utils.dart
│ │ ├── event_utils.dart
│ │ ├── html_utils.dart
│ │ └── navigator_utils.dart
│ ├── db/
│ │ ├── provider/
│ │ │ ├── event/
│ │ │ │ ├── received_event_db_provider.dart
│ │ │ │ └── user_event_db_provider.dart
│ │ │ ├── issue/
│ │ │ │ ├── issue_comment_db_provider.dart
│ │ │ │ └── issue_detail_db_provider.dart
│ │ │ ├── repos/
│ │ │ │ ├── read_history_db_provider.dart
│ │ │ │ ├── repository_branch_db_provider.dart
│ │ │ │ ├── repository_commitInfo_detail_db_provider.dart
│ │ │ │ ├── repository_commits_db_provider.dart
│ │ │ │ ├── repository_detail_db_provider.dart
│ │ │ │ ├── repository_detail_readme_db_provider.dart
│ │ │ │ ├── repository_event_db_provider.dart
│ │ │ │ ├── repository_fork_db_provider.dart
│ │ │ │ ├── repository_issue_db_provider.dart
│ │ │ │ ├── repository_pulse_db_provider.dart
│ │ │ │ ├── repository_star_db_provider.dart
│ │ │ │ ├── repository_watcher_db_provider.dart
│ │ │ │ └── trend_repository_db_provider.dart
│ │ │ └── user/
│ │ │ ├── org_member_db_provider.dart
│ │ │ ├── user_followed_db_provider.dart
│ │ │ ├── user_follower_db_provider.dart
│ │ │ ├── user_orgs_db_provider.dart
│ │ │ ├── user_repos_db_provider.dart
│ │ │ ├── user_stared_db_provider.dart
│ │ │ └── userinfo_db_provider.dart
│ │ ├── sql_manager.dart
│ │ └── sql_provider.dart
│ ├── env/
│ │ ├── AGENTS.md
│ │ ├── config_wrapper.dart
│ │ ├── dev.dart
│ │ ├── dev.g.dart
│ │ ├── env_config.dart
│ │ ├── env_config.g.dart
│ │ ├── env_json_dev.json
│ │ ├── env_json_prod.json
│ │ ├── prod.dart
│ │ └── prod.g.dart
│ ├── main.dart
│ ├── main_prod.dart
│ ├── model/
│ │ ├── branch.dart
│ │ ├── branch.g.dart
│ │ ├── commitFile.dart
│ │ ├── commitFile.g.dart
│ │ ├── commit_comment.dart
│ │ ├── commit_comment.g.dart
│ │ ├── commit_git_info.dart
│ │ ├── commit_git_info.g.dart
│ │ ├── commit_git_user.dart
│ │ ├── commit_git_user.g.dart
│ │ ├── commit_stats.dart
│ │ ├── commit_stats.g.dart
│ │ ├── commits_comparison.dart
│ │ ├── commits_comparison.g.dart
│ │ ├── common_list_datatype.dart
│ │ ├── download_source.dart
│ │ ├── download_source.g.dart
│ │ ├── event.dart
│ │ ├── event.g.dart
│ │ ├── event_payload.dart
│ │ ├── event_payload.g.dart
│ │ ├── file_model.dart
│ │ ├── file_model.g.dart
│ │ ├── issue.dart
│ │ ├── issue.g.dart
│ │ ├── issue_event.dart
│ │ ├── issue_event.g.dart
│ │ ├── license.dart
│ │ ├── license.g.dart
│ │ ├── notification.dart
│ │ ├── notification.g.dart
│ │ ├── notification_subject.dart
│ │ ├── notification_subject.g.dart
│ │ ├── push_commit.dart
│ │ ├── push_commit.g.dart
│ │ ├── push_event_commit.dart
│ │ ├── push_event_commit.g.dart
│ │ ├── release.dart
│ │ ├── release.g.dart
│ │ ├── release_asset.dart
│ │ ├── release_asset.g.dart
│ │ ├── repo_commit.dart
│ │ ├── repo_commit.g.dart
│ │ ├── repository.dart
│ │ ├── repository.g.dart
│ │ ├── repository_permissions.dart
│ │ ├── repository_permissions.g.dart
│ │ ├── repository_ql.dart
│ │ ├── search_user_ql.dart
│ │ ├── template.dart
│ │ ├── template.g.dart
│ │ ├── trending_repo_model.dart
│ │ ├── trending_repo_model.g.dart
│ │ ├── user.dart
│ │ ├── user.g.dart
│ │ ├── user_org.dart
│ │ └── user_org.g.dart
│ ├── page/
│ │ ├── AGENTS.md
│ │ ├── code_detail_page_web.dart
│ │ ├── common_list_page.dart
│ │ ├── debug/
│ │ │ ├── debug_data_page.dart
│ │ │ └── debug_label.dart
│ │ ├── dynamic/
│ │ │ ├── dynamic_bloc.dart
│ │ │ └── dynamic_page.dart
│ │ ├── error_page.dart
│ │ ├── gsy_webview.dart
│ │ ├── home/
│ │ │ ├── home_page.dart
│ │ │ └── widget/
│ │ │ └── home_drawer.dart
│ │ ├── honor_list_page.dart
│ │ ├── issue/
│ │ │ ├── issue_detail_page.dart
│ │ │ ├── issue_edit_dIalog.dart
│ │ │ └── widget/
│ │ │ ├── issue_header_item.dart
│ │ │ └── issue_item.dart
│ │ ├── login/
│ │ │ ├── login_page.dart
│ │ │ └── login_webview.dart
│ │ ├── my_page.dart
│ │ ├── notify/
│ │ │ └── notify_page.dart
│ │ ├── photoview_page.dart
│ │ ├── push/
│ │ │ ├── push_detail_page.dart
│ │ │ └── widget/
│ │ │ ├── push_coed_item.dart
│ │ │ └── push_header.dart
│ │ ├── release/
│ │ │ ├── release_page.dart
│ │ │ └── widget/
│ │ │ └── release_item.dart
│ │ ├── repos/
│ │ │ ├── provider/
│ │ │ │ ├── repos_detail_provider.dart
│ │ │ │ └── repos_network_provider.dart
│ │ │ ├── repository_detail_issue_list_page.dart
│ │ │ ├── repository_detail_page.dart
│ │ │ ├── repository_detail_readme_page.dart
│ │ │ ├── repository_file_list_page.dart
│ │ │ ├── repostory_detail_info_page.dart
│ │ │ └── widget/
│ │ │ ├── repos_header_item.dart
│ │ │ └── repos_item.dart
│ │ ├── search/
│ │ │ ├── search_bloc.dart
│ │ │ ├── search_page.dart
│ │ │ └── widget/
│ │ │ ├── gsy_search_drawer.dart
│ │ │ └── gsy_search_input_widget.dart
│ │ ├── trend/
│ │ │ ├── trend_page.dart
│ │ │ ├── trend_provider.dart
│ │ │ ├── trend_provider.g.dart
│ │ │ ├── trend_user_page.dart
│ │ │ ├── trend_user_provider.dart
│ │ │ └── trend_user_provider.g.dart
│ │ ├── user/
│ │ │ ├── base_person_provider.dart
│ │ │ ├── base_person_provider.g.dart
│ │ │ ├── base_person_state.dart
│ │ │ ├── person_page.dart
│ │ │ └── widget/
│ │ │ ├── user_header.dart
│ │ │ └── user_item.dart
│ │ ├── user_profile_page.dart
│ │ └── welcome_page.dart
│ ├── provider/
│ │ ├── app_state_provider.dart
│ │ └── app_state_provider.g.dart
│ ├── redux/
│ │ ├── gsy_state.dart
│ │ ├── login_redux.dart
│ │ ├── middleware/
│ │ │ ├── combine_epics.dart
│ │ │ ├── epic.dart
│ │ │ ├── epic_middleware.dart
│ │ │ └── epic_store.dart
│ │ └── user_redux.dart
│ ├── test/
│ │ ├── demo_app.dart
│ │ ├── demo_appbar.dart
│ │ ├── demo_bloc_page.dart
│ │ ├── demo_db.dart
│ │ ├── demo_item.dart
│ │ ├── demo_mixins.dart
│ │ ├── demo_page.dart
│ │ ├── demo_tab_page.dart
│ │ ├── demo_text_field_page.dart
│ │ ├── demo_user_store.dart
│ │ └── demo_widget.dart
│ └── widget/
│ ├── anima/
│ │ └── curves_bezier.dart
│ ├── animated_background.dart
│ ├── diff_scale_text.dart
│ ├── flutter_json_widget.dart
│ ├── gsy_bottom_action_bar.dart
│ ├── gsy_card_item.dart
│ ├── gsy_common_option_widget.dart
│ ├── gsy_event_item.dart
│ ├── gsy_flex_button.dart
│ ├── gsy_icon_text.dart
│ ├── gsy_input_widget.dart
│ ├── gsy_select_item_widget.dart
│ ├── gsy_tabbar_widget.dart
│ ├── gsy_tabs.dart
│ ├── gsy_title_bar.dart
│ ├── gsy_user_icon_widget.dart
│ ├── markdown/
│ │ ├── gsy_markdown_widget.dart
│ │ └── syntax_high_lighter.dart
│ ├── menu/
│ │ ├── flutter_radial_menu.dart
│ │ └── src/
│ │ ├── arc_progress_indicator.dart
│ │ ├── radial_menu.dart
│ │ ├── radial_menu_button.dart
│ │ ├── radial_menu_center_button.dart
│ │ └── radial_menu_item.dart
│ ├── mole_widget.dart
│ ├── never_overscroll_indicator.dart
│ ├── only_share_widget.dart
│ ├── particle/
│ │ ├── particle_model.dart
│ │ ├── particle_painter.dart
│ │ └── particle_widget.dart
│ ├── pull/
│ │ ├── custom_bouncing_scroll_physics.dart
│ │ ├── gsy_flare_mutli_pull_controller.dart
│ │ ├── gsy_flare_pull_controller.dart
│ │ ├── gsy_pull_load_widget.dart
│ │ ├── gsy_pull_new_load_widget.dart
│ │ ├── gsy_refresh_sliver.dart
│ │ └── nested/
│ │ ├── gsy_nested_pull_load_widget.dart
│ │ ├── gsy_sliver_header_delegate.dart
│ │ └── nested_refresh.dart
│ └── state/
│ └── gsy_list_state.dart
├── pubspec.yaml
├── static/
│ ├── file/
│ │ ├── Space-Demo.flr
│ │ ├── flare_flutter_logo_.flr
│ │ ├── launch.riv
│ │ ├── loading_world_now.flr
│ │ ├── rejection.json
│ │ ├── rejection2.json
│ │ ├── search.json
│ │ └── user.json
│ └── font/
│ ├── demo.css
│ ├── demo_fontclass.html
│ ├── demo_symbol.html
│ ├── demo_unicode.html
│ ├── iconfont.css
│ └── iconfont.js
└── tool/
└── ai/
└── build_review_bundle.ps1
SYMBOL INDEX (1257 symbols across 235 files)
FILE: ios/Flutter/ephemeral/flutter_lldb_helper.py
function handle_new_rx_page (line 7) | def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_d...
function __lldb_init_module (line 24) | def __lldb_init_module(debugger: lldb.SBDebugger, _):
FILE: lib/app.dart
class FlutterReduxApp (line 24) | class FlutterReduxApp extends StatefulWidget {
method createState (line 28) | _FlutterReduxAppState createState()
class _FlutterReduxAppState (line 31) | class _FlutterReduxAppState extends State<FlutterReduxApp>
method _checkSupportedLocale (line 51) | Locale _checkSupportedLocale(Locale locale)
method initState (line 67) | void initState()
method build (line 80) | Widget build(BuildContext context)
function initState (line 166) | void initState()
function dispose (line 176) | void dispose()
FILE: lib/common/config/config.dart
class Config (line 1) | class Config {
FILE: lib/common/event/event_bus.dart
class EventBus (line 13) | class EventBus {
method on (line 50) | Stream<T> on<T>()
method fire (line 60) | void fire(event)
method destroy (line 66) | void destroy()
FILE: lib/common/event/http_error_event.dart
class HttpErrorEvent (line 5) | class HttpErrorEvent {
FILE: lib/common/local/local_storage.dart
class LocalStorage (line 4) | class LocalStorage {
method save (line 6) | save(String key, value)
method get (line 11) | get(String key)
method remove (line 16) | remove(String key)
FILE: lib/common/localization/l10n/app_localizations.dart
class AppLocalizations (line 66) | abstract class AppLocalizations {
method of (line 72) | AppLocalizations? of(BuildContext context)
class _AppLocalizationsDelegate (line 928) | class _AppLocalizationsDelegate
method load (line 933) | Future<AppLocalizations> load(Locale locale)
method isSupported (line 938) | bool isSupported(Locale locale)
method shouldReload (line 942) | bool shouldReload(_AppLocalizationsDelegate old)
function lookupAppLocalizations (line 945) | AppLocalizations lookupAppLocalizations(Locale locale)
FILE: lib/common/localization/l10n/app_localizations_en.dart
class AppLocalizationsEn (line 8) | class AppLocalizationsEn extends AppLocalizations {
FILE: lib/common/localization/l10n/app_localizations_ja.dart
class AppLocalizationsJa (line 8) | class AppLocalizationsJa extends AppLocalizations {
FILE: lib/common/localization/l10n/app_localizations_ko.dart
class AppLocalizationsKo (line 8) | class AppLocalizationsKo extends AppLocalizations {
FILE: lib/common/localization/l10n/app_localizations_zh.dart
class AppLocalizationsZh (line 8) | class AppLocalizationsZh extends AppLocalizations {
FILE: lib/common/logger.dart
function printLog (line 20) | printLog(Object msg)
FILE: lib/common/net/address.dart
class Address (line 5) | class Address {
method getAuthorization (line 12) | getAuthorization()
method search (line 17) | search(q, sort, order, type, page, [pageSize = Config.PAGE_SIZE])
method searchTopic (line 29) | searchTopic(topic)
method userRepos (line 34) | userRepos(userName, sort)
method getReposDetail (line 40) | getReposDetail(reposOwner, reposName)
method getReposEvent (line 45) | getReposEvent(reposOwner, reposName)
method getReposForks (line 50) | getReposForks(reposOwner, reposName)
method getReposStar (line 55) | getReposStar(reposOwner, reposName)
method getReposWatcher (line 60) | getReposWatcher(reposOwner, reposName)
method getReposCommits (line 65) | getReposCommits(reposOwner, reposName)
method getReposCommitsInfo (line 70) | getReposCommitsInfo(reposOwner, reposName, sha)
method getReposCompare (line 75) | getReposCompare(reposOwner, reposName, base, head)
method getReposIssue (line 80) | getReposIssue(String reposOwner, String reposName, state, sort, direct...
method getReposRelease (line 88) | getReposRelease(reposOwner, reposName)
method getReposTag (line 93) | getReposTag(reposOwner, reposName)
method getReposContributors (line 98) | getReposContributors(reposOwner, reposName)
method getIssueComment (line 103) | getIssueComment(reposOwner, reposName, issueNumber)
method getIssueInfo (line 108) | getIssueInfo(reposOwner, reposName, issueNumber)
method addIssueComment (line 114) | addIssueComment(reposOwner, reposName, issueNumber)
method editIssue (line 119) | editIssue(reposOwner, reposName, issueNumber)
method lockIssue (line 124) | lockIssue(reposOwner, reposName, issueNumber)
method createIssue (line 129) | createIssue(reposOwner, reposName)
method repositoryIssueSearch (line 134) | repositoryIssueSearch(q)
method editComment (line 139) | editComment(reposOwner, reposName, commentId)
method myStar (line 144) | myStar(sort)
method userStar (line 151) | userStar(userName, sort)
method resolveStarRepos (line 158) | resolveStarRepos(reposOwner, repos)
method resolveWatcherRepos (line 163) | resolveWatcherRepos(reposOwner, repos)
method reposData (line 168) | reposData(reposOwner, repos)
method reposDataDir (line 173) | reposDataDir(reposOwner, repos, path, [branch = 'master'])
method readmeFile (line 178) | readmeFile(reposNameFullName, curBranch)
method getMyUserInfo (line 186) | getMyUserInfo()
method getUserInfo (line 191) | getUserInfo(userName)
method doFollow (line 196) | doFollow(name)
method getUserFollow (line 201) | getUserFollow(userName)
method getMyFollower (line 206) | getMyFollower()
method getUserFollower (line 211) | getUserFollower(userName)
method createFork (line 216) | createFork(reposOwner, reposName)
method getbranches (line 221) | getbranches(reposOwner, reposName)
method getForker (line 226) | getForker(reposOwner, reposName, sort)
method getReadme (line 232) | getReadme(reposOwner, reposName)
method getEventReceived (line 237) | getEventReceived(userName)
method getEvent (line 242) | getEvent(userName)
method getMember (line 247) | getMember(orgs)
method getUserOrgs (line 252) | getUserOrgs(userName)
method getNotifation (line 257) | getNotifation(all, participating)
method setNotificationAsRead (line 268) | setNotificationAsRead(threadId)
method setAllNotificationAsRead (line 273) | setAllNotificationAsRead()
method getOAuthUrl (line 277) | getOAuthUrl()
method trending (line 285) | trending(since, languageType)
method trendingApi (line 293) | trendingApi(since, languageType)
method getPageParams (line 301) | getPageParams(tab, page, [pageSize = Config.PAGE_SIZE])
FILE: lib/common/net/api.dart
class HttpManager (line 17) | class HttpManager {
method netFetch (line 43) | Future<ResultData?> netFetch(
method resultError (line 58) | resultError(DioException e)
FILE: lib/common/net/code.dart
class Code (line 5) | class Code {
method errorHandleFunction (line 20) | errorHandleFunction(code, message, noTip)
FILE: lib/common/net/graphql/client.dart
function _client (line 6) | Future<GraphQLClient> _client(token)
function initClient (line 26) | initClient(token)
function releaseClient (line 30) | releaseClient()
function getRepository (line 34) | Future<QueryResult>? getRepository(String owner, String? name)
function getTrendUser (line 45) | Future<QueryResult>? getTrendUser(String location, {String? cursor})
FILE: lib/common/net/interceptors/error_interceptor.dart
class ErrorInterceptors (line 12) | class ErrorInterceptors extends InterceptorsWrapper {
FILE: lib/common/net/interceptors/header_interceptor.dart
class HeaderInterceptors (line 6) | class HeaderInterceptors extends InterceptorsWrapper {
FILE: lib/common/net/interceptors/log_interceptor.dart
class LogsInterceptors (line 10) | class LogsInterceptors extends InterceptorsWrapper {
method addLogic (line 100) | addLogic(List list, data)
FILE: lib/common/net/interceptors/response_interceptor.dart
class ResponseInterceptors (line 9) | class ResponseInterceptors extends InterceptorsWrapper {
FILE: lib/common/net/interceptors/token_interceptor.dart
class TokenInterceptors (line 10) | class TokenInterceptors extends InterceptorsWrapper {
FILE: lib/common/net/result_data.dart
class ResultData (line 4) | class ResultData {
FILE: lib/common/net/trending/github_trending.dart
class GitHubTrending (line 12) | class GitHubTrending {
class TrendingUtil (line 42) | class TrendingUtil {
method htmlToRepo (line 43) | htmlToRepo(String responseData)
method parseContentWithNote (line 73) | parseContentWithNote(htmlStr, startFlag, endFlag)
method parseRepoBaseInfo (line 86) | parseRepoBaseInfo(repo, htmlBaseInfo)
method parseRepoLabelWithTag (line 114) | parseRepoLabelWithTag(repo, noteContent, tag)
method parseRepoLang (line 133) | parseRepoLang(repo, metaNoteContent)
method parseRepoContributors (line 139) | parseRepoContributors(TrendingRepoModel repo, htmlContributors)
method trim (line 156) | trim(text)
FILE: lib/common/repositories/data_result.dart
class DataResult (line 1) | class DataResult {
FILE: lib/common/repositories/event_repository.dart
class EventRepository (line 10) | class EventRepository {
method getEventReceived (line 11) | getEventReceived(String? userName,
method next (line 18) | next()
method getEventRequest (line 53) | getEventRequest(String userName, {page = 0, bool needDb = false})
method next (line 55) | next()
FILE: lib/common/repositories/issue_repository.dart
class IssueRepository (line 16) | class IssueRepository {
method getRepositoryIssueRequest (line 24) | getRepositoryIssueRequest(String userName, String repository, state,
method next (line 30) | next()
method searchRepositoryRequest (line 77) | searchRepositoryRequest(q, name, reposName, state, {page = 1})
method getIssueInfoRequest (line 103) | getIssueInfoRequest(userName, repository, number, {needDb = true})
method next (line 108) | next()
method getIssueCommentRequest (line 135) | getIssueCommentRequest(userName, repository, number,
method next (line 140) | next()
method addIssueCommentRequest (line 176) | addIssueCommentRequest(userName, repository, number, comment)
method editIssueRequest (line 191) | editIssueRequest(userName, repository, number, issue)
method lockIssueRequest (line 206) | lockIssueRequest(userName, repository, number, locked)
method createIssueRequest (line 222) | createIssueRequest(userName, repository, issue)
method editCommentRequest (line 237) | editCommentRequest(
method deleteCommentRequest (line 253) | deleteCommentRequest(userName, repository, number, commentId)
FILE: lib/common/repositories/repos_repository.dart
class ReposRepository (line 46) | class ReposRepository {
method getTrendRequest (line 51) | getTrendRequest(
method next (line 56) | next()
method getRepositoryDetailRequest (line 114) | getRepositoryDetailRequest(String userName, String reposName, branch,
method next (line 119) | next()
method getRepositoryEventRequest (line 149) | getRepositoryEventRequest(String userName, String reposName,
method next (line 154) | next()
method getRepositoryStatusRequest (line 188) | getRepositoryStatusRequest(String userName, String reposName)
method getReposCommitsRequest (line 198) | getReposCommitsRequest(String userName, String reposName,
method next (line 204) | next()
method getReposFileDirRequest (line 240) | getReposFileDirRequest(String userName, String reposName,
method doRepositoryStarRequest (line 280) | Future<DataResult> doRepositoryStarRequest(
method doRepositoryWatchRequest (line 291) | doRepositoryWatchRequest(
method getRepositoryWatcherRequest (line 300) | getRepositoryWatcherRequest(String userName, String reposName, page,
method next (line 305) | next()
method getRepositoryStarRequest (line 339) | getRepositoryStarRequest(String userName, String reposName, page,
method next (line 343) | next()
method getRepositoryForksRequest (line 377) | getRepositoryForksRequest(String userName, String reposName, page,
method next (line 381) | next()
method getStarRepositoryRequest (line 416) | getStarRepositoryRequest(String userName, page, sort,
method next (line 419) | next()
method getUserRepositoryRequest (line 454) | getUserRepositoryRequest(String userName, page, sort,
method next (line 457) | next()
method createForkRequest (line 492) | createForkRequest(String userName, String reposName)
method getBranchesRequest (line 500) | getBranchesRequest(userName, reposName)
method getUserRepository100StatusRequest (line 531) | getUserRepository100StatusRequest(String userName)
method getRepositoryDetailReadmeRequest (line 551) | getRepositoryDetailReadmeRequest(
method next (line 558) | next()
method searchRepositoryRequest (line 593) | searchRepositoryRequest(
method getReposCommitsInfoRequest (line 633) | getReposCommitsInfoRequest(
method getReposCompareRequest (line 646) | getReposCompareRequest(
method getRepositoryReleaseRequest (line 659) | getRepositoryReleaseRequest(String userName, String reposName, page,
method getNewsVersion (line 692) | getNewsVersion(BuildContext context, showTip)
method getRepositoryIssueStatusRequest (line 738) | getRepositoryIssueStatusRequest(
method searchTopicRepositoryRequest (line 763) | searchTopicRepositoryRequest(searchTopic, {page = 0})
method getHistoryRequest (line 787) | getHistoryRequest(page)
method saveHistoryRequest (line 797) | saveHistoryRequest(String? fullName, DateTime dateTime, String data)
FILE: lib/common/repositories/user_repository.dart
class UserRepository (line 26) | class UserRepository {
method oauth (line 27) | oauth(code, store)
method login (line 60) | login(String userName, String password, store)
method initUserInfo (line 100) | initUserInfo(Store<GSYState> store, WidgetRef ref)
method getUserInfoLocal (line 126) | getUserInfoLocal()
method getUserInfo (line 138) | getUserInfo(String? userName, {needDb = false})
method next (line 140) | next()
method clearAll (line 191) | clearAll(Store store)
method getUserStaredCountNet (line 198) | getUserStaredCountNet(String userName)
method getFollowerListRequest (line 221) | getFollowerListRequest(String userName, page, {needDb = false})
method next (line 224) | next()
method getFollowedListRequest (line 258) | getFollowedListRequest(String userName, page, {needDb = false})
method next (line 260) | next()
method getNotifyRequest (line 294) | getNotifyRequest(bool all, bool participating, page)
method setNotificationAsReadRequest (line 316) | setNotificationAsReadRequest(id)
method setAllNotificationAsReadRequest (line 329) | setAllNotificationAsReadRequest()
method checkFollowRequest (line 341) | checkFollowRequest(String name)
method doFollowRequest (line 348) | doFollowRequest(String name, bool followed)
method getMemberRequest (line 361) | getMemberRequest(String userName, page)
method updateUserRequest (line 380) | updateUserRequest(params, Store store)
method getUserOrgsRequest (line 400) | getUserOrgsRequest(String userName, page, {needDb = false})
method next (line 402) | next()
method searchTrendUserRequest (line 435) | searchTrendUserRequest(String location, {String? cursor})
FILE: lib/common/router/anima_route.dart
class SizeRoute (line 4) | class SizeRoute extends PageRouteBuilder {
class NoAnimationRoute (line 37) | class NoAnimationRoute extends PageRouteBuilder {
FILE: lib/common/style/gsy_style.dart
class GSYColors (line 4) | class GSYColors {
class GSYConstant (line 49) | class GSYConstant {
class GSYICons (line 212) | class GSYICons {
FILE: lib/common/toast.dart
function showToast (line 4) | showToast(String message)
FILE: lib/common/utils/code_utils.dart
class CodeUtils (line 4) | class CodeUtils {
method decodeListResult (line 5) | List<dynamic> decodeListResult(String? data)
method decodeMapResult (line 9) | Map<String, dynamic> decodeMapResult(String? data)
method encodeToString (line 13) | String encodeToString(String data)
FILE: lib/common/utils/common_utils.dart
type StringList (line 28) | typedef StringList = List<String>;
class CommonUtils (line 30) | class CommonUtils {
method getDateStr (line 43) | String getDateStr(DateTime? date)
method getUserChartAddress (line 52) | String getUserChartAddress(String userName)
method getNewsTimeStr (line 57) | String getNewsTimeStr(DateTime date)
method getLocalPath (line 94) | getLocalPath()
method getApplicationDocumentsPath (line 117) | getApplicationDocumentsPath()
method removeTextTag (line 130) | String? removeTextTag(String? description)
method splitFileNameByPath (line 164) | splitFileNameByPath(String path)
method getFullName (line 168) | getFullName(String? repository_url)
method getThemeData (line 184) | getThemeData(Color color)
method showLanguageDialog (line 240) | showLanguageDialog(WidgetRef ref)
method getDeviceInfo (line 255) | Future<String> getDeviceInfo()
method getThemeListColor (line 264) | List<Color> getThemeListColor()
method isImageEnd (line 278) | isImageEnd(path)
method copy (line 288) | copy(String? data, BuildContext context)
method gsyLaunchUrl (line 295) | gsyLaunchUrl(BuildContext context, String? url)
method launchWebView (line 330) | void launchWebView(BuildContext context, String? title, String url)
method launchOutURL (line 343) | launchOutURL(String? url, BuildContext context)
method showLoadingDialog (line 353) | Future<void> showLoadingDialog(BuildContext context)
method showEditDialog (line 386) | Future<void> showEditDialog(
method showCommitOptionDialog (line 416) | Future<void> showCommitOptionDialog(
method showUpdateDialog (line 462) | Future<void> showUpdateDialog(
function getRawBaseUrl (line 489) | String getRawBaseUrl(
FILE: lib/common/utils/event_utils.dart
class EventUtils (line 12) | class EventUtils {
method _isInvalidCompareBase (line 13) | bool _isInvalidCompareBase(String? sha)
method _shortSha (line 20) | String _shortSha(String? sha, [int length = 7])
method getActionAndDes (line 31) | ({String? actionStr, String? des}) getActionAndDes(Event event)
method ActionUtils (line 166) | Future<void> ActionUtils(
FILE: lib/common/utils/html_utils.dart
class HtmlUtils (line 9) | class HtmlUtils {
method generateCode2HTml (line 10) | generateCode2HTml(String? mdData,
method generateHtml (line 21) | generateHtml(String? mdData,
method generateCodeHtml (line 91) | generateCodeHtml(mdHTML, wrap,
method parseDiffSource (line 100) | parseDiffSource(String? diffSource, bool wrap)
method getRemoveStartLine (line 147) | getRemoveStartLine(line)
method getAddStartLine (line 156) | getAddStartLine(line)
method getDiffLineNumber (line 165) | getDiffLineNumber(String removeNumber, String addNumber)
method getBlank (line 175) | getBlank(num)
method resolveHtmlFile (line 183) | resolveHtmlFile(var res, String defaultLang)
method formName (line 209) | formName(name)
FILE: lib/common/utils/navigator_utils.dart
class NavigatorUtils (line 29) | class NavigatorUtils {
method pushReplacementNamed (line 31) | pushReplacementNamed(BuildContext context, String routeName)
method pushNamed (line 58) | pushNamed(BuildContext context, String routeName)
method goHome (line 63) | goHome(BuildContext context)
method goLogin (line 68) | goLogin(BuildContext context)
method gotoPhotoViewPage (line 73) | gotoPhotoViewPage(BuildContext context, String? url)
method goPerson (line 78) | goPerson(BuildContext context, String? userName)
method goDebugDataPage (line 83) | goDebugDataPage(BuildContext context)
method goReposDetail (line 88) | Future goReposDetail(
method goHonorListPage (line 118) | Future goHonorListPage(BuildContext context, List? list)
method goReleasePage (line 147) | Future goReleasePage(BuildContext context, String? userName,
method goIssueDetail (line 160) | Future goIssueDetail(
method gotoCommonList (line 174) | gotoCommonList(BuildContext context, String? title, String showType,
method goNotifyPage (line 189) | Future goNotifyPage(BuildContext context)
method goTrendUserPage (line 194) | Future goTrendUserPage(BuildContext context)
method goSearchPage (line 199) | Future goSearchPage(BuildContext context, Offset centerPosition)
method goPushDetailPage (line 226) | Future goPushDetailPage(BuildContext context, String? userName,
method goGSYWebView (line 239) | Future goGSYWebView(BuildContext context, String url, String? title)
method goLoginWebView (line 244) | Future goLoginWebView(BuildContext context, String url, String title)
method gotoCodeDetailPageWeb (line 249) | gotoCodeDetailPageWeb(BuildContext context,
method gotoCodeDetailPlatform (line 273) | gotoCodeDetailPlatform(BuildContext context,
method gotoUserProfileInfo (line 295) | gotoUserProfileInfo(BuildContext context)
method NavigatorRouter (line 300) | NavigatorRouter(BuildContext context, Widget widget)
method pageContainer (line 308) | Widget pageContainer(widget, BuildContext context)
method showGSYDialog (line 320) | Future<T?> showGSYDialog<T>({
FILE: lib/db/provider/event/received_event_db_provider.dart
class ReceivedEventDbProvider (line 12) | class ReceivedEventDbProvider extends BaseDbProvider {
method toMap (line 23) | Map<String, dynamic> toMap(String eventMapString)
method insert (line 50) | Future insert(String eventMapString)
method getEvents (line 59) | Future<List<Event>>? getEvents()
method decodeMapToObject (line 76) | List<Event> decodeMapToObject(List<dynamic> mapList)
FILE: lib/db/provider/event/user_event_db_provider.dart
class UserEventDbProvider (line 13) | class UserEventDbProvider extends BaseDbProvider {
method toMap (line 26) | Map<String, dynamic> toMap(String? userName, String eventMapString)
method _getProvider (line 57) | Future _getProvider(Database db, String? userName)
method insert (line 70) | Future insert(String? userName, String eventMapString)
method getEvents (line 81) | Future<List<Event>?> getEvents(userName)
method decodeMapToObject (line 98) | List<Event> decodeMapToObject(List<dynamic> mapList)
FILE: lib/db/provider/issue/issue_comment_db_provider.dart
class IssueCommentDbProvider (line 13) | class IssueCommentDbProvider extends BaseDbProvider {
method toMap (line 29) | Map<String, dynamic> toMap(String? fullName, String number, String data)
method _getProvider (line 64) | Future _getProvider(Database db, String? fullName, String number)
method insert (line 78) | Future insert(String? fullName, String number, String dataMapString)
method getData (line 90) | Future<List<Issue>?> getData(String? fullName, String number)
FILE: lib/db/provider/issue/issue_detail_db_provider.dart
class IssueDetailDbProvider (line 14) | class IssueDetailDbProvider extends BaseDbProvider {
method toMap (line 28) | Map<String, dynamic> toMap(String? fullName, String number, String data)
method _getProvider (line 62) | Future _getProvider(Database db, String? fullName, String number)
method insert (line 76) | Future insert(String? fullName, String number, String dataMapString)
method getRepository (line 88) | Future<Issue?> getRepository(String? fullName, String number)
FILE: lib/db/provider/repos/read_history_db_provider.dart
class ReadHistoryDbProvider (line 14) | class ReadHistoryDbProvider extends BaseDbProvider {
method toMap (line 28) | Map<String, dynamic> toMap(String? fullName, DateTime readDate, String...
method _getProvider (line 62) | Future _getProvider(Database db, int page)
method _getProviderInsert (line 74) | Future _getProviderInsert(Database db, String? fullName)
method insert (line 90) | Future insert(
method geData (line 102) | Future<List<RepositoryQL?>?> geData(int page)
FILE: lib/db/provider/repos/repository_branch_db_provider.dart
class RepositoryBranchDbProvider (line 7) | class RepositoryBranchDbProvider extends BaseDbProvider {
method toMap (line 17) | Map<String, dynamic> toMap()
FILE: lib/db/provider/repos/repository_commitInfo_detail_db_provider.dart
class RepositoryCommitInfoDetailDbProvider (line 7) | class RepositoryCommitInfoDetailDbProvider extends BaseDbProvider {
method toMap (line 19) | Map<String, dynamic> toMap()
FILE: lib/db/provider/repos/repository_commits_db_provider.dart
class RepositoryCommitsDbProvider (line 13) | class RepositoryCommitsDbProvider extends BaseDbProvider {
method toMap (line 27) | Map<String, dynamic> toMap(String? fullName, String? branch, String data)
method _getProvider (line 61) | Future _getProvider(Database db, String? fullName, String? branch)
method insert (line 75) | Future insert(String? fullName, String? branch, String dataMapString)
method getData (line 87) | Future<List<RepoCommit>?> getData(String? fullName, String? branch)
FILE: lib/db/provider/repos/repository_detail_db_provider.dart
class RepositoryDetailDbProvider (line 12) | class RepositoryDetailDbProvider extends BaseDbProvider {
method toMap (line 24) | Map<String, dynamic> toMap(String? fullName, String dataMapString)
method _getProvider (line 55) | Future _getProvider(Database db, String? fullName)
method insert (line 69) | Future insert(String? fullName, String dataMapString)
method getRepository (line 80) | Future<RepositoryQL?> getRepository(String? fullName)
FILE: lib/db/provider/repos/repository_detail_readme_db_provider.dart
class RepositoryDetailReadmeDbProvider (line 10) | class RepositoryDetailReadmeDbProvider extends BaseDbProvider {
method toMap (line 24) | Map<String, dynamic> toMap(
method _getProvider (line 59) | Future _getProvider(Database db, String? fullName, String? branch)
method insert (line 73) | Future insert(String? fullName, String? branch, String? dataMapString)
method getRepositoryReadme (line 85) | Future<String?> getRepositoryReadme(String? fullName, String? branch)
FILE: lib/db/provider/repos/repository_event_db_provider.dart
class RepositoryEventDbProvider (line 13) | class RepositoryEventDbProvider extends BaseDbProvider {
method toMap (line 26) | Map<String, dynamic> toMap(String? fullName, String data)
method _getProvider (line 54) | Future _getProvider(Database db, String? fullName)
method insert (line 68) | Future insert(String? fullName, String dataMapString)
method getEvents (line 79) | Future<List<Event>?> getEvents(String? fullName)
FILE: lib/db/provider/repos/repository_fork_db_provider.dart
class RepositoryForkDbProvider (line 13) | class RepositoryForkDbProvider extends BaseDbProvider {
method toMap (line 26) | Map<String, dynamic> toMap(String? fullName, String data)
method _getProvider (line 54) | Future _getProvider(Database db, String? fullName)
method insert (line 68) | Future insert(String? fullName, String dataMapString)
method geData (line 79) | Future<List<Repository>?> geData(String? fullName)
FILE: lib/db/provider/repos/repository_issue_db_provider.dart
class RepositoryIssueDbProvider (line 13) | class RepositoryIssueDbProvider extends BaseDbProvider {
method toMap (line 27) | Map<String, dynamic> toMap(String? fullName, String state, String data)
method _getProvider (line 61) | Future _getProvider(Database db, String? fullName, String state)
method insert (line 75) | Future insert(String? fullName, String state, String dataMapString)
method getData (line 87) | Future<List<Issue>?> getData(String? fullName, String branch)
FILE: lib/db/provider/repos/repository_pulse_db_provider.dart
class RepositoryPulseDbProvider (line 7) | class RepositoryPulseDbProvider extends BaseDbProvider {
method toMap (line 17) | Map<String, dynamic> toMap()
FILE: lib/db/provider/repos/repository_star_db_provider.dart
class RepositoryStarDbProvider (line 13) | class RepositoryStarDbProvider extends BaseDbProvider {
method toMap (line 26) | Map<String, dynamic> toMap(String? fullName, String data)
method _getProvider (line 54) | Future _getProvider(Database db, String? fullName)
method insert (line 68) | Future insert(String? fullName, String dataMapString)
method geData (line 79) | Future<List<User>?> geData(String? fullName)
FILE: lib/db/provider/repos/repository_watcher_db_provider.dart
class RepositoryWatcherDbProvider (line 13) | class RepositoryWatcherDbProvider extends BaseDbProvider {
method toMap (line 25) | Map<String, dynamic> toMap(String? fullName, String data)
method _getProvider (line 53) | Future _getProvider(Database db, String? fullName)
method insert (line 67) | Future insert(String? fullName, String dataMapString)
method geData (line 78) | Future<List<User>?> geData(String? fullName)
FILE: lib/db/provider/repos/trend_repository_db_provider.dart
class TrendRepositoryDbProvider (line 12) | class TrendRepositoryDbProvider extends BaseDbProvider {
method toMap (line 27) | Map<String, dynamic> toMap(
method insert (line 63) | Future insert(String language, String? since, String dataMapString)
method getData (line 72) | Future<List<TrendingRepoModel>>? getData(String language, String? since)
FILE: lib/db/provider/user/org_member_db_provider.dart
class OrgMemberDbProvider (line 8) | class OrgMemberDbProvider extends BaseDbProvider {
method toMap (line 19) | Map<String, dynamic> toMap()
FILE: lib/db/provider/user/user_followed_db_provider.dart
class UserFollowedDbProvider (line 11) | class UserFollowedDbProvider extends BaseDbProvider {
method toMap (line 24) | Map<String, dynamic> toMap(String? userName, String data)
method _getProvider (line 52) | Future _getProvider(Database db, String? userName)
method insert (line 66) | Future insert(String? userName, String dataMapString)
method geData (line 77) | Future<List<User>?> geData(String? userName)
FILE: lib/db/provider/user/user_follower_db_provider.dart
class UserFollowerDbProvider (line 13) | class UserFollowerDbProvider extends BaseDbProvider {
method toMap (line 26) | Map<String, dynamic> toMap(String? userName, String data)
method _getProvider (line 54) | Future _getProvider(Database db, String? userName)
method insert (line 68) | Future insert(String? userName, String dataMapString)
method geData (line 79) | Future<List<User>?> geData(String? userName)
FILE: lib/db/provider/user/user_orgs_db_provider.dart
class UserOrgsDbProvider (line 13) | class UserOrgsDbProvider extends BaseDbProvider {
method toMap (line 26) | Map<String, dynamic> toMap(String? userName, String data)
method _getProvider (line 54) | Future _getProvider(Database db, String? userName)
method insert (line 67) | Future insert(String? userName, String dataMapString)
method geData (line 78) | Future<List<UserOrg>?> geData(String? userName)
FILE: lib/db/provider/user/user_repos_db_provider.dart
class UserReposDbProvider (line 13) | class UserReposDbProvider extends BaseDbProvider {
method toMap (line 26) | Map<String, dynamic> toMap(String? fullName, String data)
method _getProvider (line 54) | Future _getProvider(Database db, String? userName)
method insert (line 67) | Future insert(String? userName, String dataMapString)
method geData (line 78) | Future<List<Repository>?> geData(String? userName)
FILE: lib/db/provider/user/user_stared_db_provider.dart
class UserStaredDbProvider (line 13) | class UserStaredDbProvider extends BaseDbProvider {
method toMap (line 26) | Map<String, dynamic> toMap(String? fullName, String data)
method _getProvider (line 54) | Future _getProvider(Database db, String? userName)
method insert (line 67) | Future insert(String? userName, String dataMapString)
method geData (line 78) | Future<List<Repository>?> geData(String? userName)
FILE: lib/db/provider/user/userinfo_db_provider.dart
class UserInfoDbProvider (line 13) | class UserInfoDbProvider extends BaseDbProvider {
method toMap (line 26) | Map<String, dynamic> toMap(String userName, String data)
method _getUserProvider (line 54) | Future _getUserProvider(Database db, String? userName)
method insert (line 67) | Future insert(String userName, String eventMapString)
method getUserInfo (line 78) | Future<User?> getUserInfo(String? userName)
FILE: lib/db/sql_manager.dart
class SqlManager (line 12) | class SqlManager {
method init (line 20) | init()
method isTableExits (line 43) | isTableExits(String tableName)
method getCurrentDatabase (line 51) | Future<Database?> getCurrentDatabase()
method close (line 59) | close()
FILE: lib/db/sql_provider.dart
class BaseDbProvider (line 13) | abstract class BaseDbProvider {
method getDataBase (line 27) | Future<Database> getDataBase()
FILE: lib/env/config_wrapper.dart
class ConfigWrapper (line 8) | class ConfigWrapper extends StatelessWidget {
method build (line 12) | Widget build(BuildContext context)
method of (line 21) | EnvConfig? of(BuildContext context)
class _InheritedConfig (line 32) | class _InheritedConfig extends InheritedWidget {
method updateShouldNotify (line 39) | bool updateShouldNotify(_InheritedConfig oldWidget)
FILE: lib/env/env_config.dart
class EnvConfig (line 6) | @JsonSerializable(createToJson: false)
FILE: lib/env/env_config.g.dart
function _$EnvConfigFromJson (line 9) | EnvConfig _$EnvConfigFromJson(Map<String, dynamic> json)
FILE: lib/main.dart
function main (line 13) | void main()
FILE: lib/main_prod.dart
function main (line 12) | void main()
FILE: lib/model/branch.dart
class Branch (line 6) | abstract class Branch implements Built<Branch, BranchBuilder> {
FILE: lib/model/branch.g.dart
class _$BranchSerializer (line 11) | class _$BranchSerializer implements StructuredSerializer<Branch> {
method serialize (line 18) | Iterable<Object?> serialize(
method deserialize (line 53) | Branch deserialize(
class _$Branch (line 97) | class _$Branch extends Branch {
method rebuild (line 110) | Branch rebuild(void Function(BranchBuilder) updates)
method toBuilder (line 114) | BranchBuilder toBuilder()
method toString (line 136) | String toString()
class BranchBuilder (line 145) | class BranchBuilder implements Builder<Branch, BranchBuilder> {
method replace (line 174) | void replace(Branch other)
method update (line 179) | void update(void Function(BranchBuilder)? updates)
method build (line 184) | Branch build()
method _build (line 186) | _$Branch _build()
FILE: lib/model/commitFile.dart
class CommitFile (line 10) | @JsonSerializable()
method toJson (line 42) | Map<String, dynamic> toJson()
FILE: lib/model/commitFile.g.dart
function _$CommitFileFromJson (line 9) | CommitFile _$CommitFileFromJson(Map<String, dynamic> json)
function _$CommitFileToJson (line 22) | Map<String, dynamic> _$CommitFileToJson(CommitFile instance)
FILE: lib/model/commit_comment.dart
class CommitComment (line 11) | @JsonSerializable()
method toJson (line 45) | Map<String, dynamic> toJson()
FILE: lib/model/commit_comment.g.dart
function _$CommitCommentFromJson (line 9) | CommitComment _$CommitCommentFromJson(Map<String, dynamic> json)
function _$CommitCommentToJson (line 30) | Map<String, dynamic> _$CommitCommentToJson(CommitComment instance)
FILE: lib/model/commit_git_info.dart
class CommitGitInfo (line 11) | @JsonSerializable()
method toJson (line 31) | Map<String, dynamic> toJson()
FILE: lib/model/commit_git_info.g.dart
function _$CommitGitInfoFromJson (line 9) | CommitGitInfo _$CommitGitInfoFromJson(Map<String, dynamic> json)
function _$CommitGitInfoToJson (line 22) | Map<String, dynamic> _$CommitGitInfoToJson(CommitGitInfo instance)
FILE: lib/model/commit_git_user.dart
class CommitGitUser (line 10) | @JsonSerializable()
method toJson (line 21) | Map<String, dynamic> toJson()
FILE: lib/model/commit_git_user.g.dart
function _$CommitGitUserFromJson (line 9) | CommitGitUser _$CommitGitUserFromJson(Map<String, dynamic> json)
function _$CommitGitUserToJson (line 16) | Map<String, dynamic> _$CommitGitUserToJson(CommitGitUser instance)
FILE: lib/model/commit_stats.dart
class CommitStats (line 10) | @JsonSerializable()
method toJson (line 20) | Map<String, dynamic> toJson()
FILE: lib/model/commit_stats.g.dart
function _$CommitStatsFromJson (line 9) | CommitStats _$CommitStatsFromJson(Map<String, dynamic> json)
function _$CommitStatsToJson (line 15) | Map<String, dynamic> _$CommitStatsToJson(CommitStats instance)
FILE: lib/model/commits_comparison.dart
class CommitsComparison (line 13) | @JsonSerializable()
method toJson (line 41) | Map<String, dynamic> toJson()
FILE: lib/model/commits_comparison.g.dart
function _$CommitsComparisonFromJson (line 9) | CommitsComparison _$CommitsComparisonFromJson(Map<String, dynamic> json)
function _$CommitsComparisonToJson (line 31) | Map<String, dynamic> _$CommitsComparisonToJson(CommitsComparison instance)
FILE: lib/model/common_list_datatype.dart
type CommonListDataType (line 1) | enum CommonListDataType {
FILE: lib/model/download_source.dart
class DownloadSource (line 10) | @JsonSerializable()
method toJson (line 26) | Map<String, dynamic> toJson()
FILE: lib/model/download_source.g.dart
function _$DownloadSourceFromJson (line 9) | DownloadSource _$DownloadSourceFromJson(Map<String, dynamic> json)
function _$DownloadSourceToJson (line 17) | Map<String, dynamic> _$DownloadSourceToJson(DownloadSource instance)
FILE: lib/model/event.dart
class Event (line 14) | @JsonSerializable()
method toJson (line 40) | Map<String, dynamic> toJson()
FILE: lib/model/event.g.dart
function _$EventFromJson (line 9) | Event _$EventFromJson(Map<String, dynamic> json)
function _$EventToJson (line 30) | Map<String, dynamic> _$EventToJson(Event instance)
FILE: lib/model/event_payload.dart
class EventPayload (line 14) | @JsonSerializable()
method toJson (line 44) | Map<String, dynamic> toJson()
FILE: lib/model/event_payload.g.dart
function _$EventPayloadFromJson (line 9) | EventPayload _$EventPayloadFromJson(Map<String, dynamic> json)
function _$EventPayloadToJson (line 34) | Map<String, dynamic> _$EventPayloadToJson(EventPayload instance)
FILE: lib/model/file_model.dart
class FileModel (line 10) | @JsonSerializable()
method toJson (line 40) | Map<String, dynamic> toJson()
FILE: lib/model/file_model.g.dart
function _$FileModelFromJson (line 9) | FileModel _$FileModelFromJson(Map<String, dynamic> json)
function _$FileModelToJson (line 21) | Map<String, dynamic> _$FileModelToJson(FileModel instance)
FILE: lib/model/issue.dart
class Issue (line 11) | @JsonSerializable()
method toJson (line 61) | Map<String, dynamic> toJson()
FILE: lib/model/issue.g.dart
function _$IssueFromJson (line 9) | Issue _$IssueFromJson(Map<String, dynamic> json)
function _$IssueToJson (line 37) | Map<String, dynamic> _$IssueToJson(Issue instance)
FILE: lib/model/issue_event.dart
class IssueEvent (line 11) | @JsonSerializable()
method toJson (line 43) | Map<String, dynamic> toJson()
FILE: lib/model/issue_event.g.dart
function _$IssueEventFromJson (line 9) | IssueEvent _$IssueEventFromJson(Map<String, dynamic> json)
function _$IssueEventToJson (line 27) | Map<String, dynamic> _$IssueEventToJson(IssueEvent instance)
FILE: lib/model/license.dart
class License (line 13) | @JsonSerializable()
method toJson (line 22) | Map<String, dynamic> toJson()
FILE: lib/model/license.g.dart
function _$LicenseFromJson (line 9) | License _$LicenseFromJson(Map<String, dynamic> json)
function _$LicenseToJson (line 12) | Map<String, dynamic> _$LicenseToJson(License instance)
FILE: lib/model/notification.dart
class Notification (line 13) | @JsonSerializable()
method toJson (line 29) | Map<String, dynamic> toJson()
FILE: lib/model/notification.g.dart
function _$NotificationFromJson (line 9) | Notification _$NotificationFromJson(Map<String, dynamic> json)
function _$NotificationToJson (line 27) | Map<String, dynamic> _$NotificationToJson(Notification instance)
FILE: lib/model/notification_subject.dart
class NotificationSubject (line 10) | @JsonSerializable()
method toJson (line 20) | Map<String, dynamic> toJson()
FILE: lib/model/notification_subject.g.dart
function _$NotificationSubjectFromJson (line 9) | NotificationSubject _$NotificationSubjectFromJson(Map<String, dynamic> j...
function _$NotificationSubjectToJson (line 16) | Map<String, dynamic> _$NotificationSubjectToJson(
FILE: lib/model/push_commit.dart
class PushCommit (line 16) | @JsonSerializable()
method toJson (line 49) | Map<String, dynamic> toJson()
FILE: lib/model/push_commit.g.dart
function _$PushCommitFromJson (line 9) | PushCommit _$PushCommitFromJson(Map<String, dynamic> json)
function _$PushCommitToJson (line 34) | Map<String, dynamic> _$PushCommitToJson(PushCommit instance)
FILE: lib/model/push_event_commit.dart
class PushEventCommit (line 11) | @JsonSerializable()
method toJson (line 29) | Map<String, dynamic> toJson()
FILE: lib/model/push_event_commit.g.dart
function _$PushEventCommitFromJson (line 9) | PushEventCommit _$PushEventCommitFromJson(Map<String, dynamic> json)
function _$PushEventCommitToJson (line 20) | Map<String, dynamic> _$PushEventCommitToJson(PushEventCommit instance)
FILE: lib/model/release.dart
class Release (line 12) | @JsonSerializable()
method toJson (line 59) | Map<String, dynamic> toJson()
FILE: lib/model/release.g.dart
function _$ReleaseFromJson (line 9) | Release _$ReleaseFromJson(Map<String, dynamic> json)
function _$ReleaseToJson (line 34) | Map<String, dynamic> _$ReleaseToJson(Release instance)
FILE: lib/model/release_asset.dart
class ReleaseAsset (line 11) | @JsonSerializable()
method toJson (line 44) | Map<String, dynamic> toJson()
FILE: lib/model/release_asset.g.dart
function _$ReleaseAssetFromJson (line 9) | ReleaseAsset _$ReleaseAssetFromJson(Map<String, dynamic> json)
function _$ReleaseAssetToJson (line 29) | Map<String, dynamic> _$ReleaseAssetToJson(ReleaseAsset instance)
FILE: lib/model/repo_commit.dart
class RepoCommit (line 12) | @JsonSerializable()
method toJson (line 38) | Map<String, dynamic> toJson()
FILE: lib/model/repo_commit.g.dart
function _$RepoCommitFromJson (line 9) | RepoCommit _$RepoCommitFromJson(Map<String, dynamic> json)
function _$RepoCommitToJson (line 28) | Map<String, dynamic> _$RepoCommitToJson(RepoCommit instance)
FILE: lib/model/repository.dart
class Repository (line 13) | @JsonSerializable()
method toJson (line 141) | Map<String, dynamic> toJson()
FILE: lib/model/repository.g.dart
function _$RepositoryFromJson (line 9) | Repository _$RepositoryFromJson(Map<String, dynamic> json)
function _$RepositoryToJson (line 60) | Map<String, dynamic> _$RepositoryToJson(Repository instance)
FILE: lib/model/repository_permissions.dart
class RepositoryPermissions (line 10) | @JsonSerializable()
method toJson (line 23) | Map<String, dynamic> toJson()
FILE: lib/model/repository_permissions.g.dart
function _$RepositoryPermissionsFromJson (line 9) | RepositoryPermissions _$RepositoryPermissionsFromJson(
function _$RepositoryPermissionsToJson (line 17) | Map<String, dynamic> _$RepositoryPermissionsToJson(
FILE: lib/model/repository_ql.dart
class RepositoryQL (line 1) | class RepositoryQL {
method fromMap (line 56) | fromMap(Map? map)
method toMap (line 101) | toMap(RepositoryQL? repositoryQL)
FILE: lib/model/search_user_ql.dart
class SearchUserQL (line 1) | class SearchUserQL {
method fromMap (line 18) | fromMap(Map map)
FILE: lib/model/template.dart
class Template (line 6) | @JsonSerializable()
method toJson (line 21) | Map<String, dynamic> toJson()
FILE: lib/model/template.g.dart
function _$TemplateFromJson (line 9) | Template _$TemplateFromJson(Map<String, dynamic> json)
function _$TemplateToJson (line 15) | Map<String, dynamic> _$TemplateToJson(Template instance)
FILE: lib/model/trending_repo_model.dart
class TrendingRepoModel (line 9) | @JsonSerializable()
method toJson (line 44) | Map<String, dynamic> toJson()
FILE: lib/model/trending_repo_model.g.dart
function _$TrendingRepoModelFromJson (line 9) | TrendingRepoModel _$TrendingRepoModelFromJson(Map<String, dynamic> json)
function _$TrendingRepoModelToJson (line 26) | Map<String, dynamic> _$TrendingRepoModelToJson(TrendingRepoModel instance)
FILE: lib/model/user.dart
class User (line 5) | @JsonSerializable()
method toJson (line 88) | Map<String, dynamic> toJson()
FILE: lib/model/user.g.dart
function _$UserFromJson (line 9) | User _$UserFromJson(Map<String, dynamic> json)
function _$UserToJson (line 53) | Map<String, dynamic> _$UserToJson(User instance)
FILE: lib/model/user_org.dart
class UserOrg (line 9) | @JsonSerializable()
method toJson (line 50) | Map<String, dynamic> toJson()
FILE: lib/model/user_org.g.dart
function _$UserOrgFromJson (line 9) | UserOrg _$UserOrgFromJson(Map<String, dynamic> json)
function _$UserOrgToJson (line 24) | Map<String, dynamic> _$UserOrgToJson(UserOrg instance)
FILE: lib/page/code_detail_page_web.dart
class CodeDetailPageWeb (line 16) | class CodeDetailPageWeb extends StatefulWidget {
method createState (line 45) | _CodeDetailPageState createState()
class _CodeDetailPageState (line 48) | class _CodeDetailPageState extends State<CodeDetailPageWeb> {
method initState (line 54) | void initState()
method _getData (line 61) | Future<Uri?> _getData()
method dispose (line 78) | void dispose()
method build (line 86) | Widget build(BuildContext context)
FILE: lib/page/common_list_page.dart
class CommonListPage (line 15) | class CommonListPage extends StatefulWidget {
method createState (line 30) | _CommonListPageState createState()
class _CommonListPageState (line 33) | class _CommonListPageState extends State<CommonListPage>
method build (line 126) | Widget build(BuildContext context)
FILE: lib/page/debug/debug_data_page.dart
class DebugDataPage (line 12) | class DebugDataPage extends StatefulWidget {
method createState (line 16) | _DebugDataPageState createState()
class _DebugDataPageState (line 19) | class _DebugDataPageState extends State<DebugDataPage> {
method build (line 33) | Widget build(BuildContext context)
class DebugDataList (line 70) | class DebugDataList extends StatefulWidget {
method createState (line 78) | _DebugDataListState createState()
class _DebugDataListState (line 81) | class _DebugDataListState extends State<DebugDataList>
method build (line 87) | Widget build(BuildContext context)
FILE: lib/page/debug/debug_label.dart
class DebugLabel (line 11) | class DebugLabel {
method showDebugLabel (line 15) | showDebugLabel(BuildContext context)
method resetDebugLabel (line 42) | resetDebugLabel(BuildContext context)
method hideDebugLabel (line 47) | hideDebugLabel()
function _getDeviceInfo (line 56) | Future<(String, String)> _getDeviceInfo()
class GlobalLabel (line 67) | class GlobalLabel extends StatefulWidget {
method createState (line 76) | _GlobalLabelState createState()
class _GlobalLabelState (line 79) | class _GlobalLabelState extends State<GlobalLabel> {
method dispose (line 84) | void dispose()
method build (line 91) | Widget build(BuildContext context)
FILE: lib/page/dynamic/dynamic_bloc.dart
class DynamicBloc (line 7) | class DynamicBloc {
method getDataLength (line 58) | int? getDataLength()
method dispose (line 94) | void dispose()
FILE: lib/page/dynamic/dynamic_page.dart
class DynamicPage (line 16) | class DynamicPage extends StatefulWidget {
method createState (line 20) | DynamicPageState createState()
class DynamicPageState (line 23) | class DynamicPageState extends State<DynamicPage>
method requestRefresh (line 66) | Future<void> requestRefresh()
method requestLoadMore (line 78) | Future<void> requestLoadMore()
method _getStore (line 92) | Store<GSYState> _getStore()
method initState (line 97) | void initState()
method didChangeDependencies (line 108) | void didChangeDependencies()
method didChangeAppLifecycleState (line 125) | void didChangeAppLifecycleState(AppLifecycleState state)
method dispose (line 137) | void dispose()
method build (line 144) | Widget build(BuildContext context)
FILE: lib/page/error_page.dart
class ErrorPage (line 9) | class ErrorPage extends StatefulWidget {
method createState (line 16) | ErrorPageState createState()
class ErrorPageState (line 19) | class ErrorPageState extends State<ErrorPage> {
method build (line 38) | Widget build(BuildContext context)
FILE: lib/page/gsy_webview.dart
class GSYWebView (line 13) | class GSYWebView extends StatefulWidget {
method createState (line 20) | _GSYWebViewState createState()
class _GSYWebViewState (line 23) | class _GSYWebViewState extends State<GSYWebView> {
method initState (line 46) | void initState()
method build (line 73) | Widget build(BuildContext context)
FILE: lib/page/home/home_page.dart
class HomePage (line 19) | class HomePage extends StatefulWidget {
method createState (line 25) | _HomePageState createState()
class _HomePageState (line 28) | class _HomePageState extends State<HomePage> {
method build (line 57) | Widget build(BuildContext context)
FILE: lib/page/home/widget/home_drawer.dart
class HomeDrawer (line 24) | class HomeDrawer extends StatelessWidget {
method build (line 61) | Widget build(BuildContext context)
FILE: lib/page/honor_list_page.dart
class HonorListPage (line 9) | class HonorListPage extends StatefulWidget {
method createState (line 15) | _HonorListPageState createState()
class _HonorListPageState (line 18) | class _HonorListPageState extends State<HonorListPage> {
method build (line 28) | Widget build(BuildContext context)
FILE: lib/page/issue/issue_detail_page.dart
class IssueDetailPage (line 23) | class IssueDetailPage extends StatefulWidget {
method createState (line 36) | _IssueDetailPageState createState()
class _IssueDetailPageState (line 39) | class _IssueDetailPageState extends State<IssueDetailPage>
method build (line 371) | Widget build(BuildContext context)
FILE: lib/page/issue/issue_edit_dIalog.dart
class IssueEditDialog (line 10) | class IssueEditDialog extends StatefulWidget {
method createState (line 39) | _IssueEditDialogState createState()
class _IssueEditDialogState (line 42) | class _IssueEditDialogState extends State<IssueEditDialog> {
method build (line 93) | Widget build(BuildContext context)
class FastInputIconModel (line 229) | class FastInputIconModel {
FILE: lib/page/issue/widget/issue_header_item.dart
class IssueHeaderItem (line 15) | class IssueHeaderItem extends StatelessWidget {
method build (line 76) | Widget build(BuildContext context)
class IssueHeaderViewModel (line 165) | class IssueHeaderViewModel {
FILE: lib/page/issue/widget/issue_item.dart
class IssueItem (line 14) | class IssueItem extends StatelessWidget {
method build (line 98) | Widget build(BuildContext context)
class IssueItemViewModel (line 154) | class IssueItemViewModel {
FILE: lib/page/login/login_page.dart
class LoginPage (line 22) | class LoginPage extends StatefulWidget {
method createState (line 28) | State createState()
class _LoginPageState (line 33) | class _LoginPageState extends State<LoginPage> with LoginBLoC {
method build (line 35) | Widget build(BuildContext context)
function initState (line 158) | void initState()
function dispose (line 164) | void dispose()
FILE: lib/page/login/login_webview.dart
class LoginWebView (line 12) | class LoginWebView extends StatefulWidget {
method createState (line 19) | _LoginWebViewState createState()
class _LoginWebViewState (line 22) | class _LoginWebViewState extends State<LoginWebView> {
method initState (line 32) | void initState()
method build (line 56) | Widget build(BuildContext context)
FILE: lib/page/my_page.dart
class MyPage (line 16) | class MyPage extends StatefulWidget {
method createState (line 20) | MyPageState createState()
class MyPageState (line 23) | class MyPageState extends BasePersonState<MyPage> {
method _getStore (line 30) | Store<GSYState>? _getStore()
method initState (line 85) | void initState()
method didChangeDependencies (line 142) | void didChangeDependencies()
method buildContainer (line 150) | Widget buildContainer(BuildContext context)
FILE: lib/page/notify/notify_page.dart
class NotifyPage (line 23) | class NotifyPage extends StatefulWidget {
method createState (line 27) | _NotifyPageState createState()
class _NotifyPageState (line 30) | class _NotifyPageState extends State<NotifyPage>
method initState (line 47) | void initState()
method build (line 174) | Widget build(BuildContext context)
FILE: lib/page/photoview_page.dart
class PhotoViewPage (line 12) | class PhotoViewPage extends StatelessWidget {
method build (line 18) | Widget build(BuildContext context)
FILE: lib/page/push/push_detail_page.dart
class PushDetailPage (line 20) | class PushDetailPage extends StatefulWidget {
method createState (line 33) | _PushDetailPageState createState()
class _PushDetailPageState (line 36) | class _PushDetailPageState extends State<PushDetailPage>
method handleRefresh (line 46) | Future<void> handleRefresh()
method build (line 119) | Widget build(BuildContext context)
FILE: lib/page/push/widget/push_coed_item.dart
class PushCodeItem (line 10) | class PushCodeItem extends StatelessWidget {
method build (line 17) | Widget build(BuildContext context)
class PushCodeItemViewModel (line 45) | class PushCodeItemViewModel {
FILE: lib/page/push/widget/push_header.dart
class PushHeader (line 13) | class PushHeader extends StatelessWidget {
method build (line 31) | Widget build(BuildContext context)
class PushHeaderViewModel (line 111) | class PushHeaderViewModel {
FILE: lib/page/release/release_page.dart
class ReleasePage (line 20) | class ReleasePage extends StatefulWidget {
method createState (line 31) | _ReleasePageState createState()
class _ReleasePageState (line 34) | class _ReleasePageState extends State<ReleasePage>
method _getUrl (line 75) | String _getUrl()
method build (line 110) | Widget build(BuildContext context)
FILE: lib/page/release/widget/release_item.dart
class ReleaseItem (line 11) | class ReleaseItem extends StatelessWidget {
method build (line 20) | Widget build(BuildContext context)
class ReleaseItemViewModel (line 39) | class ReleaseItemViewModel {
FILE: lib/page/repos/provider/repos_detail_provider.dart
class ReposDetailProvider (line 11) | class ReposDetailProvider with ChangeNotifier {
method refreshReadme (line 112) | Future<void> refreshReadme()
method getRepositoryDetailRequest (line 123) | Future<void> getRepositoryDetailRequest(
FILE: lib/page/repos/provider/repos_network_provider.dart
class ReposNetWorkProvider (line 7) | class ReposNetWorkProvider with ChangeNotifier {
FILE: lib/page/repos/repository_detail_issue_list_page.dart
class RepositoryDetailIssuePage (line 19) | class RepositoryDetailIssuePage extends StatefulWidget {
method createState (line 23) | RepositoryDetailIssuePageState createState()
class RepositoryDetailIssuePageState (line 28) | class RepositoryDetailIssuePageState extends State<RepositoryDetailIssue...
method build (line 126) | Widget build(BuildContext context)
method _sliverBuilder (line 180) | List<Widget> _sliverBuilder(BuildContext context, bool innerBoxIsScrol...
FILE: lib/page/repos/repository_detail_page.dart
class RepositoryDetailPage (line 23) | class RepositoryDetailPage extends StatefulWidget {
method createState (line 33) | _RepositoryDetailPageState createState()
class _RepositoryDetailPageState (line 36) | class _RepositoryDetailPageState extends State<RepositoryDetailPage>
method renderItem (line 68) | renderItem(String item, int i)
method initState (line 174) | void initState()
method build (line 190) | Widget build(BuildContext context)
class BottomStatusModel (line 281) | class BottomStatusModel {
FILE: lib/page/repos/repository_detail_readme_page.dart
class RepositoryDetailReadmePage (line 14) | class RepositoryDetailReadmePage extends StatefulWidget {
method createState (line 18) | RepositoryDetailReadmePageState createState()
class RepositoryDetailReadmePageState (line 22) | class RepositoryDetailReadmePageState extends State<RepositoryDetailRead...
method initState (line 36) | void initState()
method dispose (line 42) | void dispose()
method build (line 47) | Widget build(BuildContext context)
FILE: lib/page/repos/repository_file_list_page.dart
class RepositoryDetailFileListPage (line 20) | class RepositoryDetailFileListPage extends StatefulWidget {
method createState (line 24) | RepositoryDetailFileListPageState createState()
class RepositoryDetailFileListPageState (line 28) | class RepositoryDetailFileListPageState
method _getDataLogic (line 152) | Future<DataResult> _getDataLogic(String? searchString)
method build (line 193) | Widget build(BuildContext context)
class FileItemViewModel (line 226) | class FileItemViewModel {
FILE: lib/page/repos/repostory_detail_info_page.dart
class ReposDetailInfoPage (line 27) | class ReposDetailInfoPage extends StatefulWidget {
method createState (line 31) | ReposDetailInfoPageState createState()
class ReposDetailInfoPageState (line 35) | class ReposDetailInfoPageState extends State<ReposDetailInfoPage>
method _getBottomWidget (line 123) | List<Widget> _getBottomWidget(ReposDetailProvider provider)
method initState (line 205) | void initState()
method build (line 211) | Widget build(BuildContext context)
method _sliverBuilder (line 235) | List<Widget> _sliverBuilder(
FILE: lib/page/repos/widget/repos_header_item.dart
class ReposHeaderItem (line 18) | class ReposHeaderItem extends StatefulWidget {
method createState (line 27) | _ReposHeaderItemState createState()
class _ReposHeaderItemState (line 30) | class _ReposHeaderItemState extends State<ReposHeaderItem> {
method didUpdateWidget (line 352) | void didUpdateWidget(ReposHeaderItem oldWidget)
method build (line 382) | Widget build(BuildContext context)
class ReposHeaderViewModel (line 435) | class ReposHeaderViewModel {
FILE: lib/page/repos/widget/repos_item.dart
class ReposItem (line 14) | class ReposItem extends StatelessWidget {
method build (line 43) | Widget build(BuildContext context)
class ReposViewModel (line 133) | class ReposViewModel {
FILE: lib/page/search/search_bloc.dart
class SearchBLoC (line 6) | class SearchBLoC {
method resetFilters (line 33) | void resetFilters()
method dispose (line 41) | void dispose()
FILE: lib/page/search/search_page.dart
class SearchPage (line 19) | class SearchPage extends StatefulWidget {
method createState (line 25) | _SearchPageState createState()
class _SearchPageState (line 28) | class _SearchPageState extends State<SearchPage>
method initState (line 98) | void initState()
method dispose (line 123) | void dispose()
method build (line 130) | Widget build(BuildContext context)
class SearchBottom (line 210) | class SearchBottom extends StatelessWidget implements PreferredSizeWidget {
method build (line 225) | Widget build(BuildContext context)
class CRAnimation (line 251) | class CRAnimation extends StatelessWidget {
method build (line 271) | Widget build(BuildContext context)
class AnimationClipper (line 289) | class AnimationClipper extends CustomClipper<Path> {
method shouldReclip (line 306) | bool shouldReclip(oldClipper)
method getClip (line 309) | Path getClip(Size size)
method radiusSize (line 327) | double radiusSize(Size size, Offset offset)
FILE: lib/page/search/widget/gsy_search_drawer.dart
type SearchSelectItemChanged (line 9) | typedef SearchSelectItemChanged<String> = void Function(String value);
class GSYSearchDrawer (line 11) | class GSYSearchDrawer extends StatefulWidget {
method createState (line 19) | _GSYSearchDrawerState createState()
class _GSYSearchDrawerState (line 22) | class _GSYSearchDrawerState extends State<GSYSearchDrawer> {
method build (line 27) | Widget build(BuildContext context)
class FilterModel (line 133) | class FilterModel {
function resetSearchDrawerFilters (line 165) | void resetSearchDrawerFilters()
function _resetFilterList (line 171) | void _resetFilterList(List<FilterModel> list)
FILE: lib/page/search/widget/gsy_search_input_widget.dart
class GSYSearchInputWidget (line 8) | class GSYSearchInputWidget extends StatelessWidget {
method build (line 19) | Widget build(BuildContext context)
FILE: lib/page/trend/trend_page.dart
class TrendPage (line 26) | class TrendPage extends ConsumerStatefulWidget {
method createState (line 30) | TrendPageState createState()
class TrendPageState (line 33) | class TrendPageState extends ConsumerState<TrendPage>
method requestRefresh (line 181) | Future<void> requestRefresh()
method didChangeDependencies (line 190) | void didChangeDependencies()
method _buildEmpty (line 210) | Widget _buildEmpty()
method build (line 241) | Widget build(BuildContext context)
method _sliverBuilder (line 308) | List<Widget> _sliverBuilder(BuildContext context, bool innerBoxIsScrol...
class TrendTypeModel (line 343) | class TrendTypeModel {
function trendTime (line 351) | List<TrendTypeModel> trendTime(BuildContext context)
function trendType (line 360) | List<TrendTypeModel> trendType(BuildContext context)
FILE: lib/page/trend/trend_provider.dart
function trendFirst (line 13) | Future<DataResult?> trendFirst(Ref ref, String? since, String? selectType)
function trendSecond (line 26) | Future<DataResult?> trendSecond(Ref ref, String? since, String? selectType)
FILE: lib/page/trend/trend_provider.g.dart
class TrendFirstProvider (line 15) | final class TrendFirstProvider
method debugGetCreateSourceHash (line 35) | String debugGetCreateSourceHash()
method toString (line 38) | String toString()
method $createElement (line 46) | $FutureProviderElement<DataResult?> $createElement(
method create (line 51) | FutureOr<DataResult?> create(Ref ref)
function _$trendFirstHash (line 67) | String _$trendFirstHash()
class TrendFirstFamily (line 69) | final class TrendFirstFamily extends $Family
method call (line 80) | TrendFirstProvider call(String? since, String? selectType)
method toString (line 84) | String toString()
class TrendSecondProvider (line 90) | final class TrendSecondProvider
method debugGetCreateSourceHash (line 110) | String debugGetCreateSourceHash()
method toString (line 113) | String toString()
method $createElement (line 121) | $FutureProviderElement<DataResult?> $createElement(
method create (line 126) | FutureOr<DataResult?> create(Ref ref)
function _$trendSecondHash (line 142) | String _$trendSecondHash()
class TrendSecondFamily (line 144) | final class TrendSecondFamily extends $Family
method call (line 155) | TrendSecondProvider call(String? since, String? selectType)
method toString (line 159) | String toString()
FILE: lib/page/trend/trend_user_page.dart
class TrendUserPage (line 10) | class TrendUserPage extends ConsumerStatefulWidget {
method createState (line 14) | _TrendUserPageState createState()
class _TrendUserPageState (line 17) | class _TrendUserPageState extends ConsumerState<TrendUserPage> {
method loadData (line 26) | Future<void> loadData(WidgetRef ref, {bool isRefresh = false})
method build (line 47) | Widget build(BuildContext context)
FILE: lib/page/trend/trend_user_provider.dart
class TrendCNUserList (line 10) | @Riverpod(keepAlive: true)
method build (line 15) | List<SearchUserQL> build()
method setList (line 19) | void setList(List<SearchUserQL> list)
method addList (line 23) | void addList(List<SearchUserQL> list)
method clear (line 28) | void clear()
function searchTrendUserRequest (line 34) | Future<(List<SearchUserQL>, String)?> searchTrendUserRequest(
FILE: lib/page/trend/trend_user_provider.g.dart
class TrendCNUserListProvider (line 17) | final class TrendCNUserListProvider
method debugGetCreateSourceHash (line 32) | String debugGetCreateSourceHash()
method create (line 36) | TrendCNUserList create()
method overrideWithValue (line 39) | Override overrideWithValue(List<SearchUserQL> value)
function _$trendCNUserListHash (line 47) | String _$trendCNUserListHash()
class _$TrendCNUserList (line 51) | abstract class _$TrendCNUserList extends $Notifier<List<SearchUserQL>> {
method build (line 52) | List<SearchUserQL> build()
method runBuild (line 55) | void runBuild()
class SearchTrendUserRequestProvider (line 73) | final class SearchTrendUserRequestProvider
method debugGetCreateSourceHash (line 95) | String debugGetCreateSourceHash()
method toString (line 98) | String toString()
method $createElement (line 106) | $FutureProviderElement<(List<SearchUserQL>, String)?> $createElement(
method create (line 111) | FutureOr<(List<SearchUserQL>, String)?> create(Ref ref)
function _$searchTrendUserRequestHash (line 133) | String _$searchTrendUserRequestHash()
class SearchTrendUserRequestFamily (line 136) | final class SearchTrendUserRequestFamily extends $Family
method call (line 151) | SearchTrendUserRequestProvider call(
method toString (line 161) | String toString()
FILE: lib/page/user/base_person_provider.dart
function fetchHonorData (line 9) | Future<HonorModel?> fetchHonorData(Ref ref, String userName)
class HonorModel (line 17) | class HonorModel {
FILE: lib/page/user/base_person_provider.g.dart
class FetchHonorDataProvider (line 18) | final class FetchHonorDataProvider
method debugGetCreateSourceHash (line 39) | String debugGetCreateSourceHash()
method toString (line 42) | String toString()
method $createElement (line 50) | $FutureProviderElement<HonorModel?> $createElement(
method create (line 55) | FutureOr<HonorModel?> create(Ref ref)
function _$fetchHonorDataHash (line 71) | String _$fetchHonorDataHash()
class FetchHonorDataFamily (line 75) | final class FetchHonorDataFamily extends $Family
method call (line 88) | FetchHonorDataProvider call(String userName)
method toString (line 92) | String toString()
FILE: lib/page/user/base_person_state.dart
class BasePersonState (line 25) | abstract class BasePersonState<T extends StatefulWidget> extends State<T>
method buildContainer (line 76) | Widget buildContainer(BuildContext context)
method sliverBuilder (line 103) | List<Widget> sliverBuilder(
method build (line 196) | Widget build(BuildContext context)
FILE: lib/page/user/person_page.dart
class PersonPage (line 23) | class PersonPage extends StatefulWidget {
method createState (line 31) | PersonState createState()
class PersonState (line 34) | class PersonState extends BasePersonState<PersonPage> {
method handleRefresh (line 58) | Future<void> handleRefresh()
method buildContainer (line 147) | Widget buildContainer(BuildContext context)
FILE: lib/page/user/widget/user_header.dart
class UserHeaderItem (line 23) | class UserHeaderItem extends StatelessWidget {
method renderOrgsItem (line 69) | renderOrgsItem(UserOrg orgs)
method build (line 206) | Widget build(BuildContext context)
class UserHeaderBottom (line 265) | class UserHeaderBottom extends StatelessWidget {
method build (line 301) | Widget build(BuildContext context)
class UserHeaderChart (line 408) | class UserHeaderChart extends StatelessWidget {
method build (line 458) | Widget build(BuildContext context)
FILE: lib/page/user/widget/user_item.dart
class UserItem (line 13) | class UserItem extends StatelessWidget {
method build (line 24) | Widget build(BuildContext context)
class UserItemViewModel (line 116) | class UserItemViewModel {
FILE: lib/page/user_profile_page.dart
class UserProfileInfo (line 22) | class UserProfileInfo extends StatefulWidget {
method createState (line 26) | _UserProfileState createState()
class _UserProfileState (line 29) | class _UserProfileState extends State<UserProfileInfo> {
method _renderList (line 81) | List<Widget> _renderList(User userInfo, Store store)
method build (line 122) | Widget build(BuildContext context)
FILE: lib/page/welcome_page.dart
class WelcomePage (line 21) | class WelcomePage extends ConsumerStatefulWidget {
method createState (line 27) | _WelcomePageState createState()
class _WelcomePageState (line 30) | class _WelcomePageState extends ConsumerState<WelcomePage> {
method didChangeDependencies (line 37) | void didChangeDependencies()
method build (line 71) | Widget build(BuildContext context)
FILE: lib/provider/app_state_provider.dart
class AppVibrationState (line 21) | @riverpod
method build (line 24) | bool build()
method changeVibration (line 29) | void changeVibration(bool enable, {bool save = true})
class AppGrepState (line 61) | @riverpod
method build (line 64) | bool build()
method changeGrey (line 66) | void changeGrey()
class AppLocalState (line 72) | @riverpod
method build (line 75) | Locale build()
method changeLocale (line 94) | void changeLocale(String? index)
class AppThemeState (line 103) | @riverpod
method build (line 106) | ThemeData build()
method pushTheme (line 110) | void pushTheme(String? index)
method _getThemeData (line 120) | ThemeData _getThemeData(Color color)
FILE: lib/provider/app_state_provider.g.dart
class AppVibrationStateProvider (line 15) | final class AppVibrationStateProvider
method debugGetCreateSourceHash (line 29) | String debugGetCreateSourceHash()
method create (line 33) | AppVibrationState create()
method overrideWithValue (line 36) | Override overrideWithValue(bool value)
function _$appVibrationStateHash (line 44) | String _$appVibrationStateHash()
class _$AppVibrationState (line 46) | abstract class _$AppVibrationState extends $Notifier<bool> {
method build (line 47) | bool build()
method runBuild (line 50) | void runBuild()
class AppGrepStateProvider (line 71) | final class AppGrepStateProvider extends $NotifierProvider<AppGrepState,...
method debugGetCreateSourceHash (line 85) | String debugGetCreateSourceHash()
method create (line 89) | AppGrepState create()
method overrideWithValue (line 92) | Override overrideWithValue(bool value)
function _$appGrepStateHash (line 100) | String _$appGrepStateHash()
class _$AppGrepState (line 104) | abstract class _$AppGrepState extends $Notifier<bool> {
method build (line 105) | bool build()
method runBuild (line 108) | void runBuild()
class AppLocalStateProvider (line 129) | final class AppLocalStateProvider
method debugGetCreateSourceHash (line 144) | String debugGetCreateSourceHash()
method create (line 148) | AppLocalState create()
method overrideWithValue (line 151) | Override overrideWithValue(Locale value)
function _$appLocalStateHash (line 159) | String _$appLocalStateHash()
class _$AppLocalState (line 163) | abstract class _$AppLocalState extends $Notifier<Locale> {
method build (line 164) | Locale build()
method runBuild (line 167) | void runBuild()
class AppThemeStateProvider (line 188) | final class AppThemeStateProvider
method debugGetCreateSourceHash (line 203) | String debugGetCreateSourceHash()
method create (line 207) | AppThemeState create()
method overrideWithValue (line 210) | Override overrideWithValue(ThemeData value)
function _$appThemeStateHash (line 218) | String _$appThemeStateHash()
class _$AppThemeState (line 222) | abstract class _$AppThemeState extends $Notifier<ThemeData> {
method build (line 223) | ThemeData build()
method runBuild (line 226) | void runBuild()
FILE: lib/redux/gsy_state.dart
class GSYState (line 17) | class GSYState {
function appReducer (line 34) | GSYState appReducer(GSYState state, action)
FILE: lib/redux/login_redux.dart
function _loginResult (line 27) | bool? _loginResult(bool? result, LoginSuccessAction action)
function _logoutResult (line 34) | bool? _logoutResult(bool? result, LogoutAction action)
class LoginSuccessAction (line 40) | class LoginSuccessAction {
class LogoutAction (line 47) | class LogoutAction {
class LoginAction (line 53) | class LoginAction {
class OAuthAction (line 61) | class OAuthAction {
class LoginMiddleware (line 69) | class LoginMiddleware implements MiddlewareClass<GSYState> {
method call (line 71) | void call(Store<GSYState> store, dynamic action, NextDispatcher next)
function loginEpic (line 84) | Stream<dynamic> loginEpic(Stream<dynamic> actions, EpicStore<GSYState> s...
function loginIn (line 85) | Stream<dynamic> loginIn(
function oauthEpic (line 100) | Stream<dynamic> oauthEpic(Stream<dynamic> actions, EpicStore<GSYState> s...
function loginIn (line 101) | Stream<dynamic> loginIn(
FILE: lib/redux/middleware/combine_epics.dart
function combineEpics (line 25) | Epic<State> combineEpics<State>(List<Epic<State>> epics)
FILE: lib/redux/middleware/epic.dart
type Epic (line 54) | typedef Epic<State> = Stream<dynamic> Function(
class EpicClass (line 77) | abstract class EpicClass<State> {
method call (line 78) | Stream<dynamic> call(
class TypedEpic (line 110) | class TypedEpic<State, Action> extends EpicClass<State> {
method call (line 119) | Stream<dynamic> call(Stream<dynamic> actions, EpicStore<State> store)
FILE: lib/redux/middleware/epic_middleware.dart
class EpicMiddleware (line 21) | class EpicMiddleware<State> extends MiddlewareClass<State> {
method call (line 35) | void call(Store<State> store, dynamic action, NextDispatcher next)
FILE: lib/redux/middleware/epic_store.dart
class EpicStore (line 9) | class EpicStore<State> {
method dispatch (line 20) | dynamic dispatch(dynamic action)
FILE: lib/redux/user_redux.dart
function _updateLoaded (line 27) | User? _updateLoaded(User? user, action)
class UpdateUserAction (line 34) | class UpdateUserAction {
class FetchUserAction (line 40) | class FetchUserAction {}
class UserInfoMiddleware (line 42) | class UserInfoMiddleware implements MiddlewareClass<GSYState> {
method call (line 44) | void call(Store<GSYState> store, dynamic action, NextDispatcher next)
function userInfoEpic (line 53) | Stream<dynamic> userInfoEpic(
function loadUserInfo (line 56) | Stream<dynamic> loadUserInfo()
FILE: lib/test/demo_app.dart
class DemoApp (line 4) | class DemoApp extends StatelessWidget {
method build (line 8) | Widget build(BuildContext context)
FILE: lib/test/demo_appbar.dart
class ImageAppbar (line 4) | class ImageAppbar extends StatelessWidget implements PreferredSizeWidget {
method build (line 27) | Widget build(BuildContext context)
FILE: lib/test/demo_bloc_page.dart
class LoginPage (line 7) | class LoginPage extends StatefulWidget {
method createState (line 11) | State createState()
class _LoginPageState (line 14) | class _LoginPageState extends State<LoginPage> with LoginBLoC {
method build (line 16) | Widget build(BuildContext context)
function initState (line 116) | void initState()
function dispose (line 124) | void dispose()
FILE: lib/test/demo_db.dart
class DemoSqlManager (line 15) | class DemoSqlManager {
method init (line 23) | init()
method isTableExits (line 34) | isTableExits(String tableName)
method getCurrentDatabase (line 41) | Future<Database?> getCurrentDatabase()
method close (line 49) | close()
class DemoBaseDbProvider (line 58) | abstract class DemoBaseDbProvider {
method getDataBase (line 72) | Future<Database> getDataBase()
class DemoUserInfoDbProvider (line 96) | class DemoUserInfoDbProvider extends DemoBaseDbProvider {
method toMap (line 109) | Map<String, dynamic> toMap(String userName, String data)
method _getUserProvider (line 138) | Future _getUserProvider(Database db, String userName)
method insert (line 149) | Future insert(String userName, String eventMapString)
method getUserInfo (line 162) | Future<User?> getUserInfo(String userName)
FILE: lib/test/demo_item.dart
class DemoItem (line 4) | class DemoItem extends StatelessWidget {
method build (line 54) | Widget build(BuildContext context)
FILE: lib/test/demo_mixins.dart
class Base (line 9) | abstract class Base {
class B (line 46) | class B extends Base {
class G (line 67) | class G extends B with A, A2 {
function testMixins (line 72) | testMixins()
FILE: lib/test/demo_page.dart
class DemoPage (line 3) | class DemoPage extends StatefulWidget {
method createState (line 7) | _DemoPageState createState()
class _DemoPageState (line 10) | class _DemoPageState extends State<DemoPage> {
method build (line 12) | Widget build(BuildContext context)
FILE: lib/test/demo_tab_page.dart
class DemoTabPage (line 3) | class DemoTabPage extends StatefulWidget {
method createState (line 7) | _DemoTabPageState createState()
class _DemoTabPageState (line 10) | class _DemoTabPageState extends State<DemoTabPage> {
method build (line 12) | Widget build(BuildContext context)
type TabType (line 57) | enum TabType { bottom, top }
class TabWidget (line 59) | class TabWidget extends StatefulWidget {
method createState (line 92) | _GSYTabBarState createState()
class _GSYTabBarState (line 95) | class _GSYTabBarState extends State<TabWidget>
method initState (line 98) | void initState()
method dispose (line 113) | void dispose()
method _getBottomNavByType (line 119) | Widget _getBottomNavByType()
method build (line 161) | Widget build(BuildContext context)
class KeepAliveList (line 199) | class KeepAliveList extends StatefulWidget {
method createState (line 203) | _KeepAliveListState createState()
class _KeepAliveListState (line 206) | class _KeepAliveListState extends State<KeepAliveList> with AutomaticKee...
method build (line 212) | Widget build(BuildContext context)
FILE: lib/test/demo_text_field_page.dart
class DemoTextFieldPage (line 4) | class DemoTextFieldPage extends StatefulWidget {
method createState (line 8) | _DemoTextFieldPageState createState()
class _DemoTextFieldPageState (line 11) | class _DemoTextFieldPageState extends State<DemoTextFieldPage> {
method build (line 16) | Widget build(BuildContext context)
FILE: lib/test/demo_user_store.dart
class DemoUseStorePage (line 10) | class DemoUseStorePage extends StatelessWidget {
method build (line 14) | Widget build(BuildContext context)
FILE: lib/test/demo_widget.dart
class DEMOWidget (line 7) | class DEMOWidget extends StatelessWidget {
method build (line 13) | Widget build(BuildContext context)
class DemoStateWidget (line 23) | class DemoStateWidget extends StatefulWidget {
method createState (line 30) | _DemoStateWidgetState createState()
class _DemoStateWidgetState (line 33) | class _DemoStateWidgetState extends State<DemoStateWidget> with Automati...
method initState (line 40) | void initState()
method dispose (line 46) | void dispose()
method didChangeDependencies (line 52) | void didChangeDependencies()
method build (line 68) | Widget build(BuildContext context)
FILE: lib/widget/animated_background.dart
type _ColorTween (line 5) | enum _ColorTween { color1, color2 }
class AnimatedBackground (line 7) | class AnimatedBackground extends StatelessWidget {
method build (line 11) | Widget build(BuildContext context)
FILE: lib/widget/diff_scale_text.dart
class DiffScaleText (line 5) | class DiffScaleText extends StatefulWidget {
method createState (line 13) | _DiffScaleTextState createState()
class _DiffScaleTextState (line 16) | class _DiffScaleTextState extends State<DiffScaleText>
method initState (line 21) | void initState()
method didUpdateWidget (line 29) | void didUpdateWidget(DiffScaleText oldWidget)
method dispose (line 40) | void dispose()
method build (line 46) | Widget build(BuildContext context)
class _DiffText (line 70) | class _DiffText extends CustomPainter {
method paint (line 83) | void paint(Canvas canvas, Size size)
method drawText (line 133) | void drawText(Canvas canvas, String? text, double textScaleFactor,
method shouldRepaint (line 161) | bool shouldRepaint(CustomPainter oldDelegate)
method calculateLayoutInfo (line 181) | void calculateLayoutInfo(String text, List<_TextLayoutInfo> list)
method calculateMove (line 208) | void calculateMove()
class _TextLayoutInfo (line 229) | class _TextLayoutInfo {
FILE: lib/widget/flutter_json_widget.dart
class JsonViewerWidget (line 5) | class JsonViewerWidget extends StatefulWidget {
method createState (line 12) | JsonViewerWidgetState createState()
class JsonViewerWidgetState (line 15) | class JsonViewerWidgetState extends State<JsonViewerWidget> {
method build (line 19) | Widget build(BuildContext context)
method getContentWidget (line 79) | getContentWidget(dynamic content)
method isInkWell (line 87) | isInkWell(dynamic content)
method isExtensible (line 171) | isExtensible(dynamic content)
method getTypeName (line 186) | getTypeName(dynamic content)
class JsonArrayViewerWidget (line 202) | class JsonArrayViewerWidget extends StatefulWidget {
method createState (line 210) | _JsonArrayViewerWidgetState createState()
class _JsonArrayViewerWidgetState (line 214) | class _JsonArrayViewerWidgetState extends State<JsonArrayViewerWidget> {
method build (line 218) | Widget build(BuildContext context)
method initState (line 231) | void initState()
FILE: lib/widget/gsy_bottom_action_bar.dart
class GSYBottomAppBar (line 3) | class GSYBottomAppBar extends StatelessWidget {
method build (line 23) | Widget build(BuildContext context)
FILE: lib/widget/gsy_card_item.dart
class GSYCardItem (line 7) | class GSYCardItem extends StatelessWidget {
method build (line 22) | Widget build(BuildContext context)
FILE: lib/widget/gsy_common_option_widget.dart
class GSYCommonOptionWidget (line 9) | class GSYCommonOptionWidget extends StatelessWidget {
method build (line 41) | Widget build(BuildContext context)
class GSYOptionModel (line 60) | class GSYOptionModel {
FILE: lib/widget/gsy_event_item.dart
class GSYEventItem (line 16) | class GSYEventItem extends StatelessWidget {
method build (line 27) | Widget build(BuildContext context)
class EventViewModel (line 81) | class EventViewModel {
FILE: lib/widget/gsy_flex_button.dart
class GSYFlexButton (line 6) | class GSYFlexButton extends StatelessWidget {
method build (line 31) | Widget build(BuildContext context)
FILE: lib/widget/gsy_icon_text.dart
class GSYIConText (line 6) | class GSYIConText extends StatelessWidget {
method build (line 41) | Widget build(BuildContext context)
FILE: lib/widget/gsy_input_widget.dart
class GSYInputWidget (line 4) | class GSYInputWidget extends StatefulWidget {
method createState (line 27) | _GSYInputWidgetState createState()
class _GSYInputWidgetState (line 31) | class _GSYInputWidgetState extends State<GSYInputWidget> {
method build (line 33) | Widget build(BuildContext context)
FILE: lib/widget/gsy_select_item_widget.dart
type SelectItemChanged (line 9) | typedef SelectItemChanged<int> = void Function(int value);
class GSYSelectItemWidget (line 11) | class GSYSelectItemWidget extends StatefulWidget
method createState (line 35) | _GSYSelectItemWidgetState createState()
class _GSYSelectItemWidgetState (line 43) | class _GSYSelectItemWidgetState extends State<GSYSelectItemWidget> {
method initState (line 52) | void initState()
method build (line 109) | Widget build(BuildContext context)
FILE: lib/widget/gsy_tabbar_widget.dart
class GSYTabBarWidget (line 7) | class GSYTabBarWidget extends StatefulWidget {
method createState (line 56) | _GSYTabBarState createState()
class _GSYTabBarState (line 59) | class _GSYTabBarState extends State<GSYTabBarWidget>
method initState (line 68) | void initState()
method dispose (line 76) | void dispose()
method build (line 108) | Widget build(BuildContext context)
type TabType (line 166) | enum TabType { top, bottom }
FILE: lib/widget/gsy_tabs.dart
type TabBarIndicatorSize (line 19) | enum TabBarIndicatorSize {
class Tab (line 43) | class Tab extends StatelessWidget {
method _buildLabelText (line 71) | Widget _buildLabelText()
method build (line 76) | Widget build(BuildContext context)
method debugFillProperties (line 112) | void debugFillProperties(DiagnosticPropertiesBuilder properties)
class _TabStyle (line 120) | class _TabStyle extends AnimatedWidget {
method build (line 139) | Widget build(BuildContext context)
type _LayoutCallback (line 183) | typedef _LayoutCallback = void Function(
class _TabLabelBarRenderer (line 186) | class _TabLabelBarRenderer extends RenderFlex {
method performLayout (line 200) | void performLayout()
class _TabLabelBar (line 231) | class _TabLabelBar extends Flex {
method createRenderObject (line 246) | RenderFlex createRenderObject(BuildContext context)
method updateRenderObject (line 259) | void updateRenderObject(
function _indexChangeProgress (line 266) | double _indexChangeProgress(TabController controller)
class _IndicatorPainter (line 282) | class _IndicatorPainter extends CustomPainter {
method markNeedsPaint (line 306) | void markNeedsPaint()
method dispose (line 310) | void dispose()
method saveTabOffsets (line 314) | void saveTabOffsets(List<double>? tabOffsets, TextDirection? textDirec...
method centerOf (line 323) | double centerOf(int tabIndex)
method indicatorRect (line 332) | Rect indicatorRect(Size tabBarSize, int tabIndex)
method paint (line 363) | void paint(Canvas canvas, Size size)
method _tabOffsetsEqual (line 407) | bool _tabOffsetsEqual(List<double>? a, List<double>? b)
method shouldRepaint (line 416) | bool shouldRepaint(_IndicatorPainter old)
class _ChangeAnimation (line 426) | class _ChangeAnimation extends Animation<double>
class _DragAnimation (line 441) | class _DragAnimation extends Animation<double>
class _TabBarScrollPosition (line 466) | class _TabBarScrollPosition extends ScrollPositionWithSingleContext {
method applyContentDimensions (line 481) | bool applyContentDimensions(double minScrollExtent, double maxScrollEx...
class _TabBarScrollController (line 503) | class _TabBarScrollController extends ScrollController {
method createScrollPosition (line 509) | ScrollPosition createScrollPosition(ScrollPhysics physics,
class TabBar (line 539) | class TabBar extends StatefulWidget implements PreferredSizeWidget {
method createState (line 718) | _TabBarState createState()
class _TabBarState (line 721) | class _TabBarState extends State<TabBar> {
method initState (line 730) | void initState()
method _updateTabController (line 769) | void _updateTabController()
method _initIndicatorPainter (line 787) | void _initIndicatorPainter()
method didChangeDependencies (line 801) | void didChangeDependencies()
method didUpdateWidget (line 809) | void didUpdateWidget(TabBar oldWidget)
method dispose (line 830) | void dispose()
method _tabScrollOffset (line 843) | double _tabScrollOffset(
method _tabCenteredScrollOffset (line 857) | double _tabCenteredScrollOffset(int? index)
method _initialScrollOffset (line 863) | double _initialScrollOffset(
method _scrollToCurrentIndex (line 868) | void _scrollToCurrentIndex()
method _scrollToControllerValue (line 874) | void _scrollToControllerValue()
method _handleTabControllerAnimationTick (line 906) | void _handleTabControllerAnimationTick()
method _handleTabControllerTick (line 915) | void _handleTabControllerTick()
method _saveTabOffsets (line 927) | void _saveTabOffsets(
method _handleTap (line 933) | void _handleTap(int index)
method _handleDoubleTap (line 941) | void _handleDoubleTap(int index)
method _buildStyledTab (line 949) | Widget _buildStyledTab(
method build (line 963) | Widget build(BuildContext context)
class TabBarView (line 1113) | class TabBarView extends StatefulWidget {
method createState (line 1152) | _TabBarViewState createState()
class _TabBarViewState (line 1158) | class _TabBarViewState extends State<TabBarView> {
method _updateTabController (line 1171) | void _updateTabController()
method initState (line 1187) | void initState()
method didChangeDependencies (line 1193) | void didChangeDependencies()
method didUpdateWidget (line 1201) | void didUpdateWidget(TabBarView oldWidget)
method dispose (line 1210) | void dispose()
method _updateChildren (line 1219) | void _updateChildren()
method _handleTabControllerAnimationTick (line 1224) | void _handleTabControllerAnimationTick()
method _warpToCurrentIndex (line 1235) | Future<void> _warpToCurrentIndex()
method _handleScrollNotification (line 1277) | bool _handleScrollNotification(ScrollNotification notification)
method build (line 1301) | Widget build(BuildContext context)
class TabPageSelectorIndicator (line 1327) | class TabPageSelectorIndicator extends StatelessWidget {
method build (line 1348) | Widget build(BuildContext context)
class TabPageSelector (line 1369) | class TabPageSelector extends StatelessWidget {
method _buildTabIndicator (line 1400) | Widget _buildTabIndicator(
method build (line 1439) | Widget build(BuildContext context)
FILE: lib/widget/gsy_title_bar.dart
class GSYTitleBar (line 6) | class GSYTitleBar extends StatelessWidget {
method build (line 26) | Widget build(BuildContext context)
FILE: lib/widget/gsy_user_icon_widget.dart
class GSYUserIconWidget (line 8) | class GSYUserIconWidget extends StatelessWidget {
method build (line 23) | Widget build(BuildContext context)
FILE: lib/widget/markdown/gsy_markdown_widget.dart
class GSYMarkdownWidget (line 21) | class GSYMarkdownWidget extends StatelessWidget {
method _processMarkdownImages (line 142) | String _processMarkdownImages(String markdownInput, String baseUrl)
method build (line 239) | Widget build(BuildContext context)
class GSYHighlighter (line 272) | class GSYHighlighter extends SyntaxHighlighter {
method format (line 274) | TextSpan format(String source)
function kDefaultImageBuilder (line 281) | Widget kDefaultImageBuilder(
function _handleDataSchemeUri (line 332) | Widget _handleDataSchemeUri(
function _isUrlPointingToSvgDio (line 357) | Future<bool> _isUrlPointingToSvgDio(String urlString,
FILE: lib/widget/markdown/syntax_high_lighter.dart
class SyntaxHighlighterStyle (line 5) | class SyntaxHighlighterStyle {
method defaultStyle (line 17) | SyntaxHighlighterStyle defaultStyle()
class SyntaxCostomHighlighter (line 42) | abstract class SyntaxCostomHighlighter {
method format (line 43) | TextSpan format(String src)
class DartSyntaxHighlighter (line 46) | class DartSyntaxHighlighter extends SyntaxCostomHighlighter {
method format (line 143) | TextSpan format(String src)
method _generateSpans (line 176) | bool _generateSpans()
method _simplify (line 356) | void _simplify()
method _firstLetterIsUpperCase (line 367) | bool _firstLetterIsUpperCase(String str)
type _HighlightType (line 376) | enum _HighlightType {
class _HighlightSpan (line 386) | class _HighlightSpan {
method textForSpan (line 393) | String textForSpan(String src)
method textStyle (line 397) | TextStyle? textStyle(SyntaxHighlighterStyle? style)
FILE: lib/widget/menu/src/arc_progress_indicator.dart
class ArcProgressIndicator (line 8) | class ArcProgressIndicator extends StatelessWidget {
method build (line 40) | Widget build(BuildContext context)
class _ArcProgressPainter (line 75) | class _ArcProgressPainter extends CustomPainter {
method paint (line 96) | void paint(Canvas canvas, Size size)
method shouldRepaint (line 125) | bool shouldRepaint(_ArcProgressPainter other)
FILE: lib/widget/menu/src/radial_menu.dart
type ItemAngleCalculator (line 13) | typedef ItemAngleCalculator = double Function(int index);
class RadialMenu (line 33) | class RadialMenu<T> extends StatefulWidget {
method createState (line 72) | RadialMenuState createState()
class RadialMenuState (line 75) | class RadialMenuState extends State<RadialMenu> with TickerProviderState...
method calculateItemAngle (line 83) | double calculateItemAngle(int index)
method initState (line 89) | void initState()
method dispose (line 102) | void dispose()
method _openMenu (line 108) | void _openMenu()
method _closeMenu (line 113) | void _closeMenu()
method _activate (line 118) | Future<void> _activate(int itemIndex)
method reset (line 128) | void reset()
method _buildActionButton (line 137) | Widget _buildActionButton(int index)
method _buildActiveAction (line 150) | Widget _buildActiveAction(int index)
method _buildCenterButton (line 166) | Widget _buildCenterButton()
method build (line 179) | Widget build(BuildContext context)
class _RadialMenuLayout (line 211) | class _RadialMenuLayout extends MultiChildLayoutDelegate {
method performLayout (line 235) | void performLayout(Size size)
method shouldRelayout (line 293) | bool shouldRelayout(_RadialMenuLayout oldDelegate)
FILE: lib/widget/menu/src/radial_menu_button.dart
class RadialMenuButton (line 3) | class RadialMenuButton extends StatelessWidget {
method build (line 15) | Widget build(BuildContext context)
FILE: lib/widget/menu/src/radial_menu_center_button.dart
class RadialMenuCenterButton (line 8) | class RadialMenuCenterButton extends StatelessWidget {
method build (line 80) | Widget build(BuildContext context)
FILE: lib/widget/menu/src/radial_menu_item.dart
class RadialMenuItem (line 9) | class RadialMenuItem<T> extends StatelessWidget {
method build (line 56) | Widget build(BuildContext context)
FILE: lib/widget/mole_widget.dart
class Mole (line 10) | class Mole extends StatefulWidget {
method createState (line 14) | _MoleState createState()
class _MoleState (line 17) | class _MoleState extends State<Mole> {
method initState (line 22) | void initState()
method build (line 31) | Widget build(BuildContext context)
method _buildMole (line 39) | Widget _buildMole()
method _mole (line 57) | Widget _mole()
method _restartMole (line 72) | void _restartMole()
method _setMoleVisible (line 90) | void _setMoleVisible(bool visible)
method setState (line 97) | void setState(fn)
type _MoleProps (line 104) | enum _MoleProps { x, y, scale }
class MoleParticle (line 106) | class MoleParticle {
method buildWidget (line 125) | Widget buildWidget()
method progress (line 144) | double progress()
FILE: lib/widget/never_overscroll_indicator.dart
class NeverOverScrollIndicator (line 4) | class NeverOverScrollIndicator extends StatelessWidget {
method build (line 12) | Widget build(BuildContext context)
class NeverOverScrollBehavior (line 20) | class NeverOverScrollBehavior extends ScrollBehavior {
method buildOverscrollIndicator (line 26) | Widget buildOverscrollIndicator(BuildContext context, Widget child, Sc...
method getScrollPhysics (line 31) | ScrollPhysics getScrollPhysics(BuildContext context)
FILE: lib/widget/only_share_widget.dart
class OnlyShareInstanceWidget (line 4) | class OnlyShareInstanceWidget<T> extends StatelessWidget {
method build (line 8) | Widget build(BuildContext context)
method of (line 12) | V? of<V>(BuildContext context)
class _OnlyShareInstanceModel (line 23) | class _OnlyShareInstanceModel<T> extends InheritedWidget {
method updateShouldNotify (line 30) | bool updateShouldNotify(_OnlyShareInstanceModel oldWidget)
FILE: lib/widget/particle/particle_model.dart
type ParticleOffsetProps (line 7) | enum ParticleOffsetProps { x, y }
class ParticleModel (line 9) | class ParticleModel {
method shuffle (line 38) | void shuffle()
method progress (line 50) | double progress()
FILE: lib/widget/particle/particle_painter.dart
class ParticlePainter (line 5) | class ParticlePainter extends CustomPainter {
method paint (line 11) | void paint(Canvas canvas, Size size)
method shouldRepaint (line 27) | bool shouldRepaint(CustomPainter oldDelegate)
FILE: lib/widget/particle/particle_widget.dart
class ParticlesWidget (line 9) | class ParticlesWidget extends StatefulWidget {
method createState (line 15) | _ParticlesWidgetState createState()
class _ParticlesWidgetState (line 18) | class _ParticlesWidgetState extends State<ParticlesWidget>
method initState (line 25) | void initState()
method didChangeAppLifecycleState (line 32) | void didChangeAppLifecycleState(AppLifecycleState state)
method build (line 43) | Widget build(BuildContext context)
FILE: lib/widget/pull/custom_bouncing_scroll_physics.dart
class CustomBouncingScrollPhysics (line 6) | class CustomBouncingScrollPhysics extends ScrollPhysics {
method applyTo (line 13) | CustomBouncingScrollPhysics applyTo(ScrollPhysics? ancestor)
method frictionFactor (line 17) | double frictionFactor(double overscrollFraction)
method applyPhysicsToUserOffset (line 21) | double applyPhysicsToUserOffset(ScrollMetrics position, double offset)
method _applyFriction (line 50) | double _applyFriction(
method applyBoundaryConditions (line 64) | double applyBoundaryConditions(ScrollMetrics position, double value)
method createBallisticSimulation (line 67) | Simulation? createBallisticSimulation(
method carriedMomentum (line 87) | double carriedMomentum(double existingVelocity)
FILE: lib/widget/pull/gsy_flare_mutli_pull_controller.dart
function initialize (line 20) | void initialize(FlutterActorArtboard artboard)
function setViewTransform (line 28) | void setViewTransform(Mat2D viewTransform)
function advance (line 31) | bool advance(FlutterActorArtboard artboard, double elapsed)
function onRefreshing (line 55) | void onRefreshing()
function onRefreshEnd (line 59) | void onRefreshEnd()
FILE: lib/widget/pull/gsy_flare_pull_controller.dart
function initialize (line 12) | void initialize(FlutterActorArtboard artboard)
function setViewTransform (line 17) | void setViewTransform(Mat2D viewTransform)
function advance (line 20) | bool advance(FlutterActorArtboard artboard, double elapsed)
FILE: lib/widget/pull/gsy_pull_load_widget.dart
class GSYPullLoadWidget (line 8) | class GSYPullLoadWidget extends StatefulWidget {
method createState (line 28) | _GSYPullLoadWidgetState createState()
class _GSYPullLoadWidgetState (line 31) | class _GSYPullLoadWidgetState extends State<GSYPullLoadWidget> {
method initState (line 35) | void initState()
method build (line 108) | Widget build(BuildContext context)
method _buildEmpty (line 134) | Widget _buildEmpty()
method _buildProgressIndicator (line 154) | Widget _buildProgressIndicator()
class GSYPullLoadWidgetControl (line 186) | class GSYPullLoadWidgetControl {
FILE: lib/widget/pull/gsy_pull_new_load_widget.dart
class GSYPullLoadWidget (line 17) | class GSYPullLoadWidget extends StatefulWidget {
method createState (line 45) | _GSYPullLoadWidgetState createState()
class _GSYPullLoadWidgetState (line 48) | class _GSYPullLoadWidgetState extends State<GSYPullLoadWidget>
method initState (line 65) | void initState()
method doDelayed (line 140) | doDelayed()
method handleRefresh (line 154) | Future<void> handleRefresh()
method handleLoadMore (line 172) | Future<void> handleLoadMore()
method build (line 190) | Widget build(BuildContext context)
method _buildEmpty (line 255) | Widget _buildEmpty()
method _buildProgressIndicator (line 275) | Widget _buildProgressIndicator()
method buildSimpleRefreshIndicator (line 314) | Widget buildSimpleRefreshIndicator(
class GSYPullLoadWidgetControl (line 351) | class GSYPullLoadWidgetControl extends ChangeNotifier {
FILE: lib/widget/pull/gsy_refresh_sliver.dart
class _CupertinoSliverRefresh (line 14) | class _CupertinoSliverRefresh extends SingleChildRenderObjectWidget {
method createRenderObject (line 31) | _RenderCupertinoSliverRefresh createRenderObject(BuildContext context)
method updateRenderObject (line 39) | void updateRenderObject(
class _RenderCupertinoSliverRefresh (line 55) | class _RenderCupertinoSliverRefresh extends RenderSliver
method performLayout (line 98) | void performLayout()
method paint (line 164) | void paint(PaintingContext paintContext, Offset offset)
method applyPaintTransform (line 174) | void applyPaintTransform(RenderObject child, Matrix4 transform)
type RefreshIndicatorMode (line 181) | enum RefreshIndicatorMode {
type RefreshControlIndicatorBuilder (line 209) | typedef RefreshControlIndicatorBuilder =
type RefreshCallback (line 222) | typedef RefreshCallback = Future<void> Function();
class CupertinoSliverRefreshControl (line 274) | class CupertinoSliverRefreshControl extends StatefulWidget {
method state (line 349) | RefreshIndicatorMode? state(BuildContext context)
method buildSimpleRefreshIndicator (line 359) | Widget buildSimpleRefreshIndicator(
method createState (line 393) | CupertinoSliverRefreshControlState createState()
class CupertinoSliverRefreshControlState (line 397) | class CupertinoSliverRefreshControlState
method initState (line 427) | void initState()
method transitionNextState (line 434) | RefreshIndicatorMode? transitionNextState()
method goToDone (line 437) | void goToDone()
method notifyScrollNotification (line 551) | void notifyScrollNotification(ScrollNotification notification)
method build (line 569) | Widget build(BuildContext context)
FILE: lib/widget/pull/nested/gsy_nested_pull_load_widget.dart
class GSYNestedPullLoadWidget (line 10) | class GSYNestedPullLoadWidget extends StatefulWidget {
method createState (line 36) | _GSYNestedPullLoadWidgetState createState()
class _GSYNestedPullLoadWidgetState (line 40) | class _GSYNestedPullLoadWidgetState extends State<GSYNestedPullLoadWidge...
method initState (line 42) | void initState()
method build (line 92) | Widget build(BuildContext context)
method _buildEmpty (line 127) | Widget _buildEmpty()
method _buildProgressIndicator (line 147) | Widget _buildProgressIndicator()
FILE: lib/widget/pull/nested/gsy_sliver_header_delegate.dart
class GSYSliverHeaderDelegate (line 7) | class GSYSliverHeaderDelegate extends SliverPersistentHeaderDelegate {
method build (line 33) | Widget build(
method shouldRebuild (line 45) | bool shouldRebuild(GSYSliverHeaderDelegate oldDelegate)
type Builder (line 53) | typedef Builder = Widget Function(
FILE: lib/widget/pull/nested/nested_refresh.dart
type _RefreshIndicatorMode (line 35) | enum _RefreshIndicatorMode {
type RefreshIndicatorTriggerMode (line 45) | enum RefreshIndicatorTriggerMode {
class NestedScrollViewRefreshIndicator (line 95) | class NestedScrollViewRefreshIndicator extends StatefulWidget {
method createState (line 204) | NestedScrollViewRefreshIndicatorState createState()
class NestedScrollViewRefreshIndicatorState (line 210) | class NestedScrollViewRefreshIndicatorState
method initState (line 233) | void initState()
method didChangeDependencies (line 245) | void didChangeDependencies()
method didUpdateWidget (line 259) | void didUpdateWidget(covariant NestedScrollViewRefreshIndicator oldWid...
method dispose (line 275) | void dispose()
method _shouldStart (line 281) | bool _shouldStart(ScrollNotification notification)
method _handleScrollNotification (line 295) | bool _handleScrollNotification(ScrollNotification notification)
method _handleGlowNotification (line 360) | bool _handleGlowNotification(OverscrollIndicatorNotification notificat...
method _start (line 369) | bool _start(AxisDirection direction)
method _checkDragOffset (line 392) | void _checkDragOffset(double containerExtent)
method _dismiss (line 408) | Future<void> _dismiss(_RefreshIndicatorMode newMode)
method _show (line 439) | void _show()
method show (line 482) | Future<void> show({bool atTop = true})
method build (line 492) | Widget build(BuildContext context)
function NestScrollNotificationPredicate (line 562) | bool NestScrollNotificationPredicate(ScrollNotification notification)
FILE: lib/widget/state/gsy_list_state.dart
function doDelayed (line 33) | doDelayed()
function handleRefresh (line 66) | Future<void> handleRefresh()
function onLoadMore (line 94) | Future<void> onLoadMore()
function initState (line 161) | void initState()
function dispose (line 172) | void dispose()
FILE: static/font/iconfont.js
function IEContentLoaded (line 1) | function IEContentLoaded(w,fn){var d=w.document,done=false,init=function...
function appendSvg (line 1) | function appendSvg(){var div,svg;div=document.createElement("div");div.i...
Condensed preview — 369 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,335K chars).
[
{
"path": ".fvmrc",
"chars": 25,
"preview": "{\n \"flutter\": \"3.38.4\"\n}"
},
{
"path": ".github/FUNDING.yml",
"chars": 93,
"preview": "# These are supported funding model platforms\n\ncustom: http://img.cdn.guoshuyu.cn/thanks.jpg\n"
},
{
"path": ".github/workflows/ci.yml",
"chars": 3544,
"preview": "name: CI\n\non:\n push:\n branches:\n - master\n tags:\n - '*'\n pull_request:\n paths-ignore:\n - '**/*"
},
{
"path": ".gitignore",
"chars": 820,
"preview": ".DS_Store\n.dart_tool/\n\n.packages\n.pub/\n\nbuild/\n\n.flutter-plugins\n.flutter-plugins-dependencies\n\n.gradle/\n\nignoreConfig.d"
},
{
"path": ".metadata",
"chars": 306,
"preview": "# This file tracks properties of this Flutter project.\n# Used by Flutter tool to assess capabilities and perform upgrade"
},
{
"path": ".vscode/settings.json",
"chars": 65,
"preview": "{\n \"java.configuration.updateBuildConfiguration\": \"disabled\"\n}"
},
{
"path": "AGENTS.md",
"chars": 1762,
"preview": "# GSY GitHub App Flutter 协作说明\n\n这是一个 Flutter GitHub 客户端,同时也是带有教学展示性质的示例工程。\n不要假设整个仓库是单一架构风格。多种状态管理方案并存是当前设计现实,不是偶然脏代码。\n\n##"
},
{
"path": "LICENSE",
"chars": 11357,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 17399,
"preview": "\n\n[](https://gi"
},
{
"path": "README_EN.md",
"chars": 18132,
"preview": "\n\n[](https://gi"
},
{
"path": "RECORD.md",
"chars": 3263,
"preview": "flutter build apk --target-platform android-arm64 -t lib/main_prod.dart --no-sound-null-safety\n\nflutter packages pub run"
},
{
"path": "UISCENE_PLUGIN_RISK.md",
"chars": 3422,
"preview": "# UIScene Plugin Risk Checklist\n\n- Project: `gsy_github_app_flutter`\n- Generated on: 2026-02-13\n- Scope: iOS plugins lis"
},
{
"path": "VERSION.md",
"chars": 1188,
"preview": "\n### 请直接看 github release \n\n### 1.1.9\n\n* 修正弹出键盘的时候被挤压问题\n* 修复切换主题导致长按输入框弹出异常\n* 修复其他小问题。\n\n\n### 1.1.8\n\n* 修复反馈输入框遮挡问题。\n* 更新部分"
},
{
"path": "analysis_options.yaml",
"chars": 329,
"preview": "include: package:flutter_lints/flutter.yaml\n\nanalyzer:\n errors:\n mixin_inherits_from_not_object: ignore\n plugins:\n "
},
{
"path": "android/.gitignore",
"chars": 142,
"preview": "*.iml\n*.class\n.gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\nGeneratedPlugin"
},
{
"path": "android/app/build.gradle",
"chars": 8015,
"preview": "plugins {\n id \"com.android.application\"\n id \"kotlin-android\"\n id \"dev.flutter.flutter-gradle-plugin\"\n}\n\ndef loc"
},
{
"path": "android/app/exported.gradle",
"chars": 2652,
"preview": "/**\n * 修改 Android 12 因为 exported 的构建问题,主要用于演示\n */\n\nandroid.applicationVariants.all { variant ->\n variant.outputs.each"
},
{
"path": "android/app/src/main/AndroidManifest.xml",
"chars": 3143,
"preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package=\"com.shuyu.gsygithub.gsygithubappflutte"
},
{
"path": "android/app/src/main/kotlin/com/shuyu/gsygithub/gsygithubappflutter/MainActivity.kt",
"chars": 498,
"preview": "package com.shuyu.gsygithub.gsygithubappflutter\n\nimport UpdateAlbumPlugin\nimport androidx.annotation.NonNull;\nimport io."
},
{
"path": "android/app/src/main/kotlin/com/shuyu/gsygithub/gsygithubappflutter/UpdateAlbumPlugin.kt",
"chars": 1707,
"preview": "import android.content.Context\nimport android.content.Intent\nimport android.net.Uri\nimport android.provider.MediaStore\ni"
},
{
"path": "android/app/src/main/res/drawable/launch_background.xml",
"chars": 397,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Modify this file to customize your launch splash screen -->\n<layer-list xmln"
},
{
"path": "android/app/src/main/res/drawable/normal_background.xml",
"chars": 239,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Modify this file to customize your launch splash screen -->\n<layer-list xmln"
},
{
"path": "android/app/src/main/res/values/styles.xml",
"chars": 771,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <style name=\"LaunchTheme\" parent=\"@android:style/Theme.Black.NoTi"
},
{
"path": "android/build.gradle",
"chars": 299,
"preview": "allprojects {\n repositories {\n google()\n }\n}\n\nrootProject.buildDir = '../build'\nsubprojects {\n project.b"
},
{
"path": "android/gradle/wrapper/gradle-wrapper.properties",
"chars": 203,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "android/gradle.properties",
"chars": 216,
"preview": "org.gradle.jvmargs=-Xmx4096M -Dfile.encoding=UTF-8\nandroid.useAndroidX=true\n#systemProp.http.proxyHost=127.0.0.1\n#system"
},
{
"path": "android/gradlew",
"chars": 4971,
"preview": "#!/usr/bin/env bash\n\n##############################################################################\n##\n## Gradle start "
},
{
"path": "android/gradlew.bat",
"chars": 2314,
"preview": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem "
},
{
"path": "android/settings.gradle",
"chars": 725,
"preview": "pluginManagement {\n def flutterSdkPath = {\n def properties = new Properties()\n file(\"local.properties\")"
},
{
"path": "devtools_options.yaml",
"chars": 184,
"preview": "description: This file stores settings for Dart & Flutter DevTools.\ndocumentation: https://docs.flutter.dev/tools/devtoo"
},
{
"path": "docs/00-overview/project-map.md",
"chars": 1152,
"preview": "# 项目地图\n\n## 项目定位\n\n`gsy_github_app_flutter` 是一个跨平台 GitHub 客户端。\n它既是完整功能应用,也是偏教学展示风格的工程,因此仓库中会刻意保留多种实现方式,而不是追求所有模块都完全统一。\n\n##"
},
{
"path": "docs/01-architecture/app-layering.md",
"chars": 1335,
"preview": "# 应用分层\n\n## 目的\n\n这个仓库不是严格单一架构实现,而是采用“整体分层明确、局部实现多样”的方式。\n协作者不需要强行统一写法,但需要尊重已有边界,避免把局部需求扩散成全局耦合。\n\n## 1. 入口与应用壳层\n\n- `lib/main"
},
{
"path": "docs/01-architecture/state-management-matrix.md",
"chars": 769,
"preview": "# 状态管理矩阵\n\n## 为什么要有这份文档\n\n这个项目刻意保留了多种状态管理方式用于展示和演进。\n这对学习有价值,但也意味着协作者和 agent 很容易“按自己的偏好”误改边界。\n这份文档的目的是停止猜测。\n\n## 当前分布\n\n### R"
},
{
"path": "docs/02-features/debug.md",
"chars": 515,
"preview": "# 调试页功能\n\n## 相关文件\n\n- `lib/page/debug/debug_data_page.dart`\n- `lib/page/debug/debug_label.dart`\n- `lib/common/net/intercep"
},
{
"path": "docs/02-features/dynamic.md",
"chars": 652,
"preview": "# 动态页功能\n\n## 相关文件\n\n- `lib/page/dynamic/dynamic_page.dart`\n- `lib/page/dynamic/dynamic_bloc.dart`\n- `lib/common/repositori"
},
{
"path": "docs/02-features/home.md",
"chars": 552,
"preview": "# 首页容器功能\n\n## 相关文件\n\n- `lib/page/home/home_page.dart`\n- `lib/page/home/widget/home_drawer.dart`\n- `lib/page/dynamic/dynami"
},
{
"path": "docs/02-features/issue.md",
"chars": 636,
"preview": "# Issue 功能\n\n## 相关文件\n\n- `lib/page/issue/issue_detail_page.dart`\n- `lib/page/issue/issue_edit_dIalog.dart`\n- `lib/common/r"
},
{
"path": "docs/02-features/login.md",
"chars": 880,
"preview": "# 登录功能\n\n## 相关文件\n\n- `lib/page/login/login_page.dart`\n- `lib/page/login/login_webview.dart`\n- `lib/redux/login_redux.dart`"
},
{
"path": "docs/02-features/notify.md",
"chars": 760,
"preview": "# 通知功能\n\n## 相关文件\n\n- `lib/page/notify/notify_page.dart`\n- `lib/common/repositories/user_repository.dart`\n- `lib/model/noti"
},
{
"path": "docs/02-features/push.md",
"chars": 627,
"preview": "# Push 提交详情功能\n\n## 相关文件\n\n- `lib/page/push/push_detail_page.dart`\n- `lib/page/push/widget/push_header.dart`\n- `lib/page/pu"
},
{
"path": "docs/02-features/release.md",
"chars": 646,
"preview": "# Release 功能\n\n## 相关文件\n\n- `lib/page/release/release_page.dart`\n- `lib/page/release/widget/release_item.dart`\n- `lib/commo"
},
{
"path": "docs/02-features/repos.md",
"chars": 1174,
"preview": "# 仓库详情功能\n\n## 相关文件\n\n- `lib/page/repos/repository_detail_page.dart`\n- `lib/page/repos/provider/repos_detail_provider.dart`"
},
{
"path": "docs/02-features/search.md",
"chars": 646,
"preview": "# 搜索功能\n\n## 相关文件\n\n- `lib/page/search/search_page.dart`\n- `lib/page/search/search_bloc.dart`\n- `lib/page/search/widget/gsy"
},
{
"path": "docs/02-features/trend.md",
"chars": 882,
"preview": "# 趋势功能\n\n## 相关文件\n\n- `lib/page/trend/trend_page.dart`\n- `lib/page/trend/trend_provider.dart`\n- `lib/page/trend/trend_user_"
},
{
"path": "docs/02-features/user.md",
"chars": 729,
"preview": "# 用户页功能\n\n## 相关文件\n\n- `lib/page/user/person_page.dart`\n- `lib/page/user/base_person_provider.dart`\n- `lib/page/user/base_p"
},
{
"path": "docs/03-runbooks/local-setup.md",
"chars": 853,
"preview": "# 本地开发环境\n\n## 基线要求\n\n- Flutter SDK:以仓库 README 和当前 workflow 为准\n- Java:Android 构建需要\n- Android 工具链:生成 APK 需要\n\n## 首次启动\n\n1. 安装 "
},
{
"path": "docs/04-quality/smoke-matrix.md",
"chars": 1611,
"preview": "# 手工回归矩阵\n\n## 目的\n\n仓库当前缺少自动化测试基线,因此需要一份最小可执行的手工回归矩阵。\n它的目标不是覆盖全部功能,而是覆盖最容易因局部改动而回归的主链路。\n\n## 使用方式\n\n- 改动前:确认本次变更影响哪些功能域\n- 改动后"
},
{
"path": "docs/04-quality/test-strategy.md",
"chars": 814,
"preview": "# 测试策略\n\n## 当前现状\n\n- 仓库目前没有提交进来的 `test/` 目录\n- [pubspec.yaml](/D:/workspace/project/gsy_github_app_flutter/pubspec.yaml) 中 "
},
{
"path": "docs/05-ai/agent-guide.md",
"chars": 1877,
"preview": "# Agent 工作指引\n\n## 目标\n\n做范围清晰、容易验证、方便评审的改动。\n不要把 agent 的“能改”误当成“应该改很多”。\n\n## 编辑前先读\n\n1. `AGENTS.md`\n2. `docs/00-overview/proje"
},
{
"path": "docs/05-ai/feature-playbooks/debug-change.md",
"chars": 392,
"preview": "# 功能模板:修改调试页相关功能\n\n## 开始前先读\n\n1. `docs/02-features/debug.md`\n2. `lib/common/net/AGENTS.md`\n\n## 优先定位\n\n- 调试页 UI:`lib/page/de"
},
{
"path": "docs/05-ai/feature-playbooks/dynamic-change.md",
"chars": 485,
"preview": "# 功能模板:修改动态页相关功能\n\n## 开始前先读\n\n1. `docs/02-features/dynamic.md`\n2. `docs/04-quality/smoke-matrix.md`\n3. `lib/page/AGENTS.md"
},
{
"path": "docs/05-ai/feature-playbooks/home-change.md",
"chars": 492,
"preview": "# 功能模板:修改首页容器相关功能\n\n## 开始前先读\n\n1. `docs/02-features/home.md`\n2. `docs/04-quality/smoke-matrix.md`\n3. `lib/page/AGENTS.md`\n"
},
{
"path": "docs/05-ai/feature-playbooks/issue-change.md",
"chars": 488,
"preview": "# 功能模板:修改 Issue 相关功能\n\n## 开始前先读\n\n1. `docs/02-features/issue.md`\n2. `docs/04-quality/smoke-matrix.md`\n3. `lib/page/AGENTS."
},
{
"path": "docs/05-ai/feature-playbooks/notify-change.md",
"chars": 908,
"preview": "# 功能模板:修改通知页相关功能\n\n## 适用场景\n\n- 修改通知列表展示\n- 调整未读/参与/全部筛选\n- 修复刷新、分页或已读状态问题\n- 扩展通知跳转行为\n\n## 开始前先读\n\n1. `docs/02-features/notify."
},
{
"path": "docs/05-ai/feature-playbooks/push-change.md",
"chars": 489,
"preview": "# 功能模板:修改 Push 提交详情相关功能\n\n## 开始前先读\n\n1. `docs/02-features/push.md`\n2. `docs/04-quality/smoke-matrix.md`\n3. `lib/page/AGENT"
},
{
"path": "docs/05-ai/feature-playbooks/release-change.md",
"chars": 489,
"preview": "# 功能模板:修改 Release 相关功能\n\n## 开始前先读\n\n1. `docs/02-features/release.md`\n2. `docs/04-quality/smoke-matrix.md`\n3. `lib/page/AGE"
},
{
"path": "docs/05-ai/feature-playbooks/repos-change.md",
"chars": 1296,
"preview": "# 功能模板:修改仓库详情相关功能\n\n## 适用场景\n\n- 修改仓库详情页 UI\n- 调整 Readme、Issue、文件列表其中一个 tab\n- 修改分支切换逻辑\n- 调整仓库详情底部按钮行为\n- 修复仓库详情页的联动刷新问题\n\n## 开"
},
{
"path": "docs/05-ai/feature-playbooks/search-change.md",
"chars": 487,
"preview": "# 功能模板:修改搜索相关功能\n\n## 开始前先读\n\n1. `docs/02-features/search.md`\n2. `docs/04-quality/smoke-matrix.md`\n3. `lib/page/AGENTS.md`\n"
},
{
"path": "docs/05-ai/feature-playbooks/trend-change.md",
"chars": 933,
"preview": "# 功能模板:修改趋势页相关功能\n\n## 适用场景\n\n- 趋势页列表展示改动\n- 时间和语言筛选改动\n- 刷新或首次加载问题\n- 趋势页跳转链路调整\n\n## 开始前先读\n\n1. `docs/02-features/trend.md`\n2. "
},
{
"path": "docs/05-ai/feature-playbooks/user-change.md",
"chars": 484,
"preview": "# 功能模板:修改用户页相关功能\n\n## 开始前先读\n\n1. `docs/02-features/user.md`\n2. `docs/04-quality/smoke-matrix.md`\n3. `lib/page/AGENTS.md`\n\n"
},
{
"path": "docs/05-ai/prompts/author-handoff.md",
"chars": 285,
"preview": "# Author Handoff Prompt\n\n你是 author agent。你已经完成实现,现在要把改动交给 reviewer agent。\n\n你的任务不是解释自己为什么对,而是提供一个尽量中立、最小、可验证的 review bund"
},
{
"path": "docs/05-ai/prompts/reviewer-system.md",
"chars": 599,
"preview": "# Reviewer System Prompt\n\n你是 reviewer agent,不是 author agent。\n\n你的职责是独立审查当前变更,优先发现问题、风险、回归和验证缺口。\n不要默认信任 author 的实现,也不要帮助 a"
},
{
"path": "docs/05-ai/review-harness.md",
"chars": 2037,
"preview": "# Review Harness\n\n## 目标\n\n让代码审查尽量摆脱 author 视角,避免“作者自己解释自己为什么没问题”。\n本仓库默认采用 `author agent` 和 `reviewer subagent` 分离的方式进行 AI"
},
{
"path": "docs/05-ai/task-playbooks/add-api.md",
"chars": 980,
"preview": "# 任务模板:新增接口或数据请求\n\n## 适用场景\n\n- 新增 REST 或 GraphQL 请求\n- 扩展已有 repository 的数据读取能力\n- 新增页面所需的数据接口\n\n## 开始前先确认\n\n1. 这是 REST 还是 Grap"
},
{
"path": "docs/05-ai/task-playbooks/add-page.md",
"chars": 1060,
"preview": "# 任务模板:新增页面\n\n## 适用场景\n\n- 新增一个页面或子页面\n- 新增一个现有功能下的详情页、列表页、设置页\n- 需要接入已有导航和数据链路\n\n## 开始前先确认\n\n1. 这是独立功能页,还是已有功能下的一个子页\n2. 页面需要页面"
},
{
"path": "docs/05-ai/task-playbooks/fix-bug.md",
"chars": 1080,
"preview": "# 任务模板:修复 Bug\n\n## 适用场景\n\n- 页面行为异常\n- 接口数据展示错误\n- 刷新、分页、跳转、状态同步问题\n- 某个已有功能回归\n\n## 开始前先确认\n\n1. Bug 属于哪个功能域\n2. 问题发生在 UI、状态层、repo"
},
{
"path": "docs/05-ai/task-playbooks/refactor-state.md",
"chars": 1041,
"preview": "# 任务模板:整理或重构状态\n\n## 适用场景\n\n- 页面状态过于分散\n- 同一功能出现重复状态源\n- 需要把局部状态收敛到当前模块既有状态容器\n- 明确批准的小范围状态整理\n\n## 开始前先确认\n\n1. 这是普通需求里的顺手整理,还是明确"
},
{
"path": "docs/06-decisions/ADR-0001-状态管理收敛策略.md",
"chars": 1449,
"preview": "# ADR-0001 状态管理收敛策略\n\n## 状态\n\n已采纳\n\n## 日期\n\n2026-03-10\n\n## 背景\n\n当前项目同时使用 Redux、Riverpod、Provider、Signals。\n这种并存状态来自历史演进和教学展示诉求"
},
{
"path": "docs/06-decisions/ADR-0002-新增功能默认状态方案.md",
"chars": 887,
"preview": "# ADR-0002 新增功能默认状态方案\n\n## 状态\n\n已采纳\n\n## 日期\n\n2026-03-10\n\n## 背景\n\n即使接受“当前存在多种状态管理方案”,团队和 agent 仍然需要一个面向新增功能的默认选择标准。\n否则每个新页面都可"
},
{
"path": "docs/06-decisions/README.md",
"chars": 120,
"preview": "# 决策记录\n\n这个目录用于保存 ADR 风格的长期决策。\n凡是“以后还会反复被问到”的架构选择,不要只留在代码评审历史里。\n\n后续适合记录的主题包括:\n\n- 状态管理收敛策略\n- CI 最小验证基线\n- 生成代码工作流\n- 功能目录约定\n"
},
{
"path": "docs/CONTRIBUTING_AI.md",
"chars": 2249,
"preview": "# AI 协作入口\n\n这个入口页用于帮助人和 agent 快速选择正确的文档路径。\n不要从根 README 直接跳进代码,先判断你当前属于哪类任务。\n\n## 如果你要修 Bug\n\n先读:\n\n1. `docs/05-ai/task-playb"
},
{
"path": "docs/README.md",
"chars": 940,
"preview": "# 文档索引\n\n这个目录同时服务于人类协作者和代码 agent。\n第一次进入仓库时,建议按顺序阅读,不要只看根 README 就直接改代码。\n\n## 推荐阅读顺序\n\n1. `00-overview/project-map.md`\n2. `0"
},
{
"path": "fastlane/metadata/android/en-US/full_description.txt",
"chars": 171,
"preview": "<p>The purpose of the project is to facilitate personal daily maintenance and access to Github, better immerse in the mu"
},
{
"path": "fastlane/metadata/android/en-US/short_description.txt",
"chars": 22,
"preview": "Third-party Github App"
},
{
"path": "ios/.gitignore",
"chars": 537,
"preview": ".idea/\n.vagrant/\n.sconsign.dblite\n.svn/\n\n.DS_Store\n*.swp\nprofile\n\nDerivedData/\nbuild/\nGeneratedPluginRegistrant.h\nGenera"
},
{
"path": "ios/Flutter/AppFrameworkInfo.plist",
"chars": 774,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "ios/Flutter/Debug.xcconfig",
"chars": 106,
"preview": "#include \"Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig\"\n#include \"Generated.xcconfig\"\n"
},
{
"path": "ios/Flutter/Release.xcconfig",
"chars": 108,
"preview": "#include \"Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig\"\n#include \"Generated.xcconfig\"\n"
},
{
"path": "ios/Flutter/ephemeral/flutter_lldb_helper.py",
"chars": 1276,
"preview": "#\n# Generated file, do not edit.\n#\n\nimport lldb\n\ndef handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_"
},
{
"path": "ios/Flutter/ephemeral/flutter_lldbinit",
"chars": 108,
"preview": "#\n# Generated file, do not edit.\n#\n\ncommand script import --relative-to-command-file flutter_lldb_helper.py\n"
},
{
"path": "ios/Podfile",
"chars": 1355,
"preview": "# Uncomment this line to define a global platform for your project\n# platform :ios, '13.0'\n\n# CocoaPods analytics sends "
},
{
"path": "ios/Runner/AppDelegate.swift",
"chars": 546,
"preview": "import UIKit\nimport Flutter\n\n@main\n@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {\n func d"
},
{
"path": "ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json",
"chars": 1466,
"preview": "{\n \"images\" : [\n {\n \"size\" : \"20x20\",\n \"idiom\" : \"iphone\",\n \"filename\" : \"40.png\",\n \"scale\" : \"2"
},
{
"path": "ios/Runner/Assets.xcassets/Contents.json",
"chars": 62,
"preview": "{\n \"info\" : {\n \"version\" : 1,\n \"author\" : \"xcode\"\n }\n}"
},
{
"path": "ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json",
"chars": 1017,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"iphone\",\n \"scale\" : \"1x\"\n },\n {\n \"idiom\" : \"iphone\",\n \"file"
},
{
"path": "ios/Runner/Base.lproj/LaunchScreen.storyboard",
"chars": 2377,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
},
{
"path": "ios/Runner/Base.lproj/Main.storyboard",
"chars": 1605,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
},
{
"path": "ios/Runner/Info.plist",
"chars": 3525,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "ios/Runner/Runner-Bridging-Header.h",
"chars": 38,
"preview": "#import \"GeneratedPluginRegistrant.h\"\n"
},
{
"path": "ios/Runner/SceneDelegate.swift",
"chars": 61,
"preview": "import Flutter\n\nclass SceneDelegate: FlutterSceneDelegate {}\n"
},
{
"path": "ios/Runner.xcodeproj/project.pbxproj",
"chars": 34164,
"preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 54;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
},
{
"path": "ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
"chars": 135,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n version = \"1.0\">\n <FileRef\n location = \"self:\">\n </FileRef"
},
{
"path": "ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
"chars": 238,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme",
"chars": 3477,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"1510\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "ios/Runner.xcworkspace/contents.xcworkspacedata",
"chars": 224,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n version = \"1.0\">\n <FileRef\n location = \"group:Runner.xcodepr"
},
{
"path": "ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
"chars": 238,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "l10n.yaml",
"chars": 116,
"preview": "arb-dir: lib/common/localization/l10n\ntemplate-arb-file: app_en.arb\noutput-localization-file: app_localizations.dart"
},
{
"path": "lib/app.dart",
"chars": 7205,
"preview": "import 'dart:async';\n\nimport 'package:flutter/material.dart';\nimport 'package:flutter_redux/flutter_redux.dart';\nimport "
},
{
"path": "lib/common/config/config.dart",
"chars": 805,
"preview": "class Config {\n // Private constructor to prevent instantiation\n Config._();\n\n static bool? DEBUG = true;\n\n static c"
},
{
"path": "lib/common/event/event_bus.dart",
"chars": 2415,
"preview": "import 'dart:async';\n\n/// Dispatches events to listeners using the Dart [Stream] API. The [EventBus]\n/// enables decoupl"
},
{
"path": "lib/common/event/http_error_event.dart",
"chars": 168,
"preview": "/// Created by guoshuyu\n/// Date: 2018-08-16\nlibrary;\n\nclass HttpErrorEvent {\n final int? code;\n\n final String message"
},
{
"path": "lib/common/event/index.dart",
"chars": 57,
"preview": "import 'event_bus.dart';\n\nEventBus eventBus = EventBus();"
},
{
"path": "lib/common/local/local_storage.dart",
"chars": 526,
"preview": "import 'package:shared_preferences/shared_preferences.dart';\n\n///SharedPreferences 本地存储\nclass LocalStorage {\n\n static s"
},
{
"path": "lib/common/localization/extension.dart",
"chars": 243,
"preview": "import 'package:flutter/material.dart';\nimport 'package:gsy_github_app_flutter/common/localization/l10n/app_localization"
},
{
"path": "lib/common/localization/l10n/app_en.arb",
"chars": 4833,
"preview": "{\n \"welcomeMessage\": \"Welcome To Flutter\",\n \"app_name\": \"GSYGithubApp\",\n \"app_ok\": \"ok\",\n \"app_cancel\": \"cancel\",\n "
},
{
"path": "lib/common/localization/l10n/app_ja.arb",
"chars": 4396,
"preview": "{\n \"welcomeMessage\": \"Flutterへようこそ\",\n \"app_name\": \"GSYGithubApp\",\n \"app_ok\": \"OK\",\n \"app_cancel\": \"キャンセル\",\n \"app_em"
},
{
"path": "lib/common/localization/l10n/app_ko.arb",
"chars": 4280,
"preview": "{\n \"welcomeMessage\": \"Flutter에 오신 것을 환영합니다\",\n \"app_name\": \"GSYGithubApp\",\n \"app_ok\": \"확인\",\n \"app_cancel\": \"취소\",\n \"a"
},
{
"path": "lib/common/localization/l10n/app_localizations.dart",
"chars": 25863,
"preview": "import 'dart:async';\n\nimport 'package:flutter/foundation.dart';\nimport 'package:flutter/widgets.dart';\nimport 'package:f"
},
{
"path": "lib/common/localization/l10n/app_localizations_en.dart",
"chars": 8430,
"preview": "// ignore: unused_import\nimport 'package:intl/intl.dart' as intl;\nimport 'app_localizations.dart';\n\n// ignore_for_file: "
},
{
"path": "lib/common/localization/l10n/app_localizations_ja.dart",
"chars": 7982,
"preview": "// ignore: unused_import\nimport 'package:intl/intl.dart' as intl;\nimport 'app_localizations.dart';\n\n// ignore_for_file: "
},
{
"path": "lib/common/localization/l10n/app_localizations_ko.dart",
"chars": 7858,
"preview": "// ignore: unused_import\nimport 'package:intl/intl.dart' as intl;\nimport 'app_localizations.dart';\n\n// ignore_for_file: "
},
{
"path": "lib/common/localization/l10n/app_localizations_zh.dart",
"chars": 7761,
"preview": "// ignore: unused_import\nimport 'package:intl/intl.dart' as intl;\nimport 'app_localizations.dart';\n\n// ignore_for_file: "
},
{
"path": "lib/common/localization/l10n/app_zh.arb",
"chars": 4182,
"preview": "{\n \"welcomeMessage\": \"Welcome To Flutter\",\n \"app_name\": \"GSYGithubApp\",\n \"app_ok\": \"确定\",\n \"app_cancel\": \"取消\",\n \"app"
},
{
"path": "lib/common/logger.dart",
"chars": 705,
"preview": "import 'package:flutter/foundation.dart';\nimport 'package:talker_flutter/talker_flutter.dart';\n\nfinal talker = TalkerFlu"
},
{
"path": "lib/common/net/AGENTS.md",
"chars": 389,
"preview": "# 网络层协作说明\n\n这个目录承接全局共享网络能力,是高风险区域。\n这里的改动通常会影响多个页面和 repository。\n\n## 修改前先确认\n\n- 这是协议层问题,还是某个功能模块自己的展示问题?\n- 改动是否应该优先收敛在 repos"
},
{
"path": "lib/common/net/address.dart",
"chars": 8205,
"preview": "import 'package:gsy_github_app_flutter/common/config/config.dart';\nimport 'package:gsy_github_app_flutter/common/config/"
},
{
"path": "lib/common/net/api.dart",
"chars": 3922,
"preview": "import 'package:dio/dio.dart';\nimport 'package:gsy_github_app_flutter/common/net/code.dart';\n\nimport 'dart:collection';\n"
},
{
"path": "lib/common/net/code.dart",
"chars": 770,
"preview": "import 'package:gsy_github_app_flutter/common/event/http_error_event.dart';\nimport 'package:gsy_github_app_flutter/commo"
},
{
"path": "lib/common/net/graphql/client.dart",
"chars": 1752,
"preview": "import 'package:graphql/client.dart';\nimport 'package:gsy_github_app_flutter/common/net/graphql/repositories.dart';\nimpo"
},
{
"path": "lib/common/net/graphql/repositories.dart",
"chars": 1089,
"preview": "const String readRepository = r'''\nquery getRepositoryDetail($owner:String!, $name:String!){\n repository(name: $name, o"
},
{
"path": "lib/common/net/graphql/users.dart",
"chars": 1423,
"preview": "const String readTrendUser = r'''\nquery getTrendUser($location: String!){\n search(type: USER, query: $location, first: "
},
{
"path": "lib/common/net/interceptors/error_interceptor.dart",
"chars": 1035,
"preview": "import 'package:connectivity_plus/connectivity_plus.dart';\nimport 'package:dio/dio.dart';\nimport 'package:gsy_github_app"
},
{
"path": "lib/common/net/interceptors/header_interceptor.dart",
"chars": 387,
"preview": "import 'package:dio/dio.dart';\n\n/// header拦截器\n/// Created by guoshuyu\n/// on 2019/3/23.\nclass HeaderInterceptors extends"
},
{
"path": "lib/common/net/interceptors/log_interceptor.dart",
"chars": 2885,
"preview": "// ignore_for_file: type_literal_in_constant_pattern\n\nimport 'package:dio/dio.dart';\nimport 'package:gsy_github_app_flut"
},
{
"path": "lib/common/net/interceptors/response_interceptor.dart",
"chars": 1103,
"preview": "import 'package:dio/dio.dart';\nimport 'package:gsy_github_app_flutter/common/logger.dart';\nimport 'package:gsy_github_ap"
},
{
"path": "lib/common/net/interceptors/token_interceptor.dart",
"chars": 1774,
"preview": "import 'package:dio/dio.dart';\nimport 'package:gsy_github_app_flutter/common/config/config.dart';\nimport 'package:gsy_gi"
},
{
"path": "lib/common/net/result_data.dart",
"chars": 206,
"preview": "/// 网络结果数据\n/// Created by guoshuyu\n/// Date: 2018-07-16\nclass ResultData {\n dynamic data;\n bool result;\n int? code;\n "
},
{
"path": "lib/common/net/transformer.dart",
"chars": 430,
"preview": "import 'package:built_value/iso_8601_date_time_serializer.dart';\nimport 'package:built_value/serializer.dart';\nimport 'p"
},
{
"path": "lib/common/net/transformer.g.dart",
"chars": 417,
"preview": "// GENERATED CODE - DO NOT MODIFY BY HAND\n\npart of 'transformer.dart';\n\n// *********************************************"
},
{
"path": "lib/common/net/trending/github_trending.dart",
"chars": 5092,
"preview": "// ignore_for_file: unnecessary_string_escapes\n\nimport 'package:dio/dio.dart';\nimport 'package:gsy_github_app_flutter/mo"
},
{
"path": "lib/common/repositories/data_result.dart",
"chars": 122,
"preview": "class DataResult {\n Object? data;\n bool result;\n Function? next;\n\n DataResult(this.data, this.result, {this.next});\n"
},
{
"path": "lib/common/repositories/event_repository.dart",
"chars": 2755,
"preview": "import 'dart:convert';\n\nimport 'package:gsy_github_app_flutter/db/provider/event/received_event_db_provider.dart';\nimpor"
},
{
"path": "lib/common/repositories/issue_repository.dart",
"chars": 8493,
"preview": "import 'dart:convert';\n\nimport 'package:dio/dio.dart';\nimport 'package:gsy_github_app_flutter/db/provider/issue/issue_co"
},
{
"path": "lib/common/repositories/repos_repository.dart",
"chars": 27727,
"preview": "import 'dart:async';\nimport 'dart:convert';\nimport 'dart:io';\n\nimport 'package:built_value/serializer.dart';\nimport 'pac"
},
{
"path": "lib/common/repositories/user_repository.dart",
"chars": 14589,
"preview": "import 'dart:convert';\nimport 'package:dio/dio.dart';\nimport 'package:flutter_riverpod/flutter_riverpod.dart';\nimport 'p"
},
{
"path": "lib/common/router/anima_route.dart",
"chars": 1689,
"preview": "import 'package:flutter/material.dart';\n\n///动画大小变化打开的路由\nclass SizeRoute extends PageRouteBuilder {\n final Widget? widge"
},
{
"path": "lib/common/style/gsy_style.dart",
"chars": 9178,
"preview": "import 'package:flutter/material.dart';\n\n///颜色\nclass GSYColors {\n static const int primaryIntValue = 0xFF24292E;\n\n sta"
},
{
"path": "lib/common/toast.dart",
"chars": 201,
"preview": "\nimport 'package:fluttertoast/fluttertoast.dart';\n\nshowToast(String message) {\n Fluttertoast.showToast(\n msg: mess"
},
{
"path": "lib/common/utils/code_utils.dart",
"chars": 342,
"preview": "import 'dart:convert';\n\n///isolate 的 compute 需要静态方法\nclass CodeUtils {\n static List<dynamic> decodeListResult(String? da"
},
{
"path": "lib/common/utils/common_utils.dart",
"chars": 15849,
"preview": "import 'dart:async';\nimport 'dart:convert';\nimport 'dart:io';\n\nimport 'package:device_info_plus/device_info_plus.dart';\n"
},
{
"path": "lib/common/utils/event_utils.dart",
"chars": 11397,
"preview": "import 'package:flutter/material.dart';\nimport 'package:gsy_github_app_flutter/common/repositories/repos_repository.dart"
},
{
"path": "lib/common/utils/html_utils.dart",
"chars": 8324,
"preview": "// ignore_for_file: unnecessary_string_escapes, prefer_adjacent_string_concatenation\n\nimport 'package:gsy_github_app_flu"
},
{
"path": "lib/common/utils/navigator_utils.dart",
"chars": 10041,
"preview": "import 'dart:async';\n\nimport 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\nimport 'package:g"
},
{
"path": "lib/db/provider/event/received_event_db_provider.dart",
"chars": 2020,
"preview": "import 'dart:async';\nimport 'package:flutter/foundation.dart';\nimport 'package:gsy_github_app_flutter/common/utils/code_"
},
{
"path": "lib/db/provider/event/user_event_db_provider.dart",
"chars": 2659,
"preview": "import 'dart:async';\nimport 'package:gsy_github_app_flutter/common/utils/code_utils.dart';\n\nimport 'package:flutter/foun"
},
{
"path": "lib/db/provider/issue/issue_comment_db_provider.dart",
"chars": 2994,
"preview": "import 'dart:async';\nimport 'package:gsy_github_app_flutter/common/utils/code_utils.dart';\n\nimport 'package:flutter/foun"
},
{
"path": "lib/db/provider/issue/issue_detail_db_provider.dart",
"chars": 2837,
"preview": "import 'dart:async';\nimport 'package:gsy_github_app_flutter/common/utils/code_utils.dart';\n\nimport 'package:flutter/foun"
},
{
"path": "lib/db/provider/repos/read_history_db_provider.dart",
"chars": 3344,
"preview": "import 'dart:async';\n\nimport 'package:flutter/foundation.dart';\nimport 'package:gsy_github_app_flutter/db/sql_provider.d"
},
{
"path": "lib/db/provider/repos/repository_branch_db_provider.dart",
"chars": 792,
"preview": "import 'package:gsy_github_app_flutter/db/sql_provider.dart';\n\n/// 仓库分支表\n/// Created by guoshuyu\n/// Date: 2018-08-07\n\nc"
},
{
"path": "lib/db/provider/repos/repository_commitInfo_detail_db_provider.dart",
"chars": 942,
"preview": "import 'package:gsy_github_app_flutter/db/sql_provider.dart';\n\n/// 仓库提交信息详情表\n/// Created by guoshuyu\n/// Date: 2018-08-0"
},
{
"path": "lib/db/provider/repos/repository_commits_db_provider.dart",
"chars": 2950,
"preview": "import 'dart:async';\nimport 'package:gsy_github_app_flutter/common/utils/code_utils.dart';\n\nimport 'package:flutter/foun"
},
{
"path": "lib/db/provider/repos/repository_detail_db_provider.dart",
"chars": 2478,
"preview": "import 'dart:async';\nimport 'package:gsy_github_app_flutter/common/utils/code_utils.dart';\n\nimport 'package:flutter/foun"
},
{
"path": "lib/db/provider/repos/repository_detail_readme_db_provider.dart",
"chars": 2509,
"preview": "import 'dart:async';\n\nimport 'package:gsy_github_app_flutter/db/sql_provider.dart';\nimport 'package:sqflite/sqflite.dart"
},
{
"path": "lib/db/provider/repos/repository_event_db_provider.dart",
"chars": 2576,
"preview": "import 'dart:async';\nimport 'package:gsy_github_app_flutter/common/utils/code_utils.dart';\n\nimport 'package:flutter/foun"
},
{
"path": "lib/db/provider/repos/repository_fork_db_provider.dart",
"chars": 2585,
"preview": "import 'dart:async';\nimport 'package:gsy_github_app_flutter/common/utils/code_utils.dart';\n\nimport 'package:flutter/foun"
},
{
"path": "lib/db/provider/repos/repository_issue_db_provider.dart",
"chars": 2896,
"preview": "import 'dart:async';\nimport 'package:gsy_github_app_flutter/common/utils/code_utils.dart';\n\nimport 'package:flutter/foun"
},
{
"path": "lib/db/provider/repos/repository_pulse_db_provider.dart",
"chars": 793,
"preview": "import 'package:gsy_github_app_flutter/db/sql_provider.dart';\n\n/// 仓库pulse表\n/// Created by guoshuyu\n/// Date: 2018-08-07"
},
{
"path": "lib/db/provider/repos/repository_star_db_provider.dart",
"chars": 2563,
"preview": "import 'dart:async';\nimport 'package:gsy_github_app_flutter/common/utils/code_utils.dart';\n\nimport 'package:flutter/foun"
},
{
"path": "lib/db/provider/repos/repository_watcher_db_provider.dart",
"chars": 2580,
"preview": "import 'dart:async';\nimport 'package:gsy_github_app_flutter/common/utils/code_utils.dart';\n\nimport 'package:flutter/foun"
},
{
"path": "lib/db/provider/repos/trend_repository_db_provider.dart",
"chars": 2593,
"preview": "import 'dart:async';\nimport 'package:gsy_github_app_flutter/common/utils/code_utils.dart';\n\nimport 'package:flutter/foun"
},
{
"path": "lib/db/provider/user/org_member_db_provider.dart",
"chars": 742,
"preview": "import 'package:gsy_github_app_flutter/db/sql_provider.dart';\n\n/// 用户关注表\n///\n/// Created by guoshuyu\n/// Date: 2018-08-0"
},
{
"path": "lib/db/provider/user/user_followed_db_provider.dart",
"chars": 2547,
"preview": "import 'dart:async';\nimport 'package:gsy_github_app_flutter/common/utils/code_utils.dart';\nimport 'package:flutter/found"
},
{
"path": "lib/db/provider/user/user_follower_db_provider.dart",
"chars": 2549,
"preview": "import 'dart:async';\nimport 'package:gsy_github_app_flutter/common/utils/code_utils.dart';\n\nimport 'package:flutter/foun"
},
{
"path": "lib/db/provider/user/user_orgs_db_provider.dart",
"chars": 2526,
"preview": "import 'dart:async';\nimport 'package:gsy_github_app_flutter/common/utils/code_utils.dart';\n\nimport 'package:flutter/foun"
},
{
"path": "lib/db/provider/user/user_repos_db_provider.dart",
"chars": 2545,
"preview": "import 'dart:async';\n\nimport 'package:flutter/foundation.dart';\nimport 'package:gsy_github_app_flutter/db/sql_provider.d"
},
{
"path": "lib/db/provider/user/user_stared_db_provider.dart",
"chars": 2551,
"preview": "import 'dart:async';\nimport 'package:gsy_github_app_flutter/common/utils/code_utils.dart';\n\nimport 'package:flutter/foun"
},
{
"path": "lib/db/provider/user/userinfo_db_provider.dart",
"chars": 2390,
"preview": "import 'dart:async';\nimport 'package:gsy_github_app_flutter/common/utils/code_utils.dart';\n\nimport 'package:flutter/foun"
},
{
"path": "lib/db/sql_manager.dart",
"chars": 1676,
"preview": "import 'dart:async';\nimport 'dart:io';\n\nimport 'package:gsy_github_app_flutter/common/repositories/user_repository.dart'"
},
{
"path": "lib/db/sql_provider.dart",
"chars": 983,
"preview": "import 'dart:async';\n\n/**\n * 数据库表\n * Created by guoshuyu\n * Date: 2018-08-03\n */\nimport 'package:gsy_github_app_flutter/"
},
{
"path": "lib/env/AGENTS.md",
"chars": 239,
"preview": "# 环境配置协作说明\n\n这个目录包含构建期环境配置和生成文件。\n错误修改会直接影响启动、构建或运行环境切换。\n\n## 工作规则\n\n- 优先改源配置,不要直接手改生成文件\n- 修改 env 结构后,记得重新生成相关输出\n- 不要把本地密钥写入"
},
{
"path": "lib/env/config_wrapper.dart",
"chars": 1174,
"preview": "import 'package:flutter/foundation.dart';\nimport 'package:flutter/material.dart';\nimport 'package:gsy_github_app_flutter"
},
{
"path": "lib/env/dev.dart",
"chars": 180,
"preview": "import 'package:json_annotation/json_annotation.dart';\n\npart 'dev.g.dart';\n\n@JsonLiteral('env_json_dev.json', asConst: t"
},
{
"path": "lib/env/dev.g.dart",
"chars": 304,
"preview": "// GENERATED CODE - DO NOT MODIFY BY HAND\n\npart of 'dev.dart';\n\n// *****************************************************"
},
{
"path": "lib/env/env_config.dart",
"chars": 330,
"preview": "import 'package:json_annotation/json_annotation.dart';\n\npart 'env_config.g.dart';\n\n///环境配置\n@JsonSerializable(createToJso"
},
{
"path": "lib/env/env_config.g.dart",
"chars": 392,
"preview": "// GENERATED CODE - DO NOT MODIFY BY HAND\n\npart of 'env_config.dart';\n\n// **********************************************"
},
{
"path": "lib/env/env_json_dev.json",
"chars": 35,
"preview": "{\n \"env\": \"dev\",\n \"debug\": true\n}"
},
{
"path": "lib/env/env_json_prod.json",
"chars": 37,
"preview": "{\n \"env\": \"prod\",\n \"debug\": false\n}"
},
{
"path": "lib/env/prod.dart",
"chars": 182,
"preview": "import 'package:json_annotation/json_annotation.dart';\n\npart 'prod.g.dart';\n\n@JsonLiteral('env_json_prod.json', asConst:"
},
{
"path": "lib/env/prod.g.dart",
"chars": 307,
"preview": "// GENERATED CODE - DO NOT MODIFY BY HAND\n\npart of 'prod.dart';\n\n// ****************************************************"
},
{
"path": "lib/main.dart",
"chars": 1111,
"preview": "import 'dart:async';\n\nimport 'package:flutter/gestures.dart';\nimport 'package:flutter/material.dart';\nimport 'package:gs"
},
{
"path": "lib/main_prod.dart",
"chars": 975,
"preview": "import 'dart:async';\n\nimport 'package:flutter/gestures.dart';\nimport 'package:flutter/material.dart';\nimport 'package:gs"
},
{
"path": "lib/model/branch.dart",
"chars": 500,
"preview": "import 'package:built_value/built_value.dart';\nimport 'package:built_value/serializer.dart';\n\npart 'branch.g.dart';\n\nabs"
},
{
"path": "lib/model/branch.g.dart",
"chars": 4961,
"preview": "// GENERATED CODE - DO NOT MODIFY BY HAND\n\npart of 'branch.dart';\n\n// **************************************************"
},
{
"path": "lib/model/commitFile.dart",
"chars": 829,
"preview": "import 'package:json_annotation/json_annotation.dart';\n\n/**\n * Created by guoshuyu\n * Date: 2018-07-31\n */\n\npart 'commit"
},
{
"path": "lib/model/commitFile.g.dart",
"chars": 1112,
"preview": "// GENERATED CODE - DO NOT MODIFY BY HAND\n\npart of 'commitFile.dart';\n\n// **********************************************"
},
{
"path": "lib/model/commit_comment.dart",
"chars": 913,
"preview": "import 'package:gsy_github_app_flutter/model/user.dart';\nimport 'package:json_annotation/json_annotation.dart';\n\n/**\n * "
},
{
"path": "lib/model/commit_comment.g.dart",
"chars": 1460,
"preview": "// GENERATED CODE - DO NOT MODIFY BY HAND\n\npart of 'commit_comment.dart';\n\n// ******************************************"
},
{
"path": "lib/model/commit_git_info.dart",
"chars": 671,
"preview": "import 'package:gsy_github_app_flutter/model/commit_git_user.dart';\nimport 'package:json_annotation/json_annotation.dart"
},
{
"path": "lib/model/commit_git_info.g.dart",
"chars": 999,
"preview": "// GENERATED CODE - DO NOT MODIFY BY HAND\n\npart of 'commit_git_info.dart';\n\n// *****************************************"
},
{
"path": "lib/model/commit_git_user.dart",
"chars": 447,
"preview": "import 'package:json_annotation/json_annotation.dart';\n\n/**\n * Created by guoshuyu\n * Date: 2018-07-31\n */\n\npart 'commit"
},
{
"path": "lib/model/commit_git_user.g.dart",
"chars": 704,
"preview": "// GENERATED CODE - DO NOT MODIFY BY HAND\n\npart of 'commit_git_user.dart';\n\n// *****************************************"
},
{
"path": "lib/model/commit_stats.dart",
"chars": 444,
"preview": "import 'package:json_annotation/json_annotation.dart';\n\n/**\n * Created by guoshuyu\n * Date: 2018-07-31\n */\n\npart 'commit"
},
{
"path": "lib/model/commit_stats.g.dart",
"chars": 661,
"preview": "// GENERATED CODE - DO NOT MODIFY BY HAND\n\npart of 'commit_stats.dart';\n\n// ********************************************"
},
{
"path": "lib/model/commits_comparison.dart",
"chars": 952,
"preview": "import 'package:gsy_github_app_flutter/model/commitFile.dart';\nimport 'package:json_annotation/json_annotation.dart';\n\ni"
},
{
"path": "lib/model/commits_comparison.g.dart",
"chars": 1494,
"preview": "// GENERATED CODE - DO NOT MODIFY BY HAND\n\npart of 'commits_comparison.dart';\n\n// **************************************"
},
{
"path": "lib/model/common_list_datatype.dart",
"chars": 447,
"preview": "enum CommonListDataType {\n follower(\"follower\"),\n followed(\"followed\"),\n userRepos('user_repos'),\n repoStar(\"repo_st"
},
{
"path": "lib/model/download_source.dart",
"chars": 505,
"preview": "import 'package:json_annotation/json_annotation.dart';\n\n/**\n * Created by guoshuyu\n * Date: 2018-07-31\n */\n\npart 'downlo"
},
{
"path": "lib/model/download_source.g.dart",
"chars": 729,
"preview": "// GENERATED CODE - DO NOT MODIFY BY HAND\n\npart of 'download_source.dart';\n\n// *****************************************"
},
{
"path": "lib/model/event.dart",
"chars": 763,
"preview": "import 'package:gsy_github_app_flutter/model/user.dart';\nimport 'package:json_annotation/json_annotation.dart';\n\nimport "
},
{
"path": "lib/model/event.g.dart",
"chars": 1212,
"preview": "// GENERATED CODE - DO NOT MODIFY BY HAND\n\npart of 'event.dart';\n\n// ***************************************************"
}
]
// ... and 169 more files (download for full content)
About this extraction
This page contains the full source code of the CarGuo/gsy_github_app_flutter GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 369 files (1.2 MB), approximately 354.4k tokens, and a symbol index with 1257 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.