支持自定义消息发送和消息换行快捷键

This commit is contained in:
xintaofei
2026-03-12 08:53:47 +08:00
parent f9771d6f27
commit d75e0cef48
14 changed files with 126 additions and 6 deletions

View File

@@ -15,6 +15,8 @@ import {
import { Textarea } from "@/components/ui/textarea"
import { Ellipsis, FileSearch, Plus, Send, Square, X } from "lucide-react"
import { cn } from "@/lib/utils"
import { matchShortcutEvent } from "@/lib/keyboard-shortcuts"
import { useShortcutSettings } from "@/hooks/use-shortcut-settings"
import { readFileBase64 } from "@/lib/tauri"
import { disposeTauriListener } from "@/lib/tauri-listener"
import type {
@@ -261,6 +263,7 @@ export function MessageInput({
isActive = false,
}: MessageInputProps) {
const t = useTranslations("Folder.chat.messageInput")
const { shortcuts } = useShortcutSettings()
const effectiveDraftStorageKey = draftStorageKey ?? attachmentTabId ?? null
const resolvedPlaceholder = placeholder ?? t("askAnything")
const [text, setText] = useState(() => {
@@ -932,14 +935,26 @@ export function MessageInput({
}
}
if (e.key === "Enter" && !e.shiftKey) {
if (matchShortcutEvent(e, shortcuts.send_message)) {
e.preventDefault()
if (!disabled) handleSend()
} else if (matchShortcutEvent(e, shortcuts.newline_in_message)) {
e.preventDefault()
const textarea = e.currentTarget as HTMLTextAreaElement
const start = textarea.selectionStart
const end = textarea.selectionEnd
const value = textarea.value
const newValue = value.substring(0, start) + "\n" + value.substring(end)
setText(newValue)
requestAnimationFrame(() => {
textarea.selectionStart = textarea.selectionEnd = start + 1
})
}
},
[
disabled,
handleSend,
shortcuts,
slashMenuOpen,
filteredSlashCommands,
slashSelectedIndex,

View File

@@ -4,6 +4,8 @@ import { useState, useRef, useEffect, useCallback } from "react"
import { useTranslations } from "next-intl"
import { MessageCircleQuestion, SendHorizonal } from "lucide-react"
import { Button } from "@/components/ui/button"
import { matchShortcutEvent } from "@/lib/keyboard-shortcuts"
import { useShortcutSettings } from "@/hooks/use-shortcut-settings"
import type { PendingQuestion } from "@/contexts/acp-connections-context"
interface QuestionDialogProps {
@@ -13,6 +15,7 @@ interface QuestionDialogProps {
export function QuestionDialog({ question, onAnswer }: QuestionDialogProps) {
const t = useTranslations("Folder.chat.questionDialog")
const { shortcuts } = useShortcutSettings()
const [answer, setAnswer] = useState("")
const textareaRef = useRef<HTMLTextAreaElement>(null)
const prevQuestionIdRef = useRef<string | null>(null)
@@ -40,12 +43,12 @@ export function QuestionDialog({ question, onAnswer }: QuestionDialogProps) {
const handleKeyDown = useCallback(
(e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === "Enter" && !e.shiftKey) {
if (matchShortcutEvent(e, shortcuts.send_message)) {
e.preventDefault()
handleSubmit()
}
},
[handleSubmit]
[handleSubmit, shortcuts]
)
if (!question) return null

View File

@@ -8,6 +8,7 @@ import { useIsMac } from "@/hooks/use-is-mac"
import { useShortcutSettings } from "@/hooks/use-shortcut-settings"
import {
DEFAULT_SHORTCUTS,
INPUT_SHORTCUT_IDS,
SHORTCUT_DEFINITIONS,
type ShortcutActionId,
formatShortcutLabel,
@@ -64,7 +65,8 @@ export function ShortcutSettings() {
return
}
const shortcut = shortcutFromKeyboardEvent(event)
const allowNoModifier = INPUT_SHORTCUT_IDS.has(recordingAction)
const shortcut = shortcutFromKeyboardEvent(event, allowNoModifier)
if (!shortcut) return
const conflict = SHORTCUT_DEFINITIONS.find(