diff --git a/web/app/components/app/log/list.tsx b/web/app/components/app/log/list.tsx index 258d06ac79..8b3370b678 100644 --- a/web/app/components/app/log/list.tsx +++ b/web/app/components/app/log/list.tsx @@ -14,7 +14,6 @@ import timezone from 'dayjs/plugin/timezone' import { createContext, useContext } from 'use-context-selector' import { useShallow } from 'zustand/react/shallow' import { useTranslation } from 'react-i18next' -import { usePathname, useRouter, useSearchParams } from 'next/navigation' import type { ChatItemInTree } from '../../base/chat/types' import Indicator from '../../header/indicator' import VarPanel from './var-panel' @@ -43,10 +42,6 @@ import cn from '@/utils/classnames' import { noop } from 'lodash-es' import PromptLogModal from '../../base/prompt-log-modal' -type AppStoreState = ReturnType -type ConversationListItem = ChatConversationGeneralDetail | CompletionConversationGeneralDetail -type ConversationSelection = ConversationListItem | { id: string; isPlaceholder?: true } - dayjs.extend(utc) dayjs.extend(timezone) @@ -206,7 +201,7 @@ function DetailPanel({ detail, onFeedback }: IDetailPanel) { const { formatTime } = useTimestamp() const { onClose, appDetail } = useContext(DrawerContext) const { notify } = useContext(ToastContext) - const { currentLogItem, setCurrentLogItem, showMessageLogModal, setShowMessageLogModal, showPromptLogModal, setShowPromptLogModal, currentLogModalActiveTab } = useAppStore(useShallow((state: AppStoreState) => ({ + const { currentLogItem, setCurrentLogItem, showMessageLogModal, setShowMessageLogModal, showPromptLogModal, setShowPromptLogModal, currentLogModalActiveTab } = useAppStore(useShallow(state => ({ currentLogItem: state.currentLogItem, setCurrentLogItem: state.setCurrentLogItem, showMessageLogModal: state.showMessageLogModal, @@ -898,113 +893,20 @@ const ChatConversationDetailComp: FC<{ appId?: string; conversationId?: string } const ConversationList: FC = ({ logs, appDetail, onRefresh }) => { const { t } = useTranslation() const { formatTime } = useTimestamp() - const router = useRouter() - const pathname = usePathname() - const searchParams = useSearchParams() - const conversationIdInUrl = searchParams.get('conversation_id') ?? undefined const media = useBreakpoints() const isMobile = media === MediaType.mobile const [showDrawer, setShowDrawer] = useState(false) // Whether to display the chat details drawer - const [currentConversation, setCurrentConversation] = useState() // Currently selected conversation - const closingConversationIdRef = useRef(null) - const pendingConversationIdRef = useRef(null) - const pendingConversationCacheRef = useRef(undefined) + const [currentConversation, setCurrentConversation] = useState() // Currently selected conversation const isChatMode = appDetail.mode !== 'completion' // Whether the app is a chat app const isChatflow = appDetail.mode === 'advanced-chat' // Whether the app is a chatflow app - const { setShowPromptLogModal, setShowAgentLogModal, setShowMessageLogModal } = useAppStore(useShallow((state: AppStoreState) => ({ + const { setShowPromptLogModal, setShowAgentLogModal, setShowMessageLogModal } = useAppStore(useShallow(state => ({ setShowPromptLogModal: state.setShowPromptLogModal, setShowAgentLogModal: state.setShowAgentLogModal, setShowMessageLogModal: state.setShowMessageLogModal, }))) - const activeConversationId = conversationIdInUrl ?? pendingConversationIdRef.current ?? currentConversation?.id - - const buildUrlWithConversation = useCallback((conversationId?: string) => { - const params = new URLSearchParams(searchParams.toString()) - if (conversationId) - params.set('conversation_id', conversationId) - else - params.delete('conversation_id') - - const queryString = params.toString() - return queryString ? `${pathname}?${queryString}` : pathname - }, [pathname, searchParams]) - - const handleRowClick = useCallback((log: ConversationListItem) => { - if (conversationIdInUrl === log.id) { - if (!showDrawer) - setShowDrawer(true) - - if (!currentConversation || currentConversation.id !== log.id) - setCurrentConversation(log) - return - } - - pendingConversationIdRef.current = log.id - pendingConversationCacheRef.current = log - if (!showDrawer) - setShowDrawer(true) - - if (currentConversation?.id !== log.id) - setCurrentConversation(undefined) - - router.push(buildUrlWithConversation(log.id), { scroll: false }) - }, [buildUrlWithConversation, conversationIdInUrl, currentConversation, router, showDrawer]) - - const currentConversationId = currentConversation?.id - - useEffect(() => { - if (!conversationIdInUrl) { - if (pendingConversationIdRef.current) - return - - if (showDrawer || currentConversationId) { - setShowDrawer(false) - setCurrentConversation(undefined) - } - closingConversationIdRef.current = null - pendingConversationCacheRef.current = undefined - return - } - - if (closingConversationIdRef.current === conversationIdInUrl) - return - - if (pendingConversationIdRef.current === conversationIdInUrl) - pendingConversationIdRef.current = null - - const matchedConversation = logs?.data?.find((item: ConversationListItem) => item.id === conversationIdInUrl) - const nextConversation: ConversationSelection = matchedConversation - ?? pendingConversationCacheRef.current - ?? { id: conversationIdInUrl, isPlaceholder: true } - - if (!showDrawer) - setShowDrawer(true) - - if (!currentConversation || currentConversation.id !== conversationIdInUrl || (matchedConversation && currentConversation !== matchedConversation)) - setCurrentConversation(nextConversation) - - if (pendingConversationCacheRef.current?.id === conversationIdInUrl || matchedConversation) - pendingConversationCacheRef.current = undefined - }, [conversationIdInUrl, currentConversation, isChatMode, logs?.data, showDrawer]) - - const onCloseDrawer = useCallback(() => { - onRefresh() - setShowDrawer(false) - setCurrentConversation(undefined) - setShowPromptLogModal(false) - setShowAgentLogModal(false) - setShowMessageLogModal(false) - pendingConversationIdRef.current = null - pendingConversationCacheRef.current = undefined - closingConversationIdRef.current = conversationIdInUrl ?? null - - if (conversationIdInUrl) - router.replace(buildUrlWithConversation(), { scroll: false }) - }, [buildUrlWithConversation, conversationIdInUrl, onRefresh, router, setShowAgentLogModal, setShowMessageLogModal, setShowPromptLogModal]) - // Annotated data needs to be highlighted const renderTdValue = (value: string | number | null, isEmptyStyle: boolean, isHighlight = false, annotation?: LogAnnotation) => { return ( @@ -1023,6 +925,15 @@ const ConversationList: FC = ({ logs, appDetail, onRefresh }) ) } + const onCloseDrawer = () => { + onRefresh() + setShowDrawer(false) + setCurrentConversation(undefined) + setShowPromptLogModal(false) + setShowAgentLogModal(false) + setShowMessageLogModal(false) + } + if (!logs) return @@ -1049,8 +960,11 @@ const ConversationList: FC = ({ logs, appDetail, onRefresh }) const rightValue = get(log, isChatMode ? 'message_count' : 'message.answer') return handleRowClick(log)}> + className={cn('cursor-pointer border-b border-divider-subtle hover:bg-background-default-hover', currentConversation?.id !== log.id ? '' : 'bg-background-default-hover')} + onClick={() => { + setShowDrawer(true) + setCurrentConversation(log) + }}> {!log.read_at && (