feat: only show appropriate buttons in channel info sheet

Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
Infi 2023-11-11 03:46:18 +01:00
parent f0461b3bfe
commit 551be72a94
5 changed files with 118 additions and 94 deletions

View File

@ -67,6 +67,10 @@ fun Long.hasPermission(permission: PermissionBit): Boolean {
return this and permission.value == permission.value return this and permission.value == permission.value
} }
infix fun Long?.has(permission: PermissionBit): Boolean {
return this != null && this.hasPermission(permission)
}
object BitDefaults { object BitDefaults {
val AllowedInTimeout = val AllowedInTimeout =
PermissionBit.ViewChannel + PermissionBit.ReadMessageHistory PermissionBit.ViewChannel + PermissionBit.ReadMessageHistory
@ -76,30 +80,30 @@ object BitDefaults {
val Default = val Default =
ViewOnly + ViewOnly +
PermissionBit.SendMessage + PermissionBit.SendMessage +
PermissionBit.InviteOthers + PermissionBit.InviteOthers +
PermissionBit.SendEmbeds + PermissionBit.SendEmbeds +
PermissionBit.UploadFiles + PermissionBit.UploadFiles +
PermissionBit.Connect + PermissionBit.Connect +
PermissionBit.Speak PermissionBit.Speak
val SavedMessages = val SavedMessages =
PermissionBit.GrantAllSafe.value PermissionBit.GrantAllSafe.value
val DirectMessages = val DirectMessages =
Default + Default +
PermissionBit.ManageChannel + PermissionBit.ManageChannel +
PermissionBit.React PermissionBit.React
val Server = val Server =
Default + Default +
PermissionBit.React + PermissionBit.React +
PermissionBit.ChangeNickname + PermissionBit.ChangeNickname +
PermissionBit.ChangeAvatar PermissionBit.ChangeAvatar
val Webhook = val Webhook =
PermissionBit.SendMessage + PermissionBit.SendMessage +
PermissionBit.SendEmbeds + PermissionBit.SendEmbeds +
PermissionBit.Masquerade + PermissionBit.Masquerade +
PermissionBit.React PermissionBit.React
} }

View File

@ -8,12 +8,12 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
@ -21,14 +21,16 @@ import androidx.compose.ui.unit.dp
import chat.revolt.api.REVOLT_FILES import chat.revolt.api.REVOLT_FILES
import chat.revolt.api.schemas.AutumnResource import chat.revolt.api.schemas.AutumnResource
import chat.revolt.api.schemas.ChannelType import chat.revolt.api.schemas.ChannelType
import chat.revolt.api.schemas.User
import chat.revolt.components.generic.RemoteImage import chat.revolt.components.generic.RemoteImage
import chat.revolt.components.generic.UserAvatar
@Composable @Composable
fun ChannelSheetHeader( fun ChannelSheetHeader(
channelName: String, channelName: String,
channelIcon: AutumnResource? = null, channelIcon: AutumnResource? = null,
channelType: ChannelType, channelType: ChannelType,
channelId: String dmPartner: User? = null
) { ) {
Row( Row(
modifier = Modifier.padding(vertical = 4.dp), modifier = Modifier.padding(vertical = 4.dp),
@ -39,8 +41,7 @@ fun ChannelSheetHeader(
.size(48.dp) .size(48.dp)
.clip(CircleShape) .clip(CircleShape)
.background( .background(
getIconBackColour(channelId) MaterialTheme.colorScheme.primary.copy(alpha = 0.2f)
.copy(alpha = if (channelIcon != null) 0.6f else 0.2f)
), ),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
@ -54,57 +55,28 @@ fun ChannelSheetHeader(
modifier = Modifier modifier = Modifier
.size(24.dp) .size(24.dp)
) )
} else if (dmPartner != null) {
UserAvatar(
username = User.resolveDefaultName(dmPartner),
userId = dmPartner.id ?: "",
avatar = dmPartner.avatar,
presence = null,
size = 48.dp,
modifier = Modifier
.size(48.dp)
)
} else { } else {
ChannelIcon(channelType = channelType) ChannelIcon(channelType = channelType)
} }
} }
Spacer(modifier = Modifier.width(8.dp)) Spacer(modifier = Modifier.width(12.dp))
Text( Text(
text = channelName, text = channelName,
fontWeight = FontWeight.Medium, fontWeight = FontWeight.SemiBold,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis
) )
} }
} }
fun getIconBackColour(channelId: String): Color {
// The ULID alphabet does not include I, L, O, or U.
return when (channelId.uppercase().last()) {
'0' -> Color(0xFFE91E63)
'1' -> Color(0xFF9C27B0)
'2' -> Color(0xFF673AB7)
'3' -> Color(0xFF3F51B5)
'4' -> Color(0xFF2196F3)
'5' -> Color(0xFF03A9F4)
'6' -> Color(0xFF00BCD4)
'7' -> Color(0xFF009688)
'8' -> Color(0xFF4CAF50)
'9' -> Color(0xFF8BC34A)
'A' -> Color(0xFFCDDC39)
'B' -> Color(0xFFFFEB3B)
'C' -> Color(0xFFFFC107)
'D' -> Color(0xFFFF9800)
'E' -> Color(0xFFFF5722)
'F' -> Color(0xFF795548)
'G' -> Color(0xFF9E9E9E)
'H' -> Color(0xFF607D8B)
'J' -> Color(0xFF9FA8DA)
'K' -> Color(0xFF90CAF9)
'M' -> Color(0xFF81D4FA)
'N' -> Color(0xFF80DEEA)
'P' -> Color(0xFF80CBC4)
'Q' -> Color(0xFFA5D6A7)
'R' -> Color(0xFFC5E1A5)
'S' -> Color(0xFFE6EE9C)
'T' -> Color(0xFFFFF59D)
'V' -> Color(0xFFFFE082)
'W' -> Color(0xFFFFCC80)
'X' -> Color(0xFFFFAB91)
'Y' -> Color(0xFFFF8A65)
'Z' -> Color(0xFFFF8A80)
else -> Color(0xFFFFFFFF)
}
}

