diff --git a/src/content_script/content_script.ts b/src/content_script/content_script.ts index 5c47e92..c505dc9 100644 --- a/src/content_script/content_script.ts +++ b/src/content_script/content_script.ts @@ -14,14 +14,6 @@ declare global { if (window.hasRun) return; window.hasRun = true; - const setEnabled = (v: boolean) => { - document.removeEventListener("selectionchange", onSelectionChange); //Always remove it avoid duplicate event listeners - if (v) { - onSelectionChange(); // Call it since selection may have changed since it was enabled - document.addEventListener("selectionchange", onSelectionChange); - } else tippyInstance.hide(); - }; - browser.runtime.onMessage.addListener((c: command) => { switch (c.commandKind) { case commands.setEnabled: @@ -30,20 +22,7 @@ declare global { } }); - const tippyInstance = tippy(document.body, { - allowHTML: true, - trigger: "manual", - interactive: true, - getReferenceClientRect: () => - document.getSelection().getRangeAt(0).getBoundingClientRect(), - onShow: (instance) => { - instance.setContent( - `` - ); - }, - }); + const tippyInstance = setupTippy(); let timeoutID: number; const onSelectionChange = () => { @@ -52,4 +31,35 @@ declare global { if (document.getSelection().type == "Range") timeoutID = window.setTimeout(tippyInstance.show, 500); }; + + function setEnabled(v: boolean) { + document.removeEventListener("selectionchange", onSelectionChange); //Always remove it avoid duplicate event listeners + if (v) { + onSelectionChange(); // Call it since selection may have changed since it was enabled + document.addEventListener("selectionchange", onSelectionChange); + } else tippyInstance.hide(); + } + + function setupTippy() { + const translateElement = document.createElement("lingo-translate"); + return tippy(document.body, { + content: translateElement, + allowHTML: true, + trigger: "manual", + interactive: true, + getReferenceClientRect: () => + document.getSelection().getRangeAt(0).getBoundingClientRect(), + onCreate: (instance) => { + translateElement.addEventListener("translationFinished", () => + instance.popperInstance.update() + ); + }, + onShow: () => { + translateElement.setAttribute( + "translate", + document.getSelection().toString() + ); + }, + }); + } })(); diff --git a/src/content_script/custom_elements.ts b/src/content_script/custom_elements.ts index 4e81e34..a043217 100644 --- a/src/content_script/custom_elements.ts +++ b/src/content_script/custom_elements.ts @@ -2,33 +2,33 @@ import { browser } from "webextension-polyfill-ts"; import contents from "./spinner.scss?raw"; class LingoTranslate extends HTMLElement { - shadow: ShadowRoot; - constructor() { super(); - this.shadow = this.attachShadow({ mode: "open" }); + this.attachShadow({ mode: "open" }); + } + + render = () => { + this.shadowRoot.innerHTML = ""; + const toTranslate = this.getAttribute("translate"); + if (toTranslate) { + const translation = browser.runtime.sendMessage({ + commandKind: commands.translate, + toTranslate: toTranslate, + }); + translation.then((t: TranslationResponse) => { + if (t.src == this.getAttribute("translate")) { + this.shadowRoot.textContent = t.result; + this.dispatchEvent(new Event("translationFinished")); + } + }); + } + }; + attributeChangedCallback() { this.render(); } - render = () => { - this.shadow.innerHTML = ""; - const toTranslate = this.getAttribute("toTranslate"); - const translation = browser.runtime.sendMessage({ - commandKind: commands.translate, - toTranslate: toTranslate, - }); - translation.then((t) => (this.shadow.textContent = t.result)); - }; - - attributeChangedCallback = ( - attributeName: string, - oldValue: string, - newValue: string - ) => { - if (attributeName === "toTranslate" && oldValue != newValue) this.render(); - }; static get observedAttributes() { - return ["toTranslate"]; + return ["translate"]; } } customElements.define("lingo-translate", LingoTranslate);