From 8b9d3ce105d52690bcaa02d7c6d5243fac391934 Mon Sep 17 00:00:00 2001 From: Alexandru Chiriac Date: Fri, 7 Dec 2018 14:02:45 +0200 Subject: [PATCH 01/89] Update .gitignore, remove ignored files --- .gitignore | 8 +------- .idea/misc.xml | 34 ---------------------------------- .idea/modules.xml | 10 ---------- .idea/vcs.xml | 6 ------ 4 files changed, 1 insertion(+), 57 deletions(-) delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml diff --git a/.gitignore b/.gitignore index 5dc8e9c..3a7c2e7 100644 --- a/.gitignore +++ b/.gitignore @@ -34,13 +34,7 @@ captures/ # IntelliJ *.iml -.idea/workspace.xml -.idea/tasks.xml -.idea/gradle.xml -.idea/assetWizardSettings.xml -.idea/dictionaries -.idea/libraries -.idea/caches +.idea/ # Keystore files # Uncomment the following line if you do not want to check your keystore files in. diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index dc34569..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 5242c8d..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From f6ad1128c3af8530cf5af04866f61e5b95aaf94d Mon Sep 17 00:00:00 2001 From: Alexandru Chiriac Date: Fri, 7 Dec 2018 14:15:55 +0200 Subject: [PATCH 02/89] Update gradle dependencies, add dagger 2 gradle dependency --- app/build.gradle | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index a557046..dcb7543 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -37,13 +37,18 @@ dependencies { implementation 'com.android.support:cardview-v7:27.1.1' implementation 'com.android.support:design:27.1.1' - implementation 'com.squareup.retrofit2:retrofit:2.1.0' - implementation 'com.squareup.retrofit2:converter-gson:2.1.0' - implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1' + implementation 'com.squareup.retrofit2:retrofit:2.4.0' + implementation 'com.squareup.retrofit2:converter-gson:2.4.0' + implementation 'com.squareup.okhttp3:logging-interceptor:3.6.0' implementation 'com.pixplicity.easyprefs:library:1.9.0@aar' + implementation 'com.google.dagger:dagger:2.17' + implementation 'com.google.dagger:dagger-android-support:2.17' + annotationProcessor 'com.google.dagger:dagger-compiler:2.17' + annotationProcessor 'com.google.dagger:dagger-android-processor:2.17' + implementation 'io.reactivex:rxandroid:1.2.1' - implementation 'io.reactivex:rxjava:1.1.6' + implementation 'io.reactivex:rxjava:1.2.4' implementation 'org.greenrobot:eventbus:3.0.0' implementation 'net.hockeyapp.android:HockeySDK:4.1.1' From 8d2dc9d8afedef2381b0ef7d9e69466781e6b95d Mon Sep 17 00:00:00 2001 From: Alexandru Chiriac Date: Fri, 7 Dec 2018 14:23:30 +0200 Subject: [PATCH 03/89] Update gradle plugin --- app/build.gradle | 2 +- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 ++-- mediapicker/build.gradle | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index dcb7543..a342c23 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,7 +3,7 @@ apply plugin: 'realm-android' android { compileSdkVersion 27 - buildToolsVersion '27.0.3' + buildToolsVersion '28.0.3' defaultConfig { applicationId "ro.code4.monitorizarevot" diff --git a/build.gradle b/build.gradle index c195734..1d3a470 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.1.3' + classpath 'com.android.tools.build:gradle:3.2.1' classpath "io.realm:realm-gradle-plugin:3.5.0" // NOTE: Do not place your application dependencies here; they belong diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f65a1dd..dd4adb0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Jun 25 13:00:41 EEST 2018 +#Fri Dec 07 14:17:30 EET 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip diff --git a/mediapicker/build.gradle b/mediapicker/build.gradle index a078d90..551150c 100755 --- a/mediapicker/build.gradle +++ b/mediapicker/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.library' android { compileSdkVersion 27 - buildToolsVersion '27.0.3' + buildToolsVersion '28.0.3' defaultConfig { minSdkVersion 17 From d08b2a9c992d4d5e9add9902081f8a89fb86e4ce Mon Sep 17 00:00:00 2001 From: Alexandru Chiriac Date: Fri, 7 Dec 2018 14:33:11 +0200 Subject: [PATCH 04/89] Update compile sdk version, more gradle dependency updates --- app/build.gradle | 17 ++++++++++------- mediapicker/build.gradle | 8 ++++---- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index a342c23..8bdb50d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,13 +2,13 @@ apply plugin: 'com.android.application' apply plugin: 'realm-android' android { - compileSdkVersion 27 + compileSdkVersion 28 buildToolsVersion '28.0.3' defaultConfig { applicationId "ro.code4.monitorizarevot" minSdkVersion 17 - targetSdkVersion 27 + targetSdkVersion 28 versionCode 12 versionName "0.9.8" } @@ -31,11 +31,14 @@ repositories { } dependencies { + implementation project(path: ':mediapicker') + implementation fileTree(dir: 'libs', include: ['*.jar']) - testImplementation 'junit:junit:4.12' - implementation 'com.android.support:appcompat-v7:27.1.1' - implementation 'com.android.support:cardview-v7:27.1.1' - implementation 'com.android.support:design:27.1.1' + + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support:cardview-v7:28.0.0' + implementation 'com.android.support:design:28.0.0' + implementation 'android.arch.lifecycle:extensions:1.1.1' implementation 'com.squareup.retrofit2:retrofit:2.4.0' implementation 'com.squareup.retrofit2:converter-gson:2.4.0' @@ -53,5 +56,5 @@ dependencies { implementation 'org.greenrobot:eventbus:3.0.0' implementation 'net.hockeyapp.android:HockeySDK:4.1.1' - implementation project(path: ':mediapicker') + testImplementation 'junit:junit:4.12' } diff --git a/mediapicker/build.gradle b/mediapicker/build.gradle index 551150c..5056be0 100755 --- a/mediapicker/build.gradle +++ b/mediapicker/build.gradle @@ -1,12 +1,12 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 27 + compileSdkVersion 28 buildToolsVersion '28.0.3' defaultConfig { minSdkVersion 17 - targetSdkVersion 27 + targetSdkVersion 28 versionCode 1 versionName "1.0" } @@ -22,6 +22,6 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.edmodo:cropper:1.0.1' implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.3' - implementation 'com.android.support:support-v4:27.1.1' - implementation 'com.android.support:appcompat-v7:27.1.1' + implementation 'com.android.support:support-v4:28.0.0' + implementation 'com.android.support:appcompat-v7:28.0.0' } From 29c66898f56e5ff03b25f588ee8d3b24f8adebc5 Mon Sep 17 00:00:00 2001 From: Alexandru Chiriac Date: Fri, 7 Dec 2018 15:06:09 +0200 Subject: [PATCH 05/89] Prepare mock flavor --- app/build.gradle | 36 +++++++++++++++++++++++++ app/src/dev/res/values/authorities.xml | 5 ++++ app/src/main/AndroidManifest.xml | 28 +++++++++++-------- app/src/main/res/xml/syncadapter.xml | 2 +- app/src/mock/res/values/authorities.xml | 5 ++++ app/src/prod/res/values/authorities.xml | 5 ++++ 6 files changed, 69 insertions(+), 12 deletions(-) create mode 100644 app/src/dev/res/values/authorities.xml create mode 100644 app/src/mock/res/values/authorities.xml create mode 100644 app/src/prod/res/values/authorities.xml diff --git a/app/build.gradle b/app/build.gradle index 8bdb50d..4fbc570 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,6 +12,9 @@ android { versionCode 12 versionName "0.9.8" } + + flavorDimensions "default" + buildTypes { release { minifyEnabled false @@ -24,6 +27,23 @@ android { buildConfigField "String", "WEB_BASE_URL", '"http://viuat.azurewebsites.net/"' } } + + productFlavors { + dev { + applicationIdSuffix '.dev' + versionNameSuffix "d" + buildConfigField "String", "WEB_BASE_URL", '"http://viuat.azurewebsites.net/"' + } + + prod { + buildConfigField "String", "WEB_BASE_URL", '"http://viuat.azurewebsites.net/"' + } + + mock { + applicationIdSuffix '.mock' + versionNameSuffix "m" + } + } } repositories { @@ -58,3 +78,19 @@ dependencies { testImplementation 'junit:junit:4.12' } + +android.variantFilter { variant -> + + String release = 'release' + String debug = 'debug' + + boolean shouldBeExcluded = false + + shouldBeExcluded |= variant.buildType.name == release && variant.getFlavors().get(0).name == 'dev' + shouldBeExcluded |= variant.buildType.name == release && variant.getFlavors().get(0).name == 'mock' + shouldBeExcluded |= variant.buildType.name == debug && variant.getFlavors().get(0).name == 'prod' + + if (shouldBeExcluded) { + variant.setIgnore(true); + } +} diff --git a/app/src/dev/res/values/authorities.xml b/app/src/dev/res/values/authorities.xml new file mode 100644 index 0000000..7ad92d1 --- /dev/null +++ b/app/src/dev/res/values/authorities.xml @@ -0,0 +1,5 @@ + + + ro.code4.monitorizarevot.dev + ro.code4.monitorizarevot.dev + \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0cec998..dbc64a8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ - + @@ -11,6 +11,7 @@ + @@ -22,8 +23,8 @@ android:theme="@style/AppTheme"> @@ -32,23 +33,25 @@ + android:theme="@style/AppTheme.Login" /> + android:theme="@style/AppTheme" + android:windowSoftInputMode="stateAlwaysHidden" /> - + + + @@ -59,6 +62,7 @@ android:name="android.accounts.AccountAuthenticator" android:resource="@xml/authenticator" /> + @@ -69,13 +73,15 @@ android:name="android.content.SyncAdapter" android:resource="@xml/syncadapter" /> + + android:syncable="true" /> - diff --git a/app/src/main/res/xml/syncadapter.xml b/app/src/main/res/xml/syncadapter.xml index a3f4358..70fd8c3 100644 --- a/app/src/main/res/xml/syncadapter.xml +++ b/app/src/main/res/xml/syncadapter.xml @@ -1,7 +1,7 @@ + + ro.code4.monitorizarevot.mock + ro.code4.monitorizarevot.mock + \ No newline at end of file diff --git a/app/src/prod/res/values/authorities.xml b/app/src/prod/res/values/authorities.xml new file mode 100644 index 0000000..3c94a4c --- /dev/null +++ b/app/src/prod/res/values/authorities.xml @@ -0,0 +1,5 @@ + + + ro.code4.monitorizarevot + ro.code4.monitorizarevot + \ No newline at end of file From c1bac7fa0ea8ce10df5f7d1d0ae5e1f85c1ccb7b Mon Sep 17 00:00:00 2001 From: Alexandru Chiriac Date: Fri, 7 Dec 2018 15:39:55 +0200 Subject: [PATCH 06/89] Implement dagger appcomponent/injector/module --- .../java/ro/code4/monitorizarevot/App.java | 55 ++++++++++-- .../ro/code4/monitorizarevot/Injectable.java | 5 ++ .../dagger/ActivityBindingModule.java | 22 +++++ .../monitorizarevot/dagger/AppComponent.java | 29 +++++++ .../monitorizarevot/dagger/AppInjector.java | 83 +++++++++++++++++++ .../monitorizarevot/dagger/AppModule.java | 21 +++++ .../dagger/FragmentBindingModule.java | 33 ++++++++ 7 files changed, 240 insertions(+), 8 deletions(-) create mode 100644 app/src/main/java/ro/code4/monitorizarevot/Injectable.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/dagger/ActivityBindingModule.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/dagger/AppComponent.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/dagger/AppInjector.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/dagger/AppModule.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/dagger/FragmentBindingModule.java diff --git a/app/src/main/java/ro/code4/monitorizarevot/App.java b/app/src/main/java/ro/code4/monitorizarevot/App.java index c78da44..5895d48 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/App.java +++ b/app/src/main/java/ro/code4/monitorizarevot/App.java @@ -1,30 +1,58 @@ package ro.code4.monitorizarevot; +import com.pixplicity.easyprefs.library.Prefs; + +import net.hockeyapp.android.CrashManager; + +import android.app.Activity; import android.app.Application; +import android.app.Service; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.ContextWrapper; -import com.pixplicity.easyprefs.library.Prefs; - -import net.hockeyapp.android.CrashManager; +import javax.inject.Inject; +import dagger.android.AndroidInjector; +import dagger.android.DispatchingAndroidInjector; +import dagger.android.HasActivityInjector; +import dagger.android.HasBroadcastReceiverInjector; +import dagger.android.HasServiceInjector; import io.realm.Realm; import io.realm.RealmConfiguration; +import ro.code4.monitorizarevot.dagger.AppInjector; + +public class App extends Application implements HasActivityInjector, HasBroadcastReceiverInjector, HasServiceInjector { -public class App extends Application { private static Context mContext; + @Inject + DispatchingAndroidInjector mDispatchingActivityInjector; + + @Inject + DispatchingAndroidInjector mDispatchingBroadcastReceiverInjector; + + @Inject + DispatchingAndroidInjector mDispatchingServiceInjector; + + public static Context getContext() { + return mContext; + } + @Override public void onCreate() { super.onCreate(); + + AppInjector.init(this); + mContext = getApplicationContext(); CrashManager.register(this); Realm.init(this); Realm.setDefaultConfiguration(new RealmConfiguration .Builder() - .deleteRealmIfMigrationNeeded() - .build()); + .deleteRealmIfMigrationNeeded() + .build()); new Prefs.Builder() .setContext(this) @@ -34,7 +62,18 @@ public void onCreate() { .build(); } - public static Context getContext() { - return mContext; + @Override + public AndroidInjector activityInjector() { + return mDispatchingActivityInjector; + } + + @Override + public AndroidInjector broadcastReceiverInjector() { + return mDispatchingBroadcastReceiverInjector; + } + + @Override + public AndroidInjector serviceInjector() { + return mDispatchingServiceInjector; } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/Injectable.java b/app/src/main/java/ro/code4/monitorizarevot/Injectable.java new file mode 100644 index 0000000..1057b68 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/Injectable.java @@ -0,0 +1,5 @@ +package ro.code4.monitorizarevot; + +public interface Injectable { + +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/dagger/ActivityBindingModule.java b/app/src/main/java/ro/code4/monitorizarevot/dagger/ActivityBindingModule.java new file mode 100644 index 0000000..3fc41d5 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/dagger/ActivityBindingModule.java @@ -0,0 +1,22 @@ +package ro.code4.monitorizarevot.dagger; + +import dagger.Module; +import dagger.android.ContributesAndroidInjector; +import ro.code4.monitorizarevot.LoginActivity; +import ro.code4.monitorizarevot.StartActivity; +import ro.code4.monitorizarevot.ToolbarActivity; + +@Module +public abstract class ActivityBindingModule { + + @ContributesAndroidInjector + abstract StartActivity activityStart(); + + @ContributesAndroidInjector + abstract LoginActivity loginActivity(); + + @ContributesAndroidInjector(modules = {FragmentBindingModule.class}) + abstract ToolbarActivity toolbarActivity(); + + +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/dagger/AppComponent.java b/app/src/main/java/ro/code4/monitorizarevot/dagger/AppComponent.java new file mode 100644 index 0000000..fb69ac8 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/dagger/AppComponent.java @@ -0,0 +1,29 @@ +package ro.code4.monitorizarevot.dagger; + +import android.app.Application; + +import javax.inject.Singleton; + +import dagger.BindsInstance; +import dagger.Component; +import dagger.android.support.AndroidSupportInjectionModule; +import ro.code4.monitorizarevot.App; + +@Singleton +@Component(modules = { + AndroidSupportInjectionModule.class, + AppModule.class +}) +public interface AppComponent { + + void inject(App application); + + @Component.Builder + interface Builder { + + @BindsInstance + Builder application(Application application); + + AppComponent build(); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/dagger/AppInjector.java b/app/src/main/java/ro/code4/monitorizarevot/dagger/AppInjector.java new file mode 100644 index 0000000..fe7d622 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/dagger/AppInjector.java @@ -0,0 +1,83 @@ +package ro.code4.monitorizarevot.dagger; + +import android.app.Activity; +import android.app.Application; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; + +import dagger.android.AndroidInjection; +import dagger.android.support.AndroidSupportInjection; +import ro.code4.monitorizarevot.App; +import ro.code4.monitorizarevot.Injectable; + +/** + * Component that initializes the application's dependency graph (sets up the app's dagger component). + */ +public class AppInjector { + + private AppInjector() { + } + + public static void init(App application) { + DaggerAppComponent.builder().application(application).build().inject(application); + + application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() { + + @Override + public void onActivityCreated(Activity activity, Bundle bundle) { + handleActivity(activity); + } + + @Override + public void onActivityStarted(Activity activity) { + + } + + @Override + public void onActivityResumed(Activity activity) { + + } + + @Override + public void onActivityPaused(Activity activity) { + + } + + @Override + public void onActivityStopped(Activity activity) { + + } + + @Override + public void onActivitySaveInstanceState(Activity activity, Bundle bundle) { + + } + + @Override + public void onActivityDestroyed(Activity activity) { + + } + }); + } + + private static void handleActivity(Activity activity) { + AndroidInjection.inject(activity); + + if (activity instanceof FragmentActivity) { + ((FragmentActivity) activity).getSupportFragmentManager() + .registerFragmentLifecycleCallbacks(new FragmentManager.FragmentLifecycleCallbacks() { + + @Override + public void onFragmentCreated(@NonNull FragmentManager fragmentManager, @NonNull Fragment fragment, + Bundle savedInstanceState) { + if (fragment instanceof Injectable) { + AndroidSupportInjection.inject(fragment); + } + } + }, true); + } + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/dagger/AppModule.java b/app/src/main/java/ro/code4/monitorizarevot/dagger/AppModule.java new file mode 100644 index 0000000..b7a5d60 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/dagger/AppModule.java @@ -0,0 +1,21 @@ +package ro.code4.monitorizarevot.dagger; + +import android.app.Application; +import android.content.Context; + +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; + +@Module(includes = { + ActivityBindingModule.class +}) +class AppModule { + + @Provides + @Singleton + static Context provideAppContext(Application application) { + return application; + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/dagger/FragmentBindingModule.java b/app/src/main/java/ro/code4/monitorizarevot/dagger/FragmentBindingModule.java new file mode 100644 index 0000000..16e0705 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/dagger/FragmentBindingModule.java @@ -0,0 +1,33 @@ +package ro.code4.monitorizarevot.dagger; + +import dagger.Module; +import dagger.android.ContributesAndroidInjector; +import ro.code4.monitorizarevot.fragment.*; + +@Module +public abstract class FragmentBindingModule { + + @ContributesAndroidInjector + abstract AddNoteFragment contributeAddNoteFragment(); + + @ContributesAndroidInjector + abstract BranchDetailsFragment contributeBranchDetailsFragment(); + + @ContributesAndroidInjector + abstract BranchSelectionFragment contributeBranchSelectionFragment(); + + @ContributesAndroidInjector + abstract FormsListFragment contributeFormsListFragment(); + + @ContributesAndroidInjector + abstract GuideFragment contributeGuideFragment(); + + @ContributesAndroidInjector + abstract QuestionFragment contributeQuestionFragment(); + + @ContributesAndroidInjector + abstract QuestionsDetailsFragment contributeQuestionDetailsFragment(); + + @ContributesAndroidInjector + abstract QuestionsOverviewFragment contributeQuestionOverviewFragment(); +} From 5c97a0ad4cbbffb51548bac14dd3c7dcff0802b4 Mon Sep 17 00:00:00 2001 From: Alexandru Chiriac Date: Fri, 7 Dec 2018 17:53:50 +0200 Subject: [PATCH 07/89] Add ViewModels for every activity/fragment, injected via viewmodelprovider + dagger --- .../code4/monitorizarevot/BaseActivity.java | 49 ++++++--- .../code4/monitorizarevot/BaseFragment.java | 24 ++++- .../code4/monitorizarevot/LoginActivity.java | 21 +++- .../code4/monitorizarevot/StartActivity.java | 12 ++- .../monitorizarevot/ToolbarActivity.java | 46 +++++--- .../dagger/ActivityBindingModule.java | 2 +- .../monitorizarevot/dagger/ViewModelKey.java | 20 ++++ .../dagger/ViewModelModule.java | 72 +++++++++++++ .../fragment/AddNoteFragment.java | 100 ++++++++++-------- .../fragment/BranchDetailsFragment.java | 39 ++++--- .../fragment/BranchSelectionFragment.java | 36 ++++--- .../fragment/FormsListFragment.java | 36 ++++--- .../fragment/GuideFragment.java | 12 ++- .../fragment/QuestionFragment.java | 16 ++- .../fragment/QuestionsDetailsFragment.java | 29 +++-- .../fragment/QuestionsOverviewFragment.java | 24 +++-- .../util/AbstractComponentFactory.java | 42 ++++++++ .../viewmodel/AddNoteViewModel.java | 11 ++ .../viewmodel/BaseViewModel.java | 9 ++ .../viewmodel/BranchDetailsViewModel.java | 11 ++ .../viewmodel/BranchSelectionViewModel.java | 11 ++ .../viewmodel/FormsListViewModel.java | 12 +++ .../viewmodel/GuideViewModel.java | 11 ++ .../viewmodel/LoginViewModel.java | 11 ++ .../viewmodel/QuestionDetailsViewModel.java | 11 ++ .../viewmodel/QuestionOverviewViewModel.java | 11 ++ .../viewmodel/QuestionViewModel.java | 11 ++ .../viewmodel/StartViewModel.java | 11 ++ .../viewmodel/ToolbarViewModel.java | 11 ++ .../viewmodel/ViewModelFactory.java | 19 ++++ 30 files changed, 579 insertions(+), 151 deletions(-) create mode 100644 app/src/main/java/ro/code4/monitorizarevot/dagger/ViewModelKey.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/dagger/ViewModelModule.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/util/AbstractComponentFactory.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/viewmodel/AddNoteViewModel.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/viewmodel/BaseViewModel.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchDetailsViewModel.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchSelectionViewModel.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/viewmodel/FormsListViewModel.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/viewmodel/GuideViewModel.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/viewmodel/LoginViewModel.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionDetailsViewModel.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionOverviewViewModel.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionViewModel.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/viewmodel/StartViewModel.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/viewmodel/ToolbarViewModel.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/viewmodel/ViewModelFactory.java diff --git a/app/src/main/java/ro/code4/monitorizarevot/BaseActivity.java b/app/src/main/java/ro/code4/monitorizarevot/BaseActivity.java index 9c88cfd..0e0262e 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/BaseActivity.java +++ b/app/src/main/java/ro/code4/monitorizarevot/BaseActivity.java @@ -1,6 +1,11 @@ package ro.code4.monitorizarevot; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + import android.app.ProgressDialog; +import android.arch.lifecycle.ViewModelProvider; import android.content.Context; import android.content.Intent; import android.os.Bundle; @@ -10,27 +15,47 @@ import android.support.v7.app.AppCompatActivity; import android.view.inputmethod.InputMethodManager; -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; -import org.greenrobot.eventbus.ThreadMode; - import java.util.List; +import javax.inject.Inject; + import ro.code4.monitorizarevot.net.model.LogoutListener; import ro.code4.monitorizarevot.util.ActivityOperations; import ro.code4.monitorizarevot.util.AuthUtils; +import ro.code4.monitorizarevot.viewmodel.BaseViewModel; + +public abstract class BaseActivity extends AppCompatActivity implements ActivityOperations { + + protected VM viewModel; + + @Inject + protected ViewModelProvider.Factory factory; -public class BaseActivity extends AppCompatActivity implements ActivityOperations { private ProgressDialog loadingIndicator; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + setupViewModel(); + loadingIndicator = new ProgressDialog(this); loadingIndicator.setMessage("Vă rugăm așteptaţi..."); loadingIndicator.setCancelable(false); } + @Override + protected void onStart() { + super.onStart(); + EventBus.getDefault().register(this); + } + + @Override + protected void onStop() { + super.onStop(); + EventBus.getDefault().unregister(this); + } + public void showLoading() { loadingIndicator.show(); } @@ -50,18 +75,6 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis } } - @Override - protected void onStart() { - super.onStart(); - EventBus.getDefault().register(this); - } - - @Override - protected void onStop() { - super.onStop(); - EventBus.getDefault().unregister(this); - } - @Subscribe(threadMode = ThreadMode.MAIN) public void onMessageEvent(LogoutListener event) { AuthUtils.removeAccountAndStopSync(); @@ -78,4 +91,6 @@ public void hideFocusedKeyboard() { imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); } } + + protected abstract void setupViewModel(); } diff --git a/app/src/main/java/ro/code4/monitorizarevot/BaseFragment.java b/app/src/main/java/ro/code4/monitorizarevot/BaseFragment.java index d99e992..6c78ade 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/BaseFragment.java +++ b/app/src/main/java/ro/code4/monitorizarevot/BaseFragment.java @@ -1,5 +1,6 @@ package ro.code4.monitorizarevot; +import android.arch.lifecycle.ViewModelProvider; import android.content.Context; import android.content.pm.PackageManager; import android.os.Bundle; @@ -9,12 +10,23 @@ import android.support.v4.app.Fragment; import android.support.v4.content.ContextCompat; +import javax.inject.Inject; + import io.realm.Realm; import ro.code4.monitorizarevot.util.ActivityOperations; +import ro.code4.monitorizarevot.viewmodel.BaseViewModel; + +public abstract class BaseFragment extends Fragment implements Navigator, ActivityOperations, Injectable { + + protected VM viewModel; + + @Inject + protected ViewModelProvider.Factory factory; -public abstract class BaseFragment extends Fragment implements Navigator, ActivityOperations { private Navigator navigator; + private ActivityOperations operations; + private Realm realm; @Override @@ -71,6 +83,8 @@ public void navigateBackUntil(int backstackIndex) { navigator.navigateBackUntil(backstackIndex); } + public abstract String getTitle(); + @Override public void setTitle(String title) { navigator.setTitle(title); @@ -81,8 +95,6 @@ public void setMenu(boolean isEnabled) { navigator.setMenu(isEnabled); } - public abstract String getTitle(); - /** * Return false from subclass to hide the hamburger icon */ @@ -102,12 +114,14 @@ protected boolean hasGrantedPermission(@NonNull int[] grantResults) { protected void requestPermission(String permission, int requestCode) { ActivityCompat.requestPermissions(getActivity(), - new String[]{ permission }, - requestCode); + new String[]{permission}, + requestCode); } @Override public void hideFocusedKeyboard() { operations.hideFocusedKeyboard(); } + + protected abstract void setupViewModel(); } diff --git a/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java b/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java index 6788d7c..941d352 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java +++ b/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java @@ -1,6 +1,7 @@ package ro.code4.monitorizarevot; import android.app.ActivityOptions; +import android.arch.lifecycle.ViewModelProviders; import android.content.Intent; import android.os.Bundle; import android.provider.Settings; @@ -16,12 +17,17 @@ import ro.code4.monitorizarevot.net.model.User; import ro.code4.monitorizarevot.observable.ObservableListener; import ro.code4.monitorizarevot.observable.ObservableListenerDetacher; +import ro.code4.monitorizarevot.viewmodel.LoginViewModel; import vn.tungdx.mediapicker.activities.MediaPickerErrorDialog; -public class LoginActivity extends BaseActivity { +public class LoginActivity extends BaseActivity { + private EditText username; + private EditText password; + private Button loginButton; + private ObservableListenerDetacher mListenerDetacher; @Override @@ -43,10 +49,15 @@ public void onClick(View view) { setAppVersion((TextView) findViewById(R.id.app_version)); } + @Override + protected void setupViewModel() { + viewModel = ViewModelProviders.of(this, factory).get(LoginViewModel.class); + } + @Override protected void onDestroy() { super.onDestroy(); - if(mListenerDetacher != null && !mListenerDetacher.isDetached()){ + if (mListenerDetacher != null && !mListenerDetacher.isDetached()) { mListenerDetacher.detach(); } } @@ -59,7 +70,7 @@ private void login() { String userName = username.getText().toString(); String pass = password.getText().toString(); - if(!TextUtils.isEmpty(userName.trim()) && !TextUtils.isEmpty(pass.trim())){ + if (!TextUtils.isEmpty(userName.trim()) && !TextUtils.isEmpty(pass.trim())) { showLoading(); User user = new User(userName, pass, getUdid()); mListenerDetacher = NetworkService.login(user).startRequest(new LoginSubscriber()); @@ -75,6 +86,7 @@ private String getUdid() { } private class LoginSubscriber extends ObservableListener { + @Override public void onError(Throwable e) { super.onError(e); @@ -90,7 +102,8 @@ public void onSuccess() { Intent intent = new Intent(LoginActivity.this, ToolbarActivity.class); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { ActivityOptions options; - Pair sharedBackground = new Pair<>(findViewById(R.id.purple_background), getString(R.string.shared_element_login_background)); + Pair sharedBackground = new Pair<>(findViewById(R.id.purple_background), + getString(R.string.shared_element_login_background)); Pair sharedLogo = new Pair<>(findViewById(R.id.logo), getString(R.string.shared_element_logo)); options = ActivityOptions .makeSceneTransitionAnimation(LoginActivity.this, sharedBackground, sharedLogo); diff --git a/app/src/main/java/ro/code4/monitorizarevot/StartActivity.java b/app/src/main/java/ro/code4/monitorizarevot/StartActivity.java index 2017c9e..a58068f 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/StartActivity.java +++ b/app/src/main/java/ro/code4/monitorizarevot/StartActivity.java @@ -1,13 +1,16 @@ package ro.code4.monitorizarevot; +import android.arch.lifecycle.ViewModelProviders; import android.content.Intent; import android.os.Bundle; import android.support.annotation.Nullable; import ro.code4.monitorizarevot.db.Preferences; import ro.code4.monitorizarevot.observable.ObservableListener; +import ro.code4.monitorizarevot.viewmodel.StartViewModel; + +public class StartActivity extends BaseActivity { -public class StartActivity extends BaseActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -15,13 +18,18 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { Preferences.isAlreadyLoggedIn().startRequest(new PreferencesSubscriber()); } + @Override + protected void setupViewModel() { + viewModel = ViewModelProviders.of(this, factory).get(StartViewModel.class); + } + private class PreferencesSubscriber extends ObservableListener { @Override public void onNext(Boolean hasCredentials) { super.onNext(hasCredentials); startActivity(new Intent(StartActivity.this, - hasCredentials ? ToolbarActivity.class : LoginActivity.class)); + hasCredentials ? ToolbarActivity.class : LoginActivity.class)); } @Override diff --git a/app/src/main/java/ro/code4/monitorizarevot/ToolbarActivity.java b/app/src/main/java/ro/code4/monitorizarevot/ToolbarActivity.java index 5056c32..477be94 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/ToolbarActivity.java +++ b/app/src/main/java/ro/code4/monitorizarevot/ToolbarActivity.java @@ -1,5 +1,6 @@ package ro.code4.monitorizarevot; +import android.arch.lifecycle.ViewModelProviders; import android.content.Intent; import android.net.Uri; import android.os.Bundle; @@ -15,13 +16,18 @@ import ro.code4.monitorizarevot.fragment.BranchSelectionFragment; import ro.code4.monitorizarevot.fragment.FormsListFragment; import ro.code4.monitorizarevot.fragment.GuideFragment; +import ro.code4.monitorizarevot.viewmodel.ToolbarViewModel; + +public class ToolbarActivity extends BaseActivity implements Navigator { -public class ToolbarActivity extends BaseActivity implements Navigator { public static final int BRANCH_SELECTION_BACKSTACK_INDEX = 0; private DrawerLayout drawerLayout; + private View menuButton; + private TextView toolbarTitle; + private String currentFragmentClassName; @Override @@ -39,6 +45,11 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { navigateTo(BranchSelectionFragment.newInstance()); } + @Override + protected void setupViewModel() { + viewModel = ViewModelProviders.of(this, factory).get(ToolbarViewModel.class); + } + private void initNavigationDrawer() { menuButton.setOnClickListener(new View.OnClickListener() { @Override @@ -116,34 +127,35 @@ public void navigateBackUntil(int backstackIndex) { } } + @Override + public void setTitle(String title) { + toolbarTitle.setText(title); + } + + @Override + public void setMenu(boolean isEnabled) { + menuButton.setVisibility(isEnabled ? + View.VISIBLE : + View.GONE); + drawerLayout.setDrawerLockMode(isEnabled ? + DrawerLayout.LOCK_MODE_UNLOCKED : + DrawerLayout.LOCK_MODE_LOCKED_CLOSED); + } + @Override public void onBackPressed() { if (getSupportFragmentManager().getBackStackEntryCount() > 1) { hideFocusedKeyboard(); super.onBackPressed(); if (getSupportFragmentManager().getBackStackEntryCount() > 0) { - currentFragmentClassName = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1).getName(); + currentFragmentClassName = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1) + .getName(); } } else { finish(); } } - @Override - public void setTitle(String title) { - toolbarTitle.setText(title); - } - - @Override - public void setMenu(boolean isEnabled) { - menuButton.setVisibility(isEnabled ? - View.VISIBLE : - View.GONE); - drawerLayout.setDrawerLockMode(isEnabled ? - DrawerLayout.LOCK_MODE_UNLOCKED : - DrawerLayout.LOCK_MODE_LOCKED_CLOSED); - } - private void closeDrawer() { if (drawerLayout.isDrawerOpen(GravityCompat.START)) { drawerLayout.closeDrawer(GravityCompat.START); diff --git a/app/src/main/java/ro/code4/monitorizarevot/dagger/ActivityBindingModule.java b/app/src/main/java/ro/code4/monitorizarevot/dagger/ActivityBindingModule.java index 3fc41d5..84c915d 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/dagger/ActivityBindingModule.java +++ b/app/src/main/java/ro/code4/monitorizarevot/dagger/ActivityBindingModule.java @@ -6,7 +6,7 @@ import ro.code4.monitorizarevot.StartActivity; import ro.code4.monitorizarevot.ToolbarActivity; -@Module +@Module(includes = {ViewModelModule.class}) public abstract class ActivityBindingModule { @ContributesAndroidInjector diff --git a/app/src/main/java/ro/code4/monitorizarevot/dagger/ViewModelKey.java b/app/src/main/java/ro/code4/monitorizarevot/dagger/ViewModelKey.java new file mode 100644 index 0000000..5070ae3 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/dagger/ViewModelKey.java @@ -0,0 +1,20 @@ +package ro.code4.monitorizarevot.dagger; + +import android.arch.lifecycle.ViewModel; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import dagger.MapKey; + +@Documented +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@MapKey +public @interface ViewModelKey { + + Class value(); +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/dagger/ViewModelModule.java b/app/src/main/java/ro/code4/monitorizarevot/dagger/ViewModelModule.java new file mode 100644 index 0000000..5b29450 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/dagger/ViewModelModule.java @@ -0,0 +1,72 @@ +package ro.code4.monitorizarevot.dagger; + +import android.arch.lifecycle.ViewModel; +import android.arch.lifecycle.ViewModelProvider; + +import dagger.Binds; +import dagger.Module; +import dagger.multibindings.IntoMap; +import ro.code4.monitorizarevot.viewmodel.*; + +@Module +public abstract class ViewModelModule { + + @Binds + abstract ViewModelProvider.Factory bindViewModelFactory(ViewModelFactory factory); + + @Binds + @IntoMap + @ViewModelKey(StartViewModel.class) + abstract ViewModel bindStartViewModel(StartViewModel viewModel); + + @Binds + @IntoMap + @ViewModelKey(LoginViewModel.class) + abstract ViewModel bindLoginViewModel(LoginViewModel viewModel); + + @Binds + @IntoMap + @ViewModelKey(ToolbarViewModel.class) + abstract ViewModel bindToolbarViewModel(ToolbarViewModel viewModel); + + @Binds + @IntoMap + @ViewModelKey(AddNoteViewModel.class) + abstract ViewModel bindAddNoteViewModel(AddNoteViewModel viewModel); + + @Binds + @IntoMap + @ViewModelKey(BranchDetailsViewModel.class) + abstract ViewModel bindBranchDetailsViewModel(BranchDetailsViewModel viewModel); + + @Binds + @IntoMap + @ViewModelKey(BranchSelectionViewModel.class) + abstract ViewModel bindBranchSelectionViewModel(BranchSelectionViewModel viewModel); + + @Binds + @IntoMap + @ViewModelKey(FormsListViewModel.class) + abstract ViewModel bindFormsListViewModel(FormsListViewModel viewModel); + + @Binds + @IntoMap + @ViewModelKey(GuideViewModel.class) + abstract ViewModel bindGuideViewModel(GuideViewModel viewModel); + + @Binds + @IntoMap + @ViewModelKey(QuestionDetailsViewModel.class) + abstract ViewModel bindQuestionDetailsViewModel(QuestionDetailsViewModel viewModel); + + @Binds + @IntoMap + @ViewModelKey(QuestionOverviewViewModel.class) + abstract ViewModel bindQuestionOverviewViewModel(QuestionOverviewViewModel viewModel); + + @Binds + @IntoMap + @ViewModelKey(QuestionViewModel.class) + abstract ViewModel bindQuestionViewModel(QuestionViewModel viewModel); + +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/fragment/AddNoteFragment.java b/app/src/main/java/ro/code4/monitorizarevot/fragment/AddNoteFragment.java index b6193a8..aef6233 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/fragment/AddNoteFragment.java +++ b/app/src/main/java/ro/code4/monitorizarevot/fragment/AddNoteFragment.java @@ -1,6 +1,7 @@ package ro.code4.monitorizarevot.fragment; import android.Manifest; +import android.arch.lifecycle.ViewModelProviders; import android.content.Intent; import android.os.Bundle; import android.support.annotation.NonNull; @@ -21,6 +22,7 @@ import ro.code4.monitorizarevot.net.model.Note; import ro.code4.monitorizarevot.observable.GeneralSubscriber; import ro.code4.monitorizarevot.util.NetworkUtils; +import ro.code4.monitorizarevot.viewmodel.AddNoteViewModel; import ro.code4.monitorizarevot.widget.FileSelectorButton; import vn.tungdx.mediapicker.MediaItem; import vn.tungdx.mediapicker.MediaOptions; @@ -28,13 +30,20 @@ import static android.app.Activity.RESULT_OK; -public class AddNoteFragment extends BaseFragment { +public class AddNoteFragment extends BaseFragment { + private static final String ARGS_QUESTION_ID = "QuestionId"; + private static final int PERMISSIONS_READ_EXTERNAL_STORAGE = 1001; + private static final int REQUEST_MEDIA = 100; + private Integer questionId; + private EditText description; + private FileSelectorButton fileSelectorButton; + private MediaItem mediaItem; public static AddNoteFragment newInstance() { @@ -57,6 +66,49 @@ public void onCreate(Bundle savedInstanceState) { } } + @Override + public String getTitle() { + return getString(R.string.title_note); + } + + @Override + protected void setupViewModel() { + viewModel = ViewModelProviders.of(this, factory).get(AddNoteViewModel.class); + } + + private void openMediaPicker() { + MediaOptions.Builder optionsBuilder = new MediaOptions.Builder(); + optionsBuilder.canSelectBothPhotoVideo(); + MediaPickerActivity.open(AddNoteFragment.this, REQUEST_MEDIA, optionsBuilder.build()); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == REQUEST_MEDIA && resultCode == RESULT_OK) { + List mediaSelectedList = MediaPickerActivity + .getMediaItemSelected(data); + if (mediaSelectedList != null && mediaSelectedList.size() > 0) { + mediaItem = mediaSelectedList.get(0); + fileSelectorButton.setText(getFileName(mediaItem)); + } + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + switch (requestCode) { + case PERMISSIONS_READ_EXTERNAL_STORAGE: { + if (hasGrantedPermission(grantResults)) { + openMediaPicker(); + } else { + Toast.makeText(App.getContext(), "Permisiunea este necesară pentru a putea selecta o resursă", Toast.LENGTH_LONG).show(); + } + break; + } + } + } + @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { @@ -72,7 +124,7 @@ public void onClick(View v) { openMediaPicker(); } else { requestPermission(Manifest.permission.READ_EXTERNAL_STORAGE, - PERMISSIONS_READ_EXTERNAL_STORAGE); + PERMISSIONS_READ_EXTERNAL_STORAGE); } } }); @@ -93,44 +145,6 @@ public void onClick(View v) { return rootView; } - @Override - public String getTitle() { - return getString(R.string.title_note); - } - - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - switch (requestCode) { - case PERMISSIONS_READ_EXTERNAL_STORAGE: { - if (hasGrantedPermission(grantResults)) { - openMediaPicker(); - } else { - Toast.makeText(App.getContext(), "Permisiunea este necesară pentru a putea selecta o resursă", Toast.LENGTH_LONG).show(); - } - break; - } - } - } - - private void openMediaPicker() { - MediaOptions.Builder optionsBuilder = new MediaOptions.Builder(); - optionsBuilder.canSelectBothPhotoVideo(); - MediaPickerActivity.open(AddNoteFragment.this, REQUEST_MEDIA, optionsBuilder.build()); - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (requestCode == REQUEST_MEDIA && resultCode == RESULT_OK) { - List mediaSelectedList = MediaPickerActivity - .getMediaItemSelected(data); - if (mediaSelectedList != null && mediaSelectedList.size() > 0) { - mediaItem = mediaSelectedList.get(0); - fileSelectorButton.setText(getFileName(mediaItem)); - } - } - } - private void saveNote(MediaItem item) { Note note = Data.getInstance().saveNote( mediaItem != null ? item.getPathOrigin(getActivity()) : null, @@ -139,14 +153,14 @@ private void saveNote(MediaItem item) { syncCurrentNote(note); } - private void syncCurrentNote(Note note){ - if(NetworkUtils.isOnline(getActivity())){ + private void syncCurrentNote(Note note) { + if (NetworkUtils.isOnline(getActivity())) { NetworkService.syncCurrentNote(note).startRequest(new GeneralSubscriber()); } } private String getFileName(MediaItem item) { String path = item.getPathOrigin(getActivity()); - return path.substring(path.lastIndexOf("/")+1); + return path.substring(path.lastIndexOf("/") + 1); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/fragment/BranchDetailsFragment.java b/app/src/main/java/ro/code4/monitorizarevot/fragment/BranchDetailsFragment.java index 6b344a1..ec5da3c 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/fragment/BranchDetailsFragment.java +++ b/app/src/main/java/ro/code4/monitorizarevot/fragment/BranchDetailsFragment.java @@ -1,17 +1,13 @@ package ro.code4.monitorizarevot.fragment; import android.app.TimePickerDialog; +import android.arch.lifecycle.ViewModelProviders; import android.os.Bundle; import android.support.annotation.Nullable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.Button; -import android.widget.RadioButton; -import android.widget.RadioGroup; -import android.widget.TextView; -import android.widget.TimePicker; -import android.widget.Toast; +import android.widget.*; import java.text.SimpleDateFormat; import java.util.Calendar; @@ -23,15 +19,21 @@ import ro.code4.monitorizarevot.db.Preferences; import ro.code4.monitorizarevot.net.model.BranchDetails; import ro.code4.monitorizarevot.util.DateUtils; +import ro.code4.monitorizarevot.viewmodel.BranchDetailsViewModel; import ro.code4.monitorizarevot.widget.ChangeBranchBarLayout; import static ro.code4.monitorizarevot.ToolbarActivity.BRANCH_SELECTION_BACKSTACK_INDEX; -public class BranchDetailsFragment extends BaseFragment implements View.OnClickListener { +public class BranchDetailsFragment extends BaseFragment implements View.OnClickListener { + private RadioGroup environmentRadioGroup, sexRadioGroup; + private RadioButton urban, rural, male, female; + private TextView timeEnterText, timeLeaveText; + private Calendar timeEnter, timeLeave; + private BranchDetails existingBranchDetails; public static BranchDetailsFragment newInstance() { @@ -113,7 +115,13 @@ public void onClick(View v) { }); } - @Override + private void showTimePicker(int titleId, TimePickerDialog.OnTimeSetListener listener) { + Calendar now = Calendar.getInstance(); + TimePickerDialog timePickerDialog = new TimePickerDialog(getActivity(), + listener, now.get(Calendar.HOUR_OF_DAY), now.get(Calendar.MINUTE), true); + timePickerDialog.setTitle(titleId); + timePickerDialog.show(); + } @Override public void onClick(View v) { switch (v.getId()) { case R.id.branch_time_enter: @@ -139,14 +147,6 @@ public void onTimeSet(TimePicker view, int hourOfDay, int minute) { } } - private void showTimePicker(int titleId, TimePickerDialog.OnTimeSetListener listener) { - Calendar now = Calendar.getInstance(); - TimePickerDialog timePickerDialog = new TimePickerDialog(getActivity(), - listener, now.get(Calendar.HOUR_OF_DAY), now.get(Calendar.MINUTE), true); - timePickerDialog.setTitle(titleId); - timePickerDialog.show(); - } - private void updateCalendar(Calendar calendar, int hourOfDay, int minute) { calendar.set(Calendar.HOUR_OF_DAY, hourOfDay); calendar.set(Calendar.MINUTE, minute); @@ -178,4 +178,11 @@ public String getTitle() { public boolean withMenu() { return false; } + + @Override + protected void setupViewModel() { + viewModel = ViewModelProviders.of(this, factory).get(BranchDetailsViewModel.class); + } + + } diff --git a/app/src/main/java/ro/code4/monitorizarevot/fragment/BranchSelectionFragment.java b/app/src/main/java/ro/code4/monitorizarevot/fragment/BranchSelectionFragment.java index de8fe1c..85a17db 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/fragment/BranchSelectionFragment.java +++ b/app/src/main/java/ro/code4/monitorizarevot/fragment/BranchSelectionFragment.java @@ -1,5 +1,6 @@ package ro.code4.monitorizarevot.fragment; +import android.arch.lifecycle.ViewModelProviders; import android.os.Bundle; import android.support.annotation.Nullable; import android.view.LayoutInflater; @@ -15,10 +16,14 @@ import ro.code4.monitorizarevot.R; import ro.code4.monitorizarevot.constants.County; import ro.code4.monitorizarevot.db.Preferences; +import ro.code4.monitorizarevot.viewmodel.BranchSelectionViewModel; + +public class BranchSelectionFragment extends BaseFragment { -public class BranchSelectionFragment extends BaseFragment { private Spinner countySpinner; + private EditText branchNumber; + private County selectedCounty; public static BranchSelectionFragment newInstance() { @@ -51,9 +56,24 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) { } } + @Override + public String getTitle() { + return getString(R.string.title_branch_selection); + } + + @Override + public boolean withMenu() { + return false; + } + + @Override + protected void setupViewModel() { + viewModel = ViewModelProviders.of(this, factory).get(BranchSelectionViewModel.class); + } + private void setCountiesDropdown(Spinner dropdown) { ArrayAdapter countyAdapter = new ArrayAdapter<>(getActivity(), - R.layout.support_simple_spinner_dropdown_item, County.getCountiesNames()); + R.layout.support_simple_spinner_dropdown_item, County.getCountiesNames()); dropdown.setAdapter(countyAdapter); dropdown.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override @@ -89,16 +109,6 @@ public void onClick(View v) { }); } - @Override - public String getTitle() { - return getString(R.string.title_branch_selection); - } - - @Override - public boolean withMenu() { - return false; - } - private void persistSelection() { Preferences.saveCountyCode(County.getCountyByIndex(countySpinner.getSelectedItemPosition()).getCode()); Preferences.saveBranchNumber(getBranchNumber()); @@ -114,6 +124,6 @@ public int getBranchNumber() { public String getBranchExceededError() { return getString(R.string.invalid_branch_number_max, - selectedCounty.getName(), String.valueOf(selectedCounty.getBranchesCount())); + selectedCounty.getName(), String.valueOf(selectedCounty.getBranchesCount())); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/fragment/FormsListFragment.java b/app/src/main/java/ro/code4/monitorizarevot/fragment/FormsListFragment.java index 26242aa..dc0fa16 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/fragment/FormsListFragment.java +++ b/app/src/main/java/ro/code4/monitorizarevot/fragment/FormsListFragment.java @@ -1,5 +1,6 @@ package ro.code4.monitorizarevot.fragment; +import android.arch.lifecycle.ViewModelProviders; import android.os.Bundle; import android.support.annotation.Nullable; import android.view.LayoutInflater; @@ -12,11 +13,13 @@ import ro.code4.monitorizarevot.db.Data; import ro.code4.monitorizarevot.db.Preferences; import ro.code4.monitorizarevot.net.model.Form; +import ro.code4.monitorizarevot.viewmodel.FormsListViewModel; import ro.code4.monitorizarevot.widget.ChangeBranchBarLayout; import static ro.code4.monitorizarevot.ToolbarActivity.BRANCH_SELECTION_BACKSTACK_INDEX; -public class FormsListFragment extends BaseFragment implements View.OnClickListener { +public class FormsListFragment extends BaseFragment implements View.OnClickListener { + public static FormsListFragment newInstance() { return new FormsListFragment(); } @@ -46,6 +49,24 @@ public void onClick(View v) { }); } + private void showForm(Form form) { + if (form != null && form.getSections() != null && form.getSections().size() > 0) { + navigateTo(QuestionsOverviewFragment.newInstance(form.getId())); + } else { + Toast.makeText(getActivity(), getString(R.string.error_no_form_data), Toast.LENGTH_SHORT).show(); + } + } + + @Override + public String getTitle() { + return getString(R.string.title_forms_list); + } + + @Override + protected void setupViewModel() { + viewModel = ViewModelProviders.of(this, factory).get(FormsListViewModel.class); + } + @Override public void onClick(View v) { switch (v.getId()) { @@ -63,17 +84,4 @@ public void onClick(View v) { break; } } - - private void showForm(Form form) { - if (form != null && form.getSections() != null && form.getSections().size() > 0) { - navigateTo(QuestionsOverviewFragment.newInstance(form.getId())); - } else { - Toast.makeText(getActivity(), getString(R.string.error_no_form_data), Toast.LENGTH_SHORT).show(); - } - } - - @Override - public String getTitle() { - return getString(R.string.title_forms_list); - } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/fragment/GuideFragment.java b/app/src/main/java/ro/code4/monitorizarevot/fragment/GuideFragment.java index cb070ca..8d267c9 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/fragment/GuideFragment.java +++ b/app/src/main/java/ro/code4/monitorizarevot/fragment/GuideFragment.java @@ -1,5 +1,6 @@ package ro.code4.monitorizarevot.fragment; +import android.arch.lifecycle.ViewModelProviders; import android.os.Bundle; import android.support.annotation.Nullable; import android.view.LayoutInflater; @@ -10,8 +11,10 @@ import ro.code4.monitorizarevot.BaseFragment; import ro.code4.monitorizarevot.R; +import ro.code4.monitorizarevot.viewmodel.GuideViewModel; + +public class GuideFragment extends BaseFragment { -public class GuideFragment extends BaseFragment { public static GuideFragment newInstance() { return new GuideFragment(); } @@ -25,7 +28,7 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - WebView guideView = (WebView)view.findViewById(R.id.web_view_guide); + WebView guideView = (WebView) view.findViewById(R.id.web_view_guide); WebSettings webSettings = guideView.getSettings(); webSettings.setJavaScriptEnabled(true); guideView.loadUrl("http://monitorizare-vot-ghid.azurewebsites.net/"); @@ -35,4 +38,9 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { public String getTitle() { return getString(R.string.title_guide); } + + @Override + protected void setupViewModel() { + viewModel = ViewModelProviders.of(this, factory).get(GuideViewModel.class); + } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/fragment/QuestionFragment.java b/app/src/main/java/ro/code4/monitorizarevot/fragment/QuestionFragment.java index bba7a8e..8b86afd 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/fragment/QuestionFragment.java +++ b/app/src/main/java/ro/code4/monitorizarevot/fragment/QuestionFragment.java @@ -1,5 +1,6 @@ package ro.code4.monitorizarevot.fragment; +import android.arch.lifecycle.ViewModelProviders; import android.content.Context; import android.os.Bundle; import android.support.annotation.Nullable; @@ -14,14 +15,22 @@ import ro.code4.monitorizarevot.util.FormRenderer; import ro.code4.monitorizarevot.util.FormUtils; import ro.code4.monitorizarevot.util.QuestionDetailsNavigator; +import ro.code4.monitorizarevot.viewmodel.QuestionViewModel; + +public class QuestionFragment extends BaseFragment { -public class QuestionFragment extends BaseFragment { private static final String ARG_QUESTION_ID = "questionId"; + private static final String ARG_SIZE = "numberOfQuestions"; + private static final String ARG_INDEX = "indexOfQuestion"; + private Question question; + private QuestionDetailsNavigator navigator; + private int numberOfQuestions; + private int questionIndex; public static QuestionFragment newInstance(int questionId, int index, int numberOfQuestions) { @@ -57,6 +66,11 @@ public String getTitle() { return question.getCode(); } + @Override + protected void setupViewModel() { + viewModel = ViewModelProviders.of(this, factory).get(QuestionViewModel.class); + } + @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { diff --git a/app/src/main/java/ro/code4/monitorizarevot/fragment/QuestionsDetailsFragment.java b/app/src/main/java/ro/code4/monitorizarevot/fragment/QuestionsDetailsFragment.java index db9de72..01f6f8c 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/fragment/QuestionsDetailsFragment.java +++ b/app/src/main/java/ro/code4/monitorizarevot/fragment/QuestionsDetailsFragment.java @@ -1,5 +1,6 @@ package ro.code4.monitorizarevot.fragment; +import android.arch.lifecycle.ViewModelProviders; import android.os.Bundle; import android.support.annotation.Nullable; import android.view.LayoutInflater; @@ -22,11 +23,16 @@ import ro.code4.monitorizarevot.util.FormUtils; import ro.code4.monitorizarevot.util.NetworkUtils; import ro.code4.monitorizarevot.util.QuestionDetailsNavigator; +import ro.code4.monitorizarevot.viewmodel.QuestionDetailsViewModel; + +public class QuestionsDetailsFragment extends BaseFragment implements QuestionDetailsNavigator { -public class QuestionsDetailsFragment extends BaseFragment implements QuestionDetailsNavigator { private static final String ARGS_FORM_ID = "FormId"; + private static final String ARGS_START_INDEX = "StartIndex"; + private List questions; + private int currentQuestion = -1; private QuestionsDetailsPresenter mPresenter; @@ -52,6 +58,16 @@ public void onCreate(Bundle savedInstanceState) { this.mPresenter = new QuestionsDetailsPresenter(getActivity()); } + @Override + public String getTitle() { + return ""; + } + + @Override + protected void setupViewModel() { + viewModel = ViewModelProviders.of(this, factory).get(QuestionDetailsViewModel.class); + } + @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -60,11 +76,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa return rootView; } - @Override - public String getTitle() { - return ""; - } - private void showQuestion(int index) { Question question = questions.get(index); getChildFragmentManager() @@ -105,10 +116,10 @@ public void onSaveAnswerIfCompleted(ViewGroup questionContainer) { } } - private void syncCurrentData(BranchQuestionAnswer branchQuestionAnswer){ - if(NetworkUtils.isOnline(getActivity())){ + private void syncCurrentData(BranchQuestionAnswer branchQuestionAnswer) { + if (NetworkUtils.isOnline(getActivity())) { QuestionAnswer questionAnswer = new QuestionAnswer(branchQuestionAnswer, - getArguments().getString(ARGS_FORM_ID)); + getArguments().getString(ARGS_FORM_ID)); NetworkService.syncCurrentQuestion(questionAnswer).startRequest(new GeneralSubscriber()); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/fragment/QuestionsOverviewFragment.java b/app/src/main/java/ro/code4/monitorizarevot/fragment/QuestionsOverviewFragment.java index 744cdce..9a24825 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/fragment/QuestionsOverviewFragment.java +++ b/app/src/main/java/ro/code4/monitorizarevot/fragment/QuestionsOverviewFragment.java @@ -1,5 +1,6 @@ package ro.code4.monitorizarevot.fragment; +import android.arch.lifecycle.ViewModelProviders; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.widget.GridLayoutManager; @@ -15,9 +16,12 @@ import ro.code4.monitorizarevot.net.model.Form; import ro.code4.monitorizarevot.util.GridSpacingItemDecoration; import ro.code4.monitorizarevot.util.QuestionsOverviewNavigator; +import ro.code4.monitorizarevot.viewmodel.QuestionOverviewViewModel; + +public class QuestionsOverviewFragment extends BaseFragment implements QuestionsOverviewNavigator { -public class QuestionsOverviewFragment extends BaseFragment implements QuestionsOverviewNavigator { private static final String ARG_FORM_ID = "form"; + private Form form; public static QuestionsOverviewFragment newInstance(String formId) { @@ -34,6 +38,16 @@ public void onCreate(Bundle savedInstanceState) { this.form = Data.getInstance().getForm(getArguments().getString(ARG_FORM_ID)); } + @Override + public String getTitle() { + return getString(R.string.title_form, form.getId()); + } + + @Override + protected void setupViewModel() { + viewModel = ViewModelProviders.of(this, factory).get(QuestionOverviewViewModel.class); + } + @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -43,16 +57,12 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 2)); recyclerView.setAdapter(new QuestionsOverviewAdapter(getActivity(), form, this)); recyclerView.addItemDecoration(new GridSpacingItemDecoration(2, - getResources().getDimensionPixelSize(R.dimen.activity_horizontal_margin), false)); + getResources().getDimensionPixelSize(R.dimen.activity_horizontal_margin), + false)); return rootView; } - @Override - public String getTitle() { - return getString(R.string.title_form, form.getId()); - } - @Override public void showQuestionDetails(int index) { navigateTo(QuestionsDetailsFragment.newInstance(form.getId(), index)); diff --git a/app/src/main/java/ro/code4/monitorizarevot/util/AbstractComponentFactory.java b/app/src/main/java/ro/code4/monitorizarevot/util/AbstractComponentFactory.java new file mode 100644 index 0000000..81bdd71 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/util/AbstractComponentFactory.java @@ -0,0 +1,42 @@ +package ro.code4.monitorizarevot.util; + +import android.support.annotation.NonNull; + +import java.util.Map; + +import javax.inject.Provider; + +public class AbstractComponentFactory { + + protected final Map, Provider> creators; + + public AbstractComponentFactory(Map, Provider> creators) { + this.creators = creators; + } + + @NonNull + @SuppressWarnings("unchecked") + public T create(@NonNull Class modelClass) { + Provider creator = creators.get(modelClass); + + if (creator == null) { + for (Map.Entry, Provider> entry : creators.entrySet()) { + if (modelClass.isAssignableFrom(entry.getKey())) { + creator = entry.getValue(); + break; + } + } + } + + if (creator == null) { + throw new IllegalArgumentException("unknown model class " + modelClass); + } + + try { + return (T) creator.get(); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/AddNoteViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/AddNoteViewModel.java new file mode 100644 index 0000000..c421ab3 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/AddNoteViewModel.java @@ -0,0 +1,11 @@ +package ro.code4.monitorizarevot.viewmodel; + +import javax.inject.Inject; + +public class AddNoteViewModel extends BaseViewModel { + + @Inject + public AddNoteViewModel() { + super(); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BaseViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BaseViewModel.java new file mode 100644 index 0000000..a9b73a2 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BaseViewModel.java @@ -0,0 +1,9 @@ +package ro.code4.monitorizarevot.viewmodel; + +import android.arch.lifecycle.ViewModel; + +public abstract class BaseViewModel extends ViewModel { + + public BaseViewModel() { + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchDetailsViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchDetailsViewModel.java new file mode 100644 index 0000000..3c7c75a --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchDetailsViewModel.java @@ -0,0 +1,11 @@ +package ro.code4.monitorizarevot.viewmodel; + +import javax.inject.Inject; + +public class BranchDetailsViewModel extends BaseViewModel { + + @Inject + public BranchDetailsViewModel() { + super(); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchSelectionViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchSelectionViewModel.java new file mode 100644 index 0000000..70a59fb --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchSelectionViewModel.java @@ -0,0 +1,11 @@ +package ro.code4.monitorizarevot.viewmodel; + +import javax.inject.Inject; + +public class BranchSelectionViewModel extends BaseViewModel { + + @Inject + public BranchSelectionViewModel() { + super(); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/FormsListViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/FormsListViewModel.java new file mode 100644 index 0000000..6712510 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/FormsListViewModel.java @@ -0,0 +1,12 @@ +package ro.code4.monitorizarevot.viewmodel; + + +import javax.inject.Inject; + +public class FormsListViewModel extends BaseViewModel { + + @Inject + public FormsListViewModel() { + super(); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/GuideViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/GuideViewModel.java new file mode 100644 index 0000000..70c529e --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/GuideViewModel.java @@ -0,0 +1,11 @@ +package ro.code4.monitorizarevot.viewmodel; + +import javax.inject.Inject; + +public class GuideViewModel extends BaseViewModel { + + @Inject + public GuideViewModel() { + super(); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/LoginViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/LoginViewModel.java new file mode 100644 index 0000000..a4a42e0 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/LoginViewModel.java @@ -0,0 +1,11 @@ +package ro.code4.monitorizarevot.viewmodel; + +import javax.inject.Inject; + +public class LoginViewModel extends BaseViewModel { + + @Inject + public LoginViewModel() { + super(); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionDetailsViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionDetailsViewModel.java new file mode 100644 index 0000000..469ec58 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionDetailsViewModel.java @@ -0,0 +1,11 @@ +package ro.code4.monitorizarevot.viewmodel; + +import javax.inject.Inject; + +public class QuestionDetailsViewModel extends BaseViewModel { + + @Inject + public QuestionDetailsViewModel() { + super(); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionOverviewViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionOverviewViewModel.java new file mode 100644 index 0000000..e1ada3d --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionOverviewViewModel.java @@ -0,0 +1,11 @@ +package ro.code4.monitorizarevot.viewmodel; + +import javax.inject.Inject; + +public class QuestionOverviewViewModel extends BaseViewModel { + + @Inject + public QuestionOverviewViewModel() { + super(); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionViewModel.java new file mode 100644 index 0000000..d15fae8 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionViewModel.java @@ -0,0 +1,11 @@ +package ro.code4.monitorizarevot.viewmodel; + +import javax.inject.Inject; + +public class QuestionViewModel extends BaseViewModel { + + @Inject + public QuestionViewModel() { + super(); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/StartViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/StartViewModel.java new file mode 100644 index 0000000..28e4f79 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/StartViewModel.java @@ -0,0 +1,11 @@ +package ro.code4.monitorizarevot.viewmodel; + +import javax.inject.Inject; + +public class StartViewModel extends BaseViewModel { + + @Inject + public StartViewModel() { + super(); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/ToolbarViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/ToolbarViewModel.java new file mode 100644 index 0000000..7eae274 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/ToolbarViewModel.java @@ -0,0 +1,11 @@ +package ro.code4.monitorizarevot.viewmodel; + +import javax.inject.Inject; + +public class ToolbarViewModel extends BaseViewModel { + + @Inject + public ToolbarViewModel() { + super(); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/ViewModelFactory.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/ViewModelFactory.java new file mode 100644 index 0000000..e07201c --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/ViewModelFactory.java @@ -0,0 +1,19 @@ +package ro.code4.monitorizarevot.viewmodel; + +import android.arch.lifecycle.ViewModel; +import android.arch.lifecycle.ViewModelProvider; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Provider; + +import ro.code4.monitorizarevot.util.AbstractComponentFactory; + +public class ViewModelFactory extends AbstractComponentFactory implements ViewModelProvider.Factory { + + @Inject + public ViewModelFactory(Map, Provider> creators) { + super(creators); + } +} From 1ce52b57847ee0909dd873afbce133657088ae49 Mon Sep 17 00:00:00 2001 From: Alexandru Chiriac Date: Fri, 7 Dec 2018 18:21:55 +0200 Subject: [PATCH 08/89] Setup data sources (httpsource - backend communication , localsource - db/cache) --- .../monitorizarevot/dagger/AppModule.java | 3 +- .../monitorizarevot/dagger/DataModule.java | 22 ++++++++ .../monitorizarevot/dagger/DataSourceKey.java | 19 +++++++ .../data/datasource/ApiDataSource.java | 29 ++++++++++ .../data/datasource/DataSourceFactory.java | 30 ++++++++++ .../data/datasource/HttpDataSource.java | 55 +++++++++++++++++++ .../data/datasource/LocalDataSource.java | 55 +++++++++++++++++++ 7 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/ro/code4/monitorizarevot/dagger/DataModule.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/dagger/DataSourceKey.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/data/datasource/ApiDataSource.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/data/datasource/DataSourceFactory.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/data/datasource/HttpDataSource.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/data/datasource/LocalDataSource.java diff --git a/app/src/main/java/ro/code4/monitorizarevot/dagger/AppModule.java b/app/src/main/java/ro/code4/monitorizarevot/dagger/AppModule.java index b7a5d60..349b526 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/dagger/AppModule.java +++ b/app/src/main/java/ro/code4/monitorizarevot/dagger/AppModule.java @@ -9,7 +9,8 @@ import dagger.Provides; @Module(includes = { - ActivityBindingModule.class + ActivityBindingModule.class, + DataModule.class }) class AppModule { diff --git a/app/src/main/java/ro/code4/monitorizarevot/dagger/DataModule.java b/app/src/main/java/ro/code4/monitorizarevot/dagger/DataModule.java new file mode 100644 index 0000000..031a288 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/dagger/DataModule.java @@ -0,0 +1,22 @@ +package ro.code4.monitorizarevot.dagger; + +import dagger.Binds; +import dagger.Module; +import dagger.multibindings.IntoMap; +import ro.code4.monitorizarevot.data.datasource.ApiDataSource; +import ro.code4.monitorizarevot.data.datasource.HttpDataSource; +import ro.code4.monitorizarevot.data.datasource.LocalDataSource; + +@Module +public abstract class DataModule { + + @Binds + @IntoMap + @DataSourceKey(LocalDataSource.class) + abstract ApiDataSource bindLocalDataSource(LocalDataSource dataSource); + + @Binds + @IntoMap + @DataSourceKey(HttpDataSource.class) + abstract ApiDataSource bindHttpDataSource(HttpDataSource dataSource); +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/dagger/DataSourceKey.java b/app/src/main/java/ro/code4/monitorizarevot/dagger/DataSourceKey.java new file mode 100644 index 0000000..1d220cd --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/dagger/DataSourceKey.java @@ -0,0 +1,19 @@ +package ro.code4.monitorizarevot.dagger; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import dagger.MapKey; +import ro.code4.monitorizarevot.data.datasource.ApiDataSource; + +@Documented +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@MapKey +public @interface DataSourceKey { + + Class value(); +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/data/datasource/ApiDataSource.java b/app/src/main/java/ro/code4/monitorizarevot/data/datasource/ApiDataSource.java new file mode 100644 index 0000000..48cbb2f --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/data/datasource/ApiDataSource.java @@ -0,0 +1,29 @@ +package ro.code4.monitorizarevot.data.datasource; + +import java.util.List; + +import ro.code4.monitorizarevot.net.model.BranchDetails; +import ro.code4.monitorizarevot.net.model.Note; +import ro.code4.monitorizarevot.net.model.ResponseAnswerContainer; +import ro.code4.monitorizarevot.net.model.Section; +import ro.code4.monitorizarevot.net.model.User; +import ro.code4.monitorizarevot.net.model.response.Ack; +import ro.code4.monitorizarevot.net.model.response.ResponseNote; +import ro.code4.monitorizarevot.net.model.response.VersionResponse; +import ro.code4.monitorizarevot.net.model.response.question.QuestionResponse; +import rx.Observable; + +public interface ApiDataSource { + + Observable postAuth(User user); + + Observable> getForm(String formId); + + Observable getFormVersion(); + + Observable postBranchDetails(BranchDetails branchDetails); + + Observable postQuestionAnswer(ResponseAnswerContainer responseAnswerContainer); + + Observable postNote(Note note); +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/data/datasource/DataSourceFactory.java b/app/src/main/java/ro/code4/monitorizarevot/data/datasource/DataSourceFactory.java new file mode 100644 index 0000000..c3f2e15 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/data/datasource/DataSourceFactory.java @@ -0,0 +1,30 @@ +package ro.code4.monitorizarevot.data.datasource; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; + +import ro.code4.monitorizarevot.util.AbstractComponentFactory; + +@Singleton +public class DataSourceFactory extends AbstractComponentFactory { + + @Inject + public DataSourceFactory(Map, Provider> creators) { + super(creators); + } + + public ApiDataSource localSource() { + return create(LocalDataSource.class); + } + + public ApiDataSource httpSource() { + return create(HttpDataSource.class); + } + + public ApiDataSource dataSource(boolean isLocal) { + return isLocal ? localSource() : httpSource(); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/data/datasource/HttpDataSource.java b/app/src/main/java/ro/code4/monitorizarevot/data/datasource/HttpDataSource.java new file mode 100644 index 0000000..18b8d5f --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/data/datasource/HttpDataSource.java @@ -0,0 +1,55 @@ +package ro.code4.monitorizarevot.data.datasource; + +import java.util.List; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import ro.code4.monitorizarevot.net.model.BranchDetails; +import ro.code4.monitorizarevot.net.model.Note; +import ro.code4.monitorizarevot.net.model.ResponseAnswerContainer; +import ro.code4.monitorizarevot.net.model.Section; +import ro.code4.monitorizarevot.net.model.User; +import ro.code4.monitorizarevot.net.model.response.Ack; +import ro.code4.monitorizarevot.net.model.response.ResponseNote; +import ro.code4.monitorizarevot.net.model.response.VersionResponse; +import ro.code4.monitorizarevot.net.model.response.question.QuestionResponse; +import rx.Observable; + +@Singleton +public class HttpDataSource implements ApiDataSource { + + @Inject + public HttpDataSource() { + } + + @Override + public Observable postAuth(User user) { + return null; + } + + @Override + public Observable> getForm(String formId) { + return null; + } + + @Override + public Observable getFormVersion() { + return null; + } + + @Override + public Observable postBranchDetails(BranchDetails branchDetails) { + return null; + } + + @Override + public Observable postQuestionAnswer(ResponseAnswerContainer responseAnswerContainer) { + return null; + } + + @Override + public Observable postNote(Note note) { + return null; + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/data/datasource/LocalDataSource.java b/app/src/main/java/ro/code4/monitorizarevot/data/datasource/LocalDataSource.java new file mode 100644 index 0000000..5fc1654 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/data/datasource/LocalDataSource.java @@ -0,0 +1,55 @@ +package ro.code4.monitorizarevot.data.datasource; + +import java.util.List; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import ro.code4.monitorizarevot.net.model.BranchDetails; +import ro.code4.monitorizarevot.net.model.Note; +import ro.code4.monitorizarevot.net.model.ResponseAnswerContainer; +import ro.code4.monitorizarevot.net.model.Section; +import ro.code4.monitorizarevot.net.model.User; +import ro.code4.monitorizarevot.net.model.response.Ack; +import ro.code4.monitorizarevot.net.model.response.ResponseNote; +import ro.code4.monitorizarevot.net.model.response.VersionResponse; +import ro.code4.monitorizarevot.net.model.response.question.QuestionResponse; +import rx.Observable; + +@Singleton +public class LocalDataSource implements ApiDataSource { + + @Inject + public LocalDataSource() { + } + + @Override + public Observable postAuth(User user) { + return null; + } + + @Override + public Observable> getForm(String formId) { + return null; + } + + @Override + public Observable getFormVersion() { + return null; + } + + @Override + public Observable postBranchDetails(BranchDetails branchDetails) { + return null; + } + + @Override + public Observable postQuestionAnswer(ResponseAnswerContainer responseAnswerContainer) { + return null; + } + + @Override + public Observable postNote(Note note) { + return null; + } +} From 32dd3aae8fc304ccfd91223164713c76213ffd67 Mon Sep 17 00:00:00 2001 From: Mircea Serediuc Date: Fri, 7 Dec 2018 18:24:50 +0200 Subject: [PATCH 09/89] Get the phone number and set it into input --- app/src/main/AndroidManifest.xml | 1 + .../code4/monitorizarevot/LoginActivity.java | 75 +++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0cec998..199cb94 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,6 +11,7 @@ + diff --git a/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java b/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java index 6788d7c..4a057da 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java +++ b/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java @@ -1,16 +1,26 @@ package ro.code4.monitorizarevot; +import android.Manifest; import android.app.ActivityOptions; +import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Build; import android.os.Bundle; import android.provider.Settings; +import android.support.v4.app.ActivityCompat; +import android.support.v4.content.ContextCompat; +import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Pair; +import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; +import android.view.inputmethod.EditorInfo; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; +import android.widget.Toast; import ro.code4.monitorizarevot.net.NetworkService; import ro.code4.monitorizarevot.net.model.User; @@ -23,6 +33,9 @@ public class LoginActivity extends BaseActivity { private EditText password; private Button loginButton; private ObservableListenerDetacher mListenerDetacher; + private static final int PERMISSION_REQUEST_CODE = 1; + String wantPermission = Manifest.permission.READ_PHONE_STATE; + private String TAG = "Test"; @Override protected void onCreate(Bundle savedInstanceState) { @@ -32,6 +45,23 @@ protected void onCreate(Bundle savedInstanceState) { password = (EditText) findViewById(R.id.branch); username.getText(); + password.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) { + if (i == EditorInfo.IME_ACTION_DONE) { + login(); + } + return false; + } + }); + + if (!checkPermission(wantPermission)) { + requestPermission(wantPermission); + } else { + setPhone(); + } + + loginButton = (Button) findViewById(R.id.login_button); loginButton.setOnClickListener(new OnClickListener() { @Override @@ -74,6 +104,51 @@ private String getUdid() { return Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID); } + + private void setPhone() { + TelephonyManager phoneMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); + if (ActivityCompat.checkSelfPermission(this, wantPermission) == PackageManager.PERMISSION_GRANTED) { + if (phoneMgr.getLine1Number() != null && !phoneMgr.getLine1Number().isEmpty()) { + username.setText(phoneMgr.getLine1Number()); + } + }else { + requestPermission(wantPermission); + } + } + + private void requestPermission(String permission){ + if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)){ + Toast.makeText(this, "Phone state permission allows us to get phone number. Please allow it for additional functionality.", Toast.LENGTH_LONG).show(); + } + ActivityCompat.requestPermissions(this, new String[]{permission},PERMISSION_REQUEST_CODE); + } + + @Override + public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { + switch (requestCode) { + case PERMISSION_REQUEST_CODE: + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + setPhone(); + } else { + Toast.makeText(this,"Permission Denied. We can't get phone number.", Toast.LENGTH_LONG).show(); + } + break; + } + } + + private boolean checkPermission(String permission){ + if (Build.VERSION.SDK_INT >= 23) { + int result = ContextCompat.checkSelfPermission(this, permission); + if (result == PackageManager.PERMISSION_GRANTED){ + return true; + } else { + return false; + } + } else { + return true; + } + } + private class LoginSubscriber extends ObservableListener { @Override public void onError(Throwable e) { From 34386299898fa95b70b5df215628b6d64d174b6e Mon Sep 17 00:00:00 2001 From: Alexandru Chiriac Date: Fri, 7 Dec 2018 19:01:20 +0200 Subject: [PATCH 10/89] Setup mock api service --- app/build.gradle | 5 ++ .../dagger/WebServiceModule.java | 19 ++++++ .../monitorizarevot/dagger/DataModule.java | 2 +- .../dagger/RetrofitModule.java | 66 +++++++++++++++++++ .../monitorizarevot/data/rest/ApiService.java | 5 ++ .../monitorizarevot/net/AuthInterceptor.java | 10 ++- .../dagger/WebServiceModule.java | 13 ++++ .../data/rest/MockApiService.java | 5 ++ .../dagger/WebServiceModule.java | 19 ++++++ 9 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 app/src/dev/java/ro/code4/monitorizarevot/dagger/WebServiceModule.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/dagger/RetrofitModule.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/data/rest/ApiService.java create mode 100644 app/src/mock/java/ro/code4/monitorizarevot/dagger/WebServiceModule.java create mode 100644 app/src/mock/java/ro/code4/monitorizarevot/data/rest/MockApiService.java create mode 100644 app/src/prod/java/ro/code4/monitorizarevot/dagger/WebServiceModule.java diff --git a/app/build.gradle b/app/build.gradle index 4fbc570..8a395f5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -44,6 +44,10 @@ android { versionNameSuffix "m" } } + + packagingOptions { + exclude 'META-INF/rxjava.properties' + } } repositories { @@ -62,6 +66,7 @@ dependencies { implementation 'com.squareup.retrofit2:retrofit:2.4.0' implementation 'com.squareup.retrofit2:converter-gson:2.4.0' + implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0' implementation 'com.squareup.okhttp3:logging-interceptor:3.6.0' implementation 'com.pixplicity.easyprefs:library:1.9.0@aar' diff --git a/app/src/dev/java/ro/code4/monitorizarevot/dagger/WebServiceModule.java b/app/src/dev/java/ro/code4/monitorizarevot/dagger/WebServiceModule.java new file mode 100644 index 0000000..0ab79d1 --- /dev/null +++ b/app/src/dev/java/ro/code4/monitorizarevot/dagger/WebServiceModule.java @@ -0,0 +1,19 @@ +package ro.code4.monitorizarevot.dagger; + +import javax.inject.Named; +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; +import retrofit2.Retrofit; +import ro.code4.monitorizarevot.data.rest.ApiService; + +@Module(includes = RetrofitModule.class) +public class WebServiceModule { + + @Provides + @Singleton + static ApiService provideApiService(@Named("retrofit") Retrofit retrofit) { + return retrofit.create(ApiService.class); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/dagger/DataModule.java b/app/src/main/java/ro/code4/monitorizarevot/dagger/DataModule.java index 031a288..ec98396 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/dagger/DataModule.java +++ b/app/src/main/java/ro/code4/monitorizarevot/dagger/DataModule.java @@ -7,7 +7,7 @@ import ro.code4.monitorizarevot.data.datasource.HttpDataSource; import ro.code4.monitorizarevot.data.datasource.LocalDataSource; -@Module +@Module(includes = WebServiceModule.class) public abstract class DataModule { @Binds diff --git a/app/src/main/java/ro/code4/monitorizarevot/dagger/RetrofitModule.java b/app/src/main/java/ro/code4/monitorizarevot/dagger/RetrofitModule.java new file mode 100644 index 0000000..22ae43a --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/dagger/RetrofitModule.java @@ -0,0 +1,66 @@ +package ro.code4.monitorizarevot.dagger; + +import com.google.gson.ExclusionStrategy; +import com.google.gson.FieldAttributes; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; + +import javax.inject.Named; +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; +import io.realm.RealmObject; +import okhttp3.OkHttpClient; +import okhttp3.logging.HttpLoggingInterceptor; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; +import ro.code4.monitorizarevot.BuildConfig; +import ro.code4.monitorizarevot.net.AuthInterceptor; + +@Module +public class RetrofitModule { + + @Provides + @Singleton + @Named("logging_interceptor") + static HttpLoggingInterceptor provideHttpLoggingInterceptor() { + return new HttpLoggingInterceptor(); + } + + @Provides + @Singleton + @Named("retrofit") + static Retrofit provideRetrofit(@Named("logging_interceptor") HttpLoggingInterceptor loggingInterceptor, AuthInterceptor authInterceptor) { + Gson gson = new GsonBuilder() + .setExclusionStrategies(new ExclusionStrategy() { + @Override + public boolean shouldSkipField(FieldAttributes f) { + return f.getDeclaringClass().equals(RealmObject.class); + } + + @Override + public boolean shouldSkipClass(Class clazz) { + return false; + } + }) + .excludeFieldsWithoutExposeAnnotation() + .create(); + + loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); + + OkHttpClient httpClient = new OkHttpClient.Builder() + .addInterceptor(loggingInterceptor) + .addInterceptor(authInterceptor) + .build(); + + return new Retrofit.Builder() + .baseUrl(BuildConfig.WEB_BASE_URL) + .client(httpClient) + .addConverterFactory(GsonConverterFactory.create(gson)) + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + .build(); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/data/rest/ApiService.java b/app/src/main/java/ro/code4/monitorizarevot/data/rest/ApiService.java new file mode 100644 index 0000000..65e58f3 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/data/rest/ApiService.java @@ -0,0 +1,5 @@ +package ro.code4.monitorizarevot.data.rest; + +public interface ApiService { + +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/net/AuthInterceptor.java b/app/src/main/java/ro/code4/monitorizarevot/net/AuthInterceptor.java index 31777f7..c7adb49 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/net/AuthInterceptor.java +++ b/app/src/main/java/ro/code4/monitorizarevot/net/AuthInterceptor.java @@ -2,6 +2,9 @@ import org.greenrobot.eventbus.EventBus; +import javax.inject.Inject; +import javax.inject.Singleton; + import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; @@ -10,8 +13,13 @@ import static ro.code4.monitorizarevot.constants.Constants.AUTHORIZATION_KEY; +@Singleton public class AuthInterceptor implements Interceptor { + @Inject + public AuthInterceptor() { + } + @Override public Response intercept(Chain chain) throws java.io.IOException { Response response = chain.proceed(tokenAppendedRequest(chain.request())); @@ -24,7 +32,7 @@ public Response intercept(Chain chain) throws java.io.IOException { private Request tokenAppendedRequest(Request request) { String token = Preferences.getToken(); - if(token != null){ + if (token != null) { return request .newBuilder() .removeHeader(AUTHORIZATION_KEY) diff --git a/app/src/mock/java/ro/code4/monitorizarevot/dagger/WebServiceModule.java b/app/src/mock/java/ro/code4/monitorizarevot/dagger/WebServiceModule.java new file mode 100644 index 0000000..0d9a184 --- /dev/null +++ b/app/src/mock/java/ro/code4/monitorizarevot/dagger/WebServiceModule.java @@ -0,0 +1,13 @@ +package ro.code4.monitorizarevot.dagger; + +import dagger.Binds; +import dagger.Module; +import ro.code4.monitorizarevot.data.rest.ApiService; +import ro.code4.monitorizarevot.data.rest.MockApiService; + +@Module +public abstract class WebServiceModule { + + @Binds + abstract ApiService bindsApiService(MockApiService service); +} diff --git a/app/src/mock/java/ro/code4/monitorizarevot/data/rest/MockApiService.java b/app/src/mock/java/ro/code4/monitorizarevot/data/rest/MockApiService.java new file mode 100644 index 0000000..fc54576 --- /dev/null +++ b/app/src/mock/java/ro/code4/monitorizarevot/data/rest/MockApiService.java @@ -0,0 +1,5 @@ +package ro.code4.monitorizarevot.data.rest; + +public class MockApiService implements ApiService { + +} diff --git a/app/src/prod/java/ro/code4/monitorizarevot/dagger/WebServiceModule.java b/app/src/prod/java/ro/code4/monitorizarevot/dagger/WebServiceModule.java new file mode 100644 index 0000000..0ab79d1 --- /dev/null +++ b/app/src/prod/java/ro/code4/monitorizarevot/dagger/WebServiceModule.java @@ -0,0 +1,19 @@ +package ro.code4.monitorizarevot.dagger; + +import javax.inject.Named; +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; +import retrofit2.Retrofit; +import ro.code4.monitorizarevot.data.rest.ApiService; + +@Module(includes = RetrofitModule.class) +public class WebServiceModule { + + @Provides + @Singleton + static ApiService provideApiService(@Named("retrofit") Retrofit retrofit) { + return retrofit.create(ApiService.class); + } +} From fb7be5c5f581e56940948ac94ed63359864080ae Mon Sep 17 00:00:00 2001 From: Alexandru Chiriac Date: Fri, 7 Dec 2018 19:15:48 +0200 Subject: [PATCH 11/89] Implement Http data source - partial --- app/build.gradle | 2 +- .../data/datasource/HttpDataSource.java | 42 +++++++++++++++---- .../monitorizarevot/data/rest/ApiService.java | 39 ++++++++++++++++- 3 files changed, 74 insertions(+), 9 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 8a395f5..ec709a3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -66,7 +66,7 @@ dependencies { implementation 'com.squareup.retrofit2:retrofit:2.4.0' implementation 'com.squareup.retrofit2:converter-gson:2.4.0' - implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0' + implementation 'com.squareup.retrofit2:adapter-rxjava:2.1.0' implementation 'com.squareup.okhttp3:logging-interceptor:3.6.0' implementation 'com.pixplicity.easyprefs:library:1.9.0@aar' diff --git a/app/src/main/java/ro/code4/monitorizarevot/data/datasource/HttpDataSource.java b/app/src/main/java/ro/code4/monitorizarevot/data/datasource/HttpDataSource.java index 18b8d5f..13d29ee 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/data/datasource/HttpDataSource.java +++ b/app/src/main/java/ro/code4/monitorizarevot/data/datasource/HttpDataSource.java @@ -1,10 +1,16 @@ package ro.code4.monitorizarevot.data.datasource; +import java.io.File; import java.util.List; import javax.inject.Inject; import javax.inject.Singleton; +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import okhttp3.RequestBody; +import ro.code4.monitorizarevot.data.rest.ApiService; +import ro.code4.monitorizarevot.db.Preferences; import ro.code4.monitorizarevot.net.model.BranchDetails; import ro.code4.monitorizarevot.net.model.Note; import ro.code4.monitorizarevot.net.model.ResponseAnswerContainer; @@ -19,37 +25,59 @@ @Singleton public class HttpDataSource implements ApiDataSource { + private final ApiService mApiService; + @Inject - public HttpDataSource() { + public HttpDataSource(ApiService apiService) { + mApiService = apiService; + } + + private static MultipartBody.Part createMultipart(String name, int number) { + return createMultipart(name, String.valueOf(number)); + } + + private static MultipartBody.Part createMultipart(String name, String value) { + RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), value); + return MultipartBody.Part.createFormData(name, null, requestBody); } @Override public Observable postAuth(User user) { - return null; + return mApiService.postAuth(user); } @Override public Observable> getForm(String formId) { - return null; + return mApiService.getForm(formId); } @Override public Observable getFormVersion() { - return null; + return mApiService.getFormVersion(); } @Override public Observable postBranchDetails(BranchDetails branchDetails) { - return null; + return mApiService.postBranchDetails(branchDetails); } @Override public Observable postQuestionAnswer(ResponseAnswerContainer responseAnswerContainer) { - return null; + return mApiService.postQuestionAnswer(responseAnswerContainer); } @Override public Observable postNote(Note note) { - return null; + MultipartBody.Part body = null; + if (note.getUriPath() != null) { + File file = new File(note.getUriPath()); + RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file); + body = MultipartBody.Part.createFormData("file", file.getName(), requestFile); + } + + return mApiService.postNote(body, createMultipart("CodJudet", Preferences.getCountyCode()), + createMultipart("NumarSectie", Preferences.getBranchNumber()), + createMultipart("IdIntrebare", note.getQuestionId() != null ? note.getQuestionId() : 0), + createMultipart("TextNota", note.getDescription())); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/data/rest/ApiService.java b/app/src/main/java/ro/code4/monitorizarevot/data/rest/ApiService.java index 65e58f3..e5fc38e 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/data/rest/ApiService.java +++ b/app/src/main/java/ro/code4/monitorizarevot/data/rest/ApiService.java @@ -1,5 +1,42 @@ package ro.code4.monitorizarevot.data.rest; +import java.util.List; + +import okhttp3.MultipartBody; +import retrofit2.http.*; +import ro.code4.monitorizarevot.net.model.BranchDetails; +import ro.code4.monitorizarevot.net.model.ResponseAnswerContainer; +import ro.code4.monitorizarevot.net.model.Section; +import ro.code4.monitorizarevot.net.model.User; +import ro.code4.monitorizarevot.net.model.response.Ack; +import ro.code4.monitorizarevot.net.model.response.ResponseNote; +import ro.code4.monitorizarevot.net.model.response.VersionResponse; +import ro.code4.monitorizarevot.net.model.response.question.QuestionResponse; +import rx.Observable; + public interface ApiService { -} + @POST("/api/v1/access/token") + Observable postAuth(@Body User user); + + @GET("/api/v1/formular") + Observable> getForm(@Query("idformular") String formId); + + @GET("/api/v1/formular/versiune") + Observable getFormVersion(); + + @POST("/api/v1/sectie") + Observable postBranchDetails(@Body BranchDetails branchDetails); + + @POST("/api/v1/raspuns") + Observable postQuestionAnswer(@Body ResponseAnswerContainer responseAnswer); + + @Multipart + @POST("/api/v1/note/ataseaza") + Observable postNote(@Part MultipartBody.Part file, + @Part MultipartBody.Part countyCode, + @Part MultipartBody.Part branchNumber, + @Part MultipartBody.Part questionId, + @Part MultipartBody.Part description); + +} \ No newline at end of file From c1795c8e40db486698c8d61a00ed433e8f17365e Mon Sep 17 00:00:00 2001 From: Alexandru Chiriac Date: Fri, 7 Dec 2018 21:10:11 +0200 Subject: [PATCH 12/89] Setup use cases, repositories.. --- .../monitorizarevot/dagger/AppModule.java | 1 + .../dagger/DataRepositoryKey.java | 19 ++++++ .../monitorizarevot/dagger/DomainModule.java | 50 ++++++++++++++++ .../dagger/RetrofitModule.java | 5 +- .../monitorizarevot/dagger/UseCaseKey.java | 19 ++++++ .../data/datasource/ApiDataSource.java | 2 +- .../data/datasource/HttpDataSource.java | 58 ++++++++++++++++++- .../data/datasource/LocalDataSource.java | 2 +- .../data/repository/AuthRepositoryImpl.java | 30 ++++++++++ .../data/repository/FormsRepositoryImpl.java | 18 ++++++ .../data/repository/RepositoryFactory.java | 29 ++++++++++ .../domain/params/BaseDataParams.java | 22 +++++++ .../domain/params/LoginDataParams.java | 30 ++++++++++ .../domain/repository/AuthRepository.java | 9 +++ .../domain/repository/DataRepository.java | 4 ++ .../domain/repository/FormsRepository.java | 5 ++ .../domain/usecase/LoginUC.java | 23 ++++++++ .../domain/usecase/UseCase.java | 54 +++++++++++++++++ .../domain/usecase/UseCaseFactory.java | 22 +++++++ .../domain/usecase/UseCaseType.java | 6 ++ .../viewmodel/AddNoteViewModel.java | 6 +- .../viewmodel/BaseViewModel.java | 7 ++- .../viewmodel/BranchDetailsViewModel.java | 6 +- .../viewmodel/BranchSelectionViewModel.java | 6 +- .../viewmodel/FormsListViewModel.java | 6 +- .../viewmodel/GuideViewModel.java | 6 +- .../viewmodel/LoginViewModel.java | 6 +- .../viewmodel/QuestionDetailsViewModel.java | 6 +- .../viewmodel/QuestionOverviewViewModel.java | 6 +- .../viewmodel/QuestionViewModel.java | 6 +- .../viewmodel/StartViewModel.java | 6 +- .../viewmodel/ToolbarViewModel.java | 6 +- .../data/rest/MockApiService.java | 49 ++++++++++++++++ 33 files changed, 500 insertions(+), 30 deletions(-) create mode 100644 app/src/main/java/ro/code4/monitorizarevot/dagger/DataRepositoryKey.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/dagger/DomainModule.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/dagger/UseCaseKey.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/data/repository/AuthRepositoryImpl.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/data/repository/FormsRepositoryImpl.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/data/repository/RepositoryFactory.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/domain/params/BaseDataParams.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/domain/params/LoginDataParams.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/domain/repository/AuthRepository.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/domain/repository/DataRepository.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/domain/repository/FormsRepository.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/domain/usecase/LoginUC.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/domain/usecase/UseCase.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/domain/usecase/UseCaseFactory.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/domain/usecase/UseCaseType.java diff --git a/app/src/main/java/ro/code4/monitorizarevot/dagger/AppModule.java b/app/src/main/java/ro/code4/monitorizarevot/dagger/AppModule.java index 349b526..290e351 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/dagger/AppModule.java +++ b/app/src/main/java/ro/code4/monitorizarevot/dagger/AppModule.java @@ -10,6 +10,7 @@ @Module(includes = { ActivityBindingModule.class, + DomainModule.class, DataModule.class }) class AppModule { diff --git a/app/src/main/java/ro/code4/monitorizarevot/dagger/DataRepositoryKey.java b/app/src/main/java/ro/code4/monitorizarevot/dagger/DataRepositoryKey.java new file mode 100644 index 0000000..f5ed6bb --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/dagger/DataRepositoryKey.java @@ -0,0 +1,19 @@ +package ro.code4.monitorizarevot.dagger; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import dagger.MapKey; +import ro.code4.monitorizarevot.domain.repository.DataRepository; + +@Documented +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@MapKey +public @interface DataRepositoryKey { + + Class value(); +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/dagger/DomainModule.java b/app/src/main/java/ro/code4/monitorizarevot/dagger/DomainModule.java new file mode 100644 index 0000000..b6a6613 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/dagger/DomainModule.java @@ -0,0 +1,50 @@ +package ro.code4.monitorizarevot.dagger; + +import javax.inject.Named; +import javax.inject.Singleton; + +import dagger.Binds; +import dagger.Module; +import dagger.Provides; +import dagger.multibindings.IntoMap; +import ro.code4.monitorizarevot.data.repository.AuthRepositoryImpl; +import ro.code4.monitorizarevot.data.repository.FormsRepositoryImpl; +import ro.code4.monitorizarevot.domain.repository.DataRepository; +import ro.code4.monitorizarevot.domain.usecase.LoginUC; +import ro.code4.monitorizarevot.domain.usecase.UseCase; +import rx.Scheduler; +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; + +@Module +public abstract class DomainModule { + + @Provides + @Singleton + @Named("io") + static Scheduler provideIOScheduler() { + return Schedulers.io(); + } + + @Provides + @Singleton + @Named("main") + static Scheduler provideMainScheduler() { + return AndroidSchedulers.mainThread(); + } + + @Binds + @IntoMap + @DataRepositoryKey(AuthRepositoryImpl.class) + abstract DataRepository bindAuthRepository(AuthRepositoryImpl authRepository); + + @Binds + @IntoMap + @DataRepositoryKey(FormsRepositoryImpl.class) + abstract DataRepository bindEventRepository(FormsRepositoryImpl formsRepository); + + @Binds + @IntoMap + @UseCaseKey(LoginUC.class) + abstract UseCase bindLoginUC(LoginUC useCase); +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/dagger/RetrofitModule.java b/app/src/main/java/ro/code4/monitorizarevot/dagger/RetrofitModule.java index 22ae43a..c6bc990 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/dagger/RetrofitModule.java +++ b/app/src/main/java/ro/code4/monitorizarevot/dagger/RetrofitModule.java @@ -5,8 +5,6 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; - import javax.inject.Named; import javax.inject.Singleton; @@ -16,6 +14,7 @@ import okhttp3.OkHttpClient; import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Retrofit; +import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; import ro.code4.monitorizarevot.BuildConfig; import ro.code4.monitorizarevot.net.AuthInterceptor; @@ -60,7 +59,7 @@ public boolean shouldSkipClass(Class clazz) { .baseUrl(BuildConfig.WEB_BASE_URL) .client(httpClient) .addConverterFactory(GsonConverterFactory.create(gson)) - .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/dagger/UseCaseKey.java b/app/src/main/java/ro/code4/monitorizarevot/dagger/UseCaseKey.java new file mode 100644 index 0000000..dd084cb --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/dagger/UseCaseKey.java @@ -0,0 +1,19 @@ +package ro.code4.monitorizarevot.dagger; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import dagger.MapKey; +import ro.code4.monitorizarevot.domain.usecase.UseCase; + +@Documented +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@MapKey +public @interface UseCaseKey { + + Class value(); +} \ No newline at end of file diff --git a/app/src/main/java/ro/code4/monitorizarevot/data/datasource/ApiDataSource.java b/app/src/main/java/ro/code4/monitorizarevot/data/datasource/ApiDataSource.java index 48cbb2f..72c5a9f 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/data/datasource/ApiDataSource.java +++ b/app/src/main/java/ro/code4/monitorizarevot/data/datasource/ApiDataSource.java @@ -15,7 +15,7 @@ public interface ApiDataSource { - Observable postAuth(User user); + Observable login(User user); Observable> getForm(String formId); diff --git a/app/src/main/java/ro/code4/monitorizarevot/data/datasource/HttpDataSource.java b/app/src/main/java/ro/code4/monitorizarevot/data/datasource/HttpDataSource.java index 13d29ee..c8a8d23 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/data/datasource/HttpDataSource.java +++ b/app/src/main/java/ro/code4/monitorizarevot/data/datasource/HttpDataSource.java @@ -1,6 +1,10 @@ package ro.code4.monitorizarevot.data.datasource; +import org.json.JSONException; +import org.json.JSONObject; + import java.io.File; +import java.io.IOException; import java.util.List; import javax.inject.Inject; @@ -9,6 +13,8 @@ import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.RequestBody; +import retrofit2.HttpException; +import retrofit2.Response; import ro.code4.monitorizarevot.data.rest.ApiService; import ro.code4.monitorizarevot.db.Preferences; import ro.code4.monitorizarevot.net.model.BranchDetails; @@ -20,11 +26,17 @@ import ro.code4.monitorizarevot.net.model.response.ResponseNote; import ro.code4.monitorizarevot.net.model.response.VersionResponse; import ro.code4.monitorizarevot.net.model.response.question.QuestionResponse; +import ro.code4.monitorizarevot.util.AuthUtils; import rx.Observable; +import rx.functions.Func1; @Singleton public class HttpDataSource implements ApiDataSource { + private static final int NUMBER_OF_RETRIES = 3; + + private static final String ACCESS_TOKEN = "access_token"; + private final ApiService mApiService; @Inject @@ -42,8 +54,50 @@ private static MultipartBody.Part createMultipart(String name, String value) { } @Override - public Observable postAuth(User user) { - return mApiService.postAuth(user); + @SuppressWarnings({"unchecked"}) + public Observable login(final User user) { + return mApiService.postAuth(user).onErrorResumeNext(new Func1>() { + + @Override + public Observable call(Throwable throwable) { + if (throwable instanceof HttpException) { + try { + Response response = (Response) ((HttpException) throwable).response(); + + JSONObject jsonErrorMessage = new JSONObject(response.errorBody().string()); + String message = jsonErrorMessage.has("error") ? + jsonErrorMessage.getString("error") : response.message(); + + return Observable.error(new IOException(message)); + + } catch (JSONException | IOException e) { + return Observable.error(throwable); + } + + } else { + return Observable.error(throwable); + } + } + }).flatMap(new Func1>() { + + @Override + public Observable call(Object response) { + try { + JSONObject body = new JSONObject(response.toString()); + String token = body.has(ACCESS_TOKEN) ? body.getString(ACCESS_TOKEN) : null; + if (token != null) { + AuthUtils.initAccount(user.getPhone(), user.getPin(), token); + + return Observable.just(true); + + } else { + return Observable.error(new IOException("Eroare de server")); + } + } catch (JSONException ex) { + return Observable.error(ex); + } + } + }); } @Override diff --git a/app/src/main/java/ro/code4/monitorizarevot/data/datasource/LocalDataSource.java b/app/src/main/java/ro/code4/monitorizarevot/data/datasource/LocalDataSource.java index 5fc1654..923134a 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/data/datasource/LocalDataSource.java +++ b/app/src/main/java/ro/code4/monitorizarevot/data/datasource/LocalDataSource.java @@ -24,7 +24,7 @@ public LocalDataSource() { } @Override - public Observable postAuth(User user) { + public Observable login(User user) { return null; } diff --git a/app/src/main/java/ro/code4/monitorizarevot/data/repository/AuthRepositoryImpl.java b/app/src/main/java/ro/code4/monitorizarevot/data/repository/AuthRepositoryImpl.java new file mode 100644 index 0000000..1cb88f6 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/data/repository/AuthRepositoryImpl.java @@ -0,0 +1,30 @@ +package ro.code4.monitorizarevot.data.repository; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import ro.code4.monitorizarevot.data.datasource.ApiDataSource; +import ro.code4.monitorizarevot.data.datasource.DataSourceFactory; +import ro.code4.monitorizarevot.domain.params.LoginDataParams; +import ro.code4.monitorizarevot.domain.repository.AuthRepository; +import ro.code4.monitorizarevot.net.model.User; +import rx.Observable; + +@Singleton +public class AuthRepositoryImpl implements AuthRepository { + + private final DataSourceFactory mDataSourceFactory; + + @Inject + public AuthRepositoryImpl(DataSourceFactory dataSourceFactory) { + mDataSourceFactory = dataSourceFactory; + } + + @Override + public Observable login(LoginDataParams params) { + ApiDataSource apiDataSource = mDataSourceFactory.dataSource(params.isLocal()); + User user = new User(params.getPhoneNumber(), params.getPinNumber(), params.getUdid()); + + return apiDataSource.login(user); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/data/repository/FormsRepositoryImpl.java b/app/src/main/java/ro/code4/monitorizarevot/data/repository/FormsRepositoryImpl.java new file mode 100644 index 0000000..d47bac5 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/data/repository/FormsRepositoryImpl.java @@ -0,0 +1,18 @@ +package ro.code4.monitorizarevot.data.repository; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import ro.code4.monitorizarevot.data.datasource.DataSourceFactory; +import ro.code4.monitorizarevot.domain.repository.FormsRepository; + +@Singleton +public class FormsRepositoryImpl implements FormsRepository { + + private final DataSourceFactory mDataSourceFactory; + + @Inject + public FormsRepositoryImpl(DataSourceFactory dataSourceFactory) { + mDataSourceFactory = dataSourceFactory; + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/data/repository/RepositoryFactory.java b/app/src/main/java/ro/code4/monitorizarevot/data/repository/RepositoryFactory.java new file mode 100644 index 0000000..7ce39d8 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/data/repository/RepositoryFactory.java @@ -0,0 +1,29 @@ +package ro.code4.monitorizarevot.data.repository; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; + +import ro.code4.monitorizarevot.domain.repository.AuthRepository; +import ro.code4.monitorizarevot.domain.repository.DataRepository; +import ro.code4.monitorizarevot.domain.repository.FormsRepository; +import ro.code4.monitorizarevot.util.AbstractComponentFactory; + +@Singleton +public class RepositoryFactory extends AbstractComponentFactory { + + @Inject + public RepositoryFactory(Map, Provider> creators) { + super(creators); + } + + public AuthRepository auth() { + return create(AuthRepositoryImpl.class); + } + + public FormsRepository forms() { + return create(FormsRepositoryImpl.class); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/domain/params/BaseDataParams.java b/app/src/main/java/ro/code4/monitorizarevot/domain/params/BaseDataParams.java new file mode 100644 index 0000000..7bdd3ce --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/domain/params/BaseDataParams.java @@ -0,0 +1,22 @@ +package ro.code4.monitorizarevot.domain.params; + +public class BaseDataParams { + + private boolean mIsLocal = false; + + public BaseDataParams() { + this(false); + } + + public BaseDataParams(boolean isLocal) { + mIsLocal = isLocal; + } + + public boolean isLocal() { + return mIsLocal; + } + + public void setLocal(boolean local) { + mIsLocal = local; + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/domain/params/LoginDataParams.java b/app/src/main/java/ro/code4/monitorizarevot/domain/params/LoginDataParams.java new file mode 100644 index 0000000..1b26c81 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/domain/params/LoginDataParams.java @@ -0,0 +1,30 @@ +package ro.code4.monitorizarevot.domain.params; + +public class LoginDataParams extends BaseDataParams { + + private String mPhoneNumber; + + private String mPinNumber; + + private String mUdid; + + public LoginDataParams(String phoneNumber, String pinNumber, String udid) { + super(false); + + mPhoneNumber = phoneNumber; + mPinNumber = pinNumber; + mUdid = udid; + } + + public String getPhoneNumber() { + return mPhoneNumber; + } + + public String getPinNumber() { + return mPinNumber; + } + + public String getUdid() { + return mUdid; + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/domain/repository/AuthRepository.java b/app/src/main/java/ro/code4/monitorizarevot/domain/repository/AuthRepository.java new file mode 100644 index 0000000..520affb --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/domain/repository/AuthRepository.java @@ -0,0 +1,9 @@ +package ro.code4.monitorizarevot.domain.repository; + +import ro.code4.monitorizarevot.domain.params.LoginDataParams; +import rx.Observable; + +public interface AuthRepository extends DataRepository { + + Observable login(LoginDataParams params); +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/domain/repository/DataRepository.java b/app/src/main/java/ro/code4/monitorizarevot/domain/repository/DataRepository.java new file mode 100644 index 0000000..648bc88 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/domain/repository/DataRepository.java @@ -0,0 +1,4 @@ +package ro.code4.monitorizarevot.domain.repository; + +public interface DataRepository { +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/domain/repository/FormsRepository.java b/app/src/main/java/ro/code4/monitorizarevot/domain/repository/FormsRepository.java new file mode 100644 index 0000000..06ed164 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/domain/repository/FormsRepository.java @@ -0,0 +1,5 @@ +package ro.code4.monitorizarevot.domain.repository; + +public interface FormsRepository extends DataRepository { + +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/domain/usecase/LoginUC.java b/app/src/main/java/ro/code4/monitorizarevot/domain/usecase/LoginUC.java new file mode 100644 index 0000000..4ab6dca --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/domain/usecase/LoginUC.java @@ -0,0 +1,23 @@ +package ro.code4.monitorizarevot.domain.usecase; + +import javax.inject.Inject; +import javax.inject.Named; + +import ro.code4.monitorizarevot.data.repository.RepositoryFactory; +import ro.code4.monitorizarevot.domain.params.LoginDataParams; +import rx.Observable; +import rx.Scheduler; + +public class LoginUC extends UseCase { + + @Inject + public LoginUC(@Named("io") Scheduler subscribeScheduler, + @Named("main") Scheduler observeScheduler, RepositoryFactory repoFactory) { + super(UseCaseType.LOGIN, subscribeScheduler, observeScheduler, repoFactory); + } + + @Override + protected Observable buildObservable(LoginDataParams params) { + return mRepoFactory.auth().login(params); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/domain/usecase/UseCase.java b/app/src/main/java/ro/code4/monitorizarevot/domain/usecase/UseCase.java new file mode 100644 index 0000000..9ba97fe --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/domain/usecase/UseCase.java @@ -0,0 +1,54 @@ +package ro.code4.monitorizarevot.domain.usecase; + +import ro.code4.monitorizarevot.data.repository.RepositoryFactory; +import rx.Observable; +import rx.Observer; +import rx.Scheduler; +import rx.Subscription; + +public abstract class UseCase { + + protected final RepositoryFactory mRepoFactory; + + private final UseCaseType mType; + + private final Scheduler mSubscribeScheduler; + + private final Scheduler mObserveScheduler; + + private Subscription mSubscription; + + UseCase(UseCaseType type, Scheduler subscribeScheduler, Scheduler observeScheduler, RepositoryFactory repoFactory) { + mType = type; + + mSubscribeScheduler = subscribeScheduler; + mObserveScheduler = observeScheduler; + + mRepoFactory = repoFactory; + } + + public void execute(Observer observer) { + execute(observer, null); + } + + public void execute(Observer observer, Params params) { + dispose(); + + final Observable observable = buildObservable(params).subscribeOn(mSubscribeScheduler).observeOn(mObserveScheduler); + + mSubscription = observable.subscribe(observer); + } + + public UseCaseType getType() { + return mType; + } + + public void dispose() { + if (mSubscription != null && !mSubscription.isUnsubscribed()) { + mSubscription.unsubscribe(); + mSubscription = null; + } + } + + protected abstract Observable buildObservable(Params params); +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/domain/usecase/UseCaseFactory.java b/app/src/main/java/ro/code4/monitorizarevot/domain/usecase/UseCaseFactory.java new file mode 100644 index 0000000..4046d3f --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/domain/usecase/UseCaseFactory.java @@ -0,0 +1,22 @@ +package ro.code4.monitorizarevot.domain.usecase; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; + +import ro.code4.monitorizarevot.util.AbstractComponentFactory; + +@Singleton +public class UseCaseFactory extends AbstractComponentFactory { + + @Inject + public UseCaseFactory(Map, Provider> creators) { + super(creators); + } + + public LoginUC login() { + return create(LoginUC.class); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/domain/usecase/UseCaseType.java b/app/src/main/java/ro/code4/monitorizarevot/domain/usecase/UseCaseType.java new file mode 100644 index 0000000..8f64aca --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/domain/usecase/UseCaseType.java @@ -0,0 +1,6 @@ +package ro.code4.monitorizarevot.domain.usecase; + +public enum UseCaseType { + + LOGIN +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/AddNoteViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/AddNoteViewModel.java index c421ab3..6fab26c 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/AddNoteViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/AddNoteViewModel.java @@ -2,10 +2,12 @@ import javax.inject.Inject; +import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; + public class AddNoteViewModel extends BaseViewModel { @Inject - public AddNoteViewModel() { - super(); + public AddNoteViewModel(UseCaseFactory useCaseFactory) { + super(useCaseFactory); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BaseViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BaseViewModel.java index a9b73a2..1bfcd29 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BaseViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BaseViewModel.java @@ -2,8 +2,13 @@ import android.arch.lifecycle.ViewModel; +import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; + public abstract class BaseViewModel extends ViewModel { - public BaseViewModel() { + protected final UseCaseFactory mUseCaseFactory; + + public BaseViewModel(UseCaseFactory useCaseFactory) { + mUseCaseFactory = useCaseFactory; } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchDetailsViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchDetailsViewModel.java index 3c7c75a..12cce8a 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchDetailsViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchDetailsViewModel.java @@ -2,10 +2,12 @@ import javax.inject.Inject; +import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; + public class BranchDetailsViewModel extends BaseViewModel { @Inject - public BranchDetailsViewModel() { - super(); + public BranchDetailsViewModel(UseCaseFactory useCaseFactory) { + super(useCaseFactory); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchSelectionViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchSelectionViewModel.java index 70a59fb..3acb684 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchSelectionViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchSelectionViewModel.java @@ -2,10 +2,12 @@ import javax.inject.Inject; +import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; + public class BranchSelectionViewModel extends BaseViewModel { @Inject - public BranchSelectionViewModel() { - super(); + public BranchSelectionViewModel(UseCaseFactory useCaseFactory) { + super(useCaseFactory); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/FormsListViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/FormsListViewModel.java index 6712510..7d8c35e 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/FormsListViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/FormsListViewModel.java @@ -3,10 +3,12 @@ import javax.inject.Inject; +import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; + public class FormsListViewModel extends BaseViewModel { @Inject - public FormsListViewModel() { - super(); + public FormsListViewModel(UseCaseFactory useCaseFactory) { + super(useCaseFactory); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/GuideViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/GuideViewModel.java index 70c529e..ed38a7f 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/GuideViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/GuideViewModel.java @@ -2,10 +2,12 @@ import javax.inject.Inject; +import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; + public class GuideViewModel extends BaseViewModel { @Inject - public GuideViewModel() { - super(); + public GuideViewModel(UseCaseFactory useCaseFactory) { + super(useCaseFactory); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/LoginViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/LoginViewModel.java index a4a42e0..0898acc 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/LoginViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/LoginViewModel.java @@ -2,10 +2,12 @@ import javax.inject.Inject; +import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; + public class LoginViewModel extends BaseViewModel { @Inject - public LoginViewModel() { - super(); + public LoginViewModel(UseCaseFactory useCaseFactory) { + super(useCaseFactory); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionDetailsViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionDetailsViewModel.java index 469ec58..88a1f5b 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionDetailsViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionDetailsViewModel.java @@ -2,10 +2,12 @@ import javax.inject.Inject; +import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; + public class QuestionDetailsViewModel extends BaseViewModel { @Inject - public QuestionDetailsViewModel() { - super(); + public QuestionDetailsViewModel(UseCaseFactory useCaseFactory) { + super(useCaseFactory); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionOverviewViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionOverviewViewModel.java index e1ada3d..9a359d9 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionOverviewViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionOverviewViewModel.java @@ -2,10 +2,12 @@ import javax.inject.Inject; +import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; + public class QuestionOverviewViewModel extends BaseViewModel { @Inject - public QuestionOverviewViewModel() { - super(); + public QuestionOverviewViewModel(UseCaseFactory useCaseFactory) { + super(useCaseFactory); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionViewModel.java index d15fae8..dc8dcf3 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionViewModel.java @@ -2,10 +2,12 @@ import javax.inject.Inject; +import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; + public class QuestionViewModel extends BaseViewModel { @Inject - public QuestionViewModel() { - super(); + public QuestionViewModel(UseCaseFactory useCaseFactory) { + super(useCaseFactory); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/StartViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/StartViewModel.java index 28e4f79..4e2dbc8 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/StartViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/StartViewModel.java @@ -2,10 +2,12 @@ import javax.inject.Inject; +import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; + public class StartViewModel extends BaseViewModel { @Inject - public StartViewModel() { - super(); + public StartViewModel(UseCaseFactory useCaseFactory) { + super(useCaseFactory); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/ToolbarViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/ToolbarViewModel.java index 7eae274..a042137 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/ToolbarViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/ToolbarViewModel.java @@ -2,10 +2,12 @@ import javax.inject.Inject; +import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; + public class ToolbarViewModel extends BaseViewModel { @Inject - public ToolbarViewModel() { - super(); + public ToolbarViewModel(UseCaseFactory useCaseFactory) { + super(useCaseFactory); } } diff --git a/app/src/mock/java/ro/code4/monitorizarevot/data/rest/MockApiService.java b/app/src/mock/java/ro/code4/monitorizarevot/data/rest/MockApiService.java index fc54576..3c810f0 100644 --- a/app/src/mock/java/ro/code4/monitorizarevot/data/rest/MockApiService.java +++ b/app/src/mock/java/ro/code4/monitorizarevot/data/rest/MockApiService.java @@ -1,5 +1,54 @@ package ro.code4.monitorizarevot.data.rest; +import java.util.List; + +import javax.inject.Inject; + +import okhttp3.MultipartBody; +import ro.code4.monitorizarevot.net.model.BranchDetails; +import ro.code4.monitorizarevot.net.model.ResponseAnswerContainer; +import ro.code4.monitorizarevot.net.model.Section; +import ro.code4.monitorizarevot.net.model.User; +import ro.code4.monitorizarevot.net.model.response.Ack; +import ro.code4.monitorizarevot.net.model.response.ResponseNote; +import ro.code4.monitorizarevot.net.model.response.VersionResponse; +import ro.code4.monitorizarevot.net.model.response.question.QuestionResponse; +import rx.Observable; + public class MockApiService implements ApiService { + @Inject + public MockApiService() { + } + + @Override + public Observable postAuth(User user) { + return null; + } + + @Override + public Observable> getForm(String formId) { + return null; + } + + @Override + public Observable getFormVersion() { + return null; + } + + @Override + public Observable postBranchDetails(BranchDetails branchDetails) { + return null; + } + + @Override + public Observable postQuestionAnswer(ResponseAnswerContainer responseAnswer) { + return null; + } + + @Override + public Observable postNote(MultipartBody.Part file, MultipartBody.Part countyCode, MultipartBody.Part branchNumber, + MultipartBody.Part questionId, MultipartBody.Part description) { + return null; + } } From 7031bf88aa9059e09064e7f998f68ad0d218b180 Mon Sep 17 00:00:00 2001 From: Alexandru Chiriac Date: Fri, 7 Dec 2018 21:14:05 +0200 Subject: [PATCH 13/89] Add butterknife gradle dependency --- app/build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index ec709a3..cd63bd0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -64,6 +64,9 @@ dependencies { implementation 'com.android.support:design:28.0.0' implementation 'android.arch.lifecycle:extensions:1.1.1' + implementation 'com.jakewharton:butterknife:8.8.1' + annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' + implementation 'com.squareup.retrofit2:retrofit:2.4.0' implementation 'com.squareup.retrofit2:converter-gson:2.4.0' implementation 'com.squareup.retrofit2:adapter-rxjava:2.1.0' From 09660a3d5b3dd8625aa45b6ac3d670ab72208467 Mon Sep 17 00:00:00 2001 From: Alexandru Chiriac Date: Fri, 7 Dec 2018 22:40:34 +0200 Subject: [PATCH 14/89] Mock Login Api call --- .../code4/monitorizarevot/BaseFragment.java | 1 + .../code4/monitorizarevot/LoginActivity.java | 120 +++++++----------- .../monitorizarevot/ToolbarActivity.java | 16 ++- .../data/datasource/HttpDataSource.java | 4 +- .../data/repository/AuthRepositoryImpl.java | 8 ++ .../domain/exception/MessageType.java | 10 ++ .../domain/exception/VoteException.java | 15 +++ .../presentation/LoadingMessage.java | 33 +++++ .../presentation/LoadingMessageFactory.java | 23 ++++ .../monitorizarevot/presentation/Message.java | 23 ++++ .../presentation/MessageFactory.java | 51 ++++++++ .../livedata/SingleLiveEvent.java | 66 ++++++++++ .../presentation/rx/DefaultObserver.java | 31 +++++ .../viewmodel/AddNoteViewModel.java | 7 +- .../viewmodel/BaseViewModel.java | 33 ++++- .../viewmodel/BranchDetailsViewModel.java | 7 +- .../viewmodel/BranchSelectionViewModel.java | 7 +- .../viewmodel/FormsListViewModel.java | 7 +- .../viewmodel/GuideViewModel.java | 7 +- .../viewmodel/LoginViewModel.java | 48 ++++++- .../viewmodel/QuestionDetailsViewModel.java | 7 +- .../viewmodel/QuestionOverviewViewModel.java | 7 +- .../viewmodel/QuestionViewModel.java | 7 +- .../viewmodel/StartViewModel.java | 7 +- .../viewmodel/ToolbarViewModel.java | 7 +- .../data/rest/MockApiService.java | 3 +- 26 files changed, 458 insertions(+), 97 deletions(-) create mode 100644 app/src/main/java/ro/code4/monitorizarevot/domain/exception/MessageType.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/domain/exception/VoteException.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/presentation/LoadingMessage.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/presentation/LoadingMessageFactory.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/presentation/Message.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/presentation/MessageFactory.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/presentation/livedata/SingleLiveEvent.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/presentation/rx/DefaultObserver.java diff --git a/app/src/main/java/ro/code4/monitorizarevot/BaseFragment.java b/app/src/main/java/ro/code4/monitorizarevot/BaseFragment.java index 6c78ade..8eedb8c 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/BaseFragment.java +++ b/app/src/main/java/ro/code4/monitorizarevot/BaseFragment.java @@ -53,6 +53,7 @@ public void onCreate(Bundle savedInstanceState) { @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); + setupViewModel(); setTitle(getTitle()); setMenu(withMenu()); } diff --git a/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java b/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java index 941d352..9f41b16 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java +++ b/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java @@ -1,52 +1,60 @@ package ro.code4.monitorizarevot; import android.app.ActivityOptions; +import android.arch.lifecycle.Observer; import android.arch.lifecycle.ViewModelProviders; import android.content.Intent; import android.os.Bundle; import android.provider.Settings; +import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Pair; import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; import android.widget.EditText; import android.widget.TextView; -import ro.code4.monitorizarevot.net.NetworkService; -import ro.code4.monitorizarevot.net.model.User; -import ro.code4.monitorizarevot.observable.ObservableListener; -import ro.code4.monitorizarevot.observable.ObservableListenerDetacher; +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; import ro.code4.monitorizarevot.viewmodel.LoginViewModel; import vn.tungdx.mediapicker.activities.MediaPickerErrorDialog; public class LoginActivity extends BaseActivity { - private EditText username; + @BindView(R.id.phone) + EditText username; - private EditText password; + @BindView(R.id.branch) + EditText password; - private Button loginButton; - - private ObservableListenerDetacher mListenerDetacher; + @BindView(R.id.app_version) + TextView appVersion; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); - username = (EditText) findViewById(R.id.phone); - password = (EditText) findViewById(R.id.branch); - username.getText(); + ButterKnife.bind(this); + + appVersion.setText(getString(R.string.app_version, BuildConfig.VERSION_NAME)); + + viewModel.message().observe(this, new Observer() { - loginButton = (Button) findViewById(R.id.login_button); - loginButton.setOnClickListener(new OnClickListener() { @Override - public void onClick(View view) { - login(); + public void onChanged(@Nullable String message) { + showErrorDialog(message); } }); - setAppVersion((TextView) findViewById(R.id.app_version)); + viewModel.loginStatus().observe(this, new Observer() { + + @Override + public void onChanged(Boolean status) { + if (status) { + performNavigation(); + } + } + }); } @Override @@ -54,65 +62,35 @@ protected void setupViewModel() { viewModel = ViewModelProviders.of(this, factory).get(LoginViewModel.class); } - @Override - protected void onDestroy() { - super.onDestroy(); - if (mListenerDetacher != null && !mListenerDetacher.isDetached()) { - mListenerDetacher.detach(); - } - } + @OnClick(R.id.login_button) + void onLoginButtonClick() { + String phoneNumber = username.getText().toString(); + String pin = password.getText().toString(); + String udid = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID); - private void setAppVersion(TextView appVersion) { - appVersion.setText(getString(R.string.app_version, BuildConfig.VERSION_NAME)); + viewModel.login(phoneNumber, pin, udid); } - private void login() { - String userName = username.getText().toString(); - String pass = password.getText().toString(); - - if (!TextUtils.isEmpty(userName.trim()) && !TextUtils.isEmpty(pass.trim())) { - showLoading(); - User user = new User(userName, pass, getUdid()); - mListenerDetacher = NetworkService.login(user).startRequest(new LoginSubscriber()); - } else { - MediaPickerErrorDialog - .newInstance(getString(R.string.empty_credential_message)) - .show(getSupportFragmentManager(), null); + private void showErrorDialog(String message) { + if (!TextUtils.isEmpty(message)) { + MediaPickerErrorDialog.newInstance(message).show(getSupportFragmentManager(), null); } } - private String getUdid() { - return Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID); - } - - private class LoginSubscriber extends ObservableListener { - - @Override - public void onError(Throwable e) { - super.onError(e); - hideLoading(); - MediaPickerErrorDialog - .newInstance(e.getMessage()) - .show(getSupportFragmentManager(), null); - } - - @Override - public void onSuccess() { - hideLoading(); - Intent intent = new Intent(LoginActivity.this, ToolbarActivity.class); - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { - ActivityOptions options; - Pair sharedBackground = new Pair<>(findViewById(R.id.purple_background), - getString(R.string.shared_element_login_background)); - Pair sharedLogo = new Pair<>(findViewById(R.id.logo), getString(R.string.shared_element_logo)); - options = ActivityOptions - .makeSceneTransitionAnimation(LoginActivity.this, sharedBackground, sharedLogo); - startActivity(intent, options.toBundle()); - } else { - startActivity(intent); - } - finish(); //TODO finish after transition is complete + private void performNavigation() { + Intent intent = new Intent(LoginActivity.this, ToolbarActivity.class); + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { + ActivityOptions options; + Pair sharedBackground = new Pair<>(findViewById(R.id.purple_background), + getString(R.string.shared_element_login_background)); + Pair sharedLogo = new Pair<>(findViewById(R.id.logo), getString(R.string.shared_element_logo)); + options = ActivityOptions + .makeSceneTransitionAnimation(LoginActivity.this, sharedBackground, sharedLogo); + startActivity(intent, options.toBundle()); + } else { + startActivity(intent); } + finish(); //TODO finish after transition is complete } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/ToolbarActivity.java b/app/src/main/java/ro/code4/monitorizarevot/ToolbarActivity.java index 477be94..25b60ec 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/ToolbarActivity.java +++ b/app/src/main/java/ro/code4/monitorizarevot/ToolbarActivity.java @@ -5,12 +5,18 @@ import android.net.Uri; import android.os.Bundle; import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; import android.view.View; import android.widget.TextView; +import javax.inject.Inject; + +import dagger.android.AndroidInjector; +import dagger.android.DispatchingAndroidInjector; +import dagger.android.support.HasSupportFragmentInjector; import ro.code4.monitorizarevot.adapter.SyncAdapter; import ro.code4.monitorizarevot.constants.Constants; import ro.code4.monitorizarevot.fragment.BranchSelectionFragment; @@ -18,10 +24,13 @@ import ro.code4.monitorizarevot.fragment.GuideFragment; import ro.code4.monitorizarevot.viewmodel.ToolbarViewModel; -public class ToolbarActivity extends BaseActivity implements Navigator { +public class ToolbarActivity extends BaseActivity implements Navigator, HasSupportFragmentInjector { public static final int BRANCH_SELECTION_BACKSTACK_INDEX = 0; + @Inject + DispatchingAndroidInjector mDispatchingAndroidInjector; + private DrawerLayout drawerLayout; private View menuButton; @@ -161,4 +170,9 @@ private void closeDrawer() { drawerLayout.closeDrawer(GravityCompat.START); } } + + @Override + public AndroidInjector supportFragmentInjector() { + return mDispatchingAndroidInjector; + } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/data/datasource/HttpDataSource.java b/app/src/main/java/ro/code4/monitorizarevot/data/datasource/HttpDataSource.java index c8a8d23..6b2a31a 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/data/datasource/HttpDataSource.java +++ b/app/src/main/java/ro/code4/monitorizarevot/data/datasource/HttpDataSource.java @@ -17,6 +17,8 @@ import retrofit2.Response; import ro.code4.monitorizarevot.data.rest.ApiService; import ro.code4.monitorizarevot.db.Preferences; +import ro.code4.monitorizarevot.domain.exception.MessageType; +import ro.code4.monitorizarevot.domain.exception.VoteException; import ro.code4.monitorizarevot.net.model.BranchDetails; import ro.code4.monitorizarevot.net.model.Note; import ro.code4.monitorizarevot.net.model.ResponseAnswerContainer; @@ -91,7 +93,7 @@ public Observable call(Object response) { return Observable.just(true); } else { - return Observable.error(new IOException("Eroare de server")); + return Observable.error(new VoteException(MessageType.SERVER_ERROR)); } } catch (JSONException ex) { return Observable.error(ex); diff --git a/app/src/main/java/ro/code4/monitorizarevot/data/repository/AuthRepositoryImpl.java b/app/src/main/java/ro/code4/monitorizarevot/data/repository/AuthRepositoryImpl.java index 1cb88f6..497750b 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/data/repository/AuthRepositoryImpl.java +++ b/app/src/main/java/ro/code4/monitorizarevot/data/repository/AuthRepositoryImpl.java @@ -1,10 +1,14 @@ package ro.code4.monitorizarevot.data.repository; +import android.text.TextUtils; + import javax.inject.Inject; import javax.inject.Singleton; import ro.code4.monitorizarevot.data.datasource.ApiDataSource; import ro.code4.monitorizarevot.data.datasource.DataSourceFactory; +import ro.code4.monitorizarevot.domain.exception.MessageType; +import ro.code4.monitorizarevot.domain.exception.VoteException; import ro.code4.monitorizarevot.domain.params.LoginDataParams; import ro.code4.monitorizarevot.domain.repository.AuthRepository; import ro.code4.monitorizarevot.net.model.User; @@ -22,6 +26,10 @@ public AuthRepositoryImpl(DataSourceFactory dataSourceFactory) { @Override public Observable login(LoginDataParams params) { + if(TextUtils.isEmpty(params.getPhoneNumber()) || TextUtils.isEmpty(params.getPinNumber())) { + return Observable.error(new VoteException(MessageType.EMPTY_CREDENTIALS)); + } + ApiDataSource apiDataSource = mDataSourceFactory.dataSource(params.isLocal()); User user = new User(params.getPhoneNumber(), params.getPinNumber(), params.getUdid()); diff --git a/app/src/main/java/ro/code4/monitorizarevot/domain/exception/MessageType.java b/app/src/main/java/ro/code4/monitorizarevot/domain/exception/MessageType.java new file mode 100644 index 0000000..db7ef97 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/domain/exception/MessageType.java @@ -0,0 +1,10 @@ +package ro.code4.monitorizarevot.domain.exception; + +public enum MessageType { + + EMPTY_CREDENTIALS, + + SERVER_ERROR, + + UNKNOWN +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/domain/exception/VoteException.java b/app/src/main/java/ro/code4/monitorizarevot/domain/exception/VoteException.java new file mode 100644 index 0000000..215b9dc --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/domain/exception/VoteException.java @@ -0,0 +1,15 @@ +package ro.code4.monitorizarevot.domain.exception; + +public class VoteException extends Exception { + + private MessageType mType; + + public VoteException(MessageType type) { + super(); + mType = type; + } + + public MessageType getType() { + return mType; + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/presentation/LoadingMessage.java b/app/src/main/java/ro/code4/monitorizarevot/presentation/LoadingMessage.java new file mode 100644 index 0000000..d27636c --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/presentation/LoadingMessage.java @@ -0,0 +1,33 @@ +package ro.code4.monitorizarevot.presentation; + +public class LoadingMessage { + + private boolean mIsLoading; + + private String mMessage; + + public LoadingMessage() { + this(true); + } + + public LoadingMessage(String message) { + this(true, message); + } + + public LoadingMessage(boolean isLoading) { + this(isLoading, null); + } + + public LoadingMessage(boolean isLoading, String message) { + mIsLoading = isLoading; + mMessage = message; + } + + public boolean isLoading() { + return mIsLoading; + } + + public String getMessage() { + return mMessage; + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/presentation/LoadingMessageFactory.java b/app/src/main/java/ro/code4/monitorizarevot/presentation/LoadingMessageFactory.java new file mode 100644 index 0000000..ee91449 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/presentation/LoadingMessageFactory.java @@ -0,0 +1,23 @@ +package ro.code4.monitorizarevot.presentation; + +import android.content.Context; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import ro.code4.monitorizarevot.domain.usecase.UseCaseType; + +@Singleton +public class LoadingMessageFactory { + + private final Context mContext; + + @Inject + public LoadingMessageFactory(Context context) { + mContext = context; + } + + public LoadingMessage getMessage(UseCaseType type) { + return new LoadingMessage("Vă rugăm așteptaţi..."); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/presentation/Message.java b/app/src/main/java/ro/code4/monitorizarevot/presentation/Message.java new file mode 100644 index 0000000..6f3747f --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/presentation/Message.java @@ -0,0 +1,23 @@ +package ro.code4.monitorizarevot.presentation; + +import ro.code4.monitorizarevot.domain.exception.MessageType; + +public class Message { + + private MessageType mType; + + private String mMessage; + + public Message(MessageType type, String message) { + mType = type; + mMessage = message; + } + + public MessageType getType() { + return mType; + } + + public String getMessage() { + return mMessage; + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/presentation/MessageFactory.java b/app/src/main/java/ro/code4/monitorizarevot/presentation/MessageFactory.java new file mode 100644 index 0000000..4e3f0ae --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/presentation/MessageFactory.java @@ -0,0 +1,51 @@ +package ro.code4.monitorizarevot.presentation; + +import android.content.Context; + +import javax.inject.Inject; + +import ro.code4.monitorizarevot.R; +import ro.code4.monitorizarevot.domain.exception.MessageType; +import ro.code4.monitorizarevot.domain.exception.VoteException; + +import static ro.code4.monitorizarevot.domain.exception.MessageType.UNKNOWN; + +public class MessageFactory { + + private final Context mContext; + + @Inject + public MessageFactory(Context context) { + mContext = context; + } + + public Message getMessage(MessageType type) { + String message; + + switch (type) { + case EMPTY_CREDENTIALS: + message = mContext.getString(R.string.empty_credential_message); + break; + + case SERVER_ERROR: + message = "Eroare de server"; + break; + + default: + message = "unknown error"; + break; + } + + return new Message(type, message); + } + + public Message getErrorMessage(Throwable throwable) { + if (throwable == null || !(throwable instanceof VoteException)) { + return new Message(UNKNOWN, "unknown error"); + } + + VoteException exc = (VoteException) throwable; + + return getMessage(exc.getType()); + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/presentation/livedata/SingleLiveEvent.java b/app/src/main/java/ro/code4/monitorizarevot/presentation/livedata/SingleLiveEvent.java new file mode 100644 index 0000000..7a21f9f --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/presentation/livedata/SingleLiveEvent.java @@ -0,0 +1,66 @@ +package ro.code4.monitorizarevot.presentation.livedata; + +import android.arch.lifecycle.LifecycleOwner; +import android.arch.lifecycle.MutableLiveData; +import android.arch.lifecycle.Observer; +import android.support.annotation.MainThread; +import android.support.annotation.Nullable; +import android.util.Log; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * A lifecycle-aware observable that sends only new updates after subscription, used for events like + * navigation and Snackbar messages. + *

