📧 feat: Mention "@" Command Popover (#2635)

* feat: initial mockup

* wip: activesetting, may use or not use

* wip: mention with useCombobox usage

* feat: connect textarea to new mention popover

* refactor: consolidate icon logic for Landing/convos

* refactor: cleanup URL logic

* refactor(useTextarea): key up handler

* wip: render desired mention options

* refactor: improve mention detection

* feat: modular chat the default option

* WIP: first pass mention selection

* feat: scroll mention items with keypad

* chore(showMentionPopoverFamily): add typing to atomFamily

* feat: removeAtSymbol

* refactor(useListAssistantsQuery): use defaultOrderQuery as default param

* feat: assistants mentioning

* fix conversation switch errors

* filter mention selections based on startup settings and available endpoints

* fix: mentions model spec icon URL

* style: archive icon

* fix: convo renaming behavior on click

* fix(Convo): toggle hover state

* style: EditMenu refactor

* fix: archive chats table

* fix: errorsToString import

* chore: remove comments

* chore: remove comment

* feat: mention descriptions

* refactor: make sure continue hover button is always last, add correct fork button alt text
This commit is contained in:
Danny Avila 2024-05-07 13:13:55 -04:00 committed by GitHub
parent 89b1e33be0
commit b6d6343f54
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
35 changed files with 1048 additions and 217 deletions

View file

@ -1,7 +1,7 @@
import debounce from 'lodash/debounce';
import { useRecoilValue } from 'recoil';
import { useEffect, useRef, useCallback } from 'react';
import { EModelEndpoint } from 'librechat-data-provider';
import React, { useEffect, useRef, useCallback } from 'react';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import type { TEndpointOption } from 'librechat-data-provider';
import type { KeyboardEvent } from 'react';
import { forceResize, insertTextAtCursor, getAssistantName } from '~/utils';
@ -23,20 +23,24 @@ export default function useTextarea({
submitButtonRef: React.RefObject<HTMLButtonElement>;
disabled?: boolean;
}) {
const assistantMap = useAssistantsMapContext();
const enterToSend = useRecoilValue(store.enterToSend);
const {
conversation,
isSubmitting,
latestMessage,
setShowBingToneSetting,
filesLoading,
setFilesLoading,
} = useChatContext();
const localize = useLocalize();
const getSender = useGetSender();
const isComposing = useRef(false);
const { handleFiles } = useFileHandling();
const getSender = useGetSender();
const localize = useLocalize();
const assistantMap = useAssistantsMapContext();
const enterToSend = useRecoilValue(store.enterToSend);
const {
index,
conversation,
isSubmitting,
filesLoading,
latestMessage,
setFilesLoading,
setShowBingToneSetting,
} = useChatContext();
const setShowMentionPopover = useSetRecoilState(store.showMentionPopoverFamily(index));
const { conversationId, jailbreak, endpoint = '', assistant_id } = conversation || {};
const isNotAppendable =
@ -132,6 +136,30 @@ export default function useTextarea({
assistantMap,
]);
const handleKeyUp = useCallback(
(e: KeyEvent) => {
let isMention = false;
if (e.key === '@' || e.key === '2') {
const text = textAreaRef.current?.value;
isMention = !!(text && text[text.length - 1] === '@');
}
if (isMention) {
const startPos = textAreaRef.current?.selectionStart;
const isAtStart = startPos === 1;
const isPrecededBySpace =
startPos && textAreaRef.current?.value.charAt(startPos - 2) === ' ';
if (isAtStart || isPrecededBySpace) {
setShowMentionPopover(true);
} else {
setShowMentionPopover(false);
}
}
},
[textAreaRef, setShowMentionPopover],
);
const handleKeyDown = useCallback(
(e: KeyEvent) => {
if (e.key === 'Enter' && isSubmitting) {
@ -213,6 +241,7 @@ export default function useTextarea({
return {
textAreaRef,
handlePaste,
handleKeyUp,
handleKeyDown,
handleCompositionStart,
handleCompositionEnd,