optimize Translator class & EVENT_KISS event
This commit is contained in:
@@ -1,63 +1,26 @@
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { transPool } from "../libs/pool";
|
import { transPool } from "../libs/pool";
|
||||||
import { browser } from "../libs/browser";
|
|
||||||
import { MSG_TRANS_PUTRULE, EVENT_KISS } from "../config";
|
|
||||||
import { detectLang } from "../libs";
|
import { detectLang } from "../libs";
|
||||||
import { isExt } from "../libs/browser";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 翻译hook
|
* 翻译hook
|
||||||
* @param {*} q
|
* @param {*} q
|
||||||
|
* @param {*} rule
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function useTranslate(q, initRule) {
|
export function useTranslate(q, rule) {
|
||||||
const [text, setText] = useState("");
|
const [text, setText] = useState("");
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [sameLang, setSamelang] = useState(false);
|
const [sameLang, setSamelang] = useState(false);
|
||||||
const [rule, setRule] = useState(initRule);
|
|
||||||
|
|
||||||
const { translator, fromLang, toLang, textStyle, bgColor } = rule;
|
const { translator, fromLang, toLang } = 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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
const deLang = await detectLang(q);
|
const deLang = await detectLang(q);
|
||||||
if (toLang.includes(deLang)) {
|
if (toLang.includes(deLang)) {
|
||||||
setSamelang(true);
|
setSamelang(true);
|
||||||
@@ -79,5 +42,5 @@ export function useTranslate(q, initRule) {
|
|||||||
})();
|
})();
|
||||||
}, [q, translator, fromLang, toLang]);
|
}, [q, translator, fromLang, toLang]);
|
||||||
|
|
||||||
return { text, sameLang, loading, textStyle, bgColor };
|
return { text, sameLang, loading };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
import { createRoot } from "react-dom/client";
|
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 { StoragesProvider } from "../hooks/Storage";
|
||||||
import { queryEls } from ".";
|
import { queryEls } from ".";
|
||||||
import Content from "../views/Content";
|
import Content from "../views/Content";
|
||||||
@@ -28,7 +34,7 @@ export class Translator {
|
|||||||
mutations.forEach((mutation) => {
|
mutations.forEach((mutation) => {
|
||||||
mutation.addedNodes.forEach((node) => {
|
mutation.addedNodes.forEach((node) => {
|
||||||
try {
|
try {
|
||||||
queryEls(this._rule.selector, node).forEach((el) => {
|
queryEls(this.rule.selector, node).forEach((el) => {
|
||||||
this._interseObserver.observe(el);
|
this._interseObserver.observe(el);
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -39,26 +45,42 @@ export class Translator {
|
|||||||
});
|
});
|
||||||
|
|
||||||
constructor(rule) {
|
constructor(rule) {
|
||||||
this._rule = rule;
|
this.rule = rule;
|
||||||
if (rule.transOpen === "true") {
|
if (rule.transOpen === "true") {
|
||||||
this._register();
|
this._register();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get rule() {
|
get rule() {
|
||||||
|
// console.log("get rule", this._rule);
|
||||||
return 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) => {
|
updateRule = (obj) => {
|
||||||
this._rule = { ...this._rule, ...obj };
|
this.rule = { ...this.rule, ...obj };
|
||||||
};
|
};
|
||||||
|
|
||||||
toggle = () => {
|
toggle = () => {
|
||||||
if (this._rule.transOpen === "true") {
|
if (this.rule.transOpen === "true") {
|
||||||
this._rule = { ...this._rule, transOpen: "false" };
|
this.rule = { ...this.rule, transOpen: "false" };
|
||||||
this._unRegister();
|
this._unRegister();
|
||||||
} else {
|
} else {
|
||||||
this._rule = { ...this._rule, transOpen: "true" };
|
this.rule = { ...this.rule, transOpen: "true" };
|
||||||
this._register();
|
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);
|
this._interseObserver.observe(el);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -81,7 +103,7 @@ export class Translator {
|
|||||||
this._mutaObserver.disconnect();
|
this._mutaObserver.disconnect();
|
||||||
|
|
||||||
// 解除节点显示监听
|
// 解除节点显示监听
|
||||||
queryEls(this._rule.selector).forEach((el) =>
|
queryEls(this.rule.selector).forEach((el) =>
|
||||||
this._interseObserver.unobserve(el)
|
this._interseObserver.unobserve(el)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -90,14 +112,19 @@ export class Translator {
|
|||||||
};
|
};
|
||||||
|
|
||||||
_render = (el) => {
|
_render = (el) => {
|
||||||
|
// 含子元素
|
||||||
|
if (el.querySelector(this.rule.selector)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 已翻译
|
||||||
if (el.querySelector(APP_LCNAME)) {
|
if (el.querySelector(APP_LCNAME)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 除openai外,保留code和a标签
|
// 太长或太短
|
||||||
const q = el.innerText.trim();
|
const q = el.innerText.trim();
|
||||||
if (!q || q.length < TRANS_MIN_LENGTH || q.length > TRANS_MAX_LENGTH) {
|
if (!q || q.length < TRANS_MIN_LENGTH || q.length > TRANS_MAX_LENGTH) {
|
||||||
// 太长或太短不翻译
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +136,7 @@ export class Translator {
|
|||||||
const root = createRoot(span);
|
const root = createRoot(span);
|
||||||
root.render(
|
root.render(
|
||||||
<StoragesProvider>
|
<StoragesProvider>
|
||||||
<Content q={q} rule={this._rule} />
|
<Content q={q} translator={this} />
|
||||||
</StoragesProvider>
|
</StoragesProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useMemo, useState } from "react";
|
import { useMemo, useState, useEffect } from "react";
|
||||||
import LoadingIcon from "./LoadingIcon";
|
import LoadingIcon from "./LoadingIcon";
|
||||||
import {
|
import {
|
||||||
OPT_STYLE_LINE,
|
OPT_STYLE_LINE,
|
||||||
@@ -8,12 +8,16 @@ import {
|
|||||||
OPT_STYLE_FUZZY,
|
OPT_STYLE_FUZZY,
|
||||||
OPT_STYLE_HIGHTLIGHT,
|
OPT_STYLE_HIGHTLIGHT,
|
||||||
DEFAULT_COLOR,
|
DEFAULT_COLOR,
|
||||||
|
EVENT_KISS,
|
||||||
|
MSG_TRANS_CURRULE,
|
||||||
} from "../../config";
|
} from "../../config";
|
||||||
import { useTranslate } from "../../hooks/Translate";
|
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 [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 = () => {
|
const handleMouseEnter = () => {
|
||||||
setHover(true);
|
setHover(true);
|
||||||
@@ -23,6 +27,24 @@ export default function Content({ q, rule }) {
|
|||||||
setHover(false);
|
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 style = useMemo(() => {
|
||||||
const lineColor = bgColor || "";
|
const lineColor = bgColor || "";
|
||||||
switch (textStyle) {
|
switch (textStyle) {
|
||||||
|
|||||||
Reference in New Issue
Block a user