diff --git a/app/build.gradle b/app/build.gradle index fc4ece95e..3f1eea8f8 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.95' @@ -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/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..61711ca82 --- /dev/null +++ b/app/src/main/java/in/testpress/testpress/network/ProfileDetailRepository.kt @@ -0,0 +1,29 @@ +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(): MutableLiveData { + 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() + return profileDetails + } +} \ No newline at end of file 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/java/in/testpress/testpress/ui/ProfileDetailsViewModel.kt b/app/src/main/java/in/testpress/testpress/ui/ProfileDetailsViewModel.kt new file mode 100644 index 000000000..a8916cca9 --- /dev/null +++ b/app/src/main/java/in/testpress/testpress/ui/ProfileDetailsViewModel.kt @@ -0,0 +1,13 @@ +package `in`.testpress.testpress.ui + +import `in`.testpress.testpress.models.ProfileDetails +import `in`.testpress.testpress.network.ProfileDetailRepository +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel + +class ProfileDetailsViewModel(private val profileDetailRepository: ProfileDetailRepository) : ViewModel() { + + 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 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 + 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