diff --git a/src/renderer/src/pages/home/Markdown/CodeBlock.tsx b/src/renderer/src/pages/home/Markdown/CodeBlock.tsx index 63f6b1a235..38037a1d1a 100644 --- a/src/renderer/src/pages/home/Markdown/CodeBlock.tsx +++ b/src/renderer/src/pages/home/Markdown/CodeBlock.tsx @@ -1,7 +1,9 @@ -import { CheckOutlined, DownOutlined, RightOutlined } from '@ant-design/icons' +import { CheckOutlined, DownloadOutlined, DownOutlined, RightOutlined } from '@ant-design/icons' import CopyIcon from '@renderer/components/Icons/CopyIcon' +import { HStack } from '@renderer/components/Layout' import { useSyntaxHighlighter } from '@renderer/context/SyntaxHighlighterProvider' import { useSettings } from '@renderer/hooks/useSettings' +import dayjs from 'dayjs' import React, { memo, useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' @@ -16,28 +18,6 @@ interface CodeBlockProps { [key: string]: any } -const CollapseIcon: React.FC<{ expanded: boolean; onClick: () => void }> = ({ expanded, onClick }) => { - return ( - - {expanded ? : } - - ) -} - -const ExpandButton: React.FC<{ - isExpanded: boolean - onClick: () => void - showButton: boolean -}> = ({ isExpanded, onClick, showButton }) => { - if (!showButton) return null - - return ( - - {isExpanded ? '收起' : '展开'} - - ) -} - const CodeBlock: React.FC = ({ children, className }) => { const match = /language-(\w+)/.exec(className || '') const { codeShowLineNumbers, fontSize, codeCollapsible } = useSettings() @@ -50,6 +30,8 @@ const CodeBlock: React.FC = ({ children, className }) => { const showFooterCopyButton = children && children.length > 500 && !codeCollapsible + const showDownloadButton = ['csv', 'json', 'txt', 'md'].includes(language) + useEffect(() => { const loadHighlightedCode = async () => { const highlightedHtml = await codeToHtml(children, language) @@ -101,7 +83,10 @@ const CodeBlock: React.FC = ({ children, className }) => { )} {'<' + match[1].toUpperCase() + '>'} - + + {showDownloadButton && } + + = ({ children, className }) => { ) } +const CollapseIcon: React.FC<{ expanded: boolean; onClick: () => void }> = ({ expanded, onClick }) => { + return ( + + {expanded ? : } + + ) +} + +const ExpandButton: React.FC<{ + isExpanded: boolean + onClick: () => void + showButton: boolean +}> = ({ isExpanded, onClick, showButton }) => { + if (!showButton) return null + + return ( + + {isExpanded ? '收起' : '展开'} + + ) +} + const CopyButton: React.FC<{ text: string; style?: React.CSSProperties }> = ({ text, style }) => { const [copied, setCopied] = useState(false) const { t } = useTranslation() @@ -155,6 +162,19 @@ const CopyButton: React.FC<{ text: string; style?: React.CSSProperties }> = ({ t ) } +const DownloadButton = ({ language, data }: { language: string; data: string }) => { + const onDownload = () => { + const fileName = `${dayjs().format('YYYYMMDDHHmm')}.${language}` + window.api.file.save(fileName, data) + } + + return ( + + + + ) +} + const CodeBlockWrapper = styled.div`` const CodeContent = styled.div<{ isShowLineNumbers: boolean }>` @@ -264,4 +284,18 @@ const CollapseIconWrapper = styled.div` } ` +const DownloadWrapper = styled.div` + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + color: var(--color-text-3); + transition: color 0.3s; + font-size: 16px; + + &:hover { + color: var(--color-text-1); + } +` + export default memo(CodeBlock)