feat: server reporting
Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
parent
46b75c3ed3
commit
f9b778e3c4
|
|
@ -0,0 +1,131 @@
|
|||
package chat.revolt.components.screens.settings
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import chat.revolt.R
|
||||
import chat.revolt.api.REVOLT_FILES
|
||||
import chat.revolt.api.schemas.Server
|
||||
import chat.revolt.api.schemas.ServerFlags
|
||||
import chat.revolt.api.schemas.has
|
||||
import chat.revolt.components.generic.IconPlaceholder
|
||||
import chat.revolt.components.generic.RemoteImage
|
||||
|
||||
@Composable
|
||||
fun ServerOverview(server: Server) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clip(MaterialTheme.shapes.large),
|
||||
contentAlignment = Alignment.BottomStart
|
||||
) {
|
||||
server.banner?.let {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.background(Color.Black.copy(alpha = 0.25f))
|
||||
.height(166.dp)
|
||||
.fillMaxWidth()
|
||||
)
|
||||
|
||||
RemoteImage(
|
||||
url = "$REVOLT_FILES/banners/${it.id}",
|
||||
description = null,
|
||||
modifier = Modifier
|
||||
.height(166.dp)
|
||||
.fillMaxWidth(),
|
||||
contentScale = ContentScale.FillWidth
|
||||
)
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.background(
|
||||
Brush.verticalGradient(
|
||||
listOf(
|
||||
Color.Transparent,
|
||||
Color.Black.copy(alpha = 0.7f)
|
||||
)
|
||||
)
|
||||
)
|
||||
.height(166.dp)
|
||||
.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.padding(16.dp)
|
||||
) {
|
||||
server.icon?.let {
|
||||
RemoteImage(
|
||||
url = "$REVOLT_FILES/icons/${it.id}/server.png?max_side=256",
|
||||
description = null,
|
||||
modifier = Modifier
|
||||
.clip(CircleShape)
|
||||
.height(48.dp)
|
||||
.width(48.dp),
|
||||
contentScale = ContentScale.Crop
|
||||
)
|
||||
} ?: run {
|
||||
IconPlaceholder(
|
||||
name = server.name ?: stringResource(R.string.unknown),
|
||||
modifier = Modifier
|
||||
.clip(CircleShape)
|
||||
.height(48.dp)
|
||||
.width(48.dp)
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
|
||||
CompositionLocalProvider(LocalContentColor provides Color.White) {
|
||||
if (server.flags has ServerFlags.Official) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_revolt_decagram_24dp),
|
||||
contentDescription = stringResource(R.string.server_flag_official),
|
||||
modifier = Modifier
|
||||
.padding(end = 8.dp)
|
||||
.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),
|
||||
modifier = Modifier
|
||||
.padding(end = 8.dp)
|
||||
.size(24.dp)
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = server.name ?: stringResource(R.string.unknown),
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
fontSize = 16.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -94,6 +94,7 @@ import chat.revolt.internals.Changelogs
|
|||
import chat.revolt.ndk.Pipebomb
|
||||
import chat.revolt.persistence.KVStorage
|
||||
import chat.revolt.screens.chat.dialogs.safety.ReportMessageDialog
|
||||
import chat.revolt.screens.chat.dialogs.safety.ReportServerDialog
|
||||
import chat.revolt.screens.chat.dialogs.safety.ReportUserDialog
|
||||
import chat.revolt.screens.chat.views.FriendsScreen
|
||||
import chat.revolt.screens.chat.views.HomeScreen
|
||||
|
|
@ -590,6 +591,9 @@ fun ChatRouterScreen(
|
|||
onHideSheet = {
|
||||
serverContextSheetState.hide()
|
||||
showServerContextSheet = false
|
||||
},
|
||||
onReportServer = {
|
||||
navController.navigate("report/server/${serverContextSheetTarget}")
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -1088,6 +1092,16 @@ fun ChannelNavigator(
|
|||
}
|
||||
}
|
||||
|
||||
dialog("report/server/{serverId}") { backStackEntry ->
|
||||
val serverId = backStackEntry.arguments?.getString("serverId")
|
||||
if (serverId != null) {
|
||||
ReportServerDialog(
|
||||
navController = navController,
|
||||
serverId = serverId
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
dialog("report/user/{userId}") { backStackEntry ->
|
||||
val userId = backStackEntry.arguments?.getString("userId")
|
||||
if (userId != null) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,319 @@
|
|||
package chat.revolt.screens.chat.dialogs.safety
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Check
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ExposedDropdownMenuBox
|
||||
import androidx.compose.material3.ExposedDropdownMenuDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.navigation.NavController
|
||||
import chat.revolt.R
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.routes.safety.putServerReport
|
||||
import chat.revolt.api.schemas.ContentReportReason
|
||||
import chat.revolt.components.generic.FormTextField
|
||||
import chat.revolt.components.screens.settings.ServerOverview
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
enum class ServerReportFlowState {
|
||||
Reason,
|
||||
Sending,
|
||||
Done,
|
||||
Error
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ReportServerDialog(navController: NavController, serverId: String) {
|
||||
val server = RevoltAPI.serverCache[serverId]
|
||||
if (server == null) {
|
||||
navController.popBackStack()
|
||||
return
|
||||
}
|
||||
|
||||
val state = remember { mutableStateOf(ServerReportFlowState.Reason) }
|
||||
|
||||
val selectedReason = remember { mutableStateOf("Illegal") }
|
||||
val userAddedContext = remember { mutableStateOf("") }
|
||||
|
||||
when (state.value) {
|
||||
ServerReportFlowState.Reason -> {
|
||||
val reasons = mapOf(
|
||||
"Illegal" to stringResource(id = R.string.report_reason_content_illegal),
|
||||
"IllegalGoods" to stringResource(id = R.string.report_reason_content_illegal_goods),
|
||||
"IllegalExtortion" to stringResource(id = R.string.report_reason_content_illegal_extortion),
|
||||
"IllegalPornography" to stringResource(id = R.string.report_reason_content_illegal_pornography),
|
||||
"IllegalHacking" to stringResource(id = R.string.report_reason_content_illegal_hacking),
|
||||
"ExtremeViolence" to stringResource(id = R.string.report_reason_content_extreme_violence),
|
||||
"PromotesHarm" to stringResource(id = R.string.report_reason_content_promotes_harm),
|
||||
"UnsolicitedSpam" to stringResource(id = R.string.report_reason_content_unsolicited_spam),
|
||||
"Raid" to stringResource(id = R.string.report_reason_content_raid),
|
||||
"SpamAbuse" to stringResource(id = R.string.report_reason_content_spam_abuse),
|
||||
"ScamsFraud" to stringResource(id = R.string.report_reason_content_scams_fraud),
|
||||
"Malware" to stringResource(id = R.string.report_reason_content_malware),
|
||||
"Harassment" to stringResource(id = R.string.report_reason_content_harassment),
|
||||
"NoneSpecified" to stringResource(id = R.string.report_reason_content_other)
|
||||
)
|
||||
val reasonDropdownExpanded = remember { mutableStateOf(false) }
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = {
|
||||
// nothing - prevent mistaps from closing the dialog
|
||||
},
|
||||
title = {
|
||||
Text(
|
||||
text = stringResource(id = R.string.report_server_heading),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
},
|
||||
text = {
|
||||
Column {
|
||||
Text(text = stringResource(id = R.string.report_server))
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
Text(
|
||||
text = stringResource(id = R.string.report_server_preview),
|
||||
fontSize = 12.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
|
||||
ServerOverview(server)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
ExposedDropdownMenuBox(
|
||||
expanded = reasonDropdownExpanded.value,
|
||||
onExpandedChange = {
|
||||
reasonDropdownExpanded.value = it
|
||||
},
|
||||
) {
|
||||
TextField(
|
||||
value = reasons[selectedReason.value]
|
||||
?: stringResource(id = R.string.unknown),
|
||||
readOnly = true,
|
||||
onValueChange = {},
|
||||
label = {
|
||||
Text(
|
||||
text = stringResource(id = R.string.report_reason)
|
||||
)
|
||||
},
|
||||
trailingIcon = {
|
||||
ExposedDropdownMenuDefaults.TrailingIcon(expanded = reasonDropdownExpanded.value)
|
||||
},
|
||||
colors = ExposedDropdownMenuDefaults.textFieldColors(),
|
||||
modifier = Modifier.menuAnchor()
|
||||
)
|
||||
|
||||
ExposedDropdownMenu(
|
||||
expanded = reasonDropdownExpanded.value,
|
||||
onDismissRequest = {
|
||||
reasonDropdownExpanded.value = false
|
||||
}
|
||||
) {
|
||||
reasons.forEach { (key, value) ->
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(text = value)
|
||||
},
|
||||
onClick = {
|
||||
selectedReason.value = key
|
||||
reasonDropdownExpanded.value = false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
FormTextField(
|
||||
value = userAddedContext.value,
|
||||
label = stringResource(id = R.string.report_reason_additional),
|
||||
onChange = {
|
||||
userAddedContext.value = it
|
||||
},
|
||||
supportingText = {
|
||||
Text(
|
||||
text = stringResource(
|
||||
id = R.string.report_reason_additional_hint
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(
|
||||
onClick = {
|
||||
navController.popBackStack()
|
||||
},
|
||||
modifier = Modifier.testTag("report_cancel")
|
||||
) {
|
||||
Text(text = stringResource(id = R.string.report_cancel))
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(
|
||||
onClick = {
|
||||
state.value = ServerReportFlowState.Sending
|
||||
},
|
||||
modifier = Modifier.testTag("report_send")
|
||||
) {
|
||||
Text(text = stringResource(id = R.string.report_submit))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
ServerReportFlowState.Sending -> {
|
||||
AlertDialog(
|
||||
onDismissRequest = {},
|
||||
title = {
|
||||
Text(
|
||||
text = stringResource(id = R.string.report_submitting),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
},
|
||||
text = {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
CircularProgressIndicator()
|
||||
LaunchedEffect(true) {
|
||||
launch {
|
||||
try {
|
||||
Log.d("ReportServerDialog", "Reporting server $serverId")
|
||||
putServerReport(
|
||||
serverId,
|
||||
ContentReportReason.valueOf(selectedReason.value),
|
||||
userAddedContext.value
|
||||
)
|
||||
state.value = ServerReportFlowState.Done
|
||||
} catch (e: Error) {
|
||||
state.value = ServerReportFlowState.Error
|
||||
Log.e("ReportServerDialog", "Failed to report server", e)
|
||||
return@launch
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
dismissButton = {},
|
||||
confirmButton = {}
|
||||
)
|
||||
}
|
||||
|
||||
ServerReportFlowState.Done -> {
|
||||
AlertDialog(
|
||||
onDismissRequest = {
|
||||
navController.popBackStack()
|
||||
},
|
||||
icon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Check,
|
||||
contentDescription = null, // decorative
|
||||
tint = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
},
|
||||
title = {
|
||||
Text(
|
||||
text = stringResource(id = R.string.report_submit_success),
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
},
|
||||
text = {
|
||||
Column {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.report_submit_thanks),
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(
|
||||
onClick = {
|
||||
navController.popBackStack()
|
||||
},
|
||||
modifier = Modifier.testTag("report_close")
|
||||
) {
|
||||
Text(text = stringResource(id = R.string.report_submit_close))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
ServerReportFlowState.Error -> {
|
||||
AlertDialog(
|
||||
onDismissRequest = {
|
||||
navController.popBackStack()
|
||||
},
|
||||
icon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Close,
|
||||
contentDescription = null, // decorative
|
||||
tint = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
},
|
||||
title = {
|
||||
Text(
|
||||
text = stringResource(id = R.string.report_submit_error_header),
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
},
|
||||
text = {
|
||||
Column {
|
||||
Text(
|
||||
text = stringResource(id = R.string.report_submit_error),
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(
|
||||
onClick = {
|
||||
navController.popBackStack()
|
||||
},
|
||||
modifier = Modifier.testTag("report_error_ok")
|
||||
) {
|
||||
Text(text = stringResource(id = R.string.ok))
|
||||
}
|
||||
},
|
||||
confirmButton = {}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +1,21 @@
|
|||
package chat.revolt.sheets
|
||||
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.background
|
||||
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.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Checkbox
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
|
|
@ -30,32 +23,27 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalClipboardManager
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import chat.revolt.R
|
||||
import chat.revolt.api.REVOLT_FILES
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.routes.server.leaveOrDeleteServer
|
||||
import chat.revolt.api.schemas.ServerFlags
|
||||
import chat.revolt.api.schemas.has
|
||||
import chat.revolt.components.generic.IconPlaceholder
|
||||
import chat.revolt.components.generic.RemoteImage
|
||||
import chat.revolt.components.generic.SheetClickable
|
||||
import chat.revolt.components.generic.UIMarkdown
|
||||
import chat.revolt.components.screens.settings.ServerOverview
|
||||
import chat.revolt.internals.Platform
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun ServerContextSheet(serverId: String, onHideSheet: suspend () -> Unit) {
|
||||
fun ServerContextSheet(
|
||||
serverId: String,
|
||||
onReportServer: () -> Unit,
|
||||
onHideSheet: suspend () -> Unit
|
||||
) {
|
||||
val server = RevoltAPI.serverCache[serverId]
|
||||
|
||||
if (server == null) {
|
||||
|
|
@ -152,98 +140,7 @@ fun ServerContextSheet(serverId: String, onHideSheet: suspend () -> Unit) {
|
|||
Column(
|
||||
modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 0.dp, bottom = 16.dp)
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clip(MaterialTheme.shapes.large),
|
||||
contentAlignment = Alignment.BottomStart
|
||||
) {
|
||||
server.banner?.let {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.background(Color.Black.copy(alpha = 0.25f))
|
||||
.height(166.dp)
|
||||
.fillMaxWidth()
|
||||
)
|
||||
|
||||
RemoteImage(
|
||||
url = "$REVOLT_FILES/banners/${it.id}",
|
||||
description = null,
|
||||
modifier = Modifier
|
||||
.height(166.dp)
|
||||
.fillMaxWidth(),
|
||||
contentScale = ContentScale.FillWidth
|
||||
)
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.background(
|
||||
Brush.verticalGradient(
|
||||
listOf(
|
||||
Color.Transparent,
|
||||
Color.Black.copy(alpha = 0.7f)
|
||||
)
|
||||
)
|
||||
)
|
||||
.height(166.dp)
|
||||
.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.padding(16.dp)
|
||||
) {
|
||||
server.icon?.let {
|
||||
RemoteImage(
|
||||
url = "$REVOLT_FILES/icons/${it.id}/server.png?max_side=256",
|
||||
description = null,
|
||||
modifier = Modifier
|
||||
.clip(CircleShape)
|
||||
.height(48.dp)
|
||||
.width(48.dp),
|
||||
contentScale = ContentScale.Crop
|
||||
)
|
||||
} ?: run {
|
||||
IconPlaceholder(
|
||||
name = server.name ?: stringResource(R.string.unknown),
|
||||
modifier = Modifier
|
||||
.clip(CircleShape)
|
||||
.height(48.dp)
|
||||
.width(48.dp)
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
|
||||
CompositionLocalProvider(LocalContentColor provides Color.White) {
|
||||
if (server.flags has ServerFlags.Official) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_revolt_decagram_24dp),
|
||||
contentDescription = stringResource(R.string.server_flag_official),
|
||||
modifier = Modifier
|
||||
.padding(end = 8.dp)
|
||||
.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),
|
||||
modifier = Modifier
|
||||
.padding(end = 8.dp)
|
||||
.size(24.dp)
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = server.name ?: stringResource(R.string.unknown),
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
fontSize = 16.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
ServerOverview(server)
|
||||
|
||||
Column(
|
||||
modifier = Modifier.padding(horizontal = 4.dp)
|
||||
|
|
@ -321,6 +218,21 @@ fun ServerContextSheet(serverId: String, onHideSheet: suspend () -> Unit) {
|
|||
}
|
||||
|
||||
if (server.owner != RevoltAPI.selfId) {
|
||||
SheetClickable(icon = {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_flag_24dp),
|
||||
contentDescription = null,
|
||||
modifier = it
|
||||
)
|
||||
}, label = {
|
||||
Text(
|
||||
text = stringResource(id = R.string.server_context_sheet_actions_report),
|
||||
style = it
|
||||
)
|
||||
}, dangerous = true) {
|
||||
onReportServer()
|
||||
}
|
||||
|
||||
SheetClickable(icon = {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_arrow_left_bold_box_24dp),
|
||||
|
|
|
|||
|
|
@ -295,6 +295,7 @@
|
|||
<string name="server_context_sheet_actions_leave_confirm_yes">Leave</string>
|
||||
<string name="server_context_sheet_actions_leave_confirm_no">Stay</string>
|
||||
<string name="server_context_sheet_actions_leave_silently">Leave Silently</string>
|
||||
<string name="server_context_sheet_actions_report">Report</string>
|
||||
|
||||
<string name="user_info_sheet_user_not_found">Can\'t resolve this user</string>
|
||||
<string name="user_info_sheet_user_not_found_description">This user may have been deleted or you may not have permission to view them.</string>
|
||||
|
|
|
|||
Loading…
Reference in New Issue