fix(ai): ignore IME composition enter
This commit is contained in:
parent
077aaa5c06
commit
613c2f981f
|
|
@ -66,6 +66,7 @@ import { useDatabaseOptions } from "@/composables/useDatabaseOptions";
|
|||
import { resolveDefaultDatabase } from "@/lib/defaultDatabase";
|
||||
import { isSchemaAware } from "@/lib/databaseCapabilities";
|
||||
import { formatAiTableMention, parseAiTableMentions, type AiTableMention } from "@/lib/aiTableMentions";
|
||||
import { isAiPromptImeCompositionEvent, shouldSubmitAiPromptOnKeydown } from "@/lib/aiPromptKeyboard";
|
||||
|
||||
const { t } = useI18n();
|
||||
const settings = useSettingsStore();
|
||||
|
|
@ -104,6 +105,7 @@ const conversationId = ref("");
|
|||
const conversations = ref<AiConversation[]>([]);
|
||||
const showConversationList = ref(false);
|
||||
const promptTextareaRef = ref<HTMLTextAreaElement | null>(null);
|
||||
const promptCompositionActive = ref(false);
|
||||
|
||||
interface AiMentionCandidate {
|
||||
schema?: string;
|
||||
|
|
@ -430,6 +432,8 @@ function insertMention(candidate: AiMentionCandidate) {
|
|||
}
|
||||
|
||||
function onPromptKeydown(event: KeyboardEvent) {
|
||||
if (isAiPromptImeCompositionEvent(event, promptCompositionActive.value)) return;
|
||||
|
||||
if (mentionOpen.value) {
|
||||
if (event.key === "ArrowDown") {
|
||||
event.preventDefault();
|
||||
|
|
@ -456,7 +460,7 @@ function onPromptKeydown(event: KeyboardEvent) {
|
|||
}
|
||||
}
|
||||
|
||||
if (event.key === "Enter" && !event.shiftKey && !event.isComposing) {
|
||||
if (shouldSubmitAiPromptOnKeydown(event, promptCompositionActive.value)) {
|
||||
event.preventDefault();
|
||||
send();
|
||||
}
|
||||
|
|
@ -916,6 +920,8 @@ const messageRenderer = createAiMessageRenderer({ markdown: formatInlineText });
|
|||
@input="refreshMentionState"
|
||||
@click="refreshMentionState"
|
||||
@keyup="refreshMentionState"
|
||||
@compositionstart="promptCompositionActive = true"
|
||||
@compositionend="promptCompositionActive = false"
|
||||
@keydown="onPromptKeydown"
|
||||
/>
|
||||
<div class="flex items-center gap-1.5">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
export interface AiPromptKeydownLikeEvent {
|
||||
key: string;
|
||||
shiftKey?: boolean;
|
||||
isComposing?: boolean;
|
||||
keyCode?: number;
|
||||
}
|
||||
|
||||
export function isAiPromptImeCompositionEvent(event: AiPromptKeydownLikeEvent, compositionActive = false): boolean {
|
||||
return compositionActive || !!event.isComposing || event.keyCode === 229 || event.key === "Process";
|
||||
}
|
||||
|
||||
export function shouldSubmitAiPromptOnKeydown(event: AiPromptKeydownLikeEvent, compositionActive = false): boolean {
|
||||
if (event.key !== "Enter") return false;
|
||||
if (event.shiftKey) return false;
|
||||
if (isAiPromptImeCompositionEvent(event, compositionActive)) return false;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
import { strict as assert } from "node:assert";
|
||||
import test from "node:test";
|
||||
import {
|
||||
isAiPromptImeCompositionEvent,
|
||||
shouldSubmitAiPromptOnKeydown,
|
||||
} from "../../apps/desktop/src/lib/aiPromptKeyboard.ts";
|
||||
|
||||
test("submits AI prompt on plain Enter", () => {
|
||||
assert.equal(shouldSubmitAiPromptOnKeydown({ key: "Enter" }), true);
|
||||
});
|
||||
|
||||
test("does not submit AI prompt while entering a newline", () => {
|
||||
assert.equal(shouldSubmitAiPromptOnKeydown({ key: "Enter", shiftKey: true }), false);
|
||||
});
|
||||
|
||||
test("does not submit AI prompt while IME composition is active", () => {
|
||||
assert.equal(shouldSubmitAiPromptOnKeydown({ key: "Enter", isComposing: true }), false);
|
||||
assert.equal(shouldSubmitAiPromptOnKeydown({ key: "Enter" }, true), false);
|
||||
});
|
||||
|
||||
test("does not submit AI prompt for IME composition key events", () => {
|
||||
assert.equal(shouldSubmitAiPromptOnKeydown({ key: "Enter", keyCode: 229 }), false);
|
||||
assert.equal(shouldSubmitAiPromptOnKeydown({ key: "Process" }), false);
|
||||
});
|
||||
|
||||
test("detects AI prompt IME composition key events before mention handling", () => {
|
||||
assert.equal(isAiPromptImeCompositionEvent({ key: "Enter", isComposing: true }), true);
|
||||
assert.equal(isAiPromptImeCompositionEvent({ key: "Enter", keyCode: 229 }), true);
|
||||
assert.equal(isAiPromptImeCompositionEvent({ key: "Process" }), true);
|
||||
assert.equal(isAiPromptImeCompositionEvent({ key: "Enter" }), false);
|
||||
});
|
||||
Loading…
Reference in New Issue