fix: input translate
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user