feat(mobile): Support hardware keyboard shortcut to send messages in Native Chat
- Dominant language
- TypeScript
- Stars
- 71.3k
- Forks
- 4.7k
- Avg merge
- 14h 54m
- Merged PRs (30d)
- 520
Description
## Summary
On iPad, when using Orca Native Chat with a Bluetooth / hardware keyboard, pressing **Enter/Return** inserts a newline instead of sending the message.
As a result, hardware keyboard users must reach for the screen and tap the **Send** button every time they want to submit a message.
This is particularly inconvenient when Orca is being used remotely from an iPad with a keyboard.
## Current behavior
In the mobile Native Chat composer, the message field is implemented as a multiline React Native `TextInput`.
Relevant component:
`mobile/src/session/MobileNativeChatComposer.tsx`
The input is configured with `multiline`, while message submission is handled separately by `handleSend()` and the on-screen send button.
Conceptually, the current behavior is:
```text
Hardware Enter / Return
↓
↓
Insert newline
On-screen Send button
↓
handleSend()
↓
Send message
```
There does not appear to be a hardware-keyboard shortcut connected to `handleSend()`.
## Proposed behavior
For iPad / hardware keyboard users, add a keyboard shortcut for sending the current message.
### Preferred behavior
```text
Cmd + Enter → Send message
Enter → Insert newline
```
I prefer **Cmd+Enter** over changing plain Enter because it preserves the existing multiline behavior and should reduce the risk of interfering with IME composition, including Korean input.
### Alternative behavior
Another common chat convention would be:
```text
Enter → Send message
Shift + Enter → Insert newline
```
However, modifier handling and IME composition should be considered carefully on iOS/iPadOS.
## Why this matters
Orca's mobile experience works well with an iPad and external keyboard, but Native Chat currently requires touching the screen for every message submission.
Supporting a hardware-keyboard send shortcut would make Native Chat much more practical for:
- iPad + Bluetooth keyboard users
- Magic Keyboard users
- Remote development sessions
- Keyboard-focused workflows
## Implementation area
The likely implementation point is:
`mobile/src/session/MobileNativeChatComposer.tsx`
The composer currently contains a multiline `TextInput` similar to:
```tsx
{
setCursor(e.nativeEvent.selection.end)
setPendingSelection(null)
}}
placeholder={placeholder}
placeholderTextColor={colors.textMuted}
selectionColor={colors.accentBlue}
multiline
textAlignVertical="top"
/>
```
The existing send path should ideally be reused rather than introducing separate submission logic:
```text
Hardware shortcut
↓
handleSend()
↓
existing onSend() path
```
## Implementation considerations
The shortcut should avoid triggering while an IME composition is being confirmed. This is particularly important for Korean, Japanese, and Chinese input methods.
Suggested requirements:
1. Detect a hardware keyboard send shortcut in the Native Chat composer.
2. Call the existing `handleSend()` function rather than duplicating send logic.
3. Preserve normal multiline Enter behavior when the send modifier is not pressed.
4. Avoid sending while IME text composition is still active.
5. Keep the on-screen Send button behavior unchanged.
6. Verify behavior on iPadOS with a physical/Bluetooth keyboard.
## Suggested test cases
| Input | Expected result |
|---|---|
| Enter | Newline |
| Cmd+Enter | Send message |
| Cmd+Enter with empty input | Do not send |
| Cmd+Enter while sending/disabled | Respect existing disabled state |
| Korean IME composition + Enter | Confirm composition, do not accidentally send |
| Korean text + Cmd+Enter after composition | Send normally |
| On-screen Send button | Existing behavior remains unchanged |
## Acceptance criteria
- [ ] A message can be sent from an iPad hardware keyboard without touching the screen.
- [ ] `Cmd+Enter` sends the message.
- [ ] Plain `Enter` continues to insert a newline.
- [ ] Existing `handleSend()` / `onSend()` behavior is reused.
- [ ] Empty or disabled messages are not sent unexpectedly.
- [ ] Korean/IME composition does not cause accidental message submission.
- [ ] The existing on-screen Send button continues to work.
## Relevant links
- Orca repository: https://github.com/stablyai/orca
- Mobile Native Chat composer: https://github.com/stablyai/orca/blob/4cacd5552c8d161a25967e7df85101f138c42cb8/mobile/src/session/MobileNativeChatComposer.tsx
- Related mobile Native Chat PR: https://github.com/stablyai/orca/pull/13658
- Related Native Chat composer PR: https://github.com/stablyai/orca/pull/13754
Contributor guide
Assessment
This issue has not been assessed yet.