feat: add the shortcuts for 'clear' and 'new context' and fix (#786)

* Fix: ESC key to exit the expanded editor

* Add the shortcuts for 'clear' and 'new context' to the input bar
Clear Messages: Ctrl+L
New Context: Ctrl+R
https://github.com/CherryHQ/cherry-studio/issues/740
https://github.com/CherryHQ/cherry-studio/issues/766

* Fix: the paste issue when copying from an email (content was pasted as an image; ensure it is pasted as text). Prioritize the text in the clipboard during pasting.
This commit is contained in:
MrChen 2025-01-20 09:31:09 +08:00 committed by GitHub
parent 63673ec39f
commit 4c22c404ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 99 additions and 38 deletions

View File

@ -64,14 +64,14 @@
"default.description": "Hello, I'm Default Assistant. You can start chatting with me right away",
"default.name": "⭐️ Default Assistant",
"default.topic.name": "Default Topic",
"input.clear": "Clear",
"input.clear": "Clear {{Command}}",
"input.clear.content": "Do you want to clear all messages of the current topic?",
"input.clear.title": "Clear all messages?",
"input.collapse": "Collapse",
"input.context_count.tip": "Context Count",
"input.estimated_tokens.tip": "Estimated tokens",
"input.expand": "Expand",
"input.new.context": "Clear Context",
"input.new.context": "Clear Context {{Command}}",
"input.new_topic": "New Topic {{Command}}",
"input.pause": "Pause",
"input.placeholder": "Type your message here...",
@ -526,7 +526,9 @@
"toggle_show_topics": "Toggle Topics",
"copy_last_message": "Copy Last Message",
"search_message": "Search Message",
"mini_window": "Quick Assistant"
"mini_window": "Quick Assistant",
"clear_topic": "Clear Messages",
"toggle_new_context": "Clear Context"
},
"theme.auto": "Auto",
"theme.dark": "Dark",

View File

@ -64,14 +64,14 @@
"default.description": "こんにちは、私はデフォルトのアシスタントです。すぐにチャットを始められます。",
"default.name": "⭐️ デフォルトアシスタント",
"default.topic.name": "デフォルトトピック",
"input.clear": "クリア",
"input.clear": "クリア {{Command}}",
"input.clear.content": "現在のトピックのすべてのメッセージをクリアしますか?",
"input.clear.title": "すべてのメッセージをクリアしますか?",
"input.collapse": "折りたたむ",
"input.context_count.tip": "コンテキスト数",
"input.estimated_tokens.tip": "推定トークン数",
"input.expand": "展開",
"input.new.context": "コンテキストをクリア",
"input.new.context": "コンテキストをクリア {{Command}}",
"input.new_topic": "新しいトピック {{Command}}",
"input.pause": "一時停止",
"input.placeholder": "ここにメッセージを入力...",
@ -511,7 +511,9 @@
"toggle_show_topics": "トピックの表示を切り替え",
"copy_last_message": "最後のメッセージをコピー",
"search_message": "メッセージを検索",
"mini_window": "クイックアシスタント"
"mini_window": "クイックアシスタント",
"clear_topic": "メッセージを消去",
"toggle_new_context": "コンテキストをクリア"
},
"theme.auto": "自動",
"theme.dark": "ダークテーマ",

View File

@ -64,14 +64,14 @@
"default.description": "Привет, я Ассистент по умолчанию. Вы можете начать общаться со мной прямо сейчас",
"default.name": "⭐️ Ассистент по умолчанию",
"default.topic.name": "Топик по умолчанию",
"input.clear": "Очистить",
"input.clear": "Очистить {{Command}}",
"input.clear.content": "Хотите очистить все сообщения текущего топика?",
"input.clear.title": "Очистить все сообщения?",
"input.collapse": "Свернуть",
"input.context_count.tip": "Количество контекстов",
"input.estimated_tokens.tip": "Затраты токенов",
"input.expand": "Развернуть",
"input.new.context": "Очистить контекст",
"input.new.context": "Очистить контекст {{Command}}",
"input.new_topic": "Новый топик {{Command}}",
"input.pause": "Остановить",
"input.placeholder": "Введите ваше сообщение здесь...",
@ -525,7 +525,9 @@
"toggle_show_topics": "Переключить отображение топиков",
"copy_last_message": "Копировать последнее сообщение",
"search_message": "Поиск сообщения",
"mini_window": "Быстрый помощник"
"mini_window": "Быстрый помощник",
"clear_topic": "Очистить все сообщения",
"toggle_new_context": "Очистить контекст"
},
"theme.auto": "Автоматически",
"theme.dark": "Темная",

