Skip to content

Commit 3ac468c

Browse files
authored
Introduce ThreadsScreen and ThreadListHeader components (#6376)
* Introduce ThreadsScreen and ThreadListHeader composables * Dump API
1 parent 73c28b8 commit 3ac468c

19 files changed

Lines changed: 587 additions & 135 deletions

File tree

stream-chat-android-compose-sample/src/main/java/io/getstream/chat/android/compose/sample/feature/channel/list/ChannelsActivity.kt

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,11 @@ import io.getstream.chat.android.compose.ui.theme.ChannelListDividerItemParams
8888
import io.getstream.chat.android.compose.ui.theme.ChannelListItemContentParams
8989
import io.getstream.chat.android.compose.ui.theme.ChatComponentFactory
9090
import io.getstream.chat.android.compose.ui.theme.ChatTheme
91-
import io.getstream.chat.android.compose.ui.threads.ThreadList
91+
import io.getstream.chat.android.compose.ui.threads.ThreadsScreen
9292
import io.getstream.chat.android.compose.viewmodel.channels.ChannelListViewModel
9393
import io.getstream.chat.android.compose.viewmodel.channels.ChannelListViewModelFactory
9494
import io.getstream.chat.android.compose.viewmodel.mentions.MentionListViewModel
9595
import io.getstream.chat.android.compose.viewmodel.mentions.MentionListViewModelFactory
96-
import io.getstream.chat.android.compose.viewmodel.threads.ThreadListViewModel
9796
import io.getstream.chat.android.compose.viewmodel.threads.ThreadsViewModelFactory
9897
import io.getstream.chat.android.models.Channel
9998
import io.getstream.chat.android.models.Filters
@@ -127,10 +126,7 @@ class ChannelsActivity : ComponentActivity() {
127126

128127
private val channelsViewModel: ChannelListViewModel by viewModels { channelsViewModelFactory }
129128
private val mentionListViewModel: MentionListViewModel by viewModels { MentionListViewModelFactory() }
130-
private val threadsViewModel: ThreadListViewModel by viewModels {
131-
val query = QueryThreadsRequest()
132-
ThreadsViewModelFactory(query)
133-
}
129+
private val threadsViewModelFactory = ThreadsViewModelFactory(query = QueryThreadsRequest())
134130

135131
@Suppress("LongMethod")
136132
override fun onCreate(savedInstanceState: Bundle?) {
@@ -209,7 +205,13 @@ class ChannelsActivity : ComponentActivity() {
209205
)
210206

211207
AppBottomBarOption.MENTIONS -> MentionsContent()
212-
AppBottomBarOption.THREADS -> ThreadsContent()
208+
AppBottomBarOption.THREADS -> ThreadsContent(
209+
onHeaderAvatarClick = {
210+
coroutineScope.launch {
211+
drawerState.open()
212+
}
213+
},
214+
)
213215
}
214216
}
215217
}
@@ -248,10 +250,10 @@ class ChannelsActivity : ComponentActivity() {
248250
}
249251

