| allInputsHidden, | allInputsHidden, | ||||
| initUserVariables, | initUserVariables, | ||||
| } = useChatWithHistoryContext() | } = useChatWithHistoryContext() | ||||
| // Semantic variable for better code readability | |||||
| const isHistoryConversation = !!currentConversationId | |||||
| const appConfig = useMemo(() => { | const appConfig = useMemo(() => { | ||||
| const config = appParams || {} | const config = appParams || {} | ||||
| fileUploadConfig: (config as any).system_parameters, | fileUploadConfig: (config as any).system_parameters, | ||||
| }, | }, | ||||
| supportFeedback: true, | supportFeedback: true, | ||||
| opening_statement: currentConversationId ? currentConversationItem?.introduction : (config as any).opening_statement, | |||||
| opening_statement: isHistoryConversation ? currentConversationItem?.introduction : (config as any).opening_statement, | |||||
| } as ChatConfig | } as ChatConfig | ||||
| }, [appParams, currentConversationItem?.introduction, currentConversationId]) | |||||
| }, [appParams, currentConversationItem?.introduction, isHistoryConversation]) | |||||
| const { | const { | ||||
| chatList, | chatList, | ||||
| setTargetMessageId, | setTargetMessageId, | ||||
| } = useChat( | } = useChat( | ||||
| appConfig, | appConfig, | ||||
| { | { | ||||
| inputs: (currentConversationId ? currentConversationInputs : newConversationInputs) as any, | |||||
| inputs: (isHistoryConversation ? currentConversationInputs : newConversationInputs) as any, | |||||
| inputsForm: inputsForms, | inputsForm: inputsForms, | ||||
| }, | }, | ||||
| appPrevChatTree, | appPrevChatTree, | ||||
| clearChatList, | clearChatList, | ||||
| setClearChatList, | setClearChatList, | ||||
| ) | ) | ||||
| const inputsFormValue = currentConversationId ? currentConversationInputs : newConversationInputsRef?.current | |||||
| const inputsFormValue = isHistoryConversation ? currentConversationInputs : newConversationInputsRef?.current | |||||
| const inputDisabled = useMemo(() => { | const inputDisabled = useMemo(() => { | ||||
| if (allInputsHidden) | if (allInputsHidden) | ||||
| return false | return false | ||||
| const data: any = { | const data: any = { | ||||
| query: message, | query: message, | ||||
| files, | files, | ||||
| inputs: formatBooleanInputs(inputsForms, currentConversationId ? currentConversationInputs : newConversationInputs), | |||||
| inputs: formatBooleanInputs(inputsForms, isHistoryConversation ? currentConversationInputs : newConversationInputs), | |||||
| conversation_id: currentConversationId, | conversation_id: currentConversationId, | ||||
| parent_message_id: (isRegenerate ? parentAnswer?.id : getLastAnswer(chatList)?.id) || null, | parent_message_id: (isRegenerate ? parentAnswer?.id : getLastAnswer(chatList)?.id) || null, | ||||
| } | } | ||||
| data, | data, | ||||
| { | { | ||||
| onGetSuggestedQuestions: responseItemId => fetchSuggestedQuestions(responseItemId, isInstalledApp, appId), | onGetSuggestedQuestions: responseItemId => fetchSuggestedQuestions(responseItemId, isInstalledApp, appId), | ||||
| onConversationComplete: currentConversationId ? undefined : handleNewConversationCompleted, | |||||
| onConversationComplete: isHistoryConversation ? undefined : handleNewConversationCompleted, | |||||
| isPublicAPI: !isInstalledApp, | isPublicAPI: !isInstalledApp, | ||||
| }, | }, | ||||
| ) | ) | ||||
| }, [chatList, handleNewConversationCompleted, handleSend, currentConversationId, currentConversationInputs, newConversationInputs, isInstalledApp, appId]) | |||||
| }, [chatList, handleNewConversationCompleted, handleSend, isHistoryConversation, currentConversationInputs, newConversationInputs, isInstalledApp, appId]) | |||||
| const doRegenerate = useCallback((chatItem: ChatItemInTree, editedQuestion?: { message: string, files?: FileEntity[] }) => { | const doRegenerate = useCallback((chatItem: ChatItemInTree, editedQuestion?: { message: string, files?: FileEntity[] }) => { | ||||
| const question = editedQuestion ? chatItem : chatList.find(item => item.id === chatItem.parentMessageId)! | const question = editedQuestion ? chatItem : chatList.find(item => item.id === chatItem.parentMessageId)! | ||||
| }, [chatList, doSend]) | }, [chatList, doSend]) | ||||
| const messageList = useMemo(() => { | const messageList = useMemo(() => { | ||||
| if (currentConversationId) | |||||
| return chatList | |||||
| // Always filter out opening statement from message list as it's handled separately in welcome component | |||||
| return chatList.filter(item => !item.isOpeningStatement) | return chatList.filter(item => !item.isOpeningStatement) | ||||
| }, [chatList, currentConversationId]) | |||||
| }, [chatList]) | |||||
| const [collapsed, setCollapsed] = useState(!!currentConversationId) | |||||
| const [collapsed, setCollapsed] = useState(isHistoryConversation) | |||||
| const chatNode = useMemo(() => { | const chatNode = useMemo(() => { | ||||
| if (allInputsHidden || !inputsForms.length) | if (allInputsHidden || !inputsForms.length) | ||||
| return null | return null | ||||
| if (isMobile) { | if (isMobile) { | ||||
| if (!currentConversationId) | |||||
| if (!isHistoryConversation) | |||||
| return <InputsForm collapsed={collapsed} setCollapsed={setCollapsed} /> | return <InputsForm collapsed={collapsed} setCollapsed={setCollapsed} /> | ||||
| return null | return null | ||||
| } | } | ||||
| else { | else { | ||||
| return <InputsForm collapsed={collapsed} setCollapsed={setCollapsed} /> | return <InputsForm collapsed={collapsed} setCollapsed={setCollapsed} /> | ||||
| } | } | ||||
| }, [inputsForms.length, isMobile, currentConversationId, collapsed, allInputsHidden]) | |||||
| }, [inputsForms.length, isMobile, isHistoryConversation, collapsed, allInputsHidden]) | |||||
| const welcome = useMemo(() => { | const welcome = useMemo(() => { | ||||
| const welcomeMessage = chatList.find(item => item.isOpeningStatement) | const welcomeMessage = chatList.find(item => item.isOpeningStatement) | ||||
| if (respondingState) | if (respondingState) | ||||
| return null | return null | ||||
| if (currentConversationId) | |||||
| if (isHistoryConversation) | |||||
| return null | return null | ||||
| if (!welcomeMessage) | if (!welcomeMessage) | ||||
| return null | return null | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| ) | ) | ||||
| }, [appData?.site.icon, appData?.site.icon_background, appData?.site.icon_type, appData?.site.icon_url, chatList, collapsed, currentConversationId, inputsForms.length, respondingState, allInputsHidden]) | |||||
| }, [appData?.site.icon, appData?.site.icon_background, appData?.site.icon_type, appData?.site.icon_url, chatList, collapsed, isHistoryConversation, inputsForms.length, respondingState, allInputsHidden]) | |||||
| const answerIcon = (appData?.site && appData.site.use_icon_as_answer_icon) | const answerIcon = (appData?.site && appData.site.use_icon_as_answer_icon) | ||||
| ? <AnswerIcon | ? <AnswerIcon | ||||
| chatFooterClassName='pb-4' | chatFooterClassName='pb-4' | ||||
| chatFooterInnerClassName={`mx-auto w-full max-w-[768px] ${isMobile ? 'px-2' : 'px-4'}`} | chatFooterInnerClassName={`mx-auto w-full max-w-[768px] ${isMobile ? 'px-2' : 'px-4'}`} | ||||
| onSend={doSend} | onSend={doSend} | ||||
| inputs={currentConversationId ? currentConversationInputs as any : newConversationInputs} | |||||
| inputs={isHistoryConversation ? currentConversationInputs as any : newConversationInputs} | |||||
| inputsForm={inputsForms} | inputsForm={inputsForms} | ||||
| onRegenerate={doRegenerate} | onRegenerate={doRegenerate} | ||||
| onStopResponding={handleStop} | onStopResponding={handleStop} |