mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-15 01:35:07 +08:00
Adding confirmation dialog for all type of sessions
This commit is contained in:
parent
e47bf2b200
commit
082fa1e69e
@ -20,7 +20,7 @@ import im.vector.app.core.platform.VectorViewModelAction
|
|||||||
|
|
||||||
sealed class SessionOverviewAction : VectorViewModelAction {
|
sealed class SessionOverviewAction : VectorViewModelAction {
|
||||||
object VerifySession : SessionOverviewAction()
|
object VerifySession : SessionOverviewAction()
|
||||||
object SignoutSession : SessionOverviewAction()
|
object SignoutOtherSession : SessionOverviewAction()
|
||||||
object SsoAuthDone : SessionOverviewAction()
|
object SsoAuthDone : SessionOverviewAction()
|
||||||
data class PasswordAuthDone(val password: String) : SessionOverviewAction()
|
data class PasswordAuthDone(val password: String) : SessionOverviewAction()
|
||||||
object ReAuthCancelled : SessionOverviewAction()
|
object ReAuthCancelled : SessionOverviewAction()
|
||||||
|
@ -28,6 +28,7 @@ import androidx.core.view.isVisible
|
|||||||
import com.airbnb.mvrx.Success
|
import com.airbnb.mvrx.Success
|
||||||
import com.airbnb.mvrx.fragmentViewModel
|
import com.airbnb.mvrx.fragmentViewModel
|
||||||
import com.airbnb.mvrx.withState
|
import com.airbnb.mvrx.withState
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.date.VectorDateFormatter
|
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.settings.devices.v2.list.SessionInfoViewState
|
||||||
import im.vector.app.features.workers.signout.SignOutUiWorker
|
import im.vector.app.features.workers.signout.SignOutUiWorker
|
||||||
import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
|
import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
|
||||||
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,17 +89,12 @@ class SessionOverviewFragment :
|
|||||||
navigator.open4SSetup(requireActivity(), SetupMode.PASSPHRASE_AND_NEEDED_SECRETS_RESET)
|
navigator.open4SSetup(requireActivity(), SetupMode.PASSPHRASE_AND_NEEDED_SECRETS_RESET)
|
||||||
}
|
}
|
||||||
is SessionOverviewViewEvent.RequestReAuth -> askForReAuthentication(it)
|
is SessionOverviewViewEvent.RequestReAuth -> askForReAuthentication(it)
|
||||||
SessionOverviewViewEvent.ConfirmSignoutCurrentSession -> confirmSignoutCurrentSession()
|
|
||||||
SessionOverviewViewEvent.SignoutSuccess -> viewNavigator.goBack(requireActivity())
|
SessionOverviewViewEvent.SignoutSuccess -> viewNavigator.goBack(requireActivity())
|
||||||
is SessionOverviewViewEvent.SignoutError -> showFailure(it.error)
|
is SessionOverviewViewEvent.SignoutError -> showFailure(it.error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun confirmSignoutCurrentSession() {
|
|
||||||
activity?.let { SignOutUiWorker(it).perform() }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initSessionInfoView() {
|
private fun initSessionInfoView() {
|
||||||
views.sessionOverviewInfo.onLearnMoreClickListener = {
|
views.sessionOverviewInfo.onLearnMoreClickListener = {
|
||||||
Toast.makeText(context, "Learn more verification status", Toast.LENGTH_LONG).show()
|
Toast.makeText(context, "Learn more verification status", Toast.LENGTH_LONG).show()
|
||||||
@ -112,10 +109,39 @@ class SessionOverviewFragment :
|
|||||||
|
|
||||||
private fun initSignoutButton() {
|
private fun initSignoutButton() {
|
||||||
views.sessionOverviewSignout.debouncedClicks {
|
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() {
|
override fun onDestroyView() {
|
||||||
cleanUpSessionInfoView()
|
cleanUpSessionInfoView()
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
|
@ -28,7 +28,6 @@ sealed class SessionOverviewViewEvent : VectorViewEvents {
|
|||||||
val lastErrorCode: String?
|
val lastErrorCode: String?
|
||||||
) : SessionOverviewViewEvent()
|
) : SessionOverviewViewEvent()
|
||||||
|
|
||||||
object ConfirmSignoutCurrentSession : SessionOverviewViewEvent()
|
|
||||||
object SignoutSuccess : SessionOverviewViewEvent()
|
object SignoutSuccess : SessionOverviewViewEvent()
|
||||||
data class SignoutError(val error: Throwable) : SessionOverviewViewEvent()
|
data class SignoutError(val error: Throwable) : SessionOverviewViewEvent()
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ class SessionOverviewViewModel @AssistedInject constructor(
|
|||||||
override fun handle(action: SessionOverviewAction) {
|
override fun handle(action: SessionOverviewAction) {
|
||||||
when (action) {
|
when (action) {
|
||||||
is SessionOverviewAction.VerifySession -> handleVerifySessionAction()
|
is SessionOverviewAction.VerifySession -> handleVerifySessionAction()
|
||||||
SessionOverviewAction.SignoutSession -> handleSignoutSession()
|
SessionOverviewAction.SignoutOtherSession -> handleSignoutOtherSession()
|
||||||
SessionOverviewAction.SsoAuthDone -> handleSsoAuthDone()
|
SessionOverviewAction.SsoAuthDone -> handleSsoAuthDone()
|
||||||
is SessionOverviewAction.PasswordAuthDone -> handlePasswordAuthDone(action)
|
is SessionOverviewAction.PasswordAuthDone -> handlePasswordAuthDone(action)
|
||||||
SessionOverviewAction.ReAuthCancelled -> handleReAuthCancelled()
|
SessionOverviewAction.ReAuthCancelled -> handleReAuthCancelled()
|
||||||
@ -127,18 +127,13 @@ class SessionOverviewViewModel @AssistedInject constructor(
|
|||||||
_viewEvents.post(SessionOverviewViewEvent.ShowVerifyOtherSession(deviceId))
|
_viewEvents.post(SessionOverviewViewEvent.ShowVerifyOtherSession(deviceId))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleSignoutSession() = withState { state ->
|
private fun handleSignoutOtherSession() = withState { state ->
|
||||||
if (state.deviceInfo.invoke()?.isCurrentDevice.orFalse()) {
|
// signout process for current session is not handled here
|
||||||
handleSignoutCurrentSession()
|
if (!state.deviceInfo.invoke()?.isCurrentDevice.orFalse()) {
|
||||||
} else {
|
|
||||||
handleSignoutOtherSession(state.deviceId)
|
handleSignoutOtherSession(state.deviceId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleSignoutCurrentSession() {
|
|
||||||
_viewEvents.post(SessionOverviewViewEvent.ConfirmSignoutCurrentSession)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleSignoutOtherSession(deviceId: String) {
|
private fun handleSignoutOtherSession(deviceId: String) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
|
@ -199,26 +199,6 @@ class SessionOverviewViewModelTest {
|
|||||||
.finish()
|
.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
|
@Test
|
||||||
fun `given another session and no reAuth is needed when handling signout action then signout process is performed`() {
|
fun `given another session and no reAuth is needed when handling signout action then signout process is performed`() {
|
||||||
// Given
|
// Given
|
||||||
@ -227,7 +207,7 @@ class SessionOverviewViewModelTest {
|
|||||||
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID_1) } returns flowOf(deviceFullInfo)
|
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID_1) } returns flowOf(deviceFullInfo)
|
||||||
givenSignoutSuccess(A_SESSION_ID_1)
|
givenSignoutSuccess(A_SESSION_ID_1)
|
||||||
every { refreshDevicesUseCase.execute() } just runs
|
every { refreshDevicesUseCase.execute() } just runs
|
||||||
val signoutAction = SessionOverviewAction.SignoutSession
|
val signoutAction = SessionOverviewAction.SignoutOtherSession
|
||||||
givenCurrentSessionIsTrusted()
|
givenCurrentSessionIsTrusted()
|
||||||
val expectedViewState = SessionOverviewViewState(
|
val expectedViewState = SessionOverviewViewState(
|
||||||
deviceId = A_SESSION_ID_1,
|
deviceId = A_SESSION_ID_1,
|
||||||
@ -263,7 +243,7 @@ class SessionOverviewViewModelTest {
|
|||||||
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID_1) } returns flowOf(deviceFullInfo)
|
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID_1) } returns flowOf(deviceFullInfo)
|
||||||
val serverError = Failure.OtherServerError(errorBody = "", httpCode = HttpsURLConnection.HTTP_UNAUTHORIZED)
|
val serverError = Failure.OtherServerError(errorBody = "", httpCode = HttpsURLConnection.HTTP_UNAUTHORIZED)
|
||||||
givenSignoutError(A_SESSION_ID_1, serverError)
|
givenSignoutError(A_SESSION_ID_1, serverError)
|
||||||
val signoutAction = SessionOverviewAction.SignoutSession
|
val signoutAction = SessionOverviewAction.SignoutOtherSession
|
||||||
givenCurrentSessionIsTrusted()
|
givenCurrentSessionIsTrusted()
|
||||||
val expectedViewState = SessionOverviewViewState(
|
val expectedViewState = SessionOverviewViewState(
|
||||||
deviceId = A_SESSION_ID_1,
|
deviceId = A_SESSION_ID_1,
|
||||||
@ -297,7 +277,7 @@ class SessionOverviewViewModelTest {
|
|||||||
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID_1) } returns flowOf(deviceFullInfo)
|
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID_1) } returns flowOf(deviceFullInfo)
|
||||||
val error = Exception()
|
val error = Exception()
|
||||||
givenSignoutError(A_SESSION_ID_1, error)
|
givenSignoutError(A_SESSION_ID_1, error)
|
||||||
val signoutAction = SessionOverviewAction.SignoutSession
|
val signoutAction = SessionOverviewAction.SignoutOtherSession
|
||||||
givenCurrentSessionIsTrusted()
|
givenCurrentSessionIsTrusted()
|
||||||
val expectedViewState = SessionOverviewViewState(
|
val expectedViewState = SessionOverviewViewState(
|
||||||
deviceId = A_SESSION_ID_1,
|
deviceId = A_SESSION_ID_1,
|
||||||
@ -330,7 +310,7 @@ class SessionOverviewViewModelTest {
|
|||||||
every { deviceFullInfo.isCurrentDevice } returns false
|
every { deviceFullInfo.isCurrentDevice } returns false
|
||||||
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID_1) } returns flowOf(deviceFullInfo)
|
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID_1) } returns flowOf(deviceFullInfo)
|
||||||
val reAuthNeeded = givenSignoutReAuthNeeded(A_SESSION_ID_1)
|
val reAuthNeeded = givenSignoutReAuthNeeded(A_SESSION_ID_1)
|
||||||
val signoutAction = SessionOverviewAction.SignoutSession
|
val signoutAction = SessionOverviewAction.SignoutOtherSession
|
||||||
givenCurrentSessionIsTrusted()
|
givenCurrentSessionIsTrusted()
|
||||||
val expectedPendingAuth = DefaultBaseAuth(session = reAuthNeeded.flowResponse.session)
|
val expectedPendingAuth = DefaultBaseAuth(session = reAuthNeeded.flowResponse.session)
|
||||||
val expectedReAuthEvent = SessionOverviewViewEvent.RequestReAuth(reAuthNeeded.flowResponse, reAuthNeeded.errCode)
|
val expectedReAuthEvent = SessionOverviewViewEvent.RequestReAuth(reAuthNeeded.flowResponse, reAuthNeeded.errCode)
|
||||||
|
Loading…
Reference in New Issue
Block a user