fix: restore IME fix, fileTypeStyles, clearStaged fix lost in inline edit merge

This commit is contained in:
LIghtJUNction
2026-04-29 03:14:46 +08:00
parent e610c49499
commit 4925397542
5 changed files with 97 additions and 2 deletions

View File

@@ -1,4 +1,4 @@
/* Auto-generated MDI subset 260 icons */
/* Auto-generated MDI subset 267 icons */
/* Do not edit manually. Run: pnpm run subset-icons */
@font-face {
@@ -416,6 +416,10 @@
content: "\F022E";
}
.mdi-file-delimited-outline::before {
content: "\F0EA5";
}
.mdi-file-document::before {
content: "\F0219";
}
@@ -592,10 +596,34 @@
content: "\F0318";
}
.mdi-language-css3::before {
content: "\F031C";
}
.mdi-language-html5::before {
content: "\F031D";
}
.mdi-language-javascript::before {
content: "\F031E";
}
.mdi-language-markdown::before {
content: "\F0354";
}
.mdi-language-markdown-outline::before {
content: "\F0F5B";
}
.mdi-language-python::before {
content: "\F0320";
}
.mdi-language-typescript::before {
content: "\F06E6";
}
.mdi-layers-outline::before {
content: "\F09FE";
}

View File

@@ -933,7 +933,7 @@ async function sendCurrentMessage() {
draft.value = "";
replyTarget.value = null;
clearStaged();
clearStaged({ revokeUrls: false });
scrollToBottom();
sendMessageStream({

View File

@@ -50,6 +50,10 @@
ref="inputField"
v-model="localPrompt"
@keydown="handleKeyDown"
@compositionstart="handleCompositionStart"
@compositionend="handleCompositionEnd"
@compositioncancel="handleCompositionEnd"
@blur="clearCompositionState()"
:disabled="disabled"
placeholder="Ask AstrBot..."
class="chat-textarea"
@@ -304,6 +308,7 @@ import {
import { useDisplay } from "vuetify";
import { useModuleI18n } from "@/i18n/composables";
import { useCustomizerStore } from "@/stores/customizer";
import { isComposingEnter } from "@/utils/imeInput.mjs";
import ConfigSelector from "./ConfigSelector.vue";
import ProviderModelMenu from "./ProviderModelMenu.vue";
import StyledMenu from "@/components/shared/StyledMenu.vue";
@@ -375,6 +380,8 @@ const providerModelMenuRef = ref<InstanceType<typeof ProviderModelMenu> | null>(
);
const showProviderSelector = ref(true);
const isReplyClosing = ref(false);
const isComposing = ref(false);
const lastCompositionEndAt = ref<number | null>(null);
const isDragging = ref(false);
let dragLeaveTimeout: number | null = null;
@@ -397,6 +404,44 @@ const canSend = computed(() => {
);
});
const fileTypeStyles: Record<
string,
{ color: string; icon: string; label: string }
> = {
pdf: { color: "#d32f2f", icon: "mdi-file-pdf-box", label: "PDF" },
txt: { color: "#1976d2", icon: "mdi-file-document-outline", label: "TXT" },
md: { color: "#1976d2", icon: "mdi-language-markdown-outline", label: "MD" },
doc: { color: "#2b579a", icon: "mdi-file-word-box", label: "DOC" },
docx: { color: "#2b579a", icon: "mdi-file-word-box", label: "DOCX" },
xls: { color: "#217346", icon: "mdi-file-excel-box", label: "XLS" },
xlsx: { color: "#217346", icon: "mdi-file-excel-box", label: "XLSX" },
csv: { color: "#217346", icon: "mdi-file-delimited-outline", label: "CSV" },
zip: { color: "#7b5e00", icon: "mdi-folder-zip-outline", label: "ZIP" },
py: { color: "#3776ab", icon: "mdi-language-python", label: "PY" },
js: { color: "#b8860b", icon: "mdi-language-javascript", label: "JS" },
ts: { color: "#3178c6", icon: "mdi-language-typescript", label: "TS" },
html: { color: "#e34c26", icon: "mdi-language-html5", label: "HTML" },
css: { color: "#264de4", icon: "mdi-language-css3", label: "CSS" },
json: { color: "#6a1b9a", icon: "mdi-code-json", label: "JSON" },
};
function fileExtension(file: StagedFileInfo) {
const name = file.original_name || file.filename || "";
const extension = name.split(".").pop()?.toLowerCase() || "";
return extension === name.toLowerCase() ? "" : extension;
}
function filePresentation(file: StagedFileInfo) {
const extension = fileExtension(file);
return (
fileTypeStyles[extension] || {
color: "#607d8b",
icon: "mdi-file-document-outline",
label: extension ? extension.slice(0, 4).toUpperCase() : "FILE",
}
);
}
// Ctrl+B 长按录音相关
const ctrlKeyDown = ref(false);
const ctrlKeyTimer = ref<number | null>(null);
@@ -445,6 +490,10 @@ function handleKeyDown(e: KeyboardEvent) {
return;
}
if (isComposingEnter(e, isComposing.value, lastCompositionEndAt.value)) {
return;
}
const isSendHotkey =
e.ctrlKey ||
e.metaKey ||
@@ -464,6 +513,23 @@ function handleKeyDown(e: KeyboardEvent) {
}
}
function handleCompositionStart() {
isComposing.value = true;
lastCompositionEndAt.value = null;
}
function handleCompositionEnd(e: CompositionEvent) {
lastCompositionEndAt.value = e.timeStamp;
clearCompositionState({ keepLastEndAt: true });
}
function clearCompositionState({ keepLastEndAt = false } = {}) {
isComposing.value = false;
if (!keepLastEndAt) {
lastCompositionEndAt.value = null;
}
}
function handleKeyUp(e: KeyboardEvent) {
if (e.keyCode === 66) {
ctrlKeyDown.value = false;
@@ -562,6 +628,7 @@ onMounted(() => {
});
onBeforeUnmount(() => {
clearCompositionState();
if (inputField.value) {
inputField.value.removeEventListener("paste", handlePaste);
}