View File

@ -64,14 +64,14 @@
"default.description": "你好,我是默认助手。你可以立刻开始跟我聊天。",
"default.name": "⭐️ 默认助手",
"default.topic.name": "默认话题",
"input.clear": "清空消息",
"input.clear": "清空消息 {{Command}}",
"input.clear.content": "确定要清除当前会话所有消息吗?",
"input.clear.title": "清空消息",
"input.collapse": "收起",
"input.context_count.tip": "上下文数",
"input.estimated_tokens.tip": "预估 token 数",
"input.expand": "展开",
"input.new.context": "清除上下文",
"input.new.context": "清除上下文 {{Command}}",
"input.new_topic": "新话题 {{Command}}",
"input.pause": "暂停",
"input.placeholder": "在这里输入消息...",
@ -514,7 +514,9 @@
"toggle_show_topics": "切换话题显示",
"copy_last_message": "复制上一条消息",
"search_message": "搜索消息",
"mini_window": "快捷助手"
"mini_window": "快捷助手",
"clear_topic": "清空消息",
"toggle_new_context": "清除上下文"
},
"theme.auto": "跟随系统",
"theme.dark": "深色主题",

View File

@ -64,14 +64,14 @@
"default.description": "你好,我是預設助手。你可以立即開始與我聊天。",
"default.name": "⭐️ 預設助手",
"default.topic.name": "預設話題",
"input.clear": "清除",
"input.clear": "清除 {{Command}}",
"input.clear.content": "您想要清除當前話題的所有訊息嗎?",
"input.clear.title": "清除所有訊息?",
"input.collapse": "收起",
"input.context_count.tip": "上下文數量",
"input.estimated_tokens.tip": "預估 Token 數",
"input.expand": "展開",
"input.new.context": "清除上下文",
"input.new.context": "清除上下文 {{Command}}",
"input.new_topic": "新話題 {{Command}}",
"input.pause": "暫停",
"input.placeholder": "在此輸入您的訊息...",
@ -513,7 +513,9 @@
"toggle_show_topics": "切換話題顯示",
"copy_last_message": "複製上一条消息",
"search_message": "搜索消息",
"mini_window": "快捷助手"
"mini_window": "快捷助手",
"clear_topic": "清除所有訊息",
"toggle_new_context": "清除上下文"
},
"theme.auto": "自動",
"theme.dark": "深色主題",

View File

