feat: server context sheet
Signed-off-by: Infi <wingit@geist.ga>
This commit is contained in:
parent
0e67637ddf
commit
04237e3dfd
|
|
@ -6,6 +6,7 @@ import chat.revolt.api.RevoltHttp
|
||||||
import chat.revolt.api.RevoltJson
|
import chat.revolt.api.RevoltJson
|
||||||
import chat.revolt.api.schemas.Member
|
import chat.revolt.api.schemas.Member
|
||||||
import chat.revolt.api.schemas.User
|
import chat.revolt.api.schemas.User
|
||||||
|
import io.ktor.client.request.delete
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
import io.ktor.client.request.parameter
|
import io.ktor.client.request.parameter
|
||||||
import io.ktor.client.request.put
|
import io.ktor.client.request.put
|
||||||
|
|
@ -87,3 +88,11 @@ suspend fun fetchMember(serverId: String, userId: String, pure: Boolean = false)
|
||||||
|
|
||||||
return member
|
return member
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun leaveOrDeleteServer(serverId: String, leaveSilently: Boolean = false) {
|
||||||
|
RevoltHttp.delete("/servers/$serverId") {
|
||||||
|
headers.append(RevoltAPI.TOKEN_HEADER_NAME, RevoltAPI.sessionToken)
|
||||||
|
|
||||||
|
parameter("leave_silently", leaveSilently)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -79,6 +79,7 @@ import chat.revolt.screens.chat.views.HomeScreen
|
||||||
import chat.revolt.screens.chat.views.NoCurrentChannelScreen
|
import chat.revolt.screens.chat.views.NoCurrentChannelScreen
|
||||||
import chat.revolt.screens.chat.views.channel.ChannelScreen
|
import chat.revolt.screens.chat.views.channel.ChannelScreen
|
||||||
import chat.revolt.sheets.AddServerSheet
|
import chat.revolt.sheets.AddServerSheet
|
||||||
|
import chat.revolt.sheets.ServerContextSheet
|
||||||
import chat.revolt.sheets.StatusSheet
|
import chat.revolt.sheets.StatusSheet
|
||||||
import chat.revolt.sheets.UserContextSheet
|
import chat.revolt.sheets.UserContextSheet
|
||||||
import com.airbnb.lottie.RenderMode
|
import com.airbnb.lottie.RenderMode
|
||||||
|
|
@ -392,9 +393,13 @@ fun ChatRouterScreen(
|
||||||
showServerContextSheet = false
|
showServerContextSheet = false
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
Column {
|
ServerContextSheet(
|
||||||
Text(text = "this is server context sheet for $serverContextSheetTarget")
|
serverId = serverContextSheetTarget,
|
||||||
}
|
onHideSheet = {
|
||||||
|
serverContextSheetState.hide()
|
||||||
|
showServerContextSheet = false
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,294 @@
|
||||||
|
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.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.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
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.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.components.generic.IconPlaceholder
|
||||||
|
import chat.revolt.components.generic.RemoteImage
|
||||||
|
import chat.revolt.components.generic.SheetClickable
|
||||||
|
import chat.revolt.components.generic.UIMarkdown
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ServerContextSheet(
|
||||||
|
serverId: String,
|
||||||
|
onHideSheet: suspend () -> Unit
|
||||||
|
) {
|
||||||
|
val server = RevoltAPI.serverCache[serverId]
|
||||||
|
|
||||||
|
if (server == null) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(200.dp)
|
||||||
|
) {
|
||||||
|
CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
val clipboardManager = LocalClipboardManager.current
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
var showLeaveConfirmation by remember { mutableStateOf(false) }
|
||||||
|
var leaveSilently by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
if (showLeaveConfirmation) {
|
||||||
|
AlertDialog(onDismissRequest = {
|
||||||
|
showLeaveConfirmation = false
|
||||||
|
},
|
||||||
|
title = {
|
||||||
|
Text(
|
||||||
|
text = stringResource(
|
||||||
|
id = R.string.server_context_sheet_actions_leave_confirm,
|
||||||
|
server.name ?: stringResource(R.string.unknown)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
text = {
|
||||||
|
Column {
|
||||||
|
Text(text = stringResource(id = R.string.server_context_sheet_actions_leave_confirm_eyebrow))
|
||||||
|
Row(
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(start = 0.dp, end = 0.dp, top = 16.dp, bottom = 0.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Checkbox(
|
||||||
|
checked = leaveSilently,
|
||||||
|
onCheckedChange = { leaveSilently = it },
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.server_context_sheet_actions_leave_silently),
|
||||||
|
modifier = Modifier.padding(start = 4.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
coroutineScope.launch {
|
||||||
|
onHideSheet()
|
||||||
|
}
|
||||||
|
coroutineScope.launch {
|
||||||
|
leaveOrDeleteServer(serverId, leaveSilently)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(id = R.string.server_context_sheet_actions_leave_confirm_yes))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = {
|
||||||
|
TextButton(
|
||||||
|
onClick = {
|
||||||
|
showLeaveConfirmation = false
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(id = R.string.server_context_sheet_actions_leave_confirm_no))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = server.name ?: stringResource(R.string.unknown),
|
||||||
|
style = MaterialTheme.typography.labelLarge,
|
||||||
|
fontSize = 16.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(horizontal = 4.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.server_context_sheet_category_description),
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
modifier = Modifier.padding(vertical = 14.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
UIMarkdown(
|
||||||
|
text = if (server.description?.isBlank() == false) server.description else stringResource(
|
||||||
|
R.string.server_context_sheet_description_empty
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.server_context_sheet_category_actions),
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
modifier = Modifier.padding(top = 14.dp, bottom = 10.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
SheetClickable(icon = {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = R.drawable.ic_content_copy_id_24dp),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = it
|
||||||
|
)
|
||||||
|
}, label = {
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.server_context_sheet_actions_copy_id),
|
||||||
|
style = it
|
||||||
|
)
|
||||||
|
}) {
|
||||||
|
if (server.id == null) return@SheetClickable
|
||||||
|
|
||||||
|
clipboardManager.setText(AnnotatedString(server.id))
|
||||||
|
Toast.makeText(
|
||||||
|
context,
|
||||||
|
context.getString(R.string.server_context_sheet_actions_copy_id_copied),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
|
||||||
|
coroutineScope.launch {
|
||||||
|
onHideSheet()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SheetClickable(icon = {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = R.drawable.ic_eye_check_24dp),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = it
|
||||||
|
)
|
||||||
|
}, label = {
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.server_context_sheet_actions_mark_read),
|
||||||
|
style = it
|
||||||
|
)
|
||||||
|
}) {
|
||||||
|
coroutineScope.launch {
|
||||||
|
server.id?.let {
|
||||||
|
RevoltAPI.unreads.markServerAsRead(it, sync = true)
|
||||||
|
}
|
||||||
|
onHideSheet()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server.owner != RevoltAPI.selfId) {
|
||||||
|
SheetClickable(icon = {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = R.drawable.ic_arrow_left_bold_box_24dp),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = it
|
||||||
|
)
|
||||||
|
}, label = {
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.server_context_sheet_actions_leave),
|
||||||
|
style = it
|
||||||
|
)
|
||||||
|
}, dangerous = true) {
|
||||||
|
showLeaveConfirmation = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:width="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:pathData="M21,5V19A2,2 0 0,1 19,21H5A2,2 0 0,1 3,19V5A2,2 0 0,1 5,3H19A2,2 0 0,1 21,5M7,12L12,17V14H16V10H12V7L7,12Z" />
|
||||||
|
</vector>
|
||||||
|
|
@ -202,9 +202,19 @@
|
||||||
<string name="channel_context_sheet_actions_copy_id_copied">Copied channel ID to clipboard</string>
|
<string name="channel_context_sheet_actions_copy_id_copied">Copied channel ID to clipboard</string>
|
||||||
<string name="channel_context_sheet_actions_mark_read">Mark as read</string>
|
<string name="channel_context_sheet_actions_mark_read">Mark as read</string>
|
||||||
|
|
||||||
|
<string name="server_context_sheet_category_description">Description</string>
|
||||||
|
<string name="server_context_sheet_description_empty">There hasn\'t been a description set for this server yet.</string>
|
||||||
|
<string name="server_context_sheet_category_actions">Actions</string>
|
||||||
|
|
||||||
<string name="server_context_sheet_actions_copy_id">Copy ID</string>
|
<string name="server_context_sheet_actions_copy_id">Copy ID</string>
|
||||||
<string name="server_context_sheet_actions_copy_id_copied">Copied server ID to clipboard</string>
|
<string name="server_context_sheet_actions_copy_id_copied">Copied server ID to clipboard</string>
|
||||||
<string name="server_context_sheet_actions_mark_read">Mark as read</string>
|
<string name="server_context_sheet_actions_mark_read">Mark as read</string>
|
||||||
|
<string name="server_context_sheet_actions_leave">Leave</string>
|
||||||
|
<string name="server_context_sheet_actions_leave_confirm">Leave %1$s?</string>
|
||||||
|
<string name="server_context_sheet_actions_leave_confirm_eyebrow">Until you get invited back, you won\'t be able to rejoin.</string>
|
||||||
|
<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="user_context_sheet_category_bio">Bio</string>
|
<string name="user_context_sheet_category_bio">Bio</string>
|
||||||
<string name="user_context_sheet_bio_empty">This user hasn\'t set a bio yet.</string>
|
<string name="user_context_sheet_bio_empty">This user hasn\'t set a bio yet.</string>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue