Skip to content

Make canSendMessage actually gate ChatInput's FAB click#5

Merged
RomanLeshc merged 1 commit into
mainfrom
tf/chatinput-quality
May 11, 2026
Merged

Make canSendMessage actually gate ChatInput's FAB click#5
RomanLeshc merged 1 commit into
mainfrom
tf/chatinput-quality

Conversation

@phwizard
Copy link
Copy Markdown
Member

Summary

`ChatInput` accepts a `canSendMessage: Boolean = true` parameter. The contract the parameter name suggests is "set to false to block sends right now."

Today the flag only changes the FAB's container colour (dim `surfaceVariant` vs `primary`). The `onClick` handler dispatches `onSendMessage` / `onSendMedia` regardless. A host setting `canSendMessage = false` sees the dimmed pill, the user taps it, and the message goes out anyway — the exact opposite of what the contract suggests.

Fix

Add an early return at the top of the FAB's `onClick`:

```kotlin
onClick = onClick@{
if (!canSendMessage) return@onClick
// ...existing send logic...
}
```

The disabled-state `IconButton` (shown when the field is empty) was already correctly gated via Compose's `enabled = false` — this only affects the active FAB shown when the field has text or a selected file.

Behavior change vs no change

  • No change for hosts that ignored `canSendMessage` (default `true`).
  • Behavior change for hosts that set `canSendMessage = false`:
    • Before: dim styling, but click still fires send callbacks.
    • After: dim styling, click is a no-op.

Likely-affected callers: any host using `canSendMessage` to mean "block sends" — e.g. while a moderation/compliance hook evaluates, while reconnecting, while a rate-limit cool-down is active. They should benefit from this fix because the parameter now matches its contract. If anyone is relying on the old "always-fires" behavior to do something other than block sends, this change breaks that — happy to discuss alternative solutions in review.

Why this came up

Surfaced while threading semantic `testTag`s through `ChatInput` (PR #4) — needed to understand the click contract to tag the active vs disabled paths correctly. Flagged as one of two findings (the other was about `isDeleted` rendering, which I was wrong about — the tombstone is already implemented).

Test plan

  • Existing `ethora-component` unit tests still pass.
  • On the sample app, set `canSendMessage = false` in `ChatConfig` (or wherever the host wires it) and confirm: dim FAB renders, tapping does NOT add a bubble, no XMPP message goes out.
  • Set `canSendMessage = true` and confirm normal send round-trip still works.
  • After PR #3 (Compose UI tests) is rebased on this, the `emptyInputShowsSendIconWithoutFiringCallback` test gains a sibling assertion for `canSendMessage = false` + non-empty field.

ChatInput accepts a canSendMessage: Boolean = true parameter. The
contract from the host's perspective is "set to false to block
sends right now" — useful while a moderation hook is evaluating,
during reconnect, while a rate-limit cool-down is active, etc.

Today the flag only changes the FAB's container colour (dim
surface variant vs primary). The onClick handler dispatches
onSendMessage / onSendMedia regardless. So a host setting
canSendMessage = false sees the dimmed pill, taps it, and the
message goes out anyway — exact opposite of the contract the
parameter name suggests.

Add an early return at the top of the FAB's onClick:

    onClick = onClick@{
        if (!canSendMessage) return@onClick
        ...existing send logic...
    }

The disabled-state IconButton (shown when the field is empty)
was already correctly gated via Compose's `enabled = false` —
this fix only affects the active FAB shown when the field has
text or a selected file.

No host API change. Hosts that ignored canSendMessage (left it
default true) see no difference. Hosts that set it false now get
the behaviour the parameter advertises.

Companion ChatInput Compose UI test is on
ethora-sdk-android/tf/test-scaffold (PR #3); will add an explicit
assertion that canSendMessage = false suppresses the callback in
a follow-up commit on that branch.
@phwizard phwizard force-pushed the tf/chatinput-quality branch from e92348a to 568017c Compare May 11, 2026 10:07
@RomanLeshc RomanLeshc merged commit b920c58 into main May 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants