ソースを参照

refactoring auth feature

MrOzOn 5 年 前
コミット
62675be067

+ 10 - 0
core_api/src/main/java/com/mrozon/core_api/network/model/LoginResponse.kt

@@ -1,6 +1,7 @@
 package com.mrozon.core_api.network.model
 
 import com.mrozon.core_api.db.model.UserDb
+import com.mrozon.core_api.entity.User
 
 data class LoginResponse(
     val email: String,
@@ -18,4 +19,13 @@ fun LoginResponse.toUserDb(): UserDb {
         lastname = last_name,
         token = token
     )
+}
+
+fun LoginResponse.toUser(): User {
+    return User(
+        id = user_id.toLong(),
+        email = email,
+        firstname = first_name,
+        lastname = last_name
+    )
 }

+ 15 - 1
core_api/src/main/java/com/mrozon/core_api/network/model/RegisterResponse.kt

@@ -1,5 +1,10 @@
 package com.mrozon.core_api.network.model
 
+import com.mrozon.core_api.entity.Gender
+import com.mrozon.core_api.entity.Person
+import com.mrozon.core_api.entity.User
+import com.mrozon.utils.extension.toSimpleDate
+
 data class RegisterResponse(
     val email: String,
     val first_name: String,
@@ -7,4 +12,13 @@ data class RegisterResponse(
     val last_login: Any,
     val last_name: String,
     val username: String
-)
+)
+
+fun RegisterResponse.toUser(): User {
+    return User(
+        id = id.toLong(),
+        email = email,
+        firstname = first_name,
+        lastname = last_name
+    )
+}

+ 6 - 0
feature_auth/src/main/java/com/mrozon/feature_auth/data/UserAuthRemoteDataSource.kt

@@ -11,8 +11,14 @@ class UserAuthRemoteDataSource @Inject constructor(private val service: HealthDi
     suspend fun loginUser(userName: String, userPsw: String)
             = getResult { service.loginUser(LoginRequest(username = userName, password = userPsw)) }
 
+    suspend fun loginUser(loginRequest: LoginRequest)
+            = getResult { service.loginUser(loginRequest) }
+
     suspend fun registerUser(email: String, password: String, firstName: String, lastName: String)
             = getResult { service.registerUser(RegisterRequest(email = email, username = email,
                 password = password, first_name = firstName, last_name = lastName )) }
 
+    suspend fun registerUser(registerRequest: RegisterRequest)
+            = getResult { service.registerUser(registerRequest) }
+
 }

+ 49 - 0
feature_auth/src/main/java/com/mrozon/feature_auth/data/UserAuthRepository.kt

@@ -0,0 +1,49 @@
+package com.mrozon.feature_auth.data
+
+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.*
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flow
+import javax.inject.Inject
+import javax.inject.Singleton
+import com.mrozon.utils.network.Result
+import com.mrozon.utils.network.Result.Companion.error
+import com.mrozon.utils.network.Result.Companion.loading
+import com.mrozon.utils.network.Result.Companion.success
+
+@Singleton
+class UserAuthRepository @Inject constructor(private val userAuthRemoteDataSource: UserAuthRemoteDataSource,
+                                        private val dao: HealthDiaryDao
+
+) {
+
+    fun registerUser(user: User, password: String): Flow<Result<User>> {
+        return flow {
+            emit(loading())
+            val request = RegisterRequest(email = user.email,
+                first_name = user.firstname, last_name = user.lastname, password = password, username = user.email)
+            val response = userAuthRemoteDataSource.registerUser(request)
+            if (response.status == Result.Status.SUCCESS) {
+                emit(success(response.data!!.toUser()))
+            } else if (response.status == Result.Status.ERROR) {
+                emit(error(response.message!!))
+            }
+        }
+    }
+
+    fun loginUser(userName: String, password: String): Flow<Result<User>> {
+        return flow {
+            emit(loading())
+            val request = LoginRequest(username = userName, password = password)
+            val response = userAuthRemoteDataSource.loginUser(request)
+            if (response.status == Result.Status.SUCCESS) {
+                dao.insertUser(response.data!!.toUserDb())
+                emit(success(response.data!!.toUser()))
+            } else if (response.status == Result.Status.ERROR) {
+                emit(error(response.message!!))
+            }
+        }
+    }
+}

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

@@ -2,21 +2,12 @@ package com.mrozon.feature_auth.presentation
 
 import android.content.Context
 import android.os.Bundle
-import android.text.Editable
-import android.text.TextWatcher
 import android.view.View
-import android.view.View.INVISIBLE
-import android.view.View.VISIBLE
-import androidx.core.widget.addTextChangedListener
-import androidx.core.widget.doOnTextChanged
-import androidx.fragment.app.Fragment
 import androidx.fragment.app.viewModels
 import androidx.lifecycle.Observer
 import androidx.lifecycle.ViewModelProvider
 import androidx.navigation.fragment.findNavController
