Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AND-217: Introduce ChatsScreen composable #5556

Merged
merged 2 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ androidxAppcompat = "1.7.0"
androidxCompose = "1.7.5"
androidxComposeConstraintLayout = "1.1.0"
androidxComposeMaterial3 = "1.3.1"
androidxComposeMaterial3Adaptive = "1.0.0"
androidxCoreTest = "2.2.0"
androidxFragment = "1.8.5"
androidxKtx = "1.13.1"
Expand Down Expand Up @@ -100,6 +101,7 @@ androidx-benchmark-macro-junit4 = { module = "androidx.benchmark:benchmark-macro
androidx-compose-constraintlayout-compose = { module = "androidx.constraintlayout:constraintlayout-compose", version.ref = "androidxComposeConstraintLayout"}
androidx-compose-foundation = { module = "androidx.compose.foundation:foundation", version.ref = "androidxCompose"}
androidx-compose-material3 = { module = "androidx.compose.material3:material3", version.ref = "androidxComposeMaterial3"}
androidx-compose-material3-adaptive = { module = "androidx.compose.material3.adaptive:adaptive", version.ref = "androidxComposeMaterial3Adaptive"}
androidx-compose-material-icons-core = { module = "androidx.compose.material:material-icons-core", version.ref = "androidxCompose"}
androidx-compose-runtime = { module = "androidx.compose.runtime:runtime", version.ref = "androidxCompose"}
androidx-compose-ui = { module = "androidx.compose.ui:ui", version.ref = "androidxCompose"}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@
android:exported="false"
android:windowSoftInputMode="adjustResize"
/>
<activity
android:name=".ui.chats.ChatsActivity"
android:exported="false"
/>
<activity
android:name=".feature.channel.list.ChannelsActivity"
android:exported="false"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
/*
* Copyright (c) 2014-2025 Stream.io Inc. All rights reserved.
*
* Licensed under the Stream License;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://github.com/GetStream/stream-chat-android/blob/main/LICENSE
*
* 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.getstream.chat.android.compose.sample.ui.chats

import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.lifecycle.lifecycleScope
import io.getstream.chat.android.client.ChatClient
import io.getstream.chat.android.compose.sample.ChatApp
import io.getstream.chat.android.compose.sample.ChatHelper
import io.getstream.chat.android.compose.sample.R
import io.getstream.chat.android.compose.sample.feature.channel.ChannelConstants.CHANNEL_ARG_DRAFT
import io.getstream.chat.android.compose.sample.feature.channel.add.AddChannelActivity
import io.getstream.chat.android.compose.sample.feature.channel.list.CustomChatEventHandlerFactory
import io.getstream.chat.android.compose.sample.ui.BaseConnectedActivity
import io.getstream.chat.android.compose.sample.ui.MessagesActivity
import io.getstream.chat.android.compose.sample.ui.channel.ChannelInfoActivity
import io.getstream.chat.android.compose.sample.ui.component.AppBottomBar
import io.getstream.chat.android.compose.sample.ui.component.AppBottomBarOption
import io.getstream.chat.android.compose.sample.ui.login.UserLoginActivity
import io.getstream.chat.android.compose.ui.channels.SearchMode
import io.getstream.chat.android.compose.ui.chats.ChatsScreen
import io.getstream.chat.android.compose.ui.theme.ChatTheme
import io.getstream.chat.android.compose.ui.threads.ThreadList
import io.getstream.chat.android.compose.viewmodel.channels.ChannelViewModelFactory
import io.getstream.chat.android.compose.viewmodel.threads.ThreadListViewModel
import io.getstream.chat.android.compose.viewmodel.threads.ThreadsViewModelFactory
import io.getstream.chat.android.models.Channel
import io.getstream.chat.android.models.Filters
import io.getstream.chat.android.models.Thread
import io.getstream.chat.android.models.querysort.QuerySortByField
import io.getstream.chat.android.state.extensions.globalState
import kotlinx.coroutines.launch

class ChatsActivity : BaseConnectedActivity() {

private val channelViewModelFactory by lazy {
val chatClient = ChatClient.instance()
val currentUserId = chatClient.getCurrentUser()?.id ?: ""
ChannelViewModelFactory(
chatClient = chatClient,
querySort = QuerySortByField.descByName("last_updated"),
filters = Filters.and(
Filters.eq("type", "messaging"),
Filters.`in`("members", listOf(currentUserId)),
Filters.or(Filters.notExists(CHANNEL_ARG_DRAFT), Filters.eq(CHANNEL_ARG_DRAFT, false)),
),
chatEventHandlerFactory = CustomChatEventHandlerFactory(),
)
}
private val threadsViewModelFactory by lazy { ThreadsViewModelFactory() }

private val threadsViewModel: ThreadListViewModel by viewModels { threadsViewModelFactory }

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

setContent {
var selectedTab by rememberSaveable { mutableStateOf(AppBottomBarOption.CHATS) }
val globalState = ChatClient.instance().globalState
val unreadChannelsCount by globalState.channelUnreadCount.collectAsState()
val unreadThreadsCount by globalState.unreadThreadsCount.collectAsState()
var showBottomBar by remember { mutableStateOf(true) }

ChatTheme(
dateFormatter = ChatApp.dateFormatter,
autoTranslationEnabled = ChatApp.autoTranslationEnabled,
allowUIAutomationTest = true,
) {
Scaffold(
bottomBar = {
if (showBottomBar) {
AppBottomBar(
unreadChannelsCount = unreadChannelsCount,
unreadThreadsCount = unreadThreadsCount,
selectedOption = selectedTab,
onOptionSelected = { selectedTab = it },
)
}
},
content = { scaffoldPadding ->
when (selectedTab) {
AppBottomBarOption.CHATS -> ChannelsContent(
modifier = Modifier.padding(scaffoldPadding),
onNavigateToMessages = { channelId, singlePanel ->
showBottomBar = !singlePanel || channelId == null
},
)

AppBottomBarOption.THREADS -> ThreadsContent(
modifier = Modifier.padding(scaffoldPadding),
)
}
},
)
}
}
}

@Composable
private fun ChannelsContent(
modifier: Modifier,
onNavigateToMessages: (channelId: String?, singlePanel: Boolean) -> Unit,
) {
ChatsScreen(
modifier = modifier,
channelViewModelFactory = channelViewModelFactory,
title = stringResource(id = R.string.app_name),
isShowingHeader = true,
searchMode = SearchMode.Messages,
onNavigateToMessages = onNavigateToMessages,
onBackPressed = ::finish,
onChannelsHeaderAvatarClick = {
lifecycleScope.launch {
ChatHelper.disconnectUser()
openUserLogin()
}
},
onChannelsHeaderActionClick = ::openAddChannel,
onViewChannelInfoAction = ::openChannelInfo,
onMessagesHeaderTitleClick = ::openChannelInfo,
)
}

@Composable
private fun ThreadsContent(modifier: Modifier) {
ThreadList(
modifier = modifier,
viewModel = threadsViewModel,
onThreadClick = ::openThread,
)
}

private fun openThread(thread: Thread) {
startActivity(
MessagesActivity.createIntent(
context = applicationContext,
channelId = thread.parentMessage.cid,
parentMessageId = thread.parentMessageId,
),
)
}

private fun openAddChannel() {
startActivity(Intent(applicationContext, AddChannelActivity::class.java))
}

private fun openUserLogin() {
startActivity(UserLoginActivity.createIntent(applicationContext))
}

private fun openChannelInfo(channel: Channel) {
startActivity(ChannelInfoActivity.createIntent(applicationContext, channel.cid))
}

companion object {
fun createIntent(context: Context): Intent =
Intent(context, ChatsActivity::class.java)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,10 @@ public final class io/getstream/chat/android/compose/ui/channels/list/SearchResu
public static final fun SearchResultItem (Lio/getstream/chat/android/compose/state/channels/list/ItemState$SearchResultItemState;Lio/getstream/chat/android/models/User;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;II)V
}

public final class io/getstream/chat/android/compose/ui/chats/ChatsScreenKt {
public static final fun ChatsScreen (Landroidx/compose/ui/Modifier;Lio/getstream/chat/android/compose/viewmodel/channels/ChannelViewModelFactory;Ljava/lang/String;Ljava/lang/String;ZLio/getstream/chat/android/compose/ui/channels/SearchMode;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/Composer;III)V
}

public final class io/getstream/chat/android/compose/ui/components/BackButtonKt {
public static final fun BackButton (Landroidx/compose/ui/graphics/painter/Painter;Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;II)V
}
Expand Down
1 change: 1 addition & 0 deletions stream-chat-android-compose/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ dependencies {
implementation(libs.androidx.compose.foundation)
implementation(libs.androidx.compose.constraintlayout.compose)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.material3.adaptive)

implementation(libs.androidx.activity.compose)
implementation(libs.androidx.lifecycle.viewmodel.compose)
Expand Down
Loading
Loading