mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-19 18:00:15 +01:00
✨ feat: Quality-of-Life Chat/Edit-Message Enhancements (#5194)
* fix: rendering error for mermaid flowchart syntax * feat: add submit button ref and enable submit on Ctrl+Enter in EditMessage component * feat: add save button and keyboard shortcuts for saving and canceling in EditMessage component * feat: collapse chat on max height * refactor: implement scrollable detection for textarea on key down events and initial render * feat: add regenerate button for error handling in HoverButtons, closes #3658 * feat: add functionality to edit latest user message with the up arrow key when the input is empty
This commit is contained in:
parent
b01c744eb8
commit
8aa1e731ca
22 changed files with 242 additions and 66 deletions
|
|
@ -54,6 +54,7 @@ const useHandleKeyUp = ({
|
|||
permissionType: PermissionTypes.MULTI_CONVO,
|
||||
permission: Permissions.USE,
|
||||
});
|
||||
const latestMessage = useRecoilValue(store.latestMessageFamily(index));
|
||||
const setShowPromptsPopover = useSetRecoilState(store.showPromptsPopoverFamily(index));
|
||||
|
||||
// Get the current state of command toggles
|
||||
|
|
@ -94,12 +95,32 @@ const useHandleKeyUp = ({
|
|||
[handleAtCommand, handlePlusCommand, handlePromptsCommand],
|
||||
);
|
||||
|
||||
const handleUpArrow = useCallback(
|
||||
(event: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
if (!latestMessage) {
|
||||
return;
|
||||
}
|
||||
|
||||
const element = document.getElementById(`edit-${latestMessage.parentMessageId}`);
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
element.click();
|
||||
},
|
||||
[latestMessage],
|
||||
);
|
||||
|
||||
/**
|
||||
* Main key up handler.
|
||||
*/
|
||||
const handleKeyUp = useCallback(
|
||||
(event: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
const text = textAreaRef.current?.value;
|
||||
if (event.key === 'ArrowUp' && text?.length === 0) {
|
||||
handleUpArrow(event);
|
||||
return;
|
||||
}
|
||||
if (typeof text !== 'string' || text.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -115,7 +136,7 @@ const useHandleKeyUp = ({
|
|||
handler();
|
||||
}
|
||||
},
|
||||
[textAreaRef, commandHandlers],
|
||||
[textAreaRef, commandHandlers, handleUpArrow],
|
||||
);
|
||||
|
||||
return handleKeyUp;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,13 @@ import { useRecoilValue, useRecoilState } from 'recoil';
|
|||
import { Constants } from 'librechat-data-provider';
|
||||
import type { TEndpointOption } from 'librechat-data-provider';
|
||||
import type { KeyboardEvent } from 'react';
|
||||
import { forceResize, insertTextAtCursor, getEntityName, getEntity } from '~/utils';
|
||||
import {
|
||||
forceResize,
|
||||
insertTextAtCursor,
|
||||
getEntityName,
|
||||
getEntity,
|
||||
checkIfScrollable,
|
||||
} from '~/utils';
|
||||
import { useAssistantsMapContext } from '~/Providers/AssistantsMapContext';
|
||||
import { useAgentsMapContext } from '~/Providers/AgentsMapContext';
|
||||
import useGetSender from '~/hooks/Conversations/useGetSender';
|
||||
|
|
@ -20,10 +26,12 @@ type KeyEvent = KeyboardEvent<HTMLTextAreaElement>;
|
|||
export default function useTextarea({
|
||||
textAreaRef,
|
||||
submitButtonRef,
|
||||
setIsScrollable,
|
||||
disabled = false,
|
||||
}: {
|
||||
textAreaRef: React.RefObject<HTMLTextAreaElement>;
|
||||
submitButtonRef: React.RefObject<HTMLButtonElement>;
|
||||
setIsScrollable: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
disabled?: boolean;
|
||||
}) {
|
||||
const localize = useLocalize();
|
||||
|
|
@ -170,6 +178,10 @@ export default function useTextarea({
|
|||
|
||||
const handleKeyDown = useCallback(
|
||||
(e: KeyEvent) => {
|
||||
if (textAreaRef.current && checkIfScrollable(textAreaRef.current)) {
|
||||
const scrollable = checkIfScrollable(textAreaRef.current);
|
||||
scrollable && setIsScrollable(scrollable);
|
||||
}
|
||||
if (e.key === 'Enter' && isSubmitting) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -209,7 +221,15 @@ export default function useTextarea({
|
|||
submitButtonRef.current?.click();
|
||||
}
|
||||
},
|
||||
[isSubmitting, checkHealth, filesLoading, enterToSend, textAreaRef, submitButtonRef],
|
||||
[
|
||||
isSubmitting,
|
||||
checkHealth,
|
||||
filesLoading,
|
||||
enterToSend,
|
||||
setIsScrollable,
|
||||
textAreaRef,
|
||||
submitButtonRef,
|
||||
],
|
||||
);
|
||||
|
||||
const handleCompositionStart = () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue