diff --git a/changelog.d/4855.bugfix b/changelog.d/4855.bugfix
new file mode 100644
index 0000000000..d85feb42e7
--- /dev/null
+++ b/changelog.d/4855.bugfix
@@ -0,0 +1 @@
+Fix: Allow users to sign out even if the sign out request fails.
diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml
index 8ad9ad6eb4..ee7d2fea12 100644
--- a/library/ui-strings/src/main/res/values/strings.xml
+++ b/library/ui-strings/src/main/res/values/strings.xml
@@ -328,6 +328,9 @@
Back up
You’ll lose access to your encrypted messages unless you back up your keys before signing out.
+ Cannot reach the homeserver. If you sign out anyway, this device will not be erased from your device list, you may want to remove it using another client.
+ Sign out anyway
+
Loading…
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/signout/SignOutService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/signout/SignOutService.kt
index d64b2e6e92..fade51600a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/signout/SignOutService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/signout/SignOutService.kt
@@ -37,6 +37,7 @@ interface SignOutService {
/**
* Sign out, and release the session, clear all the session data, including crypto data.
* @param signOutFromHomeserver true if the sign out request has to be done
+ * @param ignoreServerRequestError true to ignore server error if any
*/
- suspend fun signOut(signOutFromHomeserver: Boolean)
+ suspend fun signOut(signOutFromHomeserver: Boolean, ignoreServerRequestError: Boolean = false)
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/DefaultSignOutService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/DefaultSignOutService.kt
index 1bb86ecb4b..2c34f1e2d9 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/DefaultSignOutService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/DefaultSignOutService.kt
@@ -35,7 +35,12 @@ internal class DefaultSignOutService @Inject constructor(
sessionParamsStore.updateCredentials(credentials)
}
- override suspend fun signOut(signOutFromHomeserver: Boolean) {
- return signOutTask.execute(SignOutTask.Params(signOutFromHomeserver))
+ override suspend fun signOut(signOutFromHomeserver: Boolean, ignoreServerRequestError: Boolean) {
+ return signOutTask.execute(
+ SignOutTask.Params(
+ signOutFromHomeserver = signOutFromHomeserver,
+ ignoreServerRequestError = ignoreServerRequestError
+ )
+ )
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/SignOutTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/SignOutTask.kt
index e5213c4696..f8ec23b24d 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/SignOutTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/SignOutTask.kt
@@ -30,7 +30,8 @@ import javax.inject.Inject
internal interface SignOutTask : Task {
data class Params(
- val signOutFromHomeserver: Boolean
+ val signOutFromHomeserver: Boolean,
+ val ignoreServerRequestError: Boolean,
)
}
@@ -59,7 +60,9 @@ internal class DefaultSignOutTask @Inject constructor(
// Ignore
Timber.w("Ignore error due to https://github.com/matrix-org/synapse/issues/5755")
} else {
- throw throwable
+ if (!params.ignoreServerRequestError) {
+ throw throwable
+ }
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/MainActivity.kt b/vector/src/main/java/im/vector/app/features/MainActivity.kt
index ff0e9721e4..48fe092524 100644
--- a/vector/src/main/java/im/vector/app/features/MainActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/MainActivity.kt
@@ -60,6 +60,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.api.failure.GlobalError
+import org.matrix.android.sdk.api.session.Session
import timber.log.Timber
import javax.inject.Inject
@@ -262,18 +263,7 @@ class MainActivity : VectorBaseActivity(), UnlockedActivity
}
}
args.clearCredentials -> {
- lifecycleScope.launch {
- try {
- session.signOutService().signOut(!args.isUserLoggedOut)
- } catch (failure: Throwable) {
- displayError(failure)
- return@launch
- }
- Timber.w("SIGN_OUT: success, start app")
- activeSessionHolder.clearActiveSession()
- doLocalCleanup(clearPreferences = true, onboardingStore)
- startNextActivityAndFinish()
- }
+ signout(session, onboardingStore, ignoreServerError = false)
}
args.clearCache -> {
lifecycleScope.launch {
@@ -286,6 +276,26 @@ class MainActivity : VectorBaseActivity(), UnlockedActivity
}
}
+ private fun signout(
+ session: Session,
+ onboardingStore: VectorSessionStore,
+ ignoreServerError: Boolean,
+ ) {
+ lifecycleScope.launch {
+ try {
+ session.signOutService().signOut(!args.isUserLoggedOut, ignoreServerError)
+ } catch (failure: Throwable) {
+ Timber.e(failure, "SIGN_OUT: error, propose to sign out anyway")
+ displaySignOutFailedDialog(session, onboardingStore)
+ return@launch
+ }
+ Timber.w("SIGN_OUT: success, start app")
+ activeSessionHolder.clearActiveSession()
+ doLocalCleanup(clearPreferences = true, onboardingStore)
+ startNextActivityAndFinish()
+ }
+ }
+
override fun handleInvalidToken(globalError: GlobalError.InvalidToken) {
// No op here
Timber.w("Ignoring invalid token global error")
@@ -313,12 +323,20 @@ class MainActivity : VectorBaseActivity(), UnlockedActivity
}
}
- private fun displayError(failure: Throwable) {
+ private fun displaySignOutFailedDialog(
+ session: Session,
+ onboardingStore: VectorSessionStore,
+ ) {
if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
MaterialAlertDialogBuilder(this)
.setTitle(R.string.dialog_title_error)
- .setMessage(errorFormatter.toHumanReadable(failure))
- .setPositiveButton(R.string.global_retry) { _, _ -> doCleanUp() }
+ .setMessage(R.string.sign_out_failed_dialog_message)
+ .setPositiveButton(R.string.sign_out_anyway) { _, _ ->
+ signout(session, onboardingStore, ignoreServerError = true)
+ }
+ .setNeutralButton(R.string.global_retry) { _, _ ->
+ signout(session, onboardingStore, ignoreServerError = false)
+ }
.setNegativeButton(R.string.action_cancel) { _, _ -> startNextActivityAndFinish(ignoreClearCredentials = true) }
.setCancelable(false)
.show()