Merge pull request #847 from heyaim/hide-command-suggestions-after-send

Hide the command and mention popups after a message is sent
This commit is contained in:
callebtc 2026-08-02 00:17:28 +02:00 committed by GitHub
commit b8c7470ace
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 50 additions and 2 deletions

View File

@ -401,6 +401,9 @@ fun ChatScreen(viewModel: ChatViewModel) {
if (accepted) {
messageText = TextFieldValue("")
viewModel.setConversationDraft(selectedPrivatePeer, "")
// Clearing the field in code does not run onMessageTextChange,
// so the popups have to be dismissed here.
viewModel.clearSuggestions()
forceScrollToBottom = !forceScrollToBottom
}
}

View File

@ -1360,7 +1360,11 @@ class ChatViewModel(
fun updateCommandSuggestions(input: String) {
commandProcessor.updateCommandSuggestions(input)
}
fun clearSuggestions() {
commandProcessor.clearSuggestions()
}
fun selectCommandSuggestion(suggestion: CommandSuggestion): String {
return commandProcessor.selectCommandSuggestion(suggestion)
}

View File

@ -465,6 +465,18 @@ class CommandProcessor(
messageManager.addMessage(systemMessage)
}
/**
* Dismiss the command and mention popups. The composer clears its field in code
* after a send, which does not run onValueChange, so the popups need an explicit
* clear.
*/
fun clearSuggestions() {
state.setShowCommandSuggestions(false)
state.setCommandSuggestions(emptyList())
state.setShowMentionSuggestions(false)
state.setMentionSuggestions(emptyList())
}
// MARK: - Command Autocomplete
fun updateCommandSuggestions(input: String) {

View File

@ -1849,7 +1849,9 @@ fun PrivateChatSheet(
onMessageTextChange = { newText ->
messageText = newText
viewModel.setConversationDraft(peerID, newText.text)
viewModel.updateMentionSuggestions(newText.text)
// Do not update the shared suggestion state here: this sheet
// renders its own popups as hidden, so an update only leaves
// a stale popup behind for the main composer.
},
onSend = {
if (messageText.text.trim().isNotEmpty()) {

View File

@ -8,6 +8,7 @@ import com.bitchat.android.geohash.GeohashChannelLevel
import com.bitchat.android.mesh.MeshService
import com.bitchat.android.model.BitchatMessage
import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.assertFalse
import junit.framework.TestCase.assertTrue
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
@ -161,4 +162,30 @@ class CommandProcessorTest() {
)
assertEquals(0, chatState.getMessagesValue().size)
}
@Test
fun `clearSuggestions hides the command suggestion popup`() {
// Typing "/" opens the command popup.
commandProcessor.updateCommandSuggestions("/")
assertTrue(chatState.getShowCommandSuggestionsValue())
// The send handlers call this after clearing the field in code, which does
// not run the text-change handler that normally hides the popup.
commandProcessor.clearSuggestions()
assertFalse(chatState.getShowCommandSuggestionsValue())
assertTrue(chatState.getCommandSuggestionsValue().isEmpty())
}
@Test
fun `clearSuggestions hides the mention suggestion popup`() {
whenever(meshService.getPeerNicknames()).thenReturn(mapOf("peer-1" to "alice"))
// Typing "@a" opens the mention popup.
commandProcessor.updateMentionSuggestions("@a", meshService, viewModel = null)
assertTrue(chatState.getShowMentionSuggestionsValue())
commandProcessor.clearSuggestions()
assertFalse(chatState.getShowMentionSuggestionsValue())
assertTrue(chatState.getMentionSuggestionsValue().isEmpty())
}
}