Refactor: Update UI elements and add server color feature

This commit introduces a new feature to display server-specific colors in the discover servers list and includes several UI refinements.

- Added `showColor` property to `ServerData` to allow servers to specify a display color.
- Updated `DiscoverServersList` to parse and apply `showColor` to server items.
- Removed animated visibility for status bar spacer in `FriendsScreen` top bar.
- Changed `LargeTopAppBar` to `TopAppBar` in `SettingsScreen`.
- Adjusted corner radius for the server banner in `ChannelSideDrawer`.
This commit is contained in:
AbronStudio 2025-08-06 15:37:47 +03:30
parent f2301c6760
commit b5159450d7
5 changed files with 104 additions and 74 deletions

View File

@ -29,6 +29,7 @@ class ServerDataRepository {
"false" -> false
else -> true
},
showColor = rowData["showcolor"]
)
}
emit(servers)
@ -46,4 +47,5 @@ data class ServerData(
val description: String,
val inviteCode: String,
val disabled: Boolean,
val showColor: String?,
)

View File

@ -17,6 +17,7 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
@ -27,6 +28,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
@ -34,6 +36,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.graphics.toColorInt
import androidx.hilt.navigation.compose.hiltViewModel
import chat.revolt.R
import chat.revolt.api.RevoltAPI
@ -154,6 +157,26 @@ fun ServerItem(
onClick: () -> Unit,
isProcessing: Boolean = false
) {
// Safely convert the hex string to a Color, or return null if invalid
fun parseColorOrNull(hex: String?): Color? {
return hex?.let { raw ->
val normalized = if (raw.startsWith("#")) raw else "#$raw"
try {
Color(normalized.toColorInt())
} catch (_: IllegalArgumentException) {
null
}
}
}
// Determine card colors based on server.showColor
val containerColor = parseColorOrNull(server.showColor)
val cardColors = if (containerColor != null) {
CardDefaults.cardColors(containerColor = containerColor)
} else {
CardDefaults.cardColors()
}
// Calculate alpha values based on disabled state
val contentAlpha = if (server.disabled) 0.5f else 1.0f
val descriptionAlpha = if (server.disabled) 0.4f else 0.7f
@ -162,7 +185,8 @@ fun ServerItem(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp)
.clickable(enabled = !isProcessing) { onClick() }
.clickable(enabled = !isProcessing) { onClick() },
colors = cardColors,
) {
Row(
modifier = Modifier
@ -262,7 +286,8 @@ private fun ServerItemPreview() {
name = "Revolt Lounge",
description = "The official Revolt server. Hang out, chat, and get help with Revolt.",
inviteCode = "revolt",
disabled = false
disabled = false,
showColor = null
)
ServerItem(
server = server,
@ -272,6 +297,26 @@ private fun ServerItemPreview() {
)
}
@Preview
@Composable
private fun ColorfulServerItemPreview() {
val server = ServerData(
id = "1",
name = "Revolt Lounge",
description = "The official Revolt server. Hang out, chat, and get help with Revolt.",
inviteCode = "revolt",
disabled = false,
showColor = "#1591ea"
)
ServerItem(
server = server,
onClick = {},
isJoined = false,
isProcessing = false
)
}
@Preview
@Composable
private fun JoinedServerItemPreview() {
@ -280,7 +325,8 @@ private fun JoinedServerItemPreview() {
name = "Revolt Lounge",
description = "The official Revolt server. Hang out, chat, and get help with Revolt.",
inviteCode = "revolt",
disabled = false
disabled = false,
showColor = null,
)
ServerItem(
server = server,

View File

@ -421,18 +421,17 @@ fun ChannelSideDrawer(
}
Column(
Modifier
.clip(
MaterialTheme.shapes.medium.copy(
topStart = CornerSize(24.dp),
)
)
.background(MaterialTheme.colorScheme.surfaceContainer)
.weight(1f)
.fillMaxHeight()
) {
Box(
Modifier
.clip(
MaterialTheme.shapes.medium.copy(
topStart = CornerSize(0.dp),
topEnd = CornerSize(0.dp)
)
)
.height(serverBannerHeight)
) {
if (server?.banner != null) {

View File

@ -4,7 +4,6 @@ import android.content.Context
import android.widget.Toast
import androidx.activity.compose.BackHandler
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
@ -12,14 +11,10 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
@ -100,7 +95,6 @@ import chat.revolt.composables.generic.CountableListHeader
import chat.revolt.composables.generic.UserAvatar
import chat.revolt.internals.extensions.zero
import chat.revolt.markdown.jbm.asHexString
import chat.revolt.screens.chat.LocalIsConnected
import io.github.g00fy2.quickie.QRResult
import io.github.g00fy2.quickie.ScanQRCode
import kotlinx.coroutines.Dispatchers
@ -474,72 +468,61 @@ fun FriendsScreen(topNav: NavController, useDrawer: Boolean = false, onDrawerCli
Scaffold(
topBar = {
Column {
AnimatedVisibility(LocalIsConnected.current) {
Spacer(
Modifier
.height(
WindowInsets.statusBars.asPaddingValues()
.calculateTopPadding()
)
TopAppBar(
title = {
Text(
text = stringResource(R.string.friends),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
TopAppBar(
title = {
Text(
text = stringResource(R.string.friends),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
},
navigationIcon = {
if (useDrawer) {
IconButton(onClick = {
onDrawerClicked()
}) {
Icon(
painter = painterResource(R.drawable.icn_menu_24dp),
contentDescription = stringResource(id = R.string.menu)
)
}
}
},
actions = {
},
navigationIcon = {
if (useDrawer) {
IconButton(onClick = {
overflowMenuShown = true
onDrawerClicked()
}) {
Icon(
painter = painterResource(R.drawable.icn_more_vert_24dp),
contentDescription = stringResource(R.string.menu)
painter = painterResource(R.drawable.icn_menu_24dp),
contentDescription = stringResource(id = R.string.menu)
)
}
DropdownMenu(
expanded = overflowMenuShown,
onDismissRequest = {
overflowMenuShown = false
}
) {
DropdownMenuItem(
text = {
Text(stringResource(R.string.friends_deny_all_incoming))
},
onClick = {
}
},
actions = {
IconButton(onClick = {
overflowMenuShown = true
}) {
Icon(
painter = painterResource(R.drawable.icn_more_vert_24dp),
contentDescription = stringResource(R.string.menu)
)
}
DropdownMenu(
expanded = overflowMenuShown,
onDismissRequest = {
overflowMenuShown = false
}
) {
DropdownMenuItem(
text = {
Text(stringResource(R.string.friends_deny_all_incoming))
},
onClick = {
scope.launch {
overflowMenuShown = false
}
with(Dispatchers.IO) {
scope.launch {
overflowMenuShown = false
}
with(Dispatchers.IO) {
scope.launch {
FriendRequests.getIncoming()
.forEach { it.id?.let { id -> unfriendUser(id) } }
}
FriendRequests.getIncoming()
.forEach { it.id?.let { id -> unfriendUser(id) } }
}
}
)
}
},
windowInsets = WindowInsets.zero
)
}
}
)
}
},
windowInsets = WindowInsets.zero
)
},
) { pv ->
Box(

View File

@ -10,11 +10,11 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.LargeTopAppBar
import androidx.compose.material3.ListItem
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
@ -67,7 +67,7 @@ fun SettingsScreen(
Column(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
) {
LargeTopAppBar(
TopAppBar(
scrollBehavior = scrollBehavior,
title = {
Text(