The AnimatedContent gate on the composer's send button required inputFieldValue.text.isNotBlank() in addition to canSend, so attaching an image or file with an empty input hid the button entirely — the attachment could never be sent on its own. ChatInputPolicy.canSend already allowed attachment-only sends and ChatViewModel.sendMessage already accepted blank text with pending attachments, but the button never rendered to trigger it. Drop the stale text gate so the send affordance tracks canSend (non-empty text OR pending attachments, plus connection). The backend handles image-only turns natively: prompt.submit with empty text + queued images routes through build_native_content_parts, which wraps the pixels with an [Image attached at: ...] hint. Add a Compose UI regression test asserting the send button is displayed with a pending image attachment and an empty input. Co-authored-by: M57 <hy4ri@users.noreply.github.com>
This commit is contained in:
1 parent
69578e7818
commit
7540f7228a
2 files changed
+42
-2
No files matched your search
@@ -8,6 +8,7 @@ import androidx.compose.ui.test.performTextInput
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.MediumTest
|
||||
import com.m57.hermescontrol.data.model.Attachment
|
||||
import com.m57.hermescontrol.data.ws.ConnectionStatus
|
||||
import com.m57.hermescontrol.ui.common.ActionProgressController
|
||||
import io.mockk.every
|
||||
@@ -82,4 +83,40 @@ class ChatScreenTest {
|
||||
composeTestRule.onNodeWithTag("send_button").assertIsDisplayed()
|
||||
composeTestRule.onNodeWithTag("mic_button").assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun chatScreen_sendButtonShownForAttachmentWithEmptyInput() {
|
||||
// Issue #956: an attachment queued with an EMPTY input must still show
|
||||
// the send button — the old AnimatedContent gate required non-blank
|
||||
// text even though ChatInputPolicy.canSend already allowed
|
||||
// attachment-only sends.
|
||||
val uiState =
|
||||
ChatUiState(
|
||||
connectionStatus = ConnectionStatus.CONNECTED,
|
||||
pendingAttachments =
|
||||
listOf(
|
||||
Attachment(
|
||||
uri = "content://test/photo.jpg",
|
||||
name = "photo.jpg",
|
||||
mimeType = "image/jpeg",
|
||||
),
|
||||
),
|
||||
)
|
||||
val mockViewModel = mockk<ChatViewModel>(relaxed = true)
|
||||
every { mockViewModel.uiState } returns MutableStateFlow(uiState).asStateFlow()
|
||||
every { mockViewModel.streamingState } returns MutableStateFlow(StreamingState()).asStateFlow()
|
||||
every { mockViewModel.actionProgress } returns
|
||||
ActionProgressController(scope = CoroutineScope(Dispatchers.Main))
|
||||
|
||||
composeTestRule.setContent {
|
||||
ChatScreen(
|
||||
onOpenDrawer = {},
|
||||
sessionId = null,
|
||||
viewModel = mockViewModel,
|
||||
)
|
||||
}
|
||||
|
||||
composeTestRule.onNodeWithTag("chat_input").assertIsDisplayed()
|
||||
composeTestRule.onNodeWithTag("send_button").assertIsDisplayed()
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user