userscript...

This commit is contained in:
Gabe Yuan
2023-08-05 20:11:02 +08:00
parent f5dd215ae7
commit b5f1da18a6
7 changed files with 96 additions and 37 deletions

View File

@@ -25,10 +25,6 @@ const banner = `// ==UserScript==
// @grant GM.getValue // @grant GM.getValue
// @grant GM_deleteValue // @grant GM_deleteValue
// @grant GM.deleteValue // @grant GM.deleteValue
// @grant GM_addValueChangeListener
// @grant GM.addValueChangeListener
// @grant GM_removeValueChangeListener
// @grant GM.removeValueChangeListener
// @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
@@ -117,10 +113,11 @@ const userscriptWebpack = (config, env) => {
]; ];
config.entry = { config.entry = {
userscript: paths.appSrc + "/userscript.js", index: paths.appSrc + "/userscriptOptions.js",
"kiss-translator.user": paths.appSrc + "/userscript.js",
}; };
config.output.filename = "kiss-translator.user.js"; config.output.filename = "[name].js";
config.optimization.splitChunks = { cacheGroups: { default: false } }; config.optimization.splitChunks = { cacheGroups: { default: false } };
config.optimization.runtimeChunk = false; config.optimization.runtimeChunk = false;
config.optimization.minimize = false; config.optimization.minimize = false;
@@ -130,10 +127,17 @@ const userscriptWebpack = (config, env) => {
); );
config.plugins.push( config.plugins.push(
new HtmlWebpackPlugin({
inject: true,
chunks: ["index"],
template: paths.appHtml,
filename: "index.html",
}),
new webpack.BannerPlugin({ new webpack.BannerPlugin({
banner, banner,
raw: true, raw: true,
entryOnly: true, entryOnly: true,
test: "kiss-translator.user.js",
}) })
); );

View File

@@ -71,11 +71,6 @@ export function StoragesProvider({ children }) {
return () => { return () => {
if (isExt) { if (isExt) {
browser.storage.onChanged.removeListener(handleChanged); browser.storage.onChanged.removeListener(handleChanged);
} else if (isGm) {
(
window.GM_removeValueChangeListener ||
window.GM.removeValueChangeListener
)(handleChanged);
} else { } else {
window.removeEventListener("storage", handleChanged); window.removeEventListener("storage", handleChanged);
} }

View File

@@ -4,11 +4,18 @@ 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 (window.GM_getValue || window.GM.getValue)(key);
await (window.GM_setValue || window.GM.setValue)(key, val); await (window.GM_setValue || window.GM.setValue)(key, val);
window.dispatchEvent(
new StorageEvent("storage", {
key,
oldValue,
newValue: val,
})
);
} else { } else {
const oldValue = window.localStorage.getItem(key); const oldValue = window.localStorage.getItem(key);
window.localStorage.setItem(key, val); window.localStorage.setItem(key, val);
// 手动唤起事件
window.dispatchEvent( window.dispatchEvent(
new StorageEvent("storage", { new StorageEvent("storage", {
key, key,
@@ -34,11 +41,18 @@ 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 (window.GM_getValue || window.GM.getValue)(key);
await (window.GM_deleteValue || window.GM.deleteValue)(key); await (window.GM_deleteValue || window.GM.deleteValue)(key);
window.dispatchEvent(
new StorageEvent("storage", {
key,
oldValue,
newValue: null,
})
);
} else { } else {
const oldValue = window.localStorage.getItem(key); const oldValue = window.localStorage.getItem(key);
window.localStorage.removeItem(key); window.localStorage.removeItem(key);
// 手动唤起事件
window.dispatchEvent( window.dispatchEvent(
new StorageEvent("storage", { new StorageEvent("storage", {
key, key,
@@ -76,11 +90,6 @@ async function putObj(key, obj) {
function onChanged(handleChanged) { function onChanged(handleChanged) {
if (isExt) { if (isExt) {
browser.storage.onChanged.addListener(handleChanged); browser.storage.onChanged.addListener(handleChanged);
} else if (isGm) {
(window.GM_addValueChangeListener || window.GM.addValueChangeListener)(
"storage",
handleChanged
);
} else { } else {
window.addEventListener("storage", handleChanged); window.addEventListener("storage", handleChanged);
} }

View File

@@ -1,19 +1,10 @@
import React from "react"; import React from "react";
import ReactDOM from "react-dom/client"; import ReactDOM from "react-dom/client";
import ThemeProvider from "./hooks/Theme";
import Options from "./views/Options"; import Options from "./views/Options";
import { HashRouter } from "react-router-dom";
import { StoragesProvider } from "./hooks/Storage";
const root = ReactDOM.createRoot(document.getElementById("root")); const root = ReactDOM.createRoot(document.getElementById("root"));
root.render( root.render(
<React.StrictMode> <React.StrictMode>
<StoragesProvider> <Options />
<ThemeProvider>
<HashRouter>
<Options />
</HashRouter>
</ThemeProvider>
</StoragesProvider>
</React.StrictMode> </React.StrictMode>
); );

View File

@@ -1,3 +1,7 @@
import React from "react";
import ReactDOM from "react-dom/client";
import Options from "./views/Options";
import { browser } from "./libs/browser"; import { browser } from "./libs/browser";
import { import {
MSG_TRANS_TOGGLE, MSG_TRANS_TOGGLE,
@@ -13,6 +17,17 @@ import { Translator } from "./libs/translator";
* 入口函数 * 入口函数
*/ */
(async () => { (async () => {
// 设置页面
if (document.location.href.includes("localhost:3000")) {
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<Options />
</React.StrictMode>
);
return;
}
const { fetchInterval, fetchLimit } = await getSetting(); const { fetchInterval, fetchLimit } = await getSetting();
transPool.update(fetchInterval, fetchLimit); transPool.update(fetchInterval, fetchLimit);

37
src/userscriptOptions.js Normal file
View File

@@ -0,0 +1,37 @@
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom/client";
const App = () => {
const [loading, setLoading] = useState(true);
useEffect(() => {
const timer = setTimeout(() => {
if (!document.querySelector("header")) {
setLoading(false);
}
}, 3000);
return () => {
clearTimeout(timer);
};
}, []);
if (loading) {
return <p style={{ textAlign: "center" }}>loading...</p>;
}
return (
<div style={{ textAlign: "center" }}>
<p>KISS Translator userscript is disabled at this browser!</p>
<p>
<a href={process.env.REACT_APP_HOMEPAGE}>Click here read more!</a>
</p>
</div>
);
};
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);

View File

@@ -1,19 +1,27 @@
import { Routes, Route } from "react-router-dom"; import { Routes, Route, HashRouter } from "react-router-dom";
import About from "./About"; import About from "./About";
import Rules from "./Rules"; import Rules from "./Rules";
import Setting from "./Setting"; import Setting from "./Setting";
import Layout from "./Layout"; import Layout from "./Layout";
import SyncSetting from "./SyncSetting"; import SyncSetting from "./SyncSetting";
import { StoragesProvider } from "../../hooks/Storage";
import ThemeProvider from "../../hooks/Theme";
export default function Options() { export default function Options() {
return ( return (
<Routes> <StoragesProvider>
<Route path="/" element={<Layout />}> <ThemeProvider>
<Route index element={<Setting />} /> <HashRouter>
<Route path="rules" element={<Rules />} /> <Routes>
<Route path="sync" element={<SyncSetting />} /> <Route path="/" element={<Layout />}>
<Route path="about" element={<About />} /> <Route index element={<Setting />} />
</Route> <Route path="rules" element={<Rules />} />
</Routes> <Route path="sync" element={<SyncSetting />} />
<Route path="about" element={<About />} />
</Route>
</Routes>
</HashRouter>
</ThemeProvider>
</StoragesProvider>
); );
} }