diff --git a/app/src/main/java/chat/revolt/api/internals/Permissions.kt b/app/src/main/java/chat/revolt/api/internals/Permissions.kt
index 43c4eb10..a7e0cc7b 100644
--- a/app/src/main/java/chat/revolt/api/internals/Permissions.kt
+++ b/app/src/main/java/chat/revolt/api/internals/Permissions.kt
@@ -67,6 +67,10 @@ fun Long.hasPermission(permission: PermissionBit): Boolean {
return this and permission.value == permission.value
}
+infix fun Long?.has(permission: PermissionBit): Boolean {
+ return this != null && this.hasPermission(permission)
+}
+
object BitDefaults {
val AllowedInTimeout =
PermissionBit.ViewChannel + PermissionBit.ReadMessageHistory
@@ -76,30 +80,30 @@ object BitDefaults {
val Default =
ViewOnly +
- PermissionBit.SendMessage +
- PermissionBit.InviteOthers +
- PermissionBit.SendEmbeds +
- PermissionBit.UploadFiles +
- PermissionBit.Connect +
- PermissionBit.Speak
+ PermissionBit.SendMessage +
+ PermissionBit.InviteOthers +
+ PermissionBit.SendEmbeds +
+ PermissionBit.UploadFiles +
+ PermissionBit.Connect +
+ PermissionBit.Speak
val SavedMessages =
PermissionBit.GrantAllSafe.value
val DirectMessages =
Default +
- PermissionBit.ManageChannel +
- PermissionBit.React
+ PermissionBit.ManageChannel +
+ PermissionBit.React
val Server =
Default +
- PermissionBit.React +
- PermissionBit.ChangeNickname +
- PermissionBit.ChangeAvatar
+ PermissionBit.React +
+ PermissionBit.ChangeNickname +
+ PermissionBit.ChangeAvatar
val Webhook =
PermissionBit.SendMessage +
- PermissionBit.SendEmbeds +
- PermissionBit.Masquerade +
- PermissionBit.React
+ PermissionBit.SendEmbeds +
+ PermissionBit.Masquerade +
+ PermissionBit.React
}
diff --git a/app/src/main/java/chat/revolt/components/screens/chat/ChannelSheetHeader.kt b/app/src/main/java/chat/revolt/components/screens/chat/ChannelSheetHeader.kt
index 15b462ec..95caf1a7 100644
--- a/app/src/main/java/chat/revolt/components/screens/chat/ChannelSheetHeader.kt
+++ b/app/src/main/java/chat/revolt/components/screens/chat/ChannelSheetHeader.kt
@@ -8,12 +8,12 @@ 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.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
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.layout.ContentScale
import androidx.compose.ui.text.font.FontWeight
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.schemas.AutumnResource
import chat.revolt.api.schemas.ChannelType
+import chat.revolt.api.schemas.User
import chat.revolt.components.generic.RemoteImage
+import chat.revolt.components.generic.UserAvatar
@Composable
fun ChannelSheetHeader(
channelName: String,
channelIcon: AutumnResource? = null,
channelType: ChannelType,
- channelId: String
+ dmPartner: User? = null
) {
Row(
modifier = Modifier.padding(vertical = 4.dp),
@@ -39,8 +41,7 @@ fun ChannelSheetHeader(
.size(48.dp)
.clip(CircleShape)
.background(
- getIconBackColour(channelId)
- .copy(alpha = if (channelIcon != null) 0.6f else 0.2f)
+ MaterialTheme.colorScheme.primary.copy(alpha = 0.2f)
),
contentAlignment = Alignment.Center
) {
@@ -54,57 +55,28 @@ fun ChannelSheetHeader(
modifier = Modifier
.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 {
ChannelIcon(channelType = channelType)
}
}
- Spacer(modifier = Modifier.width(8.dp))
+ Spacer(modifier = Modifier.width(12.dp))
Text(
text = channelName,
- fontWeight = FontWeight.Medium,
+ fontWeight = FontWeight.SemiBold,
maxLines = 1,
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)
- }
-}
diff --git a/app/src/main/java/chat/revolt/screens/chat/views/channel/ChannelScreenViewModel.kt b/app/src/main/java/chat/revolt/screens/chat/views/channel/ChannelScreenViewModel.kt
index 057de469..dc268813 100644
--- a/app/src/main/java/chat/revolt/screens/chat/views/channel/ChannelScreenViewModel.kt
+++ b/app/src/main/java/chat/revolt/screens/chat/views/channel/ChannelScreenViewModel.kt
@@ -463,8 +463,8 @@ class ChannelScreenViewModel : ViewModel() {
}
val newContent = currentContent.substring(0, currentSelection.start) +
- content +
- currentContent.substring(currentSelection.end)
+ content +
+ currentContent.substring(currentSelection.end)
pendingMessageContent = newContent
textSelection = TextRange(currentSelection.start + content.length)
diff --git a/app/src/main/java/chat/revolt/sheets/ChannelInfoSheet.kt b/app/src/main/java/chat/revolt/sheets/ChannelInfoSheet.kt
index f5d71ce6..c0036714 100644
--- a/app/src/main/java/chat/revolt/sheets/ChannelInfoSheet.kt
+++ b/app/src/main/java/chat/revolt/sheets/ChannelInfoSheet.kt
@@ -30,6 +30,10 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import chat.revolt.R
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.components.generic.SheetClickable
import chat.revolt.components.screens.chat.ChannelSheetHeader
@@ -72,32 +76,43 @@ fun ChannelInfoSheet(channelId: String) {
.padding(horizontal = 16.dp)
.verticalScroll(rememberScrollState())
) {
+ val isDM = ChannelUtils.resolveDMPartner(channel) != null
+ val partner = ChannelUtils
+ .resolveDMPartner(channel)
+ ?.let {
+ RevoltAPI.userCache[it]
+ }
+
ChannelSheetHeader(
- channelName = channel.name ?: stringResource(id = R.string.unknown),
+ channelName = channel.name
+ ?: ChannelUtils.resolveDMName(channel)
+ ?: stringResource(id = R.string.unknown),
channelIcon = channel.icon,
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 = stringResource(id = R.string.channel_info_sheet_description),
- style = MaterialTheme.typography.bodySmall,
- modifier = Modifier.padding(bottom = 10.dp)
- )
- Text(
- text = if (channel.description.isNullOrBlank()) {
- stringResource(
- id = R.string.channel_info_sheet_description_empty
- )
- } else {
- channel.description
- },
- modifier = Modifier.padding(bottom = 10.dp)
- )
+ Text(
+ text = stringResource(id = R.string.channel_info_sheet_description),
+ style = MaterialTheme.typography.bodySmall,
+ modifier = Modifier.padding(bottom = 10.dp)
+ )
+ Text(
+ text = if (channel.description.isNullOrBlank()) {
+ stringResource(
+ id = R.string.channel_info_sheet_description_empty
+ )
+ } else {
+ channel.description
+ },
+ modifier = Modifier.padding(bottom = 10.dp)
+ )
+ }
- Spacer(modifier = Modifier.height(8.dp))
+ Spacer(modifier = Modifier.height(12.dp))
Text(
text = stringResource(id = R.string.channel_info_sheet_options),
@@ -129,21 +144,53 @@ fun ChannelInfoSheet(channelId: String) {
else -> {}
}
- 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
- )
- }
+ if (
+ Roles.permissionFor(
+ channel,
+ RevoltAPI.userCache[RevoltAPI.selfId]
+ ) has PermissionBit.InviteOthers
) {
+ 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(
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 6fa15529..84ab1f4e 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -233,6 +233,7 @@
Options
Members
Invite
+ Add members
Manage notifications
Copy