From ff0930a91d62516ea278d462e647c14bd42989ca Mon Sep 17 00:00:00 2001 From: Iván Ávalos Date: Fri, 14 Jan 2022 23:01:39 -0600 Subject: Refactored even more session management code into SessionController --- .../mx/trackermap/TrackerMap/android/TrackerApp.kt | 4 +- .../TrackerMap/android/session/LoginFragment.kt | 12 ++--- .../TrackerMap/android/session/LoginViewModel.kt | 14 ++--- .../android/session/UserInformationActivity.kt | 40 +++++++------- .../android/session/UserInformationViewModel.kt | 62 ++++++++++++++++------ .../TrackerMap/controllers/SessionController.kt | 22 ++++++++ 6 files changed, 100 insertions(+), 54 deletions(-) diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt index a9d4a8b..632b29a 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt @@ -40,12 +40,12 @@ open class TrackerApp : Application() { factory { GeofencesController(get()) } factory { ReportController(get(), get()) } - viewModel { LoginViewModel(get()) } + viewModel { LoginViewModel() } viewModel { UnitInformationViewModel(get()) } viewModel { UnitCommandsViewModel(get()) } viewModel { UnitsViewModel(get()) } viewModel { UnitReportsViewModel(get()) } - viewModel { UserInformationViewModel(get()) } + viewModel { UserInformationViewModel() } } startKoin { diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt index fa61d53..5071520 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt @@ -60,14 +60,11 @@ class LoginFragment : Fragment() { } private fun setupEvents() { - binding.usernameEditText.doAfterTextChanged { - loginViewModel.email.value = it.toString() - } - binding.passwordEditText.doAfterTextChanged { - loginViewModel.password.value = it.toString() - } binding.signinButton.setOnClickListener { - loginViewModel.login() + loginViewModel.login( + binding.usernameEditText.text.toString(), + binding.passwordEditText.text.toString() + ) } } @@ -95,6 +92,7 @@ class LoginFragment : Fragment() { startActivity(intent) activity.finish() } + else -> {} } } } diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginViewModel.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginViewModel.kt index 2590504..1585970 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginViewModel.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginViewModel.kt @@ -15,15 +15,10 @@ import org.koin.core.component.KoinComponent import org.koin.core.component.inject @DelicateCoroutinesApi -class LoginViewModel( - savedStateHandle: SavedStateHandle -) : ViewModel(), KoinComponent { +class LoginViewModel : ViewModel(), KoinComponent { private val sessionController: SessionController by inject() - val email: MutableLiveData = savedStateHandle.getLiveData("user", "") - val password: MutableLiveData = savedStateHandle.getLiveData("password", "") - private val loginStateEmitter = EventEmitter() val loginState: EventSource = loginStateEmitter @@ -45,10 +40,7 @@ class LoginViewModel( sessionController.restoreSession() } - fun login() { - sessionController.login(SessionBody( - email = email.value!!, - password = password.value!! - )) + fun login(email: String, password: String) { + sessionController.login(SessionBody(email, password)) } } \ No newline at end of file diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/UserInformationActivity.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/UserInformationActivity.kt index cda8072..f384173 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/UserInformationActivity.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/UserInformationActivity.kt @@ -7,12 +7,16 @@ import android.os.Bundle import android.view.View import android.widget.Toast import androidx.appcompat.app.AppCompatActivity -import androidx.core.app.NavUtils +import com.zhuinden.liveevent.observe +import kotlinx.coroutines.DelicateCoroutinesApi import mx.trackermap.TrackerMap.android.R import mx.trackermap.TrackerMap.android.databinding.UserInformationActivityBinding import mx.trackermap.TrackerMap.client.models.User +import mx.trackermap.TrackerMap.controllers.ReportController +import mx.trackermap.TrackerMap.controllers.SessionController import org.koin.androidx.viewmodel.ext.android.viewModel +@DelicateCoroutinesApi class UserInformationActivity : AppCompatActivity() { private var _binding: UserInformationActivityBinding? = null @@ -45,19 +49,29 @@ class UserInformationActivity : AppCompatActivity() { } private fun setupObservers() { - userInformationViewModel.userInformation.observe(this) { userInformation -> + userInformationViewModel.loginState.observe(this) { userInformation -> when (userInformation) { - UserInformationViewModel.InformationState.Loading -> setLoading(true) - UserInformationViewModel.InformationState.Failure -> failure() - is UserInformationViewModel.InformationState.Success -> display(userInformation.user) - UserInformationViewModel.InformationState.Signout -> signOut() + SessionController.LoginState.Loading -> setLoading(true) + SessionController.LoginState.Failure -> failure() + SessionController.LoginState.SignOut -> signOut() + else -> {} + } + } + userInformationViewModel.user.observe(this) { user -> + setLoading(false) + binding.apply { + usernameInfo.text = user.name ?: "" + emailInfo.text = user.email ?: "" + idInfo.text = "${user.id ?: "--"}" + deviceLimitInfo.text = "${user.deviceLimit ?: "--"}" + adminInfo.text = "${user.administrator}" } } } private fun setupEvents() { binding.backButton.setOnClickListener { onBackPressed() } - binding.signoutButton.setOnClickListener { userInformationViewModel.signout() } + binding.signoutButton.setOnClickListener { userInformationViewModel.signOut() } binding.sourceCodeButton.setOnClickListener { openURL(getString(R.string.app_source_code_url)) } @@ -77,18 +91,6 @@ class UserInformationActivity : AppCompatActivity() { Toast.makeText(this, "Something went wrong...", Toast.LENGTH_LONG).show() } - private fun display(user: User) { - setLoading(false) - - binding.apply { - usernameInfo.text = user.name ?: "" - emailInfo.text = user.email ?: "" - idInfo.text = "${user.id ?: "--"}" - deviceLimitInfo.text = "${user.deviceLimit ?: "--"}" - adminInfo.text = "${user.administrator}" - } - } - private fun openURL(url: String) { val uri = Uri.parse(url) val intent = Intent(Intent.ACTION_VIEW, uri) diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/UserInformationViewModel.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/UserInformationViewModel.kt index b2379fc..607f4e5 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/UserInformationViewModel.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/UserInformationViewModel.kt @@ -1,44 +1,76 @@ package mx.trackermap.TrackerMap.android.session import android.util.Log +import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.zhuinden.eventemitter.EventEmitter +import com.zhuinden.eventemitter.EventSource +import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch import mx.trackermap.TrackerMap.client.apis.SessionApi import mx.trackermap.TrackerMap.client.models.User +import mx.trackermap.TrackerMap.controllers.SessionController +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject -class UserInformationViewModel(private val sessionApi: SessionApi) : ViewModel() { +@DelicateCoroutinesApi +class UserInformationViewModel : ViewModel(), KoinComponent { - sealed class InformationState { - object Loading: InformationState() - object Failure: InformationState() - class Success(val user: User) : InformationState() - object Signout: InformationState() + private val sessionController: SessionController by inject() + + init { + Log.d("UserInformationVM", "Initializing User Information View Model") } - var userInformation = MutableLiveData(InformationState.Loading) + private val _user = MutableLiveData() + val user: LiveData get() = _user + + private val loginStateEmitter = EventEmitter() + val loginState: EventSource = loginStateEmitter init { - Log.d("UserInformationVM", "Initializing User Information View Model") + viewModelScope.launch { + setupLoginStateObserver() + } + viewModelScope.launch { + setupUserObserver() + } + } + + private suspend fun setupLoginStateObserver() { + sessionController.loginStateFlow.collect { + it?.let { + loginStateEmitter.emit(it) + } + } + } + + private suspend fun setupUserObserver() { + sessionController.userFlow.collect { + it?.let { + _user.postValue(it) + } + } } fun fetchUserInfo() { viewModelScope.launch { - userInformation.postValue(InformationState.Loading) + loginStateEmitter.emit(SessionController.LoginState.Loading) try { - userInformation.postValue(InformationState.Success(sessionApi.sessionGet())) + sessionController.getSession() + loginStateEmitter.emit(SessionController.LoginState.Success) } catch (e: Exception) { - userInformation.postValue(InformationState.Failure) + loginStateEmitter.emit(SessionController.LoginState.Failure) } } } - fun signout() { + fun signOut() { viewModelScope.launch { - userInformation.postValue(InformationState.Loading) - sessionApi.sessionDelete() - userInformation.postValue(InformationState.Signout) + sessionController.logout() } } } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/SessionController.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/SessionController.kt index 8f5ac56..ed65824 100644 --- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/SessionController.kt +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/SessionController.kt @@ -19,11 +19,25 @@ class SessionController( object PasswordMissing : LoginState() object Failure : LoginState() object Success : LoginState() + object SignOut : LoginState() } val loginStateFlow = MutableStateFlow(null) val userFlow = MutableStateFlow(null) + fun getSession() { + loginStateFlow.value = LoginState.Loading + GlobalScope.launch { + try { + userFlow.value = sessionApi.sessionGet() + Log.d("LoginViewModel", userFlow.value.toString()) + loginStateFlow.value = LoginState.Success + } catch (e: Exception) { + loginStateFlow.value = LoginState.Failure + } + } + } + fun restoreSession() { loginStateFlow.value = LoginState.Loading GlobalScope.launch { @@ -62,4 +76,12 @@ class SessionController( } } } + + fun logout() { + GlobalScope.launch { + loginStateFlow.value = LoginState.Loading + sessionApi.sessionDelete() + loginStateFlow.value = LoginState.SignOut + } + } } \ No newline at end of file -- cgit v1.2.3