diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt index d41e2aa11f..76e691d1be 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt @@ -100,7 +100,7 @@ interface CryptoService { fun getDeviceInfo(deviceId: String, callback: MatrixCallback) - fun inboundGroupSessionsCount(onlyBackedUp: Boolean): Int + suspend fun inboundGroupSessionsCount(onlyBackedUp: Boolean): Int fun isRoomEncrypted(roomId: String): Boolean diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt index 6bb4dbc620..5a0ce933de 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt @@ -26,6 +26,7 @@ import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult import org.matrix.android.sdk.internal.crypto.store.SavedKeyBackupKeyInfo interface KeysBackupService { + /** * Retrieve the current version of the backup from the homeserver * @@ -45,12 +46,12 @@ interface KeysBackupService { /** * Facility method to get the total number of locally stored keys */ - fun getTotalNumbersOfKeys(): Int + suspend fun getTotalNumbersOfKeys(): Int /** * Facility method to get the number of backed up keys */ - fun getTotalNumbersOfBackedUpKeys(): Int + suspend fun getTotalNumbersOfBackedUpKeys(): Int // /** // * Start to back up keys immediately. @@ -71,7 +72,7 @@ interface KeysBackupService { /** * Return the current progress of the backup */ - fun getBackupProgress(progressListener: ProgressListener) + suspend fun getBackupProgress(progressListener: ProgressListener) /** * Get information about a backup version defined on the homeserver. @@ -128,7 +129,7 @@ interface KeysBackupService { * Ask if the backup on the server contains keys that we may do not have locally. * This should be called when entering in the state READY_TO_BACKUP */ - fun canRestoreKeys(): Boolean + suspend fun canRestoreKeys(): Boolean /** * Set trust on a keys backup version. @@ -199,7 +200,7 @@ interface KeysBackupService { // For gossiping fun saveBackupRecoveryKey(recoveryKey: String?, version: String?) - fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo? + suspend fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo? suspend fun isValidRecoveryKeyForCurrentVersion(recoveryKey: String): Boolean } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt index e4c0e90f6d..6523839cdd 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt @@ -132,7 +132,7 @@ internal class DefaultCryptoService @Inject constructor( private val coroutineDispatchers: MatrixCoroutineDispatchers, private val taskExecutor: TaskExecutor, private val cryptoCoroutineScope: CoroutineScope, - private val sender: RequestSender, + private val requestSender: RequestSender, private val crossSigningService: CrossSigningService, private val verificationService: RustVerificationService, private val keysBackupService: RustKeyBackupService, @@ -248,7 +248,7 @@ internal class DefaultCryptoService @Inject constructor( .executeBy(taskExecutor) } - override fun inboundGroupSessionsCount(onlyBackedUp: Boolean): Int { + override suspend fun inboundGroupSessionsCount(onlyBackedUp: Boolean): Int { return if (onlyBackedUp) { keysBackupService.getTotalNumbersOfBackedUpKeys() } else { @@ -594,7 +594,6 @@ internal class DefaultCryptoService @Inject constructor( // Timber.e(throwable, "## CRYPTO | onRoomEncryptionEvent ERROR FAILED TO SETUP CRYPTO ") // } finally { val userIds = getRoomUserIds(roomId) - olmMachine.updateTrackedUsers(userIds) setEncryptionInRoom(roomId, event.content?.get("algorithm")?.toString(), userIds) // } } @@ -758,14 +757,18 @@ internal class DefaultCryptoService @Inject constructor( } private suspend fun uploadKeys(request: Request.KeysUpload) { - val response = this.sender.uploadKeys(request) - this.olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_UPLOAD, response) + try { + val response = requestSender.uploadKeys(request) + olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_UPLOAD, response) + } catch (throwable: Throwable) { + Timber.tag(loggerTag.value).e(throwable, "## CRYPTO uploadKeys(): error") + } } private suspend fun queryKeys(request: Request.KeysQuery) { try { - val response = this.sender.queryKeys(request) - this.olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_QUERY, response) + val response = requestSender.queryKeys(request) + olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_QUERY, response) // Update the shields! cryptoCoroutineScope.launch { @@ -781,18 +784,38 @@ internal class DefaultCryptoService @Inject constructor( } private suspend fun sendToDevice(request: Request.ToDevice) { - this.sender.sendToDevice(request) - olmMachine.markRequestAsSent(request.requestId, RequestType.TO_DEVICE, "{}") + try { + requestSender.sendToDevice(request) + olmMachine.markRequestAsSent(request.requestId, RequestType.TO_DEVICE, "{}") + } catch (throwable: Throwable) { + Timber.tag(loggerTag.value).e(throwable, "## CRYPTO sendToDevice(): error") + } } private suspend fun claimKeys(request: Request.KeysClaim) { - val response = this.sender.claimKeys(request) - olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_CLAIM, response) + try { + val response = requestSender.claimKeys(request) + olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_CLAIM, response) + } catch (throwable: Throwable) { + Timber.tag(loggerTag.value).e(throwable, "## CRYPTO claimKeys(): error") + } } private suspend fun signatureUpload(request: Request.SignatureUpload) { - this.sender.sendSignatureUpload(request) - olmMachine.markRequestAsSent(request.requestId, RequestType.SIGNATURE_UPLOAD, "{}") + try { + requestSender.sendSignatureUpload(request) + olmMachine.markRequestAsSent(request.requestId, RequestType.SIGNATURE_UPLOAD, "{}") + } catch (throwable: Throwable) { + Timber.tag(loggerTag.value).e(throwable, "## CRYPTO signatureUpload(): error") + } + } + + private suspend fun sendRoomMessage(request: Request.RoomMessage){ + try { + requestSender.sendRoomMessage(request) + } catch (throwable: Throwable) { + Timber.tag(loggerTag.value).e(throwable, "## CRYPTO sendRoomMessage(): error") + } } private suspend fun sendOutgoingRequests() { @@ -822,7 +845,7 @@ internal class DefaultCryptoService @Inject constructor( } is Request.RoomMessage -> { async { - sender.sendRoomMessage(it) + sendRoomMessage(it) } } is Request.SignatureUpload -> { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt index 42aed8e38f..6dfdc3cfcb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt @@ -833,21 +833,24 @@ internal class OlmMachine( } @Throws(CryptoStoreException::class) - fun roomKeyCounts(): RoomKeyCounts { - // TODO convert this to a suspendable method - return inner.roomKeyCounts() + suspend fun roomKeyCounts(): RoomKeyCounts { + return withContext(Dispatchers.Default) { + inner.roomKeyCounts() + } } @Throws(CryptoStoreException::class) - fun getBackupKeys(): BackupKeys? { - // TODO this needs to be suspendable - return inner.getBackupKeys() + suspend fun getBackupKeys(): BackupKeys? { + return withContext(Dispatchers.Default) { + inner.getBackupKeys() + } } @Throws(CryptoStoreException::class) - fun saveRecoveryKey(key: String?, version: String?) { - // TODO convert this to a suspendable method - inner.saveRecoveryKey(key, version) + suspend fun saveRecoveryKey(key: String?, version: String?) { + withContext(Dispatchers.Default) { + inner.saveRecoveryKey(key, version) + } } @Throws(CryptoStoreException::class) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RequestSender.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RequestSender.kt index 45644d951f..942afd336e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RequestSender.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RequestSender.kt @@ -16,6 +16,7 @@ package org.matrix.android.sdk.internal.crypto +import com.squareup.moshi.Moshi import com.squareup.moshi.Types import dagger.Lazy import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor @@ -80,6 +81,7 @@ internal class RequestSender @Inject constructor( private val getSessionsDataTask: GetSessionsDataTask, private val getRoomSessionsDataTask: GetRoomSessionsDataTask, private val getRoomSessionDataTask: GetRoomSessionDataTask, + private val moshi: Moshi ) { companion object { const val REQUEST_RETRY_COUNT = 3 @@ -97,16 +99,16 @@ internal class RequestSender @Inject constructor( suspend fun queryKeys(request: Request.KeysQuery): String { val params = DownloadKeysForUsersTask.Params(request.users, null) val response = downloadKeysForUsersTask.executeRetry(params, REQUEST_RETRY_COUNT) - val adapter = MoshiProvider.providesMoshi().adapter(KeysQueryResponse::class.java) + val adapter = moshi.adapter(KeysQueryResponse::class.java) return adapter.toJson(response)!! } suspend fun uploadKeys(request: Request.KeysUpload): String { - val body = MoshiProvider.providesMoshi().adapter(Map::class.java).fromJson(request.body)!! + val body = moshi.adapter(Map::class.java).fromJson(request.body)!! val params = UploadKeysTask.Params(body) val response = uploadKeysTask.executeRetry(params, REQUEST_RETRY_COUNT) - val adapter = MoshiProvider.providesMoshi().adapter(KeysUploadResponse::class.java) + val adapter = moshi.adapter(KeysUploadResponse::class.java) return adapter.toJson(response)!! } @@ -127,7 +129,7 @@ internal class RequestSender @Inject constructor( } suspend fun sendRoomMessage(eventType: String, roomId: String, content: String, transactionId: String): String { - val adapter = MoshiProvider.providesMoshi().adapter(Map::class.java) + val adapter = moshi.adapter(Map::class.java) val jsonContent = adapter.fromJson(content) val event = Event(eventType, transactionId, jsonContent, roomId = roomId) val params = SendVerificationMessageTask.Params(event) @@ -143,7 +145,7 @@ internal class RequestSender @Inject constructor( } private suspend fun sendSignatureUpload(body: String) { - val adapter = MoshiProvider.providesMoshi().adapter>>(Map::class.java) + val adapter = moshi.adapter>>(Map::class.java) val signatures = adapter.fromJson(body)!! val params = UploadSignaturesTask.Params(signatures) this.signaturesUploadTask.executeRetry(params, REQUEST_RETRY_COUNT) @@ -153,7 +155,7 @@ internal class RequestSender @Inject constructor( request: UploadSigningKeysRequest, interactiveAuthInterceptor: UserInteractiveAuthInterceptor? ) { - val adapter = MoshiProvider.providesMoshi().adapter(RestKeyInfo::class.java) + val adapter = moshi.adapter(RestKeyInfo::class.java) val masterKey = adapter.fromJson(request.masterKey)!!.toCryptoModel() val selfSigningKey = adapter.fromJson(request.selfSigningKey)!!.toCryptoModel() val userSigningKey = adapter.fromJson(request.userSigningKey)!!.toCryptoModel() @@ -195,8 +197,7 @@ internal class RequestSender @Inject constructor( } suspend fun sendToDevice(eventType: String, body: String, transactionId: String) { - val adapter = MoshiProvider - .providesMoshi() + val adapter = moshi .newBuilder() .add(CheckNumberType.JSON_ADAPTER_FACTORY) .build() @@ -252,7 +253,7 @@ internal class RequestSender @Inject constructor( val keys = adapter.fromJson(request.rooms)!! val params = StoreSessionsDataTask.Params(request.version, KeysBackupData(keys)) val response = backupRoomKeysTask.executeRetry(params, REQUEST_RETRY_COUNT) - val responseAdapter = MoshiProvider.providesMoshi().adapter(BackupKeysResult::class.java) + val responseAdapter = moshi.adapter(BackupKeysResult::class.java) return responseAdapter.toJson(response)!! } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/RustKeyBackupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/RustKeyBackupService.kt index d4864c8234..11c1117761 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/RustKeyBackupService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/RustKeyBackupService.kt @@ -237,7 +237,7 @@ internal class RustKeyBackupService @Inject constructor( } } - override fun canRestoreKeys(): Boolean { + override suspend fun canRestoreKeys(): Boolean { val keyCountOnServer = keysBackupVersion?.count ?: return false val keyCountLocally = getTotalNumbersOfKeys() @@ -246,11 +246,11 @@ internal class RustKeyBackupService @Inject constructor( return keyCountLocally < keyCountOnServer } - override fun getTotalNumbersOfKeys(): Int { + override suspend fun getTotalNumbersOfKeys(): Int { return olmMachine.roomKeyCounts().total.toInt() } - override fun getTotalNumbersOfBackedUpKeys(): Int { + override suspend fun getTotalNumbersOfBackedUpKeys(): Int { return olmMachine.roomKeyCounts().backedUp.toInt() } @@ -405,7 +405,7 @@ internal class RustKeyBackupService @Inject constructor( } } - override fun getBackupProgress(progressListener: ProgressListener) { + override suspend fun getBackupProgress(progressListener: ProgressListener) { val backedUpKeys = getTotalNumbersOfBackedUpKeys() val total = getTotalNumbersOfKeys() @@ -725,7 +725,7 @@ internal class RustKeyBackupService @Inject constructor( } } - override fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo? { + override suspend fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo? { val info = olmMachine.getBackupKeys() ?: return null return SavedKeyBackupKeyInfo(info.recoveryKey, info.backupVersion) } diff --git a/vector/src/main/java/im/vector/app/core/extensions/Session.kt b/vector/src/main/java/im/vector/app/core/extensions/Session.kt index 87ed51522f..17e2949cda 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/Session.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/Session.kt @@ -64,12 +64,12 @@ fun Session.startSyncing(context: Context) { /** * Tell is the session has unsaved e2e keys in the backup */ -fun Session.hasUnsavedKeys(): Boolean { +suspend fun Session.hasUnsavedKeys(): Boolean { return cryptoService().inboundGroupSessionsCount(false) > 0 && cryptoService().keysBackupService().state != KeysBackupState.ReadyToBackUp } -fun Session.cannotLogoutSafely(): Boolean { +suspend fun Session.cannotLogoutSafely(): Boolean { // has some encrypted chat return hasUnsavedKeys() || // has local cross signing keys diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingViewState.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingViewState.kt index 438b502b42..9e2fa10bd3 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingViewState.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingViewState.kt @@ -26,5 +26,8 @@ import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionR data class KeysBackupSettingViewState(val keysBackupVersionTrust: Async = Uninitialized, val keysBackupState: KeysBackupState? = null, val keysBackupVersion: KeysVersionResult? = null, + val remainingKeysToBackup: Int = 0, val deleteBackupRequest: Async = Uninitialized) : MavericksState + + diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt index 577572ef14..c177cf5da8 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt @@ -124,10 +124,7 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( style(ItemStyle.BIG_TEXT) hasIndeterminateProcess(true) - val totalKeys = host.session.cryptoService().inboundGroupSessionsCount(false) - val backedUpKeys = host.session.cryptoService().inboundGroupSessionsCount(true) - - val remainingKeysToBackup = totalKeys - backedUpKeys + val remainingKeysToBackup = data.remainingKeysToBackup if (data.keysBackupVersionTrust()?.usable == false) { description(host.stringProvider.getString(R.string.keys_backup_settings_untrusted_backup).toEpoxyCharSequence()) diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt index 51213fcd38..8ca14e562a 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt @@ -18,7 +18,6 @@ package im.vector.app.features.crypto.keysbackup.settings import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.MavericksViewModelFactory -import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import dagger.assisted.Assisted import dagger.assisted.AssistedFactory @@ -32,7 +31,6 @@ import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener -import timber.log.Timber class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialState: KeysBackupSettingViewState, session: Session @@ -46,6 +44,7 @@ class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialS companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() + private val cryptoService = session.cryptoService() private val keysBackupService: KeysBackupService = session.cryptoService().keysBackupService() init { @@ -75,34 +74,12 @@ class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialS private fun getKeysBackupTrust() = withState { state -> val versionResult = keysBackupService.keysBackupVersion - Timber.d("BACKUP: HEEEEEEE $versionResult ${state.keysBackupVersionTrust}") - if (state.keysBackupVersionTrust is Uninitialized && versionResult != null) { - setState { - copy( - keysBackupVersionTrust = Loading(), - deleteBackupRequest = Uninitialized - ) - } - Timber.d("BACKUP: HEEEEEEE TWO") - - viewModelScope.launch { - try { - val data = keysBackupService.getKeysBackupTrust(versionResult) - Timber.d("BACKUP: HEEEE suceeeded $data") - setState { - copy( - keysBackupVersionTrust = Success(data) - ) - } - } catch (failure: Throwable) { - Timber.d("BACKUP: HEEEE FAILED $failure") - setState { - copy( - keysBackupVersionTrust = Fail(failure) - ) - } - } + setState { copy(deleteBackupRequest = Uninitialized) } + suspend { + keysBackupService.getKeysBackupTrust(versionResult) + }.execute { + copy(keysBackupVersionTrust = it) } } } @@ -119,10 +96,24 @@ class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialS keysBackupVersion = keysBackupService.keysBackupVersion ) } - + when (newState) { + KeysBackupState.BackingUp, KeysBackupState.WillBackUp -> updateKeysCount() + else -> Unit + } getKeysBackupTrust() } + private fun updateKeysCount() { + viewModelScope.launch { + val totalKeys = cryptoService.inboundGroupSessionsCount(false) + val backedUpKeys = cryptoService.inboundGroupSessionsCount(true) + val remainingKeysToBackup = totalKeys - backedUpKeys + setState { + copy(remainingKeysToBackup = remainingKeysToBackup) + } + } + } + private fun deleteCurrentBackup() { val keysBackupService = keysBackupService diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDrawerFragment.kt b/vector/src/main/java/im/vector/app/features/home/HomeDrawerFragment.kt index 1aee0257f4..174bd94706 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDrawerFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDrawerFragment.kt @@ -80,6 +80,7 @@ class HomeDrawerFragment @Inject constructor( } // Sign out views.homeDrawerHeaderSignoutView.debouncedClicks { + signout() sharedActionViewModel.post(HomeActivitySharedAction.CloseDrawer) SignOutUiWorker(requireActivity()).perform() } @@ -118,4 +119,8 @@ class HomeDrawerFragment @Inject constructor( navigator.openDebug(requireActivity()) } } + + private fun signout() { + + } } diff --git a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutActivity.kt b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutActivity.kt index 9acc81d0c2..bf445a7c34 100644 --- a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutActivity.kt +++ b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutActivity.kt @@ -95,7 +95,7 @@ class SoftLogoutActivity : LoginActivity() { MainActivity.restartApp(this, MainActivityArgs()) } - views.loginLoading.isVisible = softLogoutViewState.isLoading() + views.loginLoading.isVisible = softLogoutViewState.isLoading } companion object { diff --git a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutController.kt b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutController.kt index 0cd9cde547..74ce1ef615 100644 --- a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutController.kt +++ b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutController.kt @@ -34,6 +34,7 @@ import im.vector.app.features.signout.soft.epoxy.loginRedButtonItem import im.vector.app.features.signout.soft.epoxy.loginTextItem import im.vector.app.features.signout.soft.epoxy.loginTitleItem import im.vector.app.features.signout.soft.epoxy.loginTitleSmallItem +import org.matrix.android.sdk.api.extensions.orFalse import javax.inject.Inject class SoftLogoutController @Inject constructor( @@ -52,6 +53,7 @@ class SoftLogoutController @Inject constructor( override fun buildModels() { val safeViewState = viewState ?: return + if (safeViewState.hasUnsavedKeys is Incomplete) return buildHeader(safeViewState) buildForm(safeViewState) @@ -78,7 +80,7 @@ class SoftLogoutController @Inject constructor( state.userDisplayName, state.userId)) } - if (state.hasUnsavedKeys) { + if (state.hasUnsavedKeys().orFalse()) { loginTextItem { id("signText2") text(host.stringProvider.getString(R.string.soft_logout_signin_e2e_warning_notice)) diff --git a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutFragment.kt b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutFragment.kt index f40f35a6e2..44696f9505 100644 --- a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutFragment.kt +++ b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutFragment.kt @@ -32,6 +32,7 @@ import im.vector.app.features.login.AbstractLoginFragment import im.vector.app.features.login.LoginAction import im.vector.app.features.login.LoginMode import im.vector.app.features.login.LoginViewEvents +import org.matrix.android.sdk.api.extensions.orFalse import javax.inject.Inject /** @@ -118,7 +119,7 @@ class SoftLogoutFragment @Inject constructor( withState(softLogoutViewModel) { state -> cleanupUi() - val messageResId = if (state.hasUnsavedKeys) { + val messageResId = if (state.hasUnsavedKeys().orFalse()) { R.string.soft_logout_clear_data_dialog_e2e_warning_content } else { R.string.soft_logout_clear_data_dialog_content diff --git a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutViewModel.kt b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutViewModel.kt index 00422d8872..7bc88c2b7e 100644 --- a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutViewModel.kt @@ -69,7 +69,6 @@ class SoftLogoutViewModel @AssistedInject constructor( userId = userId, deviceId = session.sessionParams.deviceId.orEmpty(), userDisplayName = session.getUser(userId)?.displayName ?: userId, - hasUnsavedKeys = session.hasUnsavedKeys() ) } else { SoftLogoutViewState( @@ -77,17 +76,25 @@ class SoftLogoutViewModel @AssistedInject constructor( userId = "", deviceId = "", userDisplayName = "", - hasUnsavedKeys = false ) } } } init { + checkHasUnsavedKeys() // Get the supported login flow getSupportedLoginFlow() } + private fun checkHasUnsavedKeys() { + suspend { + session.hasUnsavedKeys() + }.execute { + copy(hasUnsavedKeys = it) + } + } + private fun getSupportedLoginFlow() { viewModelScope.launch { authenticationService.cancelPendingLoginOrRegistration() diff --git a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutViewState.kt b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutViewState.kt index 511711ab2f..2bed442fe8 100644 --- a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutViewState.kt +++ b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutViewState.kt @@ -30,13 +30,12 @@ data class SoftLogoutViewState( val userId: String, val deviceId: String, val userDisplayName: String, - val hasUnsavedKeys: Boolean, + val hasUnsavedKeys: Async = Uninitialized, val enteredPassword: String = "" ) : MavericksState { - fun isLoading(): Boolean { - return asyncLoginAction is Loading || + val isLoading: Boolean = + asyncLoginAction is Loading || // Keep loading when it is success because of the delay to switch to the next Activity asyncLoginAction is Success - } } diff --git a/vector/src/main/java/im/vector/app/features/workers/signout/ServerBackupStatusViewModel.kt b/vector/src/main/java/im/vector/app/features/workers/signout/ServerBackupStatusViewModel.kt index ded42e23e0..c35363d66f 100644 --- a/vector/src/main/java/im/vector/app/features/workers/signout/ServerBackupStatusViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/workers/signout/ServerBackupStatusViewModel.kt @@ -130,14 +130,14 @@ class ServerBackupStatusViewModel @AssistedInject constructor(@Assisted initialS /** * Safe way to get the number of keys to backup */ - fun getNumberOfKeysToBackup(): Int { + private suspend fun getNumberOfKeysToBackup(): Int { return session.cryptoService().inboundGroupSessionsCount(false) } /** * Safe way to tell if there are more keys on the server */ - fun canRestoreKeys(): Boolean { + private suspend fun canRestoreKeys(): Boolean { return session.cryptoService().keysBackupService().canRestoreKeys() } @@ -161,5 +161,5 @@ class ServerBackupStatusViewModel @AssistedInject constructor(@Assisted initialS } } - override fun handle(action: EmptyAction) {} + override fun handle(action: EmptyAction) = Unit } diff --git a/vector/src/main/java/im/vector/app/features/workers/signout/SignOutUiWorker.kt b/vector/src/main/java/im/vector/app/features/workers/signout/SignOutUiWorker.kt index 29c094bff4..66b69fd53c 100644 --- a/vector/src/main/java/im/vector/app/features/workers/signout/SignOutUiWorker.kt +++ b/vector/src/main/java/im/vector/app/features/workers/signout/SignOutUiWorker.kt @@ -17,17 +17,25 @@ package im.vector.app.features.workers.signout import androidx.fragment.app.FragmentActivity +import androidx.lifecycle.lifecycleScope import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R import im.vector.app.core.extensions.cannotLogoutSafely import im.vector.app.core.extensions.singletonEntryPoint import im.vector.app.features.MainActivity import im.vector.app.features.MainActivityArgs +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import org.matrix.android.sdk.api.session.Session class SignOutUiWorker(private val activity: FragmentActivity) { fun perform() { val session = activity.singletonEntryPoint().activeSessionHolder().getSafeActiveSession() ?: return + activity.lifecycleScope.perform(session) + } + + private fun CoroutineScope.perform(session: Session) = launch { if (session.cannotLogoutSafely()) { // The backup check on logout flow has to be displayed if there are keys in the store, and the keys backup state is not Ready val signOutDialog = SignOutBottomSheetDialogFragment.newInstance()