From 91bb89ed082d4b857f7ee8eb114560e9addfbe4f Mon Sep 17 00:00:00 2001 From: boris Date: Fri, 28 Jun 2024 10:38:48 +0300 Subject: [PATCH] fix: handle NoCommonProtocol error while starting conversation cherry-pick (#3138) --- .../ui/connection/ConnectionActionButton.kt | 68 ++++++++++++++++--- .../ConnectionActionButtonViewModel.kt | 14 ++-- app/src/main/res/values/strings.xml | 4 ++ .../ConnectionActionButtonViewModelTest.kt | 17 ++--- kalium | 2 +- 5 files changed, 80 insertions(+), 25 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/connection/ConnectionActionButton.kt b/app/src/main/kotlin/com/wire/android/ui/connection/ConnectionActionButton.kt index 08a521a0277..59958c3bc3b 100644 --- a/app/src/main/kotlin/com/wire/android/ui/connection/ConnectionActionButton.kt +++ b/app/src/main/kotlin/com/wire/android/ui/connection/ConnectionActionButton.kt @@ -29,6 +29,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.AnnotatedString import com.wire.android.R import com.wire.android.di.hiltViewModelScoped import com.wire.android.model.ClickBlockParams @@ -52,6 +53,7 @@ import com.wire.android.ui.theme.WireTheme import com.wire.android.ui.theme.wireTypography import com.wire.android.util.ui.PreviewMultipleThemes import com.wire.android.util.ui.stringWithStyledArgs +import com.wire.kalium.logic.CoreFailure import com.wire.kalium.logic.data.id.ConversationId import com.wire.kalium.logic.data.user.ConnectionState import com.wire.kalium.logic.data.user.UserId @@ -105,7 +107,7 @@ fun ConnectionActionButton( loading = viewModel.actionableState().isPerformingAction, onClick = { viewModel.onOpenConversation(onOpenConversation) { - unableStartConversationDialogState.show(UnableStartConversationDialogState(fullName)) + unableStartConversationDialogState.show(UnableStartConversationDialogState(fullName, it)) } }, ) @@ -196,16 +198,60 @@ fun ConnectionActionButton( @Composable fun UnableStartConversationDialogContent(dialogState: VisibilityState) { VisibilityState(dialogState) { state -> + val title: String + val text: AnnotatedString + + when (state.error) { + is CoreFailure.MissingKeyPackages -> { + title = stringResource(id = R.string.missing_keypackage_dialog_title) + text = LocalContext.current.resources.stringWithStyledArgs( + R.string.missing_keypackage_dialog_body, + MaterialTheme.wireTypography.body01, + MaterialTheme.wireTypography.body02, + colorsScheme().onBackground, + colorsScheme().onBackground, + state.userName + ) + } + + is CoreFailure.NoCommonProtocolFound.SelfNeedToUpdate -> { + title = stringResource(id = R.string.missing_keypackage_dialog_title) + text = LocalContext.current.resources.stringWithStyledArgs( + R.string.no_common_protocol_dialog_body_self_need_update, + MaterialTheme.wireTypography.body01, + MaterialTheme.wireTypography.body02, + colorsScheme().onBackground, + colorsScheme().onBackground, + state.userName + ) + } + + is CoreFailure.NoCommonProtocolFound.OtherNeedToUpdate -> { + title = stringResource(id = R.string.missing_keypackage_dialog_title) + text = LocalContext.current.resources.stringWithStyledArgs( + R.string.no_common_protocol_dialog_body_other_need_update, + MaterialTheme.wireTypography.body01, + MaterialTheme.wireTypography.body02, + colorsScheme().onBackground, + colorsScheme().onBackground, + state.userName + ) + } + + else -> { + title = stringResource(id = R.string.error_unknown_title) + text = LocalContext.current.resources.stringWithStyledArgs( + R.string.error_unknown_message, + MaterialTheme.wireTypography.body01, + MaterialTheme.wireTypography.body02, + colorsScheme().onBackground, + colorsScheme().onBackground + ) + } + } WireDialog( - title = stringResource(id = R.string.missing_keypackage_dialog_title), - text = LocalContext.current.resources.stringWithStyledArgs( - R.string.missing_keypackage_dialog_body, - MaterialTheme.wireTypography.body01, - MaterialTheme.wireTypography.body02, - colorsScheme().onBackground, - colorsScheme().onBackground, - state.userName - ), + title = title, + text = text, onDismiss = dialogState::dismiss, optionButton1Properties = WireDialogButtonProperties( onClick = dialogState::dismiss, @@ -216,7 +262,7 @@ fun UnableStartConversationDialogContent(dialogState: VisibilityState get() = MutableSharedFlow() + fun actionableState(): ConnectionActionState = ConnectionActionState() fun onSendConnectionRequest() {} fun onCancelConnectionRequest() {} @@ -66,7 +67,7 @@ interface ConnectionActionButtonViewModel { fun onUnblockUser() {} fun onOpenConversation(onSuccess: (conversationId: ConversationId) -> Unit) {} fun onMissingLegalHoldConsentDismissed() {} - fun onOpenConversation(onSuccess: (conversationId: ConversationId) -> Unit, onMissingKeyPackages: () -> Unit) {} + fun onOpenConversation(onSuccess: (conversationId: ConversationId) -> Unit, onFailure: (CoreFailure) -> Unit) {} } @Suppress("LongParameterList", "TooManyFunctions") @@ -192,14 +193,17 @@ class ConnectionActionButtonViewModelImpl @Inject constructor( } } - override fun onOpenConversation(onSuccess: (conversationId: ConversationId) -> Unit, onMissingKeyPackages: () -> Unit) { + override fun onOpenConversation( + onSuccess: (conversationId: ConversationId) -> Unit, + onFailure: (error: CoreFailure) -> Unit + ) { viewModelScope.launch { state = state.performAction() when (val result = withContext(dispatchers.io()) { getOrCreateOneToOneConversation(userId) }) { is CreateConversationResult.Failure -> { - appLogger.d(("Couldn't retrieve or create the conversation")) + appLogger.d(("Couldn't retrieve or create the conversation. Error ${result.coreFailure}")) state = state.finishAction() - if (result.coreFailure is CoreFailure.MissingKeyPackages) onMissingKeyPackages() + onFailure(result.coreFailure) } is CreateConversationResult.Success -> onSuccess(result.conversation.id) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c05a58dc5ba..5211db31a0d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -899,6 +899,10 @@ Unable to start conversation You can’t start the conversation with %1$s right now. %1$s needs to open Wire or log in again first. Please try again later. + + Unable to start conversation + You can’t communicate with %1$s, as your device doesn’t support the suitable protocol. Download the latest MLS Wire version, to call, and send messages and files. + You can’t communicate with %1$s, as you two use different protocols. When %1$s gets an update, you can call and send messages and files. Media Gallery Saved to Downloads folder diff --git a/app/src/test/kotlin/com/wire/android/ui/connection/ConnectionActionButtonViewModelTest.kt b/app/src/test/kotlin/com/wire/android/ui/connection/ConnectionActionButtonViewModelTest.kt index 1ca42505d07..6edc8b2cc6f 100644 --- a/app/src/test/kotlin/com/wire/android/ui/connection/ConnectionActionButtonViewModelTest.kt +++ b/app/src/test/kotlin/com/wire/android/ui/connection/ConnectionActionButtonViewModelTest.kt @@ -267,14 +267,14 @@ class ConnectionActionButtonViewModelTest { .arrange() // when - viewModel.onOpenConversation(arrangement.onOpenConversation, arrangement.onMissingKeyPackages) + viewModel.onOpenConversation(arrangement.onOpenConversation, arrangement.onStartConversationError) // then coVerify { arrangement.getOrCreateOneToOneConversation(TestUser.USER_ID) } verify { arrangement.onOpenConversation(any()) } - verify { arrangement.onMissingKeyPackages wasNot Called } + verify { arrangement.onStartConversationError wasNot Called } } @Test @@ -286,33 +286,34 @@ class ConnectionActionButtonViewModelTest { .arrange() // when - viewModel.onOpenConversation(arrangement.onOpenConversation, arrangement.onMissingKeyPackages) + viewModel.onOpenConversation(arrangement.onOpenConversation, arrangement.onStartConversationError) // then coVerify { arrangement.getOrCreateOneToOneConversation(TestUser.USER_ID) } verify { arrangement.onOpenConversation wasNot Called } - verify { arrangement.onMissingKeyPackages wasNot Called } + verify { arrangement.onStartConversationError(eq(failure)) } } @Test fun `given a conversationId, when trying to open the conversation and fails with MissingKeyPackages, then call MissingKeyPackage()`() = runTest { // given + val errorResult = CoreFailure.MissingKeyPackages(setOf()) val (arrangement, viewModel) = ConnectionActionButtonHiltArrangement() - .withGetOneToOneConversation(CreateConversationResult.Failure(CoreFailure.MissingKeyPackages(setOf()))) + .withGetOneToOneConversation(CreateConversationResult.Failure(errorResult)) .arrange() // when - viewModel.onOpenConversation(arrangement.onOpenConversation, arrangement.onMissingKeyPackages) + viewModel.onOpenConversation(arrangement.onOpenConversation, arrangement.onStartConversationError) // then coVerify { arrangement.getOrCreateOneToOneConversation(TestUser.USER_ID) } verify { arrangement.onOpenConversation wasNot Called } - verify { arrangement.onMissingKeyPackages() } + verify { arrangement.onStartConversationError(eq(errorResult)) } } companion object { @@ -356,7 +357,7 @@ internal class ConnectionActionButtonHiltArrangement { lateinit var onOpenConversation: (conversationId: ConversationId) -> Unit @MockK(relaxed = true) - lateinit var onMissingKeyPackages: () -> Unit + lateinit var onStartConversationError: (CoreFailure) -> Unit private val viewModel by lazy { ConnectionActionButtonViewModelImpl( diff --git a/kalium b/kalium index 414163558bc..8b38a32b4c5 160000 --- a/kalium +++ b/kalium @@ -1 +1 @@ -Subproject commit 414163558bca7ddd3720bc5963ef5d3425843f39 +Subproject commit 8b38a32b4c51c2800ddfdc9fe1c89101e5a60231