feat: channel menu and mark as read

This commit is contained in:
Infi 2023-02-28 00:03:11 +01:00
parent b0579d1436
commit dd78679901
8 changed files with 493 additions and 296 deletions

View File

@ -0,0 +1,127 @@
package chat.revolt.components.screens.chat.drawer.channel
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import androidx.navigation.compose.currentBackStackEntryAsState
import chat.revolt.R
import chat.revolt.api.RevoltAPI
import chat.revolt.api.schemas.ChannelType
import chat.revolt.components.screens.chat.DoubleDrawerState
import chat.revolt.components.screens.chat.drawer.server.DrawerChannel
import kotlinx.coroutines.launch
@Composable
fun RowScope.ChannelList(
serverId: String,
navController: NavController,
drawerState: DoubleDrawerState
) {
val coroutineScope = rememberCoroutineScope()
val navBackStackEntry by navController.currentBackStackEntryAsState()
Surface(
tonalElevation = 1.dp,
modifier = Modifier
.padding(start = 4.dp, top = 8.dp, bottom = 8.dp)
.clip(RoundedCornerShape(16.dp))
) {
Column(
Modifier
.weight(1f)
) {
if (serverId == "home") {
Column(
Modifier
.weight(1f)
.verticalScroll(rememberScrollState())
) {
RevoltAPI.channelCache.values.filter { it.channelType == ChannelType.Group }
.forEach { channel ->
DrawerChannel(
name = channel.name
?: "GDM #${channel.id}",
channelType = ChannelType.Group,
selected = (channel.id == navBackStackEntry?.arguments?.getString(
"channelId"
)),
hasUnread = channel.lastMessageID?.let { lastMessageID ->
RevoltAPI.unreads.hasUnread(
channel.id!!,
lastMessageID
)
} ?: false,
onClick = {
navController.navigate("channel/${channel.id}")
coroutineScope.launch { drawerState.focusCenter() }
},
onLongClick = {
navController.navigate("channel/${channel.id}/info")
}
)
}
}
} else {
val server = RevoltAPI.serverCache[serverId]
Text(
text = server?.name
?: stringResource(R.string.unknown),
style = MaterialTheme.typography.labelLarge,
fontSize = 24.sp,
modifier = Modifier.padding(16.dp)
)
Column(
Modifier
.weight(1f)
.verticalScroll(rememberScrollState())
) {
server?.channels?.forEach { channelId ->
RevoltAPI.channelCache[channelId]?.let { ch ->
DrawerChannel(
name = ch.name!!,
channelType = ch.channelType!!,
selected = navBackStackEntry?.arguments?.getString(
"channelId"
) == ch.id,
hasUnread = ch.lastMessageID?.let { lastMessageID ->
RevoltAPI.unreads.hasUnread(
ch.id!!,
lastMessageID
)
} ?: true,
onClick = {
coroutineScope.launch { drawerState.focusCenter() }
navController.navigate("channel/${ch.id}") {
popUpTo("home") {
inclusive = true
}
}
},
onLongClick = {
navController.navigate("channel/${ch.id}/menu")
}
)
}
}
}
}
}
}
}

View File

