From 3f0ecc6674bf1bb723c70cd477baea7d933c0e27 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 18 Sep 2024 11:07:07 +0200 Subject: [PATCH] Resolve send failure verification : clearer message when unsigned device is from you --- .../messages/impl/actionlist/ActionListView.kt | 3 ++- .../crypto/sendfailure/VerifiedUserSendFailure.kt | 7 ++++--- .../sendfailure/VerifiedUserSendFailureFactory.kt | 8 ++++++-- .../ResolveVerifiedUserSendFailureStateProvider.kt | 2 +- .../resolve/ResolveVerifiedUserSendFailureView.kt | 9 +++++++-- .../ResolveVerifiedUserSendFailurePresenterTest.kt | 12 ++++++------ .../ui-strings/src/main/res/values/localazy.xml | 3 +++ 7 files changed, 29 insertions(+), 15 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt index 8c950012db..a81975bf46 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt @@ -374,7 +374,8 @@ private fun VerifiedUserSendFailureView( fun VerifiedUserSendFailure.headline(): String { return when (this) { is None -> "" - is UnsignedDevice -> stringResource(CommonStrings.screen_timeline_item_menu_send_failure_unsigned_device, userDisplayName) + is UnsignedDevice.FromOther -> stringResource(CommonStrings.screen_timeline_item_menu_send_failure_unsigned_device, userDisplayName) + is UnsignedDevice.FromYou -> stringResource(CommonStrings.screen_timeline_item_menu_send_failure_you_unsigned_device) is ChangedIdentity -> stringResource(CommonStrings.screen_timeline_item_menu_send_failure_changed_identity, userDisplayName) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailure.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailure.kt index e3c798f7df..13a26a8bdb 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailure.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailure.kt @@ -13,9 +13,10 @@ import androidx.compose.runtime.Immutable sealed interface VerifiedUserSendFailure { data object None : VerifiedUserSendFailure - data class UnsignedDevice( - val userDisplayName: String, - ) : VerifiedUserSendFailure + sealed interface UnsignedDevice : VerifiedUserSendFailure { + data object FromYou : UnsignedDevice + data class FromOther(val userDisplayName: String) : UnsignedDevice + } data class ChangedIdentity( val userDisplayName: String, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailureFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailureFactory.kt index de5817c909..b96baed27d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailureFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailureFactory.kt @@ -23,8 +23,12 @@ class VerifiedUserSendFailureFactory @Inject constructor( if (userId == null) { VerifiedUserSendFailure.None } else { - val displayName = room.userDisplayName(userId).getOrNull() ?: userId.value - VerifiedUserSendFailure.UnsignedDevice(displayName) + if (userId == room.sessionId) { + VerifiedUserSendFailure.UnsignedDevice.FromYou + } else { + val displayName = room.userDisplayName(userId).getOrNull() ?: userId.value + VerifiedUserSendFailure.UnsignedDevice.FromOther(displayName) + } } } is LocalEventSendState.Failed.VerifiedUserChangedIdentity -> { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureStateProvider.kt index 1f8335b648..cdbdf6fcb0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureStateProvider.kt @@ -36,7 +36,7 @@ fun aResolveVerifiedUserSendFailureState( eventSink = eventSink ) -fun anUnsignedDeviceSendFailure(userDisplayName: String = "Alice") = VerifiedUserSendFailure.UnsignedDevice( +fun anUnsignedDeviceSendFailure(userDisplayName: String = "Alice") = VerifiedUserSendFailure.UnsignedDevice.FromOther( userDisplayName = userDisplayName, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt index e0d964fa51..fb602fa943 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt @@ -113,7 +113,11 @@ fun ResolveVerifiedUserSendFailureView( @Composable private fun VerifiedUserSendFailure.title(): String { return when (this) { - is VerifiedUserSendFailure.UnsignedDevice -> stringResource(id = CommonStrings.screen_resolve_send_failure_unsigned_device_title, userDisplayName) + is VerifiedUserSendFailure.UnsignedDevice.FromOther -> stringResource( + id = CommonStrings.screen_resolve_send_failure_unsigned_device_title, + userDisplayName + ) + VerifiedUserSendFailure.UnsignedDevice.FromYou -> stringResource(id = CommonStrings.screen_resolve_send_failure_you_unsigned_device_title) is VerifiedUserSendFailure.ChangedIdentity -> stringResource( id = CommonStrings.screen_resolve_send_failure_changed_identity_title, userDisplayName @@ -125,11 +129,12 @@ private fun VerifiedUserSendFailure.title(): String { @Composable private fun VerifiedUserSendFailure.subtitle(): String { return when (this) { - is VerifiedUserSendFailure.UnsignedDevice -> stringResource( + is VerifiedUserSendFailure.UnsignedDevice.FromOther -> stringResource( id = CommonStrings.screen_resolve_send_failure_unsigned_device_subtitle, userDisplayName, userDisplayName, ) + VerifiedUserSendFailure.UnsignedDevice.FromYou -> stringResource(id = CommonStrings.screen_resolve_send_failure_you_unsigned_device_subtitle) is VerifiedUserSendFailure.ChangedIdentity -> stringResource( id = CommonStrings.screen_resolve_send_failure_changed_identity_subtitle, userDisplayName diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenterTest.kt index 8d5884cf08..e74ae89b4f 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenterTest.kt @@ -94,7 +94,7 @@ class ResolveVerifiedUserSendFailurePresenterTest { initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(failedMessage)) skipItems(1) awaitItem().also { state -> - assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID.value)) + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromYou) state.eventSink(ResolveVerifiedUserSendFailureEvents.Dismiss) } skipItems(1) @@ -124,7 +124,7 @@ class ResolveVerifiedUserSendFailurePresenterTest { skipItems(1) awaitItem().also { state -> - assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID.value)) + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromYou) state.eventSink(ResolveVerifiedUserSendFailureEvents.Retry) } awaitItem().also { state -> @@ -158,7 +158,7 @@ class ResolveVerifiedUserSendFailurePresenterTest { skipItems(1) awaitItem().also { state -> - assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID.value)) + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromYou) state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) } awaitItem().also { state -> @@ -167,7 +167,7 @@ class ResolveVerifiedUserSendFailurePresenterTest { // This should move to the next user skipItems(2) awaitItem().also { state -> - assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID_2.value)) + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromOther(A_USER_ID_2.value)) assertThat(state.resolveAction).isEqualTo(AsyncAction.Success(Unit)) state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) } @@ -199,14 +199,14 @@ class ResolveVerifiedUserSendFailurePresenterTest { skipItems(1) awaitItem().also { state -> - assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID.value)) + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromYou) state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) } awaitItem().also { state -> assertThat(state.resolveAction).isEqualTo(AsyncAction.Loading) } awaitItem().also { state -> - assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID.value)) + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromYou) assertThat(state.resolveAction).isInstanceOf(AsyncAction.Failure::class.java) } ensureAllEventsConsumed() diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 8e2e7822bf..c71dd4d505 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -291,6 +291,8 @@ Reason: %1$s." "Send message anyway" "%1$s is using one or more unverified devices. You can send the message anyway, or you can cancel for now and try again later after %2$s has verified all their devices." "Your message was not sent because %1$s has not verified all devices" + "One or more of your devices are unverified. You can send the message anyway, or you can cancel for now and try again later after you have verified all of your devices." + "Your message was not sent because you have not verified one or more of your devices" "Pinned messages" "Failed processing media to upload, please try again." "Could not retrieve user details" @@ -314,6 +316,7 @@ Reason: %1$s." "Share this location" "Message not sent because %1$s’s verified identity has changed." "Message not sent because %1$s has not verified all devices." + "Message not sent because you have not verified one or more of your devices." "Location" "Version: %1$s (%2$s)" "en"