fix(dashboard): stop mobile send-button double-fire that aborted chats

The ChatView and QuickChat send/stop buttons each had both an
onPointerDown and an onTouchStart handler invoking the action. On a
quick mobile tap both fire, so handleSend / handleSendMessage /
stopStreaming ran twice in rapid succession. The second invocation
closed the first's SSE stream (streamRef.current.close()), the server
treated that as a cancel via beginGeneration, and the chat ended with
no output — exactly matching the reported "tap silently fails, long
press works" symptom (long press happened to suppress one of the two
events).

Both handlers now early-return when the existing handledMobile*Ref
flag is already set, so only the first event for a given tap fires the
action. The send button additionally gets touch-action: manipulation
(removes the click delay that lets the textarea blur win the race) and
an expanded invisible hit area via ::before so slightly-off taps don't
land on the surrounding textarea and dismiss the keyboard without
sending.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-05-06 19:55:37 -07:00
parent 3819d48134
commit 394b1a655a
4 changed files with 57 additions and 0 deletions

View File

@@ -856,6 +856,25 @@
align-items: center;
justify-content: center;
flex-shrink: 0;
/* Disable double-tap zoom delay on mobile so the click handler fires
immediately on tap, and ignore other gestures the browser would
otherwise speculate on. Without this, quick taps can land in the
ambiguity window where the browser dismisses the keyboard (textarea
blur) before deciding whether to register a click on the button. */
touch-action: manipulation;
}
/* Expand the effective tap target without changing the visual size, so
slightly-off taps still land on the button instead of falling through
to the surrounding textarea (which would dismiss the mobile keyboard
without sending). */
.chat-input-send::before {
content: "";
position: absolute;
inset: -8px;
}
.chat-input-send {
position: relative;
}
.chat-input-send:disabled {