Merge branch 'main' of github.com:CherryHQ/cherry-studio into v2

This commit is contained in:
fullex 2025-09-15 00:06:06 +08:00
commit 0a94609f78
4 changed files with 69 additions and 42 deletions

5
.github/CODEOWNERS vendored
View File

@ -1,3 +1,8 @@
/src/renderer/src/store/ @0xfullex
/src/main/services/ConfigManager.ts @0xfullex
/packages/shared/IpcChannel.ts @0xfullex
/src/main/ipc.ts @0xfullex
/migrations/ @0xfullex /migrations/ @0xfullex
/packages/shared/data/ @0xfullex /packages/shared/data/ @0xfullex
/src/main/data/ @0xfullex /src/main/data/ @0xfullex

View File

@ -1,12 +1,14 @@
out out/
dist dist/
pnpm-lock.yaml build/
LICENSE.md .yarn/
tsconfig.json .github/
tsconfig.*.json .husky/
CHANGELOG*.md .vscode/
agents.json *.yaml
src/renderer/src/integration/nutstore/sso/lib *.yml
AGENT.md *.mjs
*.cjs
*.md
*.json
src/main/integration/ src/main/integration/
.yarn/releases/

View File

@ -341,11 +341,12 @@ export const QuickPanelView: React.FC<Props> = ({ setInputText }) => {
scrollTriggerRef.current = 'none' scrollTriggerRef.current = 'none'
}, [index]) }, [index])
// 处理键盘事件(折叠时不拦截全局键盘) // 处理键盘事件:
// - 可见且未折叠时:拦截 Enter 及其组合键(纯 Enter 选择项;带修饰键仅拦截不处理)。
// - 软隐藏/折叠时:不拦截 Enter允许输入框处理用于发送消息等
// - 不可见时:不拦截,输入框按常规处理。
useEffect(() => { useEffect(() => {
const hasSearchTextFlag = searchText.replace(/^[/@]/, '').length > 0 if (!ctx.isVisible) return
const isCollapsed = hasSearchTextFlag && list.length === 0
if (!ctx.isVisible || isCollapsed) return
const handleKeyDown = (e: KeyboardEvent) => { const handleKeyDown = (e: KeyboardEvent) => {
if (isMac ? e.metaKey : e.ctrlKey) { if (isMac ? e.metaKey : e.ctrlKey) {
@ -438,9 +439,24 @@ export const QuickPanelView: React.FC<Props> = ({ setInputText }) => {
break break
case 'Enter': case 'Enter':
case 'NumpadEnter': case 'NumpadEnter': {
if (isComposing.current) return if (isComposing.current) return
// 折叠/软隐藏时不拦截,让输入框处理(用于发送消息)
const hasSearch = searchText.replace(/^[/@]/, '').length > 0
const nonPinnedCount = list.filter((i) => !i.alwaysVisible).length
const isCollapsed = hasSearch && nonPinnedCount === 0
if (isCollapsed) return
// 面板可见且未折叠时:拦截所有 Enter 变体;
// 纯 Enter 选择项,带修饰键仅拦截不处理
if (e.ctrlKey || e.metaKey || e.altKey || e.shiftKey) {
e.preventDefault()
e.stopPropagation()
setIsMouseOver(false)
break
}
if (list?.[index]) { if (list?.[index]) {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
@ -451,6 +467,7 @@ export const QuickPanelView: React.FC<Props> = ({ setInputText }) => {
handleClose('enter_empty') handleClose('enter_empty')
} }
break break
}
case 'Escape': case 'Escape':
e.stopPropagation() e.stopPropagation()
handleClose('esc') handleClose('esc')

View File

@ -406,37 +406,40 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
//other keys should be ignored //other keys should be ignored
const isEnterPressed = event.key === 'Enter' && !event.nativeEvent.isComposing const isEnterPressed = event.key === 'Enter' && !event.nativeEvent.isComposing
if (isEnterPressed) { if (isEnterPressed) {
if (quickPanel.isVisible) return event.preventDefault() // 1) 优先判断是否为“发送”(当前仅支持纯 Enter 发送;其余 Enter 组合键均换行)
if (isSendMessageKeyPressed(event, sendMessageShortcut)) { if (isSendMessageKeyPressed(event, sendMessageShortcut)) {
sendMessage() sendMessage()
return event.preventDefault() return event.preventDefault()
} else { }
//shift+enter's default behavior is to add a new line, ignore it
if (!event.shiftKey) {
event.preventDefault()
const textArea = textareaRef.current?.resizableTextArea?.textArea // 2) 不再基于 quickPanel.isVisible 主动拦截。
if (textArea) { // 纯 Enter 的处理权交由 QuickPanel 的全局捕获(其只在纯 Enter 时拦截),
const start = textArea.selectionStart // 其它带修饰键的 Enter 则由输入框处理为换行。
const end = textArea.selectionEnd
const text = textArea.value
const newText = text.substring(0, start) + '\n' + text.substring(end)
// update text by setState, not directly modify textarea.value if (event.shiftKey) {
setText(newText) return
}
// set cursor position in the next render cycle event.preventDefault()
setTimeoutTimer( const textArea = textareaRef.current?.resizableTextArea?.textArea
'handleKeyDown', if (textArea) {
() => { const start = textArea.selectionStart
textArea.selectionStart = textArea.selectionEnd = start + 1 const end = textArea.selectionEnd
onInput() // trigger resizeTextArea const text = textArea.value
}, const newText = text.substring(0, start) + '\n' + text.substring(end)
0
) // update text by setState, not directly modify textarea.value
} setText(newText)
}
// set cursor position in the next render cycle
setTimeoutTimer(
'handleKeyDown',
() => {
textArea.selectionStart = textArea.selectionEnd = start + 1
onInput() // trigger resizeTextArea
},
0
)
} }
} }