diff --git a/app/src/main/java/chat/revolt/components/generic/ListHeader.kt b/app/src/main/java/chat/revolt/components/generic/ListHeader.kt index 04aa6452..9bbacc16 100644 --- a/app/src/main/java/chat/revolt/components/generic/ListHeader.kt +++ b/app/src/main/java/chat/revolt/components/generic/ListHeader.kt @@ -4,12 +4,17 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.material3.LocalContentColor import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp @Composable @@ -28,4 +33,29 @@ fun ListHeader( content() } } -} \ No newline at end of file +} + +@Composable +fun CountableListHeader( + text: String, + count: Int, + backgroundColor: Color = MaterialTheme.colorScheme.background +) { + ListHeader(backgroundColor = backgroundColor) { + Text( + text = AnnotatedString.Builder().apply { + append(text) + + pushStyle( + SpanStyle( + fontWeight = FontWeight.Medium, + fontSize = LocalTextStyle.current.fontSize * 0.8, + color = LocalContentColor.current.copy(alpha = 0.6f) + ) + ) + append("—$count") + pop() + }.toAnnotatedString() + ) + } +} diff --git a/app/src/main/java/chat/revolt/screens/chat/views/FriendsScreen.kt b/app/src/main/java/chat/revolt/screens/chat/views/FriendsScreen.kt index 164c2c42..16b90c86 100644 --- a/app/src/main/java/chat/revolt/screens/chat/views/FriendsScreen.kt +++ b/app/src/main/java/chat/revolt/screens/chat/views/FriendsScreen.kt @@ -1,15 +1,9 @@ package chat.revolt.screens.chat.views import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Menu @@ -17,9 +11,6 @@ import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton -import androidx.compose.material3.LocalContentColor -import androidx.compose.material3.LocalTextStyle -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.Text import androidx.compose.material3.rememberModalBottomSheetState @@ -29,25 +20,18 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue -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.text.AnnotatedString -import androidx.compose.ui.text.SpanStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp import chat.revolt.R import chat.revolt.api.internals.FriendRequests import chat.revolt.api.routes.user.unfriendUser -import chat.revolt.api.schemas.User import chat.revolt.callbacks.Action import chat.revolt.callbacks.ActionChannel +import chat.revolt.components.chat.MemberListItem +import chat.revolt.components.generic.CountableListHeader import chat.revolt.components.generic.PageHeader import chat.revolt.components.generic.SheetClickable -import chat.revolt.components.generic.UserAvatar -import chat.revolt.components.generic.presenceFromStatus import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -132,221 +116,125 @@ fun FriendsScreen(useDrawer: Boolean, onDrawerClicked: () -> Unit) { LazyColumn { stickyHeader(key = "incoming") { - Text( - text = AnnotatedString.Builder().apply { - pushStyle(SpanStyle(fontWeight = FontWeight.Bold)) - append(stringResource(id = R.string.friends_incoming_requests)) - pop() - - pushStyle( - SpanStyle( - fontWeight = FontWeight.Medium, - fontSize = LocalTextStyle.current.fontSize * 0.8, - color = LocalContentColor.current.copy(alpha = 0.6f) - ) - ) - append("—${FriendRequests.getIncoming().size}") - pop() - }.toAnnotatedString(), - style = MaterialTheme.typography.labelLarge, - modifier = Modifier - .fillMaxWidth() - .background(MaterialTheme.colorScheme.background) - .padding(10.dp) + CountableListHeader( + text = stringResource(id = R.string.friends_incoming_requests), + count = FriendRequests.getIncoming().size ) } items(FriendRequests.getIncoming().size) { val item = FriendRequests.getIncoming()[it] - UserItem(item, onClick = { - scope.launch { - item.id?.let { userId -> - ActionChannel.send(Action.OpenUserSheet(userId, null)) + MemberListItem( + member = null, + user = item, + serverId = null, + userId = item.id ?: "", + modifier = Modifier.clickable { + scope.launch { + item.id?.let { userId -> + ActionChannel.send(Action.OpenUserSheet(userId, null)) + } } } - }) + ) } stickyHeader(key = "outgoing") { - Text( - text = AnnotatedString.Builder().apply { - pushStyle(SpanStyle(fontWeight = FontWeight.Bold)) - append(stringResource(id = R.string.friends_outgoing_requests)) - pop() - - pushStyle( - SpanStyle( - fontWeight = FontWeight.Medium, - fontSize = LocalTextStyle.current.fontSize * 0.8, - color = LocalContentColor.current.copy(alpha = 0.6f) - ) - ) - append("—${FriendRequests.getOutgoing().size}") - pop() - }.toAnnotatedString(), - style = MaterialTheme.typography.labelLarge, - modifier = Modifier - .fillMaxWidth() - .background(MaterialTheme.colorScheme.background) - .padding(10.dp) + CountableListHeader( + text = stringResource(id = R.string.friends_outgoing_requests), + count = FriendRequests.getOutgoing().size ) } items(FriendRequests.getOutgoing().size) { val item = FriendRequests.getOutgoing()[it] - UserItem(item, onClick = { - scope.launch { - item.id?.let { userId -> - ActionChannel.send(Action.OpenUserSheet(userId, null)) + MemberListItem( + member = null, + user = item, + serverId = null, + userId = item.id ?: "", + modifier = Modifier.clickable { + scope.launch { + item.id?.let { userId -> + ActionChannel.send(Action.OpenUserSheet(userId, null)) + } } } - }) + ) } stickyHeader(key = "online") { - Text( - text = AnnotatedString.Builder().apply { - pushStyle(SpanStyle(fontWeight = FontWeight.Bold)) - append(stringResource(id = R.string.status_online)) - pop() - - pushStyle( - SpanStyle( - fontWeight = FontWeight.Medium, - fontSize = LocalTextStyle.current.fontSize * 0.8, - color = LocalContentColor.current.copy(alpha = 0.6f) - ) - ) - append("—${FriendRequests.getOnlineFriends().size}") - pop() - }.toAnnotatedString(), - style = MaterialTheme.typography.labelLarge, - modifier = Modifier - .fillMaxWidth() - .background(MaterialTheme.colorScheme.background) - .padding(10.dp) + CountableListHeader( + text = stringResource(id = R.string.status_online), + count = FriendRequests.getOnlineFriends().size ) } items(FriendRequests.getOnlineFriends().size) { val item = FriendRequests.getOnlineFriends()[it] - UserItem(item, onClick = { - scope.launch { - item.id?.let { userId -> - ActionChannel.send(Action.OpenUserSheet(userId, null)) + MemberListItem( + member = null, + user = item, + serverId = null, + userId = item.id ?: "", + modifier = Modifier.clickable { + scope.launch { + item.id?.let { userId -> + ActionChannel.send(Action.OpenUserSheet(userId, null)) + } } } - }) + ) } stickyHeader(key = "not_online") { - Text( - text = AnnotatedString.Builder().apply { - pushStyle(SpanStyle(fontWeight = FontWeight.Bold)) - append(stringResource(id = R.string.friends_all)) - pop() - - pushStyle( - SpanStyle( - fontWeight = FontWeight.Medium, - fontSize = LocalTextStyle.current.fontSize * 0.8, - color = LocalContentColor.current.copy(alpha = 0.6f) - ) - ) - append("—${FriendRequests.getFriends(true).size}") - pop() - }.toAnnotatedString(), - style = MaterialTheme.typography.labelLarge, - modifier = Modifier - .fillMaxWidth() - .background(MaterialTheme.colorScheme.background) - .padding(10.dp) + CountableListHeader( + text = stringResource(id = R.string.friends_all), + count = FriendRequests.getFriends(true).size ) } items(FriendRequests.getFriends(true).size) { val item = FriendRequests.getFriends(true)[it] - UserItem(item, onClick = { - scope.launch { - item.id?.let { userId -> - ActionChannel.send(Action.OpenUserSheet(userId, null)) + MemberListItem( + member = null, + user = item, + serverId = null, + userId = item.id ?: "", + modifier = Modifier.clickable { + scope.launch { + item.id?.let { userId -> + ActionChannel.send(Action.OpenUserSheet(userId, null)) + } } } - }) + ) } stickyHeader(key = "blocked") { - Text( - text = AnnotatedString.Builder().apply { - pushStyle(SpanStyle(fontWeight = FontWeight.Bold)) - append(stringResource(id = R.string.friends_blocked)) - pop() - - pushStyle( - SpanStyle( - fontWeight = FontWeight.Medium, - fontSize = LocalTextStyle.current.fontSize * 0.8, - color = LocalContentColor.current.copy(alpha = 0.6f) - ) - ) - append("—${FriendRequests.getBlocked().size}") - pop() - }.toAnnotatedString(), - style = MaterialTheme.typography.labelLarge, - modifier = Modifier - .fillMaxWidth() - .background(MaterialTheme.colorScheme.background) - .padding(10.dp) + CountableListHeader( + text = stringResource(id = R.string.friends_blocked), + count = FriendRequests.getBlocked().size ) } items(FriendRequests.getBlocked().size) { val item = FriendRequests.getBlocked()[it] - UserItem(item, onClick = { - scope.launch { - item.id?.let { userId -> - ActionChannel.send(Action.OpenUserSheet(userId, null)) + MemberListItem( + member = null, + user = item, + serverId = null, + userId = item.id ?: "", + modifier = Modifier.clickable { + scope.launch { + item.id?.let { userId -> + ActionChannel.send(Action.OpenUserSheet(userId, null)) + } } } - }) + ) } } } -} - -@Composable -fun UserItem(user: User, onClick: () -> Unit = {}) { - Row( - modifier = Modifier - .clickable { - onClick() - } - .fillMaxWidth() - .padding(horizontal = 12.dp, vertical = 8.dp), - verticalAlignment = Alignment.CenterVertically - ) { - UserAvatar( - username = user.displayName - ?: user.username - ?: user.id!!, - avatar = user.avatar, - userId = user.id!!, - presence = presenceFromStatus( - user.status?.presence, - user.online ?: false - ) - ) - - Spacer(modifier = Modifier.width(12.dp)) - - Text( - text = user.displayName - ?: user.username - ?: user.id, - fontWeight = FontWeight.Bold, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - } } \ No newline at end of file diff --git a/app/src/main/java/chat/revolt/sheets/MemberListSheet.kt b/app/src/main/java/chat/revolt/sheets/MemberListSheet.kt index 22a71ed9..4345ab49 100644 --- a/app/src/main/java/chat/revolt/sheets/MemberListSheet.kt +++ b/app/src/main/java/chat/revolt/sheets/MemberListSheet.kt @@ -12,11 +12,8 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.LocalContentColor -import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ModalBottomSheet -import androidx.compose.material3.Text import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.material3.surfaceColorAtElevation import androidx.compose.runtime.Composable @@ -30,9 +27,6 @@ import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.SpanStyle -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.ViewModel @@ -47,7 +41,7 @@ import chat.revolt.api.routes.server.fetchMembers import chat.revolt.api.schemas.Member import chat.revolt.api.schemas.User import chat.revolt.components.chat.MemberListItem -import chat.revolt.components.generic.ListHeader +import chat.revolt.components.generic.CountableListHeader import chat.revolt.components.generic.PageHeader import chat.revolt.components.generic.Presence import chat.revolt.components.generic.presenceFromStatus @@ -268,7 +262,11 @@ fun MemberListSheet( is MemberListSheetItem.CategoryItem -> stickyHeader( key = "${item.category}-$index" ) { - MemberListCategory(text = item.category, count = item.count) + CountableListHeader( + text = item.category, + count = item.count, + backgroundColor = MaterialTheme.colorScheme.surfaceColorAtElevation(2.dp) + ) } is MemberListSheetItem.MemberItem -> item(key = item.member.id!!.user) { @@ -300,25 +298,4 @@ fun MemberListSheet( } } } -} - -@Composable -fun MemberListCategory(text: String, count: Int) { - ListHeader(backgroundColor = MaterialTheme.colorScheme.surfaceColorAtElevation(2.dp)) { - Text( - text = AnnotatedString.Builder().apply { - append(text) - - pushStyle( - SpanStyle( - fontWeight = FontWeight.Medium, - fontSize = LocalTextStyle.current.fontSize * 0.8, - color = LocalContentColor.current.copy(alpha = 0.6f) - ) - ) - append("—$count") - pop() - }.toAnnotatedString() - ) - } -} +} \ No newline at end of file