feat: save file to disk

This commit is contained in:
kangfenmao
2024-07-26 09:50:29 +08:00
parent 3aa4363f5b
commit 00a0b8df4d
8 changed files with 75 additions and 9 deletions
+4
View File
@@ -22,3 +22,7 @@ export function useShowAssistants() {
toggleShowAssistants: () => dispatch(toggleShowAssistants())
}
}
export function useRuntime() {
return useAppSelector((state) => state.runtime)
}
+8 -1
View File
@@ -24,7 +24,8 @@ const resources = {
copy: 'Copy',
regenerate: 'Regenerate',
provider: 'Provider',
you: 'You'
you: 'You',
save: 'Save'
},
button: {
add: 'Add',
@@ -46,6 +47,9 @@ const resources = {
'chat.completion.paused': 'Chat completion paused',
'switch.disabled': 'Switching is disabled while the assistant is generating'
},
chat: {
save: 'Save'
},
assistant: {
'default.name': '😀 Default Assistant',
'default.description': "Hello, I'm Default Assistant. You can start chatting with me right away",
@@ -197,6 +201,9 @@ const resources = {
'chat.completion.paused': '会话已停止',
'switch.disabled': '模型回复完成后才能切换'
},
chat: {
save: '保存'
},
assistant: {
'default.name': '😃 默认助手 - Assistant',
'default.description': '你好,我是默认助手。你可以立刻开始跟我聊天。',
@@ -1,4 +1,4 @@
import { CopyOutlined, DeleteOutlined, EditOutlined, SyncOutlined } from '@ant-design/icons'
import { CopyOutlined, DeleteOutlined, EditOutlined, MenuOutlined, SaveOutlined, SyncOutlined } from '@ant-design/icons'
import Logo from '@renderer/assets/images/logo.png'
import { getModelLogo } from '@renderer/config/provider'
import { useAssistant } from '@renderer/hooks/useAssistant'
@@ -7,14 +7,15 @@ import { useSettings } from '@renderer/hooks/useSettings'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/event'
import { Message } from '@renderer/types'
import { firstLetter } from '@renderer/utils'
import { Avatar, Tooltip } from 'antd'
import { Avatar, Dropdown, Tooltip } from 'antd'
import dayjs from 'dayjs'
import { isEmpty, upperFirst } from 'lodash'
import { FC } from 'react'
import { FC, useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import Markdown from 'react-markdown'
import styled from 'styled-components'
import CodeBlock from './CodeBlock'
import { useRuntime } from '@renderer/hooks/useStore'
interface Props {
message: Message
@@ -29,6 +30,7 @@ const MessageItem: FC<Props> = ({ message, index, showMenu, onDeleteMessage }) =
const { t } = useTranslation()
const { assistant } = useAssistant(message.assistantId)
const { userName, showMessageDivider, messageFont } = useSettings()
const { generating } = useRuntime()
const isLastMessage = index === 0
const isUserMessage = message.role === 'user'
@@ -66,7 +68,7 @@ const MessageItem: FC<Props> = ({ message, index, showMenu, onDeleteMessage }) =
return message.content
}
const getUserName = () => {
const getUserName = useCallback(() => {
if (message.id === 'assistant') {
return assistant.name
}
@@ -76,7 +78,24 @@ const MessageItem: FC<Props> = ({ message, index, showMenu, onDeleteMessage }) =
}
return userName || t('common.you')
}
}, [assistant.name, message.id, message.modelId, message.role, t, userName])
const getDropdownMenus = useCallback(
(message: Message) => {
return [
{
label: t('chat.save'),
key: 'save',
icon: <SaveOutlined />,
onClick: () => {
const fileName = message.createdAt + '.md'
window.api.saveFile(fileName, message.content)
}
}
]
},
[t]
)
const fontFamily = messageFont === 'serif' ? "Georgia, Cambria, 'Times New Roman', Times, serif" : undefined
const messageBorder = showMessageDivider ? undefined : 'none'
@@ -109,7 +128,7 @@ const MessageItem: FC<Props> = ({ message, index, showMenu, onDeleteMessage }) =
{getMessageContent(message)}
</Markdown>
)}
{message.usage && (
{message.usage && !generating && (
<MessageMetadata>
Tokens: {message.usage.total_tokens} | {message.usage.prompt_tokens}{message.usage.completion_tokens}
</MessageMetadata>
@@ -140,6 +159,13 @@ const MessageItem: FC<Props> = ({ message, index, showMenu, onDeleteMessage }) =
</ActionButton>
</Tooltip>
)}
{!isUserMessage && (
<Dropdown menu={{ items: getDropdownMenus(message) }} trigger={['click']} placement="topRight" arrow>
<ActionButton>
<MenuOutlined />
</ActionButton>
</Dropdown>
)}
</MenusBar>
)}
</MessageContent>
@@ -93,7 +93,7 @@ const Tab = styled.div`
color: #8a8a8a;
border-bottom: 1px solid transparent;
&.active {
color: #a8a8a8;
color: #bbb;
font-weight: 600;
}
`