improve plugin hotkey support (#426)

This commit is contained in:
Dornfeld Capital 2023-04-10 22:41:29 -05:00 committed by GitHub
parent da7463e901
commit 60288ad20a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 56 additions and 6 deletions

View File

@ -284,9 +284,16 @@ export const ChatInput = ({
</button> </button>
{showPluginSelect && ( {showPluginSelect && (
<div className="absolute left-0 bottom-14 bg-white dark:bg-[#343541]"> <div className="absolute left-0 bottom-14 rounded bg-white dark:bg-[#343541]">
<PluginSelect <PluginSelect
plugin={plugin} plugin={plugin}
onKeyDown={(e: any) => {
if (e.key === 'Escape') {
e.preventDefault();
setShowPluginSelect(false);
textareaRef.current?.focus();
}
}}
onPluginChange={(plugin: Plugin) => { onPluginChange={(plugin: Plugin) => {
setPlugin(plugin); setPlugin(plugin);
setShowPluginSelect(false); setShowPluginSelect(false);

View File

@ -7,13 +7,53 @@ import { Plugin, PluginList } from '@/types/plugin';
interface Props { interface Props {
plugin: Plugin | null; plugin: Plugin | null;
onPluginChange: (plugin: Plugin) => void; onPluginChange: (plugin: Plugin) => void;
onKeyDown: (e: React.KeyboardEvent<HTMLSelectElement>) => void;
} }
export const PluginSelect: FC<Props> = ({ plugin, onPluginChange }) => { export const PluginSelect: FC<Props> = ({
plugin,
onPluginChange,
onKeyDown,
}) => {
const { t } = useTranslation('chat'); const { t } = useTranslation('chat');
const selectRef = useRef<HTMLSelectElement>(null); const selectRef = useRef<HTMLSelectElement>(null);
const handleKeyDown = (e: React.KeyboardEvent<HTMLSelectElement>) => {
const selectElement = selectRef.current;
const optionCount = selectElement?.options.length || 0;
if (e.key === '/' && e.metaKey) {
e.preventDefault();
if (selectElement) {
selectElement.selectedIndex =
(selectElement.selectedIndex + 1) % optionCount;
selectElement.dispatchEvent(new Event('change'));
}
} else if (e.key === '/' && e.shiftKey && e.metaKey) {
e.preventDefault();
if (selectElement) {
selectElement.selectedIndex =
(selectElement.selectedIndex - 1 + optionCount) % optionCount;
selectElement.dispatchEvent(new Event('change'));
}
} else if (e.key === 'Enter') {
e.preventDefault();
if (selectElement) {
selectElement.dispatchEvent(new Event('change'));
}
onPluginChange(
PluginList.find(
(plugin) =>
plugin.name === selectElement?.selectedOptions[0].innerText,
) as Plugin,
);
} else {
onKeyDown(e);
}
};
useEffect(() => { useEffect(() => {
if (selectRef.current) { if (selectRef.current) {
selectRef.current.focus(); selectRef.current.focus();
@ -22,7 +62,7 @@ export const PluginSelect: FC<Props> = ({ plugin, onPluginChange }) => {
return ( return (
<div className="flex flex-col"> <div className="flex flex-col">
<div className="w-full rounded-lg border border-neutral-200 bg-transparent pr-2 text-neutral-900 dark:border-neutral-600 dark:text-white"> <div className="mb-1 w-full rounded border border-neutral-200 bg-transparent pr-2 text-neutral-900 dark:border-neutral-600 dark:text-white">
<select <select
ref={selectRef} ref={selectRef}
className="w-full cursor-pointer bg-transparent p-2" className="w-full cursor-pointer bg-transparent p-2"
@ -35,13 +75,16 @@ export const PluginSelect: FC<Props> = ({ plugin, onPluginChange }) => {
) as Plugin, ) as Plugin,
); );
}} }}
onKeyDown={(e) => {
handleKeyDown(e);
}}
> >
<option <option
key="none" key="chatgpt"
value="" value="chatgpt"
className="dark:bg-[#343541] dark:text-white" className="dark:bg-[#343541] dark:text-white"
> >
Select Plugin ChatGPT
</option> </option>
{PluginList.map((plugin) => ( {PluginList.map((plugin) => (