Adding button to trigger sign out
This commit is contained in:
parent
7e81aa6193
commit
b2b3ee1fe5
@ -3290,6 +3290,7 @@
|
|||||||
<string name="device_manager_other_sessions_no_unverified_sessions_found">No unverified sessions found.</string>
|
<string name="device_manager_other_sessions_no_unverified_sessions_found">No unverified sessions found.</string>
|
||||||
<string name="device_manager_other_sessions_no_inactive_sessions_found">No inactive sessions found.</string>
|
<string name="device_manager_other_sessions_no_inactive_sessions_found">No inactive sessions found.</string>
|
||||||
<string name="device_manager_other_sessions_clear_filter">Clear Filter</string>
|
<string name="device_manager_other_sessions_clear_filter">Clear Filter</string>
|
||||||
|
<string name="device_manager_session_overview_signout">Sign out of this session</string>
|
||||||
<string name="device_manager_session_details_title">Session details</string>
|
<string name="device_manager_session_details_title">Session details</string>
|
||||||
<string name="device_manager_session_details_description">Application, device, and activity information.</string>
|
<string name="device_manager_session_details_description">Application, device, and activity information.</string>
|
||||||
<string name="device_manager_session_details_session_name">Session name</string>
|
<string name="device_manager_session_details_session_name">Session name</string>
|
||||||
|
@ -41,6 +41,10 @@
|
|||||||
<item name="lineHeight">24sp</item>
|
<item name="lineHeight">24sp</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="Widget.Vector.Button.Text.Destructive">
|
||||||
|
<item name="materialThemeOverlay">@style/VectorMaterialThemeOverlayDestructive</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<style name="Widget.Vector.Button.Text.OnPrimary">
|
<style name="Widget.Vector.Button.Text.OnPrimary">
|
||||||
<item name="colorControlHighlight">?colorOnPrimary</item>
|
<item name="colorControlHighlight">?colorOnPrimary</item>
|
||||||
<item name="materialThemeOverlay">@style/VectorMaterialThemeOverlayOnPrimary</item>
|
<item name="materialThemeOverlay">@style/VectorMaterialThemeOverlayOnPrimary</item>
|
||||||
|
@ -70,18 +70,7 @@ class SessionOverviewFragment :
|
|||||||
observeViewEvents()
|
observeViewEvents()
|
||||||
initSessionInfoView()
|
initSessionInfoView()
|
||||||
initVerifyButton()
|
initVerifyButton()
|
||||||
}
|
initSignoutButton()
|
||||||
|
|
||||||
private fun initSessionInfoView() {
|
|
||||||
views.sessionOverviewInfo.onLearnMoreClickListener = {
|
|
||||||
Toast.makeText(context, "Learn more verification status", Toast.LENGTH_LONG).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initVerifyButton() {
|
|
||||||
views.sessionOverviewInfo.viewVerifyButton.debouncedClicks {
|
|
||||||
viewModel.handle(SessionOverviewAction.VerifySession)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun observeViewEvents() {
|
private fun observeViewEvents() {
|
||||||
@ -97,10 +86,30 @@ 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.SignoutSuccess -> viewNavigator.goBack(requireActivity())
|
||||||
|
is SessionOverviewViewEvent.SignoutError -> showFailure(it.error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun initSessionInfoView() {
|
||||||
|
views.sessionOverviewInfo.onLearnMoreClickListener = {
|
||||||
|
Toast.makeText(context, "Learn more verification status", Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initVerifyButton() {
|
||||||
|
views.sessionOverviewInfo.viewVerifyButton.debouncedClicks {
|
||||||
|
viewModel.handle(SessionOverviewAction.VerifySession)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initSignoutButton() {
|
||||||
|
views.sessionOverviewSignout.debouncedClicks {
|
||||||
|
viewModel.handle(SessionOverviewAction.SignoutSession)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
cleanUpSessionInfoView()
|
cleanUpSessionInfoView()
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
|
@ -27,4 +27,7 @@ sealed class SessionOverviewViewEvent : VectorViewEvents {
|
|||||||
val registrationFlowResponse: RegistrationFlowResponse,
|
val registrationFlowResponse: RegistrationFlowResponse,
|
||||||
val lastErrorCode: String?
|
val lastErrorCode: String?
|
||||||
) : SessionOverviewViewEvent()
|
) : SessionOverviewViewEvent()
|
||||||
|
|
||||||
|
object SignoutSuccess : SessionOverviewViewEvent()
|
||||||
|
data class SignoutError(val error: Throwable) : SessionOverviewViewEvent()
|
||||||
}
|
}
|
||||||
|
@ -21,12 +21,15 @@ import com.airbnb.mvrx.Success
|
|||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
|
import im.vector.app.R
|
||||||
import im.vector.app.core.di.ActiveSessionHolder
|
import im.vector.app.core.di.ActiveSessionHolder
|
||||||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.features.auth.PendingAuthHandler
|
import im.vector.app.features.auth.PendingAuthHandler
|
||||||
import im.vector.app.features.settings.devices.v2.IsCurrentSessionUseCase
|
import im.vector.app.features.settings.devices.v2.IsCurrentSessionUseCase
|
||||||
|
import im.vector.app.features.settings.devices.v2.RefreshDevicesUseCase
|
||||||
|
import im.vector.app.features.settings.devices.v2.VectorSessionsListViewModel
|
||||||
import im.vector.app.features.settings.devices.v2.signout.InterceptSignoutFlowResponseUseCase
|
import im.vector.app.features.settings.devices.v2.signout.InterceptSignoutFlowResponseUseCase
|
||||||
import im.vector.app.features.settings.devices.v2.signout.SignoutSessionResult
|
import im.vector.app.features.settings.devices.v2.signout.SignoutSessionResult
|
||||||
import im.vector.app.features.settings.devices.v2.signout.SignoutSessionUseCase
|
import im.vector.app.features.settings.devices.v2.signout.SignoutSessionUseCase
|
||||||
@ -39,21 +42,27 @@ import kotlinx.coroutines.launch
|
|||||||
import org.matrix.android.sdk.api.auth.UIABaseAuth
|
import org.matrix.android.sdk.api.auth.UIABaseAuth
|
||||||
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
|
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
|
||||||
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
|
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
|
||||||
|
import org.matrix.android.sdk.api.failure.Failure
|
||||||
import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
|
import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
|
||||||
import org.matrix.android.sdk.api.session.uia.DefaultBaseAuth
|
import org.matrix.android.sdk.api.session.uia.DefaultBaseAuth
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import javax.net.ssl.HttpsURLConnection
|
||||||
import kotlin.coroutines.Continuation
|
import kotlin.coroutines.Continuation
|
||||||
|
|
||||||
class SessionOverviewViewModel @AssistedInject constructor(
|
class SessionOverviewViewModel @AssistedInject constructor(
|
||||||
@Assisted val initialState: SessionOverviewViewState,
|
@Assisted val initialState: SessionOverviewViewState,
|
||||||
private val activeSessionHolder: ActiveSessionHolder,
|
|
||||||
private val isCurrentSessionUseCase: IsCurrentSessionUseCase,
|
private val isCurrentSessionUseCase: IsCurrentSessionUseCase,
|
||||||
|
private val stringProvider: StringProvider,
|
||||||
private val getDeviceFullInfoUseCase: GetDeviceFullInfoUseCase,
|
private val getDeviceFullInfoUseCase: GetDeviceFullInfoUseCase,
|
||||||
private val checkIfCurrentSessionCanBeVerifiedUseCase: CheckIfCurrentSessionCanBeVerifiedUseCase,
|
private val checkIfCurrentSessionCanBeVerifiedUseCase: CheckIfCurrentSessionCanBeVerifiedUseCase,
|
||||||
private val signoutSessionUseCase: SignoutSessionUseCase,
|
private val signoutSessionUseCase: SignoutSessionUseCase,
|
||||||
private val interceptSignoutFlowResponseUseCase: InterceptSignoutFlowResponseUseCase,
|
private val interceptSignoutFlowResponseUseCase: InterceptSignoutFlowResponseUseCase,
|
||||||
private val pendingAuthHandler: PendingAuthHandler,
|
private val pendingAuthHandler: PendingAuthHandler,
|
||||||
) : VectorViewModel<SessionOverviewViewState, SessionOverviewAction, SessionOverviewViewEvent>(initialState) {
|
activeSessionHolder: ActiveSessionHolder,
|
||||||
|
refreshDevicesUseCase: RefreshDevicesUseCase,
|
||||||
|
) : VectorSessionsListViewModel<SessionOverviewViewState, SessionOverviewAction, SessionOverviewViewEvent>(
|
||||||
|
initialState, activeSessionHolder, refreshDevicesUseCase
|
||||||
|
) {
|
||||||
|
|
||||||
companion object : MavericksViewModelFactory<SessionOverviewViewModel, SessionOverviewViewState> by hiltMavericksViewModelFactory()
|
companion object : MavericksViewModelFactory<SessionOverviewViewModel, SessionOverviewViewState> by hiltMavericksViewModelFactory()
|
||||||
|
|
||||||
@ -129,20 +138,26 @@ class SessionOverviewViewModel @AssistedInject constructor(
|
|||||||
|
|
||||||
// TODO add unit tests
|
// TODO add unit tests
|
||||||
private fun handleSignoutSession() = withState { state ->
|
private fun handleSignoutSession() = withState { state ->
|
||||||
// TODO should we do something different when it is current session?
|
// TODO for current session: do the same process as sign out button in the general settings
|
||||||
|
// TODO add a loading viewState or ViewEvent
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
signoutSessionUseCase.execute(state.deviceId, object : UserInteractiveAuthInterceptor {
|
val signoutResult = signoutSessionUseCase.execute(state.deviceId, object : UserInteractiveAuthInterceptor {
|
||||||
override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) {
|
override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) {
|
||||||
when (val result = interceptSignoutFlowResponseUseCase.execute(flowResponse, errCode, promise)) {
|
when (val result = interceptSignoutFlowResponseUseCase.execute(flowResponse, errCode, promise)) {
|
||||||
is SignoutSessionResult.ReAuthNeeded -> onReAuthNeeded(result)
|
is SignoutSessionResult.ReAuthNeeded -> onReAuthNeeded(result)
|
||||||
is SignoutSessionResult.Completed -> {
|
is SignoutSessionResult.Completed -> Unit
|
||||||
Timber.d("signout completed")
|
|
||||||
// TODO check if it is called after a reAuth
|
|
||||||
// TODO refresh devices list? + post event to close the associated screen
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (signoutResult.isSuccess) {
|
||||||
|
onSignoutSuccess()
|
||||||
|
} else {
|
||||||
|
when (val failure = signoutResult.exceptionOrNull()) {
|
||||||
|
null -> onSignoutSuccess()
|
||||||
|
else -> onSignoutFailure(failure)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,6 +168,22 @@ class SessionOverviewViewModel @AssistedInject constructor(
|
|||||||
_viewEvents.post(SessionOverviewViewEvent.RequestReAuth(reAuthNeeded.flowResponse, reAuthNeeded.errCode))
|
_viewEvents.post(SessionOverviewViewEvent.RequestReAuth(reAuthNeeded.flowResponse, reAuthNeeded.errCode))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun onSignoutSuccess() {
|
||||||
|
Timber.d("signout success")
|
||||||
|
refreshDeviceList()
|
||||||
|
_viewEvents.post(SessionOverviewViewEvent.SignoutSuccess)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onSignoutFailure(failure: Throwable) {
|
||||||
|
Timber.e("signout failure", failure)
|
||||||
|
val failureMessage = if (failure is Failure.OtherServerError && failure.httpCode == HttpsURLConnection.HTTP_UNAUTHORIZED) {
|
||||||
|
stringProvider.getString(R.string.authentication_error)
|
||||||
|
} else {
|
||||||
|
stringProvider.getString(R.string.matrix_error)
|
||||||
|
}
|
||||||
|
_viewEvents.post(SessionOverviewViewEvent.SignoutError(Exception(failureMessage)))
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleSsoAuthDone() {
|
private fun handleSsoAuthDone() {
|
||||||
pendingAuthHandler.ssoAuthDone()
|
pendingAuthHandler.ssoAuthDone()
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package im.vector.app.features.settings.devices.v2.overview
|
package im.vector.app.features.settings.devices.v2.overview
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
import im.vector.app.features.settings.devices.v2.details.SessionDetailsActivity
|
import im.vector.app.features.settings.devices.v2.details.SessionDetailsActivity
|
||||||
import im.vector.app.features.settings.devices.v2.rename.RenameSessionActivity
|
import im.vector.app.features.settings.devices.v2.rename.RenameSessionActivity
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -30,4 +31,9 @@ class SessionOverviewViewNavigator @Inject constructor() {
|
|||||||
fun goToRenameSession(context: Context, deviceId: String) {
|
fun goToRenameSession(context: Context, deviceId: String) {
|
||||||
context.startActivity(RenameSessionActivity.newIntent(context, deviceId))
|
context.startActivity(RenameSessionActivity.newIntent(context, deviceId))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO add unit test
|
||||||
|
fun goBack(fragmentActivity: FragmentActivity) {
|
||||||
|
fragmentActivity.finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,19 @@
|
|||||||
app:sessionOverviewEntryDescription="@string/device_manager_session_details_description"
|
app:sessionOverviewEntryDescription="@string/device_manager_session_details_description"
|
||||||
app:sessionOverviewEntryTitle="@string/device_manager_session_details_title" />
|
app:sessionOverviewEntryTitle="@string/device_manager_session_details_title" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/sessionOverviewSignout"
|
||||||
|
style="@style/Widget.Vector.Button.Text.Destructive"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="8dp"
|
||||||
|
android:text="@string/device_manager_session_overview_signout"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/sessionOverviewEntryDetails"
|
||||||
|
app:layout_constraintWidth="wrap_content" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user