From c57916ab2469c865a43c46711f5f75e1589f6f7d Mon Sep 17 00:00:00 2001 From: Sangeetha Date: Wed, 19 Aug 2020 11:50:44 +0530 Subject: [PATCH 1/4] Add Navigation Drawer Dependency --- app/build.gradle | 7 +++++++ build.gradle | 2 ++ 2 files changed, 9 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index f58d783fb..fa9533a0e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,6 +1,8 @@ import groovy.json.JsonSlurper apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' ext { testpressSDK = '1.3.93' @@ -66,6 +68,11 @@ dependencies { testImplementation 'org.powermock:powermock-module-junit4:1.7.4' testImplementation 'org.powermock:powermock-api-mockito2:1.7.4' + //VIEW MODEL - LIVE DATA + implementation "androidx.lifecycle:lifecycle-viewmodel:2.2.0" + implementation "androidx.lifecycle:lifecycle-livedata:2.2.0" + annotationProcessor "androidx.lifecycle:lifecycle-compiler:2.2.0" + } def key_alias = "sample" diff --git a/build.gradle b/build.gradle index 1f004ac0e..509f3de53 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { + ext.kotlin_version = '1.3.31' repositories { google() jcenter() @@ -8,6 +9,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.2.1' classpath 'com.google.gms:google-services:3.2.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files From f7a171d3e7639d5207c14aed7d4d1ad459cae862 Mon Sep 17 00:00:00 2001 From: Sangeetha Date: Wed, 19 Aug 2020 13:15:00 +0530 Subject: [PATCH 2/4] Add Navigation Drawer UI --- .../testpress/testpress/ui/MainActivity.java | 57 +++++++++----- app/src/main/res/drawable/ic_settings.xml | 5 ++ app/src/main/res/layout/main_activity.xml | 1 + .../res/layout/navigation_drawer_header.xml | 78 +++++++++++++++++++ app/src/main/res/values/colors.xml | 2 + 5 files changed, 125 insertions(+), 18 deletions(-) create mode 100644 app/src/main/res/drawable/ic_settings.xml create mode 100644 app/src/main/res/layout/navigation_drawer_header.xml diff --git a/app/src/main/java/in/testpress/testpress/ui/MainActivity.java b/app/src/main/java/in/testpress/testpress/ui/MainActivity.java index 9f6fe9e58..0d0560c3c 100644 --- a/app/src/main/java/in/testpress/testpress/ui/MainActivity.java +++ b/app/src/main/java/in/testpress/testpress/ui/MainActivity.java @@ -8,43 +8,36 @@ import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; -import androidx.coordinatorlayout.widget.CoordinatorLayout; -import androidx.core.view.GravityCompat; -import androidx.viewpager.widget.ViewPager; -import androidx.drawerlayout.widget.DrawerLayout; -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.ActionBarDrawerToggle; -import androidx.appcompat.app.AlertDialog; - import android.os.Handler; -import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.Button; import android.widget.GridView; -import android.widget.ImageButton; +import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; - +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.ActionBarDrawerToggle; +import androidx.appcompat.app.AlertDialog; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.core.view.GravityCompat; +import androidx.drawerlayout.widget.DrawerLayout; import androidx.fragment.app.Fragment; - +import androidx.viewpager.widget.ViewPager; import com.google.android.gms.common.GoogleApiAvailability; import com.google.android.material.navigation.NavigationView; - import java.io.IOException; import java.util.ArrayList; import java.util.List; - import javax.inject.Inject; - import butterknife.ButterKnife; import butterknife.InjectView; import in.testpress.core.TestpressSdk; -import in.testpress.core.TestpressSession; import in.testpress.course.TestpressCourse; import in.testpress.course.fragments.DownloadsFragment; import in.testpress.exam.ui.view.NonSwipeableViewPager; @@ -71,7 +64,6 @@ import in.testpress.testpress.util.UIUtils; import in.testpress.testpress.util.UpdateAppDialogManager; import io.sentry.android.core.SentryAndroid; - import static in.testpress.testpress.BuildConfig.ALLOW_ANONYMOUS_USER; import static in.testpress.testpress.BuildConfig.APPLICATION_ID; import static in.testpress.testpress.BuildConfig.BASE_URL; @@ -100,6 +92,11 @@ public class MainActivity extends TestpressFragmentActivity { DrawerLayout drawer; @InjectView(R.id.navigation_view) NavigationView navigationView; + ConstraintLayout navigationHeader; + ImageView settingsImage; + TextView username; + TextView displayName; + ImageView profileImage; private ActionBarDrawerToggle drawerToggle; private int mSelectedItem; @@ -137,7 +134,9 @@ protected void onCreate(final Bundle savedInstanceState) { } else { checkUpdate(); } + initializeNavigationHeader(); setupEasterEgg(); + setOnClickListener(); } @Override @@ -157,7 +156,6 @@ private void setupEasterEgg() { rateUsButton.setActionView(button); rateUsButton.getActionView().setVisibility(View.GONE); - findViewById(R.id.version_info).setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View view) { @@ -186,6 +184,29 @@ public boolean onLongClick(View view) { }); } + private void initializeNavigationHeader() { + View headerView = navigationView.getHeaderView(0); + navigationHeader = headerView.findViewById(R.id.navigation_header_container); + username = headerView.findViewById(R.id.userName); + displayName = headerView.findViewById(R.id.displayName); + profileImage = headerView.findViewById(R.id.profileImage); + settingsImage = headerView.findViewById(R.id.settingsImage); + } + + private void setOnClickListener() { + settingsImage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + navigateToProfileDetailsActivity(); + } + }); + } + + private void navigateToProfileDetailsActivity() { + Intent intent = new Intent(this, ProfileDetailsActivity.class); + startActivity(intent); + } + private void setUpNavigationDrawer() { getSupportActionBar().setHomeButtonEnabled(true); drawerToggle = setupDrawerToggle(); diff --git a/app/src/main/res/drawable/ic_settings.xml b/app/src/main/res/drawable/ic_settings.xml new file mode 100644 index 000000000..d34d081e8 --- /dev/null +++ b/app/src/main/res/drawable/ic_settings.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/main_activity.xml b/app/src/main/res/layout/main_activity.xml index 25b40b83c..2050b5a94 100644 --- a/app/src/main/res/layout/main_activity.xml +++ b/app/src/main/res/layout/main_activity.xml @@ -88,6 +88,7 @@ android:layout_gravity="start" app:itemTextColor="@color/testpress_black" android:background="@android:color/white" + app:headerLayout="@layout/navigation_drawer_header" app:menu="@menu/main_menu" > diff --git a/app/src/main/res/layout/navigation_drawer_header.xml b/app/src/main/res/layout/navigation_drawer_header.xml new file mode 100644 index 000000000..fd2fefdb7 --- /dev/null +++ b/app/src/main/res/layout/navigation_drawer_header.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 6325d9ea3..7c04dd4e2 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -63,4 +63,6 @@ #298cdd #efefef + #dedede + From 0b721038e245743c710468084a68f53ebe054cc1 Mon Sep 17 00:00:00 2001 From: Sangeetha Date: Wed, 19 Aug 2020 15:37:40 +0530 Subject: [PATCH 3/4] Add ViewModel --- .../testpress/core/AuthenticationService.java | 1 + .../testpress/core/TestpressService.java | 1 + .../network/ProfileDetailRepository.kt | 26 +++++++++++++++++++ .../testpress/ui/ProfileDetailsViewModel.kt | 15 +++++++++++ 4 files changed, 43 insertions(+) create mode 100644 app/src/main/java/in/testpress/testpress/network/ProfileDetailRepository.kt create mode 100644 app/src/main/java/in/testpress/testpress/ui/ProfileDetailsViewModel.kt diff --git a/app/src/main/java/in/testpress/testpress/core/AuthenticationService.java b/app/src/main/java/in/testpress/testpress/core/AuthenticationService.java index 8a6403194..36c54c2d2 100644 --- a/app/src/main/java/in/testpress/testpress/core/AuthenticationService.java +++ b/app/src/main/java/in/testpress/testpress/core/AuthenticationService.java @@ -2,6 +2,7 @@ import java.util.HashMap; +import in.testpress.course.network.Resource; import in.testpress.testpress.models.AuthToken; import in.testpress.testpress.models.ProfileDetails; import in.testpress.testpress.models.RegistrationSuccessResponse; diff --git a/app/src/main/java/in/testpress/testpress/core/TestpressService.java b/app/src/main/java/in/testpress/testpress/core/TestpressService.java index 32177edb9..bbd55798b 100644 --- a/app/src/main/java/in/testpress/testpress/core/TestpressService.java +++ b/app/src/main/java/in/testpress/testpress/core/TestpressService.java @@ -10,6 +10,7 @@ import java.util.List; import java.util.Map; +import in.testpress.course.network.Resource; import in.testpress.exam.models.Vote; import in.testpress.testpress.models.Category; import in.testpress.testpress.models.CheckPermission; diff --git a/app/src/main/java/in/testpress/testpress/network/ProfileDetailRepository.kt b/app/src/main/java/in/testpress/testpress/network/ProfileDetailRepository.kt new file mode 100644 index 000000000..5a70d8498 --- /dev/null +++ b/app/src/main/java/in/testpress/testpress/network/ProfileDetailRepository.kt @@ -0,0 +1,26 @@ +package `in`.testpress.testpress.network + +import `in`.testpress.testpress.TestpressServiceProvider +import `in`.testpress.testpress.models.ProfileDetails +import `in`.testpress.testpress.util.SafeAsyncTask +import android.app.Activity +import androidx.lifecycle.MutableLiveData + +class ProfileDetailRepository(val serviceProvider: TestpressServiceProvider, val activity: Activity) { + var profileDetails = MutableLiveData() + fun get() { + object : SafeAsyncTask() { + override fun call(): ProfileDetails { + return serviceProvider.getService(activity).profileDetails + } + + override fun onSuccess(resource: ProfileDetails) { + profileDetails.postValue(resource) + } + + override fun onException(exception: Exception) { + profileDetails.postValue(null) + } + }.execute() + } +} \ No newline at end of file diff --git a/app/src/main/java/in/testpress/testpress/ui/ProfileDetailsViewModel.kt b/app/src/main/java/in/testpress/testpress/ui/ProfileDetailsViewModel.kt new file mode 100644 index 000000000..d8f79b44a --- /dev/null +++ b/app/src/main/java/in/testpress/testpress/ui/ProfileDetailsViewModel.kt @@ -0,0 +1,15 @@ +package `in`.testpress.testpress.ui + +import `in`.testpress.course.network.Resource +import `in`.testpress.testpress.models.ProfileDetails +import `in`.testpress.testpress.network.ProfileDetailRepository +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel + +class ProfileDetailsViewModel(private val profileDetailRepository: ProfileDetailRepository) : ViewModel() { + var profileDetails = MutableLiveData>() + fun get(): LiveData> { + return profileDetailRepository.get() + } +} From bfa6e968f804cb19200d6f58f8092c0348d2572e Mon Sep 17 00:00:00 2001 From: Sangeetha Date: Wed, 19 Aug 2020 16:24:37 +0530 Subject: [PATCH 4/4] navigation drawer network --- .../network/ProfileDetailRepository.kt | 5 ++++- .../testpress/ui/ProfileDetailsViewModel.kt | 6 ++---- .../util/ProfileDetailViewModelFactory.kt | 19 +++++++++++++++++++ 3 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/in/testpress/testpress/util/ProfileDetailViewModelFactory.kt diff --git a/app/src/main/java/in/testpress/testpress/network/ProfileDetailRepository.kt b/app/src/main/java/in/testpress/testpress/network/ProfileDetailRepository.kt index 5a70d8498..61711ca82 100644 --- a/app/src/main/java/in/testpress/testpress/network/ProfileDetailRepository.kt +++ b/app/src/main/java/in/testpress/testpress/network/ProfileDetailRepository.kt @@ -7,8 +7,10 @@ import android.app.Activity import androidx.lifecycle.MutableLiveData class ProfileDetailRepository(val serviceProvider: TestpressServiceProvider, val activity: Activity) { + var profileDetails = MutableLiveData() - fun get() { + + fun get(): MutableLiveData { object : SafeAsyncTask() { override fun call(): ProfileDetails { return serviceProvider.getService(activity).profileDetails @@ -22,5 +24,6 @@ class ProfileDetailRepository(val serviceProvider: TestpressServiceProvider, val profileDetails.postValue(null) } }.execute() + return profileDetails } } \ No newline at end of file diff --git a/app/src/main/java/in/testpress/testpress/ui/ProfileDetailsViewModel.kt b/app/src/main/java/in/testpress/testpress/ui/ProfileDetailsViewModel.kt index d8f79b44a..a8916cca9 100644 --- a/app/src/main/java/in/testpress/testpress/ui/ProfileDetailsViewModel.kt +++ b/app/src/main/java/in/testpress/testpress/ui/ProfileDetailsViewModel.kt @@ -1,15 +1,13 @@ package `in`.testpress.testpress.ui -import `in`.testpress.course.network.Resource import `in`.testpress.testpress.models.ProfileDetails import `in`.testpress.testpress.network.ProfileDetailRepository -import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel class ProfileDetailsViewModel(private val profileDetailRepository: ProfileDetailRepository) : ViewModel() { - var profileDetails = MutableLiveData>() - fun get(): LiveData> { + + fun get(): MutableLiveData { return profileDetailRepository.get() } } diff --git a/app/src/main/java/in/testpress/testpress/util/ProfileDetailViewModelFactory.kt b/app/src/main/java/in/testpress/testpress/util/ProfileDetailViewModelFactory.kt new file mode 100644 index 000000000..db8a362da --- /dev/null +++ b/app/src/main/java/in/testpress/testpress/util/ProfileDetailViewModelFactory.kt @@ -0,0 +1,19 @@ +package `in`.testpress.testpress.util + +import `in`.testpress.testpress.TestpressServiceProvider +import `in`.testpress.testpress.network.ProfileDetailRepository +import `in`.testpress.testpress.ui.ProfileDetailsViewModel +import android.app.Activity +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import java.lang.IllegalArgumentException + +class ProfileDetailViewModelFactory(private val activity: Activity, val serviceProvider: TestpressServiceProvider): ViewModelProvider.Factory { + override fun create(modelClass: Class): T { + if (modelClass.isAssignableFrom(ProfileDetailsViewModel::class.java)) { + return ProfileDetailsViewModel(ProfileDetailRepository(serviceProvider, activity)) as T + } + + throw IllegalArgumentException("Wrong Parameters") + } +} \ No newline at end of file