fix(chat): restrict @ bot mention suggestions strictly to group chat (#1052)
This commit is contained in:
@@ -815,7 +815,6 @@ fun ChatScreen(
|
|||||||
isAgentTyping = state.isAgentTyping,
|
isAgentTyping = state.isAgentTyping,
|
||||||
isConnected = state.isConnected,
|
isConnected = state.isConnected,
|
||||||
commandCatalog = state.commandCatalog,
|
commandCatalog = state.commandCatalog,
|
||||||
availableBots = state.availableBots,
|
|
||||||
slashUsageCounts = state.slashUsageCounts,
|
slashUsageCounts = state.slashUsageCounts,
|
||||||
pendingAttachments = state.pendingAttachments,
|
pendingAttachments = state.pendingAttachments,
|
||||||
onCameraTap = {
|
onCameraTap = {
|
||||||
|
|||||||
@@ -312,7 +312,6 @@ data class ChatUiState(
|
|||||||
val typingEffectDelayMs: Int = 30,
|
val typingEffectDelayMs: Int = 30,
|
||||||
// Commands catalog
|
// Commands catalog
|
||||||
val commandCatalog: CommandCatalog = CommandCatalog(),
|
val commandCatalog: CommandCatalog = CommandCatalog(),
|
||||||
val availableBots: List<ProfileInfo> = emptyList(),
|
|
||||||
// Per-command usage counts for the slash-autocomplete ranking (issue
|
// Per-command usage counts for the slash-autocomplete ranking (issue
|
||||||
// #865). Empty until the local store loads; commands without recorded
|
// #865). Empty until the local store loads; commands without recorded
|
||||||
// usage keep their catalog order.
|
// usage keep their catalog order.
|
||||||
@@ -2205,15 +2204,6 @@ class ChatViewModel(
|
|||||||
WsMethods.COMMANDS_CATALOG,
|
WsMethods.COMMANDS_CATALOG,
|
||||||
onSent = { id -> trackRequest(id, WsMethods.COMMANDS_CATALOG) },
|
onSent = { id -> trackRequest(id, WsMethods.COMMANDS_CATALOG) },
|
||||||
)
|
)
|
||||||
// Fetch available bot profiles for @ autocomplete
|
|
||||||
val profilesResult = safeApiCall { ApiClient.hermesApi.getProfiles() }
|
|
||||||
if (profilesResult is NetworkResult.Success) {
|
|
||||||
val profiles =
|
|
||||||
profilesResult.data.profiles.orEmpty().filter {
|
|
||||||
!AuthManager.isProfileHidden(it.name) && it.botMeta()?.hidden != true
|
|
||||||
}
|
|
||||||
_uiState.update { it.copy(availableBots = profiles) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,6 @@ fun ChatInputBar(
|
|||||||
commandCatalog: CommandCatalog,
|
commandCatalog: CommandCatalog,
|
||||||
slashUsageCounts: Map<String, Int> = emptyMap(),
|
slashUsageCounts: Map<String, Int> = emptyMap(),
|
||||||
pendingAttachments: List<Attachment> = emptyList(),
|
pendingAttachments: List<Attachment> = emptyList(),
|
||||||
availableBots: List<ProfileInfo> = emptyList(),
|
|
||||||
onCameraTap: () -> Unit = {},
|
onCameraTap: () -> Unit = {},
|
||||||
onImageTap: () -> Unit = {},
|
onImageTap: () -> Unit = {},
|
||||||
onFileTap: () -> Unit = {},
|
onFileTap: () -> Unit = {},
|
||||||
@@ -190,90 +189,6 @@ fun ChatInputBar(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bot mention @ suggestions
|
|
||||||
val mentionQuery =
|
|
||||||
remember(inputFieldValue.text, inputFieldValue.selection.end) {
|
|
||||||
ChatInputPolicy.extractMentionQuery(
|
|
||||||
inputFieldValue.text,
|
|
||||||
inputFieldValue.selection.end,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
androidx.compose.animation.AnimatedVisibility(
|
|
||||||
visible = mentionQuery != null && availableBots.isNotEmpty(),
|
|
||||||
enter = androidx.compose.animation.fadeIn() + androidx.compose.animation.expandVertically(),
|
|
||||||
exit = androidx.compose.animation.fadeOut() + androidx.compose.animation.shrinkVertically(),
|
|
||||||
) {
|
|
||||||
val filteredBots =
|
|
||||||
remember(mentionQuery, availableBots) {
|
|
||||||
if (mentionQuery == null) {
|
|
||||||
emptyList()
|
|
||||||
} else {
|
|
||||||
availableBots.filter { bot ->
|
|
||||||
bot.name.startsWith(mentionQuery, ignoreCase = true) ||
|
|
||||||
bot.effectiveTitle.contains(mentionQuery, ignoreCase = true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filteredBots.isNotEmpty()) {
|
|
||||||
Surface(
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(horizontal = 12.dp, vertical = 4.dp),
|
|
||||||
shape = RoundedCornerShape(12.dp),
|
|
||||||
color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f),
|
|
||||||
border =
|
|
||||||
BorderStroke(
|
|
||||||
1.dp,
|
|
||||||
MaterialTheme.colorScheme.outline.copy(alpha = 0.2f),
|
|
||||||
),
|
|
||||||
) {
|
|
||||||
LazyColumn(
|
|
||||||
modifier = Modifier.heightIn(max = 200.dp),
|
|
||||||
) {
|
|
||||||
items(filteredBots, key = { it.name }) { bot ->
|
|
||||||
Row(
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.clickable {
|
|
||||||
onInputChange(
|
|
||||||
ChatInputPolicy.applyMention(inputFieldValue, bot.name),
|
|
||||||
)
|
|
||||||
}.padding(horizontal = 12.dp, vertical = 8.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
) {
|
|
||||||
BotAvatar(
|
|
||||||
name = bot.name,
|
|
||||||
avatar = bot.botMeta()?.avatar,
|
|
||||||
size = 28.dp,
|
|
||||||
showPresence = false,
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.width(8.dp))
|
|
||||||
Column {
|
|
||||||
Text(
|
|
||||||
text = "@${bot.name}",
|
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = MaterialTheme.colorScheme.primary,
|
|
||||||
)
|
|
||||||
if (bot.effectiveTitle != bot.name) {
|
|
||||||
Text(
|
|
||||||
text = bot.effectiveTitle,
|
|
||||||
style = MaterialTheme.typography.labelSmall,
|
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attachment preview chips
|
// Attachment preview chips
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = pendingAttachments.isNotEmpty(),
|
visible = pendingAttachments.isNotEmpty(),
|
||||||
|
|||||||
Reference in New Issue
Block a user