From cc7cfcb2d65a1164f5b75ae4292ea9a099746038 Mon Sep 17 00:00:00 2001 From: Isidro Henoch Date: Wed, 12 Jan 2022 15:09:52 -0600 Subject: Adds the user information functionality - Displays the user information - Allows the user to sign out --- androidApp/src/main/AndroidManifest.xml | 3 + .../mx/trackermap/TrackerMap/android/TrackerApp.kt | 2 + .../android/session/UserInformationActivity.kt | 78 +++++++++++ .../android/session/UserInformationViewModel.kt | 44 ++++++ .../TrackerMap/android/units/UnitsActivity.kt | 28 +--- androidApp/src/main/res/layout/units_activity.xml | 135 ++++++++---------- .../main/res/layout/user_information_activity.xml | 156 +++++++++++++++++++++ androidApp/src/main/res/menu/navigation_menu.xml | 26 ---- androidApp/src/main/res/values/dimen.xml | 3 + androidApp/src/main/res/values/strings.xml | 8 ++ .../TrackerMap/client/apis/SessionApi.kt | 13 +- 11 files changed, 369 insertions(+), 127 deletions(-) create mode 100644 androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/UserInformationActivity.kt create mode 100644 androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/UserInformationViewModel.kt create mode 100644 androidApp/src/main/res/layout/user_information_activity.xml delete mode 100644 androidApp/src/main/res/menu/navigation_menu.xml diff --git a/androidApp/src/main/AndroidManifest.xml b/androidApp/src/main/AndroidManifest.xml index 5d56847..6501532 100644 --- a/androidApp/src/main/AndroidManifest.xml +++ b/androidApp/src/main/AndroidManifest.xml @@ -26,5 +26,8 @@ + \ No newline at end of file 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 1563534..808808a 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt @@ -6,6 +6,7 @@ import mx.trackermap.TrackerMap.android.details.commands.UnitCommandsViewModel import mx.trackermap.TrackerMap.android.details.information.UnitInformationViewModel import mx.trackermap.TrackerMap.android.details.reports.UnitReportsViewModel import mx.trackermap.TrackerMap.android.session.LoginViewModel +import mx.trackermap.TrackerMap.android.session.UserInformationViewModel import mx.trackermap.TrackerMap.android.units.UnitsViewModel import mx.trackermap.TrackerMap.client.apis.* import mx.trackermap.TrackerMap.controllers.GeofencesController @@ -40,6 +41,7 @@ class TrackerApp : Application() { viewModel { UnitCommandsViewModel(get()) } single { UnitsViewModel(get()) } viewModel { UnitReportsViewModel(get(), get()) } + viewModel { UserInformationViewModel(get()) } } startKoin { 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 new file mode 100644 index 0000000..da1c0d5 --- /dev/null +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/UserInformationActivity.kt @@ -0,0 +1,78 @@ +package mx.trackermap.TrackerMap.android.session + +import android.content.Intent +import android.os.Bundle +import android.view.View +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import mx.trackermap.TrackerMap.android.databinding.UserInformationActivityBinding +import mx.trackermap.TrackerMap.client.models.User +import org.koin.androidx.viewmodel.ext.android.viewModel + +class UserInformationActivity : AppCompatActivity() { + + private var _binding: UserInformationActivityBinding? = null + private val binding get() = _binding!! + private val userInformationViewModel: UserInformationViewModel by viewModel() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + _binding = UserInformationActivityBinding.inflate(layoutInflater) + setContentView(binding.root) + + initialize() + } + + private fun initialize() { + setupObservers() + setupEvents() + + userInformationViewModel.fetchUserInfo() + } + + private fun setupObservers() { + userInformationViewModel.userInformation.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() + } + } + } + + private fun setupEvents() { + binding.signoutButton.setOnClickListener { userInformationViewModel.signout() } + } + + private fun setLoading(isLoading: Boolean) { + binding.infoLoading.visibility = if (isLoading) View.VISIBLE else View.GONE + binding.userInfoCard.visibility = if (isLoading) View.GONE else View.VISIBLE + } + + private fun failure() { + setLoading(false) + + 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 signout() { + val intent = Intent(applicationContext, LoginActivity::class.java) + intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK + startActivity(intent) + finish() + } + +} \ No newline at end of file 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 new file mode 100644 index 0000000..b2379fc --- /dev/null +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/UserInformationViewModel.kt @@ -0,0 +1,44 @@ +package mx.trackermap.TrackerMap.android.session + +import android.util.Log +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.launch +import mx.trackermap.TrackerMap.client.apis.SessionApi +import mx.trackermap.TrackerMap.client.models.User + +class UserInformationViewModel(private val sessionApi: SessionApi) : ViewModel() { + + sealed class InformationState { + object Loading: InformationState() + object Failure: InformationState() + class Success(val user: User) : InformationState() + object Signout: InformationState() + } + + var userInformation = MutableLiveData(InformationState.Loading) + + init { + Log.d("UserInformationVM", "Initializing User Information View Model") + } + + fun fetchUserInfo() { + viewModelScope.launch { + userInformation.postValue(InformationState.Loading) + try { + userInformation.postValue(InformationState.Success(sessionApi.sessionGet())) + } catch (e: Exception) { + userInformation.postValue(InformationState.Failure) + } + } + } + + fun signout() { + viewModelScope.launch { + userInformation.postValue(InformationState.Loading) + sessionApi.sessionDelete() + userInformation.postValue(InformationState.Signout) + } + } +} \ No newline at end of file diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsActivity.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsActivity.kt index 409919a..7e5f162 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsActivity.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsActivity.kt @@ -1,5 +1,6 @@ package mx.trackermap.TrackerMap.android.units +import android.content.Intent import android.os.Bundle import android.util.Log import android.view.Gravity @@ -12,6 +13,8 @@ import mx.trackermap.TrackerMap.android.R import mx.trackermap.TrackerMap.android.databinding.UnitsActivityBinding import mx.trackermap.TrackerMap.android.devices.DevicesFragment import mx.trackermap.TrackerMap.android.map.UnitMapFragment +import mx.trackermap.TrackerMap.android.session.LoginActivity +import mx.trackermap.TrackerMap.android.session.UserInformationActivity import org.koin.androidx.viewmodel.ext.android.viewModel @DelicateCoroutinesApi @@ -38,28 +41,9 @@ class UnitsActivity : AppCompatActivity() { } private fun setupEvents() { - binding.drawerButton.setOnClickListener { - binding.drawerLayout.openDrawer(binding.navigationView) - } - binding.navigationView.setNavigationItemSelectedListener { - when (it.itemId) { - R.id.nav_account -> { - Toast.makeText(this, "Account button tapped!", Toast.LENGTH_SHORT).show() - binding.drawerLayout.closeDrawers() - false - } - R.id.nav_about -> { - Toast.makeText(this, "About button tapped!", Toast.LENGTH_SHORT).show() - binding.drawerLayout.closeDrawers() - false - } - R.id.nav_logout -> { - Toast.makeText(this, "Logout button tapped!", Toast.LENGTH_SHORT).show() - binding.drawerLayout.closeDrawers() - false - } - else -> false - } + binding.userButton.setOnClickListener { + val intent = Intent(applicationContext, UserInformationActivity::class.java) + startActivity(intent) } binding.displayModeToggle.setOnClickListener { unitsViewModel.toggleDisplayMode() diff --git a/androidApp/src/main/res/layout/units_activity.xml b/androidApp/src/main/res/layout/units_activity.xml index fb39ebe..bc8d94a 100644 --- a/androidApp/src/main/res/layout/units_activity.xml +++ b/androidApp/src/main/res/layout/units_activity.xml @@ -1,87 +1,74 @@ - - - - + android:layout_height="match_parent"> - + - - - + - + - + - + - + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/fab_margin" + android:layout_marginEnd="@dimen/fab_margin" + android:backgroundTint="@android:color/white" + app:borderWidth="0dp" + app:elevation="@dimen/fab_elevation" + app:fabSize="mini" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" + tools:ignore="ContentDescription" /> - \ No newline at end of file + \ No newline at end of file diff --git a/androidApp/src/main/res/layout/user_information_activity.xml b/androidApp/src/main/res/layout/user_information_activity.xml new file mode 100644 index 0000000..8bb994a --- /dev/null +++ b/androidApp/src/main/res/layout/user_information_activity.xml @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/androidApp/src/main/res/menu/navigation_menu.xml b/androidApp/src/main/res/menu/navigation_menu.xml deleted file mode 100644 index 2713776..0000000 --- a/androidApp/src/main/res/menu/navigation_menu.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/androidApp/src/main/res/values/dimen.xml b/androidApp/src/main/res/values/dimen.xml index 8acc9a3..25d0e98 100644 --- a/androidApp/src/main/res/values/dimen.xml +++ b/androidApp/src/main/res/values/dimen.xml @@ -20,4 +20,7 @@ 12dp 8dp + + + 8dp \ No newline at end of file diff --git a/androidApp/src/main/res/values/strings.xml b/androidApp/src/main/res/values/strings.xml index 13ac79d..6901a37 100644 --- a/androidApp/src/main/res/values/strings.xml +++ b/androidApp/src/main/res/values/strings.xml @@ -86,4 +86,12 @@ Text message received Driver changed Unknown event + + + Username + Email + Unique ID + Device Limit + Administrator + Sign out diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/SessionApi.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/SessionApi.kt index 4344de0..417a818 100644 --- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/SessionApi.kt +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/SessionApi.kt @@ -25,7 +25,6 @@ class SessionApi(basePath: kotlin.String = "https://demo.traccar.org/api") : Api * @return void */ suspend fun sessionDelete(): Unit { - val localVariableConfig = RequestConfig( RequestMethod.DELETE, "/session" @@ -35,7 +34,10 @@ class SessionApi(basePath: kotlin.String = "https://demo.traccar.org/api") : Api ) return when (response.responseType) { - ResponseType.Success -> Unit + ResponseType.Success -> { + val settings = Settings() + settings.remove(ACCESS_TOKEN_KEY) + } ResponseType.Informational -> TODO() ResponseType.Redirection -> TODO() ResponseType.ClientError -> throw ClientException( @@ -54,11 +56,12 @@ class SessionApi(basePath: kotlin.String = "https://demo.traccar.org/api") : Api * @return User */ @Suppress("UNCHECKED_CAST") - suspend fun sessionGet(token: kotlin.String? = null): User { - val localVariableQuery: MultiValueMap = mapOf("token" to listOf("$token")) + suspend fun sessionGet(token: String? = null): User { + val query: MutableMap> = mutableMapOf() + token?.let { query["userId"] = listOf(it) } val localVariableConfig = RequestConfig( RequestMethod.GET, - "/session", query = localVariableQuery + "/session", query = query ) val response = request( localVariableConfig -- cgit v1.2.3