From b5f1da18a64a3ba72dbade347b331ecc4dcbc19a Mon Sep 17 00:00:00 2001 From: Gabe Yuan Date: Sat, 5 Aug 2023 20:11:02 +0800 Subject: [PATCH] userscript... --- config-overrides.js | 16 ++++++++++------ src/hooks/Storage.js | 5 ----- src/libs/storage.js | 23 ++++++++++++++++------- src/options.js | 11 +---------- src/userscript.js | 15 +++++++++++++++ src/userscriptOptions.js | 37 +++++++++++++++++++++++++++++++++++++ src/views/Options/index.js | 26 +++++++++++++++++--------- 7 files changed, 96 insertions(+), 37 deletions(-) create mode 100644 src/userscriptOptions.js diff --git a/config-overrides.js b/config-overrides.js index 44c6a2d..a1200e6 100644 --- a/config-overrides.js +++ b/config-overrides.js @@ -25,10 +25,6 @@ const banner = `// ==UserScript== // @grant GM.getValue // @grant GM_deleteValue // @grant GM.deleteValue -// @grant GM_addValueChangeListener -// @grant GM.addValueChangeListener -// @grant GM_removeValueChangeListener -// @grant GM.removeValueChangeListener // @connect translate.googleapis.com // @connect api-edge.cognitive.microsofttranslator.com // @connect edge.microsoft.com @@ -117,10 +113,11 @@ const userscriptWebpack = (config, env) => { ]; 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.runtimeChunk = false; config.optimization.minimize = false; @@ -130,10 +127,17 @@ const userscriptWebpack = (config, env) => { ); config.plugins.push( + new HtmlWebpackPlugin({ + inject: true, + chunks: ["index"], + template: paths.appHtml, + filename: "index.html", + }), new webpack.BannerPlugin({ banner, raw: true, entryOnly: true, + test: "kiss-translator.user.js", }) ); diff --git a/src/hooks/Storage.js b/src/hooks/Storage.js index 48146a3..3ae932f 100644 --- a/src/hooks/Storage.js +++ b/src/hooks/Storage.js @@ -71,11 +71,6 @@ export function StoragesProvider({ children }) { return () => { if (isExt) { browser.storage.onChanged.removeListener(handleChanged); - } else if (isGm) { - ( - window.GM_removeValueChangeListener || - window.GM.removeValueChangeListener - )(handleChanged); } else { window.removeEventListener("storage", handleChanged); } diff --git a/src/libs/storage.js b/src/libs/storage.js index 742b0ce..974eec6 100644 --- a/src/libs/storage.js +++ b/src/libs/storage.js @@ -4,11 +4,18 @@ async function set(key, val) { if (isExt) { await browser.storage.local.set({ [key]: val }); } else if (isGm) { + const oldValue = await (window.GM_getValue || window.GM.getValue)(key); await (window.GM_setValue || window.GM.setValue)(key, val); + window.dispatchEvent( + new StorageEvent("storage", { + key, + oldValue, + newValue: val, + }) + ); } else { const oldValue = window.localStorage.getItem(key); window.localStorage.setItem(key, val); - // 手动唤起事件 window.dispatchEvent( new StorageEvent("storage", { key, @@ -34,11 +41,18 @@ async function del(key) { if (isExt) { await browser.storage.local.remove([key]); } else if (isGm) { + const oldValue = await (window.GM_getValue || window.GM.getValue)(key); await (window.GM_deleteValue || window.GM.deleteValue)(key); + window.dispatchEvent( + new StorageEvent("storage", { + key, + oldValue, + newValue: null, + }) + ); } else { const oldValue = window.localStorage.getItem(key); window.localStorage.removeItem(key); - // 手动唤起事件 window.dispatchEvent( new StorageEvent("storage", { key, @@ -76,11 +90,6 @@ async function putObj(key, obj) { function onChanged(handleChanged) { if (isExt) { browser.storage.onChanged.addListener(handleChanged); - } else if (isGm) { - (window.GM_addValueChangeListener || window.GM.addValueChangeListener)( - "storage", - handleChanged - ); } else { window.addEventListener("storage", handleChanged); } diff --git a/src/options.js b/src/options.js index 1f06ca4..d1cf862 100644 --- a/src/options.js +++ b/src/options.js @@ -1,19 +1,10 @@ import React from "react"; import ReactDOM from "react-dom/client"; -import ThemeProvider from "./hooks/Theme"; import Options from "./views/Options"; -import { HashRouter } from "react-router-dom"; -import { StoragesProvider } from "./hooks/Storage"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( - - - - - - - + ); diff --git a/src/userscript.js b/src/userscript.js index 444b217..c2f4f73 100644 --- a/src/userscript.js +++ b/src/userscript.js @@ -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 { MSG_TRANS_TOGGLE, @@ -13,6 +17,17 @@ import { Translator } from "./libs/translator"; * 入口函数 */ (async () => { + // 设置页面 + if (document.location.href.includes("localhost:3000")) { + const root = ReactDOM.createRoot(document.getElementById("root")); + root.render( + + + + ); + return; + } + const { fetchInterval, fetchLimit } = await getSetting(); transPool.update(fetchInterval, fetchLimit); diff --git a/src/userscriptOptions.js b/src/userscriptOptions.js new file mode 100644 index 0000000..100811a --- /dev/null +++ b/src/userscriptOptions.js @@ -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

loading...

; + } + + return ( +
+

KISS Translator userscript is disabled at this browser!

+

+ Click here read more! +

+
+ ); +}; + +const root = ReactDOM.createRoot(document.getElementById("root")); +root.render( + + + +); diff --git a/src/views/Options/index.js b/src/views/Options/index.js index 2e55c18..2f43b5c 100644 --- a/src/views/Options/index.js +++ b/src/views/Options/index.js @@ -1,19 +1,27 @@ -import { Routes, Route } from "react-router-dom"; +import { Routes, Route, HashRouter } from "react-router-dom"; import About from "./About"; import Rules from "./Rules"; import Setting from "./Setting"; import Layout from "./Layout"; import SyncSetting from "./SyncSetting"; +import { StoragesProvider } from "../../hooks/Storage"; +import ThemeProvider from "../../hooks/Theme"; export default function Options() { return ( - - }> - } /> - } /> - } /> - } /> - - + + + + + }> + } /> + } /> + } /> + } /> + + + + + ); }