-import androidx.navigation.fragment.navArgs
 import com.mrozon.core_api.navigation.LoginNavigator
-import com.mrozon.core_api.navigation.SplashNavigator
 import com.mrozon.feature_auth.R
 import com.mrozon.feature_auth.databinding.FragmentLoginBinding
 import com.mrozon.feature_auth.di.LoginFragmentComponent
@@ -24,10 +15,9 @@ import com.mrozon.utils.base.BaseFragment
 import com.mrozon.utils.extension.hideKeyboard
 import com.mrozon.utils.extension.offer
 import com.mrozon.utils.extension.visible
-import kotlinx.android.synthetic.main.fragment_login.*
+import com.mrozon.utils.network.Result
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.FlowPreview
-import timber.log.Timber
 import javax.inject.Inject
 
 class LoginFragment : BaseFragment<FragmentLoginBinding>() {
@@ -58,7 +48,7 @@ class LoginFragment : BaseFragment<FragmentLoginBinding>() {
 
         binding?.btnLogin?.setOnClickListener {
             hideKeyboard()
-            viewModel.loginUser(etUserName.text.toString().trim(),etUserPassword.text.toString().trim())
+            viewModel.loginUser()
         }
 
         binding?.btnRegistration?.setOnClickListener {
@@ -78,22 +68,24 @@ class LoginFragment : BaseFragment<FragmentLoginBinding>() {
             }
         })
 
-        viewModel.progress.observe(viewLifecycleOwner, Observer { progress ->
-            binding?.progressBar?.visible(progress)
-            binding?.btnLogin?.isEnabled = !progress && viewModel.enableLogin.value?:false
-            binding?.btnRegistration?.isEnabled = !progress
-        })
-
-        viewModel.error.observe(viewLifecycleOwner, Observer {error ->
-            if(error!=null)
-                showError(error) {}
-        })
-
-        viewModel.showPersons.observe(viewLifecycleOwner, Observer { showPersons ->
-            if(showPersons) {
-                navigator.navigateToListPerson(findNavController())
+        viewModel.loggedUser.observe(viewLifecycleOwner, Observer { result ->
+            if(result!=null){
+                when (result.status) {
+                    Result.Status.LOADING -> {
+                        binding?.progressBar?.visible(true)
+                    }
+                    Result.Status.SUCCESS -> {
+                        binding?.progressBar?.visible(false)
+                        navigator.navigateToListPerson(findNavController())
+                    }
+                    Result.Status.ERROR -> {
+                        binding?.progressBar?.visible(false)
+                        showError(result.message!!)
+                    }
+                }
             }
         })
+
     }
 
 }

+ 17 - 36
feature_auth/src/main/java/com/mrozon/feature_auth/presentation/LoginFragmentViewModel.kt

@@ -6,10 +6,13 @@ import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.viewModelScope
 import com.mrozon.core_api.db.HealthDiaryDao
 import com.mrozon.core_api.db.model.UserDb
+import com.mrozon.core_api.entity.User
 import com.mrozon.core_api.mapper.UserToUserDbMapper
 import com.mrozon.core_api.network.model.toUserDb
 import com.mrozon.feature_auth.data.UserAuthRemoteDataSource
+import com.mrozon.feature_auth.data.UserAuthRepository
 import com.mrozon.utils.base.BaseViewModel
+import com.mrozon.utils.network.Result
 //import com.mrozon.utils.extension.asFlow
 import kotlinx.coroutines.*
 import kotlinx.coroutines.channels.ConflatedBroadcastChannel
@@ -21,21 +24,12 @@ import timber.log.Timber
 import javax.inject.Inject
 
 class LoginFragmentViewModel @Inject constructor(
-    private val userAuthRemoteDataSource: UserAuthRemoteDataSource,
-    private val healthDiaryDao: HealthDiaryDao
+    private val repository: UserAuthRepository
 ): BaseViewModel() {
 
-    private val _progress = MutableLiveData<Boolean>(false)
-    val progress: LiveData<Boolean>
-        get() = _progress
-
-    private val _showPersons = MutableLiveData<Boolean>(false)
-    val showPersons: LiveData<Boolean>
-        get() = _showPersons
-
-    private val _error = MutableLiveData<String?>()
-    val error: LiveData<String?>
-        get() = _error
+    private val _loggedUser = MutableLiveData<Result<User>?>(null)
+    val loggedUser: LiveData<Result<User>?>
+        get() = _loggedUser
 
     @ExperimentalCoroutinesApi
     val userNameChannel = ConflatedBroadcastChannel<String>()
@@ -68,31 +62,18 @@ class LoginFragmentViewModel @Inject constructor(
     private fun validateInputData(pair: Pair<String,String>) =
         (EMAIL_ADDRESS.matcher(pair.first).matches()) and (pair.second.isNotEmpty())
 
-    fun loginUser(userName: String, userPsw: String) {
-        _progress.value = true
-        CoroutineScope(Dispatchers.IO).launch(getJobErrorHandler()) {
-            val response = userAuthRemoteDataSource.loginUser(userName, userPsw)
-                if (response.status == com.mrozon.utils.network.Result.Status.SUCCESS) {
-                    val result = response.data
-                    healthDiaryDao.insertUser(result?.toUserDb()!!)
-                    Timber.d(result.token)
-                    withContext(Dispatchers.Main) {
-                        _showPersons.value = true
-                        _progress.value = false
-                    }
-                } else if (response.status == com.mrozon.utils.network.Result.Status.ERROR) {
-                    Timber.e(response.message!!)
-                    withContext(Dispatchers.Main) {
-                        _progress.value = false
-                        _error.value = response.message!!
-                    }
-                }
 
+    @ExperimentalCoroutinesApi
+    fun loginUser(){
+        val userName = userNameChannel.value
+        val psw = userPasswordChannel.value
+        viewModelScope.launch(Dispatchers.IO){
+            repository.loginUser(userName,psw).collect {
+                withContext(Dispatchers.Main) {
+                    _loggedUser.value = it
+                }
+            }
         }
-    }
 
-    private fun getJobErrorHandler() = CoroutineExceptionHandler { _, e ->
-        Timber.e(e)
-        _error.value = e.message
     }
 }

+ 18 - 12
feature_auth/src/main/java/com/mrozon/feature_auth/presentation/RegistrationFragment.kt

@@ -17,6 +17,7 @@ import com.mrozon.utils.base.BaseFragment
 import com.mrozon.utils.extension.hideKeyboard
 import com.mrozon.utils.extension.offer
 import com.mrozon.utils.extension.visible
+import com.mrozon.utils.network.Result
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.FlowPreview
 import timber.log.Timber
@@ -64,22 +65,27 @@ class RegistrationFragment: BaseFragment<FragmentRegistrationBinding>() {
     @FlowPreview
     override fun subscribeUi() {
 
-        viewModel.progress.observe(viewLifecycleOwner, Observer { progress ->
-            binding?.progressBar?.visible(progress)
-            binding?.btnRegistrationCancel?.isEnabled = !progress
-            Timber.d("progress=${progress} and valid=${viewModel.validateData.value==ValidateDataError.OK}")
-            binding?.btnRegistration?.isEnabled = (!progress) and (viewModel.validateData.value==ValidateDataError.OK)
-        })
-
         viewModel.error.observe(viewLifecycleOwner, Observer {error ->
             if(error!=null)
                 showError(error) {}
         })
 
-        viewModel.registered.observe(viewLifecycleOwner, Observer { registeredUser ->
-            if(registeredUser!=null) {
-                showInfo(getString(R.string.userRegistered)) {
-                    navigator.navigateToLoginUser(findNavController(), registeredUser)
+        viewModel.registeredUser.observe(viewLifecycleOwner, Observer { result ->
+            if(result!=null){
+                when (result.status) {
+                    Result.Status.LOADING -> {
+                        binding?.progressBar?.visible(true)
+                    }
+                    Result.Status.SUCCESS -> {
+                        binding?.progressBar?.visible(false)
+                        showInfo(getString(R.string.userRegistered)) {
+                                navigator.navigateToLoginUser(findNavController(), result.data?.email?:"")
+                            }
+                    }
+                    Result.Status.ERROR -> {
+                        binding?.progressBar?.visible(false)
+                        showError(result.message!!)
+                    }
                 }
             }
         })
@@ -93,7 +99,7 @@ class RegistrationFragment: BaseFragment<FragmentRegistrationBinding>() {
             binding?.etLastName?.error = null
             when (it) {
                 ValidateDataError.OK -> {
-                    binding?.btnRegistration?.isEnabled = true and !(viewModel.progress.value!!)
+                    binding?.btnRegistration?.isEnabled = true //and !(viewModel.progress.value!!)
                 }
                 ValidateDataError.INCORRECT_EMAIL -> {
                     binding?.etUserName?.error = getString(R.string.uncorrect_email)

+ 12 - 34
feature_auth/src/main/java/com/mrozon/feature_auth/presentation/RegistrationFragmentViewModel.kt

@@ -7,10 +7,14 @@ import androidx.lifecycle.Transformations
 import androidx.lifecycle.viewModelScope
 import com.mrozon.core_api.db.HealthDiaryDao
 import com.mrozon.core_api.db.model.UserDb
+import com.mrozon.core_api.entity.Person
+import com.mrozon.core_api.entity.User
 import com.mrozon.core_api.mapper.UserToUserDbMapper
 import com.mrozon.core_api.network.model.toUserDb
 import com.mrozon.feature_auth.data.UserAuthRemoteDataSource
+import com.mrozon.feature_auth.data.UserAuthRepository
 import com.mrozon.utils.base.BaseViewModel
+import com.mrozon.utils.network.Result
 //import com.mrozon.utils.extension.asFlow
 import kotlinx.coroutines.*
 import kotlinx.coroutines.channels.ConflatedBroadcastChannel
@@ -22,21 +26,16 @@ import timber.log.Timber
 import javax.inject.Inject
 
 class RegistrationFragmentViewModel @Inject constructor(
-    private val userAuthRemoteDataSource: UserAuthRemoteDataSource,
-    private val healthDiaryDao: HealthDiaryDao
+    private val repository: UserAuthRepository
 ): BaseViewModel() {
 
-    private val _progress = MutableLiveData<Boolean>(false)
-    val progress: LiveData<Boolean>
-        get() = _progress
-
     private val _error = MutableLiveData<String?>()
     val error: LiveData<String?>
         get() = _error
 
-    private val _registered = MutableLiveData<String?>()
-    val registered: LiveData<String?>
-        get() = _registered
+    private val _registeredUser = MutableLiveData<Result<User>?>(null)
+    val registeredUser: LiveData<Result<User>?>
+        get() = _registeredUser
 
     @ExperimentalCoroutinesApi
     val emailChannel = ConflatedBroadcastChannel<String>()
@@ -95,38 +94,17 @@ class RegistrationFragmentViewModel @Inject constructor(
 
     @ExperimentalCoroutinesApi
     fun registerUser() {
-        val email = emailChannel.value
         val psw = passwordChannel.value
-        val firstName = firstNameChannel.value
-        val lastName = lastNameChannel.value
-        _progress.value = true
-        CoroutineScope(Dispatchers.IO).launch(getJobErrorHandler()) {
-            val response = userAuthRemoteDataSource.registerUser(
-                email = email,
-                password = psw,
-                lastName = lastName,
-                firstName = firstName
-            )
-            if (response.status == com.mrozon.utils.network.Result.Status.SUCCESS) {
-                withContext(Dispatchers.Main) {
-                    _progress.value = false
-                    _registered.value = response.data?.username
-                }
-            } else if (response.status == com.mrozon.utils.network.Result.Status.ERROR) {
-                Timber.e(response.message!!)
+        val user = User(email = emailChannel.value, firstname = firstNameChannel.value, lastname = lastNameChannel.value)
+        viewModelScope.launch(Dispatchers.IO) {
+            repository.registerUser(user,psw).collect {
                 withContext(Dispatchers.Main) {
-                    _progress.value = false
-                    _error.value = response.message!!
+                    _registeredUser.value = it
                 }
             }
-
         }
     }
 
-    private fun getJobErrorHandler() = CoroutineExceptionHandler { _, e ->
-        Timber.e(e)
-        _error.value = e.message
-    }
 }
 
 enum class ValidateDataError(val code: Int) {

+ 2 - 0
feature_auth/src/main/res/layout/fragment_login.xml

@@ -90,6 +90,8 @@
                 android:layout_width="128dp"
                 android:layout_height="128dp"
                 android:indeterminate="true"
+                android:visibility="invisible"
+                tools:visibility="visible"
                 app:layout_constraintBottom_toBottomOf="parent"
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintStart_toStartOf="parent"

+ 2 - 0
feature_auth/src/main/res/layout/fragment_registration.xml

@@ -136,6 +136,8 @@
                 android:layout_width="128dp"
                 android:layout_height="128dp"
                 android:indeterminate="true"
+                android:visibility="invisible"
+                tools:visibility="visible"
                 app:layout_constraintBottom_toBottomOf="parent"
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintStart_toStartOf="parent"

+ 0 - 1
feature_auth/src/main/res/values/strings.xml

@@ -1,5 +1,4 @@
 <resources>
-    <!-- TODO: Remove or change this placeholder text -->
     <string name="hello_blank_fragment">Hello blank fragment</string>
     <string name="etUsername">Type Your e-mail</string>
     <string name="etUserPassword">Type Your password</string>

+ 0 - 1
feature_person/src/main/res/values/strings.xml

@@ -1,5 +1,4 @@
 <resources>
-    <!-- TODO: Remove or change this placeholder text -->
     <string name="hello_blank_fragment">Hello blank fragment</string>
     <string name="ivGender">gender\'s person</string>
     <string name="add_person">Add person</string>

+ 0 - 1
feature_splash/src/main/res/values/strings.xml

@@ -1,6 +1,5 @@
 <resources>
 
-    <!-- TODO: Remove or change this placeholder text -->
     <string name="hello_blank_fragment">Hello blank fragment</string>
     <string name="ivLogo">Image logo</string>
     <string name="tvLogoStatus">Loading profile...</string>