diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index bde091b0..929b1bee 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -113,6 +113,7 @@ "settings.set_as_default": "Apply to default assistant", "settings.max": "Max", "settings.show_line_numbers": "Show Line Numbers in Code", + "settings.code_collapsible": "Code block collapsible", "suggestions.title": "Suggested Questions", "add.assistant.title": "Add Assistant", "message.new.context": "New Context", diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index 114daee7..e5365ac4 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -113,6 +113,7 @@ "settings.set_as_default": "Применить к ассистенту по умолчанию", "settings.max": "Максимум", "settings.show_line_numbers": "Показать номера строк в коде", + "settings.code_collapsible": "Блок кода свернут", "suggestions.title": "Предложенные вопросы", "add.assistant.title": "Добавить ассистента", "message.new.context": "Новый контекст", diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index 86093ce2..f659903d 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -113,6 +113,7 @@ "settings.set_as_default": "应用到默认助手", "settings.max": "不限", "settings.show_line_numbers": "代码显示行号", + "settings.code_collapsible": "代码块可折叠", "suggestions.title": "建议的问题", "add.assistant.title": "添加助手", "message.new.context": "清除上下文", diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index d8c4486a..251ba9d9 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -113,6 +113,7 @@ "settings.set_as_default": "設為預設助手", "settings.max": "最大", "settings.show_line_numbers": "代码顯示行號", + "settings.code_collapsible": "代码块可折叠", "suggestions.title": "建議的問題", "add.assistant.title": "添加助手", "message.new.context": "新上下文", diff --git a/src/renderer/src/pages/home/Markdown/CodeBlock.tsx b/src/renderer/src/pages/home/Markdown/CodeBlock.tsx index f35ebdb6..48984bcf 100644 --- a/src/renderer/src/pages/home/Markdown/CodeBlock.tsx +++ b/src/renderer/src/pages/home/Markdown/CodeBlock.tsx @@ -2,7 +2,7 @@ import { CheckOutlined, DownOutlined, RightOutlined } from '@ant-design/icons' import CopyIcon from '@renderer/components/Icons/CopyIcon' import { useSyntaxHighlighter } from '@renderer/context/SyntaxHighlighterProvider' import { useSettings } from '@renderer/hooks/useSettings' -import React, { memo, useEffect, useState } from 'react' +import React, { memo, useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' @@ -16,10 +16,10 @@ interface CodeBlockProps { } const CollapseIcon: React.FC<{ expanded: boolean; onClick: () => void }> = ({ expanded, onClick }) => { - return expanded ? ( - - ) : ( - + return ( + + {expanded ? : } + ) } @@ -31,28 +31,22 @@ const ExpandButton: React.FC<{ if (!showButton) return null return ( -
- {isExpanded ? '收起' : '展开'} -
+ +
{isExpanded ? '收起' : '展开'}
+
) } const CodeBlock: React.FC = ({ children, className }) => { const match = /language-(\w+)/.exec(className || '') const showFooterCopyButton = children && children.length > 500 - const { codeShowLineNumbers, fontSize } = useSettings() + const { codeShowLineNumbers, fontSize, codeCollapsible } = useSettings() const language = match?.[1] ?? 'text' const [html, setHtml] = useState('') const { codeToHtml } = useSyntaxHighlighter() - const [isExpanded, setIsExpanded] = useState(false) + const [isExpanded, setIsExpanded] = useState(!codeCollapsible) + const [shouldShowExpandButton, setShouldShowExpandButton] = useState(false) + const codeContentRef = useRef(null) useEffect(() => { const loadHighlightedCode = async () => { @@ -62,6 +56,24 @@ const CodeBlock: React.FC = ({ children, className }) => { loadHighlightedCode() }, [children, language, codeToHtml]) + useEffect(() => { + if (codeContentRef.current) { + setShouldShowExpandButton(codeContentRef.current.scrollHeight > 350) + } + }, [html]) + + useEffect(() => { + if (!codeCollapsible) { + setIsExpanded(true) + setShouldShowExpandButton(false) + } else { + setIsExpanded(!codeCollapsible) + if (codeContentRef.current) { + setShouldShowExpandButton(codeContentRef.current.scrollHeight > 350) + } + } + }, [codeCollapsible]) + if (language === 'mermaid') { return } @@ -70,12 +82,13 @@ const CodeBlock: React.FC = ({ children, className }) => {
- setIsExpanded(!isExpanded)} /> + {codeCollapsible && setIsExpanded(!isExpanded)} />} {'<' + match[1].toUpperCase() + '>'}
= ({ children, className }) => { borderTopLeftRadius: 0, borderTopRightRadius: 0, marginTop: 0, - fontSize, - maxHeight: isExpanded ? 'none' : '300px', - overflow: 'hidden', + fontSize: fontSize - 1, + maxHeight: codeCollapsible && !isExpanded ? '350px' : 'none', + overflow: codeCollapsible && !isExpanded ? 'auto' : 'visible', position: 'relative' }} /> - setIsExpanded(!isExpanded)} - showButton={!isExpanded || showFooterCopyButton} - /> + {codeCollapsible && ( + setIsExpanded(!isExpanded)} + showButton={shouldShowExpandButton} + /> + )} {showFooterCopyButton && ( @@ -189,4 +204,45 @@ const CodeFooter = styled.div` } ` +const ExpandButtonWrapper = styled.div` + position: relative; + cursor: pointer; + height: 30px; + margin-top: -30px; + + .button-text { + position: absolute; + bottom: 0; + left: 0; + right: 0; + text-align: center; + padding: 8px; + color: var(--color-text-3); + z-index: 1; + transition: color 0.2s; + font-size: 12px; + } + + &:hover .button-text { + color: var(--color-text-1); + } +` + +const CollapseIconWrapper = styled.div` + display: flex; + align-items: center; + justify-content: center; + width: 20px; + height: 20px; + border-radius: 4px; + cursor: pointer; + color: var(--color-text-3); + transition: all 0.2s ease; + + &:hover { + background-color: var(--color-background-soft); + color: var(--color-text-1); + } +` + export default memo(CodeBlock) diff --git a/src/renderer/src/pages/home/Tabs/Settings.tsx b/src/renderer/src/pages/home/Tabs/Settings.tsx index 3fb8e04c..fd828dae 100644 --- a/src/renderer/src/pages/home/Tabs/Settings.tsx +++ b/src/renderer/src/pages/home/Tabs/Settings.tsx @@ -6,6 +6,7 @@ import { SettingDivider, SettingRow, SettingRowTitle, SettingSubtitle } from '@r import { useAppDispatch } from '@renderer/store' import { setClickAssistantToShowTopic, + setCodeCollapsible, setCodeShowLineNumbers, setCodeStyle, setFontSize, @@ -39,6 +40,7 @@ const SettingsTab: FC = () => { pasteLongTextAsFile, renderInputMessageAsMarkdown, codeShowLineNumbers, + codeCollapsible, mathEngine, topicPosition, showTopicTime, @@ -81,6 +83,11 @@ const SettingsTab: FC = () => { /> + + {t('chat.settings.code_collapsible')} + dispatch(setCodeCollapsible(checked))} /> + + {t('message.message.style')}