├── .DS_Store
├── .gitignore
├── LICENSE
├── README.md
├── android
├── android.iml
├── app
│ ├── .DS_Store
│ ├── app.iml
│ ├── build.gradle
│ ├── key.keystore
│ ├── release
│ │ ├── .DS_Store
│ │ └── output.json
│ └── src
│ │ ├── .DS_Store
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── .DS_Store
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ ├── com
│ │ │ │ └── example
│ │ │ │ │ └── ncov_2019
│ │ │ │ │ └── MainActivity.java
│ │ │ └── io
│ │ │ │ └── flutter
│ │ │ │ └── plugins
│ │ │ │ └── GeneratedPluginRegistrant.java
│ │ └── res
│ │ │ ├── .DS_Store
│ │ │ ├── drawable
│ │ │ └── launch_background.xml
│ │ │ ├── mipmap-hdpi
│ │ │ ├── .DS_Store
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ ├── .DS_Store
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── .DS_Store
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── .DS_Store
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ ├── .DS_Store
│ │ │ └── ic_launcher.png
│ │ │ ├── values
│ │ │ └── styles.xml
│ │ │ └── xml
│ │ │ └── network_security_config.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── ncov_2019_android.iml
├── settings.gradle
└── settings_aar.gradle
├── assets
├── .DS_Store
├── git
│ ├── download.png
│ ├── home.png
│ ├── left_group.png
│ ├── lore.png
│ ├── protect1.png
│ ├── protect2.png
│ ├── protect3.png
│ ├── rumor1.png
│ ├── rumor2.png
│ └── rumor3.png
└── images
│ ├── a.jpg
│ ├── bottom_home.png
│ ├── bottom_lore.png
│ ├── bottom_protect.png
│ ├── bottom_rumor.png
│ ├── entries_1.png
│ ├── entries_2.png
│ ├── entries_3.png
│ ├── entries_4.png
│ └── entries_5.png
├── ios
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ ├── Flutter.framework
│ │ ├── Flutter
│ │ ├── Headers
│ │ │ ├── Flutter.h
│ │ │ ├── FlutterAppDelegate.h
│ │ │ ├── FlutterBinaryMessenger.h
│ │ │ ├── FlutterCallbackCache.h
│ │ │ ├── FlutterChannels.h
│ │ │ ├── FlutterCodecs.h
│ │ │ ├── FlutterDartProject.h
│ │ │ ├── FlutterEngine.h
│ │ │ ├── FlutterHeadlessDartRunner.h
│ │ │ ├── FlutterMacros.h
│ │ │ ├── FlutterPlatformViews.h
│ │ │ ├── FlutterPlugin.h
│ │ │ ├── FlutterPluginAppLifeCycleDelegate.h
│ │ │ ├── FlutterTexture.h
│ │ │ └── FlutterViewController.h
│ │ ├── Info.plist
│ │ ├── Modules
│ │ │ └── module.modulemap
│ │ ├── _CodeSignature
│ │ │ └── CodeResources
│ │ └── icudtl.dat
│ ├── Flutter.podspec
│ ├── Generated.xcconfig
│ ├── Release.xcconfig
│ └── flutter_export_environment.sh
├── Podfile
├── Podfile.lock
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ └── contents.xcworkspacedata
├── Runner
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ ├── Icon-App-20x20@1x.png
│ │ │ ├── Icon-App-20x20@2x.png
│ │ │ ├── Icon-App-20x20@3x.png
│ │ │ ├── Icon-App-29x29@1x.png
│ │ │ ├── Icon-App-29x29@2x.png
│ │ │ ├── Icon-App-29x29@3x.png
│ │ │ ├── Icon-App-40x40@1x.png
│ │ │ ├── Icon-App-40x40@2x.png
│ │ │ ├── Icon-App-40x40@3x.png
│ │ │ ├── Icon-App-60x60@2x.png
│ │ │ ├── Icon-App-60x60@3x.png
│ │ │ ├── Icon-App-76x76@1x.png
│ │ │ ├── Icon-App-76x76@2x.png
│ │ │ └── Icon-App-83.5x83.5@2x.png
│ │ └── LaunchImage.imageset
│ │ │ ├── Contents.json
│ │ │ ├── LaunchImage.png
│ │ │ ├── LaunchImage@2x.png
│ │ │ ├── LaunchImage@3x.png
│ │ │ └── README.md
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── GeneratedPluginRegistrant.h
│ ├── GeneratedPluginRegistrant.m
│ ├── Info.plist
│ └── main.m
└── ServiceDefinitions.json
├── lib
├── api
│ ├── area_model.dart
│ ├── area_view_model.dart
│ ├── entries_model.dart
│ ├── entries_view_model.dart
│ ├── lore_model.dart
│ ├── lore_view_model.dart
│ ├── news_model.dart
│ ├── news_view_model.dart
│ ├── protect_model.dart
│ ├── protect_view_model.dart
│ ├── rumor_model.dart
│ ├── rumor_view_model.dart
│ ├── statistics_model.dart
│ ├── statistics_view_model.dart
│ ├── version_model.dart
│ └── version_view_model.dart
├── app.dart
├── commom
│ ├── check.dart
│ ├── commom.dart
│ ├── data
│ │ ├── data.dart
│ │ ├── notice.dart
│ │ └── store.dart
│ ├── date.dart
│ ├── file_util.dart
│ ├── shared_util.dart
│ ├── ui.dart
│ └── win_media.dart
├── config
│ ├── api.dart
│ ├── config.dart
│ ├── const.dart
│ ├── keys.dart
│ └── storage_manager.dart
├── http
│ ├── req_model.dart
│ └── view_model.dart
├── main.dart
├── pages
│ ├── home
│ │ └── home_page.dart
│ ├── lore
│ │ └── lore_page.dart
│ ├── protect
│ │ └── protect_page.dart
│ ├── root
│ │ └── root_page.dart
│ └── rumor
│ │ └── rumor_page.dart
└── widget
│ ├── bar
│ └── commom_bar.dart
│ ├── card
│ ├── lore_card.dart
│ ├── news_card.dart
│ ├── protect_card.dart
│ └── rumor_card.dart
│ ├── dialog
│ └── update_dialog.dart
│ ├── flutter
│ ├── my_expansion_tile.dart
│ └── my_list_tile.dart
│ ├── item
│ ├── entries.dart
│ └── statics.dart
│ ├── orther
│ └── turn_box.dart
│ ├── root_tabbar.dart
│ ├── scroll
│ └── my_behavior.dart
│ └── view
│ ├── loading_view.dart
│ ├── pull.dart
│ ├── title_view.dart
│ └── web_view_page.dart
└── pubspec.yaml
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.lock
4 | *.log
5 | *.pyc
6 | *.swp
7 | .DS_Store
8 | .atom/
9 | .buildlog/
10 | .history
11 | .svn/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # Visual Studio Code related
20 | .classpath
21 | .project
22 | .settings/
23 | .vscode/
24 |
25 | # Flutter repo-specific
26 | /bin/cache/
27 | /bin/mingit/
28 | /dev/benchmarks/mega_gallery/
29 | /dev/bots/.recipe_deps
30 | /dev/bots/android_tools/
31 | /dev/docs/doc/
32 | /dev/docs/flutter.docs.zip
33 | /dev/docs/lib/
34 | /dev/docs/pubspec.yaml
35 | /dev/integration_tests/**/xcuserdata
36 | /dev/integration_tests/**/Pods
37 | /packages/flutter/coverage/
38 | version
39 |
40 | # packages file containing multi-root paths
41 | .packages.generated
42 |
43 | # Flutter/Dart/Pub related
44 | **/doc/api/
45 | .dart_tool/
46 | .flutter-plugins
47 | .flutter-plugins-dependencies
48 | .packages
49 | .pub-cache/
50 | .pub/
51 | build/
52 | flutter_*.png
53 | linked_*.ds
54 | unlinked.ds
55 | unlinked_spec.ds
56 |
57 | # Android related
58 | **/android/**/gradle-wrapper.jar
59 | **/android/.gradle
60 | **/android/captures/
61 | **/android/local.properties
62 | **/android/**/GeneratedPluginRegistrant.java
63 | **/android/key.properties
64 | *.jks
65 |
66 | # iOS/XCode related
67 | **/ios/**/*.mode1v3
68 | **/ios/**/*.mode2v3
69 | **/ios/**/*.moved-aside
70 | **/ios/**/*.pbxuser
71 | **/ios/**/*.perspectivev3
72 | **/ios/**/*sync/
73 | **/ios/**/.sconsign.dblite
74 | **/ios/**/.tags*
75 | **/ios/**/.vagrant/
76 | **/ios/**/DerivedData/
77 | **/ios/**/Icon?
78 | **/ios/**/Pods/
79 | **/ios/**/.symlinks/
80 | **/ios/**/profile
81 | **/ios/**/xcuserdata
82 | **/ios/.generated/
83 | **/ios/Flutter/App.framework
84 | **/ios/Flutter/Flutter.framework
85 | **/ios/Flutter/Flutter.podspec
86 | **/ios/Flutter/Generated.xcconfig
87 | **/ios/Flutter/app.flx
88 | **/ios/Flutter/app.zip
89 | **/ios/Flutter/flutter_assets/
90 | **/ios/Flutter/flutter_export_environment.sh
91 | **/ios/ServiceDefinitions.json
92 | **/ios/Runner/GeneratedPluginRegistrant.*
93 |
94 | # macOS
95 | **/macos/Flutter/GeneratedPluginRegistrant.swift
96 | **/macos/Flutter/Flutter-Debug.xcconfig
97 | **/macos/Flutter/Flutter-Release.xcconfig
98 | **/macos/Flutter/Flutter-Profile.xcconfig
99 |
100 | # Coverage
101 | coverage/
102 |
103 | # Symbols
104 | app.*.symbols
105 |
106 | # Exceptions to above rules.
107 | !**/ios/**/default.mode1v3
108 | !**/ios/**/default.mode2v3
109 | !**/ios/**/default.pbxuser
110 | !**/ios/**/default.perspectivev3
111 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
112 | !/dev/ci/**/Gemfile.lock
113 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/fluttercandies/ncov_2019/stargazers)
2 | [](https://github.com/fluttercandies/ncov_2019/network)
3 | [](https://github.com/fluttercandies/ncov_2019/issues)
4 |
5 | > 如果产生其他依赖无法编译的问题,可以尝试将`pubspec.yaml`中的`dependencies`中的所有依赖的"^"去掉,重新编译尝试。
6 |
7 | # nCoV_2019
8 |
9 | 获取新肺炎实时动态App,支持Android和IOS。
10 |
11 | # Log
12 | * 2020.09.03 - 适配Flutter 1.20
13 |
14 | * 2020.07.04 - 适配Flutter 1.17
15 |
16 | * 2020.02.16 - 修复统计图不能展示问题。(16:45)
17 |
18 | * 2020.02.16 - 辟谣卡片标题最大行数调整为2行,统计数据布局优化。(16:32)
19 |
20 | * 2020.02.16 - 完美适配Flutter1.12.13和Androidx(13:21)
21 |
22 | * 2020.02.06 - 修复了统计信息出错和诊疗无图标和对齐问题。
23 |
24 | * 2020.02.02 - 修复了统计的分隔符导致统计数据无法正常显示。
25 |
26 | # 项目相关文章
27 |
28 | * [Flutter Candies又添一成员,为抗击疫情贡献一份技术力量](https://mp.weixin.qq.com/s?__biz=MzAxMTI4MTkwNQ==&mid=2650829796&idx=1&sn=7811875471dcabd0cfec788adc27306a&chksm=80b7a77ab7c02e6cfc9726c61be31cbd616c5593d0b9388776f15fd255ccc619be7df38341b3&mpshare=1&scene=23&srcid&sharer_sharetime=1582430519570&sharer_shareid=bdfd1967c1c7dae7e61a030ea5b2b235%23rd)
29 |
30 |
31 | # App体验
32 | ##### Android 下载地址:
33 | [http://www.flutterj.com/nCoV-2019.apk](http://www.flutterj.com/nCoV-2019.apk)
34 |
35 | ##### Android(二维码下载):
36 |
37 | 
38 |
39 | IOS:
40 |
41 | 拉下代码直接跑即可
42 |
43 | # App效果图
44 | ||  |  |  |
45 | | --- | --- | --- | --- |
46 | ||  |  |  |
47 |
48 | # 使用须知
49 | * cached_network_image
50 |
51 | 在`pubspec.yaml`文件中,关于flutter版本使用`cached_network_image`插件问题,默认使用2.0.0,
52 | 因为你们刚安装上flutter为最新版本flutter。
53 | ```yaml
54 | # cached_network_image: 1.1.1 # 1.9.0左右flutter版本的用这个
55 | cached_network_image: 2.0.0 # 2.0.0左右flutter版本直接用这个
56 | ```
57 |
58 | # 使用教程
59 |
60 | * 使用命令(拉取项目):$ git clone https://github.com/fluttercandies/ncov_2019.git
61 | * 然后命令(获取依赖):$ flutter packages get (IOS执行IOS部分再执行下一步)
62 | * 最后命令(运行):$ flutter run
63 |
64 | IOS
65 | * 进入项目IOS目录:$ cd ios/
66 | * 更新Pod(非必须):$ pod update
67 | * 安装Pod:$ pod install
68 |
69 | # 我的Flutter环境
70 | ```
71 | q1deMacBook-Pro:ncov_2019 q1$ flutter doctor -v
72 | [✓] Flutter (Channel stable, 1.20.2, on Mac OS X 10.14.5 18F2059, locale zh-Hans-CN)
73 | • Flutter version 1.20.2 at /Users/q1/flutter
74 | • Framework revision bbfbf1770c (3 weeks ago), 2020-08-13 08:33:09 -0700
75 | • Engine revision 9d5b21729f
76 | • Dart version 2.9.1
77 | • Pub download mirror https://pub.flutter-io.cn
78 | • Flutter download mirror https://storage.flutter-io.cn
79 |
80 |
81 | [✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
82 | • Android SDK at /Users/q1/Library/Android/sdk
83 | • Platform android-29, build-tools 29.0.3
84 | • ANDROID_HOME = /Users/q1/Library/Android/sdk
85 | • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
86 | • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
87 | • All Android licenses accepted.
88 |
89 | [✓] Xcode - develop for iOS and macOS (Xcode 11.3)
90 | • Xcode at /Applications/Xcode.app/Contents/Developer
91 | • Xcode 11.3, Build version 11C29
92 | • CocoaPods version 1.8.4
93 |
94 | [✓] Android Studio (version 4.0)
95 | • Android Studio at /Applications/Android Studio.app/Contents
96 | • Flutter plugin version 48.1.2
97 | • Dart plugin version 193.7361
98 | • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
99 |
100 | [✓] VS Code (version 1.47.3)
101 | • VS Code at /Applications/Visual Studio Code.app/Contents
102 | • Flutter extension version 3.12.2
103 |
104 | [✓] Connected device (1 available)
105 | • sdk gphone x86 arm (mobile) • emulator-5554 • android-x86 • Android 11 (API 30) (emulator)
106 |
107 | • No issues found!
108 | ```
109 |
110 | # 意见反馈
111 | 如果大家有好的意见或者有好的设计图的话可以群内找我。
112 |
113 | Flutter交流QQ群:[874592746](https://jq.qq.com/?_wv=1027&k=5coTYqE)
114 |
115 | Flutter交流微信群:
116 |
117 |
118 |
119 | [上图无法显示点我](http://www.flutterj.com/left_group.png)
120 |
121 |
122 | ### LICENSE
123 | ```
124 | fluttercandies/ncov_2019 is licensed under the
125 | Apache License 2.0
126 |
127 | A permissive license whose main conditions require preservation of copyright and license notices.
128 | Contributors provide an express grant of patent rights.
129 | Licensed works, modifications, and larger works may be distributed under different terms and without source code.
130 | ```
131 |
--------------------------------------------------------------------------------
/android/android.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/android/app/.DS_Store
--------------------------------------------------------------------------------
/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 | android {
28 | compileSdkVersion 28
29 |
30 | lintOptions {
31 | disable 'InvalidPackage'
32 | }
33 |
34 | defaultConfig {
35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
36 | applicationId "com.example.ncov_2019"
37 | minSdkVersion 16
38 | targetSdkVersion 28
39 | versionCode flutterVersionCode.toInteger()
40 | versionName flutterVersionName
41 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
42 | }
43 |
44 | signingConfigs {
45 | release {
46 | keyAlias "key.keystore"
47 | keyPassword "123456"
48 | storeFile file("key.keystore")
49 | storePassword "123456"
50 | }
51 | }
52 |
53 | buildTypes {
54 | release {
55 | minifyEnabled true
56 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
57 | signingConfig signingConfigs.release
58 | }
59 | debug {
60 | signingConfig signingConfigs.release
61 | }
62 | }
63 | }
64 |
65 | flutter {
66 | source '../..'
67 | }
68 |
69 | dependencies {
70 | testImplementation 'junit:junit:4.12'
71 | androidTestImplementation 'androidx.test:runner:1.1.1'
72 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
73 | }
74 |
--------------------------------------------------------------------------------
/android/app/key.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/android/app/key.keystore
--------------------------------------------------------------------------------
/android/app/release/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/android/app/release/.DS_Store
--------------------------------------------------------------------------------
/android/app/release/output.json:
--------------------------------------------------------------------------------
1 | [{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":10,"versionName":"0.0.10","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]
--------------------------------------------------------------------------------
/android/app/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/android/app/src/.DS_Store
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/main/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/android/app/src/main/.DS_Store
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
9 |
10 |
11 |
12 |
17 |
24 |
28 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/example/ncov_2019/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.ncov_2019;
2 |
3 | import android.os.Bundle;
4 | import io.flutter.app.FlutterActivity;
5 | import io.flutter.plugins.GeneratedPluginRegistrant;
6 |
7 | public class MainActivity extends FlutterActivity {
8 | @Override
9 | protected void onCreate(Bundle savedInstanceState) {
10 | super.onCreate(savedInstanceState);
11 | GeneratedPluginRegistrant.registerWith(this);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java:
--------------------------------------------------------------------------------
1 | package io.flutter.plugins;
2 |
3 | import io.flutter.plugin.common.PluginRegistry;
4 | import io.flutter.plugins.connectivity.ConnectivityPlugin;
5 | import io.flutter.plugins.deviceinfo.DeviceInfoPlugin;
6 | import com.example.nav_router.NavRouterPlugin;
7 | import com.crazecoder.openfile.OpenFilePlugin;
8 | import io.flutter.plugins.packageinfo.PackageInfoPlugin;
9 | import io.flutter.plugins.pathprovider.PathProviderPlugin;
10 | import io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin;
11 | import com.tekartik.sqflite.SqflitePlugin;
12 | import io.flutter.plugins.urllauncher.UrlLauncherPlugin;
13 | import io.flutter.plugins.webviewflutter.WebViewFlutterPlugin;
14 |
15 | /**
16 | * Generated file. Do not edit.
17 | */
18 | public final class GeneratedPluginRegistrant {
19 | public static void registerWith(PluginRegistry registry) {
20 | if (alreadyRegisteredWith(registry)) {
21 | return;
22 | }
23 | ConnectivityPlugin.registerWith(registry.registrarFor("io.flutter.plugins.connectivity.ConnectivityPlugin"));
24 | DeviceInfoPlugin.registerWith(registry.registrarFor("io.flutter.plugins.deviceinfo.DeviceInfoPlugin"));
25 | NavRouterPlugin.registerWith(registry.registrarFor("com.example.nav_router.NavRouterPlugin"));
26 | OpenFilePlugin.registerWith(registry.registrarFor("com.crazecoder.openfile.OpenFilePlugin"));
27 | PackageInfoPlugin.registerWith(registry.registrarFor("io.flutter.plugins.packageinfo.PackageInfoPlugin"));
28 | PathProviderPlugin.registerWith(registry.registrarFor("io.flutter.plugins.pathprovider.PathProviderPlugin"));
29 | SharedPreferencesPlugin.registerWith(registry.registrarFor("io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin"));
30 | SqflitePlugin.registerWith(registry.registrarFor("com.tekartik.sqflite.SqflitePlugin"));
31 | UrlLauncherPlugin.registerWith(registry.registrarFor("io.flutter.plugins.urllauncher.UrlLauncherPlugin"));
32 | WebViewFlutterPlugin.registerWith(registry.registrarFor("io.flutter.plugins.webviewflutter.WebViewFlutterPlugin"));
33 | }
34 |
35 | private static boolean alreadyRegisteredWith(PluginRegistry registry) {
36 | final String key = GeneratedPluginRegistrant.class.getCanonicalName();
37 | if (registry.hasPlugin(key)) {
38 | return true;
39 | }
40 | registry.registrarFor(key);
41 | return false;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/android/app/src/main/res/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/android/app/src/main/res/.DS_Store
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/android/app/src/main/res/mipmap-hdpi/.DS_Store
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/android/app/src/main/res/mipmap-mdpi/.DS_Store
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/android/app/src/main/res/mipmap-xhdpi/.DS_Store
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/android/app/src/main/res/mipmap-xxhdpi/.DS_Store
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/android/app/src/main/res/mipmap-xxxhdpi/.DS_Store
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/android/app/src/main/res/xml/network_security_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/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 | }
10 | }
11 |
12 | allprojects {
13 | repositories {
14 | google()
15 | jcenter()
16 | }
17 | }
18 |
19 | rootProject.buildDir = '../build'
20 | subprojects {
21 | project.buildDir = "${rootProject.buildDir}/${project.name}"
22 | }
23 | subprojects {
24 | project.evaluationDependsOn(':app')
25 | }
26 |
27 | subprojects {
28 | project.configurations.all {
29 | resolutionStrategy.eachDependency { details ->
30 | if (details.requested.group == 'androidx.lifecycle' &&
31 | !details.requested.name.contains('androidx')) {
32 | details.useVersion "2.0.0"
33 | }
34 | if (details.requested.group == 'androidx.slidingpanelayout' &&
35 | !details.requested.name.contains('androidx')) {
36 | details.useVersion "1.0.0"
37 | }
38 | if (details.requested.group == 'androidx.legacy' &&
39 | !details.requested.name.contains('androidx')) {
40 | details.useVersion "1.0.0"
41 | }
42 | if (details.requested.group == 'androidx.fragment' &&
43 | !details.requested.name.contains('androidx')) {
44 | details.useVersion "1.0.0"
45 | }
46 | if (details.requested.group == 'androidx.annotation' &&
47 | !details.requested.name.contains('androidx')) {
48 | details.useVersion "1.0.0"
49 | }
50 | }
51 | }
52 | }
53 |
54 | task clean(type: Delete) {
55 | delete rootProject.buildDir
56 | }
57 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.enableR8=true
3 | android.useAndroidX=true
4 | android.enableJetifier=true
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
7 |
--------------------------------------------------------------------------------
/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/android/ncov_2019_android.iml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/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/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/.DS_Store
--------------------------------------------------------------------------------
/assets/git/download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/git/download.png
--------------------------------------------------------------------------------
/assets/git/home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/git/home.png
--------------------------------------------------------------------------------
/assets/git/left_group.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/git/left_group.png
--------------------------------------------------------------------------------
/assets/git/lore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/git/lore.png
--------------------------------------------------------------------------------
/assets/git/protect1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/git/protect1.png
--------------------------------------------------------------------------------
/assets/git/protect2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/git/protect2.png
--------------------------------------------------------------------------------
/assets/git/protect3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/git/protect3.png
--------------------------------------------------------------------------------
/assets/git/rumor1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/git/rumor1.png
--------------------------------------------------------------------------------
/assets/git/rumor2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/git/rumor2.png
--------------------------------------------------------------------------------
/assets/git/rumor3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/git/rumor3.png
--------------------------------------------------------------------------------
/assets/images/a.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/images/a.jpg
--------------------------------------------------------------------------------
/assets/images/bottom_home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/images/bottom_home.png
--------------------------------------------------------------------------------
/assets/images/bottom_lore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/images/bottom_lore.png
--------------------------------------------------------------------------------
/assets/images/bottom_protect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/images/bottom_protect.png
--------------------------------------------------------------------------------
/assets/images/bottom_rumor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/images/bottom_rumor.png
--------------------------------------------------------------------------------
/assets/images/entries_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/images/entries_1.png
--------------------------------------------------------------------------------
/assets/images/entries_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/images/entries_2.png
--------------------------------------------------------------------------------
/assets/images/entries_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/images/entries_3.png
--------------------------------------------------------------------------------
/assets/images/entries_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/images/entries_4.png
--------------------------------------------------------------------------------
/assets/images/entries_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/assets/images/entries_5.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/Flutter.framework/Flutter:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/ios/Flutter/Flutter.framework/Flutter
--------------------------------------------------------------------------------
/ios/Flutter/Flutter.framework/Headers/Flutter.h:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Flutter Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #ifndef FLUTTER_FLUTTER_H_
6 | #define FLUTTER_FLUTTER_H_
7 |
8 | /**
9 | BREAKING CHANGES:
10 |
11 | December 17, 2018:
12 | - Changed designated initializer on FlutterEngine
13 |
14 | October 5, 2018:
15 | - Removed FlutterNavigationController.h/.mm
16 | - Changed return signature of `FlutterDartHeadlessCodeRunner.run*` from void
17 | to bool
18 | - Removed HeadlessPlatformViewIOS
19 | - Marked FlutterDartHeadlessCodeRunner deprecated
20 |
21 | August 31, 2018: Marked -[FlutterDartProject
22 | initFromDefaultSourceForConfiguration] and FlutterStandardBigInteger as
23 | unavailable.
24 |
25 | July 26, 2018: Marked -[FlutterDartProject
26 | initFromDefaultSourceForConfiguration] deprecated.
27 |
28 | February 28, 2018: Removed "initWithFLXArchive" and
29 | "initWithFLXArchiveWithScriptSnapshot".
30 |
31 | January 15, 2018: Marked "initWithFLXArchive" and
32 | "initWithFLXArchiveWithScriptSnapshot" as unavailable following the
33 | deprecation from December 11, 2017. Scheduled to be removed on February
34 | 19, 2018.
35 |
36 | January 09, 2018: Deprecated "FlutterStandardBigInteger" and its use in
37 | "FlutterStandardMessageCodec" and "FlutterStandardMethodCodec". Scheduled to
38 | be marked as unavailable once the deprecation has been available on the
39 | flutter/flutter alpha branch for four weeks. "FlutterStandardBigInteger" was
40 | needed because the Dart 1.0 int type had no size limit. With Dart 2.0, the
41 | int type is a fixed-size, 64-bit signed integer. If you need to communicate
42 | larger integers, use NSString encoding instead.
43 |
44 | December 11, 2017: Deprecated "initWithFLXArchive" and
45 | "initWithFLXArchiveWithScriptSnapshot" and scheculed the same to be marked as
46 | unavailable on January 15, 2018. Instead, "initWithFlutterAssets" and
47 | "initWithFlutterAssetsWithScriptSnapshot" should be used. The reason for this
48 | change is that the FLX archive will be deprecated and replaced with a flutter
49 | assets directory containing the same files as the FLX did.
50 |
51 | November 29, 2017: Added a BREAKING CHANGES section.
52 | */
53 |
54 | #include "FlutterAppDelegate.h"
55 | #include "FlutterBinaryMessenger.h"
56 | #include "FlutterCallbackCache.h"
57 | #include "FlutterChannels.h"
58 | #include "FlutterCodecs.h"
59 | #include "FlutterDartProject.h"
60 | #include "FlutterEngine.h"
61 | #include "FlutterHeadlessDartRunner.h"
62 | #include "FlutterMacros.h"
63 | #include "FlutterPlatformViews.h"
64 | #include "FlutterPlugin.h"
65 | #include "FlutterPluginAppLifeCycleDelegate.h"
66 | #include "FlutterTexture.h"
67 | #include "FlutterViewController.h"
68 |
69 | #endif // FLUTTER_FLUTTER_H_
70 |
--------------------------------------------------------------------------------
/ios/Flutter/Flutter.framework/Headers/FlutterAppDelegate.h:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Flutter Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #ifndef FLUTTER_FLUTTERAPPDELEGATE_H_
6 | #define FLUTTER_FLUTTERAPPDELEGATE_H_
7 |
8 | #import
9 |
10 | #include "FlutterMacros.h"
11 | #include "FlutterPlugin.h"
12 |
13 | /**
14 | * `UIApplicationDelegate` subclass for simple apps that want default behavior.
15 | *
16 | * This class implements the following behaviors:
17 | * * Status bar touches are forwarded to the key window's root view
18 | * `FlutterViewController`, in order to trigger scroll to top.
19 | * * Keeps the Flutter connection open in debug mode when the phone screen
20 | * locks.
21 | *
22 | * App delegates for Flutter applications are *not* required to inherit from
23 | * this class. Developers of custom app delegate classes should copy and paste
24 | * code as necessary from FlutterAppDelegate.mm.
25 | */
26 | FLUTTER_EXPORT
27 | @interface FlutterAppDelegate
28 | : UIResponder
29 |
30 | @property(strong, nonatomic) UIWindow* window;
31 |
32 | /**
33 | * Handle StatusBar touches.
34 | *
35 | * Call this from your AppDelegate's `touchesBegan:withEvent:` to have Flutter respond to StatusBar
36 | * touches. For example, to enable scroll-to-top behavior. FlutterAppDelegate already calls it so
37 | * you only need to manually call it if you aren't using a FlutterAppDelegate.
38 | */
39 | + (void)handleStatusBarTouches:(NSSet*)touches withEvent:(UIEvent*)event;
40 |
41 | @end
42 |
43 | #endif // FLUTTER_FLUTTERDARTPROJECT_H_
44 |
--------------------------------------------------------------------------------
/ios/Flutter/Flutter.framework/Headers/FlutterBinaryMessenger.h:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Flutter Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #ifndef FLUTTER_FLUTTERBINARYMESSENGER_H_
6 | #define FLUTTER_FLUTTERBINARYMESSENGER_H_
7 |
8 | #import
9 |
10 | #include "FlutterMacros.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 | /**
14 | * A message reply callback.
15 | *
16 | * Used for submitting a binary reply back to a Flutter message sender. Also used
17 | * in for handling a binary message reply received from Flutter.
18 | *
19 | * @param reply The reply.
20 | */
21 | typedef void (^FlutterBinaryReply)(NSData* _Nullable reply);
22 |
23 | /**
24 | * A strategy for handling incoming binary messages from Flutter and to send
25 | * asynchronous replies back to Flutter.
26 | *
27 | * @param message The message.
28 | * @param reply A callback for submitting an asynchronous reply to the sender.
29 | */
30 | typedef void (^FlutterBinaryMessageHandler)(NSData* _Nullable message, FlutterBinaryReply reply);
31 |
32 | /**
33 | * A facility for communicating with the Flutter side using asynchronous message
34 | * passing with binary messages.
35 | *
36 | * Implementated by:
37 | * - `FlutterBasicMessageChannel`, which supports communication using structured
38 | * messages.
39 | * - `FlutterMethodChannel`, which supports communication using asynchronous
40 | * method calls.
41 | * - `FlutterEventChannel`, which supports commuication using event streams.
42 | */
43 | FLUTTER_EXPORT
44 | @protocol FlutterBinaryMessenger
45 | /**
46 | * Sends a binary message to the Flutter side on the specified channel, expecting
47 | * no reply.
48 | *
49 | * @param channel The channel name.
50 | * @param message The message.
51 | */
52 | - (void)sendOnChannel:(NSString*)channel message:(NSData* _Nullable)message;
53 |
54 | /**
55 | * Sends a binary message to the Flutter side on the specified channel, expecting
56 | * an asynchronous reply.
57 | *
58 | * @param channel The channel name.
59 | * @param message The message.
60 | * @param callback A callback for receiving a reply.
61 | */
62 | - (void)sendOnChannel:(NSString*)channel
63 | message:(NSData* _Nullable)message
64 | binaryReply:(FlutterBinaryReply _Nullable)callback;
65 |
66 | /**
67 | * Registers a message handler for incoming binary messages from the Flutter side
68 | * on the specified channel.
69 | *
70 | * Replaces any existing handler. Use a `nil` handler for unregistering the
71 | * existing handler.
72 | *
73 | * @param channel The channel name.
74 | * @param handler The message handler.
75 | */
76 | - (void)setMessageHandlerOnChannel:(NSString*)channel
77 | binaryMessageHandler:(FlutterBinaryMessageHandler _Nullable)handler;
78 | @end
79 | NS_ASSUME_NONNULL_END
80 | #endif // FLUTTER_FLUTTERBINARYMESSENGER_H_
81 |
--------------------------------------------------------------------------------
/ios/Flutter/Flutter.framework/Headers/FlutterCallbackCache.h:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Flutter Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #ifndef FLUTTER_FLUTTERCALLBACKCACHE_H_
6 | #define FLUTTER_FLUTTERCALLBACKCACHE_H_
7 |
8 | #import
9 |
10 | #include "FlutterMacros.h"
11 |
12 | /**
13 | * An object containing the result of `FlutterCallbackCache`'s `lookupCallbackInformation`
14 | * method.
15 | */
16 | FLUTTER_EXPORT
17 | @interface FlutterCallbackInformation : NSObject
18 | /**
19 | * The name of the callback.
20 | */
21 | @property(retain) NSString* callbackName;
22 | /**
23 | * The class name of the callback.
24 | */
25 | @property(retain) NSString* callbackClassName;
26 | /**
27 | * The library path of the callback.
28 | */
29 | @property(retain) NSString* callbackLibraryPath;
30 | @end
31 |
32 | /**
33 | * The cache containing callback information for spawning a
34 | * `FlutterHeadlessDartRunner`.
35 | */
36 | FLUTTER_EXPORT
37 | @interface FlutterCallbackCache : NSObject
38 | /**
39 | * Returns the callback information for the given callback handle.
40 | * This callback information can be used when spawning a
41 | * `FlutterHeadlessDartRunner`.
42 | *
43 | * @param handle The handle for a callback, provided by the
44 | * Dart method `PluginUtilities.getCallbackHandle`.
45 | * @return A `FlutterCallbackInformation` object which contains the name of the
46 | * callback, the name of the class in which the callback is defined, and the
47 | * path of the library which contains the callback. If the provided handle is
48 | * invalid, nil is returned.
49 | */
50 | + (FlutterCallbackInformation*)lookupCallbackInformation:(int64_t)handle;
51 |
52 | @end
53 |
54 | #endif // FLUTTER_FLUTTERCALLBACKCACHE_H_
55 |
--------------------------------------------------------------------------------
/ios/Flutter/Flutter.framework/Headers/FlutterDartProject.h:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Flutter Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #ifndef FLUTTER_FLUTTERDARTPROJECT_H_
6 | #define FLUTTER_FLUTTERDARTPROJECT_H_
7 |
8 | #import
9 |
10 | #include "FlutterMacros.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | /**
15 | * A set of Flutter and Dart assets used by a `FlutterEngine` to initialize execution.
16 | */
17 | FLUTTER_EXPORT
18 | @interface FlutterDartProject : NSObject
19 |
20 | /**
21 | * Initializes a Flutter Dart project from a bundle.
22 | */
23 | - (instancetype)initWithPrecompiledDartBundle:(nullable NSBundle*)bundle NS_DESIGNATED_INITIALIZER;
24 |
25 | /**
26 | * Unavailable - use `init` instead.
27 | */
28 | - (instancetype)initFromDefaultSourceForConfiguration FLUTTER_UNAVAILABLE("Use -init instead.");
29 |
30 | /**
31 | * Returns the file name for the given asset. If the bundle with the identifier
32 | * "io.flutter.flutter.app" exists, it will try use that bundle; otherwise, it
33 | * will use the main bundle. To specify a different bundle, use
34 | * `-lookupKeyForAsset:asset:fromBundle`.
35 | *
36 | * @param asset The name of the asset. The name can be hierarchical.
37 | * @return the file name to be used for lookup in the main bundle.
38 | */
39 | + (NSString*)lookupKeyForAsset:(NSString*)asset;
40 |
41 | /**
42 | * Returns the file name for the given asset.
43 | * The returned file name can be used to access the asset in the supplied bundle.
44 | *
45 | * @param asset The name of the asset. The name can be hierarchical.
46 | * @param bundle The `NSBundle` to use for looking up the asset.
47 | * @return the file name to be used for lookup in the main bundle.
48 | */
49 | + (NSString*)lookupKeyForAsset:(NSString*)asset fromBundle:(nullable NSBundle*)bundle;
50 |
51 | /**
52 | * Returns the file name for the given asset which originates from the specified package.
53 | * The returned file name can be used to access the asset in the application's main bundle.
54 | *
55 | * @param asset The name of the asset. The name can be hierarchical.
56 | * @param package The name of the package from which the asset originates.
57 | * @return the file name to be used for lookup in the main bundle.
58 | */
59 | + (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package;
60 |
61 | /**
62 | * Returns the file name for the given asset which originates from the specified package.
63 | * The returned file name can be used to access the asset in the specified bundle.
64 | *
65 | * @param asset The name of the asset. The name can be hierarchical.
66 | * @param package The name of the package from which the asset originates.
67 | * @param bundle The bundle to use when doing the lookup.
68 | * @return the file name to be used for lookup in the main bundle.
69 | */
70 | + (NSString*)lookupKeyForAsset:(NSString*)asset
71 | fromPackage:(NSString*)package
72 | fromBundle:(nullable NSBundle*)bundle;
73 |
74 | /**
75 | * Returns the default identifier for the bundle where we expect to find the Flutter Dart
76 | * application.
77 | */
78 | + (NSString*)defaultBundleIdentifier;
79 |
80 | @end
81 |
82 | NS_ASSUME_NONNULL_END
83 |
84 | #endif // FLUTTER_FLUTTERDARTPROJECT_H_
85 |
--------------------------------------------------------------------------------
/ios/Flutter/Flutter.framework/Headers/FlutterHeadlessDartRunner.h:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Flutter Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #ifndef FLUTTER_FLUTTERHEADLESSDARTRUNNER_H_
6 | #define FLUTTER_FLUTTERHEADLESSDARTRUNNER_H_
7 |
8 | #import
9 |
10 | #include "FlutterBinaryMessenger.h"
11 | #include "FlutterDartProject.h"
12 | #include "FlutterEngine.h"
13 | #include "FlutterMacros.h"
14 |
15 | /**
16 | * A callback for when FlutterHeadlessDartRunner has attempted to start a Dart
17 | * Isolate in the background.
18 | *
19 | * @param success YES if the Isolate was started and run successfully, NO
20 | * otherwise.
21 | */
22 | typedef void (^FlutterHeadlessDartRunnerCallback)(BOOL success);
23 |
24 | /**
25 | * The FlutterHeadlessDartRunner runs Flutter Dart code with a null rasterizer,
26 | * and no native drawing surface. It is appropriate for use in running Dart
27 | * code e.g. in the background from a plugin.
28 | *
29 | * Most callers should prefer using `FlutterEngine` directly; this interface exists
30 | * for legacy support.
31 | */
32 | FLUTTER_EXPORT
33 | FLUTTER_DEPRECATED("FlutterEngine should be used rather than FlutterHeadlessDartRunner")
34 | @interface FlutterHeadlessDartRunner : FlutterEngine
35 |
36 | /**
37 | * Iniitalize this FlutterHeadlessDartRunner with a `FlutterDartProject`.
38 | *
39 | * If the FlutterDartProject is not specified, the FlutterHeadlessDartRunner will attempt to locate
40 | * the project in a default location.
41 | *
42 | * A newly initialized engine will not run the `FlutterDartProject` until either
43 | * `-runWithEntrypoint:` or `-runWithEntrypoint:libraryURI` is called.
44 | *
45 | * @param labelPrefix The label prefix used to identify threads for this instance. Should
46 | * be unique across FlutterEngine instances
47 | * @param projectOrNil The `FlutterDartProject` to run.
48 | */
49 | - (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)projectOrNil;
50 |
51 | /**
52 | * Iniitalize this FlutterHeadlessDartRunner with a `FlutterDartProject`.
53 | *
54 | * If the FlutterDartProject is not specified, the FlutterHeadlessDartRunner will attempt to locate
55 | * the project in a default location.
56 | *
57 | * A newly initialized engine will not run the `FlutterDartProject` until either
58 | * `-runWithEntrypoint:` or `-runWithEntrypoint:libraryURI` is called.
59 | *
60 | * @param labelPrefix The label prefix used to identify threads for this instance. Should
61 | * be unique across FlutterEngine instances
62 | * @param projectOrNil The `FlutterDartProject` to run.
63 | * @param allowHeadlessExecution Must be set to `YES`.
64 | */
65 | - (instancetype)initWithName:(NSString*)labelPrefix
66 | project:(FlutterDartProject*)projectOrNil
67 | allowHeadlessExecution:(BOOL)allowHeadlessExecution NS_DESIGNATED_INITIALIZER;
68 |
69 | /**
70 | * Not recommended for use - will initialize with a default label ("io.flutter.headless")
71 | * and the default FlutterDartProject.
72 | */
73 | - (instancetype)init;
74 |
75 | @end
76 |
77 | #endif // FLUTTER_FLUTTERHEADLESSDARTRUNNER_H_
78 |
--------------------------------------------------------------------------------
/ios/Flutter/Flutter.framework/Headers/FlutterMacros.h:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Flutter Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #ifndef FLUTTER_FLUTTERMACROS_H_
6 | #define FLUTTER_FLUTTERMACROS_H_
7 |
8 | #if defined(FLUTTER_FRAMEWORK)
9 |
10 | #define FLUTTER_EXPORT __attribute__((visibility("default")))
11 |
12 | #else // defined(FLUTTER_SDK)
13 |
14 | #define FLUTTER_EXPORT
15 |
16 | #endif // defined(FLUTTER_SDK)
17 |
18 | #ifndef NS_ASSUME_NONNULL_BEGIN
19 | #define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")
20 | #define NS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
21 | #endif // defined(NS_ASSUME_NONNULL_BEGIN)
22 |
23 | /**
24 | * Indicates that the API has been deprecated for the specified reason. Code
25 | * that uses the deprecated API will continue to work as before. However, the
26 | * API will soon become unavailable and users are encouraged to immediately take
27 | * the appropriate action mentioned in the deprecation message and the BREAKING
28 | * CHANGES section present in the Flutter.h umbrella header.
29 | */
30 | #define FLUTTER_DEPRECATED(msg) __attribute__((__deprecated__(msg)))
31 |
32 | /**
33 | * Indicates that the previously deprecated API is now unavailable. Code that
34 | * uses the API will not work and the declaration of the API is only a stub
35 | * meant to display the given message detailing the actions for the user to take
36 | * immediately.
37 | */
38 | #define FLUTTER_UNAVAILABLE(msg) __attribute__((__unavailable__(msg)))
39 |
40 | #if __has_feature(objc_arc)
41 | #define FLUTTER_ASSERT_ARC
42 | #define FLUTTER_ASSERT_NOT_ARC #error ARC must be disabled!
43 | #else
44 | #define FLUTTER_ASSERT_ARC #error ARC must be enabled!
45 | #define FLUTTER_ASSERT_NOT_ARC
46 | #endif
47 |
48 | #endif // FLUTTER_FLUTTERMACROS_H_
49 |
--------------------------------------------------------------------------------
/ios/Flutter/Flutter.framework/Headers/FlutterPlatformViews.h:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Flutter Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #ifndef FLUTTER_FLUTTERPLATFORMVIEWS_H_
6 | #define FLUTTER_FLUTTERPLATFORMVIEWS_H_
7 |
8 | #import
9 |
10 | #import "FlutterCodecs.h"
11 | #import "FlutterMacros.h"
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 | /**
16 | * Wraps a `UIView` for embedding in the Flutter hierarchy
17 | */
18 | @protocol FlutterPlatformView
19 | /**
20 | * Returns a reference to the `UIView` that is wrapped by this `FlutterPlatformView`.
21 | */
22 | - (UIView*)view;
23 | @end
24 |
25 | FLUTTER_EXPORT
26 | @protocol FlutterPlatformViewFactory
27 | /**
28 | * Create a `FlutterPlatformView`.
29 | *
30 | * Implemented by iOS code that expose a `UIView` for embedding in a Flutter app.
31 | *
32 | * The implementation of this method should create a new `UIView` and return it.
33 | *
34 | * @param frame The rectangle for the newly created `UIView` measued in points.
35 | * @param viewId A unique identifier for this `UIView`.
36 | * @param args Parameters for creating the `UIView` sent from the Dart side of the Flutter app.
37 | * If `createArgsCodec` is not implemented, or if no creation arguments were sent from the Dart
38 | * code, this will be null. Otherwise this will be the value sent from the Dart code as decoded by
39 | * `createArgsCodec`.
40 | */
41 | - (NSObject*)createWithFrame:(CGRect)frame
42 | viewIdentifier:(int64_t)viewId
43 | arguments:(id _Nullable)args;
44 |
45 | /**
46 | * Returns the `FlutterMessageCodec` for decoding the args parameter of `createWithFrame`.
47 | *
48 | * Only needs to be implemented if `createWithFrame` needs an arguments parameter.
49 | */
50 | @optional
51 | - (NSObject*)createArgsCodec;
52 | @end
53 |
54 | NS_ASSUME_NONNULL_END
55 |
56 | #endif // FLUTTER_FLUTTERPLATFORMVIEWS_H_
57 |
--------------------------------------------------------------------------------
/ios/Flutter/Flutter.framework/Headers/FlutterPluginAppLifeCycleDelegate.h:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Flutter Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #ifndef FLUTTER_FLUTTERPLUGINAPPLIFECYCLEDELEGATE_H_
6 | #define FLUTTER_FLUTTERPLUGINAPPLIFECYCLEDELEGATE_H_
7 |
8 | #include "FlutterPlugin.h"
9 |
10 | NS_ASSUME_NONNULL_BEGIN
11 |
12 | /**
13 | * Propagates `UIAppDelegate` callbacks to registered plugins.
14 | */
15 | FLUTTER_EXPORT
16 | @interface FlutterPluginAppLifeCycleDelegate : NSObject
17 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
18 |
19 | #endif
20 |
21 | /**
22 | * Registers `delegate` to receive life cycle callbacks via this FlutterPluginAppLifecycleDelegate
23 | * as long as it is alive.
24 | *
25 | * `delegate` will only referenced weakly.
26 | */
27 | - (void)addDelegate:(NSObject*)delegate;
28 |
29 | /**
30 | * Calls all plugins registered for `UIApplicationDelegate` callbacks.
31 | *
32 | * @return `NO` if any plugin vetoes application launch.
33 | */
34 | - (BOOL)application:(UIApplication*)application
35 | didFinishLaunchingWithOptions:(NSDictionary*)launchOptions;
36 |
37 | /**
38 | * Calls all plugins registered for `UIApplicationDelegate` callbacks.
39 | *
40 | * @return `NO` if any plugin vetoes application launch.
41 | */
42 | - (BOOL)application:(UIApplication*)application
43 | willFinishLaunchingWithOptions:(NSDictionary*)launchOptions;
44 |
45 | /**
46 | * Called if this plugin has been registered for `UIApplicationDelegate` callbacks.
47 | */
48 | - (void)application:(UIApplication*)application
49 | didRegisterUserNotificationSettings:(UIUserNotificationSettings*)notificationSettings
50 | API_DEPRECATED(
51 | "See -[UIApplicationDelegate application:didRegisterUserNotificationSettings:] deprecation",
52 | ios(8.0, 10.0));
53 |
54 | /**
55 | * Calls all plugins registered for `UIApplicationDelegate` callbacks.
56 | */
57 | - (void)application:(UIApplication*)application
58 | didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken;
59 |
60 | /**
61 | * Calls all plugins registered for `UIApplicationDelegate` callbacks.
62 | */
63 | - (void)application:(UIApplication*)application
64 | didReceiveRemoteNotification:(NSDictionary*)userInfo
65 | fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler;
66 |
67 | /**
68 | * Calls all plugins registered for `UIApplicationDelegate` callbacks.
69 | */
70 | - (void)application:(UIApplication*)application
71 | didReceiveLocalNotification:(UILocalNotification*)notification
72 | API_DEPRECATED(
73 | "See -[UIApplicationDelegate application:didReceiveLocalNotification:] deprecation",
74 | ios(4.0, 10.0));
75 |
76 | /**
77 | * Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until
78 | * some plugin handles the request.
79 | *
80 | * @return `YES` if any plugin handles the request.
81 | */
82 | - (BOOL)application:(UIApplication*)application
83 | openURL:(NSURL*)url
84 | options:(NSDictionary*)options;
85 |
86 | /**
87 | * Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until
88 | * some plugin handles the request.
89 | *
90 | * @return `YES` if any plugin handles the request.
91 | */
92 | - (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url;
93 |
94 | /**
95 | * Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until
96 | * some plugin handles the request.
97 | *
98 | * @return `YES` if any plugin handles the request.
99 | */
100 | - (BOOL)application:(UIApplication*)application
101 | openURL:(NSURL*)url
102 | sourceApplication:(NSString*)sourceApplication
103 | annotation:(id)annotation;
104 |
105 | /**
106 | * Calls all plugins registered for `UIApplicationDelegate` callbacks.
107 | */
108 | - (void)application:(UIApplication*)application
109 | performActionForShortcutItem:(UIApplicationShortcutItem*)shortcutItem
110 | completionHandler:(void (^)(BOOL succeeded))completionHandler
111 | API_AVAILABLE(ios(9.0));
112 |
113 | /**
114 | * Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until
115 | * some plugin handles the request.
116 | *
117 | * @return `YES` if any plugin handles the request.
118 | */
119 | - (BOOL)application:(UIApplication*)application
120 | handleEventsForBackgroundURLSession:(nonnull NSString*)identifier
121 | completionHandler:(nonnull void (^)(void))completionHandler;
122 |
123 | /**
124 | * Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until
125 | * some plugin handles the request.
126 | *
127 | * @returns `YES` if any plugin handles the request.
128 | */
129 | - (BOOL)application:(UIApplication*)application
130 | performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler;
131 |
132 | /**
133 | * Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until
134 | * some plugin handles the request.
135 | *
136 | * @return `YES` if any plugin handles the request.
137 | */
138 | - (BOOL)application:(UIApplication*)application
139 | continueUserActivity:(NSUserActivity*)userActivity
140 | restorationHandler:(void (^)(NSArray*))restorationHandler;
141 | @end
142 |
143 | NS_ASSUME_NONNULL_END
144 |
145 | #endif // FLUTTER_FLUTTERPLUGINAPPLIFECYCLEDELEGATE_H_
146 |
--------------------------------------------------------------------------------
/ios/Flutter/Flutter.framework/Headers/FlutterTexture.h:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Flutter Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #ifndef FLUTTER_FLUTTERTEXTURE_H_
6 | #define FLUTTER_FLUTTERTEXTURE_H_
7 |
8 | #import
9 | #import
10 |
11 | #include "FlutterMacros.h"
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 | FLUTTER_EXPORT
16 | @protocol FlutterTexture
17 | - (CVPixelBufferRef _Nullable)copyPixelBuffer;
18 |
19 | /**
20 | * Called when the texture is unregistered.
21 | *
22 | * Called on the GPU thread.
23 | */
24 | @optional
25 | - (void)onTextureUnregistered:(NSObject*)texture;
26 | @end
27 |
28 | FLUTTER_EXPORT
29 | @protocol FlutterTextureRegistry
30 | - (int64_t)registerTexture:(NSObject*)texture;
31 | - (void)textureFrameAvailable:(int64_t)textureId;
32 | - (void)unregisterTexture:(int64_t)textureId;
33 | @end
34 |
35 | NS_ASSUME_NONNULL_END
36 |
37 | #endif // FLUTTER_FLUTTERTEXTURE_H_
38 |
--------------------------------------------------------------------------------
/ios/Flutter/Flutter.framework/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | Flutter
9 | CFBundleIdentifier
10 | io.flutter.flutter
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | Flutter
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 8.0
25 | FlutterEngine
26 | b6b54fd60631a3828c2e2c9b079b5d1d2d8c8c37
27 | ClangVersion
28 | Apple LLVM version 10.0.1 (clang-1001.0.46.3)
29 |
30 |
31 |
--------------------------------------------------------------------------------
/ios/Flutter/Flutter.framework/Modules/module.modulemap:
--------------------------------------------------------------------------------
1 | framework module Flutter {
2 | umbrella header "Flutter.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/ios/Flutter/Flutter.framework/icudtl.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/ios/Flutter/Flutter.framework/icudtl.dat
--------------------------------------------------------------------------------
/ios/Flutter/Flutter.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # NOTE: This podspec is NOT to be published. It is only used as a local source!
3 | #
4 |
5 | Pod::Spec.new do |s|
6 | s.name = 'Flutter'
7 | s.version = '1.0.0'
8 | s.summary = 'High-performance, high-fidelity mobile apps.'
9 | s.description = <<-DESC
10 | Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS.
11 | DESC
12 | s.homepage = 'https://flutter.io'
13 | s.license = { :type => 'MIT' }
14 | s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
15 | s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s }
16 | s.ios.deployment_target = '8.0'
17 | s.vendored_frameworks = 'Flutter.framework'
18 | end
19 |
--------------------------------------------------------------------------------
/ios/Flutter/Generated.xcconfig:
--------------------------------------------------------------------------------
1 | // This is a generated file; do not edit or check into version control.
2 | FLUTTER_ROOT=/Users/q1/flutterNew/flutter
3 | FLUTTER_APPLICATION_PATH=/Users/q1/Documents/gitPro/ahyangnb/ncov_2019
4 | FLUTTER_TARGET=lib/main.dart
5 | FLUTTER_BUILD_DIR=build
6 | SYMROOT=${SOURCE_ROOT}/../build/ios
7 | OTHER_LDFLAGS=$(inherited) -framework Flutter
8 | FLUTTER_FRAMEWORK_DIR=/Users/q1/flutterNew/flutter/bin/cache/artifacts/engine/ios
9 | FLUTTER_BUILD_NAME=0.0.10
10 | FLUTTER_BUILD_NUMBER=10
11 | DART_OBFUSCATION=false
12 | TRACK_WIDGET_CREATION=false
13 | TREE_SHAKE_ICONS=false
14 | PACKAGE_CONFIG=.packages
15 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Flutter/flutter_export_environment.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # This is a generated file; do not edit or check into version control.
3 | export "FLUTTER_ROOT=/Users/q1/flutterNew/flutter"
4 | export "FLUTTER_APPLICATION_PATH=/Users/q1/Documents/gitPro/ahyangnb/ncov_2019"
5 | export "FLUTTER_TARGET=lib/main.dart"
6 | export "FLUTTER_BUILD_DIR=build"
7 | export "SYMROOT=${SOURCE_ROOT}/../build/ios"
8 | export "OTHER_LDFLAGS=$(inherited) -framework Flutter"
9 | export "FLUTTER_FRAMEWORK_DIR=/Users/q1/flutterNew/flutter/bin/cache/artifacts/engine/ios"
10 | export "FLUTTER_BUILD_NAME=0.0.10"
11 | export "FLUTTER_BUILD_NUMBER=10"
12 | export "DART_OBFUSCATION=false"
13 | export "TRACK_WIDGET_CREATION=false"
14 | export "TREE_SHAKE_ICONS=false"
15 | export "PACKAGE_CONFIG=.packages"
16 |
--------------------------------------------------------------------------------
/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 parse_KV_file(file, separator='=')
14 | file_abs_path = File.expand_path(file)
15 | if !File.exists? file_abs_path
16 | return [];
17 | end
18 | pods_ary = []
19 | skip_line_start_symbols = ["#", "/"]
20 | File.foreach(file_abs_path) { |line|
21 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
22 | plugin = line.split(pattern=separator)
23 | if plugin.length == 2
24 | podname = plugin[0].strip()
25 | path = plugin[1].strip()
26 | podpath = File.expand_path("#{path}", file_abs_path)
27 | pods_ary.push({:name => podname, :path => podpath});
28 | else
29 | puts "Invalid plugin specification: #{line}"
30 | end
31 | }
32 | return pods_ary
33 | end
34 |
35 | target 'Runner' do
36 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
37 | # referring to absolute paths on developers' machines.
38 | system('rm -rf .symlinks')
39 | system('mkdir -p .symlinks/plugins')
40 |
41 | # Flutter Pods
42 | generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig')
43 | if generated_xcode_build_settings.empty?
44 | puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first."
45 | end
46 | generated_xcode_build_settings.map { |p|
47 | if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
48 | symlink = File.join('.symlinks', 'flutter')
49 | File.symlink(File.dirname(p[:path]), symlink)
50 | pod 'Flutter', :path => File.join(symlink, File.basename(p[:path]))
51 | end
52 | }
53 |
54 | # Plugin Pods
55 | plugin_pods = parse_KV_file('../.flutter-plugins')
56 | plugin_pods.map { |p|
57 | symlink = File.join('.symlinks', 'plugins', p[:name])
58 | File.symlink(p[:path], symlink)
59 | pod p[:name], :path => File.join(symlink, 'ios')
60 | }
61 | end
62 |
63 | # Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
64 | install! 'cocoapods', :disable_input_output_paths => true
65 |
66 | post_install do |installer|
67 | installer.pods_project.targets.each do |target|
68 | target.build_configurations.each do |config|
69 | config.build_settings['ENABLE_BITCODE'] = 'NO'
70 | end
71 | end
72 | end
73 |
--------------------------------------------------------------------------------
/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - connectivity (0.0.1):
3 | - Flutter
4 | - Reachability
5 | - device_info (0.0.1):
6 | - Flutter
7 | - Flutter (1.0.0)
8 | - FMDB (2.7.5):
9 | - FMDB/standard (= 2.7.5)
10 | - FMDB/standard (2.7.5)
11 | - nav_router (0.0.1):
12 | - Flutter
13 | - open_file (0.0.1):
14 | - Flutter
15 | - package_info (0.0.1):
16 | - Flutter
17 | - path_provider (0.0.1):
18 | - Flutter
19 | - Reachability (3.2)
20 | - shared_preferences (0.0.1):
21 | - Flutter
22 | - sqflite (0.0.1):
23 | - Flutter
24 | - FMDB (~> 2.7.2)
25 | - url_launcher (0.0.1):
26 | - Flutter
27 | - webview_flutter (0.0.1):
28 | - Flutter
29 |
30 | DEPENDENCIES:
31 | - connectivity (from `.symlinks/plugins/connectivity/ios`)
32 | - device_info (from `.symlinks/plugins/device_info/ios`)
33 | - Flutter (from `.symlinks/flutter/ios`)
34 | - nav_router (from `.symlinks/plugins/nav_router/ios`)
35 | - open_file (from `.symlinks/plugins/open_file/ios`)
36 | - package_info (from `.symlinks/plugins/package_info/ios`)
37 | - path_provider (from `.symlinks/plugins/path_provider/ios`)
38 | - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
39 | - sqflite (from `.symlinks/plugins/sqflite/ios`)
40 | - url_launcher (from `.symlinks/plugins/url_launcher/ios`)
41 | - webview_flutter (from `.symlinks/plugins/webview_flutter/ios`)
42 |
43 | SPEC REPOS:
44 | trunk:
45 | - FMDB
46 | - Reachability
47 |
48 | EXTERNAL SOURCES:
49 | connectivity:
50 | :path: ".symlinks/plugins/connectivity/ios"
51 | device_info:
52 | :path: ".symlinks/plugins/device_info/ios"
53 | Flutter:
54 | :path: ".symlinks/flutter/ios"
55 | nav_router:
56 | :path: ".symlinks/plugins/nav_router/ios"
57 | open_file:
58 | :path: ".symlinks/plugins/open_file/ios"
59 | package_info:
60 | :path: ".symlinks/plugins/package_info/ios"
61 | path_provider:
62 | :path: ".symlinks/plugins/path_provider/ios"
63 | shared_preferences:
64 | :path: ".symlinks/plugins/shared_preferences/ios"
65 | sqflite:
66 | :path: ".symlinks/plugins/sqflite/ios"
67 | url_launcher:
68 | :path: ".symlinks/plugins/url_launcher/ios"
69 | webview_flutter:
70 | :path: ".symlinks/plugins/webview_flutter/ios"
71 |
72 | SPEC CHECKSUMS:
73 | connectivity: 6e94255659cc86dcbef1d452ad3e0491bb1b3e75
74 | device_info: 3ebad48f726348f69abd802f3334a8d1ed795fbd
75 | Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
76 | FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
77 | nav_router: a4bf0af66c082e6db0c3c895e6dfeba6f19777ff
78 | open_file: 02eb5cb6b21264bd3a696876f5afbfb7ca4f4b7d
79 | package_info: 78cabb3c322943c55d39676f4a5bfc748c01d055
80 | path_provider: fb74bd0465e96b594bb3b5088ee4a4e7bb1f2a9d
81 | Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
82 | shared_preferences: 1feebfa37bb57264736e16865e7ffae7fc99b523
83 | sqflite: 4001a31ff81d210346b500c55b17f4d6c7589dd0
84 | url_launcher: a1c0cc845906122c4784c542523d8cacbded5626
85 | webview_flutter: 1aa7604e6cdb451a9b7ed2c37d5454c0b440246b
86 |
87 | PODFILE CHECKSUM: 7fb83752f59ead6285236625b82473f90b1cb932
88 |
89 | COCOAPODS: 1.8.4
90 |
--------------------------------------------------------------------------------
/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 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/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" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.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" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/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/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/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/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/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/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/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/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/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/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/ncov_2019/ced6ba775426956e752ca6adbc41314014d14009/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/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/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Runner/GeneratedPluginRegistrant.h:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | #ifndef GeneratedPluginRegistrant_h
6 | #define GeneratedPluginRegistrant_h
7 |
8 | #import
9 |
10 | NS_ASSUME_NONNULL_BEGIN
11 |
12 | @interface GeneratedPluginRegistrant : NSObject
13 | + (void)registerWithRegistry:(NSObject*)registry;
14 | @end
15 |
16 | NS_ASSUME_NONNULL_END
17 | #endif /* GeneratedPluginRegistrant_h */
18 |
--------------------------------------------------------------------------------
/ios/Runner/GeneratedPluginRegistrant.m:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | #import "GeneratedPluginRegistrant.h"
6 |
7 | #if __has_include()
8 | #import
9 | #else
10 | @import connectivity;
11 | #endif
12 |
13 | #if __has_include()
14 | #import
15 | #else
16 | @import device_info;
17 | #endif
18 |
19 | #if __has_include()
20 | #import
21 | #else
22 | @import nav_router;
23 | #endif
24 |
25 | #if __has_include()
26 | #import
27 | #else
28 | @import open_file;
29 | #endif
30 |
31 | #if __has_include()
32 | #import
33 | #else
34 | @import package_info;
35 | #endif
36 |
37 | #if __has_include()
38 | #import
39 | #else
40 | @import path_provider;
41 | #endif
42 |
43 | #if __has_include()
44 | #import
45 | #else
46 | @import shared_preferences;
47 | #endif
48 |
49 | #if __has_include()
50 | #import
51 | #else
52 | @import sqflite;
53 | #endif
54 |
55 | #if __has_include()
56 | #import
57 | #else
58 | @import url_launcher;
59 | #endif
60 |
61 | #if __has_include()
62 | #import
63 | #else
64 | @import webview_flutter;
65 | #endif
66 |
67 | @implementation GeneratedPluginRegistrant
68 |
69 | + (void)registerWithRegistry:(NSObject*)registry {
70 | [FLTConnectivityPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTConnectivityPlugin"]];
71 | [FLTDeviceInfoPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTDeviceInfoPlugin"]];
72 | [NavRouterPlugin registerWithRegistrar:[registry registrarForPlugin:@"NavRouterPlugin"]];
73 | [OpenFilePlugin registerWithRegistrar:[registry registrarForPlugin:@"OpenFilePlugin"]];
74 | [FLTPackageInfoPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTPackageInfoPlugin"]];
75 | [FLTPathProviderPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTPathProviderPlugin"]];
76 | [FLTSharedPreferencesPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTSharedPreferencesPlugin"]];
77 | [SqflitePlugin registerWithRegistrar:[registry registrarForPlugin:@"SqflitePlugin"]];
78 | [FLTUrlLauncherPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTUrlLauncherPlugin"]];
79 | [FLTWebViewFlutterPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTWebViewFlutterPlugin"]];
80 | }
81 |
82 | @end
83 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ncov_2019
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 | io.flutter.embedded_views_preview
45 |
46 | NSAppTransportSecurity
47 |
48 | NSAllowsArbitraryLoads
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/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/ServiceDefinitions.json:
--------------------------------------------------------------------------------
1 | {"services":[]}
--------------------------------------------------------------------------------
/lib/api/area_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:ncov_2019/config/api.dart';
2 | import 'package:ncov_2019/http/req_model.dart';
3 |
4 | /*
5 | * 获取省份信息 - 请求
6 | * */
7 | class AreaReqModel extends ReqModel {
8 | @override
9 | String url() => API.getAreaStat;
10 |
11 | @override
12 | Map params() => {};
13 |
14 | Future data() => get();
15 | }
16 |
17 | class AreaModel {
18 | int confirmedCount;
19 | int curedCount;
20 | List cities;
21 | String provinceShortName;
22 | String comment;
23 | String provinceName;
24 | int deadCount;
25 | int suspectedCount;
26 |
27 | AreaModel({this.confirmedCount, this.curedCount, this.cities, this.provinceShortName, this.comment, this.provinceName, this.deadCount, this.suspectedCount});
28 |
29 | AreaModel.fromJson(Map json) {
30 | confirmedCount = json['confirmedCount'];
31 | curedCount = json['curedCount'];
32 | if (json['cities'] != null) {
33 | cities = new List();(json['cities'] as List).forEach((v) { cities.add(new AreaModelCity.fromJson(v)); });
34 | }
35 | provinceShortName = json['provinceShortName'];
36 | comment = json['comment'];
37 | provinceName = json['provinceName'];
38 | deadCount = json['deadCount'];
39 | suspectedCount = json['suspectedCount'];
40 | }
41 |
42 | Map toJson() {
43 | final Map data = new Map();
44 | data['confirmedCount'] = this.confirmedCount;
45 | data['curedCount'] = this.curedCount;
46 | if (this.cities != null) {
47 | data['cities'] = this.cities.map((v) => v.toJson()).toList();
48 | }
49 | data['provinceShortName'] = this.provinceShortName;
50 | data['comment'] = this.comment;
51 | data['provinceName'] = this.provinceName;
52 | data['deadCount'] = this.deadCount;
53 | data['suspectedCount'] = this.suspectedCount;
54 | return data;
55 | }
56 | }
57 |
58 | class AreaModelCity {
59 | int confirmedCount;
60 | int curedCount;
61 | String cityName;
62 | int deadCount;
63 | int suspectedCount;
64 |
65 | AreaModelCity({this.confirmedCount, this.curedCount, this.cityName, this.deadCount, this.suspectedCount});
66 |
67 | AreaModelCity.fromJson(Map json) {
68 | confirmedCount = json['confirmedCount'];
69 | curedCount = json['curedCount'];
70 | cityName = json['cityName'];
71 | deadCount = json['deadCount'];
72 | suspectedCount = json['suspectedCount'];
73 | }
74 |
75 | Map toJson() {
76 | final Map data = new Map();
77 | data['confirmedCount'] = this.confirmedCount;
78 | data['curedCount'] = this.curedCount;
79 | data['cityName'] = this.cityName;
80 | data['deadCount'] = this.deadCount;
81 | data['suspectedCount'] = this.suspectedCount;
82 | return data;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/lib/api/area_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:ncov_2019/api/area_model.dart';
2 | import 'package:ncov_2019/commom/commom.dart';
3 | export 'package:ncov_2019/api/area_model.dart';
4 | import 'package:ncov_2019/http/view_model.dart';
5 |
6 | AreaViewModel areaViewModel = new AreaViewModel();
7 |
8 | class AreaViewModel extends ViewModel {
9 | /*
10 | * 获取省份信息
11 | * */
12 | Future getData() async {
13 | final data = await AreaReqModel().data();
14 |
15 |
16 | List list = new List();
17 |
18 | if (listNoEmpty(data)) {
19 | data.forEach((json) => list.add(AreaModel.fromJson(json)));
20 | }
21 |
22 | return Future.value(list);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/lib/api/entries_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:ncov_2019/config/api.dart';
2 | import 'package:ncov_2019/http/req_model.dart';
3 |
4 | /*
5 | * 诊疗信息 - 请求
6 | * */
7 | class EntriesReqModel extends ReqModel {
8 | @override
9 | String url() => API.getEntries;
10 |
11 | @override
12 | Map params() => {};
13 |
14 | Future data() => get();
15 | }
16 |
17 | /*
18 | * 诊疗信息 - 响应
19 | * */
20 | class EntriesModel {
21 | String configName;
22 | String imgUrl;
23 | int configNo;
24 | String linkUrl;
25 | String icon;
26 | int id;
27 |
28 | EntriesModel(
29 | {this.configName, this.imgUrl, this.configNo, this.linkUrl, this.id});
30 |
31 | EntriesModel.fromJson(Map json) {
32 | configName = json['configName'];
33 | imgUrl = json['imgUrl'];
34 | configNo = json['configNo'];
35 | linkUrl = json['linkUrl'];
36 | id = json['id'];
37 | icon = 'assets/images/entries_$id.png';
38 | }
39 |
40 | Map toJson() {
41 | final Map data = new Map();
42 | data['configName'] = this.configName;
43 | data['imgUrl'] = this.imgUrl;
44 | data['configNo'] = this.configNo;
45 | data['linkUrl'] = this.linkUrl;
46 | data['id'] = this.id;
47 | return data;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/lib/api/entries_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:ncov_2019/api/entries_model.dart';
2 | export 'package:ncov_2019/api/entries_model.dart';
3 | import 'package:ncov_2019/commom/commom.dart';
4 | import 'package:ncov_2019/http/view_model.dart';
5 |
6 | EntriesViewModel entriesViewModel = new EntriesViewModel();
7 |
8 | class EntriesViewModel extends ViewModel {
9 | /*
10 | * 诊疗信息
11 | * */
12 | Future getData() async {
13 | final data = await EntriesReqModel().data();
14 |
15 | List list = new List();
16 |
17 | if (listNoEmpty(data)) {
18 | data.forEach((json) => list.add(EntriesModel.fromJson(json)));
19 | }
20 |
21 | return Future.value(list);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lib/api/lore_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:ncov_2019/config/api.dart';
2 | import 'package:ncov_2019/http/req_model.dart';
3 |
4 | /*
5 | * 最新知识百科 - 请求
6 | * */
7 | class LoreReqModel extends ReqModel {
8 | @override
9 | String url() => API.getWikiList;
10 |
11 | @override
12 | Map params() => {};
13 |
14 | Future data() => get();
15 | }
16 |
17 | class LoreModel {
18 | String imgUrl;
19 | String linkUrl;
20 | String description;
21 | int id;
22 | int sort;
23 | String title;
24 |
25 | LoreModel({this.imgUrl, this.linkUrl, this.description, this.id, this.sort, this.title});
26 |
27 | LoreModel.fromJson(Map json) {
28 | imgUrl = json['imgUrl'];
29 | linkUrl = json['linkUrl'];
30 | description = json['description'];
31 | id = json['id'];
32 | sort = json['sort'];
33 | title = json['title'];
34 | }
35 |
36 | Map toJson() {
37 | final Map data = new Map();
38 | data['imgUrl'] = this.imgUrl;
39 | data['linkUrl'] = this.linkUrl;
40 | data['description'] = this.description;
41 | data['id'] = this.id;
42 | data['sort'] = this.sort;
43 | data['title'] = this.title;
44 | return data;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/lib/api/lore_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:ncov_2019/api/lore_model.dart';
2 | export 'package:ncov_2019/api/lore_model.dart';
3 | import 'package:ncov_2019/commom/check.dart';
4 | import 'package:ncov_2019/http/view_model.dart';
5 |
6 | LoreViewModel loreViewModel = new LoreViewModel();
7 |
8 | class LoreViewModel extends ViewModel {
9 | /*
10 | * 最新知识百科
11 | * */
12 | Future getLore() async {
13 | Map map = await LoreReqModel().data();
14 |
15 | List data = map['result'];
16 |
17 | List list = new List();
18 |
19 | if (listNoEmpty(data)) {
20 | data.forEach((json) => list.add(LoreModel.fromJson(json)));
21 | }
22 |
23 | return Future.value(list);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lib/api/news_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:ncov_2019/config/api.dart';
2 | import 'package:ncov_2019/http/req_model.dart';
3 |
4 | /*
5 | * 按时间线获取事件 - 请求
6 | * */
7 | class TimeNewsReqModel extends ReqModel {
8 | @override
9 | String url() => API.timelineService;
10 |
11 | @override
12 | Map params() => {};
13 |
14 | Future data() => get();
15 | }
16 |
17 | /*
18 | * 按时间线获取事件 - 响应
19 | *
20 | * @param summary 概要
21 | * @param sourceUrl 原文Url
22 | * @param modifyTime 更新时间
23 | * @param createTime 创建时间
24 | * @param id 事件Id
25 | * @param provinceName 省份名称
26 | * @param title 标题
27 | * @param pubDate 发布日期时间戳
28 | * @param pubDateStr 发布日期文本
29 | * @param provinceId 地区编号
30 | * @param infoSource 信息来源
31 | * */
32 | class TimeNewsModel {
33 | String summary;
34 | String sourceUrl;
35 | int modifyTime;
36 | int createTime;
37 | int id;
38 | String provinceName;
39 | String title;
40 | int pubDate;
41 | String pubDateStr;
42 | String provinceId;
43 | String infoSource;
44 |
45 | TimeNewsModel({
46 | this.summary,
47 | this.sourceUrl,
48 | this.modifyTime,
49 | this.createTime,
50 | this.id,
51 | this.provinceName,
52 | this.title,
53 | this.pubDate,
54 | this.pubDateStr,
55 | this.provinceId,
56 | this.infoSource,
57 | });
58 |
59 | TimeNewsModel.fromJson(Map json) {
60 | summary = json['summary'];
61 | sourceUrl = json['sourceUrl'];
62 | modifyTime = json['modifyTime'];
63 | createTime = json['createTime'];
64 | id = json['id'];
65 | provinceName = json['provinceName'];
66 | title = json['title'];
67 | pubDate = json['pubDate'];
68 | pubDateStr = json['pubDateStr'];
69 | provinceId = json['provinceId'];
70 | infoSource = json['infoSource'];
71 | }
72 |
73 | Map toJson() {
74 | final Map data = new Map();
75 | data['summary'] = this.summary;
76 | data['sourceUrl'] = this.sourceUrl;
77 | data['modifyTime'] = this.modifyTime;
78 | data['createTime'] = this.createTime;
79 | data['id'] = this.id;
80 | data['provinceName'] = this.provinceName;
81 | data['title'] = this.title;
82 | data['pubDate'] = this.pubDate;
83 | data['pubDateStr'] = this.pubDateStr;
84 | data['provinceId'] = this.provinceId;
85 | data['infoSource'] = this.infoSource;
86 | return data;
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/lib/api/news_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:ncov_2019/api/news_model.dart';
2 | import 'package:ncov_2019/commom/check.dart';
3 | import 'package:ncov_2019/http/view_model.dart';
4 |
5 | TimeNewsViewModel timeNewsViewModel = new TimeNewsViewModel();
6 |
7 | class TimeNewsViewModel extends ViewModel {
8 | /*
9 | * 按时间线获取事件
10 | * */
11 | Future getTimeNews() async {
12 | final data = await TimeNewsReqModel().data();
13 |
14 | List list = new List();
15 |
16 | if (listNoEmpty(data)) {
17 | data.forEach((json) => list.add(TimeNewsModel.fromJson(json)));
18 | }
19 |
20 | return Future.value(list);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lib/api/protect_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:ncov_2019/config/api.dart';
2 | import 'package:ncov_2019/http/req_model.dart';
3 |
4 | /*
5 | * 最新防护知识 - 请求
6 | * */
7 | class ProtectReqModel extends ReqModel {
8 | @override
9 | String url() => API.getIndexRecommendList;
10 |
11 | @override
12 | Map params() => {};
13 |
14 | Future data() => get();
15 | }
16 |
17 | /*
18 | * 最新防护知识 - 响应
19 | *
20 | * @param imgUrl 封面图片
21 | * @param modifyTime 修改时间
22 | * @param recordStatus 记录状态
23 | * @param createTime 创建时间
24 | * @param id 事件Id
25 | * @param linkUrl 链接url
26 | * @param title 标题
27 | * @param sort 分类
28 | * @param contentType 内容类型
29 | * @param xOperator X操作符
30 | * */
31 | class ProtectModel {
32 | String imgUrl;
33 | int modifyTime;
34 | int recordStatus;
35 | int createTime;
36 | String linkUrl;
37 | int id;
38 | int sort;
39 | String title;
40 | int contentType;
41 | String xOperator;
42 |
43 | ProtectModel({this.imgUrl, this.modifyTime, this.recordStatus, this.createTime, this.linkUrl, this.id, this.sort, this.title, this.contentType, this.xOperator});
44 |
45 | ProtectModel.fromJson(Map json) {
46 | imgUrl = json['imgUrl'];
47 | modifyTime = json['modifyTime'];
48 | recordStatus = json['recordStatus'];
49 | createTime = json['createTime'];
50 | linkUrl = json['linkUrl'];
51 | id = json['id'];
52 | sort = json['sort'];
53 | title = json['title'];
54 | contentType = json['contentType'];
55 | xOperator = json['operator'];
56 | }
57 |
58 | Map toJson() {
59 | final Map data = new Map();
60 | data['imgUrl'] = this.imgUrl;
61 | data['modifyTime'] = this.modifyTime;
62 | data['recordStatus'] = this.recordStatus;
63 | data['createTime'] = this.createTime;
64 | data['linkUrl'] = this.linkUrl;
65 | data['id'] = this.id;
66 | data['sort'] = this.sort;
67 | data['title'] = this.title;
68 | data['contentType'] = this.contentType;
69 | data['operator'] = this.xOperator;
70 | return data;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/lib/api/protect_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:ncov_2019/api/protect_model.dart';
2 | import 'package:ncov_2019/commom/check.dart';
3 | export 'package:ncov_2019/api/protect_model.dart';
4 | import 'package:ncov_2019/http/view_model.dart';
5 |
6 | ProtectViewModel protectViewModel = new ProtectViewModel();
7 |
8 | class ProtectViewModel extends ViewModel {
9 | /*
10 | * 最新防护知识
11 | * */
12 | Future getData() async {
13 | final data = await ProtectReqModel().data();
14 |
15 | List list = new List();
16 |
17 | if (listNoEmpty(data)) {
18 | data.forEach((json) => list.add(ProtectModel.fromJson(json)));
19 | }
20 |
21 | return Future.value(list);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lib/api/rumor_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:ncov_2019/config/api.dart';
2 | import 'package:ncov_2019/http/req_model.dart';
3 |
4 | /*
5 | * 最新辟谣 - 请求
6 | * */
7 | class RumorListReqModel extends ReqModel {
8 | @override
9 | String url() => API.getIndexRumorList;
10 |
11 | @override
12 | Map params() => {};
13 |
14 | Future data() => get();
15 | }
16 |
17 | /*
18 | * 最新辟谣 - 响应
19 | *
20 | * @param id 事件Id
21 | * @param title 标题
22 | * @param mainSummary 辟谣方
23 | * @param summary 概要
24 | * @param sourceUrl 原文Url
25 | * @param body 详情
26 | * @param rumorType 谣言类型
27 | * */
28 | class RumorListModel {
29 | String summary;
30 | String sourceUrl;
31 | int score;
32 | int rumorType;
33 | int id;
34 | String mainSummary;
35 | String title;
36 | String body;
37 | bool isOpen;
38 |
39 | RumorListModel({
40 | this.summary,
41 | this.sourceUrl,
42 | this.score,
43 | this.rumorType,
44 | this.id,
45 | this.mainSummary,
46 | this.title,
47 | this.body,
48 | this.isOpen = false,
49 | });
50 |
51 | RumorListModel.fromJson(Map json) {
52 | summary = json['summary'];
53 | sourceUrl = json['sourceUrl'];
54 | score = json['score'];
55 | rumorType = json['rumorType'];
56 | id = json['id'];
57 | mainSummary = json['mainSummary'];
58 | title = json['title'];
59 | body = json['body'];
60 | isOpen = false;
61 | }
62 |
63 | Map toJson() {
64 | final Map data = new Map();
65 | data['summary'] = this.summary;
66 | data['sourceUrl'] = this.sourceUrl;
67 | data['score'] = this.score;
68 | data['rumorType'] = this.rumorType;
69 | data['id'] = this.id;
70 | data['mainSummary'] = this.mainSummary;
71 | data['title'] = this.title;
72 | data['body'] = this.body;
73 | return data;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/lib/api/rumor_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:ncov_2019/api/rumor_model.dart';
2 | export 'package:ncov_2019/api/rumor_model.dart';
3 | import 'package:ncov_2019/http/view_model.dart';
4 | import 'package:ncov_2019/commom/commom.dart';
5 |
6 | RumorListReqViewModel rumorListReqViewModel = new RumorListReqViewModel();
7 |
8 | class RumorListReqViewModel extends ViewModel {
9 | /*
10 | * 最新辟谣
11 | * */
12 | Future getRumor() async {
13 | final data = await RumorListReqModel().data();
14 |
15 | List list = new List();
16 |
17 | if (listNoEmpty(data)){
18 | data.forEach((json) => list.add(RumorListModel.fromJson(json)));
19 | }
20 |
21 | return Future.value(list);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lib/api/statistics_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:ncov_2019/config/api.dart';
2 | import 'package:ncov_2019/http/req_model.dart';
3 |
4 | /*
5 | * 获取整体统计信息 - 请求
6 | * */
7 | class StatisticsReqModel extends ReqModel {
8 | @override
9 | String url() => API.getStatisticsService;
10 |
11 | @override
12 | Map params() => {};
13 |
14 | Future data() => get();
15 | }
16 |
17 | /*
18 | * 获取整体统计信息 - 响应
19 | * */
20 | class StatisticsModel {
21 | String summary;
22 | String generalRemark;
23 | int curedCount;
24 | String abroadRemark;
25 | String virus;
26 | int suspectedCount;
27 | String imgUrl;
28 | int confirmedCount;
29 | String infectSource;
30 | int modifyTime;
31 | bool deleted;
32 | String passWay;
33 | int createTime;
34 | String remark5;
35 | String dailyPic;
36 | List dailyPics;
37 | String remark4;
38 | int id;
39 | String countRemark;
40 | int deadCount;
41 | String remark1;
42 | String remark3;
43 | String remark2;
44 | String note1;
45 | String note3;
46 | String note2;
47 |
48 | StatisticsModel({
49 | this.summary,
50 | this.generalRemark,
51 | this.curedCount,
52 | this.abroadRemark,
53 | this.virus,
54 | this.suspectedCount,
55 | this.imgUrl,
56 | this.confirmedCount,
57 | this.infectSource,
58 | this.modifyTime,
59 | this.deleted,
60 | this.passWay,
61 | this.createTime,
62 | this.remark5,
63 | this.dailyPic,
64 | this.dailyPics,
65 | this.remark4,
66 | this.id,
67 | this.countRemark,
68 | this.deadCount,
69 | this.remark1 = '',
70 | this.remark3,
71 | this.remark2,
72 | this.note1,
73 | this.note2,
74 | this.note3,
75 | });
76 |
77 | StatisticsModel.fromJson(Map json) {
78 | summary = json['summary'];
79 | generalRemark = json['generalRemark'];
80 | curedCount = json['curedCount'];
81 | abroadRemark = json['abroadRemark'];
82 | virus = json['virus'];
83 | suspectedCount = json['suspectedCount'];
84 | imgUrl = json['imgUrl'];
85 | confirmedCount = json['confirmedCount'];
86 | infectSource = json['infectSource'];
87 | modifyTime = json['modifyTime'];
88 | deleted = json['deleted'];
89 | passWay = json['passWay'];
90 | createTime = json['createTime'];
91 | remark5 = json['remark5'];
92 | dailyPic = json['dailyPic'];
93 | remark4 = json['remark4'];
94 | id = json['id'];
95 | countRemark = json['countRemark'];
96 | deadCount = json['deadCount'];
97 | remark1 = json['remark1'];
98 | remark3 = json['remark3'];
99 | remark2 = json['remark2'];
100 | note1 = json['note1'];
101 | note3 = json['note3'];
102 | note2 = json['note2'];
103 | dailyPics = json['dailyPics'];
104 | }
105 |
106 | Map toJson() {
107 | final Map data = new Map();
108 | data['summary'] = this.summary;
109 | data['generalRemark'] = this.generalRemark;
110 | data['curedCount'] = this.curedCount;
111 | data['abroadRemark'] = this.abroadRemark;
112 | data['virus'] = this.virus;
113 | data['suspectedCount'] = this.suspectedCount;
114 | data['imgUrl'] = this.imgUrl;
115 | data['confirmedCount'] = this.confirmedCount;
116 | data['infectSource'] = this.infectSource;
117 | data['modifyTime'] = this.modifyTime;
118 | data['deleted'] = this.deleted;
119 | data['passWay'] = this.passWay;
120 | data['createTime'] = this.createTime;
121 | data['remark5'] = this.remark5;
122 | data['dailyPic'] = this.dailyPic;
123 | data['remark4'] = this.remark4;
124 | data['id'] = this.id;
125 | data['countRemark'] = this.countRemark;
126 | data['deadCount'] = this.deadCount;
127 | data['remark1'] = this.remark1;
128 | data['remark3'] = this.remark3;
129 | data['remark2'] = this.remark2;
130 | data['note1'] = this.note1;
131 | data['note3'] = this.note3;
132 | data['note2'] = this.note2;
133 | return data;
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/lib/api/statistics_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:ncov_2019/api/statistics_model.dart';
2 | export 'package:ncov_2019/api/statistics_model.dart';
3 | import 'package:ncov_2019/http/view_model.dart';
4 |
5 | StatisticsViewModel statisticsViewModel = new StatisticsViewModel();
6 |
7 | class StatisticsViewModel extends ViewModel {
8 | /*
9 | * 获取整体统计信息
10 | * */
11 | Future getData() async {
12 | final Map data = await StatisticsReqModel().data();
13 |
14 | if (data != null && data.isNotEmpty) {
15 | return StatisticsModel.fromJson(data);
16 | }
17 |
18 | return Future.value({});
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lib/api/version_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:ncov_2019/config/api.dart';
2 | import 'package:ncov_2019/http/req_model.dart';
3 |
4 | /*
5 | * 版本更新 - 请求
6 | * */
7 | class VersionReqModel extends ReqModel {
8 | @override
9 | String url() => API.update;
10 |
11 | @override
12 | Map params() => {};
13 |
14 | Future data() => get();
15 | }
16 |
17 | /*
18 | * 版本更新 - 响应
19 | * */
20 | class VersionModel {
21 | String updateInfo;
22 | String appVersion;
23 | String appName;
24 | String appId;
25 | String downloadUrl;
26 | bool force;
27 | int appVersionCode;
28 |
29 | VersionModel({this.updateInfo, this.appVersion, this.appName, this.appId, this.downloadUrl, this.force, this.appVersionCode});
30 |
31 | VersionModel.fromJson(Map json) {
32 | updateInfo = json['updateInfo'];
33 | appVersion = json['appVersion'];
34 | appName = json['appName'];
35 | appId = json['appId'];
36 | downloadUrl = json['downloadUrl'];
37 | force = json['force'];
38 | appVersionCode = json['appVersionCode'];
39 | }
40 |
41 | Map toJson() {
42 | final Map data = new Map();
43 | data['updateInfo'] = this.updateInfo;
44 | data['appVersion'] = this.appVersion;
45 | data['appName'] = this.appName;
46 | data['appId'] = this.appId;
47 | data['downloadUrl'] = this.downloadUrl;
48 | data['force'] = this.force;
49 | data['appVersionCode'] = this.appVersionCode;
50 | return data;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/lib/api/version_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:ncov_2019/api/version_model.dart';
2 | import 'package:ncov_2019/http/view_model.dart';
3 |
4 | VersionViewModel versionViewModel = new VersionViewModel();
5 |
6 | class VersionViewModel extends ViewModel {
7 | /*
8 | * 版本更新
9 | * */
10 | Future getData() async {
11 | final Map data = await VersionReqModel().data();
12 |
13 | if (data != null && data.isNotEmpty) {
14 | return VersionModel.fromJson(data);
15 | }
16 |
17 | return Future.value(null);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lib/app.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:nav_router/nav_router.dart';
3 | import 'package:ncov_2019/config/config.dart';
4 | import 'package:ncov_2019/config/const.dart';
5 | import 'package:ncov_2019/pages/root/root_page.dart';
6 |
7 | class MyApp extends StatelessWidget {
8 | @override
9 | Widget build(BuildContext context) {
10 | return MaterialApp(
11 | debugShowCheckedModeBanner: false,
12 | title: title,
13 | navigatorKey: navGK,
14 | theme: ThemeData(
15 | indicatorColor: appBarColor,
16 | scaffoldBackgroundColor: bgColor,
17 | hintColor: Colors.grey.withOpacity(0.3),
18 | splashColor: Colors.transparent,
19 | canvasColor: Colors.transparent,
20 | ),
21 | home: new RootPage(),
22 | );
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/lib/commom/check.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | /// 手机号正则表达式->true匹配
4 | bool isMobilePhoneNumber(String value) {
5 | RegExp mobile = new RegExp(r"(0|86|17951)?(1[0-9][0-9])[0-9]{8}");
6 |
7 | return mobile.hasMatch(value);
8 | }
9 |
10 | ///验证网页URl
11 | bool isUrl(String value) {
12 | RegExp url = new RegExp(r"^((https|http|ftp|rtsp|mms)?:\/\/)[^\s]+");
13 |
14 | return url.hasMatch(value);
15 | }
16 |
17 | ///校验身份证
18 | bool isIdCard(String value) {
19 | RegExp identity = new RegExp(r"\d{17}[\d|x]|\d{15}");
20 |
21 | return identity.hasMatch(value);
22 | }
23 |
24 | ///正浮点数
25 | bool isMoney(String value) {
26 | RegExp identity = new RegExp(
27 | r"^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$");
28 | return identity.hasMatch(value);
29 | }
30 |
31 | ///校验中文
32 | bool isChinese(String value) {
33 | RegExp identity = new RegExp(r"[\u4e00-\u9fa5]");
34 |
35 | return identity.hasMatch(value);
36 | }
37 |
38 | ///校验支付宝名称
39 | bool isAliPayName(String value) {
40 | RegExp identity = new RegExp(r"[\u4e00-\u9fa5_a-zA-Z]");
41 |
42 | return identity.hasMatch(value);
43 | }
44 |
45 | /// 字符串不为空
46 | bool strNoEmpty(String value) {
47 | if (value == null) return false;
48 |
49 | return value.trim().isNotEmpty;
50 | }
51 |
52 | /// 字符串不为空
53 | bool mapNoEmpty(Map value) {
54 | if (value == null) return false;
55 | return value.isNotEmpty;
56 | }
57 |
58 | ///判断List是否为空
59 | bool listNoEmpty(List list) {
60 | if (list == null) return false;
61 |
62 | if (list.length == 0) return false;
63 |
64 | return true;
65 | }
66 |
67 | /// 判断是否网络
68 | bool isNetWorkImg(String img) {
69 | return img.startsWith('http') || img.startsWith('https');
70 | }
71 |
72 | /// 判断是否资源图片
73 | bool isAssetsImg(String img) {
74 | return img.startsWith('asset') || img.startsWith('assets');
75 | }
76 |
77 | double getMemoryImageCashe() {
78 | return PaintingBinding.instance.imageCache.maximumSize / 1000;
79 | }
80 |
81 | void clearMemoryImageCache() {
82 | PaintingBinding.instance.imageCache.clear();
83 | }
84 |
85 | String stringAsFixed(value, num) {
86 | double v = double.parse(value.toString());
87 | String str = ((v * 100).floor() / 100).toStringAsFixed(2);
88 | return str;
89 | }
90 |
91 | String hiddenPhone(String phone){
92 | String result = '';
93 |
94 | if(phone != null && phone.length >= 11){
95 | String sub = phone.substring(0,3);
96 | String end = phone.substring(8,11);
97 | result = '$sub****$end';
98 | }
99 |
100 | return result;
101 | }
102 |
103 | ///去除后面的0
104 | String stringDisposeWithDouble(v, [fix = 2]) {
105 | double b = double.parse(v.toString());
106 | String vStr = b.toStringAsFixed(fix);
107 | int len = vStr.length;
108 | for (int i = 0; i < len; i++) {
109 | if (vStr.contains('.') && vStr.endsWith('0')) {
110 | vStr = vStr.substring(0, vStr.length - 1);
111 | } else {
112 | break;
113 | }
114 | }
115 |
116 | if (vStr.endsWith('.')) {
117 | vStr = vStr.substring(0, vStr.length - 1);
118 | }
119 |
120 | return vStr;
121 | }
122 |
123 | ///去除小数点
124 | String removeDot(v) {
125 | String vStr = v.toString().replaceAll('.', '');
126 |
127 | return vStr;
128 | }
--------------------------------------------------------------------------------
/lib/commom/commom.dart:
--------------------------------------------------------------------------------
1 | /// comMom
2 | export 'check.dart';
3 | export 'ui.dart';
4 | export 'win_media.dart';
5 | export 'data/data.dart';
6 | export 'check.dart';
7 | export 'date.dart';
8 | export 'file_util.dart';
9 |
10 | /// config
11 | export 'package:ncov_2019/config/api.dart';
12 | export 'package:ncov_2019/config/config.dart';
13 | export 'package:ncov_2019/config/const.dart';
14 | export 'package:ncov_2019/config/keys.dart';
15 |
16 | /// widget
17 | export 'package:ncov_2019/widget/bar/commom_bar.dart';
18 | export 'package:ncov_2019/widget/view/title_view.dart';
19 | export 'package:ncov_2019/widget/view/loading_view.dart';
20 |
21 | /// other
22 | export 'package:nav_router/nav_router.dart';
23 | export 'package:ncov_2019/widget/view/web_view_page.dart';
24 | export 'package:cached_network_image/cached_network_image.dart';
25 | export 'package:connectivity/connectivity.dart';
26 | import 'package:connectivity/connectivity.dart';
27 | export 'package:ncov_2019/commom/shared_util.dart';
28 |
29 |
30 | var subscription = Connectivity();
31 |
--------------------------------------------------------------------------------
/lib/commom/data/data.dart:
--------------------------------------------------------------------------------
1 | import 'package:ncov_2019/commom/data/store.dart';
2 | export 'package:ncov_2019/commom/data/store.dart';
3 |
4 | class NCOVActions {
5 | static String msg() => 'msg';
6 |
7 | static String voiceImg() => 'voiceImg';
8 |
9 | static String toTabBarIndex() => 'toTabBarIndex';
10 | }
11 |
12 | class Data {
13 | static String msg() => Store(NCOVActions.msg()).value = '';
14 |
15 | static String voiceImg() => Store(NCOVActions.voiceImg()).value = '';
16 | }
17 |
--------------------------------------------------------------------------------
/lib/commom/data/notice.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | typedef Callback(data);
4 |
5 | class Notice {
6 | Notice._();
7 |
8 | static final _eventMap = >{};
9 |
10 | static Callback addListener(String event, Callback call) {
11 | var callList = _eventMap[event];
12 | if (callList == null) {
13 | callList = new List();
14 | _eventMap[event] = callList;
15 | }
16 |
17 | callList.add(call);
18 |
19 | return call;
20 | }
21 |
22 | static removeListenerByEvent(String event) {
23 | _eventMap.remove(event);
24 | }
25 |
26 | static removeListener(Callback call) {
27 | final keys = _eventMap.keys.toList(growable: false);
28 | for (final k in keys) {
29 | final v = _eventMap[k];
30 |
31 | final remove = v.remove(call);
32 | if (remove && v.isEmpty) {
33 | _eventMap.remove(k);
34 | }
35 | }
36 | }
37 |
38 | static once(String event, {data}) {
39 | final callList = _eventMap[event];
40 |
41 | if (callList != null) {
42 | for (final item in new List.from(callList, growable: false)) {
43 | removeListener(item);
44 |
45 | _errorWrap(event, item, data);
46 | }
47 | }
48 | }
49 |
50 | static send(String event, [data]) {
51 | var callList = _eventMap[event];
52 |
53 | if (callList != null) {
54 | for (final item in callList) {
55 | _errorWrap(event, item, data);
56 | }
57 | }
58 | }
59 |
60 | static _errorWrap(String event, Callback call, data) {
61 | try {
62 | // xlog(() => 'Bus>>>$event>>>$data');
63 | call(data);
64 | } catch (e) {
65 | // xlog(() => 'Bus>>>$event>>>$e');
66 | // xlog(() => 'Bus>>>$event>>>$s');
67 | }
68 | }
69 | }
70 |
71 | mixin BusStateMixin on State {
72 | List _listeners;
73 |
74 | void bus(String event, Callback call) {
75 | _listeners ??= new List();
76 | _listeners.add(Notice.addListener(event, call));
77 | }
78 |
79 | void busDel(Callback call) {
80 | if (_listeners.remove(call)) {
81 | Notice.removeListener(call);
82 | }
83 | }
84 |
85 | void busDelAll() {
86 | _listeners?.forEach(Notice.removeListener);
87 | _listeners?.clear();
88 | }
89 |
90 | @override
91 | void dispose() {
92 | busDelAll();
93 |
94 | super.dispose();
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/lib/commom/data/store.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ncov_2019/commom/data/notice.dart';
3 | export 'package:ncov_2019/commom/data/notice.dart';
4 | import 'dart:async';
5 | import 'package:shared_preferences/shared_preferences.dart';
6 |
7 | typedef Widget StoreBuilder(T item);
8 |
9 | final _storeMap = {};
10 |
11 | class Store {
12 | final String _action;
13 |
14 | const Store(this._action);
15 |
16 | T get value => _storeMap[_action];
17 |
18 | set value(T v) {
19 | if (!(v is List) && !(v is Set) && !(v is Map) && v == _storeMap[_action])
20 | return;
21 |
22 | _storeMap[_action] = v;
23 |
24 | Notice.send('Store::$_action', v);
25 | }
26 |
27 | clear() => dispose(_action);
28 |
29 | notifyListeners() => Notice.send('Store::$_action', _storeMap[_action]);
30 |
31 | static dispose(String action) {
32 | for (final key in _storeMap.keys.toList(growable: false)) {
33 | if (key.startsWith(action)) {
34 |
35 | final v = _storeMap.remove(key);
36 |
37 | Notice.send('Store::$key', null);
38 | Notice.send('Store::$key::dispose', v);
39 | }
40 | }
41 | }
42 | }
43 |
44 | class CacheWidget extends StatefulWidget {
45 | final String action;
46 | final StoreBuilder builder;
47 | final data;
48 |
49 | CacheWidget(this.action, this.builder, {Key key,this.data}) : super(key: key);
50 |
51 | @override
52 | _CacheWidgetState createState() => new _CacheWidgetState();
53 | }
54 |
55 | class _CacheWidgetState extends State>
56 | with BusStateMixin {
57 | T item;
58 |
59 | void init() {
60 | final action = widget.action;
61 |
62 | item = _storeMap[action] as T;
63 |
64 | bus('Store::$action', onData);
65 | }
66 |
67 | @override
68 | void initState() {
69 | super.initState();
70 | init();
71 | widget.builder(item);
72 | }
73 |
74 | @override
75 | void didUpdateWidget(CacheWidget oldWidget) {
76 | super.didUpdateWidget(oldWidget);
77 | busDel(onData);
78 |
79 | init();
80 | }
81 |
82 | void onData(_) {
83 | if (mounted) Timer.run(() => setState(() => item = _));
84 | }
85 |
86 | @override
87 | Widget build(BuildContext context) => widget.builder(item);
88 | }
89 |
90 | storeString(String k,v) async {
91 | SharedPreferences prefs = await SharedPreferences.getInstance();
92 | prefs.setString(k, v);
93 | }
94 |
95 | Future getStoreValue(String k) async {
96 | SharedPreferences prefs = await SharedPreferences.getInstance();
97 | return prefs.get(k);
98 | }
99 |
--------------------------------------------------------------------------------
/lib/commom/date.dart:
--------------------------------------------------------------------------------
1 | import 'package:intl/intl.dart';
2 | import 'package:ncov_2019/commom/check.dart';
3 |
4 | class DateTimeForMater {
5 | static String full = "yyyy-MM-dd HH:mm:ss";
6 |
7 | static String formatDateV(DateTime dateTime, {bool isUtc, String format}) {
8 | if (dateTime == null) return "";
9 | format = format ?? full;
10 | if (format.contains("yy")) {
11 | String year = dateTime.year.toString();
12 | if (format.contains("yyyy")) {
13 | format = format.replaceAll("yyyy", year);
14 | } else {
15 | format = format.replaceAll(
16 | "yy", year.substring(year.length - 2, year.length));
17 | }
18 | }
19 |
20 | format = _comFormat(dateTime.month, format, 'M', 'MM');
21 | format = _comFormat(dateTime.day, format, 'd', 'dd');
22 | format = _comFormat(dateTime.hour, format, 'H', 'HH');
23 | format = _comFormat(dateTime.minute, format, 'm', 'mm');
24 | format = _comFormat(dateTime.second, format, 's', 'ss');
25 | format = _comFormat(dateTime.millisecond, format, 'S', 'SSS');
26 |
27 | return format;
28 | }
29 |
30 | static String _comFormat(
31 | int value, String format, String single, String full) {
32 | if (format.contains(single)) {
33 | if (format.contains(full)) {
34 | format =
35 | format.replaceAll(full, value < 10 ? '0$value' : value.toString());
36 | } else {
37 | format = format.replaceAll(single, value.toString());
38 | }
39 | }
40 | return format;
41 | }
42 | }
43 |
44 | String formatTimeStampToString(timestamp, [format]) {
45 | assert(timestamp != null);
46 |
47 | int time = 0;
48 |
49 | if (timestamp is int) {
50 | time = timestamp;
51 | } else {
52 | time = int.parse(timestamp.toString());
53 | }
54 |
55 | if (format == null) {
56 | format = 'yyyy-MM-dd HH:mm:ss';
57 | }
58 |
59 | DateFormat dateFormat = new DateFormat(format);
60 |
61 | var date = new DateTime.fromMillisecondsSinceEpoch(time * 1000);
62 |
63 | return dateFormat.format(date);
64 | }
65 |
66 | String timeHandle(int time) {
67 | double createTimeDouble = strNoEmpty('$time') ? time / 1000 : 0;
68 | int createTime = int.parse('${stringDisposeWithDouble(createTimeDouble)}');
69 | return '${formatTimeStampToString(createTime) ?? '未知'}';
70 | }
71 |
--------------------------------------------------------------------------------
/lib/commom/file_util.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:dio/dio.dart';
4 | import 'package:flutter/services.dart';
5 | import 'package:ncov_2019/config/api.dart';
6 | import 'package:ncov_2019/config/config.dart';
7 | import 'package:path_provider/path_provider.dart';
8 |
9 | class FileUtil {
10 | static FileUtil _instance;
11 |
12 | static FileUtil getInstance() {
13 | if (_instance == null) {
14 | _instance = FileUtil._internal();
15 | }
16 | return _instance;
17 | }
18 |
19 | FileUtil._internal();
20 |
21 | Future getSavePath(String endPath) async {
22 | Directory tempDir = await getApplicationDocumentsDirectory();
23 | String path = tempDir.path + endPath;
24 | Directory directory = Directory(path);
25 | if (!directory.existsSync()) {
26 | directory.createSync(recursive: true);
27 | }
28 | return path;
29 | }
30 |
31 | void copyFile(String oldPath, String newPath) {
32 | File file = File(oldPath);
33 | if (file.existsSync()) {
34 | file.copy(newPath);
35 | }
36 | }
37 |
38 | Future> getDirChildren(String path) async {
39 | Directory directory = Directory(path);
40 | final childrenDir = directory.listSync();
41 | List pathList = [];
42 | for (var o in childrenDir) {
43 | final filename = o.path.split("/").last;
44 | if (filename.contains(".")) {
45 | pathList.add(o.path);
46 | }
47 | }
48 | return pathList;
49 | }
50 |
51 | ///[assetPath] 例子 'images/'
52 | ///[assetName] 例子 '1.jpg'
53 | ///[filePath] 例子:'/myFile/'
54 | ///[fileName] 例子 'girl.jpg'
55 | Future copyAssetToFile(String assetPath, String assetName,
56 | String filePath, String fileName) async {
57 | String newPath = await FileUtil.getInstance().getSavePath(filePath);
58 | String name = fileName;
59 | bool exists = await new File(newPath + name).exists();
60 | if (!exists) {
61 | var data = await rootBundle.load(assetPath + assetName);
62 | List bytes =
63 | data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
64 | await File(newPath + name).writeAsBytes(bytes);
65 | return newPath + name;
66 | } else
67 | return newPath + name;
68 | }
69 |
70 | void downloadFile(
71 | {String url,
72 | String filePath,
73 | String fileName,
74 | Function onComplete}) async {
75 | final path = await FileUtil.getInstance().getSavePath(filePath);
76 | String name = fileName ?? url.split("/").last;
77 |
78 | Dio _client;
79 | if (_client == null) {
80 | BaseOptions options = new BaseOptions();
81 | options.connectTimeout = connectTimeOut;
82 | options.receiveTimeout = receiveTimeOut;
83 | options.headers = const {'Content-Type': 'application/json'};
84 | options.baseUrl = API.reqUrl;
85 | _client = new Dio(options);
86 | }
87 |
88 | if (_client != null)
89 | _client.download(
90 | url,
91 | path + name,
92 | onReceiveProgress: (int count, int total) {
93 | final downloadProgress = ((count / total) * 100).toInt();
94 | if (downloadProgress == 100) {
95 | if (onComplete != null) onComplete(path + name);
96 | }
97 | },
98 | options: Options(sendTimeout: 15 * 1000, receiveTimeout: 360 * 1000),
99 | );
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/lib/commom/shared_util.dart:
--------------------------------------------------------------------------------
1 | import 'package:ncov_2019/config/keys.dart';
2 | export 'package:ncov_2019/config/keys.dart';
3 | import 'package:ncov_2019/config/storage_manager.dart';
4 |
5 | class SharedUtil {
6 | factory SharedUtil() => _getInstance();
7 |
8 | static SharedUtil get instance => _getInstance();
9 | static SharedUtil _instance;
10 |
11 | SharedUtil._internal() {
12 | //初始化
13 | //init
14 | }
15 |
16 | static SharedUtil _getInstance() {
17 | if (_instance == null) {
18 | _instance = new SharedUtil._internal();
19 | }
20 | return _instance;
21 | }
22 |
23 |
24 | /// save
25 | Future saveString(String key, String value) async {
26 | if (key == Keys.account) {
27 | await StorageManager.sp.setString(key, value);
28 | return;
29 | }
30 | String account = StorageManager.sp.getString(Keys.account) ?? "default";
31 | await StorageManager.sp.setString(key + account, value);
32 | }
33 |
34 | Future saveInt(String key, int value) async {
35 | String account = StorageManager.sp.getString(Keys.account) ?? "default";
36 | await StorageManager.sp.setInt(key + account, value);
37 | }
38 |
39 | Future saveDouble(String key, double value) async {
40 | String account = StorageManager.sp.getString(Keys.account) ?? "default";
41 | await StorageManager.sp.setDouble(key + account, value);
42 | }
43 |
44 | Future saveBoolean(String key, bool value) async {
45 | String account = StorageManager.sp.getString(Keys.account) ?? "default";
46 | await StorageManager.sp.setBool(key + account, value);
47 | }
48 |
49 | Future saveStringList(String key, List list) async {
50 | String account = StorageManager.sp.getString(Keys.account) ?? "default";
51 | await StorageManager.sp.setStringList(key + account, list);
52 | }
53 |
54 | Future readAndSaveList(String key, String data) async {
55 | String account = StorageManager.sp.getString(Keys.account) ?? "default";
56 | List strings = StorageManager.sp.getStringList(key + account) ?? [];
57 | if (strings.length >= 10) return false;
58 | strings.add(data);
59 | await StorageManager.sp.setStringList(key + account, strings);
60 | return true;
61 | }
62 |
63 | void readAndExchangeList(String key, String data, int index) async {
64 | String account = StorageManager.sp.getString(Keys.account) ?? "default";
65 | List strings = StorageManager.sp.getStringList(key + account) ?? [];
66 | strings[index] = data;
67 | await StorageManager.sp.setStringList(key + account, strings);
68 | }
69 |
70 | void readAndRemoveList(String key, int index) async {
71 | String account = StorageManager.sp.getString(Keys.account) ?? "default";
72 | List strings = StorageManager.sp.getStringList(key + account) ?? [];
73 | strings.removeAt(index);
74 | await StorageManager.sp.setStringList(key + account, strings);
75 | }
76 |
77 | /// get
78 | Future getString(String key) async {
79 | if (key == Keys.account) {
80 | return StorageManager.sp.getString(key);
81 | }
82 | String account = StorageManager.sp.getString(Keys.account) ?? "default";
83 | return StorageManager.sp.getString(key + account);
84 | }
85 |
86 | Future getInt(String key) async {
87 | String account = StorageManager.sp.getString(Keys.account) ?? "default";
88 | return StorageManager.sp.getInt(key + account);
89 | }
90 |
91 | Future getDouble(String key) async {
92 | String account = StorageManager.sp.getString(Keys.account) ?? "default";
93 | return StorageManager.sp.getDouble(key + account);
94 | }
95 |
96 | Future getBoolean(String key) async {
97 | String account = StorageManager.sp.getString(Keys.account) ?? "default";
98 | return StorageManager.sp.getBool(key + account) ?? false;
99 | }
100 |
101 | Future> getStringList(String key) async {
102 | String account = StorageManager.sp.getString(Keys.account) ?? "default";
103 | return StorageManager.sp.getStringList(key + account);
104 | }
105 |
106 | Future> readList(String key) async {
107 | String account = StorageManager.sp.getString(Keys.account) ?? "default";
108 | List strings = StorageManager.sp.getStringList(key + account) ?? [];
109 | return strings;
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/lib/commom/ui.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class HorizontalLine extends StatelessWidget {
4 | final double height;
5 | final Color color;
6 | final double horizontal;
7 |
8 | HorizontalLine({
9 | this.height = 0.5,
10 | this.color = const Color(0xFFEEEEEE),
11 | this.horizontal = 0.0,
12 | });
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | return new Container(
17 | height: height,
18 | color: color,
19 | margin: new EdgeInsets.symmetric(horizontal: horizontal),
20 | );
21 | }
22 | }
23 |
24 | class VerticalLine extends StatelessWidget {
25 | final double width;
26 | final double height;
27 | final Color color;
28 | final double vertical;
29 |
30 | VerticalLine({
31 | this.width = 1.0,
32 | this.height = 25,
33 | this.color = const Color.fromRGBO(209, 209, 209, 0.5),
34 | this.vertical = 0.0,
35 | });
36 |
37 | @override
38 | Widget build(BuildContext context) {
39 | return new Container(
40 | width: width,
41 | color: Color(0xffDCE0E5),
42 | margin: new EdgeInsets.symmetric(vertical: vertical),
43 | height: height,
44 | );
45 | }
46 | }
47 |
48 | class Space extends StatelessWidget {
49 | final double width;
50 | final double height;
51 |
52 | Space({this.width = 10.0, this.height = 10.0});
53 |
54 | @override
55 | Widget build(BuildContext context) {
56 | return new Container(width: width, height: height);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/lib/commom/win_media.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:flutter/material.dart';
4 |
5 | double winWidth(BuildContext context) {
6 | return MediaQuery.of(context).size.width;
7 | }
8 |
9 | double winHeight(BuildContext context) {
10 | return MediaQuery.of(context).size.height;
11 | }
12 |
13 | double winTop(BuildContext context) {
14 | return MediaQuery.of(context).padding.top;
15 | }
16 |
17 | double winBottom(BuildContext context) {
18 | return MediaQuery.of(context).padding.bottom;
19 | }
20 |
21 | double winLeft(BuildContext context) {
22 | return MediaQuery.of(context).padding.left;
23 | }
24 |
25 | double winRight(BuildContext context) {
26 | return MediaQuery.of(context).padding.right;
27 | }
28 |
29 | double winKeyHeight(BuildContext context) {
30 | return MediaQuery.of(context).viewInsets.bottom;
31 | }
32 |
33 | double statusBarHeight(BuildContext context) {
34 | return MediaQueryData.fromWindow(window).padding.top;
35 | }
36 |
37 | double navigationBarHeight(BuildContext context) {
38 | return kToolbarHeight;
39 | }
40 |
41 | double topBarHeight(BuildContext context) {
42 | return kToolbarHeight + MediaQueryData.fromWindow(window).padding.top;
43 | }
44 |
--------------------------------------------------------------------------------
/lib/config/api.dart:
--------------------------------------------------------------------------------
1 | class API {
2 | // 请求的url
3 | static const reqUrl = 'http://49.232.173.220:3001';
4 |
5 | // 按时间线获取事件
6 | static const timelineService = '/data/getTimelineService';
7 |
8 | // 最新辟谣
9 | static const getIndexRumorList = '/data/getIndexRumorList';
10 |
11 | // 最新防护知识
12 | static const getIndexRecommendList = '/data/getIndexRecommendList';
13 |
14 | // 最新知识百科
15 | static const getWikiList = '/data/getWikiList';
16 |
17 | // 获取整体统计信息
18 | static const getStatisticsService = '/data/getStatisticsService';
19 |
20 | // 获取省份信息
21 | static const getAreaStat = '/data/getAreaStat';
22 |
23 | // 诊疗信息
24 | static const getEntries = '/data/getEntries';
25 |
26 | // 版本更新
27 | static const update = '/app/update';
28 | }
29 |
--------------------------------------------------------------------------------
/lib/config/config.dart:
--------------------------------------------------------------------------------
1 | /// app名字
2 | const String title = 'ncov-2019';
3 |
4 | ///连接超时时间为5秒
5 | const int connectTimeOut = 5 * 1000;
6 |
7 | ///响应超时时间为7秒
8 | const int receiveTimeOut = 7 * 1000;
--------------------------------------------------------------------------------
/lib/config/const.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | const appBarColor = Color(0xff4169e2);
4 |
5 | const Color fixedColor = Colors.blue;
6 |
7 | const bgColor = Color(0xfff7f7f7);
8 |
9 | const mainSpace = 10.0;
10 |
11 | const mainLineWidth = 0.3;
12 |
13 | const lineColor = Colors.grey;
14 |
15 | const mainTextColor = Color.fromRGBO(115, 115, 115, 1.0);
16 |
17 | const defImg = 'http://www.flutterj.com/content/templates/emlog_dux/images/random/1.jpg';
--------------------------------------------------------------------------------
/lib/config/keys.dart:
--------------------------------------------------------------------------------
1 | class Keys {
2 | static final String account = "account";
3 | }
4 |
--------------------------------------------------------------------------------
/lib/config/storage_manager.dart:
--------------------------------------------------------------------------------
1 | import 'package:shared_preferences/shared_preferences.dart';
2 |
3 | class StorageManager {
4 | /// app全局配置
5 | static SharedPreferences sp;
6 |
7 | /// 网络连接
8 | var connect;
9 |
10 | /// 必备数据的初始化操作
11 | static init() async {
12 | // async 异步操作
13 | // sync 同步操作
14 | sp = await SharedPreferences.getInstance();
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/lib/http/req_model.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:dio/dio.dart';
4 | import 'package:ncov_2019/commom/commom.dart';
5 | import 'package:ncov_2019/config/api.dart';
6 | import 'package:ncov_2019/config/config.dart';
7 |
8 | // 请求计数
9 | var _id = 0;
10 |
11 | /*
12 | * 请求类型枚举
13 | * */
14 | enum RequestType { GET, POST }
15 |
16 | class ReqModel {
17 | // 请求url路径
18 | String url() => null;
19 |
20 | // 请求参数
21 | Map params() => {};
22 |
23 | /*
24 | * get请求
25 | * */
26 | Future get() async {
27 | return this._request(
28 | url: url(),
29 | method: RequestType.GET,
30 | params: params(),
31 | );
32 | }
33 |
34 | /*
35 | * post请求
36 | * */
37 | Future post() async {
38 | return this._request(
39 | url: url(),
40 | method: RequestType.POST,
41 | params: params(),
42 | );
43 | }
44 |
45 | /*
46 | * post请求-文件上传方式
47 | * */
48 | Future postUpload(
49 | ProgressCallback progressCallBack, {
50 | FormData formData,
51 | }) async {
52 | return this._request(
53 | url: url(),
54 | method: RequestType.POST,
55 | formData: formData,
56 | progressCallBack: progressCallBack,
57 | params: params(),
58 | );
59 | }
60 |
61 | /*
62 | * 请求方法
63 | * */
64 | Future _request({
65 | String url,
66 | RequestType method,
67 | Map params,
68 | FormData formData,
69 | ProgressCallback progressCallBack,
70 | }) async {
71 | Dio _client;
72 |
73 | final httpUrl = '${API.reqUrl}$url';
74 |
75 | if (_client == null) {
76 | BaseOptions options = new BaseOptions();
77 | options.connectTimeout = connectTimeOut;
78 | options.receiveTimeout = receiveTimeOut;
79 | options.headers = const {'Content-Type': 'application/json'};
80 | options.baseUrl = API.reqUrl;
81 | _client = new Dio(options);
82 | }
83 |
84 | final id = _id++;
85 | int statusCode;
86 | try {
87 | Response response;
88 | if (method == RequestType.GET) {
89 | ///组合GET请求的参数
90 | if (mapNoEmpty(params)) {
91 | response = await _client.get(
92 | url,
93 | queryParameters: params,
94 | );
95 | } else {
96 | response = await _client.get(
97 | url,
98 | );
99 | }
100 | } else {
101 | if (mapNoEmpty(params) && formData != null) {
102 | response = await _client.post(
103 | url,
104 | data: formData ?? params,
105 | onSendProgress: progressCallBack,
106 | );
107 | } else {
108 | response = await _client.post(
109 | url,
110 | );
111 | }
112 | }
113 |
114 | statusCode = response.statusCode;
115 |
116 | if (response != null) {
117 | print('HTTP_REQUEST_URL::[$id]::$httpUrl');
118 | if (mapNoEmpty(params)) {
119 | print('HTTP_REQUEST_BODY::[$id]::${json.encode(params)}');
120 | }
121 | print('HTTP_RESPONSE_BODY::[$id]::${json.encode(response.data)}');
122 | return response.data;
123 | }
124 |
125 | ///处理错误部分
126 | if (statusCode < 0) {
127 | return _handError(statusCode);
128 | }
129 | } catch (e) {
130 | return _handError(statusCode);
131 | }
132 | }
133 |
134 | ///处理异常
135 | static Future _handError(int statusCode) {
136 | String errorMsg = 'Network request error';
137 | Map errorMap = {"errorMsg": errorMsg, "errorCode": statusCode};
138 |
139 | print("HTTP_RESPONSE_ERROR::$errorMsg code:$statusCode");
140 | return Future.value(errorMap);
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/lib/http/view_model.dart:
--------------------------------------------------------------------------------
1 | class ViewModel {
2 | List dataListToModel(List data, model) {
3 | List list = new List();
4 |
5 | data.forEach((json) => list.add(model.fromJson(json)));
6 |
7 | return list;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter/services.dart';
5 | import 'package:ncov_2019/app.dart';
6 | import 'package:ncov_2019/config/storage_manager.dart';
7 |
8 | /*
9 | * App入口
10 | * */
11 | void main() async {
12 | /// 确保初始化
13 | WidgetsFlutterBinding.ensureInitialized();
14 |
15 | /// 配置初始化
16 | await StorageManager.init();
17 |
18 | /// App入口
19 | runApp(
20 | new ColorFiltered(
21 | colorFilter: ColorFilter.mode(Colors.transparent, BlendMode.color),
22 | child: new MyApp(),
23 | ),
24 | );
25 |
26 | /// 自定义报错页面
27 | ErrorWidget.builder = (FlutterErrorDetails flutterErrorDetails) {
28 | debugPrint(flutterErrorDetails.toString());
29 | return new Center(child: new Text("App错误,快去反馈给作者!"));
30 | };
31 |
32 | /// Android状态栏透明
33 | if (Platform.isAndroid) {
34 | SystemUiOverlayStyle systemUiOverlayStyle = SystemUiOverlayStyle(
35 | statusBarColor: Colors.transparent,
36 | statusBarBrightness: Brightness.light,
37 | );
38 | SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/lib/pages/home/home_page.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'package:flutter/material.dart';
3 | import 'package:ncov_2019/api/entries_view_model.dart';
4 | import 'package:ncov_2019/api/news_model.dart';
5 | import 'package:ncov_2019/api/news_view_model.dart';
6 | import 'package:ncov_2019/api/statistics_view_model.dart';
7 | import 'package:ncov_2019/commom/commom.dart';
8 | import 'package:ncov_2019/widget/card/news_card.dart';
9 | import 'package:ncov_2019/widget/item/entries.dart';
10 | import 'package:ncov_2019/widget/item/statics.dart';
11 | import 'package:pull_to_refresh/pull_to_refresh.dart';
12 |
13 | class HomePage extends StatefulWidget {
14 | @override
15 | _HomePageState createState() => _HomePageState();
16 | }
17 |
18 | class _HomePageState extends State
19 | with AutomaticKeepAliveClientMixin {
20 | RefreshController _refreshController =
21 | RefreshController(initialRefresh: false);
22 |
23 | bool isReq = false;
24 |
25 | List data = new List();
26 |
27 | // List entriesData = new List();
28 | //
29 | // StatisticsModel statisticsModel = new StatisticsModel();
30 |
31 | @override
32 | void initState() {
33 | super.initState();
34 | Notice.addListener(NCOVActions.toTabBarIndex(), (index) {
35 | if (!listNoEmpty(data)) getData();
36 | });
37 | getData();
38 | }
39 |
40 | @override
41 | bool get wantKeepAlive => true;
42 |
43 | getData() {
44 | timeNewsViewModel.getTimeNews().then((v) {
45 | setState(() {
46 | data = v;
47 | isReq = true;
48 | });
49 | });
50 | // statisticsViewModel.getData().then((v) {
51 | // setState(() => statisticsModel = v);
52 | // });
53 | // entriesViewModel.getData().then((v) {
54 | // setState(() => entriesData = v);
55 | // });
56 | }
57 |
58 | Future _refreshData() async {
59 | final Completer completer = new Completer();
60 |
61 | getData();
62 |
63 | new Future.delayed(new Duration(seconds: 2), () {
64 | completer.complete(null);
65 | _refreshController.refreshCompleted();
66 | });
67 |
68 | return completer.future;
69 | }
70 |
71 | Widget buildItem(item) {
72 | TimeNewsModel model = item;
73 | bool isNew = model.id == data[0].id;
74 | return new NewsCard(
75 | model,
76 | padding: EdgeInsets.only(
77 | left: 20.0,
78 | right: 20.0,
79 | top: isNew ? 10.0 : 10,
80 | bottom: model.id == data[data.length - 1].id ? 20.0 : 10,
81 | ),
82 | isNew: isNew,
83 | );
84 | }
85 |
86 | @override
87 | Widget build(BuildContext context) {
88 | super.build(context);
89 | return new Scaffold(
90 | body: new SmartRefresher(
91 | controller: _refreshController,
92 | onRefresh: _refreshData,
93 | child: isReq
94 | ? listNoEmpty(data)
95 | ? new ListView.builder(
96 | itemBuilder: (context, index) {
97 | TimeNewsModel model = data[index];
98 | bool isNew = model.id == data[0].id;
99 | return new NewsCard(
100 | model,
101 | padding: EdgeInsets.only(
102 | left: 20.0,
103 | right: 20.0,
104 | top: isNew ? 10.0 : 10,
105 | bottom:
106 | model.id == data[data.length - 1].id ? 20.0 : 10,
107 | ),
108 | isNew: isNew,
109 | );
110 | },
111 | itemCount: data.length,
112 | )
113 | : new Center(
114 | child: new Text(
115 | '暂无数据',
116 | style: Theme.of(context).textTheme.display1,
117 | ),
118 | )
119 | : new LoadingView(),
120 | // child: new ListView(
121 | // children: [
122 | // new Space(),
123 | // new TitleView(
124 | // '全国统计',
125 | // subTitle: '${timeHandle(statisticsModel?.modifyTime ?? 0)}',
126 | // ),
127 | // new Statics(statisticsModel),
128 | // new Divider(),
129 | // new Space(height: mainSpace / 2),
130 | // new Visibility(
131 | // visible: strNoEmpty(statisticsModel?.imgUrl ?? ''),
132 | // child: new TitleView('疫情地图', subTitle: '数据来源:国家及各省市地区卫健委'),
133 | // ),
134 | // new Visibility(
135 | // visible: strNoEmpty(statisticsModel?.imgUrl ?? ''),
136 | // child: new Padding(
137 | // padding: EdgeInsets.only(top: 10.0),
138 | // child: new CachedNetworkImage(
139 | // imageUrl: statisticsModel?.imgUrl ?? defImg),
140 | // ),
141 | // ),
142 | // new Visibility(
143 | // visible: strNoEmpty(statisticsModel?.dailyPic ?? ''),
144 | // child: new Padding(
145 | // padding: EdgeInsets.only(bottom: 10.0),
146 | // child: new CachedNetworkImage(
147 | // imageUrl: statisticsModel?.dailyPic ?? defImg),
148 | // ),
149 | // ),
150 | // new Space(),
151 | // new TitleView('诊疗'),
152 | // new Container(
153 | // margin: EdgeInsets.symmetric(horizontal: 10.0),
154 | // child: new Wrap(
155 | // children: entriesData.map((item) {
156 | // EntriesModel model = item;
157 | // return Entries(model);
158 | // }).toList(),
159 | // ),
160 | // ),
161 | // new TitleView('最新消息', subTitle: '消息数量:${data.length}'),
162 | // listNoEmpty(data)
163 | // ? new Column(children: data.map(buildItem).toList())
164 | // : new Center(
165 | // child: new Text(
166 | // '暂无数据',
167 | // style: Theme.of(context).textTheme.display1,
168 | // ),
169 | // )
170 | // ],
171 | // ),
172 | ),
173 | );
174 | }
175 | }
176 |
--------------------------------------------------------------------------------
/lib/pages/lore/lore_page.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:ncov_2019/api/lore_view_model.dart';
5 | import 'package:ncov_2019/commom/commom.dart';
6 | import 'package:ncov_2019/widget/card/lore_card.dart';
7 | import 'package:pull_to_refresh/pull_to_refresh.dart';
8 |
9 | class LorePage extends StatefulWidget {
10 | @override
11 | _LorePageState createState() => _LorePageState();
12 | }
13 |
14 | class _LorePageState extends State
15 | with AutomaticKeepAliveClientMixin {
16 | RefreshController _refreshController =
17 | RefreshController(initialRefresh: false);
18 |
19 | List data = new List();
20 |
21 | bool isReq = false;
22 |
23 | @override
24 | void initState() {
25 | super.initState();
26 | Notice.addListener(NCOVActions.toTabBarIndex(), (index) {
27 | if (!listNoEmpty(data)) getData();
28 | });
29 | getData();
30 | }
31 |
32 | @override
33 | bool get wantKeepAlive => true;
34 |
35 | getData() {
36 | loreViewModel.getLore().then((v) {
37 | setState(() {
38 | data = v;
39 | isReq = true;
40 | });
41 | });
42 | }
43 |
44 | Future _refreshData() async {
45 | final Completer completer = new Completer();
46 |
47 | getData();
48 |
49 | new Future.delayed(new Duration(seconds: 2), () {
50 | completer.complete(null);
51 | _refreshController.refreshCompleted();
52 | });
53 |
54 | return completer.future;
55 | }
56 |
57 | Widget buildItem(context, index) {
58 | LoreModel model = data[index];
59 | return new LoreCard(
60 | model,
61 | margin: EdgeInsets.only(
62 | left: 10.0,
63 | right: 10.0,
64 | top: model.id == data[0].id ? 10.0 : 0,
65 | bottom: model.id == data[data.length - 1].id ? 10.0 : 0,
66 | ),
67 | );
68 | }
69 |
70 | @override
71 | Widget build(BuildContext context) {
72 | super.build(context);
73 | return new Scaffold(
74 | body: new SmartRefresher(
75 | controller: _refreshController,
76 | onRefresh: _refreshData,
77 | child: isReq
78 | ? listNoEmpty(data)
79 | ? new ListView.builder(
80 | itemBuilder: buildItem,
81 | itemCount: data.length,
82 | )
83 | : new Center(
84 | child: new Text(
85 | '暂无数据',
86 | style: Theme.of(context).textTheme.display1,
87 | ),
88 | )
89 | : new LoadingView(),
90 | ),
91 | );
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/lib/pages/protect/protect_page.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:ncov_2019/api/area_view_model.dart';
5 | import 'package:ncov_2019/api/protect_view_model.dart';
6 | import 'package:ncov_2019/api/statistics_view_model.dart';
7 | import 'package:ncov_2019/commom/commom.dart';
8 | import 'package:ncov_2019/widget/card/protect_card.dart';
9 | import 'package:ncov_2019/widget/flutter/my_expansion_tile.dart';
10 | import 'package:ncov_2019/widget/item/statics.dart';
11 | import 'package:ncov_2019/widget/view/title_view.dart';
12 | import 'package:pull_to_refresh/pull_to_refresh.dart';
13 |
14 | class ProtectPage extends StatefulWidget {
15 | @override
16 | _ProtectPageState createState() => _ProtectPageState();
17 | }
18 |
19 | class _ProtectPageState extends State
20 | with AutomaticKeepAliveClientMixin {
21 | RefreshController _refreshController =
22 | RefreshController(initialRefresh: false);
23 |
24 | List data = new List();
25 | List areaData = new List();
26 |
27 | bool isReq = false;
28 |
29 | @override
30 | void initState() {
31 | super.initState();
32 | Notice.addListener(NCOVActions.toTabBarIndex(), (index) {
33 | if (!listNoEmpty(data)) getData();
34 | });
35 | getData();
36 | }
37 |
38 | @override
39 | bool get wantKeepAlive => true;
40 |
41 | getData() {
42 | protectViewModel.getData().then((v) {
43 | setState(() {
44 | data = v;
45 | isReq = true;
46 | });
47 | });
48 | areaViewModel.getData().then((v) {
49 | setState(() => areaData = v);
50 | });
51 | }
52 |
53 | Future _refreshData() async {
54 | final Completer completer = new Completer();
55 |
56 | getData();
57 |
58 | new Future.delayed(new Duration(seconds: 2), () {
59 | completer.complete(null);
60 | _refreshController.refreshCompleted();
61 | });
62 |
63 | return completer.future;
64 | }
65 |
66 | Widget buildItem(item) {
67 | ProtectModel model = item;
68 | return new ProtectCard(
69 | model,
70 | margin: EdgeInsets.only(
71 | left: 10.0,
72 | right: 10.0,
73 | top: model.id == data[0].id ? 0.0 : 0,
74 | bottom: model.id == data[data.length - 1].id ? 10.0 : 0,
75 | ),
76 | );
77 | }
78 |
79 | Widget _buildCity(item) {
80 | AreaModelCity model = item;
81 | return new Padding(
82 | padding: EdgeInsets.symmetric(horizontal: 20.0),
83 | child: new Row(
84 | children: [
85 | '${model?.cityName ?? '未知'}',
86 | '${model?.confirmedCount ?? 0}',
87 | '${model?.deadCount ?? 0}',
88 | '${model?.curedCount ?? 0}'
89 | ].map((item) {
90 | return new Container(
91 | padding: EdgeInsets.only(right: 10.0),
92 | width: (winWidth(context) - 80) / 4,
93 | child:
94 | new Text(item, style: TextStyle(fontWeight: FontWeight.w600)),
95 | );
96 | }).toList(),
97 | ),
98 | );
99 | }
100 |
101 | Widget areaBuild(item) {
102 | AreaModel model = item;
103 | return new MyExpansionTile(
104 | title: new Row(
105 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
106 | children: [
107 | '${model?.provinceName ?? '未知'}',
108 | '${model?.confirmedCount ?? 0}',
109 | '${model?.deadCount ?? 0}',
110 | '${model?.curedCount ?? 0}'
111 | ].map((item) {
112 | return new Container(
113 | padding: EdgeInsets.only(right: 10.0),
114 | width: (winWidth(context) - 80) / 4,
115 | child:
116 | new Text(item, style: TextStyle(fontWeight: FontWeight.w600)),
117 | );
118 | }).toList(),
119 | ),
120 | children: model.cities.map(_buildCity).toList(),
121 | );
122 | }
123 |
124 | @override
125 | Widget build(BuildContext context) {
126 | super.build(context);
127 | return new Scaffold(
128 | body: new SmartRefresher(
129 | controller: _refreshController,
130 | onRefresh: _refreshData,
131 | child: new SingleChildScrollView(
132 | child: new Column(
133 | crossAxisAlignment: CrossAxisAlignment.start,
134 | children: [
135 | new Space(),
136 | new TitleView('地区统计'),
137 | new Space(),
138 | new Container(
139 | margin: EdgeInsets.symmetric(horizontal: 20.0),
140 | padding: EdgeInsets.only(right: 40),
141 | child: new Row(
142 | mainAxisAlignment: MainAxisAlignment.spaceAround,
143 | children: ['地区', '确诊', '死亡', '治愈'].map((item) {
144 | return new SizedBox(
145 | width: (winWidth(context) - 80) / 4,
146 | child: new Text(
147 | item,
148 | style: TextStyle(fontWeight: FontWeight.w600),
149 | ),
150 | );
151 | }).toList(),
152 | ),
153 | ),
154 | new Column(children: areaData.map(areaBuild).toList()),
155 | new Divider(),
156 | new Space(height: mainSpace / 2),
157 | new TitleView('防护知识'),
158 | isReq
159 | ? listNoEmpty(data)
160 | ? new Column(children: data.map(buildItem).toList())
161 | : new Center(
162 | child: new Text(
163 | '暂无数据',
164 | style: Theme.of(context).textTheme.display1,
165 | ),
166 | )
167 | : new LoadingView(),
168 | ],
169 | ),
170 | ),
171 | ),
172 | );
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/lib/pages/root/root_page.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:ncov_2019/api/version_model.dart';
5 | import 'package:ncov_2019/api/version_view_model.dart';
6 | import 'package:ncov_2019/commom/commom.dart';
7 | import 'package:ncov_2019/pages/home/home_page.dart';
8 | import 'package:ncov_2019/pages/lore/lore_page.dart';
9 | import 'package:ncov_2019/pages/protect/protect_page.dart';
10 | import 'package:ncov_2019/pages/rumor/rumor_page.dart';
11 | import 'package:ncov_2019/widget/dialog/update_dialog.dart';
12 | import 'package:ncov_2019/widget/root_tabbar.dart';
13 | import 'package:package_info/package_info.dart';
14 |
15 | class RootPage extends StatefulWidget {
16 | @override
17 | _RootPageState createState() => _RootPageState();
18 | }
19 |
20 | class _RootPageState extends State {
21 | @override
22 | void initState() {
23 | super.initState();
24 | checkVersion();
25 | }
26 |
27 | /// 检查更新 [check update]
28 | checkVersion() async {
29 | if (Platform.isIOS) return;
30 |
31 | final packageInfo = await PackageInfo.fromPlatform();
32 |
33 | VersionModel model = await versionViewModel.getData();
34 |
35 | int currentVersion = int.parse(removeDot(packageInfo.version));
36 |
37 | int netVersion = int.parse(removeDot(model.appVersion));
38 |
39 | if (currentVersion >= netVersion) {
40 | debugPrint('当前版本是最新版本');
41 | return;
42 | }
43 |
44 | showDialog(
45 | context: context,
46 | builder: (ctx2) {
47 | return UpdateDialog(
48 | version: model.appVersion,
49 | updateUrl: model.downloadUrl,
50 | updateInfo: model.updateInfo,
51 | isForce: model.force,
52 | );
53 | },
54 | );
55 | }
56 |
57 | @override
58 | Widget build(BuildContext context) {
59 | List pages = [
60 | new TabBarModel(
61 | title: '首页',
62 | icon: new LoadImage("assets/images/bottom_home.png", false),
63 | selectIcon: new LoadImage("assets/images/bottom_home.png", true),
64 | page: new HomePage(),
65 | ),
66 | new TabBarModel(
67 | title: '辟谣',
68 | icon: new LoadImage("assets/images/bottom_rumor.png", false),
69 | selectIcon: new LoadImage("assets/images/bottom_rumor.png", true),
70 | page: new RumorPage(),
71 | ),
72 | new TabBarModel(
73 | title: '防护合辑',
74 | icon: new LoadImage("assets/images/bottom_protect.png", false),
75 | selectIcon: new LoadImage("assets/images/bottom_protect.png", true),
76 | page: new ProtectPage(),
77 | ),
78 | new TabBarModel(
79 | title: '疾病知识',
80 | icon: new LoadImage("assets/images/bottom_lore.png", false),
81 | selectIcon: new LoadImage("assets/images/bottom_lore.png", true),
82 | page: new LorePage(),
83 | ),
84 | ];
85 | return new RootTabBar(pages: pages, currentIndex: 0);
86 | }
87 | }
88 |
89 | class LoadImage extends StatelessWidget {
90 | final String img;
91 | final bool isSelect;
92 |
93 | LoadImage(this.img, [this.isSelect = false]);
94 |
95 | @override
96 | Widget build(BuildContext context) {
97 | return new Container(
98 | margin: EdgeInsets.only(bottom: 2.0),
99 | width: 30.0,
100 | height: 30.0,
101 | child: new Image.asset(
102 | img,
103 | fit: BoxFit.cover,
104 | gaplessPlayback: true,
105 | color: isSelect ? fixedColor : mainTextColor,
106 | ),
107 | );
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/lib/pages/rumor/rumor_page.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:ncov_2019/api/entries_view_model.dart';
5 | import 'package:ncov_2019/api/rumor_view_model.dart';
6 | import 'package:ncov_2019/api/statistics_view_model.dart';
7 | import 'package:ncov_2019/commom/commom.dart';
8 | import 'package:ncov_2019/widget/card/rumor_card.dart';
9 | import 'package:ncov_2019/widget/item/entries.dart';
10 | import 'package:ncov_2019/widget/item/statics.dart';
11 | import 'package:pull_to_refresh/pull_to_refresh.dart';
12 |
13 | class RumorPage extends StatefulWidget {
14 | @override
15 | _RumorPageState createState() => _RumorPageState();
16 | }
17 |
18 | class _RumorPageState extends State
19 | with AutomaticKeepAliveClientMixin {
20 | List data = new List();
21 |
22 | bool isReq = false;
23 |
24 | List entriesData = new List();
25 |
26 | StatisticsModel statisticsModel = new StatisticsModel();
27 |
28 | RefreshController _refreshController =
29 | RefreshController(initialRefresh: false);
30 |
31 | @override
32 | void initState() {
33 | super.initState();
34 | Notice.addListener(NCOVActions.toTabBarIndex(), (index) {
35 | if (!listNoEmpty(data)) getData();
36 | });
37 | getData();
38 | }
39 |
40 | @override
41 | bool get wantKeepAlive => true;
42 |
43 | getData() {
44 | rumorListReqViewModel.getRumor().then((v) {
45 | setState(() {
46 | data = v;
47 | isReq = true;
48 | });
49 | });
50 | statisticsViewModel.getData().then((v) {
51 | setState(() => statisticsModel = v);
52 | });
53 | entriesViewModel.getData().then((v) {
54 | setState(() => entriesData = v);
55 | });
56 | }
57 |
58 | Future _refreshData() async {
59 | final Completer completer = new Completer();
60 |
61 | getData();
62 |
63 | new Future.delayed(new Duration(seconds: 2), () {
64 | completer.complete(null);
65 | _refreshController.refreshCompleted();
66 | });
67 |
68 | return completer.future;
69 | }
70 |
71 | Widget buildItem(item) {
72 | RumorListModel model = item;
73 | return new RumorCard(
74 | model,
75 | margin: EdgeInsets.only(
76 | left: 20.0,
77 | right: 20.0,
78 | top: model.id == data[0].id ? 20.0 : 10,
79 | bottom: model.id == data[data.length - 1].id ? 20.0 : 10,
80 | ),
81 | onTap: () {
82 | setState(() => model.isOpen = !model.isOpen);
83 | },
84 | );
85 | }
86 |
87 | @override
88 | Widget build(BuildContext context) {
89 | super.build(context);
90 | return new Scaffold(
91 | body: new SmartRefresher(
92 | controller: _refreshController,
93 | onRefresh: _refreshData,
94 | child: new ListView(
95 | children: [
96 | new Space(),
97 | new TitleView(
98 | '全国统计',
99 | subTitle: '${timeHandle(statisticsModel?.modifyTime ?? 0)}',
100 | ),
101 | new Statics(statisticsModel ?? null),
102 | new Divider(),
103 | new Space(height: mainSpace / 2),
104 | new Visibility(
105 | visible: strNoEmpty(statisticsModel?.imgUrl ?? ''),
106 | child: new TitleView('疫情地图', subTitle: '数据来源:国家及各省市地区卫健委'),
107 | ),
108 | new Visibility(
109 | visible: strNoEmpty(statisticsModel?.imgUrl ?? ''),
110 | child: new Padding(
111 | padding: EdgeInsets.only(top: 10.0),
112 | child: new CachedNetworkImage(
113 | imageUrl: statisticsModel?.imgUrl ?? defImg),
114 | ),
115 | ),
116 | new Visibility(
117 | visible: listNoEmpty(statisticsModel?.dailyPics),
118 | child: new Column(
119 | children: listNoEmpty(statisticsModel?.dailyPics)
120 | ? statisticsModel.dailyPics.map((pics) {
121 | return new CachedNetworkImage(imageUrl: pics);
122 | }).toList()
123 | : [],
124 | ),
125 | ),
126 | new Space(),
127 | new TitleView('诊疗'),
128 | new Container(
129 | margin: EdgeInsets.symmetric(horizontal: 10.0),
130 | child: new Wrap(
131 | children: entriesData.map((item) {
132 | EntriesModel model = item;
133 | return Entries(model);
134 | }).toList(),
135 | ),
136 | ),
137 | new TitleView('辟谣', subTitle: '消息数量:${data.length}'),
138 | isReq
139 | ? listNoEmpty(data)
140 | ? new Column(
141 | children: data.map(buildItem).toList(),
142 | )
143 | : new Center(
144 | child: new Text(
145 | '暂无数据',
146 | style: Theme.of(context).textTheme.display1,
147 | ),
148 | )
149 | : new LoadingView(),
150 | ],
151 | ),
152 | ),
153 | );
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/lib/widget/bar/commom_bar.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/cupertino.dart';
3 | import 'package:ncov_2019/config/const.dart';
4 |
5 | class ComMomBar extends StatelessWidget implements PreferredSizeWidget {
6 | const ComMomBar({
7 | this.title = '',
8 | this.showShadow = false,
9 | this.rightDMActions,
10 | this.backgroundColor = appBarColor,
11 | this.mainColor = Colors.white,
12 | this.titleW,
13 | this.bottom,
14 | this.leadingImg = '',
15 | this.leadingW,
16 | });
17 |
18 | final String title;
19 | final bool showShadow;
20 | final List rightDMActions;
21 | final Color backgroundColor;
22 | final Color mainColor;
23 | final Widget titleW;
24 | final Widget leadingW;
25 | final PreferredSizeWidget bottom;
26 | final String leadingImg;
27 |
28 | @override
29 | Size get preferredSize => new Size(100, 50);
30 |
31 | Widget leading(BuildContext context) {
32 | final bool isShow = Navigator.canPop(context);
33 | if (isShow) {
34 | return new InkWell(
35 | child: new Container(
36 | width: 15,
37 | height: 28,
38 | child: leadingImg != ''
39 | ? new Image.asset(leadingImg)
40 | : new Icon(CupertinoIcons.back, color: mainColor),
41 | ),
42 | onTap: () {
43 | if (Navigator.canPop(context)) {
44 | FocusScope.of(context).requestFocus(new FocusNode());
45 | Navigator.pop(context);
46 | }
47 | },
48 | );
49 | } else {
50 | return null;
51 | }
52 | }
53 |
54 | @override
55 | Widget build(BuildContext context) {
56 | return showShadow
57 | ? new Container(
58 | decoration: BoxDecoration(
59 | border: Border(
60 | bottom: new BorderSide(
61 | color: Colors.grey, width: showShadow ? 0.5 : 0.0))),
62 | child: new AppBar(
63 | title: titleW == null
64 | ? new Text(
65 | title,
66 | style: new TextStyle(
67 | color: mainColor,
68 | fontSize: 17.0,
69 | fontWeight: FontWeight.w500),
70 | )
71 | : titleW,
72 | backgroundColor: mainColor,
73 | elevation: 0.0,
74 | brightness: Brightness.dark,
75 | leading: leadingW ?? leading(context),
76 | centerTitle: true,
77 | actions: rightDMActions ?? [new Center()],
78 | bottom: bottom != null ? bottom : null,
79 | ),
80 | )
81 | : new AppBar(
82 | title: titleW == null
83 | ? new Text(
84 | title,
85 | style: new TextStyle(
86 | color: mainColor,
87 | fontSize: 17.0,
88 | fontWeight: FontWeight.w500),
89 | )
90 | : titleW,
91 | backgroundColor: backgroundColor,
92 | elevation: 0.0,
93 | brightness: Brightness.dark,
94 | leading: leadingW ?? leading(context),
95 | centerTitle: false,
96 | bottom: bottom != null ? bottom : null,
97 | actions: rightDMActions ?? [new Center()],
98 | );
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/lib/widget/card/lore_card.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ncov_2019/api/lore_view_model.dart';
3 | import 'package:ncov_2019/commom/commom.dart';
4 |
5 | class LoreCard extends StatelessWidget {
6 | final LoreModel model;
7 | final EdgeInsetsGeometry margin;
8 |
9 | LoreCard(this.model, {@required this.margin});
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | return Container(
14 | decoration: BoxDecoration(
15 | border: Border(bottom: BorderSide(color: lineColor, width: 0.2)),
16 | ),
17 | margin: margin,
18 | child: new FlatButton(
19 | onPressed: () => routePush(
20 | new WebViewPage(model?.linkUrl ?? 'http://book.flutterj.com/',
21 | '${model?.title ?? '未知'}'),
22 | ),
23 | child: new Row(
24 | children: [
25 | new Visibility(
26 | visible: strNoEmpty(model?.imgUrl),
27 | child: new ClipRRect(
28 | borderRadius: BorderRadius.all(Radius.circular(5.0)),
29 | child: new CachedNetworkImage(
30 | imageUrl: '${model.imgUrl}',
31 | height: 102.0,
32 | width: 102.0,
33 | fit: BoxFit.cover,
34 | ),
35 | ),
36 | ),
37 | new Space(),
38 | new Expanded(
39 | child: new Container(
40 | padding: EdgeInsets.symmetric(vertical: 25.0),
41 | child: new Column(
42 | crossAxisAlignment: CrossAxisAlignment.start,
43 | children: [
44 | new Text(
45 | '${model?.title ?? '未知'}',
46 | style: TextStyle(
47 | fontSize: 16.0, fontWeight: FontWeight.w600),
48 | ),
49 | new Space(height: 15.0),
50 | new Text(
51 | '${model?.description ?? '未知'}',
52 | style: TextStyle(color: mainTextColor),
53 | ),
54 | ],
55 | ),
56 | ),
57 | ),
58 | ],
59 | ),
60 | ),
61 | );
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/lib/widget/card/news_card.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ncov_2019/api/news_model.dart';
3 | import 'package:ncov_2019/commom/commom.dart';
4 |
5 | class NewsCard extends StatelessWidget {
6 | final TimeNewsModel model;
7 | final EdgeInsetsGeometry padding;
8 | final bool isNew;
9 |
10 | NewsCard(
11 | this.model, {
12 | @required this.padding,
13 | this.isNew = false,
14 | });
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | double pubDateDouble =
19 | strNoEmpty('${model?.pubDate}') ? model.pubDate / 1000 : 0;
20 | int pubDate = int.parse('${stringDisposeWithDouble(pubDateDouble)}');
21 |
22 | bool isTimeStr =
23 | DateTime.now().millisecondsSinceEpoch - model?.pubDate < 43200000;
24 | return Container(
25 | padding: padding,
26 | alignment: Alignment.centerLeft,
27 | width: winWidth(context),
28 | child: new FlatButton(
29 | onPressed: () => routePush(
30 | new WebViewPage(model?.sourceUrl ?? 'http://book.flutterj.com/',
31 | '${model?.title ?? '未知'}'),
32 | ),
33 | color: Colors.white,
34 | padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 15.0),
35 | shape: RoundedRectangleBorder(
36 | borderRadius: BorderRadius.all(Radius.circular(5.0)),
37 | ),
38 | child: new Column(
39 | crossAxisAlignment: CrossAxisAlignment.start,
40 | children: [
41 | new Row(
42 | children: [
43 | new Visibility(
44 | visible: isNew,
45 | child: new Container(
46 | decoration: BoxDecoration(
47 | color: Colors.redAccent,
48 | borderRadius: BorderRadius.all(Radius.circular(5.0))),
49 | alignment: Alignment.center,
50 | padding: EdgeInsets.symmetric(horizontal: 3.0, vertical: 2),
51 | margin: EdgeInsets.only(right: 5.0),
52 | child: new Text(
53 | '最新',
54 | style: TextStyle(color: Colors.white),
55 | ),
56 | ),
57 | ),
58 | new SizedBox(
59 | width:
60 | isNew ? winWidth(context) - 120 : winWidth(context) - 70,
61 | child: new Text(
62 | '${model?.title ?? '未知'}',
63 | style:
64 | TextStyle(fontSize: 16.0, fontWeight: FontWeight.w600),
65 | maxLines: 1,
66 | overflow: TextOverflow.ellipsis,
67 | ),
68 | )
69 | ],
70 | ),
71 | new Padding(
72 | padding: EdgeInsets.symmetric(vertical: 10.0),
73 | child: new Text(
74 | '${model?.summary ?? '未知'}',
75 | maxLines: 5,
76 | overflow: TextOverflow.ellipsis,
77 | style: TextStyle(color: Color(0xff999999), fontSize: 12.0),
78 | ),
79 | ),
80 | new Row(
81 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
82 | children: [
83 | new Text(
84 | '时间:${isTimeStr ? model?.pubDateStr ?? '未知' : formatTimeStampToString(pubDate) ?? '未知'}',
85 | style: TextStyle(color: Color(0xff999999), fontSize: 13.0),
86 | ),
87 | new Text(
88 | '来源:${model?.infoSource ?? '未知'}',
89 | style: TextStyle(color: Color(0xff999999), fontSize: 13.0),
90 | ),
91 | ],
92 | )
93 | ],
94 | ),
95 | ),
96 | );
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/lib/widget/card/protect_card.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ncov_2019/api/protect_view_model.dart';
3 | import 'package:ncov_2019/commom/commom.dart';
4 |
5 | class ProtectCard extends StatelessWidget {
6 | final ProtectModel model;
7 | final EdgeInsetsGeometry margin;
8 |
9 | ProtectCard(this.model, {@required this.margin});
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | return Container(
14 | decoration: BoxDecoration(
15 | border: Border(bottom: BorderSide(color: lineColor, width: 0.2)),
16 | ),
17 | margin: margin,
18 | child: new FlatButton(
19 | onPressed: () => routePush(
20 | new WebViewPage(model?.linkUrl ?? 'http://book.flutterj.com/',
21 | '${model?.title ?? '未知'}'),
22 | ),
23 | child: new Row(
24 | children: [
25 | new Expanded(
26 | child: new Container(
27 | padding: EdgeInsets.symmetric(vertical: 25.0),
28 | child: new Column(
29 | crossAxisAlignment: CrossAxisAlignment.start,
30 | children: [
31 | new Text(
32 | '${model?.title ?? '未知'}',
33 | style: TextStyle(
34 | fontSize: 16.0, fontWeight: FontWeight.w600),
35 | ),
36 | new Space(height: 15.0),
37 | new Text(
38 | '${timeHandle(model?.createTime ?? 0)}',
39 | style: TextStyle(color: mainTextColor),
40 | ),
41 | ],
42 | ),
43 | ),
44 | ),
45 | new ClipRRect(
46 | borderRadius: BorderRadius.all(Radius.circular(5.0)),
47 | child: new CachedNetworkImage(
48 | imageUrl:
49 | '${strNoEmpty(model?.imgUrl) ? model.imgUrl : defImg}',
50 | height: 68.0,
51 | width: 91.0,
52 | fit: BoxFit.cover,
53 | ),
54 | )
55 | ],
56 | ),
57 | ),
58 | );
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/lib/widget/card/rumor_card.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ncov_2019/api/rumor_view_model.dart';
3 | import 'package:ncov_2019/commom/commom.dart';
4 |
5 | class RumorCard extends StatelessWidget {
6 | final RumorListModel model;
7 | final EdgeInsetsGeometry margin;
8 | final GestureTapCallback onTap;
9 |
10 | RumorCard(this.model, {@required this.margin, this.onTap});
11 |
12 | static TextStyle defStyle = TextStyle(
13 | color: Color(0xff999999), fontSize: 16.0, fontWeight: FontWeight.w600);
14 |
15 | @override
16 | Widget build(BuildContext context) {
17 | return new Container(
18 | margin: margin,
19 | padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 15.0),
20 | decoration: BoxDecoration(
21 | borderRadius: BorderRadius.all(Radius.circular(5.0)),
22 | gradient: LinearGradient(
23 | colors: [Color(0xff68869e), Color(0xff292f4b)],
24 | ),
25 | ),
26 | child: new Column(
27 | crossAxisAlignment: CrossAxisAlignment.start,
28 | children: [
29 | new Text(
30 | '${model?.title ?? '未知'}',
31 | style: TextStyle(
32 | fontSize: 20.0,
33 | fontWeight: FontWeight.w600,
34 | color: Colors.white,
35 | ),
36 | maxLines: 2,
37 | overflow: TextOverflow.ellipsis,
38 | ),
39 | new Container(
40 | padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 15.0),
41 | decoration: BoxDecoration(
42 | color: Colors.white,
43 | borderRadius: BorderRadius.all(Radius.circular(5.0)),
44 | ),
45 | margin: EdgeInsets.symmetric(vertical: 10.0),
46 | child: new Column(
47 | crossAxisAlignment: CrossAxisAlignment.start,
48 | children: [
49 | new Text('${model?.mainSummary ?? '未知'}', style: defStyle),
50 | new Text('${model?.summary ?? '未知'}', style: defStyle),
51 | new Space(),
52 | new Visibility(
53 | visible: model.isOpen,
54 | child: new Text(
55 | '${model?.body ?? '未知'}',
56 | style: TextStyle(color: Color(0xff999999), fontSize: 16.0),
57 | ),
58 | ),
59 | new GestureDetector(
60 | child: new Padding(
61 | padding: EdgeInsets.all(3.0),
62 | child: new Row(
63 | mainAxisAlignment: MainAxisAlignment.end,
64 | children: [
65 | new Text(
66 | '${model.isOpen ? '收起' : '展开'}详情',
67 | style: TextStyle(
68 | color: Color(0xff999999),
69 | fontSize: 12.0,
70 | fontWeight: FontWeight.w600,
71 | ),
72 | ),
73 | new Icon(
74 | model.isOpen
75 | ? Icons.keyboard_arrow_up
76 | : Icons.keyboard_arrow_down,
77 | color: Color(0xff999999),
78 | )
79 | ],
80 | ),
81 | ),
82 | onTap: () {
83 | if (onTap != null) {
84 | onTap();
85 | }
86 | },
87 | ),
88 | ],
89 | ),
90 | )
91 | ],
92 | ),
93 | );
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/lib/widget/item/entries.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ncov_2019/api/entries_view_model.dart';
3 | import 'package:ncov_2019/commom/commom.dart';
4 |
5 | class Entries extends StatelessWidget {
6 | final EntriesModel model;
7 |
8 | Entries(this.model);
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return new Container(
13 | width: (winWidth(context) - 20) / 3,
14 | padding: EdgeInsets.symmetric(vertical: 10.0),
15 | child: new FlatButton(
16 | onPressed: () => routePush(
17 | new WebViewPage(model?.linkUrl ?? 'http://book.flutterj.com/',
18 | '${model?.configName ?? '未知'}'),
19 | ),
20 | child: new Padding(
21 | padding: EdgeInsets.symmetric(vertical: 5.0),
22 | child: new Column(
23 | children: [
24 | new Image.asset('${model.icon}', width: 50.0, height: 50.0),
25 | new Padding(
26 | padding: EdgeInsets.only(top: 2.0),
27 | child: new Text(
28 | '${model.configName}',
29 | overflow: TextOverflow.ellipsis,
30 | style: TextStyle(fontSize: 12.0, color: mainTextColor),
31 | ),
32 | ),
33 | ],
34 | ),
35 | ),
36 | ),
37 | );
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/lib/widget/item/statics.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ncov_2019/api/statistics_view_model.dart';
3 | import 'package:ncov_2019/commom/commom.dart';
4 |
5 | class Statics extends StatelessWidget {
6 | final StatisticsModel statisticsModel;
7 |
8 | Statics(this.statisticsModel);
9 |
10 | Color strColor(name) {
11 | switch (name) {
12 | case '全国确诊':
13 | return Colors.red;
14 | break;
15 | case '疑似病例':
16 | return Colors.amber;
17 | break;
18 | case '治愈人数':
19 | return Colors.green;
20 | break;
21 | case '死亡人数':
22 | return Colors.grey;
23 | break;
24 | }
25 | return Colors.black;
26 | }
27 |
28 | static TextStyle defStyle =
29 | TextStyle(fontSize: 15.0, fontWeight: FontWeight.w600);
30 |
31 | Color iconColor(String label) {
32 | switch (label) {
33 | case '传染源':
34 | return Colors.blueAccent;
35 | break;
36 | case '病毒':
37 | return Colors.blueAccent;
38 | break;
39 | case '传播途径':
40 | return Colors.blueAccent;
41 | break;
42 | default:
43 | return Colors.red;
44 | break;
45 | }
46 | }
47 |
48 | @override
49 | Widget build(BuildContext context) {
50 | if (statisticsModel == null) {
51 | return LinearProgressIndicator();
52 | }
53 |
54 | List personInfo = [
55 | {'label': '全国确诊', 'value': '${statisticsModel?.confirmedCount ?? 0}'},
56 | {'label': '疑似病例', 'value': '${statisticsModel?.suspectedCount ?? 0}'},
57 | {'label': '治愈人数', 'value': '${statisticsModel?.curedCount ?? 0}'},
58 | {'label': '死亡人数', 'value': '${statisticsModel?.deadCount ?? 0}'},
59 | ];
60 |
61 | bool contains1Big = statisticsModel.remark1.contains(':');
62 | bool contains1Small = statisticsModel.remark1.contains(':');
63 | bool containsOr = contains1Big || contains1Small;
64 | Pattern splitStr = contains1Big ? ':' : ':';
65 |
66 | List note1 = strNoEmpty(statisticsModel?.note1) && containsOr
67 | ? statisticsModel.note1.split(splitStr)
68 | : ['未知', '未知'];
69 | List note2 = strNoEmpty(statisticsModel?.note2) && containsOr
70 | ? statisticsModel.note2.split(splitStr)
71 | : ['未知', '未知'];
72 | List note3 = strNoEmpty(statisticsModel?.note3) && containsOr
73 | ? statisticsModel.note3.split(splitStr)
74 | : ['未知', '未知'];
75 | List remark1 = strNoEmpty(statisticsModel?.remark1) && containsOr
76 | ? statisticsModel.remark1.split(splitStr)
77 | : ['未知', '未知'];
78 | List remark2 = strNoEmpty(statisticsModel?.remark2) && containsOr
79 | ? statisticsModel.remark2.split(splitStr)
80 | : ['未知', '未知'];
81 |
82 | List staticsInfo = [
83 | {'label': '${note1[0]}', 'value': '${note1[1]}'},
84 | {'label': '${note2[0]}', 'value': '${note2[1]}'},
85 | {'label': '${note3[0]}', 'value': '${note3[1]}'},
86 | {'label': '${remark1[0]}', 'value': '${remark1[1]}'},
87 | {'label': '${remark2[0]}', 'value': '${remark2[1]}'},
88 | ];
89 |
90 | Widget itemBuild(item) {
91 | PersonInfoModel model = PersonInfoModel(item);
92 | return FlatButton(
93 | onPressed: () {},
94 | padding: EdgeInsets.symmetric(vertical: 10.0),
95 | child: new SizedBox(
96 | width: (winWidth(context) - 20) / 4,
97 | child: new Column(
98 | children: [
99 | new Text(
100 | '${model.value}',
101 | style: TextStyle(
102 | fontSize: 22.0,
103 | fontWeight: FontWeight.w600,
104 | color: strColor(model.label),
105 | ),
106 | ),
107 | new Text(
108 | '${model.label}',
109 | style: TextStyle(fontSize: 13.0),
110 | ),
111 | ],
112 | ),
113 | ),
114 | );
115 | }
116 |
117 | Widget _staticsBuild(item) {
118 | PersonInfoModel model = PersonInfoModel(item);
119 |
120 | return new SizedBox(
121 | width: winWidth(context) - 20,
122 | child: new Column(
123 | crossAxisAlignment: CrossAxisAlignment.start,
124 | children: [
125 | new Visibility(
126 | visible: model.label != '病毒',
127 | child: new Space(),
128 | ),
129 | new SizedBox(
130 | width: 120,
131 | child: new Row(
132 | children: [
133 | new Icon(
134 | Icons.insert_chart,
135 | color: iconColor(model.label),
136 | ),
137 | new Space(width: mainSpace / 2),
138 | new Text('${model.label}:', style: defStyle),
139 | ],
140 | ),
141 | ),
142 | new Text(
143 | ' · ${model.value}',
144 | style: defStyle,
145 | maxLines: 5,
146 | overflow: TextOverflow.ellipsis,
147 | ),
148 | ],
149 | ),
150 | );
151 | }
152 |
153 | return new Column(
154 | children: [
155 | new Container(
156 | padding: EdgeInsets.symmetric(horizontal: 10.0),
157 | margin: EdgeInsets.only(top: 10.0),
158 | child: new Row(
159 | children: personInfo.map(itemBuild).toList(),
160 | ),
161 | ),
162 | new Divider(),
163 | new Container(
164 | padding: EdgeInsets.symmetric(horizontal: 10.0),
165 | margin: EdgeInsets.symmetric(vertical: 10.0),
166 | child: new Column(
167 | children: staticsInfo.map(_staticsBuild).toList(),
168 | ),
169 | )
170 | ],
171 | );
172 | }
173 | }
174 |
175 | class PersonInfoModel {
176 | String label;
177 | String value;
178 |
179 | PersonInfoModel(Map value) {
180 | this.label = value['label'];
181 | this.value = value['value'];
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/lib/widget/orther/turn_box.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/widgets.dart';
2 |
3 | /// Animates the rotation of a widget when [turns] is changed.
4 |
5 | class TurnBox extends StatefulWidget {
6 | const TurnBox({
7 | Key key,
8 | this.turns = .0,
9 | this.speed = 200,
10 | this.child,
11 | }) : super(key: key);
12 |
13 | /// Controls the rotation of the child.
14 | ///
15 | /// If the current value of the turns is v, the child will be
16 | /// rotated v * 2 * pi radians before being painted.
17 | final double turns;
18 |
19 | /// Animation duration in milliseconds
20 | final int speed;
21 |
22 | final Widget child;
23 |
24 | @override
25 | _TurnBoxState createState() => new _TurnBoxState();
26 | }
27 |
28 | class _TurnBoxState extends State with SingleTickerProviderStateMixin {
29 | AnimationController _controller;
30 |
31 | @override
32 | void initState() {
33 | super.initState();
34 | _controller = new AnimationController(
35 | vsync: this, lowerBound: -double.infinity, upperBound: double.infinity);
36 | _controller.value = widget.turns;
37 | }
38 |
39 | @override
40 | void dispose() {
41 | _controller.dispose();
42 | super.dispose();
43 | }
44 |
45 | @override
46 | Widget build(BuildContext context) {
47 | return RotationTransition(
48 | turns: _controller,
49 | child: widget.child,
50 | );
51 | }
52 |
53 | @override
54 | void didUpdateWidget(TurnBox oldWidget) {
55 | super.didUpdateWidget(oldWidget);
56 | if (oldWidget.turns != widget.turns) {
57 | _controller.animateTo(
58 | widget.turns,
59 | duration: Duration(milliseconds: widget.speed ?? 200),
60 | curve: Curves.easeOut,
61 | );
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/lib/widget/root_tabbar.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:ncov_2019/commom/commom.dart';
6 | import 'package:ncov_2019/config/const.dart';
7 | import 'package:ncov_2019/widget/scroll/my_behavior.dart';
8 | import 'package:url_launcher/url_launcher.dart';
9 |
10 | class RootTabBar extends StatefulWidget {
11 | RootTabBar({this.pages, this.currentIndex = 0});
12 |
13 | final List pages;
14 | final int currentIndex;
15 |
16 | @override
17 | State createState() => new RootTabBarState();
18 | }
19 |
20 | class RootTabBarState extends State {
21 | var pages = new List();
22 | int currentIndex;
23 | var contents = new List();
24 | PageController pageController;
25 |
26 | @override
27 | void initState() {
28 | super.initState();
29 | currentIndex = widget.currentIndex;
30 | pageController = PageController(initialPage: currentIndex);
31 | for (int i = 0; i < widget.pages.length; i++) {
32 | TabBarModel model = widget.pages[i];
33 | pages.add(
34 | new BottomNavigationBarItem(
35 | icon: model.icon,
36 | activeIcon: model.selectIcon,
37 | title: new Text(model.title, style: new TextStyle(fontSize: 12.0)),
38 | ),
39 | );
40 | }
41 | }
42 |
43 | @override
44 | Widget build(BuildContext context) {
45 | final BottomNavigationBar bottomNavigationBar = new BottomNavigationBar(
46 | items: pages,
47 | type: BottomNavigationBarType.fixed,
48 | currentIndex: currentIndex,
49 | unselectedItemColor: mainTextColor,
50 | fixedColor: fixedColor,
51 | onTap: (int index) {
52 | setState(() => currentIndex = index);
53 | pageController.jumpToPage(currentIndex);
54 | Notice.send(NCOVActions.toTabBarIndex(), index);
55 | },
56 | unselectedFontSize: 18.0,
57 | selectedFontSize: 18.0,
58 | elevation: 0,
59 | );
60 |
61 | String title() {
62 | if (currentIndex == 0) {
63 | return '首页';
64 | } else if (currentIndex == 1) {
65 | return '辟谣';
66 | } else if (currentIndex == 2) {
67 | return '防护';
68 | } else {
69 | return '知识';
70 | }
71 | }
72 |
73 | return new Scaffold(
74 | bottomNavigationBar: new Theme(
75 | data: new ThemeData(
76 | canvasColor: Colors.grey[50],
77 | highlightColor: Colors.transparent,
78 | splashColor: Colors.transparent,
79 | ),
80 | child: new Container(
81 | decoration: BoxDecoration(
82 | border: Border(top: BorderSide(color: lineColor, width: 0.2))),
83 | child: bottomNavigationBar,
84 | ),
85 | ),
86 | appBar: new ComMomBar(
87 | titleW: new AnimatedSwitcher(
88 | duration: Duration(milliseconds: 400),
89 | transitionBuilder: (Widget child, Animation animation) {
90 | var tween = Tween(begin: 0, end: 1);
91 | return FadeTransition(
92 | child: child,
93 | opacity: tween.animate(animation),
94 | );
95 | },
96 | child: new Text(
97 | title() ?? '',
98 | key: ValueKey(title() ?? ''),
99 | style: TextStyle(color: Colors.white, fontSize: 20.0),
100 | ),
101 | ),
102 | rightDMActions: [
103 | new MaterialButton(
104 | onPressed: () => launch('https://github.com/ahyangnb/ncov_2019'),
105 | padding: EdgeInsets.symmetric(horizontal: 10.0),
106 | child: new Text(
107 | '开源地址',
108 | style: TextStyle(color: Colors.white),
109 | ),
110 | )
111 | ],
112 | ),
113 | body: new ScrollConfiguration(
114 | behavior: MyBehavior(),
115 | child: new PageView.builder(
116 | itemBuilder: (BuildContext context, int index) =>
117 | widget.pages[index].page,
118 | controller: pageController,
119 | itemCount: pages.length,
120 | physics: Platform.isAndroid
121 | ? new ClampingScrollPhysics()
122 | : new NeverScrollableScrollPhysics(),
123 | onPageChanged: (int index) {
124 | setState(() => currentIndex = index);
125 | },
126 | ),
127 | ),
128 | );
129 | }
130 | }
131 |
132 | class TabBarModel {
133 | const TabBarModel({this.title, this.page, this.icon, this.selectIcon});
134 |
135 | final String title;
136 | final Widget icon;
137 | final Widget selectIcon;
138 | final Widget page;
139 | }
140 |
--------------------------------------------------------------------------------
/lib/widget/scroll/my_behavior.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 | import 'package:flutter/material.dart';
3 |
4 | class MyBehavior extends ScrollBehavior {
5 | @override
6 | Widget buildViewportChrome(
7 | BuildContext context, Widget child, AxisDirection axisDirection) {
8 | if (Platform.isAndroid || Platform.isFuchsia) {
9 | return child;
10 | } else {
11 | return super.buildViewportChrome(context, child, axisDirection);
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/lib/widget/view/loading_view.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ncov_2019/commom/commom.dart';
3 |
4 | class LoadingView extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return new SizedBox(
8 | width: winWidth(context),
9 | child: new Column(
10 | mainAxisAlignment: MainAxisAlignment.center,
11 | children: [
12 | new CircularProgressIndicator(),
13 | new Space(),
14 | new Text(
15 | '加载中',
16 | style: TextStyle(color: mainTextColor),
17 | ),
18 | ],
19 | ),
20 | );
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lib/widget/view/title_view.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ncov_2019/commom/commom.dart';
3 |
4 | class TitleView extends StatelessWidget {
5 | final String title;
6 | final String subTitle;
7 |
8 | TitleView(this.title, {this.subTitle = ''});
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return new Row(
13 | children: [
14 | new Container(
15 | margin: EdgeInsets.only(left: 10.0),
16 | decoration: BoxDecoration(
17 | color: appBarColor,
18 | borderRadius: BorderRadius.all(Radius.circular(2.0)),
19 | ),
20 | width: 5.0,
21 | height: 15.0,
22 | ),
23 | new Space(width: 10.0),
24 | new Text(
25 | '$title',
26 | style: TextStyle(fontSize: 17.0, fontWeight: FontWeight.w600),
27 | ),
28 | new Spacer(),
29 | new Text(
30 | strNoEmpty(subTitle) ? '$subTitle' : '',
31 | style: TextStyle(color: mainTextColor),
32 | ),
33 | new Space(),
34 | ],
35 | );
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/lib/widget/view/web_view_page.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'package:flutter/cupertino.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:webview_flutter/webview_flutter.dart';
5 | import 'package:ncov_2019/commom/commom.dart';
6 |
7 | class WebViewPage extends StatefulWidget {
8 | final String url;
9 | final String title;
10 |
11 | WebViewPage(this.url, this.title);
12 |
13 | @override
14 | State createState() => new WebViewPageState();
15 | }
16 |
17 | class WebViewPageState extends State {
18 | final Completer _controller =
19 | new Completer();
20 | WebViewController _webViewController;
21 |
22 | @override
23 | Widget build(BuildContext context) {
24 | return Scaffold(
25 | backgroundColor: Colors.white,
26 | appBar: new ComMomBar(title: widget.title ?? ''),
27 | body: new WillPopScope(
28 | child: new Builder(builder: (BuildContext context) {
29 | return new WebView(
30 | initialUrl: widget.url,
31 | javascriptMode: JavascriptMode.unrestricted,
32 | onWebViewCreated: (WebViewController webViewController) {
33 | _controller.complete(webViewController);
34 | _webViewController = webViewController;
35 | },
36 | javascriptChannels: [
37 | _toasterJavascriptChannel(context),
38 | ].toSet(),
39 | navigationDelegate: (NavigationRequest request) {
40 | if (request.url
41 | .startsWith('https://github.com/ahyangnb/ncov_2019')) {
42 | print('blocking navigation to $request}');
43 | return NavigationDecision.prevent;
44 | }
45 | print('allowing navigation to $request');
46 | return NavigationDecision.navigate;
47 | },
48 | onPageFinished: (String url) {
49 | print('Page finished loading: $url');
50 | },
51 | );
52 | }),
53 | onWillPop: () => pop(),
54 | ),
55 | );
56 | }
57 |
58 | Future pop() async {
59 | bool canGoBack = await _webViewController.canGoBack();
60 |
61 | if (canGoBack) {
62 | _webViewController.goBack();
63 |
64 | return false;
65 | } else {
66 | return true;
67 | }
68 | }
69 |
70 | JavascriptChannel _toasterJavascriptChannel(BuildContext context) {
71 | return new JavascriptChannel(
72 | name: 'Toaster',
73 | onMessageReceived: (JavascriptMessage message) {
74 | Scaffold.of(context).showSnackBar(
75 | new SnackBar(content: Text(message.message)),
76 | );
77 | },
78 | );
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: ncov_2019
2 | description: A new Flutter project.
3 |
4 | version: 0.0.10+10
5 |
6 | environment:
7 | sdk: ">=2.1.0 <3.0.0"
8 |
9 | dependencies:
10 | flutter:
11 | sdk: flutter
12 | cupertino_icons: ^0.1.2
13 | # dio: 2.2.2 #低于Flutter-1.17使用此版本
14 | dio: ^3.0.9
15 | nav_router: ^0.0.5
16 | webview_flutter: ^0.3.12
17 | device_info: ^0.4.0+1
18 | package_info: ^0.4.0+6
19 | pull_to_refresh: ^1.5.6
20 | flutter_swiper: ^1.1.6
21 | # cached_network_image: ^1.1.1 # ^1.9.0左右flutter版本的用这个
22 | cached_network_image: ^2.0.0 # ^2.0.0左右flutter版本直接用这个
23 | shared_preferences: ^0.5.2+2
24 | intl: ^0.16.1
25 | open_file: ^2.1.1
26 | url_launcher: ^5.2.7
27 | connectivity: ^0.4.6
28 |
29 | dev_dependencies:
30 | flutter_test:
31 | sdk: flutter
32 |
33 |
34 | flutter:
35 |
36 | uses-material-design: true
37 |
38 | assets:
39 | - assets/images/bottom_home.png
40 | - assets/images/bottom_rumor.png
41 | - assets/images/bottom_protect.png
42 | - assets/images/bottom_lore.png
43 | - assets/images/entries_1.png
44 | - assets/images/entries_2.png
45 | - assets/images/entries_3.png
46 | - assets/images/entries_4.png
47 | - assets/images/entries_5.png
48 |
--------------------------------------------------------------------------------