fix(dashboard): make ChatView mobile send fire on quick tap
The mobile send button used pointerdown + touchstart with preventDefault and a focus-preservation dance to keep the keyboard up while sending. That path silently failed on quick taps on iOS — only a long press registered. Switching to plain onClick (with touch-action: manipulation to skip the click delay) fires reliably on tap. The soft keyboard may dismiss on send now, which is a minor regression vs. the previous intent but vastly preferable to silent failure. QuickChat is unchanged because it already works on mobile. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
13
.changeset/chatview-mobile-send-quick-tap.md
Normal file
13
.changeset/chatview-mobile-send-quick-tap.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
"@runfusion/fusion": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Workaround long-standing bug where ChatView's mobile send button only
|
||||||
|
fired on a long press — quick taps silently did nothing. The previous
|
||||||
|
implementation used `pointerdown` + `touchstart` with `preventDefault`
|
||||||
|
and a focus-preservation dance so the keyboard would stay up while
|
||||||
|
sending; on iOS that path made quick taps fall through entirely. The
|
||||||
|
button now uses plain `onClick` with `touch-action: manipulation`. The
|
||||||
|
soft keyboard may dismiss on send, which is a minor UX regression
|
||||||
|
compared to silent failure. QuickChat is unchanged (it already works
|
||||||
|
on mobile).
|
||||||
@@ -1994,43 +1994,19 @@ export function ChatView({ projectId, addToast }: ChatViewProps) {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="chat-input-send"
|
className="chat-input-send"
|
||||||
onPointerDown={(event) => {
|
// Workaround: previous mobile flow used pointerdown +
|
||||||
if (typeof window === "undefined" || window.innerWidth > 768) return;
|
// touchstart with preventDefault and a focus-preservation
|
||||||
event.preventDefault();
|
// dance to keep the keyboard up while sending. On iOS that
|
||||||
if (event.pointerType && event.pointerType !== "mouse") {
|
// path made quick taps fail entirely (only long press
|
||||||
handledMobileSendRef.current = true;
|
// registered). Falling back to plain onClick reliably fires
|
||||||
markPreserveComposerFocus();
|
// the send on tap; the soft keyboard may dismiss but the
|
||||||
focusComposerInput();
|
// message goes through, which beats silent failure.
|
||||||
void handleSend();
|
|
||||||
window.setTimeout(() => {
|
|
||||||
preserveComposerFocusRef.current = false;
|
|
||||||
}, 1500);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onTouchStart={(event) => {
|
|
||||||
if (typeof window === "undefined" || window.innerWidth > 768) return;
|
|
||||||
event.preventDefault();
|
|
||||||
handledMobileSendRef.current = true;
|
|
||||||
markPreserveComposerFocus();
|
|
||||||
focusComposerInput();
|
|
||||||
void handleSend();
|
|
||||||
window.setTimeout(() => {
|
|
||||||
preserveComposerFocusRef.current = false;
|
|
||||||
}, 1500);
|
|
||||||
}}
|
|
||||||
onMouseDown={(event) => {
|
|
||||||
if (typeof window === "undefined" || window.innerWidth > 768) return;
|
|
||||||
event.preventDefault();
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (handledMobileSendRef.current) {
|
|
||||||
handledMobileSendRef.current = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
void handleSend();
|
void handleSend();
|
||||||
}}
|
}}
|
||||||
disabled={!messageInput.trim() && pendingAttachments.length === 0}
|
disabled={!messageInput.trim() && pendingAttachments.length === 0}
|
||||||
data-testid="chat-send-btn"
|
data-testid="chat-send-btn"
|
||||||
|
style={{ touchAction: "manipulation" }}
|
||||||
>
|
>
|
||||||
<Send size={16} />
|
<Send size={16} />
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user