Pārlūkot izejas kodu

add logout and navigate to login for MainActivity

MrOzOn 5 gadi atpakaļ
vecāks
revīzija
72a4f79c5b

+ 3 - 5
app/src/main/java/com/mrozon/healthdiary/di/main/MainActivityModule.kt

@@ -2,15 +2,13 @@ package com.mrozon.healthdiary.di.main
 
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
-import com.mrozon.core_api.db.DatabaseProvider
 import com.mrozon.core_api.db.HealthDiaryDao
 import com.mrozon.core_api.mapper.UserToUserDbMapper
 import com.mrozon.core_api.viewmodel.ViewModelKey
 import com.mrozon.feature_splash.di.DaggerViewModelFactory
-import com.mrozon.feature_splash.presentation.SplashFragmentViewModel
 import com.mrozon.healthdiary.presentation.main.MainActivityViewModel
-import com.mrozon.healthdiary.repository.LocalUser
-import com.mrozon.healthdiary.repository.LocalUserImp
+import com.mrozon.healthdiary.repository.LocalUserDataSource
+import com.mrozon.healthdiary.repository.LocalUserDataSourceImp
 import dagger.Binds
 import dagger.Module
 import dagger.Provides
@@ -36,7 +34,7 @@ abstract class MainActivityModule {
         fun provideLocalUser(
             healthDiaryDao: HealthDiaryDao,
             mapper: UserToUserDbMapper
-        ): LocalUser = LocalUserImp(healthDiaryDao, mapper)
+        ): LocalUserDataSource = LocalUserDataSourceImp(healthDiaryDao, mapper)
     }
 
 }

+ 29 - 10
app/src/main/java/com/mrozon/healthdiary/presentation/main/MainActivity.kt

@@ -1,7 +1,10 @@
 package com.mrozon.healthdiary.presentation.main
 
+import android.annotation.SuppressLint
 import android.os.Bundle
 import android.view.View
+import android.widget.ImageView
+import android.widget.TextView
 import androidx.activity.viewModels
 import androidx.appcompat.app.AppCompatActivity
 import androidx.core.view.GravityCompat
@@ -28,27 +31,22 @@ import com.mrozon.utils.base.BaseActivity
 import timber.log.Timber
 import javax.inject.Inject
 
