Browse Source

Merge pull request #3686 from element-hq/feature/bma/identityChangeWording

Add userId in identity change warning banner
pull/3673/head
Benoit Marty 2 days ago committed by GitHub
parent
commit
ce318b3719
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStatePresenter.kt
  2. 24
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStateProvider.kt
  3. 20
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStateView.kt
  4. 2
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityRoomMember.kt
  5. 9
      features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStatePresenterTest.kt
  6. 5
      libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/UserId.kt
  7. 6
      libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMember.kt
  8. 2
      libraries/ui-strings/src/main/res/values/localazy.xml
  9. 4
      tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en.png
  10. 3
      tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en.png
  11. 4
      tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en.png
  12. 3
      tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en.png
  13. 4
      tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en.png
  14. 3
      tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en.png
  15. 4
      tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en.png
  16. 3
      tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en.png

4
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStatePresenter.kt

@ -105,13 +105,13 @@ class IdentityChangeStatePresenter @Inject constructor(
private fun RoomMember.toIdentityRoomMember() = IdentityRoomMember( private fun RoomMember.toIdentityRoomMember() = IdentityRoomMember(
userId = userId, userId = userId,
disambiguatedDisplayName = disambiguatedDisplayName, displayNameOrDefault = displayNameOrDefault,
avatarData = getAvatarData(AvatarSize.ComposerAlert), avatarData = getAvatarData(AvatarSize.ComposerAlert),
) )
private fun createDefaultRoomMemberForIdentityChange(userId: UserId) = IdentityRoomMember( private fun createDefaultRoomMemberForIdentityChange(userId: UserId) = IdentityRoomMember(
userId = userId, userId = userId,
disambiguatedDisplayName = userId.value, displayNameOrDefault = userId.extractedDisplayName,
avatarData = AvatarData( avatarData = AvatarData(
id = userId.value, id = userId.value,
name = null, name = null,

24
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStateProvider.kt

@ -20,8 +20,16 @@ class IdentityChangeStateProvider : PreviewParameterProvider<IdentityChangeState
anIdentityChangeState(), anIdentityChangeState(),
anIdentityChangeState( anIdentityChangeState(
roomMemberIdentityStateChanges = listOf( roomMemberIdentityStateChanges = listOf(
RoomMemberIdentityStateChange( aRoomMemberIdentityStateChange(
identityRoomMember = anIdentityRoomMember(disambiguatedDisplayName = "Alice"), identityRoomMember = anIdentityRoomMember(),
identityState = IdentityState.PinViolation,
),
),
),
anIdentityChangeState(
roomMemberIdentityStateChanges = listOf(
aRoomMemberIdentityStateChange(
identityRoomMember = anIdentityRoomMember(displayNameOrDefault = "Alice"),
identityState = IdentityState.PinViolation, identityState = IdentityState.PinViolation,
), ),
), ),
@ -29,6 +37,14 @@ class IdentityChangeStateProvider : PreviewParameterProvider<IdentityChangeState
) )
} }
internal fun aRoomMemberIdentityStateChange(
identityRoomMember: IdentityRoomMember = anIdentityRoomMember(),
identityState: IdentityState = IdentityState.PinViolation,
) = RoomMemberIdentityStateChange(
identityRoomMember = identityRoomMember,
identityState = identityState,
)
internal fun anIdentityChangeState( internal fun anIdentityChangeState(
roomMemberIdentityStateChanges: List<RoomMemberIdentityStateChange> = emptyList(), roomMemberIdentityStateChanges: List<RoomMemberIdentityStateChange> = emptyList(),
) = IdentityChangeState( ) = IdentityChangeState(
@ -38,7 +54,7 @@ internal fun anIdentityChangeState(
internal fun anIdentityRoomMember( internal fun anIdentityRoomMember(
userId: UserId = UserId("@alice:example.com"), userId: UserId = UserId("@alice:example.com"),
disambiguatedDisplayName: String = userId.value, displayNameOrDefault: String = userId.extractedDisplayName,
avatarData: AvatarData = AvatarData( avatarData: AvatarData = AvatarData(
id = userId.value, id = userId.value,
name = null, name = null,
@ -47,6 +63,6 @@ internal fun anIdentityRoomMember(
), ),
) = IdentityRoomMember( ) = IdentityRoomMember(
userId = userId, userId = userId,
disambiguatedDisplayName = disambiguatedDisplayName, displayNameOrDefault = displayNameOrDefault,
avatarData = avatarData, avatarData = avatarData,
) )

20
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStateView.kt

@ -40,13 +40,27 @@ fun IdentityChangeStateView(
avatar = pinViolationIdentityChange.identityRoomMember.avatarData, avatar = pinViolationIdentityChange.identityRoomMember.avatarData,
content = buildAnnotatedString { content = buildAnnotatedString {
val learnMoreStr = stringResource(CommonStrings.action_learn_more) val learnMoreStr = stringResource(CommonStrings.action_learn_more)
val displayName = pinViolationIdentityChange.identityRoomMember.displayNameOrDefault
val userIdStr = stringResource(
CommonStrings.crypto_identity_change_pin_violation_new_user_id,
pinViolationIdentityChange.identityRoomMember.userId,
)
val fullText = stringResource( val fullText = stringResource(
id = CommonStrings.crypto_identity_change_pin_violation, id = CommonStrings.crypto_identity_change_pin_violation_new,
pinViolationIdentityChange.identityRoomMember.disambiguatedDisplayName, displayName,
userIdStr,
learnMoreStr, learnMoreStr,
) )
val learnMoreStartIndex = fullText.indexOf(learnMoreStr)
append(fullText) append(fullText)
val userIdStartIndex = fullText.indexOf(userIdStr)
addStyle(
style = SpanStyle(
fontWeight = FontWeight.Bold,
),
start = userIdStartIndex,
end = userIdStartIndex + userIdStr.length,
)
val learnMoreStartIndex = fullText.lastIndexOf(learnMoreStr)
addStyle( addStyle(
style = SpanStyle( style = SpanStyle(
textDecoration = TextDecoration.Underline, textDecoration = TextDecoration.Underline,

2
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityRoomMember.kt

@ -12,6 +12,6 @@ import io.element.android.libraries.matrix.api.core.UserId
data class IdentityRoomMember( data class IdentityRoomMember(
val userId: UserId, val userId: UserId,
val disambiguatedDisplayName: String, val displayNameOrDefault: String,
val avatarData: AvatarData, val avatarData: AvatarData,
) )

9
features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStatePresenterTest.kt

@ -69,7 +69,7 @@ class IdentityChangeStatePresenterTest {
} }
@Test @Test
fun `present - when the room emits identity change, but the feature is disabled, the presenter emits new state`() = runTest { fun `present - when the room emits identity change, but the feature is disabled, the presenter does not emit new state`() = runTest {
val room = FakeMatrixRoom( val room = FakeMatrixRoom(
isEncrypted = true, isEncrypted = true,
) )
@ -106,7 +106,7 @@ class IdentityChangeStatePresenterTest {
} }
@Test @Test
fun `present - when the clear room emits identity change, the presenter does not emits new state`() = runTest { fun `present - when the clear room emits identity change, the presenter does not emit new state`() = runTest {
val room = FakeMatrixRoom(isEncrypted = false) val room = FakeMatrixRoom(isEncrypted = false)
val presenter = createIdentityChangeStatePresenter(room) val presenter = createIdentityChangeStatePresenter(room)
presenter.test { presenter.test {
@ -128,6 +128,7 @@ class IdentityChangeStatePresenterTest {
assertThat(finalItem.roomMemberIdentityStateChanges).hasSize(1) assertThat(finalItem.roomMemberIdentityStateChanges).hasSize(1)
val value = finalItem.roomMemberIdentityStateChanges.first() val value = finalItem.roomMemberIdentityStateChanges.first()
assertThat(value.identityRoomMember.userId).isEqualTo(A_USER_ID_2) assertThat(value.identityRoomMember.userId).isEqualTo(A_USER_ID_2)
assertThat(value.identityRoomMember.displayNameOrDefault).isEqualTo(A_USER_ID_2.extractedDisplayName)
assertThat(value.identityState).isEqualTo(IdentityState.PinViolation) assertThat(value.identityState).isEqualTo(IdentityState.PinViolation)
} }
} }
@ -163,14 +164,14 @@ class IdentityChangeStatePresenterTest {
assertThat(finalItem.roomMemberIdentityStateChanges).hasSize(1) assertThat(finalItem.roomMemberIdentityStateChanges).hasSize(1)
val value = finalItem.roomMemberIdentityStateChanges.first() val value = finalItem.roomMemberIdentityStateChanges.first()
assertThat(value.identityRoomMember.userId).isEqualTo(A_USER_ID_2) assertThat(value.identityRoomMember.userId).isEqualTo(A_USER_ID_2)
assertThat(value.identityRoomMember.disambiguatedDisplayName).isEqualTo("Alice") assertThat(value.identityRoomMember.displayNameOrDefault).isEqualTo("Alice")
assertThat(value.identityRoomMember.avatarData.size).isEqualTo(AvatarSize.ComposerAlert) assertThat(value.identityRoomMember.avatarData.size).isEqualTo(AvatarSize.ComposerAlert)
assertThat(value.identityState).isEqualTo(IdentityState.PinViolation) assertThat(value.identityState).isEqualTo(IdentityState.PinViolation)
} }
} }
@Test @Test
fun `present - when the user pin the identity, the presenter invokes the encryption service api`() = fun `present - when the user pins the identity, the presenter invokes the encryption service api`() =
runTest { runTest {
val lambda = lambdaRecorder<UserId, Result<Unit>> { Result.success(Unit) } val lambda = lambdaRecorder<UserId, Result<Unit>> { Result.success(Unit) }
val encryptionService = FakeEncryptionService( val encryptionService = FakeEncryptionService(

5
libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/UserId.kt

@ -24,4 +24,9 @@ value class UserId(val value: String) : Serializable {
} }
override fun toString(): String = value override fun toString(): String = value
val extractedDisplayName: String
get() = value
.removePrefix("@")
.substringBefore(":")
} }

6
libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMember.kt

@ -51,6 +51,12 @@ data class RoomMember(
isNameAmbiguous -> "$displayName ($userId)" isNameAmbiguous -> "$displayName ($userId)"
else -> displayName else -> displayName
} }
val displayNameOrDefault: String
get() = when {
displayName == null -> userId.extractedDisplayName
else -> displayName
}
} }
enum class RoomMembershipState { enum class RoomMembershipState {

2
libraries/ui-strings/src/main/res/values/localazy.xml

@ -252,6 +252,8 @@ Reason: %1$s."</string>
<string name="common_waiting_for_decryption_key">"Waiting for this message"</string> <string name="common_waiting_for_decryption_key">"Waiting for this message"</string>
<string name="common_you">"You"</string> <string name="common_you">"You"</string>
<string name="crypto_identity_change_pin_violation">"%1$s\'s identity appears to have changed. %2$s"</string> <string name="crypto_identity_change_pin_violation">"%1$s\'s identity appears to have changed. %2$s"</string>
<string name="crypto_identity_change_pin_violation_new">"%1$s’s %2$s identity appears to have changed. %3$s"</string>
<string name="crypto_identity_change_pin_violation_new_user_id">"(%1$s)"</string>
<string name="dialog_title_confirmation">"Confirmation"</string> <string name="dialog_title_confirmation">"Confirmation"</string>
<string name="dialog_title_error">"Error"</string> <string name="dialog_title_error">"Error"</string>
<string name="dialog_title_success">"Success"</string> <string name="dialog_title_success">"Success"</string>

4
tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:24481773bfccc5eb1ebf3f9955cdc77e8b3b5130d4fa56f96df732e3627ea3c6 oid sha256:66419e3ac6da49bd535a005759cba38fe4b57d5307ad9ad3cb3e2fa4eed38890
size 21018 size 25136

3
tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:35651217adb52b19136f99922d7573071084ae7c4109feb525d182274ab4df78
size 25131

4
tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:1421adb601d9a8050a5ed1b60aba8a05b8eab61aaf18d3936226efe891acd8b6 oid sha256:d2831daee948b612f15623948ef49c497732a143fa50f331e82e689decd5a4c0
size 23880 size 27967

3
tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3055ebf4ef01148506cac22bfd7c05aea5315d4a63952affc998c918cd6055b6
size 27880

4
tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:8d37a9ffee50f8e9ea0c9fd50c61310969c4fbaa99cf858481b3f42f8db4467d oid sha256:38b158a90790d6183df45914382ec16275ae8e4c5e7054c988d20d179cfebc44
size 61102 size 64996

3
tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b3b3a017453f60f98f245374089fa604848f5e764be20463d63b0ebc51eadd18
size 65118

4
tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:d0952d9cf3812ca419e144936faf523e0b865a22a61d2a55e07f089d9e6e9009 oid sha256:5c4f814532fb387a3a38de6fbbf31563884de658ab7d930fe5e91b3fd299f355
size 64824 size 69088

3
tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d9bfcbe306160d48ac80ad1a6c4e0d611da72a376bdfe3532ace022d9bbb5c9a
size 69181
Loading…
Cancel
Save