fix: input translate (#342)

This commit is contained in:
Gabe
2025-10-31 01:39:27 +08:00
parent 635e588bcc
commit 0a6f4a9f02

View File

@@ -4,7 +4,7 @@ import {
OPT_LANGS_LIST, OPT_LANGS_LIST,
DEFAULT_API_SETTING, DEFAULT_API_SETTING,
} from "../config"; } from "../config";
import { genEventName, removeEndchar, matchInputStr } from "./utils"; import { genEventName, removeEndchar, matchInputStr, sleep } from "./utils";
import { stepShortcutRegister } from "./shortcut"; import { stepShortcutRegister } from "./shortcut";
import { apiTranslate } from "../apis"; import { apiTranslate } from "../apis";
import { createLoadingSVG } from "./svg"; import { createLoadingSVG } from "./svg";
@@ -18,21 +18,93 @@ function isEditAbleNode(node) {
return node.hasAttribute("contenteditable"); return node.hasAttribute("contenteditable");
} }
function replaceContentEditableText(node, newText) { async function replaceContentEditableText(node, newText) {
node.focus(); node.focus();
const selection = window.getSelection();
if (!selection) return;
const range = document.createRange(); const originalText = node.innerText;
range.selectNodeContents(node);
selection.removeAllRanges();
selection.addRange(range);
range.deleteContents(); try {
const textNode = document.createTextNode(newText); const selection = window.getSelection();
range.insertNode(textNode); if (!selection) throw new Error("window.getSelection() is not available.");
selection.collapseToEnd(); const targetNode = node.querySelector("p") || node;
const range = document.createRange();
range.selectNodeContents(targetNode);
selection.removeAllRanges();
selection.addRange(range);
const dataTransfer = new DataTransfer();
dataTransfer.setData("text/plain", newText);
const pasteEvent = new ClipboardEvent("paste", {
clipboardData: dataTransfer,
bubbles: true,
cancelable: true,
});
node.dispatchEvent(pasteEvent);
await sleep(50);
if (
node.innerText.includes(newText) &&
(newText.length > 0 || node.innerText.length === 0)
) {
return true;
}
if (node.innerText !== originalText) {
document.execCommand("undo");
}
throw new Error("Strategy 1 failed to replace text correctly.");
} catch (error) {
kissLog("Strategy 1 Failed:", error.message);
}
try {
node.focus();
const selection = window.getSelection();
if (!selection) throw new Error("window.getSelection() is not available.");
const targetNode = node.querySelector("p") || node;
const range = document.createRange();
range.selectNodeContents(targetNode);
selection.removeAllRanges();
selection.addRange(range);
document.execCommand("insertText", false, newText);
await sleep(50);
if (node.innerText === newText) {
return true;
}
throw new Error("Strategy 2 failed to replace text correctly.");
} catch (error) {
kissLog("Strategy 2 Failed:", error.message);
}
try {
const targetNode = node.querySelector("p") || node;
const textSpan = targetNode.querySelector('span[data-lexical-text="true"]');
if (textSpan) {
textSpan.textContent = newText;
} else {
targetNode.textContent = newText;
}
node.dispatchEvent(new Event("input", { bubbles: true, cancelable: true }));
await sleep(50);
if (node.innerText === newText) {
return true;
}
throw new Error("Strategy 3 failed to replace text correctly.");
} catch (error) {
kissLog("Strategy 3 Failed:", error.message);
}
return false;
} }
function getNodeText(node) { function getNodeText(node) {
@@ -208,7 +280,10 @@ export class InputTranslator {
new Event("input", { bubbles: true, cancelable: true }) new Event("input", { bubbles: true, cancelable: true })
); );
} else { } else {
replaceContentEditableText(node, trText); const success = await replaceContentEditableText(node, trText);
if (!success) {
// todo: 提示可以黏贴
}
} }
} catch (err) { } catch (err) {
kissLog("Translate input error:", err); kissLog("Translate input error:", err);