Skip to content

Commit 9d05eb8

Browse files
committed
feature(space): make sure to handle topic properly
1 parent dbc0c42 commit 9d05eb8

File tree

7 files changed

+102
-3
lines changed

7 files changed

+102
-3
lines changed

features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceEvents.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,7 @@ sealed interface SpaceEvents {
1515
data object ClearFailures : SpaceEvents
1616
data class AcceptInvite(val spaceRoom: SpaceRoom) : SpaceEvents
1717
data class DeclineInvite(val spaceRoom: SpaceRoom) : SpaceEvents
18+
19+
data class ShowTopicViewer(val topic: String) : SpaceEvents
20+
data object HideTopicViewer : SpaceEvents
1821
}

features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpacePresenter.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ class SpacePresenter(
8080
val currentSpace by spaceRoomList.currentSpaceFlow.collectAsState()
8181
val (joinActions, setJoinActions) = remember { mutableStateOf(emptyMap<RoomId, AsyncAction<Unit>>()) }
8282

83+
var topicViewerState: TopicViewerState by remember { mutableStateOf(TopicViewerState.Hidden) }
84+
8385
LaunchedEffect(children) {
8486
// Remove joined children from the join actions
8587
val joinedChildren = children
@@ -112,6 +114,8 @@ class SpacePresenter(
112114
AcceptDeclineInviteEvents.DeclineInvite(invite = event.spaceRoom.toInviteData(), shouldConfirm = true, blockUser = false)
113115
)
114116
}
117+
SpaceEvents.HideTopicViewer -> topicViewerState = TopicViewerState.Hidden
118+
is SpaceEvents.ShowTopicViewer -> topicViewerState = TopicViewerState.Shown(event.topic)
115119
}
116120
}
117121
return SpaceState(
@@ -122,6 +126,7 @@ class SpacePresenter(
122126
hasMoreToLoad = hasMoreToLoad,
123127
joinActions = joinActions.toPersistentMap(),
124128
acceptDeclineInviteState = acceptDeclineInviteState,
129+
topicViewerState = topicViewerState,
125130
eventSink = ::handleEvents,
126131
)
127132
}

features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceState.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
package io.element.android.features.space.impl.root
99

10+
import androidx.compose.runtime.Immutable
1011
import io.element.android.features.invite.api.acceptdecline.AcceptDeclineInviteState
1112
import io.element.android.libraries.architecture.AsyncAction
1213
import io.element.android.libraries.matrix.api.core.RoomId
@@ -23,10 +24,17 @@ data class SpaceState(
2324
val hasMoreToLoad: Boolean,
2425
val joinActions: ImmutableMap<RoomId, AsyncAction<Unit>>,
2526
val acceptDeclineInviteState: AcceptDeclineInviteState,
27+
val topicViewerState: TopicViewerState,
2628
val eventSink: (SpaceEvents) -> Unit
2729
) {
2830
fun isJoining(spaceId: RoomId): Boolean = joinActions[spaceId] == AsyncAction.Loading
2931
val hasAnyFailure: Boolean = joinActions.values.any {
3032
it is AsyncAction.Failure
3133
}
3234
}
35+
36+
@Immutable
37+
sealed interface TopicViewerState {
38+
data object Hidden : TopicViewerState
39+
data class Shown(val topic: String) : TopicViewerState
40+
}

