diff --git a/src/aura/init/main/ipcModules/fsIpcHandler.js b/src/aura/init/main/ipcModules/fsIpcHandler.js index 2759376..8079399 100755 --- a/src/aura/init/main/ipcModules/fsIpcHandler.js +++ b/src/aura/init/main/ipcModules/fsIpcHandler.js @@ -38,10 +38,13 @@ const composableFunctions = { progressCallback(failedTemplate); return false; } - if (!fs.existsSync(path.dirname(targetPath))) { - failedTemplate.message = "Path not exists"; - progressCallback(failedTemplate); + + const dirName = path.dirname(targetPath); + + if (!fs.existsSync(dirName)) { + fs.mkdirSync(dirName); } + const httpModuleIns = url.startsWith("https") ? nodeHttps : nodeHttp; global.__HUGO_AURA__.fsTasks?.downloadTasks.set(taskId, { @@ -49,6 +52,14 @@ const composableFunctions = { cancelReq: null, }); + progressCallback({ + id: taskId, + progress: 0, + status: "waiting", + dlUrl: url, + savePath: targetPath, + }); + const fsStream = fs.createWriteStream(targetPath); const dlReq = httpModuleIns.get(url, (response) => { @@ -64,9 +75,12 @@ const composableFunctions = { const totalBytes = parseInt(contentLength, 10) || 0; // No error handling 😆 let curRecvBytes = 0; + let hasCancelled = false; + global.__HUGO_AURA__.fsTasks?.downloadTasks.set(taskId, { status: "progressing", cancelReq: () => { + hasCancelled = true; dlReq.destroy(); fsStream.close(); fs.unlink(targetPath, () => {}); @@ -102,6 +116,9 @@ const composableFunctions = { fsStream.on("finish", () => { fsStream.close(); + if (hasCancelled) { + return; + } progressCallback({ id: taskId, progress: (100).toFixed(2), @@ -111,9 +128,9 @@ const composableFunctions = { dlUrl: url, savePath: targetPath, }); + global.__HUGO_AURA__.fsTasks?.downloadTasks.delete(taskId); }); - global.__HUGO_AURA__.fsTasks?.downloadTasks.delete(taskId); return true; }); @@ -123,7 +140,10 @@ const composableFunctions = { failedTemplate.message = "Request error: Unexpected error while downloading file"; failedTemplate.errorObj = e; - console.error(`[HugoAura / IPC / FS / ERROR] Error downloading file from ${url}, errorObj:`, e); + console.error( + `[HugoAura / IPC / FS / ERROR] Error downloading file from ${url}, errorObj:`, + e + ); progressCallback(failedTemplate); global.__HUGO_AURA__.fsTasks?.downloadTasks.delete(taskId); return false; diff --git a/src/aura/init/main/ipcModules/plsIpcHandler.js b/src/aura/init/main/ipcModules/plsIpcHandler.js index d147c4b..df78316 100755 --- a/src/aura/init/main/ipcModules/plsIpcHandler.js +++ b/src/aura/init/main/ipcModules/plsIpcHandler.js @@ -71,34 +71,92 @@ const functions = { handlePLSDownload: async (channel, callbackFn, binPath) => { // TODO: Channel selection const apiInfo = global.__HUGO_AURA_API__; - let plsVersionInfo = {}; - const getVerPromise = new Promise((resolve) => { + const getVerPromise = new Promise(async (resolveGetVerReq) => { // ↓ 目前 channel param 没有什么用处 - nodeHttps - .get( - `${apiInfo.baseUrl}${apiInfo.plsUpdate}?channel=${channel}`, - (rep) => { - let dataChunk = ""; - rep.on("data", (chunk) => { - dataChunk += chunk; - }); + for (const apiDomain of apiInfo.domains) { + const reqPromise = new Promise((resolveHttpRequest) => { + nodeHttps + .get( + `${apiDomain}${apiInfo.plsUpdate}?channel=${channel}`, + (rep) => { + let dataChunk = ""; + rep.on("data", (chunk) => { + dataChunk += chunk; + }); - rep.on("end", () => { - resolve({ - success: true, - data: dataChunk, + rep.on("end", () => { + let parsedData = {}; + try { + parsedData = JSON.parse(dataChunk); + } catch (e) { + callbackFn({ + id: "", + progress: 0, + status: "struggling", + dlUrl: null, + savePath: null, + message: `数据解析失败, 正在尝试 API 域名 ${ + apiInfo.domains[apiInfo.domains.indexOf(apiDomain) + 1] + } ...`, + errorObj: e, + }); + + setTimeout(() => { + resolveHttpRequest({ + success: false, + errorObj: e, + }); + }, 1000); + return; + } + + resolveHttpRequest({ + success: true, + data: parsedData, + }); + return; + }); + } + ) + .on("error", (e) => { + callbackFn({ + id: "", + progress: 0, + status: "struggling", + dlUrl: null, + savePath: null, + message: `连接失败, 正在尝试 API 域名 ${ + apiInfo.domains[apiInfo.domains.indexOf(apiDomain) + 1] + } ...`, + errorObj: e, }); + + setTimeout(() => { + resolveHttpRequest({ + success: false, + errorObj: e, + }); + }, 1000); }); - } - ) - .on("error", (e) => { - resolve({ - success: false, - data: null, - errorObj: e, - }); }); + + const requestResult = await reqPromise; + if (requestResult.success) { + resolveGetVerReq({ + success: true, + data: requestResult.data, + }); + break; + } else { + continue; + } + } + + resolveGetVerReq({ + success: false, + data: null, + }); }); const rawResInfo = await getVerPromise; @@ -109,30 +167,12 @@ const functions = { status: "failed", dlUrl: null, savePath: null, - message: "未能获取 PLS 版本信息", - errorObj: rawResInfo.errorObj ? rawResInfo.errorObj : null, + message: "未能获取 PLS 版本信息, 所有 API 域名均无法连接", }); return false; } - try { - plsVersionInfo = JSON.parse(rawResInfo.data); - } catch (e) { - callbackFn({ - id: "", - progress: 0, - status: "failed", - dlUrl: null, - savePath: null, - message: "PLS 版本信息解析失败", - errorObj: e, - }); - console.error( - "[HugoAura / IPC / PLS] Error querying PLS version info:", - e - ); - return false; - } + const plsVersionInfo = rawResInfo.data; let deviceArch = process.env.PROCESSOR_ARCHITEW6432 ? process.env.PROCESSOR_ARCHITEW6432 @@ -155,7 +195,16 @@ const functions = { fsComposables.downloadFile( plsVersionInfo.data.downloadUrl[deviceArch], binPath, - callbackFn + (...args) => { + if (args[0].status === "done") { + if (global.__HUGO_AURA__.plsStats) { + global.__HUGO_AURA__.plsStats.installed = true; + global.__HUGO_AURA__.plsStats.status = "dead"; + } + } + + callbackFn(...args); + } ); }, }; @@ -192,11 +241,18 @@ const applyPlsIpcHandler = (ipcMain) => { (_event, _arg) => { try { const result = fs.existsSync(PLS_BIN_PATH); + + if (global.__HUGO_AURA__.plsStats?.status === "notInstalled") { + global.__HUGO_AURA__.plsStats.status = "dead"; + } + return { success: true, data: { isExists: result }, }; } catch (e) { + // @ts-expect-error + global.__HUGO_AURA__.plsStats.status = "notInstalled"; return { success: false, data: { isExists: false }, diff --git a/src/aura/types/main/ipc/fs.d.ts b/src/aura/types/main/ipc/fs.d.ts index 58483bd..a454376 100755 --- a/src/aura/types/main/ipc/fs.d.ts +++ b/src/aura/types/main/ipc/fs.d.ts @@ -1,5 +1,5 @@ type DownloadTaskID = string; -type DownloadTaskStatus = "waiting" | "progressing" | "done" | "failed" | "cancelled"; +type DownloadTaskStatus = "waiting" | "progressing" | "done" | "failed" | "cancelled" | "struggling"; interface DownloadTask { id: DownloadTaskID; diff --git a/src/aura/types/shared/global.d.ts b/src/aura/types/shared/global.d.ts index 8ef256f..12f7fcd 100755 --- a/src/aura/types/shared/global.d.ts +++ b/src/aura/types/shared/global.d.ts @@ -24,7 +24,7 @@ interface GlobalHugoAuraInfo { } interface GlobalHugoAuraApiInfo { - baseUrl: string; + domains: string[]; plsUpdate: string; auraUpdate: string; } diff --git a/src/aura/types/shared/pls/status.d.ts b/src/aura/types/shared/pls/status.d.ts index 113d2d8..0538d06 100755 --- a/src/aura/types/shared/pls/status.d.ts +++ b/src/aura/types/shared/pls/status.d.ts @@ -1,15 +1,28 @@ import { RendererProcessOnlyVal } from "../global"; +type PLSStatusDesc = + | "dead" + | "running" + | "notReady" + | "downloading" + | "notInstalled"; + interface PLSStatus { installed: boolean; detached: boolean; connected: boolean; launched: boolean; - status: string; + status: PLSStatusDesc; version: string; authToken: string; } type PLSLifecycleType = "isDetached" | "isSvcInstalled" | "isSvcStart"; -type PLSLifecycleControlType = "instSvc" | "rmSvc" | "startSvc" | "stopSvc" | "rmBin" | "dlBin"; +type PLSLifecycleControlType = + | "instSvc" + | "rmSvc" + | "startSvc" + | "stopSvc" + | "rmBin" + | "dlBin"; diff --git a/src/aura/ui/js/plsConnectionManager.js b/src/aura/ui/js/plsConnectionManager.js index cadd536..86ca96b 100755 --- a/src/aura/ui/js/plsConnectionManager.js +++ b/src/aura/ui/js/plsConnectionManager.js @@ -6,7 +6,7 @@ detached: false, connected: false, launched: false, - status: "unknown", + status: "dead", version: "未知", authToken: "", }; @@ -259,7 +259,10 @@ `${IPC_METHOD_BASE}.getPlsStats` ); let updatedPlsStats = {}; - if (curPlsStats === null || !curPlsStats.success) { + if ( + (curPlsStats === null || !curPlsStats.success) && + curPlsStats.status !== "downloading" + ) { updatedPlsStats = { installed: false, launched: false, @@ -269,15 +272,14 @@ status: "dead", authToken: "66ccff0d000721114514191981023333", }; + const isPlsFolderExists = ( + await global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.getPlsBinExists`) + ).data.isExists; + updatedPlsStats.installed = isPlsFolderExists; } else { updatedPlsStats = curPlsStats.data; } - const isPlsFolderExists = ( - await global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.getPlsBinExists`) - ).data.isExists; - updatedPlsStats.installed = isPlsFolderExists; - // @ts-expect-error global.__HUGO_AURA__.plsStats = updatedPlsStats; console.debug( diff --git a/src/aura/ui/pages/configSubPages/behaviourCtrl/plsStatus.css b/src/aura/ui/pages/configSubPages/behaviourCtrl/plsStatus.css index bc47f57..4598933 100755 --- a/src/aura/ui/pages/configSubPages/behaviourCtrl/plsStatus.css +++ b/src/aura/ui/pages/configSubPages/behaviourCtrl/plsStatus.css @@ -33,6 +33,10 @@ margin-bottom: 1rem; } +.acs-bc-psp-operations-container.acs-bc-psp-oper-ctnr-hidden { + display: none; +} + .acs-bc-psp-operation-btn { --svg-color: rgb(17, 140, 255); @@ -85,6 +89,50 @@ opacity: 0.3; } +.acs-bc-psp-download-progress-area { + display: flex; + flex-direction: column; + width: 80%; + justify-content: center; + align-items: center; +} + +.acs-bc-psp-download-progress-area.acs-bc-psp-dl-pbar-hidden { + display: none; +} + +.acs-bc-psp-download-progress-area .progress { + height: 2px; + width: 80%; + margin-bottom: 0.6rem; +} + +.acs-bc-psp-download-progress-area .progress-bar { + transition: all 0.15s; +} + +.acs-bc-psp-download-progress-area #acsBcPspDownloadPbarDesc { + opacity: 0.6; + margin-bottom: 0.25rem; +} + +.acs-bc-psp-download-progress-info-area { + display: flex; +} + +.acs-bc-psp-download-progress-info-area .acs-bc-psp-operation-btn { + margin-left: 1rem; + margin-bottom: 0.25rem; +} + +.acs-bc-psp-download-progress-info-area .acs-bc-psp-operation-btn.hidden { + display: none; +} + +.acs-bc-psp-download-progress-info-area .acs-bc-psp-operation-btn svg { + margin-top: 1px; +} + .acs-bc-pls-status-page-status-el { display: flex; align-items: center; diff --git a/src/aura/ui/pages/configSubPages/behaviourCtrl/plsStatus.html b/src/aura/ui/pages/configSubPages/behaviourCtrl/plsStatus.html index 04e88f1..4c9123d 100755 --- a/src/aura/ui/pages/configSubPages/behaviourCtrl/plsStatus.html +++ b/src/aura/ui/pages/configSubPages/behaviourCtrl/plsStatus.html @@ -124,6 +124,37 @@ +
+安装状态