fix: Ensure Message Send Requires Key 🔑 (#1281)

* fix: only allow message send when key is provided when required
- create useRequiresKey hook
- pass same disabled prop to Textarea, AttachFile, and SendButton
- EndpointItem: add localization, stopPropagation, and remove commented code
- separate some hooks to new Input dir
- completely remove textareaHeight recoil state as is not needed
- update imports for moved hooks
- pass disabled prop to useTextarea

* feat: add localization to textarea placeholders
This commit is contained in:
Danny Avila 2023-12-05 09:38:04 -05:00 committed by GitHub
parent f6118879e5
commit 00b6af8c74
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 54 additions and 50 deletions

View file

@ -0,0 +1,4 @@
export { default as useUserKey } from './useUserKey';
export { default as useDebounce } from './useDebounce';
export { default as useTextarea } from './useTextarea';
export { default as useRequiresKey } from './useRequiresKey';

View file

@ -0,0 +1,14 @@
import { useGetEndpointsQuery } from 'librechat-data-provider';
import { useChatContext } from '~/Providers/ChatContext';
import useUserKey from './useUserKey';
export default function useRequiresKey() {
const { conversation } = useChatContext();
const { data: endpointsConfig } = useGetEndpointsQuery();
const { endpoint } = conversation || {};
const userProvidesKey = endpointsConfig?.[endpoint ?? '']?.userProvide;
const { getExpiry } = useUserKey(endpoint ?? '');
const expiryTime = getExpiry();
const requiresKey = !expiryTime && userProvidesKey;
return { requiresKey };
}

View file

@ -2,23 +2,18 @@ import { useEffect, useRef } from 'react';
import { TEndpointOption, getResponseSender } from 'librechat-data-provider';
import type { KeyboardEvent } from 'react';
import { useChatContext } from '~/Providers/ChatContext';
import useFileHandling from './useFileHandling';
import useFileHandling from '~/hooks/useFileHandling';
import useLocalize from '~/hooks/useLocalize';
type KeyEvent = KeyboardEvent<HTMLTextAreaElement>;
export default function useTextarea({ setText, submitMessage }) {
const {
conversation,
isSubmitting,
latestMessage,
setShowBingToneSetting,
textareaHeight,
setTextareaHeight,
setFilesLoading,
} = useChatContext();
export default function useTextarea({ setText, submitMessage, disabled = false }) {
const { conversation, isSubmitting, latestMessage, setShowBingToneSetting, setFilesLoading } =
useChatContext();
const isComposing = useRef(false);
const inputRef = useRef<HTMLTextAreaElement | null>(null);
const { handleFiles } = useFileHandling();
const localize = useLocalize();
const isNotAppendable = (latestMessage?.unfinished && !isSubmitting) || latestMessage?.error;
const { conversationId, jailbreak } = conversation || {};
@ -88,23 +83,16 @@ export default function useTextarea({ setText, submitMessage }) {
};
const getPlaceholderText = () => {
if (disabled) {
return localize('com_endpoint_config_placeholder');
}
if (isNotAppendable) {
return 'Edit your message or Regenerate.';
return localize('com_endpoint_message_not_appendable');
}
const sender = getResponseSender(conversation as TEndpointOption);
return `Message ${sender ? sender : 'ChatGPT'}`;
};
const onHeightChange = (height: number) => {
if (height > 208 && textareaHeight < 208) {
setTextareaHeight(Math.min(height, 208));
} else if (height > 208) {
return;
} else {
setTextareaHeight(height);
}
return `${localize('com_endpoint_message')} ${sender ? sender : 'ChatGPT'}`;
};
const handlePaste = (e: React.ClipboardEvent<HTMLTextAreaElement>) => {
@ -123,6 +111,5 @@ export default function useTextarea({ setText, submitMessage }) {
handleCompositionStart,
handleCompositionEnd,
placeholder: getPlaceholderText(),
onHeightChange,
};
}

View file

@ -1,4 +1,5 @@
export * from './Messages';
export * from './Input';
export * from './AuthContext';
export * from './ThemeContext';
@ -7,10 +8,7 @@ export * from './ApiErrorBoundaryContext';
export { default as useSSE } from './useSSE';
export { default as useToast } from './useToast';
export { default as useTimeout } from './useTimeout';
export { default as useUserKey } from './useUserKey';
export { default as useNewConvo } from './useNewConvo';
export { default as useDebounce } from './useDebounce';
export { default as useTextarea } from './useTextarea';
export { default as useLocalize } from './useLocalize';
export { default as useMediaQuery } from './useMediaQuery';
export { default as useSetOptions } from './useSetOptions';

View file

@ -18,8 +18,8 @@ import type {
import type { TAskFunction } from '~/common';
import useSetFilesToDelete from './useSetFilesToDelete';
import { useAuthContext } from './AuthContext';
import useUserKey from './Input/useUserKey';
import useNewConvo from './useNewConvo';
import useUserKey from './useUserKey';
import store from '~/store';
// this to be set somewhere else
@ -324,7 +324,6 @@ export default function useChatHelpers(index = 0, paramId: string | undefined) {
const [showPopover, setShowPopover] = useRecoilState(store.showPopoverFamily(index));
const [abortScroll, setAbortScroll] = useRecoilState(store.abortScrollFamily(index));
const [preset, setPreset] = useRecoilState(store.presetByIndex(index));
const [textareaHeight, setTextareaHeight] = useRecoilState(store.textareaHeightFamily(index));
const [optionSettings, setOptionSettings] = useRecoilState(store.optionSettingsFamily(index));
const [showAgentSettings, setShowAgentSettings] = useRecoilState(
store.showAgentSettingsFamily(index),
@ -364,8 +363,6 @@ export default function useChatHelpers(index = 0, paramId: string | undefined) {
setOptionSettings,
showAgentSettings,
setShowAgentSettings,
textareaHeight,
setTextareaHeight,
files,
setFiles,
invalidateConvos,

View file

@ -3,7 +3,7 @@ import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
import { parseConvo, getResponseSender, useGetEndpointsQuery } from 'librechat-data-provider';
import type { TMessage, TSubmission, TEndpointOption } from 'librechat-data-provider';
import type { TAskFunction } from '~/common';
import useUserKey from './useUserKey';
import useUserKey from './Input/useUserKey';
import store from '~/store';
const useMessageHandler = () => {