+ * This avoids a common problem with events: on configuration change (like rotation) an update + * can be emitted if the observer is active. This LiveData only calls the observable if there's an + * explicit call to setValue() or call(). + *

+ * Note that only one observer is going to be notified of changes. + */ +public class SingleLiveEvent extends MutableLiveData { + + private static final String TAG = "SingleLiveEvent"; + + private final AtomicBoolean mPending = new AtomicBoolean(false); + + @MainThread + public void observe(LifecycleOwner owner, final Observer observer) { + + if (hasActiveObservers()) { + Log.w(TAG, "Multiple observers registered but only one will be notified of changes."); + } + + // Observe the internal MutableLiveData + super.observe(owner, new Observer() { + + @Override + public void onChanged(@Nullable T t) { + if (mPending.compareAndSet(true, false)) { + observer.onChanged(t); + } + } + }); + } + + public void postValue(@Nullable T t) { + mPending.set(true); + super.postValue(t); + } + + @MainThread + public void setValue(@Nullable T t) { + mPending.set(true); + super.setValue(t); + } + + /** + * Used for cases where T is Void, to make calls cleaner. + */ + @MainThread + public void call() { + setValue(null); + } +} + diff --git a/app/src/main/java/ro/code4/monitorizarevot/presentation/rx/DefaultObserver.java b/app/src/main/java/ro/code4/monitorizarevot/presentation/rx/DefaultObserver.java new file mode 100644 index 0000000..a0cd71d --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/presentation/rx/DefaultObserver.java @@ -0,0 +1,31 @@ +package ro.code4.monitorizarevot.presentation.rx; + +import ro.code4.monitorizarevot.presentation.Message; +import ro.code4.monitorizarevot.presentation.MessageFactory; +import rx.Observer; + +public abstract class DefaultObserver implements Observer { + + private final MessageFactory mMessageFactory; + + public DefaultObserver(MessageFactory messageFactory) { + super(); + mMessageFactory = messageFactory; + } + + @Override + public void onCompleted() { + } + + @Override + public void onError(Throwable throwable) { + onErrorMessage(mMessageFactory.getErrorMessage(throwable)); + } + + @Override + public void onNext(T t) { + } + + public void onErrorMessage(Message message) { + } +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/AddNoteViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/AddNoteViewModel.java index 6fab26c..6fbac22 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/AddNoteViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/AddNoteViewModel.java @@ -3,11 +3,14 @@ import javax.inject.Inject; import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; +import ro.code4.monitorizarevot.presentation.LoadingMessageFactory; +import ro.code4.monitorizarevot.presentation.MessageFactory; public class AddNoteViewModel extends BaseViewModel { @Inject - public AddNoteViewModel(UseCaseFactory useCaseFactory) { - super(useCaseFactory); + public AddNoteViewModel(UseCaseFactory useCaseFactory, LoadingMessageFactory loadingMessageFactory, + MessageFactory messageFactory) { + super(useCaseFactory, loadingMessageFactory, messageFactory); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BaseViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BaseViewModel.java index 1bfcd29..e0af3ce 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BaseViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BaseViewModel.java @@ -1,14 +1,45 @@ package ro.code4.monitorizarevot.viewmodel; +import android.arch.lifecycle.LiveData; +import android.arch.lifecycle.MutableLiveData; import android.arch.lifecycle.ViewModel; import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; +import ro.code4.monitorizarevot.domain.usecase.UseCaseType; +import ro.code4.monitorizarevot.presentation.LoadingMessage; +import ro.code4.monitorizarevot.presentation.LoadingMessageFactory; +import ro.code4.monitorizarevot.presentation.MessageFactory; +import ro.code4.monitorizarevot.presentation.livedata.SingleLiveEvent; public abstract class BaseViewModel extends ViewModel { protected final UseCaseFactory mUseCaseFactory; - public BaseViewModel(UseCaseFactory useCaseFactory) { + protected final LoadingMessageFactory mLoadingMessageFactory; + + protected final MessageFactory mMessageFactory; + + protected final SingleLiveEvent mMessage = new SingleLiveEvent<>(); + + protected final MutableLiveData mContentLoading = new MutableLiveData<>(); + + public BaseViewModel(UseCaseFactory useCaseFactory, + LoadingMessageFactory loadingMessageFactory, + MessageFactory messageFactory) { mUseCaseFactory = useCaseFactory; + mLoadingMessageFactory = loadingMessageFactory; + mMessageFactory = messageFactory; + } + + public LiveData message() { + return mMessage; + } + + public LiveData contentLoading() { + return mContentLoading; + } + + protected LoadingMessage getLoadingMessage(UseCaseType useCaseType) { + return mLoadingMessageFactory.getMessage(useCaseType); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchDetailsViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchDetailsViewModel.java index 12cce8a..4c38853 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchDetailsViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchDetailsViewModel.java @@ -3,11 +3,14 @@ import javax.inject.Inject; import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; +import ro.code4.monitorizarevot.presentation.LoadingMessageFactory; +import ro.code4.monitorizarevot.presentation.MessageFactory; public class BranchDetailsViewModel extends BaseViewModel { @Inject - public BranchDetailsViewModel(UseCaseFactory useCaseFactory) { - super(useCaseFactory); + public BranchDetailsViewModel(UseCaseFactory useCaseFactory, LoadingMessageFactory loadingMessageFactory, + MessageFactory messageFactory) { + super(useCaseFactory, loadingMessageFactory, messageFactory); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchSelectionViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchSelectionViewModel.java index 3acb684..0d8f68d 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchSelectionViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/BranchSelectionViewModel.java @@ -3,11 +3,14 @@ import javax.inject.Inject; import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; +import ro.code4.monitorizarevot.presentation.LoadingMessageFactory; +import ro.code4.monitorizarevot.presentation.MessageFactory; public class BranchSelectionViewModel extends BaseViewModel { @Inject - public BranchSelectionViewModel(UseCaseFactory useCaseFactory) { - super(useCaseFactory); + public BranchSelectionViewModel(UseCaseFactory useCaseFactory, LoadingMessageFactory loadingMessageFactory, + MessageFactory messageFactory) { + super(useCaseFactory, loadingMessageFactory, messageFactory); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/FormsListViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/FormsListViewModel.java index 7d8c35e..27d5bba 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/FormsListViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/FormsListViewModel.java @@ -4,11 +4,14 @@ import javax.inject.Inject; import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; +import ro.code4.monitorizarevot.presentation.LoadingMessageFactory; +import ro.code4.monitorizarevot.presentation.MessageFactory; public class FormsListViewModel extends BaseViewModel { @Inject - public FormsListViewModel(UseCaseFactory useCaseFactory) { - super(useCaseFactory); + public FormsListViewModel(UseCaseFactory useCaseFactory, LoadingMessageFactory loadingMessageFactory, + MessageFactory messageFactory) { + super(useCaseFactory, loadingMessageFactory, messageFactory); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/GuideViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/GuideViewModel.java index ed38a7f..13af8f5 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/GuideViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/GuideViewModel.java @@ -3,11 +3,14 @@ import javax.inject.Inject; import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; +import ro.code4.monitorizarevot.presentation.LoadingMessageFactory; +import ro.code4.monitorizarevot.presentation.MessageFactory; public class GuideViewModel extends BaseViewModel { @Inject - public GuideViewModel(UseCaseFactory useCaseFactory) { - super(useCaseFactory); + public GuideViewModel(UseCaseFactory useCaseFactory, LoadingMessageFactory loadingMessageFactory, + MessageFactory messageFactory) { + super(useCaseFactory, loadingMessageFactory, messageFactory); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/LoginViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/LoginViewModel.java index 0898acc..89ad12a 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/LoginViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/LoginViewModel.java @@ -1,13 +1,57 @@ package ro.code4.monitorizarevot.viewmodel; +import android.arch.lifecycle.LiveData; + import javax.inject.Inject; +import ro.code4.monitorizarevot.domain.params.LoginDataParams; +import ro.code4.monitorizarevot.domain.usecase.LoginUC; import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; +import ro.code4.monitorizarevot.presentation.LoadingMessage; +import ro.code4.monitorizarevot.presentation.LoadingMessageFactory; +import ro.code4.monitorizarevot.presentation.Message; +import ro.code4.monitorizarevot.presentation.MessageFactory; +import ro.code4.monitorizarevot.presentation.livedata.SingleLiveEvent; +import ro.code4.monitorizarevot.presentation.rx.DefaultObserver; public class LoginViewModel extends BaseViewModel { + private SingleLiveEvent mLoginStatus = new SingleLiveEvent<>(); + @Inject - public LoginViewModel(UseCaseFactory useCaseFactory) { - super(useCaseFactory); + public LoginViewModel(UseCaseFactory useCaseFactory, LoadingMessageFactory loadingMessageFactory, MessageFactory messageFactory) { + super(useCaseFactory, loadingMessageFactory, messageFactory); + } + + public LiveData loginStatus() { + return mLoginStatus; + } + + public void login(String phoneNumber, String pin, String udid) { + LoginUC loginUC = mUseCaseFactory.login(); + + mContentLoading.postValue(getLoadingMessage(loginUC.getType())); + + LoginDataParams params = new LoginDataParams(phoneNumber, pin, udid); + loginUC.execute(new LoginObserver(mMessageFactory), params); + } + + private class LoginObserver extends DefaultObserver { + + public LoginObserver(MessageFactory messageFactory) { + super(messageFactory); + } + + @Override + public void onNext(Boolean success) { + mLoginStatus.postValue(success); + mContentLoading.postValue(new LoadingMessage(false)); + } + + @Override + public void onErrorMessage(Message message) { + mMessage.postValue(message.getMessage()); + mContentLoading.postValue(new LoadingMessage(false)); + } } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionDetailsViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionDetailsViewModel.java index 88a1f5b..565d53e 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionDetailsViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionDetailsViewModel.java @@ -3,11 +3,14 @@ import javax.inject.Inject; import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; +import ro.code4.monitorizarevot.presentation.LoadingMessageFactory; +import ro.code4.monitorizarevot.presentation.MessageFactory; public class QuestionDetailsViewModel extends BaseViewModel { @Inject - public QuestionDetailsViewModel(UseCaseFactory useCaseFactory) { - super(useCaseFactory); + public QuestionDetailsViewModel(UseCaseFactory useCaseFactory, LoadingMessageFactory loadingMessageFactory, + MessageFactory messageFactory) { + super(useCaseFactory, loadingMessageFactory, messageFactory); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionOverviewViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionOverviewViewModel.java index 9a359d9..b0189ae 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionOverviewViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionOverviewViewModel.java @@ -3,11 +3,14 @@ import javax.inject.Inject; import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; +import ro.code4.monitorizarevot.presentation.LoadingMessageFactory; +import ro.code4.monitorizarevot.presentation.MessageFactory; public class QuestionOverviewViewModel extends BaseViewModel { @Inject - public QuestionOverviewViewModel(UseCaseFactory useCaseFactory) { - super(useCaseFactory); + public QuestionOverviewViewModel(UseCaseFactory useCaseFactory, LoadingMessageFactory loadingMessageFactory, + MessageFactory messageFactory) { + super(useCaseFactory, loadingMessageFactory, messageFactory); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionViewModel.java index dc8dcf3..d296281 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/QuestionViewModel.java @@ -3,11 +3,14 @@ import javax.inject.Inject; import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; +import ro.code4.monitorizarevot.presentation.LoadingMessageFactory; +import ro.code4.monitorizarevot.presentation.MessageFactory; public class QuestionViewModel extends BaseViewModel { @Inject - public QuestionViewModel(UseCaseFactory useCaseFactory) { - super(useCaseFactory); + public QuestionViewModel(UseCaseFactory useCaseFactory, LoadingMessageFactory loadingMessageFactory, + MessageFactory messageFactory) { + super(useCaseFactory, loadingMessageFactory, messageFactory); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/StartViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/StartViewModel.java index 4e2dbc8..bf9eb1b 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/StartViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/StartViewModel.java @@ -3,11 +3,14 @@ import javax.inject.Inject; import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; +import ro.code4.monitorizarevot.presentation.LoadingMessageFactory; +import ro.code4.monitorizarevot.presentation.MessageFactory; public class StartViewModel extends BaseViewModel { @Inject - public StartViewModel(UseCaseFactory useCaseFactory) { - super(useCaseFactory); + public StartViewModel(UseCaseFactory useCaseFactory, LoadingMessageFactory loadingMessageFactory, + MessageFactory messageFactory) { + super(useCaseFactory, loadingMessageFactory, messageFactory); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/ToolbarViewModel.java b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/ToolbarViewModel.java index a042137..7ee717e 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/viewmodel/ToolbarViewModel.java +++ b/app/src/main/java/ro/code4/monitorizarevot/viewmodel/ToolbarViewModel.java @@ -3,11 +3,14 @@ import javax.inject.Inject; import ro.code4.monitorizarevot.domain.usecase.UseCaseFactory; +import ro.code4.monitorizarevot.presentation.LoadingMessageFactory; +import ro.code4.monitorizarevot.presentation.MessageFactory; public class ToolbarViewModel extends BaseViewModel { @Inject - public ToolbarViewModel(UseCaseFactory useCaseFactory) { - super(useCaseFactory); + public ToolbarViewModel(UseCaseFactory useCaseFactory, LoadingMessageFactory loadingMessageFactory, + MessageFactory messageFactory) { + super(useCaseFactory, loadingMessageFactory, messageFactory); } } diff --git a/app/src/mock/java/ro/code4/monitorizarevot/data/rest/MockApiService.java b/app/src/mock/java/ro/code4/monitorizarevot/data/rest/MockApiService.java index 3c810f0..55f1991 100644 --- a/app/src/mock/java/ro/code4/monitorizarevot/data/rest/MockApiService.java +++ b/app/src/mock/java/ro/code4/monitorizarevot/data/rest/MockApiService.java @@ -1,6 +1,7 @@ package ro.code4.monitorizarevot.data.rest; import java.util.List; +import java.util.concurrent.TimeUnit; import javax.inject.Inject; @@ -23,7 +24,7 @@ public MockApiService() { @Override public Observable postAuth(User user) { - return null; + return Observable.just((Object) "{\"access_token\": \"12335dssdbddre\"}").delay(1, TimeUnit.SECONDS); } @Override From 84f5eb4457502594e9bb7bb71038cb7ef5a8be0b Mon Sep 17 00:00:00 2001 From: Alexandru Chiriac Date: Fri, 7 Dec 2018 23:29:00 +0200 Subject: [PATCH 15/89] Fix sync adapter auth --- app/build.gradle | 5 ++--- .../dev/java/ro/code4/monitorizarevot/constants/Sync.java | 8 ++++++++ app/src/dev/res/values/authorities.xml | 1 + .../ro/code4/monitorizarevot/adapter/SyncAdapter.java | 1 - app/src/main/res/xml/authenticator.xml | 2 +- app/src/main/res/xml/syncadapter.xml | 2 +- .../java/ro/code4/monitorizarevot/constants/Sync.java | 8 ++++++++ app/src/mock/res/values/authorities.xml | 1 + .../java/ro/code4/monitorizarevot/constants/Sync.java | 2 ++ app/src/prod/res/values/authorities.xml | 1 + 10 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 app/src/dev/java/ro/code4/monitorizarevot/constants/Sync.java create mode 100644 app/src/mock/java/ro/code4/monitorizarevot/constants/Sync.java rename app/src/{main => prod}/java/ro/code4/monitorizarevot/constants/Sync.java (98%) diff --git a/app/build.gradle b/app/build.gradle index cd63bd0..2b1de82 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -19,12 +19,10 @@ android { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - buildConfigField "String", "WEB_BASE_URL", '"http://viuat.azurewebsites.net/"' } debug { debuggable true - buildConfigField "String", "WEB_BASE_URL", '"http://viuat.azurewebsites.net/"' } } @@ -32,7 +30,7 @@ android { dev { applicationIdSuffix '.dev' versionNameSuffix "d" - buildConfigField "String", "WEB_BASE_URL", '"http://viuat.azurewebsites.net/"' + buildConfigField "String", "WEB_BASE_URL", '"http://10.3.193.203:44379"' } prod { @@ -42,6 +40,7 @@ android { mock { applicationIdSuffix '.mock' versionNameSuffix "m" + buildConfigField "String", "WEB_BASE_URL", '""' } } diff --git a/app/src/dev/java/ro/code4/monitorizarevot/constants/Sync.java b/app/src/dev/java/ro/code4/monitorizarevot/constants/Sync.java new file mode 100644 index 0000000..b0720a8 --- /dev/null +++ b/app/src/dev/java/ro/code4/monitorizarevot/constants/Sync.java @@ -0,0 +1,8 @@ +package ro.code4.monitorizarevot.constants; + +public class Sync { + + public static final String AUTHORITY = "ro.code4.monitorizarevot.dev"; + + public static final String ACCOUNT_TYPE = "dev.code4.ro"; +} diff --git a/app/src/dev/res/values/authorities.xml b/app/src/dev/res/values/authorities.xml index 7ad92d1..d20ac64 100644 --- a/app/src/dev/res/values/authorities.xml +++ b/app/src/dev/res/values/authorities.xml @@ -2,4 +2,5 @@ ro.code4.monitorizarevot.dev ro.code4.monitorizarevot.dev + dev.code4.ro \ No newline at end of file diff --git a/app/src/main/java/ro/code4/monitorizarevot/adapter/SyncAdapter.java b/app/src/main/java/ro/code4/monitorizarevot/adapter/SyncAdapter.java index 95402f8..bfff119 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/adapter/SyncAdapter.java +++ b/app/src/main/java/ro/code4/monitorizarevot/adapter/SyncAdapter.java @@ -13,7 +13,6 @@ import java.util.ArrayList; import java.util.List; -import ro.code4.monitorizarevot.LoginActivity; import ro.code4.monitorizarevot.constants.Sync; import ro.code4.monitorizarevot.db.Data; import ro.code4.monitorizarevot.net.NetworkService; diff --git a/app/src/main/res/xml/authenticator.xml b/app/src/main/res/xml/authenticator.xml index 2867784..e3cc60c 100644 --- a/app/src/main/res/xml/authenticator.xml +++ b/app/src/main/res/xml/authenticator.xml @@ -1,4 +1,4 @@ \ No newline at end of file diff --git a/app/src/main/res/xml/syncadapter.xml b/app/src/main/res/xml/syncadapter.xml index 70fd8c3..cc66421 100644 --- a/app/src/main/res/xml/syncadapter.xml +++ b/app/src/main/res/xml/syncadapter.xml @@ -2,7 +2,7 @@ ro.code4.monitorizarevot.mock ro.code4.monitorizarevot.mock + mock.code4.ro \ No newline at end of file diff --git a/app/src/main/java/ro/code4/monitorizarevot/constants/Sync.java b/app/src/prod/java/ro/code4/monitorizarevot/constants/Sync.java similarity index 98% rename from app/src/main/java/ro/code4/monitorizarevot/constants/Sync.java rename to app/src/prod/java/ro/code4/monitorizarevot/constants/Sync.java index fd6ad3f..e869b02 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/constants/Sync.java +++ b/app/src/prod/java/ro/code4/monitorizarevot/constants/Sync.java @@ -1,6 +1,8 @@ package ro.code4.monitorizarevot.constants; public class Sync { + public static final String AUTHORITY = "ro.code4.monitorizarevot"; + public static final String ACCOUNT_TYPE = "code4.ro"; } diff --git a/app/src/prod/res/values/authorities.xml b/app/src/prod/res/values/authorities.xml index 3c94a4c..7b6a1e0 100644 --- a/app/src/prod/res/values/authorities.xml +++ b/app/src/prod/res/values/authorities.xml @@ -2,4 +2,5 @@ ro.code4.monitorizarevot ro.code4.monitorizarevot + code4.ro \ No newline at end of file From 84cab7fcaaa3d4bb451976c955eec0efbc6b529d Mon Sep 17 00:00:00 2001 From: Mircea Serediuc Date: Fri, 7 Dec 2018 23:30:32 +0200 Subject: [PATCH 16/89] no message --- app/build.gradle | 2 +- app/src/main/AndroidManifest.xml | 8 ++++ .../code4/monitorizarevot/LoginActivity.java | 30 +++++++++++++ .../monitorizarevot/util/SmsListener.java | 5 +++ .../monitorizarevot/util/SmsReceiver.java | 42 +++++++++++++++++++ 5 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/ro/code4/monitorizarevot/util/SmsListener.java create mode 100644 app/src/main/java/ro/code4/monitorizarevot/util/SmsReceiver.java diff --git a/app/build.gradle b/app/build.gradle index 8bdb50d..0722f2c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -21,7 +21,7 @@ android { debug { debuggable true - buildConfigField "String", "WEB_BASE_URL", '"http://viuat.azurewebsites.net/"' + buildConfigField "String", "WEB_BASE_URL", '"http://10.3.193.203:44379"' } } } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 199cb94..ddb7a2e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -12,6 +12,9 @@ + + + @@ -50,6 +53,11 @@ + + + + + diff --git a/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java b/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java index 4a057da..1ba25e4 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java +++ b/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java @@ -12,6 +12,7 @@ import android.support.v4.content.ContextCompat; import android.telephony.TelephonyManager; import android.text.TextUtils; +import android.util.Log; import android.util.Pair; import android.view.KeyEvent; import android.view.View; @@ -22,10 +23,15 @@ import android.widget.TextView; import android.widget.Toast; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import ro.code4.monitorizarevot.net.NetworkService; import ro.code4.monitorizarevot.net.model.User; import ro.code4.monitorizarevot.observable.ObservableListener; import ro.code4.monitorizarevot.observable.ObservableListenerDetacher; +import ro.code4.monitorizarevot.util.SmsListener; +import ro.code4.monitorizarevot.util.SmsReceiver; import vn.tungdx.mediapicker.activities.MediaPickerErrorDialog; public class LoginActivity extends BaseActivity { @@ -71,6 +77,30 @@ public void onClick(View view) { }); setAppVersion((TextView) findViewById(R.id.app_version)); + + SmsReceiver.bindListener(new SmsListener() { + @Override + public void messageReceived(String messageText) { + + //From the received text string you may do string operations to get the required OTP + //It depends on your SMS format + Log.e("Message",messageText); + Toast.makeText(getBaseContext(),"Message: "+messageText,Toast.LENGTH_LONG).show(); + + // If your OTP is six digits number, you may use the below code + String OTP_REGEX = "[0-9]{1,6}"; + Pattern pattern = Pattern.compile(OTP_REGEX); + Matcher matcher = pattern.matcher(messageText); + String otp = ""; + while (matcher.find()) + { + otp = matcher.group(); + } + + Toast.makeText(LoginActivity.this,"OTP: "+ otp ,Toast.LENGTH_LONG).show(); + + } + }); } @Override diff --git a/app/src/main/java/ro/code4/monitorizarevot/util/SmsListener.java b/app/src/main/java/ro/code4/monitorizarevot/util/SmsListener.java new file mode 100644 index 0000000..6593a4f --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/util/SmsListener.java @@ -0,0 +1,5 @@ +package ro.code4.monitorizarevot.util; + +public interface SmsListener { + void messageReceived(String messageText); +} diff --git a/app/src/main/java/ro/code4/monitorizarevot/util/SmsReceiver.java b/app/src/main/java/ro/code4/monitorizarevot/util/SmsReceiver.java new file mode 100644 index 0000000..21ea5a0 --- /dev/null +++ b/app/src/main/java/ro/code4/monitorizarevot/util/SmsReceiver.java @@ -0,0 +1,42 @@ +package ro.code4.monitorizarevot.util; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.telephony.SmsMessage; + +public class SmsReceiver extends BroadcastReceiver { + + //interface + private static SmsListener mListener; + + @Override + public void onReceive(Context context, Intent intent) { + Bundle data = intent.getExtras(); + + Object[] pdus = (Object[]) data.get("pdus"); + + for(int i=0;i Date: Sat, 8 Dec 2018 00:01:05 +0200 Subject: [PATCH 17/89] Logout button implemented / login at done button from keyboard --- .../ro/code4/monitorizarevot/LoginActivity.java | 17 ++++++++++++++++- .../code4/monitorizarevot/ToolbarActivity.java | 9 +++++++++ app/src/main/res/layout/activity_login.xml | 1 + app/src/main/res/layout/activity_toolbar.xml | 6 ++++++ app/src/main/res/values/strings.xml | 1 + 5 files changed, 33 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java b/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java index 9f41b16..6d43b09 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java +++ b/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java @@ -9,7 +9,9 @@ import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Pair; +import android.view.KeyEvent; import android.view.View; +import android.view.inputmethod.EditorInfo; import android.widget.EditText; import android.widget.TextView; @@ -55,6 +57,16 @@ public void onChanged(Boolean status) { } } }); + + password.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) { + if (i == EditorInfo.IME_ACTION_DONE) { + login(); + } + return false; + } + }); } @Override @@ -64,10 +76,13 @@ protected void setupViewModel() { @OnClick(R.id.login_button) void onLoginButtonClick() { + login(); + } + + private void login(){ String phoneNumber = username.getText().toString(); String pin = password.getText().toString(); String udid = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID); - viewModel.login(phoneNumber, pin, udid); } diff --git a/app/src/main/java/ro/code4/monitorizarevot/ToolbarActivity.java b/app/src/main/java/ro/code4/monitorizarevot/ToolbarActivity.java index 25b60ec..8baf307 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/ToolbarActivity.java +++ b/app/src/main/java/ro/code4/monitorizarevot/ToolbarActivity.java @@ -12,6 +12,8 @@ import android.view.View; import android.widget.TextView; +import org.greenrobot.eventbus.EventBus; + import javax.inject.Inject; import dagger.android.AndroidInjector; @@ -22,6 +24,7 @@ import ro.code4.monitorizarevot.fragment.BranchSelectionFragment; import ro.code4.monitorizarevot.fragment.FormsListFragment; import ro.code4.monitorizarevot.fragment.GuideFragment; +import ro.code4.monitorizarevot.net.model.LogoutListener; import ro.code4.monitorizarevot.viewmodel.ToolbarViewModel; public class ToolbarActivity extends BaseActivity implements Navigator, HasSupportFragmentInjector { @@ -90,6 +93,12 @@ public void onClick(View v) { callSupportCenter(); } }); + findViewById(R.id.menu_logout).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + EventBus.getDefault().post(new LogoutListener()); + } + }); } private void callSupportCenter() { diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index a7cd974..14952aa 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -78,6 +78,7 @@ android:layout_height="@dimen/input_height" android:hint="@string/login_branch" android:inputType="textPassword" + android:imeOptions="actionDone" style="@style/InputLogin"/> diff --git a/app/src/main/res/layout/activity_toolbar.xml b/app/src/main/res/layout/activity_toolbar.xml index 3aa2ccb..aac2d71 100644 --- a/app/src/main/res/layout/activity_toolbar.xml +++ b/app/src/main/res/layout/activity_toolbar.xml @@ -56,6 +56,12 @@ android:layout_height="@dimen/menu_item_height" android:text="@string/menu_call" style="@style/menuItem"/> + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bd1de22..a9ddcd8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -24,6 +24,7 @@ Schimbă secţia Ghidul observatorului Apelează TelVerde + Delogare Phone icon From 9a6e8592b8f434c717a858cecd585147b26bb7d6 Mon Sep 17 00:00:00 2001 From: Alexandru Chiriac Date: Sat, 8 Dec 2018 00:27:52 +0200 Subject: [PATCH 18/89] Restore loading indicator on login api call --- .../code4/monitorizarevot/BaseActivity.java | 31 +++++++++++++------ .../code4/monitorizarevot/LoginActivity.java | 2 ++ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/ro/code4/monitorizarevot/BaseActivity.java b/app/src/main/java/ro/code4/monitorizarevot/BaseActivity.java index 0e0262e..4ce2ea9 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/BaseActivity.java +++ b/app/src/main/java/ro/code4/monitorizarevot/BaseActivity.java @@ -5,6 +5,7 @@ import org.greenrobot.eventbus.ThreadMode; import android.app.ProgressDialog; +import android.arch.lifecycle.Observer; import android.arch.lifecycle.ViewModelProvider; import android.content.Context; import android.content.Intent; @@ -20,6 +21,7 @@ import javax.inject.Inject; import ro.code4.monitorizarevot.net.model.LogoutListener; +import ro.code4.monitorizarevot.presentation.LoadingMessage; import ro.code4.monitorizarevot.util.ActivityOperations; import ro.code4.monitorizarevot.util.AuthUtils; import ro.code4.monitorizarevot.viewmodel.BaseViewModel; @@ -39,8 +41,15 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { setupViewModel(); + viewModel.contentLoading().observe(this, new Observer() { + + @Override + public void onChanged(@Nullable LoadingMessage loadingMessage) { + showHideLoading(loadingMessage); + } + }); + loadingIndicator = new ProgressDialog(this); - loadingIndicator.setMessage("Vă rugăm așteptaţi..."); loadingIndicator.setCancelable(false); } @@ -56,14 +65,6 @@ protected void onStop() { EventBus.getDefault().unregister(this); } - public void showLoading() { - loadingIndicator.show(); - } - - public void hideLoading() { - loadingIndicator.dismiss(); - } - @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); @@ -92,5 +93,17 @@ public void hideFocusedKeyboard() { } } + protected void showHideLoading(LoadingMessage loadingMessage) { + if (loadingMessage != null) { + if (loadingMessage.isLoading()) { + loadingIndicator.setMessage(loadingMessage.getMessage()); + loadingIndicator.show(); + + } else { + loadingIndicator.hide(); + } + } + } + protected abstract void setupViewModel(); } diff --git a/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java b/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java index 6d43b09..be5996b 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java +++ b/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java @@ -58,6 +58,8 @@ public void onChanged(Boolean status) { } }); + + password.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) { From 19ea05296a5be626211ba26b09f904157ddee581 Mon Sep 17 00:00:00 2001 From: Alexandru Chiriac Date: Sat, 8 Dec 2018 01:09:56 +0200 Subject: [PATCH 19/89] Use butterknife to setup listeners --- .../code4/monitorizarevot/LoginActivity.java | 44 ++++++++----------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java b/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java index 198868e..3ad5681 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java +++ b/app/src/main/java/ro/code4/monitorizarevot/LoginActivity.java @@ -19,7 +19,7 @@ import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; -import ro.code4.monitorizarevot.observable.ObservableListenerDetacher; +import butterknife.OnEditorAction; import ro.code4.monitorizarevot.viewmodel.LoginViewModel; import vn.tungdx.mediapicker.activities.MediaPickerErrorDialog; @@ -36,8 +36,6 @@ public class LoginActivity extends BaseActivity { @BindView(R.id.app_version) TextView appVersion; - private ObservableListenerDetacher mListenerDetacher; - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -45,6 +43,7 @@ protected void onCreate(Bundle savedInstanceState) { ButterKnife.bind(this); appVersion.setText(getString(R.string.app_version, BuildConfig.VERSION_NAME)); + viewModel.message().observe(this, new Observer() { @Override @@ -53,14 +52,6 @@ public void onChanged(@Nullable String message) { } }); - View organisationLink = findViewById(R.id.login_organisation_link); - organisationLink.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - openOrganisationWebpage(); - } - }); - viewModel.loginStatus().observe(this, new Observer() { @Override @@ -70,16 +61,11 @@ public void onChanged(Boolean status) { } } }); + } - password.setOnEditorActionListener(new TextView.OnEditorActionListener() { - @Override - public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) { - if (i == EditorInfo.IME_ACTION_DONE) { - login(); - } - return false; - } - }); + @Override + protected void setupViewModel() { + viewModel = ViewModelProviders.of(this, factory).get(LoginViewModel.class); } private void openOrganisationWebpage() { @@ -87,16 +73,24 @@ private void openOrganisationWebpage() { startActivity(openBrowser); } - @Override - protected void setupViewModel() { - viewModel = ViewModelProviders.of(this, factory).get(LoginViewModel.class); - } - @OnClick(R.id.login_button) void onLoginButtonClick() { login(); } + @OnClick(R.id.login_organisation_link) + void onOrganisationLinkClick() { + openOrganisationWebpage(); + } + + @OnEditorAction(R.id.branch) + boolean onDoneEditPassword(TextView textView, int i, KeyEvent keyEvent) { + if (i == EditorInfo.IME_ACTION_DONE) { + login(); + } + return false; + } + private void login() { String phoneNumber = username.getText().toString(); String pin = password.getText().toString(); From d8c4b54215e0fa7079a10d6afcb64bebacc272c8 Mon Sep 17 00:00:00 2001 From: Alexandru Chiriac Date: Sat, 8 Dec 2018 01:31:10 +0200 Subject: [PATCH 20/89] Clear credentials on logout --- app/src/main/java/ro/code4/monitorizarevot/BaseActivity.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/ro/code4/monitorizarevot/BaseActivity.java b/app/src/main/java/ro/code4/monitorizarevot/BaseActivity.java index 4ce2ea9..cba682a 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/BaseActivity.java +++ b/app/src/main/java/ro/code4/monitorizarevot/BaseActivity.java @@ -20,6 +20,7 @@ import javax.inject.Inject; +import ro.code4.monitorizarevot.db.Preferences; import ro.code4.monitorizarevot.net.model.LogoutListener; import ro.code4.monitorizarevot.presentation.LoadingMessage; import ro.code4.monitorizarevot.util.ActivityOperations; @@ -79,6 +80,7 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis @Subscribe(threadMode = ThreadMode.MAIN) public void onMessageEvent(LogoutListener event) { AuthUtils.removeAccountAndStopSync(); + Preferences.clear(); Intent intent = new Intent(this, LoginActivity.class); startActivity(intent); From 478eb0adaa39ba6466e27ef75851bb1395614936 Mon Sep 17 00:00:00 2001 From: Alexandru Chiriac Date: Sat, 8 Dec 2018 01:40:34 +0200 Subject: [PATCH 21/89] Fix loading message on login screen (use string resource) --- .../monitorizarevot/presentation/LoadingMessageFactory.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/ro/code4/monitorizarevot/presentation/LoadingMessageFactory.java b/app/src/main/java/ro/code4/monitorizarevot/presentation/LoadingMessageFactory.java index ee91449..21c6b35 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/presentation/LoadingMessageFactory.java +++ b/app/src/main/java/ro/code4/monitorizarevot/presentation/LoadingMessageFactory.java @@ -5,6 +5,7 @@ import javax.inject.Inject; import javax.inject.Singleton; +import ro.code4.monitorizarevot.R; import ro.code4.monitorizarevot.domain.usecase.UseCaseType; @Singleton @@ -18,6 +19,6 @@ public LoadingMessageFactory(Context context) { } public LoadingMessage getMessage(UseCaseType type) { - return new LoadingMessage("Vă rugăm așteptaţi..."); + return new LoadingMessage(mContext.getString(R.string.please_wait)); } } From ca9780afbb283b40a8c1ebf956cd966d7d01f7f6 Mon Sep 17 00:00:00 2001 From: Mircea Serediuc Date: Sat, 8 Dec 2018 10:36:11 +0200 Subject: [PATCH 22/89] *Fixed message sent after each message is completed *Insert previous button --- .../fragment/QuestionFragment.java | 38 ++++++++++++++++++- .../fragment/QuestionsDetailsFragment.java | 16 +++++++- .../util/QuestionDetailsNavigator.java | 1 + app/src/main/res/layout/fragment_question.xml | 7 ++++ app/src/main/res/values-ro/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + 6 files changed, 62 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/ro/code4/monitorizarevot/fragment/QuestionFragment.java b/app/src/main/java/ro/code4/monitorizarevot/fragment/QuestionFragment.java index c444817..7dde3fe 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/fragment/QuestionFragment.java +++ b/app/src/main/java/ro/code4/monitorizarevot/fragment/QuestionFragment.java @@ -8,6 +8,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; import android.widget.TextView; import ro.code4.monitorizarevot.BaseFragment; @@ -30,6 +31,10 @@ public class QuestionFragment extends BaseFragment { private QuestionDetailsNavigator navigator; + private Button nextButton; + + private Button previousButton; + private int numberOfQuestions; private int questionIndex; @@ -88,10 +93,11 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c rootView.findViewById(R.id.button_question_next).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - navigator.onSaveAnswerIfCompleted(questionContainer); - navigator.onNext(); + } }); + + rootView.findViewById(R.id.button_question_notes).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { @@ -99,10 +105,38 @@ public void onClick(View view) { navigator.onNotes(); } }); + nextButton = rootView.findViewById(R.id.button_question_next); + nextButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + navigator.onSaveAnswerIfCompleted(questionContainer); + navigator.onNext(); + + } + }); + + previousButton = rootView.findViewById(R.id.button_question_previous); + previousButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + navigator.onSaveAnswerIfCompleted(questionContainer); + navigator.onPrevious(); + hideButtons(); + } + }); + hideButtons(); return rootView; } private void setDescription(TextView description) { description.setText(question.getText()); } + + private void hideButtons(){ + if(questionIndex > 1){ + previousButton.setVisibility(View.VISIBLE); + }else{ + previousButton.setVisibility(View.GONE); + } + } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/fragment/QuestionsDetailsFragment.java b/app/src/main/java/ro/code4/monitorizarevot/fragment/QuestionsDetailsFragment.java index d1d5a7d..8eec522 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/fragment/QuestionsDetailsFragment.java +++ b/app/src/main/java/ro/code4/monitorizarevot/fragment/QuestionsDetailsFragment.java @@ -7,6 +7,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Toast; import java.util.List; @@ -108,12 +109,23 @@ public void onNext() { @Override public void onSaveAnswerIfCompleted(ViewGroup questionContainer) { List answers = mPresenter.getAnswerIfCompleted(questionContainer); + Question question = questions.get(currentQuestion); if (answers.size() > 0) { - Question question = questions.get(currentQuestion); BranchQuestionAnswer branchQuestionAnswer = new BranchQuestionAnswer(question.getId(), answers); Data.getInstance().saveAnswerResponse(branchQuestionAnswer); - syncCurrentData(branchQuestionAnswer); + Toast.makeText(getContext(),getString(R.string.question_confirmation_message),Toast.LENGTH_SHORT).show(); + } + } + + @Override + public void onPrevious() { + hideFocusedKeyboard(); + if (currentQuestion > 1) { + showQuestion(currentQuestion - 1); + } else { + SyncAdapter.requestUploadSync(getActivity()); + navigateBack(); } } diff --git a/app/src/main/java/ro/code4/monitorizarevot/util/QuestionDetailsNavigator.java b/app/src/main/java/ro/code4/monitorizarevot/util/QuestionDetailsNavigator.java index 6d2d921..c75fa62 100644 --- a/app/src/main/java/ro/code4/monitorizarevot/util/QuestionDetailsNavigator.java +++ b/app/src/main/java/ro/code4/monitorizarevot/util/QuestionDetailsNavigator.java @@ -6,4 +6,5 @@ public interface QuestionDetailsNavigator { void onNotes(); void onNext(); void onSaveAnswerIfCompleted(ViewGroup questionContainer); + void onPrevious(); } diff --git a/app/src/main/res/layout/fragment_question.xml b/app/src/main/res/layout/fragment_question.xml index e024103..34d824e 100644 --- a/app/src/main/res/layout/fragment_question.xml +++ b/app/src/main/res/layout/fragment_question.xml @@ -37,6 +37,13 @@ android:layout_height="wrap_content" android:orientation="horizontal" android:layout_alignParentBottom="true"> +