import { MessageType } from '@/constants/chat'; import { useCreateSharedConversation, useFetchSharedConversation, } from '@/hooks/chat-hooks'; import { useSendMessageWithSse } from '@/hooks/logic-hooks'; import { useOneNamespaceEffectsLoading } from '@/hooks/store-hooks'; import { IAnswer } from '@/interfaces/database/chat'; import api from '@/utils/api'; import omit from 'lodash/omit'; import trim from 'lodash/trim'; import { Dispatch, SetStateAction, useCallback, useEffect, useState, } from 'react'; import { useSearchParams } from 'umi'; import { v4 as uuid } from 'uuid'; import { useHandleMessageInputChange, useScrollToBottom } from './hooks'; import { IClientConversation, IMessage } from './interface'; export const useCreateSharedConversationOnMount = () => { const [currentQueryParameters] = useSearchParams(); const [conversationId, setConversationId] = useState(''); const createConversation = useCreateSharedConversation(); const sharedId = currentQueryParameters.get('shared_id'); const userId = currentQueryParameters.get('user_id'); const setConversation = useCallback(async () => { console.info(sharedId); if (sharedId) { const data = await createConversation(userId ?? undefined); const id = data.data?.id; if (id) { setConversationId(id); } } }, [createConversation, sharedId, userId]); useEffect(() => { setConversation(); }, [setConversation]); return { conversationId }; }; export const useSelectCurrentSharedConversation = (conversationId: string) => { const [currentConversation, setCurrentConversation] = useState({} as IClientConversation); const fetchConversation = useFetchSharedConversation(); const loading = useOneNamespaceEffectsLoading('chatModel', [ 'getExternalConversation', ]); const ref = useScrollToBottom(currentConversation); const addNewestConversation = useCallback((message: string) => { setCurrentConversation((pre) => { return { ...pre, message: [ ...(pre.message ?? []), { role: MessageType.User, content: message, id: uuid(), } as IMessage, { role: MessageType.Assistant, content: '', id: uuid(), reference: [], } as IMessage, ], }; }); }, []); const addNewestAnswer = useCallback((answer: IAnswer) => { setCurrentConversation((pre) => { const latestMessage = pre.message?.at(-1); if (latestMessage) { return { ...pre, message: [ ...pre.message.slice(0, -1), { ...latestMessage, content: answer.answer, reference: answer.reference, } as IMessage, ], }; } return pre; }); }, []); const removeLatestMessage = useCallback(() => { setCurrentConversation((pre) => { const nextMessages = pre.message.slice(0, -2); return { ...pre, message: nextMessages, }; }); }, []); const fetchConversationOnMount = useCallback(async () => { if (conversationId) { const data = await fetchConversation(conversationId); if (data.retcode === 0) { setCurrentConversation(data.data); } } }, [conversationId, fetchConversation]); useEffect(() => { fetchConversationOnMount(); }, [fetchConversationOnMount]); return { currentConversation, addNewestConversation, removeLatestMessage, loading, ref, setCurrentConversation, addNewestAnswer, }; }; export const useSendButtonDisabled = (value: string) => { return trim(value) === ''; }; export const useSendSharedMessage = ( conversation: IClientConversation, addNewestConversation: (message: string) => void, removeLatestMessage: () => void, setCurrentConversation: Dispatch>, addNewestAnswer: (answer: IAnswer) => void, ) => { const conversationId = conversation.id; const setConversation = useCreateSharedConversation(); const { handleInputChange, value, setValue } = useHandleMessageInputChange(); const { send, answer, done } = useSendMessageWithSse( api.completeExternalConversation, ); const sendMessage = useCallback( async (message: string, id?: string) => { const res = await send({ conversation_id: id ?? conversationId, quote: false, messages: [ ...(conversation?.message ?? []).map((x: IMessage) => omit(x, 'id')), { role: MessageType.User, content: message, }, ], }); if (res && (res?.response.status !== 200 || res?.data?.retcode !== 0)) { // cancel loading setValue(message); removeLatestMessage(); } }, [ conversationId, conversation?.message, // fetchConversation, removeLatestMessage, setValue, send, // setCurrentConversation, ], ); const handleSendMessage = useCallback( async (message: string) => { if (conversationId !== '') { sendMessage(message); } else { const data = await setConversation('user id'); if (data.retcode === 0) { const id = data.data.id; sendMessage(message, id); } } }, [conversationId, setConversation, sendMessage], ); useEffect(() => { if (answer.answer) { addNewestAnswer(answer); } }, [answer, addNewestAnswer]); const handlePressEnter = useCallback(() => { if (trim(value) === '') return; if (done) { setValue(''); addNewestConversation(value); handleSendMessage(value.trim()); } }, [addNewestConversation, done, handleSendMessage, setValue, value]); return { handlePressEnter, handleInputChange, value, loading: !done, }; };