View File

@ -463,8 +463,8 @@ class ChannelScreenViewModel : ViewModel() {
} }
val newContent = currentContent.substring(0, currentSelection.start) + val newContent = currentContent.substring(0, currentSelection.start) +
content + content +
currentContent.substring(currentSelection.end) currentContent.substring(currentSelection.end)
pendingMessageContent = newContent pendingMessageContent = newContent
textSelection = TextRange(currentSelection.start + content.length) textSelection = TextRange(currentSelection.start + content.length)

View File

@ -30,6 +30,10 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import chat.revolt.R import chat.revolt.R
import chat.revolt.api.RevoltAPI import chat.revolt.api.RevoltAPI
import chat.revolt.api.internals.ChannelUtils
import chat.revolt.api.internals.PermissionBit
import chat.revolt.api.internals.Roles
import chat.revolt.api.internals.has
import chat.revolt.api.schemas.ChannelType import chat.revolt.api.schemas.ChannelType
import chat.revolt.components.generic.SheetClickable import chat.revolt.components.generic.SheetClickable
import chat.revolt.components.screens.chat.ChannelSheetHeader import chat.revolt.components.screens.chat.ChannelSheetHeader
@ -72,32 +76,43 @@ fun ChannelInfoSheet(channelId: String) {
.padding(horizontal = 16.dp) .padding(horizontal = 16.dp)
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())
) { ) {
val isDM = ChannelUtils.resolveDMPartner(channel) != null
val partner = ChannelUtils
.resolveDMPartner(channel)
?.let {
RevoltAPI.userCache[it]
}
ChannelSheetHeader( ChannelSheetHeader(
channelName = channel.name ?: stringResource(id = R.string.unknown), channelName = channel.name
?: ChannelUtils.resolveDMName(channel)
?: stringResource(id = R.string.unknown),
channelIcon = channel.icon, channelIcon = channel.icon,
channelType = channel.channelType ?: ChannelType.TextChannel, channelType = channel.channelType ?: ChannelType.TextChannel,
channelId = channel.id ?: "9" dmPartner = partner
) )
Spacer(modifier = Modifier.height(8.dp)) if (!isDM) {
Spacer(modifier = Modifier.height(12.dp))
Text( Text(
text = stringResource(id = R.string.channel_info_sheet_description), text = stringResource(id = R.string.channel_info_sheet_description),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
modifier = Modifier.padding(bottom = 10.dp) modifier = Modifier.padding(bottom = 10.dp)
) )
Text( Text(
text = if (channel.description.isNullOrBlank()) { text = if (channel.description.isNullOrBlank()) {
stringResource( stringResource(
id = R.string.channel_info_sheet_description_empty id = R.string.channel_info_sheet_description_empty
) )
} else { } else {
channel.description channel.description
}, },
modifier = Modifier.padding(bottom = 10.dp) modifier = Modifier.padding(bottom = 10.dp)
) )
}
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(12.dp))
Text( Text(
text = stringResource(id = R.string.channel_info_sheet_options), text = stringResource(id = R.string.channel_info_sheet_options),
@ -129,21 +144,53 @@ fun ChannelInfoSheet(channelId: String) {
else -> {} else -> {}
} }
SheetClickable( if (
icon = { modifier -> Roles.permissionFor(
Icon( channel,
imageVector = Icons.Default.Add, RevoltAPI.userCache[RevoltAPI.selfId]
contentDescription = null, ) has PermissionBit.InviteOthers
modifier = modifier
)
},
label = { style ->
Text(
text = stringResource(id = R.string.channel_info_sheet_options_invite),
style = style
)
}
) { ) {
when (channel.channelType) {
ChannelType.TextChannel, ChannelType.VoiceChannel -> {
SheetClickable(
icon = { modifier ->
Icon(
imageVector = Icons.Default.Add,
contentDescription = null,
modifier = modifier
)
},
label = { style ->
Text(
text = stringResource(id = R.string.channel_info_sheet_options_invite),
style = style
)
}
) {
}
}
ChannelType.Group -> {
SheetClickable(
icon = { modifier ->
Icon(
imageVector = Icons.Default.Add,
contentDescription = null,
modifier = modifier
)
},
label = { style ->
Text(
text = stringResource(id = R.string.channel_info_sheet_options_add),
style = style
)
}
) {
}
}
else -> {}
}
} }
SheetClickable( SheetClickable(

View File

@ -233,6 +233,7 @@
<string name="channel_info_sheet_options">Options</string> <string name="channel_info_sheet_options">Options</string>
<string name="channel_info_sheet_options_members">Members</string> <string name="channel_info_sheet_options_members">Members</string>
<string name="channel_info_sheet_options_invite">Invite</string> <string name="channel_info_sheet_options_invite">Invite</string>
<string name="channel_info_sheet_options_add">Add members</string>
<string name="channel_info_sheet_options_notifications_manage">Manage notifications</string> <string name="channel_info_sheet_options_notifications_manage">Manage notifications</string>
<string name="message_context_sheet_actions_copy">Copy</string> <string name="message_context_sheet_actions_copy">Copy</string>