├── .github └── FUNDING.yml ├── .gitignore ├── .metadata ├── 1.jpg ├── 2.jpg ├── 3.jpg ├── LICENSE ├── README.md ├── README_EN.md ├── RECORD.md ├── VERSION.md ├── analysis_options.yaml ├── android ├── .gitignore ├── app │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ └── com │ │ │ └── shuyu │ │ │ └── gsygithub │ │ │ └── gsygithubappflutter │ │ │ ├── MainActivity.kt │ │ │ └── UpdateAlbumPlugin.kt │ │ └── res │ │ ├── drawable │ │ └── launch_background.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── launch_image.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── launch_image.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── launch_image.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── launch_image.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── launch_image.png │ │ └── values │ │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── gsygithubapp-debug.jks └── settings.gradle ├── download.png ├── folder.png ├── framework2.png ├── ios.gif ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Podfile ├── Podfile.lock ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── WorkspaceSettings.xcsettings └── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── logo-2.png │ │ ├── logo-3.png │ │ ├── logo-4.png │ │ ├── logo2x-2.png │ │ ├── logo2x-3.png │ │ └── logo2x.png │ ├── Contents.json │ └── LaunchImage.imageset │ │ ├── Contents.json │ │ ├── Default@2x.png │ │ ├── Default@3x-1.png │ │ ├── Default@3x-2.png │ │ ├── Default@3x-3.png │ │ ├── Default@3x-4.png │ │ └── Default@3x.png │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h ├── ios_wait.png ├── lib ├── bloc │ ├── base │ │ └── base_bloc.dart │ ├── dynamic_bloc.dart │ └── trend_bloc.dart ├── common │ ├── ab │ │ ├── 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 │ ├── config │ │ └── config.dart │ ├── dao │ │ ├── dao_result.dart │ │ ├── event_dao.dart │ │ ├── issue_dao.dart │ │ ├── repos_dao.dart │ │ └── user_dao.dart │ ├── event │ │ └── http_error_event.dart │ ├── local │ │ └── local_storage.dart │ ├── localization │ │ ├── default_localizations.dart │ │ └── gsy_localizations_delegate.dart │ ├── model │ │ ├── Branch.dart │ │ ├── Branch.g.dart │ │ ├── CommitComment.dart │ │ ├── CommitComment.g.dart │ │ ├── CommitFile.dart │ │ ├── CommitFile.g.dart │ │ ├── CommitGitInfo.dart │ │ ├── CommitGitInfo.g.dart │ │ ├── CommitGitUser.dart │ │ ├── CommitGitUser.g.dart │ │ ├── CommitStats.dart │ │ ├── CommitStats.g.dart │ │ ├── CommitsComparison.dart │ │ ├── CommitsComparison.g.dart │ │ ├── DownloadSource.dart │ │ ├── DownloadSource.g.dart │ │ ├── Event.dart │ │ ├── Event.g.dart │ │ ├── EventPayload.dart │ │ ├── EventPayload.g.dart │ │ ├── FileModel.dart │ │ ├── FileModel.g.dart │ │ ├── Issue.dart │ │ ├── Issue.g.dart │ │ ├── IssueEvent.dart │ │ ├── IssueEvent.g.dart │ │ ├── License.dart │ │ ├── License.g.dart │ │ ├── Notification.dart │ │ ├── Notification.g.dart │ │ ├── NotificationSubject.dart │ │ ├── NotificationSubject.g.dart │ │ ├── PushCommit.dart │ │ ├── PushCommit.g.dart │ │ ├── PushEventCommit.dart │ │ ├── PushEventCommit.g.dart │ │ ├── Release.dart │ │ ├── Release.g.dart │ │ ├── ReleaseAsset.dart │ │ ├── ReleaseAsset.g.dart │ │ ├── RepoCommit.dart │ │ ├── RepoCommit.g.dart │ │ ├── Repository.dart │ │ ├── Repository.g.dart │ │ ├── RepositoryPermissions.dart │ │ ├── RepositoryPermissions.g.dart │ │ ├── Template.dart │ │ ├── Template.g.dart │ │ ├── TrendingRepoModel.dart │ │ ├── TrendingRepoModel.g.dart │ │ ├── User.dart │ │ ├── User.g.dart │ │ ├── UserOrg.dart │ │ └── UserOrg.g.dart │ ├── net │ │ ├── address.dart │ │ ├── api.dart │ │ ├── code.dart │ │ ├── interceptors │ │ │ ├── error_interceptor.dart │ │ │ ├── header_interceptor.dart │ │ │ ├── log_interceptor.dart │ │ │ ├── response_interceptor.dart │ │ │ └── token_interceptor.dart │ │ ├── result_data.dart │ │ └── trending │ │ │ └── github_trending.dart │ ├── redux │ │ ├── gsy_state.dart │ │ ├── locale_redux.dart │ │ ├── middleware │ │ │ ├── combine_epics.dart │ │ │ ├── epic.dart │ │ │ ├── epic_middleware.dart │ │ │ └── epic_store.dart │ │ ├── theme_redux.dart │ │ └── user_redux.dart │ ├── style │ │ ├── gsy_string_base.dart │ │ ├── gsy_string_en.dart │ │ ├── gsy_string_zh.dart │ │ └── gsy_style.dart │ └── utils │ │ ├── code_utils.dart │ │ ├── common_utils.dart │ │ ├── event_utils.dart │ │ ├── html_utils.dart │ │ └── navigator_utils.dart ├── main.dart ├── page │ ├── code_detail_page.dart │ ├── code_detail_page_web.dart │ ├── common_list_page.dart │ ├── dynamic_page.dart │ ├── gsy_webview.dart │ ├── home_page.dart │ ├── issue_detail_page.dart │ ├── login_page.dart │ ├── my_page.dart │ ├── notify_page.dart │ ├── person_page.dart │ ├── photoview_page.dart │ ├── push_detail_page.dart │ ├── release_page.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 │ ├── search_page.dart │ ├── trend_page.dart │ ├── user_profile_page.dart │ └── welcome_page.dart ├── test │ ├── demo_app.dart │ ├── demo_db.dart │ ├── demo_item.dart │ ├── demo_mixins.dart │ ├── demo_page.dart │ ├── demo_user_store.dart │ └── demo_widget.dart └── widget │ ├── base_person_state.dart │ ├── event_item.dart │ ├── gsy_bloc_list_state.dart │ ├── gsy_card_item.dart │ ├── gsy_common_option_widget.dart │ ├── gsy_flex_button.dart │ ├── gsy_icon_text.dart │ ├── gsy_input_widget.dart │ ├── gsy_list_state.dart │ ├── gsy_markdown_widget.dart │ ├── gsy_pull_load_widget.dart │ ├── gsy_pull_new_load_widget.dart │ ├── gsy_search_drawer.dart │ ├── gsy_search_input_widget.dart │ ├── gsy_select_item_widget.dart │ ├── gsy_tabbar_widget.dart │ ├── gsy_title_bar.dart │ ├── gsy_user_icon_widget.dart │ ├── home_drawer.dart │ ├── issue_edit_dIalog.dart │ ├── issue_header_item.dart │ ├── issue_item.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 │ ├── nested │ ├── gsy_nested_pull_load_widget.dart │ └── nested_refresh.dart │ ├── network_cache_image.dart │ ├── push_coed_item.dart │ ├── push_header.dart │ ├── release_item.dart │ ├── repos_header_item.dart │ ├── repos_item.dart │ ├── syntax_high_lighter.dart │ ├── user_header.dart │ └── user_item.dart ├── logo.png ├── pubspec.lock ├── pubspec.yaml ├── register0.jpg ├── register1.jpg ├── static ├── file │ ├── rejection.json │ └── rejection2.json ├── font │ ├── demo.css │ ├── demo_fontclass.html │ ├── demo_symbol.html │ ├── demo_unicode.html │ ├── iconfont.css │ ├── iconfont.eot │ ├── iconfont.js │ ├── iconfont.svg │ ├── iconfont.ttf │ └── iconfont.woff └── images │ ├── default_img.png │ ├── logo.png │ └── welcome.png ├── thanks.jpg └── theme.gif /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [CarGuo] 4 | custom: https://github.com/CarGuo/GSYVideoPlayer/blob/master/img/thanks.jpg 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | 4 | .packages 5 | .pub/ 6 | 7 | build/ 8 | 9 | .flutter-plugins 10 | 11 | *.iml 12 | 13 | .idea/ 14 | 15 | .gradle/ 16 | 17 | ignoreConfig.dart -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: c7ea3ca377e909469c68f2ab878a5bc53d3cf66b 8 | channel: beta 9 | -------------------------------------------------------------------------------- /1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/1.jpg -------------------------------------------------------------------------------- /2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/2.jpg -------------------------------------------------------------------------------- /3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/3.jpg -------------------------------------------------------------------------------- /VERSION.md: -------------------------------------------------------------------------------- 1 | 2 | ###(待处理) 3 | 4 | * 仓库Pulse。 5 | * markdown点击跳转。 6 | * webview点击跳转。 7 | * markdown htmlview 表格。 8 | * 版本信息列表 9 | * 监听滚动,设置底部和顶部隐藏显示 10 | 11 | ### 1.1.9 12 | 13 | * 修正弹出键盘的时候被挤压问题 14 | * 修复切换主题导致长按输入框弹出异常 15 | * 修复其他小问题。 16 | 17 | 18 | ### 1.1.8 19 | 20 | * 修复反馈输入框遮挡问题。 21 | * 更新部分插件,更新了 sdk 到 1.1.9 22 | 23 | ### 1.1.7 24 | 25 | * 更新flutter SDK 到 1.1.3 版本,修复TargetSDK 28以上在9.0键盘无法弹出问题。 26 | 27 | 28 | 29 | ### 1.1.6 30 | * flutter升级正式版1.0 31 | 32 | 33 | ### 1.1.5 34 | 35 | * Android 代码详情使用 AndroidView 实现WebView 36 | * 升级flutter Sdk 37 | * 升级第三方包 38 | 39 | ### 1.1.3 40 | * 修复详情tab切换问题。 41 | 42 | ### 1.1.2 43 | * 增加滑动返回。 44 | * 修复主页抽屉小屏幕无法滚动。 45 | * 增加部分代码高亮。 46 | * 修复搜索排序按键问题。 47 | * 更新flutter SDK 48 | 49 | 50 | ### 1.1.1 51 | * 更新flutter SDK 0.5.8。 52 | * 修复一些仓库下的readme问题。 53 | 54 | ### 1.1.0 55 | * 切换用户切换数据库。 56 | * 多语言。 57 | 58 | ### 1.0.9 59 | * 切换主题支持 60 | * 问题修复 61 | 62 | ### 1.0.8 63 | * readme图片解析优化 64 | * readme图片增加点击查看 65 | * 组织账号不显示活跃记录Item 66 | * 增加用户组织显示 67 | 68 | 69 | 70 | ### 1.0.7 71 | * 增加图片预览 72 | * 修复未读的通知打开提示其他异常 73 | * 增加fork仓库跳转到原仓库 74 | * 增加仓库点击展示 issue 状态信息 75 | * 增加个人状态信息可跳转 76 | * 增加仓库Topic显示 77 | * 通知中心增加侧滑点击已读 78 | 79 | ### 1.0.6 80 | * trend修改为redux 81 | * 增加本地阅读历史 82 | * drawer 状态栏样式处理 83 | * 增加个人动态提交表。 84 | 85 | ### 1.0.5 86 | * 增加本地数据库 87 | * 修复分享问题。 88 | * 修改用户页面样式 89 | * 增加用户加入github时间显示 90 | 91 | ### 1.0.4 92 | 93 | * 修复启动页变形问题。 94 | * 调整个人页面字体动态大小。 95 | * 增加趋势语言,搜索语言dart选项。 96 | * 增加前后台切换刷新动态。 97 | * 增加触摸隐藏键盘。 98 | * 增加点击检测版本。 99 | * 增加 issue 使用markdown解析 100 | * 增加 issue 输入框的快速输入按键。 101 | * 增加 issue 关闭操作信息。 102 | * 返回文件列表的返回键处理逻辑。 103 | * 修复详情中存在的model转化问题。 104 | 105 | 106 | ### 1.0.1 (已发布) 107 | 108 | * 修复loading弹出框黄线问题。 109 | * 调整部分ui。 110 | * 增加Release列表。 111 | * 增加版检测。 112 | * Issue详情页显示问题。 113 | * 返回按键退出问题。 114 | 115 | 116 | 117 | ### 1.0.0 118 | 119 | * 第一版完成 -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | analyzer: 2 | language: 3 | enableSuperMixins: true 4 | errors: 5 | mixin_inherits_from_not_object: ignore 6 | mixin_references_super: ignore -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | *.class 3 | .gradle 4 | /local.properties 5 | /.idea/workspace.xml 6 | /.idea/libraries 7 | .DS_Store 8 | /build 9 | /captures 10 | GeneratedPluginRegistrant.java 11 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | apply plugin: 'com.android.application' 15 | apply plugin: 'kotlin-android' 16 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 17 | 18 | android { 19 | compileSdkVersion 28 20 | 21 | sourceSets { 22 | main.java.srcDirs += 'src/main/kotlin' 23 | } 24 | 25 | lintOptions { 26 | disable 'InvalidPackage' 27 | } 28 | 29 | defaultConfig { 30 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 31 | applicationId "com.shuyu.gsygithub.gsygithubappflutter" 32 | minSdkVersion 16 33 | targetSdkVersion 28 34 | versionCode 22 35 | versionName "1.4.0" 36 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 37 | } 38 | 39 | 40 | signingConfigs { 41 | debug { 42 | storeFile file("../gsygithubapp-debug.jks") 43 | storePassword "123456" 44 | keyAlias "debug" 45 | keyPassword "123456" 46 | } 47 | release { 48 | storeFile file("../gsygithubapp-debug.jks") 49 | storePassword "123456" 50 | keyAlias "debug" 51 | keyPassword "123456" 52 | } 53 | } 54 | 55 | buildTypes { 56 | debug { 57 | signingConfig signingConfigs.debug 58 | } 59 | release { 60 | signingConfig signingConfigs.release 61 | } 62 | } 63 | lintOptions { 64 | abortOnError false 65 | } 66 | } 67 | 68 | flutter { 69 | source '../..' 70 | } 71 | 72 | dependencies { 73 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 74 | testImplementation 'junit:junit:4.12' 75 | androidTestImplementation 'com.android.support.test:runner:1.0.1' 76 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' 77 | } 78 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 11 | 16 | 20 | 27 | 31 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/shuyu/gsygithub/gsygithubappflutter/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.shuyu.gsygithub.gsygithubappflutter 2 | 3 | import android.os.Bundle 4 | 5 | import io.flutter.app.FlutterActivity 6 | import io.flutter.plugins.GeneratedPluginRegistrant 7 | 8 | class MainActivity(): FlutterActivity() { 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | GeneratedPluginRegistrant.registerWith(this) 12 | UpdateAlbumPlugin.register(this, flutterView) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/shuyu/gsygithub/gsygithubappflutter/UpdateAlbumPlugin.kt: -------------------------------------------------------------------------------- 1 | import android.content.Context 2 | import android.content.Intent 3 | import android.net.Uri 4 | import android.provider.MediaStore 5 | import io.flutter.plugin.common.BinaryMessenger 6 | import io.flutter.plugin.common.MethodChannel 7 | 8 | object UpdateAlbumPlugin { 9 | 10 | /** Channel名称 **/ 11 | private const val ChannelName = "com.shuyu.gsygithub.gsygithubflutter/UpdateAlbumPlugin" 12 | 13 | /** 14 | * 注册Toast插件 15 | * @param context 上下文对象 16 | * @param messenger 数据信息交流对象 17 | */ 18 | @JvmStatic 19 | fun register(context: Context, messenger: BinaryMessenger) = MethodChannel(messenger, ChannelName).setMethodCallHandler { methodCall, result -> 20 | when (methodCall.method) { 21 | "updateAlbum" -> { 22 | val path: String? = methodCall.argument("path") 23 | val name: String? = methodCall.argument("name") 24 | try { 25 | MediaStore.Images.Media.insertImage(context.contentResolver, path, name, null) 26 | } catch (e: Exception) { 27 | e.printStackTrace() 28 | } 29 | // 最后通知图库更新 30 | context.sendBroadcast(Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://$path"))) 31 | } 32 | } 33 | result.success(null) //没有返回值,所以直接返回为null 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/launch_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/android/app/src/main/res/mipmap-hdpi/launch_image.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/launch_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/android/app/src/main/res/mipmap-mdpi/launch_image.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/launch_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/android/app/src/main/res/mipmap-xhdpi/launch_image.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/launch_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/android/app/src/main/res/mipmap-xxhdpi/launch_image.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/launch_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/android/app/src/main/res/mipmap-xxxhdpi/launch_image.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.2.71' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.2.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip 7 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /android/gsygithubapp-debug.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/android/gsygithubapp-debug.jks -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/download.png -------------------------------------------------------------------------------- /folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/folder.png -------------------------------------------------------------------------------- /framework2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/framework2.png -------------------------------------------------------------------------------- /ios.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/ios.gif -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | .generated/ 16 | 17 | *.pbxuser 18 | *.mode1v3 19 | *.mode2v3 20 | *.perspectivev3 21 | 22 | !default.pbxuser 23 | !default.mode1v3 24 | !default.mode2v3 25 | !default.perspectivev3 26 | 27 | xcuserdata 28 | 29 | *.moved-aside 30 | 31 | *.pyc 32 | *sync/ 33 | Icon? 34 | .tags* 35 | 36 | /Flutter/app.flx 37 | /Flutter/app.zip 38 | /Flutter/flutter_assets/ 39 | /Flutter/App.framework 40 | /Flutter/Flutter.framework 41 | /Flutter/Generated.xcconfig 42 | /ServiceDefinitions.json 43 | 44 | Pods/ 45 | .symlinks/ 46 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | def parse_KV_file(file, separator='=') 8 | file_abs_path = File.expand_path(file) 9 | if !File.exists? file_abs_path 10 | return []; 11 | end 12 | pods_ary = [] 13 | skip_line_start_symbols = ["#", "/"] 14 | File.foreach(file_abs_path) { |line| 15 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } 16 | plugin = line.split(pattern=separator) 17 | if plugin.length == 2 18 | podname = plugin[0].strip() 19 | path = plugin[1].strip() 20 | podpath = File.expand_path("#{path}", file_abs_path) 21 | pods_ary.push({:name => podname, :path => podpath}); 22 | else 23 | puts "Invalid plugin specification: #{line}" 24 | end 25 | } 26 | return pods_ary 27 | end 28 | 29 | target 'Runner' do 30 | use_frameworks! 31 | 32 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock 33 | # referring to absolute paths on developers' machines. 34 | system('rm -rf .symlinks') 35 | system('mkdir -p .symlinks/plugins') 36 | 37 | # Flutter Pods 38 | generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig') 39 | if generated_xcode_build_settings.empty? 40 | puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first." 41 | end 42 | generated_xcode_build_settings.map { |p| 43 | if p[:name] == 'FLUTTER_FRAMEWORK_DIR' 44 | symlink = File.join('.symlinks', 'flutter') 45 | File.symlink(File.dirname(p[:path]), symlink) 46 | pod 'Flutter', :path => File.join(symlink, File.basename(p[:path])) 47 | end 48 | } 49 | 50 | # Plugin Pods 51 | plugin_pods = parse_KV_file('../.flutter-plugins') 52 | plugin_pods.map { |p| 53 | symlink = File.join('.symlinks', 'plugins', p[:name]) 54 | File.symlink(p[:path], symlink) 55 | pod p[:name], :path => File.join(symlink, 'ios') 56 | } 57 | end 58 | 59 | post_install do |installer| 60 | installer.pods_project.targets.each do |target| 61 | target.build_configurations.each do |config| 62 | config.build_settings['ENABLE_BITCODE'] = 'NO' 63 | end 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildSystemType 6 | Original 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "logo-2.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "logo2x-2.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "logo-3.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "logo2x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "logo2x-3.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "logo-4.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "idiom" : "iphone", 41 | "size" : "60x60", 42 | "scale" : "2x" 43 | }, 44 | { 45 | "idiom" : "iphone", 46 | "size" : "60x60", 47 | "scale" : "3x" 48 | }, 49 | { 50 | "idiom" : "ios-marketing", 51 | "size" : "1024x1024", 52 | "scale" : "1x" 53 | } 54 | ], 55 | "info" : { 56 | "version" : 1, 57 | "author" : "xcode" 58 | } 59 | } -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/logo-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/ios/Runner/Assets.xcassets/AppIcon.appiconset/logo-2.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/logo-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/ios/Runner/Assets.xcassets/AppIcon.appiconset/logo-3.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/logo-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/ios/Runner/Assets.xcassets/AppIcon.appiconset/logo-4.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/logo2x-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/ios/Runner/Assets.xcassets/AppIcon.appiconset/logo2x-2.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/logo2x-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/ios/Runner/Assets.xcassets/AppIcon.appiconset/logo2x-3.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/logo2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/ios/Runner/Assets.xcassets/AppIcon.appiconset/logo2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "iphone", 9 | "subtype" : "retina4", 10 | "scale" : "1x" 11 | }, 12 | { 13 | "idiom" : "iphone", 14 | "filename" : "Default@3x-1.png", 15 | "scale" : "2x" 16 | }, 17 | { 18 | "idiom" : "iphone", 19 | "filename" : "Default@3x-2.png", 20 | "subtype" : "retina4", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "filename" : "Default@2x.png", 26 | "subtype" : "667h", 27 | "scale" : "2x" 28 | }, 29 | { 30 | "idiom" : "iphone", 31 | "filename" : "Default@3x.png", 32 | "scale" : "3x" 33 | }, 34 | { 35 | "idiom" : "iphone", 36 | "filename" : "Default@3x-4.png", 37 | "subtype" : "retina4", 38 | "scale" : "3x" 39 | }, 40 | { 41 | "idiom" : "iphone", 42 | "subtype" : "736h", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "idiom" : "iphone", 47 | "filename" : "Default@3x-3.png", 48 | "subtype" : "2436h", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "idiom" : "iphone", 53 | "scale" : "2x", 54 | "unassigned" : true 55 | }, 56 | { 57 | "idiom" : "iphone", 58 | "unassigned" : true, 59 | "subtype" : "retina4", 60 | "scale" : "2x" 61 | } 62 | ], 63 | "info" : { 64 | "version" : 1, 65 | "author" : "xcode" 66 | } 67 | } -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/ios/Runner/Assets.xcassets/LaunchImage.imageset/Default@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Default@3x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/ios/Runner/Assets.xcassets/LaunchImage.imageset/Default@3x-1.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Default@3x-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/ios/Runner/Assets.xcassets/LaunchImage.imageset/Default@3x-2.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Default@3x-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/ios/Runner/Assets.xcassets/LaunchImage.imageset/Default@3x-3.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Default@3x-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/ios/Runner/Assets.xcassets/LaunchImage.imageset/Default@3x-4.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Default@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/ios/Runner/Assets.xcassets/LaunchImage.imageset/Default@3x.png -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | GSYGithubAppFlutter 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | GSYGithubAppFlutter 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.4.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 22 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSAllowsArbitraryLoads 30 | 31 | NSAllowsArbitraryLoadsInWebContent 32 | 33 | NSExceptionDomains 34 | 35 | localhost 36 | 37 | NSExceptionAllowsInsecureHTTPLoads 38 | 39 | 40 | 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIMainStoryboardFile 45 | Main 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UISupportedInterfaceOrientations~ipad 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationPortraitUpsideDown 56 | UIInterfaceOrientationLandscapeLeft 57 | UIInterfaceOrientationLandscapeRight 58 | 59 | UIViewControllerBasedStatusBarAppearance 60 | 61 | io.flutter.embedded_views_preview 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /ios_wait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/ios_wait.png -------------------------------------------------------------------------------- /lib/bloc/dynamic_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'package:gsy_github_app_flutter/bloc/base/base_bloc.dart'; 2 | import 'package:gsy_github_app_flutter/common/dao/event_dao.dart'; 3 | 4 | /** 5 | * Created by guoshuyu 6 | * on 2019/3/23. 7 | */ 8 | class DynamicBloc extends BlocListBase { 9 | requestRefresh(String userName) async { 10 | pageReset(); 11 | var res = await EventDao.getEventReceived(userName, page: page, needDb: true); 12 | changeLoadMoreStatus(getLoadMoreStatus(res)); 13 | refreshData(res); 14 | await doNext(res); 15 | return res; 16 | } 17 | 18 | requestLoadMore(String userName) async { 19 | pageUp(); 20 | var res = await EventDao.getEventReceived(userName, page: page); 21 | changeLoadMoreStatus(getLoadMoreStatus(res)); 22 | loadMoreData(res); 23 | return res; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /lib/bloc/trend_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'package:gsy_github_app_flutter/common/dao/repos_dao.dart'; 2 | import 'package:gsy_github_app_flutter/common/model/TrendingRepoModel.dart'; 3 | import 'package:rxdart/rxdart.dart'; 4 | 5 | /** 6 | * Created by guoshuyu 7 | * on 2019/3/23. 8 | */ 9 | class TrendBloc { 10 | bool _requested = false; 11 | 12 | bool _isLoading = false; 13 | 14 | ///是否正在loading 15 | bool get isLoading => _isLoading; 16 | 17 | ///是否已经请求过 18 | bool get requested => _requested; 19 | 20 | ///rxdart 实现的 stream 21 | var _subject = PublishSubject>(); 22 | 23 | Observable> get stream => _subject.stream; 24 | 25 | ///根据数据库和网络返回数据 26 | Future requestRefresh(selectTime, selectType) async { 27 | _isLoading = true; 28 | //_subject.add([]); 29 | var res = await ReposDao.getTrendDao(since: selectTime.value, languageType: selectType.value); 30 | if (res != null && res.result) { 31 | _subject.add(res.data); 32 | } 33 | await doNext(res); 34 | _isLoading = false; 35 | _requested = true; 36 | return; 37 | } 38 | 39 | ///请求next,是否有网络 40 | doNext(res) async { 41 | if (res.next != null) { 42 | var resNext = await res.next; 43 | if (resNext != null && resNext.result) { 44 | if (res != null && res.result) { 45 | _subject.add(res.data); 46 | } 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/common/ab/provider/event/received_event_db_provider.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter/foundation.dart'; 3 | import 'package:gsy_github_app_flutter/common/utils/code_utils.dart'; 4 | import 'package:gsy_github_app_flutter/common/ab/sql_provider.dart'; 5 | import 'package:gsy_github_app_flutter/common/model/Event.dart'; 6 | import 'package:sqflite/sqflite.dart'; 7 | 8 | /** 9 | * 用户接受事件表 10 | * Created by guoshuyu 11 | * Date: 2018-08-07 12 | */ 13 | 14 | class ReceivedEventDbProvider extends BaseDbProvider { 15 | final String name = 'ReceivedEvent'; 16 | 17 | final String columnId = "_id"; 18 | final String columnData = "data"; 19 | 20 | int id; 21 | String data; 22 | 23 | ReceivedEventDbProvider(); 24 | 25 | Map toMap(String eventMapString) { 26 | Map map = {columnData: eventMapString}; 27 | if (id != null) { 28 | map[columnId] = id; 29 | } 30 | return map; 31 | } 32 | 33 | ReceivedEventDbProvider.fromMap(Map map) { 34 | id = map[columnId]; 35 | data = map[columnData]; 36 | } 37 | 38 | @override 39 | tableSqlString() { 40 | return tableBaseString(name, columnId) + 41 | ''' 42 | $columnData text not null) 43 | '''; 44 | } 45 | 46 | @override 47 | tableName() { 48 | return name; 49 | } 50 | 51 | ///插入到数据库 52 | Future insert(String eventMapString) async { 53 | Database db = await getDataBase(); 54 | 55 | ///清空后再插入,因为只保存第一页面 56 | db.execute("delete from $name"); 57 | return await db.insert(name, toMap(eventMapString)); 58 | } 59 | 60 | ///获取事件数据 61 | Future> getEvents() async { 62 | Database db = await getDataBase(); 63 | List maps = await db.query(name, columns: [columnId, columnData]); 64 | List list = new List(); 65 | if (maps.length > 0) { 66 | ReceivedEventDbProvider provider = ReceivedEventDbProvider.fromMap(maps.first); 67 | 68 | ///使用 compute 的 Isolate 优化 json decode 69 | List eventMap = await compute(CodeUtils.decodeListResult, provider.data); 70 | 71 | if (eventMap.length > 0) { 72 | for (var item in eventMap) { 73 | list.add(Event.fromJson(item)); 74 | } 75 | } 76 | } 77 | return list; 78 | } 79 | } -------------------------------------------------------------------------------- /lib/common/ab/provider/event/user_event_db_provider.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:gsy_github_app_flutter/common/utils/code_utils.dart'; 3 | 4 | import 'package:flutter/foundation.dart'; 5 | import 'package:gsy_github_app_flutter/common/ab/sql_provider.dart'; 6 | import 'package:gsy_github_app_flutter/common/model/Event.dart'; 7 | import 'package:sqflite/sqflite.dart'; 8 | 9 | /** 10 | * 用户动态表 11 | * Created by guoshuyu 12 | * Date: 2018-08-07 13 | */ 14 | 15 | class UserEventDbProvider extends BaseDbProvider { 16 | final String name = 'UserEvent'; 17 | 18 | final String columnId = "_id"; 19 | final String columnUserName = "userName"; 20 | final String columnData = "data"; 21 | 22 | int id; 23 | String userName; 24 | String data; 25 | 26 | UserEventDbProvider(); 27 | 28 | Map toMap(String userName, String eventMapString) { 29 | Map map = {columnUserName: userName, columnData: eventMapString}; 30 | if (id != null) { 31 | map[columnId] = id; 32 | } 33 | return map; 34 | } 35 | 36 | UserEventDbProvider.fromMap(Map map) { 37 | id = map[columnId]; 38 | userName = map[columnUserName]; 39 | data = map[columnData]; 40 | } 41 | 42 | @override 43 | tableSqlString() { 44 | return tableBaseString(name, columnId) + 45 | ''' 46 | $columnUserName text not null, 47 | $columnData text not null) 48 | '''; 49 | } 50 | 51 | @override 52 | tableName() { 53 | return name; 54 | } 55 | 56 | Future _getProvider(Database db, String userName) async { 57 | List maps = await db.query(name, columns: [columnId, columnData, columnUserName], where: "$columnUserName = ?", whereArgs: [userName]); 58 | if (maps.length > 0) { 59 | UserEventDbProvider provider = UserEventDbProvider.fromMap(maps.first); 60 | return provider; 61 | } 62 | return null; 63 | } 64 | 65 | ///插入到数据库 66 | Future insert(String userName, String eventMapString) async { 67 | Database db = await getDataBase(); 68 | var provider = await _getProvider(db, userName); 69 | if (provider != null) { 70 | await db.delete(name, where: "$columnUserName = ?", whereArgs: [userName]); 71 | } 72 | return await db.insert(name, toMap(userName, eventMapString)); 73 | } 74 | 75 | ///获取事件数据 76 | Future> getEvents(userName) async { 77 | Database db = await getDataBase(); 78 | var provider = await _getProvider(db, userName); 79 | if (provider != null) { 80 | List list = new List(); 81 | 82 | ///使用 compute 的 Isolate 优化 json decode 83 | List eventMap = await compute(CodeUtils.decodeListResult, provider.data as String); 84 | 85 | if (eventMap.length > 0) { 86 | for (var item in eventMap) { 87 | list.add(Event.fromJson(item)); 88 | } 89 | } 90 | return list; 91 | } 92 | return null; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /lib/common/ab/provider/repos/repository_branch_db_provider.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:gsy_github_app_flutter/common/ab/sql_provider.dart'; 3 | 4 | /** 5 | * 仓库分支表 6 | * Created by guoshuyu 7 | * Date: 2018-08-07 8 | */ 9 | 10 | class RepositoryBranchDbProvider extends BaseDbProvider { 11 | final String name = 'RepositoryPulse'; 12 | final String columnId = "_id"; 13 | final String columnFullName = "fullName"; 14 | final String columnData = "data"; 15 | 16 | int id; 17 | String fullName; 18 | String data; 19 | 20 | Map toMap() { 21 | Map map = {columnFullName: fullName, columnData: data}; 22 | if (id != null) { 23 | map[columnId] = id; 24 | } 25 | return map; 26 | } 27 | 28 | RepositoryBranchDbProvider.fromMap(Map map) { 29 | id = map[columnId]; 30 | fullName = map[columnFullName]; 31 | data = map[columnData]; 32 | } 33 | 34 | @override 35 | tableSqlString() {} 36 | 37 | @override 38 | tableName() { 39 | return name; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/common/ab/provider/repos/repository_commitInfo_detail_db_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:gsy_github_app_flutter/common/ab/sql_provider.dart'; 2 | 3 | /** 4 | * 仓库提交信息详情表 5 | * Created by guoshuyu 6 | * Date: 2018-08-07 7 | */ 8 | 9 | class RepositoryCommitInfoDetailDbProvider extends BaseDbProvider { 10 | final String name = 'RepositoryCommitInfoDetail'; 11 | int id; 12 | String fullName; 13 | String data; 14 | String sha; 15 | 16 | final String columnId = "_id"; 17 | final String columnFullName = "fullName"; 18 | final String columnSha = "sha"; 19 | final String columnData = "data"; 20 | 21 | Map toMap() { 22 | Map map = {columnFullName: fullName, columnSha: sha, columnData: data}; 23 | if (id != null) { 24 | map[columnId] = id; 25 | } 26 | return map; 27 | } 28 | 29 | RepositoryCommitInfoDetailDbProvider.fromMap(Map map) { 30 | id = map[columnId]; 31 | fullName = map[columnFullName]; 32 | sha = map[columnSha]; 33 | data = map[columnData]; 34 | } 35 | 36 | @override 37 | tableSqlString() {} 38 | 39 | @override 40 | tableName() { 41 | return name; 42 | } 43 | } -------------------------------------------------------------------------------- /lib/common/ab/provider/repos/repository_detail_db_provider.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:gsy_github_app_flutter/common/utils/code_utils.dart'; 3 | 4 | import 'package:flutter/foundation.dart'; 5 | import 'package:gsy_github_app_flutter/common/ab/sql_provider.dart'; 6 | import 'package:gsy_github_app_flutter/common/model/Repository.dart'; 7 | import 'package:sqflite/sqflite.dart'; 8 | 9 | /** 10 | * 仓库详情数据表 11 | * Created by guoshuyu 12 | * Date: 2018-08-07 13 | */ 14 | class RepositoryDetailDbProvider extends BaseDbProvider { 15 | final String name = 'RepositoryDetail'; 16 | int id; 17 | String fullName; 18 | String data; 19 | 20 | final String columnId = "_id"; 21 | final String columnFullName = "fullName"; 22 | final String columnData = "data"; 23 | 24 | RepositoryDetailDbProvider(); 25 | 26 | Map toMap(String fullName, String dataMapString) { 27 | Map map = {columnFullName: fullName, columnData: dataMapString}; 28 | if (id != null) { 29 | map[columnId] = id; 30 | } 31 | return map; 32 | } 33 | 34 | RepositoryDetailDbProvider.fromMap(Map map) { 35 | id = map[columnId]; 36 | fullName = map[columnFullName]; 37 | data = map[columnData]; 38 | } 39 | 40 | @override 41 | tableSqlString() { 42 | return tableBaseString(name, columnId) + 43 | ''' 44 | $columnFullName text not null, 45 | $columnData text not null) 46 | '''; 47 | } 48 | 49 | @override 50 | tableName() { 51 | return name; 52 | } 53 | 54 | 55 | Future _getProvider(Database db, String fullName) async { 56 | List> maps = 57 | await db.query(name, columns: [columnId, columnFullName, columnData], where: "$columnFullName = ?", whereArgs: [fullName]); 58 | if (maps.length > 0) { 59 | RepositoryDetailDbProvider provider = RepositoryDetailDbProvider.fromMap(maps.first); 60 | return provider; 61 | } 62 | return null; 63 | } 64 | 65 | ///插入到数据库 66 | Future insert(String fullName, String dataMapString) async { 67 | Database db = await getDataBase(); 68 | var provider = await _getProvider(db, fullName); 69 | if (provider != null) { 70 | await db.delete(name, where: "$columnFullName = ?", whereArgs: [fullName]); 71 | } 72 | return await db.insert(name, toMap(fullName, dataMapString)); 73 | } 74 | 75 | ///获取详情 76 | Future getRepository(String fullName) async { 77 | Database db = await getDataBase(); 78 | var provider = await _getProvider(db, fullName); 79 | if (provider != null) { 80 | 81 | 82 | ///使用 compute 的 Isolate 优化 json decode 83 | var mapData = await compute(CodeUtils.decodeMapResult, provider.data as String); 84 | 85 | return Repository.fromJson(mapData); 86 | } 87 | return null; 88 | } 89 | 90 | 91 | } 92 | -------------------------------------------------------------------------------- /lib/common/ab/provider/repos/repository_detail_readme_db_provider.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:gsy_github_app_flutter/common/ab/sql_provider.dart'; 4 | import 'package:sqflite/sqflite.dart'; 5 | 6 | /** 7 | * 仓库readme文件表 8 | * Created by guoshuyu 9 | * Date: 2018-08-07 10 | */ 11 | 12 | class RepositoryDetailReadmeDbProvider extends BaseDbProvider { 13 | final String name = 'RepositoryDetailReadme'; 14 | int id; 15 | String fullName; 16 | String data; 17 | String branch; 18 | 19 | final String columnId = "_id"; 20 | final String columnFullName = "fullName"; 21 | final String columnBranch = "branch"; 22 | final String columnData = "data"; 23 | 24 | RepositoryDetailReadmeDbProvider(); 25 | 26 | Map toMap(String fullName, String branch, String dataMapString) { 27 | Map map = {columnFullName: fullName, columnBranch: branch, columnData: dataMapString}; 28 | if (id != null) { 29 | map[columnId] = id; 30 | } 31 | return map; 32 | } 33 | 34 | RepositoryDetailReadmeDbProvider.fromMap(Map map) { 35 | id = map[columnId]; 36 | fullName = map[columnFullName]; 37 | branch = map[columnBranch]; 38 | data = map[columnData]; 39 | } 40 | @override 41 | tableSqlString() { 42 | return tableBaseString(name, columnId) + 43 | ''' 44 | $columnFullName text not null, 45 | $columnBranch text not null, 46 | $columnData text not null) 47 | '''; 48 | } 49 | 50 | @override 51 | tableName() { 52 | return name; 53 | } 54 | 55 | 56 | Future _getProvider(Database db, String fullName, String branch) async { 57 | List> maps = 58 | await db.query(name, columns: [columnId, columnFullName, columnData], where: "$columnFullName = ? and $columnBranch = ?", whereArgs: [fullName, branch]); 59 | if (maps.length > 0) { 60 | RepositoryDetailReadmeDbProvider provider = RepositoryDetailReadmeDbProvider.fromMap(maps.first); 61 | return provider; 62 | } 63 | return null; 64 | } 65 | 66 | ///插入到数据库 67 | Future insert(String fullName, String branch, String dataMapString) async { 68 | Database db = await getDataBase(); 69 | var provider = await _getProvider(db, fullName, branch); 70 | if (provider != null) { 71 | await db.delete(name, where: "$columnFullName = ? and $columnBranch = ?", whereArgs: [fullName, branch]); 72 | } 73 | return await db.insert(name, toMap(fullName, branch, dataMapString)); 74 | } 75 | 76 | ///获取readme详情 77 | Future getRepositoryReadme(String fullName, String branch) async { 78 | Database db = await getDataBase(); 79 | var provider = await _getProvider(db, fullName, branch); 80 | if (provider != null) { 81 | return provider.data; 82 | } 83 | return null; 84 | } 85 | 86 | } -------------------------------------------------------------------------------- /lib/common/ab/provider/repos/repository_event_db_provider.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:gsy_github_app_flutter/common/utils/code_utils.dart'; 3 | 4 | import 'package:flutter/foundation.dart'; 5 | import 'package:gsy_github_app_flutter/common/ab/sql_provider.dart'; 6 | import 'package:gsy_github_app_flutter/common/model/Event.dart'; 7 | import 'package:sqflite/sqflite.dart'; 8 | 9 | /** 10 | * 仓库活跃事件表 11 | * Created by guoshuyu 12 | * Date: 2018-08-07 13 | */ 14 | 15 | class RepositoryEventDbProvider extends BaseDbProvider { 16 | final String name = 'RepositoryEvent'; 17 | 18 | final String columnId = "_id"; 19 | final String columnFullName = "fullName"; 20 | final String columnData = "data"; 21 | 22 | int id; 23 | String fullName; 24 | String data; 25 | 26 | RepositoryEventDbProvider(); 27 | 28 | Map toMap(String fullName, String data) { 29 | Map map = {columnFullName: fullName, columnData: data}; 30 | if (id != null) { 31 | map[columnId] = id; 32 | } 33 | return map; 34 | } 35 | 36 | RepositoryEventDbProvider.fromMap(Map map) { 37 | id = map[columnId]; 38 | fullName = map[columnFullName]; 39 | data = map[columnData]; 40 | } 41 | 42 | @override 43 | tableSqlString() { 44 | return tableBaseString(name, columnId) + 45 | ''' 46 | $columnFullName text not null, 47 | $columnData text not null) 48 | '''; 49 | } 50 | 51 | @override 52 | tableName() { 53 | return name; 54 | } 55 | 56 | Future _getProvider(Database db, String fullName) async { 57 | List> maps = 58 | await db.query(name, columns: [columnId, columnFullName, columnData], where: "$columnFullName = ?", whereArgs: [fullName]); 59 | if (maps.length > 0) { 60 | RepositoryEventDbProvider provider = RepositoryEventDbProvider.fromMap(maps.first); 61 | return provider; 62 | } 63 | return null; 64 | } 65 | 66 | ///插入到数据库 67 | Future insert(String fullName, String dataMapString) async { 68 | Database db = await getDataBase(); 69 | var provider = await _getProvider(db, fullName); 70 | if (provider != null) { 71 | await db.delete(name, where: "$columnFullName = ?", whereArgs: [fullName]); 72 | } 73 | return await db.insert(name, toMap(fullName, dataMapString)); 74 | } 75 | 76 | ///获取事件数据 77 | Future> getEvents(String fullName) async { 78 | Database db = await getDataBase(); 79 | 80 | var provider = await _getProvider(db, fullName); 81 | if (provider != null) { 82 | List list = new List(); 83 | 84 | ///使用 compute 的 Isolate 优化 json decode 85 | List eventMap = await compute(CodeUtils.decodeListResult, provider.data as String); 86 | 87 | 88 | if (eventMap.length > 0) { 89 | for (var item in eventMap) { 90 | list.add(Event.fromJson(item)); 91 | } 92 | } 93 | return list; 94 | } 95 | return null; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /lib/common/ab/provider/repos/repository_fork_db_provider.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:gsy_github_app_flutter/common/utils/code_utils.dart'; 3 | 4 | import 'package:flutter/foundation.dart'; 5 | import 'package:gsy_github_app_flutter/common/ab/sql_provider.dart'; 6 | import 'package:gsy_github_app_flutter/common/model/Repository.dart'; 7 | import 'package:sqflite/sqflite.dart'; 8 | 9 | /** 10 | * 仓库分支表 11 | * Created by guoshuyu 12 | * Date: 2018-08-07 13 | */ 14 | 15 | class RepositoryForkDbProvider extends BaseDbProvider { 16 | final String name = 'RepositoryFork'; 17 | 18 | final String columnId = "_id"; 19 | final String columnFullName = "fullName"; 20 | final String columnData = "data"; 21 | 22 | int id; 23 | String fullName; 24 | String data; 25 | 26 | RepositoryForkDbProvider(); 27 | 28 | Map toMap(String fullName, String data) { 29 | Map map = {columnFullName: fullName, columnData: data}; 30 | if (id != null) { 31 | map[columnId] = id; 32 | } 33 | return map; 34 | } 35 | 36 | RepositoryForkDbProvider.fromMap(Map map) { 37 | id = map[columnId]; 38 | fullName = map[columnFullName]; 39 | data = map[columnData]; 40 | } 41 | 42 | @override 43 | tableSqlString() { 44 | return tableBaseString(name, columnId) + 45 | ''' 46 | $columnFullName text not null, 47 | $columnData text not null) 48 | '''; 49 | } 50 | 51 | @override 52 | tableName() { 53 | return name; 54 | } 55 | 56 | Future _getProvider(Database db, String fullName) async { 57 | List> maps = 58 | await db.query(name, columns: [columnId, columnFullName, columnData], where: "$columnFullName = ?", whereArgs: [fullName]); 59 | if (maps.length > 0) { 60 | RepositoryForkDbProvider provider = RepositoryForkDbProvider.fromMap(maps.first); 61 | return provider; 62 | } 63 | return null; 64 | } 65 | 66 | ///插入到数据库 67 | Future insert(String fullName, String dataMapString) async { 68 | Database db = await getDataBase(); 69 | var provider = await _getProvider(db, fullName); 70 | if (provider != null) { 71 | await db.delete(name, where: "$columnFullName = ?", whereArgs: [fullName]); 72 | } 73 | return await db.insert(name, toMap(fullName, dataMapString)); 74 | } 75 | 76 | ///获取事件数据 77 | Future> geData(String fullName) async { 78 | Database db = await getDataBase(); 79 | 80 | var provider = await _getProvider(db, fullName); 81 | if (provider != null) { 82 | List list = new List(); 83 | 84 | ///使用 compute 的 Isolate 优化 json decode 85 | List eventMap = await compute(CodeUtils.decodeListResult, provider.data as String); 86 | 87 | if (eventMap.length > 0) { 88 | for (var item in eventMap) { 89 | list.add(Repository.fromJson(item)); 90 | } 91 | } 92 | return list; 93 | } 94 | return null; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /lib/common/ab/provider/repos/repository_pulse_db_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:gsy_github_app_flutter/common/ab/sql_provider.dart'; 2 | 3 | /** 4 | * 仓库pulse表 5 | * Created by guoshuyu 6 | * Date: 2018-08-07 7 | */ 8 | 9 | class RepositoryPulseDbProvider extends BaseDbProvider { 10 | final String name = 'RepositoryPulse'; 11 | final String columnId = "_id"; 12 | final String columnFullName = "fullName"; 13 | final String columnData = "data"; 14 | 15 | int id; 16 | String fullName; 17 | String data; 18 | 19 | Map toMap() { 20 | Map map = {columnFullName: fullName, columnData: data}; 21 | if (id != null) { 22 | map[columnId] = id; 23 | } 24 | return map; 25 | } 26 | 27 | RepositoryPulseDbProvider.fromMap(Map map) { 28 | id = map[columnId]; 29 | fullName = map[columnFullName]; 30 | data = map[columnData]; 31 | } 32 | 33 | @override 34 | tableSqlString() {} 35 | 36 | @override 37 | tableName() { 38 | return name; 39 | } 40 | } -------------------------------------------------------------------------------- /lib/common/ab/provider/repos/repository_star_db_provider.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'dart:async'; 3 | import 'package:gsy_github_app_flutter/common/utils/code_utils.dart'; 4 | 5 | import 'package:flutter/foundation.dart'; 6 | import 'package:gsy_github_app_flutter/common/ab/sql_provider.dart'; 7 | import 'package:gsy_github_app_flutter/common/model/User.dart'; 8 | import 'package:sqflite/sqflite.dart'; 9 | 10 | /** 11 | * 仓库收藏用户表 12 | * Created by guoshuyu 13 | * Date: 2018-08-07 14 | */ 15 | 16 | class RepositoryStarDbProvider extends BaseDbProvider { 17 | final String name = 'RepositoryStar'; 18 | 19 | final String columnId = "_id"; 20 | final String columnFullName = "fullName"; 21 | final String columnData = "data"; 22 | 23 | int id; 24 | String fullName; 25 | String data; 26 | 27 | 28 | RepositoryStarDbProvider(); 29 | 30 | Map toMap(String fullName, String data) { 31 | Map map = {columnFullName: fullName, columnData: data}; 32 | if (id != null) { 33 | map[columnId] = id; 34 | } 35 | return map; 36 | } 37 | 38 | RepositoryStarDbProvider.fromMap(Map map) { 39 | id = map[columnId]; 40 | fullName = map[columnFullName]; 41 | data = map[columnData]; 42 | } 43 | 44 | @override 45 | tableSqlString() { 46 | return tableBaseString(name, columnId) + 47 | ''' 48 | $columnFullName text not null, 49 | $columnData text not null) 50 | '''; 51 | } 52 | 53 | @override 54 | tableName() { 55 | return name; 56 | } 57 | 58 | Future _getProvider(Database db, String fullName) async { 59 | List> maps = 60 | await db.query(name, columns: [columnId, columnFullName, columnData], where: "$columnFullName = ?", whereArgs: [fullName]); 61 | if (maps.length > 0) { 62 | RepositoryStarDbProvider provider = RepositoryStarDbProvider.fromMap(maps.first); 63 | return provider; 64 | } 65 | return null; 66 | } 67 | 68 | ///插入到数据库 69 | Future insert(String fullName, String dataMapString) async { 70 | Database db = await getDataBase(); 71 | var provider = await _getProvider(db, fullName); 72 | if (provider != null) { 73 | await db.delete(name, where: "$columnFullName = ?", whereArgs: [fullName]); 74 | } 75 | return await db.insert(name, toMap(fullName, dataMapString)); 76 | } 77 | 78 | ///获取事件数据 79 | Future> geData(String fullName) async { 80 | Database db = await getDataBase(); 81 | 82 | var provider = await _getProvider(db, fullName); 83 | if (provider != null) { 84 | List list = new List(); 85 | 86 | ///使用 compute 的 Isolate 优化 json decode 87 | List eventMap = await compute(CodeUtils.decodeListResult, provider.data as String); 88 | 89 | if (eventMap.length > 0) { 90 | for (var item in eventMap) { 91 | list.add(User.fromJson(item)); 92 | } 93 | } 94 | return list; 95 | } 96 | return null; 97 | } 98 | } -------------------------------------------------------------------------------- /lib/common/ab/provider/repos/repository_watcher_db_provider.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:gsy_github_app_flutter/common/utils/code_utils.dart'; 3 | 4 | import 'package:flutter/foundation.dart'; 5 | import 'package:gsy_github_app_flutter/common/ab/sql_provider.dart'; 6 | import 'package:gsy_github_app_flutter/common/model/User.dart'; 7 | import 'package:sqflite/sqflite.dart'; 8 | 9 | /** 10 | * 仓库订阅用户表 11 | * Created by guoshuyu 12 | * Date: 2018-08-07 13 | */ 14 | 15 | class RepositoryWatcherDbProvider extends BaseDbProvider { 16 | final String name = 'RepositoryWatcher'; 17 | final String columnId = "_id"; 18 | final String columnFullName = "fullName"; 19 | final String columnData = "data"; 20 | 21 | int id; 22 | String fullName; 23 | String data; 24 | 25 | RepositoryWatcherDbProvider(); 26 | 27 | Map toMap(String fullName, String data) { 28 | Map map = {columnFullName: fullName, columnData: data}; 29 | if (id != null) { 30 | map[columnId] = id; 31 | } 32 | return map; 33 | } 34 | 35 | RepositoryWatcherDbProvider.fromMap(Map map) { 36 | id = map[columnId]; 37 | fullName = map[columnFullName]; 38 | data = map[columnData]; 39 | } 40 | 41 | @override 42 | tableSqlString() { 43 | return tableBaseString(name, columnId) + 44 | ''' 45 | $columnFullName text not null, 46 | $columnData text not null) 47 | '''; 48 | } 49 | 50 | @override 51 | tableName() { 52 | return name; 53 | } 54 | 55 | Future _getProvider(Database db, String fullName) async { 56 | List> maps = 57 | await db.query(name, columns: [columnId, columnFullName, columnData], where: "$columnFullName = ?", whereArgs: [fullName]); 58 | if (maps.length > 0) { 59 | RepositoryWatcherDbProvider provider = RepositoryWatcherDbProvider.fromMap(maps.first); 60 | return provider; 61 | } 62 | return null; 63 | } 64 | 65 | ///插入到数据库 66 | Future insert(String fullName, String dataMapString) async { 67 | Database db = await getDataBase(); 68 | var provider = await _getProvider(db, fullName); 69 | if (provider != null) { 70 | await db.delete(name, where: "$columnFullName = ?", whereArgs: [fullName]); 71 | } 72 | return await db.insert(name, toMap(fullName, dataMapString)); 73 | } 74 | 75 | ///获取事件数据 76 | Future> geData(String fullName) async { 77 | Database db = await getDataBase(); 78 | 79 | var provider = await _getProvider(db, fullName); 80 | if (provider != null) { 81 | List list = new List(); 82 | 83 | ///使用 compute 的 Isolate 优化 json decode 84 | List eventMap = await compute(CodeUtils.decodeListResult, provider.data as String); 85 | 86 | if (eventMap.length > 0) { 87 | for (var item in eventMap) { 88 | list.add(User.fromJson(item)); 89 | } 90 | } 91 | return list; 92 | } 93 | return null; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /lib/common/ab/provider/user/org_member_db_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:gsy_github_app_flutter/common/ab/sql_provider.dart'; 2 | 3 | /** 4 | * 用户关注表 5 | * 6 | * Created by guoshuyu 7 | * Date: 2018-08-07 8 | */ 9 | 10 | class OrgMemberDbProvider extends BaseDbProvider { 11 | final String name = 'OrgMember'; 12 | 13 | final String columnId = "_id"; 14 | final String columnOrg = "org"; 15 | final String columnData = "data"; 16 | 17 | int id; 18 | String org; 19 | String data; 20 | 21 | Map toMap() { 22 | Map map = {columnOrg: org, columnData: data}; 23 | if (id != null) { 24 | map[columnId] = id; 25 | } 26 | return map; 27 | } 28 | 29 | OrgMemberDbProvider.fromMap(Map map) { 30 | id = map[columnId]; 31 | org = map[columnOrg]; 32 | data = map[columnData]; 33 | } 34 | 35 | @override 36 | tableSqlString() {} 37 | 38 | @override 39 | tableName() { 40 | return name; 41 | } 42 | } -------------------------------------------------------------------------------- /lib/common/ab/provider/user/user_followed_db_provider.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:gsy_github_app_flutter/common/utils/code_utils.dart'; 3 | import 'package:flutter/foundation.dart'; 4 | import 'package:gsy_github_app_flutter/common/ab/sql_provider.dart'; 5 | import 'package:gsy_github_app_flutter/common/model/User.dart'; 6 | import 'package:sqflite/sqflite.dart'; 7 | 8 | /** 9 | * 用户关注表 10 | * Created by guoshuyu 11 | * Date: 2018-08-07 12 | */ 13 | class UserFollowedDbProvider extends BaseDbProvider { 14 | final String name = 'UserFollowed'; 15 | 16 | final String columnId = "_id"; 17 | final String columnUserName = "userName"; 18 | final String columnData = "data"; 19 | 20 | int id; 21 | String userName; 22 | String data; 23 | 24 | 25 | UserFollowedDbProvider(); 26 | 27 | Map toMap(String userName, String data) { 28 | Map map = {columnUserName: userName, columnData: data}; 29 | if (id != null) { 30 | map[columnId] = id; 31 | } 32 | return map; 33 | } 34 | 35 | UserFollowedDbProvider.fromMap(Map map) { 36 | id = map[columnId]; 37 | userName = map[columnUserName]; 38 | data = map[columnData]; 39 | } 40 | 41 | @override 42 | tableSqlString() { 43 | return tableBaseString(name, columnId) + 44 | ''' 45 | $columnUserName text not null, 46 | $columnData text not null) 47 | '''; 48 | } 49 | 50 | @override 51 | tableName() { 52 | return name; 53 | } 54 | 55 | Future _getProvider(Database db, String userName) async { 56 | List> maps = 57 | await db.query(name, columns: [columnId, columnUserName, columnData], where: "$columnUserName = ?", whereArgs: [userName]); 58 | if (maps.length > 0) { 59 | UserFollowedDbProvider provider = UserFollowedDbProvider.fromMap(maps.first); 60 | return provider; 61 | } 62 | return null; 63 | } 64 | 65 | ///插入到数据库 66 | Future insert(String userName, String dataMapString) async { 67 | Database db = await getDataBase(); 68 | var provider = await _getProvider(db, userName); 69 | if (provider != null) { 70 | await db.delete(name, where: "$columnUserName = ?", whereArgs: [userName]); 71 | } 72 | return await db.insert(name, toMap(userName, dataMapString)); 73 | } 74 | 75 | ///获取事件数据 76 | Future> geData(String userName) async { 77 | Database db = await getDataBase(); 78 | 79 | var provider = await _getProvider(db, userName); 80 | if (provider != null) { 81 | List list = new List(); 82 | 83 | ///使用 compute 的 Isolate 优化 json decode 84 | List eventMap = await compute(CodeUtils.decodeListResult, provider.data as String); 85 | 86 | if (eventMap.length > 0) { 87 | for (var item in eventMap) { 88 | list.add(User.fromJson(item)); 89 | } 90 | } 91 | return list; 92 | } 93 | return null; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /lib/common/ab/provider/user/user_follower_db_provider.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'dart:async'; 3 | import 'package:gsy_github_app_flutter/common/utils/code_utils.dart'; 4 | 5 | import 'package:flutter/foundation.dart'; 6 | import 'package:gsy_github_app_flutter/common/ab/sql_provider.dart'; 7 | import 'package:gsy_github_app_flutter/common/model/User.dart'; 8 | import 'package:sqflite/sqflite.dart'; 9 | 10 | /** 11 | * 用户粉丝表 12 | * Created by guoshuyu 13 | * Date: 2018-08-07 14 | */ 15 | 16 | class UserFollowerDbProvider extends BaseDbProvider { 17 | final String name = 'UserFollower'; 18 | 19 | final String columnId = "_id"; 20 | final String columnUserName = "userName"; 21 | final String columnData = "data"; 22 | 23 | int id; 24 | String userName; 25 | String data; 26 | 27 | UserFollowerDbProvider(); 28 | 29 | Map toMap(String userName, String data) { 30 | Map map = {columnUserName: userName, columnData: data}; 31 | if (id != null) { 32 | map[columnId] = id; 33 | } 34 | return map; 35 | } 36 | 37 | UserFollowerDbProvider.fromMap(Map map) { 38 | id = map[columnId]; 39 | userName = map[columnUserName]; 40 | data = map[columnData]; 41 | } 42 | 43 | @override 44 | tableSqlString() { 45 | return tableBaseString(name, columnId) + 46 | ''' 47 | $columnUserName text not null, 48 | $columnData text not null) 49 | '''; 50 | } 51 | 52 | @override 53 | tableName() { 54 | return name; 55 | } 56 | 57 | Future _getProvider(Database db, String userName) async { 58 | List> maps = 59 | await db.query(name, columns: [columnId, columnUserName, columnData], where: "$columnUserName = ?", whereArgs: [userName]); 60 | if (maps.length > 0) { 61 | UserFollowerDbProvider provider = UserFollowerDbProvider.fromMap(maps.first); 62 | return provider; 63 | } 64 | return null; 65 | } 66 | 67 | ///插入到数据库 68 | Future insert(String userName, String dataMapString) async { 69 | Database db = await getDataBase(); 70 | var provider = await _getProvider(db, userName); 71 | if (provider != null) { 72 | await db.delete(name, where: "$columnUserName = ?", whereArgs: [userName]); 73 | } 74 | return await db.insert(name, toMap(userName, dataMapString)); 75 | } 76 | 77 | ///获取事件数据 78 | Future> geData(String userName) async { 79 | Database db = await getDataBase(); 80 | 81 | var provider = await _getProvider(db, userName); 82 | if (provider != null) { 83 | List list = new List(); 84 | 85 | 86 | ///使用 compute 的 Isolate 优化 json decode 87 | List eventMap = await compute(CodeUtils.decodeListResult, provider.data as String); 88 | 89 | if (eventMap.length > 0) { 90 | for (var item in eventMap) { 91 | list.add(User.fromJson(item)); 92 | } 93 | } 94 | return list; 95 | } 96 | return null; 97 | } 98 | } -------------------------------------------------------------------------------- /lib/common/ab/provider/user/user_orgs_db_provider.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:gsy_github_app_flutter/common/utils/code_utils.dart'; 3 | 4 | import 'package:flutter/foundation.dart'; 5 | import 'package:gsy_github_app_flutter/common/ab/sql_provider.dart'; 6 | import 'package:gsy_github_app_flutter/common/model/UserOrg.dart'; 7 | import 'package:sqflite/sqflite.dart'; 8 | 9 | /** 10 | * 用户组织表 11 | * Created by guoshuyu 12 | * Date: 2018-08-07 13 | */ 14 | 15 | class UserOrgsDbProvider extends BaseDbProvider { 16 | final String name = 'UserOrgs'; 17 | 18 | final String columnId = "_id"; 19 | final String columnUserName = "userName"; 20 | final String columnData = "data"; 21 | 22 | int id; 23 | String userName; 24 | String data; 25 | 26 | UserOrgsDbProvider(); 27 | 28 | Map toMap(String userName, String data) { 29 | Map map = {columnUserName: userName, columnData: data}; 30 | if (id != null) { 31 | map[columnId] = id; 32 | } 33 | return map; 34 | } 35 | 36 | UserOrgsDbProvider.fromMap(Map map) { 37 | id = map[columnId]; 38 | userName = map[columnUserName]; 39 | data = map[columnData]; 40 | } 41 | 42 | @override 43 | tableSqlString() { 44 | return tableBaseString(name, columnId) + 45 | ''' 46 | $columnUserName text not null, 47 | $columnData text not null) 48 | '''; 49 | } 50 | 51 | @override 52 | tableName() { 53 | return name; 54 | } 55 | 56 | Future _getProvider(Database db, String userName) async { 57 | List> maps = 58 | await db.query(name, columns: [columnId, columnUserName, columnData], where: "$columnUserName = ?", whereArgs: [userName]); 59 | if (maps.length > 0) { 60 | UserOrgsDbProvider provider = UserOrgsDbProvider.fromMap(maps.first); 61 | return provider; 62 | } 63 | return null; 64 | } 65 | 66 | ///插入到数据库 67 | Future insert(String userName, String dataMapString) async { 68 | Database db = await getDataBase(); 69 | var provider = await _getProvider(db, userName); 70 | if (provider != null) { 71 | await db.delete(name, where: "$columnUserName = ?", whereArgs: [userName]); 72 | } 73 | return await db.insert(name, toMap(userName, dataMapString)); 74 | } 75 | 76 | ///获取数据 77 | Future> geData(String userName) async { 78 | Database db = await getDataBase(); 79 | 80 | var provider = await _getProvider(db, userName); 81 | if (provider != null) { 82 | List list = new List(); 83 | 84 | ///使用 compute 的 Isolate 优化 json decode 85 | List eventMap = await compute(CodeUtils.decodeListResult, provider.data as String); 86 | 87 | if (eventMap.length > 0) { 88 | for (var item in eventMap) { 89 | list.add(UserOrg.fromJson(item)); 90 | } 91 | } 92 | return list; 93 | } 94 | return null; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /lib/common/ab/provider/user/user_repos_db_provider.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:convert'; 3 | 4 | import 'package:flutter/foundation.dart'; 5 | import 'package:gsy_github_app_flutter/common/ab/sql_provider.dart'; 6 | import 'package:gsy_github_app_flutter/common/model/Repository.dart'; 7 | import 'package:gsy_github_app_flutter/common/utils/code_utils.dart'; 8 | import 'package:sqflite/sqflite.dart'; 9 | 10 | /** 11 | * 用户仓库表 12 | * Created by guoshuyu 13 | * Date: 2018-08-07 14 | */ 15 | 16 | class UserReposDbProvider extends BaseDbProvider { 17 | final String name = 'UserRepos'; 18 | 19 | final String columnId = "_id"; 20 | final String columnUserName = "userName"; 21 | final String columnData = "data"; 22 | 23 | int id; 24 | String userName; 25 | String data; 26 | 27 | UserReposDbProvider(); 28 | 29 | Map toMap(String fullName, String data) { 30 | Map map = {columnUserName: fullName, columnData: data}; 31 | if (id != null) { 32 | map[columnId] = id; 33 | } 34 | return map; 35 | } 36 | 37 | UserReposDbProvider.fromMap(Map map) { 38 | id = map[columnId]; 39 | userName = map[columnUserName]; 40 | data = map[columnData]; 41 | } 42 | 43 | @override 44 | tableSqlString() { 45 | return tableBaseString(name, columnId) + 46 | ''' 47 | $columnUserName text not null, 48 | $columnData text not null) 49 | '''; 50 | } 51 | 52 | @override 53 | tableName() { 54 | return name; 55 | } 56 | 57 | Future _getProvider(Database db, String userName) async { 58 | List> maps = 59 | await db.query(name, columns: [columnId, columnUserName, columnData], where: "$columnUserName = ?", whereArgs: [userName]); 60 | if (maps.length > 0) { 61 | UserReposDbProvider provider = UserReposDbProvider.fromMap(maps.first); 62 | return provider; 63 | } 64 | return null; 65 | } 66 | 67 | ///插入到数据库 68 | Future insert(String userName, String dataMapString) async { 69 | Database db = await getDataBase(); 70 | var provider = await _getProvider(db, userName); 71 | if (provider != null) { 72 | await db.delete(name, where: "$columnUserName = ?", whereArgs: [userName]); 73 | } 74 | return await db.insert(name, toMap(userName, dataMapString)); 75 | } 76 | 77 | ///获取事件数据 78 | Future> geData(String userName) async { 79 | Database db = await getDataBase(); 80 | 81 | var provider = await _getProvider(db, userName); 82 | if (provider != null) { 83 | List list = new List(); 84 | 85 | 86 | ///使用 compute 的 Isolate 优化 json decode 87 | List eventMap = await compute(CodeUtils.decodeListResult, provider.data as String); 88 | 89 | if (eventMap.length > 0) { 90 | for (var item in eventMap) { 91 | list.add(Repository.fromJson(item)); 92 | } 93 | } 94 | return list; 95 | } 96 | return null; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /lib/common/ab/provider/user/user_stared_db_provider.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:gsy_github_app_flutter/common/utils/code_utils.dart'; 3 | 4 | import 'package:flutter/foundation.dart'; 5 | import 'package:gsy_github_app_flutter/common/ab/sql_provider.dart'; 6 | import 'package:gsy_github_app_flutter/common/model/Repository.dart'; 7 | import 'package:sqflite/sqflite.dart'; 8 | 9 | /** 10 | * 用户收藏表 11 | * Created by guoshuyu 12 | * Date: 2018-08-07 13 | */ 14 | 15 | class UserStaredDbProvider extends BaseDbProvider { 16 | final String name = 'UserStared'; 17 | 18 | final String columnId = "_id"; 19 | final String columnUserName = "userName"; 20 | final String columnData = "data"; 21 | 22 | int id; 23 | String userName; 24 | String data; 25 | 26 | UserStaredDbProvider(); 27 | 28 | Map toMap(String fullName, String data) { 29 | Map map = {columnUserName: fullName, columnData: data}; 30 | if (id != null) { 31 | map[columnId] = id; 32 | } 33 | return map; 34 | } 35 | 36 | UserStaredDbProvider.fromMap(Map map) { 37 | id = map[columnId]; 38 | userName = map[columnUserName]; 39 | data = map[columnData]; 40 | } 41 | 42 | @override 43 | tableSqlString() { 44 | return tableBaseString(name, columnId) + 45 | ''' 46 | $columnUserName text not null, 47 | $columnData text not null) 48 | '''; 49 | } 50 | 51 | @override 52 | tableName() { 53 | return name; 54 | } 55 | 56 | Future _getProvider(Database db, String userName) async { 57 | List> maps = 58 | await db.query(name, columns: [columnId, columnUserName, columnData], where: "$columnUserName = ?", whereArgs: [userName]); 59 | if (maps.length > 0) { 60 | UserStaredDbProvider provider = UserStaredDbProvider.fromMap(maps.first); 61 | return provider; 62 | } 63 | return null; 64 | } 65 | 66 | ///插入到数据库 67 | Future insert(String userName, String dataMapString) async { 68 | Database db = await getDataBase(); 69 | var provider = await _getProvider(db, userName); 70 | if (provider != null) { 71 | await db.delete(name, where: "$columnUserName = ?", whereArgs: [userName]); 72 | } 73 | return await db.insert(name, toMap(userName, dataMapString)); 74 | } 75 | 76 | ///获取事件数据 77 | Future> geData(String userName) async { 78 | Database db = await getDataBase(); 79 | 80 | var provider = await _getProvider(db, userName); 81 | if (provider != null) { 82 | List list = new List(); 83 | 84 | 85 | ///使用 compute 的 Isolate 优化 json decode 86 | List eventMap = await compute(CodeUtils.decodeListResult, provider.data as String); 87 | 88 | 89 | if (eventMap.length > 0) { 90 | for (var item in eventMap) { 91 | list.add(Repository.fromJson(item)); 92 | } 93 | } 94 | return list; 95 | } 96 | return null; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /lib/common/ab/provider/user/userinfo_db_provider.dart: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | import 'dart:async'; 5 | import 'package:gsy_github_app_flutter/common/utils/code_utils.dart'; 6 | 7 | import 'package:flutter/foundation.dart'; 8 | import 'package:gsy_github_app_flutter/common/ab/sql_provider.dart'; 9 | import 'package:gsy_github_app_flutter/common/model/User.dart'; 10 | import 'package:sqflite/sqflite.dart'; 11 | 12 | /** 13 | * 用户表 14 | * Created by guoshuyu 15 | * Date: 2018-08-07 16 | */ 17 | 18 | class UserInfoDbProvider extends BaseDbProvider { 19 | final String name = 'UserInfo'; 20 | 21 | final String columnId = "_id"; 22 | final String columnUserName = "userName"; 23 | final String columnData = "data"; 24 | 25 | int id; 26 | String userName; 27 | String data; 28 | 29 | UserInfoDbProvider(); 30 | 31 | Map toMap(String userName, String data) { 32 | Map map = {columnUserName: userName, columnData: data}; 33 | if (id != null) { 34 | map[columnId] = id; 35 | } 36 | return map; 37 | } 38 | 39 | UserInfoDbProvider.fromMap(Map map) { 40 | id = map[columnId]; 41 | userName = map[columnUserName]; 42 | data = map[columnData]; 43 | } 44 | 45 | @override 46 | tableSqlString() { 47 | return tableBaseString(name, columnId) + 48 | ''' 49 | $columnUserName text not null, 50 | $columnData text not null) 51 | '''; 52 | } 53 | 54 | @override 55 | tableName() { 56 | return name; 57 | } 58 | 59 | Future _getUserProvider(Database db, String userName) async { 60 | List> maps = 61 | await db.query(name, columns: [columnId, columnUserName, columnData], where: "$columnUserName = ?", whereArgs: [userName]); 62 | if (maps.length > 0) { 63 | UserInfoDbProvider provider = UserInfoDbProvider.fromMap(maps.first); 64 | return provider; 65 | } 66 | return null; 67 | } 68 | 69 | ///插入到数据库 70 | Future insert(String userName, String eventMapString) async { 71 | Database db = await getDataBase(); 72 | var userProvider = await _getUserProvider(db, userName); 73 | if (userProvider != null) { 74 | await db.delete(name, where: "$columnUserName = ?", whereArgs: [userName]); 75 | } 76 | return await db.insert(name, toMap(userName, eventMapString)); 77 | } 78 | 79 | ///获取事件数据 80 | Future getUserInfo(String userName) async { 81 | Database db = await getDataBase(); 82 | var userProvider = await _getUserProvider(db, userName); 83 | if (userProvider != null) { 84 | 85 | 86 | ///使用 compute 的 Isolate 优化 json decode 87 | var mapData = await compute(CodeUtils.decodeMapResult, userProvider.data as String); 88 | return User.fromJson(mapData); 89 | } 90 | return null; 91 | } 92 | } -------------------------------------------------------------------------------- /lib/common/ab/sql_manager.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:io'; 3 | 4 | import 'package:gsy_github_app_flutter/common/dao/user_dao.dart'; 5 | import 'package:gsy_github_app_flutter/common/model/User.dart'; 6 | import 'package:sqflite/sqflite.dart'; 7 | 8 | /** 9 | * 数据库管理 10 | * Created by guoshuyu 11 | * Date: 2018-08-03 12 | */ 13 | 14 | class SqlManager { 15 | static const _VERSION = 1; 16 | 17 | static const _NAME = "gsy_github_app_flutter.db"; 18 | 19 | static Database _database; 20 | 21 | ///初始化 22 | static init() async { 23 | // open the database 24 | var databasesPath = await getDatabasesPath(); 25 | var userRes= await UserDao.getUserInfoLocal(); 26 | String dbName = _NAME; 27 | if(userRes != null && userRes.result) { 28 | User user = userRes.data; 29 | if(user != null && user.login != null) { 30 | dbName = user.login + "_" + _NAME; 31 | } 32 | } 33 | String path = databasesPath + dbName; 34 | if (Platform.isIOS) { 35 | path = databasesPath + "/" + dbName; 36 | } 37 | _database = await openDatabase(path, version: _VERSION, onCreate: (Database db, int version) async { 38 | // When creating the db, create the table 39 | //await db.execute("CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value INTEGER, num REAL)"); 40 | }); 41 | } 42 | 43 | /** 44 | * 表是否存在 45 | */ 46 | static isTableExits(String tableName) async { 47 | await getCurrentDatabase(); 48 | var res = await _database.rawQuery("select * from Sqlite_master where type = 'table' and name = '$tableName'"); 49 | return res != null && res.length > 0; 50 | } 51 | 52 | ///获取当前数据库对象 53 | static Future getCurrentDatabase() async { 54 | if (_database == null) { 55 | await init(); 56 | } 57 | return _database; 58 | } 59 | 60 | ///关闭 61 | static close() { 62 | _database?.close(); 63 | _database = null; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /lib/common/ab/sql_provider.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:convert'; 3 | /** 4 | * 数据库表 5 | * Created by guoshuyu 6 | * Date: 2018-08-03 7 | */ 8 | import 'package:gsy_github_app_flutter/common/ab/sql_manager.dart'; 9 | import 'package:meta/meta.dart'; 10 | import 'package:sqflite/sqflite.dart'; 11 | 12 | ///基类 13 | abstract class BaseDbProvider { 14 | bool isTableExits = false; 15 | 16 | tableSqlString(); 17 | 18 | tableName(); 19 | 20 | tableBaseString(String name, String columnId) { 21 | return ''' 22 | create table $name ( 23 | $columnId integer primary key autoincrement, 24 | '''; 25 | } 26 | 27 | Future getDataBase() async { 28 | return await open(); 29 | } 30 | 31 | @mustCallSuper 32 | prepare(name, String createSql) async { 33 | isTableExits = await SqlManager.isTableExits(name); 34 | if (!isTableExits) { 35 | Database db = await SqlManager.getCurrentDatabase(); 36 | return await db.execute(createSql); 37 | } 38 | } 39 | 40 | @mustCallSuper 41 | open() async { 42 | if (!isTableExits) { 43 | await prepare(tableName(), tableSqlString()); 44 | } 45 | return await SqlManager.getCurrentDatabase(); 46 | } 47 | } 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /lib/common/config/config.dart: -------------------------------------------------------------------------------- 1 | class Config { 2 | static const PAGE_SIZE = 20; 3 | static const DEBUG = true; 4 | static const USE_NATIVE_WEBVIEW = true; 5 | 6 | 7 | /// //////////////////////////////////////常量////////////////////////////////////// /// 8 | static const TOKEN_KEY = "token"; 9 | static const USER_NAME_KEY = "user-name"; 10 | static const PW_KEY = "user-pw"; 11 | static const USER_BASIC_CODE = "user-basic-code"; 12 | static const USER_INFO = "user-info"; 13 | static const LANGUAGE_SELECT = "language-select"; 14 | static const LANGUAGE_SELECT_NAME = "language-select-name"; 15 | static const REFRESH_LANGUAGE = "refreshLanguageApp"; 16 | static const THEME_COLOR = "theme-color"; 17 | static const LOCALE = "locale"; 18 | } 19 | -------------------------------------------------------------------------------- /lib/common/dao/dao_result.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | class DataResult { 4 | var data; 5 | bool result; 6 | Future next; 7 | 8 | DataResult(this.data, this.result, {this.next}); 9 | } 10 | -------------------------------------------------------------------------------- /lib/common/event/http_error_event.dart: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by guoshuyu 3 | * Date: 2018-08-16 4 | */ 5 | 6 | class HttpErrorEvent { 7 | final int code; 8 | 9 | final String message; 10 | 11 | HttpErrorEvent(this.code, this.message); 12 | } 13 | -------------------------------------------------------------------------------- /lib/common/local/local_storage.dart: -------------------------------------------------------------------------------- 1 | import 'package:shared_preferences/shared_preferences.dart'; 2 | 3 | ///SharedPreferences 本地存储 4 | class LocalStorage { 5 | 6 | static save(String key, value) async { 7 | SharedPreferences prefs = await SharedPreferences.getInstance(); 8 | prefs.setString(key, value); 9 | } 10 | 11 | static get(String key) async { 12 | SharedPreferences prefs = await SharedPreferences.getInstance(); 13 | return prefs.get(key); 14 | } 15 | 16 | static remove(String key) async { 17 | SharedPreferences prefs = await SharedPreferences.getInstance(); 18 | prefs.remove(key); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/common/localization/default_localizations.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:gsy_github_app_flutter/common/style/gsy_string_base.dart'; 5 | import 'package:gsy_github_app_flutter/common/style/gsy_string_en.dart'; 6 | import 'package:gsy_github_app_flutter/common/style/gsy_string_zh.dart'; 7 | 8 | ///自定义多语言实现 9 | class GSYLocalizations { 10 | final Locale locale; 11 | 12 | GSYLocalizations(this.locale); 13 | 14 | ///根据不同 locale.languageCode 加载不同语言对应 15 | ///GSYStringEn和GSYStringZh都继承了GSYStringBase 16 | static Map _localizedValues = { 17 | 'en': new GSYStringEn(), 18 | 'zh': new GSYStringZh(), 19 | }; 20 | 21 | GSYStringBase get currentLocalized { 22 | return _localizedValues[locale.languageCode]; 23 | } 24 | 25 | ///通过 Localizations 加载当前的 GSYLocalizations 26 | ///获取对应的 GSYStringBase 27 | static GSYLocalizations of(BuildContext context) { 28 | return Localizations.of(context, GSYLocalizations); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/common/localization/gsy_localizations_delegate.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/foundation.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:gsy_github_app_flutter/common/localization/default_localizations.dart'; 6 | 7 | /** 8 | * 多语言代理 9 | * Created by guoshuyu 10 | * Date: 2018-08-15 11 | */ 12 | class GSYLocalizationsDelegate extends LocalizationsDelegate { 13 | 14 | GSYLocalizationsDelegate(); 15 | 16 | @override 17 | bool isSupported(Locale locale) { 18 | ///支持中文和英语 19 | return ['en', 'zh'].contains(locale.languageCode); 20 | } 21 | 22 | ///根据locale,创建一个对象用于提供当前locale下的文本显示 23 | @override 24 | Future load(Locale locale) { 25 | return new SynchronousFuture(new GSYLocalizations(locale)); 26 | } 27 | 28 | @override 29 | bool shouldReload(LocalizationsDelegate old) { 30 | return false; 31 | } 32 | 33 | ///全局静态的代理 34 | static GSYLocalizationsDelegate delegate = new GSYLocalizationsDelegate(); 35 | } 36 | -------------------------------------------------------------------------------- /lib/common/model/Branch.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | /** 4 | * Created by guoshuyu 5 | * Date: 2018-07-31 6 | */ 7 | 8 | part 'Branch.g.dart'; 9 | 10 | @JsonSerializable() 11 | class Branch { 12 | String name; 13 | String tarballUrl; 14 | @JsonKey(name: "zipball_url") 15 | String zipballUrl; 16 | @JsonKey(name: "tarball_url") 17 | 18 | bool isBranch = true; 19 | 20 | Branch(this.name, this.isBranch, this.tarballUrl, this.zipballUrl); 21 | 22 | factory Branch.fromJson(Map json) => _$BranchFromJson(json); 23 | 24 | Map toJson() => _$BranchToJson(this); 25 | } 26 | -------------------------------------------------------------------------------- /lib/common/model/Branch.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'Branch.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | Branch _$BranchFromJson(Map json) { 10 | return Branch(json['name'] as String, json['tarball_url'] as bool, 11 | json['tarballUrl'] as String, json['zipball_url'] as String); 12 | } 13 | 14 | Map _$BranchToJson(Branch instance) => { 15 | 'name': instance.name, 16 | 'tarballUrl': instance.tarballUrl, 17 | 'zipball_url': instance.zipballUrl, 18 | 'tarball_url': instance.isBranch 19 | }; 20 | -------------------------------------------------------------------------------- /lib/common/model/CommitComment.dart: -------------------------------------------------------------------------------- 1 | import 'package:gsy_github_app_flutter/common/model/User.dart'; 2 | import 'package:json_annotation/json_annotation.dart'; 3 | 4 | /** 5 | * Created by guoshuyu 6 | * Date: 2018-07-31 7 | */ 8 | 9 | part 'CommitComment.g.dart'; 10 | 11 | @JsonSerializable() 12 | class CommitComment{ 13 | int id; 14 | String body; 15 | String path; 16 | int position; 17 | int line; 18 | @JsonKey(name: "commit_id") 19 | String commitId; 20 | @JsonKey(name: "created_at") 21 | DateTime createdAt; 22 | @JsonKey(name: "updated_at") 23 | DateTime updatedAt; 24 | @JsonKey(name: "html_url") 25 | String htmlUrl; 26 | String url; 27 | User user; 28 | 29 | CommitComment( 30 | this.id, 31 | this.body, 32 | this.path, 33 | this.position, 34 | this.line, 35 | this.commitId, 36 | this.createdAt, 37 | this.updatedAt, 38 | this.htmlUrl, 39 | this.url, 40 | this.user, 41 | ); 42 | 43 | factory CommitComment.fromJson(Map json) => _$CommitCommentFromJson(json); 44 | 45 | Map toJson() => _$CommitCommentToJson(this); 46 | } 47 | -------------------------------------------------------------------------------- /lib/common/model/CommitComment.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'CommitComment.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | CommitComment _$CommitCommentFromJson(Map json) { 10 | return CommitComment( 11 | json['id'] as int, 12 | json['body'] as String, 13 | json['path'] as String, 14 | json['position'] as int, 15 | json['line'] as int, 16 | json['commit_id'] as String, 17 | json['created_at'] == null 18 | ? null 19 | : DateTime.parse(json['created_at'] as String), 20 | json['updated_at'] == null 21 | ? null 22 | : DateTime.parse(json['updated_at'] as String), 23 | json['html_url'] as String, 24 | json['url'] as String, 25 | json['user'] == null 26 | ? null 27 | : User.fromJson(json['user'] as Map)); 28 | } 29 | 30 | Map _$CommitCommentToJson(CommitComment instance) => 31 | { 32 | 'id': instance.id, 33 | 'body': instance.body, 34 | 'path': instance.path, 35 | 'position': instance.position, 36 | 'line': instance.line, 37 | 'commit_id': instance.commitId, 38 | 'created_at': instance.createdAt?.toIso8601String(), 39 | 'updated_at': instance.updatedAt?.toIso8601String(), 40 | 'html_url': instance.htmlUrl, 41 | 'url': instance.url, 42 | 'user': instance.user 43 | }; 44 | -------------------------------------------------------------------------------- /lib/common/model/CommitFile.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | /** 4 | * Created by guoshuyu 5 | * Date: 2018-07-31 6 | */ 7 | 8 | part 'CommitFile.g.dart'; 9 | 10 | @JsonSerializable() 11 | class CommitFile { 12 | String sha; 13 | @JsonKey(name: "filename") 14 | String fileName; 15 | String status; 16 | int additions; 17 | int deletions; 18 | int changes; 19 | @JsonKey(name: "blob_url") 20 | String blobUrl; 21 | @JsonKey(name: "raw_url") 22 | String rawUrl; 23 | @JsonKey(name: "contents_url") 24 | String contentsUrl; 25 | String patch; 26 | 27 | CommitFile( 28 | this.sha, 29 | this.fileName, 30 | this.status, 31 | this.additions, 32 | this.deletions, 33 | this.changes, 34 | this.blobUrl, 35 | this.rawUrl, 36 | this.contentsUrl, 37 | this.patch, 38 | ); 39 | 40 | factory CommitFile.fromJson(Map json) => _$CommitFileFromJson(json); 41 | 42 | Map toJson() => _$CommitFileToJson(this); 43 | } 44 | -------------------------------------------------------------------------------- /lib/common/model/CommitFile.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'CommitFile.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | CommitFile _$CommitFileFromJson(Map json) { 10 | return CommitFile( 11 | json['sha'] as String, 12 | json['filename'] as String, 13 | json['status'] as String, 14 | json['additions'] as int, 15 | json['deletions'] as int, 16 | json['changes'] as int, 17 | json['blob_url'] as String, 18 | json['raw_url'] as String, 19 | json['contents_url'] as String, 20 | json['patch'] as String); 21 | } 22 | 23 | Map _$CommitFileToJson(CommitFile instance) => 24 | { 25 | 'sha': instance.sha, 26 | 'filename': instance.fileName, 27 | 'status': instance.status, 28 | 'additions': instance.additions, 29 | 'deletions': instance.deletions, 30 | 'changes': instance.changes, 31 | 'blob_url': instance.blobUrl, 32 | 'raw_url': instance.rawUrl, 33 | 'contents_url': instance.contentsUrl, 34 | 'patch': instance.patch 35 | }; 36 | -------------------------------------------------------------------------------- /lib/common/model/CommitGitInfo.dart: -------------------------------------------------------------------------------- 1 | import 'package:gsy_github_app_flutter/common/model/CommitGitUser.dart'; 2 | import 'package:json_annotation/json_annotation.dart'; 3 | 4 | /** 5 | * Created by guoshuyu 6 | * Date: 2018-07-31 7 | */ 8 | 9 | part 'CommitGitInfo.g.dart'; 10 | 11 | @JsonSerializable() 12 | class CommitGitInfo { 13 | String message; 14 | String url; 15 | @JsonKey(name: "comment_count") 16 | int commentCount; 17 | CommitGitUser author; 18 | CommitGitUser committer; 19 | 20 | CommitGitInfo( 21 | this.message, 22 | this.url, 23 | this.commentCount, 24 | this.author, 25 | this.committer, 26 | ); 27 | 28 | factory CommitGitInfo.fromJson(Map json) => _$CommitGitInfoFromJson(json); 29 | 30 | 31 | Map toJson() => _$CommitGitInfoToJson(this); 32 | } 33 | -------------------------------------------------------------------------------- /lib/common/model/CommitGitInfo.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'CommitGitInfo.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | CommitGitInfo _$CommitGitInfoFromJson(Map json) { 10 | return CommitGitInfo( 11 | json['message'] as String, 12 | json['url'] as String, 13 | json['comment_count'] as int, 14 | json['author'] == null 15 | ? null 16 | : CommitGitUser.fromJson(json['author'] as Map), 17 | json['committer'] == null 18 | ? null 19 | : CommitGitUser.fromJson(json['committer'] as Map)); 20 | } 21 | 22 | Map _$CommitGitInfoToJson(CommitGitInfo instance) => 23 | { 24 | 'message': instance.message, 25 | 'url': instance.url, 26 | 'comment_count': instance.commentCount, 27 | 'author': instance.author, 28 | 'committer': instance.committer 29 | }; 30 | -------------------------------------------------------------------------------- /lib/common/model/CommitGitUser.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | /** 4 | * Created by guoshuyu 5 | * Date: 2018-07-31 6 | */ 7 | 8 | part 'CommitGitUser.g.dart'; 9 | 10 | @JsonSerializable() 11 | class CommitGitUser{ 12 | String name; 13 | String email; 14 | DateTime date; 15 | 16 | CommitGitUser(this.name, this.email, this.date); 17 | 18 | factory CommitGitUser.fromJson(Map json) => _$CommitGitUserFromJson(json); 19 | 20 | 21 | Map toJson() => _$CommitGitUserToJson(this); 22 | } 23 | -------------------------------------------------------------------------------- /lib/common/model/CommitGitUser.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'CommitGitUser.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | CommitGitUser _$CommitGitUserFromJson(Map json) { 10 | return CommitGitUser(json['name'] as String, json['email'] as String, 11 | json['date'] == null ? null : DateTime.parse(json['date'] as String)); 12 | } 13 | 14 | Map _$CommitGitUserToJson(CommitGitUser instance) => 15 | { 16 | 'name': instance.name, 17 | 'email': instance.email, 18 | 'date': instance.date?.toIso8601String() 19 | }; -------------------------------------------------------------------------------- /lib/common/model/CommitStats.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | /** 4 | * Created by guoshuyu 5 | * Date: 2018-07-31 6 | */ 7 | 8 | part 'CommitStats.g.dart'; 9 | 10 | @JsonSerializable() 11 | class CommitStats { 12 | int total; 13 | int additions; 14 | int deletions; 15 | 16 | CommitStats(this.total, this.additions, this.deletions); 17 | 18 | factory CommitStats.fromJson(Map json) => _$CommitStatsFromJson(json); 19 | 20 | Map toJson() => _$CommitStatsToJson(this); 21 | } 22 | -------------------------------------------------------------------------------- /lib/common/model/CommitStats.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'CommitStats.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | CommitStats _$CommitStatsFromJson(Map json) { 10 | return CommitStats( 11 | json['total'] as int, json['additions'] as int, json['deletions'] as int); 12 | } 13 | 14 | Map _$CommitStatsToJson(CommitStats instance) => 15 | { 16 | 'total': instance.total, 17 | 'additions': instance.additions, 18 | 'deletions': instance.deletions 19 | }; 20 | -------------------------------------------------------------------------------- /lib/common/model/CommitsComparison.dart: -------------------------------------------------------------------------------- 1 | import 'package:gsy_github_app_flutter/common/model/CommitFile.dart'; 2 | import 'package:gsy_github_app_flutter/common/model/RepoCommit.dart'; 3 | import 'package:json_annotation/json_annotation.dart'; 4 | 5 | /** 6 | * Created by guoshuyu 7 | * Date: 2018-07-31 8 | */ 9 | 10 | part 'CommitsComparison.g.dart'; 11 | 12 | @JsonSerializable() 13 | class CommitsComparison{ 14 | String url; 15 | @JsonKey(name: "html_url") 16 | String htmlUrl; 17 | @JsonKey(name: "base_commit") 18 | RepoCommit baseCommit; 19 | @JsonKey(name: "merge_base_commit") 20 | RepoCommit mergeBaseCommit; 21 | String status; 22 | @JsonKey(name: "total_commits") 23 | int totalCommits; 24 | List commits; 25 | List files; 26 | 27 | CommitsComparison( 28 | this.url, 29 | this.htmlUrl, 30 | this.baseCommit, 31 | this.mergeBaseCommit, 32 | this.status, 33 | this.totalCommits, 34 | this.commits, 35 | this.files, 36 | ); 37 | 38 | factory CommitsComparison.fromJson(Map json) => _$CommitsComparisonFromJson(json); 39 | 40 | Map toJson() => _$CommitsComparisonToJson(this); 41 | } 42 | -------------------------------------------------------------------------------- /lib/common/model/CommitsComparison.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'CommitsComparison.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | CommitsComparison _$CommitsComparisonFromJson(Map json) { 10 | return CommitsComparison( 11 | json['url'] as String, 12 | json['html_url'] as String, 13 | json['base_commit'] == null 14 | ? null 15 | : RepoCommit.fromJson(json['base_commit'] as Map), 16 | json['merge_base_commit'] == null 17 | ? null 18 | : RepoCommit.fromJson( 19 | json['merge_base_commit'] as Map), 20 | json['status'] as String, 21 | json['total_commits'] as int, 22 | (json['commits'] as List) 23 | ?.map((e) => 24 | e == null ? null : RepoCommit.fromJson(e as Map)) 25 | ?.toList(), 26 | (json['files'] as List) 27 | ?.map((e) => 28 | e == null ? null : CommitFile.fromJson(e as Map)) 29 | ?.toList()); 30 | } 31 | 32 | Map _$CommitsComparisonToJson(CommitsComparison instance) => 33 | { 34 | 'url': instance.url, 35 | 'html_url': instance.htmlUrl, 36 | 'base_commit': instance.baseCommit, 37 | 'merge_base_commit': instance.mergeBaseCommit, 38 | 'status': instance.status, 39 | 'total_commits': instance.totalCommits, 40 | 'commits': instance.commits, 41 | 'files': instance.files 42 | }; 43 | -------------------------------------------------------------------------------- /lib/common/model/DownloadSource.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | /** 4 | * Created by guoshuyu 5 | * Date: 2018-07-31 6 | */ 7 | 8 | part 'DownloadSource.g.dart'; 9 | 10 | @JsonSerializable() 11 | class DownloadSource { 12 | String url; 13 | bool isSourceCode; 14 | String name; 15 | int size; 16 | 17 | DownloadSource( 18 | this.url, 19 | this.isSourceCode, 20 | this.name, 21 | this.size, 22 | ); 23 | 24 | factory DownloadSource.fromJson(Map json) => _$DownloadSourceFromJson(json); 25 | 26 | Map toJson() => _$DownloadSourceToJson(this); 27 | } 28 | -------------------------------------------------------------------------------- /lib/common/model/DownloadSource.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'DownloadSource.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | DownloadSource _$DownloadSourceFromJson(Map json) { 10 | return DownloadSource(json['url'] as String, json['isSourceCode'] as bool, 11 | json['name'] as String, json['size'] as int); 12 | } 13 | 14 | Map _$DownloadSourceToJson(DownloadSource instance) => 15 | { 16 | 'url': instance.url, 17 | 'isSourceCode': instance.isSourceCode, 18 | 'name': instance.name, 19 | 'size': instance.size 20 | }; 21 | -------------------------------------------------------------------------------- /lib/common/model/Event.dart: -------------------------------------------------------------------------------- 1 | import 'package:gsy_github_app_flutter/common/model/EventPayload.dart'; 2 | import 'package:gsy_github_app_flutter/common/model/Repository.dart'; 3 | import 'package:gsy_github_app_flutter/common/model/User.dart'; 4 | import 'package:json_annotation/json_annotation.dart'; 5 | 6 | /** 7 | * Created by guoshuyu 8 | * Date: 2018-07-31 9 | */ 10 | 11 | part 'Event.g.dart'; 12 | 13 | @JsonSerializable() 14 | class Event { 15 | String id; 16 | String type; 17 | User actor; 18 | Repository repo; 19 | User org; 20 | EventPayload payload; 21 | @JsonKey(name: "public") 22 | bool isPublic; 23 | @JsonKey(name: "created_at") 24 | DateTime createdAt; 25 | 26 | Event( 27 | this.id, 28 | this.type, 29 | this.actor, 30 | this.repo, 31 | this.org, 32 | this.payload, 33 | this.isPublic, 34 | this.createdAt, 35 | ); 36 | 37 | factory Event.fromJson(Map json) => _$EventFromJson(json); 38 | 39 | Map toJson() => _$EventToJson(this); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /lib/common/model/Event.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'Event.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | Event _$EventFromJson(Map json) { 10 | return Event( 11 | json['id'] as String, 12 | json['type'] as String, 13 | json['actor'] == null 14 | ? null 15 | : User.fromJson(json['actor'] as Map), 16 | json['repo'] == null 17 | ? null 18 | : Repository.fromJson(json['repo'] as Map), 19 | json['org'] == null 20 | ? null 21 | : User.fromJson(json['org'] as Map), 22 | json['payload'] == null 23 | ? null 24 | : EventPayload.fromJson(json['payload'] as Map), 25 | json['public'] as bool, 26 | json['created_at'] == null 27 | ? null 28 | : DateTime.parse(json['created_at'] as String)); 29 | } 30 | 31 | Map _$EventToJson(Event instance) => { 32 | 'id': instance.id, 33 | 'type': instance.type, 34 | 'actor': instance.actor, 35 | 'repo': instance.repo, 36 | 'org': instance.org, 37 | 'payload': instance.payload, 38 | 'public': instance.isPublic, 39 | 'created_at': instance.createdAt?.toIso8601String() 40 | }; 41 | -------------------------------------------------------------------------------- /lib/common/model/EventPayload.dart: -------------------------------------------------------------------------------- 1 | import 'package:gsy_github_app_flutter/common/model/Issue.dart'; 2 | import 'package:gsy_github_app_flutter/common/model/IssueEvent.dart'; 3 | import 'package:gsy_github_app_flutter/common/model/PushEventCommit.dart'; 4 | import 'package:gsy_github_app_flutter/common/model/Release.dart'; 5 | import 'package:json_annotation/json_annotation.dart'; 6 | 7 | /** 8 | * Created by guoshuyu 9 | * Date: 2018-07-31 10 | */ 11 | 12 | part 'EventPayload.g.dart'; 13 | 14 | @JsonSerializable() 15 | class EventPayload { 16 | 17 | @JsonKey(name: "push_id") 18 | int pushId; 19 | int size; 20 | @JsonKey(name: "distinct_size") 21 | int distinctSize; 22 | String ref; 23 | String head; 24 | String before; 25 | List commits; 26 | 27 | String action; 28 | @JsonKey(name: "ref_type") 29 | String refType; 30 | @JsonKey(name: "master_branch") 31 | String masterBranch; 32 | String description; 33 | @JsonKey(name: "pusher_type") 34 | String pusherType; 35 | 36 | Release release; 37 | Issue issue; 38 | IssueEvent comment; 39 | 40 | EventPayload(); 41 | 42 | factory EventPayload.fromJson(Map json) => _$EventPayloadFromJson(json); 43 | 44 | Map toJson() => _$EventPayloadToJson(this); 45 | } 46 | -------------------------------------------------------------------------------- /lib/common/model/EventPayload.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'EventPayload.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | EventPayload _$EventPayloadFromJson(Map json) { 10 | return EventPayload() 11 | ..pushId = json['push_id'] as int 12 | ..size = json['size'] as int 13 | ..distinctSize = json['distinct_size'] as int 14 | ..ref = json['ref'] as String 15 | ..head = json['head'] as String 16 | ..before = json['before'] as String 17 | ..commits = (json['commits'] as List) 18 | ?.map((e) => e == null 19 | ? null 20 | : PushEventCommit.fromJson(e as Map)) 21 | ?.toList() 22 | ..action = json['action'] as String 23 | ..refType = json['ref_type'] as String 24 | ..masterBranch = json['master_branch'] as String 25 | ..description = json['description'] as String 26 | ..pusherType = json['pusher_type'] as String 27 | ..release = json['release'] == null 28 | ? null 29 | : Release.fromJson(json['release'] as Map) 30 | ..issue = json['issue'] == null 31 | ? null 32 | : Issue.fromJson(json['issue'] as Map) 33 | ..comment = json['comment'] == null 34 | ? null 35 | : IssueEvent.fromJson(json['comment'] as Map); 36 | } 37 | 38 | Map _$EventPayloadToJson(EventPayload instance) => 39 | { 40 | 'push_id': instance.pushId, 41 | 'size': instance.size, 42 | 'distinct_size': instance.distinctSize, 43 | 'ref': instance.ref, 44 | 'head': instance.head, 45 | 'before': instance.before, 46 | 'commits': instance.commits, 47 | 'action': instance.action, 48 | 'ref_type': instance.refType, 49 | 'master_branch': instance.masterBranch, 50 | 'description': instance.description, 51 | 'pusher_type': instance.pusherType, 52 | 'release': instance.release, 53 | 'issue': instance.issue, 54 | 'comment': instance.comment 55 | }; 56 | -------------------------------------------------------------------------------- /lib/common/model/FileModel.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | /** 4 | * Created by guoshuyu 5 | * Date: 2018-07-31 6 | */ 7 | 8 | part 'FileModel.g.dart'; 9 | 10 | @JsonSerializable() 11 | class FileModel { 12 | String name; 13 | String path; 14 | String sha; 15 | int size; 16 | String url; 17 | @JsonKey(name: "html_url") 18 | String htmlUrl; 19 | @JsonKey(name: "git_url") 20 | String gitUrl; 21 | @JsonKey(name: "download_url") 22 | String downloadUrl; 23 | @JsonKey(name: "type") 24 | String type; 25 | 26 | FileModel( 27 | this.name, 28 | this.path, 29 | this.sha, 30 | this.size, 31 | this.url, 32 | this.htmlUrl, 33 | this.gitUrl, 34 | this.downloadUrl, 35 | this.type, 36 | ); 37 | 38 | factory FileModel.fromJson(Map json) => _$FileModelFromJson(json); 39 | 40 | Map toJson() => _$FileModelToJson(this); 41 | } 42 | -------------------------------------------------------------------------------- /lib/common/model/FileModel.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'FileModel.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | FileModel _$FileModelFromJson(Map json) { 10 | return FileModel( 11 | json['name'] as String, 12 | json['path'] as String, 13 | json['sha'] as String, 14 | json['size'] as int, 15 | json['url'] as String, 16 | json['html_url'] as String, 17 | json['git_url'] as String, 18 | json['download_url'] as String, 19 | json['type'] as String); 20 | } 21 | 22 | Map _$FileModelToJson(FileModel instance) => { 23 | 'name': instance.name, 24 | 'path': instance.path, 25 | 'sha': instance.sha, 26 | 'size': instance.size, 27 | 'url': instance.url, 28 | 'html_url': instance.htmlUrl, 29 | 'git_url': instance.gitUrl, 30 | 'download_url': instance.downloadUrl, 31 | 'type': instance.type 32 | }; 33 | -------------------------------------------------------------------------------- /lib/common/model/Issue.dart: -------------------------------------------------------------------------------- 1 | import 'package:gsy_github_app_flutter/common/model/User.dart'; 2 | import 'package:json_annotation/json_annotation.dart'; 3 | 4 | /** 5 | * Created by guoshuyu 6 | * Date: 2018-07-31 7 | */ 8 | 9 | part 'Issue.g.dart'; 10 | 11 | @JsonSerializable() 12 | class Issue { 13 | int id; 14 | int number; 15 | String title; 16 | String state; 17 | bool locked; 18 | @JsonKey(name: "comments") 19 | int commentNum; 20 | 21 | @JsonKey(name: "created_at") 22 | DateTime createdAt; 23 | @JsonKey(name: "updated_at") 24 | DateTime updatedAt; 25 | @JsonKey(name: "closed_at") 26 | DateTime closedAt; 27 | String body; 28 | @JsonKey(name: "body_html") 29 | String bodyHtml; 30 | 31 | User user; 32 | @JsonKey(name: "repository_url") 33 | String repoUrl; 34 | @JsonKey(name: "html_url") 35 | String htmlUrl; 36 | @JsonKey(name: "closed_by") 37 | User closeBy; 38 | 39 | 40 | 41 | Issue( 42 | this.id, 43 | this.number, 44 | this.title, 45 | this.state, 46 | this.locked, 47 | this.commentNum, 48 | this.createdAt, 49 | this.updatedAt, 50 | this.closedAt, 51 | this.body, 52 | this.bodyHtml, 53 | this.user, 54 | this.repoUrl, 55 | this.htmlUrl, 56 | this.closeBy, 57 | ); 58 | 59 | factory Issue.fromJson(Map json) => _$IssueFromJson(json); 60 | 61 | Map toJson() => _$IssueToJson(this); 62 | } 63 | -------------------------------------------------------------------------------- /lib/common/model/Issue.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'Issue.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | Issue _$IssueFromJson(Map json) { 10 | return Issue( 11 | json['id'] as int, 12 | json['number'] as int, 13 | json['title'] as String, 14 | json['state'] as String, 15 | json['locked'] as bool, 16 | json['comments'] as int, 17 | json['created_at'] == null 18 | ? null 19 | : DateTime.parse(json['created_at'] as String), 20 | json['updated_at'] == null 21 | ? null 22 | : DateTime.parse(json['updated_at'] as String), 23 | json['closed_at'] == null 24 | ? null 25 | : DateTime.parse(json['closed_at'] as String), 26 | json['body'] as String, 27 | json['body_html'] as String, 28 | json['user'] == null 29 | ? null 30 | : User.fromJson(json['user'] as Map), 31 | json['repository_url'] as String, 32 | json['html_url'] as String, 33 | json['closed_by'] == null 34 | ? null 35 | : User.fromJson(json['closed_by'] as Map)); 36 | } 37 | 38 | Map _$IssueToJson(Issue instance) => { 39 | 'id': instance.id, 40 | 'number': instance.number, 41 | 'title': instance.title, 42 | 'state': instance.state, 43 | 'locked': instance.locked, 44 | 'comments': instance.commentNum, 45 | 'created_at': instance.createdAt?.toIso8601String(), 46 | 'updated_at': instance.updatedAt?.toIso8601String(), 47 | 'closed_at': instance.closedAt?.toIso8601String(), 48 | 'body': instance.body, 49 | 'body_html': instance.bodyHtml, 50 | 'user': instance.user, 51 | 'repository_url': instance.repoUrl, 52 | 'html_url': instance.htmlUrl, 53 | 'closed_by': instance.closeBy 54 | }; 55 | -------------------------------------------------------------------------------- /lib/common/model/IssueEvent.dart: -------------------------------------------------------------------------------- 1 | import 'package:gsy_github_app_flutter/common/model/User.dart'; 2 | import 'package:json_annotation/json_annotation.dart'; 3 | 4 | /** 5 | * Created by guoshuyu 6 | * Date: 2018-07-31 7 | */ 8 | 9 | part 'IssueEvent.g.dart'; 10 | 11 | @JsonSerializable() 12 | class IssueEvent{ 13 | int id; 14 | User user; 15 | @JsonKey(name: "created_at") 16 | DateTime createdAt; 17 | @JsonKey(name: "updated_at") 18 | DateTime updatedAt; 19 | @JsonKey(name: "author_association") 20 | String authorAssociation; 21 | String body; 22 | @JsonKey(name: "body_html") 23 | String bodyHtml; 24 | @JsonKey(name: "event") 25 | String type; 26 | @JsonKey(name: "html_url") 27 | String htmlUrl; 28 | 29 | IssueEvent( 30 | this.id, 31 | this.user, 32 | this.createdAt, 33 | this.updatedAt, 34 | this.authorAssociation, 35 | this.body, 36 | this.bodyHtml, 37 | this.type, 38 | this.htmlUrl, 39 | ); 40 | 41 | factory IssueEvent.fromJson(Map json) => _$IssueEventFromJson(json); 42 | 43 | Map toJson() => _$IssueEventToJson(this); 44 | } 45 | -------------------------------------------------------------------------------- /lib/common/model/IssueEvent.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'IssueEvent.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | IssueEvent _$IssueEventFromJson(Map json) { 10 | return IssueEvent( 11 | json['id'] as int, 12 | json['user'] == null 13 | ? null 14 | : User.fromJson(json['user'] as Map), 15 | json['created_at'] == null 16 | ? null 17 | : DateTime.parse(json['created_at'] as String), 18 | json['updated_at'] == null 19 | ? null 20 | : DateTime.parse(json['updated_at'] as String), 21 | json['author_association'] as String, 22 | json['body'] as String, 23 | json['body_html'] as String, 24 | json['event'] as String, 25 | json['html_url'] as String); 26 | } 27 | 28 | Map _$IssueEventToJson(IssueEvent instance) => 29 | { 30 | 'id': instance.id, 31 | 'user': instance.user, 32 | 'created_at': instance.createdAt?.toIso8601String(), 33 | 'updated_at': instance.updatedAt?.toIso8601String(), 34 | 'author_association': instance.authorAssociation, 35 | 'body': instance.body, 36 | 'body_html': instance.bodyHtml, 37 | 'event': instance.type, 38 | 'html_url': instance.htmlUrl 39 | }; 40 | -------------------------------------------------------------------------------- /lib/common/model/License.dart: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by guoshuyu 3 | * Date: 2018-07-31 4 | */ 5 | import 'package:json_annotation/json_annotation.dart'; 6 | 7 | /** 8 | * Created by guoshuyu 9 | * Date: 2018-07-31 10 | */ 11 | 12 | part 'License.g.dart'; 13 | 14 | @JsonSerializable() 15 | class License { 16 | 17 | String name; 18 | 19 | License(this.name); 20 | 21 | factory License.fromJson(Map json) => _$LicenseFromJson(json); 22 | 23 | Map toJson() => _$LicenseToJson(this); 24 | } 25 | -------------------------------------------------------------------------------- /lib/common/model/License.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'License.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | License _$LicenseFromJson(Map json) { 10 | return License(json['name'] as String); 11 | } 12 | 13 | Map _$LicenseToJson(License instance) => 14 | {'name': instance.name}; 15 | -------------------------------------------------------------------------------- /lib/common/model/Notification.dart: -------------------------------------------------------------------------------- 1 | import 'package:gsy_github_app_flutter/common/model/NotificationSubject.dart'; 2 | import 'package:gsy_github_app_flutter/common/model/Repository.dart'; 3 | import 'package:json_annotation/json_annotation.dart'; 4 | 5 | /** 6 | * Created by guoshuyu 7 | * Date: 2018-07-31 8 | */ 9 | 10 | part 'Notification.g.dart'; 11 | 12 | @JsonSerializable() 13 | class Notification { 14 | String id; 15 | bool unread; 16 | String reason; 17 | @JsonKey(name: "updated_at") 18 | DateTime updateAt; 19 | @JsonKey(name: "last_read_at") 20 | DateTime lastReadAt; 21 | Repository repository; 22 | NotificationSubject subject; 23 | 24 | Notification(this.id, this.unread, this.reason, this.updateAt, this.lastReadAt, this.repository, this.subject); 25 | 26 | factory Notification.fromJson(Map json) => _$NotificationFromJson(json); 27 | 28 | Map toJson() => _$NotificationToJson(this); 29 | } 30 | -------------------------------------------------------------------------------- /lib/common/model/Notification.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'Notification.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | Notification _$NotificationFromJson(Map json) { 10 | return Notification( 11 | json['id'] as String, 12 | json['unread'] as bool, 13 | json['reason'] as String, 14 | json['updated_at'] == null 15 | ? null 16 | : DateTime.parse(json['updated_at'] as String), 17 | json['last_read_at'] == null 18 | ? null 19 | : DateTime.parse(json['last_read_at'] as String), 20 | json['repository'] == null 21 | ? null 22 | : Repository.fromJson(json['repository'] as Map), 23 | json['subject'] == null 24 | ? null 25 | : NotificationSubject.fromJson( 26 | json['subject'] as Map)); 27 | } 28 | 29 | Map _$NotificationToJson(Notification instance) => 30 | { 31 | 'id': instance.id, 32 | 'unread': instance.unread, 33 | 'reason': instance.reason, 34 | 'updated_at': instance.updateAt?.toIso8601String(), 35 | 'last_read_at': instance.lastReadAt?.toIso8601String(), 36 | 'repository': instance.repository, 37 | 'subject': instance.subject 38 | }; 39 | -------------------------------------------------------------------------------- /lib/common/model/NotificationSubject.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | /** 4 | * Created by guoshuyu 5 | * Date: 2018-07-31 6 | */ 7 | 8 | part 'NotificationSubject.g.dart'; 9 | 10 | @JsonSerializable() 11 | class NotificationSubject { 12 | String title; 13 | String url; 14 | String type; 15 | 16 | NotificationSubject(this.title, this.url, this.type); 17 | 18 | factory NotificationSubject.fromJson(Map json) => _$NotificationSubjectFromJson(json); 19 | 20 | Map toJson() => _$NotificationSubjectToJson(this); 21 | } 22 | -------------------------------------------------------------------------------- /lib/common/model/NotificationSubject.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'NotificationSubject.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | NotificationSubject _$NotificationSubjectFromJson(Map json) { 10 | return NotificationSubject( 11 | json['title'] as String, json['url'] as String, json['type'] as String); 12 | } 13 | 14 | Map _$NotificationSubjectToJson( 15 | NotificationSubject instance) => 16 | { 17 | 'title': instance.title, 18 | 'url': instance.url, 19 | 'type': instance.type 20 | }; 21 | -------------------------------------------------------------------------------- /lib/common/model/PushCommit.dart: -------------------------------------------------------------------------------- 1 | import 'package:gsy_github_app_flutter/common/model/CommitFile.dart'; 2 | import 'package:gsy_github_app_flutter/common/model/CommitGitInfo.dart'; 3 | import 'package:gsy_github_app_flutter/common/model/CommitStats.dart'; 4 | import 'package:gsy_github_app_flutter/common/model/RepoCommit.dart'; 5 | import 'package:gsy_github_app_flutter/common/model/User.dart'; 6 | import 'package:json_annotation/json_annotation.dart'; 7 | 8 | /** 9 | * Created by guoshuyu 10 | * Date: 2018-07-31 11 | */ 12 | 13 | part 'PushCommit.g.dart'; 14 | 15 | @JsonSerializable() 16 | class PushCommit { 17 | List files; 18 | 19 | CommitStats stats; 20 | 21 | String sha; 22 | String url; 23 | @JsonKey(name: "html_url") 24 | String htmlUrl; 25 | @JsonKey(name: "comments_url") 26 | String commentsUrl; 27 | 28 | CommitGitInfo commit; 29 | User author; 30 | User committer; 31 | List parents; 32 | 33 | PushCommit( 34 | this.files, 35 | this.stats, 36 | this.sha, 37 | this.url, 38 | this.htmlUrl, 39 | this.commentsUrl, 40 | this.commit, 41 | this.author, 42 | this.committer, 43 | this.parents, 44 | ); 45 | 46 | factory PushCommit.fromJson(Map json) => _$PushCommitFromJson(json); 47 | 48 | Map toJson() => _$PushCommitToJson(this); 49 | } 50 | -------------------------------------------------------------------------------- /lib/common/model/PushCommit.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'PushCommit.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | PushCommit _$PushCommitFromJson(Map json) { 10 | return PushCommit( 11 | (json['files'] as List) 12 | ?.map((e) => 13 | e == null ? null : CommitFile.fromJson(e as Map)) 14 | ?.toList(), 15 | json['stats'] == null 16 | ? null 17 | : CommitStats.fromJson(json['stats'] as Map), 18 | json['sha'] as String, 19 | json['url'] as String, 20 | json['html_url'] as String, 21 | json['comments_url'] as String, 22 | json['commit'] == null 23 | ? null 24 | : CommitGitInfo.fromJson(json['commit'] as Map), 25 | json['author'] == null 26 | ? null 27 | : User.fromJson(json['author'] as Map), 28 | json['committer'] == null 29 | ? null 30 | : User.fromJson(json['committer'] as Map), 31 | (json['parents'] as List) 32 | ?.map((e) => 33 | e == null ? null : RepoCommit.fromJson(e as Map)) 34 | ?.toList()); 35 | } 36 | 37 | Map _$PushCommitToJson(PushCommit instance) => 38 | { 39 | 'files': instance.files, 40 | 'stats': instance.stats, 41 | 'sha': instance.sha, 42 | 'url': instance.url, 43 | 'html_url': instance.htmlUrl, 44 | 'comments_url': instance.commentsUrl, 45 | 'commit': instance.commit, 46 | 'author': instance.author, 47 | 'committer': instance.committer, 48 | 'parents': instance.parents 49 | }; 50 | -------------------------------------------------------------------------------- /lib/common/model/PushEventCommit.dart: -------------------------------------------------------------------------------- 1 | import 'package:gsy_github_app_flutter/common/model/User.dart'; 2 | import 'package:json_annotation/json_annotation.dart'; 3 | 4 | /** 5 | * Created by guoshuyu 6 | * Date: 2018-07-31 7 | */ 8 | 9 | part 'PushEventCommit.g.dart'; 10 | 11 | @JsonSerializable() 12 | class PushEventCommit { 13 | String sha; 14 | User author; 15 | String message; 16 | bool distinct; 17 | String url; 18 | 19 | PushEventCommit( 20 | this.sha, 21 | this.author, 22 | this.message, 23 | this.distinct, 24 | this.url, 25 | ); 26 | 27 | factory PushEventCommit.fromJson(Map json) => _$PushEventCommitFromJson(json); 28 | 29 | Map toJson() => _$PushEventCommitToJson(this); 30 | } 31 | -------------------------------------------------------------------------------- /lib/common/model/PushEventCommit.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'PushEventCommit.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | PushEventCommit _$PushEventCommitFromJson(Map json) { 10 | return PushEventCommit( 11 | json['sha'] as String, 12 | json['author'] == null 13 | ? null 14 | : User.fromJson(json['author'] as Map), 15 | json['message'] as String, 16 | json['distinct'] as bool, 17 | json['url'] as String); 18 | } 19 | 20 | Map _$PushEventCommitToJson(PushEventCommit instance) => 21 | { 22 | 'sha': instance.sha, 23 | 'author': instance.author, 24 | 'message': instance.message, 25 | 'distinct': instance.distinct, 26 | 'url': instance.url 27 | }; 28 | -------------------------------------------------------------------------------- /lib/common/model/Release.dart: -------------------------------------------------------------------------------- 1 | import 'package:gsy_github_app_flutter/common/model/ReleaseAsset.dart'; 2 | import 'package:gsy_github_app_flutter/common/model/User.dart'; 3 | import 'package:json_annotation/json_annotation.dart'; 4 | 5 | /** 6 | * Created by guoshuyu 7 | * Date: 2018-07-31 8 | */ 9 | 10 | part 'Release.g.dart'; 11 | 12 | @JsonSerializable() 13 | class Release { 14 | int id; 15 | @JsonKey(name: "tag_name") 16 | String tagName; 17 | @JsonKey(name: "target_commitish") 18 | String targetCommitish; 19 | String name; 20 | String body; 21 | @JsonKey(name: "body_html") 22 | String bodyHtml; 23 | @JsonKey(name: "tarball_url") 24 | String tarballUrl; 25 | @JsonKey(name: "zipball_url") 26 | String zipballUrl; 27 | 28 | bool draft; 29 | @JsonKey(name: "prerelease") 30 | bool preRelease; 31 | @JsonKey(name: "created_at") 32 | DateTime createdAt; 33 | @JsonKey(name: "published_at") 34 | DateTime publishedAt; 35 | 36 | User author; 37 | List assets; 38 | 39 | Release( 40 | this.id, 41 | this.tagName, 42 | @JsonKey(name: "target_commitish") this.targetCommitish, 43 | this.name, 44 | this.body, 45 | this.bodyHtml, 46 | this.tarballUrl, 47 | this.zipballUrl, 48 | this.draft, 49 | this.preRelease, 50 | this.createdAt, 51 | this.publishedAt, 52 | this.author, 53 | this.assets, 54 | ); 55 | 56 | factory Release.fromJson(Map json) => _$ReleaseFromJson(json); 57 | 58 | Map toJson() => _$ReleaseToJson(this); 59 | } 60 | -------------------------------------------------------------------------------- /lib/common/model/Release.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'Release.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | Release _$ReleaseFromJson(Map json) { 10 | return Release( 11 | json['id'] as int, 12 | json['tag_name'] as String, 13 | json['target_commitish'] as String, 14 | json['name'] as String, 15 | json['body'] as String, 16 | json['body_html'] as String, 17 | json['tarball_url'] as String, 18 | json['zipball_url'] as String, 19 | json['draft'] as bool, 20 | json['prerelease'] as bool, 21 | json['created_at'] == null 22 | ? null 23 | : DateTime.parse(json['created_at'] as String), 24 | json['published_at'] == null 25 | ? null 26 | : DateTime.parse(json['published_at'] as String), 27 | json['author'] == null 28 | ? null 29 | : User.fromJson(json['author'] as Map), 30 | (json['assets'] as List) 31 | ?.map((e) => e == null 32 | ? null 33 | : ReleaseAsset.fromJson(e as Map)) 34 | ?.toList()); 35 | } 36 | 37 | Map _$ReleaseToJson(Release instance) => { 38 | 'id': instance.id, 39 | 'tag_name': instance.tagName, 40 | 'target_commitish': instance.targetCommitish, 41 | 'name': instance.name, 42 | 'body': instance.body, 43 | 'body_html': instance.bodyHtml, 44 | 'tarball_url': instance.tarballUrl, 45 | 'zipball_url': instance.zipballUrl, 46 | 'draft': instance.draft, 47 | 'prerelease': instance.preRelease, 48 | 'created_at': instance.createdAt?.toIso8601String(), 49 | 'published_at': instance.publishedAt?.toIso8601String(), 50 | 'author': instance.author, 51 | 'assets': instance.assets 52 | }; 53 | -------------------------------------------------------------------------------- /lib/common/model/ReleaseAsset.dart: -------------------------------------------------------------------------------- 1 | import 'package:gsy_github_app_flutter/common/model/User.dart'; 2 | import 'package:json_annotation/json_annotation.dart'; 3 | 4 | /** 5 | * Created by guoshuyu 6 | * Date: 2018-07-31 7 | */ 8 | 9 | part 'ReleaseAsset.g.dart'; 10 | 11 | @JsonSerializable() 12 | class ReleaseAsset { 13 | int id; 14 | String name; 15 | String label; 16 | User uploader; 17 | @JsonKey(name: "content_type") 18 | String contentType; 19 | String state; 20 | int size; 21 | int downloadCout; 22 | @JsonKey(name: "created_at") 23 | DateTime createdAt; 24 | @JsonKey(name: "updated_at") 25 | DateTime updatedAt; 26 | @JsonKey(name: "browser_download_url") 27 | String downloadUrl; 28 | 29 | ReleaseAsset( 30 | this.id, 31 | this.name, 32 | this.label, 33 | this.uploader, 34 | this.contentType, 35 | this.state, 36 | this.size, 37 | this.downloadCout, 38 | this.createdAt, 39 | this.updatedAt, 40 | this.downloadUrl, 41 | ); 42 | 43 | factory ReleaseAsset.fromJson(Map json) => _$ReleaseAssetFromJson(json); 44 | Map toJson() => _$ReleaseAssetToJson(this); 45 | } 46 | -------------------------------------------------------------------------------- /lib/common/model/ReleaseAsset.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'ReleaseAsset.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | ReleaseAsset _$ReleaseAssetFromJson(Map json) { 10 | return ReleaseAsset( 11 | json['id'] as int, 12 | json['name'] as String, 13 | json['label'] as String, 14 | json['uploader'] == null 15 | ? null 16 | : User.fromJson(json['uploader'] as Map), 17 | json['content_type'] as String, 18 | json['state'] as String, 19 | json['size'] as int, 20 | json['downloadCout'] as int, 21 | json['created_at'] == null 22 | ? null 23 | : DateTime.parse(json['created_at'] as String), 24 | json['updated_at'] == null 25 | ? null 26 | : DateTime.parse(json['updated_at'] as String), 27 | json['browser_download_url'] as String); 28 | } 29 | 30 | Map _$ReleaseAssetToJson(ReleaseAsset instance) => 31 | { 32 | 'id': instance.id, 33 | 'name': instance.name, 34 | 'label': instance.label, 35 | 'uploader': instance.uploader, 36 | 'content_type': instance.contentType, 37 | 'state': instance.state, 38 | 'size': instance.size, 39 | 'downloadCout': instance.downloadCout, 40 | 'created_at': instance.createdAt?.toIso8601String(), 41 | 'updated_at': instance.updatedAt?.toIso8601String(), 42 | 'browser_download_url': instance.downloadUrl 43 | }; 44 | -------------------------------------------------------------------------------- /lib/common/model/RepoCommit.dart: -------------------------------------------------------------------------------- 1 | import 'package:gsy_github_app_flutter/common/model/CommitGitInfo.dart'; 2 | import 'package:gsy_github_app_flutter/common/model/User.dart'; 3 | import 'package:json_annotation/json_annotation.dart'; 4 | 5 | /** 6 | * Created by guoshuyu 7 | * Date: 2018-07-31 8 | */ 9 | 10 | part 'RepoCommit.g.dart'; 11 | 12 | @JsonSerializable() 13 | class RepoCommit { 14 | String sha; 15 | String url; 16 | @JsonKey(name: "html_url") 17 | String htmlUrl; 18 | @JsonKey(name: "comments_url") 19 | String commentsUrl; 20 | 21 | CommitGitInfo commit; 22 | User author; 23 | User committer; 24 | List parents; 25 | 26 | RepoCommit( 27 | this.sha, 28 | this.url, 29 | this.htmlUrl, 30 | this.commentsUrl, 31 | this.commit, 32 | this.author, 33 | this.committer, 34 | this.parents, 35 | ); 36 | 37 | factory RepoCommit.fromJson(Map json) => _$RepoCommitFromJson(json); 38 | Map toJson() => _$RepoCommitToJson(this); 39 | } 40 | -------------------------------------------------------------------------------- /lib/common/model/RepoCommit.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'RepoCommit.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | RepoCommit _$RepoCommitFromJson(Map json) { 10 | return RepoCommit( 11 | json['sha'] as String, 12 | json['url'] as String, 13 | json['html_url'] as String, 14 | json['comments_url'] as String, 15 | json['commit'] == null 16 | ? null 17 | : CommitGitInfo.fromJson(json['commit'] as Map), 18 | json['author'] == null 19 | ? null 20 | : User.fromJson(json['author'] as Map), 21 | json['committer'] == null 22 | ? null 23 | : User.fromJson(json['committer'] as Map), 24 | (json['parents'] as List) 25 | ?.map((e) => 26 | e == null ? null : RepoCommit.fromJson(e as Map)) 27 | ?.toList()); 28 | } 29 | 30 | Map _$RepoCommitToJson(RepoCommit instance) => 31 | { 32 | 'sha': instance.sha, 33 | 'url': instance.url, 34 | 'html_url': instance.htmlUrl, 35 | 'comments_url': instance.commentsUrl, 36 | 'commit': instance.commit, 37 | 'author': instance.author, 38 | 'committer': instance.committer, 39 | 'parents': instance.parents 40 | }; 41 | -------------------------------------------------------------------------------- /lib/common/model/RepositoryPermissions.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | /** 4 | * Created by guoshuyu 5 | * Date: 2018-07-31 6 | */ 7 | 8 | part 'RepositoryPermissions.g.dart'; 9 | 10 | @JsonSerializable() 11 | class RepositoryPermissions { 12 | bool admin; 13 | bool push; 14 | bool pull; 15 | 16 | RepositoryPermissions( 17 | this.admin, 18 | this.push, 19 | this.pull, 20 | ); 21 | 22 | factory RepositoryPermissions.fromJson(Map json) => _$RepositoryPermissionsFromJson(json); 23 | Map toJson() => _$RepositoryPermissionsToJson(this); 24 | } 25 | -------------------------------------------------------------------------------- /lib/common/model/RepositoryPermissions.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'RepositoryPermissions.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | RepositoryPermissions _$RepositoryPermissionsFromJson( 10 | Map json) { 11 | return RepositoryPermissions( 12 | json['admin'] as bool, json['push'] as bool, json['pull'] as bool); 13 | } 14 | 15 | Map _$RepositoryPermissionsToJson( 16 | RepositoryPermissions instance) => 17 | { 18 | 'admin': instance.admin, 19 | 'push': instance.push, 20 | 'pull': instance.pull 21 | }; 22 | -------------------------------------------------------------------------------- /lib/common/model/Template.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | 4 | part 'Template.g.dart'; 5 | 6 | @JsonSerializable() 7 | class Template { 8 | 9 | String name; 10 | 11 | int id; 12 | 13 | 14 | @JsonKey(name: "push_id") 15 | int pushId; 16 | 17 | Template(this.name, this.id, this.pushId); 18 | 19 | 20 | factory Template.fromJson(Map json) => _$TemplateFromJson(json); 21 | Map toJson() => _$TemplateToJson(this); 22 | } 23 | -------------------------------------------------------------------------------- /lib/common/model/Template.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'Template.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | Template _$TemplateFromJson(Map json) { 10 | return Template( 11 | json['name'] as String, json['id'] as int, json['push_id'] as int); 12 | } 13 | 14 | Map _$TemplateToJson(Template instance) => { 15 | 'name': instance.name, 16 | 'id': instance.id, 17 | 'push_id': instance.pushId 18 | }; 19 | -------------------------------------------------------------------------------- /lib/common/model/TrendingRepoModel.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | /** 4 | * Created by guoshuyu 5 | * Date: 2018-08-07 6 | */ 7 | part 'TrendingRepoModel.g.dart'; 8 | 9 | @JsonSerializable() 10 | class TrendingRepoModel { 11 | String fullName; 12 | String url; 13 | 14 | String description; 15 | String language; 16 | String meta; 17 | List contributors; 18 | String contributorsUrl; 19 | 20 | String starCount; 21 | String forkCount; 22 | String name; 23 | 24 | String reposName; 25 | 26 | TrendingRepoModel( 27 | this.fullName, 28 | this.url, 29 | this.description, 30 | this.language, 31 | this.meta, 32 | this.contributors, 33 | this.contributorsUrl, 34 | this.starCount, 35 | this.name, 36 | this.reposName, 37 | this.forkCount, 38 | ); 39 | 40 | TrendingRepoModel.empty(); 41 | 42 | factory TrendingRepoModel.fromJson(Map json) => _$TrendingRepoModelFromJson(json); 43 | 44 | Map toJson() => _$TrendingRepoModelToJson(this); 45 | } 46 | -------------------------------------------------------------------------------- /lib/common/model/TrendingRepoModel.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'TrendingRepoModel.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | TrendingRepoModel _$TrendingRepoModelFromJson(Map json) { 10 | return TrendingRepoModel( 11 | json['fullName'] as String, 12 | json['url'] as String, 13 | json['description'] as String, 14 | json['language'] as String, 15 | json['meta'] as String, 16 | (json['contributors'] as List)?.map((e) => e as String)?.toList(), 17 | json['contributorsUrl'] as String, 18 | json['starCount'] as String, 19 | json['name'] as String, 20 | json['reposName'] as String, 21 | json['forkCount'] as String); 22 | } 23 | 24 | Map _$TrendingRepoModelToJson(TrendingRepoModel instance) => 25 | { 26 | 'fullName': instance.fullName, 27 | 'url': instance.url, 28 | 'description': instance.description, 29 | 'language': instance.language, 30 | 'meta': instance.meta, 31 | 'contributors': instance.contributors, 32 | 'contributorsUrl': instance.contributorsUrl, 33 | 'starCount': instance.starCount, 34 | 'forkCount': instance.forkCount, 35 | 'name': instance.name, 36 | 'reposName': instance.reposName 37 | }; 38 | -------------------------------------------------------------------------------- /lib/common/model/User.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'User.g.dart'; 4 | 5 | @JsonSerializable() 6 | class User { 7 | User( 8 | this.login, 9 | this.id, 10 | this.node_id, 11 | this.avatar_url, 12 | this.gravatar_id, 13 | this.url, 14 | this.html_url, 15 | this.followers_url, 16 | this.following_url, 17 | this.gists_url, 18 | this.starred_url, 19 | this.subscriptions_url, 20 | this.organizations_url, 21 | this.repos_url, 22 | this.events_url, 23 | this.received_events_url, 24 | this.type, 25 | this.site_admin, 26 | this.name, 27 | this.company, 28 | this.blog, 29 | this.location, 30 | this.email, 31 | this.starred, 32 | this.bio, 33 | this.public_repos, 34 | this.public_gists, 35 | this.followers, 36 | this.following, 37 | this.created_at, 38 | this.updated_at, 39 | this.private_gists, 40 | this.total_private_repos, 41 | this.owned_private_repos, 42 | this.disk_usage, 43 | this.collaborators, 44 | this.two_factor_authentication); 45 | 46 | String login; 47 | int id; 48 | String node_id; 49 | String avatar_url; 50 | String gravatar_id; 51 | String url; 52 | String html_url; 53 | String followers_url; 54 | String following_url; 55 | String gists_url; 56 | String starred_url; 57 | String subscriptions_url; 58 | String organizations_url; 59 | String repos_url; 60 | String events_url; 61 | String received_events_url; 62 | String type; 63 | bool site_admin; 64 | String name; 65 | String company; 66 | String blog; 67 | String location; 68 | String email; 69 | String starred; 70 | String bio; 71 | int public_repos; 72 | int public_gists; 73 | int followers; 74 | int following; 75 | DateTime created_at; 76 | DateTime updated_at; 77 | int private_gists; 78 | int total_private_repos; 79 | int owned_private_repos; 80 | int disk_usage; 81 | int collaborators; 82 | bool two_factor_authentication; 83 | 84 | 85 | factory User.fromJson(Map json) => _$UserFromJson(json); 86 | 87 | 88 | Map toJson() => _$UserToJson(this); 89 | 90 | // 命名构造函数 91 | User.empty(); 92 | 93 | } 94 | -------------------------------------------------------------------------------- /lib/common/model/UserOrg.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | /** 4 | * Created by guoshuyu 5 | * Date: 2018-08-10 6 | */ 7 | part 'UserOrg.g.dart'; 8 | 9 | @JsonSerializable() 10 | class UserOrg { 11 | String login; 12 | int id; 13 | String url; 14 | String description; 15 | @JsonKey(name: "node_id") 16 | String nodeId; 17 | @JsonKey(name: "repos_url") 18 | String reposUrl; 19 | @JsonKey(name: "events_url") 20 | String eventsUrl; 21 | @JsonKey(name: "hooks_url") 22 | String hooksUrl; 23 | @JsonKey(name: "issues_url") 24 | String issuesUrl; 25 | @JsonKey(name: "members_url") 26 | String membersUrl; 27 | @JsonKey(name: "public_members_url") 28 | String publicMembersUrl; 29 | @JsonKey(name: "avatar_url") 30 | String avatarUrl; 31 | 32 | UserOrg( 33 | this.login, 34 | this.id, 35 | this.url, 36 | this.description, 37 | this.nodeId, 38 | this.reposUrl, 39 | this.eventsUrl, 40 | this.hooksUrl, 41 | this.issuesUrl, 42 | this.membersUrl, 43 | this.publicMembersUrl, 44 | this.avatarUrl, 45 | ); 46 | 47 | factory UserOrg.fromJson(Map json) => _$UserOrgFromJson(json); 48 | 49 | 50 | Map toJson() => _$UserOrgToJson(this); 51 | 52 | // 命名构造函数 53 | UserOrg.empty(); 54 | } 55 | -------------------------------------------------------------------------------- /lib/common/model/UserOrg.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'UserOrg.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | UserOrg _$UserOrgFromJson(Map json) { 10 | return UserOrg( 11 | json['login'] as String, 12 | json['id'] as int, 13 | json['url'] as String, 14 | json['description'] as String, 15 | json['node_id'] as String, 16 | json['repos_url'] as String, 17 | json['events_url'] as String, 18 | json['hooks_url'] as String, 19 | json['issues_url'] as String, 20 | json['members_url'] as String, 21 | json['public_members_url'] as String, 22 | json['avatar_url'] as String); 23 | } 24 | 25 | Map _$UserOrgToJson(UserOrg instance) => { 26 | 'login': instance.login, 27 | 'id': instance.id, 28 | 'url': instance.url, 29 | 'description': instance.description, 30 | 'node_id': instance.nodeId, 31 | 'repos_url': instance.reposUrl, 32 | 'events_url': instance.eventsUrl, 33 | 'hooks_url': instance.hooksUrl, 34 | 'issues_url': instance.issuesUrl, 35 | 'members_url': instance.membersUrl, 36 | 'public_members_url': instance.publicMembersUrl, 37 | 'avatar_url': instance.avatarUrl 38 | }; 39 | -------------------------------------------------------------------------------- /lib/common/net/code.dart: -------------------------------------------------------------------------------- 1 | import 'package:event_bus/event_bus.dart'; 2 | import 'package:gsy_github_app_flutter/common/event/http_error_event.dart'; 3 | ///错误编码 4 | class Code { 5 | ///网络错误 6 | static const NETWORK_ERROR = -1; 7 | 8 | ///网络超时 9 | static const NETWORK_TIMEOUT = -2; 10 | 11 | ///网络返回数据格式化一次 12 | static const NETWORK_JSON_EXCEPTION = -3; 13 | 14 | static const SUCCESS = 200; 15 | 16 | static final EventBus eventBus = new EventBus(); 17 | 18 | static errorHandleFunction(code, message, noTip) { 19 | if(noTip) { 20 | return message; 21 | } 22 | eventBus.fire(new HttpErrorEvent(code, message)); 23 | return message; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/common/net/interceptors/error_interceptor.dart: -------------------------------------------------------------------------------- 1 | import 'package:connectivity/connectivity.dart'; 2 | import 'package:dio/dio.dart'; 3 | import 'package:gsy_github_app_flutter/common/net/code.dart'; 4 | import 'package:gsy_github_app_flutter/common/net/result_data.dart'; 5 | 6 | ///是否需要弹提示 7 | const NOT_TIP_KEY = "noTip"; 8 | 9 | /** 10 | * 错误拦截 11 | * Created by guoshuyu 12 | * on 2019/3/23. 13 | */ 14 | class ErrorInterceptors extends InterceptorsWrapper { 15 | final Dio _dio; 16 | 17 | ErrorInterceptors(this._dio); 18 | 19 | @override 20 | onRequest(RequestOptions options) async { 21 | //没有网络 22 | var connectivityResult = await (new Connectivity().checkConnectivity()); 23 | if (connectivityResult == ConnectivityResult.none) { 24 | return _dio.resolve(new ResultData(Code.errorHandleFunction(Code.NETWORK_ERROR, "", false), false, Code.NETWORK_ERROR)); 25 | } 26 | return options; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/common/net/interceptors/header_interceptor.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | 3 | /** 4 | * header拦截器 5 | * Created by guoshuyu 6 | * on 2019/3/23. 7 | */ 8 | class HeaderInterceptors extends InterceptorsWrapper { 9 | 10 | 11 | @override 12 | onRequest(RequestOptions options) { 13 | ///超时 14 | options.connectTimeout = 15000; 15 | 16 | return options; 17 | } 18 | } -------------------------------------------------------------------------------- /lib/common/net/interceptors/log_interceptor.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | import 'package:gsy_github_app_flutter/common/config/config.dart'; 3 | 4 | /** 5 | * Log 拦截器 6 | * Created by guoshuyu 7 | * on 2019/3/23. 8 | */ 9 | class LogsInterceptors extends InterceptorsWrapper { 10 | @override 11 | onRequest(RequestOptions options) { 12 | if (Config.DEBUG) { 13 | print("请求url:${options.path}"); 14 | print('请求头: ' + options.headers.toString()); 15 | if (options.data != null) { 16 | print('请求参数: ' + options.data.toString()); 17 | } 18 | } 19 | return options; 20 | } 21 | 22 | @override 23 | onResponse(Response response) { 24 | if (Config.DEBUG) { 25 | if (response != null) { 26 | print('返回参数: ' + response.toString()); 27 | } 28 | } 29 | return response; // continue 30 | } 31 | 32 | @override 33 | onError(DioError err) { 34 | if (Config.DEBUG) { 35 | print('请求异常: ' + err.toString()); 36 | print('请求异常信息: ' + err.response?.toString() ?? ""); 37 | } 38 | return err; 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /lib/common/net/interceptors/response_interceptor.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | import 'package:gsy_github_app_flutter/common/net/code.dart'; 3 | import 'package:gsy_github_app_flutter/common/net/result_data.dart'; 4 | 5 | /** 6 | * Token拦截器 7 | * Created by guoshuyu 8 | * on 2019/3/23. 9 | */ 10 | class ResponseInterceptors extends InterceptorsWrapper { 11 | 12 | @override 13 | onResponse(Response response) { 14 | RequestOptions option = response.request; 15 | try { 16 | if (option.contentType != null && option.contentType.primaryType == "text") { 17 | return new ResultData(response.data, true, Code.SUCCESS); 18 | } 19 | if (response.statusCode == 200 || response.statusCode == 201) { 20 | return new ResultData(response.data, true, Code.SUCCESS, headers: response.headers); 21 | } 22 | } catch (e) { 23 | print(e.toString() + option.path); 24 | return new ResultData(response.data, false, response.statusCode, headers: response.headers); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /lib/common/net/interceptors/token_interceptor.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | import 'package:gsy_github_app_flutter/common/config/config.dart'; 3 | import 'package:gsy_github_app_flutter/common/local/local_storage.dart'; 4 | 5 | /** 6 | * Token拦截器 7 | * Created by guoshuyu 8 | * on 2019/3/23. 9 | */ 10 | class TokenInterceptors extends InterceptorsWrapper { 11 | 12 | String _token; 13 | 14 | @override 15 | onRequest(RequestOptions options) async { 16 | //授权码 17 | if (_token == null) { 18 | var authorizationCode = await getAuthorization(); 19 | if (authorizationCode != null) { 20 | _token = authorizationCode; 21 | } 22 | } 23 | options.headers["Authorization"] = _token; 24 | return options; 25 | } 26 | 27 | 28 | @override 29 | onResponse(Response response) async{ 30 | try { 31 | var responseJson = response.data; 32 | if (response.statusCode == 201 && responseJson["token"] != null) { 33 | _token = 'token ' + responseJson["token"]; 34 | await LocalStorage.save(Config.TOKEN_KEY, _token); 35 | } 36 | } catch (e) { 37 | print(e); 38 | } 39 | return response; 40 | } 41 | 42 | ///清除授权 43 | clearAuthorization() { 44 | this._token = null; 45 | LocalStorage.remove(Config.TOKEN_KEY); 46 | } 47 | 48 | ///获取授权token 49 | getAuthorization() async { 50 | String token = await LocalStorage.get(Config.TOKEN_KEY); 51 | if (token == null) { 52 | String basic = await LocalStorage.get(Config.USER_BASIC_CODE); 53 | if (basic == null) { 54 | //提示输入账号密码 55 | } else { 56 | //通过 basic 去获取token,获取到设置,返回token 57 | return "Basic $basic"; 58 | } 59 | } else { 60 | this._token = token; 61 | return token; 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /lib/common/net/result_data.dart: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * 网络结果数据 4 | * Created by guoshuyu 5 | * Date: 2018-07-16 6 | */ 7 | class ResultData { 8 | var data; 9 | bool result; 10 | int code; 11 | var headers; 12 | 13 | ResultData(this.data, this.result, this.code, {this.headers}); 14 | } 15 | -------------------------------------------------------------------------------- /lib/common/redux/gsy_state.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:gsy_github_app_flutter/common/model/User.dart'; 3 | import 'package:gsy_github_app_flutter/common/redux/middleware/epic_middleware.dart'; 4 | import 'package:gsy_github_app_flutter/common/redux/user_redux.dart'; 5 | import 'package:gsy_github_app_flutter/common/redux/theme_redux.dart'; 6 | import 'package:gsy_github_app_flutter/common/redux/locale_redux.dart'; 7 | import 'package:redux/redux.dart'; 8 | 9 | /** 10 | * Redux全局State 11 | * Created by guoshuyu 12 | * Date: 2018-07-16 13 | */ 14 | 15 | ///全局Redux store 的对象,保存State数据 16 | class GSYState { 17 | ///用户信息 18 | User userInfo; 19 | 20 | ///主题数据 21 | ThemeData themeData; 22 | 23 | ///语言 24 | Locale locale; 25 | 26 | ///当前手机平台默认语言 27 | Locale platformLocale; 28 | 29 | ///构造方法 30 | GSYState({this.userInfo, this.themeData, this.locale}); 31 | } 32 | 33 | ///创建 Reducer 34 | ///源码中 Reducer 是一个方法 typedef State Reducer(State state, dynamic action); 35 | ///我们自定义了 appReducer 用于创建 store 36 | GSYState appReducer(GSYState state, action) { 37 | return GSYState( 38 | ///通过 UserReducer 将 GSYState 内的 userInfo 和 action 关联在一起 39 | userInfo: UserReducer(state.userInfo, action), 40 | 41 | ///通过 ThemeDataReducer 将 GSYState 内的 themeData 和 action 关联在一起 42 | themeData: ThemeDataReducer(state.themeData, action), 43 | 44 | ///通过 LocaleReducer 将 GSYState 内的 locale 和 action 关联在一起 45 | locale: LocaleReducer(state.locale, action), 46 | ); 47 | } 48 | 49 | 50 | 51 | final List> middleware = [ 52 | EpicMiddleware(UserInfoEpic()), 53 | UserInfoMiddleware(), 54 | ]; -------------------------------------------------------------------------------- /lib/common/redux/locale_redux.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:flutter/material.dart'; 3 | import 'package:redux/redux.dart'; 4 | 5 | /** 6 | * 语言Redux 7 | * Created by guoshuyu 8 | * Date: 2018-07-16 9 | */ 10 | 11 | final LocaleReducer = combineReducers([ 12 | TypedReducer(_refresh), 13 | ]); 14 | 15 | Locale _refresh(Locale locale, RefreshLocaleAction action) { 16 | locale = action.locale; 17 | return locale; 18 | } 19 | 20 | class RefreshLocaleAction { 21 | final Locale locale; 22 | 23 | RefreshLocaleAction(this.locale); 24 | } 25 | 26 | 27 | -------------------------------------------------------------------------------- /lib/common/redux/middleware/combine_epics.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:gsy_github_app_flutter/common/redux/middleware/epic.dart'; 4 | import 'package:gsy_github_app_flutter/common/redux/middleware/epic_store.dart'; 5 | import 'package:rxdart/streams.dart'; 6 | 7 | /// Combines a list of [Epic]s into one. 8 | /// 9 | /// Rather than having one massive [Epic] that handles every possible type of 10 | /// action, it's best to break [Epic]s down into smaller, more manageable and 11 | /// testable units. This way we could have a `searchEpic`, a `chatEpic`, 12 | /// and an `updateProfileEpic`, for example. 13 | /// 14 | /// However, the [EpicMiddleware] accepts only one [Epic]. So what are we to do? 15 | /// Fear not: redux_epics includes class for combining [Epic]s together! 16 | /// 17 | /// Example: 18 | /// 19 | /// final epic = combineEpics([ 20 | /// searchEpic, 21 | /// chatEpic, 22 | /// updateProfileEpic, 23 | /// ]); 24 | Epic combineEpics(List> epics) { 25 | return (Stream actions, EpicStore store) { 26 | return new MergeStream(epics.map((epic) => epic(actions, store))); 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /lib/common/redux/middleware/epic_middleware.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:gsy_github_app_flutter/common/redux/middleware/epic.dart'; 4 | import 'package:gsy_github_app_flutter/common/redux/middleware/epic_store.dart'; 5 | import 'package:redux/redux.dart'; 6 | import 'package:rxdart/transformers.dart'; 7 | 8 | /// A [Redux](https://pub.dartlang.org/packages/redux) middleware that passes 9 | /// a stream of dispatched actions to the given [Epic]. 10 | /// 11 | /// It is recommended that you put your `EpicMiddleware` first when constructing 12 | /// the list of middleware for your store so any actions dispatched from 13 | /// your [Epic] will be intercepted by the remaining Middleware. 14 | /// 15 | /// Example: 16 | /// 17 | /// var epicMiddleware = new EpicMiddleware(new ExampleEpic()); 18 | /// var store = new Store, Action>(reducer, 19 | /// initialState: [], middleware: [epicMiddleware]); 20 | class EpicMiddleware extends MiddlewareClass { 21 | final StreamController _actions = 22 | new StreamController.broadcast(); 23 | final StreamController> _epics = 24 | new StreamController.broadcast(sync: true); 25 | 26 | final bool supportAsyncGenerators; 27 | Epic _epic; 28 | bool _isSubscribed = false; 29 | 30 | EpicMiddleware(Epic epic, {this.supportAsyncGenerators = true}) 31 | : _epic = epic; 32 | 33 | @override 34 | call(Store store, dynamic action, NextDispatcher next) { 35 | if (!_isSubscribed) { 36 | _epics.stream 37 | .transform( 38 | new SwitchMapStreamTransformer, dynamic>( 39 | (epic) => epic(_actions.stream, new EpicStore(store)))) 40 | .listen(store.dispatch); 41 | 42 | _epics.add(_epic); 43 | 44 | _isSubscribed = true; 45 | } 46 | 47 | next(action); 48 | 49 | if (supportAsyncGenerators) { 50 | // Future.delayed is an ugly hack to support async* functions. 51 | // 52 | // See: https://github.com/dart-lang/sdk/issues/33818 53 | new Future.delayed(Duration.zero, () { 54 | _actions.add(action); 55 | }); 56 | } else { 57 | _actions.add(action); 58 | } 59 | } 60 | 61 | /// Gets or replaces the epic currently used by the middleware. 62 | /// 63 | /// Replacing epics is considered an advanced API. You might need this if your 64 | /// app grows large and want to instantiate Epics on the fly, rather than 65 | /// as a whole up front. 66 | Epic get epic => _epic; 67 | 68 | set epic(Epic newEpic) { 69 | _epic = newEpic; 70 | 71 | _epics.add(newEpic); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /lib/common/redux/middleware/epic_store.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:redux/redux.dart'; 4 | 5 | /// A stripped-down Redux [Store]. Removes unsupported [Store] methods. 6 | /// 7 | /// Due to the way streams are implemented with Dart, it's impossible to 8 | /// perform `store.dispatch` from within an [Epic] or observe the store directly. 9 | class EpicStore { 10 | final Store _store; 11 | 12 | EpicStore(this._store); 13 | 14 | /// Returns the current state of the redux store 15 | State get state => _store.state; 16 | 17 | Stream get onChange => _store.onChange; 18 | } 19 | -------------------------------------------------------------------------------- /lib/common/redux/theme_redux.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:redux/redux.dart'; 3 | 4 | /** 5 | * 事件Redux 6 | * Created by guoshuyu 7 | * Date: 2018-07-16 8 | */ 9 | 10 | ///通过 flutter_redux 的 combineReducers,实现 Reducer 方法 11 | final ThemeDataReducer = combineReducers([ 12 | ///将 Action 、处理 Action 的方法、State 绑定 13 | TypedReducer(_refresh), 14 | ]); 15 | 16 | ///定义处理 Action 行为的方法,返回新的 State 17 | ThemeData _refresh(ThemeData themeData, action) { 18 | themeData = action.themeData; 19 | return themeData; 20 | } 21 | 22 | ///定义一个 Action 类 23 | ///将该 Action 在 Reducer 中与处理该Action的方法绑定 24 | class RefreshThemeDataAction { 25 | 26 | final ThemeData themeData; 27 | 28 | RefreshThemeDataAction(this.themeData); 29 | } 30 | -------------------------------------------------------------------------------- /lib/common/redux/user_redux.dart: -------------------------------------------------------------------------------- 1 | import 'package:gsy_github_app_flutter/common/dao/user_dao.dart'; 2 | import 'package:gsy_github_app_flutter/common/model/User.dart'; 3 | import 'package:gsy_github_app_flutter/common/redux/gsy_state.dart'; 4 | import 'package:gsy_github_app_flutter/common/redux/middleware/epic.dart'; 5 | import 'package:gsy_github_app_flutter/common/redux/middleware/epic_store.dart'; 6 | import 'package:redux/redux.dart'; 7 | import 'package:rxdart/rxdart.dart'; 8 | 9 | /** 10 | * 用户相关Redux 11 | * Created by guoshuyu 12 | * Date: 2018-07-16 13 | */ 14 | 15 | /// redux 的 combineReducers, 通过 TypedReducer 将 UpdateUserAction 与 reducers 关联起来 16 | final UserReducer = combineReducers([ 17 | TypedReducer(_updateLoaded), 18 | ]); 19 | 20 | /// 如果有 UpdateUserAction 发起一个请求时 21 | /// 就会调用到 _updateLoaded 22 | /// _updateLoaded 这里接受一个新的userInfo,并返回 23 | User _updateLoaded(User user, action) { 24 | user = action.userInfo; 25 | return user; 26 | } 27 | 28 | ///定一个 UpdateUserAction ,用于发起 userInfo 的的改变 29 | ///类名随你喜欢定义,只要通过上面TypedReducer绑定就好 30 | class UpdateUserAction { 31 | final User userInfo; 32 | 33 | UpdateUserAction(this.userInfo); 34 | } 35 | 36 | class FetchUserAction { 37 | } 38 | 39 | 40 | class UserInfoMiddleware implements MiddlewareClass { 41 | 42 | @override 43 | void call(Store store, dynamic action, NextDispatcher next) { 44 | if (action is UpdateUserAction) { 45 | print("*********** UserInfoMiddleware *********** "); 46 | } 47 | // Make sure to forward actions to the next middleware in the chain! 48 | next(action); 49 | } 50 | } 51 | 52 | class UserInfoEpic implements EpicClass { 53 | @override 54 | Stream call(Stream actions, EpicStore store) { 55 | return Observable(actions) 56 | // to UpdateUserAction actions 57 | .ofType(TypeToken()) 58 | // Don't start until the 10ms 59 | .debounce(((_) => TimerStream(true, const Duration(milliseconds: 10)))) 60 | .switchMap((action) => _loadUserInfo()); 61 | } 62 | 63 | // Use the async* function to make easier 64 | Stream _loadUserInfo() async* { 65 | print("*********** userInfoEpic _loadUserInfo ***********"); 66 | var res = await UserDao.getUserInfo(null); 67 | yield UpdateUserAction(res.data); 68 | } 69 | } -------------------------------------------------------------------------------- /lib/common/utils/code_utils.dart: -------------------------------------------------------------------------------- 1 | 2 | 3 | import 'dart:convert'; 4 | 5 | ///isolate 的 compute 需要静态方法 6 | class CodeUtils { 7 | 8 | static List decodeListResult(String data) { 9 | return json.decode(data); 10 | } 11 | 12 | static Map decodeMapResult(String data) { 13 | return json.decode(data); 14 | } 15 | 16 | static String encodeToString(String data) { 17 | return json.encode(data); 18 | } 19 | } -------------------------------------------------------------------------------- /lib/page/home_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:io'; 3 | 4 | import 'package:android_intent/android_intent.dart'; 5 | import 'package:flutter/material.dart'; 6 | import 'package:gsy_github_app_flutter/common/localization/default_localizations.dart'; 7 | import 'package:gsy_github_app_flutter/common/style/gsy_style.dart'; 8 | import 'package:gsy_github_app_flutter/common/utils/common_utils.dart'; 9 | import 'package:gsy_github_app_flutter/common/utils/navigator_utils.dart'; 10 | import 'package:gsy_github_app_flutter/page/dynamic_page.dart'; 11 | import 'package:gsy_github_app_flutter/page/my_page.dart'; 12 | import 'package:gsy_github_app_flutter/page/trend_page.dart'; 13 | import 'package:gsy_github_app_flutter/widget/gsy_tabbar_widget.dart'; 14 | import 'package:gsy_github_app_flutter/widget/gsy_title_bar.dart'; 15 | import 'package:gsy_github_app_flutter/widget/home_drawer.dart'; 16 | 17 | /** 18 | * 主页 19 | * Created by guoshuyu 20 | * Date: 2018-07-16 21 | */ 22 | class HomePage extends StatelessWidget { 23 | static final String sName = "home"; 24 | 25 | /// 不退出 26 | Future _dialogExitApp(BuildContext context) async { 27 | if (Platform.isAndroid) { 28 | AndroidIntent intent = AndroidIntent( 29 | action: 'android.intent.action.MAIN', 30 | category: "android.intent.category.HOME", 31 | ); 32 | await intent.launch(); 33 | } 34 | 35 | return Future.value(false); 36 | } 37 | 38 | _renderTab(icon, text) { 39 | return new Tab( 40 | child: new Column( 41 | mainAxisAlignment: MainAxisAlignment.center, 42 | children: [new Icon(icon, size: 16.0), new Text(text)], 43 | ), 44 | ); 45 | } 46 | 47 | // This widget is the root of your application. 48 | @override 49 | Widget build(BuildContext context) { 50 | List tabs = [ 51 | _renderTab(GSYICons.MAIN_DT, CommonUtils.getLocale(context).home_dynamic), 52 | _renderTab(GSYICons.MAIN_QS, CommonUtils.getLocale(context).home_trend), 53 | _renderTab(GSYICons.MAIN_MY, CommonUtils.getLocale(context).home_my), 54 | ]; 55 | return WillPopScope( 56 | onWillPop: () { 57 | return _dialogExitApp(context); 58 | }, 59 | child: new GSYTabBarWidget( 60 | drawer: new HomeDrawer(), 61 | type: GSYTabBarWidget.BOTTOM_TAB, 62 | tabItems: tabs, 63 | tabViews: [ 64 | new DynamicPage(), 65 | new TrendPage(), 66 | new MyPage(), 67 | ], 68 | backgroundColor: GSYColors.primarySwatch, 69 | indicatorColor: Color(GSYColors.white), 70 | title: GSYTitleBar( 71 | GSYLocalizations.of(context).currentLocalized.app_name, 72 | iconData: GSYICons.MAIN_SEARCH, 73 | needRightLocalIcon: true, 74 | onPressed: () { 75 | NavigatorUtils.goSearchPage(context); 76 | }, 77 | ), 78 | ), 79 | ); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /lib/page/photoview_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/services.dart'; 5 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 6 | import 'package:fluttertoast/fluttertoast.dart'; 7 | import 'package:gsy_github_app_flutter/common/style/gsy_style.dart'; 8 | import 'package:gsy_github_app_flutter/common/utils/common_utils.dart'; 9 | import 'package:gsy_github_app_flutter/widget/gsy_common_option_widget.dart'; 10 | import 'package:gsy_github_app_flutter/widget/gsy_title_bar.dart'; 11 | import 'package:photo_view/photo_view.dart'; 12 | 13 | /** 14 | * 图片预览 15 | * Created by guoshuyu 16 | * Date: 2018-08-09 17 | */ 18 | 19 | class PhotoViewPage extends StatelessWidget { 20 | final String url; 21 | 22 | PhotoViewPage(this.url); 23 | 24 | @override 25 | Widget build(BuildContext context) { 26 | OptionControl optionControl = new OptionControl(); 27 | optionControl.url = url; 28 | return new Scaffold( 29 | floatingActionButton: new FloatingActionButton( 30 | child: new Icon(Icons.file_download), 31 | onPressed: () { 32 | CommonUtils.saveImage(url).then((res) { 33 | if (res != null) { 34 | Fluttertoast.showToast(msg: res); 35 | if (Platform.isAndroid) { 36 | const updateAlbum = const MethodChannel('com.shuyu.gsygithub.gsygithubflutter/UpdateAlbumPlugin'); 37 | updateAlbum.invokeMethod('updateAlbum', { 'path': res, 'name': CommonUtils.splitFileNameByPath(res)}); 38 | } 39 | } 40 | }); 41 | }, 42 | ), 43 | appBar: new AppBar( 44 | title: GSYTitleBar("", rightWidget: new GSYCommonOptionWidget(optionControl)), 45 | ), 46 | body: new Container( 47 | color: Colors.black, 48 | child: new PhotoView( 49 | imageProvider: new NetworkImage(url ?? GSYICons.DEFAULT_REMOTE_PIC), 50 | loadingChild: Container( 51 | child: new Stack( 52 | children: [ 53 | new Center(child: new Image.asset(GSYICons.DEFAULT_IMAGE, height: 180.0, width: 180.0)), 54 | new Center(child: new SpinKitFoldingCube(color: Colors.white30, size: 60.0)), 55 | ], 56 | ), 57 | ), 58 | ), 59 | )); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/page/welcome_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_lottie/flutter_lottie.dart'; 5 | import 'package:flutter_redux/flutter_redux.dart'; 6 | import 'package:gsy_github_app_flutter/common/dao/user_dao.dart'; 7 | import 'package:gsy_github_app_flutter/common/redux/gsy_state.dart'; 8 | import 'package:gsy_github_app_flutter/common/style/gsy_style.dart'; 9 | import 'package:gsy_github_app_flutter/common/utils/common_utils.dart'; 10 | import 'package:gsy_github_app_flutter/common/utils/navigator_utils.dart'; 11 | import 'package:redux/redux.dart'; 12 | 13 | /** 14 | * 欢迎页 15 | * Created by guoshuyu 16 | * Date: 2018-07-16 17 | */ 18 | 19 | class WelcomePage extends StatefulWidget { 20 | static final String sName = "/"; 21 | 22 | @override 23 | _WelcomePageState createState() => _WelcomePageState(); 24 | } 25 | 26 | class _WelcomePageState extends State { 27 | bool hadInit = false; 28 | 29 | @override 30 | void didChangeDependencies() { 31 | super.didChangeDependencies(); 32 | if (hadInit) { 33 | return; 34 | } 35 | hadInit = true; 36 | 37 | ///防止多次进入 38 | Store store = StoreProvider.of(context); 39 | CommonUtils.initStatusBarHeight(context); 40 | new Future.delayed(const Duration(seconds: 2, milliseconds: 500), () { 41 | UserDao.initUserInfo(store).then((res) { 42 | if (res != null && res.result) { 43 | NavigatorUtils.goHome(context); 44 | } else { 45 | NavigatorUtils.goLogin(context); 46 | } 47 | return true; 48 | }); 49 | }); 50 | } 51 | 52 | void onViewCreatedFile(LottieController controller) { 53 | 54 | } 55 | 56 | @override 57 | Widget build(BuildContext context) { 58 | return StoreBuilder( 59 | builder: (context, store) { 60 | double size = 200; 61 | return new Container( 62 | color: Color(GSYColors.white), 63 | child: Stack( 64 | children: [ 65 | new Center( 66 | child: new Image( 67 | image: new AssetImage('static/images/welcome.png')), 68 | ), 69 | new Align( 70 | alignment: Alignment.bottomCenter, 71 | child: new Container( 72 | width: size, 73 | height: size, 74 | color: Colors.white, 75 | child: LottieView.fromFile( 76 | filePath: "static/file/rejection2.json", 77 | autoPlay: true, 78 | loop: true, 79 | reverse: false, 80 | onViewCreated: onViewCreatedFile, 81 | ), 82 | ), 83 | ) 84 | ], 85 | ), 86 | ); 87 | }, 88 | ); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /lib/test/demo_app.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:gsy_github_app_flutter/test/demo_page.dart'; 3 | 4 | class DemoApp extends StatelessWidget { 5 | DemoApp({Key key}) : super(key: key); 6 | 7 | @override 8 | Widget build(BuildContext context) { 9 | return new MaterialApp(home: DemoPage()); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /lib/test/demo_mixins.dart: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by guoshuyu 3 | * Date: 2018-10-12 4 | */ 5 | 6 | abstract class Base { 7 | a() { 8 | print("base a()"); 9 | } 10 | 11 | b() { 12 | print("base b()"); 13 | } 14 | 15 | c() { 16 | print("base c()"); 17 | } 18 | } 19 | 20 | class A extends Base { 21 | a() { 22 | print("A.a()"); 23 | //super.a(); 24 | } 25 | 26 | b() { 27 | print("A.b()"); 28 | super.b(); 29 | } 30 | } 31 | 32 | class A2 extends Base { 33 | a() { 34 | print("A2.a()"); 35 | super.a(); 36 | } 37 | } 38 | 39 | class B extends Base { 40 | a() { 41 | print("B.a()"); 42 | super.a(); 43 | } 44 | 45 | b() { 46 | print("B.b()"); 47 | super.b(); 48 | } 49 | 50 | c() { 51 | print("B.c()"); 52 | super.c(); 53 | } 54 | } 55 | 56 | class G extends B with A, A2 { 57 | 58 | } 59 | 60 | 61 | testMixins() { 62 | G t = new G(); 63 | t.a(); 64 | t.b(); 65 | t.c(); 66 | } 67 | 68 | 69 | ///I/flutter (13627): A2.a() 70 | ///I/flutter (13627): A.a() 71 | ///I/flutter (13627): B.a() 72 | ///I/flutter (13627): base a() 73 | ///I/flutter (13627): A.b() 74 | ///I/flutter (13627): B.b() 75 | ///I/flutter (13627): base b() 76 | ///I/flutter (13627): B.c() 77 | ///I/flutter (13627): base c() -------------------------------------------------------------------------------- /lib/test/demo_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:gsy_github_app_flutter/test/demo_item.dart'; 5 | 6 | class DemoPage extends StatefulWidget { 7 | @override 8 | _DemoPageState createState() => _DemoPageState(); 9 | } 10 | 11 | class _DemoPageState extends State { 12 | @override 13 | Widget build(BuildContext context) { 14 | ///一个页面的开始 15 | ///如果是新页面,会自带返回按键 16 | return new Scaffold( 17 | ///背景样式 18 | backgroundColor: Colors.blue, 19 | 20 | ///标题栏,当然不仅仅是标题栏 21 | appBar: new AppBar( 22 | ///这个title是一个Widget 23 | title: new Text("Title"), 24 | ), 25 | 26 | ///正式的页面开始 27 | ///一个ListView,20个Item 28 | body: new ListView.builder( 29 | itemBuilder: (context, index) { 30 | return new DemoItem(); 31 | }, 32 | itemCount: 20, 33 | ), 34 | ); 35 | } 36 | 37 | request() async { 38 | await Future.delayed(Duration(seconds: 1)); 39 | return "ok!"; 40 | } 41 | 42 | doSomeThing() async { 43 | String data = await request(); 44 | data = "ok from request"; 45 | return data; 46 | } 47 | 48 | renderSome() { 49 | doSomeThing().then((value) { 50 | print(value); 51 | ///输出ok from request 52 | }); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lib/test/demo_user_store.dart: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by guoshuyu 3 | * Date: 2018-08-06 4 | */ 5 | 6 | import 'package:flutter/material.dart'; 7 | import 'package:flutter_redux/flutter_redux.dart'; 8 | import 'package:gsy_github_app_flutter/common/model/User.dart'; 9 | import 'package:gsy_github_app_flutter/common/redux/gsy_state.dart'; 10 | 11 | class DemoUseStorePage extends StatelessWidget { 12 | @override 13 | Widget build(BuildContext context) { 14 | ///通过 StoreConnector 关联 GSYState 中的 User 15 | return new StoreConnector( 16 | ///通过 converter 将 GSYState 中的 userInfo返回 17 | converter: (store) => store.state.userInfo, 18 | ///在 userInfo 中返回实际渲染的控件 19 | builder: (context, userInfo) { 20 | return new Text( 21 | userInfo.name, 22 | style: Theme.of(context).textTheme.display1, 23 | ); 24 | }, 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lib/test/demo_widget.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | class DEMOWidget extends StatelessWidget { 6 | final String text; 7 | 8 | DEMOWidget(this.text); 9 | 10 | @override 11 | Widget build(BuildContext context) { 12 | //这里返回你需要的控件 13 | //这里末尾有没有的逗号,对于格式化代码而已是不一样的。 14 | return Container( 15 | color: Colors.white, 16 | child: Text(text ?? "这就是无状态DMEO"), 17 | ); 18 | } 19 | } 20 | 21 | class DemoStateWidget extends StatefulWidget { 22 | 23 | final String text; 24 | 25 | DemoStateWidget(this.text); 26 | 27 | @override 28 | _DemoStateWidgetState createState() => _DemoStateWidgetState(text); 29 | } 30 | 31 | class _DemoStateWidgetState extends State with AutomaticKeepAliveClientMixin { 32 | 33 | String text; 34 | 35 | _DemoStateWidgetState(this.text); 36 | 37 | @override 38 | void initState() { 39 | ///初始化,这个函数在生命周期中只调用一次 40 | super.initState(); 41 | } 42 | 43 | @override 44 | void dispose() { 45 | ///销毁 46 | super.dispose(); 47 | } 48 | 49 | @override 50 | void didChangeDependencies() { 51 | ///在initState之后调 Called when a dependency of this [State] object changes. 52 | super.didChangeDependencies(); 53 | new Future.delayed(const Duration(seconds: 1), () { 54 | setState(() { 55 | text = "这就变了数值"; 56 | }); 57 | return true; 58 | }); 59 | } 60 | 61 | 62 | @override 63 | bool get wantKeepAlive => true; 64 | 65 | @override 66 | Widget build(BuildContext context) { 67 | return Container( 68 | child: Text(text ?? "这就是有状态DMEO"), 69 | ); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /lib/widget/base_person_state.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:gsy_github_app_flutter/common/dao/user_dao.dart'; 5 | import 'package:gsy_github_app_flutter/common/model/Event.dart'; 6 | import 'package:gsy_github_app_flutter/common/model/User.dart'; 7 | import 'package:gsy_github_app_flutter/common/model/UserOrg.dart'; 8 | import 'package:gsy_github_app_flutter/common/utils/event_utils.dart'; 9 | import 'package:gsy_github_app_flutter/common/utils/navigator_utils.dart'; 10 | import 'package:gsy_github_app_flutter/widget/event_item.dart'; 11 | import 'package:gsy_github_app_flutter/widget/gsy_list_state.dart'; 12 | import 'package:gsy_github_app_flutter/widget/user_header.dart'; 13 | import 'package:gsy_github_app_flutter/widget/user_item.dart'; 14 | 15 | /** 16 | * Created by guoshuyu 17 | * Date: 2018-08-30 18 | */ 19 | 20 | abstract class BasePersonState extends State with AutomaticKeepAliveClientMixin, GSYListState { 21 | final List orgList = new List(); 22 | 23 | @protected 24 | renderItem(index, User userInfo, String beStaredCount, Color notifyColor, VoidCallback refreshCallBack, List orgList) { 25 | if (index == 0) { 26 | return new UserHeaderItem(userInfo, beStaredCount, Theme.of(context).primaryColor, 27 | notifyColor: notifyColor, refreshCallBack: refreshCallBack, orgList: orgList); 28 | } 29 | if (userInfo.type == "Organization") { 30 | return new UserItem(UserItemViewModel.fromMap(pullLoadWidgetControl.dataList[index - 1]), onPressed: () { 31 | NavigatorUtils.goPerson(context, UserItemViewModel.fromMap(pullLoadWidgetControl.dataList[index - 1]).userName); 32 | }); 33 | } else { 34 | Event event = pullLoadWidgetControl.dataList[index - 1]; 35 | return new EventItem(EventViewModel.fromEventMap(event), onPressed: () { 36 | EventUtils.ActionUtils(context, event, ""); 37 | }); 38 | } 39 | } 40 | 41 | @override 42 | bool get wantKeepAlive => true; 43 | 44 | @override 45 | bool get isRefreshFirst => true; 46 | 47 | @override 48 | bool get needHeader => true; 49 | 50 | @protected 51 | getUserOrg(String userName) { 52 | if (page <= 1 && userName != null) { 53 | UserDao.getUserOrgsDao(userName, page, needDb: true).then((res) { 54 | if (res != null && res.result) { 55 | setState(() { 56 | orgList.clear(); 57 | orgList.addAll(res.data); 58 | }); 59 | return res.next; 60 | } 61 | return new Future.value(null); 62 | }).then((res) { 63 | if (res != null && res.result) { 64 | setState(() { 65 | orgList.clear(); 66 | orgList.addAll(res.data); 67 | }); 68 | } 69 | }); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /lib/widget/gsy_bloc_list_state.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:gsy_github_app_flutter/bloc/base/base_bloc.dart'; 5 | import 'package:gsy_github_app_flutter/common/config/config.dart'; 6 | 7 | /** 8 | * 上下拉刷新列表的通用State 9 | * Created by guoshuyu 10 | * Date: 2018-07-20 11 | */ 12 | mixin GSYListState on State, AutomaticKeepAliveClientMixin { 13 | 14 | final GlobalKey refreshIndicatorKey = new GlobalKey(); 15 | 16 | ///显示刷新 17 | showRefreshLoading() { 18 | new Future.delayed(const Duration(seconds: 0), () { 19 | refreshIndicatorKey.currentState.show().then((e) {}); 20 | return true; 21 | }); 22 | } 23 | 24 | ///下拉刷新数据 25 | @protected 26 | Future requestRefresh(); 27 | 28 | ///上拉更多请求数据 29 | @protected 30 | Future requestLoadMore(); 31 | 32 | ///是否需要第一次进入自动刷新 33 | @protected 34 | bool get isRefreshFirst; 35 | 36 | ///是否需要头部 37 | @protected 38 | bool get needHeader => false; 39 | 40 | ///是否需要保持 41 | @override 42 | bool get wantKeepAlive => true; 43 | 44 | @protected 45 | BlocListBase get bloc; 46 | 47 | @override 48 | void initState() { 49 | super.initState(); 50 | bloc.changeNeedHeaderStatus(needHeader); 51 | if (bloc.getDataLength() == 0 && isRefreshFirst) { 52 | showRefreshLoading(); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /lib/widget/gsy_card_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:gsy_github_app_flutter/common/style/gsy_style.dart'; 3 | 4 | /** 5 | * Card Widget 6 | * Created by guoshuyu 7 | * Date: 2018-07-16 8 | */ 9 | class GSYCardItem extends StatelessWidget { 10 | final Widget child; 11 | final EdgeInsets margin; 12 | final Color color; 13 | final RoundedRectangleBorder shape; 14 | final double elevation; 15 | 16 | 17 | GSYCardItem({@required this.child, this.margin, this.color, this.shape, this.elevation = 5.0}); 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | EdgeInsets margin = this.margin; 22 | RoundedRectangleBorder shape = this.shape; 23 | Color color = this.color; 24 | margin ??= EdgeInsets.only(left: 10.0, top: 10.0, right: 10.0, bottom: 10.0); 25 | shape ??= new RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))); 26 | color ??= new Color(GSYColors.cardWhite); 27 | return new Card(elevation: elevation, shape: shape, color: color, margin: margin, child: child); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/widget/gsy_common_option_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:gsy_github_app_flutter/common/style/gsy_style.dart'; 3 | import 'package:gsy_github_app_flutter/common/utils/common_utils.dart'; 4 | import 'package:share/share.dart'; 5 | 6 | /** 7 | * Created by guoshuyu 8 | * Date: 2018-07-26 9 | */ 10 | class GSYCommonOptionWidget extends StatelessWidget { 11 | final List otherList; 12 | 13 | final OptionControl control; 14 | 15 | GSYCommonOptionWidget(this.control, {this.otherList}); 16 | 17 | _renderHeaderPopItem(List list) { 18 | return new PopupMenuButton( 19 | child: new Icon(GSYICons.MORE), 20 | onSelected: (model) { 21 | model.selected(model); 22 | }, 23 | itemBuilder: (BuildContext context) { 24 | return _renderHeaderPopItemChild(list); 25 | }, 26 | ); 27 | } 28 | 29 | _renderHeaderPopItemChild(List data) { 30 | List> list = new List(); 31 | for (GSYOptionModel item in data) { 32 | list.add(PopupMenuItem( 33 | value: item, 34 | child: new Text(item.name), 35 | )); 36 | } 37 | return list; 38 | } 39 | 40 | 41 | @override 42 | Widget build(BuildContext context) { 43 | List list = [ 44 | new GSYOptionModel(CommonUtils.getLocale(context).option_web, CommonUtils.getLocale(context).option_web, (model) { 45 | CommonUtils.launchOutURL(control.url, context); 46 | }), 47 | new GSYOptionModel(CommonUtils.getLocale(context).option_copy, CommonUtils.getLocale(context).option_copy, (model) { 48 | CommonUtils.copy(control.url ?? "", context); 49 | }), 50 | new GSYOptionModel(CommonUtils.getLocale(context).option_share, CommonUtils.getLocale(context).option_share, (model) { 51 | Share.share(CommonUtils.getLocale(context).option_share_title + control.url ?? ""); 52 | }), 53 | ]; 54 | if (otherList != null && otherList.length > 0) { 55 | list.addAll(otherList); 56 | } 57 | return _renderHeaderPopItem(list); 58 | } 59 | } 60 | 61 | class OptionControl { 62 | String url = GSYConstant.app_default_share_url; 63 | } 64 | 65 | class GSYOptionModel { 66 | final String name; 67 | final String value; 68 | final PopupMenuItemSelected selected; 69 | 70 | GSYOptionModel(this.name, this.value, this.selected); 71 | } 72 | -------------------------------------------------------------------------------- /lib/widget/gsy_flex_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /** 4 | * 充满的button 5 | * Created by guoshuyu 6 | * Date: 2018-07-16 7 | */ 8 | class GSYFlexButton extends StatelessWidget { 9 | final String text; 10 | 11 | final Color color; 12 | 13 | final Color textColor; 14 | 15 | final VoidCallback onPress; 16 | 17 | final double fontSize; 18 | final int maxLines; 19 | 20 | final MainAxisAlignment mainAxisAlignment; 21 | 22 | GSYFlexButton( 23 | {Key key, this.text, this.color, this.textColor, this.onPress, this.fontSize = 20.0, this.mainAxisAlignment = MainAxisAlignment.center, this.maxLines = 1}) 24 | : super(key: key); 25 | 26 | @override 27 | Widget build(BuildContext context) { 28 | return new RaisedButton( 29 | padding: new EdgeInsets.only(left: 20.0, top: 10.0, right: 20.0, bottom: 10.0), 30 | textColor: textColor, 31 | color: color, 32 | child: new Flex( 33 | mainAxisAlignment: mainAxisAlignment, 34 | direction: Axis.horizontal, 35 | children: [new Text(text, style: new TextStyle(fontSize: fontSize), maxLines: maxLines, overflow:TextOverflow.ellipsis)], 36 | ), 37 | onPressed: () { 38 | this.onPress?.call(); 39 | }); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/widget/gsy_icon_text.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /** 4 | * 带图标Icon的文本,可调节 5 | * Created by guoshuyu 6 | * Date: 2018-07-16 7 | */ 8 | class GSYIConText extends StatelessWidget { 9 | final String iconText; 10 | 11 | final IconData iconData; 12 | 13 | final TextStyle textStyle; 14 | 15 | final Color iconColor; 16 | 17 | final double padding; 18 | 19 | final double iconSize; 20 | 21 | final VoidCallback onPressed; 22 | 23 | final MainAxisAlignment mainAxisAlignment; 24 | 25 | final MainAxisSize mainAxisSize; 26 | 27 | final double textWidth; 28 | 29 | GSYIConText( 30 | this.iconData, 31 | this.iconText, 32 | this.textStyle, 33 | this.iconColor, 34 | this.iconSize, { 35 | this.padding = 0.0, 36 | this.onPressed, 37 | this.mainAxisAlignment = MainAxisAlignment.start, 38 | this.mainAxisSize = MainAxisSize.max, 39 | this.textWidth = -1, 40 | }); 41 | 42 | @override 43 | Widget build(BuildContext context) { 44 | Widget showText = (textWidth == -1) 45 | ? new Container( 46 | child: new Text( 47 | iconText ?? "", 48 | style: textStyle.merge(new TextStyle(textBaseline: TextBaseline.alphabetic)), 49 | overflow: TextOverflow.ellipsis, 50 | maxLines: 1, 51 | ), 52 | ) 53 | : new Container( 54 | width: textWidth, 55 | child: 56 | 57 | ///显示数量文本 58 | new Text( 59 | iconText, 60 | style: textStyle.merge(new TextStyle(textBaseline: TextBaseline.alphabetic)), 61 | overflow: TextOverflow.ellipsis, 62 | maxLines: 1, 63 | )); 64 | 65 | return new Container( 66 | child: new Row( 67 | textBaseline: TextBaseline.alphabetic, 68 | mainAxisAlignment: mainAxisAlignment, 69 | mainAxisSize: mainAxisSize, 70 | crossAxisAlignment: CrossAxisAlignment.baseline, 71 | children: [ 72 | new Icon( 73 | iconData, 74 | size: iconSize, 75 | color: iconColor, 76 | ), 77 | new Padding(padding: new EdgeInsets.all(padding)), 78 | showText 79 | ], 80 | ), 81 | ); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /lib/widget/gsy_input_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// 带图标的输入框 4 | class GSYInputWidget extends StatefulWidget { 5 | final bool obscureText; 6 | 7 | final String hintText; 8 | 9 | final IconData iconData; 10 | 11 | final ValueChanged onChanged; 12 | 13 | final TextStyle textStyle; 14 | 15 | final TextEditingController controller; 16 | 17 | GSYInputWidget({Key key, this.hintText, this.iconData, this.onChanged, this.textStyle, this.controller, this.obscureText = false}) : super(key: key); 18 | 19 | @override 20 | _GSYInputWidgetState createState() => new _GSYInputWidgetState(); 21 | } 22 | 23 | /// State for [GSYInputWidget] widgets. 24 | class _GSYInputWidgetState extends State { 25 | 26 | _GSYInputWidgetState() : super(); 27 | 28 | @override 29 | Widget build(BuildContext context) { 30 | return new TextField( 31 | controller: widget.controller, 32 | onChanged: widget.onChanged, 33 | obscureText: widget.obscureText, 34 | decoration: new InputDecoration( 35 | hintText: widget.hintText, 36 | icon: widget.iconData == null ? null : new Icon(widget.iconData), 37 | ), 38 | ); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/widget/gsy_search_input_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:gsy_github_app_flutter/common/style/gsy_style.dart'; 3 | import 'package:gsy_github_app_flutter/common/utils/common_utils.dart'; 4 | 5 | /** 6 | * 搜索输入框 7 | * Created by guoshuyu 8 | * Date: 2018-07-20 9 | */ 10 | class GSYSearchInputWidget extends StatelessWidget { 11 | final ValueChanged onChanged; 12 | 13 | final ValueChanged onSubmitted; 14 | 15 | final VoidCallback onSubmitPressed; 16 | 17 | GSYSearchInputWidget(this.onChanged, this.onSubmitted, this.onSubmitPressed); 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | return new Container( 22 | decoration: new BoxDecoration( 23 | borderRadius: BorderRadius.all(Radius.circular(4.0)), 24 | color: Color(GSYColors.white), 25 | border: new Border.all(color: Theme.of(context).primaryColor, width: 0.3), 26 | boxShadow: [BoxShadow(color: Theme.of(context).primaryColorDark, blurRadius: 4.0)]), 27 | padding: new EdgeInsets.only(left: 20.0, top: 12.0, right: 20.0, bottom: 12.0), 28 | child: new Row( 29 | children: [ 30 | new Expanded( 31 | child: new TextField( 32 | autofocus: false, 33 | decoration: new InputDecoration.collapsed( 34 | hintText: CommonUtils.getLocale(context).repos_issue_search, 35 | hintStyle: GSYConstant.middleSubText, 36 | ), 37 | style: GSYConstant.middleText, 38 | onChanged: onChanged, 39 | onSubmitted: onSubmitted)), 40 | new RawMaterialButton( 41 | materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, 42 | padding: const EdgeInsets.only(right: 5.0, left: 10.0), 43 | constraints: const BoxConstraints(minWidth: 0.0, minHeight: 0.0), 44 | child: new Icon(GSYICons.SEARCH, size: 15.0, color: Theme.of(context).primaryColorDark,), 45 | onPressed: onSubmitPressed) 46 | ], 47 | ), 48 | ); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/widget/gsy_title_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /** 4 | * title 控件 5 | * Created by guoshuyu 6 | * on 2018/7/24. 7 | */ 8 | class GSYTitleBar extends StatelessWidget { 9 | final String title; 10 | 11 | final IconData iconData; 12 | 13 | final VoidCallback onPressed; 14 | 15 | final bool needRightLocalIcon; 16 | 17 | final Widget rightWidget; 18 | 19 | GSYTitleBar(this.title, {this.iconData, this.onPressed, this.needRightLocalIcon = false, this.rightWidget}); 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | Widget widget = rightWidget; 24 | if (rightWidget == null) { 25 | widget = (needRightLocalIcon) 26 | ? new IconButton( 27 | icon: new Icon( 28 | iconData, 29 | size: 19.0, 30 | ), 31 | onPressed: onPressed) 32 | : new Container(); 33 | } 34 | return Container( 35 | child: new Row( 36 | children: [ 37 | new Expanded( 38 | child: new Text( 39 | title, 40 | maxLines: 1, 41 | overflow: TextOverflow.ellipsis, 42 | ), 43 | ), 44 | widget 45 | ], 46 | ), 47 | ); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/widget/gsy_user_icon_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:gsy_github_app_flutter/common/style/gsy_style.dart'; 3 | import 'package:gsy_github_app_flutter/widget/network_cache_image.dart'; 4 | 5 | /** 6 | * 头像Icon 7 | * Created by guoshuyu 8 | * Date: 2018-07-30 9 | */ 10 | 11 | class GSYUserIconWidget extends StatelessWidget { 12 | final String image; 13 | final VoidCallback onPressed; 14 | final double width; 15 | final double height; 16 | final EdgeInsetsGeometry padding; 17 | 18 | GSYUserIconWidget({this.image, this.onPressed, this.width = 30.0, this.height = 30.0, this.padding}); 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | return new RawMaterialButton( 23 | materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, 24 | padding: padding ?? const EdgeInsets.only(top: 4.0, right: 5.0, left: 5.0), 25 | constraints: const BoxConstraints(minWidth: 0.0, minHeight: 0.0), 26 | child: new ClipOval( 27 | child: FadeInImage( 28 | placeholder: AssetImage( 29 | GSYICons.DEFAULT_USER_ICON, 30 | ), 31 | image: NetworkCacheImage(image), 32 | //预览图 33 | fit: BoxFit.fitWidth, 34 | width: width, 35 | height: height, 36 | ), 37 | ), 38 | onPressed: onPressed); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/widget/menu/flutter_radial_menu.dart: -------------------------------------------------------------------------------- 1 | library flutter_radial_menu; 2 | 3 | export 'src/radial_menu.dart'; 4 | export 'src/radial_menu_item.dart'; 5 | -------------------------------------------------------------------------------- /lib/widget/menu/src/radial_menu_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class RadialMenuButton extends StatelessWidget { 5 | const RadialMenuButton({ 6 | @required this.child, 7 | this.backgroundColor, 8 | this.onPressed, 9 | }); 10 | 11 | final Widget child; 12 | final Color backgroundColor; 13 | final VoidCallback onPressed; 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | final Color color = backgroundColor ?? Theme.of(context).primaryColor; 18 | 19 | return new Semantics( 20 | button: true, 21 | enabled: true, 22 | child: new Material( 23 | type: MaterialType.circle, 24 | color: color, 25 | child: new InkWell( 26 | onTap: onPressed, 27 | child: child, 28 | ), 29 | ), 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/widget/menu/src/radial_menu_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | const double _defaultButtonSize = 48.0; 5 | 6 | /// An item in a [RadialMenu]. 7 | /// 8 | /// The type `T` is the type of the value the entry represents. All the entries 9 | /// in a given menu must represent values with consistent types. 10 | class RadialMenuItem extends StatelessWidget { 11 | /// Creates a circular action button for an item in a [RadialMenu]. 12 | /// 13 | /// The [child] argument is required. 14 | const RadialMenuItem({ 15 | Key key, 16 | @required this.child, 17 | this.value, 18 | this.tooltip, 19 | this.size = _defaultButtonSize, 20 | this.backgroundColor, 21 | this.iconColor, 22 | // this.iconSize: 24.0, 23 | }) : assert(child != null), 24 | assert(size != null), 25 | super(key: key); 26 | 27 | /// The widget below this widget in the tree. 28 | /// 29 | /// Typically an [Icon] widget. 30 | final Widget child; 31 | 32 | /// The value to return if the user selects this menu item. 33 | /// 34 | /// Eventually returned in a call to [RadialMenu.onSelected]. 35 | final T value; 36 | 37 | /// Text that describes the action that will occur when the button is pressed. 38 | /// 39 | /// This text is displayed when the user long-presses on the button and is 40 | /// used for accessibility. 41 | final String tooltip; 42 | 43 | /// The color to use when filling the button. 44 | /// 45 | /// Defaults to the primary color of the current theme. 46 | final Color backgroundColor; 47 | 48 | /// The size of the button. 49 | /// 50 | /// Defaults to 48.0. 51 | final double size; 52 | 53 | /// The color to use when painting the child icon. 54 | /// 55 | /// Defaults to the primary icon theme color. 56 | final Color iconColor; 57 | 58 | @override 59 | Widget build(BuildContext context) { 60 | final Color _iconColor = 61 | iconColor ?? Theme.of(context).primaryIconTheme.color; 62 | 63 | Widget result; 64 | 65 | if (child != null) { 66 | result = new Center( 67 | child: IconTheme.merge( 68 | data: new IconThemeData( 69 | color: _iconColor, 70 | ), 71 | child: child, 72 | ), 73 | ); 74 | } 75 | 76 | if (tooltip != null) { 77 | result = new Tooltip( 78 | message: tooltip, 79 | child: result, 80 | ); 81 | } 82 | 83 | result = new Container( 84 | width: size, 85 | height: size, 86 | child: result, 87 | ); 88 | 89 | return result; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /lib/widget/push_coed_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:gsy_github_app_flutter/common/model/CommitFile.dart'; 3 | import 'package:gsy_github_app_flutter/common/style/gsy_style.dart'; 4 | import 'package:gsy_github_app_flutter/widget/gsy_card_item.dart'; 5 | 6 | /** 7 | * 推送修改代码Item 8 | * Created by guoshuyu 9 | * Date: 2018-07-27 10 | */ 11 | 12 | class PushCodeItem extends StatelessWidget { 13 | final PushCodeItemViewModel pushCodeItemViewModel; 14 | final VoidCallback onPressed; 15 | 16 | PushCodeItem(this.pushCodeItemViewModel, this.onPressed); 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | return new Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ 21 | new Container( 22 | ///修改文件路径 23 | margin: EdgeInsets.only(left: 10.0, top: 5.0, right: 10.0, bottom: 0.0), 24 | child: new Text( 25 | pushCodeItemViewModel.path, 26 | style: GSYConstant.smallSubLightText, 27 | ), 28 | ), 29 | new GSYCardItem( 30 | ///修改文件名 31 | margin: EdgeInsets.only(left: 10.0, top: 5.0, right: 10.0, bottom: 5.0), 32 | child: new ListTile( 33 | title: new Text(pushCodeItemViewModel.name, style: GSYConstant.smallSubText), 34 | leading: new Icon( 35 | GSYICons.REPOS_ITEM_FILE, 36 | size: 15.0, 37 | ), 38 | onTap: () { 39 | onPressed(); 40 | }, 41 | ), 42 | ), 43 | ]); 44 | } 45 | } 46 | 47 | class PushCodeItemViewModel { 48 | String path; 49 | String name; 50 | String patch; 51 | 52 | String blob_url; 53 | 54 | PushCodeItemViewModel(); 55 | 56 | PushCodeItemViewModel.fromMap(CommitFile map) { 57 | String filename = map.fileName; 58 | List nameSplit = filename.split("/"); 59 | name = nameSplit[nameSplit.length - 1]; 60 | path = filename; 61 | patch = map.patch; 62 | blob_url = map.blobUrl; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /lib/widget/release_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:gsy_github_app_flutter/common/model/Release.dart'; 3 | import 'package:gsy_github_app_flutter/common/style/gsy_style.dart'; 4 | import 'package:gsy_github_app_flutter/common/utils/common_utils.dart'; 5 | import 'package:gsy_github_app_flutter/widget/gsy_card_item.dart'; 6 | 7 | /** 8 | * 版本TagItem 9 | * Created by guoshuyu 10 | * Date: 2018-07-30 11 | */ 12 | 13 | class ReleaseItem extends StatelessWidget { 14 | final ReleaseItemViewModel releaseItemViewModel; 15 | 16 | final GestureTapCallback onPressed; 17 | final GestureLongPressCallback onLongPress; 18 | 19 | ReleaseItem(this.releaseItemViewModel, {this.onPressed, this.onLongPress}) : super(); 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return new Container( 24 | child: new GSYCardItem( 25 | child: new InkWell( 26 | onTap: onPressed, 27 | onLongPress: onLongPress, 28 | child: new Padding( 29 | padding: new EdgeInsets.only(left: 10.0, top: 15.0, right: 10.0, bottom: 15.0), 30 | child: new Row( 31 | children: [ 32 | new Expanded(child: new Text(releaseItemViewModel.actionTitle, style: GSYConstant.smallTextBold)), 33 | new Container(child: new Text(releaseItemViewModel.actionTime ?? "", style: GSYConstant.smallSubText)), 34 | ], 35 | ), 36 | ), 37 | ), 38 | ), 39 | ); 40 | } 41 | } 42 | 43 | class ReleaseItemViewModel { 44 | String actionTime; 45 | String actionTitle; 46 | String actionMode; 47 | String actionTarget; 48 | String actionTargetHtml; 49 | String body; 50 | 51 | ReleaseItemViewModel(); 52 | 53 | ReleaseItemViewModel.fromMap(Release map) { 54 | if (map.publishedAt != null) { 55 | actionTime = CommonUtils.getNewsTimeStr(map.publishedAt); 56 | } 57 | actionTitle = map.name ?? map.tagName; 58 | actionTarget = map.targetCommitish; 59 | actionTargetHtml = map.bodyHtml; 60 | body = map.body ?? ""; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /lib/widget/user_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:gsy_github_app_flutter/common/model/User.dart'; 3 | import 'package:gsy_github_app_flutter/common/model/UserOrg.dart'; 4 | import 'package:gsy_github_app_flutter/common/style/gsy_style.dart'; 5 | import 'package:gsy_github_app_flutter/widget/gsy_card_item.dart'; 6 | 7 | /** 8 | * 用户item 9 | * Created by guoshuyu 10 | * Date: 2018-07-23 11 | */ 12 | class UserItem extends StatelessWidget { 13 | final UserItemViewModel userItemViewModel; 14 | 15 | final VoidCallback onPressed; 16 | 17 | final bool needImage; 18 | 19 | UserItem(this.userItemViewModel, {this.onPressed, this.needImage = true}) : super(); 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | Widget userImage = new IconButton( 24 | padding: EdgeInsets.only(top: 0.0, left: 0.0, bottom: 0.0, right: 10.0), 25 | icon: new ClipOval( 26 | child: new FadeInImage.assetNetwork( 27 | placeholder: GSYICons.DEFAULT_USER_ICON, 28 | //预览图 29 | fit: BoxFit.fitWidth, 30 | image: userItemViewModel.userPic, 31 | width: 30.0, 32 | height: 30.0, 33 | ), 34 | ), 35 | onPressed: null); 36 | return new Container( 37 | child: new GSYCardItem( 38 | child: new FlatButton( 39 | onPressed: onPressed, 40 | child: new Padding( 41 | padding: new EdgeInsets.only(left: 0.0, top: 5.0, right: 0.0, bottom: 10.0), 42 | child: new Row( 43 | children: [ 44 | userImage, 45 | new Expanded(child: new Text(userItemViewModel.userName, style: GSYConstant.smallTextBold)), 46 | ], 47 | ), 48 | ), 49 | ), 50 | )); 51 | } 52 | } 53 | 54 | class UserItemViewModel { 55 | String userPic; 56 | String userName; 57 | 58 | UserItemViewModel.fromMap(User user) { 59 | userName = user.login; 60 | userPic = user.avatar_url; 61 | } 62 | 63 | UserItemViewModel.fromOrgMap(UserOrg org) { 64 | userName = org.login; 65 | userPic = org.avatarUrl; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/logo.png -------------------------------------------------------------------------------- /register0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/register0.jpg -------------------------------------------------------------------------------- /register1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/register1.jpg -------------------------------------------------------------------------------- /static/font/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/static/font/iconfont.eot -------------------------------------------------------------------------------- /static/font/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/static/font/iconfont.ttf -------------------------------------------------------------------------------- /static/font/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/static/font/iconfont.woff -------------------------------------------------------------------------------- /static/images/default_img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/static/images/default_img.png -------------------------------------------------------------------------------- /static/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/static/images/logo.png -------------------------------------------------------------------------------- /static/images/welcome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/static/images/welcome.png -------------------------------------------------------------------------------- /thanks.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/thanks.jpg -------------------------------------------------------------------------------- /theme.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongyangAndroid/GSYGithubAppFlutter/fac4f138c86f7e42530943d67bb49b6987918d35/theme.gif --------------------------------------------------------------------------------