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