From c0918bd96553410491f441fc1ac628673a918182 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 12 Apr 2024 14:09:57 +0200 Subject: [PATCH] Join room : change state and view --- .../joinroom/impl/JoinRoomPresenter.kt | 52 ++---- .../features/joinroom/impl/JoinRoomState.kt | 54 +++--- .../joinroom/impl/JoinRoomStateProvider.kt | 36 ++-- .../features/joinroom/impl/JoinRoomView.kt | 165 ++++++++++++------ .../joinroom/impl/JoinRoomPresenterTest.kt | 26 +-- .../roomdirectory/api/RoomDescription.kt | 19 +- .../impl/root/RoomDirectoryStateProvider.kt | 6 +- .../impl/root/RoomDirectoryView.kt | 4 +- .../impl/root/model/RoomDescription.kt | 22 +-- .../atomic/pages/HeaderFooterPage.kt | 4 +- .../matrix/impl/util/CallbackFlow.kt | 5 +- 11 files changed, 228 insertions(+), 165 deletions(-) diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt index 777de024c5..26b661b3eb 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt @@ -26,7 +26,6 @@ import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents import io.element.android.features.invite.api.response.AcceptDeclineInviteState import io.element.android.features.invite.api.response.InviteData import io.element.android.features.roomdirectory.api.RoomDescription -import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId @@ -49,18 +48,16 @@ class JoinRoomPresenter @AssistedInject constructor( @Composable override fun present(): JoinRoomState { val roomInfo by matrixClient.getRoomInfoFlow(roomId).collectAsState(initial = Optional.empty()) - val contentState by produceState>(initialValue = AsyncData.Uninitialized, key1 = roomInfo) { + val contentState by produceState(initialValue = ContentState.Loading(roomId), key1 = roomInfo) { value = when { roomInfo.isPresent -> { - val contentState = roomInfo.get().toContentState() - AsyncData.Success(contentState) + roomInfo.get().toContentState() } roomDescription.isPresent -> { - val contentState = roomDescription.get().toContentState() - AsyncData.Success(contentState) + roomDescription.get().toContentState() } else -> { - AsyncData.Uninitialized + ContentState.UnknownRoom(roomId) } } } @@ -93,10 +90,11 @@ class JoinRoomPresenter @AssistedInject constructor( @VisibleForTesting internal fun RoomDescription.toContentState(): ContentState { - return ContentState( + return ContentState.Loaded( roomId = roomId, name = name, - description = description, + topic = topic, + alias = alias, numberOfMembers = numberOfMembers, isDirect = false, roomAvatarUrl = avatarUrl, @@ -110,26 +108,11 @@ internal fun RoomDescription.toContentState(): ContentState { @VisibleForTesting internal fun MatrixRoomInfo.toContentState(): ContentState { - fun title(): String { - return name ?: canonicalAlias ?: id - } - - fun description(): String? { - val topic = topic - val alias = canonicalAlias - val name = name - return when { - topic != null -> topic - name != null && alias != null -> alias - name == null && alias == null -> null - else -> id - } - } - - return ContentState( + return ContentState.Loaded( roomId = RoomId(id), - name = title(), - description = description(), + name = name, + topic = topic, + alias = canonicalAlias, numberOfMembers = activeMembersCount, isDirect = isDirect, roomAvatarUrl = avatarUrl, @@ -142,12 +125,13 @@ internal fun MatrixRoomInfo.toContentState(): ContentState { } @VisibleForTesting -internal fun AsyncData.toInviteData(): InviteData? { - return dataOrNull()?.let { contentState -> - InviteData( - roomId = contentState.roomId, - roomName = contentState.name, - isDirect = contentState.isDirect +internal fun ContentState.toInviteData(): InviteData? { + return when (this) { + is ContentState.Loaded -> InviteData( + roomId = roomId, + roomName = computedTitle, + isDirect = isDirect ) + else -> null } } diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt index c8211feb0d..01647e1fdd 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt @@ -18,39 +18,53 @@ package io.element.android.features.joinroom.impl import androidx.compose.runtime.Immutable import io.element.android.features.invite.api.response.AcceptDeclineInviteState -import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.core.RoomId @Immutable data class JoinRoomState( - val contentState: AsyncData, + val contentState: ContentState, val acceptDeclineInviteState: AcceptDeclineInviteState, val eventSink: (JoinRoomEvents) -> Unit ) { - val joinAuthorisationStatus = contentState.dataOrNull()?.joinAuthorisationStatus ?: JoinAuthorisationStatus.Unknown + val joinAuthorisationStatus = when(contentState) { + is ContentState.Loaded -> contentState.joinAuthorisationStatus + else -> JoinAuthorisationStatus.Unknown + } } -data class ContentState( - val roomId: RoomId, - val name: String, - val description: String?, - val numberOfMembers: Long?, - val isDirect: Boolean, - val roomAvatarUrl: String?, - val joinAuthorisationStatus: JoinAuthorisationStatus, -) { +sealed interface ContentState { + data class Loading(val roomId: RoomId) : ContentState + data class UnknownRoom(val roomId: RoomId) : ContentState + data class Loaded( + val roomId: RoomId, + val name: String?, + val topic: String?, + val alias: String?, + val numberOfMembers: Long?, + val isDirect: Boolean, + val roomAvatarUrl: String?, + val joinAuthorisationStatus: JoinAuthorisationStatus, + ) : ContentState { + val computedTitle = name ?: roomId.value - val showMemberCount = numberOfMembers != null + val computedSubtitle = when { + alias != null -> alias + name == null -> "" + else -> roomId.value + } - fun avatarData(size: AvatarSize): AvatarData { - return AvatarData( - id = roomId.value, - name = name, - url = roomAvatarUrl, - size = size, - ) + val showMemberCount = numberOfMembers != null + + fun avatarData(size: AvatarSize): AvatarData { + return AvatarData( + id = roomId.value, + name = name, + url = roomAvatarUrl, + size = size, + ) + } } } diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt index 994f914a19..5e10613557 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt @@ -19,45 +19,47 @@ package io.element.android.features.joinroom.impl import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.invite.api.response.AcceptDeclineInviteState import io.element.android.features.invite.api.response.anAcceptDeclineInviteState -import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.core.RoomId open class JoinRoomStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( aJoinRoomState( - contentState = AsyncData.Uninitialized + contentState = anUninitializedContentState() ), aJoinRoomState( - contentState = AsyncData.Success( - aContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin) - ) + contentState = anUnknownContentState() ), aJoinRoomState( - contentState = AsyncData.Success( - aContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock) - ) + contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin) ), aJoinRoomState( - contentState = AsyncData.Success( - aContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited) - ) + contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock) + ), + aJoinRoomState( + contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited) ), ) } -fun aContentState( +fun anUnknownContentState(roomId: RoomId = RoomId("@exa:matrix.org")) = ContentState.UnknownRoom(roomId) + +fun anUninitializedContentState(roomId: RoomId = RoomId("@exa:matrix.org")) = ContentState.Loading(roomId) + +fun aLoadedContentState( roomId: RoomId = RoomId("@exa:matrix.org"), name: String = "Element x android", - description: String? = "#exa:matrix.org", + alias: String? = "#exa:matrix.org", + topic: String? = "Element X is a secure, private and decentralized messenger.", numberOfMembers: Long? = null, isDirect: Boolean = false, roomAvatarUrl: String? = null, joinAuthorisationStatus: JoinAuthorisationStatus = JoinAuthorisationStatus.Unknown -) = ContentState( +) = ContentState.Loaded( roomId = roomId, name = name, - description = description, + alias = alias, + topic = topic, numberOfMembers = numberOfMembers, isDirect = isDirect, roomAvatarUrl = roomAvatarUrl, @@ -65,9 +67,7 @@ fun aContentState( ) fun aJoinRoomState( - contentState: AsyncData = AsyncData.Success( - aContentState() - ), + contentState: ContentState = aLoadedContentState(), acceptDeclineInviteState: AcceptDeclineInviteState = anAcceptDeclineInviteState(), eventSink: (JoinRoomEvents) -> Unit = {} ) = JoinRoomState( diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt index 5cef755af2..3ac19b5daf 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt @@ -16,9 +16,11 @@ package io.element.android.features.joinroom.impl +import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement 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.fillMaxWidth @@ -30,14 +32,15 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons -import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.atomic.atoms.PlaceholderAtom import io.element.android.libraries.designsystem.atomic.molecules.ButtonRowMolecule import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage @@ -61,11 +64,12 @@ fun JoinRoomView( ) { HeaderFooterPage( modifier = modifier, + paddingValues = PaddingValues(16.dp), topBar = { JoinRoomTopBar(onBackClicked = onBackPressed) }, content = { - JoinRoomContent(asyncContentState = state.contentState) + JoinRoomContent(contentState = state.contentState) }, footer = { JoinRoomFooter( @@ -111,22 +115,19 @@ private fun JoinRoomFooter( } JoinAuthorisationStatus.CanJoin -> { Button( - text = stringResource(CommonStrings.action_join), + text = stringResource(R.string.screen_join_room_join_action), onClick = onJoinRoom, modifier = modifier.fillMaxWidth(), size = ButtonSize.Medium, ) } JoinAuthorisationStatus.CanKnock -> { - //TODO knock - /* Button( - text = stringResource(CommonStrings.action_knock), + text = stringResource(R.string.screen_join_room_knock_action), onClick = onJoinRoom, modifier = modifier.fillMaxWidth(), size = ButtonSize.Medium, ) - */ } JoinAuthorisationStatus.Unknown -> Unit } @@ -134,63 +135,60 @@ private fun JoinRoomFooter( @Composable private fun JoinRoomContent( - asyncContentState: AsyncData, + contentState: ContentState, modifier: Modifier = Modifier, ) { - @Composable - fun ContentScaffold( - avatar: @Composable () -> Unit, - title: String, - description: String, - memberCount: @Composable (() -> Unit)? = null - ) { - avatar() - Spacer(modifier = Modifier.height(16.dp)) - Text( - text = title, - style = ElementTheme.typography.fontHeadingMdBold, - textAlign = TextAlign.Center, - color = ElementTheme.colors.textPrimary, - ) - Spacer(modifier = Modifier.height(8.dp)) - Text( - text = description, - style = ElementTheme.typography.fontBodyMdRegular, - textAlign = TextAlign.Center, - color = ElementTheme.colors.textSecondary, - ) - memberCount?.invoke() - } - Column( - modifier = modifier - .fillMaxWidth() - .padding(all = 16.dp), + modifier = modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) { - when (asyncContentState) { - is AsyncData.Success -> { - val contentState = asyncContentState.data + when (contentState) { + is ContentState.Loaded -> { ContentScaffold( avatar = { Avatar(contentState.avatarData(AvatarSize.RoomHeader)) }, - title = contentState.name, - description = contentState.description ?: stringResource(R.string.screen_join_room_subtitle_no_preview) - ) { - if (contentState.showMemberCount) { - JoinRoomMembersCount(memberCount = contentState.numberOfMembers ?: 0) + title = { + Title(contentState.computedTitle) + }, + subtitle = { + Subtitle(contentState.computedSubtitle) + }, + description = { + Description(contentState.topic ?: "") + }, + memberCount = { + if (contentState.showMemberCount) { + MembersCount(memberCount = contentState.numberOfMembers ?: 0) + } } - } + ) } - else -> { + is ContentState.UnknownRoom -> { ContentScaffold( avatar = { PlaceholderAtom(width = AvatarSize.RoomHeader.dp, height = AvatarSize.RoomHeader.dp) }, - title = stringResource(R.string.screen_join_room_title_no_preview), - description = stringResource(R.string.screen_join_room_subtitle_no_preview), + title = { + Title(stringResource(R.string.screen_join_room_title_no_preview)) + }, + subtitle = { + Subtitle(stringResource(R.string.screen_join_room_subtitle_no_preview)) + }, + ) + } + is ContentState.Loading -> { + ContentScaffold( + avatar = { + PlaceholderAtom(width = AvatarSize.RoomHeader.dp, height = AvatarSize.RoomHeader.dp) + }, + title = { + PlaceholderAtom(width = 200.dp, height = 22.dp) + }, + subtitle = { + PlaceholderAtom(width = 140.dp, height = 20.dp) + }, ) } } @@ -198,13 +196,72 @@ private fun JoinRoomContent( } @Composable -private fun JoinRoomMembersCount(memberCount: Long) { +private fun ContentScaffold( + avatar: @Composable () -> Unit, + title: @Composable () -> Unit, + subtitle: @Composable () -> Unit, + description: @Composable (() -> Unit)? = null, + memberCount: @Composable (() -> Unit)? = null, +) { + avatar() + Spacer(modifier = Modifier.height(16.dp)) + title() + Spacer(modifier = Modifier.height(8.dp)) + subtitle() + Spacer(modifier = Modifier.height(8.dp)) + if (memberCount != null) { + memberCount() + } + Spacer(modifier = Modifier.height(8.dp)) + if (description != null) { + description() + } + Spacer(modifier = Modifier.height(24.dp)) +} + +@Composable +private fun Title(title: String, modifier: Modifier = Modifier) { + Text( + modifier = modifier, + text = title, + style = ElementTheme.typography.fontHeadingMdBold, + textAlign = TextAlign.Center, + color = ElementTheme.colors.textPrimary, + ) +} + +@Composable +private fun Subtitle(subtitle: String, modifier: Modifier = Modifier) { + Text( + modifier = modifier, + text = subtitle, + style = ElementTheme.typography.fontBodyLgRegular, + textAlign = TextAlign.Center, + color = ElementTheme.colors.textSecondary, + ) +} + +@Composable +private fun Description(description: String, modifier: Modifier = Modifier) { + Text( + modifier = modifier, + text = description, + style = ElementTheme.typography.fontBodySmRegular, + textAlign = TextAlign.Center, + color = ElementTheme.colors.textSecondary, + maxLines = 3, + overflow = TextOverflow.Ellipsis, + ) +} + +@Composable +private fun MembersCount(memberCount: Long) { Spacer(modifier = Modifier.height(8.dp)) Row( modifier = Modifier - .background(color = ElementTheme.colors.bgSubtleSecondary, shape = CircleShape) - .widthIn(min = 48.dp) - .padding(all = 2.dp), + .background(color = ElementTheme.colors.bgSubtleSecondary, shape = CircleShape) + .widthIn(min = 48.dp) + .padding(all = 2.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(4.dp) ) { @@ -230,9 +287,7 @@ private fun JoinRoomTopBar( navigationIcon = { BackButton(onClick = onBackClicked) }, - title = { - - }, + title = {}, ) } diff --git a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt index 45dc4361c5..19cc23c995 100644 --- a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt +++ b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt @@ -21,7 +21,6 @@ import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents import io.element.android.features.invite.api.response.AcceptDeclineInviteState import io.element.android.features.invite.api.response.anAcceptDeclineInviteState import io.element.android.features.roomdirectory.api.RoomDescription -import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId @@ -51,10 +50,13 @@ class JoinRoomPresenterTest { val presenter = createJoinRoomPresenter() presenter.test { awaitItem().also { state -> - assertThat(state.contentState).isInstanceOf(AsyncData.Uninitialized::class.java) + assertThat(state.contentState).isEqualTo(ContentState.Loading(A_ROOM_ID)) assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.Unknown) assertThat(state.acceptDeclineInviteState).isEqualTo(anAcceptDeclineInviteState()) } + awaitItem().also { state -> + assertThat(state.contentState).isEqualTo(ContentState.UnknownRoom(A_ROOM_ID)) + } } } @@ -72,11 +74,11 @@ class JoinRoomPresenterTest { presenter.test { skipItems(1) awaitItem().also { state -> - assertThat(state.contentState).isInstanceOf(AsyncData.Success::class.java) - val contentState = state.contentState.dataOrNull()!! + val contentState = state.contentState as ContentState.Loaded assertThat(contentState.roomId).isEqualTo(A_ROOM_ID) assertThat(contentState.name).isEqualTo(roomInfo.name) - assertThat(contentState.description).isEqualTo(roomInfo.topic) + assertThat(contentState.topic).isEqualTo(roomInfo.topic) + assertThat(contentState.alias).isEqualTo(roomInfo.canonicalAlias) assertThat(contentState.numberOfMembers).isEqualTo(roomInfo.activeMembersCount) assertThat(contentState.isDirect).isEqualTo(roomInfo.isDirect) assertThat(contentState.roomAvatarUrl).isEqualTo(roomInfo.avatarUrl) @@ -186,11 +188,11 @@ class JoinRoomPresenterTest { presenter.test { skipItems(1) awaitItem().also { state -> - assertThat(state.contentState).isInstanceOf(AsyncData.Success::class.java) - val contentState = state.contentState.dataOrNull()!! + val contentState = state.contentState as ContentState.Loaded assertThat(contentState.roomId).isEqualTo(A_ROOM_ID) assertThat(contentState.name).isEqualTo(roomDescription.name) - assertThat(contentState.description).isEqualTo(roomDescription.description) + assertThat(contentState.topic).isEqualTo(roomDescription.topic) + assertThat(contentState.alias).isEqualTo(roomDescription.alias) assertThat(contentState.numberOfMembers).isEqualTo(roomDescription.numberOfMembers) assertThat(contentState.isDirect).isFalse() assertThat(contentState.roomAvatarUrl).isEqualTo(roomDescription.avatarUrl) @@ -256,8 +258,9 @@ class JoinRoomPresenterTest { private fun aRoomDescription( roomId: RoomId = A_ROOM_ID, - name: String = A_ROOM_NAME, - description: String = "A room about something", + name: String? = A_ROOM_NAME, + topic: String? = "A room about something", + alias: String? = "#alias:matrix.org", avatarUrl: String? = null, joinRule: RoomDescription.JoinRule = RoomDescription.JoinRule.UNKNOWN, numberOfMembers: Long = 2L @@ -265,7 +268,8 @@ class JoinRoomPresenterTest { return RoomDescription( roomId = roomId, name = name, - description = description, + topic = topic, + alias = alias, avatarUrl = avatarUrl, joinRule = joinRule, numberOfMembers = numberOfMembers diff --git a/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDescription.kt b/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDescription.kt index a0a0e45a54..632173100a 100644 --- a/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDescription.kt +++ b/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDescription.kt @@ -17,16 +17,19 @@ package io.element.android.features.roomdirectory.api import android.os.Parcelable +import androidx.compose.runtime.Immutable import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.core.RoomId import kotlinx.parcelize.Parcelize @Parcelize +@Immutable data class RoomDescription( val roomId: RoomId, - val name: String, - val description: String, + val name: String?, + val alias: String?, + val topic: String?, val avatarUrl: String?, val joinRule: JoinRule, val numberOfMembers: Long, @@ -38,6 +41,18 @@ data class RoomDescription( UNKNOWN } + val computedName = name ?: alias ?: roomId.value + + val computedDescription: String + get() { + return when { + topic != null -> topic + name != null && alias != null -> alias + name == null && alias == null -> "" + else -> roomId.value + } + } + fun canBeJoined() = joinRule == JoinRule.PUBLIC || joinRule == JoinRule.KNOCK fun avatarData(size: AvatarSize) = AvatarData( diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryStateProvider.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryStateProvider.kt index ccfdd4c1f1..e94271cfb8 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryStateProvider.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryStateProvider.kt @@ -68,7 +68,8 @@ fun aRoomDescriptionList(): ImmutableList { RoomDescription( roomId = RoomId("!exa:matrix.org"), name = "Element X Android", - description = "Element X is a secure, private and decentralized messenger.", + topic = "Element X is a secure, private and decentralized messenger.", + alias = "#element-x-android:matrix.org", avatarUrl = null, joinRule = RoomDescription.JoinRule.PUBLIC, numberOfMembers = 2765, @@ -76,7 +77,8 @@ fun aRoomDescriptionList(): ImmutableList { RoomDescription( roomId = RoomId("!exi:matrix.org"), name = "Element X iOS", - description = "Element X is a secure, private and decentralized messenger.", + topic = "Element X is a secure, private and decentralized messenger.", + alias = "#element-x-ios:matrix.org", avatarUrl = null, joinRule = RoomDescription.JoinRule.UNKNOWN, numberOfMembers = 356, diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt index f1ea915c17..c8fe34e85e 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt @@ -292,14 +292,14 @@ private fun RoomDirectoryRoomRow( .padding(start = 16.dp) ) { Text( - text = roomDescription.name, + text = roomDescription.computedName, maxLines = 1, style = ElementTheme.typography.fontBodyLgRegular, color = ElementTheme.colors.textPrimary, overflow = TextOverflow.Ellipsis, ) Text( - text = roomDescription.description, + text = roomDescription.computedDescription, maxLines = 1, style = ElementTheme.typography.fontBodyMdRegular, color = ElementTheme.colors.textSecondary, diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/model/RoomDescription.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/model/RoomDescription.kt index eec9f6acf9..994f20dd16 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/model/RoomDescription.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/model/RoomDescription.kt @@ -17,31 +17,15 @@ package io.element.android.features.roomdirectory.impl.root.model import io.element.android.features.roomdirectory.api.RoomDescription -import io.element.android.libraries.designsystem.components.avatar.AvatarData -import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.roomdirectory.RoomDescription as MatrixRoomDescription fun MatrixRoomDescription.toFeatureModel(): RoomDescription { - fun name(): String { - return name ?: alias ?: roomId.value - } - - fun description(): String { - val topic = topic - val alias = alias - val name = name - return when { - topic != null -> topic - name != null && alias != null -> alias - name == null && alias == null -> "" - else -> roomId.value - } - } return RoomDescription( roomId = roomId, - name = name(), - description = description(), + name = name, + alias = alias, + topic = topic, avatarUrl = avatarUrl, numberOfMembers = numberOfMembers, joinRule = when (joinRule) { diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt index b2cf88b8bc..71dfecddb8 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt @@ -18,6 +18,7 @@ package io.element.android.libraries.designsystem.atomic.pages import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -43,6 +44,7 @@ import io.element.android.libraries.designsystem.theme.components.Text @Composable fun HeaderFooterPage( modifier: Modifier = Modifier, + paddingValues: PaddingValues = PaddingValues(20.dp), background: @Composable () -> Unit = {}, topBar: @Composable () -> Unit = {}, header: @Composable () -> Unit = {}, @@ -57,7 +59,7 @@ fun HeaderFooterPage( background() Column( modifier = Modifier - .padding(all = 20.dp) + .padding(paddingValues = paddingValues) .padding(padding) .consumeWindowInsets(padding) ) { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/CallbackFlow.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/CallbackFlow.kt index fbf393e587..b17a2f8cf2 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/CallbackFlow.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/CallbackFlow.kt @@ -16,6 +16,7 @@ package io.element.android.libraries.matrix.impl.util +import io.element.android.libraries.core.data.tryOrNull import kotlinx.coroutines.channels.ProducerScope import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.callbackFlow @@ -23,7 +24,9 @@ import org.matrix.rustcomponents.sdk.TaskHandle internal fun mxCallbackFlow(block: suspend ProducerScope.() -> TaskHandle?) = callbackFlow { - val taskHandle: TaskHandle? = block(this) + val taskHandle: TaskHandle? = tryOrNull { + block(this) + } awaitClose { taskHandle?.cancelAndDestroy() }