diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index e086e15e42..fe15beb983 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -86,7 +86,7 @@ class RoomDetailsPresenter @Inject constructor( val isPublic by remember { derivedStateOf { roomInfo?.isPublic.orFalse() } } val canShowPinnedMessages = isPinnedMessagesFeatureEnabled() - val pinnedMessagesCount by remember { derivedStateOf { roomInfo?.pinnedEventIds?.size ?: 0 } } + val pinnedMessagesCount by remember { derivedStateOf { roomInfo?.pinnedEventIds?.size } } LaunchedEffect(Unit) { canShowNotificationSettings.value = featureFlagService.isFeatureEnabled(FeatureFlags.NotificationSettings) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt index 0d3578db1d..afce4f879a 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt @@ -47,7 +47,7 @@ data class RoomDetailsState( val isPublic: Boolean, val heroes: ImmutableList, val canShowPinnedMessages: Boolean, - val pinnedMessagesCount: Int, + val pinnedMessagesCount: Int?, val eventSink: (RoomDetailsEvent) -> Unit ) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt index f6cbebaf7c..5c881787e4 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt @@ -53,6 +53,7 @@ open class RoomDetailsStateProvider : PreviewParameterProvider aRoomDetailsState(canCall = false, canInvite = false), aRoomDetailsState(isPublic = false), aRoomDetailsState(heroes = aMatrixUserList()), + aRoomDetailsState(pinnedMessagesCount = 3), // Add other state here ) } @@ -106,7 +107,7 @@ fun aRoomDetailsState( isPublic: Boolean = true, heroes: List = emptyList(), canShowPinnedMessages: Boolean = true, - pinnedMessagesCount: Int = 3, + pinnedMessagesCount: Int? = null, eventSink: (RoomDetailsEvent) -> Unit = {}, ) = RoomDetailsState( roomId = roomId, 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 2ef9e0718e..a0519aa3fa 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 @@ -27,6 +27,7 @@ import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons @@ -66,6 +67,7 @@ import io.element.android.libraries.designsystem.components.preferences.Preferen import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.PreviewWithLargeHeight +import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.designsystem.theme.components.DropdownMenu import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem import io.element.android.libraries.designsystem.theme.components.Icon @@ -184,7 +186,7 @@ fun RoomDetailsView( } ) - if(state.canShowPinnedMessages) { + if (state.canShowPinnedMessages) { PinnedMessagesItem( pinnedMessagesCount = state.pinnedMessagesCount, onPinnedMessagesClick = onPinnedMessagesClick @@ -513,13 +515,20 @@ private fun MembersItem( @Composable private fun PinnedMessagesItem( - pinnedMessagesCount: Int, + pinnedMessagesCount: Int?, onPinnedMessagesClick: () -> Unit, ) { ListItem( headlineContent = { Text(stringResource(CommonStrings.screen_room_details_pinned_events_row_title)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Pin())), - trailingContent = ListItemContent.Text(pinnedMessagesCount.toString()), + trailingContent = + if (pinnedMessagesCount == null) { + ListItemContent.Custom { + CircularProgressIndicator(strokeWidth = 2.dp, modifier = Modifier.size(24.dp)) + } + } else { + ListItemContent.Text(pinnedMessagesCount.toString()) + }, onClick = onPinnedMessagesClick, ) } diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTest.kt index ff89aba9be..d2f01498c3 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTest.kt @@ -42,6 +42,7 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.StateEventType +import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.A_USER_ID_2 import io.element.android.libraries.matrix.test.FakeMatrixClient @@ -81,6 +82,7 @@ class RoomDetailsPresenterTest { dispatchers: CoroutineDispatchers = testCoroutineDispatchers(), notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(), analyticsService: AnalyticsService = FakeAnalyticsService(), + isPinnedMessagesFeatureEnabled: Boolean = true, ): RoomDetailsPresenter { val matrixClient = FakeMatrixClient(notificationSettingsService = notificationSettingsService) val roomMemberDetailsPresenterFactory = object : RoomMemberDetailsPresenter.Factory { @@ -99,6 +101,7 @@ class RoomDetailsPresenterTest { roomMembersDetailsPresenterFactory = roomMemberDetailsPresenterFactory, leaveRoomPresenter = leaveRoomPresenter, dispatchers = dispatchers, + isPinnedMessagesFeatureEnabled = { isPinnedMessagesFeatureEnabled }, analyticsService = analyticsService, ) } @@ -127,14 +130,15 @@ class RoomDetailsPresenterTest { assertThat(initialState.roomTopic).isEqualTo(RoomTopicState.ExistingTopic(room.topic!!)) assertThat(initialState.memberCount).isEqualTo(room.joinedMemberCount) assertThat(initialState.isEncrypted).isEqualTo(room.isEncrypted) - + assertThat(initialState.canShowPinnedMessages).isTrue() + assertThat(initialState.pinnedMessagesCount).isNull() cancelAndIgnoreRemainingEvents() } } @Test fun `present - initial state is updated with roomInfo if it exists`() = runTest { - val roomInfo = aRoomInfo(name = "A room name", topic = "A topic", avatarUrl = "https://matrix.org/avatar.jpg") + val roomInfo = aRoomInfo(name = "A room name", topic = "A topic", avatarUrl = "https://matrix.org/avatar.jpg", pinnedEventIds = listOf(AN_EVENT_ID)) val room = aMatrixRoom( canInviteResult = { Result.success(true) }, canUserJoinCallResult = { Result.success(true) }, @@ -149,7 +153,7 @@ class RoomDetailsPresenterTest { assertThat(updatedState.roomName).isEqualTo(roomInfo.name) assertThat(updatedState.roomAvatarUrl).isEqualTo(roomInfo.avatarUrl) assertThat(updatedState.roomTopic).isEqualTo(RoomTopicState.ExistingTopic(roomInfo.topic!!)) - + assertThat(updatedState.pinnedMessagesCount).isEqualTo(roomInfo.pinnedEventIds.size) cancelAndIgnoreRemainingEvents() } } diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt index b3bbb21cf6..a5a2f7f18a 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt @@ -127,6 +127,22 @@ class RoomDetailsViewTest { } } + + @Config(qualifiers = "h1024dp") + @Test + fun `click on pinned messages invokes expected callback`() { + ensureCalledOnce { callback -> + rule.setRoomDetailView( + state = aRoomDetailsState( + eventSink = EventsRecorder(expectEvents = false), + canInvite = true, + ), + onPinnedMessagesClick = callback, + ) + rule.clickOn(CommonStrings.screen_room_details_pinned_events_row_title) + } + } + @Config(qualifiers = "h1024dp") @Test fun `click on add topic emit expected event`() { @@ -263,6 +279,7 @@ private fun AndroidComposeTestRule.setRoomD openPollHistory: () -> Unit = EnsureNeverCalled(), openAdminSettings: () -> Unit = EnsureNeverCalled(), onJoinCallClick: () -> Unit = EnsureNeverCalled(), + onPinnedMessagesClick: () -> Unit = EnsureNeverCalled(), ) { setContent { RoomDetailsView( @@ -277,6 +294,7 @@ private fun AndroidComposeTestRule.setRoomD openPollHistory = openPollHistory, openAdminSettings = openAdminSettings, onJoinCallClick = onJoinCallClick, + onPinnedMessagesClick = onPinnedMessagesClick, ) } }