features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceStateProvider.kt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,17 @@ open class SpaceStateProvider : PreviewParameterProvider<SpaceState> {
5151
hasMoreToLoad = false,
5252
children = aListOfSpaceRooms(),
5353
joiningRooms = setOf(RoomId("!spaceId0:example.com")),
54-
)
54+
),
55+
aSpaceState(
56+
hasMoreToLoad = false,
57+
topicViewerState = TopicViewerState.Shown(
58+
topic = "Description of the space goes right here. Lorem ipsum dolor sit amet consectetur. " +
59+
"Leo viverra morbi habitant in. Sem amet enim habitant nibh augue mauris. " +
60+
"Interdum mauris ultrices tincidunt proin morbi erat aenean risus nibh. " +
61+
"Diam amet sit fermentum vulputate faucibus."
62+
),
63+
children = aListOfSpaceRooms(),
64+
),
5565
// Add other states here
5666
)
5767
}
@@ -70,6 +80,7 @@ fun aSpaceState(
7080
hideInvitesAvatar: Boolean = false,
7181
hasMoreToLoad: Boolean = false,
7282
acceptDeclineInviteState: AcceptDeclineInviteState = anAcceptDeclineInviteState(),
83+
topicViewerState: TopicViewerState = TopicViewerState.Hidden,
7384
eventSink: (SpaceEvents) -> Unit = { },
7485
) = SpaceState(
7586
currentSpace = parentSpace,
@@ -79,6 +90,7 @@ fun aSpaceState(
7990
hasMoreToLoad = hasMoreToLoad,
8091
joinActions = joinActions.toImmutableMap(),
8192
acceptDeclineInviteState = acceptDeclineInviteState,
93+
topicViewerState = topicViewerState,
8294
eventSink = eventSink,
8395
)
8496

features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceView.kt

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,18 @@
77

88
package io.element.android.features.space.impl.root
99

10+
import androidx.compose.foundation.interaction.MutableInteractionSource
1011
import androidx.compose.foundation.layout.Box
12+
import androidx.compose.foundation.layout.Column
1113
import androidx.compose.foundation.layout.Row
14+
import androidx.compose.foundation.layout.Spacer
1215
import androidx.compose.foundation.layout.fillMaxSize
1316
import androidx.compose.foundation.layout.fillMaxWidth
17+
import androidx.compose.foundation.layout.height
1418
import androidx.compose.foundation.layout.padding
1519
import androidx.compose.foundation.lazy.LazyColumn
1620
import androidx.compose.material3.ExperimentalMaterial3Api
21+
import androidx.compose.material3.rememberModalBottomSheetState
1722
import androidx.compose.runtime.Composable
1823
import androidx.compose.runtime.LaunchedEffect
1924
import androidx.compose.runtime.getValue
@@ -33,6 +38,7 @@ import androidx.compose.ui.unit.dp
3338
import io.element.android.compound.theme.ElementTheme
3439
import io.element.android.compound.tokens.generated.CompoundIcons
3540
import io.element.android.libraries.designsystem.atomic.molecules.InviteButtonsRowMolecule
41+
import io.element.android.libraries.designsystem.components.ClickableLinkText
3642
import io.element.android.libraries.designsystem.components.async.AsyncIndicator
3743
import io.element.android.libraries.designsystem.components.async.AsyncIndicatorHost
3844
import io.element.android.libraries.designsystem.components.async.rememberAsyncIndicatorState
@@ -48,6 +54,7 @@ import io.element.android.libraries.designsystem.theme.components.DropdownMenu
4854
import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem
4955
import io.element.android.libraries.designsystem.theme.components.Icon
5056
import io.element.android.libraries.designsystem.theme.components.IconButton
57+
import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet
5158
import io.element.android.libraries.designsystem.theme.components.Scaffold
5259
import io.element.android.libraries.designsystem.theme.components.Text
5360
import io.element.android.libraries.designsystem.theme.components.TopAppBar
@@ -61,6 +68,7 @@ import io.element.android.libraries.ui.strings.CommonStrings
6168
import kotlinx.collections.immutable.toImmutableList
6269
import kotlinx.coroutines.delay
6370

71+
@OptIn(ExperimentalMaterial3Api::class)
6472
@Composable
6573
fun SpaceView(
6674
state: SpaceState,
@@ -87,7 +95,10 @@ fun SpaceView(
8795
) {
8896
SpaceViewContent(
8997
state = state,
90-
onRoomClick = onRoomClick
98+
onRoomClick = onRoomClick,
99+
onTopicClick = { topic ->
100+
state.eventSink(SpaceEvents.ShowTopicViewer(topic))
101+
}
91102
)
92103
JoinRoomFailureEffect(
93104
hasAnyFailure = state.hasAnyFailure,
@@ -97,6 +108,14 @@ fun SpaceView(
97108
}
98109
},
99110
)
111+
if (state.topicViewerState is TopicViewerState.Shown) {
112+
TopicViewerBottomSheet(
113+
topicViewerState = state.topicViewerState,
114+
onDismiss = {
115+
state.eventSink(SpaceEvents.HideTopicViewer)
116+
}
117+
)
118+
}
100119
}
101120

102121
@Composable
@@ -120,10 +139,44 @@ private fun JoinRoomFailureEffect(
120139
}
121140
}
122141

