diff --git a/src/components/chat-view/ChatView.tsx b/src/components/chat-view/ChatView.tsx index 568b63a..b23c418 100644 --- a/src/components/chat-view/ChatView.tsx +++ b/src/components/chat-view/ChatView.tsx @@ -3,7 +3,7 @@ import * as path from 'path' import { BaseSerializedNode } from '@lexical/clipboard/clipboard' import { useMutation } from '@tanstack/react-query' import { CircleStop, History, NotebookPen, Plus, Search, Server, SquareSlash, Undo } from 'lucide-react' -import { App, Notice } from 'obsidian' +import { App, Notice, TFile, WorkspaceLeaf } from 'obsidian' import { forwardRef, useCallback, @@ -15,8 +15,9 @@ import { } from 'react' import { v4 as uuidv4 } from 'uuid' -import { ApplyViewState } from '../../ApplyView' +import { ApplyView, ApplyViewState } from '../../ApplyView' import { APPLY_VIEW_TYPE, PREVIEW_VIEW_TYPE } from '../../constants' +import { PreviewView } from '../../PreviewView' import { useApp } from '../../contexts/AppContext' import { useDiffStrategy } from '../../contexts/DiffStrategyContext' import { useLLM } from '../../contexts/LLMContext' @@ -181,7 +182,7 @@ const Chat = forwardRef((props, ref) => { const [tab, setTab] = useState<'chat' | 'commands' | 'custom-mode' | 'mcp' | 'search' | 'history'>('chat') const [selectedSerializedNodes, setSelectedSerializedNodes] = useState([]) - + // 跟踪正在编辑的消息ID const [editingMessageId, setEditingMessageId] = useState(null) @@ -854,6 +855,8 @@ const Chat = forwardRef((props, ref) => { useEffect(() => { setFocusedMessageId(inputMessage.id) + // 初始化当前活动文件引用 + currentActiveFileRef.current = app.workspace.getActiveFile() // eslint-disable-next-line react-hooks/exhaustive-deps }, []) @@ -871,20 +874,27 @@ const Chat = forwardRef((props, ref) => { updateConversationAsync() }, [currentConversationId, chatMessages, createOrUpdateConversation]) + // 保存当前活动文件的引用,用于比较是否真的发生了变化 + const currentActiveFileRef = useRef(null) + // Updates the currentFile of the focused message (input or chat history) // This happens when active file changes or focused message changes - const handleActiveLeafChange = useCallback(() => { - // 如果当前活动的是PreviewView或ApplyView,不更新状态以避免不必要的重新渲染 - // @ts-expect-error Obsidian API type mismatch - const activeLeaf = app.workspace.getActiveLeaf() - if (activeLeaf?.view && ( - activeLeaf.view.getViewType() === PREVIEW_VIEW_TYPE || - activeLeaf.view.getViewType() === APPLY_VIEW_TYPE - )) { + const handleActiveLeafChange = useCallback((leaf: WorkspaceLeaf | null) => { + // 过滤掉 ApplyView 和 PreviewView 的切换 + if ((leaf?.view instanceof ApplyView) || (leaf?.view instanceof PreviewView)) { return } const activeFile = app.workspace.getActiveFile() + + // 🎯 关键优化:只有当活动文件真正发生变化时才更新 + if (activeFile === currentActiveFileRef.current) { + return // 文件没有变化,不需要更新 + } + + // 更新文件引用 + currentActiveFileRef.current = activeFile + if (!activeFile) return const mentionable: Omit = { diff --git a/src/components/chat-view/Markdown/MermaidBlock.tsx b/src/components/chat-view/Markdown/MermaidBlock.tsx index 91a973c..1936747 100644 --- a/src/components/chat-view/Markdown/MermaidBlock.tsx +++ b/src/components/chat-view/Markdown/MermaidBlock.tsx @@ -1,5 +1,5 @@ import mermaid from "mermaid" -import { useEffect, useRef, useState } from "react" +import { memo, useEffect, useRef, useState } from "react" import styled from "styled-components" import { PREVIEW_VIEW_TYPE } from "../../../constants" @@ -76,7 +76,7 @@ interface MermaidBlockProps { code: string } -export default function MermaidBlock({ code }: MermaidBlockProps) { +function MermaidBlock({ code }: MermaidBlockProps) { const containerRef = useRef(null) const [isLoading, setIsLoading] = useState(false) const [error, setError] = useState(null) @@ -206,7 +206,8 @@ export default function MermaidBlock({ code }: MermaidBlockProps) { if (existingLeaf) { // 如果已存在,关闭现有的然后重新创建以更新内容 - existingLeaf.detach() + // existingLeaf.detach() + return } // 创建新的预览 tab @@ -391,3 +392,5 @@ const SvgContainer = styled.div` z-index: 10; } ` + +export const MemoizedMermaidBlock = memo(MermaidBlock) \ No newline at end of file diff --git a/src/components/chat-view/Markdown/RawMarkdownBlock.tsx b/src/components/chat-view/Markdown/RawMarkdownBlock.tsx index cf08597..684a3b4 100644 --- a/src/components/chat-view/Markdown/RawMarkdownBlock.tsx +++ b/src/components/chat-view/Markdown/RawMarkdownBlock.tsx @@ -5,7 +5,7 @@ import remarkGfm from 'remark-gfm' import { useDarkModeContext } from '../../../contexts/DarkModeContext' -import MermaidBlock from './MermaidBlock' +import { MemoizedMermaidBlock } from './MermaidBlock' import { MemoizedSyntaxHighlighterWrapper } from './SyntaxHighlighterWrapper' interface RawMarkdownBlockProps { @@ -34,7 +34,7 @@ export default function RawMarkdownBlock({ if (!isInline && language === 'mermaid') { const codeText = String(children || "") return ( - )