Bot Command Tooltip: Fix sending wrong command

This commit is contained in:
Alexander Zinchuk 2023-02-22 23:48:42 +01:00
parent 6d5625ce0c
commit a219f67624
5 changed files with 41 additions and 10 deletions

View File

@ -4,6 +4,7 @@ import React, {
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { getActions, withGlobal } from '../../../global'; import { getActions, withGlobal } from '../../../global';
import type { Signal } from '../../../util/signals';
import type { ApiBotCommand, ApiUser } from '../../../api/types'; import type { ApiBotCommand, ApiUser } from '../../../api/types';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
@ -20,6 +21,7 @@ export type OwnProps = {
isOpen: boolean; isOpen: boolean;
withUsername?: boolean; withUsername?: boolean;
botCommands?: ApiBotCommand[]; botCommands?: ApiBotCommand[];
getHtml: Signal<string>;
onClick: NoneToVoidFunction; onClick: NoneToVoidFunction;
onClose: NoneToVoidFunction; onClose: NoneToVoidFunction;
}; };
@ -33,6 +35,7 @@ const BotCommandTooltip: FC<OwnProps & StateProps> = ({
isOpen, isOpen,
withUsername, withUsername,
botCommands, botCommands,
getHtml,
onClick, onClick,
onClose, onClose,
}) => { }) => {
@ -50,10 +53,20 @@ const BotCommandTooltip: FC<OwnProps & StateProps> = ({
onClick(); onClick();
}, [onClick, sendBotCommand, usersById, withUsername]); }, [onClick, sendBotCommand, usersById, withUsername]);
const handleSelect = useCallback((botCommand: ApiBotCommand) => {
// We need an additional check because tooltip is updated with throttling
if (!botCommand.command.startsWith(getHtml())) {
return false;
}
handleSendCommand(botCommand);
return true;
}, [getHtml, handleSendCommand]);
const selectedCommandIndex = useKeyboardNavigation({ const selectedCommandIndex = useKeyboardNavigation({
isActive: isOpen, isActive: isOpen,
items: botCommands, items: botCommands,
onSelect: handleSendCommand, onSelect: handleSelect,
onClose, onClose,
}); });

View File

@ -1267,6 +1267,7 @@ const Composer: FC<OwnProps & StateProps> = ({
isOpen={isBotCommandTooltipOpen} isOpen={isBotCommandTooltipOpen}
withUsername={Boolean(chatBotCommands)} withUsername={Boolean(chatBotCommands)}
botCommands={botTooltipCommands} botCommands={botTooltipCommands}
getHtml={getHtml}
onClick={handleBotCommandSelect} onClick={handleBotCommandSelect}
onClose={closeBotCommandTooltip} onClose={closeBotCommandTooltip}
/> />

View File

@ -8,7 +8,7 @@ import useFlag from '../../../../hooks/useFlag';
import useDerivedSignal from '../../../../hooks/useDerivedSignal'; import useDerivedSignal from '../../../../hooks/useDerivedSignal';
import { useThrottledResolver } from '../../../../hooks/useAsyncResolvers'; import { useThrottledResolver } from '../../../../hooks/useAsyncResolvers';
const RE_COMMAND = /^\/([\w@]{1,32}\s?)?/i; const RE_COMMAND = /^\/([\w@]{1,32})?$/i;
const THROTTLE = 300; const THROTTLE = 300;

View File

@ -20,7 +20,7 @@ export function useKeyboardNavigation({
noArrowNavigation?: boolean; noArrowNavigation?: boolean;
items?: any[]; items?: any[];
shouldSelectOnTab?: boolean; shouldSelectOnTab?: boolean;
onSelect: AnyToVoidFunction; onSelect: (item: any) => void | boolean;
onClose: NoneToVoidFunction; onClose: NoneToVoidFunction;
}) { }) {
const [selectedItemIndex, setSelectedItemIndex] = useState(-1); const [selectedItemIndex, setSelectedItemIndex] = useState(-1);
@ -42,10 +42,15 @@ export function useKeyboardNavigation({
if (items && items.length && selectedItemIndex > -1) { if (items && items.length && selectedItemIndex > -1) {
const item = items[selectedItemIndex]; const item = items[selectedItemIndex];
if (item) { if (item) {
if (onSelect(item) === false) {
return false;
}
e.preventDefault(); e.preventDefault();
onSelect(item);
} }
} }
return true;
}, [items, onSelect, selectedItemIndex]); }, [items, onSelect, selectedItemIndex]);
const isSelectionOutOfRange = !items || selectedItemIndex > items.length - 1; const isSelectionOutOfRange = !items || selectedItemIndex > items.length - 1;

View File

@ -1,6 +1,14 @@
type HandlerName = 'onEnter' | 'onBackspace' | 'onDelete' | 'onEsc' | 'onUp' | 'onDown' | 'onLeft' | 'onRight' type HandlerName =
| 'onTab'; 'onEnter'
type Handler = (e: KeyboardEvent) => void; | 'onBackspace'
| 'onDelete'
| 'onEsc'
| 'onUp'
| 'onDown'
| 'onLeft'
| 'onRight'
| 'onTab';
type Handler = (e: KeyboardEvent) => void | boolean;
type CaptureOptions = Partial<Record<HandlerName, Handler>>; type CaptureOptions = Partial<Record<HandlerName, Handler>>;
const keyToHandlerName: Record<string, HandlerName> = { const keyToHandlerName: Record<string, HandlerName> = {
@ -64,10 +72,14 @@ function handleKeyDown(e: KeyboardEvent) {
if (!length) { if (!length) {
return; return;
} }
e.stopPropagation();
const handler = handlers[handlerName][length - 1]; for (let i = length - 1; i >= 0; i--) {
handler!(e); const handler = handlers[handlerName][i]!;
if (handler(e) !== false) {
e.stopPropagation();
break;
}
}
} }
function releaseKeyboardListener(options: CaptureOptions) { function releaseKeyboardListener(options: CaptureOptions) {