142+
@OptIn(ExperimentalMaterial3Api::class)
143+
@Composable
144+
private fun TopicViewerBottomSheet(
145+
topicViewerState: TopicViewerState.Shown,
146+
onDismiss: () -> Unit,
147+
modifier: Modifier = Modifier,
148+
) {
149+
ModalBottomSheet(
150+
onDismissRequest = onDismiss,
151+
modifier = modifier,
152+
sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true),
153+
) {
154+
Column(
155+
modifier = Modifier
156+
.fillMaxWidth()
157+
.padding(16.dp),
158+
) {
159+
Text(
160+
stringResource(CommonStrings.common_description),
161+
style = ElementTheme.typography.fontBodyLgMedium,
162+
color = ElementTheme.colors.textPrimary,
163+
)
164+
Spacer(Modifier.height(8.dp))
165+
ClickableLinkText(
166+
text = topicViewerState.topic,
167+
interactionSource = remember { MutableInteractionSource() },
168+
style = ElementTheme.typography.fontBodyMdRegular,
169+
color = ElementTheme.colors.textSecondary,
170+
)
171+
}
172+
}
173+
}
174+
123175
@Composable
124176
private fun SpaceViewContent(
125177
state: SpaceState,
126178
onRoomClick: (spaceRoom: SpaceRoom) -> Unit,
179+
onTopicClick: (String) -> Unit,
127180
modifier: Modifier = Modifier,
128181
) {
129182
LazyColumn(modifier.fillMaxSize()) {
@@ -134,9 +187,11 @@ private fun SpaceViewContent(
134187
avatarData = currentSpace.getAvatarData(AvatarSize.SpaceHeader),
135188
name = currentSpace.displayName,
136189
topic = currentSpace.topic,
190+
topicMaxLines = 2,
137191
visibility = currentSpace.visibility,
138192
heroes = currentSpace.heroes.toImmutableList(),
139193
numberOfMembers = currentSpace.numJoinedMembers,
194+
onTopicClick = onTopicClick
140195
)
141196
}
142197
}

libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ClickableLinkText.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import androidx.compose.runtime.mutableStateOf
2020
import androidx.compose.runtime.remember
2121
import androidx.compose.ui.Modifier
2222
import androidx.compose.ui.geometry.Offset
23+
import androidx.compose.ui.graphics.Color
2324
import androidx.compose.ui.input.pointer.pointerInput
2425
import androidx.compose.ui.platform.LocalUriHandler
2526
import androidx.compose.ui.text.AnnotatedString
@@ -51,6 +52,7 @@ fun ClickableLinkText(
5152
onClick: () -> Unit = {},
5253
onLongClick: () -> Unit = {},
5354
style: TextStyle = LocalTextStyle.current,
55+
color: Color = Color.Unspecified,
5456
inlineContent: ImmutableMap<String, InlineTextContent> = persistentMapOf(),
5557
) {
5658
ClickableLinkText(
@@ -62,6 +64,7 @@ fun ClickableLinkText(
6264
onClick = onClick,
6365
onLongClick = onLongClick,
6466
style = style,
67+
color = color,
6568
inlineContent = inlineContent,
6669
)
6770
}
@@ -76,6 +79,7 @@ fun ClickableLinkText(
7679
onClick: () -> Unit = {},
7780
onLongClick: () -> Unit = {},
7881
style: TextStyle = LocalTextStyle.current,
82+
color: Color = Color.Unspecified,
7983
inlineContent: ImmutableMap<String, InlineTextContent> = persistentMapOf(),
8084
) {
8185
@Suppress("NAME_SHADOWING")
@@ -126,6 +130,7 @@ fun ClickableLinkText(
126130
text = annotatedString,
127131
modifier = modifier.then(pressIndicator),
128132
style = style,
133+
color = color,
129134
onTextLayout = {
130135
layoutResult.value = it
131136
},

libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderView.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
package io.element.android.libraries.matrix.ui.components
99

10+
import androidx.compose.foundation.clickable
1011
import androidx.compose.foundation.layout.padding
1112
import androidx.compose.runtime.Composable
1213
import androidx.compose.ui.Modifier
@@ -43,6 +44,7 @@ fun SpaceHeaderView(
4344
numberOfMembers: Int,
4445
modifier: Modifier = Modifier,
4546
topicMaxLines: Int = Int.MAX_VALUE,
47+
onTopicClick: ((String) -> Unit)? = null,
4648
) {
4749
RoomPreviewOrganism(
4850
modifier = modifier.padding(24.dp),
@@ -68,7 +70,16 @@ fun SpaceHeaderView(
6870
description = if (topic.isNullOrBlank()) {
6971
null
7072
} else {
71-
{ RoomPreviewDescriptionAtom(description = topic, maxLines = topicMaxLines) }
73+
{
74+
RoomPreviewDescriptionAtom(
75+
description = topic,
76+
maxLines = topicMaxLines,
77+
modifier = Modifier.clickable(
78+
enabled = onTopicClick != null,
79+
onClick = { onTopicClick?.invoke(topic) }
80+
)
81+
)
82+
}
7283
},
7384
memberCount = {
7485
SpaceMembersView(

0 commit comments

Comments
 (0)