From 7bd03a6e70920f5ce3da7a9bddabaa6396e490ca Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Tue, 2 Apr 2024 12:14:42 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A0=EF=B8=8F=20fix:=20Correct=20Unwant?= =?UTF-8?q?ed=20Newlines=20after=20Undo=20in=20Textarea=20(#2289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: edit docker_override note for deploy-compose * 🛠️ fix: Correct Unwanted Newlines after Undo in Textarea --- client/src/hooks/Input/useTextarea.ts | 13 +++++++-- client/src/utils/textarea.ts | 27 ++++++++++++++++--- docs/install/configuration/docker_override.md | 8 +++--- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/client/src/hooks/Input/useTextarea.ts b/client/src/hooks/Input/useTextarea.ts index d0c560cc6..599b5f520 100644 --- a/client/src/hooks/Input/useTextarea.ts +++ b/client/src/hooks/Input/useTextarea.ts @@ -4,7 +4,7 @@ import { EModelEndpoint } from 'librechat-data-provider'; import type { TEndpointOption } from 'librechat-data-provider'; import type { UseFormSetValue } from 'react-hook-form'; import type { KeyboardEvent } from 'react'; -import { forceResize, insertTextAtCursor, getAssistantName } from '~/utils'; +import { forceResize, insertTextAtCursor, trimUndoneRange, getAssistantName } from '~/utils'; import { useAssistantsMapContext } from '~/Providers/AssistantsMapContext'; import useGetSender from '~/hooks/Conversations/useGetSender'; import useFileHandling from '~/hooks/Files/useFileHandling'; @@ -157,7 +157,16 @@ export default function useTextarea({ const handleKeyUp = (e: KeyEvent) => { const target = e.target as HTMLTextAreaElement; - if (e.keyCode === 8 && target.value.trim() === '') { + const isUndo = e.key === 'z' && (e.ctrlKey || e.metaKey); + if (isUndo && target.value.trim() === '') { + textAreaRef.current?.setRangeText('', 0, textAreaRef.current?.value?.length, 'end'); + forceResize(textAreaRef); + } else if (isUndo) { + trimUndoneRange(textAreaRef); + forceResize(textAreaRef); + } + + if ((e.keyCode === 8 || e.key === 'Backspace') && target.value.trim() === '') { textAreaRef.current?.setRangeText('', 0, textAreaRef.current?.value?.length, 'end'); } diff --git a/client/src/utils/textarea.ts b/client/src/utils/textarea.ts index ac3aad9c4..7266ba542 100644 --- a/client/src/utils/textarea.ts +++ b/client/src/utils/textarea.ts @@ -32,9 +32,28 @@ export function insertTextAtCursor(element: HTMLTextAreaElement, textToInsert: s 3) Reseting back to scrollHeight reads and applies the ideal height for the current content dynamically */ export const forceResize = (textAreaRef: React.RefObject) => { - if (textAreaRef.current) { - textAreaRef.current.style.height = 'auto'; - textAreaRef.current.offsetHeight; - textAreaRef.current.style.height = `${textAreaRef.current.scrollHeight}px`; + if (!textAreaRef.current) { + return; } + textAreaRef.current.style.height = 'auto'; + textAreaRef.current.offsetHeight; + textAreaRef.current.style.height = `${textAreaRef.current.scrollHeight}px`; +}; + +/** + * Necessary undo event helper for edge cases where undoing pasted content leaves newlines filling the previous container height. + */ +export const trimUndoneRange = (textAreaRef: React.RefObject) => { + if (!textAreaRef.current) { + return; + } + const { value, selectionStart, selectionEnd } = textAreaRef.current; + const afterCursor = value.substring(selectionEnd).trim(); + if (afterCursor.length) { + return; + } + const beforeCursor = value.substring(0, selectionStart); + const newValue = beforeCursor + afterCursor; + textAreaRef.current.value = newValue; + textAreaRef.current.setSelectionRange(selectionStart, selectionStart); }; diff --git a/docs/install/configuration/docker_override.md b/docs/install/configuration/docker_override.md index 940c961fd..d47c22573 100644 --- a/docs/install/configuration/docker_override.md +++ b/docs/install/configuration/docker_override.md @@ -109,11 +109,13 @@ The npm commands for "deployed" do this for you but they do not account for over "stop:deployed": "docker compose -f ./deploy-compose.yml down", ``` -For example, if you use `deploy-compose.yml` as your main Docker Compose configuration and you have an override file named `deploy-compose.override.yml` (you can name the override file whatever you want), you would run Docker Compose commands like so: +I would include the default override file in these commands, but doing so would require one to exist for every setup. + +If you use `deploy-compose.yml` as your main Docker Compose configuration and you have an override file named `docker-compose.override.yml` (you can name the override file whatever you want, but you may have this specific file already), you would run Docker Compose commands like so: ```bash -docker compose -f deploy-compose.yml -f deploy-compose.override.yml pull -docker compose -f deploy-compose.yml -f deploy-compose.override.yml up +docker compose -f deploy-compose.yml -f docker-compose.override.yml pull +docker compose -f deploy-compose.yml -f docker-compose.override.yml up ``` ## MongoDB Authentication