fix: quick assistant bugs
This commit is contained in:
parent
9c55b4516c
commit
88cc783a95
@ -305,7 +305,9 @@ export class WindowService {
|
|||||||
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
|
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
|
||||||
this.miniWindow.loadURL(process.env['ELECTRON_RENDERER_URL'] + '#/mini')
|
this.miniWindow.loadURL(process.env['ELECTRON_RENDERER_URL'] + '#/mini')
|
||||||
} else {
|
} else {
|
||||||
this.miniWindow.loadFile(join(__dirname, '../renderer/index.html') + '#/mini')
|
this.miniWindow.loadFile(join(__dirname, '../renderer/index.html'), {
|
||||||
|
hash: '#/mini'
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,7 @@ export function useSettings() {
|
|||||||
},
|
},
|
||||||
setTray(isActive: boolean) {
|
setTray(isActive: boolean) {
|
||||||
dispatch(setTray(isActive))
|
dispatch(setTray(isActive))
|
||||||
|
window.api.setTray(isActive)
|
||||||
},
|
},
|
||||||
setTheme(theme: ThemeMode) {
|
setTheme(theme: ThemeMode) {
|
||||||
dispatch(setTheme(theme))
|
dispatch(setTheme(theme))
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import { SettingContainer, SettingDivider, SettingGroup, SettingRow, SettingRowT
|
|||||||
const QuickAssistantSettings: FC = () => {
|
const QuickAssistantSettings: FC = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { theme } = useTheme()
|
const { theme } = useTheme()
|
||||||
const { enableQuickAssistant, clickTrayToShowQuickAssistant, setTray } = useSettings()
|
const { enableQuickAssistant, clickTrayToShowQuickAssistant, tray, setTray } = useSettings()
|
||||||
const dispatch = useAppDispatch()
|
const dispatch = useAppDispatch()
|
||||||
|
|
||||||
const handleEnableQuickAssistant = async (enable: boolean) => {
|
const handleEnableQuickAssistant = async (enable: boolean) => {
|
||||||
@ -32,15 +32,16 @@ const QuickAssistantSettings: FC = () => {
|
|||||||
key: 'quick-assistant-info'
|
key: 'quick-assistant-info'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (enable && clickTrayToShowQuickAssistant) {
|
||||||
|
setTray(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleClickTrayToShowQuickAssistant = async (checked: boolean) => {
|
const handleClickTrayToShowQuickAssistant = async (checked: boolean) => {
|
||||||
dispatch(setClickTrayToShowQuickAssistant(checked))
|
dispatch(setClickTrayToShowQuickAssistant(checked))
|
||||||
await window.api.config.set('clickTrayToShowQuickAssistant', checked)
|
await window.api.config.set('clickTrayToShowQuickAssistant', checked)
|
||||||
if (checked) {
|
checked && setTray(true)
|
||||||
setTray(true)
|
|
||||||
window.api.setTray(true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -847,6 +847,7 @@ const migrateConfig = {
|
|||||||
})
|
})
|
||||||
|
|
||||||
state.settings.enableQuickAssistant = false
|
state.settings.enableQuickAssistant = false
|
||||||
|
state.settings.clickTrayToShowQuickAssistant = true
|
||||||
|
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import styled from 'styled-components'
|
|||||||
interface Props {
|
interface Props {
|
||||||
message: Message
|
message: Message
|
||||||
index?: number
|
index?: number
|
||||||
total?: number
|
total: number
|
||||||
route: string
|
route: string
|
||||||
onGetMessages?: () => Message[]
|
onGetMessages?: () => Message[]
|
||||||
onSetMessages?: Dispatch<SetStateAction<Message[]>>
|
onSetMessages?: Dispatch<SetStateAction<Message[]>>
|
||||||
@ -36,6 +36,8 @@ const MessageItem: FC<Props> = ({ message: _message, index, total, route, onSetM
|
|||||||
|
|
||||||
const messageBackground = getMessageBackground(true, isAssistantMessage)
|
const messageBackground = getMessageBackground(true, isAssistantMessage)
|
||||||
|
|
||||||
|
const maxWidth = window.location.hash === '#/mini' ? '480px' : '100%'
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (onGetMessages && onSetMessages) {
|
if (onGetMessages && onSetMessages) {
|
||||||
if (message.status === 'sending') {
|
if (message.status === 'sending') {
|
||||||
@ -70,7 +72,7 @@ const MessageItem: FC<Props> = ({ message: _message, index, total, route, onSetM
|
|||||||
<MessageContainer
|
<MessageContainer
|
||||||
key={message.id}
|
key={message.id}
|
||||||
ref={messageContainerRef}
|
ref={messageContainerRef}
|
||||||
style={{ ...(isBubbleStyle ? { alignItems: isAssistantMessage ? 'start' : 'end' } : {}) }}>
|
style={{ ...(isBubbleStyle ? { alignItems: isAssistantMessage ? 'start' : 'end' } : {}), maxWidth }}>
|
||||||
<MessageContentContainer
|
<MessageContentContainer
|
||||||
className="message-content-container"
|
className="message-content-container"
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
import Scrollbar from '@renderer/components/Scrollbar'
|
import Scrollbar from '@renderer/components/Scrollbar'
|
||||||
|
import { useShortcut } from '@renderer/hooks/useShortcuts'
|
||||||
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
|
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
|
||||||
import { getAssistantMessage } from '@renderer/services/MessagesService'
|
import { getAssistantMessage } from '@renderer/services/MessagesService'
|
||||||
import { Assistant, Message } from '@renderer/types'
|
import { Assistant, Message } from '@renderer/types'
|
||||||
|
import { last } from 'lodash'
|
||||||
import { FC, useCallback, useEffect, useRef, useState } from 'react'
|
import { FC, useCallback, useEffect, useRef, useState } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
import MessageItem from './Message'
|
import MessageItem from './Message'
|
||||||
@ -22,6 +25,8 @@ const Messages: FC<Props> = ({ assistant, route }) => {
|
|||||||
const containerRef = useRef<HTMLDivElement>(null)
|
const containerRef = useRef<HTMLDivElement>(null)
|
||||||
const messagesRef = useRef(messages)
|
const messagesRef = useRef(messages)
|
||||||
|
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
messagesRef.current = messages
|
messagesRef.current = messages
|
||||||
|
|
||||||
const onSendMessage = useCallback(
|
const onSendMessage = useCallback(
|
||||||
@ -44,6 +49,14 @@ const Messages: FC<Props> = ({ assistant, route }) => {
|
|||||||
return () => unsubscribes.forEach((unsub) => unsub())
|
return () => unsubscribes.forEach((unsub) => unsub())
|
||||||
}, [assistant.id, onSendMessage])
|
}, [assistant.id, onSendMessage])
|
||||||
|
|
||||||
|
useShortcut('copy_last_message', () => {
|
||||||
|
const lastMessage = last(messages)
|
||||||
|
if (lastMessage) {
|
||||||
|
navigator.clipboard.writeText(lastMessage.content)
|
||||||
|
window.message.success(t('message.copy.success'))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container id="messages" key={assistant.id} ref={containerRef}>
|
<Container id="messages" key={assistant.id} ref={containerRef}>
|
||||||
{[...messages].reverse().map((message, index) => (
|
{[...messages].reverse().map((message, index) => (
|
||||||
|
|||||||
@ -30,9 +30,9 @@ const HomeWindow: FC = () => {
|
|||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const textRef = useRef(text)
|
const textRef = useRef(text)
|
||||||
|
|
||||||
const referenceText = selectedText || clipboardText
|
const referenceText = selectedText || clipboardText || text
|
||||||
|
|
||||||
textRef.current = `${referenceText}\n\n${text}`
|
textRef.current = referenceText === text ? text : `${referenceText}\n\n${text}`
|
||||||
|
|
||||||
const onReadClipboard = useCallback(async () => {
|
const onReadClipboard = useCallback(async () => {
|
||||||
const text = await navigator.clipboard.readText()
|
const text = await navigator.clipboard.readText()
|
||||||
@ -58,6 +58,7 @@ const HomeWindow: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') {
|
||||||
|
e.preventDefault()
|
||||||
if (text.trim() === '') {
|
if (text.trim() === '') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -69,11 +70,12 @@ const HomeWindow: FC = () => {
|
|||||||
|
|
||||||
const onSendMessage = useCallback(
|
const onSendMessage = useCallback(
|
||||||
async (prompt?: string) => {
|
async (prompt?: string) => {
|
||||||
|
const text = textRef.current.trim()
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const message = {
|
const message = {
|
||||||
id: uuid(),
|
id: uuid(),
|
||||||
role: 'user',
|
role: 'user',
|
||||||
content: prompt ? `${prompt}\n\n${textRef.current}` : textRef.current,
|
content: prompt ? `${prompt}\n\n${text}` : text,
|
||||||
assistantId: defaultAssistant.id,
|
assistantId: defaultAssistant.id,
|
||||||
topicId: defaultAssistant.topics[0].id || uuid(),
|
topicId: defaultAssistant.topics[0].id || uuid(),
|
||||||
createdAt: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
createdAt: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||||
|
|||||||
@ -24,7 +24,7 @@ const InputBar: FC<InputBarProps> = ({ text, model, placeholder, handleKeyDown,
|
|||||||
bordered={false}
|
bordered={false}
|
||||||
autoFocus
|
autoFocus
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
onChange={(e) => setText(e.target.value)}
|
onChange={(e) => setText(e.target.value.trim())}
|
||||||
disabled={generating}
|
disabled={generating}
|
||||||
/>
|
/>
|
||||||
</InputWrapper>
|
</InputWrapper>
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { Assistant, Message } from '@renderer/types'
|
|||||||
import { runAsyncFunction, uuid } from '@renderer/utils'
|
import { runAsyncFunction, uuid } from '@renderer/utils'
|
||||||
import { Select, Space } from 'antd'
|
import { Select, Space } from 'antd'
|
||||||
import { isEmpty } from 'lodash'
|
import { isEmpty } from 'lodash'
|
||||||
import { FC, useCallback, useEffect, useState } from 'react'
|
import { FC, useCallback, useEffect, useRef, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
@ -24,13 +24,20 @@ const Translate: FC<Props> = ({ text }) => {
|
|||||||
const [targetLanguage, setTargetLanguage] = useState(_targetLanguage)
|
const [targetLanguage, setTargetLanguage] = useState(_targetLanguage)
|
||||||
const { translateModel } = useDefaultModel()
|
const { translateModel } = useDefaultModel()
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const translatingRef = useRef(false)
|
||||||
|
|
||||||
_targetLanguage = targetLanguage
|
_targetLanguage = targetLanguage
|
||||||
|
|
||||||
const translate = useCallback(async () => {
|
const translate = useCallback(async () => {
|
||||||
if (!text.trim() || !translateModel) return
|
if (!text.trim() || !translateModel) return
|
||||||
|
|
||||||
const assistant: Assistant = getDefaultTranslateAssistant(targetLanguage, text)
|
if (translatingRef.current) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
translatingRef.current = true
|
||||||
|
|
||||||
|
const targetLang = await db.settings.get({ id: 'translate:target:language' })
|
||||||
|
const assistant: Assistant = getDefaultTranslateAssistant(targetLang?.value || targetLanguage, text)
|
||||||
const message: Message = {
|
const message: Message = {
|
||||||
id: uuid(),
|
id: uuid(),
|
||||||
role: 'user',
|
role: 'user',
|
||||||
@ -44,6 +51,13 @@ const Translate: FC<Props> = ({ text }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await fetchTranslate({ message, assistant, onResponse: setResult })
|
await fetchTranslate({ message, assistant, onResponse: setResult })
|
||||||
|
|
||||||
|
translatingRef.current = false
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
} finally {
|
||||||
|
translatingRef.current = false
|
||||||
|
}
|
||||||
}, [text, targetLanguage, translateModel])
|
}, [text, targetLanguage, translateModel])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -75,9 +89,9 @@ const Translate: FC<Props> = ({ text }) => {
|
|||||||
style={{ width: 200 }}
|
style={{ width: 200 }}
|
||||||
optionFilterProp="label"
|
optionFilterProp="label"
|
||||||
options={TranslateLanguageOptions}
|
options={TranslateLanguageOptions}
|
||||||
onChange={(value) => {
|
onChange={async (value) => {
|
||||||
|
await db.settings.put({ id: 'translate:target:language', value })
|
||||||
setTargetLanguage(value)
|
setTargetLanguage(value)
|
||||||
db.settings.put({ id: 'translate:target:language', value })
|
|
||||||
}}
|
}}
|
||||||
optionRender={(option) => (
|
optionRender={(option) => (
|
||||||
<Space>
|
<Space>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user