@ -3,8 +3,9 @@ package chat.revolt.components.screens.chat.drawer.server
import androidx.compose.animation.animateColorAsState import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.spring import androidx.compose.animation.core.spring
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.LocalContentColor import androidx.compose.material3.LocalContentColor
@ -22,13 +23,15 @@ import androidx.compose.ui.unit.dp
import chat.revolt.api.schemas.ChannelType import chat.revolt.api.schemas.ChannelType
import chat.revolt.components.screens.chat.ChannelIcon import chat.revolt.components.screens.chat.ChannelIcon
@OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
fun DrawerChannel( fun DrawerChannel(
channelType: ChannelType, channelType: ChannelType,
name: String, name: String,
selected: Boolean, selected: Boolean,
hasUnread: Boolean, hasUnread: Boolean,
onClick: () -> Unit onClick: () -> Unit,
onLongClick: () -> Unit = {},
) { ) {
val backgroundColor = animateColorAsState( val backgroundColor = animateColorAsState(
if (selected) MaterialTheme.colorScheme.background if (selected) MaterialTheme.colorScheme.background
@ -52,7 +55,10 @@ fun DrawerChannel(
.clip(MaterialTheme.shapes.medium) .clip(MaterialTheme.shapes.medium)
.background(backgroundColor.value) .background(backgroundColor.value)
.alpha(channelAlpha.value) .alpha(channelAlpha.value)
.clickable(onClick = onClick) .combinedClickable(
onClick = onClick,
onLongClick = onLongClick
)
.padding(vertical = 8.dp, horizontal = 16.dp), .padding(vertical = 8.dp, horizontal = 16.dp),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {

View File

@ -12,12 +12,10 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -30,17 +28,17 @@ import chat.revolt.R
import chat.revolt.api.RevoltAPI import chat.revolt.api.RevoltAPI
import chat.revolt.api.realtime.DisconnectionState import chat.revolt.api.realtime.DisconnectionState
import chat.revolt.api.realtime.RealtimeSocket import chat.revolt.api.realtime.RealtimeSocket
import chat.revolt.api.schemas.ChannelType
import chat.revolt.components.chat.DisconnectedNotice import chat.revolt.components.chat.DisconnectedNotice
import chat.revolt.components.generic.UserAvatar import chat.revolt.components.generic.UserAvatar
import chat.revolt.components.generic.presenceFromStatus import chat.revolt.components.generic.presenceFromStatus
import chat.revolt.components.screens.chat.DoubleDrawer import chat.revolt.components.screens.chat.DoubleDrawer
import chat.revolt.components.screens.chat.drawer.server.DrawerChannel import chat.revolt.components.screens.chat.drawer.channel.ChannelList
import chat.revolt.components.screens.chat.drawer.server.DrawerServer import chat.revolt.components.screens.chat.drawer.server.DrawerServer
import chat.revolt.components.screens.chat.drawer.server.DrawerServerlikeIcon import chat.revolt.components.screens.chat.drawer.server.DrawerServerlikeIcon
import chat.revolt.components.screens.chat.drawer.server.ServerDrawerSeparator import chat.revolt.components.screens.chat.drawer.server.ServerDrawerSeparator
import chat.revolt.components.screens.chat.rememberDoubleDrawerState import chat.revolt.components.screens.chat.rememberDoubleDrawerState
import chat.revolt.screens.chat.dialogs.safety.ReportMessageDialog import chat.revolt.screens.chat.dialogs.safety.ReportMessageDialog
import chat.revolt.screens.chat.sheets.ChannelContextSheet
import chat.revolt.screens.chat.sheets.ChannelInfoSheet import chat.revolt.screens.chat.sheets.ChannelInfoSheet
import chat.revolt.screens.chat.sheets.MessageContextSheet import chat.revolt.screens.chat.sheets.MessageContextSheet
import chat.revolt.screens.chat.sheets.StatusSheet import chat.revolt.screens.chat.sheets.StatusSheet
@ -91,7 +89,6 @@ fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = vie
val bottomSheetNavigator = rememberBottomSheetNavigator() val bottomSheetNavigator = rememberBottomSheetNavigator()
val navController = rememberNavController(bottomSheetNavigator) val navController = rememberNavController(bottomSheetNavigator)
val navBackStackEntry by navController.currentBackStackEntryAsState()
ModalBottomSheetLayout( ModalBottomSheetLayout(
sheetShape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp), sheetShape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
@ -176,91 +173,11 @@ fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = vie
} }
Crossfade(targetState = viewModel.currentServer) { Crossfade(targetState = viewModel.currentServer) {
Surface( ChannelList(
tonalElevation = 1.dp, serverId = it,
modifier = Modifier navController = navController,
.padding(start = 4.dp, top = 8.dp, bottom = 8.dp) drawerState = drawerState
.clip(RoundedCornerShape(16.dp)) )
) {
Column(
Modifier
.weight(1f)
) {
if (it == "home") {
Column(
Modifier
.weight(1f)
.verticalScroll(rememberScrollState())
) {
RevoltAPI.channelCache.values.filter { it.channelType == ChannelType.Group }
.forEach { channel ->
DrawerChannel(
name = channel.name
?: "GDM #${channel.id}",
channelType = ChannelType.Group,
selected = channel.id == (navBackStackEntry?.arguments?.getString(
"channelId"
) ?: false),
hasUnread = channel.lastMessageID?.let { lastMessageID ->
RevoltAPI.unreads.hasUnread(
channel.id!!,
lastMessageID
)
} ?: false,
onClick = {
navController.navigate("channel/${channel.id}")
scope.launch {
drawerState.focusCenter()
}
}
)
}
}
} else {
val server = RevoltAPI.serverCache[it]
Text(
text = server?.name
?: stringResource(R.string.unknown),
style = MaterialTheme.typography.labelLarge,
fontSize = 24.sp,
modifier = Modifier.padding(16.dp)
)
Column(
Modifier
.weight(1f)
.verticalScroll(rememberScrollState())
) {
server?.channels?.forEach { channelId ->
RevoltAPI.channelCache[channelId]?.let { ch ->
DrawerChannel(
name = ch.name!!,
channelType = ch.channelType!!,
selected = navBackStackEntry?.arguments?.getString(
"channelId"
) == ch.id,
hasUnread = ch.lastMessageID?.let { lastMessageID ->
RevoltAPI.unreads.hasUnread(
ch.id!!,
lastMessageID
)
} ?: true,
onClick = {
scope.launch { drawerState.focusCenter() }
navController.navigate("channel/${ch.id}") {
popUpTo("home") {
inclusive = true
}
}
}
)
}
}
}
}
}
}
} }
} }
} }
@ -300,6 +217,15 @@ fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = vie
) )
} }
} }
bottomSheet("channel/{channelId}/menu") { backStackEntry ->
val channelId = backStackEntry.arguments?.getString("channelId")
if (channelId != null) {
ChannelContextSheet(
navController = navController,
channelId = channelId
)
}
}
bottomSheet("message/{messageId}/menu") { backStackEntry -> bottomSheet("message/{messageId}/menu") { backStackEntry ->
val messageId = backStackEntry.arguments?.getString("messageId") val messageId = backStackEntry.arguments?.getString("messageId")
if (messageId != null) { if (messageId != null) {

View File

@ -0,0 +1,86 @@
package chat.revolt.screens.chat.sheets
import android.widget.Toast
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
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.navigation.NavController
import chat.revolt.R
import chat.revolt.api.RevoltAPI
import chat.revolt.components.generic.SheetClickable
import kotlinx.coroutines.launch
@Composable
fun ChannelContextSheet(
navController: NavController,
channelId: String,
) {
val channel = RevoltAPI.channelCache[channelId]
if (channel == null) {
navController.popBackStack()
return
}
val clipboardManager = LocalClipboardManager.current
val context = LocalContext.current
val coroutineScope = rememberCoroutineScope()
Column {
SheetClickable(
icon = { modifier ->
Icon(
painter = painterResource(id = R.drawable.ic_content_copy_id_24dp),
contentDescription = null,
modifier = modifier
)
},
label = { style ->
Text(
text = stringResource(id = R.string.channel_context_sheet_actions_copy_id),
style = style
)
},
) {
if (channel.id == null) return@SheetClickable
clipboardManager.setText(AnnotatedString(channel.id))
Toast.makeText(
context,
context.getString(R.string.channel_context_sheet_actions_copy_id_copied),
Toast.LENGTH_SHORT
).show()
navController.popBackStack()
}
SheetClickable(
icon = { modifier ->
Icon(
painter = painterResource(id = R.drawable.ic_eye_check_24dp),
contentDescription = null,
modifier = modifier
)
},
label = { style ->
Text(
text = stringResource(id = R.string.channel_context_sheet_actions_mark_read),
style = style
)
},
) {
coroutineScope.launch {
channel.lastMessageID?.let {
RevoltAPI.unreads.markAsRead(channelId, it, sync = true)
}
}
navController.popBackStack()
}
}
}

View File

@ -8,7 +8,10 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Edit import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.* import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
@ -40,234 +43,256 @@ fun MessageContextSheet(
val context = LocalContext.current val context = LocalContext.current
val clipboardManager = LocalClipboardManager.current val clipboardManager = LocalClipboardManager.current
Surface { Column(
Column( modifier = Modifier
.padding(horizontal = 16.dp, vertical = 8.dp)
.verticalScroll(rememberScrollState()),
) {
Box(
modifier = Modifier modifier = Modifier
.padding(horizontal = 16.dp, vertical = 8.dp) .clip(MaterialTheme.shapes.medium)
.verticalScroll(rememberScrollState()), .background(MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp))
.padding(bottom = 8.dp)
) { ) {
Box( Message(
modifier = Modifier message = message.copy(
.clip(MaterialTheme.shapes.medium) tail = false,
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp)) masquerade = null
.padding(bottom = 8.dp) ),
) { truncate = true
Message( )
message = message.copy( }
tail = false,
masquerade = null Spacer(modifier = Modifier.height(8.dp))
),
truncate = true SheetClickable(
icon = { modifier ->
Icon(
painter = painterResource(id = R.drawable.ic_reply_24dp),
contentDescription = null,
modifier = modifier
) )
} },
label = { style ->
Text(
text = stringResource(id = R.string.message_context_sheet_actions_reply),
style = style
)
},
) {
UiCallbacks.emitQueueMessageForReply(messageId)
navController.popBackStack()
}
Spacer(modifier = Modifier.height(8.dp)) SheetClickable(
icon = { modifier ->
Icon(
painter = painterResource(id = R.drawable.ic_hamburger_plus_24dp),
contentDescription = null,
modifier = modifier
)
},
label = { style ->
Text(
text = stringResource(id = R.string.message_context_sheet_actions_react),
style = style
)
},
) {
Toast.makeText(
context,
context.getString(R.string.comingsoon_toast),
Toast.LENGTH_SHORT
).show()
navController.popBackStack()
}
SheetClickable( SheetClickable(
icon = { modifier -> icon = { modifier ->
Icon( Icon(
painter = painterResource(id = R.drawable.ic_reply_24dp), painter = painterResource(id = R.drawable.ic_content_copy_24dp),
contentDescription = null, contentDescription = null,
modifier = modifier modifier = modifier
) )
}, },
label = { style -> label = { style ->
Text( Text(
text = stringResource(id = R.string.message_context_sheet_actions_reply), text = stringResource(id = R.string.message_context_sheet_actions_copy),
style = style style = style
) )
}, },
) { ) {
UiCallbacks.emitQueueMessageForReply(messageId) if (message.content == null || message.content.isEmpty()) {
navController.popBackStack()
}
SheetClickable(
icon = { modifier ->
Icon(
painter = painterResource(id = R.drawable.ic_hamburger_plus_24dp),
contentDescription = null,
modifier = modifier
)
},
label = { style ->
Text(
text = stringResource(id = R.string.message_context_sheet_actions_react),
style = style
)
},
) {
Toast.makeText( Toast.makeText(
context, context,
context.getString(R.string.comingsoon_toast), context.getString(R.string.message_context_sheet_actions_copy_failed_empty),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
navController.popBackStack() navController.popBackStack()
return@SheetClickable
} }
SheetClickable( clipboardManager.setText(AnnotatedString(message.content))
icon = { modifier -> Toast.makeText(
Icon( context,
painter = painterResource(id = R.drawable.ic_content_copy_24dp), context.getString(R.string.copied),
contentDescription = null, Toast.LENGTH_SHORT
modifier = modifier ).show()
) navController.popBackStack()
}, }
label = { style ->
Text(
text = stringResource(id = R.string.message_context_sheet_actions_copy),
style = style
)
},
) {
if (message.content == null || message.content.isEmpty()) {
Toast.makeText(
context,
context.getString(R.string.message_context_sheet_actions_copy_failed_empty),
Toast.LENGTH_SHORT
).show()
navController.popBackStack()
return@SheetClickable
}
clipboardManager.setText(AnnotatedString(message.content)) SheetClickable(
icon = { modifier ->
Icon(
painter = painterResource(id = R.drawable.ic_link_variant_24dp),
contentDescription = null,
modifier = modifier
)
},
label = { style ->
Text(
text = stringResource(id = R.string.message_context_sheet_actions_copy_link),
style = style
)
},
) {
if (message.content == null || message.content.isEmpty()) {
Toast.makeText( Toast.makeText(
context, context,
context.getString(R.string.copied), context.getString(R.string.message_context_sheet_actions_copy_failed_empty),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
navController.popBackStack() navController.popBackStack()
return@SheetClickable
} }
SheetClickable( val server = RevoltAPI.serverCache.values.find { server ->
icon = { modifier -> server.channels?.contains(message.channel) ?: false
Icon(
painter = painterResource(id = R.drawable.ic_link_variant_24dp),
contentDescription = null,
modifier = modifier
)
},
label = { style ->
Text(
text = stringResource(id = R.string.message_context_sheet_actions_copy_link),
style = style
)
},
) {
if (message.content == null || message.content.isEmpty()) {
Toast.makeText(
context,
context.getString(R.string.message_context_sheet_actions_copy_failed_empty),
Toast.LENGTH_SHORT
).show()
navController.popBackStack()
return@SheetClickable
}
val server = RevoltAPI.serverCache.values.find { server ->
server.channels?.contains(message.channel) ?: false
}
val messageLink =
"$REVOLT_APP/server/${server?.id}/channel/${message.channel}/${message.id}"
clipboardManager.setText(AnnotatedString(messageLink))
Toast.makeText(
context,
context.getString(R.string.message_context_sheet_actions_copy_link_copied),
Toast.LENGTH_SHORT
).show()
navController.popBackStack()
} }
val messageLink =
"$REVOLT_APP/server/${server?.id}/channel/${message.channel}/${message.id}"
SheetClickable( clipboardManager.setText(AnnotatedString(messageLink))
icon = { modifier -> Toast.makeText(
Icon( context,
painter = painterResource(id = R.drawable.ic_content_copy_id_24dp), context.getString(R.string.message_context_sheet_actions_copy_link_copied),
contentDescription = null, Toast.LENGTH_SHORT
modifier = modifier ).show()
) navController.popBackStack()
}, }
label = { style ->
Text(
text = stringResource(id = R.string.message_context_sheet_actions_copy_id),
style = style
)
},
) {
if (message.id == null) return@SheetClickable
clipboardManager.setText(AnnotatedString(message.id)) SheetClickable(
Toast.makeText( icon = { modifier ->
context, Icon(
context.getString(R.string.message_context_sheet_actions_copy_id_copied), painter = painterResource(id = R.drawable.ic_content_copy_id_24dp),
Toast.LENGTH_SHORT contentDescription = null,
).show() modifier = modifier
navController.popBackStack() )
} },
label = { style ->
Text(
text = stringResource(id = R.string.message_context_sheet_actions_copy_id),
style = style
)
},
) {
if (message.id == null) return@SheetClickable
SheetClickable( clipboardManager.setText(AnnotatedString(message.id))
icon = { modifier -> Toast.makeText(
Icon( context,
imageVector = Icons.Default.Edit, context.getString(R.string.message_context_sheet_actions_copy_id_copied),
contentDescription = null, Toast.LENGTH_SHORT
modifier = modifier ).show()
) navController.popBackStack()
}, }
label = { style ->
Text(
text = stringResource(id = R.string.message_context_sheet_actions_edit),
style = style
)
},
) {
Toast.makeText(
context,
context.getString(R.string.comingsoon_toast),
Toast.LENGTH_SHORT
).show()
navController.popBackStack()
}
SheetClickable(
icon = { modifier ->
Icon(
imageVector = Icons.Default.Delete,
contentDescription = null,
modifier = modifier
)
},
label = { style ->
Text(
text = stringResource(id = R.string.message_context_sheet_actions_delete),
style = style
)
},
) {
Toast.makeText(
context,
context.getString(R.string.comingsoon_toast),
Toast.LENGTH_SHORT
).show()
navController.popBackStack()
}
SheetClickable( SheetClickable(
icon = { modifier -> icon = { modifier ->
Icon( Icon(
painter = painterResource(id = R.drawable.ic_flag_24dp), painter = painterResource(id = R.drawable.ic_eye_off_24dp),
contentDescription = null, contentDescription = null,
modifier = modifier modifier = modifier
) )
}, },
label = { style -> label = { style ->
Text( Text(
text = stringResource(id = R.string.message_context_sheet_actions_report), text = stringResource(id = R.string.message_context_sheet_actions_mark_unread),
style = style style = style
) )
}, },
) { ) {
navController.navigate("report/message/${message.id}") Toast.makeText(
} context,
context.getString(R.string.comingsoon_toast),
Toast.LENGTH_SHORT
).show()
navController.popBackStack()
}
SheetClickable(
icon = { modifier ->
Icon(
imageVector = Icons.Default.Edit,
contentDescription = null,
modifier = modifier
)
},
label = { style ->
Text(
text = stringResource(id = R.string.message_context_sheet_actions_edit),
style = style
)
},
) {
Toast.makeText(
context,
context.getString(R.string.comingsoon_toast),
Toast.LENGTH_SHORT
).show()
navController.popBackStack()
}
SheetClickable(
icon = { modifier ->
Icon(
imageVector = Icons.Default.Delete,
contentDescription = null,
modifier = modifier
)
},
label = { style ->
Text(
text = stringResource(id = R.string.message_context_sheet_actions_delete),
style = style
)
},
) {
Toast.makeText(
context,
context.getString(R.string.comingsoon_toast),
Toast.LENGTH_SHORT
).show()
navController.popBackStack()
}
SheetClickable(
icon = { modifier ->
Icon(
painter = painterResource(id = R.drawable.ic_flag_24dp),
contentDescription = null,
modifier = modifier
)
},
label = { style ->
Text(
text = stringResource(id = R.string.message_context_sheet_actions_report),
style = style
)
},
) {
navController.navigate("report/message/${message.id}")
} }
} }
} }

View File

@ -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="M23.5,17L18.5,22L15,18.5L16.5,17L18.5,19L22,15.5L23.5,17M12,9A3,3 0 0,1 15,12A3,3 0 0,1 12,15A3,3 0 0,1 9,12A3,3 0 0,1 12,9M12,17C12.5,17 12.97,16.93 13.42,16.79C13.15,17.5 13,18.22 13,19V19.45L12,19.5C7,19.5 2.73,16.39 1,12C2.73,7.61 7,4.5 12,4.5C17,4.5 21.27,7.61 23,12C22.75,12.64 22.44,13.26 22.08,13.85C21.18,13.31 20.12,13 19,13C18.22,13 17.5,13.15 16.79,13.42C16.93,12.97 17,12.5 17,12A5,5 0 0,0 12,7A5,5 0 0,0 7,12A5,5 0 0,0 12,17Z" />
</vector>

View File

@ -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="M11.83,9L15,12.16C15,12.11 15,12.05 15,12A3,3 0 0,0 12,9C11.94,9 11.89,9 11.83,9M7.53,9.8L9.08,11.35C9.03,11.56 9,11.77 9,12A3,3 0 0,0 12,15C12.22,15 12.44,14.97 12.65,14.92L14.2,16.47C13.53,16.8 12.79,17 12,17A5,5 0 0,1 7,12C7,11.21 7.2,10.47 7.53,9.8M2,4.27L4.28,6.55L4.73,7C3.08,8.3 1.78,10 1,12C2.73,16.39 7,19.5 12,19.5C13.55,19.5 15.03,19.2 16.38,18.66L16.81,19.08L19.73,22L21,20.73L3.27,3M12,7A5,5 0 0,1 17,12C17,12.64 16.87,13.26 16.64,13.82L19.57,16.75C21.07,15.5 22.27,13.86 23,12C21.27,7.61 17,4.5 12,4.5C10.6,4.5 9.26,4.75 8,5.2L10.17,7.35C10.74,7.13 11.35,7 12,7Z" />
</vector>

View File

@ -140,6 +140,15 @@
<string name="message_context_sheet_actions_copy_link_copied">Copied message link to clipboard</string> <string name="message_context_sheet_actions_copy_link_copied">Copied message link to clipboard</string>
<string name="message_context_sheet_actions_react">React</string> <string name="message_context_sheet_actions_react">React</string>
<string name="message_context_sheet_actions_report">Report</string> <string name="message_context_sheet_actions_report">Report</string>
<string name="message_context_sheet_actions_mark_unread">Mark as unread</string>
<string name="channel_context_sheet_actions_copy_id">Copy ID</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="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_mark_read">Mark as read</string>
<string name="report">Report</string> <string name="report">Report</string>
<string name="report_cancel">Cancel</string> <string name="report_cancel">Cancel</string>