From c89a8b95df29dad32032d811dd721218391eb3d0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 16 Sep 2025 18:03:05 +0200 Subject: [PATCH 1/3] Add preview with a11y details. --- .../features/messages/impl/MessagesView.kt | 64 +++++++++++++++++++ .../roomdetails/impl/RoomDetailsView.kt | 9 +++ 2 files changed, 73 insertions(+) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index 5479836bb3..ea50cf0fe2 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -46,6 +46,7 @@ import androidx.compose.ui.semantics.role import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme @@ -68,6 +69,10 @@ import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBan import io.element.android.features.messages.impl.timeline.FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS import io.element.android.features.messages.impl.timeline.TimelineEvents import io.element.android.features.messages.impl.timeline.TimelineView +import io.element.android.features.messages.impl.timeline.aGroupedEvents +import io.element.android.features.messages.impl.timeline.aTimelineItemDaySeparator +import io.element.android.features.messages.impl.timeline.aTimelineItemEvent +import io.element.android.features.messages.impl.timeline.aTimelineState import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionBottomSheet import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionEvents import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvents @@ -75,6 +80,9 @@ import io.element.android.features.messages.impl.timeline.components.reactionsum import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheet import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetEvents import io.element.android.features.messages.impl.timeline.model.TimelineItem +import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition +import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemStateEventContent +import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent import io.element.android.features.messages.impl.topbars.MessagesViewTopBar import io.element.android.features.messages.impl.topbars.ThreadTopBar import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessagePermissionRationaleDialog @@ -103,10 +111,12 @@ import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.textcomposer.model.TextEditorState import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.wysiwyg.link.Link +import kotlinx.collections.immutable.persistentListOf import timber.log.Timber import kotlin.time.Duration.Companion.milliseconds @@ -572,3 +582,57 @@ internal fun MessagesViewPreview(@PreviewParameter(MessagesStateProvider::class) knockRequestsBannerView = {}, ) } + +@Preview +@Composable +internal fun MessagesViewA11yPreview() = ElementPreview { + val content = aTimelineItemTextContent( + body = "A message content" + ) + MessagesView( + state = aMessagesState( + roomName = "A DM with a very looong name", + dmUserVerificationState = IdentityState.VerificationViolation, + timelineState = aTimelineState( + timelineItems = persistentListOf( + // 1 items with isMine = false + aTimelineItemEvent( + isMine = false, + content = content, + groupPosition = TimelineItemGroupPosition.None, + sendState = LocalEventSendState.Failed.Unknown("Message failed to send"), + ), + // A state event on top of it + aTimelineItemEvent( + isMine = false, + content = aTimelineItemStateEventContent(), + groupPosition = TimelineItemGroupPosition.None + ), + // 1 item with isMine = true + aTimelineItemEvent( + isMine = true, + content = content, + groupPosition = TimelineItemGroupPosition.None + ), + // A grouped event on top of it + aGroupedEvents(), + // A day separator + aTimelineItemDaySeparator(), + ), + // Render a focused event for an event with sender information displayed + focusedEventIndex = 2, + ) + ), + onBackClick = {}, + onRoomDetailsClick = {}, + onEventContentClick = { _, _ -> false }, + onUserDataClick = {}, + onLinkClick = { _, _ -> }, + onSendLocationClick = {}, + onCreatePollClick = {}, + onJoinCallClick = {}, + onViewAllPinnedMessagesClick = { }, + forceJumpToBottomVisibility = true, + knockRequestsBannerView = {}, + ) +} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index 05f26daedb..86481be026 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -59,6 +59,7 @@ import io.element.android.libraries.designsystem.components.list.ListItemContent import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch import io.element.android.libraries.designsystem.modifiers.niceClickable +import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.PreviewWithLargeHeight @@ -768,6 +769,14 @@ internal fun RoomDetailsPreview(@PreviewParameter(RoomDetailsStateProvider::clas internal fun RoomDetailsDarkPreview(@PreviewParameter(RoomDetailsStateProvider::class) state: RoomDetailsState) = ElementPreviewDark { ContentToPreview(state) } +@PreviewWithLargeHeight +@Composable +internal fun RoomDetailsA11yPreview() = ElementPreview { + ContentToPreview( + state = aRoomDetailsState(displayAdminSettings = true) + ) +} + @ExcludeFromCoverage @Composable private fun ContentToPreview(state: RoomDetailsState) { From 5b95e8c480f33dd226ed3cd8e56824db7713067c Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 9 Jan 2026 13:57:10 +0000 Subject: [PATCH 2/3] Update screenshots --- .../images/features.messages.impl_MessagesViewA11y_en.png | 3 +++ .../images/features.roomdetails.impl_RoomDetailsA11y_en.png | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png new file mode 100644 index 0000000000..08972f09ac --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:769dd2d263461b4a4597ca6ca08fb5c9e93cf3b3c25121c9dc1451e4fd0ad9c6 +size 133844 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png new file mode 100644 index 0000000000..1076b7d302 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c057a0a0a7656f4fc77180902962aa14e0422442f139248dbdcfef0fb4216f43 +size 79689 From bd5857ae2353120516614c55c867e8320f0471ce Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 9 Jan 2026 15:36:10 +0100 Subject: [PATCH 3/3] Fix konsist test. --- .../io/element/android/tests/konsist/KonsistPreviewTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt index 32f2908cf7..b7ee2d5743 100644 --- a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt +++ b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt @@ -47,7 +47,7 @@ class KonsistPreviewTest { " and should be internal." ) { val testedView = it.name.removeSuffix("A11yPreview") - it.text.contains("$testedView(") && + (it.text.contains("$testedView(") || it.text.contains("ContentToPreview(")) && it.hasAllAnnotationsOf(PreviewsDayNight::class).not() && it.text.contains("ElementPreview") && it.hasInternalModifier