fix: input translate

This commit is contained in:
Gabe
2025-10-31 10:05:01 +08:00
parent 0a6f4a9f02
commit 9ded6446a7

View File

@@ -8,7 +8,7 @@ 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";
import { kissLog } from "./log"; import { logger } from "./log";
function isInputNode(node) { function isInputNode(node) {
return node.nodeName === "INPUT" || node.nodeName === "TEXTAREA"; return node.nodeName === "INPUT" || node.nodeName === "TEXTAREA";
@@ -19,11 +19,11 @@ function isEditAbleNode(node) {
} }
async function replaceContentEditableText(node, newText) { async function replaceContentEditableText(node, newText) {
node.focus();
const originalText = node.innerText;
try { try {
logger.debug("try replace editable 1: pasteEvent");
node.focus();
const selection = window.getSelection(); const selection = window.getSelection();
if (!selection) throw new Error("window.getSelection() is not available."); if (!selection) throw new Error("window.getSelection() is not available.");
@@ -41,27 +41,23 @@ async function replaceContentEditableText(node, newText) {
bubbles: true, bubbles: true,
cancelable: true, cancelable: true,
}); });
node.dispatchEvent(pasteEvent); node.dispatchEvent(pasteEvent);
await sleep(50); await sleep(50);
if ( if (node.innerText.trim() === newText) {
node.innerText.includes(newText) &&
(newText.length > 0 || node.innerText.length === 0)
) {
return true; return true;
} }
if (node.innerText !== originalText) {
document.execCommand("undo");
}
throw new Error("Strategy 1 failed to replace text correctly."); throw new Error("Strategy 1 failed to replace text correctly.");
} catch (error) { } catch (error) {
kissLog("Strategy 1 Failed:", error.message); logger.debug("Strategy 1 Failed:", error.message);
} }
try { try {
logger.debug("try replace editable 2: execCommand");
node.focus(); node.focus();
const selection = window.getSelection(); const selection = window.getSelection();
if (!selection) throw new Error("window.getSelection() is not available."); if (!selection) throw new Error("window.getSelection() is not available.");
@@ -74,16 +70,20 @@ async function replaceContentEditableText(node, newText) {
document.execCommand("insertText", false, newText); document.execCommand("insertText", false, newText);
await sleep(50); await sleep(50);
if (node.innerText === newText) { if (node.innerText.trim() === newText) {
return true; return true;
} }
throw new Error("Strategy 2 failed to replace text correctly."); throw new Error("Strategy 2 failed to replace text correctly.");
} catch (error) { } catch (error) {
kissLog("Strategy 2 Failed:", error.message); logger.debug("Strategy 2 Failed:", error.message);
} }
try { try {
logger.debug("try replace editable 3: textContent");
node.focus();
const targetNode = node.querySelector("p") || node; const targetNode = node.querySelector("p") || node;
const textSpan = targetNode.querySelector('span[data-lexical-text="true"]'); const textSpan = targetNode.querySelector('span[data-lexical-text="true"]');
@@ -96,12 +96,13 @@ async function replaceContentEditableText(node, newText) {
node.dispatchEvent(new Event("input", { bubbles: true, cancelable: true })); node.dispatchEvent(new Event("input", { bubbles: true, cancelable: true }));
await sleep(50); await sleep(50);
if (node.innerText === newText) { if (node.innerText.trim() === newText) {
return true; return true;
} }
throw new Error("Strategy 3 failed to replace text correctly."); throw new Error("Strategy 3 failed to replace text correctly.");
} catch (error) { } catch (error) {
kissLog("Strategy 3 Failed:", error.message); logger.debug("Strategy 3 Failed:", error.message);
} }
return false; return false;
@@ -179,7 +180,7 @@ export class InputTranslator {
); );
this.#isEnabled = true; this.#isEnabled = true;
kissLog("Input Translator enabled."); logger.info("Input Translator enabled.");
} }
/** /**
@@ -194,7 +195,7 @@ export class InputTranslator {
this.#unregisterShortcut = null; this.#unregisterShortcut = null;
} }
this.#isEnabled = false; this.#isEnabled = false;
kissLog("Input Translator disabled."); logger.info("Input Translator disabled.");
} }
/** /**
@@ -272,21 +273,23 @@ export class InputTranslator {
apiSetting, apiSetting,
}); });
if (!trText || isSame) return; const newText = trText?.trim() || "";
if (!newText || isSame) return;
if (isInputNode(node)) { if (isInputNode(node)) {
node.value = trText; node.value = newText;
node.dispatchEvent( node.dispatchEvent(
new Event("input", { bubbles: true, cancelable: true }) new Event("input", { bubbles: true, cancelable: true })
); );
} else { } else {
const success = await replaceContentEditableText(node, trText); const success = await replaceContentEditableText(node, newText);
if (!success) { if (!success) {
// todo: 提示可以黏贴 // todo: 提示可以黏贴
logger.info("Replace editable text failed");
} }
} }
} catch (err) { } catch (err) {
kissLog("Translate input error:", err); logger.info("Translate input error:", err);
} finally { } finally {
removeLoading(loadingId); removeLoading(loadingId);
} }