@ -97,6 +97,8 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic }) => {
[estimateTextTokens, showInputEstimatedTokens, text]
)
const newTopicShortcut = useShortcutDisplay('new_topic')
const newContextShortcut = useShortcutDisplay('toggle_new_context')
const cleanTopicShortcut = useShortcutDisplay('clear_topic')
const inputEmpty = isEmpty(text.trim()) && files.length === 0
_text = text
@ -188,7 +190,7 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic }) => {
if (expended) {
if (event.key === 'Escape') {
return setExpend(false)
return onToggleExpended()
}
}
@ -281,25 +283,31 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic }) => {
const onPaste = useCallback(
async (event: ClipboardEvent) => {
for (const file of event.clipboardData?.files || []) {
event.preventDefault()
const clipboardText = event.clipboardData?.getData('text')
if (clipboardText) {
// Prioritize the text when pasting.
// handled by the default event
} else {
for (const file of event.clipboardData?.files || []) {
event.preventDefault()
if (file.path === '') {
if (file.type.startsWith('image/')) {
const tempFilePath = await window.api.file.create(file.name)
const arrayBuffer = await file.arrayBuffer()
const uint8Array = new Uint8Array(arrayBuffer)
await window.api.file.write(tempFilePath, uint8Array)
const selectedFile = await window.api.file.get(tempFilePath)
selectedFile && setFiles((prevFiles) => [...prevFiles, selectedFile])
break
if (file.path === '') {
if (file.type.startsWith('image/')) {
const tempFilePath = await window.api.file.create(file.name)
const arrayBuffer = await file.arrayBuffer()
const uint8Array = new Uint8Array(arrayBuffer)
await window.api.file.write(tempFilePath, uint8Array)
const selectedFile = await window.api.file.get(tempFilePath)
selectedFile && setFiles((prevFiles) => [...prevFiles, selectedFile])
break
}
}
}
if (file.path) {
if (supportExts.includes(getFileExtension(file.path))) {
const selectedFile = await window.api.file.get(file.path)
selectedFile && setFiles((prevFiles) => [...prevFiles, selectedFile])
if (file.path) {
if (supportExts.includes(getFileExtension(file.path))) {
const selectedFile = await window.api.file.get(file.path)
selectedFile && setFiles((prevFiles) => [...prevFiles, selectedFile])
}
}
}
}
@ -355,6 +363,14 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic }) => {
}
})
useShortcut('clear_topic', () => {
clearTopic()
})
useShortcut('toggle_new_context', () => {
onNewContext()
})
useEffect(() => {
const _setEstimateTokenCount = debounce(setEstimateTokenCount, 100, { leading: false, trailing: true })
const unsubscribes = [
@ -468,14 +484,14 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic }) => {
</ToolbarButton>
</Tooltip>
)}
<Tooltip placement="top" title={t('chat.input.clear')} arrow>
<Tooltip placement="top" title={t('chat.input.clear', { Command: cleanTopicShortcut })} arrow>
<Popconfirm
title={t('chat.input.clear.content')}
placement="top"
onConfirm={clearTopic}
okButtonProps={{ danger: true }}
icon={<QuestionCircleOutlined style={{ color: 'red' }} />}
okText={t('chat.input.clear')}>
okText={t('chat.input.clear.title')}>
<ToolbarButton type="text">
<ClearOutlined />
</ToolbarButton>
@ -500,11 +516,11 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic }) => {
/>
)}
<AttachmentButton model={model} files={files} setFiles={setFiles} ToolbarButton={ToolbarButton} />
<ToolbarButton type="text" onClick={onNewContext}>
<Tooltip placement="top" title={t('chat.input.new.context')}>
<Tooltip placement="top" title={t('chat.input.new.context', { Command: newContextShortcut })} arrow>
<ToolbarButton type="text" onClick={onNewContext}>
<PicCenterOutlined />
</Tooltip>
</ToolbarButton>
</ToolbarButton>
</Tooltip>
<Tooltip placement="top" title={expended ? t('chat.input.collapse') : t('chat.input.expand')} arrow>
<ToolbarButton type="text" onClick={onToggleExpended}>
{expended ? <FullscreenExitOutlined /> : <FullscreenOutlined />}

View File

@ -849,6 +849,27 @@ const migrateConfig = {
state.settings.enableQuickAssistant = false
state.settings.clickTrayToShowQuickAssistant = true
return state
},
'58': (state: RootState) => {
if (state.shortcuts) {
state.shortcuts.shortcuts.push(
{
key: 'clear_topic',
shortcut: [isMac ? 'Command' : 'Ctrl', 'L'],
editable: true,
enabled: true,
system: false
},
{
key: 'toggle_new_context',
shortcut: [isMac ? 'Command' : 'Ctrl', 'R'],
editable: true,
enabled: true,
system: false
}
)
}
return state
}
}

View File

@ -58,6 +58,20 @@ const initialState: ShortcutsState = {
editable: true,
enabled: false,
system: true
},
{
key: 'clear_topic',
shortcut: [isMac ? 'Command' : 'Ctrl', 'L'],
editable: true,
enabled: true,
system: false
},
{
key: 'toggle_new_context',
shortcut: [isMac ? 'Command' : 'Ctrl', 'R'],
editable: true,
enabled: true,
system: false
}
]
}