250252
@Composable
251-
private fun ThreadsContent() {
252-
ThreadList(
253-
viewModel = threadsViewModel,
254-
modifier = Modifier.fillMaxSize(),
253+
private fun ThreadsContent(onHeaderAvatarClick: () -> Unit) {
254+
ThreadsScreen(
255+
viewModelFactory = threadsViewModelFactory,
256+
onHeaderAvatarClick = onHeaderAvatarClick,
255257
onThreadClick = ::openThread,
256258
)
257259
}

stream-chat-android-compose/api/stream-chat-android-compose.api

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3451,6 +3451,7 @@ public abstract interface class io/getstream/chat/android/compose/ui/theme/ChatC
34513451
public fun SwipeToReplyContent (Landroidx/compose/foundation/layout/RowScope;Lio/getstream/chat/android/compose/ui/theme/SwipeToReplyContentParams;Landroidx/compose/runtime/Composer;I)V
34523452
public fun ThreadListBanner (Lio/getstream/chat/android/compose/ui/theme/ThreadListBannerParams;Landroidx/compose/runtime/Composer;I)V
34533453
public fun ThreadListEmptyContent (Lio/getstream/chat/android/compose/ui/theme/ThreadListEmptyContentParams;Landroidx/compose/runtime/Composer;I)V
3454+
public fun ThreadListHeader (Lio/getstream/chat/android/compose/ui/theme/ThreadListHeaderParams;Landroidx/compose/runtime/Composer;I)V
34543455
public fun ThreadListItem (Lio/getstream/chat/android/compose/ui/theme/ThreadListItemParams;Landroidx/compose/runtime/Composer;I)V
34553456
public fun ThreadListLoadingContent (Lio/getstream/chat/android/compose/ui/theme/ThreadListLoadingContentParams;Landroidx/compose/runtime/Composer;I)V
34563457
public fun ThreadListLoadingMoreContent (Lio/getstream/chat/android/compose/ui/theme/ThreadListLoadingMoreContentParams;Landroidx/compose/runtime/Composer;I)V
@@ -3639,6 +3640,7 @@ public final class io/getstream/chat/android/compose/ui/theme/ChatComponentFacto
36393640
public static fun SwipeToReplyContent (Lio/getstream/chat/android/compose/ui/theme/ChatComponentFactory;Landroidx/compose/foundation/layout/RowScope;Lio/getstream/chat/android/compose/ui/theme/SwipeToReplyContentParams;Landroidx/compose/runtime/Composer;I)V
36403641
public static fun ThreadListBanner (Lio/getstream/chat/android/compose/ui/theme/ChatComponentFactory;Lio/getstream/chat/android/compose/ui/theme/ThreadListBannerParams;Landroidx/compose/runtime/Composer;I)V
36413642
public static fun ThreadListEmptyContent (Lio/getstream/chat/android/compose/ui/theme/ChatComponentFactory;Lio/getstream/chat/android/compose/ui/theme/ThreadListEmptyContentParams;Landroidx/compose/runtime/Composer;I)V
3643+
public static fun ThreadListHeader (Lio/getstream/chat/android/compose/ui/theme/ChatComponentFactory;Lio/getstream/chat/android/compose/ui/theme/ThreadListHeaderParams;Landroidx/compose/runtime/Composer;I)V
36423644
public static fun ThreadListItem (Lio/getstream/chat/android/compose/ui/theme/ChatComponentFactory;Lio/getstream/chat/android/compose/ui/theme/ThreadListItemParams;Landroidx/compose/runtime/Composer;I)V
36433645
public static fun ThreadListLoadingContent (Lio/getstream/chat/android/compose/ui/theme/ChatComponentFactory;Lio/getstream/chat/android/compose/ui/theme/ThreadListLoadingContentParams;Landroidx/compose/runtime/Composer;I)V
36443646
public static fun ThreadListLoadingMoreContent (Lio/getstream/chat/android/compose/ui/theme/ChatComponentFactory;Lio/getstream/chat/android/compose/ui/theme/ThreadListLoadingMoreContentParams;Landroidx/compose/runtime/Composer;I)V
@@ -6049,6 +6051,27 @@ public final class io/getstream/chat/android/compose/ui/theme/ThreadListEmptyCon
60496051
public fun toString ()Ljava/lang/String;
60506052
}
60516053

6054+
public final class io/getstream/chat/android/compose/ui/theme/ThreadListHeaderParams {
6055+
public static final field $stable I
6056+
public fun <init> (Lio/getstream/chat/android/models/ConnectionState;Landroidx/compose/ui/Modifier;Ljava/lang/String;Lio/getstream/chat/android/models/User;Lkotlin/jvm/functions/Function1;)V
6057+
public synthetic fun <init> (Lio/getstream/chat/android/models/ConnectionState;Landroidx/compose/ui/Modifier;Ljava/lang/String;Lio/getstream/chat/android/models/User;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
6058+
public final fun component1 ()Lio/getstream/chat/android/models/ConnectionState;
6059+
public final fun component2 ()Landroidx/compose/ui/Modifier;
6060+
public final fun component3 ()Ljava/lang/String;
6061+
public final fun component4 ()Lio/getstream/chat/android/models/User;
6062+
public final fun component5 ()Lkotlin/jvm/functions/Function1;
6063+
public final fun copy (Lio/getstream/chat/android/models/ConnectionState;Landroidx/compose/ui/Modifier;Ljava/lang/String;Lio/getstream/chat/android/models/User;Lkotlin/jvm/functions/Function1;)Lio/getstream/chat/android/compose/ui/theme/ThreadListHeaderParams;
6064+
public static synthetic fun copy$default (Lio/getstream/chat/android/compose/ui/theme/ThreadListHeaderParams;Lio/getstream/chat/android/models/ConnectionState;Landroidx/compose/ui/Modifier;Ljava/lang/String;Lio/getstream/chat/android/models/User;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lio/getstream/chat/android/compose/ui/theme/ThreadListHeaderParams;
6065+
public fun equals (Ljava/lang/Object;)Z
6066+
public final fun getConnectionState ()Lio/getstream/chat/android/models/ConnectionState;
6067+
public final fun getCurrentUser ()Lio/getstream/chat/android/models/User;
6068+
public final fun getModifier ()Landroidx/compose/ui/Modifier;
6069+
public final fun getOnAvatarClick ()Lkotlin/jvm/functions/Function1;
6070+
public final fun getTitle ()Ljava/lang/String;
6071+
public fun hashCode ()I
6072+
public fun toString ()Ljava/lang/String;
6073+
}
6074+
60526075
public final class io/getstream/chat/android/compose/ui/theme/ThreadListItemParams {
60536076
public static final field $stable I
60546077
public fun <init> (Lio/getstream/chat/android/models/Thread;Lio/getstream/chat/android/models/User;Lkotlin/jvm/functions/Function1;)V
@@ -6137,6 +6160,14 @@ public final class io/getstream/chat/android/compose/ui/threads/ComposableSingle
61376160
public final fun getLambda$881034423$stream_chat_android_compose_release ()Lkotlin/jvm/functions/Function2;
61386161
}
61396162

6163+
public final class io/getstream/chat/android/compose/ui/threads/ComposableSingletons$ThreadListHeaderKt {
6164+
public static final field INSTANCE Lio/getstream/chat/android/compose/ui/threads/ComposableSingletons$ThreadListHeaderKt;
6165+
public fun <init> ()V
6166+
public final fun getLambda$-798078767$stream_chat_android_compose_release ()Lkotlin/jvm/functions/Function2;
6167+
public final fun getLambda$1850390573$stream_chat_android_compose_release ()Lkotlin/jvm/functions/Function3;
6168+
public final fun getLambda$381085544$stream_chat_android_compose_release ()Lkotlin/jvm/functions/Function2;
6169+
}
6170+
61406171
public final class io/getstream/chat/android/compose/ui/threads/ComposableSingletons$ThreadListKt {
61416172
public static final field INSTANCE Lio/getstream/chat/android/compose/ui/threads/ComposableSingletons$ThreadListKt;
61426173
public fun <init> ()V
@@ -6192,11 +6223,19 @@ public final class io/getstream/chat/android/compose/ui/threads/ThreadListBanner
61926223
public fun toString ()Ljava/lang/String;
61936224
}
61946225

6226+
public final class io/getstream/chat/android/compose/ui/threads/ThreadListHeaderKt {
6227+
public static final fun ThreadListHeader (Landroidx/compose/ui/Modifier;Ljava/lang/String;Lio/getstream/chat/android/models/User;Lio/getstream/chat/android/models/ConnectionState;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)V
6228+
}
6229+
61956230
public final class io/getstream/chat/android/compose/ui/threads/ThreadListKt {
61966231
public static final fun ThreadList (Lio/getstream/chat/android/compose/viewmodel/threads/ThreadListViewModel;Landroidx/compose/ui/Modifier;Lio/getstream/chat/android/models/User;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/Composer;II)V
61976232
public static final fun ThreadList (Lio/getstream/chat/android/ui/common/state/threads/ThreadListState;Landroidx/compose/ui/Modifier;Lio/getstream/chat/android/models/User;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/Composer;II)V
61986233
}
61996234

6235+
public final class io/getstream/chat/android/compose/ui/threads/ThreadsScreenKt {
6236+
public static final fun ThreadsScreen (Lio/getstream/chat/android/compose/viewmodel/threads/ThreadsViewModelFactory;Ljava/lang/String;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)V
6237+
}
6238+
62006239
public final class io/getstream/chat/android/compose/ui/util/ChannelUtilsKt {
62016240
public static final fun getLastMessage (Lio/getstream/chat/android/models/Channel;Lio/getstream/chat/android/models/User;)Lio/getstream/chat/android/models/Message;
62026241
public static final fun getMembersStatusText (Lio/getstream/chat/android/models/Channel;Landroid/content/Context;Lio/getstream/chat/android/models/User;)Ljava/lang/String;
@@ -6815,7 +6854,9 @@ public final class io/getstream/chat/android/compose/viewmodel/pinned/PinnedMess
68156854
public final class io/getstream/chat/android/compose/viewmodel/threads/ThreadListViewModel : androidx/lifecycle/ViewModel {
68166855
public static final field $stable I
68176856
public fun <init> (Lio/getstream/chat/android/ui/common/feature/threads/ThreadListController;)V
6857+
public final fun getConnectionState ()Lkotlinx/coroutines/flow/StateFlow;
68186858
public final fun getState ()Lkotlinx/coroutines/flow/StateFlow;
6859+
public final fun getUser ()Lkotlinx/coroutines/flow/StateFlow;
68196860
public final fun load ()V
68206861
public final fun loadNextPage ()V
68216862
}

stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channels/header/ChannelListHeader.kt

Lines changed: 7 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -16,41 +16,21 @@
1616

1717
package io.getstream.chat.android.compose.ui.channels.header
1818

19-
import androidx.compose.foundation.layout.Arrangement
20-
import androidx.compose.foundation.layout.Box
21-
import androidx.compose.foundation.layout.Column
22-
import androidx.compose.foundation.layout.Row
2319
import androidx.compose.foundation.layout.RowScope
24-
import androidx.compose.foundation.layout.Spacer
25-
import androidx.compose.foundation.layout.fillMaxWidth
26-
import androidx.compose.foundation.layout.padding
27-
import androidx.compose.foundation.layout.size
28-
import androidx.compose.foundation.layout.wrapContentWidth
29-
import androidx.compose.foundation.shape.CircleShape
30-
import androidx.compose.material3.HorizontalDivider
3120
import androidx.compose.material3.Icon
32-
import androidx.compose.material3.Surface
33-
import androidx.compose.material3.Text
3421
import androidx.compose.runtime.Composable
35-
import androidx.compose.ui.Alignment
3622
import androidx.compose.ui.Modifier
37-
import androidx.compose.ui.draw.clip
3823
import androidx.compose.ui.platform.testTag
3924
import androidx.compose.ui.res.painterResource
4025
import androidx.compose.ui.res.stringResource
4126
import androidx.compose.ui.tooling.preview.Preview
42-
import androidx.compose.ui.unit.dp
4327
import io.getstream.chat.android.compose.R
44-
import io.getstream.chat.android.compose.ui.components.NetworkLoadingIndicator
45-
import io.getstream.chat.android.compose.ui.components.avatar.AvatarSize
28+
import io.getstream.chat.android.compose.ui.components.ListHeader
4629
import io.getstream.chat.android.compose.ui.components.button.StreamButton
4730
import io.getstream.chat.android.compose.ui.theme.ChannelListHeaderCenterContentParams
4831
import io.getstream.chat.android.compose.ui.theme.ChannelListHeaderLeadingContentParams
4932
import io.getstream.chat.android.compose.ui.theme.ChannelListHeaderTrailingContentParams
5033
import io.getstream.chat.android.compose.ui.theme.ChatTheme
51-
import io.getstream.chat.android.compose.ui.theme.StreamTokens
52-
import io.getstream.chat.android.compose.ui.theme.UserAvatarParams
53-
import io.getstream.chat.android.compose.ui.util.clickable
5434
import io.getstream.chat.android.models.ConnectionState
5535
import io.getstream.chat.android.models.User
5636
import io.getstream.chat.android.previewdata.PreviewUserData
@@ -111,104 +91,12 @@ public fun ChannelListHeader(
11191
}
11292
},
11393
) {
114-
Surface(
115-
modifier = modifier.fillMaxWidth(),
116-
color = ChatTheme.colors.backgroundCoreElevation1,
117-
) {
118-
Column {
119-
Row(
120-
Modifier
121-
.fillMaxWidth()
122-
.padding(StreamTokens.spacingSm),
123-
verticalAlignment = Alignment.CenterVertically,
124-
horizontalArrangement = Arrangement.spacedBy(StreamTokens.spacingXs),
125-
) {
126-
leadingContent()
127-
128-
centerContent()
129-
130-
trailingContent()
131-
}
132-
HorizontalDivider(
133-
thickness = 1.dp,
134-
color = ChatTheme.colors.borderCoreDefault,
135-
)
136-
}
137-
}
138-
}
139-
140-
/**
141-
* Represents the default leading content of a channel list header, which is the currently logged-in user avatar.
142-
*
143-
* We show the avatar if the user is available, otherwise we add a spacer to make sure the alignment is correct.
144-
*/
145-
@Composable
146-
internal fun DefaultChannelListHeaderLeadingContent(
147-
currentUser: User?,
148-
onAvatarClick: (User?) -> Unit,
149-
) {
150-
if (currentUser != null) {
151-
Box(
152-
modifier = Modifier
153-
.size(AvatarSize.ExtraLarge)
154-
.clip(CircleShape)
155-
.clickable { onAvatarClick(currentUser) },
156-
contentAlignment = Alignment.Center,
157-
) {
158-
ChatTheme.componentFactory.UserAvatar(
159-
params = UserAvatarParams(
160-
modifier = Modifier
161-
.size(AvatarSize.Large)
162-
.testTag("Stream_UserAvatar"),
163-
user = currentUser,
164-
),
165-
)
166-
}
167-
} else {
168-
Spacer(modifier = Modifier.size(AvatarSize.ExtraLarge))
169-
}
170-
}
171-
172-
/**
173-
* Represents the channel header's center slot. It either shows a [Text] if [connectionState] is
174-
* [ConnectionState.CONNECTED], or a [NetworkLoadingIndicator] if there is no connections.
175-
*
176-
* @param connectionState The state of WebSocket connection.
177-
* @param title The title to show.
178-
*/
179-
@Composable
180-
internal fun RowScope.DefaultChannelListHeaderCenterContent(
181-
connectionState: ConnectionState,
182-
title: String,
183-
) {
184-
when (connectionState) {
185-
is ConnectionState.Connected -> {
186-
Text(
187-
modifier = Modifier
188-
.weight(1f)
189-
.wrapContentWidth()
190-
.padding(horizontal = StreamTokens.spacingMd),
191-
text = title,
192-
style = ChatTheme.typography.headingSmall,
193-
maxLines = 1,
194-
color = ChatTheme.colors.textPrimary,
195-
)
196-
}
197-
198-
is ConnectionState.Connecting -> NetworkLoadingIndicator(modifier = Modifier.weight(1f))
199-
is ConnectionState.Offline -> {
200-
Text(
201-
modifier = Modifier
202-
.weight(1f)
203-
.wrapContentWidth()
204-
.padding(horizontal = StreamTokens.spacingMd),
205-
text = stringResource(R.string.stream_compose_disconnected),
206-
style = ChatTheme.typography.headingSmall,
207-
maxLines = 1,
208-
color = ChatTheme.colors.textPrimary,
209-
)
210-
}
211-
}
94+
ListHeader(
95+
modifier = modifier,
96+
leadingContent = leadingContent,
97+
centerContent = centerContent,
98+
trailingContent = trailingContent,
99+
)
212100
}
213101

214102
/**

0 commit comments

Comments
 (0)