diff --git a/build.gradle.kts b/build.gradle.kts index 970dfe8465..9cbf6cd3cc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -200,6 +200,7 @@ koverMerged { "*Node$*", // Exclude `:libraries:matrix:impl` module, it contains only wrappers to access the Rust Matrix SDK api, so it is not really relevant to unit test it: there is no logic to test. "io.element.android.libraries.matrix.impl.*", + "*Presenter\$present\$*" ) ) } @@ -252,6 +253,7 @@ koverMerged { excludes += "io.element.android.appnav.loggedin.LoggedInPresenter$*" // Some options can't be tested at the moment excludes += "io.element.android.features.preferences.impl.developer.DeveloperSettingsPresenter$*" + excludes += "*Presenter\$present\$*" } bound { minValue = 85 diff --git a/changelog.d/1158.feature b/changelog.d/1158.feature new file mode 100644 index 0000000000..d2bf822649 --- /dev/null +++ b/changelog.d/1158.feature @@ -0,0 +1 @@ +Element Call: change the 'join call' button in a chat room when there's an active call. diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index adae018fee..ea9eade4b3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -21,6 +21,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -74,6 +75,7 @@ import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.room.MatrixRoomInfo import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo @@ -113,6 +115,7 @@ class MessagesPresenter @AssistedInject constructor( @Composable override fun present(): MessagesState { + val roomInfo by room.roomInfoFlow.collectAsState(null) val localCoroutineScope = rememberCoroutineScope() val composerState = composerPresenter.present() val voiceMessageComposerState = voiceMessageComposerPresenter.present() @@ -125,14 +128,13 @@ class MessagesPresenter @AssistedInject constructor( val syncUpdateFlow = room.syncUpdateFlow.collectAsState() val userHasPermissionToSendMessage by room.canSendMessageAsState(type = MessageEventType.ROOM_MESSAGE, updateKey = syncUpdateFlow.value) val userHasPermissionToRedact by room.canRedactAsState(updateKey = syncUpdateFlow.value) - var roomName: Async by remember { mutableStateOf(Async.Uninitialized) } - var roomAvatar: Async by remember { mutableStateOf(Async.Uninitialized) } - LaunchedEffect(syncUpdateFlow.value) { - withContext(dispatchers.io) { - roomName = Async.Success(room.displayName) - roomAvatar = Async.Success(room.avatarData()) - } + val roomName: Async by remember { + derivedStateOf { roomInfo?.name?.let { Async.Success(it) } ?: Async.Uninitialized } } + val roomAvatar: Async by remember { + derivedStateOf { roomInfo?.avatarData()?.let { Async.Success(it) } ?: Async.Uninitialized } + } + var hasDismissedInviteDialog by rememberSaveable { mutableStateOf(false) } @@ -207,14 +209,15 @@ class MessagesPresenter @AssistedInject constructor( enableVoiceMessages = enableVoiceMessages, enableInRoomCalls = enableInRoomCalls, appName = buildMeta.applicationName, + isCallOngoing = roomInfo?.hasRoomCall ?: false, eventSink = { handleEvents(it) } ) } - private fun MatrixRoom.avatarData(): AvatarData { + private fun MatrixRoomInfo.avatarData(): AvatarData { return AvatarData( - id = roomId.value, - name = displayName, + id = id, + name = name, url = avatarUrl, size = AvatarSize.TimelineRoom ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt index 86784edc7a..5bce4f19a1 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt @@ -50,6 +50,7 @@ data class MessagesState( val enableTextFormatting: Boolean, val enableVoiceMessages: Boolean, val enableInRoomCalls: Boolean, + val isCallOngoing: Boolean, val appName: String, val eventSink: (MessagesEvents) -> Unit ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt index 9d12207362..275b324862 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt @@ -63,6 +63,9 @@ open class MessagesStateProvider : PreviewParameterProvider { attachmentsState = AttachmentsState.Sending.Uploading(0.33f) ), ), + aMessagesState().copy( + isCallOngoing = true, + ) ) } @@ -102,6 +105,7 @@ fun aMessagesState() = MessagesState( enableTextFormatting = true, enableVoiceMessages = true, enableInRoomCalls = true, + isCallOngoing = false, appName = "Element", eventSink = {} ) 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 3ff07def41..9ecf63dd29 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 @@ -21,17 +21,21 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.width +import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable @@ -94,6 +98,7 @@ import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList import timber.log.Timber +import androidx.compose.material3.Button as Material3Button @Composable fun MessagesView( @@ -174,6 +179,7 @@ fun MessagesView( inRoomCallsEnabled = state.enableInRoomCalls, onBackPressed = onBackPressed, onRoomDetailsClicked = onRoomDetailsClicked, + isCallOngoing = state.isCallOngoing, onJoinCallClicked = onJoinCallClicked, ) } @@ -375,6 +381,7 @@ private fun MessagesViewTopBar( roomName: String?, roomAvatar: AvatarData?, inRoomCallsEnabled: Boolean, + isCallOngoing: Boolean, modifier: Modifier = Modifier, onRoomDetailsClicked: () -> Unit = {}, onJoinCallClicked: () -> Unit = {}, @@ -402,15 +409,48 @@ private fun MessagesViewTopBar( }, actions = { if (inRoomCallsEnabled) { - IconButton(onClick = onJoinCallClicked) { - Icon(CommonDrawables.ic_compound_video_call, contentDescription = null) // TODO add proper content description once we have the state + if (isCallOngoing) { + JoinCallMenuItem(onJoinCallClicked = onJoinCallClicked) + } else { + IconButton(onClick = onJoinCallClicked) { + Icon(CommonDrawables.ic_compound_video_call, contentDescription = stringResource(CommonStrings.a11y_start_call)) + } } } + Spacer(Modifier.width(8.dp)) }, windowInsets = WindowInsets(0.dp) ) } +@Composable +private fun JoinCallMenuItem( + modifier: Modifier = Modifier, + onJoinCallClicked: () -> Unit, +) { + Material3Button( + onClick = onJoinCallClicked, + colors = ButtonDefaults.buttonColors( + contentColor = ElementTheme.colors.bgCanvasDefault, + containerColor = ElementTheme.colors.iconAccentTertiary + ), + contentPadding = PaddingValues(horizontal = 10.dp, vertical = 0.dp), + modifier = modifier.heightIn(min = 36.dp), + ) { + Icon( + modifier = Modifier.size(20.dp), + resourceId = CommonDrawables.ic_compound_video_call, + contentDescription = null + ) + Spacer(Modifier.width(8.dp)) + Text( + text = stringResource(CommonStrings.action_join), + style = ElementTheme.typography.fontBodyMdMedium + ) + Spacer(Modifier.width(8.dp)) + } +} + @Composable private fun RoomAvatarAndNameRow( roomName: String, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt index b5bbebfa33..190edd6173 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt @@ -68,6 +68,7 @@ import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.A_SESSION_ID_2 import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.libraries.matrix.test.room.aRoomInfo import io.element.android.libraries.matrix.test.room.aRoomMember import io.element.android.libraries.mediapickers.test.FakePickerProvider import io.element.android.libraries.mediaupload.api.MediaSender @@ -106,7 +107,8 @@ class MessagesPresenterTest { val initialState = consumeItemsUntilTimeout().last() assertThat(initialState.roomId).isEqualTo(A_ROOM_ID) assertThat(initialState.roomName).isEqualTo(Async.Success("")) - assertThat(initialState.roomAvatar).isEqualTo(Async.Success(AvatarData(id = A_ROOM_ID.value, name = "", size = AvatarSize.TimelineRoom))) + assertThat(initialState.roomAvatar) + .isEqualTo(Async.Success(AvatarData(id = A_ROOM_ID.value, name = "", url = AN_AVATAR_URL, size = AvatarSize.TimelineRoom))) assertThat(initialState.userHasPermissionToSendMessage).isTrue() assertThat(initialState.userHasPermissionToRedact).isFalse() assertThat(initialState.hasNetworkConnection).isTrue() @@ -603,7 +605,9 @@ class MessagesPresenterTest { private fun TestScope.createMessagesPresenter( coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers(), - matrixRoom: MatrixRoom = FakeMatrixRoom(), + matrixRoom: MatrixRoom = FakeMatrixRoom().apply { + givenRoomInfo(aRoomInfo(id = roomId.value, name = "")) + }, navigator: FakeMessagesNavigator = FakeMessagesNavigator(), clipboardHelper: FakeClipboardHelper = FakeClipboardHelper(), analyticsService: FakeAnalyticsService = FakeAnalyticsService(), diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/CurrentUserMembership.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/CurrentUserMembership.kt new file mode 100644 index 0000000000..3aa71a9459 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/CurrentUserMembership.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.api.room + +enum class CurrentUserMembership { + INVITED, JOINED, LEFT +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index 4b7e4e4470..1cce3f03b7 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -32,6 +32,7 @@ import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.timeline.MatrixTimeline import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow import java.io.Closeable import java.io.File @@ -51,6 +52,8 @@ interface MatrixRoom : Closeable { val activeMemberCount: Long val joinedMemberCount: Long + val roomInfoFlow: Flow + /** * A one-to-one is a room with exactly 2 members. * See [the Matrix spec](https://spec.matrix.org/latest/client-server-api/#default-underride-rules). diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt new file mode 100644 index 0000000000..6690387b04 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.api.room + +import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem + +data class MatrixRoomInfo( + val id: String, + val name: String?, + val topic: String?, + val avatarUrl: String?, + val isDirect: Boolean, + val isPublic: Boolean, + val isSpace: Boolean, + val isTombstoned: Boolean, + val canonicalAlias: String?, + val alternativeAliases: List, + val currentUserMembership: CurrentUserMembership, + val latestEvent: EventTimelineItem?, + val inviter: RoomMember?, + val activeMembersCount: Long, + val invitedMembersCount: Long, + val joinedMembersCount: Long, + val highlightCount: Long, + val notificationCount: Long, + val userDefinedNotificationMode: RoomNotificationMode?, + val hasRoomCall: Boolean, + val activeRoomCallParticipants: List +) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index 21a489904b..67bbcb835c 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -47,6 +47,7 @@ import io.element.android.libraries.matrix.impl.notification.RustNotificationSer import io.element.android.libraries.matrix.impl.notificationsettings.RustNotificationSettingsService import io.element.android.libraries.matrix.impl.oidc.toRustAction import io.element.android.libraries.matrix.impl.pushers.RustPushersService +import io.element.android.libraries.matrix.impl.room.MatrixRoomInfoMapper import io.element.android.libraries.matrix.impl.room.RoomContentForwarder import io.element.android.libraries.matrix.impl.room.RoomSyncSubscriber import io.element.android.libraries.matrix.impl.room.RustMatrixRoom @@ -201,7 +202,8 @@ class RustMatrixClient constructor( systemClock = clock, roomContentForwarder = roomContentForwarder, sessionData = sessionStore.getSession(sessionId.value)!!, - roomSyncSubscriber = roomSyncSubscriber + roomSyncSubscriber = roomSyncSubscriber, + matrixRoomInfoMapper = MatrixRoomInfoMapper(), ) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt new file mode 100644 index 0000000000..c24d996714 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.impl.room + +import io.element.android.libraries.matrix.api.room.CurrentUserMembership +import io.element.android.libraries.matrix.api.room.MatrixRoomInfo +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelineItemMapper +import org.matrix.rustcomponents.sdk.use +import org.matrix.rustcomponents.sdk.Membership as RustMembership +import org.matrix.rustcomponents.sdk.RoomInfo as RustRoomInfo +import org.matrix.rustcomponents.sdk.RoomNotificationMode as RustRoomNotificationMode + +class MatrixRoomInfoMapper( + private val timelineItemMapper: EventTimelineItemMapper = EventTimelineItemMapper(), +) { + + fun map(rustRoomInfo: RustRoomInfo): MatrixRoomInfo = rustRoomInfo.use { + return MatrixRoomInfo( + id = it.id, + name = it.name, + topic = it.topic, + avatarUrl = it.avatarUrl, + isDirect = it.isDirect, + isPublic = it.isPublic, + isSpace = it.isSpace, + isTombstoned = it.isTombstoned, + canonicalAlias = it.canonicalAlias, + alternativeAliases = it.alternativeAliases, + currentUserMembership = it.membership.map(), + latestEvent = it.latestEvent?.use (timelineItemMapper::map), + inviter = it.inviter?.use(RoomMemberMapper::map), + activeMembersCount = it.activeMembersCount.toLong(), + invitedMembersCount = it.invitedMembersCount.toLong(), + joinedMembersCount = it.joinedMembersCount.toLong(), + highlightCount = it.highlightCount.toLong(), + notificationCount = it.notificationCount.toLong(), + userDefinedNotificationMode = it.userDefinedNotificationMode?.map(), + hasRoomCall = it.hasRoomCall, + activeRoomCallParticipants = it.activeRoomCallParticipants + ) + } +} + +fun RustMembership.map(): CurrentUserMembership = when(this) { + RustMembership.INVITED -> CurrentUserMembership.INVITED + RustMembership.JOINED -> CurrentUserMembership.JOINED + RustMembership.LEFT -> CurrentUserMembership.LEFT +} + +fun RustRoomNotificationMode.map(): RoomNotificationMode = when(this) { + RustRoomNotificationMode.ALL_MESSAGES -> RoomNotificationMode.ALL_MESSAGES + RustRoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY + RustRoomNotificationMode.MUTE -> RoomNotificationMode.MUTE +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index 8dd0c02321..d45508e424 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -32,6 +32,7 @@ import io.element.android.libraries.matrix.api.media.MediaUploadHandler import io.element.android.libraries.matrix.api.media.VideoInfo import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.room.MatrixRoomInfo import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.api.room.MatrixRoomNotificationSettingsState import io.element.android.libraries.matrix.api.room.MessageEventType @@ -50,6 +51,7 @@ import io.element.android.libraries.matrix.impl.poll.toInner import io.element.android.libraries.matrix.impl.room.location.toInner import io.element.android.libraries.matrix.impl.timeline.RustMatrixTimeline import io.element.android.libraries.matrix.impl.util.destroyAll +import io.element.android.libraries.matrix.impl.util.mxCallbackFlow import io.element.android.libraries.matrix.impl.widget.RustWidgetDriver import io.element.android.libraries.matrix.impl.widget.generateWidgetWebViewUrl import io.element.android.libraries.sessionstorage.api.SessionData @@ -59,12 +61,16 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.cancel import kotlinx.coroutines.ensureActive +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.matrix.rustcomponents.sdk.EventTimelineItem import org.matrix.rustcomponents.sdk.Room +import org.matrix.rustcomponents.sdk.RoomInfo +import org.matrix.rustcomponents.sdk.RoomInfoListener import org.matrix.rustcomponents.sdk.RoomListItem import org.matrix.rustcomponents.sdk.RoomMember import org.matrix.rustcomponents.sdk.RoomMessageEventContentWithoutRelation @@ -73,6 +79,7 @@ import org.matrix.rustcomponents.sdk.WidgetCapabilities import org.matrix.rustcomponents.sdk.WidgetCapabilitiesProvider import org.matrix.rustcomponents.sdk.messageEventContentFromHtml import org.matrix.rustcomponents.sdk.messageEventContentFromMarkdown +import org.matrix.rustcomponents.sdk.use import timber.log.Timber import java.io.File @@ -88,10 +95,23 @@ class RustMatrixRoom( private val roomContentForwarder: RoomContentForwarder, private val sessionData: SessionData, private val roomSyncSubscriber: RoomSyncSubscriber, + private val matrixRoomInfoMapper: MatrixRoomInfoMapper, ) : MatrixRoom { override val roomId = RoomId(innerRoom.id()) + override val roomInfoFlow: Flow = mxCallbackFlow { + launch { + val initial = innerRoom.roomInfo().use(matrixRoomInfoMapper::map) + channel.trySend(initial) + } + innerRoom.subscribeToRoomInfoUpdates(object : RoomInfoListener { + override fun call(roomInfo: RoomInfo) { + channel.trySend(matrixRoomInfoMapper.map(roomInfo)) + } + }) + } + // Create a dispatcher for all room methods... private val roomDispatcher = coroutineDispatchers.io.limitedParallelism(32) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/RustWidgetDriver.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/RustWidgetDriver.kt index 2764cecfdc..33e829a206 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/RustWidgetDriver.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/RustWidgetDriver.kt @@ -68,7 +68,11 @@ class RustWidgetDriver( } override suspend fun send(message: String) { - driverAndHandle.handle.send(message) + try { + driverAndHandle.handle.send(message) + } catch (e: IllegalStateException) { + // The handle is closed, ignore + } } override fun close() { diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index c08a742391..844a049a40 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -29,16 +29,23 @@ import io.element.android.libraries.matrix.api.media.MediaUploadHandler import io.element.android.libraries.matrix.api.media.VideoInfo import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.poll.PollKind +import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.room.MatrixRoomInfo import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.api.room.MatrixRoomNotificationSettingsState import io.element.android.libraries.matrix.api.room.MessageEventType +import io.element.android.libraries.matrix.api.room.RoomMember +import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.timeline.MatrixTimeline +import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings +import io.element.android.libraries.matrix.test.AN_AVATAR_URL import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_ROOM_NAME import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.media.FakeMediaUploadHandler import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService @@ -46,6 +53,8 @@ import io.element.android.libraries.matrix.test.timeline.FakeMatrixTimeline import io.element.android.libraries.matrix.test.widget.FakeWidgetDriver import io.element.android.tests.testutils.simulateLongTask import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import java.io.File @@ -143,6 +152,9 @@ class FakeMatrixRoom( private var leaveRoomError: Throwable? = null + private val _roomInfoFlow: MutableSharedFlow = MutableStateFlow(aRoomInfo()) + override val roomInfoFlow: Flow = _roomInfoFlow + override val membersStateFlow: MutableStateFlow = MutableStateFlow(MatrixRoomMembersState.Unknown) override val roomNotificationSettingsStateFlow: MutableStateFlow = @@ -497,6 +509,10 @@ class FakeMatrixRoom( fun givenGetWidgetDriverResult(result: Result) { getWidgetDriverResult = result } + + fun givenRoomInfo(roomInfo: MatrixRoomInfo) { + _roomInfoFlow.tryEmit(roomInfo) + } } data class SendLocationInvocation( @@ -523,3 +539,49 @@ data class EndPollInvocation( val pollStartId: EventId, val text: String, ) + +fun aRoomInfo( + id: String = A_ROOM_ID.value, + name: String? = A_ROOM_NAME, + topic: String? = "A topic", + avatarUrl: String? = AN_AVATAR_URL, + isDirect: Boolean = false, + isPublic: Boolean = true, + isSpace: Boolean = false, + isTombstoned: Boolean = false, + canonicalAlias: String? = null, + alternativeAliases: List = emptyList(), + currentUserMembership: CurrentUserMembership = CurrentUserMembership.JOINED, + latestEvent: EventTimelineItem? = null, + inviter: RoomMember? = null, + activeMembersCount: Long = 1, + invitedMembersCount: Long = 0, + joinedMembersCount: Long = 1, + highlightCount: Long = 0, + notificationCount: Long = 0, + userDefinedNotificationMode: RoomNotificationMode? = null, + hasRoomCall: Boolean = false, + activeRoomCallParticipants: List = emptyList() +) = MatrixRoomInfo( + id = id, + name = name, + topic = topic, + avatarUrl = avatarUrl, + isDirect = isDirect, + isPublic = isPublic, + isSpace = isSpace, + isTombstoned = isTombstoned, + canonicalAlias = canonicalAlias, + alternativeAliases = alternativeAliases, + currentUserMembership = currentUserMembership, + latestEvent = latestEvent, + inviter = inviter, + activeMembersCount = activeMembersCount, + invitedMembersCount = invitedMembersCount, + joinedMembersCount = joinedMembersCount, + highlightCount = highlightCount, + notificationCount = notificationCount, + userDefinedNotificationMode = userDefinedNotificationMode, + hasRoomCall = hasRoomCall, + activeRoomCallParticipants = activeRoomCallParticipants +) diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index c70eceb21f..85f499e404 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -11,6 +11,7 @@ "Ended poll" "Send files" "Show password" + "Start a call" "User menu" "Record voice message. Double tap and hold to record. Release to end recording." "Accept" diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_0,NEXUS_5,1.0,en].png index 6f1f867a7c..4b4c8a1c3c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5f219bd9b9363f237e15bb73655dd53b2ec143e18c8544c11efbfa90390e091c -size 54312 +oid sha256:0eee7139a7675a08899accf49a97139b56333737e649e51ca1644ae6ae68d915 +size 54358 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_1,NEXUS_5,1.0,en].png index 062dfb77f8..049ce0c7a1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6065f5330e1b3638719c6743db098bf6576fcffc6ccf8215f7f600a0b981144b -size 55731 +oid sha256:39e0b212a2cc423f3e33254d4a965c3071e88e5dd21268c42b3b555b1800b236 +size 55774 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_10,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..6f2b4996d3 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_10,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:33afbe67d0e4156d615e6a58d4356386d5e2c0922cf646c2ec385338d869d8f5 +size 56023 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_3,NEXUS_5,1.0,en].png index 1de7fbc725..3db6eef5cb 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f4bdafdfa50665f05ba5cd8749252e7e5d65bea8a8c6bfc1c46eb1acd1570b52 -size 56086 +oid sha256:42445e54ca2cfadbbd3f041f327825ea5595e27877376a760c37b746529d0980 +size 56135 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_4,NEXUS_5,1.0,en].png index d348a6f13f..143870a1b8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2bfcc4dcaa8980cfc9c724e64a93116ac1fb81a1bf4421532cb196d4e07db7c5 -size 56024 +oid sha256:b9f1300da0ac7ef29286fb37d4489b38fa07632f71aa7d1f1cc0e0786749c626 +size 56124 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_5,NEXUS_5,1.0,en].png index 224cef4b67..6c6e0a9ef4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c86a6da3d45b767a41f65e0cf4e8cacefb33e0409386a6233140891deb2258f6 -size 51965 +oid sha256:95f81914a56679419a7a6055040ae51b11616c87012310cbd221e3af41d55e8e +size 52039 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_6,NEXUS_5,1.0,en].png index 82636b3e21..8d15129b08 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a1fc20759ff45eeef547621853b9684a663fe9dcdf78b316454dcae26d078f9 -size 52286 +oid sha256:ce97ccc29b01824ddd251dbe7756aa80749c0acc4fd8278cb1c3e4fc24c2337e +size 52334 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_7,NEXUS_5,1.0,en].png index b147d8489d..bfa886fbed 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b65df67b1384aaa169f25d81e87072f2732c88676122e58e5d08850ada050ce -size 60073 +oid sha256:6d387f9678367ec0b8d6617a3ba378d309979af0e534e9f683805e71cd6c2794 +size 60172 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_8,NEXUS_5,1.0,en].png index 6ead9a5063..26057e68a3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:abe449182a4cddbf11b9004579d27043e41c74d45261c1435d18b516946f9eed -size 42175 +oid sha256:0708776dd8884bd8975845c9fbb0b30fe6317d5692aaba36781fed5cff065c1b +size 42279 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_9,NEXUS_5,1.0,en].png index d28a44a2bd..9b5fc514e3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_9,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-D-0_0_null_9,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5deb0929efaab3160a7d0441bde9afe278064e8c0641cc62408bb25acbdced21 -size 41329 +oid sha256:766086d64f70b2a9f028149190d3f3c5b2ff34599907b38997657b6d093fa0f4 +size 41428 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_0,NEXUS_5,1.0,en].png index 094ab2536a..6ae5a8b8e0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b9bc4654b6911d7f50b4b0242b650a529cb22c13a58caf5eae50366a2d27b37 -size 52532 +oid sha256:6d42806b454f15ed83e883bf5e2765d345163a57049b4b598c1b8d08458588dc +size 52624 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_1,NEXUS_5,1.0,en].png index 32de8d07f9..a432f0e416 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0e051668beb9030ff184d6e75831a00202854f6448880f399a7ee2d5be187740 -size 53880 +oid sha256:27f4fd957e004579b8b20373e1649f8c067a604595a5dcaae60b0caec7c43954 +size 53972 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_10,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..b64203f138 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_10,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:010d76d537104b914a35cdb783c5cfcc1953a470d2d9bc23781c8837c9558f5f +size 54122 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_3,NEXUS_5,1.0,en].png index 009ddeadaa..d5195bd919 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c6c6603452db218811f3f5a2baa934ca640755b969e81ca8cbf6b3dcf663aee9 -size 54551 +oid sha256:397f061ceeefb2ea67a5d9a342050cea136554e936854bd26b92c3acfde45d74 +size 54646 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_4,NEXUS_5,1.0,en].png index d2f2f56d9b..578ad1301e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e953bc91e9959f1635d12416f6afde79427aeac4edef44fb38f1512672e544bd -size 51552 +oid sha256:a1a0280d6321b754e5e36d25eefc2d5c7192af16e52ae1304b4e7c57a7824e19 +size 51611 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_5,NEXUS_5,1.0,en].png index 9437874ffd..ef03d74710 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0157713ae934c0771a5d3d4d064ce6dc9be11b1d8011f2360740d7f4a20f6f04 -size 50162 +oid sha256:99ded72c99dc1ba5b8c61cbacca6cc91f4b6325a16c12013150c6d63afd28182 +size 50273 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_6,NEXUS_5,1.0,en].png index af4dae6214..5006c63543 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:24f1d30bb62ed620671e87062a338fd53f409bce6e08fb7b116249decf74e409 -size 50295 +oid sha256:d2fc04a6c21e851b4e10c88ad9485f43f2f1576f5aeb40d4611513352341536e +size 50384 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_7,NEXUS_5,1.0,en].png index 8e1be7bda7..ad11262fbe 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9457cbf3ff35a5677f983eba7d5087ca82e4d99a2bb942f64f5f7ccdb71e01b5 -size 54882 +oid sha256:5f3a764349e13ebe7205ff4d0b04a02f64c6eee5d65bb3b9cc62ac1d721d2d39 +size 54944 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_8,NEXUS_5,1.0,en].png index e41893a3b4..d9af4e88ee 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:549892647be61e9fd5fbbb80fa14734533e1b4628f95d409f2772dd990000f42 -size 38953 +oid sha256:459029e7871910e085378a40ff503d286b72fb7029c251d1e04a8a1f39cfd0ba +size 39017 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_9,NEXUS_5,1.0,en].png index 366b48f4ca..3f51c51648 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_9,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesView-N-0_1_null_9,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c6bef454d8f57ba76b34b8588ba73635719feb6b1dde967b90f812d2410a7749 -size 38165 +oid sha256:a2d6cb8081da15f265d35e909c1d22bb6a48219162b20e1472230a698fdc2d2b +size 38231