From bec207a09ff21a5061c7889fa7bde85cce4d4ad4 Mon Sep 17 00:00:00 2001 From: Gabe Yuan Date: Sat, 5 Aug 2023 18:15:01 +0800 Subject: [PATCH] polyfill codes --- src/apis/index.js | 10 +++--- src/background.js | 8 ++--- src/config/index.js | 1 + src/hooks/Storage.js | 8 +++-- src/libs/auth.js | 4 +-- src/libs/browser.js | 5 +++ src/libs/fetch.js | 78 ++++++++++++++++++++++++++++++-------------- src/libs/storage.js | 19 ++++++++--- 8 files changed, 89 insertions(+), 44 deletions(-) diff --git a/src/apis/index.js b/src/apis/index.js index f31eceb..7207b26 100644 --- a/src/apis/index.js +++ b/src/apis/index.js @@ -1,5 +1,5 @@ import queryString from "query-string"; -import { fetchData } from "../libs/fetch"; +import { fetchPolyfill } from "../libs/fetch"; import { OPT_TRANS_GOOGLE, OPT_TRANS_MICROSOFT, @@ -20,7 +20,7 @@ import { getSetting, detectLang } from "../libs"; * @returns */ export const apiSyncData = async (url, key, data) => - fetchData(url, { + fetchPolyfill(url, { headers: { "Content-type": "application/json", [KV_HEADER_KEY]: key, @@ -48,7 +48,7 @@ const apiGoogleTranslate = async (translator, text, to, from) => { }; const { googleUrl } = await getSetting(); const input = `${googleUrl}?${queryString.stringify(params)}`; - return fetchData( + return fetchPolyfill( input, { headers: { @@ -73,7 +73,7 @@ const apiMicrosoftTranslate = (translator, text, to, from, token) => { "api-version": "3.0", }; const input = `${URL_MICROSOFT_TRANS}?${queryString.stringify(params)}`; - return fetchData( + return fetchPolyfill( input, { headers: { @@ -100,7 +100,7 @@ const apiOpenaiTranslate = async (translator, text, to, from) => { let prompt = openaiPrompt .replaceAll(PROMPT_PLACE_FROM, from) .replaceAll(PROMPT_PLACE_TO, to); - return fetchData( + return fetchPolyfill( openaiUrl, { headers: { diff --git a/src/background.js b/src/background.js index cd51699..f0e5912 100644 --- a/src/background.js +++ b/src/background.js @@ -1,4 +1,4 @@ -import { browser } from "webextension-polyfill"; +import browser from "webextension-polyfill"; import { MSG_FETCH, DEFAULT_SETTING, @@ -12,6 +12,7 @@ import { import storage from "./libs/storage"; import { getSetting } from "./libs"; import { syncAll } from "./libs/sync"; +import { fetchData } from "./libs/fetch"; /** * 插件安装 @@ -46,10 +47,7 @@ browser.runtime.onMessage.addListener( ({ action, args }, sender, sendResponse) => { switch (action) { case MSG_FETCH: - fetch(args.input, args.init) - .then((res) => { - return res.json(); - }) + fetchData(args.input, args.init, args.opts) .then((data) => { sendResponse({ data }); }) diff --git a/src/config/index.js b/src/config/index.js index 4b2952b..d15bb3a 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -15,6 +15,7 @@ export const CLIENT_CHROME = "chrome"; export const CLIENT_EDGE = "edge"; export const CLIENT_FIREFOX = "firefox"; export const CLIENT_USERSCRIPT = "userscript"; +export const CLIENT_EXTS = [CLIENT_CHROME, CLIENT_EDGE, CLIENT_FIREFOX]; export const KV_HEADER_KEY = "X-KISS-PSK"; export const KV_RULES_KEY = "KT_RULES"; diff --git a/src/hooks/Storage.js b/src/hooks/Storage.js index 8fca3fa..4ff78ae 100644 --- a/src/hooks/Storage.js +++ b/src/hooks/Storage.js @@ -1,5 +1,5 @@ import { createContext, useContext, useEffect, useState } from "react"; -import { browser } from "../libs/browser"; +import { browser, isExt, isGm, isWeb } from "../libs/browser"; import { STOKEY_SETTING, STOKEY_RULES, @@ -27,7 +27,7 @@ export function StoragesProvider({ children }) { const [storages, setStorages] = useState(null); const handleChanged = (changes) => { - if (!browser) { + if (isWeb || isGm) { const { key, oldValue, newValue } = changes; changes = { [key]: { @@ -69,8 +69,10 @@ export function StoragesProvider({ children }) { // 解除监听 return () => { - if (browser?.storage) { + if (isExt) { browser.storage.onChanged.removeListener(handleChanged); + } else if (isGm) { + window.GM.removeValueChangeListener(handleChanged); } else { window.removeEventListener("storage", handleChanged); } diff --git a/src/libs/auth.js b/src/libs/auth.js index f44f182..bfc7725 100644 --- a/src/libs/auth.js +++ b/src/libs/auth.js @@ -1,6 +1,6 @@ import storage from "./storage"; import { STOKEY_MSAUTH, URL_MICROSOFT_AUTH } from "../config"; -import { fetchData } from "./fetch"; +import { fetchPolyfill } from "./fetch"; const parseMSToken = (token) => JSON.parse(atob(token.split(".")[1])).exp; @@ -27,7 +27,7 @@ const _msAuth = () => { } // 缓存没有或失效,查询接口 - token = await fetchData(URL_MICROSOFT_AUTH); + token = await fetchPolyfill(URL_MICROSOFT_AUTH); exp = parseMSToken(token); await storage.setObj(STOKEY_MSAUTH, { token, exp }); return [token, exp]; diff --git a/src/libs/browser.js b/src/libs/browser.js index 67fc24a..c8ea7a6 100644 --- a/src/libs/browser.js +++ b/src/libs/browser.js @@ -1,3 +1,5 @@ +import { CLIENT_EXTS, CLIENT_USERSCRIPT, CLIENT_WEB } from "../config"; + /** * 浏览器兼容插件,另可用于判断是插件模式还是网页模式,方便开发 * @returns @@ -12,3 +14,6 @@ function _browser() { export const browser = _browser(); export const client = process.env.REACT_APP_CLIENT; +export const isExt = CLIENT_EXTS.includes(client); +export const isGm = client === CLIENT_USERSCRIPT; +export const isWeb = client === CLIENT_WEB; diff --git a/src/libs/fetch.js b/src/libs/fetch.js index d721f8a..4d6129d 100644 --- a/src/libs/fetch.js +++ b/src/libs/fetch.js @@ -1,4 +1,4 @@ -import { browser } from "./browser"; +import { isExt, isGm } from "./browser"; import { sendMsg } from "./msg"; import { MSG_FETCH, @@ -8,7 +8,33 @@ import { } from "../config"; /** - * request 改造,因缓存必须是GET方法 + * 油猴脚本的请求封装 + * @param {*} input + * @param {*} init + * @returns + */ +const fetchGM = async (input, { method, headers, body }) => + new Promise((resolve, reject) => { + try { + window.GM.xmlhttpRequest({ + method, + url: input, + headers, + data: body, + onload: (response) => { + resolve(new Response(response.response)); + }, + onerror: (error) => { + reject(error); + }, + }); + } catch (error) { + reject(error); + } + }); + +/** + * 构造缓存 request * @param {*} request * @returns */ @@ -30,27 +56,6 @@ const newCacheReq = async (request, translator) => { return request; }; -/** - * 兼容性封装 - * @param {*} input - * @param {*} init - * @param {*} opts - * @returns - */ -export const fetchPolyfill = async (input, init) => { - if (browser?.runtime) { - // 插件调用 - const res = await sendMsg(MSG_FETCH, { input, init }); - if (res.error) { - throw new Error(res.error); - } - return res.data; - } - - // 网页直接调用 - return await fetch(input, init); -}; - /** * 请求数据 * @param {*} input @@ -74,7 +79,11 @@ export const fetchData = async (input, init, { useCache, translator } = {}) => { // 发送请求 if (!res) { - res = await fetchPolyfill(input, init); + if (isGm) { + res = await fetchGM(input, init); + } else { + res = await fetch(input, init); + } } if (!res?.ok) { @@ -96,3 +105,24 @@ export const fetchData = async (input, init, { useCache, translator } = {}) => { } return await res.text(); }; + +/** + * fetch 兼容性封装 + * @param {*} input + * @param {*} init + * @param {*} opts + * @returns + */ +export const fetchPolyfill = async (input, init, opts) => { + // 插件 + if (isExt) { + const res = await sendMsg(MSG_FETCH, { input, init, opts }); + if (res.error) { + throw new Error(res.error); + } + return res.data; + } + + // 油猴/网页 + return await fetchData(input, init, opts); +}; diff --git a/src/libs/storage.js b/src/libs/storage.js index 61563c7..0531bd8 100644 --- a/src/libs/storage.js +++ b/src/libs/storage.js @@ -1,8 +1,10 @@ -import { browser } from "./browser"; +import { browser, isExt, isGm } from "./browser"; async function set(key, val) { - if (browser?.storage) { + if (isExt) { await browser.storage.local.set({ [key]: val }); + } else if (isGm) { + await window.GM.setValue(key, val); } else { const oldValue = window.localStorage.getItem(key); window.localStorage.setItem(key, val); @@ -18,16 +20,21 @@ async function set(key, val) { } async function get(key) { - if (browser?.storage) { + if (isExt) { const res = await browser.storage.local.get([key]); return res[key]; + } else if (isGm) { + const res = await window.GM.getValue(key); + return res; } return window.localStorage.getItem(key); } async function del(key) { - if (browser?.storage) { + if (isExt) { await browser.storage.local.remove([key]); + } else if (isGm) { + await window.GM.deleteValue(key); } else { const oldValue = window.localStorage.getItem(key); window.localStorage.removeItem(key); @@ -67,8 +74,10 @@ async function putObj(key, obj) { * @param {*} handleChanged */ function onChanged(handleChanged) { - if (browser?.storage) { + if (isExt) { browser.storage.onChanged.addListener(handleChanged); + } else if (isGm) { + window.GM.addValueChangeListener("storage", handleChanged); } else { window.addEventListener("storage", handleChanged); }