Refactor: Enhance ChannelIcon and ChannelSideDrawer UI

This commit improves the UI of the ChannelIcon and ChannelSideDrawer components by adding background styling and padding to the ChannelIcon for SavedMessages. Additionally, it introduces a FloatingActionButton in the ChannelSideDrawer for quick navigation to the Friends screen, enhancing user experience.

- Updated ChannelIcon to include a circular background and padding for SavedMessages.
- Added FloatingActionButton in ChannelSideDrawer for navigating to Friends screen.
- Updated string resource for channel notes to "Saved Notes".
This commit is contained in:
AbronStudio 2025-08-07 11:18:09 +03:30
parent 062375287d
commit f3632854ad
5 changed files with 402 additions and 372 deletions

View File

@ -1,13 +1,21 @@
package chat.revolt.composables.screens.chat
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp
import chat.revolt.R
import chat.revolt.api.schemas.ChannelType
@ -31,11 +39,20 @@ fun ChannelIcon(channelType: ChannelType, modifier: Modifier = Modifier) {
}
ChannelType.SavedMessages -> {
Icon(
painter = painterResource(R.drawable.icn_note_stack_24dp),
contentDescription = stringResource(R.string.channel_notes),
modifier = modifier
)
Box(
modifier = Modifier
.clip(CircleShape)
.size(32.dp)
.background(MaterialTheme.colorScheme.secondaryContainer)
) {
Icon(
painter = painterResource(R.drawable.icn_note_stack_24dp),
contentDescription = stringResource(R.string.channel_notes),
modifier = modifier
.padding(6.dp)
)
}
}
ChannelType.DirectMessage -> {

View File

@ -35,7 +35,14 @@ import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonMenu
import androidx.compose.material3.FloatingActionButtonMenuItem
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
@ -43,6 +50,9 @@ import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Text
import androidx.compose.material3.ToggleFloatingActionButton
import androidx.compose.material3.ToggleFloatingActionButtonDefaults.animateIcon
import androidx.compose.material3.animateFloatingActionButton
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
@ -60,9 +70,13 @@ import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.isTraversalGroup
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.traversalIndex
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
@ -73,7 +87,6 @@ import chat.revolt.api.RevoltAPI
import chat.revolt.api.internals.CategorisedChannelList
import chat.revolt.api.internals.ChannelUtils
import chat.revolt.api.internals.DirectMessages
import chat.revolt.api.internals.FriendRequests
import chat.revolt.api.schemas.Category
import chat.revolt.api.schemas.Channel
import chat.revolt.api.schemas.ChannelType
@ -93,13 +106,14 @@ import chat.revolt.composables.screens.chat.discover.DiscoverServersList
import chat.revolt.screens.chat.ChatRouterDestination
import chat.revolt.sheets.ChannelContextSheet
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class,
ExperimentalMaterial3ExpressiveApi::class
)
@Composable
fun ChannelSideDrawer(
currentServer: String?,
currentDestination: ChatRouterDestination,
onDestinationChanged: (ChatRouterDestination) -> Unit,
onLongPressAvatar: () -> Unit,
navigateToServer: (String) -> Unit,
onShowServerContextSheet: (String) -> Unit,
showSettingsIcon: Boolean,
@ -183,372 +197,388 @@ fun ChannelSideDrawer(
}
}
Row(modifier.fillMaxSize()) {
LazyColumn(
Modifier.width(64.dp),
verticalArrangement = Arrangement.spacedBy(6.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
stickyHeader(key = "self") {
Column(Modifier.background(MaterialTheme.colorScheme.background)) {
UserAvatar(
username = RevoltAPI.userCache[RevoltAPI.selfId]?.let {
User.resolveDefaultName(
it
Box {
Row(modifier.fillMaxSize()) {
LazyColumn(
Modifier.width(64.dp),
verticalArrangement = Arrangement.spacedBy(6.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
stickyHeader(key = "self") {
Column(Modifier.background(MaterialTheme.colorScheme.background)) {
Box(
Modifier
.padding(8.dp)
.clip(RoundedCornerShape(16.dp))
.clickable {
onDestinationChanged(ChatRouterDestination.Home)
}
.size(48.dp)
.background(MaterialTheme.colorScheme.secondaryContainer),
contentAlignment = Alignment.Center
) {
Icon(
painter = painterResource(R.drawable.ic_message_text_24dp),
contentDescription = stringResource(R.string.discover_alt)
)
}
?: "",
presence = presenceFromStatus(
RevoltAPI.userCache[RevoltAPI.selfId]?.status?.presence,
RevoltAPI.userCache[RevoltAPI.selfId]?.online ?: false
),
userId = RevoltAPI.selfId ?: "",
avatar = RevoltAPI.userCache[RevoltAPI.selfId]?.avatar,
size = 48.dp,
presenceSize = 16.dp,
onClick = {
onDestinationChanged(ChatRouterDestination.Home)
},
onLongClick = onLongPressAvatar,
modifier = Modifier
.padding(8.dp)
.size(48.dp)
)
}
}
}
items(
DirectMessages.unreadDMs().size,
key = { DirectMessages.unreadDMs()[it].id ?: it }
) {
val dm = DirectMessages.unreadDMs()[it]
when (dm.channelType) {
ChannelType.Group -> GroupIcon(
name = dm.name ?: "?",
size = 48.dp,
onClick = {
dm.id?.let { id ->
onDestinationChanged(ChatRouterDestination.Channel(id))
}
},
icon = dm.icon,
modifier = Modifier
.padding(8.dp)
.size(48.dp)
)
else -> {
val partner =
if (dm.channelType == ChannelType.DirectMessage) {
RevoltAPI.userCache[
ChannelUtils.resolveDMPartner(
dm
)
]
} else {
null
}
UserAvatar(
username = partner?.let { p ->
User.resolveDefaultName(
p
)
} ?: dm.name ?: "?",
presence = presenceFromStatus(
partner?.status?.presence,
partner?.online ?: false
),
userId = partner?.id ?: dm.id ?: "",
avatar = partner?.avatar ?: dm.icon,
items(
count = DirectMessages.unreadDMs().size,
key = { DirectMessages.unreadDMs()[it].id ?: it }
) {
val dm = DirectMessages.unreadDMs()[it]
when (dm.channelType) {
ChannelType.Group -> GroupIcon(
name = dm.name ?: "?",
size = 48.dp,
presenceSize = 16.dp,
onClick = {
dm.id?.let { id ->
onDestinationChanged(ChatRouterDestination.Channel(id))
}
},
icon = dm.icon,
modifier = Modifier
.padding(8.dp)
.size(48.dp)
)
}
}
}
item(key = "divider") {
HorizontalDivider(
Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp)
)
}
else -> {
val partner =
if (dm.channelType == ChannelType.DirectMessage) {
RevoltAPI.userCache[
ChannelUtils.resolveDMPartner(
dm
)
]
} else {
null
}
item(key = "discover") {
Box(
Modifier
.padding(8.dp)
.clip(RoundedCornerShape(16.dp))
.clickable {
onDestinationChanged(
ChatRouterDestination.Discover
)
}
.size(48.dp)
.background(MaterialTheme.colorScheme.onPrimary),
contentAlignment = Alignment.Center
) {
Icon(
painter = painterResource(R.drawable.icn_explore_24dp),
contentDescription = stringResource(R.string.discover_alt)
)
}
}
item(key = "add_server") {
Box(
Modifier
.padding(8.dp)
.clip(CircleShape)
.clickable {
onShowAddServerSheet()
}
.size(48.dp)
.background(MaterialTheme.colorScheme.onPrimary),
contentAlignment = Alignment.Center
) {
Icon(
painter = painterResource(R.drawable.icn_add_24dp),
contentDescription = stringResource(R.string.server_plus_alt)
)
}
}
items(
serverList.size,
key = { serverList[it].id ?: it }
) {
val serverInList = serverList[it]
val serverHasUnread =
serverInList.id?.let { srvId -> RevoltAPI.unreads.serverHasUnread(srvId) }
?: false
val leftIndicatorHeight = animateDpAsState(
targetValue = if (serverInList.id == currentServer) 32.dp
else if (serverHasUnread) 8.dp
else 0.dp,
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessLow
), label = "Left indicator width"
)
val leftIndicatorColour = animateColorAsState(
targetValue =
if (serverInList.id == currentServer)
MaterialTheme.colorScheme.primary
else if (serverHasUnread)
MaterialTheme.colorScheme.onSurfaceVariant
else
Color.Transparent,
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessLow
),
label = "Left indicator colour"
)
Box(Modifier.fillMaxWidth()) {
Box(
Modifier
.padding(8.dp)
.clip(CircleShape)
.clickable {
serverInList.id?.let { srvId -> navigateToServer(srvId) }
}) {
val icon = serverInList.icon?.id?.let { iconId ->
"${RevoltAPI.getCurrentFilesUrl()}/icons/$iconId"
}
if (icon != null) {
RemoteImage(
url = icon,
allowAnimation = false,
UserAvatar(
username = partner?.let { p ->
User.resolveDefaultName(
p
)
} ?: dm.name ?: "?",
presence = presenceFromStatus(
partner?.status?.presence,
partner?.online ?: false
),
userId = partner?.id ?: dm.id ?: "",
avatar = partner?.avatar ?: dm.icon,
size = 48.dp,
presenceSize = 16.dp,
onClick = {
dm.id?.let { id ->
onDestinationChanged(ChatRouterDestination.Channel(id))
}
},
modifier = Modifier
.padding(8.dp)
.size(48.dp)
.clip(CircleShape),
description = serverInList.name ?: stringResource(R.string.unknown)
)
} else {
IconPlaceholder(
name = serverInList.name ?: stringResource(R.string.unknown),
modifier = Modifier
.size(48.dp)
.clip(CircleShape)
)
}
}
}
Box(
item(key = "divider") {
HorizontalDivider(
Modifier
.height(leftIndicatorHeight.value)
.width(8.dp)
.offset(x = (-4).dp)
.clip(CircleShape)
.background(leftIndicatorColour.value)
.align(Alignment.CenterStart)
.fillMaxWidth()
.padding(horizontal = 8.dp)
)
}
}
if (showSettingsIcon) {
item(key = "settings") {
item(key = "discover") {
Box(
Modifier
.padding(8.dp)
.clip(CircleShape)
.clip(RoundedCornerShape(16.dp))
.clickable {
onOpenSettings()
onDestinationChanged(
ChatRouterDestination.Discover
)
}
.size(48.dp),
.size(48.dp)
.background(MaterialTheme.colorScheme.onPrimary),
contentAlignment = Alignment.Center
) {
Icon(
painter = painterResource(R.drawable.icn_settings_24dp),
contentDescription = stringResource(R.string.settings)
painter = painterResource(R.drawable.icn_explore_24dp),
contentDescription = stringResource(R.string.discover_alt)
)
}
}
item(key = "add_server") {
Box(
Modifier
.padding(8.dp)
.clip(CircleShape)
.clickable {
onShowAddServerSheet()
}
.size(48.dp)
.background(MaterialTheme.colorScheme.onPrimary),
contentAlignment = Alignment.Center
) {
Icon(
painter = painterResource(R.drawable.icn_add_24dp),
contentDescription = stringResource(R.string.server_plus_alt)
)
}
}
items(
serverList.size,
key = { serverList[it].id ?: it }
) {
val serverInList = serverList[it]
val serverHasUnread =
serverInList.id?.let { srvId -> RevoltAPI.unreads.serverHasUnread(srvId) }
?: false
val leftIndicatorHeight = animateDpAsState(
targetValue = if (serverInList.id == currentServer) 32.dp
else if (serverHasUnread) 8.dp
else 0.dp,
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessLow
), label = "Left indicator width"
)
val leftIndicatorColour = animateColorAsState(
targetValue =
if (serverInList.id == currentServer)
MaterialTheme.colorScheme.primary
else if (serverHasUnread)
MaterialTheme.colorScheme.onSurfaceVariant
else
Color.Transparent,
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessLow
),
label = "Left indicator colour"
)
Box(Modifier.fillMaxWidth()) {
Box(
Modifier
.padding(8.dp)
.clip(CircleShape)
.clickable {
serverInList.id?.let { srvId -> navigateToServer(srvId) }
}) {
val icon = serverInList.icon?.id?.let { iconId ->
"${RevoltAPI.getCurrentFilesUrl()}/icons/$iconId"
}
if (icon != null) {
RemoteImage(
url = icon,
allowAnimation = false,
modifier = Modifier
.size(48.dp)
.clip(CircleShape),
description = serverInList.name
?: stringResource(R.string.unknown)
)
} else {
IconPlaceholder(
name = serverInList.name ?: stringResource(R.string.unknown),
modifier = Modifier
.size(48.dp)
.clip(CircleShape)
)
}
}
Box(
Modifier
.height(leftIndicatorHeight.value)
.width(8.dp)
.offset(x = (-4).dp)
.clip(CircleShape)
.background(leftIndicatorColour.value)
.align(Alignment.CenterStart)
)
}
}
if (showSettingsIcon) {
item(key = "settings") {
Box(
Modifier
.padding(8.dp)
.clip(CircleShape)
.clickable {
onOpenSettings()
}
.size(48.dp),
contentAlignment = Alignment.Center
) {
Icon(
painter = painterResource(R.drawable.icn_settings_24dp),
contentDescription = stringResource(R.string.settings)
)
}
}
}
}
Column(
Modifier
.clip(shape = RoundedCornerShape(topStart = 24.dp))
.background(color = MaterialTheme.colorScheme.surfaceContainer)
.weight(weight = 1f)
.fillMaxHeight()
) {
Box(
Modifier
.height(serverBannerHeight)
) {
if (server?.banner != null) {
RemoteImage(
url = "${RevoltAPI.getCurrentFilesUrl()}/banners/${server.banner.id}",
description = null,
contentScale = ContentScale.Crop,
modifier = Modifier
.fillMaxSize()
)
with(MaterialTheme.colorScheme) {
Box(
Modifier
.fillMaxSize()
.drawBehind {
drawRect(
Brush.linearGradient(
listOf(
Color.Black.copy(alpha = 0.6f),
Color.Transparent
),
Offset.Zero,
Offset.Infinite.copy(x = 0f)
),
)
})
}
}
Row(
Modifier
.padding(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
CompositionLocalProvider(
LocalContentColor provides
if (server?.banner != null) Color.White
else LocalContentColor.current
) {
Row(
Modifier.weight(1f),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
if (server?.flags has ServerFlags.Official) {
Icon(
painter = painterResource(
id = R.drawable.ic_revolt_decagram_24dp
),
contentDescription = stringResource(
R.string.server_flag_official
),
tint = LocalContentColor.current,
modifier = Modifier
.size(24.dp)
)
}
if (server?.flags has ServerFlags.Verified) {
Icon(
painter = painterResource(
id = R.drawable.ic_check_decagram_24dp
),
contentDescription = stringResource(
R.string.server_flag_verified
),
tint = LocalContentColor.current,
modifier = Modifier
.size(24.dp)
)
}
Text(
text = when (currentServer) {
null -> stringResource(if (currentDestination is ChatRouterDestination.Discover) R.string.discover_servers else R.string.direct_messages)
else -> server?.name ?: stringResource(R.string.unknown)
},
style = MaterialTheme.typography.titleMedium,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
if (currentServer != null) {
IconButton(onClick = {
server?.id?.let { srvId -> onShowServerContextSheet(srvId) }
}) {
Icon(
painter = painterResource(R.drawable.icn_more_vert_24dp),
contentDescription = stringResource(R.string.menu),
tint = LocalContentColor.current
)
}
} else {
Spacer(Modifier.height(64.dp))
}
}
}
}
if (currentDestination is ChatRouterDestination.Discover) {
DiscoverServersList(
onJoinToServerSuccess = navigateToServer
)
} else {
if (currentServer == null) {
DirectMessagesChannelListRenderer(
currentDestination,
onDestinationChanged,
channelListState,
onOpenChannelContextSheet = { channelContextSheetTarget = it }
)
} else {
ServerChannelListRenderer(
categorisedChannels,
currentDestination,
onDestinationChanged,
channelListState,
onOpenChannelContextSheet = { channelContextSheetTarget = it },
serverId = currentServer
)
}
}
}
}
Column(
Modifier
.clip(shape = RoundedCornerShape(topStart = 24.dp))
.background(color = MaterialTheme.colorScheme.surfaceContainer)
.weight(weight = 1f)
.fillMaxHeight()
) {
Box(
Modifier
.height(serverBannerHeight)
if(currentDestination is ChatRouterDestination.Home){
FloatingActionButton(
modifier = Modifier
.padding(16.dp)
.align(Alignment.BottomEnd),
onClick = {
onDestinationChanged(ChatRouterDestination.Friends)
},
containerColor = MaterialTheme.colorScheme.primary,
contentColor = MaterialTheme.colorScheme.onPrimary,
shape = CircleShape
) {
if (server?.banner != null) {
RemoteImage(
url = "${RevoltAPI.getCurrentFilesUrl()}/banners/${server.banner.id}",
description = null,
contentScale = ContentScale.Crop,
modifier = Modifier
.fillMaxSize()
)
with(MaterialTheme.colorScheme) {
Box(
Modifier
.fillMaxSize()
.drawBehind {
drawRect(
Brush.linearGradient(
listOf(
Color.Black.copy(alpha = 0.6f),
Color.Transparent
),
Offset.Zero,
Offset.Infinite.copy(x = 0f)
),
)
})
}
}
Row(
Modifier
.padding(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
CompositionLocalProvider(
LocalContentColor provides
if (server?.banner != null) Color.White
else LocalContentColor.current
) {
Row(
Modifier.weight(1f),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
if (server?.flags has ServerFlags.Official) {
Icon(
painter = painterResource(
id = R.drawable.ic_revolt_decagram_24dp
),
contentDescription = stringResource(
R.string.server_flag_official
),
tint = LocalContentColor.current,
modifier = Modifier
.size(24.dp)
)
}
if (server?.flags has ServerFlags.Verified) {
Icon(
painter = painterResource(
id = R.drawable.ic_check_decagram_24dp
),
contentDescription = stringResource(
R.string.server_flag_verified
),
tint = LocalContentColor.current,
modifier = Modifier
.size(24.dp)
)
}
Text(
text = when (currentServer) {
null -> stringResource(if (currentDestination is ChatRouterDestination.Discover) R.string.discover_servers else R.string.direct_messages)
else -> server?.name ?: stringResource(R.string.unknown)
},
style = MaterialTheme.typography.titleMedium,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
if (currentServer != null) {
IconButton(onClick = {
server?.id?.let { srvId -> onShowServerContextSheet(srvId) }
}) {
Icon(
painter = painterResource(R.drawable.icn_more_vert_24dp),
contentDescription = stringResource(R.string.menu),
tint = LocalContentColor.current
)
}
} else {
Spacer(Modifier.height(64.dp))
}
}
}
}
if (currentDestination is ChatRouterDestination.Discover) {
DiscoverServersList(
onJoinToServerSuccess = navigateToServer
Icon(
painter = painterResource(R.drawable.icn_message_24dp),
contentDescription = stringResource(R.string.message_friends)
)
} else {
if (currentServer == null) {
DirectMessagesChannelListRenderer(
currentDestination,
onDestinationChanged,
channelListState,
onOpenChannelContextSheet = { channelContextSheetTarget = it }
)
} else {
ServerChannelListRenderer(
categorisedChannels,
currentDestination,
onDestinationChanged,
channelListState,
onOpenChannelContextSheet = { channelContextSheetTarget = it },
serverId = currentServer
)
}
}
}
}
@ -574,45 +604,18 @@ private fun ColumnScope.DirectMessagesChannelListRenderer(
.fillMaxSize()
.weight(1f)
) {
item(key = "overview") {
ChannelItem(
channel = Channel(
id = "overview",
name = stringResource(R.string.overview_screen_title),
channelType = ChannelType.TextChannel
),
iconType = ChannelItemIconType.Painter(painterResource(R.drawable.icn_star_shine_24dp)),
isCurrent = currentDestination is ChatRouterDestination.Settings,
onDestinationChanged = {
onDestinationChanged(ChatRouterDestination.Settings)
},
hasUnread = false,
onOpenChannelContextSheet = {}
item("top-divider") {
HorizontalDivider(
Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp, vertical = 4.dp)
)
Spacer(Modifier.height(4.dp))
}
item(key = "friends") {
ChannelItem(
channel = Channel(
id = "friends",
name = stringResource(R.string.friends),
channelType = ChannelType.TextChannel
),
iconType = ChannelItemIconType.Painter(painterResource(R.drawable.icn_group_24dp)),
isCurrent = currentDestination is ChatRouterDestination.Friends,
onDestinationChanged = {
onDestinationChanged(ChatRouterDestination.Friends)
},
hasUnread = FriendRequests.getIncoming().isNotEmpty(),
onOpenChannelContextSheet = {},
)
Spacer(Modifier.height(4.dp))
}
item(key = "saved_messages") {
val notesChannel =
RevoltAPI.channelCache.values.firstOrNull { it.channelType == ChannelType.SavedMessages }
val notesChannel = RevoltAPI.channelCache.values.firstOrNull {
it.channelType == ChannelType.SavedMessages
}
if (notesChannel != null) {
ChannelItem(
@ -629,11 +632,10 @@ private fun ColumnScope.DirectMessagesChannelListRenderer(
hasUnread = false,
onOpenChannelContextSheet = {},
)
Spacer(Modifier.height(4.dp))
}
}
item("divider") {
item("bottom-divider") {
HorizontalDivider(
Modifier
.fillMaxWidth()

View File

@ -932,7 +932,6 @@ fun ChannelNavigator(
else -> null
},
navigateToServer = viewModel::navigateToServer,
onLongPressAvatar = onShowStatusSheet,
onShowServerContextSheet = onShowServerContextSheet,
showSettingsIcon = isTouchExplorationEnabled,
onOpenSettings = {

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal"
android:autoMirrored="true">
<path
android:fillColor="@android:color/white"
android:pathData="M80,880L80,160Q80,127 103.5,103.5Q127,80 160,80L800,80Q833,80 856.5,103.5Q880,127 880,160L880,640Q880,673 856.5,696.5Q833,720 800,720L240,720L80,880ZM206,640L800,640Q800,640 800,640Q800,640 800,640L800,160Q800,160 800,160Q800,160 800,160L160,160Q160,160 160,160Q160,160 160,160L160,685L206,640ZM480,400Q447,400 423.5,376.5Q400,353 400,320Q400,287 423.5,263.5Q447,240 480,240Q513,240 536.5,263.5Q560,287 560,320Q560,353 536.5,376.5Q513,400 480,400ZM320,560Q287,560 263.5,536.5Q240,513 240,480Q240,447 263.5,423.5Q287,400 320,400Q353,400 376.5,423.5Q400,447 400,480Q400,513 376.5,536.5Q353,560 320,560ZM640,560Q607,560 583.5,536.5Q560,513 560,480Q560,447 583.5,423.5Q607,400 640,400Q673,400 696.5,423.5Q720,447 720,480Q720,513 696.5,536.5Q673,560 640,560Z"/>
</vector>

View File

@ -16,6 +16,7 @@
<string name="terms_of_service">Terms of Service</string>
<string name="privacy_policy">Privacy Policy</string>
<string name="community_guidelines">Community Guidelines</string>
<string name="message_friends">Message Friends</string>
<string name="login_onboarding_heading">Welcome to PepChat!</string>
<string name="login_onboarding_body">Join endless chats and connections; PepChat is your place to vibe with friends!</string>
@ -233,7 +234,7 @@
<string name="channel_text">Text Channel</string>
<string name="channel_voice">Voice Channel</string>
<string name="channel_group">Group</string>
<string name="channel_notes">Notes</string>
<string name="channel_notes">Saved Notes</string>
<string name="start_of_conversation">This is the start of your conversation</string>
<string name="time_rift_heading">There may be some messages missing here.</string>