feat: material 3-ise friends screen

Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
Infi 2024-01-20 00:14:33 +01:00
parent 74b33380ab
commit ad4d06db7d
3 changed files with 110 additions and 215 deletions

View File

@ -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()
}
}
}
}
@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()
)
}
}

View File

@ -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
)
}
}

View File

@ -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()
)
}
}
}