mirror of
https://github.com/HugoAura/Seewo-HugoAura.git
synced 2026-06-29 13:34:27 +08:00
Compare commits
7 Commits
v0.1.1-pre
...
v0.1.1-pre
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54df7011c0 | ||
|
|
423142d785 | ||
|
|
a639ae0ac6 | ||
|
|
ed29f1b86f | ||
|
|
8ab55bc93c | ||
|
|
50bde49414 | ||
|
|
7b7254f1bb |
136
.github/workflows/pack.yml
vendored
Normal file
136
.github/workflows/pack.yml
vendored
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
name: Patch ASAR & Pack source code
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [dev, stable]
|
||||||
|
pull_request:
|
||||||
|
branches: [dev, stable, main, master]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
pack:
|
||||||
|
name: Patch & Pack
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Setup Node.JS 20 LTS
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: "20"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y p7zip-full wget
|
||||||
|
npm install -g asar
|
||||||
|
|
||||||
|
- name: Checkout repository code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
path: "./HugoAura-Code"
|
||||||
|
|
||||||
|
- name: Download SeewoServiceSetup
|
||||||
|
run: |
|
||||||
|
echo "[DEBUG] Working DIR:"
|
||||||
|
pwd
|
||||||
|
|
||||||
|
wget -nv -O "SeewoService.exe" "https://e.seewo.com/download/file?code=SeewoServiceSetup"
|
||||||
|
echo "[DEBUG] Listing downloaded file"
|
||||||
|
ls -la SeewoService*
|
||||||
|
|
||||||
|
- name: Extract SeewoServiceSetup as zip
|
||||||
|
run: |
|
||||||
|
mkdir -p SeewoServiceSource
|
||||||
|
7z x "SeewoService.exe" -o"./SeewoServiceSource/" -y
|
||||||
|
|
||||||
|
echo "[DEBUG] Listing extracted files"
|
||||||
|
ls -la SeewoServiceSource/
|
||||||
|
|
||||||
|
- name: Extract ASAR file
|
||||||
|
run: |
|
||||||
|
cd SeewoServiceSource
|
||||||
|
SEEWO_DIR=$(find . -name "SeewoService_*" -type d | head -1)
|
||||||
|
echo "[INFO] Found SeewoService directory: $SEEWO_DIR"
|
||||||
|
|
||||||
|
cd "$SEEWO_DIR/SeewoServiceAssistant/resources/"
|
||||||
|
|
||||||
|
asar extract ./app.asar ./app-unpacked
|
||||||
|
|
||||||
|
- name: Move app-unpacked and clean SSASource
|
||||||
|
run: |
|
||||||
|
mkdir -p SSARes
|
||||||
|
|
||||||
|
cd SeewoServiceSource
|
||||||
|
SEEWO_DIR=$(find . -name "SeewoService_*" -type d | head -1)
|
||||||
|
mv "$SEEWO_DIR/SeewoServiceAssistant/resources/app-unpacked" "../SSARes/"
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
rm -rf SeewoServiceSource
|
||||||
|
rm -rf *.exe
|
||||||
|
echo "[DEBUG] Listing Working DIR"
|
||||||
|
ls -la
|
||||||
|
|
||||||
|
- name: Patch main.js
|
||||||
|
run: |
|
||||||
|
cd SSARes/app-unpacked
|
||||||
|
|
||||||
|
### cp main.js main.js.bak
|
||||||
|
|
||||||
|
cat > patch_main.js << 'EOF'
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
let content = fs.readFileSync('main.js', 'utf8');
|
||||||
|
|
||||||
|
content = 'const hook = require("./hook.js");\n' + content;
|
||||||
|
|
||||||
|
content = content.replace(/n\.m=e/, ';const zeron = require("./zeron.js");n = zeron(n);n.m=e');
|
||||||
|
|
||||||
|
content = content.replace(/let f=new s\(Object\.assign\(\{\},\{transparent:!0,/, ';hook({ central: n, windowName: this.wname, config: c });let f=new s(Object.assign({},{transparent:!0,');
|
||||||
|
|
||||||
|
content = content.replace(/c\.canOpenDevTool/, 'c.canOpenDevTool,preload: __dirname + "\\\\preload.js"');
|
||||||
|
|
||||||
|
fs.writeFileSync('main.js', content);
|
||||||
|
|
||||||
|
console.log('[SUCCESS] main.js has been modified successfully');
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "[DEBUG] Running patch_main.js"
|
||||||
|
node ./patch_main.js
|
||||||
|
|
||||||
|
rm -rf patch_main.js
|
||||||
|
|
||||||
|
- name: Copy HugoAura core files
|
||||||
|
run: |
|
||||||
|
cp -r HugoAura-Code/src/core/* SSARes/app-unpacked/
|
||||||
|
|
||||||
|
echo "[DEBUG] Listing files under <Working DIR>/SSARes/app-unpacked/"
|
||||||
|
ls -la SSARes/app-unpacked/
|
||||||
|
|
||||||
|
- name: Create artifacts DIR and re-pack ASAR
|
||||||
|
run: |
|
||||||
|
echo "[DEBUG] Creating artifacts directory"
|
||||||
|
mkdir -p Artifacts
|
||||||
|
|
||||||
|
asar pack SSARes/app-unpacked Artifacts/app-patched.asar
|
||||||
|
|
||||||
|
- name: Create aura.zip
|
||||||
|
run: |
|
||||||
|
cd HugoAura-Code/src/aura
|
||||||
|
zip -r ../../../Artifacts/aura.zip .
|
||||||
|
cd ../../..
|
||||||
|
|
||||||
|
echo "[DEBUG] Files in <Working DIR>/Artifacts directory:"
|
||||||
|
ls -la Artifacts/
|
||||||
|
|
||||||
|
- name: Upload patched ASAR
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: asar-patched
|
||||||
|
path: Artifacts/app-patched.asar
|
||||||
|
|
||||||
|
- name: Upload aura.zip
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: aura-code
|
||||||
|
path: Artifacts/aura.zip
|
||||||
@@ -14,6 +14,8 @@
|
|||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
> 已经过测试的希沃管家版本: v1.5.4.3824
|
> 已经过测试的希沃管家版本: v1.5.4.3824
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## ✨ 概览
|
## ✨ 概览
|
||||||
|
|
||||||
[天下](https://www.bilibili.com/video/BV1UN4y1k7bA) [苦希沃管家](https://www.bilibili.com/video/BV18Z421j7Lf) [久矣](https://github.com/255doesnotexist/SeewoAssistantPasswordRecovery), 如此~~好用~~的一款集控软件, 让广大电教委员对它~~爱不释手~~。
|
[天下](https://www.bilibili.com/video/BV1UN4y1k7bA) [苦希沃管家](https://www.bilibili.com/video/BV18Z421j7Lf) [久矣](https://github.com/255doesnotexist/SeewoAssistantPasswordRecovery), 如此~~好用~~的一款集控软件, 让广大电教委员对它~~爱不释手~~。
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "HugoAura",
|
"name": "HugoAura",
|
||||||
"version": "0.1.1-pre-III",
|
"version": "0.1.1-pre-IV",
|
||||||
"description": "Aura for SeewoHugo",
|
"description": "Aura for SeewoHugo",
|
||||||
"main": "app.asar/main.js",
|
"main": "app.asar/main.js",
|
||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ const buildIpcMain = (electron) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const { applyConfigIpcHandler } = require("./ipcModules/configIpcHandler");
|
const { applyConfigIpcHandler } = require("./ipcModules/configIpcHandler");
|
||||||
|
const { applyFsIpcHandler } = require("./ipcModules/fsIpcHandler");
|
||||||
const { applyPlsIpcHandler } = require("./ipcModules/plsIpcHandler");
|
const { applyPlsIpcHandler } = require("./ipcModules/plsIpcHandler");
|
||||||
|
|
||||||
ipcMain.handle("$aura.base.restartApplication", async () => {
|
ipcMain.handle("$aura.base.restartApplication", async () => {
|
||||||
@@ -82,6 +83,7 @@ const buildIpcMain = (electron) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
applyConfigIpcHandler(ipcMain);
|
applyConfigIpcHandler(ipcMain);
|
||||||
|
applyFsIpcHandler(ipcMain);
|
||||||
applyPlsIpcHandler(ipcMain);
|
applyPlsIpcHandler(ipcMain);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
186
src/aura/init/main/ipcModules/fsIpcHandler.js
Executable file
186
src/aura/init/main/ipcModules/fsIpcHandler.js
Executable file
@@ -0,0 +1,186 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
const __SCOPE = "main";
|
||||||
|
|
||||||
|
const { exec } = require("child_process");
|
||||||
|
const nodeHttp = require("http");
|
||||||
|
const nodeHttps = require("https");
|
||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
const { genRandomHex } = require("../../../utils/crypto");
|
||||||
|
|
||||||
|
const composableFunctions = {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} url
|
||||||
|
* @param {string} targetPath
|
||||||
|
* @param {((arg: DownloadTask) => any)} progressCallback
|
||||||
|
*/
|
||||||
|
downloadFile: async (url, targetPath, progressCallback) => {
|
||||||
|
if (!progressCallback) return false;
|
||||||
|
const taskId = genRandomHex();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {DownloadTask}
|
||||||
|
*/
|
||||||
|
const failedTemplate = {
|
||||||
|
id: taskId,
|
||||||
|
progress: 100,
|
||||||
|
status: "failed",
|
||||||
|
dlUrl: url,
|
||||||
|
savePath: targetPath,
|
||||||
|
message: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!url || !targetPath) {
|
||||||
|
failedTemplate.message = "Invalid arg";
|
||||||
|
progressCallback(failedTemplate);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!fs.existsSync(path.dirname(targetPath))) {
|
||||||
|
failedTemplate.message = "Path not exists";
|
||||||
|
progressCallback(failedTemplate);
|
||||||
|
}
|
||||||
|
const httpModuleIns = url.startsWith("https") ? nodeHttps : nodeHttp;
|
||||||
|
|
||||||
|
global.__HUGO_AURA__.fsTasks?.downloadTasks.set(taskId, {
|
||||||
|
status: "waiting",
|
||||||
|
cancelReq: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const fsStream = fs.createWriteStream(targetPath);
|
||||||
|
|
||||||
|
const dlReq = httpModuleIns.get(url, (response) => {
|
||||||
|
if (response.statusCode !== 200) {
|
||||||
|
fsStream.close();
|
||||||
|
failedTemplate.message = `Request error: HTTP ${response.statusCode}`;
|
||||||
|
progressCallback(failedTemplate);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentLength = response.headers["content-length"];
|
||||||
|
// @ts-expect-error
|
||||||
|
const totalBytes = parseInt(contentLength, 10) || 0; // No error handling 😆
|
||||||
|
let curRecvBytes = 0;
|
||||||
|
|
||||||
|
global.__HUGO_AURA__.fsTasks?.downloadTasks.set(taskId, {
|
||||||
|
status: "progressing",
|
||||||
|
cancelReq: () => {
|
||||||
|
dlReq.destroy();
|
||||||
|
fsStream.close();
|
||||||
|
fs.unlink(targetPath, () => {});
|
||||||
|
global.__HUGO_AURA__.fsTasks?.downloadTasks.delete(taskId);
|
||||||
|
progressCallback({
|
||||||
|
id: taskId,
|
||||||
|
progress: 100,
|
||||||
|
curBytes: curRecvBytes,
|
||||||
|
totalBytes: totalBytes,
|
||||||
|
status: "cancelled",
|
||||||
|
dlUrl: url,
|
||||||
|
savePath: targetPath,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
response.on("data", (chunk) => {
|
||||||
|
curRecvBytes += chunk.length;
|
||||||
|
const curProgress =
|
||||||
|
totalBytes > 0 ? (curRecvBytes / totalBytes) * 100 : 0;
|
||||||
|
progressCallback({
|
||||||
|
id: taskId,
|
||||||
|
progress: curProgress.toFixed(2),
|
||||||
|
curBytes: curRecvBytes,
|
||||||
|
totalBytes: totalBytes,
|
||||||
|
status: "progressing",
|
||||||
|
dlUrl: url,
|
||||||
|
savePath: targetPath,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
response.pipe(fsStream);
|
||||||
|
|
||||||
|
fsStream.on("finish", () => {
|
||||||
|
fsStream.close();
|
||||||
|
progressCallback({
|
||||||
|
id: taskId,
|
||||||
|
progress: (100).toFixed(2),
|
||||||
|
curBytes: curRecvBytes,
|
||||||
|
totalBytes: totalBytes,
|
||||||
|
status: "done",
|
||||||
|
dlUrl: url,
|
||||||
|
savePath: targetPath,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
global.__HUGO_AURA__.fsTasks?.downloadTasks.delete(taskId);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
dlReq.on("error", (e) => {
|
||||||
|
fsStream.close();
|
||||||
|
fs.unlink(targetPath, () => {});
|
||||||
|
failedTemplate.message =
|
||||||
|
"Request error: Unexpected error while downloading file";
|
||||||
|
failedTemplate.errorObj = e;
|
||||||
|
progressCallback(failedTemplate);
|
||||||
|
global.__HUGO_AURA__.fsTasks?.downloadTasks.delete(taskId);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("electron").IpcMain} ipcMain
|
||||||
|
*/
|
||||||
|
const applyFsIpcHandler = (ipcMain) => {
|
||||||
|
const methodBase = "$aura.fs";
|
||||||
|
|
||||||
|
global.__HUGO_AURA__.fsTasks = {
|
||||||
|
downloadTasks: new Map(),
|
||||||
|
};
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.dl.cancelDownloadTask`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("electron").IpcMainInvokeEvent} _evt
|
||||||
|
* @param {{ targetTaskId: string }} arg
|
||||||
|
* @returns {{ success: boolean, error: string | null }}
|
||||||
|
*/
|
||||||
|
(_evt, arg) => {
|
||||||
|
if (!arg.targetTaskId) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: "ARG_INVALID",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!global.__HUGO_AURA__.fsTasks?.downloadTasks.has(arg.targetTaskId)) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: "TASK_ID_NOT_FOUND",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const taskObj = global.__HUGO_AURA__.fsTasks.downloadTasks.get(
|
||||||
|
arg.targetTaskId
|
||||||
|
);
|
||||||
|
if (!taskObj?.cancelReq) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: "TASK_NOT_STARTED",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
taskObj.cancelReq();
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = { fsComposables: composableFunctions, applyFsIpcHandler };
|
||||||
@@ -2,9 +2,163 @@
|
|||||||
|
|
||||||
const __SCOPE = "main";
|
const __SCOPE = "main";
|
||||||
|
|
||||||
const os = require("os");
|
const { exec } = require("child_process");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
const nodeHttps = require("https");
|
||||||
|
const { fsComposables } = require("./fsIpcHandler");
|
||||||
|
|
||||||
|
const functions = {
|
||||||
|
querySvcDetail: (
|
||||||
|
/** @type {string} */ svcName,
|
||||||
|
/** @type {string} */ findTarget
|
||||||
|
) => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
exec(
|
||||||
|
`sc query ${svcName}`,
|
||||||
|
{ encoding: "utf8" },
|
||||||
|
(error, stdout, stderr) => {
|
||||||
|
if (error) {
|
||||||
|
resolve({
|
||||||
|
success: true,
|
||||||
|
result: false,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (stdout.includes(findTarget)) {
|
||||||
|
resolve({
|
||||||
|
success: true,
|
||||||
|
result: true,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
resolve({
|
||||||
|
success: true,
|
||||||
|
result: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} logHeader
|
||||||
|
* @param {string} binPath
|
||||||
|
* @param {string} command
|
||||||
|
* @returns {Promise<{ success: boolean, errorObj?: Error }>}
|
||||||
|
*/
|
||||||
|
execCommand: (logHeader, binPath, command) => {
|
||||||
|
const processedPath = binPath.includes(" ") ? `"${binPath}"` : binPath;
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
exec(`${processedPath} ${command}`, (error, stdout, stderr) => {
|
||||||
|
if (error) {
|
||||||
|
console.error(`${logHeader} Failed to execute command:`, error);
|
||||||
|
resolve({ success: false, errorObj: error });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve({ success: true });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {"stable" | "alpha"} channel
|
||||||
|
* @param {(arg: DownloadTask) => any} callbackFn
|
||||||
|
* @param {string} binPath
|
||||||
|
*/
|
||||||
|
handlePLSDownload: async (channel, callbackFn, binPath) => {
|
||||||
|
// TODO: Channel selection
|
||||||
|
const apiInfo = global.__HUGO_AURA_API__;
|
||||||
|
let plsVersionInfo = {};
|
||||||
|
|
||||||
|
const getVerPromise = new Promise((resolve) => {
|
||||||
|
// ↓ 目前 channel param 没有什么用处
|
||||||
|
nodeHttps
|
||||||
|
.get(
|
||||||
|
`${apiInfo.baseUrl}${apiInfo.plsUpdate}?channel=${channel}`,
|
||||||
|
(rep) => {
|
||||||
|
let dataChunk = "";
|
||||||
|
rep.on("data", (chunk) => {
|
||||||
|
dataChunk += chunk;
|
||||||
|
});
|
||||||
|
|
||||||
|
rep.on("end", () => {
|
||||||
|
resolve({
|
||||||
|
success: true,
|
||||||
|
data: dataChunk,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.on("error", (e) => {
|
||||||
|
resolve({
|
||||||
|
success: false,
|
||||||
|
data: null,
|
||||||
|
errorObj: e,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const rawResInfo = await getVerPromise;
|
||||||
|
if (!rawResInfo.success) {
|
||||||
|
callbackFn({
|
||||||
|
id: "",
|
||||||
|
progress: 0,
|
||||||
|
status: "failed",
|
||||||
|
dlUrl: null,
|
||||||
|
savePath: null,
|
||||||
|
message: "未能获取 PLS 版本信息",
|
||||||
|
errorObj: rawResInfo.errorObj ? rawResInfo.errorObj : null,
|
||||||
|
});
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
let deviceArch = process.env.PROCESSOR_ARCHITEW6432
|
||||||
|
? process.env.PROCESSOR_ARCHITEW6432
|
||||||
|
: process.env.PROCESSOR_ARCHITECTURE;
|
||||||
|
// @ts-expect-error
|
||||||
|
deviceArch = deviceArch.toLowerCase();
|
||||||
|
|
||||||
|
if (!Object.keys(plsVersionInfo.data.downloadUrl).includes(deviceArch)) {
|
||||||
|
callbackFn({
|
||||||
|
id: "",
|
||||||
|
progress: 0,
|
||||||
|
status: "failed",
|
||||||
|
dlUrl: null,
|
||||||
|
savePath: null,
|
||||||
|
message: `处理器架构识别失败, 检测到的架构: ${deviceArch}`,
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fsComposables.downloadFile(
|
||||||
|
plsVersionInfo.data.downloadUrl[deviceArch],
|
||||||
|
binPath,
|
||||||
|
callbackFn
|
||||||
|
);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -13,6 +167,10 @@ const path = require("path");
|
|||||||
const applyPlsIpcHandler = (ipcMain) => {
|
const applyPlsIpcHandler = (ipcMain) => {
|
||||||
const methodBase = "$aura.pls";
|
const methodBase = "$aura.pls";
|
||||||
|
|
||||||
|
const PLS_INSTALL_DIR = path.join("C:\\Program Files", "HugoAura PLS", "bin");
|
||||||
|
const PLS_BIN_PATH = path.join(PLS_INSTALL_DIR, "HugoAura-PLS.exe");
|
||||||
|
const PLS_SVC_NAME = "HugoAuraPLS";
|
||||||
|
|
||||||
const isPlsDetached = process.argv.includes("--pls-detach");
|
const isPlsDetached = process.argv.includes("--pls-detach");
|
||||||
|
|
||||||
global.__HUGO_AURA__.plsStats = {
|
global.__HUGO_AURA__.plsStats = {
|
||||||
@@ -26,15 +184,14 @@ const applyPlsIpcHandler = (ipcMain) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ipcMain.handle(
|
ipcMain.handle(
|
||||||
`${methodBase}.getPlsFolderExists`,
|
`${methodBase}.getPlsBinExists`,
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @returns {{ success: boolean; data: { isExists: boolean }; error?: Error }}
|
* @returns {{ success: boolean; data: { isExists: boolean }; error?: Error }}
|
||||||
*/
|
*/
|
||||||
(_event, _arg) => {
|
(_event, _arg) => {
|
||||||
const plsFolderPath = path.join("C:\\Program Files", "HugoAura PLS");
|
|
||||||
try {
|
try {
|
||||||
const result = fs.existsSync(plsFolderPath);
|
const result = fs.existsSync(PLS_BIN_PATH);
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
data: { isExists: result },
|
data: { isExists: result },
|
||||||
@@ -49,6 +206,48 @@ const applyPlsIpcHandler = (ipcMain) => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.ensurePlsInstallDir`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("electron").IpcMainInvokeEvent} _event
|
||||||
|
* @param {any} _arg
|
||||||
|
* @returns {{ success: boolean; data: { alreadyExists: boolean; createdDir: string; }; error?: Error }}
|
||||||
|
*/
|
||||||
|
(_event, _arg) => {
|
||||||
|
const alreadyExists = fs.existsSync(PLS_INSTALL_DIR);
|
||||||
|
if (alreadyExists) {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data: {
|
||||||
|
alreadyExists: true,
|
||||||
|
createdDir: PLS_INSTALL_DIR,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
fs.mkdirSync(PLS_INSTALL_DIR);
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data: {
|
||||||
|
alreadyExists: false,
|
||||||
|
createdDir: PLS_INSTALL_DIR,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
data: {
|
||||||
|
alreadyExists: false,
|
||||||
|
createdDir: PLS_INSTALL_DIR,
|
||||||
|
},
|
||||||
|
error: error,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
ipcMain.handle(
|
ipcMain.handle(
|
||||||
`${methodBase}.getPlsStats`,
|
`${methodBase}.getPlsStats`,
|
||||||
/**
|
/**
|
||||||
@@ -189,6 +388,115 @@ const applyPlsIpcHandler = (ipcMain) => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.plsLifecycleQuery`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("electron").IpcMainInvokeEvent} _event
|
||||||
|
* @param {{ target: import("../../../types/shared/pls/status").PLSLifecycleType }} arg
|
||||||
|
* @returns {Promise<{ success: boolean, result: boolean }>}
|
||||||
|
*/
|
||||||
|
async (_event, arg) => {
|
||||||
|
switch (arg.target) {
|
||||||
|
case "isDetached":
|
||||||
|
return { success: true, result: isPlsDetached };
|
||||||
|
case "isSvcInstalled":
|
||||||
|
return await functions.querySvcDetail(PLS_SVC_NAME, "SERVICE_NAME");
|
||||||
|
case "isSvcStart":
|
||||||
|
return await functions.querySvcDetail(PLS_SVC_NAME, "RUNNING");
|
||||||
|
default:
|
||||||
|
console.warn(
|
||||||
|
`[HugoAura / IPC / PLS] <plsLifecycleQuery> Invalid arg.target: ${arg.target}`
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
result: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.plsLifecycleControl`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} _event
|
||||||
|
* @param {{ target: import("../../../types/shared/pls/status").PLSLifecycleControlType }} arg
|
||||||
|
* @returns {Promise<{ success: boolean, errorObj?: Error }>}
|
||||||
|
*/
|
||||||
|
async (_event, arg) => {
|
||||||
|
const logHeader = "[HugoAura / IPC / PLS] <plsLifecycleControl>";
|
||||||
|
|
||||||
|
if (!global.__HUGO_AURA__.plsStats?.installed) {
|
||||||
|
return { success: false, errorObj: new Error("PLS not installed") };
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (arg.target) {
|
||||||
|
case "instSvc":
|
||||||
|
return await functions.execCommand(
|
||||||
|
logHeader,
|
||||||
|
PLS_BIN_PATH,
|
||||||
|
"--startup auto install"
|
||||||
|
);
|
||||||
|
case "rmSvc":
|
||||||
|
return await functions.execCommand(logHeader, PLS_BIN_PATH, "remove");
|
||||||
|
case "startSvc":
|
||||||
|
return await functions.execCommand(logHeader, PLS_BIN_PATH, "start");
|
||||||
|
case "stopSvc":
|
||||||
|
return await functions.execCommand(logHeader, PLS_BIN_PATH, "stop");
|
||||||
|
case "rmBin":
|
||||||
|
const unlinkPromise = new Promise((resolve) => {
|
||||||
|
fs.unlink(PLS_BIN_PATH, (error) => {
|
||||||
|
if (error) {
|
||||||
|
resolve({
|
||||||
|
success: false,
|
||||||
|
errorObj: error,
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve({
|
||||||
|
success: true,
|
||||||
|
errorObj: null,
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const unlinkRet = await unlinkPromise;
|
||||||
|
|
||||||
|
return unlinkRet;
|
||||||
|
default:
|
||||||
|
return { success: false, errorObj: new Error("Method not found") };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.downloadPls`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("electron").IpcMainInvokeEvent} _evt
|
||||||
|
* @param {{channel?: "stable" | "alpha", reportTo?: import("../../../types/main/core").WindowName}} arg
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
(_evt, arg) => {
|
||||||
|
const channel = arg.channel ? arg.channel : "stable";
|
||||||
|
const reportWin = arg.reportTo ? arg.reportTo : "assistant";
|
||||||
|
functions.handlePLSDownload(
|
||||||
|
channel,
|
||||||
|
(status) => {
|
||||||
|
ipcMain.send(
|
||||||
|
reportWin,
|
||||||
|
`${methodBase}.post.reportPlsDownloadStatus`,
|
||||||
|
status
|
||||||
|
);
|
||||||
|
},
|
||||||
|
PLS_BIN_PATH
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
ipcMain.handle(
|
ipcMain.handle(
|
||||||
`${methodBase}.retryPlsConnect`,
|
`${methodBase}.retryPlsConnect`,
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -24,40 +24,6 @@
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const createStore = () => {
|
|
||||||
const store = {
|
|
||||||
router: "/",
|
|
||||||
};
|
|
||||||
const internal = {
|
|
||||||
get: (key) => store[key],
|
|
||||||
set: (key, value) => {
|
|
||||||
store[key] = value;
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
window.$store = {
|
|
||||||
get: (key) => {
|
|
||||||
const stack = new Error().stack;
|
|
||||||
if (stack.includes("aura/ui/pages/")) {
|
|
||||||
return internal.get(key);
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
},
|
|
||||||
set: (key, value) => {
|
|
||||||
const stack = new Error().stack;
|
|
||||||
if (stack.includes("aura/ui/pages/")) {
|
|
||||||
return internal.set(key, value);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return internal;
|
|
||||||
};
|
|
||||||
|
|
||||||
const store = createStore();
|
|
||||||
|
|
||||||
const createUILoader = () => {
|
const createUILoader = () => {
|
||||||
const modules = "__TEMPLATE_TARGETS__";
|
const modules = "__TEMPLATE_TARGETS__";
|
||||||
const containers = new Map();
|
const containers = new Map();
|
||||||
@@ -65,6 +31,63 @@
|
|||||||
const moduleResources = new Map();
|
const moduleResources = new Map();
|
||||||
const globalScripts = new Set();
|
const globalScripts = new Set();
|
||||||
|
|
||||||
|
const flattenTargets = (targets, parentKey = "") => {
|
||||||
|
const flattened = {};
|
||||||
|
|
||||||
|
for (const [key, config] of Object.entries(targets)) {
|
||||||
|
const fullKey = parentKey ? `${parentKey}.${key}` : key;
|
||||||
|
flattened[fullKey] = { ...config };
|
||||||
|
|
||||||
|
if (
|
||||||
|
config.childs &&
|
||||||
|
typeof config.childs === "object" &&
|
||||||
|
!Array.isArray(config.childs)
|
||||||
|
) {
|
||||||
|
const childTargets = flattenTargets(config.childs, fullKey);
|
||||||
|
Object.assign(flattened, childTargets);
|
||||||
|
delete flattened[fullKey].childs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return flattened;
|
||||||
|
};
|
||||||
|
|
||||||
|
const flatModules = flattenTargets(modules);
|
||||||
|
|
||||||
|
const createAccessProxy = (originalModules, flatModules) => {
|
||||||
|
const createNestedProxy = (target, path = []) => {
|
||||||
|
return new Proxy(target, {
|
||||||
|
get(target, prop) {
|
||||||
|
const currentPath = [...path, prop].join(".");
|
||||||
|
|
||||||
|
if (flatModules[currentPath]) {
|
||||||
|
return flatModules[currentPath];
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = Reflect.get(target, prop);
|
||||||
|
if (typeof value === "object" && value !== null) {
|
||||||
|
return createNestedProxy(value, [...path, prop]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
set(target, prop, value) {
|
||||||
|
const currentPath = [...path, prop].join(".");
|
||||||
|
|
||||||
|
if (flatModules[currentPath]) {
|
||||||
|
flatModules[currentPath] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Reflect.set(target, prop, value);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return createNestedProxy(originalModules);
|
||||||
|
};
|
||||||
|
|
||||||
|
const accessibleModules = createAccessProxy(modules, flatModules);
|
||||||
|
|
||||||
const insertElement = (target, element, mode = "appendChild") => {
|
const insertElement = (target, element, mode = "appendChild") => {
|
||||||
const elementId = element.id;
|
const elementId = element.id;
|
||||||
if (document.getElementById(elementId)) {
|
if (document.getElementById(elementId)) {
|
||||||
@@ -120,12 +143,12 @@
|
|||||||
const observer = new MutationObserver((_mutations) => {
|
const observer = new MutationObserver((_mutations) => {
|
||||||
if (!document.getElementById(elementId)) {
|
if (!document.getElementById(elementId)) {
|
||||||
let targetElement = document.querySelector(
|
let targetElement = document.querySelector(
|
||||||
modules[moduleKey].pageSelector
|
flatModules[moduleKey].pageSelector
|
||||||
);
|
);
|
||||||
if (
|
if (
|
||||||
targetElement &&
|
targetElement &&
|
||||||
modules[moduleKey].active &&
|
flatModules[moduleKey].active &&
|
||||||
modules[moduleKey].revive
|
flatModules[moduleKey].revive
|
||||||
) {
|
) {
|
||||||
if (!document.getElementById(elementId)) {
|
if (!document.getElementById(elementId)) {
|
||||||
console.log(
|
console.log(
|
||||||
@@ -145,12 +168,53 @@
|
|||||||
observers.set(moduleKey, observer);
|
observers.set(moduleKey, observer);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const loadResources = async (resources, type, moduleKey, isRevive) => {
|
||||||
|
if (!resources || isRevive) return [];
|
||||||
|
|
||||||
|
const resourceArray = Array.isArray(resources) ? resources : [resources];
|
||||||
|
const loadedResources = [];
|
||||||
|
|
||||||
|
for (const resource of resourceArray) {
|
||||||
|
try {
|
||||||
|
let element;
|
||||||
|
if (type === "css") {
|
||||||
|
element = document.createElement("link");
|
||||||
|
element.rel = "stylesheet";
|
||||||
|
element.href = `../../aura/${resource}`;
|
||||||
|
document.head.appendChild(element);
|
||||||
|
} else if (type === "js") {
|
||||||
|
element = document.createElement("script");
|
||||||
|
element.src = `../../aura/${resource}`;
|
||||||
|
document.body.appendChild(element);
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
element.onload = resolve;
|
||||||
|
element.onerror = reject;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element) {
|
||||||
|
loadedResources.push(element);
|
||||||
|
console.log(
|
||||||
|
`[HugoAura / UI / ${moduleKey}] Loaded ${type}: ${resource}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
`[HugoAura / UI / Error] Failed to load ${type} ${resource} for ${moduleKey}:`,
|
||||||
|
err
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadedResources;
|
||||||
|
};
|
||||||
|
|
||||||
const loader = {
|
const loader = {
|
||||||
async loadModule(moduleKey, isRevive = false) {
|
async loadModule(moduleKey, isRevive = false) {
|
||||||
if (!modules[moduleKey]?.active) return;
|
if (!flatModules[moduleKey]?.active) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const config = modules[moduleKey];
|
const config = flatModules[moduleKey];
|
||||||
const target = await waitForElement(config.pageSelector);
|
const target = await waitForElement(config.pageSelector);
|
||||||
const elementId = `aura-container-${moduleKey.replace(/\./g, "-")}`;
|
const elementId = `aura-container-${moduleKey.replace(/\./g, "-")}`;
|
||||||
|
|
||||||
@@ -168,12 +232,14 @@
|
|||||||
const resources = new Set();
|
const resources = new Set();
|
||||||
moduleResources.set(moduleKey, resources);
|
moduleResources.set(moduleKey, resources);
|
||||||
|
|
||||||
if (config.pageCSS && !isRevive) {
|
if (config.pageCSS) {
|
||||||
const link = document.createElement("link");
|
const cssResources = await loadResources(
|
||||||
link.rel = "stylesheet";
|
config.pageCSS,
|
||||||
link.href = `../../aura/${config.pageCSS}`;
|
"css",
|
||||||
document.head.appendChild(link);
|
moduleKey,
|
||||||
resources.add(link);
|
isRevive
|
||||||
|
);
|
||||||
|
cssResources.forEach((resource) => resources.add(resource));
|
||||||
}
|
}
|
||||||
|
|
||||||
const html = await fetch(`../../aura/${config.pageURI}`).then((r) =>
|
const html = await fetch(`../../aura/${config.pageURI}`).then((r) =>
|
||||||
@@ -184,18 +250,21 @@
|
|||||||
insertElement(target, container, config.selectorMode);
|
insertElement(target, container, config.selectorMode);
|
||||||
monitorParent(moduleKey, target, container, config.selectorMode);
|
monitorParent(moduleKey, target, container, config.selectorMode);
|
||||||
|
|
||||||
if (config.pageScript && !isRevive) {
|
if (config.pageScript) {
|
||||||
const script = document.createElement("script");
|
const jsResources = await loadResources(
|
||||||
script.src = `../../aura/${config.pageScript}`;
|
config.pageScript,
|
||||||
document.body.appendChild(script);
|
"js",
|
||||||
resources.add(script);
|
moduleKey,
|
||||||
|
isRevive
|
||||||
|
);
|
||||||
|
jsResources.forEach((resource) => resources.add(resource));
|
||||||
}
|
}
|
||||||
|
|
||||||
const observer = new MutationObserver(() => {
|
const observer = new MutationObserver(() => {
|
||||||
if (
|
if (
|
||||||
!document.contains(container) &&
|
!document.contains(container) &&
|
||||||
modules[moduleKey].active &&
|
flatModules[moduleKey].active &&
|
||||||
modules[moduleKey].revive
|
flatModules[moduleKey].revive
|
||||||
) {
|
) {
|
||||||
this.loadModule(moduleKey, true);
|
this.loadModule(moduleKey, true);
|
||||||
}
|
}
|
||||||
@@ -238,13 +307,13 @@
|
|||||||
|
|
||||||
handleModuleChange(moduleKey, path = []) {
|
handleModuleChange(moduleKey, path = []) {
|
||||||
const fullPath = [...path, moduleKey].join(".");
|
const fullPath = [...path, moduleKey].join(".");
|
||||||
if (path.length === 0 && modules[moduleKey].active) {
|
if (path.length === 0 && flatModules[moduleKey].active) {
|
||||||
this.loadModule(moduleKey);
|
this.loadModule(moduleKey);
|
||||||
} else if (path.length === 0) {
|
} else if (path.length === 0) {
|
||||||
this.unloadModule(moduleKey);
|
this.unloadModule(moduleKey);
|
||||||
} else {
|
} else {
|
||||||
if (moduleKey === "active") {
|
if (moduleKey === "active") {
|
||||||
if (modules[path[0]].active) {
|
if (flatModules[path[0]].active) {
|
||||||
this.loadModule(path[0]);
|
this.loadModule(path[0]);
|
||||||
} else {
|
} else {
|
||||||
this.unloadModule(path[0]);
|
this.unloadModule(path[0]);
|
||||||
@@ -297,7 +366,7 @@
|
|||||||
try {
|
try {
|
||||||
await loadGlobalJS();
|
await loadGlobalJS();
|
||||||
|
|
||||||
for (const [key, config] of Object.entries(modules)) {
|
for (const [key, config] of Object.entries(flatModules)) {
|
||||||
if (config.active) {
|
if (config.active) {
|
||||||
await loader.loadModule(key);
|
await loader.loadModule(key);
|
||||||
}
|
}
|
||||||
@@ -309,7 +378,7 @@
|
|||||||
|
|
||||||
initialLoad();
|
initialLoad();
|
||||||
|
|
||||||
return createDeepProxy(modules, (path, prop, value) => {
|
return createDeepProxy(accessibleModules, (path, prop, value) => {
|
||||||
loader.handleModuleChange(prop, path);
|
loader.handleModuleChange(prop, path);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class RendererHooksManager {
|
|||||||
|
|
||||||
const hooksPath = path.join(__dirname, "../../../aura/ui/hookDefinitions");
|
const hooksPath = path.join(__dirname, "../../../aura/ui/hookDefinitions");
|
||||||
|
|
||||||
/** @type {import("../../types/main/core").HooksMap} */
|
/** @type {import("../../types/main/core").UIHooksMap} */
|
||||||
const hooks = new Map();
|
const hooks = new Map();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -65,6 +65,7 @@ class RendererHooksManager {
|
|||||||
webContents.removeListener("destroyed", destroyedListener);
|
webContents.removeListener("destroyed", destroyedListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
global.__HUGO_AURA__.hookedWindows.delete(windowKey);
|
global.__HUGO_AURA__.hookedWindows.delete(windowKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,6 +81,7 @@ class RendererHooksManager {
|
|||||||
|
|
||||||
/** @type {import("../../types/main/core").WindowName} */
|
/** @type {import("../../types/main/core").WindowName} */
|
||||||
const windowKey = `${hookConfig.windowName || windowName}`;
|
const windowKey = `${hookConfig.windowName || windowName}`;
|
||||||
|
// @ts-expect-error
|
||||||
if (global.__HUGO_AURA__.hookedWindows.has(windowKey)) {
|
if (global.__HUGO_AURA__.hookedWindows.has(windowKey)) {
|
||||||
console.log(
|
console.log(
|
||||||
`[HugoAura / Init / RDH] Duplicate ui hook for ${windowKey}, ignoring...`
|
`[HugoAura / Init / RDH] Duplicate ui hook for ${windowKey}, ignoring...`
|
||||||
@@ -137,6 +139,7 @@ class RendererHooksManager {
|
|||||||
const destroyedListener = () => {
|
const destroyedListener = () => {
|
||||||
this.cleanupWindow(
|
this.cleanupWindow(
|
||||||
windowKey,
|
windowKey,
|
||||||
|
// @ts-expect-error
|
||||||
global.__HUGO_AURA__.hookedWindows.get(windowKey)
|
global.__HUGO_AURA__.hookedWindows.get(windowKey)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -144,6 +147,7 @@ class RendererHooksManager {
|
|||||||
webContents.on("dom-ready", domReadyListener);
|
webContents.on("dom-ready", domReadyListener);
|
||||||
webContents.on("destroyed", destroyedListener);
|
webContents.on("destroyed", destroyedListener);
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
global.__HUGO_AURA__.hookedWindows.set(windowKey, {
|
global.__HUGO_AURA__.hookedWindows.set(windowKey, {
|
||||||
webContents,
|
webContents,
|
||||||
domReadyListener,
|
domReadyListener,
|
||||||
|
|||||||
@@ -164,12 +164,12 @@ class ConfigManager {
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {Record<any, any>} config
|
* @param {Record<any, any>} config
|
||||||
* @returns {boolean}
|
* @returns {Promise<boolean>}
|
||||||
*/
|
*/
|
||||||
writeConfig(config) {
|
async writeConfig(config) {
|
||||||
try {
|
try {
|
||||||
if (this.useEncConfig) {
|
if (this.useEncConfig) {
|
||||||
const hashedPasswdResultObj = this.retrieveEncPassword();
|
const hashedPasswdResultObj = await this.retrieveEncPasswordAsync();
|
||||||
if (hashedPasswdResultObj.success && hashedPasswdResultObj.data) {
|
if (hashedPasswdResultObj.success && hashedPasswdResultObj.data) {
|
||||||
this.encryptConfig(config, hashedPasswdResultObj.data);
|
this.encryptConfig(config, hashedPasswdResultObj.data);
|
||||||
} else {
|
} else {
|
||||||
@@ -261,7 +261,7 @@ class ConfigManager {
|
|||||||
*
|
*
|
||||||
* @param {SHA256EncryptedPassword} password
|
* @param {SHA256EncryptedPassword} password
|
||||||
*/
|
*/
|
||||||
saveEncPassword(password) {
|
async saveEncPassword(password) {
|
||||||
let macAddr = this.priv_getMacAddr();
|
let macAddr = this.priv_getMacAddr();
|
||||||
let fallbackToStaticKey = false;
|
let fallbackToStaticKey = false;
|
||||||
|
|
||||||
@@ -290,25 +290,25 @@ class ConfigManager {
|
|||||||
const ivHex = iv.toString("hex");
|
const ivHex = iv.toString("hex");
|
||||||
const saltHex = randomSalt.toString("hex");
|
const saltHex = randomSalt.toString("hex");
|
||||||
|
|
||||||
registryManager.createOrUpdateRegKey(
|
await registryManager.createOrUpdateRegKey(
|
||||||
LMAK_SETTINGS_BASE,
|
LMAK_SETTINGS_BASE,
|
||||||
"LMAK_Value",
|
"LMAK_Value",
|
||||||
encryptedPassword,
|
encryptedPassword,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
registryManager.createOrUpdateRegKey(
|
await registryManager.createOrUpdateRegKey(
|
||||||
LMAK_SETTINGS_BASE,
|
LMAK_SETTINGS_BASE,
|
||||||
"LMAK_IV",
|
"LMAK_IV",
|
||||||
ivHex,
|
ivHex,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
registryManager.createOrUpdateRegKey(
|
await registryManager.createOrUpdateRegKey(
|
||||||
LMAK_SETTINGS_BASE,
|
LMAK_SETTINGS_BASE,
|
||||||
"LMAK_Salt",
|
"LMAK_Salt",
|
||||||
saltHex,
|
saltHex,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
registryManager.createOrUpdateRegKey(
|
await registryManager.createOrUpdateRegKey(
|
||||||
LMAK_SETTINGS_BASE,
|
LMAK_SETTINGS_BASE,
|
||||||
"LMAK_AuthTag",
|
"LMAK_AuthTag",
|
||||||
authTagHex,
|
authTagHex,
|
||||||
@@ -316,7 +316,7 @@ class ConfigManager {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (fallbackToStaticKey) {
|
if (fallbackToStaticKey) {
|
||||||
registryManager.createOrUpdateRegKey(
|
await registryManager.createOrUpdateRegKey(
|
||||||
LMAK_SETTINGS_BASE,
|
LMAK_SETTINGS_BASE,
|
||||||
"LMAK_FakeMac",
|
"LMAK_FakeMac",
|
||||||
macAddr,
|
macAddr,
|
||||||
@@ -329,22 +329,22 @@ class ConfigManager {
|
|||||||
|
|
||||||
retrieveEncPassword() {
|
retrieveEncPassword() {
|
||||||
try {
|
try {
|
||||||
const authTagHex = registryManager.readRegKey(
|
const authTagHex = registryManager.readRegKeySync(
|
||||||
LMAK_SETTINGS_BASE,
|
LMAK_SETTINGS_BASE,
|
||||||
"LMAK_AuthTag",
|
"LMAK_AuthTag",
|
||||||
true
|
true
|
||||||
)?.data;
|
)?.data;
|
||||||
const ivHex = registryManager.readRegKey(
|
const ivHex = registryManager.readRegKeySync(
|
||||||
LMAK_SETTINGS_BASE,
|
LMAK_SETTINGS_BASE,
|
||||||
"LMAK_IV",
|
"LMAK_IV",
|
||||||
true
|
true
|
||||||
)?.data;
|
)?.data;
|
||||||
const saltHex = registryManager.readRegKey(
|
const saltHex = registryManager.readRegKeySync(
|
||||||
LMAK_SETTINGS_BASE,
|
LMAK_SETTINGS_BASE,
|
||||||
"LMAK_Salt",
|
"LMAK_Salt",
|
||||||
true
|
true
|
||||||
)?.data;
|
)?.data;
|
||||||
const encPasswdHex = registryManager.readRegKey(
|
const encPasswdHex = registryManager.readRegKeySync(
|
||||||
LMAK_SETTINGS_BASE,
|
LMAK_SETTINGS_BASE,
|
||||||
"LMAK_Value",
|
"LMAK_Value",
|
||||||
true
|
true
|
||||||
@@ -353,7 +353,7 @@ class ConfigManager {
|
|||||||
let macAddr = null;
|
let macAddr = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
macAddr = registryManager.readRegKey(
|
macAddr = registryManager.readRegKeySync(
|
||||||
LMAK_SETTINGS_BASE,
|
LMAK_SETTINGS_BASE,
|
||||||
"LMAK_FakeMac",
|
"LMAK_FakeMac",
|
||||||
true
|
true
|
||||||
@@ -433,8 +433,112 @@ class ConfigManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clearEncPasswdRegKey() {
|
async retrieveEncPasswordAsync() {
|
||||||
registryManager.delRegKey(LMAK_SETTINGS_BASE, null);
|
try {
|
||||||
|
const authTagHex = (
|
||||||
|
await registryManager.readRegKey(
|
||||||
|
LMAK_SETTINGS_BASE,
|
||||||
|
"LMAK_AuthTag",
|
||||||
|
true
|
||||||
|
)
|
||||||
|
).data;
|
||||||
|
const ivHex = (
|
||||||
|
await registryManager.readRegKey(LMAK_SETTINGS_BASE, "LMAK_IV", true)
|
||||||
|
).data;
|
||||||
|
const saltHex = (
|
||||||
|
await registryManager.readRegKey(LMAK_SETTINGS_BASE, "LMAK_Salt", true)
|
||||||
|
).data;
|
||||||
|
const encPasswdHex = (
|
||||||
|
await registryManager.readRegKey(LMAK_SETTINGS_BASE, "LMAK_Value", true)
|
||||||
|
).data;
|
||||||
|
let isStaticKey = false;
|
||||||
|
let macAddr = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
macAddr = (
|
||||||
|
await registryManager.readRegKey(
|
||||||
|
LMAK_SETTINGS_BASE,
|
||||||
|
"LMAK_FakeMac",
|
||||||
|
true
|
||||||
|
)
|
||||||
|
).data;
|
||||||
|
if (!macAddr) {
|
||||||
|
isStaticKey = false;
|
||||||
|
} else {
|
||||||
|
isStaticKey = true;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
isStaticKey = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isStaticKey) {
|
||||||
|
macAddr = this.priv_getMacAddr();
|
||||||
|
|
||||||
|
if (!macAddr) {
|
||||||
|
console.error(
|
||||||
|
"[HugoAura / Config / ERROR] Failed to retrieve password from reg: MAC Address invalid."
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
data: null,
|
||||||
|
error: new Error("Mac is null or undefined"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!saltHex || !ivHex || !authTagHex || !encPasswdHex) {
|
||||||
|
console.error(
|
||||||
|
"[HugoAura / Config / ERROR] Failed to retrieve password from reg: Reg keys invalid."
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
data: null,
|
||||||
|
error: new Error("Reg key invalid"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const salt = Buffer.from(saltHex, "hex");
|
||||||
|
const iv = Buffer.from(ivHex, "hex");
|
||||||
|
const authTag = Buffer.from(authTagHex, "hex");
|
||||||
|
const encPasswd = Buffer.from(encPasswdHex, "utf-8").toString();
|
||||||
|
|
||||||
|
const key = crypto.scryptSync(macAddr, salt, 32);
|
||||||
|
const decipherIns = crypto.createDecipheriv(
|
||||||
|
CRYPTO_SETTINGS_AES.mode,
|
||||||
|
key,
|
||||||
|
iv,
|
||||||
|
{
|
||||||
|
// @ts-expect-error
|
||||||
|
authTagLength: CRYPTO_SETTINGS_AES.tagLength,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
decipherIns.setAuthTag(authTag);
|
||||||
|
|
||||||
|
const result = Buffer.concat([
|
||||||
|
decipherIns.update(encPasswd, "hex"),
|
||||||
|
decipherIns.final(),
|
||||||
|
]).toString();
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data: result,
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
console.error(
|
||||||
|
"[HugoAura / Config / ERROR] Unexpected error occurred while retrieving password from reg, error:",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
data: null,
|
||||||
|
error: e,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearEncPasswdRegKey() {
|
||||||
|
await registryManager.delRegKey(LMAK_SETTINGS_BASE, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -443,7 +547,7 @@ class ConfigManager {
|
|||||||
* @param {SHA256EncryptedPassword} passwd
|
* @param {SHA256EncryptedPassword} passwd
|
||||||
*/
|
*/
|
||||||
encryptConfig(configData, passwd) {
|
encryptConfig(configData, passwd) {
|
||||||
registryManager.initRegistry();
|
registryManager.initRegistrySync();
|
||||||
const salt = crypto.randomBytes(CRYPTO_SETTINGS_AES.saltLength);
|
const salt = crypto.randomBytes(CRYPTO_SETTINGS_AES.saltLength);
|
||||||
const key = crypto.pbkdf2Sync(
|
const key = crypto.pbkdf2Sync(
|
||||||
passwd,
|
passwd,
|
||||||
@@ -617,9 +721,9 @@ class ConfigManager {
|
|||||||
*
|
*
|
||||||
* @param {Record<any, any> | null} curConfig
|
* @param {Record<any, any> | null} curConfig
|
||||||
* @param {SHA256EncryptedPassword | undefined | null} passwd
|
* @param {SHA256EncryptedPassword | undefined | null} passwd
|
||||||
* @returns {{success: boolean}}
|
* @returns {Promise<{success: boolean}>}
|
||||||
*/
|
*/
|
||||||
switchToDecConfig(curConfig, passwd = null) {
|
async switchToDecConfig(curConfig, passwd = null) {
|
||||||
let decConfig = null;
|
let decConfig = null;
|
||||||
if (!curConfig && passwd) {
|
if (!curConfig && passwd) {
|
||||||
const getDecConfigResult = this.decryptConfig(passwd);
|
const getDecConfigResult = this.decryptConfig(passwd);
|
||||||
@@ -639,7 +743,7 @@ class ConfigManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.useEncConfig = false;
|
this.useEncConfig = false;
|
||||||
this.clearEncPasswdRegKey();
|
await this.clearEncPasswdRegKey();
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
this.writeConfig(curConfig ? curConfig : decConfig);
|
this.writeConfig(curConfig ? curConfig : decConfig);
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,20 +1,52 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
const childProc = require("child_process");
|
const { exec, execSync } = require("child_process");
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
|
|
||||||
const LOG_PREFIX = "[HugoAura / Init / Reg";
|
const LOG_PREFIX = "[HugoAura / Init / Reg";
|
||||||
const LOG_PREFIX_FUNC = "[HugoAura / Reg";
|
const LOG_PREFIX_FUNC = "[HugoAura / Reg";
|
||||||
const AURA_REGISTRY_PATH = ["HKCU", "SOFTWARE", "HugoAura"].join("\\");
|
const AURA_REGISTRY_PATH = ["HKEY_USERS", ".DEFAULT", "SOFTWARE", "HugoAura"].join("\\");
|
||||||
|
|
||||||
class RegistryManager {
|
class RegistryManager {
|
||||||
/**
|
/**
|
||||||
* @param {string} [path]
|
* @param {string} [path]
|
||||||
|
* @returns {Promise<boolean>}
|
||||||
*/
|
*/
|
||||||
handleCreateReg(path) {
|
async handleCreateReg(path) {
|
||||||
try {
|
try {
|
||||||
const createResult = childProc.execSync(["reg", "add", path].join(" "), {
|
const { stdout } = await new Promise((resolve, reject) => {
|
||||||
|
exec(
|
||||||
|
["reg", "add", path].join(" "),
|
||||||
|
{ encoding: "utf8" },
|
||||||
|
(error, stdout, stderr) => {
|
||||||
|
if (error) reject(error);
|
||||||
|
else resolve({ stdout, stderr });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`${LOG_PREFIX} / SUCCESS] Registry path ${path} successfully created.`
|
||||||
|
);
|
||||||
|
console.debug(`${LOG_PREFIX} / DEBUG] Reg add command stdout:`, stdout);
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(
|
||||||
|
`${LOG_PREFIX} / ERROR] Failed creating registry path, error:`,
|
||||||
|
e
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} [path]
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
handleCreateRegSync(path) {
|
||||||
|
try {
|
||||||
|
const createResult = execSync(["reg", "add", path].join(" "), {
|
||||||
encoding: "utf8",
|
encoding: "utf8",
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -27,6 +59,8 @@ class RegistryManager {
|
|||||||
createResult
|
createResult
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(
|
console.error(
|
||||||
@@ -37,9 +71,37 @@ class RegistryManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
initRegistry() {
|
/**
|
||||||
|
* @returns {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
async initRegistry() {
|
||||||
try {
|
try {
|
||||||
const queryResult = childProc.execSync(
|
const { stdout } = await new Promise((resolve, reject) => {
|
||||||
|
exec(
|
||||||
|
["reg", "query", AURA_REGISTRY_PATH].join(" "),
|
||||||
|
{ encoding: "utf8" },
|
||||||
|
(error, stdout, stderr) => {
|
||||||
|
if (error) reject(error);
|
||||||
|
else resolve({ stdout, stderr });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`${LOG_PREFIX}] Registry check up success.`);
|
||||||
|
console.debug(`${LOG_PREFIX}] Command stdout:`, stdout);
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(`${LOG_PREFIX} / WARN] Failed to query registry, error:`, e);
|
||||||
|
return await this.handleCreateReg(AURA_REGISTRY_PATH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
initRegistrySync() {
|
||||||
|
try {
|
||||||
|
const queryResult = execSync(
|
||||||
["reg", "query", AURA_REGISTRY_PATH].join(" "),
|
["reg", "query", AURA_REGISTRY_PATH].join(" "),
|
||||||
{ encoding: "utf8" }
|
{ encoding: "utf8" }
|
||||||
);
|
);
|
||||||
@@ -48,23 +110,81 @@ class RegistryManager {
|
|||||||
console.log(`${LOG_PREFIX}] Registry check up success.`);
|
console.log(`${LOG_PREFIX}] Registry check up success.`);
|
||||||
console.debug(`${LOG_PREFIX}] Command stdout:`, queryResult);
|
console.debug(`${LOG_PREFIX}] Command stdout:`, queryResult);
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn(`${LOG_PREFIX} / WARN] Failed to query registry, error:`, e);
|
console.warn(`${LOG_PREFIX} / WARN] Failed to query registry, error:`, e);
|
||||||
return this.handleCreateReg(AURA_REGISTRY_PATH);
|
return this.handleCreateRegSync(AURA_REGISTRY_PATH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param {string} relativePath
|
* @param {string} relativePath
|
||||||
* @param {string} keyName
|
* @param {string} keyName
|
||||||
* @param {string} keyVal
|
* @param {string} keyVal
|
||||||
* @param {boolean | undefined} silent
|
* @param {boolean | undefined} silent
|
||||||
|
* @returns {Promise<{ success: boolean, error: Error | null }>}
|
||||||
*/
|
*/
|
||||||
createOrUpdateRegKey(relativePath, keyName, keyVal, silent = false) {
|
async createOrUpdateRegKey(relativePath, keyName, keyVal, silent = false) {
|
||||||
try {
|
try {
|
||||||
const result = childProc.execSync(
|
const { stdout } = await new Promise((resolve, reject) => {
|
||||||
|
exec(
|
||||||
|
[
|
||||||
|
"reg",
|
||||||
|
"add",
|
||||||
|
[AURA_REGISTRY_PATH, relativePath].join("\\"),
|
||||||
|
"/v",
|
||||||
|
keyName,
|
||||||
|
"/t",
|
||||||
|
"REG_SZ",
|
||||||
|
"/d",
|
||||||
|
`\"${keyVal}\"`,
|
||||||
|
"/f",
|
||||||
|
].join(" "),
|
||||||
|
{ encoding: "utf8" },
|
||||||
|
(error, stdout, stderr) => {
|
||||||
|
if (error) reject(error);
|
||||||
|
else resolve({ stdout, stderr });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!silent) {
|
||||||
|
console.debug(
|
||||||
|
`${LOG_PREFIX_FUNC} / SUCCESS] Successfully created / updated reg key ${relativePath}/${keyName} with data: ${keyVal}`
|
||||||
|
);
|
||||||
|
console.debug(
|
||||||
|
`${LOG_PREFIX_FUNC} / SUCCESS] Add key command stdout:`,
|
||||||
|
stdout
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
console.error(
|
||||||
|
`${LOG_PREFIX_FUNC} / ERROR] Failed to create / update reg key, error:`,
|
||||||
|
silent ? "<Hidden>" : e
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: e,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} relativePath
|
||||||
|
* @param {string} keyName
|
||||||
|
* @param {string} keyVal
|
||||||
|
* @param {boolean | undefined} silent
|
||||||
|
* @returns {{ success: boolean, error: Error | null }}
|
||||||
|
*/
|
||||||
|
createOrUpdateRegKeySync(relativePath, keyName, keyVal, silent = false) {
|
||||||
|
try {
|
||||||
|
const result = execSync(
|
||||||
[
|
[
|
||||||
"reg",
|
"reg",
|
||||||
"add",
|
"add",
|
||||||
@@ -83,21 +203,76 @@ class RegistryManager {
|
|||||||
if (result) {
|
if (result) {
|
||||||
if (!silent) {
|
if (!silent) {
|
||||||
console.debug(
|
console.debug(
|
||||||
`${LOG_PREFIX_FUNC} / SUCCESS] Successfully created / updated reg key ${relativePath}/${keyName} with data: ${keyVal}`
|
`${LOG_PREFIX} / SUCCESS] Successfully created / updated reg key ${relativePath}/${keyName} with data: ${keyVal}`,
|
||||||
);
|
|
||||||
console.debug(
|
|
||||||
`${LOG_PREFIX_FUNC} / SUCCESS] Add key command stdout:`,
|
|
||||||
result
|
result
|
||||||
);
|
);
|
||||||
|
console.error("");
|
||||||
}
|
}
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
error: null,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(
|
console.error(
|
||||||
`${LOG_PREFIX_FUNC} / ERROR] Failed to create / update reg key, error:`,
|
`${LOG_PREFIX_FUNC} / ERROR] Failed to create / update reg key error:`,
|
||||||
|
e
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: e,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} relativePath
|
||||||
|
* @param {string | null} keyName
|
||||||
|
* @param {boolean | undefined} silent
|
||||||
|
* @returns {Promise<{ success: boolean, error: Error | null }>}
|
||||||
|
*/
|
||||||
|
async delRegKey(relativePath, keyName, silent = false) {
|
||||||
|
if (keyName === undefined) {
|
||||||
|
throw new Error(
|
||||||
|
`${LOG_PREFIX_FUNC} / CRITICAL] Arg \"keyName\" for function \"delRegKey\" cannot be undefined. Only null or null accepted.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { stdout } = await new Promise((resolve, reject) => {
|
||||||
|
exec(
|
||||||
|
[
|
||||||
|
"reg",
|
||||||
|
"delete",
|
||||||
|
[AURA_REGISTRY_PATH, relativePath].join("\\"),
|
||||||
|
keyName ? "/v" : "",
|
||||||
|
keyName ? keyName : "",
|
||||||
|
"/f",
|
||||||
|
].join(" "),
|
||||||
|
{ encoding: "utf8" },
|
||||||
|
(error, stdout, stderr) => {
|
||||||
|
if (error) reject(error);
|
||||||
|
else resolve({ stdout, stderr });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!silent) {
|
||||||
|
console.debug(
|
||||||
|
`${LOG_PREFIX_FUNC} / SUCCESS] Successfully deleted reg key ${relativePath}/${keyName}`
|
||||||
|
);
|
||||||
|
console.debug(
|
||||||
|
`${LOG_PREFIX_FUNC} / SUCCESS] Delete key command stdout:`,
|
||||||
|
stdout
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
console.error(
|
||||||
|
`${LOG_PREFIX_FUNC} / ERROR] Failed to delete reg key, error:`,
|
||||||
silent ? "<Hidden>" : e
|
silent ? "<Hidden>" : e
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
@@ -107,24 +282,21 @@ class RegistryManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*>>> BUC <<<
|
|
||||||
keyName === null --> delete the whole entry
|
|
||||||
>>> EUC <<<*/
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param {string} relativePath
|
* @param {string} relativePath
|
||||||
* @param {string | null} keyName
|
* @param {string | null} keyName
|
||||||
* @param {boolean | undefined} silent
|
* @param {boolean | undefined} silent
|
||||||
|
* @returns {{ success: boolean, error: Error | null }}
|
||||||
*/
|
*/
|
||||||
delRegKey(relativePath, keyName, silent = false) {
|
delRegKeySync(relativePath, keyName, silent = false) {
|
||||||
if (keyName === undefined) {
|
if (keyName === undefined) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`${LOG_PREFIX_FUNC} / CRITICAL] Arg \"keyName\" for function \"delRegKey\" cannot be undefined. Only null or string accepted.`
|
`${LOG_PREFIX_FUNC} / CRITICAL] Arg \"keyName\" for function \"delRegKeySync\" cannot be undefined. Only null or string accepted.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = childProc.execSync(
|
const result = execSync(
|
||||||
[
|
[
|
||||||
"reg",
|
"reg",
|
||||||
"delete",
|
"delete",
|
||||||
@@ -150,6 +322,11 @@ class RegistryManager {
|
|||||||
success: true,
|
success: true,
|
||||||
error: null,
|
error: null,
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(
|
console.error(
|
||||||
@@ -164,14 +341,76 @@ class RegistryManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param {string} relativePath
|
* @param {string} relativePath
|
||||||
* @param {string} keyName
|
* @param {string} keyName
|
||||||
* @param {boolean | undefined} silent
|
* @param {boolean | undefined} silent
|
||||||
|
* @returns {Promise<{ success: boolean, data: string | null, error: Error | null }>}
|
||||||
*/
|
*/
|
||||||
readRegKey(relativePath, keyName, silent = false) {
|
async readRegKey(relativePath, keyName, silent = false) {
|
||||||
try {
|
try {
|
||||||
const readResult = childProc.execSync(
|
const { stdout } = await new Promise((resolve, reject) => {
|
||||||
|
exec(
|
||||||
|
[
|
||||||
|
"reg",
|
||||||
|
"query",
|
||||||
|
[AURA_REGISTRY_PATH, relativePath].join("\\"),
|
||||||
|
"/v",
|
||||||
|
`\"${keyName}\"`,
|
||||||
|
].join(" "),
|
||||||
|
{ encoding: "utf8" },
|
||||||
|
(error, stdout, stderr) => {
|
||||||
|
if (error) reject(error);
|
||||||
|
else resolve({ stdout, stderr });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!silent) {
|
||||||
|
console.debug(
|
||||||
|
`${LOG_PREFIX_FUNC} / SUCCESS] Successfully read reg key ${relativePath}/${keyName}, stdout:`,
|
||||||
|
stdout
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const match = stdout.match(/REG_SZ\s+(.+)/);
|
||||||
|
|
||||||
|
if (!match) {
|
||||||
|
console.warn(`${LOG_PREFIX} / WARN] Data not found in stdout`);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
data: null,
|
||||||
|
error: new Error("Data not found"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = match[1].trim();
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data,
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
console.error(
|
||||||
|
`${LOG_PREFIX} / ERROR] Failed to read reg key, error:`,
|
||||||
|
e
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
data: null,
|
||||||
|
error: e,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} relativePath
|
||||||
|
* @param {string} keyName
|
||||||
|
* @param {boolean | undefined} silent
|
||||||
|
* @returns {{ success: boolean, data: string | null, error: Error | null }}
|
||||||
|
*/
|
||||||
|
readRegKeySync(relativePath, keyName, silent = false) {
|
||||||
|
try {
|
||||||
|
const readResult = execSync(
|
||||||
[
|
[
|
||||||
"reg",
|
"reg",
|
||||||
"query",
|
"query",
|
||||||
@@ -185,14 +424,14 @@ class RegistryManager {
|
|||||||
if (readResult) {
|
if (readResult) {
|
||||||
if (!silent) {
|
if (!silent) {
|
||||||
console.debug(
|
console.debug(
|
||||||
`${LOG_PREFIX}] Successfully read reg key ${relativePath}/${keyName}, stdout:`,
|
`${LOG_PREFIX_FUNC} / SUCCESS] Successfully read reg key ${relativePath}/${keyName}, stdout:`,
|
||||||
readResult
|
readResult
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const match = readResult.match(/REG_SZ\s+(.+)/);
|
const match = readResult.match(/REG_SZ\s+(.+)/);
|
||||||
|
|
||||||
if (!match) {
|
if (!match) {
|
||||||
console.warn(`${LOG_PREFIX_FUNC} / WARN] Data not found in stdout`);
|
console.warn(`${LOG_PREFIX} / WARN] Data not found in stdout`);
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
data: null,
|
data: null,
|
||||||
@@ -206,10 +445,16 @@ class RegistryManager {
|
|||||||
data,
|
data,
|
||||||
error: null,
|
error: null,
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
data: null,
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(
|
console.error(
|
||||||
`${LOG_PREFIX_FUNC} / ERROR] Failed to read reg key, error:`,
|
`${LOG_PREFIX} / ERROR] Failed to read reg key, error:`,
|
||||||
silent ? "<Hidden>" : e
|
silent ? "<Hidden>" : e
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
|
|||||||
21
src/aura/types/main/ipc/fs.d.ts
vendored
Executable file
21
src/aura/types/main/ipc/fs.d.ts
vendored
Executable file
@@ -0,0 +1,21 @@
|
|||||||
|
type DownloadTaskID = string;
|
||||||
|
type DownloadTaskStatus = "waiting" | "progressing" | "done" | "failed" | "cancelled";
|
||||||
|
|
||||||
|
interface DownloadTask {
|
||||||
|
id: DownloadTaskID;
|
||||||
|
progress: float;
|
||||||
|
curBytes?: number;
|
||||||
|
totalBytes?: number;
|
||||||
|
status: DownloadTaskStatus;
|
||||||
|
dlUrl: string | null;
|
||||||
|
savePath: string | null;
|
||||||
|
message?: string;
|
||||||
|
errorObj?: Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FSTasks {
|
||||||
|
downloadTasks: Map<
|
||||||
|
DownloadTaskID,
|
||||||
|
{ status: DownloadTaskStatus; cancelReq: any }
|
||||||
|
>;
|
||||||
|
}
|
||||||
13
src/aura/types/render/uiHook.d.ts
vendored
13
src/aura/types/render/uiHook.d.ts
vendored
@@ -1,12 +1,13 @@
|
|||||||
import { WindowName } from "../main/core";
|
import { WindowName } from "../main/core";
|
||||||
|
|
||||||
interface UIHookTarget {
|
interface UIHookTarget {
|
||||||
active: boolean;
|
active?: boolean;
|
||||||
pageURI: string;
|
pageURI?: string;
|
||||||
pageScript: string;
|
pageScript?: string;
|
||||||
pageSelector: string;
|
pageSelector?: string;
|
||||||
selectorMode: "insertAfter" | "insertBefore" | "appendChild";
|
selectorMode?: "insertAfter" | "insertBefore" | "appendChild";
|
||||||
pageCSS: string;
|
pageCSS?: string;
|
||||||
|
childs?: Record<AuraElementUID, UIHookTarget>;
|
||||||
revive?: boolean;
|
revive?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
9
src/aura/types/shared/global.d.ts
vendored
9
src/aura/types/shared/global.d.ts
vendored
@@ -11,6 +11,7 @@ type RendererProcessOnlyVal<T> = T;
|
|||||||
interface GlobalHugoAuraInfo {
|
interface GlobalHugoAuraInfo {
|
||||||
central?: MainProcessOnlyVal<(...args: any) => any>;
|
central?: MainProcessOnlyVal<(...args: any) => any>;
|
||||||
configInit: boolean;
|
configInit: boolean;
|
||||||
|
fsTasks?: MainProcessOnlyVal<FSTasks>;
|
||||||
hookedWindows?: MainProcessOnlyVal<HookedWindowsMap>;
|
hookedWindows?: MainProcessOnlyVal<HookedWindowsMap>;
|
||||||
ipcInit?: MainProcessOnlyVal<boolean>;
|
ipcInit?: MainProcessOnlyVal<boolean>;
|
||||||
plsRules?: Record<any, any> | null;
|
plsRules?: Record<any, any> | null;
|
||||||
@@ -22,11 +23,19 @@ interface GlobalHugoAuraInfo {
|
|||||||
version: RendererProcessOnlyVal<string>;
|
version: RendererProcessOnlyVal<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface GlobalHugoAuraApiInfo {
|
||||||
|
baseUrl: string;
|
||||||
|
plsUpdate: string;
|
||||||
|
auraUpdate: string;
|
||||||
|
}
|
||||||
|
|
||||||
type GlobalHugoAuraConfig = AuraConfig;
|
type GlobalHugoAuraConfig = AuraConfig;
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
var ipcRenderer: RendererProcessOnlyVal<IpcRenderer>;
|
var ipcRenderer: RendererProcessOnlyVal<IpcRenderer>;
|
||||||
|
var _ACCEPT_DATA: any;
|
||||||
var __HUGO_AURA__: GlobalHugoAuraInfo;
|
var __HUGO_AURA__: GlobalHugoAuraInfo;
|
||||||
|
var __HUGO_AURA_API__: GlobalHugoAuraApiInfo;
|
||||||
var __HUGO_AURA_CONFIG__: GlobalHugoAuraConfig;
|
var __HUGO_AURA_CONFIG__: GlobalHugoAuraConfig;
|
||||||
var __HUGO_AURA_CONFIG_MGR__: ConfigManager;
|
var __HUGO_AURA_CONFIG_MGR__: ConfigManager;
|
||||||
var __HUGO_AURA_EVENT_BUS__: EventBus;
|
var __HUGO_AURA_EVENT_BUS__: EventBus;
|
||||||
|
|||||||
4
src/aura/types/shared/pls/status.d.ts
vendored
4
src/aura/types/shared/pls/status.d.ts
vendored
@@ -9,3 +9,7 @@ interface PLSStatus {
|
|||||||
version: string;
|
version: string;
|
||||||
authToken: string;
|
authToken: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PLSLifecycleType = "isDetached" | "isSvcInstalled" | "isSvcStart";
|
||||||
|
|
||||||
|
type PLSLifecycleControlType = "instSvc" | "rmSvc" | "startSvc" | "stopSvc" | "rmBin" | "dlBin";
|
||||||
|
|||||||
@@ -28,18 +28,7 @@ const updatePlsRulesFromLocal = async () => {
|
|||||||
return plsRules;
|
return plsRules;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
const { genRandomHex } = require("../../utils/crypto");
|
||||||
*
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
const genRandomHex = () => {
|
|
||||||
let result = "";
|
|
||||||
for (let i = 0; i < 8; i++) {
|
|
||||||
const randomNum = Math.floor(Math.random() * 0x10000);
|
|
||||||
result += randomNum.toString(16).padStart(4, "0");
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -48,24 +37,22 @@ const genRandomHex = () => {
|
|||||||
*/
|
*/
|
||||||
const updatePlsConfigToRemote = async (configKey, configValue) => {
|
const updatePlsConfigToRemote = async (configKey, configValue) => {
|
||||||
const configLevels = configKey.split(".");
|
const configLevels = configKey.split(".");
|
||||||
/** @type {Record<any, any>} */
|
|
||||||
// @ts-expect-error
|
|
||||||
let localUpdateTarget =
|
|
||||||
configLevels[0] === "ruleSettings"
|
|
||||||
? global.__HUGO_AURA__.plsRules
|
|
||||||
: global.__HUGO_AURA__.plsSettings;
|
|
||||||
for (const level of configLevels.slice(0, -1)) {
|
|
||||||
localUpdateTarget = localUpdateTarget[level];
|
|
||||||
}
|
|
||||||
localUpdateTarget[configLevels.slice(-1)[0]] = configValue;
|
|
||||||
|
|
||||||
const plsConfigUpdateEvent = new CustomEvent("onPLSConfigUpdate", {
|
const plsConfigUpdateEvent = new CustomEvent("onPLSConfigUpdate", {
|
||||||
detail: {
|
detail: {
|
||||||
path: configKey,
|
path: configLevels,
|
||||||
value: configValue,
|
value: configValue,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
document.dispatchEvent(plsConfigUpdateEvent);
|
document.dispatchEvent(plsConfigUpdateEvent);
|
||||||
|
const settingsEntries = document.getElementsByClassName(
|
||||||
|
"aura-settings-entry"
|
||||||
|
);
|
||||||
|
if (settingsEntries.length > 0) {
|
||||||
|
Array.from(settingsEntries).forEach((entry) => {
|
||||||
|
entry.dispatchEvent(plsConfigUpdateEvent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {ClientPLSRequest}
|
* @type {ClientPLSRequest}
|
||||||
|
|||||||
@@ -36,12 +36,331 @@ const showToast = (entry) => {
|
|||||||
showReloadToast();
|
showReloadToast();
|
||||||
} else if (entry.restart) {
|
} else if (entry.restart) {
|
||||||
showRelaunchToast();
|
showRelaunchToast();
|
||||||
} else if (entry.restartPLS) {
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
else if (entry.restartPLS) {
|
||||||
showRelaunchPLSToast();
|
showRelaunchPLSToast();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
const insertOrRemoveEl = (parent, child, isInsert = true) => {
|
||||||
|
if (Array.isArray(child)) {
|
||||||
|
for (const perEl of child) {
|
||||||
|
isInsert ? parent.appendChild(perEl) : parent.removeChild(perEl);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isInsert ? parent.appendChild(child) : parent.removeChild(child);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const settingsRenderer = (pendingEl, settingsObj, isPls = false) => {
|
const createOnLeaveEvtListener =
|
||||||
|
global.__HUGO_AURA_GLOBAL__.utils.createOnLeaveEvtListener;
|
||||||
|
|
||||||
|
const renderInputArea = (entry, operationArea, descriptionArea) => {
|
||||||
|
switch (entry.type) {
|
||||||
|
case "switch": {
|
||||||
|
const switchEl = document.createElement("input");
|
||||||
|
switchEl.classList.add("form-check-input");
|
||||||
|
switchEl.type = "checkbox";
|
||||||
|
switchEl.role = "switch";
|
||||||
|
switchEl.id = entry.id;
|
||||||
|
const elValue = entry.valueGetter();
|
||||||
|
switchEl.value = elValue;
|
||||||
|
switchEl.checked = elValue;
|
||||||
|
switchEl.addEventListener("change", async (event) => {
|
||||||
|
showToast(entry);
|
||||||
|
await entry.callbackFn(event.target.checked);
|
||||||
|
});
|
||||||
|
operationArea.classList.add("form-check", "form-switch");
|
||||||
|
return switchEl;
|
||||||
|
}
|
||||||
|
case "radio": {
|
||||||
|
const elValue = entry.valueGetter();
|
||||||
|
const elArr = [];
|
||||||
|
for (const template of entry.templates) {
|
||||||
|
const inlineContainerEl = document.createElement("div");
|
||||||
|
inlineContainerEl.classList.add("form-check", "form-check-inline");
|
||||||
|
const radioEl = document.createElement("input");
|
||||||
|
radioEl.value = template;
|
||||||
|
radioEl.classList.add("form-check-input");
|
||||||
|
radioEl.type = "radio";
|
||||||
|
radioEl.name = `${entry.id}Radios`;
|
||||||
|
radioEl.id = `${entry.id}Radio${entry.templates.indexOf(template)}`;
|
||||||
|
radioEl.checked = template === elValue ? true : false;
|
||||||
|
radioEl.addEventListener("change", async (event) => {
|
||||||
|
if (event.target.checked) {
|
||||||
|
showToast(entry);
|
||||||
|
await entry.callbackFn(event.target.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
inlineContainerEl.appendChild(radioEl);
|
||||||
|
const labelEl = document.createElement("label");
|
||||||
|
labelEl.classList.add("form-check-label");
|
||||||
|
labelEl.setAttribute("for", radioEl.id);
|
||||||
|
labelEl.textContent =
|
||||||
|
entry.templateLabels[entry.templates.indexOf(template)];
|
||||||
|
inlineContainerEl.appendChild(labelEl);
|
||||||
|
elArr.push(inlineContainerEl);
|
||||||
|
}
|
||||||
|
return elArr;
|
||||||
|
}
|
||||||
|
case "input": {
|
||||||
|
const inputEl = document.createElement("input");
|
||||||
|
inputEl.classList.add("form-control");
|
||||||
|
inputEl.type = entry.subType;
|
||||||
|
inputEl.value = entry.valueGetter();
|
||||||
|
inputEl.placeholder = entry.placeHolder;
|
||||||
|
inputEl.id = entry.id;
|
||||||
|
inputEl.addEventListener("change", async (event) => {
|
||||||
|
const result = await entry.callbackFn(event.target.value);
|
||||||
|
const success = result.valid;
|
||||||
|
if (success) {
|
||||||
|
showToast(entry);
|
||||||
|
|
||||||
|
if (inputEl.className.includes("is-invalid")) {
|
||||||
|
inputEl.classList.remove("is-invalid");
|
||||||
|
descriptionArea.textContent = entry.description;
|
||||||
|
descriptionArea.classList.remove("ase-desc-error-hint");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
inputEl.classList.add("is-invalid");
|
||||||
|
descriptionArea.textContent = result.hint;
|
||||||
|
descriptionArea.classList.add("ase-desc-error-hint");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
operationArea.classList.add("ase-operation-area-expanded");
|
||||||
|
return inputEl;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderNormalSettingsItem = (entry, formEl) => {
|
||||||
|
const entryContainerEl = document.createElement("div");
|
||||||
|
entryContainerEl.classList.add("aura-settings-entry");
|
||||||
|
entryContainerEl.id = `${entry.id}Container`;
|
||||||
|
|
||||||
|
const entryInfoContainerEl = document.createElement("div");
|
||||||
|
entryInfoContainerEl.classList.add("aura-settings-entry-info-container");
|
||||||
|
const entryTitle = document.createElement("p");
|
||||||
|
entryTitle.classList.add("aura-settings-entry-title");
|
||||||
|
entryTitle.textContent = entry.name;
|
||||||
|
if (entry.restart) {
|
||||||
|
const powerIcon = document.createElement("i");
|
||||||
|
powerIcon.classList.add(
|
||||||
|
"layui-icon",
|
||||||
|
"layui-icon-logout",
|
||||||
|
"aura-settings-entry-property-icon"
|
||||||
|
);
|
||||||
|
powerIcon.setAttribute("data-bs-toggle", "tooltip");
|
||||||
|
powerIcon.setAttribute("data-bs-placement", "top");
|
||||||
|
powerIcon.setAttribute("data-bs-title", "需要重启 Electron 进程");
|
||||||
|
entryTitle.appendChild(powerIcon);
|
||||||
|
}
|
||||||
|
if (entry.PLSRequired) {
|
||||||
|
const plsIcon = document.createElement("i");
|
||||||
|
plsIcon.classList.add(
|
||||||
|
"layui-icon",
|
||||||
|
"layui-icon-component",
|
||||||
|
"aura-settings-entry-property-icon"
|
||||||
|
);
|
||||||
|
plsIcon.setAttribute("data-bs-toggle", "tooltip");
|
||||||
|
plsIcon.setAttribute("data-bs-placement", "top");
|
||||||
|
plsIcon.setAttribute("data-bs-title", "需要 PLS 支持");
|
||||||
|
entryTitle.appendChild(plsIcon);
|
||||||
|
}
|
||||||
|
if (entry.restartPLS) {
|
||||||
|
const plsIcon = document.createElement("i");
|
||||||
|
plsIcon.classList.add(
|
||||||
|
"layui-icon",
|
||||||
|
"layui-icon-logout",
|
||||||
|
"aura-settings-entry-property-icon"
|
||||||
|
);
|
||||||
|
plsIcon.setAttribute("data-bs-toggle", "tooltip");
|
||||||
|
plsIcon.setAttribute("data-bs-placement", "top");
|
||||||
|
plsIcon.setAttribute("data-bs-title", "需要重启 PLS 进程");
|
||||||
|
entryTitle.appendChild(plsIcon);
|
||||||
|
}
|
||||||
|
if (entry.reload) {
|
||||||
|
const reloadIcon = document.createElement("i");
|
||||||
|
reloadIcon.classList.add(
|
||||||
|
"layui-icon",
|
||||||
|
"layui-icon-refresh",
|
||||||
|
"aura-settings-entry-property-icon"
|
||||||
|
);
|
||||||
|
reloadIcon.setAttribute("data-bs-toggle", "tooltip");
|
||||||
|
reloadIcon.setAttribute("data-bs-placement", "top");
|
||||||
|
reloadIcon.setAttribute("data-bs-title", "需要重载页面");
|
||||||
|
entryTitle.appendChild(reloadIcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
const createToolTipIcon = (type, content) => {
|
||||||
|
const tipIcon = document.createElement("i");
|
||||||
|
tipIcon.classList.add(
|
||||||
|
"layui-icon",
|
||||||
|
"layui-icon-tips",
|
||||||
|
"aura-settings-entry-property-icon"
|
||||||
|
);
|
||||||
|
if (type === "warning") {
|
||||||
|
tipIcon.classList.add("aura-settings-entry-warning-icon");
|
||||||
|
}
|
||||||
|
tipIcon.setAttribute("data-bs-toggle", "tooltip");
|
||||||
|
tipIcon.setAttribute("data-bs-placement", "top");
|
||||||
|
tipIcon.setAttribute("data-bs-title", content);
|
||||||
|
entryTitle.appendChild(tipIcon);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (entry.tip) {
|
||||||
|
createToolTipIcon("tip", entry.tipTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry.warning) {
|
||||||
|
createToolTipIcon("warning", entry.warningContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
const entryDescription = document.createElement("p");
|
||||||
|
entryDescription.classList.add("aura-settings-entry-desc");
|
||||||
|
entryDescription.innerHTML = entry.description;
|
||||||
|
entryInfoContainerEl.appendChild(entryTitle);
|
||||||
|
entryInfoContainerEl.appendChild(entryDescription);
|
||||||
|
|
||||||
|
entryContainerEl.appendChild(entryInfoContainerEl);
|
||||||
|
|
||||||
|
const entryOperationArea = document.createElement("div");
|
||||||
|
entryOperationArea.classList.add("aura-settings-entry-operation-area");
|
||||||
|
|
||||||
|
let targetEl = renderInputArea(entry, entryOperationArea, entryDescription);
|
||||||
|
insertOrRemoveEl(entryOperationArea, targetEl, true);
|
||||||
|
|
||||||
|
if (entry.reactive) {
|
||||||
|
const evtListener = (event) => {
|
||||||
|
if (entry.reactiveVal.includes(event.detail.path.join("."))) {
|
||||||
|
insertOrRemoveEl(entryOperationArea, targetEl, false);
|
||||||
|
targetEl = renderInputArea(entry, entryOperationArea, entryDescription);
|
||||||
|
insertOrRemoveEl(entryOperationArea, targetEl, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const channel = entry.PLSRequired
|
||||||
|
? "onPLSConfigUpdate"
|
||||||
|
: "onHugoAuraConfigUpdate";
|
||||||
|
entryContainerEl.addEventListener(channel, evtListener);
|
||||||
|
// createOnLeaveEvtListener(channel, evtListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
const setDisableStatus = (el, isDisable, hint = null) => {
|
||||||
|
if (isDisable) {
|
||||||
|
el.classList.add("ase-operation-area-disabled");
|
||||||
|
if (hint) {
|
||||||
|
el.setAttribute("data-bs-toggle", "tooltip");
|
||||||
|
el.setAttribute("data-bs-placement", "top");
|
||||||
|
el.setAttribute("data-bs-title", hint);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
el.setAttribute("data-bs-toggle", "");
|
||||||
|
el.setAttribute("data-bs-placement", "");
|
||||||
|
el.setAttribute("data-bs-title", "");
|
||||||
|
el.classList.remove("ase-operation-area-disabled");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (entry.PLSRequired) {
|
||||||
|
if (!global.__HUGO_AURA__.plsStats.connected) {
|
||||||
|
setDisableStatus(entryOperationArea, true, "连接至 PLS 以继续");
|
||||||
|
}
|
||||||
|
|
||||||
|
const evtListener = (event) => {
|
||||||
|
if (event.detail.connected) {
|
||||||
|
setDisableStatus(entryOperationArea, false);
|
||||||
|
} else {
|
||||||
|
setDisableStatus(entryOperationArea, true, "连接至 PLS 以继续");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
entryContainerEl.addEventListener("onPLSStatsUpdate", evtListener);
|
||||||
|
// createOnLeaveEvtListener("onPLSStatsUpdate", evtListener);
|
||||||
|
}
|
||||||
|
entryContainerEl.appendChild(entryOperationArea);
|
||||||
|
const isShow = entry.auraIf();
|
||||||
|
if (!isShow) entryContainerEl.classList.add("aura-settings-entry-hidden");
|
||||||
|
|
||||||
|
if (entry.associateVal) {
|
||||||
|
const evtListener = (event) => {
|
||||||
|
if (!entry.associateVal.includes(event.detail.path.join("."))) return;
|
||||||
|
const cls = entryContainerEl.classList;
|
||||||
|
const isShow = entry.auraIf();
|
||||||
|
isShow
|
||||||
|
? cls.remove("aura-settings-entry-hidden")
|
||||||
|
: cls.add("aura-settings-entry-hidden");
|
||||||
|
};
|
||||||
|
const channel = entry.PLSRequired
|
||||||
|
? "onPLSConfigUpdate"
|
||||||
|
: "onHugoAuraConfigUpdate";
|
||||||
|
entryContainerEl.addEventListener(channel, evtListener);
|
||||||
|
// createOnLeaveEvtListener(channel, evtListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
formEl.appendChild(entryContainerEl);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderPreviewItem = (entry, formEl) => {
|
||||||
|
const elementId = entry.customId ? entry.customId : `${entry.id}Container`;
|
||||||
|
const eventChannel = entry.listenerType;
|
||||||
|
|
||||||
|
const separateHrContainer = document.createElement("div");
|
||||||
|
separateHrContainer.classList.add("aura-settings-preview-area-hr-container");
|
||||||
|
|
||||||
|
const hrTitle = document.createElement("p");
|
||||||
|
hrTitle.textContent = "预览";
|
||||||
|
|
||||||
|
const hrElement = document.createElement("hr");
|
||||||
|
hrElement.classList.add("aura-settings-preview-hr");
|
||||||
|
|
||||||
|
separateHrContainer.appendChild(hrElement);
|
||||||
|
separateHrContainer.appendChild(hrTitle);
|
||||||
|
separateHrContainer.appendChild(hrElement.cloneNode());
|
||||||
|
|
||||||
|
formEl.appendChild(separateHrContainer);
|
||||||
|
|
||||||
|
const previewContainerEl = document.createElement("div");
|
||||||
|
previewContainerEl.classList.add("aura-settings-preview-area-container");
|
||||||
|
previewContainerEl.id = elementId;
|
||||||
|
|
||||||
|
const eventListener = (event) => {
|
||||||
|
const childs = previewContainerEl.querySelectorAll("*");
|
||||||
|
Array.from(childs).forEach((el) => {
|
||||||
|
el.dispatchEvent(
|
||||||
|
new CustomEvent("onAssociateValueUpdated", { detail: event.detail })
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener(
|
||||||
|
eventChannel === "pls" ? "onPLSConfigUpdate" : "onHugoAuraConfigUpdate",
|
||||||
|
eventListener
|
||||||
|
);
|
||||||
|
createOnLeaveEvtListener(eventListener); // Clean up
|
||||||
|
|
||||||
|
formEl.appendChild(previewContainerEl);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
global.__HUGO_AURA_LOADER__[entry.loaderTarget].active = true;
|
||||||
|
}, 50);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderChild = (entry, formEl) => {
|
||||||
|
switch (entry.type) {
|
||||||
|
case "preview":
|
||||||
|
renderPreviewItem(entry, formEl);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
renderNormalSettingsItem(entry, formEl);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const settingsRenderer = (pendingEl, settingsObj) => {
|
||||||
const formEl = document.createElement("form");
|
const formEl = document.createElement("form");
|
||||||
formEl.classList.add("aura-settings-form");
|
formEl.classList.add("aura-settings-form");
|
||||||
for (const category of settingsObj) {
|
for (const category of settingsObj) {
|
||||||
@@ -50,234 +369,7 @@ const settingsRenderer = (pendingEl, settingsObj, isPls = false) => {
|
|||||||
categoryTitleEl.textContent = category.categoryName;
|
categoryTitleEl.textContent = category.categoryName;
|
||||||
formEl.appendChild(categoryTitleEl);
|
formEl.appendChild(categoryTitleEl);
|
||||||
for (const entry of category.child) {
|
for (const entry of category.child) {
|
||||||
const entryContainerEl = document.createElement("div");
|
renderChild(entry, formEl);
|
||||||
entryContainerEl.classList.add("aura-settings-entry");
|
|
||||||
entryContainerEl.id = `${entry.id}Container`;
|
|
||||||
|
|
||||||
const entryInfoContainerEl = document.createElement("div");
|
|
||||||
entryInfoContainerEl.classList.add("aura-settings-entry-info-container");
|
|
||||||
const entryTitle = document.createElement("p");
|
|
||||||
entryTitle.classList.add("aura-settings-entry-title");
|
|
||||||
entryTitle.textContent = entry.name;
|
|
||||||
if (entry.restart) {
|
|
||||||
const powerIcon = document.createElement("i");
|
|
||||||
powerIcon.classList.add(
|
|
||||||
"layui-icon",
|
|
||||||
"layui-icon-logout",
|
|
||||||
"aura-settings-entry-property-icon"
|
|
||||||
);
|
|
||||||
powerIcon.setAttribute("data-bs-toggle", "tooltip");
|
|
||||||
powerIcon.setAttribute("data-bs-placement", "top");
|
|
||||||
powerIcon.setAttribute("data-bs-title", "需要重启 Electron 进程");
|
|
||||||
entryTitle.appendChild(powerIcon);
|
|
||||||
}
|
|
||||||
if (entry.PLSRequired) {
|
|
||||||
const plsIcon = document.createElement("i");
|
|
||||||
plsIcon.classList.add(
|
|
||||||
"layui-icon",
|
|
||||||
"layui-icon-component",
|
|
||||||
"aura-settings-entry-property-icon"
|
|
||||||
);
|
|
||||||
plsIcon.setAttribute("data-bs-toggle", "tooltip");
|
|
||||||
plsIcon.setAttribute("data-bs-placement", "top");
|
|
||||||
plsIcon.setAttribute("data-bs-title", "需要 PLS 支持");
|
|
||||||
entryTitle.appendChild(plsIcon);
|
|
||||||
}
|
|
||||||
if (entry.restartPLS) {
|
|
||||||
const plsIcon = document.createElement("i");
|
|
||||||
plsIcon.classList.add(
|
|
||||||
"layui-icon",
|
|
||||||
"layui-icon-logout",
|
|
||||||
"aura-settings-entry-property-icon"
|
|
||||||
);
|
|
||||||
plsIcon.setAttribute("data-bs-toggle", "tooltip");
|
|
||||||
plsIcon.setAttribute("data-bs-placement", "top");
|
|
||||||
plsIcon.setAttribute("data-bs-title", "需要重启 PLS 进程");
|
|
||||||
entryTitle.appendChild(plsIcon);
|
|
||||||
}
|
|
||||||
if (entry.reload) {
|
|
||||||
const reloadIcon = document.createElement("i");
|
|
||||||
reloadIcon.classList.add(
|
|
||||||
"layui-icon",
|
|
||||||
"layui-icon-refresh",
|
|
||||||
"aura-settings-entry-property-icon"
|
|
||||||
);
|
|
||||||
reloadIcon.setAttribute("data-bs-toggle", "tooltip");
|
|
||||||
reloadIcon.setAttribute("data-bs-placement", "top");
|
|
||||||
reloadIcon.setAttribute("data-bs-title", "需要重载页面");
|
|
||||||
entryTitle.appendChild(reloadIcon);
|
|
||||||
}
|
|
||||||
|
|
||||||
const createToolTipIcon = (type, content) => {
|
|
||||||
const tipIcon = document.createElement("i");
|
|
||||||
tipIcon.classList.add(
|
|
||||||
"layui-icon",
|
|
||||||
"layui-icon-tips",
|
|
||||||
"aura-settings-entry-property-icon"
|
|
||||||
);
|
|
||||||
if (type === "warning") {
|
|
||||||
tipIcon.classList.add("aura-settings-entry-warning-icon");
|
|
||||||
}
|
|
||||||
tipIcon.setAttribute("data-bs-toggle", "tooltip");
|
|
||||||
tipIcon.setAttribute("data-bs-placement", "top");
|
|
||||||
tipIcon.setAttribute("data-bs-title", content);
|
|
||||||
entryTitle.appendChild(tipIcon);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (entry.tip) {
|
|
||||||
createToolTipIcon("tip", entry.tipTitle);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry.warning) {
|
|
||||||
createToolTipIcon("warning", entry.warningContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
const entryDescription = document.createElement("p");
|
|
||||||
entryDescription.classList.add("aura-settings-entry-desc");
|
|
||||||
entryDescription.textContent = entry.description;
|
|
||||||
entryInfoContainerEl.appendChild(entryTitle);
|
|
||||||
entryInfoContainerEl.appendChild(entryDescription);
|
|
||||||
|
|
||||||
entryContainerEl.appendChild(entryInfoContainerEl);
|
|
||||||
|
|
||||||
const entryOperationArea = document.createElement("div");
|
|
||||||
entryOperationArea.classList.add("aura-settings-entry-operation-area");
|
|
||||||
switch (entry.type) {
|
|
||||||
case "switch":
|
|
||||||
{
|
|
||||||
const switchEl = document.createElement("input");
|
|
||||||
switchEl.classList.add("form-check-input");
|
|
||||||
switchEl.type = "checkbox";
|
|
||||||
switchEl.role = "switch";
|
|
||||||
switchEl.id = entry.id;
|
|
||||||
const elValue = entry.valueGetter();
|
|
||||||
switchEl.value = elValue;
|
|
||||||
switchEl.checked = elValue;
|
|
||||||
switchEl.addEventListener("change", async (event) => {
|
|
||||||
showToast(entry);
|
|
||||||
await entry.callbackFn(event.target.checked);
|
|
||||||
});
|
|
||||||
entryOperationArea.classList.add("form-check", "form-switch");
|
|
||||||
entryOperationArea.appendChild(switchEl);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "radio":
|
|
||||||
{
|
|
||||||
const elValue = entry.valueGetter();
|
|
||||||
for (const template of entry.templates) {
|
|
||||||
const inlineContainerEl = document.createElement("div");
|
|
||||||
inlineContainerEl.classList.add(
|
|
||||||
"form-check",
|
|
||||||
"form-check-inline"
|
|
||||||
);
|
|
||||||
const radioEl = document.createElement("input");
|
|
||||||
radioEl.value = template;
|
|
||||||
radioEl.classList.add("form-check-input");
|
|
||||||
radioEl.type = "radio";
|
|
||||||
radioEl.name = `${entry.id}Radios`;
|
|
||||||
radioEl.id = `${entry.id}Radio${entry.templates.indexOf(
|
|
||||||
template
|
|
||||||
)}`;
|
|
||||||
radioEl.checked = template === elValue ? true : false;
|
|
||||||
radioEl.addEventListener("change", async (event) => {
|
|
||||||
if (event.target.checked) {
|
|
||||||
showToast(entry);
|
|
||||||
await entry.callbackFn(event.target.value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
inlineContainerEl.appendChild(radioEl);
|
|
||||||
const labelEl = document.createElement("label");
|
|
||||||
labelEl.classList.add("form-check-label");
|
|
||||||
labelEl.setAttribute("for", radioEl.id);
|
|
||||||
labelEl.textContent =
|
|
||||||
entry.templateLabels[entry.templates.indexOf(template)];
|
|
||||||
inlineContainerEl.appendChild(labelEl);
|
|
||||||
entryOperationArea.appendChild(inlineContainerEl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "input":
|
|
||||||
{
|
|
||||||
const inputEl = document.createElement("input");
|
|
||||||
inputEl.classList.add("form-control");
|
|
||||||
inputEl.type = entry.subType;
|
|
||||||
inputEl.value = entry.valueGetter();
|
|
||||||
inputEl.placeholder = entry.placeHolder;
|
|
||||||
inputEl.id = entry.id;
|
|
||||||
inputEl.addEventListener("change", async (event) => {
|
|
||||||
const result = await entry.callbackFn(event.target.value);
|
|
||||||
const success = result.valid;
|
|
||||||
if (success) {
|
|
||||||
showToast(entry);
|
|
||||||
|
|
||||||
if (inputEl.className.includes("is-invalid")) {
|
|
||||||
inputEl.classList.remove("is-invalid");
|
|
||||||
entryDescription.textContent = entry.description;
|
|
||||||
entryDescription.classList.remove("ase-desc-error-hint");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
inputEl.classList.add("is-invalid");
|
|
||||||
entryDescription.textContent = result.hint;
|
|
||||||
entryDescription.classList.add("ase-desc-error-hint");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
entryOperationArea.classList.add("ase-operation-area-expanded");
|
|
||||||
entryOperationArea.appendChild(inputEl);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const setDisableStatus = (el, isDisable, hint = null) => {
|
|
||||||
if (isDisable) {
|
|
||||||
el.classList.add("ase-operation-area-disabled");
|
|
||||||
if (hint) {
|
|
||||||
el.setAttribute("data-bs-toggle", "tooltip");
|
|
||||||
el.setAttribute("data-bs-placement", "top");
|
|
||||||
el.setAttribute("data-bs-title", hint);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
el.setAttribute("data-bs-toggle", "");
|
|
||||||
el.setAttribute("data-bs-placement", "");
|
|
||||||
el.setAttribute("data-bs-title", "");
|
|
||||||
el.classList.remove("ase-operation-area-disabled");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (entry.PLSRequired) {
|
|
||||||
if (!global.__HUGO_AURA__.plsStats.connected) {
|
|
||||||
setDisableStatus(entryOperationArea, true, "连接至 PLS 以继续");
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener("onPLSStatsUpdate", (event) => {
|
|
||||||
if (event.detail.connected) {
|
|
||||||
setDisableStatus(entryOperationArea, false);
|
|
||||||
} else {
|
|
||||||
setDisableStatus(entryOperationArea, true, "连接至 PLS 以继续");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
entryContainerEl.appendChild(entryOperationArea);
|
|
||||||
const isShow = entry.auraIf();
|
|
||||||
if (!isShow) entryContainerEl.classList.add("aura-settings-entry-hidden");
|
|
||||||
|
|
||||||
if (entry.associateVal) {
|
|
||||||
document.addEventListener(
|
|
||||||
isPls ? "onPLSConfigUpdate" : "onHugoAuraConfigUpdate",
|
|
||||||
(event) => {
|
|
||||||
if (!entry.associateVal.includes(event.detail.path.join(".")))
|
|
||||||
return;
|
|
||||||
const cls = entryContainerEl.classList;
|
|
||||||
const isShow = entry.auraIf();
|
|
||||||
isShow
|
|
||||||
? cls.remove("aura-settings-entry-hidden")
|
|
||||||
: cls.add("aura-settings-entry-hidden");
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
formEl.appendChild(entryContainerEl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const hrEl = document.createElement("hr");
|
const hrEl = document.createElement("hr");
|
||||||
|
|||||||
@@ -65,6 +65,33 @@
|
|||||||
border-bottom: 0.75px solid rgba(0, 0, 0, 0.25);
|
border-bottom: 0.75px solid rgba(0, 0, 0, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.aura-settings-preview-area-hr-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aura-settings-preview-hr {
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
border-bottom: 0.75px solid rgba(0, 0, 0, 0.25);
|
||||||
|
width: -webkit-fill-available;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aura-settings-preview-area-hr-container p {
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
min-width: 2rem;
|
||||||
|
opacity: 0.75;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aura-settings-preview-area-container {
|
||||||
|
width: 100%;
|
||||||
|
padding-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.aura-settings-entry-property-icon {
|
.aura-settings-entry-property-icon {
|
||||||
margin-left: 0.5rem;
|
margin-left: 0.5rem;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
@@ -81,7 +108,7 @@
|
|||||||
.aura-settings-entry-warning-icon {
|
.aura-settings-entry-warning-icon {
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
color: rgb(241, 155, 0);
|
color: rgb(147, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Animations */
|
/* Animations */
|
||||||
|
|||||||
@@ -25,3 +25,7 @@ button.nav-link {
|
|||||||
.nav-underline {
|
.nav-underline {
|
||||||
--bs-nav-underline-link-active-color: #0d6efd !important;
|
--bs-nav-underline-link-active-color: #0d6efd !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tooltip {
|
||||||
|
--bs-tooltip-max-width: 400px !important;
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,41 +21,60 @@ const def = {
|
|||||||
pageSelector: "#root",
|
pageSelector: "#root",
|
||||||
selectorMode: "appendChild",
|
selectorMode: "appendChild",
|
||||||
pageCSS: "ui/pages/config/config.css",
|
pageCSS: "ui/pages/config/config.css",
|
||||||
},
|
childs: {
|
||||||
"Aura.UI.Assistant.Config.DisableLimitations": {
|
DisableLimitations: {
|
||||||
active: false,
|
active: false,
|
||||||
pageURI:
|
pageURI:
|
||||||
"ui/pages/configSubPages/disableLimitations/disableLimitations.html",
|
"ui/pages/configSubPages/disableLimitations/disableLimitations.html",
|
||||||
pageScript:
|
pageScript:
|
||||||
"ui/pages/configSubPages/disableLimitations/disableLimitations.js",
|
"ui/pages/configSubPages/disableLimitations/disableLimitations.js",
|
||||||
pageSelector: ".aura-config-page-subpage-container",
|
pageSelector: ".aura-config-page-subpage-container",
|
||||||
selectorMode: "appendChild",
|
selectorMode: "appendChild",
|
||||||
pageCSS:
|
pageCSS:
|
||||||
"ui/pages/configSubPages/disableLimitations/disableLimitations.css",
|
"ui/pages/configSubPages/disableLimitations/disableLimitations.css",
|
||||||
},
|
},
|
||||||
"Aura.UI.Assistant.Config.BehaviourCtrl": {
|
BehaviourCtrl: {
|
||||||
active: false,
|
active: false,
|
||||||
pageURI: "ui/pages/configSubPages/behaviourCtrl/behaviourCtrl.html",
|
pageURI: "ui/pages/configSubPages/behaviourCtrl/behaviourCtrl.html",
|
||||||
pageScript: "ui/pages/configSubPages/behaviourCtrl/behaviourCtrl.js",
|
pageScript: "ui/pages/configSubPages/behaviourCtrl/behaviourCtrl.js",
|
||||||
pageSelector: ".aura-config-page-subpage-container",
|
pageSelector: ".aura-config-page-subpage-container",
|
||||||
selectorMode: "appendChild",
|
selectorMode: "appendChild",
|
||||||
pageCSS: "ui/pages/configSubPages/behaviourCtrl/behaviourCtrl.css",
|
pageCSS: "ui/pages/configSubPages/behaviourCtrl/behaviourCtrl.css",
|
||||||
},
|
childs: {
|
||||||
"Aura.UI.Assistant.Config.BehaviourCtrl.PlsStatus": {
|
PlsStatus: {
|
||||||
active: false,
|
active: false,
|
||||||
pageURI: "ui/pages/configSubPages/behaviourCtrl/plsStatus.html",
|
pageURI: "ui/pages/configSubPages/behaviourCtrl/plsStatus.html",
|
||||||
pageScript: "ui/pages/configSubPages/behaviourCtrl/plsStatus.js",
|
pageScript: "ui/pages/configSubPages/behaviourCtrl/plsStatus.js",
|
||||||
pageSelector: "#status-subpage",
|
pageSelector: "#status-subpage",
|
||||||
selectorMode: "appendChild",
|
selectorMode: "appendChild",
|
||||||
pageCSS: "ui/pages/configSubPages/behaviourCtrl/plsStatus.css",
|
pageCSS: "ui/pages/configSubPages/behaviourCtrl/plsStatus.css",
|
||||||
},
|
},
|
||||||
"Aura.UI.Assistant.Config.Preferences": {
|
DeviceSecurity: {
|
||||||
active: false,
|
childs: {
|
||||||
pageURI: "ui/pages/configSubPages/preferences/preferences.html",
|
FreezeOverridePreview: {
|
||||||
pageScript: "ui/pages/configSubPages/preferences/preferences.js",
|
active: false,
|
||||||
pageSelector: ".aura-config-page-subpage-container",
|
pageURI:
|
||||||
selectorMode: "appendChild",
|
"ui/pages/configSubPages/behaviourCtrl/settings/previews/freezeOverridePreview/freezeOverridePreview.html",
|
||||||
pageCSS: "ui/pages/configSubPages/preferences/preferences.css",
|
pageScript:
|
||||||
|
"ui/pages/configSubPages/behaviourCtrl/settings/previews/freezeOverridePreview/freezeOverridePreview.js",
|
||||||
|
pageSelector: "#freezeInfoReportOverridePreviewContainer",
|
||||||
|
selectorMode: "appendChild",
|
||||||
|
pageCSS:
|
||||||
|
"ui/pages/configSubPages/behaviourCtrl/settings/previews/freezeOverridePreview/freezeOverridePreview.css",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Preferences: {
|
||||||
|
active: false,
|
||||||
|
pageURI: "ui/pages/configSubPages/preferences/preferences.html",
|
||||||
|
pageScript: "ui/pages/configSubPages/preferences/preferences.js",
|
||||||
|
pageSelector: ".aura-config-page-subpage-container",
|
||||||
|
selectorMode: "appendChild",
|
||||||
|
pageCSS: "ui/pages/configSubPages/preferences/preferences.css",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
globalStyles: [
|
globalStyles: [
|
||||||
@@ -65,7 +84,11 @@ const def = {
|
|||||||
"ui/layui/css/layui.css",
|
"ui/layui/css/layui.css",
|
||||||
"ui/bootstrap/bootstrap.min.css",
|
"ui/bootstrap/bootstrap.min.css",
|
||||||
],
|
],
|
||||||
globalJS: ["ui/js/global.js", "ui/js/plsListener.js", "ui/bootstrap/bootstrap.bundle.min.js"],
|
globalJS: [
|
||||||
|
"ui/js/global.js",
|
||||||
|
"ui/js/plsListener.js",
|
||||||
|
"ui/bootstrap/bootstrap.bundle.min.js",
|
||||||
|
],
|
||||||
onLoaded: `
|
onLoaded: `
|
||||||
console.log('[HugoAura / UI / Hooks / Assistant] Page loaded.');
|
console.log('[HugoAura / UI / Hooks / Assistant] Page loaded.');
|
||||||
`,
|
`,
|
||||||
|
|||||||
@@ -20,10 +20,24 @@
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const createOnLeaveEvtListener = (
|
||||||
|
channel,
|
||||||
|
pendingRmEvtListener,
|
||||||
|
leaveEvt = "onCurConfigPageLeave"
|
||||||
|
) => {
|
||||||
|
const rmEvtListener = (event) => {
|
||||||
|
document.removeEventListener(channel, pendingRmEvtListener);
|
||||||
|
document.removeEventListener(leaveEvt, rmEvtListener);
|
||||||
|
};
|
||||||
|
document.addEventListener(leaveEvt, rmEvtListener);
|
||||||
|
return rmEvtListener;
|
||||||
|
};
|
||||||
|
|
||||||
if (!window.__HUGO_AURA_GLOBAL__) window.__HUGO_AURA_GLOBAL__ = {};
|
if (!window.__HUGO_AURA_GLOBAL__) window.__HUGO_AURA_GLOBAL__ = {};
|
||||||
|
|
||||||
window.__HUGO_AURA_GLOBAL__.utils = {
|
window.__HUGO_AURA_GLOBAL__.utils = {
|
||||||
sleep,
|
sleep,
|
||||||
refreshBsTooltip,
|
refreshBsTooltip,
|
||||||
|
createOnLeaveEvtListener,
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -15,19 +15,91 @@
|
|||||||
const REQUIRE_BASE = "../../aura/ui";
|
const REQUIRE_BASE = "../../aura/ui";
|
||||||
const __SCOPE = "desktopAssistant";
|
const __SCOPE = "desktopAssistant";
|
||||||
|
|
||||||
|
const PLS_REG_PATH = "ProxyLayerServices";
|
||||||
|
|
||||||
const { pushMsgHandler } = require(`${REQUIRE_BASE}/pls/pushHandler`);
|
const { pushMsgHandler } = require(`${REQUIRE_BASE}/pls/pushHandler`);
|
||||||
|
const RegistryManager = require(`${REQUIRE_BASE}/../init/shared/registryManager`);
|
||||||
|
|
||||||
|
const registryManager = new RegistryManager();
|
||||||
|
|
||||||
/** @type {number} */
|
/** @type {number} */
|
||||||
let failedCounter = 0;
|
let failedCounter = 0;
|
||||||
/** @type {boolean} */
|
/** @type {boolean} */
|
||||||
let isErrorOccurred = false;
|
let isErrorOccurred = false;
|
||||||
|
|
||||||
|
/** @type {number} */
|
||||||
|
let plsPort = 22077;
|
||||||
|
/** @type {"wss" | "ws"} */
|
||||||
|
let plsProtocol = "wss";
|
||||||
|
|
||||||
|
/** @type {boolean} */
|
||||||
|
let isRetrying = false;
|
||||||
|
|
||||||
|
/** @type {any} */
|
||||||
|
let curSendListener = null;
|
||||||
|
|
||||||
const sendRetryStatusToMain = (/** @type {Boolean} */ status) => {
|
const sendRetryStatusToMain = (/** @type {Boolean} */ status) => {
|
||||||
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.post.updateRetryStatus`, {
|
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.post.updateRetryStatus`, {
|
||||||
success: status,
|
success: status,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const calcFullAuthToken = (/** @type {string} */ authToken) => {
|
||||||
|
const trustToken = window._ACCEPT_DATA.getData("deviceId");
|
||||||
|
const conjToken = authToken + "AuraXAuth" + trustToken + "NeverEnds";
|
||||||
|
const crypto = require("crypto");
|
||||||
|
return crypto.createHash("sha512").update(conjToken).digest("hex");
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearIpcListener = () => {
|
||||||
|
if (curSendListener) {
|
||||||
|
global.ipcRenderer.off(
|
||||||
|
`${IPC_METHOD_BASE}.ws.post.onReqSendMsg`,
|
||||||
|
curSendListener
|
||||||
|
);
|
||||||
|
curSendListener = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const startConnPlsProc = async (updatedPlsStats) => {
|
||||||
|
const authTokenRet = await registryManager.readRegKey(
|
||||||
|
PLS_REG_PATH,
|
||||||
|
"AuthToken",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
if (authTokenRet.success) {
|
||||||
|
updatedPlsStats.authToken = authTokenRet.data;
|
||||||
|
// @ts-expect-error
|
||||||
|
global.__HUGO_AURA__.plsStats.authToken = authTokenRet.data;
|
||||||
|
} else {
|
||||||
|
sendRetryStatusToMain(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const portRet = await registryManager.readRegKey(
|
||||||
|
PLS_REG_PATH,
|
||||||
|
"WsPort",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
if (portRet.success) {
|
||||||
|
try {
|
||||||
|
plsPort = Number(portRet.data);
|
||||||
|
} catch {
|
||||||
|
console.warn(
|
||||||
|
`[HugoAura / UI / PLS Manager] Invalid PLS port: ${portRet.data}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const protoRet = await registryManager.readRegKey(
|
||||||
|
PLS_REG_PATH,
|
||||||
|
"Protocol",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
if (protoRet.success) {
|
||||||
|
plsProtocol = protoRet.data;
|
||||||
|
}
|
||||||
|
createPlsConnection(updatedPlsStats.authToken, connectionResultCallback);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {string} authToken
|
* @param {string} authToken
|
||||||
@@ -43,9 +115,11 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fullAuthToken = calcFullAuthToken(authToken);
|
||||||
|
|
||||||
/** @type {WebSocket} */
|
/** @type {WebSocket} */
|
||||||
const plsWs = new WebSocket(
|
const plsWs = new WebSocket(
|
||||||
`wss://pls.hugoaura.local:22077/?auth=${authToken}`
|
`${plsProtocol}://pls.hugoaura.local:${plsPort}/?auth=${fullAuthToken}`
|
||||||
);
|
);
|
||||||
|
|
||||||
plsWs.onopen = () => {
|
plsWs.onopen = () => {
|
||||||
@@ -59,6 +133,26 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
plsWs.onclose = () => {
|
plsWs.onclose = () => {
|
||||||
|
clearIpcListener();
|
||||||
|
if (global.__HUGO_AURA__.plsStats) {
|
||||||
|
if (global.__HUGO_AURA__.plsStats.status === "notReady") {
|
||||||
|
if (isRetrying) {
|
||||||
|
sendRetryStatusToMain(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.warn(
|
||||||
|
"[HugoAura / UI / PLS Manager / WARN] PLS not ready, try again after 10s..."
|
||||||
|
);
|
||||||
|
isRetrying = true;
|
||||||
|
setTimeout(async () => {
|
||||||
|
isRetrying = false;
|
||||||
|
startConnPlsProc(global.__HUGO_AURA__.plsStats);
|
||||||
|
}, 10000);
|
||||||
|
sendRetryStatusToMain(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
console.error(
|
console.error(
|
||||||
"[HugoAura / UI / PLS Manager / ERROR] WebSocket connection closed."
|
"[HugoAura / UI / PLS Manager / ERROR] WebSocket connection closed."
|
||||||
);
|
);
|
||||||
@@ -73,16 +167,18 @@
|
|||||||
* @param {WebSocket} wsObj
|
* @param {WebSocket} wsObj
|
||||||
*/
|
*/
|
||||||
const registerSendReqListener = (wsObj) => {
|
const registerSendReqListener = (wsObj) => {
|
||||||
|
clearIpcListener();
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("electron").IpcRendererEvent} _evt
|
||||||
|
* @param {any} arg
|
||||||
|
*/
|
||||||
|
curSendListener = (_evt, arg) => {
|
||||||
|
wsObj.send(JSON.stringify(arg));
|
||||||
|
};
|
||||||
global.ipcRenderer.on(
|
global.ipcRenderer.on(
|
||||||
`${IPC_METHOD_BASE}.ws.post.onReqSendMsg`,
|
`${IPC_METHOD_BASE}.ws.post.onReqSendMsg`,
|
||||||
/**
|
curSendListener
|
||||||
*
|
|
||||||
* @param {import("electron").IpcRendererEvent} _evt
|
|
||||||
* @param {any} arg
|
|
||||||
*/
|
|
||||||
(_evt, arg) => {
|
|
||||||
wsObj.send(JSON.stringify(arg));
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -151,6 +247,11 @@
|
|||||||
const initPlsConnection = async () => {
|
const initPlsConnection = async () => {
|
||||||
if (!global.__HUGO_AURA__.plsStats) return;
|
if (!global.__HUGO_AURA__.plsStats) return;
|
||||||
|
|
||||||
|
if (isRetrying) {
|
||||||
|
sendRetryStatusToMain(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
failedCounter = 0;
|
failedCounter = 0;
|
||||||
isErrorOccurred = false;
|
isErrorOccurred = false;
|
||||||
|
|
||||||
@@ -173,7 +274,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isPlsFolderExists = (
|
const isPlsFolderExists = (
|
||||||
await global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.getPlsFolderExists`)
|
await global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.getPlsBinExists`)
|
||||||
).data.isExists;
|
).data.isExists;
|
||||||
updatedPlsStats.installed = isPlsFolderExists;
|
updatedPlsStats.installed = isPlsFolderExists;
|
||||||
|
|
||||||
@@ -189,15 +290,11 @@
|
|||||||
updatedPlsStats
|
updatedPlsStats
|
||||||
);
|
);
|
||||||
|
|
||||||
const startConnPls = () => {
|
|
||||||
createPlsConnection(updatedPlsStats.authToken, connectionResultCallback);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (updatedPlsStats.detached && updatedPlsStats.installed) {
|
if (updatedPlsStats.detached && updatedPlsStats.installed) {
|
||||||
*/
|
*/
|
||||||
if (updatedPlsStats.installed) {
|
if (updatedPlsStats.installed) {
|
||||||
startConnPls();
|
await startConnPlsProc(updatedPlsStats);
|
||||||
} else {
|
} else {
|
||||||
sendRetryStatusToMain(false);
|
sendRetryStatusToMain(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,23 @@
|
|||||||
`${IPC_METHOD_BASE}.post.onPlsStatsUpdate`,
|
`${IPC_METHOD_BASE}.post.onPlsStatsUpdate`,
|
||||||
(_event, arg) => {
|
(_event, arg) => {
|
||||||
global.__HUGO_AURA__.plsStats = arg;
|
global.__HUGO_AURA__.plsStats = arg;
|
||||||
|
|
||||||
|
const event = new CustomEvent("onPLSStatsUpdate", {
|
||||||
|
detail: {
|
||||||
|
connected: arg.connected,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
document.dispatchEvent(event);
|
||||||
|
|
||||||
|
const settingsEntries = document.getElementsByClassName(
|
||||||
|
"aura-settings-entry"
|
||||||
|
);
|
||||||
|
if (settingsEntries.length > 0) {
|
||||||
|
Array.from(settingsEntries).forEach((entry) => {
|
||||||
|
entry.dispatchEvent(event);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -21,6 +38,24 @@
|
|||||||
`${IPC_METHOD_BASE}.post.onPlsSettingsUpdate`,
|
`${IPC_METHOD_BASE}.post.onPlsSettingsUpdate`,
|
||||||
(_event, arg) => {
|
(_event, arg) => {
|
||||||
global.__HUGO_AURA__.plsSettings = arg;
|
global.__HUGO_AURA__.plsSettings = arg;
|
||||||
|
|
||||||
|
const event = new CustomEvent("onPLSConfigUpdate", {
|
||||||
|
detail: {
|
||||||
|
path: ["root", "settings"],
|
||||||
|
value: arg,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
document.dispatchEvent(event);
|
||||||
|
|
||||||
|
const settingsEntries = document.getElementsByClassName(
|
||||||
|
"aura-settings-entry"
|
||||||
|
);
|
||||||
|
if (settingsEntries.length > 0) {
|
||||||
|
Array.from(settingsEntries).forEach((entry) => {
|
||||||
|
entry.dispatchEvent(event);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -28,19 +63,38 @@
|
|||||||
`${IPC_METHOD_BASE}.post.onPlsRulesUpdate`,
|
`${IPC_METHOD_BASE}.post.onPlsRulesUpdate`,
|
||||||
(_event, arg) => {
|
(_event, arg) => {
|
||||||
global.__HUGO_AURA__.plsRules = arg;
|
global.__HUGO_AURA__.plsRules = arg;
|
||||||
|
|
||||||
|
const event = new CustomEvent("onPLSConfigUpdate", {
|
||||||
|
detail: {
|
||||||
|
path: ["root", "ruleSettings"],
|
||||||
|
value: arg,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
document.dispatchEvent(event);
|
||||||
|
|
||||||
|
const settingsEntries = document.getElementsByClassName(
|
||||||
|
"aura-settings-entry"
|
||||||
|
);
|
||||||
|
if (settingsEntries.length > 0) {
|
||||||
|
Array.from(settingsEntries).forEach((entry) => {
|
||||||
|
entry.dispatchEvent(event);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
ipcRenderer.on(
|
ipcRenderer.on(
|
||||||
`${IPC_METHOD_BASE}.post.updateRetryStatus`,
|
`${IPC_METHOD_BASE}.post.updateRetryStatus`,
|
||||||
(_event, arg) => {
|
(_event, arg) => {
|
||||||
document.dispatchEvent(
|
const event = new CustomEvent("onPLSStatsUpdate", {
|
||||||
new CustomEvent("onPLSStatsUpdate", {
|
detail: {
|
||||||
detail: {
|
connected: arg.success,
|
||||||
connected: arg.success,
|
},
|
||||||
},
|
});
|
||||||
})
|
|
||||||
);
|
document.dispatchEvent(event);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
global.__HUGO_AURA_LOADER__["Aura.UI.Assistant.Config.BehaviourCtrl"]
|
global.__HUGO_AURA_LOADER__["Aura.UI.Assistant.Config.BehaviourCtrl"]
|
||||||
.active
|
.active
|
||||||
|
|||||||
@@ -189,6 +189,11 @@
|
|||||||
<div class="toast-header">
|
<div class="toast-header">
|
||||||
<i class="layui-icon layui-icon-tips"></i>
|
<i class="layui-icon layui-icon-tips"></i>
|
||||||
<strong class="me-auto">重载页面以应用设置</strong>
|
<strong class="me-auto">重载页面以应用设置</strong>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn-close"
|
||||||
|
data-bs-dismiss="toast"
|
||||||
|
></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="toast-body">
|
<div class="toast-body">
|
||||||
<p>请重载当前窗口以应用修改的设置</p>
|
<p>请重载当前窗口以应用修改的设置</p>
|
||||||
@@ -217,6 +222,11 @@
|
|||||||
<div class="toast-header">
|
<div class="toast-header">
|
||||||
<i class="layui-icon layui-icon-tips"></i>
|
<i class="layui-icon layui-icon-tips"></i>
|
||||||
<strong class="me-auto">重启进程以应用设置</strong>
|
<strong class="me-auto">重启进程以应用设置</strong>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn-close"
|
||||||
|
data-bs-dismiss="toast"
|
||||||
|
></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="toast-body">
|
<div class="toast-body">
|
||||||
<p>请重启 Electron 进程以应用修改的设置</p>
|
<p>请重启 Electron 进程以应用修改的设置</p>
|
||||||
@@ -245,6 +255,11 @@
|
|||||||
<div class="toast-header">
|
<div class="toast-header">
|
||||||
<i class="layui-icon layui-icon-tips"></i>
|
<i class="layui-icon layui-icon-tips"></i>
|
||||||
<strong class="me-auto">重启 PLS 进程以应用设置</strong>
|
<strong class="me-auto">重启 PLS 进程以应用设置</strong>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn-close"
|
||||||
|
data-bs-dismiss="toast"
|
||||||
|
></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="toast-body">
|
<div class="toast-body">
|
||||||
<p>请重启 PLS 进程以应用修改的设置</p>
|
<p>请重启 PLS 进程以应用修改的设置</p>
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ global.__HUGO_AURA_UI_FUNCTIONS__.config = {
|
|||||||
global.__HUGO_AURA_UI_REACTIVES__.config.currentActiveSubPage,
|
global.__HUGO_AURA_UI_REACTIVES__.config.currentActiveSubPage,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
const onLeaveEvent = new CustomEvent("onCurConfigPageLeave");
|
||||||
|
document.dispatchEvent(onLeaveEvent);
|
||||||
} else {
|
} else {
|
||||||
global.__HUGO_AURA_UI_FUNCTIONS__.config.hideConfigPage();
|
global.__HUGO_AURA_UI_FUNCTIONS__.config.hideConfigPage();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
} = require(`${REQUIRE_BASE}/../../../../composables/settingsRenderer`);
|
} = require(`${REQUIRE_BASE}/../../../../composables/settingsRenderer`);
|
||||||
|
|
||||||
const { basicSettings } = require(`${REQUIRE_BASE}/basic`);
|
const { basicSettings } = require(`${REQUIRE_BASE}/basic`);
|
||||||
|
const { deviceSecuritySettings } = require(`${REQUIRE_BASE}/deviceSecurity`);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
updatePlsSettingsFromLocal,
|
updatePlsSettingsFromLocal,
|
||||||
@@ -24,19 +25,27 @@
|
|||||||
settingsRenderer(basicSubPageEl, basicSettings);
|
settingsRenderer(basicSubPageEl, basicSettings);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const initDeviceSecuritySettingsPage = () => {
|
||||||
|
const deviceSecuritySubPageEl = document.getElementById(
|
||||||
|
"security-config-subpage"
|
||||||
|
);
|
||||||
|
settingsRenderer(deviceSecuritySubPageEl, deviceSecuritySettings);
|
||||||
|
};
|
||||||
|
|
||||||
const renderSubPages = async () => {
|
const renderSubPages = async () => {
|
||||||
await updatePlsSettingsFromLocal();
|
await updatePlsSettingsFromLocal();
|
||||||
await updatePlsRulesFromLocal();
|
await updatePlsRulesFromLocal();
|
||||||
|
|
||||||
initBasicSettingsPage();
|
initBasicSettingsPage();
|
||||||
|
initDeviceSecuritySettingsPage();
|
||||||
};
|
};
|
||||||
|
|
||||||
const onMounted = () => {
|
const onMounted = () => {
|
||||||
const rootEl = document.getElementById("acs-behaviour-control-el");
|
const rootEl = document.getElementById("acs-behaviour-control-el");
|
||||||
initStatusPage();
|
initStatusPage();
|
||||||
renderSubPages();
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
rootEl.classList.remove("acs-behaviour-control-hidden");
|
rootEl.classList.remove("acs-behaviour-control-hidden");
|
||||||
|
renderSubPages(); // 如果立即渲染子页面, 此时 plsRules 还未初始化, 会导致子页面 auraIf 失效
|
||||||
}, 500);
|
}, 500);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -137,3 +137,62 @@
|
|||||||
.acs-bc-pls-status-page-status-area.failed p {
|
.acs-bc-pls-status-page-status-area.failed p {
|
||||||
color: rgb(175, 0, 0);
|
color: rgb(175, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.acs-bc-pls-status-page-status-area.warning
|
||||||
|
.acs-bc-pls-status-page-status-area-circle {
|
||||||
|
background-color: rgb(212, 127, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-pls-status-page-status-area.warning p {
|
||||||
|
color: rgb(212, 127, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-pls-status-page-status-area.info
|
||||||
|
.acs-bc-pls-status-page-status-area-circle {
|
||||||
|
background-color: #3d78ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-pls-status-page-status-area.info p {
|
||||||
|
color: #3d78ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-psp-toast.body-display-none .toast-body {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-psp-toast.body-display-none .toast-header {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-psp-toast[closable="false"] .btn-close {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-psp-toast[variant="success"] .toast-header {
|
||||||
|
background-color: rgb(6, 196, 65);
|
||||||
|
color: rgb(255, 255, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-psp-toast[variant="warning"] .toast-header {
|
||||||
|
background-color: rgb(225, 178, 44);
|
||||||
|
color: rgb(255 255 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-psp-toast[variant="error"] .toast-header {
|
||||||
|
background-color: rgb(217, 57, 4);
|
||||||
|
color: rgb(255 255 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-psp-toast[variant="info"] .toast-header {
|
||||||
|
background-color: rgb(0, 149, 222);
|
||||||
|
color: rgb(255 255 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-psp-toast[variant="success"] .btn-close,
|
||||||
|
.acs-bc-psp-toast[variant="warning"] .btn-close,
|
||||||
|
.acs-bc-psp-toast[variant="error"] .btn-close,
|
||||||
|
.acs-bc-psp-toast[variant="info"] .btn-close {
|
||||||
|
color: rgb(255, 255, 255);
|
||||||
|
filter: invert(1);
|
||||||
|
opacity: 0.95;
|
||||||
|
}
|
||||||
|
|||||||
@@ -92,6 +92,36 @@
|
|||||||
</svg>
|
</svg>
|
||||||
<p>卸载服务</p>
|
<p>卸载服务</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="acs-bc-psp-operation-btn" id="acsBcPsp-operBtn-Start">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
viewBox="0 0 32 32"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="var(--svg-color)"
|
||||||
|
d="M7 28a1 1 0 0 1-1-1V5a1 1 0 0 1 1.482-.876l20 11a1 1 0 0 1 0 1.752l-20 11A1 1 0 0 1 7 28M8 6.69v18.62L24.925 16Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<p>启动服务</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="acs-bc-psp-operation-btn" id="acsBcPsp-operBtn-Stop">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
viewBox="0 0 32 32"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="var(--svg-color)"
|
||||||
|
d="M24 8v16H8V8zm0-2H8a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<p>停止服务</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="acs-bc-pls-status-page-status-el">
|
<div class="acs-bc-pls-status-page-status-el">
|
||||||
@@ -133,4 +163,18 @@
|
|||||||
<p id="acs-bc-psp-version-text">不可用</p>
|
<p id="acs-bc-psp-version-text">不可用</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="toast-container position-fixed bottom-0 end-0 p-3">
|
||||||
|
<div id="plsStatusNotifyToast" class="acs-bc-psp-toast toast" data-bs-autohide="false">
|
||||||
|
<div class="toast-header">
|
||||||
|
<strong class="me-auto" id="plsStatusNotifyToastTitle"></strong>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn-close"
|
||||||
|
data-bs-dismiss="toast"
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
|
<div class="toast-body" id="plsStatusNotifyToastBody"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,32 +1,339 @@
|
|||||||
if (!global.__HUGO_AURA_UI_FUNCTIONS__.subConfig)
|
if (!global.__HUGO_AURA_UI_FUNCTIONS__.subConfig)
|
||||||
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig = {};
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig = {};
|
||||||
|
|
||||||
|
if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig)
|
||||||
|
global.__HUGO_AURA_UI_REACTIVES__.subConfig = {};
|
||||||
|
|
||||||
(() => {
|
(() => {
|
||||||
const REQUIRE_BASE = "../../aura/ui/pages/configSubPages/behaviourCtrl";
|
const REQUIRE_BASE = "../../aura/ui/pages/configSubPages/behaviourCtrl";
|
||||||
const IPC_METHOD_BASE = "$aura.pls";
|
const IPC_METHOD_BASE = "$aura.pls";
|
||||||
|
|
||||||
|
const lifecycleStatus = {
|
||||||
|
installed: false,
|
||||||
|
detached: false,
|
||||||
|
svcInstalled: false,
|
||||||
|
svcRunning: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
global.__HUGO_AURA_UI_REACTIVES__.subConfig.plsStatus = {
|
||||||
|
toastAutoHideTimeout: null,
|
||||||
|
};
|
||||||
|
|
||||||
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus = {
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus = {
|
||||||
updateOperationBtnStatus: async (btnName, side, btnContent = null) => {
|
updateToast: async (
|
||||||
|
variant,
|
||||||
|
title,
|
||||||
|
body = null,
|
||||||
|
closable = true,
|
||||||
|
autoHide = true,
|
||||||
|
hideAfter = 3000
|
||||||
|
) => {
|
||||||
|
const toastRootEl = document.getElementById("plsStatusNotifyToast");
|
||||||
|
const toastHeaderEl = document.getElementById(
|
||||||
|
"plsStatusNotifyToastTitle"
|
||||||
|
);
|
||||||
|
const toastBodyEl = document.getElementById("plsStatusNotifyToastBody");
|
||||||
|
|
||||||
|
const bsToastIns = bootstrap.Toast.getOrCreateInstance(toastRootEl);
|
||||||
|
if (bsToastIns.isShown) {
|
||||||
|
bsToastIns.hide();
|
||||||
|
const timeout =
|
||||||
|
global.__HUGO_AURA_UI_REACTIVES__.subConfig.plsStatus
|
||||||
|
.toastAutoHideTimeout;
|
||||||
|
if (timeout) {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
}
|
||||||
|
await global.__HUGO_AURA_GLOBAL__.utils.sleep(160);
|
||||||
|
}
|
||||||
|
|
||||||
|
toastRootEl.setAttribute("variant", variant);
|
||||||
|
toastHeaderEl.innerHTML = title;
|
||||||
|
if (body) {
|
||||||
|
toastBodyEl.innerHTML = body;
|
||||||
|
toastRootEl.classList.remove("body-display-none");
|
||||||
|
} else {
|
||||||
|
toastRootEl.classList.add("body-display-none");
|
||||||
|
}
|
||||||
|
|
||||||
|
toastRootEl.setAttribute("closable", closable.toString());
|
||||||
|
|
||||||
|
bsToastIns.show();
|
||||||
|
if (autoHide && hideAfter) {
|
||||||
|
global.__HUGO_AURA_UI_REACTIVES__.subConfig.plsStatus.toastAutoHideTimeout =
|
||||||
|
setTimeout(() => {
|
||||||
|
bsToastIns.hide();
|
||||||
|
}, hideAfter);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
updateOperationBtnStatus: async (
|
||||||
|
btnName,
|
||||||
|
isDisabled,
|
||||||
|
btnContent = null
|
||||||
|
) => {
|
||||||
const btnEl = document.getElementById(`acsBcPsp-operBtn-${btnName}`);
|
const btnEl = document.getElementById(`acsBcPsp-operBtn-${btnName}`);
|
||||||
if (!btnEl) return false;
|
if (!btnEl) return false;
|
||||||
btnEl.setAttribute("aura-disabled", side ? "true" : "false");
|
btnEl.setAttribute("aura-disabled", isDisabled ? "true" : "false");
|
||||||
if (btnContent) {
|
if (btnContent) {
|
||||||
const btnPEl = btnEl.getElementsByTagName("p")[0];
|
const btnPEl = btnEl.getElementsByTagName("p")[0];
|
||||||
btnPEl.textContent = btnContent;
|
btnPEl.textContent = btnContent;
|
||||||
}
|
}
|
||||||
if (side) {
|
if (isDisabled) {
|
||||||
btnEl.onclick = () => {};
|
btnEl.onclick = () => {};
|
||||||
} else {
|
} else {
|
||||||
switch (btnName) {
|
switch (btnName) {
|
||||||
case "Refresh":
|
case "Refresh":
|
||||||
btnEl.onclick = () =>
|
btnEl.onclick = () => {
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
||||||
|
"warning",
|
||||||
|
"正在更新",
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null
|
||||||
|
);
|
||||||
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.refreshPlsStatus();
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.refreshPlsStatus();
|
||||||
|
};
|
||||||
break;
|
break;
|
||||||
case "Download":
|
case "Download":
|
||||||
|
btnEl.onclick = async () => {
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.downloadPLSBin();
|
||||||
|
};
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// ↓ 这边的确可以把这些全都合并到一个可复用 fn 里去, 但没必要
|
||||||
|
// 如果后续要引入错误视觉反馈, 合并到单个 fn 反而会增加实现复杂度
|
||||||
case "Install":
|
case "Install":
|
||||||
|
btnEl.onclick = async () => {
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateOperationBtnStatus(
|
||||||
|
"Install",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
||||||
|
"info",
|
||||||
|
"正在请求安装",
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
const ret = await ipcRenderer.invoke(
|
||||||
|
`${IPC_METHOD_BASE}.plsLifecycleControl`,
|
||||||
|
{ target: "instSvc" }
|
||||||
|
);
|
||||||
|
if (ret.success) {
|
||||||
|
lifecycleStatus.svcInstalled = true;
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
||||||
|
"success",
|
||||||
|
"服务安装成功",
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
2000
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
||||||
|
"error",
|
||||||
|
"服务安装失败",
|
||||||
|
"<p>检查日志以获取详细信息</p>",
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateStatusContent();
|
||||||
|
};
|
||||||
break;
|
break;
|
||||||
case "Uninstall":
|
case "Uninstall":
|
||||||
|
if (btnContent === "删除内核") {
|
||||||
|
btnEl.onclick = async () => {
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateOperationBtnStatus(
|
||||||
|
"Uninstall",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
||||||
|
"warning",
|
||||||
|
"正在删除内核",
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
const ret = await ipcRenderer.invoke(
|
||||||
|
`${IPC_METHOD_BASE}.plsLifecycleControl`,
|
||||||
|
{ target: "rmBin" }
|
||||||
|
);
|
||||||
|
if (ret.success) {
|
||||||
|
lifecycleStatus.installed = false;
|
||||||
|
lifecycleStatus.svcInstalled = false;
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
||||||
|
"success",
|
||||||
|
"内核已删除",
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
2000
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
||||||
|
"error",
|
||||||
|
"内核删除失败",
|
||||||
|
"<p>检查日志以获取详细信息</p>",
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateStatusContent();
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
btnEl.onclick = async () => {
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateOperationBtnStatus(
|
||||||
|
"Uninstall",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
||||||
|
"info",
|
||||||
|
lifecycleStatus.svcRunning
|
||||||
|
? "正在停止服务并卸载"
|
||||||
|
: "正在请求卸载",
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
if (lifecycleStatus.svcRunning) {
|
||||||
|
const stopRet = await ipcRenderer.invoke(
|
||||||
|
`${IPC_METHOD_BASE}.plsLifecycleControl`,
|
||||||
|
{ target: "stopSvc" }
|
||||||
|
);
|
||||||
|
if (!stopRet.success) {
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
||||||
|
"error",
|
||||||
|
"服务卸载失败: 无法停止服务",
|
||||||
|
"<p>检查日志以获取详细信息</p><p>您可以尝试手动停止 PLS 服务</p>",
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
lifecycleStatus.svcRunning = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const ret = await ipcRenderer.invoke(
|
||||||
|
`${IPC_METHOD_BASE}.plsLifecycleControl`,
|
||||||
|
{ target: "rmSvc" }
|
||||||
|
);
|
||||||
|
if (ret.success) {
|
||||||
|
lifecycleStatus.svcInstalled = false;
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
||||||
|
"success",
|
||||||
|
"服务卸载成功",
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
2000
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
||||||
|
"error",
|
||||||
|
"服务卸载失败",
|
||||||
|
"<p>检查日志以获取详细信息</p>",
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateStatusContent();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "Start":
|
||||||
|
btnEl.onclick = async () => {
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateOperationBtnStatus(
|
||||||
|
"Start",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
||||||
|
"info",
|
||||||
|
"正在请求启动",
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
const ret = await ipcRenderer.invoke(
|
||||||
|
`${IPC_METHOD_BASE}.plsLifecycleControl`,
|
||||||
|
{ target: "startSvc" }
|
||||||
|
);
|
||||||
|
if (ret.success) {
|
||||||
|
lifecycleStatus.svcRunning = true;
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateStatusContent();
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
||||||
|
"success",
|
||||||
|
"PLS 已启动",
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
2000
|
||||||
|
);
|
||||||
|
await global.__HUGO_AURA_GLOBAL__.utils.sleep(100);
|
||||||
|
await ipcRenderer.invoke(`${IPC_METHOD_BASE}.retryPlsConnect`);
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateStatusContent();
|
||||||
|
} else {
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateStatusContent();
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
||||||
|
"error",
|
||||||
|
"PLS 启动失败",
|
||||||
|
"<p>检查 PLS 日志目录以获取详细信息</p>",
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case "Stop":
|
||||||
|
btnEl.onclick = async () => {
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateOperationBtnStatus(
|
||||||
|
"Stop",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
||||||
|
"info",
|
||||||
|
"正在请求停止",
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
const ret = await ipcRenderer.invoke(
|
||||||
|
`${IPC_METHOD_BASE}.plsLifecycleControl`,
|
||||||
|
{ target: "stopSvc" }
|
||||||
|
);
|
||||||
|
if (ret.success) {
|
||||||
|
lifecycleStatus.svcRunning = false;
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
||||||
|
"success",
|
||||||
|
"PLS 已停止",
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
2000
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
||||||
|
"error",
|
||||||
|
"PLS 停止失败",
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateStatusContent();
|
||||||
|
}
|
||||||
|
};
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -35,32 +342,68 @@ if (!global.__HUGO_AURA_UI_FUNCTIONS__.subConfig)
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
updateStatus: async () => {
|
updateStatusContent: async () => {
|
||||||
const curPlsStats = await updatePlsStatusFromLocal();
|
const curPlsStats = await updatePlsStatusFromLocal();
|
||||||
|
|
||||||
const acIdInst = "acs-bc-psp-installStatus-container";
|
const acIdInst = "acs-bc-psp-installStatus-container";
|
||||||
const atIdInst = "acs-bc-psp-installStatus-text";
|
const atIdInst = "acs-bc-psp-installStatus-text";
|
||||||
switch (curPlsStats.installed) {
|
switch (lifecycleStatus.installed) {
|
||||||
case true:
|
case true:
|
||||||
updateStatusEl(acIdInst, atIdInst, "SUCCESS", "已安装");
|
if (!lifecycleStatus.svcInstalled) {
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Install", false);
|
updateStatusEl(acIdInst, atIdInst, "WARNING", "已下载, 服务未安装");
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Uninstall", false);
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Install", false);
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus(
|
||||||
|
"Uninstall",
|
||||||
|
false,
|
||||||
|
"删除内核"
|
||||||
|
);
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Start", true);
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Stop", true);
|
||||||
|
} else {
|
||||||
|
updateStatusEl(acIdInst, atIdInst, "SUCCESS", "已安装");
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Install", true);
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus(
|
||||||
|
"Uninstall",
|
||||||
|
false,
|
||||||
|
"卸载服务"
|
||||||
|
);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case false:
|
case false:
|
||||||
updateStatusEl(acIdInst, atIdInst, "PENDING", "未安装");
|
updateStatusEl(acIdInst, atIdInst, "PENDING", "未下载");
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Download", false);
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Install", true);
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Install", true);
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Uninstall", true);
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Uninstall", true);
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Start", true);
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Stop", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
const acIdLaunch = "acs-bc-psp-launchStatus-container";
|
const acIdLaunch = "acs-bc-psp-launchStatus-container";
|
||||||
const atIdLaunch = "acs-bc-psp-launchStatus-text";
|
const atIdLaunch = "acs-bc-psp-launchStatus-text";
|
||||||
switch (curPlsStats.launched) {
|
|
||||||
case true:
|
if (lifecycleStatus.detached) {
|
||||||
updateStatusEl(acIdLaunch, atIdLaunch, "SUCCESS", "已启动");
|
updateStatusEl(acIdLaunch, atIdLaunch, "INFO", "已分离");
|
||||||
break;
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Start", true);
|
||||||
case false:
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Stop", true);
|
||||||
updateStatusEl(acIdLaunch, atIdLaunch, "PENDING", "未启动");
|
} else if (lifecycleStatus.svcInstalled && lifecycleStatus.installed) {
|
||||||
break;
|
switch (lifecycleStatus.svcRunning || curPlsStats.launched) {
|
||||||
|
case true:
|
||||||
|
if (curPlsStats.status !== "notReady") {
|
||||||
|
updateStatusEl(acIdLaunch, atIdLaunch, "SUCCESS", "已启动");
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Start", true);
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Stop", false);
|
||||||
|
} else {
|
||||||
|
updateStatusEl(acIdLaunch, atIdLaunch, "WARNING", "启动中");
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Start", true);
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Stop", false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case false:
|
||||||
|
updateStatusEl(acIdLaunch, atIdLaunch, "PENDING", "未启动");
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Start", false);
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Stop", true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const acIdConn = "acs-bc-psp-connStatus-container";
|
const acIdConn = "acs-bc-psp-connStatus-container";
|
||||||
@@ -70,7 +413,11 @@ if (!global.__HUGO_AURA_UI_FUNCTIONS__.subConfig)
|
|||||||
updateStatusEl(acIdConn, atIdConn, "SUCCESS", "已连接");
|
updateStatusEl(acIdConn, atIdConn, "SUCCESS", "已连接");
|
||||||
break;
|
break;
|
||||||
case false:
|
case false:
|
||||||
updateStatusEl(acIdConn, atIdConn, "FAILED", "连接失败");
|
if (curPlsStats.status !== "notReady") {
|
||||||
|
updateStatusEl(acIdConn, atIdConn, "FAILED", "连接失败");
|
||||||
|
} else {
|
||||||
|
updateStatusEl(acIdConn, atIdConn, "PENDING", "等待启动");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +429,61 @@ if (!global.__HUGO_AURA_UI_FUNCTIONS__.subConfig)
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
refreshPlsStatus: async () => {
|
refreshPlsStatus: async (init = false) => {
|
||||||
|
const binExistsRet = await ipcRenderer.invoke(
|
||||||
|
`${IPC_METHOD_BASE}.getPlsBinExists`
|
||||||
|
);
|
||||||
|
if (binExistsRet.success && binExistsRet.data.isExists) {
|
||||||
|
lifecycleStatus.installed = true;
|
||||||
|
} else {
|
||||||
|
lifecycleStatus.installed = false;
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
||||||
|
"error",
|
||||||
|
"请下载 PLS 内核以继续",
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
3000
|
||||||
|
);
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateStatusContent();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isDetachedRet = await ipcRenderer.invoke(
|
||||||
|
`${IPC_METHOD_BASE}.plsLifecycleQuery`,
|
||||||
|
{ target: "isDetached" }
|
||||||
|
);
|
||||||
|
if (isDetachedRet.success && isDetachedRet.result) {
|
||||||
|
lifecycleStatus.detached = true;
|
||||||
|
} else {
|
||||||
|
lifecycleStatus.detached = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isSvcInstalledRet = await ipcRenderer.invoke(
|
||||||
|
`${IPC_METHOD_BASE}.plsLifecycleQuery`,
|
||||||
|
{ target: "isSvcInstalled" }
|
||||||
|
);
|
||||||
|
if (isSvcInstalledRet.success && isSvcInstalledRet.result) {
|
||||||
|
lifecycleStatus.svcInstalled = true;
|
||||||
|
} else {
|
||||||
|
lifecycleStatus.svcInstalled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isSvcRunningRet = await ipcRenderer.invoke(
|
||||||
|
`${IPC_METHOD_BASE}.plsLifecycleQuery`,
|
||||||
|
{ target: "isSvcStart" }
|
||||||
|
);
|
||||||
|
if (isSvcRunningRet.success && isSvcRunningRet.result) {
|
||||||
|
lifecycleStatus.svcRunning = true;
|
||||||
|
} else {
|
||||||
|
lifecycleStatus.svcRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (init) {
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateStatusContent();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const updateOperationBtnStatus =
|
const updateOperationBtnStatus =
|
||||||
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus
|
||||||
.updateOperationBtnStatus;
|
.updateOperationBtnStatus;
|
||||||
@@ -95,16 +496,109 @@ if (!global.__HUGO_AURA_UI_FUNCTIONS__.subConfig)
|
|||||||
|
|
||||||
ipcRenderer.once(
|
ipcRenderer.once(
|
||||||
`${IPC_METHOD_BASE}.post.updateRetryStatus`,
|
`${IPC_METHOD_BASE}.post.updateRetryStatus`,
|
||||||
async (_evt, _arg) => {
|
async (_evt, arg) => {
|
||||||
await global.__HUGO_AURA_GLOBAL__.utils.sleep(50);
|
await global.__HUGO_AURA_GLOBAL__.utils.sleep(50);
|
||||||
updateOperationBtnStatus("Refresh", false, "刷新状态");
|
updateOperationBtnStatus("Refresh", false, "刷新状态");
|
||||||
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateStatus();
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
||||||
|
arg.success ? "success" : "error",
|
||||||
|
arg.success ? "更新成功" : "连接失败",
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
3000
|
||||||
|
);
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateStatusContent();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else if (result.success && result.status === "Already") {
|
} else if (result.success && result.status === "Already") {
|
||||||
updateOperationBtnStatus("Refresh", false, "刷新状态");
|
updateOperationBtnStatus("Refresh", false, "刷新状态");
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
||||||
|
"success",
|
||||||
|
"更新成功",
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
3000
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
downloadPLSBin: async () => {
|
||||||
|
const GLOBAL_FUNCTIONS =
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus;
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Download", true, "正在检查");
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Refresh", true);
|
||||||
|
const CUR_CHANNEL = `${IPC_METHOD_BASE}.post.reportPlsDownloadStatus`;
|
||||||
|
await ipcRenderer.invoke(`${IPC_METHOD_BASE}.ensurePlsInstallDir`);
|
||||||
|
GLOBAL_FUNCTIONS.updateToast(
|
||||||
|
"info",
|
||||||
|
"准备开始下载...",
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
2000
|
||||||
|
);
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Download", true, "等待下载");
|
||||||
|
|
||||||
|
const callbackFn = (_evt, info) => {
|
||||||
|
switch (info.status) {
|
||||||
|
case "failed":
|
||||||
|
GLOBAL_FUNCTIONS.updateToast(
|
||||||
|
"error",
|
||||||
|
"下载失败",
|
||||||
|
`<p>${
|
||||||
|
info.message ? info.message : "检查日志以获取错误信息"
|
||||||
|
}</p>`,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
5000
|
||||||
|
);
|
||||||
|
ipcRenderer.off(CUR_CHANNEL, callbackFn);
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Refresh", false);
|
||||||
|
break;
|
||||||
|
case "done":
|
||||||
|
GLOBAL_FUNCTIONS.updateToast(
|
||||||
|
"success",
|
||||||
|
"下载成功",
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
2500
|
||||||
|
);
|
||||||
|
ipcRenderer.off(CUR_CHANNEL, callbackFn);
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Refresh", false);
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus(
|
||||||
|
"Download",
|
||||||
|
true,
|
||||||
|
"下载内核"
|
||||||
|
);
|
||||||
|
lifecycleStatus.installed = true;
|
||||||
|
GLOBAL_FUNCTIONS.updateStatusContent();
|
||||||
|
break;
|
||||||
|
case "waiting":
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus(
|
||||||
|
"Download",
|
||||||
|
true,
|
||||||
|
"等待中..."
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "progressing":
|
||||||
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus(
|
||||||
|
"Download",
|
||||||
|
true,
|
||||||
|
`下载 ${Math.round(info.progress)}%`
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ipcRenderer.on(CUR_CHANNEL, callbackFn);
|
||||||
|
|
||||||
|
ipcRenderer.invoke(`$aura.pls.downloadPls`, {
|
||||||
|
channel: "stable",
|
||||||
|
reportTo: "assistant",
|
||||||
|
});
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const GLOBAL_FUNCTIONS =
|
const GLOBAL_FUNCTIONS =
|
||||||
@@ -147,6 +641,9 @@ if (!global.__HUGO_AURA_UI_FUNCTIONS__.subConfig)
|
|||||||
areaContainerEl.className =
|
areaContainerEl.className =
|
||||||
"acs-bc-pls-status-page-status-area warning";
|
"acs-bc-pls-status-page-status-area warning";
|
||||||
break;
|
break;
|
||||||
|
case "INFO":
|
||||||
|
areaContainerEl.className = "acs-bc-pls-status-page-status-area info";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -155,12 +652,18 @@ if (!global.__HUGO_AURA_UI_FUNCTIONS__.subConfig)
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onMounted = () => {
|
const onMounted = () => {
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Refresh", false);
|
|
||||||
initBsTooltip();
|
initBsTooltip();
|
||||||
GLOBAL_FUNCTIONS.updateStatus();
|
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Refresh", false);
|
||||||
document.addEventListener("onPLSStatsUpdate", () => {
|
GLOBAL_FUNCTIONS.refreshPlsStatus(true);
|
||||||
GLOBAL_FUNCTIONS.updateStatus();
|
|
||||||
});
|
const eventListener = () => {
|
||||||
|
GLOBAL_FUNCTIONS.updateStatusContent();
|
||||||
|
};
|
||||||
|
document.addEventListener("onPLSStatsUpdate", eventListener);
|
||||||
|
global.__HUGO_AURA_GLOBAL__.utils.createOnLeaveEvtListener(
|
||||||
|
"onPLSStatsUpdate",
|
||||||
|
eventListener
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted();
|
onMounted();
|
||||||
|
|||||||
@@ -4,53 +4,48 @@ const {
|
|||||||
updatePlsConfigToRemote,
|
updatePlsConfigToRemote,
|
||||||
} = require(`${REQUIRE_BASE}/../../../../composables/plsConfigManager`);
|
} = require(`${REQUIRE_BASE}/../../../../composables/plsConfigManager`);
|
||||||
|
|
||||||
|
const reusableChkFn = {
|
||||||
|
checkRelativePath: () => {
|
||||||
|
if (newVal === "" || !newVal)
|
||||||
|
return { valid: false, hint: "请输入证书路径" };
|
||||||
|
|
||||||
|
if (newVal.includes(":/") || newVal.includes(":\\")) {
|
||||||
|
return { valid: false, hint: "请输入相对路径, 而非绝对路径" };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newVal.includes("\\")) {
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
hint: '请输入正确的路径, 使用 "/" 作为路径符',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
valid: true,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const basicSettings = [
|
const basicSettings = [
|
||||||
{
|
{
|
||||||
id: 0,
|
id: 0,
|
||||||
categoryName: "可访问性",
|
categoryName: "可访问性",
|
||||||
child: [
|
child: [
|
||||||
/*
|
|
||||||
{
|
|
||||||
index: 0,
|
|
||||||
id: "authToken",
|
|
||||||
type: "input",
|
|
||||||
subType: "text",
|
|
||||||
name: "WebSocket 认证密钥",
|
|
||||||
description: "选择一个安全的密钥, 用于 PLS 侧验证 Aura 前端身份",
|
|
||||||
restart: true,
|
|
||||||
reload: false,
|
|
||||||
restartPLS: true,
|
|
||||||
associateVal: null,
|
|
||||||
auraIf: () => true,
|
|
||||||
defaultValue: "",
|
|
||||||
placeHolder: "输入一个密钥",
|
|
||||||
valueGetter: () => {
|
|
||||||
return global.__HUGO_AURA_CONFIG__.plsToken;
|
|
||||||
},
|
|
||||||
callbackFn: (newVal) => {
|
|
||||||
if (newVal === "" || !newVal)
|
|
||||||
return { valid: false, hint: "请输入认证密钥" };
|
|
||||||
|
|
||||||
if (newVal.length < 8) {
|
|
||||||
return { valid: false, hint: "至少输入 8 位字符" };
|
|
||||||
}
|
|
||||||
|
|
||||||
global.__HUGO_AURA_CONFIG__.plsToken = newVal;
|
|
||||||
return { valid: true };
|
|
||||||
},
|
|
||||||
},
|
|
||||||
*/
|
|
||||||
{
|
{
|
||||||
index: 0,
|
index: 0,
|
||||||
id: "plsListenPort",
|
id: "plsListenPort",
|
||||||
type: "input",
|
type: "input",
|
||||||
subType: "text",
|
subType: "number",
|
||||||
name: "PLS WS 监听端口",
|
name: "PLS WS 默认监听端口",
|
||||||
description: "PLS 的 WebSocket 服务器将监听指定的端口",
|
description: "PLS 的 WebSocket 服务器将默认监听指定的端口",
|
||||||
|
reactive: true,
|
||||||
|
reactiveVal: ["root.settings"],
|
||||||
restart: false,
|
restart: false,
|
||||||
reload: false,
|
reload: false,
|
||||||
PLSRequired: true,
|
PLSRequired: true,
|
||||||
restartPLS: true,
|
restartPLS: false,
|
||||||
|
warning: true,
|
||||||
|
warningContent: "PLS 仍会在默认端口被占用时, 自动随机端口重试",
|
||||||
associateVal: null,
|
associateVal: null,
|
||||||
auraIf: () => true,
|
auraIf: () => true,
|
||||||
defaultValue: "",
|
defaultValue: "",
|
||||||
@@ -64,14 +59,114 @@ const basicSettings = [
|
|||||||
return { valid: false, hint: "请输入端口号" };
|
return { valid: false, hint: "请输入端口号" };
|
||||||
|
|
||||||
const numberNewVal = Number(newVal);
|
const numberNewVal = Number(newVal);
|
||||||
if (numberNewVal === NaN || !(10000 <= numberNewVal <= 65535)) {
|
if (numberNewVal === NaN || !(10000 <= numberNewVal) || !(newVal <= 65535)) {
|
||||||
return { valid: false, hint: "请输入合法的端口号 (10000 ~ 65535)" };
|
return { valid: false, hint: "请输入合法的端口号 (10000 ~ 65535)" };
|
||||||
}
|
}
|
||||||
|
|
||||||
global.__HUGO_AURA__.plsSettings.wsPort = numberNewVal;
|
global.__HUGO_AURA__.plsSettings.wsPort = numberNewVal;
|
||||||
|
updatePlsConfigToRemote("wsPort", numberNewVal);
|
||||||
return { valid: true };
|
return { valid: true };
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
index: 1,
|
||||||
|
id: "plsCertPath",
|
||||||
|
type: "input",
|
||||||
|
subType: "text",
|
||||||
|
name: "WSS TLS 证书相对路径",
|
||||||
|
description: "PLS 将使用指定路径下的证书启动 WSS 服务器",
|
||||||
|
reactive: true,
|
||||||
|
reactiveVal: ["root.settings"],
|
||||||
|
restart: false,
|
||||||
|
reload: false,
|
||||||
|
PLSRequired: true,
|
||||||
|
restartPLS: true,
|
||||||
|
tip: true,
|
||||||
|
tipTitle:
|
||||||
|
'路径相对于 "%PROGRAMDATA%\\HugoAura\\Aura-PLS\\", 使用 "/" 作为路径符',
|
||||||
|
associateVal: null,
|
||||||
|
auraIf: () => true,
|
||||||
|
defaultValue: "",
|
||||||
|
placeHolder: "输入相对路径, 例如: config/vme50/cert.crt",
|
||||||
|
valueGetter: () => {
|
||||||
|
if (!global.__HUGO_AURA__.plsSettings) return "";
|
||||||
|
return global.__HUGO_AURA__.plsSettings.certPath;
|
||||||
|
},
|
||||||
|
callbackFn: (newVal) => {
|
||||||
|
const validate = reusableChkFn.checkRelativePath();
|
||||||
|
if (!validate.valid) {
|
||||||
|
return validate;
|
||||||
|
}
|
||||||
|
|
||||||
|
global.__HUGO_AURA__.plsSettings.certPath = newVal;
|
||||||
|
updatePlsConfigToRemote("certPath", newVal);
|
||||||
|
return { valid: true };
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 2,
|
||||||
|
id: "plsCertPath",
|
||||||
|
type: "input",
|
||||||
|
subType: "text",
|
||||||
|
name: "WSS TLS 证书私钥相对路径",
|
||||||
|
description: "PLS 将使用指定路径下的私钥启动 WSS 服务器",
|
||||||
|
reactive: true,
|
||||||
|
reactiveVal: ["root.settings"],
|
||||||
|
restart: false,
|
||||||
|
reload: false,
|
||||||
|
PLSRequired: true,
|
||||||
|
restartPLS: true,
|
||||||
|
tip: true,
|
||||||
|
tipTitle:
|
||||||
|
'路径相对于 "%PROGRAMDATA%\\HugoAura\\Aura-PLS\\", 使用 "/" 作为路径符',
|
||||||
|
warning: true,
|
||||||
|
warningContent: "请使用 PEM 格式的密钥",
|
||||||
|
associateVal: null,
|
||||||
|
auraIf: () => true,
|
||||||
|
defaultValue: "",
|
||||||
|
placeHolder: "输入相对路径, 例如: config/vme50/cert.key",
|
||||||
|
valueGetter: () => {
|
||||||
|
if (!global.__HUGO_AURA__.plsSettings) return "";
|
||||||
|
return global.__HUGO_AURA__.plsSettings.keyPath;
|
||||||
|
},
|
||||||
|
callbackFn: (newVal) => {
|
||||||
|
const validate = reusableChkFn.checkRelativePath();
|
||||||
|
if (!validate.valid) {
|
||||||
|
return validate;
|
||||||
|
}
|
||||||
|
|
||||||
|
global.__HUGO_AURA__.plsSettings.keyPath = newVal;
|
||||||
|
updatePlsConfigToRemote("keyPath", newVal);
|
||||||
|
return { valid: true };
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 3,
|
||||||
|
id: "plsRegenCertAftRelaunch",
|
||||||
|
type: "switch",
|
||||||
|
name: "重新生成 TLS 证书",
|
||||||
|
description: "PLS 将在下次启动时重新生成 TLS 证书",
|
||||||
|
reactive: true,
|
||||||
|
reactiveVal: ["root.settings"],
|
||||||
|
restart: false,
|
||||||
|
reload: false,
|
||||||
|
PLSRequired: true,
|
||||||
|
restartPLS: true,
|
||||||
|
associateVal: null,
|
||||||
|
auraIf: () => true,
|
||||||
|
defaultValue: false,
|
||||||
|
valueGetter: () => {
|
||||||
|
if (!global.__HUGO_AURA__.plsSettings) return "";
|
||||||
|
return global.__HUGO_AURA__.plsSettings.regenCert;
|
||||||
|
},
|
||||||
|
callbackFn: (newVal) => {
|
||||||
|
if (typeof newVal !== "boolean") return false;
|
||||||
|
|
||||||
|
global.__HUGO_AURA__.plsSettings.regenCert = newVal;
|
||||||
|
updatePlsConfigToRemote("regenCert", newVal);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
99
src/aura/ui/pages/configSubPages/behaviourCtrl/settings/deviceSecurity.js
Executable file
99
src/aura/ui/pages/configSubPages/behaviourCtrl/settings/deviceSecurity.js
Executable file
@@ -0,0 +1,99 @@
|
|||||||
|
const REQUIRE_BASE = ".";
|
||||||
|
|
||||||
|
const {
|
||||||
|
updatePlsConfigToRemote,
|
||||||
|
} = require(`${REQUIRE_BASE}/../../../../composables/plsConfigManager`);
|
||||||
|
|
||||||
|
const composables = {};
|
||||||
|
|
||||||
|
const deviceSecuritySettings = [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
categoryName: "冰点管理",
|
||||||
|
child: [
|
||||||
|
{
|
||||||
|
index: 0,
|
||||||
|
id: "enableFreezeInfoReportOverride",
|
||||||
|
type: "switch",
|
||||||
|
name: "启用冰冻状态篡改",
|
||||||
|
description: "篡改上报的冰冻数据, 可自定义集控端显示的状态",
|
||||||
|
reactive: true,
|
||||||
|
reactiveVal: ["root.ruleSettings"],
|
||||||
|
restart: false,
|
||||||
|
reload: false,
|
||||||
|
PLSRequired: true,
|
||||||
|
restartPLS: false,
|
||||||
|
associateVal: null,
|
||||||
|
auraIf: () => true,
|
||||||
|
defaultValue: false,
|
||||||
|
valueGetter: () => {
|
||||||
|
if (!global.__HUGO_AURA__.plsRules) return "";
|
||||||
|
return global.__HUGO_AURA__.plsRules.client.security.uploadFreezeInfo
|
||||||
|
.enable;
|
||||||
|
},
|
||||||
|
callbackFn: (newVal) => {
|
||||||
|
if (typeof newVal !== "boolean") return;
|
||||||
|
if (!global.__HUGO_AURA__.plsRules) return;
|
||||||
|
|
||||||
|
global.__HUGO_AURA__.plsRules.client.security.uploadFreezeInfo.enable =
|
||||||
|
newVal;
|
||||||
|
updatePlsConfigToRemote(
|
||||||
|
"ruleSettings.client.security.uploadFreezeInfo.enable",
|
||||||
|
newVal
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 1,
|
||||||
|
id: "freezeInfoReportOverrideType",
|
||||||
|
type: "radio",
|
||||||
|
name: "篡改模式",
|
||||||
|
description:
|
||||||
|
"选择一种篡改模式, 选中的磁盘范围会<b>被上报</b>为冻结 (不是实际行为)",
|
||||||
|
restart: false,
|
||||||
|
reload: false,
|
||||||
|
PLSRequired: true,
|
||||||
|
restartPLS: false,
|
||||||
|
reactive: true,
|
||||||
|
reactiveVal: ["root.ruleSettings"],
|
||||||
|
associateVal: ["ruleSettings.client.security.uploadFreezeInfo.enable"],
|
||||||
|
auraIf: () => {
|
||||||
|
if (!global.__HUGO_AURA__.plsRules) return true;
|
||||||
|
|
||||||
|
return global.__HUGO_AURA__.plsRules.client.security.uploadFreezeInfo
|
||||||
|
.enable;
|
||||||
|
},
|
||||||
|
defaultValue: "allFreeze",
|
||||||
|
templates: ["allFreeze", "systemOnly", "exceptSecondDisk"],
|
||||||
|
templateLabels: ["全部冻结", "仅系统盘", "第二磁盘除外"],
|
||||||
|
valueGetter: () => {
|
||||||
|
if (!global.__HUGO_AURA__.plsRules) return;
|
||||||
|
|
||||||
|
return global.__HUGO_AURA__.plsRules.client.security.uploadFreezeInfo
|
||||||
|
.rewriteMode;
|
||||||
|
},
|
||||||
|
callbackFn: (newVal) => {
|
||||||
|
global.__HUGO_AURA__.plsRules.client.security.uploadFreezeInfo.rewriteMode =
|
||||||
|
newVal;
|
||||||
|
updatePlsConfigToRemote(
|
||||||
|
"ruleSettings.client.security.uploadFreezeInfo.rewriteMode",
|
||||||
|
newVal
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 2,
|
||||||
|
id: "freezeInfoReportOverridePreview",
|
||||||
|
type: "preview",
|
||||||
|
loaderTarget:
|
||||||
|
"Aura.UI.Assistant.Config.BehaviourCtrl.DeviceSecurity.FreezeOverridePreview",
|
||||||
|
associateVal: ["ruleSettings.client.security.uploadFreezeInfo"],
|
||||||
|
listenerType: "pls",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
module.exports = { deviceSecuritySettings };
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
.acs-bc-dsc-fop-container {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-dsc-fop-please-wait,
|
||||||
|
.acs-bc-dsc-fop-on-req-error,
|
||||||
|
.acs-bc-dsc-fop-on-not-bind {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-dsc-fop-please-wait svg,
|
||||||
|
.acs-bc-dsc-fop-on-req-error svg,
|
||||||
|
.acs-bc-dsc-fop-on-not-bind svg {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-dsc-fop-please-wait p,
|
||||||
|
.acs-bc-dsc-fop-on-req-error p,
|
||||||
|
.acs-bc-dsc-fop-on-not-bind p {
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
margin-top: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-dsc-fop-please-wait[auraIf="false"],
|
||||||
|
.acs-bc-dsc-fop-on-req-error[auraIf="false"],
|
||||||
|
.acs-bc-dsc-fop-on-not-bind[auraIf="false"],
|
||||||
|
.acs-bc-dsc-fop-main[auraIf="false"] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-dsc-fop-main {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-dsc-fop-main .disks-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-dsc-fop-disk-el {
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 0.5px solid rgba(0, 0, 0, 0.25);
|
||||||
|
margin-left: 0.375rem;
|
||||||
|
margin-right: 0.375rem;
|
||||||
|
|
||||||
|
transition: all 0.5s;
|
||||||
|
/* 没有用, 因为元素全被重新创建了 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-dsc-fop-disk-el.active {
|
||||||
|
background-color: #1d70f2;
|
||||||
|
color: white;
|
||||||
|
border: 0.5px solid rgba(0, 0, 0, 0.125);
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-dsc-fop-disk-el.active:hover {
|
||||||
|
background-color: #4e8df2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-dsc-fop-main-hint-area {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-top: 1rem;
|
||||||
|
margin-bottom: -0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-dsc-fop-main-hint-area svg {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-dsc-fop-main-hint-area div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-dsc-fop-main-hint-area p {
|
||||||
|
margin-top: -1px;
|
||||||
|
margin-left: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-dsc-fop-main-hint-area .acs-bc-dsc-fop-main-hint-freeze {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
color: #1d70f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.acs-bc-dsc-fop-main-hint-area .acs-bc-dsc-fop-main-hint-unfreeze {
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
<div class="acs-bc-dsc-fop-container">
|
||||||
|
<div class="acs-bc-dsc-fop-please-wait" auraIf="true">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
viewBox="0 0 32 32"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M16 30a14 14 0 1 1 14-14a14 14 0 0 1-14 14m0-26a12 12 0 1 0 12 12A12 12 0 0 0 16 4"
|
||||||
|
/>
|
||||||
|
<path fill="currentColor" d="M20.59 22L15 16.41V7h2v8.58l5 5.01z" />
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<p>请稍候...</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="acs-bc-dsc-fop-on-req-error" auraIf="false">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
viewBox="0 0 32 32"
|
||||||
|
>
|
||||||
|
<path fill="currentColor" d="M9 10.555L10.555 9L23 21.444L21.444 23z" />
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M16 2A13.914 13.914 0 0 0 2 16a13.914 13.914 0 0 0 14 14a13.914 13.914 0 0 0 14-14A13.914 13.914 0 0 0 16 2m0 26a12 12 0 1 1 12-12a12.035 12.035 0 0 1-12 12"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<p>获取磁盘信息失败: <font id="acsBcDscFopOnReqErrorDetail"></font></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="acs-bc-dsc-fop-on-not-bind" auraIf="false">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
viewBox="0 0 32 32"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M31.324 11.261A14.27 14.27 0 0 0 22.25 8H22v2h.25c2.608 0 5.155.837 7.246 2.372a12.18 12.18 0 0 1-7.548 7.036q.052-.605.052-1.22C22 10.366 15.635 4 7.812 4c-.929 0-1.856.09-2.757.268l-.657.13l-.13.657A14.3 14.3 0 0 0 4 7.812c0 4.124 1.78 7.831 4.598 10.426A14.2 14.2 0 0 0 8 22.254l.001.001a14.27 14.27 0 0 0 3.261 9.07l.439.53l.652-.22a14.18 14.18 0 0 0 9.237-10.046a14.18 14.18 0 0 0 10.045-9.237l.22-.652zM12.372 29.496A12.27 12.27 0 0 1 10 22.251c0-.912.113-1.796.303-2.652a14.1 14.1 0 0 0 9.105 2.349a12.18 12.18 0 0 1-7.036 7.548m7.51-9.613q-.833.116-1.694.117c-2.715 0-5.218-.904-7.247-2.412a12.4 12.4 0 0 1 4.048-5.204l-1.28-1.53A14.3 14.3 0 0 0 9.37 16.2A12.14 12.14 0 0 1 6.117 6.117A12 12 0 0 1 7.812 6C14.532 6 20 11.468 20 18.188q0 .862-.117 1.695Z"
|
||||||
|
/>
|
||||||
|
<circle cx="20" cy="2" r="2" fill="currentColor" />
|
||||||
|
<circle cx="27" cy="26" r="2" fill="currentColor" />
|
||||||
|
<circle cx="2" cy="20" r="2" fill="currentColor" />
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<p>当前设备暂未绑定学校, 无法查询冰点信息</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="acs-bc-dsc-fop-main" auraIf="false">
|
||||||
|
<div class="disks-container">
|
||||||
|
<p class="acs-bc-dsc-fop-disk-el">C 盘</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="acs-bc-dsc-fop-main-hint-area">
|
||||||
|
<div class="acs-bc-dsc-fop-main-hint-freeze">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
viewBox="0 0 32 32"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M21.415 12H28v-2h-4.585L28 5.415L26.586 4L22 8.587V4h-2v6.587L18.587 12H17V8h-2v4h-1.587L12 10.587V4h-2v4.587L5.414 4L4 5.415L8.585 10H4v2h6.585L12 13.415V15H8v2h4v1.587L10.587 20H4v2h4.587L4 26.586l1.414 1.415L10 23.415V28h2v-6.585L13.415 20H15v4h2v-4h1.585L20 21.415V28h2v-4.585l4.585 4.586L28 26.586L23.413 22H28v-2h-6.587L20 18.587V17h4v-2h-4v-1.585ZM18 18h-4v-4h4Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<p>已冻结</p>
|
||||||
|
</div>
|
||||||
|
<div class="acs-bc-dsc-fop-main-hint-unfreeze">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
viewBox="0 0 32 32"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M16 12.005a4 4 0 1 1-4 4a4.005 4.005 0 0 1 4-4m0-2a6 6 0 1 0 6 6a6 6 0 0 0-6-6M5.394 6.813L6.81 5.399l3.505 3.506L8.9 10.319zM2 15.005h5v2H2zm3.394 10.193L8.9 21.692l1.414 1.414l-3.505 3.506zM15 25.005h2v5h-2zm6.687-1.9l1.414-1.414l3.506 3.506l-1.414 1.414zm3.313-8.1h5v2h-5zm-3.313-6.101l3.506-3.506l1.414 1.414l-3.506 3.506zM15 2.005h2v5h-2z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<p>未冻结</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
(() => {
|
||||||
|
const REQUIRE_BASE = "../..";
|
||||||
|
const { genRandomHex } = require(`${REQUIRE_BASE}/aura/utils/crypto`);
|
||||||
|
|
||||||
|
const composables = {
|
||||||
|
getAndUpdateDiskInfo: async (curConfig) => {
|
||||||
|
const progressingEl = document.getElementsByClassName(
|
||||||
|
"acs-bc-dsc-fop-please-wait"
|
||||||
|
)[0];
|
||||||
|
const onErrorEl = document.getElementsByClassName(
|
||||||
|
"acs-bc-dsc-fop-on-req-error"
|
||||||
|
)[0];
|
||||||
|
const onNotBindEl = document.getElementsByClassName(
|
||||||
|
"acs-bc-dsc-fop-on-not-bind"
|
||||||
|
)[0];
|
||||||
|
const mainEl = document.getElementsByClassName("acs-bc-dsc-fop-main")[0];
|
||||||
|
const diskContainerEl =
|
||||||
|
document.getElementsByClassName("disks-container")[0];
|
||||||
|
|
||||||
|
const seewoProxyPort = window._ACCEPT_DATA.data.ports.SeewoProxyHTTP;
|
||||||
|
|
||||||
|
const reqPromise = new Promise((resolve) => {
|
||||||
|
fetch(
|
||||||
|
`https://127.0.0.1:${seewoProxyPort}/forward/freeze/api/v1/get_disk_data`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
accept: "application/json, text/plain, */*",
|
||||||
|
"X-Auth-Traceid": genRandomHex(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(async (response) => {
|
||||||
|
const parsedData = await response.json();
|
||||||
|
|
||||||
|
resolve({
|
||||||
|
success: true,
|
||||||
|
data: parsedData,
|
||||||
|
status: response.status,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
resolve({ success: false, data: null, errorObj: e });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const responseInfo = await reqPromise;
|
||||||
|
|
||||||
|
progressingEl.setAttribute("auraIf", "false");
|
||||||
|
|
||||||
|
if (!responseInfo.success) {
|
||||||
|
onNotBindEl.setAttribute("auraIf", "false");
|
||||||
|
mainEl.setAttribute("auraIf", "false");
|
||||||
|
onErrorEl.setAttribute("auraIf", "true");
|
||||||
|
const detailEl = document.getElementById("acsBcDscFopOnReqErrorDetail");
|
||||||
|
// @ts-expect-error
|
||||||
|
detailEl.textContent = responseInfo.errorObj;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (responseInfo.status !== 200) {
|
||||||
|
onErrorEl.setAttribute("auraIf", "false");
|
||||||
|
mainEl.setAttribute("auraIf", "false");
|
||||||
|
onNotBindEl.setAttribute("auraIf", "true");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
diskContainerEl.innerHTML = ``;
|
||||||
|
|
||||||
|
const curDisks = [];
|
||||||
|
for (const disk of responseInfo.data.data[0].disksData) {
|
||||||
|
curDisks.push({ name: disk.diskName, status: disk.protectedStatus });
|
||||||
|
}
|
||||||
|
|
||||||
|
const diskElTemplate = document.createElement("p");
|
||||||
|
diskElTemplate.classList.add("acs-bc-dsc-fop-disk-el");
|
||||||
|
if (!curConfig.enable) {
|
||||||
|
for (const disk of curDisks) {
|
||||||
|
const curDiskEl = diskElTemplate.cloneNode();
|
||||||
|
if (disk.status !== 0) {
|
||||||
|
// @ts-expect-error
|
||||||
|
curDiskEl.classList.add("active");
|
||||||
|
}
|
||||||
|
curDiskEl.textContent = `${disk.name.toUpperCase()} 盘`;
|
||||||
|
diskContainerEl.appendChild(curDiskEl);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (curConfig.rewriteMode) {
|
||||||
|
case "allFreeze":
|
||||||
|
{
|
||||||
|
for (const disk of curDisks) {
|
||||||
|
const curDiskEl = diskElTemplate.cloneNode();
|
||||||
|
// @ts-expect-error
|
||||||
|
curDiskEl.classList.add("active");
|
||||||
|
curDiskEl.textContent = `${disk.name.toUpperCase()} 盘`;
|
||||||
|
diskContainerEl.appendChild(curDiskEl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "systemOnly":
|
||||||
|
{
|
||||||
|
let idx = 0;
|
||||||
|
for (const disk of curDisks) {
|
||||||
|
const curDiskEl = diskElTemplate.cloneNode();
|
||||||
|
// @ts-expect-error
|
||||||
|
if (idx === 0) curDiskEl.classList.add("active");
|
||||||
|
curDiskEl.textContent = `${disk.name.toUpperCase()} 盘`;
|
||||||
|
diskContainerEl.appendChild(curDiskEl);
|
||||||
|
idx += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "exceptSecondDisk":
|
||||||
|
{
|
||||||
|
let idx = 0;
|
||||||
|
for (const disk of curDisks) {
|
||||||
|
const curDiskEl = diskElTemplate.cloneNode();
|
||||||
|
// @ts-expect-error
|
||||||
|
if (idx === 0) curDiskEl.classList.add("active");
|
||||||
|
curDiskEl.textContent = `${disk.name.toUpperCase()} 盘`;
|
||||||
|
diskContainerEl.appendChild(curDiskEl);
|
||||||
|
idx += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onErrorEl.setAttribute("auraIf", "false");
|
||||||
|
onNotBindEl.setAttribute("auraIf", "false");
|
||||||
|
mainEl.setAttribute("auraIf", "true");
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const onMounted = () => {
|
||||||
|
const rootEl = document.getElementsByClassName(
|
||||||
|
"acs-bc-dsc-fop-container"
|
||||||
|
)[0];
|
||||||
|
|
||||||
|
const eventListener = (_event) => {
|
||||||
|
if (!global.__HUGO_AURA__.plsRules) return;
|
||||||
|
composables.getAndUpdateDiskInfo(
|
||||||
|
global.__HUGO_AURA__.plsRules.client.security.uploadFreezeInfo
|
||||||
|
);
|
||||||
|
};
|
||||||
|
rootEl.addEventListener("onAssociateValueUpdated", eventListener);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
eventListener();
|
||||||
|
}, 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted();
|
||||||
|
})();
|
||||||
@@ -30,7 +30,7 @@ const functions = {
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "update":
|
case "update":
|
||||||
const result = global.__HUGO_AURA_CONFIG_MGR__.switchToDecConfig(
|
const result = await global.__HUGO_AURA_CONFIG_MGR__.switchToDecConfig(
|
||||||
global.__HUGO_AURA_CONFIG__,
|
global.__HUGO_AURA_CONFIG__,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
@@ -179,7 +179,7 @@ const auraSettings = [
|
|||||||
return global.__HUGO_AURA_CONFIG__.auraSettings
|
return global.__HUGO_AURA_CONFIG__.auraSettings
|
||||||
.settingsPasswordEnabled;
|
.settingsPasswordEnabled;
|
||||||
},
|
},
|
||||||
callbackFn: (newVal) => {
|
callbackFn: async (newVal) => {
|
||||||
if (typeof newVal !== "boolean") return;
|
if (typeof newVal !== "boolean") return;
|
||||||
global.__HUGO_AURA_CONFIG__.auraSettings.settingsPasswordEnabled =
|
global.__HUGO_AURA_CONFIG__.auraSettings.settingsPasswordEnabled =
|
||||||
newVal;
|
newVal;
|
||||||
@@ -192,7 +192,7 @@ const auraSettings = [
|
|||||||
!newVal &&
|
!newVal &&
|
||||||
global.__HUGO_AURA_CONFIG__.auraSettings.encryptConfig
|
global.__HUGO_AURA_CONFIG__.auraSettings.encryptConfig
|
||||||
) {
|
) {
|
||||||
global.__HUGO_AURA_CONFIG_MGR__.switchToDecConfig(
|
await global.__HUGO_AURA_CONFIG_MGR__.switchToDecConfig(
|
||||||
global.__HUGO_AURA_CONFIG__,
|
global.__HUGO_AURA_CONFIG__,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
@@ -220,13 +220,13 @@ const auraSettings = [
|
|||||||
valueGetter: () => {
|
valueGetter: () => {
|
||||||
return global.__HUGO_AURA_CONFIG__.auraSettings.encryptConfig;
|
return global.__HUGO_AURA_CONFIG__.auraSettings.encryptConfig;
|
||||||
},
|
},
|
||||||
callbackFn: (newVal) => {
|
callbackFn: async (newVal) => {
|
||||||
if (typeof newVal !== "boolean") return;
|
if (typeof newVal !== "boolean") return;
|
||||||
global.__HUGO_AURA_CONFIG__.auraSettings.encryptConfig = newVal;
|
global.__HUGO_AURA_CONFIG__.auraSettings.encryptConfig = newVal;
|
||||||
if (newVal) {
|
if (newVal) {
|
||||||
functions.handleEnableConfigEncryption("enc", null);
|
functions.handleEnableConfigEncryption("enc", null);
|
||||||
} else {
|
} else {
|
||||||
global.__HUGO_AURA_CONFIG_MGR__.switchToDecConfig(
|
await global.__HUGO_AURA_CONFIG_MGR__.switchToDecConfig(
|
||||||
global.__HUGO_AURA_CONFIG__,
|
global.__HUGO_AURA_CONFIG__,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -11,8 +11,10 @@ const basicRouteHandler = (parsedWsMsg) => {
|
|||||||
const target = parsedWsMsg.type.split(".").slice(-1)[0];
|
const target = parsedWsMsg.type.split(".").slice(-1)[0];
|
||||||
switch (target) {
|
switch (target) {
|
||||||
case "pushPlsInfo":
|
case "pushPlsInfo":
|
||||||
global.__HUGO_AURA__.plsStats.status = parsedWsMsg.data.status;
|
if (global.__HUGO_AURA__.plsStats) {
|
||||||
global.__HUGO_AURA__.plsStats.version = parsedWsMsg.data.version;
|
global.__HUGO_AURA__.plsStats.status = parsedWsMsg.data.status;
|
||||||
|
global.__HUGO_AURA__.plsStats.version = parsedWsMsg.data.version;
|
||||||
|
}
|
||||||
|
|
||||||
global.ipcRenderer.invoke(
|
global.ipcRenderer.invoke(
|
||||||
`${IPC_METHOD_BASE}.updatePlsStats`,
|
`${IPC_METHOD_BASE}.updatePlsStats`,
|
||||||
@@ -24,6 +26,19 @@ const basicRouteHandler = (parsedWsMsg) => {
|
|||||||
global.__HUGO_AURA__.plsStats
|
global.__HUGO_AURA__.plsStats
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "plsNotReadyError":
|
||||||
|
if (global.__HUGO_AURA__.plsStats) {
|
||||||
|
global.__HUGO_AURA__.plsStats.launched = true;
|
||||||
|
global.__HUGO_AURA__.plsStats.connected = false;
|
||||||
|
global.__HUGO_AURA__.plsStats.status = "notReady";
|
||||||
|
}
|
||||||
|
|
||||||
|
global.ipcRenderer.invoke(
|
||||||
|
`${IPC_METHOD_BASE}.updatePlsStats`,
|
||||||
|
global.__HUGO_AURA__.plsStats
|
||||||
|
);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
14
src/aura/utils/crypto.js
Executable file
14
src/aura/utils/crypto.js
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
const genRandomHex = () => {
|
||||||
|
let result = "";
|
||||||
|
for (let i = 0; i < 8; i++) {
|
||||||
|
const randomNum = Math.floor(Math.random() * 0x10000);
|
||||||
|
result += randomNum.toString(16).padStart(4, "0");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = { genRandomHex };
|
||||||
@@ -16,6 +16,16 @@ if (!global.__HUGO_AURA__) {
|
|||||||
global.__HUGO_AURA__ = __HUGO_AURA__;
|
global.__HUGO_AURA__ = __HUGO_AURA__;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!global.__HUGO_AURA_API__) {
|
||||||
|
/** @type {import("../aura/types/shared/global").GlobalHugoAuraApiInfo} */
|
||||||
|
const __HUGO_AURA_API__ = {
|
||||||
|
baseUrl: "https://api-aura.xwx.li",
|
||||||
|
plsUpdate: "/api/v1/getPLSLatestVersion",
|
||||||
|
auraUpdate: "/api/v1/getAuraLatestVersion",
|
||||||
|
};
|
||||||
|
global.__HUGO_AURA_API__ = __HUGO_AURA_API__;
|
||||||
|
}
|
||||||
|
|
||||||
if (!global.__HUGO_AURA_CONFIG__) {
|
if (!global.__HUGO_AURA_CONFIG__) {
|
||||||
global.__HUGO_AURA_CONFIG__ = {};
|
global.__HUGO_AURA_CONFIG__ = {};
|
||||||
}
|
}
|
||||||
@@ -134,7 +144,8 @@ const launcher = ({ central, windowName, config }) => {
|
|||||||
configManager.ensureConfigExists();
|
configManager.ensureConfigExists();
|
||||||
const loadedConfig = configManager.loadConfig();
|
const loadedConfig = configManager.loadConfig();
|
||||||
if (!global.__HUGO_AURA__.configInit) global.__HUGO_AURA__.configInit = true;
|
if (!global.__HUGO_AURA__.configInit) global.__HUGO_AURA__.configInit = true;
|
||||||
if (!global.__HUGO_AURA_CONFIG_MGR__) global.__HUGO_AURA_CONFIG_MGR__ = configManager;
|
if (!global.__HUGO_AURA_CONFIG_MGR__)
|
||||||
|
global.__HUGO_AURA_CONFIG_MGR__ = configManager;
|
||||||
|
|
||||||
global.__HUGO_AURA_CONFIG__ = loadedConfig;
|
global.__HUGO_AURA_CONFIG__ = loadedConfig;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
const __AURA_VERSION__ = "0.1.1-pre-III";
|
const __AURA_VERSION__ = "0.1.1-pre-IV";
|
||||||
|
|
||||||
(() => {
|
(() => {
|
||||||
if (require.main) return; // 如果只是导入 Aura Version, 不运行闭包逻辑
|
if (require.main) return; // 如果只是导入 Aura Version, 不运行闭包逻辑
|
||||||
@@ -63,6 +63,15 @@ const __AURA_VERSION__ = "0.1.1-pre-III";
|
|||||||
});
|
});
|
||||||
const pathName = [...path, prop].join(".");
|
const pathName = [...path, prop].join(".");
|
||||||
document.dispatchEvent(configUpdateEvent);
|
document.dispatchEvent(configUpdateEvent);
|
||||||
|
|
||||||
|
const settingsEntries = document.getElementsByClassName(
|
||||||
|
"aura-settings-entry"
|
||||||
|
);
|
||||||
|
if (settingsEntries.length > 0) {
|
||||||
|
Array.from(settingsEntries).forEach((entry) => {
|
||||||
|
entry.dispatchEvent(configUpdateEvent);
|
||||||
|
});
|
||||||
|
}
|
||||||
console.log(
|
console.log(
|
||||||
`[HugoAura / Config] Config changed at path: ${[...path, prop].join(
|
`[HugoAura / Config] Config changed at path: ${[...path, prop].join(
|
||||||
"."
|
"."
|
||||||
|
|||||||
Reference in New Issue
Block a user