fix: preserve composer taps while the keyboard dismisses
Keeps mobile composer controls from missing taps during keyboard blur/reflow Applies the deferred blur behavior to mobile browsers and installed PWAs Leaves Capacitor behavior unchanged
This commit is contained in:
@@ -1016,13 +1016,13 @@ const ChatInputComponent: React.FC<ChatInputProps> = ({ onOpenSettings, scrollTo
|
|||||||
// so the chat compensates keyboard + composer height in a single motion.
|
// so the chat compensates keyboard + composer height in a single motion.
|
||||||
const [mobileComposerExpanded, setMobileComposerExpanded] = React.useState(false);
|
const [mobileComposerExpanded, setMobileComposerExpanded] = React.useState(false);
|
||||||
const [mobileTextareaFocused, setMobileTextareaFocused] = React.useState(false);
|
const [mobileTextareaFocused, setMobileTextareaFocused] = React.useState(false);
|
||||||
// Installed PWA (standalone): tapping a composer control while the keyboard
|
// Mobile browser / installed PWA: tapping a composer control while the
|
||||||
// is up blurs the textarea first, and the keyboard-resize reflow moves the
|
// keyboard is up blurs the textarea first, and the keyboard-resize reflow
|
||||||
// control out from under the finger BEFORE iOS synthesizes the click — the
|
// moves the control out from under the finger BEFORE the browser
|
||||||
// tap dismisses the keyboard but the control's onClick never fires. Defer
|
// synthesizes the click — the tap dismisses the keyboard but the control's
|
||||||
// the blur-driven state flip so the pinned composer holds still through the
|
// onClick never fires. Defer the blur-driven state flip so the pinned
|
||||||
// tap; a refocus cancels it. Browser (pan mode) and Capacitor keep the
|
// composer holds still through the tap; a refocus cancels it. Capacitor
|
||||||
// immediate flip.
|
// keeps the immediate flip.
|
||||||
const mobileBlurTimerRef = React.useRef<number | null>(null);
|
const mobileBlurTimerRef = React.useRef<number | null>(null);
|
||||||
React.useEffect(() => () => {
|
React.useEffect(() => () => {
|
||||||
if (mobileBlurTimerRef.current !== null) {
|
if (mobileBlurTimerRef.current !== null) {
|
||||||
@@ -5204,9 +5204,12 @@ const ChatInputComponent: React.FC<ChatInputProps> = ({ onOpenSettings, scrollTo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
lastMobileBlurAtRef.current = Date.now();
|
lastMobileBlurAtRef.current = Date.now();
|
||||||
const standalone = !isCapacitorApp()
|
// Mobile browsers and installed PWAs share the
|
||||||
&& window.matchMedia?.('(display-mode: standalone)')?.matches;
|
// blur race: the keyboard-dismiss reflow moves
|
||||||
if (!standalone) {
|
// composer buttons before the tap's synthesized
|
||||||
|
// click lands, so the click misses its target.
|
||||||
|
// Capacitor's WebView does not need the hold.
|
||||||
|
if (isCapacitorApp()) {
|
||||||
setMobileTextareaFocused(false);
|
setMobileTextareaFocused(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user