refactor(Inputbar, Markdown): optimize citation handling and improve performance
- Refactored AttachmentButton to use useMemo for extensions calculation. - Simplified citation extraction in Markdown by moving logic to a new utility function. - Updated TopicsTab dependencies for better performance and reactivity.
This commit is contained in:
parent
8501ab82c6
commit
d74f05f27e
@ -3,7 +3,7 @@ import { isVisionModel } from '@renderer/config/models'
|
||||
import { FileType, Model } from '@renderer/types'
|
||||
import { documentExts, imageExts, textExts } from '@shared/config/constant'
|
||||
import { Tooltip } from 'antd'
|
||||
import { FC, useCallback, useImperativeHandle } from 'react'
|
||||
import { FC, useCallback, useImperativeHandle, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
export interface AttachmentButtonRef {
|
||||
@ -21,9 +21,11 @@ interface Props {
|
||||
|
||||
const AttachmentButton: FC<Props> = ({ ref, model, files, setFiles, ToolbarButton, disabled }) => {
|
||||
const { t } = useTranslation()
|
||||
const extensions = isVisionModel(model)
|
||||
? [...imageExts, ...documentExts, ...textExts]
|
||||
: [...documentExts, ...textExts]
|
||||
|
||||
const extensions = useMemo(
|
||||
() => (isVisionModel(model) ? [...imageExts, ...documentExts, ...textExts] : [...documentExts, ...textExts]),
|
||||
[model]
|
||||
)
|
||||
|
||||
const onSelectFile = useCallback(async () => {
|
||||
const _files = await window.api.file.select({
|
||||
@ -39,7 +41,7 @@ const AttachmentButton: FC<Props> = ({ ref, model, files, setFiles, ToolbarButto
|
||||
if (_files) {
|
||||
setFiles([...files, ..._files])
|
||||
}
|
||||
}, [files, setFiles])
|
||||
}, [extensions, files, setFiles])
|
||||
|
||||
const openQuickPanel = useCallback(() => {
|
||||
onSelectFile()
|
||||
|
||||
@ -5,7 +5,9 @@ import 'katex/dist/contrib/mhchem'
|
||||
import MarkdownShadowDOMRenderer from '@renderer/components/MarkdownShadowDOMRenderer'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import type { Message } from '@renderer/types'
|
||||
import { parseJSON } from '@renderer/utils'
|
||||
import { escapeBrackets, removeSvgEmptyLines, withGeminiGrounding } from '@renderer/utils/formats'
|
||||
import { findCitationInChildren } from '@renderer/utils/markdown'
|
||||
import { isEmpty } from 'lodash'
|
||||
import { type FC, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -51,44 +53,13 @@ const Markdown: FC<Props> = ({ message }) => {
|
||||
|
||||
const components = useMemo(() => {
|
||||
const baseComponents = {
|
||||
a: (props: any) => {
|
||||
// 更彻底的查找方法,递归搜索所有子元素
|
||||
const findCitationInChildren = (children) => {
|
||||
if (!children) return null
|
||||
|
||||
// 直接搜索子元素
|
||||
for (const child of Array.isArray(children) ? children : [children]) {
|
||||
if (typeof child === 'object' && child?.props?.['data-citation']) {
|
||||
return child.props['data-citation']
|
||||
}
|
||||
|
||||
// 递归查找更深层次
|
||||
if (typeof child === 'object' && child?.props?.children) {
|
||||
const found = findCitationInChildren(child.props.children)
|
||||
if (found) return found
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
// 然后在组件中使用
|
||||
const citationData = findCitationInChildren(props.children)
|
||||
if (citationData) {
|
||||
try {
|
||||
return <Link {...props} citationData={JSON.parse(citationData)} />
|
||||
} catch (e) {
|
||||
console.error('Failed to parse citation data', e)
|
||||
}
|
||||
}
|
||||
return <Link {...props} />
|
||||
},
|
||||
a: (props: any) => <Link {...props} citationData={parseJSON(findCitationInChildren(props.children))} />,
|
||||
code: CodeBlock,
|
||||
img: ImagePreview,
|
||||
pre: (props: any) => <pre style={{ overflow: 'visible' }} {...props} />
|
||||
} as Partial<Components>
|
||||
return baseComponents
|
||||
}, [messageContent])
|
||||
}, [])
|
||||
|
||||
if (message.role === 'user' && !renderInputMessageAsMarkdown) {
|
||||
return <p style={{ marginBottom: 5, whiteSpace: 'pre-wrap' }}>{messageContent}</p>
|
||||
|
||||
@ -367,7 +367,27 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic
|
||||
|
||||
return menus
|
||||
},
|
||||
[assistant, assistants, onClearMessages, onDeleteTopic, onPinTopic, onMoveTopic, t, updateTopic, exportMenuOptions]
|
||||
[
|
||||
activeTopic.id,
|
||||
assistant,
|
||||
assistants,
|
||||
exportMenuOptions.docx,
|
||||
exportMenuOptions.image,
|
||||
exportMenuOptions.joplin,
|
||||
exportMenuOptions.markdown,
|
||||
exportMenuOptions.markdown_reason,
|
||||
exportMenuOptions.notion,
|
||||
exportMenuOptions.obsidian,
|
||||
exportMenuOptions.siyuan,
|
||||
exportMenuOptions.yuque,
|
||||
onClearMessages,
|
||||
onDeleteTopic,
|
||||
onMoveTopic,
|
||||
onPinTopic,
|
||||
setActiveTopic,
|
||||
t,
|
||||
updateTopic
|
||||
]
|
||||
)
|
||||
|
||||
return (
|
||||
|
||||
19
src/renderer/src/utils/markdown.ts
Normal file
19
src/renderer/src/utils/markdown.ts
Normal file
@ -0,0 +1,19 @@
|
||||
// 更彻底的查找方法,递归搜索所有子元素
|
||||
export const findCitationInChildren = (children) => {
|
||||
if (!children) return null
|
||||
|
||||
// 直接搜索子元素
|
||||
for (const child of Array.isArray(children) ? children : [children]) {
|
||||
if (typeof child === 'object' && child?.props?.['data-citation']) {
|
||||
return child.props['data-citation']
|
||||
}
|
||||
|
||||
// 递归查找更深层次
|
||||
if (typeof child === 'object' && child?.props?.children) {
|
||||
const found = findCitationInChildren(child.props.children)
|
||||
if (found) return found
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user