|
@@ -14,7 +14,7 @@ import { ToastContext } from '@/app/components/base/toast'
|
|
|
import Sidebar from '@/app/components/share/chat/sidebar'
|
|
|
import ConfigSence from '@/app/components/share/chat/config-scence'
|
|
|
import Header from '@/app/components/share/header'
|
|
|
-import { fetchAppInfo, fetchAppParams, fetchChatList, fetchConversations, fetchSuggestedQuestions, sendChatMessage, stopChatMessageResponding, updateFeedback } from '@/service/share'
|
|
|
+import { delConversation, fetchAppInfo, fetchAppParams, fetchChatList, fetchConversations, fetchSuggestedQuestions, pinConversation, sendChatMessage, stopChatMessageResponding, unpinConversation, updateFeedback } from '@/service/share'
|
|
|
import type { ConversationItem, SiteInfo } from '@/models/share'
|
|
|
import type { PromptConfig, SuggestedQuestionsAfterAnswerConfig } from '@/models/debug'
|
|
|
import type { Feedbacktype, IChatItem } from '@/app/components/app/chat'
|
|
@@ -25,6 +25,7 @@ import Loading from '@/app/components/base/loading'
|
|
|
import { replaceStringWithValues } from '@/app/components/app/configuration/prompt-value-panel'
|
|
|
import { userInputsFormToPromptVariables } from '@/utils/model-config'
|
|
|
import type { InstalledApp } from '@/models/explore'
|
|
|
+import Confirm from '@/app/components/base/confirm'
|
|
|
|
|
|
export type IMainProps = {
|
|
|
isInstalledApp?: boolean
|
|
@@ -65,9 +66,12 @@ const Main: FC<IMainProps> = ({
|
|
|
/*
|
|
|
* conversation info
|
|
|
*/
|
|
|
+ const [allConversationList, setAllConversationList] = useState<ConversationItem[]>([])
|
|
|
const {
|
|
|
conversationList,
|
|
|
setConversationList,
|
|
|
+ pinnedConversationList,
|
|
|
+ setPinnedConversationList,
|
|
|
currConversationId,
|
|
|
setCurrConversationId,
|
|
|
getConversationIdFromStorage,
|
|
@@ -81,11 +85,50 @@ const Main: FC<IMainProps> = ({
|
|
|
setNewConversationInfo,
|
|
|
setExistConversationInfo,
|
|
|
} = useConversation()
|
|
|
- const [hasMore, setHasMore] = useState<boolean>(false)
|
|
|
+ const [hasMore, setHasMore] = useState<boolean>(true)
|
|
|
+ const [hasPinnedMore, setHasPinnedMore] = useState<boolean>(true)
|
|
|
const onMoreLoaded = ({ data: conversations, has_more }: any) => {
|
|
|
setHasMore(has_more)
|
|
|
setConversationList([...conversationList, ...conversations])
|
|
|
}
|
|
|
+ const onPinnedMoreLoaded = ({ data: conversations, has_more }: any) => {
|
|
|
+ setHasPinnedMore(has_more)
|
|
|
+ setPinnedConversationList([...pinnedConversationList, ...conversations])
|
|
|
+ }
|
|
|
+ const [controlUpdateConversationList, setControlUpdateConversationList] = useState(0)
|
|
|
+ const noticeUpdateList = () => {
|
|
|
+ setConversationList([])
|
|
|
+ setHasMore(true)
|
|
|
+ setPinnedConversationList([])
|
|
|
+ setHasPinnedMore(true)
|
|
|
+ setControlUpdateConversationList(Date.now())
|
|
|
+ }
|
|
|
+ const handlePin = async (id: string) => {
|
|
|
+ await pinConversation(isInstalledApp, installedAppInfo?.id, id)
|
|
|
+ notify({ type: 'success', message: t('common.api.success') })
|
|
|
+ noticeUpdateList()
|
|
|
+ }
|
|
|
+
|
|
|
+ const handleUnpin = async (id: string) => {
|
|
|
+ await unpinConversation(isInstalledApp, installedAppInfo?.id, id)
|
|
|
+ notify({ type: 'success', message: t('common.api.success') })
|
|
|
+ noticeUpdateList()
|
|
|
+ }
|
|
|
+ const [isShowConfirm, { setTrue: showConfirm, setFalse: hideConfirm }] = useBoolean(false)
|
|
|
+ const [toDeleteConversationId, setToDeleteConversationId] = useState('')
|
|
|
+ const handleDelete = (id: string) => {
|
|
|
+ setToDeleteConversationId(id)
|
|
|
+ hideSidebar() // mobile
|
|
|
+ showConfirm()
|
|
|
+ }
|
|
|
+
|
|
|
+ const didDelete = async () => {
|
|
|
+ await delConversation(isInstalledApp, installedAppInfo?.id, toDeleteConversationId)
|
|
|
+ notify({ type: 'success', message: t('common.api.success') })
|
|
|
+ hideConfirm()
|
|
|
+ noticeUpdateList()
|
|
|
+ }
|
|
|
+
|
|
|
const [suggestedQuestionsAfterAnswerConfig, setSuggestedQuestionsAfterAnswerConfig] = useState<SuggestedQuestionsAfterAnswerConfig | null>(null)
|
|
|
|
|
|
const [conversationIdChangeBecauseOfNew, setConversationIdChangeBecauseOfNew, getConversationIdChangeBecauseOfNew] = useGetState(false)
|
|
@@ -121,7 +164,7 @@ const Main: FC<IMainProps> = ({
|
|
|
let notSyncToStateIntroduction = ''
|
|
|
let notSyncToStateInputs: Record<string, any> | undefined | null = {}
|
|
|
if (!isNewConversation) {
|
|
|
- const item = conversationList.find(item => item.id === currConversationId)
|
|
|
+ const item = allConversationList.find(item => item.id === currConversationId)
|
|
|
notSyncToStateInputs = item?.inputs || {}
|
|
|
setCurrInputs(notSyncToStateInputs)
|
|
|
notSyncToStateIntroduction = item?.introduction || ''
|
|
@@ -229,6 +272,10 @@ const Main: FC<IMainProps> = ({
|
|
|
return []
|
|
|
}
|
|
|
|
|
|
+ const fetchAllConversations = () => {
|
|
|
+ return fetchConversations(isInstalledApp, installedAppInfo?.id, undefined, undefined, 100)
|
|
|
+ }
|
|
|
+
|
|
|
const fetchInitData = () => {
|
|
|
return Promise.all([isInstalledApp
|
|
|
? {
|
|
@@ -240,7 +287,7 @@ const Main: FC<IMainProps> = ({
|
|
|
},
|
|
|
plan: 'basic',
|
|
|
}
|
|
|
- : fetchAppInfo(), fetchConversations(isInstalledApp, installedAppInfo?.id), fetchAppParams(isInstalledApp, installedAppInfo?.id)])
|
|
|
+ : fetchAppInfo(), fetchAllConversations(), fetchAppParams(isInstalledApp, installedAppInfo?.id)])
|
|
|
}
|
|
|
|
|
|
// init
|
|
@@ -255,10 +302,10 @@ const Main: FC<IMainProps> = ({
|
|
|
setIsPublicVersion(tempIsPublicVersion)
|
|
|
const prompt_template = ''
|
|
|
// handle current conversation id
|
|
|
- const { data: conversations, has_more } = conversationData as { data: ConversationItem[]; has_more: boolean }
|
|
|
+ const { data: allConversations } = conversationData as { data: ConversationItem[]; has_more: boolean }
|
|
|
const _conversationId = getConversationIdFromStorage(appId)
|
|
|
- const isNotNewConversation = conversations.some(item => item.id === _conversationId)
|
|
|
- setHasMore(has_more)
|
|
|
+ const isNotNewConversation = allConversations.some(item => item.id === _conversationId)
|
|
|
+ setAllConversationList(allConversations)
|
|
|
// fetch new conversation info
|
|
|
const { user_input_form, opening_statement: introduction, suggested_questions_after_answer }: any = appParams
|
|
|
const prompt_variables = userInputsFormToPromptVariables(user_input_form)
|
|
@@ -276,7 +323,7 @@ const Main: FC<IMainProps> = ({
|
|
|
} as PromptConfig)
|
|
|
setSuggestedQuestionsAfterAnswerConfig(suggested_questions_after_answer)
|
|
|
|
|
|
- setConversationList(conversations as ConversationItem[])
|
|
|
+ // setConversationList(conversations as ConversationItem[])
|
|
|
|
|
|
if (isNotNewConversation)
|
|
|
setCurrConversationId(_conversationId, appId, false)
|
|
@@ -403,12 +450,10 @@ const Main: FC<IMainProps> = ({
|
|
|
if (hasError)
|
|
|
return
|
|
|
|
|
|
- let currChatList = conversationList
|
|
|
if (getConversationIdChangeBecauseOfNew()) {
|
|
|
- const { data: conversations, has_more }: any = await fetchConversations(isInstalledApp, installedAppInfo?.id)
|
|
|
- setHasMore(has_more)
|
|
|
- setConversationList(conversations as ConversationItem[])
|
|
|
- currChatList = conversations
|
|
|
+ const { data: allConversations }: any = await fetchAllConversations()
|
|
|
+ setAllConversationList(allConversations)
|
|
|
+ noticeUpdateList()
|
|
|
}
|
|
|
setConversationIdChangeBecauseOfNew(false)
|
|
|
resetNewConversationInputs()
|
|
@@ -451,14 +496,21 @@ const Main: FC<IMainProps> = ({
|
|
|
return (
|
|
|
<Sidebar
|
|
|
list={conversationList}
|
|
|
+ pinnedList={pinnedConversationList}
|
|
|
onMoreLoaded={onMoreLoaded}
|
|
|
+ onPinnedMoreLoaded={onPinnedMoreLoaded}
|
|
|
isNoMore={!hasMore}
|
|
|
+ isPinnedNoMore={!hasPinnedMore}
|
|
|
onCurrentIdChange={handleConversationIdChange}
|
|
|
currentId={currConversationId}
|
|
|
copyRight={siteInfo.copyright || siteInfo.title}
|
|
|
isInstalledApp={isInstalledApp}
|
|
|
installedAppId={installedAppInfo?.id}
|
|
|
siteInfo={siteInfo}
|
|
|
+ onPin={handlePin}
|
|
|
+ onUnpin={handleUnpin}
|
|
|
+ controlUpdateList={controlUpdateConversationList}
|
|
|
+ onDelete={handleDelete}
|
|
|
/>
|
|
|
)
|
|
|
}
|
|
@@ -482,9 +534,6 @@ const Main: FC<IMainProps> = ({
|
|
|
/>
|
|
|
)}
|
|
|
|
|
|
- {/* {isNewConversation ? 'new' : 'exist'}
|
|
|
- {JSON.stringify(newConversationInputs ? newConversationInputs : {})}
|
|
|
- {JSON.stringify(existConversationInputs ? existConversationInputs : {})} */}
|
|
|
<div
|
|
|
className={cn(
|
|
|
'flex rounded-t-2xl bg-white overflow-hidden',
|
|
@@ -551,6 +600,17 @@ const Main: FC<IMainProps> = ({
|
|
|
</div>
|
|
|
</div>)
|
|
|
}
|
|
|
+
|
|
|
+ {isShowConfirm && (
|
|
|
+ <Confirm
|
|
|
+ title={t('share.chat.deleteConversation.title')}
|
|
|
+ content={t('share.chat.deleteConversation.content')}
|
|
|
+ isShow={isShowConfirm}
|
|
|
+ onClose={hideConfirm}
|
|
|
+ onConfirm={didDelete}
|
|
|
+ onCancel={hideConfirm}
|
|
|
+ />
|
|
|
+ )}
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|