fix(mobile): restore original MobileAgentButton using onPointerUp instead of onClick (#524)
The original design used onPointerUp to cycle agents, which doesn't trigger focus transfer and keeps the soft keyboard open. Recent changes switched to onClick which causes button to gain focus and closes the keyboard. - Remove onClick handler entirely - Restore handlePointerDown, handlePointerUp, handlePointerLeave handlers - Use onPointerUp to trigger agent cycling - Add onContextMenu to prevent context menu on long-press - Add extensive comments explaining why pointer events must be used This reverts to the behavior from commit 337c458f where clicking the agent button doesn't close the soft keyboard. Co-authored-by: Jovines <jovines@qq.com>
This commit is contained in:
committed by
GitHub
co-authored by
Jovines
parent
32619e9f90
commit
0e9b231fed
@@ -13,58 +13,63 @@ interface MobileAgentButtonProps {
|
||||
|
||||
const LONG_PRESS_MS = 500;
|
||||
|
||||
export const MobileAgentButton: React.FC<MobileAgentButtonProps> = ({ onOpenAgentPanel, onCycleAgent, className }) => {
|
||||
// NOTE: Use pointer events instead of onClick to keep soft keyboard open on mobile
|
||||
export const MobileAgentButton: React.FC<MobileAgentButtonProps> = ({ onCycleAgent, onOpenAgentPanel, className }) => {
|
||||
const { currentAgentName, getVisibleAgents } = useConfigStore();
|
||||
const currentSessionId = useSessionStore((state) => state.currentSessionId);
|
||||
const sessionAgentName = useSessionStore((state) =>
|
||||
currentSessionId ? state.getSessionAgentSelection(currentSessionId) : null
|
||||
);
|
||||
const longPressTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const longPressTriggeredRef = React.useRef(false);
|
||||
|
||||
const agents = getVisibleAgents();
|
||||
const uiAgentName = currentSessionId ? (sessionAgentName || currentAgentName) : currentAgentName;
|
||||
const agentLabel = getAgentDisplayName(agents, uiAgentName);
|
||||
const agentColor = getAgentColor(uiAgentName);
|
||||
|
||||
const clearLongPressTimer = React.useCallback(() => {
|
||||
const longPressTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const isLongPressRef = React.useRef(false);
|
||||
|
||||
const handlePointerDown = () => {
|
||||
isLongPressRef.current = false;
|
||||
longPressTimerRef.current = setTimeout(() => {
|
||||
isLongPressRef.current = true;
|
||||
onOpenAgentPanel();
|
||||
}, LONG_PRESS_MS);
|
||||
};
|
||||
|
||||
// Use onPointerUp (not onClick) to prevent focus transfer that closes mobile keyboard
|
||||
const handlePointerUp = () => {
|
||||
if (longPressTimerRef.current) {
|
||||
clearTimeout(longPressTimerRef.current);
|
||||
longPressTimerRef.current = null;
|
||||
}
|
||||
}, []);
|
||||
if (!isLongPressRef.current) {
|
||||
onCycleAgent();
|
||||
}
|
||||
};
|
||||
|
||||
const startLongPressTimer = React.useCallback(() => {
|
||||
clearLongPressTimer();
|
||||
longPressTriggeredRef.current = false;
|
||||
longPressTimerRef.current = setTimeout(() => {
|
||||
longPressTriggeredRef.current = true;
|
||||
onOpenAgentPanel();
|
||||
}, LONG_PRESS_MS);
|
||||
}, [clearLongPressTimer, onOpenAgentPanel]);
|
||||
const handlePointerLeave = () => {
|
||||
if (longPressTimerRef.current) {
|
||||
clearTimeout(longPressTimerRef.current);
|
||||
longPressTimerRef.current = null;
|
||||
}
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
return () => clearLongPressTimer();
|
||||
}, [clearLongPressTimer]);
|
||||
return () => {
|
||||
if (longPressTimerRef.current) {
|
||||
clearTimeout(longPressTimerRef.current);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onPointerDown={(event) => {
|
||||
if (event.button !== 0) return;
|
||||
startLongPressTimer();
|
||||
}}
|
||||
onPointerUp={clearLongPressTimer}
|
||||
onPointerLeave={clearLongPressTimer}
|
||||
onPointerCancel={clearLongPressTimer}
|
||||
onClick={(event) => {
|
||||
if (longPressTriggeredRef.current) {
|
||||
event.preventDefault();
|
||||
longPressTriggeredRef.current = false;
|
||||
return;
|
||||
}
|
||||
onCycleAgent();
|
||||
}}
|
||||
onPointerDown={handlePointerDown}
|
||||
onPointerUp={handlePointerUp} // Don't use onClick - it closes mobile keyboard
|
||||
onPointerLeave={handlePointerLeave}
|
||||
onContextMenu={(e) => e.preventDefault()}
|
||||
className={cn(
|
||||
'inline-flex min-w-0 items-center select-none',
|
||||
'rounded-lg border border-border/50 px-1.5',
|
||||
@@ -81,9 +86,7 @@ export const MobileAgentButton: React.FC<MobileAgentButtonProps> = ({ onOpenAgen
|
||||
}}
|
||||
title={agentLabel}
|
||||
>
|
||||
<span className="min-w-0 max-w-full overflow-x-auto whitespace-nowrap scrollbar-hidden">
|
||||
{agentLabel}
|
||||
</span>
|
||||
<span className="truncate">{agentLabel}</span>
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user