diff --git a/src/locales/ach-UG/translation.json b/src/locales/ach-UG/translation.json index cf254e349..7b984f867 100644 --- a/src/locales/ach-UG/translation.json +++ b/src/locales/ach-UG/translation.json @@ -325,8 +325,10 @@ "header_other_update": "crwdns12784:0crwdne12784:0" }, "downloading_status_text": "Downloading. Received {{bytes}}.", - "install_page_loading": "Installation page loading", - "invalid_page": "Invalid page", + "install_page_please_wait": "Please wait", + "install_page_loading": "Loading Installation Page", + "install_page_load_failed": "Failed to Load Installation Page", + "invalid_page": "Invalid Page", "background_script_tag": "crwdns8460:0crwdne8460:0", "scheduled_script_tag": "crwdns8462:0crwdne8462:0", "background_script": "crwdns8464:0crwdne8464:0", diff --git a/src/locales/de-DE/translation.json b/src/locales/de-DE/translation.json index 6ea643df8..dc389e7ea 100644 --- a/src/locales/de-DE/translation.json +++ b/src/locales/de-DE/translation.json @@ -334,7 +334,9 @@ "header_other_update": "Andere verfügbare Updates" }, "downloading_status_text": "Wird heruntergeladen. {{bytes}} empfangen.", + "install_page_please_wait": "Bitte warten Sie", "install_page_loading": "Installationsseite wird geladen", + "install_page_load_failed": "Installationsseite konnte nicht geladen werden", "invalid_page": "Ungültige Seite", "background_script_tag": "Dies ist ein Hintergrundskript", "scheduled_script_tag": "Dies ist ein geplantes Skript", diff --git a/src/locales/en-US/translation.json b/src/locales/en-US/translation.json index 1091314dd..006a3af2d 100644 --- a/src/locales/en-US/translation.json +++ b/src/locales/en-US/translation.json @@ -334,8 +334,10 @@ "header_other_update": "Other available updates" }, "downloading_status_text": "Downloading. Received {{bytes}}.", - "install_page_loading": "Installation page loading", - "invalid_page": "Invalid page", + "install_page_please_wait": "Please wait", + "install_page_loading": "Loading Installation Page", + "install_page_load_failed": "Failed to Load Installation Page", + "invalid_page": "Invalid Page", "background_script_tag": "This is a Background Script", "scheduled_script_tag": "This is a Scheduled Script", "background_script": "Background Script", diff --git a/src/locales/ja-JP/translation.json b/src/locales/ja-JP/translation.json index 346ac1524..68a3db516 100644 --- a/src/locales/ja-JP/translation.json +++ b/src/locales/ja-JP/translation.json @@ -334,7 +334,9 @@ "header_other_update": "その他の利用可能な更新" }, "downloading_status_text": "ダウンロード中。{{bytes}} を受信しました。", + "install_page_please_wait": "しばらくお待ちください", "install_page_loading": "インストールページを読み込み中", + "install_page_load_failed": "インストールページの読み込みに失敗しました", "invalid_page": "無効なページ", "background_script_tag": "これはバックグラウンドスクリプトです", "scheduled_script_tag": "これはスケジュールスクリプトです", diff --git a/src/locales/ru-RU/translation.json b/src/locales/ru-RU/translation.json index cc80fe49e..f3da00dc2 100644 --- a/src/locales/ru-RU/translation.json +++ b/src/locales/ru-RU/translation.json @@ -334,7 +334,9 @@ "header_other_update": "Другие доступные обновления" }, "downloading_status_text": "Загрузка. Получено {{bytes}}.", + "install_page_please_wait": "Пожалуйста, подождите", "install_page_loading": "Загрузка страницы установки", + "install_page_load_failed": "Не удалось загрузить страницу установки", "invalid_page": "Недействительная страница", "background_script_tag": "Это фоновый скрипт", "scheduled_script_tag": "Это запланированный скрипт", diff --git a/src/locales/vi-VN/translation.json b/src/locales/vi-VN/translation.json index f16febc99..ed482f3ed 100644 --- a/src/locales/vi-VN/translation.json +++ b/src/locales/vi-VN/translation.json @@ -334,7 +334,9 @@ "header_other_update": "Các bản cập nhật khác" }, "downloading_status_text": "Đang tải xuống. Đã nhận {{bytes}}.", + "install_page_please_wait": "Vui lòng chờ", "install_page_loading": "Đang tải trang cài đặt", + "install_page_load_failed": "Tải trang cài đặt thất bại", "invalid_page": "Trang không hợp lệ", "background_script_tag": "Đây là một script nền", "scheduled_script_tag": "Đây là một script hẹn giờ", diff --git a/src/locales/zh-CN/translation.json b/src/locales/zh-CN/translation.json index 508c9ea3d..80be7c663 100644 --- a/src/locales/zh-CN/translation.json +++ b/src/locales/zh-CN/translation.json @@ -334,7 +334,9 @@ "header_other_update": "其他可用更新" }, "downloading_status_text": "正在下载。已接收 {{bytes}}。", + "install_page_please_wait": "请稍等", "install_page_loading": "安装页面加载中", + "install_page_load_failed": "安装页面加载失败", "invalid_page": "无效页面", "background_script_tag": "这是一个后台脚本", "scheduled_script_tag": "这是一个定时脚本", diff --git a/src/locales/zh-TW/translation.json b/src/locales/zh-TW/translation.json index abb5c289d..c384e2ab4 100644 --- a/src/locales/zh-TW/translation.json +++ b/src/locales/zh-TW/translation.json @@ -334,7 +334,9 @@ "header_other_update": "其他可用更新" }, "downloading_status_text": "正在下載。已接收 {{bytes}}。", - "install_page_loading": "安裝頁載入中", + "install_page_please_wait": "請稍等", + "install_page_loading": "安裝頁面載入中", + "install_page_load_failed": "安裝頁面載入失敗", "invalid_page": "無效頁面", "background_script_tag": "這是一個背景腳本", "scheduled_script_tag": "這是一個排程腳本", diff --git a/src/pages/install/App.tsx b/src/pages/install/App.tsx index b0d3c229c..01c2817fc 100644 --- a/src/pages/install/App.tsx +++ b/src/pages/install/App.tsx @@ -225,13 +225,13 @@ function App() { try { const uuid = searchParams.get("uuid"); const fid = searchParams.get("file"); - let info: ScriptInfo | undefined; - let isKnownUpdate: boolean = false; - // 如果没有 uuid 和 file,跳过初始化逻辑 - if (!uuid && !fid) { + // 如果有 url 或 没有 uuid 和 file,跳过初始化逻辑 + if (searchParams.get("url") || (!uuid && !fid)) { return; } + let info: ScriptInfo | undefined; + let isKnownUpdate: boolean = false; if (window.history.length > 1) { setDoBackwards(true); @@ -649,84 +649,107 @@ function App() { }, [memoWatchFile]); // 检查是否有 uuid 或 file - const hasUUIDorFile = useMemo(() => { - return !!(searchParams.get("uuid") || searchParams.get("file")); - }, [searchParams]); + const searchParamUrl = searchParams.get("url"); + const hasValidSourceParam = !searchParamUrl && !!(searchParams.get("uuid") || searchParams.get("file")); const urlHref = useMemo(() => { - try { - if (!hasUUIDorFile) { - const url = searchParams.get("url"); - if (url) { - const urlObject = new URL(url); + if (!hasValidSourceParam) { + let rawUrl; + try { + // 取url=之后的所有内容 + rawUrl = location.search.match(/\?url=([^&]+)/)?.[1] || ""; + if (rawUrl) { + const urlObject = new URL(rawUrl); + // 验证解析后的 URL 是否具备核心要素,确保安全性与合法性 if (urlObject.protocol && urlObject.hostname && urlObject.pathname) { - return urlObject.href; + return rawUrl; } } + } catch { + // ignored } - } catch { - // ignored } return ""; - }, [hasUUIDorFile, searchParams]); + }, [hasValidSourceParam]); const [fetchingState, setFetchingState] = useState({ loadingStatus: "", errorStatus: "", }); - const loadURLAsync = async (urlHref: string) => { - try { - const { code, metadata } = await fetchScriptBody(urlHref, { + const loadURLAsync = async (url: string) => { + // 1. 定义获取单个脚本的内部逻辑,负责处理进度条与单次错误 + const fetchValidScript = async () => { + const result = await fetchScriptBody(url, { onProgress: (info: { receivedLength: number }) => { setFetchingState((prev) => ({ ...prev, - loadingStatus: t("downloading_status_text", { bytes: `${formatBytes(info.receivedLength)}` }), + loadingStatus: t("downloading_status_text", { bytes: formatBytes(info.receivedLength) }), })); }, }); - const update = false; + if (result.code && result.metadata) { + return { result, url } as const; // 找到有效的立即返回 + } + throw new Error(t("install_page_load_failed")); + }; + + try { + // 2. 执行获取 + const { result, url } = await fetchValidScript(); + const { code, metadata } = result; + + // 3. 处理数据与缓存 const uuid = uuidv4(); - const url = urlHref; - const upsertBy = "user"; - - const si = [update, createScriptInfo(uuid, code, url, upsertBy, metadata)]; - await cacheInstance.set(`${CACHE_KEY_SCRIPT_INFO}${uuid}`, si); - setSearchParams( - (prev) => { - prev.delete("url"); - prev.set("uuid", uuid); - return prev; - }, - { replace: true } - ); + const scriptData = [false, createScriptInfo(uuid, code, url, "user", metadata)]; + + await cacheInstance.set(`${CACHE_KEY_SCRIPT_INFO}${uuid}`, scriptData); + + // 4. 更新导向 + setSearchParams(new URLSearchParams(`?uuid=${uuid}`), { replace: true }); } catch (err: any) { - const errMessage = `${err.message || err}`; + // 5. 统一错误处理 setFetchingState((prev) => ({ ...prev, loadingStatus: "", - errorStatus: errMessage, + errorStatus: `${err?.message || err}`, })); } }; + const handleUrlChangeAndFetch = (targetUrlHref: string) => { + setFetchingState((prev) => ({ + ...prev, + loadingStatus: t("install_page_please_wait"), + })); + loadURLAsync(targetUrlHref); + }; + + // 有 url 的话下载内容 useEffect(() => { - if (!urlHref) return; - loadURLAsync(urlHref); + if (urlHref) handleUrlChangeAndFetch(urlHref); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [urlHref]); - if (!hasUUIDorFile) { + if (!hasValidSourceParam) { return urlHref ? (
- {t("install_page_loading")} {fetchingState.loadingStatus && ( -
- {fetchingState.loadingStatus} -
-
+ <> + {t("install_page_loading")} +
+ {fetchingState.loadingStatus} +
+
+ + )} + {fetchingState.errorStatus && ( + <> + {t("install_page_load_failed")} +
{fetchingState.errorStatus}
+ )} - {fetchingState.errorStatus &&
{fetchingState.errorStatus}
}
) : (