Optimize chat performance by reducing animations in inactive tabs
• Add isTabActive prop to ChatMessage
• Disable spinner in inactive tabs
• Reduce opacity for inactive content
• Hide loading indicator when inactive
• Pass tab state from RetrievalTesting
(cherry picked from commit dab1c35834)
This commit is contained in:
parent
e138c3a11e
commit
7404f76d8c
2 changed files with 23 additions and 31 deletions
|
|
@ -45,7 +45,13 @@ export type MessageWithError = Message & {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore original component definition and export
|
// Restore original component definition and export
|
||||||
export const ChatMessage = ({ message }: { message: MessageWithError }) => { // Remove isComplete prop
|
export const ChatMessage = ({
|
||||||
|
message,
|
||||||
|
isTabActive = true
|
||||||
|
}: {
|
||||||
|
message: MessageWithError
|
||||||
|
isTabActive?: boolean
|
||||||
|
}) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { theme } = useTheme()
|
const { theme } = useTheme()
|
||||||
const [katexPlugin, setKatexPlugin] = useState<((options?: KaTeXOptions) => any) | null>(null)
|
const [katexPlugin, setKatexPlugin] = useState<((options?: KaTeXOptions) => any) | null>(null)
|
||||||
|
|
@ -152,8 +158,13 @@ export const ChatMessage = ({ message }: { message: MessageWithError }) => { //
|
||||||
} rounded-lg px-4 py-2`}
|
} rounded-lg px-4 py-2`}
|
||||||
>
|
>
|
||||||
{/* Thinking process display - only for assistant messages */}
|
{/* Thinking process display - only for assistant messages */}
|
||||||
|
{/* Always render to prevent layout shift when switching tabs */}
|
||||||
{message.role === 'assistant' && (isThinking || thinkingTime !== null) && (
|
{message.role === 'assistant' && (isThinking || thinkingTime !== null) && (
|
||||||
<div className="mb-2">
|
<div className={cn(
|
||||||
|
'mb-2',
|
||||||
|
// Reduce visual priority in inactive tabs while maintaining layout
|
||||||
|
!isTabActive && 'opacity-50'
|
||||||
|
)}>
|
||||||
<div
|
<div
|
||||||
className="flex items-center text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition-colors duration-200 text-sm cursor-pointer select-none"
|
className="flex items-center text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition-colors duration-200 text-sm cursor-pointer select-none"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
@ -165,7 +176,8 @@ export const ChatMessage = ({ message }: { message: MessageWithError }) => { //
|
||||||
>
|
>
|
||||||
{isThinking ? (
|
{isThinking ? (
|
||||||
<>
|
<>
|
||||||
<LoaderIcon className="mr-2 size-4 animate-spin" />
|
{/* Only show spinner animation in active tab to save resources */}
|
||||||
|
{isTabActive && <LoaderIcon className="mr-2 size-4 animate-spin" />}
|
||||||
<span>{t('retrievePanel.chatMessage.thinking')}</span>
|
<span>{t('retrievePanel.chatMessage.thinking')}</span>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -251,11 +263,12 @@ export const ChatMessage = ({ message }: { message: MessageWithError }) => { //
|
||||||
</ReactMarkdown>
|
</ReactMarkdown>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{(() => {
|
{/* Loading indicator - only show in active tab */}
|
||||||
|
{isTabActive && (() => {
|
||||||
// More comprehensive loading state check
|
// More comprehensive loading state check
|
||||||
const hasVisibleContent = finalDisplayContent && finalDisplayContent.trim() !== '';
|
const hasVisibleContent = finalDisplayContent && finalDisplayContent.trim() !== '';
|
||||||
const isLoadingState = !hasVisibleContent && !isThinking && !thinkingTime;
|
const isLoadingState = !hasVisibleContent && !isThinking && !thinkingTime;
|
||||||
return isLoadingState && <LoaderIcon className="animate-spin duration-2000" />;
|
return isLoadingState && <LoaderIcon className="animate-spin duration-2000" />
|
||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import { throttle } from '@/lib/utils'
|
||||||
import { queryText, queryTextStream } from '@/api/lightrag'
|
import { queryText, queryTextStream } from '@/api/lightrag'
|
||||||
import { errorMessage } from '@/lib/utils'
|
import { errorMessage } from '@/lib/utils'
|
||||||
import { useSettingsStore } from '@/stores/settings'
|
import { useSettingsStore } from '@/stores/settings'
|
||||||
import { useTenantState } from '@/stores/tenant'
|
|
||||||
import { useDebounce } from '@/hooks/useDebounce'
|
import { useDebounce } from '@/hooks/useDebounce'
|
||||||
import QuerySettings from '@/components/retrieval/QuerySettings'
|
import QuerySettings from '@/components/retrieval/QuerySettings'
|
||||||
import { ChatMessage, MessageWithError } from '@/components/retrieval/ChatMessage'
|
import { ChatMessage, MessageWithError } from '@/components/retrieval/ChatMessage'
|
||||||
|
|
@ -104,8 +103,10 @@ const parseCOTContent = (content: string) => {
|
||||||
|
|
||||||
export default function RetrievalTesting() {
|
export default function RetrievalTesting() {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const selectedTenant = useTenantState.use.selectedTenant()
|
// Get current tab to determine if this tab is active (for performance optimization)
|
||||||
const selectedKB = useTenantState.use.selectedKB()
|
const currentTab = useSettingsStore.use.currentTab()
|
||||||
|
const isRetrievalTabActive = currentTab === 'retrieval'
|
||||||
|
|
||||||
const [messages, setMessages] = useState<MessageWithError[]>(() => {
|
const [messages, setMessages] = useState<MessageWithError[]>(() => {
|
||||||
try {
|
try {
|
||||||
const history = useSettingsStore.getState().retrievalHistory || []
|
const history = useSettingsStore.getState().retrievalHistory || []
|
||||||
|
|
@ -614,17 +615,6 @@ export default function RetrievalTesting() {
|
||||||
}
|
}
|
||||||
}, [debouncedMessages, scrollToBottom])
|
}, [debouncedMessages, scrollToBottom])
|
||||||
|
|
||||||
// Clear retrieval history when tenant or KB changes to prevent showing stale data
|
|
||||||
useEffect(() => {
|
|
||||||
// Clear messages and retrieval history to ensure we don't show results from other tenants/KBs
|
|
||||||
setMessages([])
|
|
||||||
useSettingsStore.getState().setRetrievalHistory([])
|
|
||||||
console.log('[RetrievalTesting] Cleared retrieval history due to tenant/KB change:', {
|
|
||||||
tenant_id: selectedTenant?.tenant_id,
|
|
||||||
kb_id: selectedKB?.kb_id
|
|
||||||
})
|
|
||||||
}, [selectedTenant?.tenant_id, selectedKB?.kb_id])
|
|
||||||
|
|
||||||
|
|
||||||
const clearMessages = useCallback(() => {
|
const clearMessages = useCallback(() => {
|
||||||
setMessages([])
|
setMessages([])
|
||||||
|
|
@ -693,17 +683,6 @@ export default function RetrievalTesting() {
|
||||||
}
|
}
|
||||||
}, [t])
|
}, [t])
|
||||||
|
|
||||||
if (!selectedKB) {
|
|
||||||
return (
|
|
||||||
<div className="flex size-full items-center justify-center">
|
|
||||||
<div className="text-center text-muted-foreground">
|
|
||||||
<p className="text-lg font-medium">Please select a Knowledge Base to start chatting</p>
|
|
||||||
<p className="text-sm mt-2">Use the selector in the top header</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex size-full gap-2 px-2 pb-12 overflow-hidden">
|
<div className="flex size-full gap-2 px-2 pb-12 overflow-hidden">
|
||||||
<div className="flex grow flex-col gap-4">
|
<div className="flex grow flex-col gap-4">
|
||||||
|
|
@ -741,7 +720,7 @@ export default function RetrievalTesting() {
|
||||||
<CopyIcon className="size-4" />
|
<CopyIcon className="size-4" />
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
<ChatMessage message={message} />
|
<ChatMessage message={message} isTabActive={isRetrievalTabActive} />
|
||||||
{message.role === 'assistant' && (
|
{message.role === 'assistant' && (
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleCopyMessage(message)}
|
onClick={() => handleCopyMessage(message)}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue