mirror of https://github.com/buster-so/buster.git
Merge pull request #444 from buster-so/big-nate/bus-1327-prevent-spam-on-button-click
Big nate/bus 1327 prevent spam on button click
This commit is contained in:
commit
356e870145
|
@ -16,7 +16,7 @@ import { useAppLayoutContextSelector } from '../BusterAppLayout';
|
|||
import { BusterRoutes } from '@/routes/busterRoutes';
|
||||
|
||||
export const useBusterNewChat = () => {
|
||||
const { mutateAsync: startNewChat } = useStartNewChat();
|
||||
const { mutateAsync: startNewChat, isPending: isSubmittingChat } = useStartNewChat();
|
||||
const onChangePage = useAppLayoutContextSelector((x) => x.onChangePage);
|
||||
const getChatMessageMemoized = useGetChatMessageMemoized();
|
||||
const getChatMemoized = useGetChatMemoized();
|
||||
|
@ -57,7 +57,6 @@ export const useBusterNewChat = () => {
|
|||
message_id: messageId
|
||||
});
|
||||
|
||||
|
||||
initializeNewChat(res);
|
||||
}
|
||||
);
|
||||
|
@ -149,7 +148,8 @@ export const useBusterNewChat = () => {
|
|||
onFollowUpChat,
|
||||
onStartChatFromFile,
|
||||
onReplaceMessageInChat,
|
||||
onStopChat
|
||||
onStopChat,
|
||||
isSubmittingChat
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -8,6 +8,13 @@ import { NewChatInput } from './NewChatInput';
|
|||
import { NewChatWarning } from './NewChatWarning';
|
||||
import { useNewChatWarning } from './useNewChatWarning';
|
||||
|
||||
enum TimeOfDay {
|
||||
MORNING = 'morning',
|
||||
AFTERNOON = 'afternoon',
|
||||
EVENING = 'evening',
|
||||
NIGHT = 'night'
|
||||
}
|
||||
|
||||
export const HomePageController: React.FC<Record<string, never>> = () => {
|
||||
const newChatWarningProps = useNewChatWarning();
|
||||
const { showWarning } = newChatWarningProps;
|
||||
|
@ -15,18 +22,35 @@ export const HomePageController: React.FC<Record<string, never>> = () => {
|
|||
const user = useUserConfigContextSelector((state) => state.user);
|
||||
const userName = user?.name;
|
||||
|
||||
const isMorning = useMemo(() => {
|
||||
const timeOfDay = useMemo(() => {
|
||||
const now = new Date();
|
||||
const hours = now.getHours();
|
||||
return hours < 12;
|
||||
|
||||
if (hours >= 5 && hours < 12) {
|
||||
return TimeOfDay.MORNING;
|
||||
} else if (hours >= 12 && hours < 17) {
|
||||
return TimeOfDay.AFTERNOON;
|
||||
} else if (hours >= 17 && hours < 21) {
|
||||
return TimeOfDay.EVENING;
|
||||
} else {
|
||||
return TimeOfDay.NIGHT;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const greeting = useMemo(() => {
|
||||
if (isMorning) {
|
||||
return `Good morning, ${userName}`;
|
||||
switch (timeOfDay) {
|
||||
case TimeOfDay.MORNING:
|
||||
return `Good morning, ${userName}`;
|
||||
case TimeOfDay.AFTERNOON:
|
||||
return `Good afternoon, ${userName}`;
|
||||
case TimeOfDay.EVENING:
|
||||
return `Good evening, ${userName}`;
|
||||
case TimeOfDay.NIGHT:
|
||||
return `Good night, ${userName}`;
|
||||
default:
|
||||
return `Hello, ${userName}`;
|
||||
}
|
||||
return `Good afternoon, ${userName}`;
|
||||
}, [userName]);
|
||||
}, [timeOfDay, userName]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center p-4.5">
|
||||
|
|
|
@ -22,7 +22,7 @@ export const NewChatInput: React.FC<Record<string, never>> = () => {
|
|||
}, [inputValue]);
|
||||
|
||||
const onSubmit = useMemoizedFn(async (value: string) => {
|
||||
if (disabledSubmit) return;
|
||||
if (disabledSubmit || loading) return;
|
||||
try {
|
||||
setLoading(true);
|
||||
const trimmedValue = value.trim();
|
||||
|
@ -32,12 +32,6 @@ export const NewChatInput: React.FC<Record<string, never>> = () => {
|
|||
}
|
||||
});
|
||||
|
||||
const onStop = useMemoizedFn(() => {
|
||||
setLoading(false);
|
||||
textAreaRef.current?.focus();
|
||||
textAreaRef.current?.select();
|
||||
});
|
||||
|
||||
const onChange = useMemoizedFn((e: ChangeEvent<HTMLTextAreaElement>) => {
|
||||
setInputValue(e.target.value);
|
||||
});
|
||||
|
@ -56,7 +50,6 @@ export const NewChatInput: React.FC<Record<string, never>> = () => {
|
|||
autoResize={autoResizeConfig}
|
||||
onSubmit={onSubmit}
|
||||
onChange={onChange}
|
||||
onStop={onStop}
|
||||
loading={loading}
|
||||
disabled={false}
|
||||
disabledSubmit={disabledSubmit}
|
||||
|
|
|
@ -11,8 +11,9 @@ const autoResizeConfig = { minRows: 2, maxRows: 16 };
|
|||
|
||||
export const ChatInput: React.FC = React.memo(() => {
|
||||
const textAreaRef = useRef<HTMLTextAreaElement>(null);
|
||||
const loading = useChatIndividualContextSelector((x) => x.isStreamingMessage);
|
||||
const isStreamingMessage = useChatIndividualContextSelector((x) => x.isStreamingMessage);
|
||||
const hasChat = useChatIndividualContextSelector((x) => x.hasChat);
|
||||
|
||||
const [inputValue, setInputValue] = useState('');
|
||||
|
||||
const disableSubmit = useMemo(() => {
|
||||
|
@ -23,7 +24,7 @@ export const ChatInput: React.FC = React.memo(() => {
|
|||
disableSubmit,
|
||||
inputValue,
|
||||
setInputValue,
|
||||
loading,
|
||||
loading: isStreamingMessage,
|
||||
textAreaRef
|
||||
});
|
||||
|
||||
|
@ -42,7 +43,7 @@ export const ChatInput: React.FC = React.memo(() => {
|
|||
onSubmit={onSubmitPreflight}
|
||||
onChange={onChange}
|
||||
onStop={onStopChat}
|
||||
loading={loading}
|
||||
loading={isStreamingMessage}
|
||||
value={inputValue}
|
||||
disabled={!hasChat}
|
||||
disabledSubmit={disableSubmit}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type React from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import { useMemo, useRef } from 'react';
|
||||
import { useBusterNotifications } from '@/context/BusterNotifications';
|
||||
import { useBusterNewChatContextSelector } from '@/context/Chats';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
|
@ -27,6 +27,7 @@ export const useChatInputFlow = ({
|
|||
const selectedFileId = useChatIndividualContextSelector((x) => x.selectedFileId);
|
||||
const onStartNewChat = useBusterNewChatContextSelector((state) => state.onStartNewChat);
|
||||
const onFollowUpChat = useBusterNewChatContextSelector((state) => state.onFollowUpChat);
|
||||
const isSubmittingChat = useBusterNewChatContextSelector((state) => state.isSubmittingChat);
|
||||
const onStartChatFromFile = useBusterNewChatContextSelector((state) => state.onStartChatFromFile);
|
||||
const onStopChatContext = useBusterNewChatContextSelector((state) => state.onStopChat);
|
||||
const currentMessageId = useChatIndividualContextSelector((x) => x.currentMessageId);
|
||||
|
@ -34,6 +35,8 @@ export const useChatInputFlow = ({
|
|||
const onResetToOriginal = useChatIndividualContextSelector((x) => x.onResetToOriginal);
|
||||
const { openConfirmModal } = useBusterNotifications();
|
||||
|
||||
const submittingCooldown = useRef(isSubmittingChat);
|
||||
|
||||
const flow: FlowType = useMemo(() => {
|
||||
if (hasChat) return 'followup-chat';
|
||||
if (selectedFileType === 'metric' && selectedFileId) return 'followup-metric';
|
||||
|
@ -42,7 +45,14 @@ export const useChatInputFlow = ({
|
|||
}, [hasChat, selectedFileType, selectedFileId]);
|
||||
|
||||
const onSubmitPreflight = useMemoizedFn(async () => {
|
||||
if (disableSubmit || !chatId || !currentMessageId) return;
|
||||
if (
|
||||
disableSubmit ||
|
||||
!chatId ||
|
||||
!currentMessageId ||
|
||||
submittingCooldown.current ||
|
||||
isSubmittingChat
|
||||
)
|
||||
return;
|
||||
|
||||
if (loading) {
|
||||
onStopChat();
|
||||
|
@ -52,6 +62,7 @@ export const useChatInputFlow = ({
|
|||
const trimmedInputValue = inputValue.trim();
|
||||
|
||||
const method = async () => {
|
||||
submittingCooldown.current = true;
|
||||
switch (flow) {
|
||||
case 'followup-chat':
|
||||
await onFollowUpChat({ prompt: trimmedInputValue, chatId });
|
||||
|
@ -89,6 +100,10 @@ export const useChatInputFlow = ({
|
|||
setTimeout(() => {
|
||||
textAreaRef.current?.focus();
|
||||
}, 50);
|
||||
|
||||
setTimeout(() => {
|
||||
submittingCooldown.current = false;
|
||||
}, 350);
|
||||
};
|
||||
|
||||
if (!isFileChanged) {
|
||||
|
|
Loading…
Reference in New Issue