Skip to content

Commit

Permalink
fix: handle NoCommonProtocol error while starting conversation
Browse files Browse the repository at this point in the history
  • Loading branch information
borichellow committed Jun 24, 2024
1 parent ab3cabe commit 2f2a3b2
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -51,6 +52,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
Expand Down Expand Up @@ -98,7 +100,7 @@ fun ConnectionActionButton(
loading = viewModel.actionableState().isPerformingAction,
onClick = {
viewModel.onOpenConversation(onOpenConversation) {
unableStartConversationDialogState.show(UnableStartConversationDialogState(fullName))
unableStartConversationDialogState.show(UnableStartConversationDialogState(fullName, it))
}
},
)
Expand Down Expand Up @@ -189,16 +191,60 @@ fun ConnectionActionButton(
@Composable
fun UnableStartConversationDialogContent(dialogState: VisibilityState<UnableStartConversationDialogState>) {
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,
Expand All @@ -209,7 +255,7 @@ fun UnableStartConversationDialogContent(dialogState: VisibilityState<UnableStar
}
}

data class UnableStartConversationDialogState(val userName: String)
data class UnableStartConversationDialogState(val userName: String, val error: CoreFailure)

@Composable
@PreviewMultipleThemes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ interface ConnectionActionButtonViewModel {
fun onAcceptConnectionRequest() {}
fun onIgnoreConnectionRequest(onSuccess: (userName: String) -> Unit) {}
fun onUnblockUser() {}
fun onOpenConversation(onSuccess: (conversationId: ConversationId) -> Unit, onMissingKeyPackages: () -> Unit) {}
fun onOpenConversation(onSuccess: (conversationId: ConversationId) -> Unit, onFailure: (CoreFailure) -> Unit) {}
}

@Suppress("LongParameterList", "TooManyFunctions")
Expand Down Expand Up @@ -193,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)
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,10 @@
<!-- Missing keyPackages dialog -->
<string name="missing_keypackage_dialog_title">Unable to start conversation</string>
<string name="missing_keypackage_dialog_body">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.</string>
<!-- No Common protocol dialog -->
<string name="no_common_protocol_dialog_title">Unable to start conversation</string>
<string name="no_common_protocol_dialog_body_self_need_update">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.</string>
<string name="no_common_protocol_dialog_body_other_need_update">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.</string>
<!-- Gallery -->
<string name="media_gallery_default_title_name">Media Gallery</string>
<string name="media_gallery_on_image_downloaded">Saved to Downloads folder</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,14 +248,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
Expand All @@ -267,33 +267,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 {
Expand Down Expand Up @@ -337,7 +338,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(
Expand Down
2 changes: 1 addition & 1 deletion kalium
Submodule kalium updated 22 files
+10 βˆ’1 logic/src/commonMain/kotlin/com/wire/kalium/logic/CoreFailure.kt
+6 βˆ’2 logic/src/commonMain/kotlin/com/wire/kalium/logic/configuration/E2EISettings.kt
+30 βˆ’22 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/e2ei/CertificateRevocationListRepository.kt
+6 βˆ’2 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/featureConfig/FeatureConfigMapper.kt
+3 βˆ’1 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/featureConfig/FeatureConfigModel.kt
+2 βˆ’1 logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt
+4 βˆ’2 logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/featureConfig/handler/E2EIConfigHandler.kt
+2 βˆ’1 logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/protocol/OneOnOneProtocolSelector.kt
+84 βˆ’1 logic/src/commonTest/kotlin/com/wire/kalium/logic/data/e2ei/CertificateRevocationListRepositoryTest.kt
+4 βˆ’4 logic/src/commonTest/kotlin/com/wire/kalium/logic/data/e2ei/E2EIRepositoryTest.kt
+1 βˆ’1 logic/src/commonTest/kotlin/com/wire/kalium/logic/data/event/FeatureConfigMapperTest.kt
+2 βˆ’2 logic/src/commonTest/kotlin/com/wire/kalium/logic/data/featureConfig/FeatureConfigRepositoryTest.kt
+1 βˆ’1 logic/src/commonTest/kotlin/com/wire/kalium/logic/data/featureConfig/FeatureConfigTest.kt
+1 βˆ’1 logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/client/ObserveE2EIRequiredUseCaseTest.kt
+1 βˆ’1 logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/client/RegisterMLSClientUseCaseTest.kt
+1 βˆ’1 .../commonTest/kotlin/com/wire/kalium/logic/feature/conversation/GetOrCreateOneToOneConversationUseCaseTest.kt
+1 βˆ’1 logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/featureConfig/SyncFeatureConfigsUseCaseTest.kt
+16 βˆ’1 logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/protocol/OneOnOneProtocolSelectorTest.kt
+4 βˆ’0 ...rc/commonMain/kotlin/com/wire/kalium/network/api/base/authenticated/featureConfigs/FeatureConfigResponse.kt
+5 βˆ’5 network/src/commonMain/kotlin/com/wire/kalium/network/api/base/unbound/acme/ACMEApi.kt
+1 βˆ’1 network/src/commonTest/kotlin/com/wire/kalium/model/FeatureConfigJson.kt
+2 βˆ’0 persistence/src/commonMain/kotlin/com/wire/kalium/persistence/config/UserConfigStorage.kt

0 comments on commit 2f2a3b2

Please sign in to comment.