improve plugin hotkey support (#426)
This commit is contained in:
parent
da7463e901
commit
60288ad20a
|
@ -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);
|
||||||
|
|
|
@ -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) => (
|
||||||
|
|
Loading…
Reference in New Issue