diff --git a/src/hooks/Translate.js b/src/hooks/Translate.js index 6668a71..40415f1 100644 --- a/src/hooks/Translate.js +++ b/src/hooks/Translate.js @@ -1,63 +1,26 @@ import { useEffect } from "react"; import { useState } from "react"; import { transPool } from "../libs/pool"; -import { browser } from "../libs/browser"; -import { MSG_TRANS_PUTRULE, EVENT_KISS } from "../config"; import { detectLang } from "../libs"; -import { isExt } from "../libs/browser"; /** * 翻译hook * @param {*} q + * @param {*} rule * @returns */ -export function useTranslate(q, initRule) { +export function useTranslate(q, rule) { const [text, setText] = useState(""); const [loading, setLoading] = useState(false); const [sameLang, setSamelang] = useState(false); - const [rule, setRule] = useState(initRule); - const { translator, fromLang, toLang, textStyle, bgColor } = rule; - - const handleMessage = ({ action, args }) => { - if (action === MSG_TRANS_PUTRULE) { - setRule((pre) => ({ ...pre, ...args })); - } - return true; - }; - - const handleKissEvent = (e) => { - const action = e?.detail?.action; - const args = e?.detail?.args || {}; - switch (action) { - case MSG_TRANS_PUTRULE: - setRule((pre) => ({ ...pre, ...args })); - break; - default: - // console.log(`[popup] kissEvent action skip: ${action}`); - } - }; - - useEffect(() => { - if (isExt) { - browser?.runtime.onMessage.addListener(handleMessage); - } else { - window.addEventListener(EVENT_KISS, handleKissEvent); - } - - return () => { - if (isExt) { - browser?.runtime.onMessage.removeListener(handleMessage); - } else { - window.removeEventListener(EVENT_KISS, handleKissEvent); - } - }; - }, []); + const { translator, fromLang, toLang } = rule; useEffect(() => { (async () => { try { setLoading(true); + const deLang = await detectLang(q); if (toLang.includes(deLang)) { setSamelang(true); @@ -79,5 +42,5 @@ export function useTranslate(q, initRule) { })(); }, [q, translator, fromLang, toLang]); - return { text, sameLang, loading, textStyle, bgColor }; + return { text, sameLang, loading }; } diff --git a/src/libs/translator.js b/src/libs/translator.js index d5b8381..a89b8f0 100644 --- a/src/libs/translator.js +++ b/src/libs/translator.js @@ -1,5 +1,11 @@ import { createRoot } from "react-dom/client"; -import { APP_LCNAME, TRANS_MIN_LENGTH, TRANS_MAX_LENGTH } from "../config"; +import { + APP_LCNAME, + TRANS_MIN_LENGTH, + TRANS_MAX_LENGTH, + EVENT_KISS, + MSG_TRANS_CURRULE, +} from "../config"; import { StoragesProvider } from "../hooks/Storage"; import { queryEls } from "."; import Content from "../views/Content"; @@ -28,7 +34,7 @@ export class Translator { mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { try { - queryEls(this._rule.selector, node).forEach((el) => { + queryEls(this.rule.selector, node).forEach((el) => { this._interseObserver.observe(el); }); } catch (err) { @@ -39,26 +45,42 @@ export class Translator { }); constructor(rule) { - this._rule = rule; + this.rule = rule; if (rule.transOpen === "true") { this._register(); } } get rule() { + // console.log("get rule", this._rule); return this._rule; } + set rule(rule) { + // console.log("set rule", rule); + this._rule = rule; + + // 广播消息 + window.dispatchEvent( + new CustomEvent(EVENT_KISS, { + detail: { + action: MSG_TRANS_CURRULE, + args: rule, + }, + }) + ); + } + updateRule = (obj) => { - this._rule = { ...this._rule, ...obj }; + this.rule = { ...this.rule, ...obj }; }; toggle = () => { - if (this._rule.transOpen === "true") { - this._rule = { ...this._rule, transOpen: "false" }; + if (this.rule.transOpen === "true") { + this.rule = { ...this.rule, transOpen: "false" }; this._unRegister(); } else { - this._rule = { ...this._rule, transOpen: "true" }; + this.rule = { ...this.rule, transOpen: "true" }; this._register(); } }; @@ -71,7 +93,7 @@ export class Translator { }); // 监听节点显示 - queryEls(this._rule.selector).forEach((el) => { + queryEls(this.rule.selector).forEach((el) => { this._interseObserver.observe(el); }); }; @@ -81,7 +103,7 @@ export class Translator { this._mutaObserver.disconnect(); // 解除节点显示监听 - queryEls(this._rule.selector).forEach((el) => + queryEls(this.rule.selector).forEach((el) => this._interseObserver.unobserve(el) ); @@ -90,14 +112,19 @@ export class Translator { }; _render = (el) => { + // 含子元素 + if (el.querySelector(this.rule.selector)) { + return; + } + + // 已翻译 if (el.querySelector(APP_LCNAME)) { return; } - // 除openai外,保留code和a标签 + // 太长或太短 const q = el.innerText.trim(); if (!q || q.length < TRANS_MIN_LENGTH || q.length > TRANS_MAX_LENGTH) { - // 太长或太短不翻译 return; } @@ -109,7 +136,7 @@ export class Translator { const root = createRoot(span); root.render( - + ); }; diff --git a/src/views/Content/index.js b/src/views/Content/index.js index de72511..c65282d 100644 --- a/src/views/Content/index.js +++ b/src/views/Content/index.js @@ -1,4 +1,4 @@ -import { useMemo, useState } from "react"; +import { useMemo, useState, useEffect } from "react"; import LoadingIcon from "./LoadingIcon"; import { OPT_STYLE_LINE, @@ -8,12 +8,16 @@ import { OPT_STYLE_FUZZY, OPT_STYLE_HIGHTLIGHT, DEFAULT_COLOR, + EVENT_KISS, + MSG_TRANS_CURRULE, } from "../../config"; import { useTranslate } from "../../hooks/Translate"; -export default function Content({ q, rule }) { +export default function Content({ q, translator }) { + const [rule, setRule] = useState(translator.rule); const [hover, setHover] = useState(false); - const { text, sameLang, loading, textStyle, bgColor } = useTranslate(q, rule); + const { text, sameLang, loading } = useTranslate(q, rule); + const { textStyle, bgColor } = rule; const handleMouseEnter = () => { setHover(true); @@ -23,6 +27,24 @@ export default function Content({ q, rule }) { setHover(false); }; + const handleKissEvent = (e) => { + const { action, args } = e.detail; + switch (action) { + case MSG_TRANS_CURRULE: + setRule(args); + break; + default: + // console.log(`[popup] kissEvent action skip: ${action}`); + } + }; + + useEffect(() => { + window.addEventListener(EVENT_KISS, handleKissEvent); + return () => { + window.removeEventListener(EVENT_KISS, handleKissEvent); + }; + }, []); + const style = useMemo(() => { const lineColor = bgColor || ""; switch (textStyle) {