Spaces:
Paused
Paused
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<IClientConversation>({} 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<SetStateAction<IClientConversation>>, | |
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, | |
}; | |
}; | |