Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13e7c1b754 | ||
|
|
d314d5515f | ||
|
|
09b19e3ca0 | ||
|
|
687bd11fd1 | ||
|
|
56cb1cd30d | ||
|
|
7a3df25521 | ||
|
|
ea8919ba07 | ||
|
|
3dece4fcdb | ||
|
|
df950a1bd2 | ||
|
|
74b9ee31fa | ||
|
|
64cd55fe58 | ||
|
|
e80ede14fb | ||
|
|
45ba9d3320 | ||
|
|
47c7048538 | ||
|
|
f9bfa8101f |
24
.env
24
.env
@@ -2,12 +2,22 @@ GENERATE_SOURCEMAP=false
|
|||||||
|
|
||||||
REACT_APP_NAME=KISS Translator
|
REACT_APP_NAME=KISS Translator
|
||||||
REACT_APP_NAME_CN=简约翻译
|
REACT_APP_NAME_CN=简约翻译
|
||||||
REACT_APP_VERSION=1.5.6
|
REACT_APP_VERSION=1.5.8
|
||||||
|
|
||||||
REACT_APP_HOMEPAGE=https://github.com/fishjar/kiss-translator
|
REACT_APP_HOMEPAGE=https://github.com/fishjar/kiss-translator
|
||||||
REACT_APP_OPTIONSPAGE=https://kiss-translator.rayjar.com/options
|
|
||||||
REACT_APP_OPTIONSPAGE2=https://fishjar.github.io/kiss-translator/options.html
|
REACT_APP_OPTIONSPAGE=https://fishjar.github.io/kiss-translator/options.html
|
||||||
|
REACT_APP_OPTIONSPAGE2=https://kiss-translator.rayjar.com/options
|
||||||
REACT_APP_OPTIONSPAGE_DEV=http://localhost:3000/options.html
|
REACT_APP_OPTIONSPAGE_DEV=http://localhost:3000/options.html
|
||||||
REACT_APP_LOGOURL=https://kiss-translator.rayjar.com/images/logo192.png
|
|
||||||
REACT_APP_RULESURL=https://kiss-translator.rayjar.com/kiss-translator-rules.json
|
REACT_APP_LOGOURL=https://fishjar.github.io/kiss-translator/images/logo192.png
|
||||||
REACT_APP_USERSCRIPT_DOWNLOADURL=https://kiss-translator.rayjar.com/kiss-translator.user.js
|
REACT_APP_LOGOURL2=https://kiss-translator.rayjar.com/images/logo192.png
|
||||||
REACT_APP_USERSCRIPT_DOWNLOADURL2=https://fishjar.github.io/kiss-translator/kiss-translator.user.js
|
|
||||||
|
REACT_APP_RULESURL=https://fishjar.github.io/kiss-translator/kiss-translator-rules.json
|
||||||
|
REACT_APP_RULESURL2=https://kiss-translator.rayjar.com/kiss-translator-rules.json
|
||||||
|
|
||||||
|
REACT_APP_VERSIONFILE=https://fishjar.github.io/kiss-translator/version.txt
|
||||||
|
REACT_APP_VERSIONFILE2=https://kiss-translator.rayjar.com/version.txt
|
||||||
|
|
||||||
|
REACT_APP_USERSCRIPT_DOWNLOADURL=https://fishjar.github.io/kiss-translator/kiss-translator.user.js
|
||||||
|
REACT_APP_USERSCRIPT_DOWNLOADURL2=https://kiss-translator.rayjar.com/kiss-translator.user.js
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ If you also like a little more simplicity, welcome to pick it up.
|
|||||||
- [x] Data Synchronization Function
|
- [x] Data Synchronization Function
|
||||||
- [x] Greasemonkey Script ([link 1](https://fishjar.github.io/kiss-translator/kiss-translator.user.js)、[link 2](https://kiss-translator.rayjar.com/kiss-translator.user.js))
|
- [x] Greasemonkey Script ([link 1](https://fishjar.github.io/kiss-translator/kiss-translator.user.js)、[link 2](https://kiss-translator.rayjar.com/kiss-translator.user.js))
|
||||||
- [x] [Tampermonkey](https://www.tampermonkey.net/) (Chrome/Edge/Firefox)
|
- [x] [Tampermonkey](https://www.tampermonkey.net/) (Chrome/Edge/Firefox)
|
||||||
- [ ] [Userscripts Safari](https://github.com/quoid/userscripts) (need test)
|
- [x] [Userscripts Safari](https://github.com/quoid/userscripts) (iOS Safari)
|
||||||
|
|
||||||
### Guide
|
### Guide
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
- [x] 数据同步功能
|
- [x] 数据同步功能
|
||||||
- [x] 油猴脚本([链接 1](https://fishjar.github.io/kiss-translator/kiss-translator.user.js)、[链接 2](https://kiss-translator.rayjar.com/kiss-translator.user.js))
|
- [x] 油猴脚本([链接 1](https://fishjar.github.io/kiss-translator/kiss-translator.user.js)、[链接 2](https://kiss-translator.rayjar.com/kiss-translator.user.js))
|
||||||
- [x] [Tampermonkey](https://www.tampermonkey.net/) (Chrome/Edge/Firefox)
|
- [x] [Tampermonkey](https://www.tampermonkey.net/) (Chrome/Edge/Firefox)
|
||||||
- [ ] [Userscripts Safari](https://github.com/quoid/userscripts) (待测)
|
- [x] [Userscripts Safari](https://github.com/quoid/userscripts) (iOS Safari)
|
||||||
|
|
||||||
### 指引
|
### 指引
|
||||||
|
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ const userscriptWebpack = (config, env) => {
|
|||||||
// @grant GM.getValue
|
// @grant GM.getValue
|
||||||
// @grant GM.deleteValue
|
// @grant GM.deleteValue
|
||||||
// @grant GM.info
|
// @grant GM.info
|
||||||
// @grant unsafeWindow
|
// @inject-into content
|
||||||
// @connect translate.googleapis.com
|
// @connect translate.googleapis.com
|
||||||
// @connect api-edge.cognitive.microsofttranslator.com
|
// @connect api-edge.cognitive.microsofttranslator.com
|
||||||
// @connect edge.microsoft.com
|
// @connect edge.microsoft.com
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "kiss-translator",
|
"name": "kiss-translator",
|
||||||
"description": "A minimalist bilingual translation Extension & Greasemonkey Script",
|
"description": "A minimalist bilingual translation Extension & Greasemonkey Script",
|
||||||
"version": "1.5.6",
|
"version": "1.5.8",
|
||||||
"author": "Gabe<yugang2002@gmail.com>",
|
"author": "Gabe<yugang2002@gmail.com>",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -37,8 +37,7 @@
|
|||||||
"react-app/jest"
|
"react-app/jest"
|
||||||
],
|
],
|
||||||
"globals": {
|
"globals": {
|
||||||
"GM": true,
|
"GM": true
|
||||||
"unsafeWindow": true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"name": "__MSG_app_name__",
|
"name": "__MSG_app_name__",
|
||||||
"description": "__MSG_app_description__",
|
"description": "__MSG_app_description__",
|
||||||
"version": "1.5.6",
|
"version": "1.5.8",
|
||||||
"default_locale": "en",
|
"default_locale": "en",
|
||||||
"author": "Gabe<yugang2002@gmail.com>",
|
"author": "Gabe<yugang2002@gmail.com>",
|
||||||
"homepage_url": "https://github.com/fishjar/kiss-translator",
|
"homepage_url": "https://github.com/fishjar/kiss-translator",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "__MSG_app_name__",
|
"name": "__MSG_app_name__",
|
||||||
"description": "__MSG_app_description__",
|
"description": "__MSG_app_description__",
|
||||||
"version": "1.5.6",
|
"version": "1.5.8",
|
||||||
"default_locale": "en",
|
"default_locale": "en",
|
||||||
"author": "Gabe<yugang2002@gmail.com>",
|
"author": "Gabe<yugang2002@gmail.com>",
|
||||||
"homepage_url": "https://github.com/fishjar/kiss-translator",
|
"homepage_url": "https://github.com/fishjar/kiss-translator",
|
||||||
|
|||||||
@@ -285,11 +285,11 @@ export const I18N = {
|
|||||||
en: `Data Sync Error`,
|
en: `Data Sync Error`,
|
||||||
},
|
},
|
||||||
error_got_some_wrong: {
|
error_got_some_wrong: {
|
||||||
zh: "抱歉,出错了!",
|
zh: `抱歉,出错了!`,
|
||||||
en: "Sorry, something went wrong!",
|
en: `Sorry, something went wrong!`,
|
||||||
},
|
},
|
||||||
error_sync_setting: {
|
error_sync_setting: {
|
||||||
zh: "您的同步设置未填写,无法在线分享。",
|
zh: `您的同步设置未填写,无法在线分享。`,
|
||||||
en: "Your sync settings are missing and cannot be shared online.",
|
en: `Your sync settings are missing and cannot be shared online.`,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
22
src/index.js
22
src/index.js
@@ -6,6 +6,7 @@ import ReactMarkdown from "react-markdown";
|
|||||||
import Paper from "@mui/material/Paper";
|
import Paper from "@mui/material/Paper";
|
||||||
import Stack from "@mui/material/Stack";
|
import Stack from "@mui/material/Stack";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
|
import Link from "@mui/material/Link";
|
||||||
import { useFetch } from "./hooks/Fetch";
|
import { useFetch } from "./hooks/Fetch";
|
||||||
import { I18N, URL_RAW_PREFIX } from "./config";
|
import { I18N, URL_RAW_PREFIX } from "./config";
|
||||||
|
|
||||||
@@ -26,7 +27,26 @@ function App() {
|
|||||||
{lang === "zh" ? "ENGLISH" : "中文"}
|
{lang === "zh" ? "ENGLISH" : "中文"}
|
||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Divider>{`KISS Translator v${process.env.REACT_APP_VERSION}`}</Divider>
|
<Divider>
|
||||||
|
<Link
|
||||||
|
href={process.env.REACT_APP_HOMEPAGE}
|
||||||
|
>{`KISS Translator v${process.env.REACT_APP_VERSION}`}</Link>
|
||||||
|
</Divider>
|
||||||
|
<Stack spacing={2} direction="row" useFlexGap flexWrap="wrap">
|
||||||
|
<Link href={process.env.REACT_APP_USERSCRIPT_DOWNLOADURL}>
|
||||||
|
Install Userscript 1
|
||||||
|
</Link>
|
||||||
|
<Link href={process.env.REACT_APP_USERSCRIPT_DOWNLOADURL2}>
|
||||||
|
Install Userscript 2
|
||||||
|
</Link>
|
||||||
|
<Link href={process.env.REACT_APP_OPTIONSPAGE}>
|
||||||
|
Open Options Page 1
|
||||||
|
</Link>
|
||||||
|
<Link href={process.env.REACT_APP_OPTIONSPAGE2}>
|
||||||
|
Open Options Page 2
|
||||||
|
</Link>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<center>
|
<center>
|
||||||
<CircularProgress />
|
<CircularProgress />
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { msAuth } from "./auth";
|
|||||||
* @param {*} init
|
* @param {*} init
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const fetchGM = async (input, { method = "GET", headers, body } = {}) =>
|
export const fetchGM = async (input, { method = "GET", headers, body } = {}) =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
GM.xmlHttpRequest({
|
GM.xmlHttpRequest({
|
||||||
method,
|
method,
|
||||||
@@ -74,13 +74,23 @@ const fetchApi = async ({ input, init = {}, translator, token }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isGm) {
|
if (isGm) {
|
||||||
const connects = GM?.info?.script?.connects || [];
|
let info;
|
||||||
|
if (window.KISS_GM) {
|
||||||
|
info = await window.KISS_GM.getInfo();
|
||||||
|
} else {
|
||||||
|
info = GM.info;
|
||||||
|
}
|
||||||
|
const connects = info?.script?.connects || [];
|
||||||
const url = new URL(input);
|
const url = new URL(input);
|
||||||
const isSafe = connects.find((item) => url.hostname.endsWith(item));
|
const isSafe = connects.find((item) => url.hostname.endsWith(item));
|
||||||
if (isSafe) {
|
if (isSafe) {
|
||||||
|
if (window.KISS_GM) {
|
||||||
|
return window.KISS_GM.fetch(input, init);
|
||||||
|
} else {
|
||||||
return fetchGM(input, init);
|
return fetchGM(input, init);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return fetch(input, init);
|
return fetch(input, init);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
97
src/libs/gm.js
Normal file
97
src/libs/gm.js
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
import { fetchGM } from "./fetch";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注入页面的脚本,请求并接受GM接口信息
|
||||||
|
* @param {*} param0
|
||||||
|
*/
|
||||||
|
export const injectScript = (ping) => {
|
||||||
|
const MSG_GM_xmlHttpRequest = "xmlHttpRequest";
|
||||||
|
const MSG_GM_setValue = "setValue";
|
||||||
|
const MSG_GM_getValue = "getValue";
|
||||||
|
const MSG_GM_deleteValue = "deleteValue";
|
||||||
|
const MSG_GM_info = "info";
|
||||||
|
let GM_info;
|
||||||
|
|
||||||
|
const promiseGM = (action, args, timeout = 5000) =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
const pong = btoa(Math.random()).slice(3, 11);
|
||||||
|
const handleEvent = (e) => {
|
||||||
|
window.removeEventListener(pong, handleEvent);
|
||||||
|
const { data, error } = e.detail;
|
||||||
|
if (error) {
|
||||||
|
reject(new Error(error));
|
||||||
|
} else {
|
||||||
|
resolve(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener(pong, handleEvent);
|
||||||
|
window.dispatchEvent(
|
||||||
|
new CustomEvent(ping, { detail: { action, args, pong } })
|
||||||
|
);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
window.removeEventListener(pong, handleEvent);
|
||||||
|
reject(new Error("timeout"));
|
||||||
|
}, timeout);
|
||||||
|
});
|
||||||
|
|
||||||
|
window.KISS_GM = {
|
||||||
|
fetch: (input, init) => promiseGM(MSG_GM_xmlHttpRequest, { input, init }),
|
||||||
|
setValue: (key, val) => promiseGM(MSG_GM_setValue, { key, val }),
|
||||||
|
getValue: (key) => promiseGM(MSG_GM_getValue, { key }),
|
||||||
|
deleteValue: (key) => promiseGM(MSG_GM_deleteValue, { key }),
|
||||||
|
getInfo: () => {
|
||||||
|
if (GM_info) {
|
||||||
|
return GM_info;
|
||||||
|
}
|
||||||
|
return promiseGM(MSG_GM_info);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
window.APP_NAME = process.env.REACT_APP_NAME;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 监听并回应页面对GM接口的请求
|
||||||
|
* @param {*} param0
|
||||||
|
*/
|
||||||
|
export const handlePing = async (e) => {
|
||||||
|
const MSG_GM_xmlHttpRequest = "xmlHttpRequest";
|
||||||
|
const MSG_GM_setValue = "setValue";
|
||||||
|
const MSG_GM_getValue = "getValue";
|
||||||
|
const MSG_GM_deleteValue = "deleteValue";
|
||||||
|
const MSG_GM_info = "info";
|
||||||
|
const { action, args, pong } = e.detail;
|
||||||
|
let res;
|
||||||
|
try {
|
||||||
|
switch (action) {
|
||||||
|
case MSG_GM_xmlHttpRequest:
|
||||||
|
const { input, init } = args;
|
||||||
|
res = await fetchGM(input, init);
|
||||||
|
break;
|
||||||
|
case MSG_GM_setValue:
|
||||||
|
const { key, val } = args;
|
||||||
|
await GM.setValue(key, val);
|
||||||
|
res = val;
|
||||||
|
break;
|
||||||
|
case MSG_GM_getValue:
|
||||||
|
res = await GM.getValue(args.key);
|
||||||
|
break;
|
||||||
|
case MSG_GM_deleteValue:
|
||||||
|
await GM.deleteValue(args.key);
|
||||||
|
res = "ok";
|
||||||
|
break;
|
||||||
|
case MSG_GM_info:
|
||||||
|
res = GM.info;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`message action is unavailable: ${action}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.dispatchEvent(new CustomEvent(pong, { detail: { data: res } }));
|
||||||
|
} catch (err) {
|
||||||
|
window.dispatchEvent(
|
||||||
|
new CustomEvent(pong, { detail: { error: err.message } })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -100,7 +100,7 @@ export const matchRule = async (
|
|||||||
*/
|
*/
|
||||||
export const detectLang = async (q) => {
|
export const detectLang = async (q) => {
|
||||||
try {
|
try {
|
||||||
const res = await browser?.i18n.detectLanguage(q);
|
const res = await browser?.i18n?.detectLanguage(q);
|
||||||
return res?.languages?.[0]?.language;
|
return res?.languages?.[0]?.language;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("[detect lang]", err);
|
console.log("[detect lang]", err);
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ async function set(key, val) {
|
|||||||
if (isExt) {
|
if (isExt) {
|
||||||
await browser.storage.local.set({ [key]: val });
|
await browser.storage.local.set({ [key]: val });
|
||||||
} else if (isGm) {
|
} else if (isGm) {
|
||||||
const oldValue = await GM.getValue(key);
|
const oldValue = await (window.KISS_GM || GM).getValue(key);
|
||||||
await GM.setValue(key, val);
|
await (window.KISS_GM || GM).setValue(key, val);
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new StorageEvent("storage", {
|
new StorageEvent("storage", {
|
||||||
key,
|
key,
|
||||||
@@ -31,7 +31,7 @@ async function get(key) {
|
|||||||
const val = await browser.storage.local.get([key]);
|
const val = await browser.storage.local.get([key]);
|
||||||
return val[key];
|
return val[key];
|
||||||
} else if (isGm) {
|
} else if (isGm) {
|
||||||
const val = await GM.getValue(key);
|
const val = await (window.KISS_GM || GM).getValue(key);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
return window.localStorage.getItem(key);
|
return window.localStorage.getItem(key);
|
||||||
@@ -41,8 +41,8 @@ async function del(key) {
|
|||||||
if (isExt) {
|
if (isExt) {
|
||||||
await browser.storage.local.remove([key]);
|
await browser.storage.local.remove([key]);
|
||||||
} else if (isGm) {
|
} else if (isGm) {
|
||||||
const oldValue = await GM.getValue(key);
|
const oldValue = await (window.KISS_GM || GM).getValue(key);
|
||||||
await GM.deleteValue(key);
|
await (window.KISS_GM || GM).deleteValue(key);
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new StorageEvent("storage", {
|
new StorageEvent("storage", {
|
||||||
key,
|
key,
|
||||||
|
|||||||
11
src/rules.js
11
src/rules.js
@@ -3,6 +3,7 @@ import path from "path";
|
|||||||
import { BUILTIN_RULES } from "./config/rules";
|
import { BUILTIN_RULES } from "./config/rules";
|
||||||
|
|
||||||
(() => {
|
(() => {
|
||||||
|
// rules
|
||||||
try {
|
try {
|
||||||
const data = JSON.stringify(BUILTIN_RULES, null, " ");
|
const data = JSON.stringify(BUILTIN_RULES, null, " ");
|
||||||
const file = path.resolve(
|
const file = path.resolve(
|
||||||
@@ -14,4 +15,14 @@ import { BUILTIN_RULES } from "./config/rules";
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// version
|
||||||
|
try {
|
||||||
|
var pjson = require("../package.json");
|
||||||
|
const file = path.resolve(__dirname, "../build/web/version.txt");
|
||||||
|
fs.writeFileSync(file, pjson.version);
|
||||||
|
console.info(`Version file generated: ${file}`);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { trySyncAllSubRules } from "./libs/rules";
|
|||||||
import { isGm } from "./libs/browser";
|
import { isGm } from "./libs/browser";
|
||||||
import { MSG_TRANS_TOGGLE, MSG_TRANS_PUTRULE } from "./config";
|
import { MSG_TRANS_TOGGLE, MSG_TRANS_PUTRULE } from "./config";
|
||||||
import { isIframe } from "./libs/iframe";
|
import { isIframe } from "./libs/iframe";
|
||||||
|
import { handlePing, injectScript } from "./libs/gm";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 入口函数
|
* 入口函数
|
||||||
@@ -20,8 +21,16 @@ const init = async () => {
|
|||||||
document.location.href.includes(process.env.REACT_APP_OPTIONSPAGE) ||
|
document.location.href.includes(process.env.REACT_APP_OPTIONSPAGE) ||
|
||||||
document.location.href.includes(process.env.REACT_APP_OPTIONSPAGE2)
|
document.location.href.includes(process.env.REACT_APP_OPTIONSPAGE2)
|
||||||
) {
|
) {
|
||||||
unsafeWindow.GM = GM;
|
// unsafeWindow.GM = GM;
|
||||||
unsafeWindow.APP_NAME = process.env.REACT_APP_NAME;
|
// unsafeWindow.APP_NAME = process.env.REACT_APP_NAME;
|
||||||
|
const ping = btoa(Math.random()).slice(3, 11);
|
||||||
|
window.addEventListener(ping, handlePing);
|
||||||
|
// window.eval(`(${injectScript})("${ping}")`); // eslint-disable-line
|
||||||
|
const script = document.createElement("script");
|
||||||
|
script.textContent = `(${injectScript})("${ping}")`;
|
||||||
|
if (document.head) {
|
||||||
|
document.head.append(script);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,31 +47,28 @@ export default function Content({ q, translator }) {
|
|||||||
|
|
||||||
const style = useMemo(() => {
|
const style = useMemo(() => {
|
||||||
const lineColor = bgColor || "";
|
const lineColor = bgColor || "";
|
||||||
|
const underlineStyle = (st) => ({
|
||||||
|
opacity: hover ? 1 : 0.6,
|
||||||
|
textDecorationLine: "underline",
|
||||||
|
textDecorationColor: lineColor,
|
||||||
|
textDecorationStyle: st,
|
||||||
|
textDecorationThickness: "2px",
|
||||||
|
textUnderlineOffset: "0.3em",
|
||||||
|
WebkittextDecorationLine: "underline",
|
||||||
|
WebkittextDecorationColor: lineColor,
|
||||||
|
WebkittextDecorationStyle: st,
|
||||||
|
WebkittextDecorationThickness: "2px",
|
||||||
|
WebkittextTextUnderlineOffset: "0.3em",
|
||||||
|
});
|
||||||
switch (textStyle) {
|
switch (textStyle) {
|
||||||
case OPT_STYLE_LINE: // 下划线
|
case OPT_STYLE_LINE: // 下划线
|
||||||
return {
|
return underlineStyle("solid");
|
||||||
opacity: hover ? 1 : 0.6,
|
|
||||||
textDecoration: `underline 2px ${lineColor}`,
|
|
||||||
textUnderlineOffset: "0.3em",
|
|
||||||
};
|
|
||||||
case OPT_STYLE_DOTLINE: // 点状线
|
case OPT_STYLE_DOTLINE: // 点状线
|
||||||
return {
|
return underlineStyle("dotted");
|
||||||
opacity: hover ? 1 : 0.6,
|
|
||||||
textDecoration: `dotted underline 2px ${lineColor}`,
|
|
||||||
textUnderlineOffset: "0.3em",
|
|
||||||
};
|
|
||||||
case OPT_STYLE_DASHLINE: // 虚线
|
case OPT_STYLE_DASHLINE: // 虚线
|
||||||
return {
|
return underlineStyle("dashed");
|
||||||
opacity: hover ? 1 : 0.6,
|
|
||||||
textDecoration: `dashed underline 2px ${lineColor}`,
|
|
||||||
textUnderlineOffset: "0.3em",
|
|
||||||
};
|
|
||||||
case OPT_STYLE_WAVYLINE: // 波浪线
|
case OPT_STYLE_WAVYLINE: // 波浪线
|
||||||
return {
|
return underlineStyle("wavy");
|
||||||
opacity: hover ? 1 : 0.6,
|
|
||||||
textDecoration: `wavy underline 2px ${lineColor}`,
|
|
||||||
textUnderlineOffset: "0.3em",
|
|
||||||
};
|
|
||||||
case OPT_STYLE_FUZZY: // 模糊
|
case OPT_STYLE_FUZZY: // 模糊
|
||||||
return {
|
return {
|
||||||
filter: hover ? "none" : "blur(5px)",
|
filter: hover ? "none" : "blur(5px)",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { useDarkModeSwitch } from "../../hooks/ColorMode";
|
|||||||
import { useDarkMode } from "../../hooks/ColorMode";
|
import { useDarkMode } from "../../hooks/ColorMode";
|
||||||
import LightModeIcon from "@mui/icons-material/LightMode";
|
import LightModeIcon from "@mui/icons-material/LightMode";
|
||||||
import DarkModeIcon from "@mui/icons-material/DarkMode";
|
import DarkModeIcon from "@mui/icons-material/DarkMode";
|
||||||
|
import Link from "@mui/material/Link";
|
||||||
import { useI18n } from "../../hooks/I18n";
|
import { useI18n } from "../../hooks/I18n";
|
||||||
|
|
||||||
function Header(props) {
|
function Header(props) {
|
||||||
@@ -35,9 +36,13 @@ function Header(props) {
|
|||||||
<MenuIcon />
|
<MenuIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ flexGrow: 1 }}>{`${i18n("app_name")} v${
|
<Box sx={{ flexGrow: 1 }}>
|
||||||
process.env.REACT_APP_VERSION
|
<Link
|
||||||
}`}</Box>
|
underline="none"
|
||||||
|
color="inherit"
|
||||||
|
href={process.env.REACT_APP_HOMEPAGE}
|
||||||
|
>{`${i18n("app_name")} v${process.env.REACT_APP_VERSION}`}</Link>
|
||||||
|
</Box>
|
||||||
<IconButton onClick={switchColorMode} color="inherit">
|
<IconButton onClick={switchColorMode} color="inherit">
|
||||||
{darkMode ? <LightModeIcon /> : <DarkModeIcon />}
|
{darkMode ? <LightModeIcon /> : <DarkModeIcon />}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ import { sleep } from "../../libs/utils";
|
|||||||
import CircularProgress from "@mui/material/CircularProgress";
|
import CircularProgress from "@mui/material/CircularProgress";
|
||||||
import { trySyncAll } from "../../libs/sync";
|
import { trySyncAll } from "../../libs/sync";
|
||||||
import { AlertProvider } from "../../hooks/Alert";
|
import { AlertProvider } from "../../hooks/Alert";
|
||||||
|
import Link from "@mui/material/Link";
|
||||||
|
import Divider from "@mui/material/Divider";
|
||||||
|
import Stack from "@mui/material/Stack";
|
||||||
|
|
||||||
export default function Options() {
|
export default function Options() {
|
||||||
const [error, setError] = useState(false);
|
const [error, setError] = useState(false);
|
||||||
@@ -45,16 +48,29 @@ export default function Options() {
|
|||||||
if (error) {
|
if (error) {
|
||||||
return (
|
return (
|
||||||
<center>
|
<center>
|
||||||
|
<Divider>
|
||||||
|
<Link
|
||||||
|
href={process.env.REACT_APP_HOMEPAGE}
|
||||||
|
>{`KISS Translator v${process.env.REACT_APP_VERSION}`}</Link>
|
||||||
|
</Divider>
|
||||||
<h2>
|
<h2>
|
||||||
Please confirm whether to install or enable{" "}
|
Please confirm whether to install or enable KISS Translator
|
||||||
<a href={process.env.REACT_APP_HOMEPAGE}>KISS Translator</a>{" "}
|
|
||||||
GreaseMonkey script?
|
GreaseMonkey script?
|
||||||
</h2>
|
</h2>
|
||||||
<h2>
|
<Stack spacing={2}>
|
||||||
<a href={process.env.REACT_APP_USERSCRIPT_DOWNLOADURL}>Click here</a>{" "}
|
<Link href={process.env.REACT_APP_USERSCRIPT_DOWNLOADURL}>
|
||||||
to install, or <a href={process.env.REACT_APP_HOMEPAGE}>click here</a>{" "}
|
Install Userscript 1
|
||||||
for help.
|
</Link>
|
||||||
</h2>
|
<Link href={process.env.REACT_APP_USERSCRIPT_DOWNLOADURL2}>
|
||||||
|
Install Userscript 2
|
||||||
|
</Link>
|
||||||
|
<Link href={process.env.REACT_APP_OPTIONSPAGE}>
|
||||||
|
Open Options Page 1
|
||||||
|
</Link>
|
||||||
|
<Link href={process.env.REACT_APP_OPTIONSPAGE2}>
|
||||||
|
Open Options Page 2
|
||||||
|
</Link>
|
||||||
|
</Stack>
|
||||||
</center>
|
</center>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -62,6 +78,11 @@ export default function Options() {
|
|||||||
if (isGm && !ready) {
|
if (isGm && !ready) {
|
||||||
return (
|
return (
|
||||||
<center>
|
<center>
|
||||||
|
<Divider>
|
||||||
|
<Link
|
||||||
|
href={process.env.REACT_APP_HOMEPAGE}
|
||||||
|
>{`KISS Translator v${process.env.REACT_APP_VERSION}`}</Link>
|
||||||
|
</Divider>
|
||||||
<CircularProgress />
|
<CircularProgress />
|
||||||
</center>
|
</center>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user