feat: material 3-ise friends screen
Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
parent
74b33380ab
commit
ad4d06db7d
|
|
@ -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()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue