├── .gitignore
├── .metadata
├── LICENSE
├── README.md
├── android
├── app
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ ├── com
│ │ │ └── zrgteam
│ │ │ │ └── tinmoi
│ │ │ │ └── MainActivity.java
│ │ └── io
│ │ │ └── flutter
│ │ │ └── plugins
│ │ │ └── GeneratedPluginRegistrant.java
│ │ └── res
│ │ ├── drawable
│ │ ├── launch_background.xml
│ │ └── splash.png
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── launcher_icon.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── launcher_icon.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── launcher_icon.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── launcher_icon.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── launcher_icon.png
│ │ └── values
│ │ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── settings.gradle
├── assets
├── fonts
│ ├── FFF_Tusj.ttf
│ ├── Poppins-SemiBold.ttf
│ └── circle.ttf
├── images
│ ├── banner-1.png
│ ├── banner-2.png
│ ├── banner-3.png
│ ├── banner-icon-2.png
│ ├── banner1.png
│ ├── chinhphu.jpg
│ ├── congnghe.jpg
│ ├── giaitri.jpg
│ ├── giaoduc.jpg
│ ├── honnhan.jpg
│ ├── icon-banner-1.png
│ ├── ictnews.png
│ ├── khoahoc.jpg
│ ├── kienthuc.jpeg
│ ├── kinhdoanh.jpg
│ ├── kinhte.jpg
│ ├── lamdep.jpg
│ ├── laodong.jpg
│ ├── latest.jpg
│ ├── login.jpg
│ ├── noimage-reading.jpg
│ ├── noimage.jpg
│ ├── petrotimes.png
│ ├── phapluat.png
│ ├── saostart.jpg
│ ├── swipe-left.png
│ ├── swipeleft.png
│ ├── swiperight.png
│ ├── thanhnien.jpg
│ ├── thegioi.jpg
│ ├── thethao.jpg
│ ├── tick.png
│ ├── tienphong.png
│ ├── tinhot.png
│ ├── vanhoa.jpg
│ ├── videoplayer.jpg
│ ├── vietnamfinance.png
│ ├── vietnamnet.png
│ ├── vietnamplus.jpg
│ ├── vnmedia.png
│ ├── vov.jpg
│ ├── vtc.png
│ ├── xahoi.jpg
│ └── zing.png
└── store
│ ├── feature-graphic.png
│ ├── good-3.png
│ ├── good-4.png
│ ├── good-5.png
│ ├── good-6.png
│ ├── good-7.png
│ ├── hi-res.png
│ ├── icon.png
│ ├── store-2.png
│ ├── store-3-512.jpg
│ ├── store-3.jpg
│ ├── store-3.png
│ ├── store-4.png
│ ├── store.png
│ └── store.svg
├── documents
└── ABOUT.md
├── ios
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Podfile
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
└── Runner
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-App-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
│ ├── Info.plist
│ └── main.m
├── lib
├── common
│ ├── actions
│ │ └── common.dart
│ ├── components
│ │ ├── BottomBar.dart
│ │ ├── ContentLoading.dart
│ │ ├── Form.dart
│ │ ├── FrostedGlassAppBar.dart
│ │ ├── GradientAppBar.dart
│ │ ├── ImageCached.dart
│ │ ├── InputFields.dart
│ │ ├── MainDrawer.dart
│ │ ├── MiniNewsList.dart
│ │ ├── MiniNewsfeed.dart
│ │ ├── NewsList.dart
│ │ ├── Newsfeed.dart
│ │ └── SpinLoading.dart
│ ├── configs.dart
│ ├── reducers
│ │ ├── app.dart
│ │ └── common.dart
│ ├── repository.dart
│ ├── state.dart
│ ├── states
│ │ └── common.dart
│ ├── store.dart
│ └── utils
│ │ └── navigation.dart
├── main.dart
├── modules
│ ├── category
│ │ ├── actions.dart
│ │ ├── components
│ │ │ ├── CategoriesView.dart
│ │ │ ├── NewDetailTopicView.dart
│ │ │ ├── SubNewsView.dart
│ │ │ ├── TopicDetailView.dart
│ │ │ └── TopicItemView.dart
│ │ ├── containers
│ │ │ └── SubNews.dart
│ │ └── repository.dart
│ ├── dashboard
│ │ ├── actions.dart
│ │ ├── components
│ │ │ ├── ContinueReadingDetailView.dart
│ │ │ ├── ContinueReadingView.dart
│ │ │ ├── NewsTabView.dart
│ │ │ ├── ReadingView.dart
│ │ │ ├── TopicView.dart
│ │ │ └── VideoNewsView.dart
│ │ ├── containers
│ │ │ ├── ContinueReading.dart
│ │ │ ├── ContinueReadingDetail.dart
│ │ │ ├── NewsTab.dart
│ │ │ └── Reading.dart
│ │ ├── reducer.dart
│ │ ├── repository.dart
│ │ ├── state.dart
│ │ └── styles.dart
│ ├── soccer
│ │ ├── actions.dart
│ │ ├── components
│ │ │ └── SoccerCalendarView.dart
│ │ ├── containers
│ │ │ └── SoccerCalendar.dart
│ │ ├── reducer.dart
│ │ ├── repository.dart
│ │ └── state.dart
│ ├── user
│ │ ├── actions.dart
│ │ ├── animations
│ │ │ └── login.dart
│ │ ├── components
│ │ │ ├── LoginFormView.dart
│ │ │ ├── SavedNewsView.dart
│ │ │ └── SignInButton.dart
│ │ ├── containers
│ │ │ ├── LoginForm.dart
│ │ │ └── SavedNews.dart
│ │ ├── models
│ │ │ └── user.dart
│ │ ├── reducer.dart
│ │ ├── state.dart
│ │ └── styles.dart
│ └── welcome
│ │ ├── animations
│ │ ├── page_dragger.dart
│ │ └── page_reveal.dart
│ │ └── components
│ │ ├── PagerIndicatorView.dart
│ │ └── PagerView.dart
├── pages
│ ├── AboutPage.dart
│ ├── BoardingPage.dart
│ ├── CategoriesPage.dart
│ ├── ContentLoadingPage.dart
│ ├── ContinueReadingPage.dart
│ ├── HomePage.dart
│ ├── LoadingPage.dart
│ ├── LoginPage.dart
│ ├── NewsSourcePage.dart
│ ├── OverlayLoadingPage.dart
│ ├── ReadingPage.dart
│ ├── SavedNewsPage.dart
│ ├── SoccerPage.dart
│ ├── SubNewsPage.dart
│ ├── TestAnimationPage.dart
│ ├── TopicDetailPage.dart
│ ├── TopicPage.dart
│ └── VideosPage.dart
├── presentation
│ └── platform_adaptive.dart
└── styles
│ ├── colors.dart
│ └── texts.dart
├── pubspec.yaml
└── test
└── widget_test.dart
/.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 | .vscode/
21 |
22 | # Flutter/Dart/Pub related
23 | **/doc/api/
24 | .dart_tool/
25 | .flutter-plugins
26 | .packages
27 | .pub-cache/
28 | .pub/
29 | build/
30 |
31 | # Android related
32 | **/android/**/gradle-wrapper.jar
33 | **/android/.gradle
34 | **/android/captures/
35 | **/android/gradlew
36 | **/android/gradlew.bat
37 | **/android/local.properties
38 | **/android/key.properties
39 | **/android/**/my-release-key.keystore
40 |
41 | # iOS/XCode related
42 | **/ios/**/*.mode1v3
43 | **/ios/**/*.mode2v3
44 | **/ios/**/*.moved-aside
45 | **/ios/**/*.pbxuser
46 | **/ios/**/*.perspectivev3
47 | **/ios/**/*sync/
48 | **/ios/**/.sconsign.dblite
49 | **/ios/**/.tags*
50 | **/ios/**/.vagrant/
51 | **/ios/**/DerivedData/
52 | **/ios/**/Icon?
53 | **/ios/**/Pods/
54 | **/ios/**/.symlinks/
55 | **/ios/**/profile
56 | **/ios/**/xcuserdata
57 | **/ios/.generated/
58 | **/ios/Flutter/App.framework
59 | **/ios/Flutter/Flutter.framework
60 | **/ios/Flutter/Generated.xcconfig
61 | **/ios/Flutter/app.flx
62 | **/ios/Flutter/app.zip
63 | **/ios/Flutter/flutter_assets/
64 | **/ios/ServiceDefinitions.json
65 | **/ios/Runner/GeneratedPluginRegistrant.*
66 |
67 | # Exceptions to above rules.
68 | !**/ios/**/default.mode1v3
69 | !**/ios/**/default.mode2v3
70 | !**/ios/**/default.pbxuser
71 | !**/ios/**/default.perspectivev3
72 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
73 |
74 | # Firebase config
75 | ios/Runner/GoogleService-Info.plist
76 | android/app/google-services.json
77 |
78 |
79 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 Protocol Labs, Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## About
2 |
3 | **Flutter_redux** is a simple flutter application. It demonstrates how to implement Redux for Dart.
4 |
5 | ## Redux
6 |
7 | Redux.JS author advice : If you've got a simple app, use the simplest thing possible. In Flutter, StatefulWidget is perfect for a simple counter app.
8 |
9 | However, say you have more complex app, such as an E-commerce app with a Shopping Cart. The Shopping Cart should appear on multiple screens in your app and should be updated by many different types of Widgets on those different screens (An "Add Item to Cart" Widget on all your Product Screens, "Remove Item from Cart" Widget on the Shopping Cart Screen, "Change quantity" Widgets, etc).
10 | Now, in this case, you could create a Testable ShoppingCart class as a Singleton or Create a Root StatefulWidget that passes the ShoppingCartDown Down Down through your widget hierarchy to the "add to cart" or "remove from cart" Widgets .
11 | Yet passing the ShoppingCart all over the place can get messy. It also means it's way harder to move that "Add to Item" button to a new location, b/c you'd need up update the Widgets throughout your app that passes the state down.
12 |
13 | Furthermore, you'd need a way to Observe when the ShoppingCart Changes so you could rebuild your Widgets when it does (from an "Add" button to an "Added" button, as an example).
14 | One way to handle it would be to simply setState every time the ShoppingCart changes in your Root Widget, but then your whole app below the RootWidget would be required to rebuild as well! Flutter is fast, but we should be smart about what we ask Flutter to rebuild!
15 |
16 | ## Project structure
17 | * **main.dart** is where navigation live and where Redux's Store is provided to the app, and also the main entry point of the app that initiliaze a new Redux's Store.
18 | * **common**:
19 | 1. components: Flutter Widget with usage as common
20 | 2. actions: common actions.
21 | 3. reducers: common reducer and main app reducer.
22 | 4. states: common state class.
23 | 5. configs.dart: config of your application.
24 | 6. repository.dart: common api fetch.
25 | 7. state.dart: main state.
26 | 8. store.dart: create redux store.
27 | * **modules**: every application make up of many module. Sample: todo application make up of user (login information, user infomation, etc), todo (list todo, temp todo, etc). It make simpler to develop and easier finding problems.
28 | 1. components: module's View Widget
29 | 2. containers: where Flutter's widgets are connected to Redux state
30 | 3. state.dart: describe the object Redux's state
31 | 4. repository.dart: api fetch
32 | 5. reducers.dart: module reducer
33 | 6. actions.dart: contains Redux actions that can be triggered from widgets
34 | * **pages**: Screen of your application which made up of many components of module
35 | * **styles**: your styles
36 |
37 | ## Demo
38 | download at: https://play.google.com/store/apps/details?id=com.zrgteam.tinmoi
39 |
40 | Checkout "develop" branch
41 |
42 | 
43 | 
44 | 
45 | 
46 |
47 | ## Install
48 |
49 | + Step 1 : `flutter packages get`
50 | + Step 2 : Create a firebase project at `https://firebase.google.com/`
51 | + Step 3 : Put firebase's project file into `android/app/google-services.json` and `ios/Runner/GoogleService-Info.plist`
52 | + Step 4 : Correct your admob APPLICATION_ID in `android/app/src/AndroidManifest.xml`
53 |
54 | **Checkout branch `starter` for easier setup**
55 |
56 | ## Donate
57 | ethereum address: 0x46D1c53249cA6232eb7d3E046713Bc3D2Ae15BA3
58 |
--------------------------------------------------------------------------------
/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 | def keystoreProperties = new Properties()
28 | def keystorePropertiesFile = rootProject.file('key.properties')
29 | if (keystorePropertiesFile.exists()) {
30 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
31 | }
32 |
33 | android {
34 | compileSdkVersion 27
35 |
36 | lintOptions {
37 | disable 'InvalidPackage'
38 | }
39 |
40 | defaultConfig {
41 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
42 | applicationId "com.zrgteam.tinmoi"
43 | minSdkVersion 16
44 | targetSdkVersion 27
45 | versionCode 31
46 | versionName flutterVersionName
47 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
48 | }
49 |
50 | signingConfigs {
51 | release {
52 | keyAlias keystoreProperties['keyAlias']
53 | keyPassword keystoreProperties['keyPassword']
54 | storeFile file(keystoreProperties['storeFile'])
55 | storePassword keystoreProperties['storePassword']
56 | }
57 | }
58 | buildTypes {
59 | release {
60 | signingConfig signingConfigs.release
61 | minifyEnabled true
62 | useProguard true
63 |
64 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
65 | }
66 | }
67 |
68 | compileOptions {
69 | sourceCompatibility JavaVersion.VERSION_1_8
70 | targetCompatibility JavaVersion.VERSION_1_8
71 | }
72 | }
73 |
74 | flutter {
75 | source '../..'
76 | }
77 |
78 | dependencies {
79 | testImplementation 'junit:junit:4.12'
80 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
81 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
82 | }
83 |
84 | // ADD THIS AT THE BOTTOM
85 | apply plugin: 'com.google.gms.google-services'
86 |
--------------------------------------------------------------------------------
/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | #Flutter Wrapper
2 | -keep class io.flutter.app.** { *; }
3 | -keep class io.flutter.plugin.** { *; }
4 | -keep class io.flutter.util.** { *; }
5 | -keep class io.flutter.view.** { *; }
6 | -keep class io.flutter.** { *; }
7 | -keep class io.flutter.plugins.** { *; }
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
14 |
18 |
21 |
24 |
31 |
35 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/zrgteam/tinmoi/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.zrgteam.tinmoi;
2 |
3 | import android.os.Bundle;
4 | import android.view.WindowManager;
5 | import android.view.ViewTreeObserver;
6 | import io.flutter.app.FlutterActivity;
7 | import io.flutter.plugins.GeneratedPluginRegistrant;
8 |
9 | public class MainActivity extends FlutterActivity {
10 | @Override
11 | protected void onCreate(Bundle savedInstanceState) {
12 | super.onCreate(savedInstanceState);
13 | //make transparent status bar
14 | getWindow().setStatusBarColor(0x00000000);
15 | GeneratedPluginRegistrant.registerWith(this);
16 | //Remove full screen flag after load
17 | ViewTreeObserver vto = getFlutterView().getViewTreeObserver();
18 | vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
19 | @Override
20 | public void onGlobalLayout() {
21 | getFlutterView().getViewTreeObserver().removeOnGlobalLayoutListener(this);
22 | getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
23 | }
24 | });
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/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.firebaseadmob.FirebaseAdMobPlugin;
5 | import io.flutter.plugins.pathprovider.PathProviderPlugin;
6 | import io.flutter.plugins.share.SharePlugin;
7 | import io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin;
8 | import io.flutter.plugins.urllauncher.UrlLauncherPlugin;
9 |
10 | /**
11 | * Generated file. Do not edit.
12 | */
13 | public final class GeneratedPluginRegistrant {
14 | public static void registerWith(PluginRegistry registry) {
15 | if (alreadyRegisteredWith(registry)) {
16 | return;
17 | }
18 | FirebaseAdMobPlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebaseadmob.FirebaseAdMobPlugin"));
19 | PathProviderPlugin.registerWith(registry.registrarFor("io.flutter.plugins.pathprovider.PathProviderPlugin"));
20 | SharePlugin.registerWith(registry.registrarFor("io.flutter.plugins.share.SharePlugin"));
21 | SharedPreferencesPlugin.registerWith(registry.registrarFor("io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin"));
22 | UrlLauncherPlugin.registerWith(registry.registrarFor("io.flutter.plugins.urllauncher.UrlLauncherPlugin"));
23 | }
24 |
25 | private static boolean alreadyRegisteredWith(PluginRegistry registry) {
26 | final String key = GeneratedPluginRegistrant.class.getCanonicalName();
27 | if (registry.hasPlugin(key)) {
28 | return true;
29 | }
30 | registry.registrarFor(key);
31 | return false;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 | -
14 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/android/app/src/main/res/drawable/splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/android/app/src/main/res/mipmap-hdpi/launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/android/app/src/main/res/mipmap-mdpi/launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 | #FAFAFA
10 |
11 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | jcenter()
5 | mavenLocal()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.2.1'
10 | classpath 'com.google.gms:google-services:4.2.0'
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | jcenter()
18 | mavenLocal()
19 | }
20 | }
21 |
22 | rootProject.buildDir = '../build'
23 | subprojects {
24 | project.buildDir = "${rootProject.buildDir}/${project.name}"
25 | }
26 | subprojects {
27 | project.evaluationDependsOn(':app')
28 | }
29 |
30 | task clean(type: Delete) {
31 | delete rootProject.buildDir
32 | }
33 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/assets/fonts/FFF_Tusj.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/fonts/FFF_Tusj.ttf
--------------------------------------------------------------------------------
/assets/fonts/Poppins-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/fonts/Poppins-SemiBold.ttf
--------------------------------------------------------------------------------
/assets/fonts/circle.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/fonts/circle.ttf
--------------------------------------------------------------------------------
/assets/images/banner-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/banner-1.png
--------------------------------------------------------------------------------
/assets/images/banner-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/banner-2.png
--------------------------------------------------------------------------------
/assets/images/banner-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/banner-3.png
--------------------------------------------------------------------------------
/assets/images/banner-icon-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/banner-icon-2.png
--------------------------------------------------------------------------------
/assets/images/banner1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/banner1.png
--------------------------------------------------------------------------------
/assets/images/chinhphu.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/chinhphu.jpg
--------------------------------------------------------------------------------
/assets/images/congnghe.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/congnghe.jpg
--------------------------------------------------------------------------------
/assets/images/giaitri.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/giaitri.jpg
--------------------------------------------------------------------------------
/assets/images/giaoduc.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/giaoduc.jpg
--------------------------------------------------------------------------------
/assets/images/honnhan.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/honnhan.jpg
--------------------------------------------------------------------------------
/assets/images/icon-banner-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/icon-banner-1.png
--------------------------------------------------------------------------------
/assets/images/ictnews.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/ictnews.png
--------------------------------------------------------------------------------
/assets/images/khoahoc.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/khoahoc.jpg
--------------------------------------------------------------------------------
/assets/images/kienthuc.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/kienthuc.jpeg
--------------------------------------------------------------------------------
/assets/images/kinhdoanh.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/kinhdoanh.jpg
--------------------------------------------------------------------------------
/assets/images/kinhte.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/kinhte.jpg
--------------------------------------------------------------------------------
/assets/images/lamdep.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/lamdep.jpg
--------------------------------------------------------------------------------
/assets/images/laodong.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/laodong.jpg
--------------------------------------------------------------------------------
/assets/images/latest.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/latest.jpg
--------------------------------------------------------------------------------
/assets/images/login.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/login.jpg
--------------------------------------------------------------------------------
/assets/images/noimage-reading.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/noimage-reading.jpg
--------------------------------------------------------------------------------
/assets/images/noimage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/noimage.jpg
--------------------------------------------------------------------------------
/assets/images/petrotimes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/petrotimes.png
--------------------------------------------------------------------------------
/assets/images/phapluat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/phapluat.png
--------------------------------------------------------------------------------
/assets/images/saostart.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/saostart.jpg
--------------------------------------------------------------------------------
/assets/images/swipe-left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/swipe-left.png
--------------------------------------------------------------------------------
/assets/images/swipeleft.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/swipeleft.png
--------------------------------------------------------------------------------
/assets/images/swiperight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/swiperight.png
--------------------------------------------------------------------------------
/assets/images/thanhnien.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/thanhnien.jpg
--------------------------------------------------------------------------------
/assets/images/thegioi.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/thegioi.jpg
--------------------------------------------------------------------------------
/assets/images/thethao.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/thethao.jpg
--------------------------------------------------------------------------------
/assets/images/tick.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/tick.png
--------------------------------------------------------------------------------
/assets/images/tienphong.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/tienphong.png
--------------------------------------------------------------------------------
/assets/images/tinhot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/tinhot.png
--------------------------------------------------------------------------------
/assets/images/vanhoa.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/vanhoa.jpg
--------------------------------------------------------------------------------
/assets/images/videoplayer.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/videoplayer.jpg
--------------------------------------------------------------------------------
/assets/images/vietnamfinance.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/vietnamfinance.png
--------------------------------------------------------------------------------
/assets/images/vietnamnet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/vietnamnet.png
--------------------------------------------------------------------------------
/assets/images/vietnamplus.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/vietnamplus.jpg
--------------------------------------------------------------------------------
/assets/images/vnmedia.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/vnmedia.png
--------------------------------------------------------------------------------
/assets/images/vov.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/vov.jpg
--------------------------------------------------------------------------------
/assets/images/vtc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/vtc.png
--------------------------------------------------------------------------------
/assets/images/xahoi.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/xahoi.jpg
--------------------------------------------------------------------------------
/assets/images/zing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/images/zing.png
--------------------------------------------------------------------------------
/assets/store/feature-graphic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/store/feature-graphic.png
--------------------------------------------------------------------------------
/assets/store/good-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/store/good-3.png
--------------------------------------------------------------------------------
/assets/store/good-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/store/good-4.png
--------------------------------------------------------------------------------
/assets/store/good-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/store/good-5.png
--------------------------------------------------------------------------------
/assets/store/good-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/store/good-6.png
--------------------------------------------------------------------------------
/assets/store/good-7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/store/good-7.png
--------------------------------------------------------------------------------
/assets/store/hi-res.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/store/hi-res.png
--------------------------------------------------------------------------------
/assets/store/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/store/icon.png
--------------------------------------------------------------------------------
/assets/store/store-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/store/store-2.png
--------------------------------------------------------------------------------
/assets/store/store-3-512.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/store/store-3-512.jpg
--------------------------------------------------------------------------------
/assets/store/store-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/store/store-3.jpg
--------------------------------------------------------------------------------
/assets/store/store-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/store/store-3.png
--------------------------------------------------------------------------------
/assets/store/store-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/store/store-4.png
--------------------------------------------------------------------------------
/assets/store/store.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/assets/store/store.png
--------------------------------------------------------------------------------
/assets/store/store.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/documents/ABOUT.md:
--------------------------------------------------------------------------------
1 | # Thông Tin
2 |
3 | **Tin Mới** là ứng dụng đọc báo đơn giản, tổng hợp tin tức tự động. Ứng dụng cho phép bạn đọc nhanh các tin tức nóng và mới nhất trong ngày được chọn lọc từ hơn các báo điện tử tại Việt Nam.
4 | cung cấp các chức năng chính :
5 | * Duyệt các tin tức nóng hổi
6 | * Nguồn tin tức phong phú
7 | * Nhiều thể loại tin tức phong phú
8 | * Lưu trữ tin tức offline
9 | * Dễ dàng chia sẻ thông tin
10 | * ...
11 |
12 | ## Công nghệ
13 |
14 | Ứng dụng là sản phẩm của quá trình nghiên cứu công nghệ "Flutter" nhằm viết ứng dụng đa nền tảng với một codebase duy nhất
15 | Ứng dụng có thời gian hoàn thiện 5 ngày: từ ban đầu cho đến khi hoàn thiện thành sản phẩm bao gồm: design, logic, source structure, ...
16 |
17 | ## Tác giả
18 | [Hungdt](https://zrg-team.github.io/store/)
19 |
20 | ## Source
21 | https://github.com/zrg-team/flutter_redux
22 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '9.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | 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 packages 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 | post_install do |installer|
64 | installer.pods_project.targets.each do |target|
65 | target.build_configurations.each do |config|
66 | config.build_settings['ENABLE_BITCODE'] = 'NO'
67 | end
68 | end
69 | end
70 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
56 |
58 |
64 |
65 |
66 |
67 |
68 |
69 |
75 |
77 |
83 |
84 |
85 |
86 |
88 |
89 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildSystemType
6 | Original
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : FlutterAppDelegate
5 |
6 | @end
7 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.m:
--------------------------------------------------------------------------------
1 | #include "AppDelegate.h"
2 | #include "GeneratedPluginRegistrant.h"
3 |
4 | @implementation AppDelegate
5 |
6 | - (BOOL)application:(UIApplication *)application
7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
8 | [GeneratedPluginRegistrant registerWithRegistry:self];
9 | // Override point for customization after application launch.
10 | return [super application:application didFinishLaunchingWithOptions:launchOptions];
11 | }
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "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/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/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/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/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/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/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/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/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/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/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/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/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/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/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/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/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/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/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/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/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/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/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/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/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/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/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/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/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/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/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/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrg-team/flutter_redux/cb8b8600f0ce3ffb5f732bb7f89cf40199c39b35/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/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSAppTransportSecurity
6 |
7 | NSAllowsArbitraryLoads
8 |
9 | CFBundleDevelopmentRegion
10 | en
11 | CFBundleExecutable
12 | $(EXECUTABLE_NAME)
13 | CFBundleIdentifier
14 | $(PRODUCT_BUNDLE_IDENTIFIER)
15 | CFBundleInfoDictionaryVersion
16 | 6.0
17 | CFBundleName
18 | cat_dog
19 | CFBundlePackageType
20 | APPL
21 | CFBundleShortVersionString
22 | $(FLUTTER_BUILD_NAME)
23 | CFBundleSignature
24 | ????
25 | CFBundleVersion
26 | $(FLUTTER_BUILD_NUMBER)
27 | LSRequiresIPhoneOS
28 |
29 | NSAllowsArbitraryLoads
30 |
31 | NSAppTransportSecurity
32 |
33 | UILaunchStoryboardName
34 | LaunchScreen
35 | UIMainStoryboardFile
36 | Main
37 | UISupportedInterfaceOrientations
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationLandscapeLeft
41 | UIInterfaceOrientationLandscapeRight
42 |
43 | UISupportedInterfaceOrientations~ipad
44 |
45 | UIInterfaceOrientationPortrait
46 | UIInterfaceOrientationPortraitUpsideDown
47 | UIInterfaceOrientationLandscapeLeft
48 | UIInterfaceOrientationLandscapeRight
49 |
50 | UIViewControllerBasedStatusBarAppearance
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/lib/common/actions/common.dart:
--------------------------------------------------------------------------------
1 | import 'package:redux/redux.dart';
2 | import 'package:cat_dog/common/state.dart';
3 | import 'package:cat_dog/common/repository.dart';
4 |
5 | class SetUserLanguage {
6 | final String language;
7 | SetUserLanguage(this.language);
8 | }
9 |
10 | class SetAboutInformation {
11 | final String data;
12 | SetAboutInformation(this.data);
13 | }
14 |
15 | class SetFirstOpen {
16 | final bool first;
17 | SetFirstOpen(this.first);
18 | }
19 |
20 | class AddReadingCount {
21 | AddReadingCount();
22 | }
23 |
24 | class ClearReadingCount {
25 | ClearReadingCount();
26 | }
27 |
28 | final Function actionSetUserLanguage = (String language) {
29 | return (Store store) {
30 | if (language != '') {
31 | store.dispatch(new SetUserLanguage(language));
32 | }
33 | };
34 | };
35 |
36 | final Function getAboutAction = () {
37 | return (Store store) async {
38 | var result = await fetchAboutInformation();
39 | store.dispatch(SetAboutInformation(result));
40 | };
41 | };
42 |
43 | final Function setFirstOpenAction = () {
44 | return (Store store) async {
45 | store.dispatch(SetFirstOpen(false));
46 | };
47 | };
48 |
49 | final Function addReadingCountAction = () {
50 | return (Store store) async {
51 | store.dispatch(AddReadingCount());
52 | };
53 | };
54 |
55 | final Function clearReadingCountAction = () {
56 | return (Store store) async {
57 | store.dispatch(ClearReadingCount());
58 | };
59 | };
--------------------------------------------------------------------------------
/lib/common/components/BottomBar.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:cat_dog/styles/colors.dart';
3 | import 'package:cat_dog/presentation/platform_adaptive.dart';
4 | import 'package:cat_dog/styles/texts.dart';
5 |
6 | class BottomBar extends StatelessWidget {
7 |
8 | final int _index;
9 | final Function onTap;
10 | final double barHeight = 66.0;
11 |
12 | BottomBar(this._index, this.onTap);
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | final double statusBarHeight = MediaQuery
17 | .of(context)
18 | .padding
19 | .top;
20 |
21 | return new Container(
22 | padding: new EdgeInsets.only(top: statusBarHeight),
23 | height: statusBarHeight + barHeight,
24 | decoration: new BoxDecoration(
25 | gradient: new LinearGradient(
26 | colors: [
27 | AppColors.appBarGradientStart,
28 | AppColors.appBarGradientEnd
29 | ],
30 | begin: const FractionalOffset(0.0, 0.0),
31 | end: const FractionalOffset(0.5, 0.0),
32 | stops: [0.0, 0.5],
33 | tileMode: TileMode.clamp
34 | ),
35 | ),
36 | child: PlatformAdaptiveBottomBar(
37 | currentIndex: _index,
38 | onTap: onTap,
39 | items: TabItems.map((TabItem item) {
40 | return new BottomNavigationBarItem(
41 | title: new Text(
42 | item.title,
43 | style: textStyles['bottom_label'],
44 | ),
45 | icon: new Icon(item.icon),
46 | );
47 | }).toList(),
48 | )
49 | );
50 | }
51 | }
52 |
53 | class TabItem {
54 | final String title;
55 | final IconData icon;
56 |
57 | const TabItem({ this.title, this.icon });
58 | }
59 |
60 | const List TabItems = const [
61 | const TabItem(title: 'Hot', icon: Icons.assignment),
62 | const TabItem(title: 'Categories', icon: Icons.category),
63 | const TabItem(title: 'Discover', icon: Icons.group_work)
64 | ];
--------------------------------------------------------------------------------
/lib/common/components/ContentLoading.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shimmer/shimmer.dart';
3 |
4 | class ContentLoading extends StatelessWidget {
5 |
6 | ContentLoading();
7 |
8 | @override
9 | Widget build(BuildContext context) {
10 | return Shimmer.fromColors(
11 | baseColor: Colors.grey[300],
12 | highlightColor: Colors.grey[100],
13 | child: Column(
14 | crossAxisAlignment: CrossAxisAlignment.start,
15 | children: [
16 | Container(
17 | width: MediaQuery.of(context).size.width - 40.0,
18 | height: 8.0,
19 | margin: EdgeInsets.only(left: 40),
20 | color: Colors.white,
21 | ),
22 | Padding(
23 | padding:
24 | const EdgeInsets.symmetric(vertical: 4.0),
25 | ),
26 | Container(
27 | width: double.infinity,
28 | height: 8.0,
29 | color: Colors.white,
30 | ),
31 | Padding(
32 | padding:
33 | const EdgeInsets.symmetric(vertical: 4.0),
34 | ),
35 | Container(
36 | width: double.infinity,
37 | height: 8.0,
38 | color: Colors.white,
39 | ),
40 | Padding(
41 | padding:
42 | const EdgeInsets.symmetric(vertical: 4.0),
43 | ),
44 | Container(
45 | width: 100.0,
46 | height: 8.0,
47 | color: Colors.white,
48 | ),
49 | Padding(
50 | padding:
51 | const EdgeInsets.symmetric(vertical: 4.0),
52 | ),
53 | Container(
54 | width: double.infinity,
55 | height: 300,
56 | color: Colors.white,
57 | ),
58 | Container(
59 | width: double.infinity,
60 | height: 8.0,
61 | color: Colors.white,
62 | ),
63 | Padding(
64 | padding:
65 | const EdgeInsets.symmetric(vertical: 4.0),
66 | ),
67 | Container(
68 | width: double.infinity,
69 | height: 8.0,
70 | color: Colors.white,
71 | ),
72 | Padding(
73 | padding:
74 | const EdgeInsets.symmetric(vertical: 4.0),
75 | ),
76 | Container(
77 | width: 40.0,
78 | height: 8.0,
79 | color: Colors.white,
80 | ),
81 | Padding(
82 | padding:
83 | const EdgeInsets.symmetric(vertical: 4.0),
84 | )
85 | ]
86 | )
87 | );
88 | }
89 | }
--------------------------------------------------------------------------------
/lib/common/components/Form.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import './InputFields.dart';
3 |
4 | class FormContainer extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return (new Container(
8 | margin: new EdgeInsets.symmetric(horizontal: 20.0),
9 | child: new Column(
10 | mainAxisAlignment: MainAxisAlignment.spaceEvenly,
11 | children: [
12 | new Form(
13 | child: new Column(
14 | mainAxisAlignment: MainAxisAlignment.spaceAround,
15 | children: [
16 | new InputFieldArea(
17 | hint: "Username",
18 | obscureText: false,
19 | icon: Icons.person_outline,
20 | ),
21 | new InputFieldArea(
22 | hint: "Password",
23 | obscureText: true,
24 | icon: Icons.lock_outline,
25 | ),
26 | ],
27 | )),
28 | ],
29 | ),
30 | ));
31 | }
32 | }
--------------------------------------------------------------------------------
/lib/common/components/FrostedGlassAppBar.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 | import 'package:flutter/material.dart';
3 | import 'package:cat_dog/styles/colors.dart';
4 |
5 | class FrostedGlassAppBar extends StatelessWidget {
6 |
7 | final String title;
8 | final dynamic iconLeftButton;
9 | final Function onPressLeftButton;
10 | final dynamic iconRighButton;
11 | final Function onPressRightButton;
12 | final double barHeight = 60.0;
13 |
14 | FrostedGlassAppBar(this.title, this.iconLeftButton, this.onPressLeftButton, this.iconRighButton, this.onPressRightButton);
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | final double statusBarHeight = MediaQuery
19 | .of(context)
20 | .padding
21 | .top;
22 |
23 | return new Container(
24 | padding: new EdgeInsets.only(top: 0),
25 | height: statusBarHeight + barHeight,
26 | child: new Center(
27 | child: new ClipRect(
28 | child: new BackdropFilter(
29 | filter: new ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
30 | child: new Container(
31 | padding: new EdgeInsets.only(top: statusBarHeight),
32 | width: MediaQuery.of(context).size.width,
33 | height: statusBarHeight + barHeight,
34 | decoration: new BoxDecoration(
35 | gradient: new LinearGradient(
36 | colors: [
37 | AppColors.appBarGradientStart.withOpacity(0.8),
38 | AppColors.appBarGradientEnd.withOpacity(0.8)
39 | ],
40 | begin: const FractionalOffset(0.0, 0.0),
41 | end: const FractionalOffset(0.5, 0.0),
42 | stops: [0.0, 0.5],
43 | tileMode: TileMode.clamp
44 | ),
45 | ),
46 | child: Row(
47 | mainAxisSize: MainAxisSize.max,
48 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
49 | children: [
50 | iconLeftButton != null ? Container(
51 | child: IconButton(
52 | color: AppColors.white,
53 | icon: iconLeftButton,
54 | iconSize: 32,
55 | onPressed: onPressLeftButton
56 | )
57 | ) : Container(width: 32, height: 32),
58 | Container(
59 | child: new Center(
60 | child: new Text(
61 | title,
62 | style: const TextStyle(
63 | color: Colors.white,
64 | fontWeight: FontWeight.bold,
65 | fontSize: 30.0
66 | )
67 | )
68 | )
69 | ),
70 | iconRighButton != null ? Container(
71 | child: IconButton(
72 | color: AppColors.white,
73 | icon: iconRighButton,
74 | iconSize: 32,
75 | onPressed: onPressRightButton
76 | )
77 | ) : Container(width: 32, height: 32)
78 | ]
79 | )
80 | ),
81 | ),
82 | ),
83 | ),
84 | );
85 | }
86 | }
--------------------------------------------------------------------------------
/lib/common/components/GradientAppBar.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:cat_dog/styles/colors.dart';
3 |
4 | class GradientAppBar extends StatelessWidget {
5 |
6 | final String title;
7 | final dynamic iconLeftButton;
8 | final Function onPressLeftButton;
9 | final dynamic iconRighButton;
10 | final Function onPressRightButton;
11 | final Function onPressRightButtonDownload;
12 | final Function onPressRightButtonShare;
13 | final double barHeight = 60.0;
14 |
15 | GradientAppBar(
16 | this.title,
17 | this.iconLeftButton,
18 | this.onPressLeftButton,
19 | this.iconRighButton,
20 | this.onPressRightButton,
21 | {
22 | dynamic onPressRightButtonDownload,
23 | dynamic onPressRightButtonShare
24 | }
25 | ) :
26 | onPressRightButtonShare = onPressRightButtonShare,
27 | onPressRightButtonDownload = onPressRightButtonDownload,
28 | super();
29 |
30 | @override
31 | Widget build(BuildContext context) {
32 | final double statusBarHeight = MediaQuery
33 | .of(context)
34 | .padding
35 | .top;
36 |
37 | return new Container(
38 | padding: new EdgeInsets.only(top: statusBarHeight),
39 | height: statusBarHeight + barHeight,
40 | decoration: new BoxDecoration(
41 | gradient: new LinearGradient(
42 | colors: [
43 | AppColors.appBarGradientStart,
44 | AppColors.appBarGradientEnd
45 | ],
46 | begin: const FractionalOffset(0.0, 0.0),
47 | end: const FractionalOffset(0.5, 0.0),
48 | stops: [0.0, 0.5],
49 | tileMode: TileMode.clamp
50 | ),
51 | ),
52 | child: Row(
53 | mainAxisSize: MainAxisSize.max,
54 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
55 | children: [
56 | iconLeftButton != null ? Container(
57 | child: IconButton(
58 | color: AppColors.white,
59 | icon: iconLeftButton,
60 | iconSize: 32,
61 | onPressed: onPressLeftButton
62 | )
63 | ) : Container(width: 32, height: 32),
64 | Container(
65 | child: new Center(
66 | child: new Text(
67 | title,
68 | style: const TextStyle(
69 | color: Colors.white,
70 | fontWeight: FontWeight.bold,
71 | fontSize: 24.0
72 | )
73 | )
74 | )
75 | ),
76 | new Row(
77 | children: [
78 | iconRighButton != null ? Container(
79 | child: IconButton(
80 | color: AppColors.white,
81 | icon: iconRighButton,
82 | iconSize: 32,
83 | onPressed: onPressRightButton
84 | )
85 | ) : Container(width: 32, height: 32),
86 | onPressRightButtonDownload != null ? Container(
87 | child: IconButton(
88 | color: AppColors.white,
89 | icon: Icon(Icons.save),
90 | iconSize: 32,
91 | onPressed: onPressRightButtonDownload
92 | )
93 | ) : Container(width: 0, height: 0),
94 | onPressRightButtonShare != null ? Container(
95 | child: IconButton(
96 | color: AppColors.white,
97 | icon: Icon(Icons.share),
98 | iconSize: 32,
99 | onPressed: onPressRightButtonShare
100 | )
101 | ) : Container(width: 0, height: 0)
102 | ]
103 | )
104 | ]
105 | )
106 | );
107 | }
108 | }
--------------------------------------------------------------------------------
/lib/common/components/ImageCached.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:cached_network_image/cached_network_image.dart';
3 | import 'package:flutter_spinkit/flutter_spinkit.dart';
4 | import 'package:cat_dog/styles/colors.dart';
5 |
6 | class ImageCached extends StatelessWidget {
7 | final String url;
8 | final double width;
9 | final double height;
10 | final Widget placeholder;
11 | final String noimage;
12 | final BoxFit fit;
13 | ImageCached({
14 | Key key,
15 | this.url,
16 | dynamic fit,
17 | dynamic width,
18 | dynamic height,
19 | dynamic noimage,
20 | dynamic placeholder
21 | }) :
22 | noimage = noimage,
23 | fit = fit == null ? BoxFit.cover : fit,
24 | width = width == null ? double.infinity : width,
25 | height = height == null ? double.infinity : height,
26 | placeholder = placeholder != null
27 | ? placeholder
28 | : Center(
29 | child: SpinKitPulse(
30 | color: AppColors.specicalBackgroundColor,
31 | size: 32
32 | )
33 | ),
34 | super(key: key);
35 | @override
36 | Widget build(BuildContext context) {
37 | return CachedNetworkImage(
38 | imageUrl: url,
39 | width: width,
40 | height: height,
41 | placeholder: placeholder,
42 | errorWidget: noimage == null
43 | ? Icon(Icons.broken_image, color: AppColors.specicalBackgroundColor)
44 | : Image.asset(
45 | noimage,
46 | fit: BoxFit.cover
47 | ),
48 | fit: fit
49 | );
50 | }
51 | }
--------------------------------------------------------------------------------
/lib/common/components/InputFields.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class InputFieldArea extends StatelessWidget {
4 | final String hint;
5 | final bool obscureText;
6 | final IconData icon;
7 | final Function validator;
8 | final Function onSaved;
9 | InputFieldArea({this.hint, this.obscureText, this.icon, this.validator, this.onSaved});
10 | @override
11 | Widget build(BuildContext context) {
12 | return (new Container(
13 | decoration: new BoxDecoration(
14 | border: new Border(
15 | bottom: new BorderSide(
16 | width: 0.5,
17 | color: Colors.white24,
18 | ),
19 | ),
20 | ),
21 | child: new TextFormField(
22 | onSaved: onSaved,
23 | obscureText: obscureText,
24 | validator: validator,
25 | style: const TextStyle(
26 | color: Colors.white,
27 | ),
28 | decoration: new InputDecoration(
29 | icon: new Icon(
30 | icon,
31 | color: Colors.white,
32 | ),
33 | border: InputBorder.none,
34 | hintText: hint,
35 | hintStyle: const TextStyle(color: Colors.white, fontSize: 15.0),
36 | contentPadding: const EdgeInsets.only(
37 | top: 30.0, right: 30.0, bottom: 30.0, left: 5.0),
38 | ),
39 | ),
40 | ));
41 | }
42 | }
--------------------------------------------------------------------------------
/lib/common/components/MiniNewsList.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:cat_dog/common/components/MiniNewsfeed.dart';
3 | import 'package:cat_dog/common/utils/navigation.dart';
4 | import 'package:folding_cell/folding_cell.dart';
5 | import 'package:cat_dog/common/components/Newsfeed.dart';
6 |
7 | class MiniNewsList extends StatefulWidget {
8 | MiniNewsList({
9 | Key key,
10 | dynamic metaData,
11 | dynamic folding,
12 | List list,
13 | dynamic controller,
14 | dynamic widget,
15 | dynamic features,
16 | Function onTap,
17 | Function handleRefresh,
18 | }) :
19 | metaData = metaData != null ? metaData : false,
20 | folding = folding != null ? folding : false,
21 | list = list,
22 | onTap = onTap,
23 | parentWidget = widget,
24 | controller = controller,
25 | handleRefresh = handleRefresh,
26 | super(key: key);
27 |
28 | final List list;
29 | final ScrollController controller;
30 | final Function onTap;
31 | final Function handleRefresh;
32 | final parentWidget;
33 | final bool metaData;
34 | final bool folding;
35 |
36 | @override
37 | _MiniNewsListState createState() => new _MiniNewsListState();
38 | }
39 | class _MiniNewsListState extends State {
40 | Widget _buildItem(
41 | BuildContext context, int index) {
42 | if (widget.list[index] == null) {
43 | return new Container();
44 | }
45 | if (widget.folding == true && widget.list[index]['news'] != null && widget.list[index]['news'].length >= 2) {
46 | return SimpleFoldingCell(
47 | frontWidget: MiniNewsfeed(
48 | item: widget.list[index],
49 | metaData: widget.metaData,
50 | imageWidth: 120.0,
51 | imageHeight: 120.0,
52 | folding: true
53 | ),
54 | innerTopWidget: Newsfeed(
55 | item: widget.list[index]['news'][0],
56 | onTap: (seleted) {
57 | pushByName('/reading', context, { 'news': seleted });
58 | },
59 | onDownload: null,
60 | onShare: null,
61 | onRemove: null
62 | ),
63 | innerBottomWidget: Newsfeed(
64 | item: widget.list[index]['news'][1],
65 | onTap: (seleted) {
66 | pushByName('/reading', context, { 'news': seleted });
67 | },
68 | onDownload: null,
69 | onShare: null,
70 | onRemove: null
71 | ),
72 | cellSize: Size(MediaQuery.of(context).size.width, 165),
73 | padding: EdgeInsets.all(0.0),
74 | );
75 | }
76 | return MiniNewsfeed(
77 | item: widget.list[index],
78 | metaData: widget.metaData,
79 | onTap: (seleted) {
80 | if (widget.onTap != null) {
81 | widget.onTap(seleted);
82 | } else {
83 | pushByName('/reading', context, { 'news': seleted });
84 | }
85 | }
86 | );
87 | }
88 | @override
89 | Widget build(BuildContext context) {
90 | return ListView.builder(
91 | controller: widget.controller,
92 | itemCount: widget.list.length,
93 | itemBuilder: _buildItem,
94 | );
95 | }
96 | }
--------------------------------------------------------------------------------
/lib/common/components/MiniNewsfeed.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:cat_dog/styles/colors.dart';
3 | import 'package:timeago/timeago.dart' as timeago;
4 |
5 | class MiniNewsfeed extends StatelessWidget {
6 | const MiniNewsfeed(
7 | {
8 | Key key,
9 | this.onTap,
10 | dynamic folding,
11 | dynamic metaData,
12 | dynamic imageWidth,
13 | dynamic imageHeight,
14 | @required this.item
15 | })
16 | : assert(item != null),
17 | imageWidth = imageWidth != null ? imageWidth : 100.0,
18 | imageHeight = imageHeight != null ? imageHeight : 100.0,
19 | metaData = metaData != null ? metaData : false,
20 | folding = folding != null ? folding : false,
21 | super(key: key);
22 | final Function onTap;
23 | final dynamic item;
24 | final bool metaData;
25 | final bool folding;
26 | final double imageWidth;
27 | final double imageHeight;
28 |
29 | @override
30 | Widget build(BuildContext context) {
31 | return new Card(
32 | elevation: 1.7,
33 | child: new Container(
34 | decoration: new BoxDecoration(color: AppColors.white),
35 | child: new Padding(
36 | padding: new EdgeInsets.all(5.0),
37 | child: new Column(
38 | children: [
39 | new GestureDetector(
40 | onTap: !folding ? () {
41 | onTap != null && onTap(item);
42 | } : null,
43 | child: new Row(
44 | children: [
45 | new Column(
46 | children: [
47 | new Padding(
48 | padding:
49 | new EdgeInsets.only(top: 8.0),
50 | child: new SizedBox(
51 | height: imageWidth,
52 | width: imageHeight,
53 | child: Hero(
54 | tag: "mini-news-feed-${item['url']}",
55 | child: new Image.network(
56 | item['image'],
57 | fit: BoxFit.cover,
58 | )
59 | ),
60 | ),
61 | )
62 | ]
63 | ),
64 | new Expanded(
65 | child: new Column(
66 | mainAxisAlignment: MainAxisAlignment.start,
67 | crossAxisAlignment:
68 | CrossAxisAlignment.start,
69 | children: [
70 | this.metaData != null ? new Row(
71 | children: [
72 | new Padding(
73 | padding: new EdgeInsets.only(left: 4.0),
74 | child: new Text(
75 | timeago.format(DateTime.parse(item['time']), allowFromNow: true),
76 | style: new TextStyle(
77 | fontWeight: FontWeight.w400,
78 | color: Colors.grey[600],
79 | ),
80 | ),
81 | ),
82 | new Padding(
83 | padding: new EdgeInsets.all(5.0),
84 | child: new Text(
85 | item['source'],
86 | style: new TextStyle(
87 | fontWeight: FontWeight.w500,
88 | color: Colors.grey[700],
89 | ),
90 | ),
91 | ),
92 | ],
93 | ) : new Container(),
94 | new Padding(
95 | padding: new EdgeInsets.only(
96 | left: 4.0,
97 | right: 8.0,
98 | bottom: 8.0,
99 | top: 8.0),
100 | child: new Text(
101 | item['heading'].trim(),
102 | style: new TextStyle(
103 | fontWeight: FontWeight.bold,
104 | ),
105 | ),
106 | )
107 | ],
108 | )
109 | )
110 | ]
111 | )
112 | )
113 | ]
114 | )
115 | )
116 | )
117 | );
118 | }
119 | }
--------------------------------------------------------------------------------
/lib/common/components/SpinLoading.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_spinkit/flutter_spinkit.dart';
3 | import 'package:cat_dog/styles/colors.dart';
4 |
5 | class SpinLoading extends StatelessWidget {
6 | final bool overlay;
7 | final Color iconColor;
8 | SpinLoading({ Key key, dynamic overlay, dynamic iconColor }) :
9 | overlay = overlay == null ? false : overlay,
10 | iconColor = iconColor == null ? AppColors.specicalBackgroundColor : iconColor,
11 | super(key: key);
12 | @override
13 | Widget build(BuildContext context) {
14 | return (new Container(
15 | decoration: new BoxDecoration(
16 | color: overlay ? Colors.transparent : AppColors.commonBackgroundColor
17 | ),
18 | child: new Center(
19 | child: SpinKitDoubleBounce(
20 | color: iconColor,
21 | size: 100
22 | )
23 | )
24 | ));
25 | }
26 | }
--------------------------------------------------------------------------------
/lib/common/configs.dart:
--------------------------------------------------------------------------------
1 | const String GET_NEWS_API = 'https://m.baomoi.com';
2 | const String DEFAULT_URL = 'https://baomoi.com';
3 |
4 | const String FEEDBACK_URL = 'https://goo.gl/forms/lGaQ86rtkEKhXLZ22';
5 | const String ABOUT_URL = 'https://raw.githubusercontent.com/zrg-team/flutter_redux/develop/documents/ABOUT.md';
6 |
7 | const List SOURCE_NEWS = [
8 | {
9 | 'name': 'Zing',
10 | 'image': 'assets/images/zing.png',
11 | 'url': 'https://m.baomoi.com/bao-tri-thuc-truc-tuyen-zing/p/119.epi'
12 | },
13 | {
14 | 'name': 'VOV',
15 | 'image': 'assets/images/vov.jpg',
16 | 'url': 'https://m.baomoi.com/bao-vov-vov/p/65.epi'
17 | },
18 | {
19 | 'name': 'Thanh Niên',
20 | 'image': 'assets/images/thanhnien.jpg',
21 | 'url': 'https://m.baomoi.com/bao-thanh-nien-thanh-nien/p/19.epi'
22 | },
23 | {
24 | 'name': 'Lao Động',
25 | 'image': 'assets/images/laodong.jpg',
26 | 'url': 'https://m.baomoi.com/bao-lao-dong-lao-dong/p/12.epi'
27 | },
28 | {
29 | 'name': 'Vietnam Plus',
30 | 'image': 'assets/images/vietnamplus.jpg',
31 | 'url': 'https://m.baomoi.com/bao-vietnamplus-vietnamplus/p/293.epi'
32 | },
33 | {
34 | 'name': 'Vietnam Net',
35 | 'image': 'assets/images/vietnamnet.png',
36 | 'url': 'https://m.baomoi.com/bao-vietnamnet-vietnamnet/p/23.epi'
37 | },
38 | {
39 | 'name': 'VTC',
40 | 'image': 'assets/images/vtc.png',
41 | 'url': 'https://m.baomoi.com/bao-vtc-news-vtc/p/83.epi'
42 | },
43 | {
44 | 'name': 'SaoStart',
45 | 'image': 'assets/images/saostart.jpg',
46 | 'url': 'https://m.baomoi.com/saostar-saostar/p/329.epi'
47 | },
48 | {
49 | 'name': 'VN Media',
50 | 'image': 'assets/images/vnmedia.png',
51 | 'url': 'https://m.baomoi.com/vnmedia-vnmedia/p/22.epi'
52 | },
53 | {
54 | 'name': 'ICT News',
55 | 'image': 'assets/images/ictnews.png',
56 | 'url': 'https://m.baomoi.com/ictnews-ictnews/p/107.epi'
57 | },
58 | {
59 | 'name': 'Tiền Phong',
60 | 'image': 'assets/images/tienphong.png',
61 | 'url': 'https://m.baomoi.com/bao-tien-phong-tien-phong/p/20.epi'
62 | },
63 | {
64 | 'name': 'Kiến Thức',
65 | 'image': 'assets/images/kienthuc.jpeg',
66 | 'url': 'https://m.baomoi.com/bao-kien-thuc-kien-thuc/p/180.epi'
67 | },
68 | {
69 | 'name': 'Petro Times',
70 | 'image': 'assets/images/petrotimes.png',
71 | 'url': 'https://m.baomoi.com/bao-nang-luong-moi-petrotimes/p/232.epi'
72 | },
73 | {
74 | 'name': 'Chính Phủ',
75 | 'image': 'assets/images/chinhphu.jpg',
76 | 'url': 'https://m.baomoi.com/bao-chinh-phu-chinh-phu/p/146.epi'
77 | },
78 | {
79 | 'name': 'Chính Phủ',
80 | 'image': 'assets/images/phapluat.png',
81 | 'url': 'https://m.baomoi.com/bao-chinh-phu-chinh-phu/p/146.epi'
82 | }
83 | ];
84 |
85 |
86 | const String APP_ID = 'com.zrgteam.tinmoi';
87 | const String ADMOB_APP_ID = 'ca-app-pub-6308632307209872~8632944973';
88 |
89 | const int SHOW_ADS_COUNT = 5;
90 | const int SHOW_ADS_COUNT_MAX = 10;
91 | const String READING_ADS_ID = 'ca-app-pub-6308632307209872/4190797775';
92 |
--------------------------------------------------------------------------------
/lib/common/reducers/app.dart:
--------------------------------------------------------------------------------
1 | import 'package:cat_dog/common/state.dart';
2 | import 'package:cat_dog/modules/user/reducer.dart';
3 | import 'package:cat_dog/common/reducers/common.dart';
4 | import 'package:cat_dog/modules/dashboard/reducer.dart';
5 | import 'package:cat_dog/modules/soccer/reducer.dart';
6 |
7 | AppState appReducer(AppState state, action){
8 | return new AppState(
9 | user: authReducer(state.user, action),
10 | common: commonReducer(state.common, action),
11 | dashboard: dashboardReducer(state.dashboard, action),
12 | soccer: soccerReducer(state.soccer, action)
13 | );
14 | }
--------------------------------------------------------------------------------
/lib/common/reducers/common.dart:
--------------------------------------------------------------------------------
1 | import 'package:redux/redux.dart';
2 | import 'package:cat_dog/common/actions/common.dart';
3 | import 'package:cat_dog/common/states/common.dart';
4 |
5 | Reducer commonReducer = combineReducers([
6 | new TypedReducer(setFirstOpenReducer),
7 | new TypedReducer(setUserLanguageReducer),
8 | new TypedReducer(setAboutInformationReducer),
9 | new TypedReducer(addReadingCountReducer),
10 | new TypedReducer(clearReadingCountReducer),
11 | ]);
12 |
13 | CommonState setUserLanguageReducer(CommonState common, SetUserLanguage action) {
14 | return common.copyWith(
15 | language: action.language
16 | );
17 | }
18 |
19 | CommonState setAboutInformationReducer(CommonState common, SetAboutInformation action) {
20 | return common.copyWith(
21 | about: action.data
22 | );
23 | }
24 |
25 | CommonState setFirstOpenReducer(CommonState common, SetFirstOpen action) {
26 | return common.copyWith(
27 | first: action.first
28 | );
29 | }
30 |
31 | CommonState addReadingCountReducer(CommonState common, AddReadingCount action) {
32 | return common.copyWith(
33 | readingCount: (common.readingCount ?? 0) + 1
34 | );
35 | }
36 |
37 | CommonState clearReadingCountReducer(CommonState common, ClearReadingCount action) {
38 | return common.copyWith(
39 | readingCount: 0
40 | );
41 | }
--------------------------------------------------------------------------------
/lib/common/repository.dart:
--------------------------------------------------------------------------------
1 | import 'package:http/http.dart' as http;
2 | import 'package:cat_dog/common/configs.dart';
3 |
4 | Future fetchAboutInformation() async {
5 | const url = ABOUT_URL;
6 | var response = await http.get(url);
7 | // print("Response status: ${response.statusCode}");
8 | // print("Response body: ${response.body}");
9 | return response.body;
10 | }
--------------------------------------------------------------------------------
/lib/common/state.dart:
--------------------------------------------------------------------------------
1 | import 'package:meta/meta.dart';
2 | import 'package:cat_dog/common/states/common.dart';
3 | import 'package:cat_dog/modules/user/state.dart';
4 | import 'package:cat_dog/modules/dashboard/state.dart';
5 | import 'package:cat_dog/modules/soccer/state.dart';
6 |
7 | @immutable
8 | class AppState {
9 | final UserState user;
10 | final CommonState common;
11 | final DashboardState dashboard;
12 | final SoccerState soccer;
13 |
14 | AppState({ UserState user, CommonState common, DashboardState dashboard, SoccerState soccer }):
15 | user = user ?? new UserState(),
16 | dashboard = dashboard ?? new DashboardState(),
17 | common = common ?? new CommonState(),
18 | soccer = soccer ?? new SoccerState();
19 |
20 | static AppState rehydrationJSON(dynamic json) {
21 | return new AppState(
22 | user: json != null ? new UserState.fromJSON(json['user']) : new UserState(),
23 | common: json != null ? new CommonState.fromJSON(json['common']) : new CommonState(),
24 | dashboard: json != null ? new DashboardState.fromJSON(json['dashboard']) : new DashboardState(),
25 | soccer: json != null ? new SoccerState.fromJSON(json['soccer']) : new SoccerState()
26 | );
27 | }
28 |
29 | Map toJson() => {
30 | 'user': user.toJSON(),
31 | 'common': common.toJSON(),
32 | 'dashboard': dashboard.toJSON(),
33 | 'soccer': soccer.toJSON()
34 | };
35 |
36 | AppState copyWith({
37 | bool rehydrated,
38 | UserState user,
39 | CommonState common,
40 | DashboardState dashboard,
41 | SoccerState soccer,
42 | }) {
43 | return new AppState(
44 | user: user ?? this.user,
45 | common: common ?? this.common,
46 | dashboard: dashboard ?? this.dashboard,
47 | soccer: soccer ?? this.soccer
48 | );
49 | }
50 | }
--------------------------------------------------------------------------------
/lib/common/states/common.dart:
--------------------------------------------------------------------------------
1 | import 'package:meta/meta.dart';
2 |
3 | @immutable
4 | class CommonState {
5 | // properties
6 | final String language;
7 | final String about;
8 | final bool first;
9 | final int readingCount;
10 |
11 | // constructor with default
12 | CommonState({
13 | this.language = 'en',
14 | this.first = true,
15 | this.about = '',
16 | this.readingCount = 0
17 | });
18 |
19 | // allows to modify AuthState parameters while cloning previous ones
20 | CommonState copyWith({
21 | bool first,
22 | String about,
23 | String language,
24 | int readingCount,
25 | }) {
26 | return new CommonState(
27 | first: first ?? this.first,
28 | about: about ?? this.about,
29 | language: language ?? this.language,
30 | readingCount: readingCount ?? this.readingCount
31 | );
32 | }
33 |
34 | factory CommonState.fromJSON(Map json) => new CommonState(
35 | first: json['first'],
36 | language: json['language'],
37 | about: json['about'],
38 | readingCount: json['readingCount']
39 | );
40 |
41 | Map toJSON() => {
42 | 'first': this.first,
43 | 'language': this.language,
44 | 'about': this.about,
45 | 'readingCount': this.readingCount
46 | };
47 |
48 | @override
49 | String toString() {
50 | return '''{
51 | first: $first,
52 | language: $language,
53 | about: $about,
54 | readingCount: $readingCount
55 | }''';
56 | }
57 | }
--------------------------------------------------------------------------------
/lib/common/store.dart:
--------------------------------------------------------------------------------
1 | import 'package:redux/redux.dart';
2 | import 'package:redux_persist/redux_persist.dart';
3 | import 'package:redux_persist_flutter/redux_persist_flutter.dart';
4 | import 'package:redux_thunk/redux_thunk.dart';
5 | import 'package:cat_dog/common/reducers/app.dart';
6 | import 'package:cat_dog/common/state.dart';
7 | import 'package:redux_logging/redux_logging.dart';
8 |
9 | Future> createStore() async {
10 | final persistor = Persistor(
11 | storage: FlutterStorage(),
12 | serializer: JsonSerializer(AppState.rehydrationJSON)
13 | );
14 | // Load initial state
15 | var initialState;
16 | try {
17 | initialState = await persistor.load();
18 | } catch (err) {}
19 | final store = Store(
20 | appReducer,
21 | initialState: initialState ?? AppState(),
22 | middleware: [
23 | thunkMiddleware,
24 | persistor.createMiddleware(),
25 | new LoggingMiddleware.printer()
26 | ],
27 | );
28 |
29 | return store;
30 | }
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/foundation.dart';
3 | import 'package:flutter_redux/flutter_redux.dart';
4 | import 'package:redux/redux.dart';
5 | import 'package:cat_dog/common/store.dart';
6 | import 'package:cat_dog/common/state.dart';
7 | import 'package:cat_dog/styles/colors.dart';
8 | import 'package:cat_dog/presentation/platform_adaptive.dart';
9 | // PAGES
10 | import 'package:cat_dog/pages/HomePage.dart';
11 |
12 | void main() async {
13 | final store = await createStore();
14 | runApp(new App(
15 | store: store
16 | ));
17 | }
18 |
19 | class App extends StatelessWidget {
20 | final Store store;
21 |
22 | const App({Key key, this.store}) : super(key: key);
23 |
24 | @override
25 | Widget build(BuildContext context) {
26 | return StoreProvider(
27 | store: store,
28 | child: new MaterialApp(
29 | title: 'Tin Mới',
30 | color: AppColors.commonBackgroundColor,
31 | debugShowCheckedModeBanner: false,
32 | showSemanticsDebugger: false,
33 | theme: defaultTargetPlatform == TargetPlatform.iOS
34 | ? kIOSTheme
35 | : kDefaultTheme,
36 | routes: {
37 | // Login feature comming soon
38 | '/': (BuildContext context) => new StoreConnector(
39 | converter: (store) {
40 | return store.state.common.first;
41 | },
42 | builder: (BuildContext context, first) => new HomePage()
43 | )
44 | }
45 | )
46 | );
47 | }
48 | }
--------------------------------------------------------------------------------
/lib/modules/category/actions.dart:
--------------------------------------------------------------------------------
1 | import 'package:html/parser.dart' show parse;
2 | import 'package:cat_dog/modules/category/repository.dart';
3 |
4 |
5 | getNewsFromUrl (String url,int page) async {
6 | String urlPage = "${url.replaceAll('.epi', '')}/trang$page.epi?loadmore=1";
7 | String result = await fetchNewsFromUrl(urlPage);
8 | if (result != '') {
9 | List