-class MainActivity : AppCompatActivity(){ //BaseActivity<ActivityMainBinding>() {
+class MainActivity : BaseActivity<ActivityMainBinding>() {
 
     @Inject
     lateinit var viewModelFactory: ViewModelProvider.Factory
 
     private val viewModel by viewModels<MainActivityViewModel> { viewModelFactory }
 
-//    override fun getLayoutId(): Int = R.layout.activity_main
+    override fun getLayoutId(): Int = R.layout.activity_main
 
     private lateinit var drawerLayout: DrawerLayout
     private lateinit var appBarConfiguration: AppBarConfiguration
     private lateinit var navController: NavController
 
-    private lateinit var binding: ActivityMainBinding
-
-
     override fun onCreate(savedInstanceState: Bundle?) {
         initDI()
         super.onCreate(savedInstanceState)
-        binding = DataBindingUtil.setContentView(this,
-            R.layout.activity_main)
         initNavigation()
         subscribeUi()
     }
@@ -79,18 +77,39 @@ class MainActivity : AppCompatActivity(){ //BaseActivity<ActivityMainBinding>()
         }
     }
 
-    fun subscribeUi() {
-        viewModel.currentUser.observe(this, Observer {
-            if(it==null){
+    override fun subscribeUi() {
+
+        viewModel.cleared.observe(this, Observer { cleared ->
+            if(cleared){
+                navController.navigate(R.id.action_global_loginFragment)
+            }
+        })
+
+        viewModel.currentUser.observe(this, Observer { user ->
+            val headerView = binding.navView.getHeaderView(0)
+            val tvUserEmail = headerView.findViewById<TextView>(R.id.tvUserEmail)
+            val tvUserName = headerView.findViewById<TextView>(R.id.tvUserName)
+            val ivLogout = headerView.findViewById<ImageView>(R.id.ivLogout)
+
+            if(user==null){
                 Timber.d("user is null")
                 supportActionBar?.hide()
                 drawerLayout.setDrawerLockMode(LOCK_MODE_LOCKED_CLOSED)
+                ivLogout.setOnClickListener(null)
             }
             else
             {
                 Timber.d("user not null")
                 supportActionBar?.show()
                 drawerLayout.setDrawerLockMode(LOCK_MODE_UNLOCKED)
+                tvUserEmail.text = user.email
+                tvUserName.text = "${user.firstname}  ${user.lastname}"
+                ivLogout.setOnClickListener {
+                    if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
+                        drawerLayout.closeDrawer(GravityCompat.START)
+                    }
+                    viewModel.logoutUser(user)
+                }
             }
         })
     }

+ 23 - 4
app/src/main/java/com/mrozon/healthdiary/presentation/main/MainActivityViewModel.kt

@@ -3,14 +3,33 @@ package com.mrozon.healthdiary.presentation.main
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
-import com.mrozon.healthdiary.repository.LocalUser
-import com.mrozon.utils.base.BaseViewModel
+import com.mrozon.core_api.entity.User
+import com.mrozon.healthdiary.repository.LocalUserDataSource
+import kotlinx.coroutines.*
+import timber.log.Timber
 import javax.inject.Inject
 
 class MainActivityViewModel @Inject constructor(
-    private val localUser: LocalUser
+    private val localUserDataSource: LocalUserDataSource
 ): ViewModel() {
 
-    val currentUser = localUser.getLocalUser()
+    val currentUser = localUserDataSource.getLocalUser()
+
+    private val _cleared = MutableLiveData<Boolean>(false)
+    val cleared: LiveData<Boolean>
+        get() = _cleared
+
+    fun logoutUser(user: User) {
+        CoroutineScope(Dispatchers.IO).launch(getJobErrorHandler()) {
+            localUserDataSource.clearLocalUser(user)
+            withContext(Dispatchers.Main){
+                _cleared.value = true
+            }
+        }
+    }
+
+    private fun getJobErrorHandler() = CoroutineExceptionHandler { _, e ->
+        Timber.e(e)
+    }
 
 }

+ 3 - 1
app/src/main/java/com/mrozon/healthdiary/repository/LocalUser.kt → app/src/main/java/com/mrozon/healthdiary/repository/LocalUserDataSource.kt

@@ -3,7 +3,9 @@ package com.mrozon.healthdiary.repository
 import androidx.lifecycle.LiveData
 import com.mrozon.core_api.entity.User
 
-interface LocalUser {
+interface LocalUserDataSource {
 
     fun getLocalUser(): LiveData<User>
+
+    suspend fun clearLocalUser(user: User)
 }

+ 12 - 3
app/src/main/java/com/mrozon/healthdiary/repository/LocalUserImp.kt → app/src/main/java/com/mrozon/healthdiary/repository/LocalUserDataSourceImp.kt

@@ -2,16 +2,18 @@ package com.mrozon.healthdiary.repository
 
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.Transformations
-import com.mrozon.core_api.db.DatabaseProvider
 import com.mrozon.core_api.db.HealthDiaryDao
 import com.mrozon.core_api.entity.User
 import com.mrozon.core_api.mapper.UserToUserDbMapper
+import com.mrozon.core_api.network.model.toUserDb
+import kotlinx.coroutines.*
+import timber.log.Timber
 import javax.inject.Inject
 
-class LocalUserImp @Inject constructor(
+class LocalUserDataSourceImp @Inject constructor(
     private val healthDiaryDao: HealthDiaryDao,
     private val mapper: UserToUserDbMapper
-): LocalUser {
+): LocalUserDataSource {
 
     override fun getLocalUser(): LiveData<User> {
         val userDb = healthDiaryDao.getUser()
@@ -20,4 +22,11 @@ class LocalUserImp @Inject constructor(
         }
     }
 
+    override suspend fun clearLocalUser(user: User) {
+        val userDb = mapper.map(user)
+            userDb?.let {
+                healthDiaryDao.deleteUser(userDb)
+        }
+    }
+
 }

+ 5 - 0
app/src/main/res/drawable/ic_logout.xml

@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="@android:color/white"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M10.09,15.59L11.5,17l5,-5 -5,-5 -1.41,1.41L12.67,11H3v2h9.67l-2.58,2.59zM19,3H5c-1.11,0 -2,0.9 -2,2v4h2V5h14v14H5v-4H3v4c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2z"/>
+</vector>

+ 9 - 0
app/src/main/res/drawable/ic_userprofile.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="100dp"
+    android:height="100dp"
+    android:viewportWidth="100"
+    android:viewportHeight="100">
+  <path
+      android:pathData="M50,0C22.429,0 0,22.429 0,50C0,77.571 22.429,100 50,100C50.504,100 50.996,99.938 51.5,99.925L51.675,99.958C51.813,99.983 51.946,100 52.083,100C52.275,100 52.471,99.975 52.654,99.921L52.888,99.854C79.113,98.342 100,76.596 100,50C100,22.429 77.571,0 50,0ZM79.717,84.829C79.521,84.192 79.079,83.654 78.438,83.442L67.471,79.792C63.642,78.196 61.858,72.067 61.442,69.608C64.279,66.971 66.9,63.042 66.9,59.492C66.9,58.283 67.242,57.821 67.175,57.808C67.825,57.646 68.354,57.183 68.604,56.562C68.808,56.05 70.604,51.471 70.604,48.383C70.604,48.212 70.583,48.042 70.542,47.879C70.279,46.833 69.667,45.779 68.75,45.121V35.421C68.75,29.425 66.925,26.912 64.992,25.458C64.558,22.475 61.363,16.671 50,16.671C38.384,16.671 31.25,27.592 31.25,35.421V45.121C30.334,45.779 29.721,46.833 29.459,47.879C29.417,48.046 29.396,48.217 29.396,48.383C29.396,51.471 31.192,56.05 31.396,56.562C31.646,57.183 31.975,57.579 32.625,57.741C32.759,57.82 33.1,58.287 33.1,59.491C33.1,63.041 35.721,66.97 38.559,69.608C38.146,72.062 36.38,78.187 32.671,79.737L21.559,83.441C20.921,83.654 20.463,84.179 20.263,84.816C10.425,76.404 4.158,63.929 4.158,50C4.158,24.729 24.721,4.167 49.992,4.167C75.263,4.167 95.825,24.729 95.825,50C95.833,63.933 89.563,76.417 79.717,84.829Z"
+      android:fillColor="#000000"/>
+</vector>

+ 3 - 3
app/src/main/res/drawable/side_nav_bar.xml

@@ -2,8 +2,8 @@
     android:shape="rectangle">
     <gradient
         android:angle="135"
-        android:centerColor="#0091EA"
-        android:endColor="#3700B3"
-        android:startColor="#6200EE"
+        android:centerColor="#009688"
+        android:endColor="#00695C"
+        android:startColor="#4DB6AC"
         android:type="linear" />
 </shape>

+ 46 - 2
app/src/main/res/layout/view_nav_header.xml

@@ -1,8 +1,52 @@
 <?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="160dp"
     android:background="@drawable/side_nav_bar">
 
+    <ImageView
+        android:id="@+id/imageView"
+        android:layout_width="64dp"
+        android:layout_height="64dp"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="36dp"
+        android:alpha="0.6"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:srcCompat="@drawable/ic_userprofile" />
+
+    <TextView
+        android:id="@+id/tvUserName"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="8dp"
+        android:layout_marginEnd="8dp"
+        android:textColor="#FFFFFF"
+        app:layout_constraintEnd_toStartOf="@+id/ivLogout"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/imageView"
+        tools:text="Ivanov Ivan" />
+
+    <TextView
+        android:id="@+id/tvUserEmail"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:alpha="0.7"
+        android:textColor="#FFFFFF"
+        android:textStyle="bold"
+        app:layout_constraintStart_toStartOf="@+id/imageView"
+        app:layout_constraintTop_toBottomOf="@+id/tvUserName"
+        tools:text="mymail@ya.ru" />
+
+    <ImageView
+        android:id="@+id/ivLogout"
+        android:layout_width="32dp"
+        android:layout_height="32dp"
+        android:layout_marginEnd="16dp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="@+id/tvUserName"
+        app:srcCompat="@drawable/ic_logout" />
 </androidx.constraintlayout.widget.ConstraintLayout>

+ 1 - 1
app/src/main/res/navigation/nav_graph.xml

@@ -33,6 +33,6 @@
         <action
             android:id="@+id/action_registrationFragment_to_loginFragment"
             app:destination="@id/loginFragment" />
-    </fragment>
+    </fragment><action android:id="@+id/action_global_loginFragment" app:destination="@id/loginFragment"/>
 
 </navigation>

+ 4 - 4
core_api/src/main/java/com/mrozon/core_api/db/HealthDiaryDao.kt

@@ -1,10 +1,7 @@
 package com.mrozon.core_api.db
 
 import androidx.lifecycle.LiveData
-import androidx.room.Dao
-import androidx.room.Insert
-import androidx.room.OnConflictStrategy
-import androidx.room.Query
+import androidx.room.*
 import com.mrozon.core_api.db.model.UserDb
 
 @Dao
@@ -15,4 +12,7 @@ interface HealthDiaryDao {
 
     @Insert(onConflict = OnConflictStrategy.REPLACE)
     suspend fun insertUser(userDb: UserDb)
+
+    @Delete
+    suspend fun deleteUser(userDb: UserDb)
 }

+ 1 - 1
feature_auth/src/main/java/com/mrozon/feature_auth/presentation/LoginFragment.kt

@@ -51,9 +51,9 @@ class LoginFragment : BaseFragment<FragmentLoginBinding>() {
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
 
+        binding?.etUserName?.offer(viewModel.userNameChannel)
         binding?.etUserName?.setText(arguments?.getString("userName"))
 
-        binding?.etUserName?.offer(viewModel.userNameChannel)
         binding?.etUserPassword?.offer(viewModel.userPasswordChannel)
 
         binding?.btnLogin?.setOnClickListener {