├── .gitignore
├── .metadata
├── CHANGELOG.md
├── README-EN.md
├── README.md
├── android
├── app
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── cn
│ │ │ │ └── phoenixsky
│ │ │ │ └── wan_android
│ │ │ │ └── MainActivity.java
│ │ └── res
│ │ │ ├── drawable-night
│ │ │ └── launch_background.xml
│ │ │ ├── drawable
│ │ │ └── launch_background.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── launch_image.png
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── launch_image.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── launch_image.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values
│ │ │ └── styles.xml
│ │ │ └── xml
│ │ │ └── network_security_config.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── settings.gradle
└── settings_aar.gradle
├── assets
├── animations
│ └── like.flr
├── fonts
│ ├── ZCOOLKuaiLe-Regular.ttf
│ └── iconfont.ttf
└── images
│ ├── home_second_floor_builder.png
│ ├── login_logo.png
│ ├── logo_wechat.png
│ ├── logo_weibo.png
│ ├── splash_android.png
│ ├── splash_bg.png
│ ├── splash_bg_dark.png
│ ├── splash_flutter.png
│ ├── splash_fun.png
│ └── user_avatar.png
├── ios
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Podfile
├── Podfile.lock
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
└── Runner
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-App-20x20@1x.png
│ │ ├── Icon-App-20x20@2x.png
│ │ ├── Icon-App-29x29@1x.png
│ │ ├── Icon-App-29x29@2x.png
│ │ ├── Icon-App-40x40@1x.png
│ │ ├── Icon-App-40x40@2x.png
│ │ ├── Icon-App-76x76@1x.png
│ │ ├── Icon-App-76x76@2x.png
│ │ ├── Icon-App-83.5x83.5@2x.png
│ │ ├── appicon-0.png
│ │ ├── appicon-1.png
│ │ ├── appicon-2.png
│ │ ├── appicon-3.png
│ │ ├── appicon-4.png
│ │ ├── appicon-5.png
│ │ ├── appicon-6.png
│ │ ├── appicon-7.png
│ │ ├── appicon-8.png
│ │ └── appicon.png
│ ├── Contents.json
│ └── LaunchImage.imageset
│ │ ├── Contents.json
│ │ ├── README.md
│ │ ├── appicon-1.png
│ │ ├── appicon-2.png
│ │ ├── appicon-3.png
│ │ ├── appicon-4.png
│ │ ├── appicon-5.png
│ │ └── appicon.png
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Info.plist
│ ├── main.m
│ └── zh-Hans.lproj
│ ├── LaunchScreen.strings
│ └── Main.strings
├── lib
├── config
│ ├── net
│ │ ├── api.dart
│ │ ├── pgyer_api.dart
│ │ └── wan_android_api.dart
│ ├── provider_manager.dart
│ ├── resource_mananger.dart
│ ├── router_manger.dart
│ ├── storage_manager.dart
│ └── ui_adapter_config.dart
├── flutter
│ ├── dropdown.dart
│ ├── refresh_animatedlist.dart
│ └── search.dart
├── generated
│ ├── intl
│ │ ├── messages_all.dart
│ │ ├── messages_en.dart
│ │ └── messages_zh.dart
│ └── l10n.dart
├── l10n
│ ├── intl_en.arb
│ └── intl_zh.arb
├── main.dart
├── model
│ ├── article.dart
│ ├── banner.dart
│ ├── coin_record.dart
│ ├── navigation_site.dart
│ ├── search.dart
│ ├── tree.dart
│ └── user.dart
├── provider
│ ├── provider_widget.dart
│ ├── provider_widget_selector.dart
│ ├── view_state.dart
│ ├── view_state_list_model.dart
│ ├── view_state_model.dart
│ ├── view_state_refresh_list_model.dart
│ └── view_state_widget.dart
├── service
│ ├── app_repository.dart
│ └── wan_android_repository.dart
├── ui
│ ├── helper
│ │ ├── dialog_helper.dart
│ │ ├── favourite_helper.dart
│ │ ├── popup_helper.dart
│ │ ├── refresh_helper.dart
│ │ └── theme_helper.dart
│ ├── page
│ │ ├── article
│ │ │ ├── article_detail_page.dart
│ │ │ ├── article_detail_plugin_page.dart
│ │ │ └── article_list_page.dart
│ │ ├── change_log_page.dart
│ │ ├── coin
│ │ │ ├── coin_ranking_list_page.dart
│ │ │ └── coin_record_list_page.dart
│ │ ├── favourite_list_page.dart
│ │ ├── search
│ │ │ ├── search_delegate.dart
│ │ │ ├── search_results.dart
│ │ │ └── search_suggestions.dart
│ │ ├── setting_page.dart
│ │ ├── splash.dart
│ │ ├── tab
│ │ │ ├── home_page.dart
│ │ │ ├── home_second_floor_page.dart
│ │ │ ├── project_page.dart
│ │ │ ├── structure_page.dart
│ │ │ ├── tab_navigator.dart
│ │ │ ├── user_page.dart
│ │ │ └── wechat_account_page.dart
│ │ └── user
│ │ │ ├── login_field_widget.dart
│ │ │ ├── login_page.dart
│ │ │ ├── login_widget.dart
│ │ │ └── register_page.dart
│ └── widget
│ │ ├── activity_indicator.dart
│ │ ├── animated_provider.dart
│ │ ├── app_bar.dart
│ │ ├── app_update.dart
│ │ ├── article_list_Item.dart
│ │ ├── article_skeleton.dart
│ │ ├── article_tag.dart
│ │ ├── banner_image.dart
│ │ ├── bottom_clipper.dart
│ │ ├── button_progress_indicator.dart
│ │ ├── favourite_animation.dart
│ │ ├── image.dart
│ │ ├── page_route_anim.dart
│ │ ├── skeleton.dart
│ │ └── third_component.dart
├── utils
│ ├── animation_utils.dart
│ ├── platform_utils.dart
│ ├── status_bar_utils.dart
│ ├── string_utils.dart
│ └── third_app_utils.dart
└── view_model
│ ├── app_model.dart
│ ├── coin_model.dart
│ ├── favourite_model.dart
│ ├── home_model.dart
│ ├── locale_model.dart
│ ├── login_model.dart
│ ├── project_model.dart
│ ├── register_model.dart
│ ├── scroll_controller_model.dart
│ ├── search_model.dart
│ ├── setting_model.dart
│ ├── structure_model.dart
│ ├── theme_model.dart
│ ├── user_model.dart
│ └── wechat_account_model.dart
├── pubspec.yaml
└── test
└── widget_test.dart
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | !.vscode/
22 | .vscode/settings.json
23 | **/.settings
24 | **/.project
25 | **/.classpath
26 |
27 | # Flutter/Dart/Pub related
28 | **/doc/api/
29 | .dart_tool/
30 | .flutter-plugins
31 | .flutter-plugins-dependencies
32 | .packages
33 | .pub-cache/
34 | .pub/
35 | /build/
36 |
37 | # Android related
38 | **/android/**/gradle-wrapper.jar
39 | **/android/.gradle
40 | **/android/captures/
41 | **/android/gradlew
42 | **/android/gradlew.bat
43 | **/android/local.properties
44 | **/android/**/GeneratedPluginRegistrant.java
45 | **/android/signing
46 |
47 | # iOS/XCode related
48 | **/ios/**/*.mode1v3
49 | **/ios/**/*.mode2v3
50 | **/ios/**/*.moved-aside
51 | **/ios/**/*.pbxuser
52 | **/ios/**/*.perspectivev3
53 | **/ios/**/*sync/
54 | **/ios/**/.sconsign.dblite
55 | **/ios/**/.tags*
56 | **/ios/**/.vagrant/
57 | **/ios/**/DerivedData/
58 | **/ios/**/Icon?
59 | **/ios/**/Pods/
60 | **/ios/**/.symlinks/
61 | **/ios/**/profile
62 | **/ios/**/xcuserdata
63 | **/ios/.generated/
64 | **/ios/Flutter/App.framework
65 | **/ios/Flutter/Flutter.framework
66 | **/ios/Flutter/Generated.xcconfig
67 | **/ios/Flutter/app.flx
68 | **/ios/Flutter/app.zip
69 | **/ios/Flutter/flutter_assets/
70 | **/ios/ServiceDefinitions.json
71 | **/ios/Runner/GeneratedPluginRegistrant.*
72 | **/ios/Flutter/flutter_export_environment.sh
73 |
74 | # Exceptions to above rules.
75 | !**/ios/**/default.mode1v3
76 | !**/ios/**/default.mode2v3
77 | !**/ios/**/default.pbxuser
78 | !**/ios/**/default.perspectivev3
79 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
80 | /.fvm/
81 |
--------------------------------------------------------------------------------
/.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: 20e59316b8b8474554b38493b8ca888794b0234a
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # 编译环境
2 | > Channel stable, v1.12.13+hotfix.5
3 |
4 |
5 | # 最近更新
6 |
7 | ## V0.1.15 `2020-02-24` (未打包)
8 | - 优化ViewStateError
9 | - ViewState状态重命名
10 | - 升级部分依赖库
11 |
12 | ## V0.1.14 `2020-02-13` (未打包)
13 | - 更新SDK版本为`stable, v1.12.13+hotfix.8`
14 | - 适配Provider4.x
15 | - 迁移国际化方案到`flutter_intl`,使用说明见[FunFlutter系列之国际化Intl方案 \- 掘金](https://juejin.im/post/5e4536d0e51d4526ef5f85a9)
16 |
17 | ## V0.1.13 `2019-12-20` (未打包)
18 | - 修复之前未上传签名文件导致编译出错的问题
19 | - 更新SDK版本为`stable, v1.12.13+hotfix.5`
20 | - 更新Provider版本到3.2.0
21 | - 更新Cache_Network_Image到2.0.0RC
22 | - 隐藏部分重写导致import冲突的widget
23 | - 增加部分ignore配置
24 | - 感谢[liyujiang-gzu](https://github.com/liyujiang-gzu)的pr
25 |
26 | ## V0.1.12 `2019-10-21`
27 | - 下拉刷新列表在加载失败时,如果当前页没有数据显示错误提示页,有数据则弹出toast提示
28 |
29 | ## V0.1.11 `2019-10-17`
30 | - 增加网络加载失败的提示
31 |
32 |
33 | ## V0.1.10 `2019-10-16`
34 | - 修复收藏页面'shareUser'字段为空导致报错的bug
35 |
36 | ## V0.1.9 `2019-10-14`
37 | - 极致黑(Native的闪屏页面适配darkMode)
38 | - 首页banner高度根据屏幕宽高适应
39 | - 签名文件调整
40 |
41 | ## V0.1.8 `2019-10-13`
42 | - 文章列表加入分享人
43 | - 首页加入数据为空的逻辑判断
44 | - ViewStateModel中逻辑优化,bug fix
45 | - 状态栏字体颜色优化
46 | - 修复TextField中hint为中文时不居中的问题
47 |
48 | ## V0.1.7 `2019-09-23`
49 |
50 | - DarkMode自动跟随系统设置
51 | - App更新UI调整
52 | - 适配Dio3.0版本
53 | - pull_to_refresh更新:加入国际化
54 |
55 |
56 | ## V0.1.6 `2019-09-20`
57 |
58 | - 修复收藏列表进入详情时,页面报错的bug
59 |
60 | ## V0.1.5 `2019-09-19`
61 |
62 | - Flutter SDK更新至**Channel dev, v1.10.3**,修复`我的`页面莫名卡死的问题
63 | - 修改Android端App名称为Fun Android
64 | - 版本更新加入提示
65 |
66 | ## V0.1.4 `2019-09-18`
67 |
68 | - **Android加入版本更新**
69 | - 适配Flutter新版本`Channel dev, v1.10.3`
70 | - 移除修复首页黑屏问题的代码`官方在1.10.1版本已修复`
71 | - 加入LeanCloud API云服务
72 | - 移除之前屏幕适配方案,对NativeView影响过大
73 | - 修复版本更新导致的AppBar中进度条颜色与背景色不明显的问题
74 | - 重构Http使用方式,解耦性更好
75 | - 首页banner高度调整
76 | - Android状态栏透明
77 |
78 | ## 0.1.3
79 |
80 | - 修复各页面里文章**收藏**状态没有同步的问题
81 | - 优化Dropdown弹出动画
82 | - 禁用首页初次加载数据的上拉记载更多功能
83 | - 登录页面输入框可通过回车键切换光标
84 |
85 |
86 | ## 0.1.2
87 |
88 | - 修复积分数值在登录后没有刷新的bug
89 | - 修复进入Splash页面短暂黑屏的bug
90 | - 修复未登录时,点击收藏还可以播放动画的bug
91 | - 默认主题色调整为亮色
92 |
93 | ## 0.1.1
94 |
95 | - 添加积分记录和排行榜功能
96 | - 在设置中添加WebViewPlugin的开关
97 | - 更新收藏动画的实现方式和效果,此刻尽丝滑
98 | - 在详情中移除收藏后,回到收藏列表页面更新
99 |
100 | ## 0.1.0
101 |
102 | - 初始发布
103 |
104 |
105 |
--------------------------------------------------------------------------------
/README-EN.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | Language: [English](https://github.com/phoenixsky/fun_android_flutter/blob/master/README-EN.md) | [中文简体](https://github.com/phoenixsky/fun_android_flutter/blob/master/README.md)
4 |
5 |
6 |
7 | 
8 |
9 | > Big F, it's `Fun`, also it means `Flutter`.
10 |
11 | `FunAndroid` is a production project , Provider's best practices with MVVM
12 |
13 | # ScreenShot
14 |
15 | |  |  |  |
16 | | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
17 | |  |  |  |
18 | |  |  |  |
19 |
20 | # Home Page
21 |
22 | > [https://github.com/phoenixsky/fun_android_flutter](https://github.com/phoenixsky/fun_android_flutter)
23 |
24 | # Download page
25 |
26 | # 下载地址
27 |
28 | > [download page](https://www.pgyer.com/Ki0F)
29 |
30 | 
31 |
32 | # Environment :
33 | * Flutter SDK (Channel dev, v1.10.3)
34 |
35 |
36 | # Update
37 |
38 | ## 2019-08-28
39 |
40 | - add WebViewPlugin switcher in Setting Page
41 | - My favourite list can refresh after the unlike in the detail page
42 |
43 | ## 2019-08-26
44 |
45 | - update favourite animation with Hero and Route . (hiding original hero after hero transition.见[pr-37341](https://github.com/flutter/flutter/pull/37341))
46 |
47 | 
48 |
49 |
50 |
51 | # Provider MVVM Best Practices
52 |
53 | - Quickly add a page with pull-down refresh and pull up to load more pages. For example
54 | 1. Model
55 | 
56 | 2. ViewModel
57 | 
58 | 3. View
59 | 
60 |
61 | > `model.viewState == ViewState.busy` is better way ,but `isBusy` easy to write
62 |
63 | # What can you find here??
64 |
65 | 1. Provider
66 | 1. When and Where init data
67 | 2. how to be with ViewState(`loading`、`error`、`empty`、`idle`、`unAuthorized`)。
68 | 3. use together with `pull to refresh`
69 | 2. Clear Structure。
70 | 3. Drop setState, Partial Rerefresh with XxxBuilder
71 | 4. App base module
72 | 1. Theme
73 | 2. DarkMode
74 | 3. Switch Font
75 | 4. Skeleton
76 | 5. i18n
77 | 6. Dio with Cookjar,use cookie login
78 |
79 | # To-Do
80 |
81 | 1. homepage second floor can't navigate
82 | 2. Sign in Hero animation shift
83 | 3. Sign out add animation
84 |
85 | # Bug
86 |
87 | 1. webview_flutter](https://pub.dev/packages/webview_flutter) some url can't navigate
88 | 2. [webview_flutter](https://pub.dev/packages/webview_flutter) in `CustomScrollView` can't scroll ,[issue](https://github.com/flutter/flutter/issues/31243#issuecomment-521564216) 。
89 | 3. anti-aliasing when same-colour blocks in SignIn Page。见[issue](https://github.com/flutter/flutter/issues/14288) 。
90 |
91 |
92 |
93 | # Thanks
94 |
95 | 1. [V2Lf](https://github.com/w4mxl/V2LF) ,made me like flutter
96 | 2. `goweii`[WanAndroid](https://github.com/goweii/WanAndroid)
97 | 3. [Tutorials](https://github.com/FilledStacks/flutter-tutorials),Video tutorial on youtube
98 | 4. [pull_to_refresh](https://pub.dev/packages/pull_to_refresh)
99 | 5. ZCOOL Font
100 | 6. [WanAndroid](https://www.wanandroid.com/blog/show/2) provide Api
101 |
102 | # About Me
103 |
104 | - [Github](https://github.com/phoenixsky)
105 | - [Blog](http://blog.phoenixsky.cn/)
106 | - [简书](https://www.jianshu.com/u/145e6297cb26)
107 | - Email: moran.fc@gmail.com
108 |
109 | # License
110 |
111 | Copyright 2019 phoenixsky
112 |
113 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
114 |
115 | http://www.apache.org/licenses/LICENSE-2.0
116 |
117 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
118 |
--------------------------------------------------------------------------------
/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 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
26 |
27 |
28 | android {
29 | compileSdkVersion 29
30 |
31 | lintOptions {
32 | disable 'InvalidPackage'
33 | }
34 |
35 | defaultConfig {
36 | applicationId "cn.phoenixsky.wan_android"
37 | minSdkVersion 16
38 | targetSdkVersion 28
39 | versionCode flutterVersionCode.toInteger()
40 | versionName flutterVersionName
41 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
42 | }
43 | signingConfigs {
44 | release {
45 | // 签名文件并没有开源,可以直接在${project}/android/目录下创建signing文件夹
46 | // 根据`keystoreProperties`自行配置文件
47 | def keystorePropertiesFile = rootProject.file("signing/key.properties")
48 | if (keystorePropertiesFile.exists()) {
49 | def keystoreProperties = new Properties()
50 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
51 | keyAlias keystoreProperties['keyAlias']
52 | keyPassword keystoreProperties['keyPassword']
53 | storeFile file(keystoreProperties['storeFile'])
54 | storePassword keystoreProperties['storePassword']
55 | }
56 | }
57 | }
58 | buildTypes {
59 | // 签名文件并没有上传,可以使用自己的签名文件或者移除一下指令使用默认的签名
60 | release {
61 | signingConfig signingConfigs.release
62 | }
63 | debug {
64 | }
65 | }
66 |
67 | // lintOptions {
68 | //
69 | // checkReleaseBuilds false
70 | //
71 | // abortOnError false
72 | //
73 | // }
74 |
75 | }
76 |
77 | flutter {
78 | source '../..'
79 | }
80 |
81 | dependencies {
82 | testImplementation 'junit:junit:4.12'
83 | androidTestImplementation 'androidx.test:runner:1.1.1'
84 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
85 | }
86 |
--------------------------------------------------------------------------------
/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | #Flutter Wrapper
2 | -keep class io.flutter.app.** { *; }
3 | -keep class io.flutter.plugin.** { *; }
4 | -keep class io.flutter.util.** { *; }
5 | -keep class io.flutter.view.** { *; }
6 | -keep class io.flutter.** { *; }
7 | -keep class io.flutter.plugins.** { *; }
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
22 |
29 |
33 |
34 |
37 |
38 |
39 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
55 |
59 |
60 |
61 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/android/app/src/main/java/cn/phoenixsky/wan_android/MainActivity.java:
--------------------------------------------------------------------------------
1 | package cn.phoenixsky.wan_android;
2 |
3 | import io.flutter.embedding.android.FlutterActivity;
4 |
5 | public class MainActivity extends FlutterActivity {
6 | }
7 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-night/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 | -
8 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/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/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/launch_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/android/app/src/main/res/mipmap-mdpi/launch_image.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/launch_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/android/app/src/main/res/mipmap-xhdpi/launch_image.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/launch_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/android/app/src/main/res/mipmap-xxhdpi/launch_image.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/android/app/src/main/res/xml/network_security_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | jcenter()
5 | }
6 |
7 | dependencies {
8 | //classpath 'com.android.tools.build:gradle:3.2.1'
9 | classpath 'com.android.tools.build:gradle:3.5.1'
10 | }
11 | }
12 |
13 | allprojects {
14 | repositories {
15 | google()
16 | jcenter()
17 | }
18 | }
19 |
20 | rootProject.buildDir = '../build'
21 | subprojects {
22 | project.buildDir = "${rootProject.buildDir}/${project.name}"
23 | }
24 | subprojects {
25 | project.evaluationDependsOn(':app')
26 | }
27 |
28 | task clean(type: Delete) {
29 | delete rootProject.buildDir
30 | }
31 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 |
3 | android.useAndroidX=true
4 | android.enableJetifier=true
5 | android.enableR8=true
6 |
--------------------------------------------------------------------------------
/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-5.4.1-all.zip
7 | #distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
8 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/android/settings_aar.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/assets/animations/like.flr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/assets/animations/like.flr
--------------------------------------------------------------------------------
/assets/fonts/ZCOOLKuaiLe-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/assets/fonts/ZCOOLKuaiLe-Regular.ttf
--------------------------------------------------------------------------------
/assets/fonts/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/assets/fonts/iconfont.ttf
--------------------------------------------------------------------------------
/assets/images/home_second_floor_builder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/assets/images/home_second_floor_builder.png
--------------------------------------------------------------------------------
/assets/images/login_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/assets/images/login_logo.png
--------------------------------------------------------------------------------
/assets/images/logo_wechat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/assets/images/logo_wechat.png
--------------------------------------------------------------------------------
/assets/images/logo_weibo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/assets/images/logo_weibo.png
--------------------------------------------------------------------------------
/assets/images/splash_android.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/assets/images/splash_android.png
--------------------------------------------------------------------------------
/assets/images/splash_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/assets/images/splash_bg.png
--------------------------------------------------------------------------------
/assets/images/splash_bg_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/assets/images/splash_bg_dark.png
--------------------------------------------------------------------------------
/assets/images/splash_flutter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/assets/images/splash_flutter.png
--------------------------------------------------------------------------------
/assets/images/splash_fun.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/assets/images/splash_fun.png
--------------------------------------------------------------------------------
/assets/images/user_avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/assets/images/user_avatar.png
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
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 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def flutter_root
14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
15 | unless File.exist?(generated_xcode_build_settings_path)
16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
17 | end
18 |
19 | File.foreach(generated_xcode_build_settings_path) do |line|
20 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
21 | return matches[1].strip if matches
22 | end
23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
24 | end
25 |
26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
27 |
28 | flutter_ios_podfile_setup
29 |
30 | target 'Runner' do
31 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
32 | end
33 |
34 | post_install do |installer|
35 | installer.pods_project.targets.each do |target|
36 | flutter_additional_ios_build_settings(target)
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - device_info (0.0.1):
3 | - Flutter
4 | - Flutter (1.0.0)
5 | - flutter_webview_plugin (0.0.1):
6 | - Flutter
7 | - FMDB (2.7.5):
8 | - FMDB/standard (= 2.7.5)
9 | - FMDB/standard (2.7.5)
10 | - launch_review (0.0.1):
11 | - Flutter
12 | - open_file (0.0.1):
13 | - Flutter
14 | - package_info (0.0.1):
15 | - Flutter
16 | - path_provider (0.0.1):
17 | - Flutter
18 | - screen (0.0.1):
19 | - Flutter
20 | - share (0.5.2):
21 | - Flutter
22 | - shared_preferences (0.0.1):
23 | - Flutter
24 | - sqflite (0.0.1):
25 | - Flutter
26 | - FMDB (~> 2.7.2)
27 | - url_launcher (0.0.1):
28 | - Flutter
29 | - video_player (0.0.1):
30 | - Flutter
31 | - wakelock (0.0.1):
32 | - Flutter
33 | - webview_flutter (0.0.1):
34 | - Flutter
35 |
36 | DEPENDENCIES:
37 | - device_info (from `.symlinks/plugins/device_info/ios`)
38 | - Flutter (from `Flutter`)
39 | - flutter_webview_plugin (from `.symlinks/plugins/flutter_webview_plugin/ios`)
40 | - launch_review (from `.symlinks/plugins/launch_review/ios`)
41 | - open_file (from `.symlinks/plugins/open_file/ios`)
42 | - package_info (from `.symlinks/plugins/package_info/ios`)
43 | - path_provider (from `.symlinks/plugins/path_provider/ios`)
44 | - screen (from `.symlinks/plugins/screen/ios`)
45 | - share (from `.symlinks/plugins/share/ios`)
46 | - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
47 | - sqflite (from `.symlinks/plugins/sqflite/ios`)
48 | - url_launcher (from `.symlinks/plugins/url_launcher/ios`)
49 | - video_player (from `.symlinks/plugins/video_player/ios`)
50 | - wakelock (from `.symlinks/plugins/wakelock/ios`)
51 | - webview_flutter (from `.symlinks/plugins/webview_flutter/ios`)
52 |
53 | SPEC REPOS:
54 | trunk:
55 | - FMDB
56 |
57 | EXTERNAL SOURCES:
58 | device_info:
59 | :path: ".symlinks/plugins/device_info/ios"
60 | Flutter:
61 | :path: Flutter
62 | flutter_webview_plugin:
63 | :path: ".symlinks/plugins/flutter_webview_plugin/ios"
64 | launch_review:
65 | :path: ".symlinks/plugins/launch_review/ios"
66 | open_file:
67 | :path: ".symlinks/plugins/open_file/ios"
68 | package_info:
69 | :path: ".symlinks/plugins/package_info/ios"
70 | path_provider:
71 | :path: ".symlinks/plugins/path_provider/ios"
72 | screen:
73 | :path: ".symlinks/plugins/screen/ios"
74 | share:
75 | :path: ".symlinks/plugins/share/ios"
76 | shared_preferences:
77 | :path: ".symlinks/plugins/shared_preferences/ios"
78 | sqflite:
79 | :path: ".symlinks/plugins/sqflite/ios"
80 | url_launcher:
81 | :path: ".symlinks/plugins/url_launcher/ios"
82 | video_player:
83 | :path: ".symlinks/plugins/video_player/ios"
84 | wakelock:
85 | :path: ".symlinks/plugins/wakelock/ios"
86 | webview_flutter:
87 | :path: ".symlinks/plugins/webview_flutter/ios"
88 |
89 | SPEC CHECKSUMS:
90 | device_info: d7d233b645a32c40dfdc212de5cf646ca482f175
91 | Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
92 | flutter_webview_plugin: ed9e8a6a96baf0c867e90e1bce2673913eeac694
93 | FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
94 | launch_review: 75d5a956ba8eaa493e9c9d4bf4c05e505e8d5ed0
95 | open_file: 02eb5cb6b21264bd3a696876f5afbfb7ca4f4b7d
96 | package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
97 | path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
98 | screen: abd91ca7bf3426e1cc3646d27e9b2358d6bf07b0
99 | share: 7d22fe8baedfe93aefd864bf0b73f29711fbb0a3
100 | shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
101 | sqflite: 4001a31ff81d210346b500c55b17f4d6c7589dd0
102 | url_launcher: 0067ddb8f10d36786672aa0722a21717dba3a298
103 | video_player: 9cc823b1d9da7e8427ee591e8438bfbcde500e6e
104 | wakelock: 0d4a70faf8950410735e3f61fb15d517c8a6efc4
105 | webview_flutter: d2b4d6c66968ad042ad94cbb791f5b72b4678a96
106 |
107 | PODFILE CHECKSUM: 8e679eca47255a8ca8067c4c67aab20e64cb974d
108 |
109 | COCOAPODS: 1.8.4
110 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
54 |
60 |
61 |
62 |
63 |
69 |
71 |
77 |
78 |
79 |
80 |
82 |
83 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : FlutterAppDelegate
5 |
6 | @end
7 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.m:
--------------------------------------------------------------------------------
1 | #include "AppDelegate.h"
2 | #include "GeneratedPluginRegistrant.h"
3 |
4 | @implementation AppDelegate
5 |
6 | - (BOOL)application:(UIApplication *)application
7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
8 | [GeneratedPluginRegistrant registerWithRegistry:self];
9 | // Override point for customization after application launch.
10 | return [super application:application didFinishLaunchingWithOptions:launchOptions];
11 | }
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "appicon.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "appicon-1.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "appicon-0.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "appicon-8.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "appicon-7.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "appicon-6.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "appicon-5.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "appicon-4.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "appicon-3.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "appicon-2.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/appicon-0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/AppIcon.appiconset/appicon-0.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/appicon-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/AppIcon.appiconset/appicon-1.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/appicon-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/AppIcon.appiconset/appicon-2.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/appicon-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/AppIcon.appiconset/appicon-3.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/appicon-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/AppIcon.appiconset/appicon-4.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/appicon-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/AppIcon.appiconset/appicon-5.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/appicon-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/AppIcon.appiconset/appicon-6.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/appicon-7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/AppIcon.appiconset/appicon-7.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/appicon-8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/AppIcon.appiconset/appicon-8.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/appicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/AppIcon.appiconset/appicon.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" : "universal",
5 | "filename" : "appicon-3.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "appicon.png",
11 | "appearances" : [
12 | {
13 | "appearance" : "luminosity",
14 | "value" : "dark"
15 | }
16 | ],
17 | "scale" : "1x"
18 | },
19 | {
20 | "idiom" : "universal",
21 | "filename" : "appicon-4.png",
22 | "scale" : "2x"
23 | },
24 | {
25 | "idiom" : "universal",
26 | "filename" : "appicon-1.png",
27 | "appearances" : [
28 | {
29 | "appearance" : "luminosity",
30 | "value" : "dark"
31 | }
32 | ],
33 | "scale" : "2x"
34 | },
35 | {
36 | "idiom" : "universal",
37 | "filename" : "appicon-5.png",
38 | "scale" : "3x"
39 | },
40 | {
41 | "idiom" : "universal",
42 | "filename" : "appicon-2.png",
43 | "appearances" : [
44 | {
45 | "appearance" : "luminosity",
46 | "value" : "dark"
47 | }
48 | ],
49 | "scale" : "3x"
50 | }
51 | ],
52 | "info" : {
53 | "version" : 1,
54 | "author" : "xcode"
55 | }
56 | }
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/appicon-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/LaunchImage.imageset/appicon-1.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/appicon-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/LaunchImage.imageset/appicon-2.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/appicon-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/LaunchImage.imageset/appicon-3.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/appicon-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/LaunchImage.imageset/appicon-4.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/appicon-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/LaunchImage.imageset/appicon-5.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/appicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phoenixsky/fun_android_flutter/1d56e91b79693ef452209395aedfdbb9c0094f34/ios/Runner/Assets.xcassets/LaunchImage.imageset/appicon.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 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/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 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | Fun Flutter
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | Fun Android
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(FLUTTER_BUILD_NUMBER)
25 | LSApplicationQueriesSchemes
26 |
27 | itms
28 | jianshu
29 | juejin
30 |
31 | LSRequiresIPhoneOS
32 |
33 | NSAppTransportSecurity
34 |
35 | NSAllowsArbitraryLoads
36 |
37 | NSAllowsArbitraryLoadsInWebContent
38 |
39 |
40 | UILaunchStoryboardName
41 | LaunchScreen
42 | UIMainStoryboardFile
43 | Main
44 | UISupportedInterfaceOrientations
45 |
46 | UIInterfaceOrientationPortrait
47 |
48 | UISupportedInterfaceOrientations~ipad
49 |
50 | UIInterfaceOrientationPortrait
51 | UIInterfaceOrientationPortraitUpsideDown
52 | UIInterfaceOrientationLandscapeLeft
53 | UIInterfaceOrientationLandscapeRight
54 |
55 | UIViewControllerBasedStatusBarAppearance
56 |
57 | io.flutter.embedded_views_preview
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/ios/Runner/main.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import "AppDelegate.h"
4 |
5 | int main(int argc, char* argv[]) {
6 | @autoreleasepool {
7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/ios/Runner/zh-Hans.lproj/LaunchScreen.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/ios/Runner/zh-Hans.lproj/Main.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/lib/config/net/api.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:dio/native_imp.dart';
4 | import 'package:flutter/foundation.dart';
5 | import 'package:dio/dio.dart';
6 | import 'package:fun_android/utils/platform_utils.dart';
7 |
8 | export 'package:dio/dio.dart';
9 |
10 | // 必须是顶层函数
11 | _parseAndDecode(String response) {
12 | return jsonDecode(response);
13 | }
14 |
15 | parseJson(String text) {
16 | return compute(_parseAndDecode, text);
17 | }
18 |
19 | abstract class BaseHttp extends DioForNative {
20 | BaseHttp() {
21 | /// 初始化 加入app通用处理
22 | (transformer as DefaultTransformer).jsonDecodeCallback = parseJson;
23 | interceptors..add(HeaderInterceptor());
24 | init();
25 | }
26 |
27 | void init();
28 | }
29 |
30 | /// 添加常用Header
31 | class HeaderInterceptor extends InterceptorsWrapper {
32 | @override
33 | onRequest(RequestOptions options) async {
34 | options.connectTimeout = 1000 * 45;
35 | options.receiveTimeout = 1000 * 45;
36 |
37 | var appVersion = await PlatformUtils.getAppVersion();
38 | var version = Map()
39 | ..addAll({
40 | 'appVerison': appVersion,
41 | });
42 | options.headers['version'] = version;
43 | options.headers['platform'] = Platform.operatingSystem;
44 | return options;
45 | }
46 | }
47 |
48 | /// 子类需要重写
49 | abstract class BaseResponseData {
50 | int code = 0;
51 | String message;
52 | dynamic data;
53 |
54 | bool get success;
55 |
56 | BaseResponseData({this.code, this.message, this.data});
57 |
58 | @override
59 | String toString() {
60 | return 'BaseRespData{code: $code, message: $message, data: $data}';
61 | }
62 | }
63 |
64 |
65 | /// 接口的code没有返回为true的异常
66 | class NotSuccessException implements Exception {
67 | String message;
68 |
69 | NotSuccessException.fromRespData(BaseResponseData respData) {
70 | message = respData.message;
71 | }
72 |
73 | @override
74 | String toString() {
75 | return 'NotExpectedException{respData: $message}';
76 | }
77 | }
78 |
79 | /// 用于未登录等权限不够,需要跳转授权页面
80 | class UnAuthorizedException implements Exception {
81 | const UnAuthorizedException();
82 |
83 | @override
84 | String toString() => 'UnAuthorizedException';
85 | }
86 |
87 |
--------------------------------------------------------------------------------
/lib/config/net/pgyer_api.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:flutter/foundation.dart';
3 |
4 | import 'api.dart';
5 |
6 | final Http http = Http();
7 |
8 | class Http extends BaseHttp {
9 | @override
10 | void init() {
11 | options.baseUrl = 'https://www.pgyer.com/apiv2/';
12 | interceptors.add(PgyerApiInterceptor());
13 | }
14 | }
15 |
16 | /// App相关 API
17 | class PgyerApiInterceptor extends InterceptorsWrapper {
18 | @override
19 | onRequest(RequestOptions options) async {
20 | options.queryParameters['_api_key'] = '00f25cece8e201753872c268b5832df9';
21 | options.queryParameters['appKey'] = '0f7026d9c95933c7d0553628605b6ea4';
22 | debugPrint('---api-request--->url--> ${options.baseUrl}${options.path}' +
23 | ' queryParameters: ${options.queryParameters}');
24 | return options;
25 | }
26 |
27 | @override
28 | onResponse(Response response) {
29 | ResponseData respData = ResponseData.fromJson(response.data);
30 | if (respData.success) {
31 | response.data = respData.data;
32 | return http.resolve(response);
33 | } else {
34 | throw NotSuccessException.fromRespData(respData);
35 | }
36 | }
37 | }
38 |
39 | class ResponseData extends BaseResponseData {
40 | bool get success => code == 0;
41 |
42 | ResponseData.fromJson(Map json) {
43 | code = json['code'];
44 | message = json['message'];
45 | data = json['data'];
46 | }
47 | }
48 |
49 | /// CheckApp更新接口
50 | class AppUpdateInfo {
51 | String buildBuildVersion;
52 | String forceUpdateVersion;
53 | String forceUpdateVersionNo;
54 | bool needForceUpdate;
55 | String downloadURL;
56 | bool buildHaveNewVersion;
57 | String buildVersionNo;
58 | String buildVersion;
59 | String buildShortcutUrl;
60 | String buildUpdateDescription;
61 |
62 | static AppUpdateInfo fromMap(Map map) {
63 | if (map == null) return null;
64 | AppUpdateInfo pgyerApiBean = AppUpdateInfo();
65 | pgyerApiBean.buildBuildVersion = map['buildBuildVersion'];
66 | pgyerApiBean.forceUpdateVersion = map['forceUpdateVersion'];
67 | pgyerApiBean.forceUpdateVersionNo = map['forceUpdateVersionNo'];
68 | pgyerApiBean.needForceUpdate = map['needForceUpdate'];
69 | pgyerApiBean.downloadURL = map['downloadURL'];
70 | pgyerApiBean.buildHaveNewVersion = map['buildHaveNewVersion'];
71 | pgyerApiBean.buildVersionNo = map['buildVersionNo'];
72 | pgyerApiBean.buildVersion = map['buildVersion'];
73 | pgyerApiBean.buildShortcutUrl = map['buildShortcutUrl'];
74 | pgyerApiBean.buildUpdateDescription = map['buildUpdateDescription'];
75 | return pgyerApiBean;
76 | }
77 |
78 | Map toJson() => {
79 | "buildBuildVersion": buildBuildVersion,
80 | "forceUpdateVersion": forceUpdateVersion,
81 | "forceUpdateVersionNo": forceUpdateVersionNo,
82 | "needForceUpdate": needForceUpdate,
83 | "downloadURL": downloadURL,
84 | "buildHaveNewVersion": buildHaveNewVersion,
85 | "buildVersionNo": buildVersionNo,
86 | "buildVersion": buildVersion,
87 | "buildShortcutUrl": buildShortcutUrl,
88 | "buildUpdateDescription": buildUpdateDescription,
89 | };
90 | }
91 |
--------------------------------------------------------------------------------
/lib/config/net/wan_android_api.dart:
--------------------------------------------------------------------------------
1 | import 'package:cookie_jar/cookie_jar.dart';
2 | import 'package:dio/dio.dart';
3 | import 'package:dio_cookie_manager/dio_cookie_manager.dart';
4 | import 'package:flutter/foundation.dart';
5 | import 'api.dart';
6 | import '../storage_manager.dart';
7 |
8 | final Http http = Http();
9 |
10 | class Http extends BaseHttp {
11 | @override
12 | void init() {
13 | options.baseUrl = 'https://www.wanandroid.com/';
14 | interceptors
15 | ..add(ApiInterceptor())
16 | // cookie持久化 异步
17 | ..add(CookieManager(
18 | PersistCookieJar(dir: StorageManager.temporaryDirectory.path)));
19 | }
20 | }
21 |
22 | /// 玩Android API
23 | class ApiInterceptor extends InterceptorsWrapper {
24 | @override
25 | onRequest(RequestOptions options) async {
26 | debugPrint('---api-request--->url--> ${options.baseUrl}${options.path}' +
27 | ' queryParameters: ${options.queryParameters}');
28 | // debugPrint('---api-request--->data--->${options.data}');
29 | return options;
30 | }
31 |
32 | @override
33 | onResponse(Response response) {
34 | // debugPrint('---api-response--->resp----->${response.data}');
35 | ResponseData respData = ResponseData.fromJson(response.data);
36 | if (respData.success) {
37 | response.data = respData.data;
38 | return http.resolve(response);
39 | } else {
40 | if (respData.code == -1001) {
41 | // 如果cookie过期,需要清除本地存储的登录信息
42 | // StorageManager.localStorage.deleteItem(UserModel.keyUser);
43 | throw const UnAuthorizedException(); // 需要登录
44 | } else {
45 | throw NotSuccessException.fromRespData(respData);
46 | }
47 | }
48 | }
49 | }
50 |
51 | class ResponseData extends BaseResponseData {
52 | bool get success => 0 == code;
53 |
54 | ResponseData.fromJson(Map json) {
55 | code = json['errorCode'];
56 | message = json['errorMsg'];
57 | data = json['data'];
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/lib/config/provider_manager.dart:
--------------------------------------------------------------------------------
1 | import 'package:fun_android/view_model/favourite_model.dart';
2 | import 'package:fun_android/view_model/locale_model.dart';
3 | import 'package:provider/provider.dart';
4 | import 'package:fun_android/view_model/theme_model.dart';
5 | import 'package:fun_android/view_model/user_model.dart';
6 | import 'package:provider/single_child_widget.dart';
7 |
8 | List providers = [
9 | ...independentServices,
10 | ...dependentServices,
11 | ...uiConsumableProviders
12 | ];
13 |
14 | /// 独立的model
15 | List independentServices = [
16 | ChangeNotifierProvider(
17 | create: (context) => ThemeModel(),
18 | ),
19 | ChangeNotifierProvider(
20 | create: (context) => LocaleModel(),
21 | ),
22 | ChangeNotifierProvider(
23 | create: (context) => GlobalFavouriteStateModel(),
24 | )
25 | ];
26 |
27 | /// 需要依赖的model
28 | ///
29 | /// UserModel依赖globalFavouriteStateModel
30 | List dependentServices = [
31 | ChangeNotifierProxyProvider(
32 | create: null,
33 | update: (context, globalFavouriteStateModel, userModel) =>
34 | userModel ??
35 | UserModel(globalFavouriteStateModel: globalFavouriteStateModel),
36 | )
37 | ];
38 |
39 | List uiConsumableProviders = [
40 | // StreamProvider(
41 | // builder: (context) => Provider.of(context, listen: false).user,
42 | // )
43 | ];
44 |
--------------------------------------------------------------------------------
/lib/config/resource_mananger.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter/widgets.dart';
6 |
7 | class ImageHelper {
8 | static const String baseUrl = 'http://www.meetingplus.cn';
9 | static const String imagePrefix = '$baseUrl/uimg/';
10 |
11 | static String wrapUrl(String url) {
12 | if (url.startsWith('http')) {
13 | return url;
14 | } else {}
15 | return imagePrefix + url;
16 | }
17 |
18 | static String wrapAssets(String url) {
19 | return "assets/images/" + url;
20 | }
21 |
22 | static Widget placeHolder({double width, double height}) {
23 | return SizedBox(
24 | width: width,
25 | height: height,
26 | child: CupertinoActivityIndicator(radius: min(10.0, width / 3)));
27 | }
28 |
29 | static Widget error({double width, double height, double size}) {
30 | return SizedBox(
31 | width: width,
32 | height: height,
33 | child: Icon(
34 | Icons.error_outline,
35 | size: size,
36 | ));
37 | }
38 |
39 | static String randomUrl(
40 | {int width = 100, int height = 100, Object key = ''}) {
41 | return 'http://placeimg.com/$width/$height/${key.hashCode.toString() + key.toString()}';
42 | }
43 | }
44 |
45 | class IconFonts {
46 | IconFonts._();
47 |
48 | /// iconfont:flutter base
49 | static const String fontFamily = 'iconfont';
50 |
51 | static const IconData pageEmpty = IconData(0xe63c, fontFamily: fontFamily);
52 | static const IconData pageError = IconData(0xe600, fontFamily: fontFamily);
53 | static const IconData pageNetworkError = IconData(0xe678, fontFamily: fontFamily);
54 | static const IconData pageUnAuth = IconData(0xe65f, fontFamily: fontFamily);
55 | }
56 |
--------------------------------------------------------------------------------
/lib/config/router_manger.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/cupertino.dart';
3 | import 'package:fun_android/config/storage_manager.dart';
4 | import 'package:fun_android/model/article.dart';
5 | import 'package:fun_android/model/tree.dart';
6 | import 'package:fun_android/ui/page/coin/coin_ranking_list_page.dart';
7 | import 'package:fun_android/ui/page/coin/coin_record_list_page.dart';
8 | import 'package:fun_android/ui/page/favourite_list_page.dart';
9 | import 'package:fun_android/ui/page/article/article_list_page.dart';
10 | import 'package:fun_android/ui/page/setting_page.dart';
11 | import 'package:fun_android/ui/page/tab/home_second_floor_page.dart';
12 | import 'package:fun_android/ui/page/user/login_page.dart';
13 | import 'package:fun_android/ui/page/splash.dart';
14 | import 'package:fun_android/ui/page/tab/tab_navigator.dart';
15 | import 'package:fun_android/ui/page/article/article_detail_page.dart';
16 | import 'package:fun_android/ui/page/article/article_detail_plugin_page.dart';
17 | import 'package:fun_android/ui/page/user/register_page.dart';
18 | import 'package:fun_android/ui/widget/page_route_anim.dart';
19 | import 'package:fun_android/view_model/setting_model.dart';
20 |
21 | class RouteName {
22 | static const String splash = 'splash';
23 | static const String tab = '/';
24 | static const String homeSecondFloor = 'homeSecondFloor';
25 | static const String login = 'login';
26 | static const String register = 'register';
27 | static const String articleDetail = 'articleDetail';
28 | static const String structureList = 'structureList';
29 | static const String favouriteList = 'favouriteList';
30 | static const String setting = 'setting';
31 | static const String coinRecordList = 'coinRecordList';
32 | static const String coinRankingList = 'coinRankingList';
33 | }
34 |
35 | class MyRouter {
36 | static Route generateRoute(RouteSettings settings) {
37 | switch (settings.name) {
38 | case RouteName.splash:
39 | return NoAnimRouteBuilder(SplashPage());
40 | case RouteName.tab:
41 | return NoAnimRouteBuilder(TabNavigator());
42 | case RouteName.homeSecondFloor:
43 | return SlideTopRouteBuilder(MyBlogPage());
44 | case RouteName.login:
45 | return CupertinoPageRoute(
46 | fullscreenDialog: true, builder: (_) => LoginPage());
47 | case RouteName.register:
48 | return CupertinoPageRoute(builder: (_) => RegisterPage());
49 | case RouteName.articleDetail:
50 | var article = settings.arguments as Article;
51 | return CupertinoPageRoute(builder: (_) {
52 | // 根据配置调用页面
53 | return StorageManager.sharedPreferences.getBool(kUseWebViewPlugin) ??
54 | false
55 | ? ArticleDetailPluginPage(
56 | article: article,
57 | )
58 | : ArticleDetailPage(
59 | article: article,
60 | );
61 | });
62 | case RouteName.structureList:
63 | var list = settings.arguments as List;
64 | Tree tree = list[0] as Tree;
65 | int index = list[1];
66 | return CupertinoPageRoute(
67 | builder: (_) => ArticleCategoryTabPage(tree, index));
68 | case RouteName.favouriteList:
69 | return CupertinoPageRoute(builder: (_) => FavouriteListPage());
70 | case RouteName.setting:
71 | return CupertinoPageRoute(builder: (_) => SettingPage());
72 | case RouteName.coinRecordList:
73 | return CupertinoPageRoute(builder: (_) => CoinRecordListPage());
74 | case RouteName.coinRankingList:
75 | return CupertinoPageRoute(builder: (_) => CoinRankingListPage());
76 | default:
77 | return CupertinoPageRoute(
78 | builder: (_) => Scaffold(
79 | body: Center(
80 | child: Text('No route defined for ${settings.name}'),
81 | ),
82 | ));
83 | }
84 | }
85 | }
86 |
87 | /// Pop路由
88 | class PopRoute extends PopupRoute {
89 | final Duration _duration = Duration(milliseconds: 300);
90 | Widget child;
91 |
92 | PopRoute({@required this.child});
93 |
94 | @override
95 | Color get barrierColor => null;
96 |
97 | @override
98 | bool get barrierDismissible => true;
99 |
100 | @override
101 | String get barrierLabel => null;
102 |
103 | @override
104 | Widget buildPage(BuildContext context, Animation animation,
105 | Animation secondaryAnimation) {
106 | return child;
107 | }
108 |
109 | @override
110 | Duration get transitionDuration => _duration;
111 | }
112 |
--------------------------------------------------------------------------------
/lib/config/storage_manager.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:localstorage/localstorage.dart';
4 | import 'package:shared_preferences/shared_preferences.dart';
5 | import 'package:path_provider/path_provider.dart';
6 |
7 | class StorageManager {
8 | /// app全局配置 eg:theme
9 | static SharedPreferences sharedPreferences;
10 |
11 | /// 临时目录 eg: cookie
12 | static Directory temporaryDirectory;
13 |
14 |
15 | /// 初始化必备操作 eg:user数据
16 | static LocalStorage localStorage;
17 |
18 | /// 必备数据的初始化操作
19 | ///
20 | /// 由于是同步操作会导致阻塞,所以应尽量减少存储容量
21 | static init() async {
22 | // async 异步操作
23 | // sync 同步操作
24 | temporaryDirectory = await getTemporaryDirectory();
25 | sharedPreferences = await SharedPreferences.getInstance();
26 | localStorage = LocalStorage('LocalStorage');
27 | await localStorage.ready;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lib/config/ui_adapter_config.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'dart:collection';
3 |
4 | import 'package:flutter/gestures.dart';
5 | import 'package:flutter/rendering.dart';
6 | import 'dart:ui' as ui;
7 |
8 | import 'package:flutter/widgets.dart';
9 | /// https://github.com/genius158/FlutterTest
10 |
11 | const double SCREEN_WIDTH = 414;
12 |
13 | class InnerWidgetsFlutterBinding extends WidgetsFlutterBinding {
14 |
15 | static WidgetsBinding ensureInitialized() {
16 | if (WidgetsBinding.instance == null) InnerWidgetsFlutterBinding();
17 | return WidgetsBinding.instance;
18 | }
19 |
20 | double get adapterRatio {
21 | return ui.window.physicalSize.width / SCREEN_WIDTH;
22 | }
23 |
24 | @override
25 | ViewConfiguration createViewConfiguration() {
26 |
27 | return ViewConfiguration(
28 | size: window.physicalSize / adapterRatio,
29 | devicePixelRatio: adapterRatio,
30 | );
31 | }
32 |
33 |
34 | /// wrap [GestureBinding _handlePointerDataPacket]
35 | /// replace the [PixelRatio]
36 |
37 | @override
38 | void initInstances() {
39 | super.initInstances();
40 | ui.window.onPointerDataPacket = _handlePointerDataPacket;
41 | }
42 |
43 | @override
44 | void unlocked() {
45 | super.unlocked();
46 | _flushPointerEventQueue();
47 | }
48 |
49 | final Queue _pendingPointerEvents = Queue();
50 |
51 | void _handlePointerDataPacket(ui.PointerDataPacket packet) {
52 | _pendingPointerEvents.addAll(PointerEventConverter.expand(
53 | packet.data,
54 | // 适配事件的转换比率,采用我们修改的
55 | adapterRatio));
56 | if (!locked) _flushPointerEventQueue();
57 | }
58 |
59 | @override
60 | void cancelPointer(int pointer) {
61 | if (_pendingPointerEvents.isEmpty && !locked)
62 | scheduleMicrotask(_flushPointerEventQueue);
63 | _pendingPointerEvents.addFirst(PointerCancelEvent(pointer: pointer));
64 | }
65 |
66 | void _flushPointerEventQueue() {
67 | assert(!locked);
68 | while (_pendingPointerEvents.isNotEmpty)
69 | _handlePointerEvent(_pendingPointerEvents.removeFirst());
70 | }
71 |
72 | final Map _hitTests = {};
73 |
74 | void _handlePointerEvent(PointerEvent event) {
75 | assert(!locked);
76 | HitTestResult result;
77 | if (event is PointerDownEvent) {
78 | assert(!_hitTests.containsKey(event.pointer));
79 | result = HitTestResult();
80 | hitTest(result, event.position);
81 | _hitTests[event.pointer] = result;
82 | assert(() {
83 | if (debugPrintHitTestResults) debugPrint('$event: $result');
84 | return true;
85 | }());
86 | } else if (event is PointerUpEvent || event is PointerCancelEvent) {
87 | result = _hitTests.remove(event.pointer);
88 | } else if (event.down) {
89 | result = _hitTests[event.pointer];
90 | } else {
91 | return; // We currently ignore add, remove, and hover move events.
92 | }
93 | if (result != null) dispatchEvent(event, result);
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/lib/generated/intl/messages_all.dart:
--------------------------------------------------------------------------------
1 | // DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
2 | // This is a library that looks up messages for specific locales by
3 | // delegating to the appropriate library.
4 |
5 | // Ignore issues from commonly used lints in this file.
6 | // ignore_for_file:implementation_imports, file_names, unnecessary_new
7 | // ignore_for_file:unnecessary_brace_in_string_interps, directives_ordering
8 | // ignore_for_file:argument_type_not_assignable, invalid_assignment
9 | // ignore_for_file:prefer_single_quotes, prefer_generic_function_type_aliases
10 | // ignore_for_file:comment_references
11 |
12 | import 'dart:async';
13 |
14 | import 'package:intl/intl.dart';
15 | import 'package:intl/message_lookup_by_library.dart';
16 | import 'package:intl/src/intl_helpers.dart';
17 |
18 | import 'messages_en.dart' as messages_en;
19 | import 'messages_zh.dart' as messages_zh;
20 |
21 | typedef Future LibraryLoader();
22 | Map _deferredLibraries = {
23 | 'en': () => new Future.value(null),
24 | 'zh': () => new Future.value(null),
25 | };
26 |
27 | MessageLookupByLibrary _findExact(String localeName) {
28 | switch (localeName) {
29 | case 'en':
30 | return messages_en.messages;
31 | case 'zh':
32 | return messages_zh.messages;
33 | default:
34 | return null;
35 | }
36 | }
37 |
38 | /// User programs should call this before using [localeName] for messages.
39 | Future initializeMessages(String localeName) async {
40 | var availableLocale = Intl.verifiedLocale(
41 | localeName,
42 | (locale) => _deferredLibraries[locale] != null,
43 | onFailure: (_) => null);
44 | if (availableLocale == null) {
45 | return new Future.value(false);
46 | }
47 | var lib = _deferredLibraries[availableLocale];
48 | await (lib == null ? new Future.value(false) : lib());
49 | initializeInternalMessageLookup(() => new CompositeMessageLookup());
50 | messageLookup.addLocale(availableLocale, _findGeneratedMessagesFor);
51 | return new Future.value(true);
52 | }
53 |
54 | bool _messagesExistFor(String locale) {
55 | try {
56 | return _findExact(locale) != null;
57 | } catch (e) {
58 | return false;
59 | }
60 | }
61 |
62 | MessageLookupByLibrary _findGeneratedMessagesFor(String locale) {
63 | var actualLocale = Intl.verifiedLocale(locale, _messagesExistFor,
64 | onFailure: (_) => null);
65 | if (actualLocale == null) return null;
66 | return _findExact(actualLocale);
67 | }
68 |
--------------------------------------------------------------------------------
/lib/l10n/intl_en.arb:
--------------------------------------------------------------------------------
1 | {
2 | "appName": "Fun Android",
3 | "actionConfirm": "Confirm",
4 | "actionCancel": "Cancel",
5 | "viewStateMessageError": "Load Failed",
6 | "viewStateMessageNetworkError": "Load Failed,Check network ",
7 | "viewStateMessageEmpty": "Nothing Found",
8 | "viewStateMessageUnAuth": "Not sign in yet",
9 | "viewStateButtonRefresh": "Refresh",
10 | "viewStateButtonRetry": "Retry",
11 | "viewStateButtonLogin": "Sign In",
12 | "refreshTwoLevel": "release to enter second floor",
13 | "retry": "Retry",
14 | "splashSkip": "Skip",
15 | "tabHome": "Home",
16 | "tabProject": "Project",
17 | "tabStructure": "Structure",
18 | "tabUser": "Me",
19 | "setting": "Setting",
20 | "settingLanguage": "Language",
21 | "settingFont": "System Font",
22 | "logout": "Sign Out",
23 | "favourites": "Favorites",
24 | "darkMode": "Dark Mode",
25 | "theme": "Theme",
26 | "about": "About",
27 | "close": "Close",
28 | "feedback": "FeedBack",
29 | "githubIssue": "Can't find mail app,please github issues",
30 | "autoBySystem": "Auto",
31 | "fontKuaiLe": "ZCOOL KuaiLe",
32 | "fieldNotNull": "not empty",
33 | "userName": "Username",
34 | "password": "Password",
35 | "toSignUp": "Sign Up",
36 | "signUp": "Sign Up",
37 | "rePassword": "Confirm Password",
38 | "twoPwdDifferent": "The two passwords differ",
39 | "toSignIn": "Sign In",
40 | "signIn": "Sign In",
41 | "noAccount": "No Account ? ",
42 | "myFavourites": "My favourites",
43 | "signIn3thd": "More",
44 | "searchHot": "Hot",
45 | "searchShake": "Shake",
46 | "searchHistory": "History",
47 | "clear": "Clear",
48 | "refresh": "Refresh",
49 | "unLike": "UnLike",
50 | "Like": "Like",
51 | "share": "Share",
52 | "wechatAccount": "Wechat",
53 | "rate": "Rate",
54 | "needLogin": "Go to Sign In",
55 | "loadFailed": "Load failed,retry later",
56 | "collectionRemove": "Remove",
57 | "article_tag_top": "Top",
58 | "openBrowser": "Open Browser",
59 | "coin": "Coin",
60 | "appUpdateCheckUpdate": "Check Update",
61 | "appUpdateActionUpdate": "Update",
62 | "appUpdateLeastVersion": "Least version now ",
63 | "appUpdateDownloading": "Downloading...",
64 | "appUpdateDownloadFailed": "Download failed",
65 | "appUpdateReDownloadContent": "It has been detected that it has been downloaded, whether it is installed?",
66 | "appUpdateActionDownloadAgain": "Download",
67 | "appUpdateActionInstallApk": "Install",
68 | "appUpdateUpdate": "Version Update",
69 | "appUpdateFoundNewVersion": "New version {version}",
70 | "appUpdateDownloadCanceled": "Download canceled",
71 | "appUpdateDoubleBackTips": "Press back again, cancel download"
72 | }
--------------------------------------------------------------------------------
/lib/l10n/intl_zh.arb:
--------------------------------------------------------------------------------
1 | {
2 | "appName": "玩Android",
3 | "actionConfirm": "确认",
4 | "actionCancel": "取消",
5 | "viewStateMessageError": "加载失败",
6 | "viewStateMessageNetworkError": "网络连接异常,请检查网络或稍后重试",
7 | "viewStateMessageEmpty": "空空如也",
8 | "viewStateMessageUnAuth": "未登录",
9 | "viewStateButtonRefresh": "刷新一下",
10 | "viewStateButtonRetry": "重试",
11 | "viewStateButtonLogin": "登录",
12 | "refreshTwoLevel": "欢迎光临,我的空中楼阁",
13 | "retry": "重试",
14 | "splashSkip": "跳过",
15 | "tabHome": "首页",
16 | "tabProject": "项目",
17 | "tabStructure": "体系",
18 | "tabUser": "我的",
19 | "setting": "设置",
20 | "settingLanguage": "多语言",
21 | "settingFont": "字体",
22 | "logout": "退出登录",
23 | "favourites": "收藏",
24 | "darkMode": "黑夜模式",
25 | "theme": "色彩主题",
26 | "about": "关于",
27 | "close": "关闭",
28 | "feedback": "意见反馈",
29 | "githubIssue": "未找到邮件客户端,请前往github,提issue",
30 | "autoBySystem": "跟随系统",
31 | "fontKuaiLe": "快乐字体",
32 | "fieldNotNull": "不能为空",
33 | "userName": "用户名",
34 | "password": "密码",
35 | "signUp": "注册",
36 | "toSignUp": "去注册",
37 | "rePassword": "确认密码",
38 | "twoPwdDifferent": "两次密码不一致",
39 | "toSignIn": "点我登录",
40 | "signIn": "登录",
41 | "noAccount": "还没账号? ",
42 | "myFavourites": "我的收藏",
43 | "signIn3thd": "第三方登录",
44 | "searchHot": "热门搜索",
45 | "searchShake": "换一换",
46 | "searchHistory": "历史搜索",
47 | "clear": "清空",
48 | "refresh": "刷新",
49 | "unLike": "取消收藏",
50 | "Like": "收藏",
51 | "share": "分享",
52 | "wechatAccount": "公众号",
53 | "rate": "评分",
54 | "needLogin": "请先登录",
55 | "loadFailed": "加载失败,请稍后重试",
56 | "collectionRemove": "移除收藏",
57 | "article_tag_top": "置顶",
58 | "openBrowser": "浏览器打开",
59 | "coin": "积分",
60 | "appUpdateCheckUpdate": "检查更新",
61 | "appUpdateActionUpdate": "更新",
62 | "appUpdateLeastVersion": "已是最新版本",
63 | "appUpdateDownloading": "下载中,请稍后...",
64 | "appUpdateDownloadFailed": "下载失败",
65 | "appUpdateReDownloadContent": "检测到本地已下载过该版本,是否直接安装?",
66 | "appUpdateActionDownloadAgain": "重新下载",
67 | "appUpdateActionInstallApk": "直接安装",
68 | "appUpdateUpdate": "版本更新",
69 | "appUpdateFoundNewVersion": "发现新版本{version},是否更新?",
70 | "appUpdateDownloadCanceled": "下载已取消",
71 | "appUpdateDoubleBackTips": "再次点击返回键,取消下载"
72 | }
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter/services.dart';
4 | import 'package:flutter_localizations/flutter_localizations.dart';
5 |
6 | import 'package:oktoast/oktoast.dart';
7 | import 'package:provider/provider.dart';
8 | import 'package:pull_to_refresh/pull_to_refresh.dart';
9 |
10 | import 'package:fun_android/config/storage_manager.dart';
11 |
12 | import 'config/provider_manager.dart';
13 | import 'config/router_manger.dart';
14 | import 'generated/l10n.dart';
15 | import 'view_model/locale_model.dart';
16 | import 'view_model/theme_model.dart';
17 |
18 | main() async {
19 | Provider.debugCheckInvalidValueType = null;
20 | WidgetsFlutterBinding.ensureInitialized();
21 | await StorageManager.init();
22 | runApp(App());
23 | // Android状态栏透明 splash为白色,所以调整状态栏文字为黑色
24 | SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
25 | statusBarColor: Colors.transparent,
26 | statusBarBrightness: Brightness.light));
27 | }
28 |
29 | class App extends StatelessWidget {
30 | @override
31 | Widget build(BuildContext context) {
32 | return OKToast(
33 | child: MultiProvider(
34 | providers: providers,
35 | child: Consumer2(
36 | builder: (context, themeModel, localeModel, child) {
37 | return RefreshConfiguration(
38 | hideFooterWhenNotFull: true, //列表数据不满一页,不触发加载更多
39 | child: MaterialApp(
40 | debugShowCheckedModeBanner: false,
41 | theme: themeModel.themeData(),
42 | darkTheme: themeModel.themeData(platformDarkMode: true),
43 | locale: localeModel.locale,
44 | localizationsDelegates: const [
45 | S.delegate,
46 | RefreshLocalizations.delegate, //下拉刷新
47 | GlobalCupertinoLocalizations.delegate,
48 | GlobalMaterialLocalizations.delegate,
49 | GlobalWidgetsLocalizations.delegate
50 | ],
51 | supportedLocales: S.delegate.supportedLocales,
52 | onGenerateRoute: MyRouter.generateRoute,
53 | initialRoute: RouteName.splash,
54 | ),
55 | );
56 | })));
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/lib/model/article.dart:
--------------------------------------------------------------------------------
1 | import 'package:fun_android/utils/string_utils.dart';
2 |
3 | class Article {
4 | String apkLink;
5 | String author;
6 | /// 2019.10.13 添加分享人,author可能为空
7 | String shareUser;
8 | int chapterId;
9 | String chapterName;
10 | bool collect;
11 | int courseId;
12 | String desc;
13 | String envelopePic;
14 | bool fresh;
15 | int id;
16 | String link;
17 | String niceDate;
18 | String origin;
19 | int originId;
20 | String prefix;
21 | String projectLink;
22 | int publishTime;
23 | int superChapterId;
24 | String superChapterName;
25 | List tags;
26 | String title;
27 | int type;
28 | int userId;
29 | int visible;
30 | int zan;
31 |
32 |
33 |
34 | static Article fromMap(Map map) {
35 | if (map == null) return null;
36 | Article articleBean = Article();
37 | articleBean.apkLink = map['apkLink'];
38 | articleBean.author = map['author'];
39 | articleBean.shareUser = map['shareUser'];
40 | articleBean.chapterId = map['chapterId'];
41 | // articleBean.chapterName = map['chapterName'];
42 | articleBean.chapterName = StringUtils.urlDecoder(map["chapterName"]);
43 | articleBean.collect = map['collect'];
44 | articleBean.courseId = map['courseId'];
45 | // articleBean.desc = map['desc'];
46 | articleBean.desc = StringUtils.urlDecoder(map["desc"]);
47 | articleBean.envelopePic = map['envelopePic'];
48 | articleBean.fresh = map['fresh'];
49 | articleBean.id = map['id'];
50 | articleBean.link = map['link'];
51 | articleBean.niceDate = map['niceDate'];
52 | articleBean.origin = map['origin'];
53 | articleBean.originId = map['originId'];
54 | articleBean.prefix = map['prefix'];
55 | articleBean.projectLink = map['projectLink'];
56 | articleBean.publishTime = map['publishTime'];
57 | articleBean.superChapterId = map['superChapterId'];
58 | // articleBean.superChapterName = map['superChapterName'];
59 | articleBean.superChapterName = StringUtils.urlDecoder(map["superChapterName"]);
60 | articleBean.tags = List()
61 | ..addAll((map['tags'] as List ?? []).map((o) => TagsBean.fromMap(o)));
62 | articleBean.title = StringUtils.urlDecoder(map["title"]);
63 | articleBean.type = map['type'];
64 | articleBean.userId = map['userId'];
65 | articleBean.visible = map['visible'];
66 | articleBean.zan = map['zan'];
67 | return articleBean;
68 | }
69 |
70 | Map toJson() => {
71 | "apkLink": apkLink,
72 | "author": author,
73 | "shareUser": shareUser,
74 | "chapterId": chapterId,
75 | "chapterName": chapterName,
76 | "collect": collect,
77 | "courseId": courseId,
78 | "desc": desc,
79 | "envelopePic": envelopePic,
80 | "fresh": fresh,
81 | "id": id,
82 | "link": link,
83 | "niceDate": niceDate,
84 | "origin": origin,
85 | "originId": originId,
86 | "prefix": prefix,
87 | "projectLink": projectLink,
88 | "publishTime": publishTime,
89 | "superChapterId": superChapterId,
90 | "superChapterName": superChapterName,
91 | "tags": tags,
92 | "title": title,
93 | "type": type,
94 | "userId": userId,
95 | "visible": visible,
96 | "zan": zan,
97 | };
98 | }
99 |
100 | class TagsBean {
101 | String name;
102 | String url;
103 |
104 | static TagsBean fromMap(Map map) {
105 | if (map == null) return null;
106 | TagsBean tagsBean = TagsBean();
107 | tagsBean.name = map['name'];
108 | tagsBean.url = map['url'];
109 | return tagsBean;
110 | }
111 |
112 | Map toJson() => {
113 | "name": name,
114 | "url": url,
115 | };
116 | }
117 |
--------------------------------------------------------------------------------
/lib/model/banner.dart:
--------------------------------------------------------------------------------
1 | class Banner {
2 | String desc;
3 | int id;
4 | String imagePath;
5 | int isVisible;
6 | int order;
7 | String title;
8 | int type;
9 | String url;
10 |
11 | Banner.fromJsonMap(Map map)
12 | : desc = map["desc"],
13 | id = map["id"],
14 | imagePath = map["imagePath"],
15 | isVisible = map["isVisible"],
16 | order = map["order"],
17 | title = map["title"],
18 | type = map["type"],
19 | url = map["url"];
20 |
21 | Map toJson() {
22 | final Map data = new Map();
23 | data['desc'] = desc;
24 | data['id'] = id;
25 | data['imagePath'] = imagePath;
26 | data['isVisible'] = isVisible;
27 | data['order'] = order;
28 | data['title'] = title;
29 | data['type'] = type;
30 | data['url'] = url;
31 | return data;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/lib/model/coin_record.dart:
--------------------------------------------------------------------------------
1 | class CoinRecord {
2 | int coinCount;
3 | int date;
4 | String desc;
5 | int id;
6 | int type;
7 | int userId;
8 | String userName;
9 |
10 | static CoinRecord fromMap(Map map) {
11 | if (map == null) return null;
12 | CoinRecord coinRecordBean = CoinRecord();
13 | coinRecordBean.coinCount = map['coinCount'];
14 | coinRecordBean.date = map['date'];
15 | coinRecordBean.desc = map['desc'];
16 | coinRecordBean.id = map['id'];
17 | coinRecordBean.type = map['type'];
18 | coinRecordBean.userId = map['userId'];
19 | coinRecordBean.userName = map['userName'];
20 | return coinRecordBean;
21 | }
22 |
23 | Map toJson() => {
24 | "coinCount": coinCount,
25 | "date": date,
26 | "desc": desc,
27 | "id": id,
28 | "type": type,
29 | "userId": userId,
30 | "userName": userName,
31 | };
32 | }
33 |
--------------------------------------------------------------------------------
/lib/model/navigation_site.dart:
--------------------------------------------------------------------------------
1 | import 'article.dart';
2 |
3 | class NavigationSite {
4 |
5 | List articles;
6 | int cid;
7 | String name;
8 |
9 | static NavigationSite fromMap(Map map) {
10 | if (map == null) return null;
11 | NavigationSite naviBean = NavigationSite();
12 | naviBean.articles = List()
13 | ..addAll((map['articles'] as List ?? []).map((o) => Article.fromMap(o)));
14 | naviBean.cid = map['cid'];
15 | naviBean.name = map['name'];
16 | return naviBean;
17 | }
18 |
19 | Map toJson() => {
20 | "articles": articles,
21 | "cid": cid,
22 | "name": name,
23 | };
24 | }
25 |
--------------------------------------------------------------------------------
/lib/model/search.dart:
--------------------------------------------------------------------------------
1 | class SearchHotKey {
2 | int id;
3 | String link;
4 | String name;
5 | int order;
6 | int visible;
7 |
8 | static SearchHotKey fromMap(Map map) {
9 | if (map == null) return null;
10 | SearchHotKey searchBean = SearchHotKey();
11 | searchBean.id = map['id'];
12 | searchBean.link = map['link'];
13 | searchBean.name = map['name'];
14 | searchBean.order = map['order'];
15 | searchBean.visible = map['visible'];
16 | return searchBean;
17 | }
18 |
19 | Map toJson() => {
20 | "id": id,
21 | "link": link,
22 | "name": name,
23 | "order": order,
24 | "visible": visible,
25 | };
26 | }
--------------------------------------------------------------------------------
/lib/model/tree.dart:
--------------------------------------------------------------------------------
1 | import 'package:fun_android/utils/string_utils.dart';
2 |
3 | class Tree {
4 | List children;
5 | int courseId;
6 | int id;
7 | String name;
8 | int order;
9 | int parentChapterId;
10 | bool userControlSetTop;
11 | int visible;
12 |
13 | Tree.fromJsonMap(Map map)
14 | : children =
15 | List.from(map["children"].map((it) => Tree.fromJsonMap(it))),
16 | courseId = map["courseId"],
17 | id = map["id"],
18 | name = StringUtils.urlDecoder(map["name"]),
19 | order = map["order"],
20 | parentChapterId = map["parentChapterId"],
21 | userControlSetTop = map["userControlSetTop"],
22 | visible = map["visible"];
23 |
24 | Map toJson() {
25 | final Map data = new Map();
26 | data['children'] =
27 | children != null ? children.map((v) => v.toJson()).toList() : null;
28 | data['courseId'] = courseId;
29 | data['id'] = id;
30 | data['name'] = name;
31 | data['order'] = order;
32 | data['parentChapterId'] = parentChapterId;
33 | data['userControlSetTop'] = userControlSetTop;
34 | data['visible'] = visible;
35 | return data;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/lib/model/user.dart:
--------------------------------------------------------------------------------
1 |
2 | class User {
3 |
4 | bool admin;
5 | List