mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 10:25:19 +00:00
Add CommandSuggestionsBox quick access (#146)
* Add CommandSuggestionsBox quick access * Remove unnecessary evaluation * Use a FilledTonalIconButton for the CommandSuggestionsBox quick access button * fix import * quick command instead of send * simplify --------- Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
This commit is contained in:
co-authored by
callebtc
parent
1d1a91108e
commit
b418aa3899
@@ -15,19 +15,23 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextRange
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.OffsetMapping
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.input.OffsetMapping
|
||||
import androidx.compose.ui.text.input.TransformedText
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.bitchat.android.R
|
||||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.text.withStyle
|
||||
|
||||
@@ -45,13 +49,13 @@ class SlashCommandVisualTransformation : VisualTransformation {
|
||||
val slashCommandRegex = Regex("(/\\w+)(?=\\s|$)")
|
||||
val annotatedString = buildAnnotatedString {
|
||||
var lastIndex = 0
|
||||
|
||||
|
||||
slashCommandRegex.findAll(text.text).forEach { match ->
|
||||
// Add text before the match
|
||||
if (match.range.first > lastIndex) {
|
||||
append(text.text.substring(lastIndex, match.range.first))
|
||||
}
|
||||
|
||||
|
||||
// Add the styled slash command
|
||||
withStyle(
|
||||
style = SpanStyle(
|
||||
@@ -63,16 +67,16 @@ class SlashCommandVisualTransformation : VisualTransformation {
|
||||
) {
|
||||
append(match.value)
|
||||
}
|
||||
|
||||
|
||||
lastIndex = match.range.last + 1
|
||||
}
|
||||
|
||||
|
||||
// Add remaining text
|
||||
if (lastIndex < text.text.length) {
|
||||
append(text.text.substring(lastIndex))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return TransformedText(
|
||||
text = annotatedString,
|
||||
offsetMapping = OffsetMapping.Identity
|
||||
@@ -162,7 +166,8 @@ fun MessageInput(
|
||||
|
||||
Row(
|
||||
modifier = modifier.padding(horizontal = 12.dp, vertical = 8.dp), // Reduced padding
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
// Text input with placeholder
|
||||
Box(
|
||||
@@ -205,48 +210,64 @@ fun MessageInput(
|
||||
|
||||
Spacer(modifier = Modifier.width(8.dp)) // Reduced spacing
|
||||
|
||||
// Send button with enabled/disabled state
|
||||
IconButton(
|
||||
onClick = { if (hasText) onSend() }, // Only execute if there's text
|
||||
enabled = hasText, // Enable only when there's text
|
||||
modifier = Modifier.size(32.dp)
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(30.dp)
|
||||
.background(
|
||||
color = if (!hasText) {
|
||||
// Disabled state - muted grey
|
||||
colorScheme.onSurface.copy(alpha = 0.3f)
|
||||
} else if (selectedPrivatePeer != null || currentChannel != null) {
|
||||
// Orange for both private messages and channels when enabled
|
||||
Color(0xFFFF9500).copy(alpha = 0.75f)
|
||||
} else if (colorScheme.background == Color.Black) {
|
||||
Color(0xFF00FF00).copy(alpha = 0.75f) // Bright green for dark theme
|
||||
} else {
|
||||
Color(0xFF008000).copy(alpha = 0.75f) // Dark green for light theme
|
||||
},
|
||||
shape = CircleShape
|
||||
),
|
||||
contentAlignment = Alignment.Center
|
||||
// Command quick access button
|
||||
if (value.text.isEmpty()) {
|
||||
FilledTonalIconButton(
|
||||
onClick = {
|
||||
onValueChange(TextFieldValue(text = "/", selection = TextRange("/".length)))
|
||||
},
|
||||
modifier = Modifier.size(32.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.ArrowUpward,
|
||||
contentDescription = "Send message",
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = if (!hasText) {
|
||||
// Disabled state - muted grey icon
|
||||
colorScheme.onSurface.copy(alpha = 0.5f)
|
||||
} else if (selectedPrivatePeer != null || currentChannel != null) {
|
||||
// Black arrow on orange for both private and channel modes
|
||||
Color.Black
|
||||
} else if (colorScheme.background == Color.Black) {
|
||||
Color.Black // Black arrow on bright green in dark theme
|
||||
} else {
|
||||
Color.White // White arrow on dark green in light theme
|
||||
}
|
||||
Text(
|
||||
text = "/",
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// Send button with enabled/disabled state
|
||||
IconButton(
|
||||
onClick = { if (hasText) onSend() }, // Only execute if there's text
|
||||
enabled = hasText, // Enable only when there's text
|
||||
modifier = Modifier.size(32.dp)
|
||||
) {
|
||||
// Update send button to match input field colors
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(30.dp)
|
||||
.background(
|
||||
color = if (!hasText) {
|
||||
// Disabled state - muted grey
|
||||
colorScheme.onSurface.copy(alpha = 0.3f)
|
||||
} else if (selectedPrivatePeer != null || currentChannel != null) {
|
||||
// Orange for both private messages and channels when enabled
|
||||
Color(0xFFFF9500).copy(alpha = 0.75f)
|
||||
} else if (colorScheme.background == Color.Black) {
|
||||
Color(0xFF00FF00).copy(alpha = 0.75f) // Bright green for dark theme
|
||||
} else {
|
||||
Color(0xFF008000).copy(alpha = 0.75f) // Dark green for light theme
|
||||
},
|
||||
shape = CircleShape
|
||||
),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.ArrowUpward,
|
||||
contentDescription = stringResource(id = R.string.send_message),
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = if (!hasText) {
|
||||
// Disabled state - muted grey icon
|
||||
colorScheme.onSurface.copy(alpha = 0.5f)
|
||||
} else if (selectedPrivatePeer != null || currentChannel != null) {
|
||||
// Black arrow on orange for both private and channel modes
|
||||
Color.Black
|
||||
} else if (colorScheme.background == Color.Black) {
|
||||
Color.Black // Black arrow on bright green in dark theme
|
||||
} else {
|
||||
Color.White // White arrow on dark green in light theme
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -258,9 +279,10 @@ fun CommandSuggestionsBox(
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.verticalScroll(rememberScrollState())
|
||||
.background(colorScheme.surface)
|
||||
.border(1.dp, colorScheme.outline.copy(alpha = 0.3f), RoundedCornerShape(4.dp))
|
||||
.padding(vertical = 8.dp)
|
||||
@@ -280,14 +302,15 @@ fun CommandSuggestionItem(
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { onClick() }
|
||||
.padding(horizontal = 12.dp, vertical = 3.dp)
|
||||
.background(Color.Gray.copy(alpha = 0.1f)),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
// Show all aliases together
|
||||
val allCommands = if (suggestion.aliases.isNotEmpty()) {
|
||||
@@ -295,7 +318,7 @@ fun CommandSuggestionItem(
|
||||
} else {
|
||||
listOf(suggestion.command)
|
||||
}
|
||||
|
||||
|
||||
Text(
|
||||
text = allCommands.joinToString(", "),
|
||||
style = MaterialTheme.typography.bodySmall.copy(
|
||||
@@ -305,10 +328,9 @@ fun CommandSuggestionItem(
|
||||
color = colorScheme.primary,
|
||||
fontSize = 11.sp
|
||||
)
|
||||
|
||||
|
||||
// Show syntax if any
|
||||
suggestion.syntax?.let { syntax ->
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(
|
||||
text = syntax,
|
||||
style = MaterialTheme.typography.bodySmall.copy(
|
||||
@@ -318,9 +340,7 @@ fun CommandSuggestionItem(
|
||||
fontSize = 10.sp
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
|
||||
// Show description
|
||||
Text(
|
||||
text = suggestion.description,
|
||||
|
||||
Reference in New Issue
Block a user