Adding confirmation dialog for all type of sessions

This commit is contained in:
Maxime NATUREL 2022-09-29 10:27:13 +02:00
parent e47bf2b200
commit 082fa1e69e
5 changed files with 41 additions and 41 deletions

View File

@ -20,7 +20,7 @@ import im.vector.app.core.platform.VectorViewModelAction
sealed class SessionOverviewAction : VectorViewModelAction {
object VerifySession : SessionOverviewAction()
object SignoutSession : SessionOverviewAction()
object SignoutOtherSession : SessionOverviewAction()
object SsoAuthDone : SessionOverviewAction()
data class PasswordAuthDone(val password: String) : SessionOverviewAction()
object ReAuthCancelled : SessionOverviewAction()

View File

@ -28,6 +28,7 @@ import androidx.core.view.isVisible
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
import im.vector.app.core.date.VectorDateFormatter
@ -42,6 +43,7 @@ import im.vector.app.features.crypto.recover.SetupMode
import im.vector.app.features.settings.devices.v2.list.SessionInfoViewState
import im.vector.app.features.workers.signout.SignOutUiWorker
import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
import org.matrix.android.sdk.api.extensions.orFalse
import javax.inject.Inject
/**
@ -87,17 +89,12 @@ class SessionOverviewFragment :
navigator.open4SSetup(requireActivity(), SetupMode.PASSPHRASE_AND_NEEDED_SECRETS_RESET)
}
is SessionOverviewViewEvent.RequestReAuth -> askForReAuthentication(it)
SessionOverviewViewEvent.ConfirmSignoutCurrentSession -> confirmSignoutCurrentSession()
SessionOverviewViewEvent.SignoutSuccess -> viewNavigator.goBack(requireActivity())
is SessionOverviewViewEvent.SignoutError -> showFailure(it.error)
}
}
}
private fun confirmSignoutCurrentSession() {
activity?.let { SignOutUiWorker(it).perform() }
}
private fun initSessionInfoView() {
views.sessionOverviewInfo.onLearnMoreClickListener = {
Toast.makeText(context, "Learn more verification status", Toast.LENGTH_LONG).show()
@ -112,10 +109,39 @@ class SessionOverviewFragment :
private fun initSignoutButton() {
views.sessionOverviewSignout.debouncedClicks {
viewModel.handle(SessionOverviewAction.SignoutSession)
confirmSignoutSession()
}
}
private fun confirmSignoutSession() = withState(viewModel) { state ->
if (state.deviceInfo.invoke()?.isCurrentDevice.orFalse()) {
confirmSignoutCurrentSession()
} else {
confirmSignoutOtherSession()
}
}
private fun confirmSignoutCurrentSession() {
activity?.let { SignOutUiWorker(it).perform() }
}
private fun confirmSignoutOtherSession() {
activity?.let {
MaterialAlertDialogBuilder(it)
.setTitle(R.string.action_sign_out)
.setMessage(R.string.action_sign_out_confirmation_simple)
.setPositiveButton(R.string.action_sign_out) { _, _ ->
signoutSession()
}
.setNegativeButton(R.string.action_cancel, null)
.show()
}
}
private fun signoutSession() {
viewModel.handle(SessionOverviewAction.SignoutOtherSession)
}
override fun onDestroyView() {
cleanUpSessionInfoView()
super.onDestroyView()

View File

@ -28,7 +28,6 @@ sealed class SessionOverviewViewEvent : VectorViewEvents {
val lastErrorCode: String?
) : SessionOverviewViewEvent()
object ConfirmSignoutCurrentSession : SessionOverviewViewEvent()
object SignoutSuccess : SessionOverviewViewEvent()
data class SignoutError(val error: Throwable) : SessionOverviewViewEvent()
}

View File

@ -97,7 +97,7 @@ class SessionOverviewViewModel @AssistedInject constructor(
override fun handle(action: SessionOverviewAction) {
when (action) {
is SessionOverviewAction.VerifySession -> handleVerifySessionAction()
SessionOverviewAction.SignoutSession -> handleSignoutSession()
SessionOverviewAction.SignoutOtherSession -> handleSignoutOtherSession()
SessionOverviewAction.SsoAuthDone -> handleSsoAuthDone()
is SessionOverviewAction.PasswordAuthDone -> handlePasswordAuthDone(action)
SessionOverviewAction.ReAuthCancelled -> handleReAuthCancelled()
@ -127,18 +127,13 @@ class SessionOverviewViewModel @AssistedInject constructor(
_viewEvents.post(SessionOverviewViewEvent.ShowVerifyOtherSession(deviceId))
}
private fun handleSignoutSession() = withState { state ->
if (state.deviceInfo.invoke()?.isCurrentDevice.orFalse()) {
handleSignoutCurrentSession()
} else {
private fun handleSignoutOtherSession() = withState { state ->
// signout process for current session is not handled here
if (!state.deviceInfo.invoke()?.isCurrentDevice.orFalse()) {
handleSignoutOtherSession(state.deviceId)
}
}
private fun handleSignoutCurrentSession() {
_viewEvents.post(SessionOverviewViewEvent.ConfirmSignoutCurrentSession)
}
private fun handleSignoutOtherSession(deviceId: String) {
viewModelScope.launch {
setLoading(true)

View File

@ -199,26 +199,6 @@ class SessionOverviewViewModelTest {
.finish()
}
@Test
fun `given current session when handling signout action then confirmation event is posted`() {
// Given
val deviceFullInfo = mockk<DeviceFullInfo>()
every { deviceFullInfo.isCurrentDevice } returns true
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID_1) } returns flowOf(deviceFullInfo)
val signoutAction = SessionOverviewAction.SignoutSession
givenCurrentSessionIsTrusted()
// When
val viewModel = createViewModel()
val viewModelTest = viewModel.test()
viewModel.handle(signoutAction)
// Then
viewModelTest
.assertEvent { it is SessionOverviewViewEvent.ConfirmSignoutCurrentSession }
.finish()
}
@Test
fun `given another session and no reAuth is needed when handling signout action then signout process is performed`() {
// Given
@ -227,7 +207,7 @@ class SessionOverviewViewModelTest {
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID_1) } returns flowOf(deviceFullInfo)
givenSignoutSuccess(A_SESSION_ID_1)
every { refreshDevicesUseCase.execute() } just runs
val signoutAction = SessionOverviewAction.SignoutSession
val signoutAction = SessionOverviewAction.SignoutOtherSession
givenCurrentSessionIsTrusted()
val expectedViewState = SessionOverviewViewState(
deviceId = A_SESSION_ID_1,
@ -263,7 +243,7 @@ class SessionOverviewViewModelTest {
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID_1) } returns flowOf(deviceFullInfo)
val serverError = Failure.OtherServerError(errorBody = "", httpCode = HttpsURLConnection.HTTP_UNAUTHORIZED)
givenSignoutError(A_SESSION_ID_1, serverError)
val signoutAction = SessionOverviewAction.SignoutSession
val signoutAction = SessionOverviewAction.SignoutOtherSession
givenCurrentSessionIsTrusted()
val expectedViewState = SessionOverviewViewState(
deviceId = A_SESSION_ID_1,
@ -297,7 +277,7 @@ class SessionOverviewViewModelTest {
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID_1) } returns flowOf(deviceFullInfo)
val error = Exception()
givenSignoutError(A_SESSION_ID_1, error)
val signoutAction = SessionOverviewAction.SignoutSession
val signoutAction = SessionOverviewAction.SignoutOtherSession
givenCurrentSessionIsTrusted()
val expectedViewState = SessionOverviewViewState(
deviceId = A_SESSION_ID_1,
@ -330,7 +310,7 @@ class SessionOverviewViewModelTest {
every { deviceFullInfo.isCurrentDevice } returns false
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID_1) } returns flowOf(deviceFullInfo)
val reAuthNeeded = givenSignoutReAuthNeeded(A_SESSION_ID_1)
val signoutAction = SessionOverviewAction.SignoutSession
val signoutAction = SessionOverviewAction.SignoutOtherSession
givenCurrentSessionIsTrusted()
val expectedPendingAuth = DefaultBaseAuth(session = reAuthNeeded.flowResponse.session)
val expectedReAuthEvent = SessionOverviewViewEvent.RequestReAuth(reAuthNeeded.flowResponse, reAuthNeeded.errCode)