Skip to content

Commit

Permalink
[PBE-3749] Implement 'Threads' tab in compose sample app.
Browse files Browse the repository at this point in the history
  • Loading branch information
PetarVelikov committed Oct 14, 2024
1 parent 8d30835 commit fdb1ac1
Show file tree
Hide file tree
Showing 6 changed files with 221 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ 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.Alignment
import androidx.compose.ui.Modifier
Expand All @@ -49,6 +50,8 @@ 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.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.state.channels.list.ItemState
import io.getstream.chat.android.compose.state.channels.list.SearchQuery
Expand All @@ -60,8 +63,11 @@ import io.getstream.chat.android.compose.ui.channels.list.ChannelItem
import io.getstream.chat.android.compose.ui.channels.list.ChannelList
import io.getstream.chat.android.compose.ui.components.SearchInput
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.ChannelListViewModel
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.Message
import io.getstream.chat.android.models.User
Expand All @@ -70,15 +76,17 @@ import kotlinx.coroutines.launch

class ChannelsActivity : BaseConnectedActivity() {

private val factory by lazy {
private val listViewModelFactory by lazy {
ChannelViewModelFactory(
ChatClient.instance(),
QuerySortByField.descByName("last_updated"),
null,
)
}
private val threadsViewModelFactory by lazy { ThreadsViewModelFactory() }

private val listViewModel: ChannelListViewModel by viewModels { factory }
private val listViewModel: ChannelListViewModel by viewModels { listViewModelFactory }
private val threadsViewModel: ThreadListViewModel by viewModels { threadsViewModelFactory }

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -91,34 +99,64 @@ class ChannelsActivity : BaseConnectedActivity() {
* or build a custom component yourself, like [MyCustomUi].
*/
setContent {
var selectedTab by rememberSaveable { mutableStateOf(AppBottomBarOption.CHATS) }

ChatTheme(
dateFormatter = ChatApp.dateFormatter,
autoTranslationEnabled = ChatApp.autoTranslationEnabled,
allowUIAutomationTest = true,
) {
ChannelsScreen(
viewModelFactory = factory,
title = stringResource(id = R.string.app_name),
isShowingHeader = true,
searchMode = SearchMode.Messages,
onChannelClick = ::openMessages,
onSearchMessageItemClick = ::openMessages,
onBackPressed = ::finish,
onHeaderAvatarClick = {
listViewModel.viewModelScope.launch {
ChatHelper.disconnectUser()
openUserLogin()
}
Scaffold(
bottomBar = {
AppBottomBar(
selectedOption = selectedTab,
onOptionSelected = { selectedTab = it },
)
},
onHeaderActionClick = {
listViewModel.refresh()
content = { _ ->
when (selectedTab) {
AppBottomBarOption.CHATS -> ChannelsContent()
AppBottomBarOption.THREADS -> ThreadsContent()
}
},
)
}
}
}

@Composable
private fun ChannelsContent() {
ChannelsScreen(
viewModelFactory = listViewModelFactory,
title = stringResource(id = R.string.app_name),
isShowingHeader = true,
searchMode = SearchMode.Messages,
onChannelClick = ::openMessages,
onSearchMessageItemClick = ::openMessages,
onBackPressed = ::finish,
onHeaderAvatarClick = {
listViewModel.viewModelScope.launch {
ChatHelper.disconnectUser()
openUserLogin()
}
},
onHeaderActionClick = {
listViewModel.refresh()
},
)

// MyCustomUiSimplified()
// MyCustomUi()
}
}
}

@Composable
private fun ThreadsContent() {
ThreadList(
viewModel = threadsViewModel,
modifier = Modifier
.fillMaxSize()
.background(ChatTheme.colors.appBackground),
)
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright (c) 2014-2024 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.component

import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Icon
import androidx.compose.material.Text
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.unit.dp
import androidx.compose.ui.unit.sp
import io.getstream.chat.android.compose.sample.R
import io.getstream.chat.android.compose.ui.theme.ChatTheme

/**
* Defines the possible options of the app bottom bar.
*/
enum class AppBottomBarOption {
CHATS,
THREADS,
}

/**
* Renders the default app bottom bar for switching between chats/threads.
*
* @param selectedOption The currently selected [AppBottomBarOption].
* @param onOptionSelected Action when invoked when the user clicks on an [AppBottomBarOption].
*/
@Composable
fun AppBottomBar(
selectedOption: AppBottomBarOption,
onOptionSelected: (AppBottomBarOption) -> Unit,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.background(ChatTheme.colors.barsBackground),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly,
) {
AppBottomBarOptionTile(
icon = R.drawable.ic_chats,
text = R.string.app_bottom_bar_chats,
isSelected = selectedOption == AppBottomBarOption.CHATS,
onClick = { onOptionSelected(AppBottomBarOption.CHATS) },
)
AppBottomBarOptionTile(
icon = R.drawable.ic_threads,
text = R.string.app_bottom_bar_threads,
isSelected = selectedOption == AppBottomBarOption.THREADS,
onClick = { onOptionSelected(AppBottomBarOption.THREADS) },
)
}
}

@Composable
private fun AppBottomBarOptionTile(
@DrawableRes icon: Int,
@StringRes text: Int,
isSelected: Boolean,
onClick: () -> Unit,
) {
val contentColor = if (isSelected) ChatTheme.colors.textHighEmphasis else ChatTheme.colors.textLowEmphasis
Column(
modifier = Modifier
.clickable { onClick() }
.padding(8.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Icon(
painter = painterResource(icon),
contentDescription = null,
tint = contentColor,
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = stringResource(text),
fontSize = 12.sp,
color = contentColor,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2014-2024 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M20,2H4C2.9,2 2,2.9 2,4V22L6,18H20C21.1,18 22,17.1 22,16V4C22,2.9 21.1,2 20,2ZM20,16H6L4,18V4H20V16Z"
android:fillColor="#080707"/>
</vector>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2014-2024 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M4,4H20V16H5.17L4,17.17V4ZM4,2C2.9,2 2.01,2.9 2.01,4L2,22L6,18H20C21.1,18 22,17.1 22,16V4C22,2.9 21.1,2 20,2H4ZM6,12H14V14H6V12ZM6,9H18V11H6V9ZM6,6H18V8H6V6Z"
android:fillColor="#080707"/>
</vector>
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,8 @@
<string name="channel_group_info_owner">Owner</string>
<string name="channel_group_info_member">Member</string>
<string name="channel_group_info_moderator">Moderator</string>

<!-- App Bottom Bar -->
<string name="app_bottom_bar_chats">Chats</string>
<string name="app_bottom_bar_threads">Threads</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ private fun ThreadTitle(
Icon(
painter = painterResource(id = R.drawable.stream_compose_ic_thread),
contentDescription = null,
tint = ChatTheme.colors.textHighEmphasis,
)
Spacer(modifier = Modifier.width(4.dp))
Text(
Expand Down

0 comments on commit fdb1ac1

Please sign in to comment.