mirror of
https://github.com/HugoAura/Seewo-HugoAura.git
synced 2026-06-20 23:14:28 +08:00
Compare commits
42 Commits
vAutoBuild
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9622c28ad | ||
|
|
8a44af078a | ||
|
|
c5c63c6639 | ||
|
|
420f35a5e4 | ||
|
|
1031bf04bb | ||
|
|
db55f54cc1 | ||
|
|
46ca11caad | ||
|
|
6ee3f99411 | ||
|
|
f2bb2ab06a | ||
|
|
971d3db43a | ||
|
|
f7feca7ff2 | ||
|
|
b27b1a6573 | ||
|
|
1b90932869 | ||
|
|
c84aaef994 | ||
|
|
8656fd0334 | ||
|
|
80354cc310 | ||
|
|
cd946a60fb | ||
|
|
a6c68782a0 | ||
|
|
d6db3e398a | ||
|
|
7afeb39275 | ||
|
|
b277a61923 | ||
|
|
08290301a3 | ||
|
|
5a29e909f2 | ||
|
|
2b9d1c97c5 | ||
|
|
abd5a10d24 | ||
|
|
c857f00771 | ||
|
|
6b64481e2e | ||
|
|
fb01b27d1d | ||
|
|
585f1713a9 | ||
|
|
2ff4a28b70 | ||
|
|
d5b4c4b61e | ||
|
|
774d999752 | ||
|
|
ae2e2ff62d | ||
|
|
b8f27d9f7c | ||
|
|
807ac913da | ||
|
|
f6a30351fd | ||
|
|
0494394fd8 | ||
|
|
6be31652f9 | ||
|
|
a638a29cc6 | ||
|
|
dae0f033a5 | ||
|
|
bd2f2e4154 | ||
|
|
290cbfed53 |
18
.github/ISSUE_TEMPLATE/bugReport.yml
vendored
18
.github/ISSUE_TEMPLATE/bugReport.yml
vendored
@@ -3,6 +3,19 @@ description: 反馈应用中的问题, 或预期外的行为
|
|||||||
labels: ["Bug"]
|
labels: ["Bug"]
|
||||||
title: "[Bug] "
|
title: "[Bug] "
|
||||||
body:
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: 在开始之前 / Before starting
|
||||||
|
options:
|
||||||
|
- label: 我了解本 Repo 仅接受 HugoAura-Main 本体 (管家 Electron 侧 Hook) 的问题反馈
|
||||||
|
required: true
|
||||||
|
- label: 我知晓, 如果这是关于 HugoAura 安装器的 Bug, 我应该前往 [HugoAura-Install Issues](https://github.com/HugoAura/HugoAura-Install/issues) 提交 Bug Report
|
||||||
|
required: true
|
||||||
|
- label: 我知晓, 如果这是 HugoAura Aikari 的 Bug, 我应该前往 [HugoAura-Aikari Issues](https://github.com/HugoAura/HugoAura-Aikari/issues) 提交 Bug Report
|
||||||
|
required: true
|
||||||
|
- label: 我知晓, 如果我将 Issue 提交到了错误的 Repo, 可能会引发开发者响应速度降低 / Issue 被忽略 / Issue 被 Close as duplicate / Issue 被 Transfer 等情况
|
||||||
|
required: true
|
||||||
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: 复现步骤 / Reproduce steps
|
label: 复现步骤 / Reproduce steps
|
||||||
@@ -48,16 +61,17 @@ body:
|
|||||||
options:
|
options:
|
||||||
- label: 我已经在 [HugoAura Issues](https://github.com/HugoAura/Seewo-HugoAura/issues) 中查询过相关关键词, 并确定此 Issue 是唯一的。
|
- label: 我已经在 [HugoAura Issues](https://github.com/HugoAura/Seewo-HugoAura/issues) 中查询过相关关键词, 并确定此 Issue 是唯一的。
|
||||||
required: true
|
required: true
|
||||||
- label: 我已经确认, 我运行的 HugoAura 版本与希沃管家客户端版本相兼容
|
- label: 我已经确认, 我正在使用最新版本的希沃管家客户端
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: 日志 / Logs
|
label: 日志 / Logs
|
||||||
description: 请前往 `用户文件夹/Documents/HugoAura/logs` 取得日志
|
description: 请前往 `偏好设置` - `调试选项` 打开日志文件夹
|
||||||
placeholder: |
|
placeholder: |
|
||||||
[LOG] Logger initialized. Log file: C:\...
|
[LOG] Logger initialized. Log file: C:\...
|
||||||
[LOG] [HugoAura / Loaded] Aura is loaded!
|
[LOG] [HugoAura / Loaded] Aura is loaded!
|
||||||
|
render: bash
|
||||||
validations:
|
validations:
|
||||||
required: false
|
required: false
|
||||||
|
|
||||||
|
|||||||
2
.github/ISSUE_TEMPLATE/config.yml
vendored
2
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1 +1 @@
|
|||||||
blank_issues_enabled: false
|
blank_issues_enabled: true
|
||||||
|
|||||||
13
.github/ISSUE_TEMPLATE/featureRequest.yml
vendored
13
.github/ISSUE_TEMPLATE/featureRequest.yml
vendored
@@ -3,6 +3,19 @@ description: 提交你想要的新功能
|
|||||||
labels: ["Feature"]
|
labels: ["Feature"]
|
||||||
title: "[Feature Request] "
|
title: "[Feature Request] "
|
||||||
body:
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: 在开始之前 / Before starting
|
||||||
|
options:
|
||||||
|
- label: 我了解本 Repo 仅接受 HugoAura-Main 本体 (管家 Electron 侧 Hook) 的功能请求
|
||||||
|
required: true
|
||||||
|
- label: 我知晓, 如果这是关于 HugoAura 安装器的功能请求, 我应该前往 [HugoAura-Install Issues](https://github.com/HugoAura/HugoAura-Install/issues) 提交 Feature Request
|
||||||
|
required: true
|
||||||
|
- label: 我知晓, 如果本功能请求涉及流量过滤、底层修改等目的, 我应该前往 [HugoAura-Aikari Issues](https://github.com/HugoAura/HugoAura-Aikari/issues) 提交 Feature Request
|
||||||
|
required: true
|
||||||
|
- label: 我知晓, 如果我将 Issue 提交到了错误的 Repo, 可能会引发开发者响应速度降低 / Issue 被忽略 / Issue 被 Close as duplicate / Issue 被 Transfer 等情况
|
||||||
|
required: true
|
||||||
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: 概述 / Overview
|
label: 概述 / Overview
|
||||||
|
|||||||
2
.github/ISSUE_TEMPLATE/other.yml
vendored
2
.github/ISSUE_TEMPLATE/other.yml
vendored
@@ -16,5 +16,5 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: 提交前请确认 / Confirm before submit
|
label: 提交前请确认 / Confirm before submit
|
||||||
options:
|
options:
|
||||||
- label: 请勿利用此 Issue 类型进行灌水 / 闲聊, 如果您有相关需求, 可留意后续 HugoAura 的论坛 / 用户讨论群开放情况
|
- label: 请勿利用此 Issue 类型进行闲聊 / 灌水, 如需闲聊, 可移步至 HugoAura 位于 STCN Forum 的论坛版块 (https://forum.smart-teach.cn/t/hugoaura)
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
130
.github/workflows/pack.yml
vendored
130
.github/workflows/pack.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: Patch ASAR & Pack source code
|
name: Pack source code & Create CI/CD Release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -11,156 +11,68 @@ permissions: write-all
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pack:
|
pack:
|
||||||
name: Patch & Pack
|
name: Pack
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
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
|
- name: Checkout repository code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
path: "./HugoAura-Code"
|
path: "./HugoAura-Code"
|
||||||
|
|
||||||
- name: Download SeewoServiceSetup
|
- name: Create aura.zip
|
||||||
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: |
|
run: |
|
||||||
echo "[DEBUG] Creating artifacts directory"
|
echo "[DEBUG] Creating artifacts directory"
|
||||||
mkdir -p Artifacts
|
mkdir -p Artifacts
|
||||||
|
cd ./HugoAura-Code/src/aura
|
||||||
asar pack SSARes/app-unpacked Artifacts/app-patched.asar
|
|
||||||
|
|
||||||
- name: Create aura.zip
|
|
||||||
run: |
|
|
||||||
cd HugoAura-Code/src/aura
|
|
||||||
zip -r ../../../Artifacts/aura.zip .
|
zip -r ../../../Artifacts/aura.zip .
|
||||||
|
cd ../core
|
||||||
|
zip -r ../../../Artifacts/core.zip .
|
||||||
cd ../../..
|
cd ../../..
|
||||||
|
|
||||||
echo "[DEBUG] Files in <Working DIR>/Artifacts directory:"
|
echo "[DEBUG] Files in <Working DIR>/Artifacts directory:"
|
||||||
ls -la Artifacts/
|
ls -la Artifacts/
|
||||||
|
|
||||||
- name: Get short commit hash
|
- name: Get commit hash & build time
|
||||||
run: |
|
run: |
|
||||||
cd ./HugoAura-Code
|
cd ./HugoAura-Code
|
||||||
SHORT_HASH=$(git rev-parse --short=7 HEAD)
|
SHORT_HASH=$(git rev-parse --short=7 HEAD)
|
||||||
|
FULL_HASH=$(git rev-parse HEAD)
|
||||||
echo "SHORT_HASH=$SHORT_HASH" >> $GITHUB_ENV
|
echo "SHORT_HASH=$SHORT_HASH" >> $GITHUB_ENV
|
||||||
|
echo "FULL_HASH=$FULL_HASH" >> $GITHUB_ENV
|
||||||
|
echo "BUILDTIME=$(TZ=Asia/Shanghai date)" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Create release content
|
- name: Create release content
|
||||||
run: |
|
run: |
|
||||||
cat > rel_msg.txt << EOF
|
cat > rel_msg.txt << 'EOF'
|
||||||
## 这是 HugoAura 的 CI 自动构建版本
|
## 这是 HugoAura 的 CI 自动构建版本
|
||||||
|
|
||||||
### 版本类型: 🔁 自动构建版
|
### 版本类型: 🔁 自动构建版
|
||||||
|
|
||||||
### 版本号: `vAutoBuild-${{ env.SHORT_HASH }}`
|
### 版本号: `vAutoBuild-${{ env.SHORT_HASH }}`
|
||||||
|
|
||||||
### 对应 Commit: [`${{ env.SHORT_HASH }}`](https://github.com/HugoAura/Seewo-HugoAura/commit/${{ env.GITHUB_SHA }})
|
### 对应 Commit: [`${{ env.SHORT_HASH }}`](https://github.com/HugoAura/Seewo-HugoAura/commit/${{ env.FULL_HASH }})
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### ⚠ 注意: CI 自动构建版本可能不稳定 / 存在较多 Bug, 更新时请留意
|
### ⚠ 注意: CI 自动构建版本可能不稳定 / 存在较多 Bug, 更新时请留意
|
||||||
|
|
||||||
**🕘 构建时间: ${{ env.BUILDTIME }}**
|
#### 🕘 构建时间: ${{ env.BUILDTIME }}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
- name: Upload patched ASAR
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: asar-patched
|
|
||||||
path: Artifacts/app-patched.asar
|
|
||||||
|
|
||||||
- name: Upload aura.zip
|
- name: Upload aura.zip
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: aura-code
|
name: aura-code
|
||||||
path: Artifacts/aura.zip
|
path: Artifacts/aura.zip
|
||||||
|
|
||||||
|
- name: Upload core.zip
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: aura-core
|
||||||
|
path: Artifacts/core.zip
|
||||||
|
|
||||||
- name: Upload release
|
- name: Upload release
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
@@ -170,6 +82,6 @@ jobs:
|
|||||||
prerelease: true
|
prerelease: true
|
||||||
generate_release_notes: false
|
generate_release_notes: false
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
file: |
|
files: |
|
||||||
Artifacts/app-patched.asar
|
|
||||||
Artifacts/aura.zip
|
Artifacts/aura.zip
|
||||||
|
Artifacts/core.zip
|
||||||
|
|||||||
26
.github/workflows/trigger-install-upd.yml
vendored
Normal file
26
.github/workflows/trigger-install-upd.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
name: Trigger Aura Install static JSON update
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
trigger-dispatch:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
if: github.event.release.tag_name != 'vAutoBuild'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Trigger repository dispatch
|
||||||
|
uses: peter-evans/repository-dispatch@v3
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.AURA_INSTALL_REPO_PAT }}
|
||||||
|
repository: HugoAura/HugoAura-Install
|
||||||
|
event-type: hugoaura_rel
|
||||||
|
client-payload: |
|
||||||
|
{
|
||||||
|
"tag_name": "${{ github.event.release.tag_name }}",
|
||||||
|
"release_name": "${{ github.event.release.name }}",
|
||||||
|
"release_url": "${{ github.event.release.html_url }}",
|
||||||
|
"repository": "${{ github.repository }}"
|
||||||
|
}
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -15,6 +15,7 @@ autoConfiguration.json
|
|||||||
|
|
||||||
# NPM Packages
|
# NPM Packages
|
||||||
node_modules/
|
node_modules/
|
||||||
|
package-lock.json
|
||||||
|
|
||||||
# OS Files
|
# OS Files
|
||||||
desktop.ini
|
desktop.ini
|
||||||
@@ -22,3 +23,6 @@ desktop.ini
|
|||||||
|
|
||||||
# Editor Files
|
# Editor Files
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
*.bak
|
||||||
|
|||||||
45
README.md
45
README.md
@@ -3,16 +3,37 @@
|
|||||||
<h1 align="center">HugoAura</h1>
|
<h1 align="center">HugoAura</h1>
|
||||||
<h4 align="center">下一代希沃管家注入式修改方案</h4>
|
<h4 align="center">下一代希沃管家注入式修改方案</h4>
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<a href="https://github.com/HugoAura/HugoAura">首页</a> · <a href="https://hugoaura.org/about">关于</a> · <a href="https://github.com/HugoAura/HugoAura/wiki">文档</a> · <a href="https://github.com/HugoAura/HugoAura/issues">反馈</a>
|
<a href="https://github.com/HugoAura/HugoAura">首页</a> · <a href="https://hugo.aurax.cc/about">关于 (WIP)</a> · <a href="https://docs.aurax.cc/">文档</a> · <a href="https://github.com/HugoAura/HugoAura/issues">反馈</a> · <a href="https://forum.smart-teach.cn/t/hugoaura">社区</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
|
<center>
|
||||||
|
<a href="https://forum.smart-teach.cn/d/898-xi-wo-guan-jia-zhe-kuai-zhen-de-shi-zhao-xiao-si-liao">
|
||||||
|
<img src="https://docs.aurax.cc/static/img/emg_announcement_banner.png" />
|
||||||
|
</a>
|
||||||
|
</center>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> HugoAura 的首个预览版已发布! [查看安装教程](https://github.com/HugoAura/HugoAura/wiki)
|
> 在[此处](https://docs.aurax.cc/)查看 HugoAura 的文档与安装教程
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
>
|
||||||
|
> 我们正在进行品牌形象更新, 本仓库 (`HugoAura/Seewo-HugoAura` / HugoAura SSA Electron Injection Loader) 将会逐渐改称 `HugoAura-Main`。这是为了区分 Project HugoAura 与 HugoAura SSA Electron Injection Loader 二者。
|
||||||
|
|
||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
> 已经过测试的希沃管家版本: v1.5.4.3824
|
> 已经过测试的希沃管家版本: v1.5.5.3917
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> **社群信息**
|
||||||
|
>
|
||||||
|
> - [QQ 群 (用户自治)](https://c.colchicum.moe)
|
||||||
|
> - [Telegram 公告频道](https://t.me/HugoAura)
|
||||||
|
> - [Telegram 群组](https://t.me/HugoAura_Chat)
|
||||||
|
> - [STCN 论坛讨论版块](https://forum.smart-teach.cn/t/hugoaura)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -33,7 +54,7 @@
|
|||||||
- [x] 修改希沃管家密码认证组件 (自定义密码 / 解除密码 / 重设认证方式 / ...)
|
- [x] 修改希沃管家密码认证组件 (自定义密码 / 解除密码 / 重设认证方式 / ...)
|
||||||
- [x] 阻止希沃管家前端 Audit 上报行为
|
- [x] 阻止希沃管家前端 Audit 上报行为
|
||||||
- [x] 屏蔽屏幕锁 / 自定义屏幕锁行为
|
- [x] 屏蔽屏幕锁 / 自定义屏幕锁行为
|
||||||
- [ ] Aura 代理层服务 (篡改上报数据 / 欺骗冰冻状态)
|
- [x] Aura 代理层服务 (篡改上报数据 / 欺骗冰冻状态)
|
||||||
- [ ] 窥屏提醒
|
- [ ] 窥屏提醒
|
||||||
- [ ] 插件功能
|
- [ ] 插件功能
|
||||||
|
|
||||||
@@ -45,16 +66,28 @@
|
|||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
> 演示图片, 请以实际安装后效果为准
|
> 演示图片, 请以实际安装后效果为准
|
||||||
|
|
||||||
<center><img src="https://s2.loli.net/2025/04/18/2KoGaXR9463tAgP.png" /></center>
|
<center><img src="https://s2.loli.net/2025/11/24/CUNDch9yps5IY1L.png" /></center>
|
||||||
|
|
||||||
<center><img src="https://s2.loli.net/2025/04/18/2lANiTpX79FcwfC.png" /></center>
|
<center><img src="https://s2.loli.net/2025/04/18/2lANiTpX79FcwfC.png" /></center>
|
||||||
|
|
||||||
<center><img src="https://s2.loli.net/2025/04/18/VNrdt7IC1PgXSpl.png" /></center>
|
<center><img src="https://s2.loli.net/2025/11/24/YgOqytCkxncRAs7.png" /></center>
|
||||||
|
|
||||||
## ⚡ 安装与使用
|
## ⚡ 安装与使用
|
||||||
|
|
||||||
请参阅 [Wiki](https://github.com/HugoAura/HugoAura/wiki) 以了解安装流程。
|
请参阅 [Wiki](https://github.com/HugoAura/HugoAura/wiki) 以了解安装流程。
|
||||||
|
|
||||||
|
## 🤖 AIGC 声明
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 📦 贡献准则
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 🎉 鸣谢
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## ❗ 免责声明
|
## ❗ 免责声明
|
||||||
|
|
||||||
本项目仅用于研究或教育目的, 请勿将本项目用于可能违反当地法律、侵犯著作权或其他软件 EULA 的用途。若将本项目用于非法用途, 一切后果由使用者承担。开发者不承担此类行为带来的任何后果或责任。
|
本项目仅用于研究或教育目的, 请勿将本项目用于可能违反当地法律、侵犯著作权或其他软件 EULA 的用途。若将本项目用于非法用途, 一切后果由使用者承担。开发者不承担此类行为带来的任何后果或责任。
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "HugoAura",
|
"name": "HugoAura",
|
||||||
"version": "0.1.1-pre-IV",
|
"version": "0.2.0-rc1-p3",
|
||||||
"description": "Aura for SeewoHugo",
|
"description": "Aura for SeewoHugo",
|
||||||
"main": "app.asar/main.js",
|
|
||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"electron": "^36.3.2"
|
"electron": "^36.3.2"
|
||||||
|
|||||||
@@ -77,9 +77,10 @@ const buildIpcMain = (electron) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const { applyBaseIpcHandler } = require("./ipcModules/baseIpcHandler");
|
const { applyBaseIpcHandler } = require("./ipcModules/baseIpcHandler");
|
||||||
|
const { applyDebugIpcHandler } = require("./ipcModules/debugIpcHandler");
|
||||||
const { applyConfigIpcHandler } = require("./ipcModules/configIpcHandler");
|
const { applyConfigIpcHandler } = require("./ipcModules/configIpcHandler");
|
||||||
const { applyFsIpcHandler } = require("./ipcModules/fsIpcHandler");
|
const { applyFsIpcHandler } = require("./ipcModules/fsIpcHandler");
|
||||||
const { applyPlsIpcHandler } = require("./ipcModules/plsIpcHandler");
|
const { applyAikariIpcHandler } = require("./ipcModules/aikariIpcHandler");
|
||||||
|
|
||||||
ipcMain.handle("$aura.base.restartApplication", async () => {
|
ipcMain.handle("$aura.base.restartApplication", async () => {
|
||||||
app.relaunch();
|
app.relaunch();
|
||||||
@@ -87,9 +88,10 @@ const buildIpcMain = (electron) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
applyBaseIpcHandler(ipcMain);
|
applyBaseIpcHandler(ipcMain);
|
||||||
|
applyDebugIpcHandler(ipcMain);
|
||||||
applyConfigIpcHandler(ipcMain);
|
applyConfigIpcHandler(ipcMain);
|
||||||
applyFsIpcHandler(ipcMain);
|
applyFsIpcHandler(ipcMain);
|
||||||
applyPlsIpcHandler(ipcMain);
|
applyAikariIpcHandler(ipcMain);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = { buildIpcMain };
|
module.exports = { buildIpcMain };
|
||||||
|
|||||||
915
src/aura/init/main/ipcModules/aikariIpcHandler.js
Normal file
915
src/aura/init/main/ipcModules/aikariIpcHandler.js
Normal file
@@ -0,0 +1,915 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
const __SCOPE = "main";
|
||||||
|
|
||||||
|
const { exec, execSync } = require("child_process");
|
||||||
|
const fs = require("fs");
|
||||||
|
const os = require("os");
|
||||||
|
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
|
||||||
|
* @param {string} logPath
|
||||||
|
* @param {string} progressFilePath
|
||||||
|
*/
|
||||||
|
handleAikariDlAndInstall: async (
|
||||||
|
channel,
|
||||||
|
callbackFn,
|
||||||
|
binPath,
|
||||||
|
logPath,
|
||||||
|
progressFilePath
|
||||||
|
) => {
|
||||||
|
let dlResult = false;
|
||||||
|
if (fs.existsSync(path.join(path.dirname(binPath), ".force"))) {
|
||||||
|
dlResult = true;
|
||||||
|
} else {
|
||||||
|
// TODO: Channel selection
|
||||||
|
const apiInfo = global.__HUGO_AURA_API__;
|
||||||
|
|
||||||
|
const getVerPromise = new Promise(async (resolveGetVerReq) => {
|
||||||
|
// ↓ 目前 channel param 没有什么用处
|
||||||
|
for (const apiDomain of apiInfo.domains) {
|
||||||
|
const reqPromise = new Promise((resolveHttpRequest) => {
|
||||||
|
nodeHttps
|
||||||
|
.get(
|
||||||
|
`${apiDomain}${apiInfo.aikariUpdate}?channel=${channel}`,
|
||||||
|
(rep) => {
|
||||||
|
let dataChunk = "";
|
||||||
|
rep.on("data", (chunk) => {
|
||||||
|
dataChunk += chunk;
|
||||||
|
});
|
||||||
|
|
||||||
|
rep.on("end", () => {
|
||||||
|
let parsedData = {};
|
||||||
|
try {
|
||||||
|
parsedData = JSON.parse(dataChunk);
|
||||||
|
} catch (e) {
|
||||||
|
callbackFn({
|
||||||
|
id: "",
|
||||||
|
progress: 0,
|
||||||
|
status: "struggling",
|
||||||
|
dlUrl: null,
|
||||||
|
savePath: null,
|
||||||
|
message: `数据解析失败, 正在尝试 API 域名 ${
|
||||||
|
apiInfo.domains[
|
||||||
|
apiInfo.domains.indexOf(apiDomain) + 1
|
||||||
|
]
|
||||||
|
} ...`,
|
||||||
|
errorObj: e,
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
resolveHttpRequest({
|
||||||
|
success: false,
|
||||||
|
errorObj: e,
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolveHttpRequest({
|
||||||
|
success: true,
|
||||||
|
data: parsedData,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.on("error", (e) => {
|
||||||
|
callbackFn({
|
||||||
|
id: "",
|
||||||
|
progress: 0,
|
||||||
|
status: "struggling",
|
||||||
|
dlUrl: null,
|
||||||
|
savePath: null,
|
||||||
|
message: `连接失败, 正在尝试 API 域名 ${
|
||||||
|
apiInfo.domains[apiInfo.domains.indexOf(apiDomain) + 1]
|
||||||
|
} ...`,
|
||||||
|
errorObj: e,
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
resolveHttpRequest({
|
||||||
|
success: false,
|
||||||
|
errorObj: e,
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const requestResult = await reqPromise;
|
||||||
|
if (requestResult.success) {
|
||||||
|
resolveGetVerReq({
|
||||||
|
success: true,
|
||||||
|
data: requestResult.data,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resolveGetVerReq({
|
||||||
|
success: false,
|
||||||
|
data: null,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const rawResInfo = await getVerPromise;
|
||||||
|
if (!rawResInfo.success) {
|
||||||
|
callbackFn({
|
||||||
|
id: "",
|
||||||
|
progress: 0,
|
||||||
|
status: "failed",
|
||||||
|
dlUrl: null,
|
||||||
|
savePath: null,
|
||||||
|
message:
|
||||||
|
"未能获取 Aikari 版本信息, 所有 API 域名均无法连接, 建议前往 GitHub 下载安装包并自行安装",
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const aikariVersionInfo = rawResInfo.data;
|
||||||
|
|
||||||
|
let deviceArch = process.env.PROCESSOR_ARCHITEW6432
|
||||||
|
? process.env.PROCESSOR_ARCHITEW6432
|
||||||
|
: process.env.PROCESSOR_ARCHITECTURE;
|
||||||
|
// @ts-expect-error
|
||||||
|
deviceArch = deviceArch.toLowerCase();
|
||||||
|
|
||||||
|
if (
|
||||||
|
!Object.keys(aikariVersionInfo.data.downloadUrl).includes(deviceArch)
|
||||||
|
) {
|
||||||
|
callbackFn({
|
||||||
|
id: "",
|
||||||
|
progress: 0,
|
||||||
|
status: "failed",
|
||||||
|
dlUrl: null,
|
||||||
|
savePath: null,
|
||||||
|
message: `不支持的处理器架构, 检测到的架构: "${deviceArch}"`,
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const downloadFilePromise = new Promise((resolve) => {
|
||||||
|
fsComposables.downloadFile(
|
||||||
|
aikariVersionInfo.data.downloadUrl[deviceArch],
|
||||||
|
binPath,
|
||||||
|
(...args) => {
|
||||||
|
if (args[0].status === "done") {
|
||||||
|
resolve(true);
|
||||||
|
} else if (args[0].status === "failed") {
|
||||||
|
resolve(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
callbackFn(...args);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
dlResult = await downloadFilePromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dlResult) {
|
||||||
|
callbackFn({
|
||||||
|
id: "INSTALL_STAGE",
|
||||||
|
progress: 5,
|
||||||
|
status: "waiting",
|
||||||
|
dlUrl: null,
|
||||||
|
savePath: null,
|
||||||
|
message: "准备运行 Aikari 安装程序...",
|
||||||
|
});
|
||||||
|
|
||||||
|
const runInstPromise = new Promise((resolve) => {
|
||||||
|
exec(
|
||||||
|
`"${binPath}" /VERYSILENT /SUPPRESSMSGBOXES /LOG="${logPath}" /PROGRESS_FILE="${progressFilePath}"`,
|
||||||
|
(err, stdout, stderr) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(
|
||||||
|
`[HugoAura / Main / Aikari IPC Handler / Install Aikari] Error running installer: ${stderr}`
|
||||||
|
);
|
||||||
|
resolve({ success: false });
|
||||||
|
}
|
||||||
|
resolve({ success: true });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!fs.existsSync(path.dirname(progressFilePath))) {
|
||||||
|
fs.mkdirSync(path.dirname(progressFilePath));
|
||||||
|
}
|
||||||
|
if (!fs.existsSync(progressFilePath)) {
|
||||||
|
fs.writeFileSync(progressFilePath, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
callbackFn({
|
||||||
|
id: "INSTALL_STAGE",
|
||||||
|
progress: 15,
|
||||||
|
status: "progressing",
|
||||||
|
dlUrl: null,
|
||||||
|
savePath: null,
|
||||||
|
message: "正在安装 Aikari...",
|
||||||
|
});
|
||||||
|
|
||||||
|
let instFilesStageLastFakeLoadProgressPercent = -1;
|
||||||
|
|
||||||
|
const fileProgressWatcher = fs.watch(progressFilePath, (eventType) => {
|
||||||
|
if (eventType === "change") {
|
||||||
|
try {
|
||||||
|
const content = fs.readFileSync(progressFilePath, "utf-8").trim();
|
||||||
|
if (content === "") {
|
||||||
|
callbackFn({
|
||||||
|
id: "INSTALL_STAGE",
|
||||||
|
progress: 20,
|
||||||
|
status: "progressing",
|
||||||
|
dlUrl: null,
|
||||||
|
savePath: null,
|
||||||
|
message: "正在准备安装...",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const contentArr = content.split(";");
|
||||||
|
switch (contentArr[0]) {
|
||||||
|
case "DL_VC_REDIST":
|
||||||
|
callbackFn({
|
||||||
|
id: "INSTALL_STAGE",
|
||||||
|
progress:
|
||||||
|
20 +
|
||||||
|
Math.round((parseFloat(contentArr[1]) / 10) * 2), // 20 + [0, 20] === 20 ~ 40
|
||||||
|
status: "progressing",
|
||||||
|
dlUrl: null,
|
||||||
|
savePath: null,
|
||||||
|
message: `正在下载 VC++ 运行时... (${contentArr[1]}%)`,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "INST_FILES":
|
||||||
|
if (instFilesStageLastFakeLoadProgressPercent === -1) {
|
||||||
|
instFilesStageLastFakeLoadProgressPercent = 60;
|
||||||
|
} else if (instFilesStageLastFakeLoadProgressPercent < 85) {
|
||||||
|
instFilesStageLastFakeLoadProgressPercent +=
|
||||||
|
Math.random() * (5 - 1) + 1;
|
||||||
|
}
|
||||||
|
callbackFn({
|
||||||
|
id: "INSTALL_STAGE",
|
||||||
|
progress: instFilesStageLastFakeLoadProgressPercent,
|
||||||
|
status: "progressing",
|
||||||
|
dlUrl: null,
|
||||||
|
savePath: null,
|
||||||
|
message: `正在解压文件...`,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "INST_VC_REDIST":
|
||||||
|
callbackFn({
|
||||||
|
id: "INSTALL_STAGE",
|
||||||
|
progress: 90,
|
||||||
|
status: "progressing",
|
||||||
|
dlUrl: null,
|
||||||
|
savePath: null,
|
||||||
|
message: `正在安装 VC++ 运行时...`,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "DONE":
|
||||||
|
callbackFn({
|
||||||
|
id: "INSTALL_STAGE",
|
||||||
|
progress: 99,
|
||||||
|
status: "progressing",
|
||||||
|
dlUrl: null,
|
||||||
|
savePath: null,
|
||||||
|
message: `即将完成`,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const instResult = await runInstPromise;
|
||||||
|
|
||||||
|
fileProgressWatcher.close();
|
||||||
|
|
||||||
|
callbackFn({
|
||||||
|
id: "INSTALL_STAGE",
|
||||||
|
progress: 100,
|
||||||
|
status: instResult.success ? "done" : "failed",
|
||||||
|
dlUrl: null,
|
||||||
|
savePath: null,
|
||||||
|
message: instResult.success
|
||||||
|
? "Aikari 安装成功"
|
||||||
|
: "安装失败, 请检查 %TEMP%/Aikari-Install-Temp 下的安装日志",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (instResult.success) {
|
||||||
|
if (global.__HUGO_AURA__.aikariStats) {
|
||||||
|
global.__HUGO_AURA__.aikariStats.installed = true;
|
||||||
|
global.__HUGO_AURA__.aikariStats.status = "dead";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.unlinkSync(binPath);
|
||||||
|
fs.unlinkSync(logPath);
|
||||||
|
fs.unlinkSync(progressFilePath);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clearHostFileItem: async () => {
|
||||||
|
const AIKARI_HOST_STR =
|
||||||
|
"127.11.45.14 iot-broker-mis.seewo.com # This line is generated by HugoAura-Aikari, please do not edit or delete it";
|
||||||
|
const hostPath = path.join(
|
||||||
|
process.env.SystemRoot || "C:\\WINDOWS",
|
||||||
|
"System32",
|
||||||
|
"drivers",
|
||||||
|
"etc",
|
||||||
|
"hosts"
|
||||||
|
);
|
||||||
|
if (fs.existsSync(hostPath)) {
|
||||||
|
try {
|
||||||
|
const content = fs.readFileSync(hostPath, "utf-8");
|
||||||
|
const lines = content.split(/\r?\n/);
|
||||||
|
const newContent = lines.filter((line) => {
|
||||||
|
const shouldKeep = !line.includes(AIKARI_HOST_STR);
|
||||||
|
if (!shouldKeep) {
|
||||||
|
console.log(
|
||||||
|
`[HugoAura / IPC / Aikari] Cleaned hosts file item: ${line}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return shouldKeep;
|
||||||
|
});
|
||||||
|
if (lines.length === newContent.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const newData = newContent.join(os.EOL);
|
||||||
|
fs.writeFileSync(hostPath, newData, "utf-8");
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[HugoAura / IPC / Aikari] Error cleaning hosts file: ",
|
||||||
|
err
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("../../../types/main/electron").AuraIPCMain} ipcMain
|
||||||
|
*/
|
||||||
|
const applyAikariIpcHandler = (ipcMain) => {
|
||||||
|
const methodBase = "$aura.aikari";
|
||||||
|
|
||||||
|
const AIKARI_DEFAULT_INSTALL_DIR = path.join(
|
||||||
|
"C:\\Program Files",
|
||||||
|
"HugoAura",
|
||||||
|
"Aikari"
|
||||||
|
);
|
||||||
|
const AIKARI_LAUNCHER_PATH = path.join(
|
||||||
|
AIKARI_DEFAULT_INSTALL_DIR,
|
||||||
|
"Aikari-Launcher.exe"
|
||||||
|
);
|
||||||
|
const AIKARI_UNINSTALLER_PATH = path.join(
|
||||||
|
AIKARI_DEFAULT_INSTALL_DIR,
|
||||||
|
"unins000.exe"
|
||||||
|
);
|
||||||
|
const AIKARI_SVC_NAME = "HugoAuraAikari";
|
||||||
|
|
||||||
|
const AIKARI_TEMP_DL_DIR = path.join(
|
||||||
|
require("os").tmpdir(),
|
||||||
|
"Aikari-Install-Temp"
|
||||||
|
);
|
||||||
|
const AIKARI_TEMP_INSTALLER_FILENAME = path.join(
|
||||||
|
AIKARI_TEMP_DL_DIR,
|
||||||
|
"Aikari-Installer.exe"
|
||||||
|
);
|
||||||
|
const AIKARI_INSTALLER_LOG_FILENAME = path.join(
|
||||||
|
AIKARI_TEMP_DL_DIR,
|
||||||
|
"install.log"
|
||||||
|
);
|
||||||
|
const AIKARI_INSTALLER_PROGRESS_FIPC_FILENAME = path.join(
|
||||||
|
AIKARI_TEMP_DL_DIR,
|
||||||
|
"PROGRESS"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Prev PLS Cfg
|
||||||
|
const OLD_PLS_INSTALL_DIR = path.join(
|
||||||
|
"C:\\Program Files",
|
||||||
|
"HugoAura PLS",
|
||||||
|
"bin"
|
||||||
|
);
|
||||||
|
const OLD_PLS_SVC_NAME = "HugoAuraPLS";
|
||||||
|
|
||||||
|
const isAikariDetached = process.argv.includes("--aikari-detach");
|
||||||
|
|
||||||
|
global.__HUGO_AURA__.aikariStats = {
|
||||||
|
installed: false,
|
||||||
|
launched: false,
|
||||||
|
detached: isAikariDetached,
|
||||||
|
connected: false,
|
||||||
|
version: "unknown",
|
||||||
|
status: "dead",
|
||||||
|
authToken: global.__HUGO_AURA_CONFIG__.aikariToken,
|
||||||
|
};
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.getIfAikariBinExists`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns {{ success: boolean; data: { isExists: boolean }; error?: Error }}
|
||||||
|
*/
|
||||||
|
(_event, _arg) => {
|
||||||
|
try {
|
||||||
|
const result = fs.existsSync(AIKARI_LAUNCHER_PATH);
|
||||||
|
|
||||||
|
if (global.__HUGO_AURA__.aikariStats?.status === "notInstalled") {
|
||||||
|
global.__HUGO_AURA__.aikariStats.status = "dead";
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data: { isExists: result },
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
// @ts-expect-error
|
||||||
|
global.__HUGO_AURA__.aikariStats.status = "notInstalled";
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
data: { isExists: false },
|
||||||
|
error: e,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.ensureAikariInstallDir`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("electron").IpcMainInvokeEvent} _event
|
||||||
|
* @param {any} _arg
|
||||||
|
* @returns {{ success: boolean; data: { alreadyExists: boolean; createdDir: string; }; error?: Error }}
|
||||||
|
*/
|
||||||
|
(_event, _arg) => {
|
||||||
|
const alreadyExists = fs.existsSync(AIKARI_DEFAULT_INSTALL_DIR);
|
||||||
|
if (alreadyExists) {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data: {
|
||||||
|
alreadyExists: true,
|
||||||
|
createdDir: AIKARI_DEFAULT_INSTALL_DIR,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
fs.mkdirSync(AIKARI_DEFAULT_INSTALL_DIR, { recursive: true });
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data: {
|
||||||
|
alreadyExists: false,
|
||||||
|
createdDir: AIKARI_DEFAULT_INSTALL_DIR,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
data: {
|
||||||
|
alreadyExists: false,
|
||||||
|
createdDir: AIKARI_DEFAULT_INSTALL_DIR,
|
||||||
|
},
|
||||||
|
error: error,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.getAikariStatus`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns {{ success: boolean; data: import("../../../types/shared/aikari/status").AikariStatus | null | undefined; }}
|
||||||
|
*/
|
||||||
|
(_event, _arg) => {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data: global.__HUGO_AURA__.aikariStats,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.updateAikariStatus`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("electron").IpcMainInvokeEvent} _event
|
||||||
|
* @param {import("../../../types/shared/aikari/status").AikariStatus} arg
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
(_event, arg) => {
|
||||||
|
global.__HUGO_AURA__.aikariStats = arg;
|
||||||
|
ipcMain.send("assistant", `${methodBase}.post.onAikariStatsUpdate`, arg);
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.getAikariSettings`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns {{ success: boolean; data: Record<any, any> | null | undefined }}
|
||||||
|
*/
|
||||||
|
(_event, _arg) => {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data: global.__HUGO_AURA__.aikariSettings,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.updateAikariSettings`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("electron").IpcMainInvokeEvent} _event
|
||||||
|
* @param {Record<any, any>} arg
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
(_event, arg) => {
|
||||||
|
global.__HUGO_AURA__.aikariSettings = arg;
|
||||||
|
ipcMain.send(
|
||||||
|
"assistant",
|
||||||
|
`${methodBase}.post.onAikariSettingsUpdate`,
|
||||||
|
arg
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.getAikariRules`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns {{ success: boolean; data: Record<any, any> | null | undefined }}
|
||||||
|
*/
|
||||||
|
(_event, _arg) => {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data: global.__HUGO_AURA__.aikariRules,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.updateAikariRules`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("electron").IpcMainInvokeEvent} _event
|
||||||
|
* @param {Record<any, any>} arg
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
(_event, arg) => {
|
||||||
|
global.__HUGO_AURA__.aikariRules = arg;
|
||||||
|
ipcMain.send("assistant", `${methodBase}.post.onAikariRulesUpdate`, arg);
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.on(
|
||||||
|
`${methodBase}.ws.broadcastMessageRecv`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("electron").IpcMainEvent} _event
|
||||||
|
* @param {AikariResponse} arg
|
||||||
|
*/
|
||||||
|
(_event, arg) => {
|
||||||
|
ipcMain.send("assistant", `${methodBase}.ws.post.onNewMsgRecv`, arg);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.ws.sendWsMessage`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("electron").IpcMainInvokeEvent} _event
|
||||||
|
* @param {ClientAikariRequest} arg
|
||||||
|
*/
|
||||||
|
(_event, arg) => {
|
||||||
|
ipcMain.send(
|
||||||
|
"auraWsKeepAlive",
|
||||||
|
`${methodBase}.ws.post.onReqSendMsg`,
|
||||||
|
arg
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.syncAikariConfig`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("electron").IpcMainInvokeEvent} event
|
||||||
|
* @param {{ basic: Record<any, any>, rules: Record<any, any> }} arg
|
||||||
|
*/
|
||||||
|
(event, arg) => {
|
||||||
|
global.__HUGO_AURA__.aikariRules = arg.rules;
|
||||||
|
global.__HUGO_AURA__.aikariSettings = arg.basic;
|
||||||
|
|
||||||
|
ipcMain.send("*", `${methodBase}.syncAikariConfig`, arg, event.sender);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.aikariLifecycleQuery`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("electron").IpcMainInvokeEvent} _event
|
||||||
|
* @param {{ target: import("../../../types/shared/aikari/status").AikariLifecycleType }} arg
|
||||||
|
* @returns {Promise<{ success: boolean, result: boolean }>}
|
||||||
|
*/
|
||||||
|
async (_event, arg) => {
|
||||||
|
switch (arg.target) {
|
||||||
|
case "isDetached":
|
||||||
|
return { success: true, result: isAikariDetached };
|
||||||
|
case "isSvcInstalled":
|
||||||
|
return await functions.querySvcDetail(
|
||||||
|
AIKARI_SVC_NAME,
|
||||||
|
"SERVICE_NAME"
|
||||||
|
);
|
||||||
|
case "isSvcStart":
|
||||||
|
return await functions.querySvcDetail(AIKARI_SVC_NAME, "RUNNING");
|
||||||
|
default:
|
||||||
|
console.warn(
|
||||||
|
`[HugoAura / IPC / Aikari] <AikariLifecycleQuery> Invalid arg.target: ${arg.target}`
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
result: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.aikariLifecycleControl`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} _event
|
||||||
|
* @param {{ target: import("../../../types/shared/aikari/status").AikariLifecycleControlType }} arg
|
||||||
|
* @returns {Promise<{ success: boolean, errorObj?: Error }>}
|
||||||
|
*/
|
||||||
|
async (_event, arg) => {
|
||||||
|
const logHeader = "[HugoAura / IPC / Aikari] <AikariLifecycleControl>";
|
||||||
|
|
||||||
|
// TODO: Impl this
|
||||||
|
switch (arg.target) {
|
||||||
|
case "instSvc":
|
||||||
|
return await functions.execCommand(
|
||||||
|
logHeader,
|
||||||
|
AIKARI_LAUNCHER_PATH,
|
||||||
|
"--service install"
|
||||||
|
);
|
||||||
|
case "uninstSvc": {
|
||||||
|
const result = await functions.execCommand(
|
||||||
|
logHeader,
|
||||||
|
AIKARI_LAUNCHER_PATH,
|
||||||
|
"--service uninstall"
|
||||||
|
);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
case "startSvc":
|
||||||
|
return await functions.execCommand(
|
||||||
|
logHeader,
|
||||||
|
"sc.exe",
|
||||||
|
`start ${AIKARI_SVC_NAME}`
|
||||||
|
);
|
||||||
|
case "stopSvc": {
|
||||||
|
const result = await functions.execCommand(
|
||||||
|
logHeader,
|
||||||
|
"sc.exe",
|
||||||
|
`stop ${AIKARI_SVC_NAME}`
|
||||||
|
);
|
||||||
|
if (result.success && global.__HUGO_AURA__.aikariStats) {
|
||||||
|
global.__HUGO_AURA__.aikariStats.connected = false;
|
||||||
|
global.__HUGO_AURA__.aikariStats.launched = false;
|
||||||
|
global.__HUGO_AURA__.aikariStats.version = "unknown";
|
||||||
|
global.__HUGO_AURA__.aikariStats.status = "dead";
|
||||||
|
|
||||||
|
ipcMain.send(
|
||||||
|
"assistant",
|
||||||
|
`${methodBase}.post.onAikariStatsUpdate`,
|
||||||
|
global.__HUGO_AURA__.aikariStats
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.send(
|
||||||
|
"auraWsKeepAlive",
|
||||||
|
`${methodBase}.post.aikariStopped`,
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
case "inst":
|
||||||
|
// TODO: Impl Aikari INST
|
||||||
|
case "uninst":
|
||||||
|
await functions.clearHostFileItem();
|
||||||
|
return await functions.execCommand(
|
||||||
|
logHeader,
|
||||||
|
AIKARI_UNINSTALLER_PATH,
|
||||||
|
""
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return { success: false, errorObj: new Error("Method not found") };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.downloadAndInstallAikari`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("electron").IpcMainInvokeEvent} _evt
|
||||||
|
* @param {{channel?: "stable" | "alpha", reportTo?: import("../../../types/main/core").WindowName}} arg
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async (_evt, arg) => {
|
||||||
|
if (fs.existsSync(AIKARI_TEMP_DL_DIR)) {
|
||||||
|
try {
|
||||||
|
fs.unlinkSync(AIKARI_INSTALLER_LOG_FILENAME);
|
||||||
|
fs.unlinkSync(AIKARI_INSTALLER_PROGRESS_FIPC_FILENAME);
|
||||||
|
fs.unlinkSync(AIKARI_TEMP_DL_DIR);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fs.mkdirSync(AIKARI_TEMP_DL_DIR);
|
||||||
|
}
|
||||||
|
if (fs.existsSync(OLD_PLS_INSTALL_DIR)) {
|
||||||
|
try {
|
||||||
|
execSync(`sc stop ${OLD_PLS_SVC_NAME}`);
|
||||||
|
execSync(`sc delete ${OLD_PLS_SVC_NAME}`);
|
||||||
|
} catch (err) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
fs.unlinkSync(OLD_PLS_INSTALL_DIR);
|
||||||
|
} catch (err) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const channel = arg.channel ? arg.channel : "stable";
|
||||||
|
const reportWin = arg.reportTo ? arg.reportTo : "assistant";
|
||||||
|
functions.handleAikariDlAndInstall(
|
||||||
|
channel,
|
||||||
|
(status) => {
|
||||||
|
ipcMain.send(
|
||||||
|
reportWin,
|
||||||
|
`${methodBase}.post.reportAikariInstallStep`,
|
||||||
|
status
|
||||||
|
);
|
||||||
|
},
|
||||||
|
AIKARI_TEMP_INSTALLER_FILENAME,
|
||||||
|
AIKARI_INSTALLER_LOG_FILENAME,
|
||||||
|
AIKARI_INSTALLER_PROGRESS_FIPC_FILENAME
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.retryAikariConnect`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("electron").IpcMainInvokeEvent} _event
|
||||||
|
* @param {any} arg
|
||||||
|
* @returns {{ success: boolean, status: "Already" | "Retrying" }}
|
||||||
|
*/
|
||||||
|
(_event, arg) => {
|
||||||
|
if (global.__HUGO_AURA__.aikariStats?.connected) {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
status: "Already",
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
ipcMain.send(
|
||||||
|
"auraWsKeepAlive",
|
||||||
|
`${methodBase}.retryAikariConnect`,
|
||||||
|
arg
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
status: "Retrying",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.forceReloadKeepAliveWin`,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("electron").IpcMainInvokeEvent} _event
|
||||||
|
* @param {any} arg
|
||||||
|
*/
|
||||||
|
(_event, arg) => {
|
||||||
|
ipcMain.send(
|
||||||
|
"auraWsKeepAlive",
|
||||||
|
`${methodBase}.post.onForceReloadRequested`,
|
||||||
|
arg
|
||||||
|
);
|
||||||
|
|
||||||
|
return { success: true };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
`${methodBase}.post.updateRetryStatus`,
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("electron").IpcMainInvokeEvent} _event
|
||||||
|
* @param {{ success: boolean; message: string }} arg
|
||||||
|
*/
|
||||||
|
(_event, arg) => {
|
||||||
|
ipcMain.send("assistant", `${methodBase}.post.updateRetryStatus`, arg);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = { applyAikariIpcHandler };
|
||||||
@@ -1,59 +1,73 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
const { BrowserWindow } = require("electron");
|
const { BrowserWindow } = require("electron");
|
||||||
|
|
||||||
const composables = {
|
const composables = {
|
||||||
getBrowserWindowInstance: (windowKey) => {
|
getBrowserWindowInstance: (windowKey) => {
|
||||||
if (!global.__HUGO_AURA__.hookedWindows) return null;
|
if (!global.__HUGO_AURA__.hookedWindows) return null;
|
||||||
const hookedWindowIns = global.__HUGO_AURA__.hookedWindows.get(windowKey);
|
const hookedWindowIns = global.__HUGO_AURA__.hookedWindows.get(windowKey);
|
||||||
if (!hookedWindowIns) return undefined;
|
if (!hookedWindowIns) return undefined;
|
||||||
const browserWindowIns = BrowserWindow.fromWebContents(
|
const browserWindowIns = BrowserWindow.fromWebContents(
|
||||||
hookedWindowIns.webContents
|
hookedWindowIns.webContents
|
||||||
);
|
);
|
||||||
return browserWindowIns;
|
return browserWindowIns;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {import("electron").IpcMain} ipcMain
|
* @param {import("electron").IpcMain} ipcMain
|
||||||
*/
|
*/
|
||||||
const applyBaseIpcHandler = (ipcMain) => {
|
const applyBaseIpcHandler = (ipcMain) => {
|
||||||
const methodBase = "$aura.base";
|
const methodBase = "$aura.base";
|
||||||
|
|
||||||
ipcMain.on(
|
ipcMain.on(
|
||||||
`${methodBase}.minimizeWindow`,
|
`${methodBase}.minimizeWindow`,
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {import("electron").IpcMainEvent} _event
|
* @param {import("electron").IpcMainEvent} _event
|
||||||
* @param {{ targetWindowKey: string }} arg
|
* @param {{ targetWindowKey: string }} arg
|
||||||
*/
|
*/
|
||||||
(_event, arg) => {
|
(_event, arg) => {
|
||||||
const browserWindowIns = composables.getBrowserWindowInstance(
|
const browserWindowIns = composables.getBrowserWindowInstance(
|
||||||
arg.targetWindowKey
|
arg.targetWindowKey
|
||||||
);
|
);
|
||||||
if (!browserWindowIns) return;
|
if (!browserWindowIns) return;
|
||||||
|
|
||||||
browserWindowIns.minimize();
|
browserWindowIns.minimize();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
ipcMain.on(
|
ipcMain.on(
|
||||||
`${methodBase}.closeWindow`,
|
`${methodBase}.closeWindow`,
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {import("electron").IpcMainEvent} _event
|
* @param {import("electron").IpcMainEvent} _event
|
||||||
* @param {{ targetWindowKey: string }} arg
|
* @param {{ targetWindowKey: string }} arg
|
||||||
*/
|
*/
|
||||||
(_event, arg) => {
|
(_event, arg) => {
|
||||||
const browserWindowIns = composables.getBrowserWindowInstance(
|
const browserWindowIns = composables.getBrowserWindowInstance(
|
||||||
arg.targetWindowKey
|
arg.targetWindowKey
|
||||||
);
|
);
|
||||||
if (!browserWindowIns) return;
|
if (!browserWindowIns) return;
|
||||||
|
|
||||||
browserWindowIns.close();
|
browserWindowIns.close();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
|
||||||
|
ipcMain.handle(`${methodBase}.getAuraDirAsync`, (_evt, _arg) => {
|
||||||
module.exports = { applyBaseIpcHandler };
|
return {
|
||||||
|
success: true,
|
||||||
|
data: global.__HUGO_AURA__.auraDir,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on(`${methodBase}.getAuraDirSync`, (event, _arg) => {
|
||||||
|
event.returnValue = {
|
||||||
|
success: true,
|
||||||
|
data: global.__HUGO_AURA__.auraDir,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = { applyBaseIpcHandler };
|
||||||
|
|||||||
13
src/aura/init/main/ipcModules/debugIpcHandler.js
Normal file
13
src/aura/init/main/ipcModules/debugIpcHandler.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
const __SCOPE = "main";
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("electron").IpcMain} ipcMain
|
||||||
|
*/
|
||||||
|
const applyDebugIpcHandler = (ipcMain) => {
|
||||||
|
const methodBase = "$aura.debug";
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = { applyDebugIpcHandler };
|
||||||
@@ -1,599 +0,0 @@
|
|||||||
// @ts-check
|
|
||||||
|
|
||||||
const __SCOPE = "main";
|
|
||||||
|
|
||||||
const { exec } = require("child_process");
|
|
||||||
const fs = require("fs");
|
|
||||||
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__;
|
|
||||||
|
|
||||||
const getVerPromise = new Promise(async (resolveGetVerReq) => {
|
|
||||||
// ↓ 目前 channel param 没有什么用处
|
|
||||||
for (const apiDomain of apiInfo.domains) {
|
|
||||||
const reqPromise = new Promise((resolveHttpRequest) => {
|
|
||||||
nodeHttps
|
|
||||||
.get(
|
|
||||||
`${apiDomain}${apiInfo.plsUpdate}?channel=${channel}`,
|
|
||||||
(rep) => {
|
|
||||||
let dataChunk = "";
|
|
||||||
rep.on("data", (chunk) => {
|
|
||||||
dataChunk += chunk;
|
|
||||||
});
|
|
||||||
|
|
||||||
rep.on("end", () => {
|
|
||||||
let parsedData = {};
|
|
||||||
try {
|
|
||||||
parsedData = JSON.parse(dataChunk);
|
|
||||||
} catch (e) {
|
|
||||||
callbackFn({
|
|
||||||
id: "",
|
|
||||||
progress: 0,
|
|
||||||
status: "struggling",
|
|
||||||
dlUrl: null,
|
|
||||||
savePath: null,
|
|
||||||
message: `数据解析失败, 正在尝试 API 域名 ${
|
|
||||||
apiInfo.domains[apiInfo.domains.indexOf(apiDomain) + 1]
|
|
||||||
} ...`,
|
|
||||||
errorObj: e,
|
|
||||||
});
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
resolveHttpRequest({
|
|
||||||
success: false,
|
|
||||||
errorObj: e,
|
|
||||||
});
|
|
||||||
}, 1000);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
resolveHttpRequest({
|
|
||||||
success: true,
|
|
||||||
data: parsedData,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.on("error", (e) => {
|
|
||||||
callbackFn({
|
|
||||||
id: "",
|
|
||||||
progress: 0,
|
|
||||||
status: "struggling",
|
|
||||||
dlUrl: null,
|
|
||||||
savePath: null,
|
|
||||||
message: `连接失败, 正在尝试 API 域名 ${
|
|
||||||
apiInfo.domains[apiInfo.domains.indexOf(apiDomain) + 1]
|
|
||||||
} ...`,
|
|
||||||
errorObj: e,
|
|
||||||
});
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
resolveHttpRequest({
|
|
||||||
success: false,
|
|
||||||
errorObj: e,
|
|
||||||
});
|
|
||||||
}, 1000);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const requestResult = await reqPromise;
|
|
||||||
if (requestResult.success) {
|
|
||||||
resolveGetVerReq({
|
|
||||||
success: true,
|
|
||||||
data: requestResult.data,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resolveGetVerReq({
|
|
||||||
success: false,
|
|
||||||
data: null,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const rawResInfo = await getVerPromise;
|
|
||||||
if (!rawResInfo.success) {
|
|
||||||
callbackFn({
|
|
||||||
id: "",
|
|
||||||
progress: 0,
|
|
||||||
status: "failed",
|
|
||||||
dlUrl: null,
|
|
||||||
savePath: null,
|
|
||||||
message: "未能获取 PLS 版本信息, 所有 API 域名均无法连接",
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const plsVersionInfo = rawResInfo.data;
|
|
||||||
|
|
||||||
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,
|
|
||||||
(...args) => {
|
|
||||||
if (args[0].status === "done") {
|
|
||||||
if (global.__HUGO_AURA__.plsStats) {
|
|
||||||
global.__HUGO_AURA__.plsStats.installed = true;
|
|
||||||
global.__HUGO_AURA__.plsStats.status = "dead";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
callbackFn(...args);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {import("../../../types/main/electron").AuraIPCMain} ipcMain
|
|
||||||
*/
|
|
||||||
const applyPlsIpcHandler = (ipcMain) => {
|
|
||||||
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");
|
|
||||||
|
|
||||||
global.__HUGO_AURA__.plsStats = {
|
|
||||||
installed: false,
|
|
||||||
launched: false,
|
|
||||||
detached: isPlsDetached,
|
|
||||||
connected: false,
|
|
||||||
version: "未知",
|
|
||||||
status: "dead",
|
|
||||||
authToken: global.__HUGO_AURA_CONFIG__.plsToken,
|
|
||||||
};
|
|
||||||
|
|
||||||
ipcMain.handle(
|
|
||||||
`${methodBase}.getPlsBinExists`,
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @returns {{ success: boolean; data: { isExists: boolean }; error?: Error }}
|
|
||||||
*/
|
|
||||||
(_event, _arg) => {
|
|
||||||
try {
|
|
||||||
const result = fs.existsSync(PLS_BIN_PATH);
|
|
||||||
|
|
||||||
if (global.__HUGO_AURA__.plsStats?.status === "notInstalled") {
|
|
||||||
global.__HUGO_AURA__.plsStats.status = "dead";
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
data: { isExists: result },
|
|
||||||
};
|
|
||||||
} catch (e) {
|
|
||||||
// @ts-expect-error
|
|
||||||
global.__HUGO_AURA__.plsStats.status = "notInstalled";
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
data: { isExists: false },
|
|
||||||
error: e,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
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, { recursive: true });
|
|
||||||
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(
|
|
||||||
`${methodBase}.getPlsStats`,
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @returns {{ success: boolean; data: import("../../../types/shared/pls/status").PLSStatus | null | undefined; }}
|
|
||||||
*/
|
|
||||||
(_event, _arg) => {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
data: global.__HUGO_AURA__.plsStats,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
ipcMain.handle(
|
|
||||||
`${methodBase}.updatePlsStats`,
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {import("electron").IpcMainInvokeEvent} _event
|
|
||||||
* @param {import("../../../types/shared/pls/status").PLSStatus} arg
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
(_event, arg) => {
|
|
||||||
global.__HUGO_AURA__.plsStats = arg;
|
|
||||||
ipcMain.send("assistant", `${methodBase}.post.onPlsStatsUpdate`, arg);
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
ipcMain.handle(
|
|
||||||
`${methodBase}.getPlsSettings`,
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @returns {{ success: boolean; data: Record<any, any> | null | undefined }}
|
|
||||||
*/
|
|
||||||
(_event, _arg) => {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
data: global.__HUGO_AURA__.plsSettings,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
ipcMain.handle(
|
|
||||||
`${methodBase}.updatePlsSettings`,
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {import("electron").IpcMainInvokeEvent} _event
|
|
||||||
* @param {Record<any, any>} arg
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
(_event, arg) => {
|
|
||||||
global.__HUGO_AURA__.plsSettings = arg;
|
|
||||||
ipcMain.send("assistant", `${methodBase}.post.onPlsSettingsUpdate`, arg);
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
ipcMain.handle(
|
|
||||||
`${methodBase}.getPlsRules`,
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @returns {{ success: boolean; data: Record<any, any> | null | undefined }}
|
|
||||||
*/
|
|
||||||
(_event, _arg) => {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
data: global.__HUGO_AURA__.plsRules,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
ipcMain.handle(
|
|
||||||
`${methodBase}.updatePlsRules`,
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {import("electron").IpcMainInvokeEvent} _event
|
|
||||||
* @param {Record<any, any>} arg
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
(_event, arg) => {
|
|
||||||
global.__HUGO_AURA__.plsRules = arg;
|
|
||||||
ipcMain.send("assistant", `${methodBase}.post.onPlsRulesUpdate`, arg);
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
ipcMain.on(
|
|
||||||
`${methodBase}.ws.broadcastMessageRecv`,
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {import("electron").IpcMainEvent} _event
|
|
||||||
* @param {PLSResponse} arg
|
|
||||||
*/
|
|
||||||
(_event, arg) => {
|
|
||||||
ipcMain.send("assistant", `${methodBase}.ws.post.onNewMsgRecv`, arg);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
ipcMain.handle(
|
|
||||||
`${methodBase}.ws.sendWsMessage`,
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {import("electron").IpcMainInvokeEvent} _event
|
|
||||||
* @param {ClientPLSRequest} arg
|
|
||||||
*/
|
|
||||||
(_event, arg) => {
|
|
||||||
ipcMain.send(
|
|
||||||
"desktopAssistant",
|
|
||||||
`${methodBase}.ws.post.onReqSendMsg`,
|
|
||||||
arg
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
ipcMain.handle(
|
|
||||||
`${methodBase}.syncPlsConfig`,
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {import("electron").IpcMainInvokeEvent} event
|
|
||||||
* @param {{ basic: Record<any, any>, rules: Record<any, any> }} arg
|
|
||||||
*/
|
|
||||||
(event, arg) => {
|
|
||||||
global.__HUGO_AURA__.plsRules = arg.rules;
|
|
||||||
global.__HUGO_AURA__.plsSettings = arg.basic;
|
|
||||||
|
|
||||||
ipcMain.send("*", `${methodBase}.syncPlsConfig`, arg, event.sender);
|
|
||||||
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
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>";
|
|
||||||
|
|
||||||
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,
|
|
||||||
});
|
|
||||||
console.error(
|
|
||||||
`${logHeader} Failed to remove PLS bin, error:`,
|
|
||||||
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(
|
|
||||||
`${methodBase}.retryPlsConnect`,
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {import("electron").IpcMainInvokeEvent} _event
|
|
||||||
* @param {any} arg
|
|
||||||
* @returns {{ success: boolean, status: "Already" | "Retrying" }}
|
|
||||||
*/
|
|
||||||
(_event, arg) => {
|
|
||||||
if (global.__HUGO_AURA__.plsStats?.connected) {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
status: "Already",
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
ipcMain.send("desktopAssistant", `${methodBase}.retryPlsConnect`, arg);
|
|
||||||
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
status: "Retrying",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
ipcMain.handle(
|
|
||||||
`${methodBase}.post.updateRetryStatus`,
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {import("electron").IpcMainInvokeEvent} _event
|
|
||||||
* @param {{ success: boolean }} arg
|
|
||||||
*/
|
|
||||||
(_event, arg) => {
|
|
||||||
ipcMain.send("assistant", `${methodBase}.post.updateRetryStatus`, arg);
|
|
||||||
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = { applyPlsIpcHandler };
|
|
||||||
@@ -8,7 +8,10 @@ const util = require("util");
|
|||||||
* @param {import("../aura/types/main/core").WindowName} windowName
|
* @param {import("../aura/types/main/core").WindowName} windowName
|
||||||
*/
|
*/
|
||||||
const initLogger = (windowName) => {
|
const initLogger = (windowName) => {
|
||||||
const logDir = path.join(os.homedir(), "Documents", "HugoAura", "logs");
|
const logDir = path.join(global.__HUGO_AURA__.auraDir, "logs");
|
||||||
|
|
||||||
|
global.__HUGO_AURA__.logDir = logDir;
|
||||||
|
|
||||||
if (!fs.existsSync(logDir)) {
|
if (!fs.existsSync(logDir)) {
|
||||||
fs.mkdirSync(logDir, { recursive: true });
|
fs.mkdirSync(logDir, { recursive: true });
|
||||||
}
|
}
|
||||||
@@ -64,25 +67,22 @@ const initLogger = (windowName) => {
|
|||||||
console.error("[CRITICAL] UNCAUGHT EXCEPTION:", err);
|
console.error("[CRITICAL] UNCAUGHT EXCEPTION:", err);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(
|
console.log("[HugoAura / Logger] Logger initialized. Log file:", logFile);
|
||||||
"[HugoAura / Logger] Logger initialized. Log file:",
|
|
||||||
logFile
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const cleanupOldLogs = (logDir) => {
|
const cleanupOldLogs = (logDir) => {
|
||||||
try {
|
try {
|
||||||
const files = fs.readdirSync(logDir);
|
const files = fs.readdirSync(logDir);
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const sevenDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
|
const daysAgo = new Date(now.getTime() - 15 * 24 * 60 * 60 * 1000);
|
||||||
|
|
||||||
files.forEach((file) => {
|
files.forEach((file) => {
|
||||||
if (file.endsWith(".log")) {
|
if (file.endsWith(".log")) {
|
||||||
const filePath = path.join(logDir, file);
|
const filePath = path.join(logDir, file);
|
||||||
const stats = fs.statSync(filePath);
|
const stats = fs.statSync(filePath);
|
||||||
|
|
||||||
// 如果文件创建时间超过 30 天, 则删除
|
// 如果文件创建时间超过两周, 则删除
|
||||||
if (stats.birthtime < sevenDaysAgo) {
|
if (stats.birthtime < daysAgo) {
|
||||||
fs.unlinkSync(filePath);
|
fs.unlinkSync(filePath);
|
||||||
console.log(
|
console.log(
|
||||||
`[HugoAura / Logger / Cleanup] Cleaned log file: ${file}`
|
`[HugoAura / Logger / Cleanup] Cleaned log file: ${file}`
|
||||||
@@ -91,7 +91,10 @@ const cleanupOldLogs = (logDir) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("[HugoAura / Logger / Cleanup] Unexpected error occurred cleaning log file:", error);
|
console.error(
|
||||||
|
"[HugoAura / Logger / Cleanup] Unexpected error occurred cleaning log file:",
|
||||||
|
error
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class WindowHooksManager {
|
|||||||
|
|
||||||
const hooksPath = path.join(__dirname, "../../../aura/mainProcess/hooks");
|
const hooksPath = path.join(__dirname, "../../../aura/mainProcess/hooks");
|
||||||
|
|
||||||
/** @type {import("../../types/main/core").HooksMap} */
|
/** @type {import("../../types/main/core").UIHooksMap} */
|
||||||
const hooks = new Map();
|
const hooks = new Map();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -55,6 +55,9 @@ class WindowHooksManager {
|
|||||||
browserWindowInstance
|
browserWindowInstance
|
||||||
) {
|
) {
|
||||||
const stripWindowName = windowName.split("_")[0];
|
const stripWindowName = windowName.split("_")[0];
|
||||||
|
|
||||||
|
if (!global.__HUGO_AURA__.windowHooks) return;
|
||||||
|
|
||||||
if (!global.__HUGO_AURA__.windowHooks.has(stripWindowName)) {
|
if (!global.__HUGO_AURA__.windowHooks.has(stripWindowName)) {
|
||||||
console.log(
|
console.log(
|
||||||
`[HugoAura / Init / WDH] Window ${windowName} has no corresponding main process hooks, ignoring...`
|
`[HugoAura / Init / WDH] Window ${windowName} has no corresponding main process hooks, ignoring...`
|
||||||
|
|||||||
@@ -168,8 +168,8 @@
|
|||||||
observers.set(moduleKey, observer);
|
observers.set(moduleKey, observer);
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadResources = async (resources, type, moduleKey, isRevive) => {
|
const loadResources = async (resources, type, moduleKey) => {
|
||||||
if (!resources || isRevive) return [];
|
if (!resources) return [];
|
||||||
|
|
||||||
const resourceArray = Array.isArray(resources) ? resources : [resources];
|
const resourceArray = Array.isArray(resources) ? resources : [resources];
|
||||||
const loadedResources = [];
|
const loadedResources = [];
|
||||||
@@ -232,12 +232,11 @@
|
|||||||
const resources = new Set();
|
const resources = new Set();
|
||||||
moduleResources.set(moduleKey, resources);
|
moduleResources.set(moduleKey, resources);
|
||||||
|
|
||||||
if (config.pageCSS) {
|
if (config.pageCSS && !isRevive) {
|
||||||
const cssResources = await loadResources(
|
const cssResources = await loadResources(
|
||||||
config.pageCSS,
|
config.pageCSS,
|
||||||
"css",
|
"css",
|
||||||
moduleKey,
|
moduleKey
|
||||||
isRevive
|
|
||||||
);
|
);
|
||||||
cssResources.forEach((resource) => resources.add(resource));
|
cssResources.forEach((resource) => resources.add(resource));
|
||||||
}
|
}
|
||||||
@@ -250,16 +249,22 @@
|
|||||||
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) {
|
if (config.pageScript && !isRevive) {
|
||||||
const jsResources = await loadResources(
|
const jsResources = await loadResources(
|
||||||
config.pageScript,
|
config.pageScript,
|
||||||
"js",
|
"js",
|
||||||
moduleKey,
|
moduleKey
|
||||||
isRevive
|
|
||||||
);
|
);
|
||||||
jsResources.forEach((resource) => resources.add(resource));
|
jsResources.forEach((resource) => resources.add(resource));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isRevive) {
|
||||||
|
const onReviveEvent = new CustomEvent(
|
||||||
|
`onLoaderElRevive:${moduleKey}`
|
||||||
|
);
|
||||||
|
document.dispatchEvent(onReviveEvent);
|
||||||
|
}
|
||||||
|
|
||||||
const observer = new MutationObserver(() => {
|
const observer = new MutationObserver(() => {
|
||||||
if (
|
if (
|
||||||
!document.contains(container) &&
|
!document.contains(container) &&
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ class NetworkHook {
|
|||||||
endOfHook: rule.endOfHook || null,
|
endOfHook: rule.endOfHook || null,
|
||||||
hookedContent: rule.hookedContent || null,
|
hookedContent: rule.hookedContent || null,
|
||||||
hookedContentFunc: rule.hookedContentFunc || null,
|
hookedContentFunc: rule.hookedContentFunc || null,
|
||||||
|
ruleFn: rule.ruleFn || null,
|
||||||
|
config: ruleConfig || null,
|
||||||
});
|
});
|
||||||
console.log(`[HugoAura / NetworkHook] Loaded rule: ${rulePath}`);
|
console.log(`[HugoAura / NetworkHook] Loaded rule: ${rulePath}`);
|
||||||
}
|
}
|
||||||
@@ -240,44 +242,49 @@ class NetworkHook {
|
|||||||
hookContent +
|
hookContent +
|
||||||
endHook +
|
endHook +
|
||||||
content.substring(endIdx);
|
content.substring(endIdx);
|
||||||
|
|
||||||
const tempDir = path.join(os.tmpdir(), "hugo-aura-temp");
|
|
||||||
if (!fs.existsSync(tempDir)) {
|
|
||||||
fs.mkdirSync(tempDir, { recursive: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
const tempFile = path.join(tempDir, path.basename(normalizedPath));
|
|
||||||
fs.writeFileSync(tempFile, content, "utf8");
|
|
||||||
|
|
||||||
return {
|
|
||||||
redirectURL: `file://${
|
|
||||||
process.platform === "win32" ? "/" : ""
|
|
||||||
}${encodeURI(tempFile.replace(/\\/g, "/"))}`, // Seewo Hugo is still on Node 12 / Electron 8 TwT
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
console.warn(
|
console.warn(
|
||||||
`[HugoAura / NetworkHook] Could not find match points in file: ${normalizedPath}`
|
`[HugoAura / NetworkHook] Could not find match points in file: ${normalizedPath}`
|
||||||
);
|
);
|
||||||
return undefined;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else if (rule.ruleFn) {
|
||||||
|
content = rule.ruleFn(content, rule.config);
|
||||||
} else {
|
} else {
|
||||||
console.error(
|
console.error(
|
||||||
`[HugoAura / NetworkHook] Error processing rule:`,
|
`[HugoAura / NetworkHook] Error processing rule:`,
|
||||||
rule
|
rule,
|
||||||
|
"No available hook impl found."
|
||||||
);
|
);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const tempDir = path.join(os.tmpdir(), "hugo-aura-temp");
|
||||||
|
if (!fs.existsSync(tempDir)) {
|
||||||
|
fs.mkdirSync(tempDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const tempFile = path.join(tempDir, path.basename(normalizedPath));
|
||||||
|
fs.writeFileSync(tempFile, content, "utf8");
|
||||||
|
|
||||||
|
return {
|
||||||
|
redirectURL: `file://${
|
||||||
|
process.platform === "win32" ? "/" : ""
|
||||||
|
}${encodeURI(tempFile.replace(/\\/g, "/"))}`, // Seewo Hugo is still on Node 12 / Electron 8 TwT
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
console.error(
|
console.error(
|
||||||
`[HugoAura / NetworkHook] Error processing local file: normalizedPath not exists`,
|
`[HugoAura / NetworkHook] Error processing local file: normalizedPath not exists`,
|
||||||
normalizedPath
|
normalizedPath
|
||||||
);
|
);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(
|
console.error(
|
||||||
`[HugoAura / NetworkHook] Error processing local file:`,
|
`[HugoAura / NetworkHook] Error processing local file:`,
|
||||||
err
|
err
|
||||||
);
|
);
|
||||||
return null;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ const deepMerge = (target, source) => {
|
|||||||
|
|
||||||
class ConfigManager {
|
class ConfigManager {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.configDir = path.join(os.homedir(), "Documents", "HugoAura");
|
this.configDir = global.__HUGO_AURA__.auraDir;
|
||||||
this.configPath = path.join(this.configDir, "config.json");
|
this.configPath = path.join(this.configDir, "config.json");
|
||||||
this.encConfigPath = path.join(this.configDir, ".cache_2eafc8d0.dat"); // (雾
|
this.encConfigPath = path.join(this.configDir, ".cache_2eafc8d0.dat"); // (雾
|
||||||
/* ↑ 不使用 .tmp 扩展名, 不然容易真被清理了 */
|
/* ↑ 不使用 .tmp 扩展名, 不然容易真被清理了 */
|
||||||
@@ -78,10 +78,10 @@ class ConfigManager {
|
|||||||
this.isConfigReadFailed = false;
|
this.isConfigReadFailed = false;
|
||||||
this.side = "unknown";
|
this.side = "unknown";
|
||||||
|
|
||||||
if (fs.existsSync(this.configPath)) {
|
if (fs.existsSync(this.encConfigPath)) {
|
||||||
this.useEncConfig = false;
|
|
||||||
} else {
|
|
||||||
this.useEncConfig = true;
|
this.useEncConfig = true;
|
||||||
|
} else {
|
||||||
|
this.useEncConfig = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (global.__HUGO_AURA_EVENT_BUS__) {
|
if (global.__HUGO_AURA_EVENT_BUS__) {
|
||||||
@@ -95,6 +95,45 @@ class ConfigManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
migrateOldConfigFile() {
|
||||||
|
if (this.configDir === path.join(os.homedir(), "Documents", "HugoAura")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldConfigPath = path.join(
|
||||||
|
os.homedir(),
|
||||||
|
"Documents",
|
||||||
|
"HugoAura",
|
||||||
|
"config.json"
|
||||||
|
);
|
||||||
|
const oldEncConfigPath = path.join(
|
||||||
|
os.homedir(),
|
||||||
|
"Documents",
|
||||||
|
"HugoAura",
|
||||||
|
".cache_2eafc8d0.dat"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (fs.existsSync(oldConfigPath)) {
|
||||||
|
console.log(
|
||||||
|
`[HugoAura / Config] Old plain config file detected at ${oldConfigPath}, migrating...`
|
||||||
|
);
|
||||||
|
fs.copyFileSync(oldConfigPath, this.configPath);
|
||||||
|
fs.unlinkSync(oldConfigPath);
|
||||||
|
this.useEncConfig = false;
|
||||||
|
} else if (fs.existsSync(oldEncConfigPath)) {
|
||||||
|
console.log(
|
||||||
|
`[HugoAura / Config] Old enc config file detected at ${oldEncConfigPath}, migrating...`
|
||||||
|
);
|
||||||
|
fs.copyFileSync(oldEncConfigPath, this.encConfigPath);
|
||||||
|
fs.unlinkSync(oldEncConfigPath);
|
||||||
|
this.useEncConfig = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`[HugoAura / Config] Moved old config file to ${this.configDir}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
getHugoAuraConfigPath() {
|
getHugoAuraConfigPath() {
|
||||||
return path.dirname(
|
return path.dirname(
|
||||||
this.useEncConfig ? this.encConfigPath : this.configPath
|
this.useEncConfig ? this.encConfigPath : this.configPath
|
||||||
@@ -144,9 +183,14 @@ class ConfigManager {
|
|||||||
return this.getDefaultConfig(); // should be changed, too
|
return this.getDefaultConfig(); // should be changed, too
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error("[HugoAura / Config / ERROR] Failed to decrypt config");
|
console.error(
|
||||||
|
"[HugoAura / Config / ERROR] Failed to decrypt config, falling back to use plain config"
|
||||||
|
);
|
||||||
|
this.useEncConfig = false;
|
||||||
this.isConfigReadFailed = true;
|
this.isConfigReadFailed = true;
|
||||||
return this.getDefaultConfig(); // This behaviour should be changed later
|
config = JSON.parse(fs.readFileSync(this.configPath, "utf8"));
|
||||||
|
if (this.isConfigReadFailed) this.isConfigReadFailed = false;
|
||||||
|
return config; // This behaviour should be changed later
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
config = JSON.parse(fs.readFileSync(this.configPath, "utf8"));
|
config = JSON.parse(fs.readFileSync(this.configPath, "utf8"));
|
||||||
@@ -176,7 +220,15 @@ class ConfigManager {
|
|||||||
console.error(
|
console.error(
|
||||||
"[HugoAura / Config / Write / ERROR] Failed to write config: Retrieve enc password failed"
|
"[HugoAura / Config / Write / ERROR] Failed to write config: Retrieve enc password failed"
|
||||||
);
|
);
|
||||||
return false;
|
console.warn(
|
||||||
|
"[HugoAura / Config / Write / WARN] Falling back to use plain config."
|
||||||
|
);
|
||||||
|
fs.writeFileSync(
|
||||||
|
this.configPath,
|
||||||
|
JSON.stringify(config, null, 2),
|
||||||
|
"utf8"
|
||||||
|
);
|
||||||
|
this.useEncConfig = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
|
|||||||
@@ -11,6 +11,9 @@
|
|||||||
},
|
},
|
||||||
"vendor/screenLock": {
|
"vendor/screenLock": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
"fastfail": false,
|
||||||
|
"showDirectUnlock": false,
|
||||||
|
"clickBtnToExit": true,
|
||||||
"disableKeyboardHook": false,
|
"disableKeyboardHook": false,
|
||||||
"authRewriteType": "customActivationCode",
|
"authRewriteType": "customActivationCode",
|
||||||
"customActivationCode": {
|
"customActivationCode": {
|
||||||
@@ -24,13 +27,32 @@
|
|||||||
},
|
},
|
||||||
"disableBehaviorAudit": {
|
"disableBehaviorAudit": {
|
||||||
"enabled": true
|
"enabled": true
|
||||||
|
},
|
||||||
|
"appearance/switchUsbInsertPromptBtn": {
|
||||||
|
"enabled": false,
|
||||||
|
"mode": "switch"
|
||||||
|
},
|
||||||
|
"appearance/banAdBlockPrompt": {
|
||||||
|
"enabled": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ssa": {
|
||||||
|
"ux": {
|
||||||
|
"easiAssistant": {
|
||||||
|
"autoHide": false,
|
||||||
|
"notDisplay": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"auraSettings": {
|
"auraSettings": {
|
||||||
"settingsPasswordEnabled": false,
|
"settingsPasswordEnabled": false,
|
||||||
"settingsPasswordWithSalt": "32703D292460CC9A3B867494D6AD9A8E4A3ADF0FAA4D6867BC4D412CC3927D02E47C6D0B1763BB53E57B2241C6193433561CDA09D7C48CA03983072B876F0965",
|
"settingsPasswordWithSalt": "32703D292460CC9A3B867494D6AD9A8E4A3ADF0FAA4D6867BC4D412CC3927D02E47C6D0B1763BB53E57B2241C6193433561CDA09D7C48CA03983072B876F0965",
|
||||||
"encryptConfig": false,
|
"encryptConfig": false,
|
||||||
"appearance": {},
|
"appearance": {
|
||||||
|
"appBar": {
|
||||||
|
"actionBtnsOnRight": false
|
||||||
|
}
|
||||||
|
},
|
||||||
"uiAccessMethod": {
|
"uiAccessMethod": {
|
||||||
"showEntryIcon": true,
|
"showEntryIcon": true,
|
||||||
"fallbackAccessMethods": {
|
"fallbackAccessMethods": {
|
||||||
|
|||||||
@@ -6,7 +6,12 @@ const { exec, execSync } = require("child_process");
|
|||||||
|
|
||||||
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 = ["HKEY_USERS", ".DEFAULT", "SOFTWARE", "HugoAura"].join("\\");
|
const AURA_REGISTRY_PATH = [
|
||||||
|
"HKEY_USERS",
|
||||||
|
".DEFAULT",
|
||||||
|
"SOFTWARE",
|
||||||
|
"HugoAura",
|
||||||
|
].join("\\");
|
||||||
|
|
||||||
class RegistryManager {
|
class RegistryManager {
|
||||||
/**
|
/**
|
||||||
@@ -341,19 +346,27 @@ class RegistryManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} relativePath
|
* @param {string} keyPath
|
||||||
* @param {string} keyName
|
* @param {string} keyName
|
||||||
* @param {boolean | undefined} silent
|
* @param {boolean | undefined} silent
|
||||||
|
* @param {boolean} absolute
|
||||||
|
* @param {any} regex
|
||||||
* @returns {Promise<{ success: boolean, data: string | null, error: Error | null }>}
|
* @returns {Promise<{ success: boolean, data: string | null, error: Error | null }>}
|
||||||
*/
|
*/
|
||||||
async readRegKey(relativePath, keyName, silent = false) {
|
async readRegKey(
|
||||||
|
keyPath,
|
||||||
|
keyName,
|
||||||
|
silent = false,
|
||||||
|
absolute = false,
|
||||||
|
regex = null
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
const { stdout } = await new Promise((resolve, reject) => {
|
const { stdout } = await new Promise((resolve, reject) => {
|
||||||
exec(
|
exec(
|
||||||
[
|
[
|
||||||
"reg",
|
"reg",
|
||||||
"query",
|
"query",
|
||||||
[AURA_REGISTRY_PATH, relativePath].join("\\"),
|
absolute ? keyPath : [AURA_REGISTRY_PATH, keyPath].join("\\"),
|
||||||
"/v",
|
"/v",
|
||||||
`\"${keyName}\"`,
|
`\"${keyName}\"`,
|
||||||
].join(" "),
|
].join(" "),
|
||||||
@@ -367,12 +380,12 @@ class RegistryManager {
|
|||||||
|
|
||||||
if (!silent) {
|
if (!silent) {
|
||||||
console.debug(
|
console.debug(
|
||||||
`${LOG_PREFIX_FUNC} / SUCCESS] Successfully read reg key ${relativePath}/${keyName}, stdout:`,
|
`${LOG_PREFIX_FUNC} / SUCCESS] Successfully read reg key ${keyPath}/${keyName}, stdout:`,
|
||||||
stdout
|
stdout
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const match = stdout.match(/REG_SZ\s+(.+)/);
|
const match = regex ? stdout.match(regex) : stdout.match(/REG_SZ\s+(.+)/);
|
||||||
|
|
||||||
if (!match) {
|
if (!match) {
|
||||||
console.warn(`${LOG_PREFIX} / WARN] Data not found in stdout`);
|
console.warn(`${LOG_PREFIX} / WARN] Data not found in stdout`);
|
||||||
@@ -390,10 +403,7 @@ class RegistryManager {
|
|||||||
error: null,
|
error: null,
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(
|
console.error(`${LOG_PREFIX} / ERROR] Failed to read reg key, error:`, e);
|
||||||
`${LOG_PREFIX} / ERROR] Failed to read reg key, error:`,
|
|
||||||
e
|
|
||||||
);
|
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
data: null,
|
data: null,
|
||||||
@@ -403,18 +413,26 @@ class RegistryManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} relativePath
|
* @param {string} keyPath
|
||||||
* @param {string} keyName
|
* @param {string} keyName
|
||||||
* @param {boolean | undefined} silent
|
* @param {boolean | undefined} silent
|
||||||
|
* @param {boolean} absolute
|
||||||
|
* @param {any} regex
|
||||||
* @returns {{ success: boolean, data: string | null, error: Error | null }}
|
* @returns {{ success: boolean, data: string | null, error: Error | null }}
|
||||||
*/
|
*/
|
||||||
readRegKeySync(relativePath, keyName, silent = false) {
|
readRegKeySync(
|
||||||
|
keyPath,
|
||||||
|
keyName,
|
||||||
|
silent = false,
|
||||||
|
absolute = false,
|
||||||
|
regex = null
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
const readResult = execSync(
|
const readResult = execSync(
|
||||||
[
|
[
|
||||||
"reg",
|
"reg",
|
||||||
"query",
|
"query",
|
||||||
[AURA_REGISTRY_PATH, relativePath].join("\\"),
|
absolute ? keyPath : [AURA_REGISTRY_PATH, keyPath].join("\\"),
|
||||||
"/v",
|
"/v",
|
||||||
`\"${keyName}\"`,
|
`\"${keyName}\"`,
|
||||||
].join(" "),
|
].join(" "),
|
||||||
@@ -424,11 +442,13 @@ class RegistryManager {
|
|||||||
if (readResult) {
|
if (readResult) {
|
||||||
if (!silent) {
|
if (!silent) {
|
||||||
console.debug(
|
console.debug(
|
||||||
`${LOG_PREFIX_FUNC} / SUCCESS] Successfully read reg key ${relativePath}/${keyName}, stdout:`,
|
`${LOG_PREFIX_FUNC} / SUCCESS] Successfully read reg key ${keyPath}/${keyName}, stdout:`,
|
||||||
readResult
|
readResult
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const match = readResult.match(/REG_SZ\s+(.+)/);
|
const match = regex
|
||||||
|
? readResult.match(regex)
|
||||||
|
: readResult.match(/REG_SZ\s+(.+)/);
|
||||||
|
|
||||||
if (!match) {
|
if (!match) {
|
||||||
console.warn(`${LOG_PREFIX} / WARN] Data not found in stdout`);
|
console.warn(`${LOG_PREFIX} / WARN] Data not found in stdout`);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const buildClass = (n) => {
|
const buildClass = (n) => {
|
||||||
// >>> BEGIN OF SEEWO HUGO ORIGINAL CODE <<< //
|
// >>> BEGIN OF SEEWO HUGO ORIGINAL CODE <<< //
|
||||||
const s = n(237),
|
const s = n(239),
|
||||||
o = n(7);
|
o = n(7);
|
||||||
class WebSocketManager {
|
class WebSocketManager {
|
||||||
constructor(e, t) {
|
constructor(e, t) {
|
||||||
|
|||||||
20
src/aura/jsRewrite/network/appearance/banAdBlockPrompt.js
Normal file
20
src/aura/jsRewrite/network/appearance/banAdBlockPrompt.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/// Rewrite rules basic config section begins ///
|
||||||
|
|
||||||
|
const type = "localResource";
|
||||||
|
|
||||||
|
const urlPattern = "floatWindow.js";
|
||||||
|
|
||||||
|
/// End of the rewrite rules basic config section ///
|
||||||
|
|
||||||
|
let ruleFn = (originalContent, ruleConfig) => {
|
||||||
|
if (ruleConfig.enabled) {
|
||||||
|
originalContent = `(() => { window.close() });`;
|
||||||
|
}
|
||||||
|
return originalContent;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
type,
|
||||||
|
urlPattern,
|
||||||
|
ruleFn,
|
||||||
|
};
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/// Rewrite rules basic config section begins ///
|
||||||
|
|
||||||
|
const type = "localResource";
|
||||||
|
|
||||||
|
const urlPattern = "usbInsertPrompt.js";
|
||||||
|
|
||||||
|
/// End of the rewrite rules basic config section ///
|
||||||
|
|
||||||
|
let ruleFn = (originalContent, ruleConfig) => {
|
||||||
|
if (ruleConfig.mode === "switch") {
|
||||||
|
originalContent = originalContent.replace(/查杀可预防设备感染,守护设备安全/g, "检测到新的设备插入");
|
||||||
|
originalContent = originalContent.replace(/开始查杀(推荐)/g, "打开 U 盘");
|
||||||
|
originalContent = originalContent.replace(
|
||||||
|
/onClick:this.handleStartVirusKilling/g,
|
||||||
|
"onClick:this.handleOpen"
|
||||||
|
);
|
||||||
|
originalContent = originalContent.replace(
|
||||||
|
/,D.a.createElement\("p",null,"打开U盘"\)/g,
|
||||||
|
""
|
||||||
|
);
|
||||||
|
} else if (ruleConfig.mode === "hide") {
|
||||||
|
originalContent = originalContent.replace(/15e3/g, "0");
|
||||||
|
}
|
||||||
|
return originalContent;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
type,
|
||||||
|
urlPattern,
|
||||||
|
ruleFn,
|
||||||
|
};
|
||||||
10
src/aura/jsRewrite/vendor/passwordValidation.js
vendored
10
src/aura/jsRewrite/vendor/passwordValidation.js
vendored
@@ -46,8 +46,8 @@ const newFunction = function (e, t, b) {
|
|||||||
_ = b(14),
|
_ = b(14),
|
||||||
M = b(44),
|
M = b(44),
|
||||||
g = b(22),
|
g = b(22),
|
||||||
w = (b(432), b(7)),
|
w = (b(433), b(7)),
|
||||||
D = b(17),
|
D = b(15),
|
||||||
T = b.n(D),
|
T = b.n(D),
|
||||||
j = b(10),
|
j = b(10),
|
||||||
E = b.n(j),
|
E = b.n(j),
|
||||||
@@ -56,7 +56,7 @@ const newFunction = function (e, t, b) {
|
|||||||
z = b(19),
|
z = b(19),
|
||||||
Y = b(78),
|
Y = b(78),
|
||||||
L = b.n(Y);
|
L = b.n(Y);
|
||||||
b(444);
|
b(445);
|
||||||
var x,
|
var x,
|
||||||
k = 2,
|
k = 2,
|
||||||
S = 0,
|
S = 0,
|
||||||
@@ -178,7 +178,7 @@ const newFunction = function (e, t, b) {
|
|||||||
value: s,
|
value: s,
|
||||||
size: n.width || null,
|
size: n.width || null,
|
||||||
})
|
})
|
||||||
: v.a.createElement("img", { src: b(447) })
|
: v.a.createElement("img", { src: b(448) })
|
||||||
),
|
),
|
||||||
d !== C &&
|
d !== C &&
|
||||||
d !== O &&
|
d !== O &&
|
||||||
@@ -386,8 +386,8 @@ const newFunction = function (e, t, b) {
|
|||||||
} else {
|
} else {
|
||||||
originalFunc();
|
originalFunc();
|
||||||
}
|
}
|
||||||
|
// ### EOR ### //
|
||||||
break;
|
break;
|
||||||
// ### EOR ### //
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
63
src/aura/jsRewrite/vendor/screenLock.js
vendored
63
src/aura/jsRewrite/vendor/screenLock.js
vendored
@@ -30,12 +30,12 @@ const newFunction = function (e, t, n) {
|
|||||||
p = n.n(h),
|
p = n.n(h),
|
||||||
_ = n(41),
|
_ = n(41),
|
||||||
M = n.n(_),
|
M = n.n(_),
|
||||||
g = (n(808), n(7)),
|
g = (n(814), n(7)),
|
||||||
b = n(9),
|
b = n(9),
|
||||||
y = n(8),
|
y = n(8),
|
||||||
v = n.n(y),
|
v = n.n(y),
|
||||||
w =
|
w =
|
||||||
(n(810),
|
(n(816),
|
||||||
{
|
{
|
||||||
"./numberKeyboard.less": {
|
"./numberKeyboard.less": {
|
||||||
"ps-icon": "numberKeyboard__ps-icon__1KO_WOCz",
|
"ps-icon": "numberKeyboard__ps-icon__1KO_WOCz",
|
||||||
@@ -528,9 +528,12 @@ const newFunction = function (e, t, n) {
|
|||||||
scanCode: "scanCode",
|
scanCode: "scanCode",
|
||||||
activationCode: "activationCode",
|
activationCode: "activationCode",
|
||||||
password: "password",
|
password: "password",
|
||||||
|
// ### BOR ### //
|
||||||
|
direct: "direct",
|
||||||
|
// ### EOR ### //
|
||||||
},
|
},
|
||||||
G = n(19);
|
G = n(19);
|
||||||
n(812);
|
n(818);
|
||||||
function W(e) {
|
function W(e) {
|
||||||
var t = e.canvasRender,
|
var t = e.canvasRender,
|
||||||
n = void 0 === t || t,
|
n = void 0 === t || t,
|
||||||
@@ -589,12 +592,12 @@ const newFunction = function (e, t, n) {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
n(815);
|
n(821);
|
||||||
var J = n(64),
|
var J = n(64),
|
||||||
V = n(20);
|
V = n(20);
|
||||||
var q,
|
var q,
|
||||||
Z,
|
Z,
|
||||||
X = n(16);
|
X = n(17);
|
||||||
function K(r) {
|
function K(r) {
|
||||||
var a = (function () {
|
var a = (function () {
|
||||||
if ("undefined" == typeof Reflect || !Reflect.construct) return !1;
|
if ("undefined" == typeof Reflect || !Reflect.construct) return !1;
|
||||||
@@ -805,7 +808,7 @@ const newFunction = function (e, t, n) {
|
|||||||
);
|
);
|
||||||
})(h.PureComponent))
|
})(h.PureComponent))
|
||||||
) || Z,
|
) || Z,
|
||||||
oe = (n(817), n(137).a);
|
oe = (n(823), n(137).a);
|
||||||
function se(t, e) {
|
function se(t, e) {
|
||||||
var n = Object.keys(t);
|
var n = Object.keys(t);
|
||||||
if (Object.getOwnPropertySymbols) {
|
if (Object.getOwnPropertySymbols) {
|
||||||
@@ -913,6 +916,7 @@ const newFunction = function (e, t, n) {
|
|||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
(o.checkPasswordCorrect = function () {
|
(o.checkPasswordCorrect = function () {
|
||||||
|
// ### BOR ### //
|
||||||
const originalAuthFailed = () => {
|
const originalAuthFailed = () => {
|
||||||
o.failCount++,
|
o.failCount++,
|
||||||
o.passwordCheckFail(),
|
o.passwordCheckFail(),
|
||||||
@@ -955,6 +959,7 @@ const newFunction = function (e, t, n) {
|
|||||||
o.state.inputPassword.join("") === o.password
|
o.state.inputPassword.join("") === o.password
|
||||||
? (o.props.onActivationCorrect(), (o.failCount = 0))
|
? (o.props.onActivationCorrect(), (o.failCount = 0))
|
||||||
: customAuthFailed();
|
: customAuthFailed();
|
||||||
|
// ### EOR ### //
|
||||||
}),
|
}),
|
||||||
(o.insertHtml = function () {
|
(o.insertHtml = function () {
|
||||||
return p.a.createElement(
|
return p.a.createElement(
|
||||||
@@ -1002,7 +1007,7 @@ const newFunction = function (e, t, n) {
|
|||||||
n
|
n
|
||||||
);
|
);
|
||||||
})(I),
|
})(I),
|
||||||
me = (n(819), n(38));
|
me = (n(825), n(38));
|
||||||
function fe(r) {
|
function fe(r) {
|
||||||
var a = (function () {
|
var a = (function () {
|
||||||
if ("undefined" == typeof Reflect || !Reflect.construct) return !1;
|
if ("undefined" == typeof Reflect || !Reflect.construct) return !1;
|
||||||
@@ -1051,6 +1056,9 @@ const newFunction = function (e, t, n) {
|
|||||||
f()(de, H.scanCode, "扫码"),
|
f()(de, H.scanCode, "扫码"),
|
||||||
f()(de, H.activationCode, "激活码"),
|
f()(de, H.activationCode, "激活码"),
|
||||||
f()(de, H.password, "密码"),
|
f()(de, H.password, "密码"),
|
||||||
|
// ### BOR ### //
|
||||||
|
__config.showDirectUnlock ? f()(de, H.direct, "直接") : null,
|
||||||
|
// ### EOR ### //
|
||||||
de),
|
de),
|
||||||
ge = (function (e) {
|
ge = (function (e) {
|
||||||
u()(i, e);
|
u()(i, e);
|
||||||
@@ -1076,6 +1084,26 @@ const newFunction = function (e, t, n) {
|
|||||||
(r.adminHidePassword = !1),
|
(r.adminHidePassword = !1),
|
||||||
(r.handleChooseType = function (e) {
|
(r.handleChooseType = function (e) {
|
||||||
return function () {
|
return function () {
|
||||||
|
// ### BOR ### //
|
||||||
|
if (e === "direct" && __config.showDirectUnlock) {
|
||||||
|
global.__HUGO_AURA_BREAKUP__[
|
||||||
|
"vendor/screenLock"
|
||||||
|
].goActivationCorrect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e === "activationCode" && __config.clickBtnToExit) {
|
||||||
|
global.__HUGO_AURA_BREAKUP__["vendor/screenLock"]
|
||||||
|
.btnClickCounter++;
|
||||||
|
if (
|
||||||
|
global.__HUGO_AURA_BREAKUP__["vendor/screenLock"]
|
||||||
|
.btnClickCounter === 10
|
||||||
|
) {
|
||||||
|
global.__HUGO_AURA_BREAKUP__[
|
||||||
|
"vendor/screenLock"
|
||||||
|
].goActivationCorrect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ### EOR ### //
|
||||||
r.setState({ chooseType: e }),
|
r.setState({ chooseType: e }),
|
||||||
(r.hasTouched = !0),
|
(r.hasTouched = !0),
|
||||||
r.handleGetSelectItemPos(e);
|
r.handleGetSelectItemPos(e);
|
||||||
@@ -1208,6 +1236,21 @@ const newFunction = function (e, t, n) {
|
|||||||
{
|
{
|
||||||
key: "componentDidMount",
|
key: "componentDidMount",
|
||||||
value: function () {
|
value: function () {
|
||||||
|
// ### BOR ### //
|
||||||
|
if (__config.enabled && __config.fastfail) {
|
||||||
|
this.props.onActivationCorrect();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (!global.__HUGO_AURA_BREAKUP__)
|
||||||
|
global.__HUGO_AURA_BREAKUP__ = {};
|
||||||
|
global.__HUGO_AURA_BREAKUP__["vendor/screenLock"] = {
|
||||||
|
goActivationCorrect: () => {
|
||||||
|
this.props.onActivationCorrect();
|
||||||
|
},
|
||||||
|
btnClickCounter: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// ### EOR ### //
|
||||||
var e = this;
|
var e = this;
|
||||||
this.handleChangeHidePassword(),
|
this.handleChangeHidePassword(),
|
||||||
this.chooseTypeOfIotLineStatus(function () {
|
this.chooseTypeOfIotLineStatus(function () {
|
||||||
@@ -1323,7 +1366,10 @@ const newFunction = function (e, t, n) {
|
|||||||
style: { left: o, width: s },
|
style: { left: o, width: s },
|
||||||
}),
|
}),
|
||||||
Object.keys(Me).map(function (e, t) {
|
Object.keys(Me).map(function (e, t) {
|
||||||
return r.includes(e)
|
// ### BOR ### //
|
||||||
|
const showDirectCondition =
|
||||||
|
__config.showDirectUnlock && e === "direct";
|
||||||
|
return r.includes(e) || showDirectCondition
|
||||||
? p.a.createElement(
|
? p.a.createElement(
|
||||||
"div",
|
"div",
|
||||||
{
|
{
|
||||||
@@ -1338,6 +1384,7 @@ const newFunction = function (e, t, n) {
|
|||||||
m
|
m
|
||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
|
// ### EOR ### //
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
6
src/aura/types/render/global.d.ts
vendored
6
src/aura/types/render/global.d.ts
vendored
@@ -3,14 +3,14 @@ interface HugoAuraGlobal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface AssistantHugoAuraGlobal extends HugoAuraGlobal {
|
interface AssistantHugoAuraGlobal extends HugoAuraGlobal {
|
||||||
plsStatus: PLSStatus;
|
plsStatus: AikariStatus;
|
||||||
plsRules: Record<any, any>;
|
plsRules: Record<any, any>;
|
||||||
plsSettings: Record<any, any>;
|
plsSettings: Record<any, any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DesktopAssistantHugoAuraGlobal extends HugoAuraGlobal {
|
interface AuraWSKeepAliveWindowHugoAuraGlobal extends HugoAuraGlobal {
|
||||||
plsWs: WebSocket | null;
|
plsWs: WebSocket | null;
|
||||||
plsStats: PLSStatus;
|
plsStats: AikariStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
type UIFunctionsObject = Record<string, any>;
|
type UIFunctionsObject = Record<string, any>;
|
||||||
|
|||||||
17
src/aura/types/shared/pls/status.d.ts → src/aura/types/shared/aikari/status.d.ts
vendored
Executable file → Normal file
17
src/aura/types/shared/pls/status.d.ts → src/aura/types/shared/aikari/status.d.ts
vendored
Executable file → Normal file
@@ -1,28 +1,29 @@
|
|||||||
import { RendererProcessOnlyVal } from "../global";
|
import { RendererProcessOnlyVal } from "../global";
|
||||||
|
|
||||||
type PLSStatusDesc =
|
type AikariStatusDesc =
|
||||||
| "dead"
|
| "dead"
|
||||||
| "running"
|
| "running"
|
||||||
| "notReady"
|
| "notReady"
|
||||||
| "downloading"
|
| "downloading"
|
||||||
|
| "installing"
|
||||||
| "notInstalled";
|
| "notInstalled";
|
||||||
|
|
||||||
interface PLSStatus {
|
interface AikariStatus {
|
||||||
installed: boolean;
|
installed: boolean;
|
||||||
detached: boolean;
|
detached: boolean;
|
||||||
connected: boolean;
|
connected: boolean;
|
||||||
launched: boolean;
|
launched: boolean;
|
||||||
status: PLSStatusDesc;
|
status: AikariStatusDesc;
|
||||||
version: string;
|
version: string;
|
||||||
authToken: string;
|
authToken: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
type PLSLifecycleType = "isDetached" | "isSvcInstalled" | "isSvcStart";
|
type AikariLifecycleType = "isDetached" | "isSvcInstalled" | "isSvcStart";
|
||||||
|
|
||||||
type PLSLifecycleControlType =
|
type AikariLifecycleControlType =
|
||||||
| "instSvc"
|
| "instSvc"
|
||||||
| "rmSvc"
|
| "uninstSvc"
|
||||||
| "startSvc"
|
| "startSvc"
|
||||||
| "stopSvc"
|
| "stopSvc"
|
||||||
| "rmBin"
|
| "uninst"
|
||||||
| "dlBin";
|
| "inst";
|
||||||
7
src/aura/types/shared/pls/websocket.d.ts → src/aura/types/shared/aikari/websocket.d.ts
vendored
Executable file → Normal file
7
src/aura/types/shared/pls/websocket.d.ts → src/aura/types/shared/aikari/websocket.d.ts
vendored
Executable file → Normal file
@@ -1,17 +1,18 @@
|
|||||||
interface ClientPLSRequest {
|
interface ClientAikariRequest {
|
||||||
method: string;
|
method: string;
|
||||||
data: Record<any, any>;
|
data: Record<any, any>;
|
||||||
eventId: string;
|
eventId: string;
|
||||||
|
module: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PLSResponse {
|
interface AikariResponse {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
code: number;
|
code: number;
|
||||||
data: Record<any, any>;
|
data: Record<any, any>;
|
||||||
eventId: string;
|
eventId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PLSPush {
|
interface AikariPush {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
type: string;
|
type: string;
|
||||||
data: Record<any, any>;
|
data: Record<any, any>;
|
||||||
13
src/aura/types/shared/global.d.ts
vendored
13
src/aura/types/shared/global.d.ts
vendored
@@ -3,7 +3,7 @@ import type EventBus from "../../utils/eventBus";
|
|||||||
import { HookedWindowsMap, UIHooksMap, WindowHooksMap } from "../main/core";
|
import { HookedWindowsMap, UIHooksMap, WindowHooksMap } from "../main/core";
|
||||||
import { UIHooksObject } from "../render/uiHook";
|
import { UIHooksObject } from "../render/uiHook";
|
||||||
import ConfigManager from "../../init/shared/configManager";
|
import ConfigManager from "../../init/shared/configManager";
|
||||||
import { PLSStatus } from "./pls/status";
|
import { AikariStatus } from "./aikari/status";
|
||||||
|
|
||||||
type MainProcessOnlyVal<T> = T;
|
type MainProcessOnlyVal<T> = T;
|
||||||
type RendererProcessOnlyVal<T> = T;
|
type RendererProcessOnlyVal<T> = T;
|
||||||
@@ -14,10 +14,11 @@ interface GlobalHugoAuraInfo {
|
|||||||
fsTasks?: MainProcessOnlyVal<FSTasks>;
|
fsTasks?: MainProcessOnlyVal<FSTasks>;
|
||||||
hookedWindows?: MainProcessOnlyVal<HookedWindowsMap>;
|
hookedWindows?: MainProcessOnlyVal<HookedWindowsMap>;
|
||||||
ipcInit?: MainProcessOnlyVal<boolean>;
|
ipcInit?: MainProcessOnlyVal<boolean>;
|
||||||
plsRules?: Record<any, any> | null;
|
auraDir: MainProcessOnlyVal<string>;
|
||||||
plsSettings?: Record<any, any> | null;
|
aikariRules?: Record<any, any> | null;
|
||||||
plsStats?: PLSStatus | null;
|
aikariSettings?: Record<any, any> | null;
|
||||||
plsWs?: RendererProcessOnlyVal<WebSocket>;
|
aikariStats?: AikariStatus | null;
|
||||||
|
aikariWs?: RendererProcessOnlyVal<WebSocket>;
|
||||||
uiHooks?: MainProcessOnlyVal<UIHooksMap>;
|
uiHooks?: MainProcessOnlyVal<UIHooksMap>;
|
||||||
windowHooks?: MainProcessOnlyVal<WindowHooksMap>;
|
windowHooks?: MainProcessOnlyVal<WindowHooksMap>;
|
||||||
version: RendererProcessOnlyVal<string>;
|
version: RendererProcessOnlyVal<string>;
|
||||||
@@ -25,7 +26,7 @@ interface GlobalHugoAuraInfo {
|
|||||||
|
|
||||||
interface GlobalHugoAuraApiInfo {
|
interface GlobalHugoAuraApiInfo {
|
||||||
domains: string[];
|
domains: string[];
|
||||||
plsUpdate: string;
|
aikariUpdate: string;
|
||||||
auraUpdate: string;
|
auraUpdate: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
129
src/aura/ui/aikari/onConnectedSeq.js
Normal file
129
src/aura/ui/aikari/onConnectedSeq.js
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
const { genRandomHex } = require("../../utils/crypto");
|
||||||
|
|
||||||
|
const IPC_METHOD_BASE = "$aura.aikari";
|
||||||
|
|
||||||
|
/** @type {Map<string, any>} */
|
||||||
|
const wsGetCallbacks = new Map();
|
||||||
|
|
||||||
|
const actions = {
|
||||||
|
getAikariVersion: async (originalAikariStates, wsObj) => {
|
||||||
|
const eventId = genRandomHex();
|
||||||
|
wsObj.send(
|
||||||
|
JSON.stringify({
|
||||||
|
module: "launcher",
|
||||||
|
eventId: eventId,
|
||||||
|
method: "basic.props.getVersion",
|
||||||
|
data: {},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const promise = new Promise((resolve) => {
|
||||||
|
wsGetCallbacks.set(eventId, resolve);
|
||||||
|
});
|
||||||
|
const data = await promise;
|
||||||
|
if (data.success) {
|
||||||
|
originalAikariStates.version = data.data.version;
|
||||||
|
console.debug(
|
||||||
|
"[HugoAura / UI / Aikari OCMS] Updated Aikari version info: " +
|
||||||
|
data.data.version
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getAikariLauncherConfig: async (wsObj) => {
|
||||||
|
const eventId = genRandomHex();
|
||||||
|
wsObj.send(
|
||||||
|
JSON.stringify({
|
||||||
|
module: "launcher",
|
||||||
|
eventId,
|
||||||
|
method: "config.actions.getConfig",
|
||||||
|
data: {},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const promiseForConfig = new Promise((resolve) => {
|
||||||
|
wsGetCallbacks.set(eventId, resolve);
|
||||||
|
});
|
||||||
|
const data = await promiseForConfig;
|
||||||
|
if (data.success) {
|
||||||
|
console.debug(
|
||||||
|
"[HugoAura / UI / Aikari OCMS] Received Aikari launcher config: ",
|
||||||
|
data
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
wsObj.send(
|
||||||
|
JSON.stringify({
|
||||||
|
module: "launcher",
|
||||||
|
eventId,
|
||||||
|
method: "config.actions.getTelemetryIsEnabled",
|
||||||
|
data: {},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const promiseForTelemetry = new Promise((resolve) => {
|
||||||
|
wsGetCallbacks.set(eventId, resolve);
|
||||||
|
});
|
||||||
|
const telemetryConfig = await promiseForTelemetry;
|
||||||
|
if (telemetryConfig.success) {
|
||||||
|
data.data.telemetryEnabled = telemetryConfig.data.isEnabled;
|
||||||
|
} else {
|
||||||
|
data.data.telemetryEnabled = false;
|
||||||
|
}
|
||||||
|
return data.data;
|
||||||
|
},
|
||||||
|
getAikariPLSRules: async (wsObj) => {
|
||||||
|
const eventId = genRandomHex();
|
||||||
|
wsObj.send(
|
||||||
|
JSON.stringify({
|
||||||
|
module: "pls",
|
||||||
|
eventId,
|
||||||
|
method: "config.rules.getConfig",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const promise = new Promise((resolve) => {
|
||||||
|
wsGetCallbacks.set(eventId, resolve);
|
||||||
|
});
|
||||||
|
const data = await promise;
|
||||||
|
if (data.success) {
|
||||||
|
console.debug(
|
||||||
|
"[HugoAura / UI / Aikari OCMS] Received Aikari PLS rules: ",
|
||||||
|
data
|
||||||
|
);
|
||||||
|
return data.data;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const onAikariConnectedMsgSeq = async ({ curAikariStates, wsObj }) => {
|
||||||
|
const updatedAikariStates = { ...curAikariStates };
|
||||||
|
const onMsgRecvListener = (data) => {
|
||||||
|
if (wsGetCallbacks.has(data.detail.eventId)) {
|
||||||
|
wsGetCallbacks.get(data.detail.eventId)(data.detail);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
document.addEventListener("onAikariMessageRecv", onMsgRecvListener);
|
||||||
|
// Get Aikari Version
|
||||||
|
await actions.getAikariVersion(updatedAikariStates, wsObj);
|
||||||
|
// Get Aikari Launcher Config
|
||||||
|
const aikariLauncherConfig = await actions.getAikariLauncherConfig(wsObj);
|
||||||
|
if (aikariLauncherConfig) {
|
||||||
|
global.ipcRenderer.invoke(
|
||||||
|
`${IPC_METHOD_BASE}.updateAikariSettings`,
|
||||||
|
aikariLauncherConfig
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Get Aikari PLS Rules
|
||||||
|
const aikariPLSRules = await actions.getAikariPLSRules(wsObj);
|
||||||
|
if (aikariPLSRules) {
|
||||||
|
global.ipcRenderer.invoke(
|
||||||
|
`${IPC_METHOD_BASE}.updateAikariRules`,
|
||||||
|
aikariPLSRules
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return updatedAikariStates;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = { onAikariConnectedMsgSeq };
|
||||||
2
src/aura/ui/pls/pushHandler.js → src/aura/ui/aikari/pushHandler.js
Executable file → Normal file
2
src/aura/ui/pls/pushHandler.js → src/aura/ui/aikari/pushHandler.js
Executable file → Normal file
@@ -7,7 +7,7 @@ const { configRouteHandler } = require(`${REQUIRE_BASE}/routes/config`);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {PLSPush} parsedWsMsg
|
* @param {AikariPush} parsedWsMsg
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const pushMsgHandler = (parsedWsMsg) => {
|
const pushMsgHandler = (parsedWsMsg) => {
|
||||||
49
src/aura/ui/aikari/routes/basic.js
Normal file
49
src/aura/ui/aikari/routes/basic.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
const IPC_METHOD_BASE = "$aura.aikari";
|
||||||
|
|
||||||
|
// TODO: REFACTOR
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {AikariPush} parsedWsMsg
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
const basicRouteHandler = (parsedWsMsg) => {
|
||||||
|
const target = parsedWsMsg.type.split(".").slice(-1)[0];
|
||||||
|
switch (target) {
|
||||||
|
case "pushPlsInfo":
|
||||||
|
if (global.__HUGO_AURA__.aikariStats) {
|
||||||
|
global.__HUGO_AURA__.aikariStats.status = parsedWsMsg.data.status;
|
||||||
|
global.__HUGO_AURA__.aikariStats.version = parsedWsMsg.data.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
global.ipcRenderer.invoke(
|
||||||
|
`${IPC_METHOD_BASE}.updateAikariStatus`,
|
||||||
|
global.__HUGO_AURA__.aikariStats
|
||||||
|
);
|
||||||
|
|
||||||
|
console.debug(
|
||||||
|
"[HugoAura / UI / Aikari Routes / DEBUG] Updated aikariStats basic info:",
|
||||||
|
global.__HUGO_AURA__.aikariStats
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "plsNotReadyError":
|
||||||
|
if (global.__HUGO_AURA__.aikariStats) {
|
||||||
|
global.__HUGO_AURA__.aikariStats.launched = true;
|
||||||
|
global.__HUGO_AURA__.aikariStats.connected = false;
|
||||||
|
global.__HUGO_AURA__.aikariStats.status = "notReady";
|
||||||
|
}
|
||||||
|
|
||||||
|
global.ipcRenderer.invoke(
|
||||||
|
`${IPC_METHOD_BASE}.updateAikariStatus`,
|
||||||
|
global.__HUGO_AURA__.aikariStats
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = { basicRouteHandler };
|
||||||
8
src/aura/ui/pls/routes/config.js → src/aura/ui/aikari/routes/config.js
Executable file → Normal file
8
src/aura/ui/pls/routes/config.js → src/aura/ui/aikari/routes/config.js
Executable file → Normal file
@@ -1,10 +1,10 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
const IPC_METHOD_BASE = "$aura.pls";
|
const IPC_METHOD_BASE = "$aura.aikari";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {PLSPush} parsedWsMsg
|
* @param {AikariPush} parsedWsMsg
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const configRouteHandler = (parsedWsMsg) => {
|
const configRouteHandler = (parsedWsMsg) => {
|
||||||
@@ -12,13 +12,13 @@ const configRouteHandler = (parsedWsMsg) => {
|
|||||||
switch (target) {
|
switch (target) {
|
||||||
case "pushBasicConfig":
|
case "pushBasicConfig":
|
||||||
global.ipcRenderer.invoke(
|
global.ipcRenderer.invoke(
|
||||||
`${IPC_METHOD_BASE}.updatePlsSettings`,
|
`${IPC_METHOD_BASE}.updateAikariSettings`,
|
||||||
parsedWsMsg.data
|
parsedWsMsg.data
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "pushRuleSettings":
|
case "pushRuleSettings":
|
||||||
global.ipcRenderer.invoke(
|
global.ipcRenderer.invoke(
|
||||||
`${IPC_METHOD_BASE}.updatePlsRules`,
|
`${IPC_METHOD_BASE}.updateAikariRules`,
|
||||||
parsedWsMsg.data
|
parsedWsMsg.data
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
177
src/aura/ui/composables/aikariConfigManager.js
Normal file
177
src/aura/ui/composables/aikariConfigManager.js
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
const __SCOPE = "assistant / rendererCommon";
|
||||||
|
|
||||||
|
const IPC_METHOD_BASE = "$aura.aikari";
|
||||||
|
|
||||||
|
const updateAikariStatusFromLocal = async () => {
|
||||||
|
const aikariStatus = (
|
||||||
|
await global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.getAikariStatus`)
|
||||||
|
).data;
|
||||||
|
global.__HUGO_AURA__.aikariStats = aikariStatus;
|
||||||
|
return aikariStatus;
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateAikariSettingsFromLocal = async () => {
|
||||||
|
const aikariSettings = (
|
||||||
|
await global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.getAikariSettings`)
|
||||||
|
).data;
|
||||||
|
global.__HUGO_AURA__.aikariSettings = aikariSettings;
|
||||||
|
return aikariSettings;
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateAikariRulesFromLocal = async () => {
|
||||||
|
const aikariRules = (
|
||||||
|
await global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.getAikariRules`)
|
||||||
|
).data;
|
||||||
|
global.__HUGO_AURA__.aikariRules = aikariRules;
|
||||||
|
return aikariRules;
|
||||||
|
};
|
||||||
|
|
||||||
|
const { genRandomHex } = require("../../utils/crypto");
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} configKey
|
||||||
|
* @param {any} configValue
|
||||||
|
*/
|
||||||
|
const updateAikariConfigToRemote = async (
|
||||||
|
configKey,
|
||||||
|
configValue,
|
||||||
|
module = "launcher",
|
||||||
|
writeToDisk = true
|
||||||
|
) => {
|
||||||
|
const configLevels = configKey.split(".");
|
||||||
|
|
||||||
|
const aikariConfigUpdateEvent = new CustomEvent("onAikariConfigUpdate", {
|
||||||
|
detail: {
|
||||||
|
path: configLevels,
|
||||||
|
value: configValue,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
document.dispatchEvent(aikariConfigUpdateEvent);
|
||||||
|
const settingsEntries = document.getElementsByClassName(
|
||||||
|
"aura-settings-entry"
|
||||||
|
);
|
||||||
|
if (settingsEntries.length > 0) {
|
||||||
|
Array.from(settingsEntries).forEach((entry) => {
|
||||||
|
entry.dispatchEvent(aikariConfigUpdateEvent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {ClientAikariRequest}
|
||||||
|
*/
|
||||||
|
const data = {
|
||||||
|
method: "config.actions.updateConfig",
|
||||||
|
data: {
|
||||||
|
key: configKey,
|
||||||
|
value: configValue,
|
||||||
|
write: writeToDisk,
|
||||||
|
},
|
||||||
|
eventId: genRandomHex(), // 不用 crypto, 因为会带来不必要的性能开销
|
||||||
|
module: module,
|
||||||
|
};
|
||||||
|
|
||||||
|
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.ws.sendWsMessage`, data);
|
||||||
|
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.syncAikariConfig`, {
|
||||||
|
basic: global.__HUGO_AURA__.aikariSettings,
|
||||||
|
rules: global.__HUGO_AURA__.aikariRules,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {boolean} newValue
|
||||||
|
*/
|
||||||
|
const updateAikariTelemetryConfigToRemote = async (newValue) => {
|
||||||
|
const aikariConfigUpdateEvent = new CustomEvent("onAikariConfigUpdate", {
|
||||||
|
detail: {
|
||||||
|
path: ["telemetry"],
|
||||||
|
value: newValue,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
document.dispatchEvent(aikariConfigUpdateEvent);
|
||||||
|
const settingsEntries = document.getElementsByClassName(
|
||||||
|
"aura-settings-entry"
|
||||||
|
);
|
||||||
|
if (settingsEntries.length > 0) {
|
||||||
|
Array.from(settingsEntries).forEach((entry) => {
|
||||||
|
entry.dispatchEvent(aikariConfigUpdateEvent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {ClientAikariRequest}
|
||||||
|
*/
|
||||||
|
const data = {
|
||||||
|
method: "config.actions.setTelemetryIsEnabled",
|
||||||
|
data: {
|
||||||
|
isEnabled: newValue,
|
||||||
|
},
|
||||||
|
eventId: genRandomHex(),
|
||||||
|
module: "launcher",
|
||||||
|
};
|
||||||
|
|
||||||
|
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.ws.sendWsMessage`, data);
|
||||||
|
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.syncAikariConfig`, {
|
||||||
|
basic: global.__HUGO_AURA__.aikariSettings,
|
||||||
|
rules: global.__HUGO_AURA__.aikariRules,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// [!] Will be deprecated
|
||||||
|
const updateAikariPLSRulesToRemote = async (
|
||||||
|
configKey,
|
||||||
|
configValue,
|
||||||
|
affiliated,
|
||||||
|
writeToDisk = true
|
||||||
|
) => {
|
||||||
|
const configLevels = configKey.split(".");
|
||||||
|
|
||||||
|
const aikariRuleConfigUpdateEvent = new CustomEvent("onAikariConfigUpdate", {
|
||||||
|
detail: {
|
||||||
|
path: configLevels,
|
||||||
|
value: configValue,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
document.dispatchEvent(aikariRuleConfigUpdateEvent);
|
||||||
|
const settingsEntries = document.getElementsByClassName(
|
||||||
|
"aura-settings-entry"
|
||||||
|
);
|
||||||
|
if (settingsEntries.length > 0) {
|
||||||
|
Array.from(settingsEntries).forEach((entry) => {
|
||||||
|
entry.dispatchEvent(aikariRuleConfigUpdateEvent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {ClientAikariRequest}
|
||||||
|
*/
|
||||||
|
const data = {
|
||||||
|
method: "config.rules.updateConfig",
|
||||||
|
data: {
|
||||||
|
key: configKey,
|
||||||
|
value: configValue,
|
||||||
|
write: writeToDisk,
|
||||||
|
affiliated,
|
||||||
|
},
|
||||||
|
eventId: genRandomHex(),
|
||||||
|
module: "pls",
|
||||||
|
};
|
||||||
|
|
||||||
|
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.ws.sendWsMessage`, data);
|
||||||
|
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.syncAikariConfig`, {
|
||||||
|
basic: global.__HUGO_AURA__.aikariSettings,
|
||||||
|
rules: global.__HUGO_AURA__.aikariRules,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
updateAikariRulesFromLocal,
|
||||||
|
updateAikariStatusFromLocal,
|
||||||
|
updateAikariSettingsFromLocal,
|
||||||
|
updateAikariTelemetryConfigToRemote,
|
||||||
|
updateAikariConfigToRemote,
|
||||||
|
updateAikariPLSRulesToRemote,
|
||||||
|
};
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
// @ts-check
|
|
||||||
|
|
||||||
const __SCOPE = "assistant / rendererCommon";
|
|
||||||
|
|
||||||
const IPC_METHOD_BASE = "$aura.pls";
|
|
||||||
|
|
||||||
const updatePlsStatusFromLocal = async () => {
|
|
||||||
const plsStatus = (
|
|
||||||
await global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.getPlsStats`)
|
|
||||||
).data;
|
|
||||||
global.__HUGO_AURA__.plsStats = plsStatus;
|
|
||||||
return plsStatus;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updatePlsSettingsFromLocal = async () => {
|
|
||||||
const plsSettings = (
|
|
||||||
await global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.getPlsSettings`)
|
|
||||||
).data;
|
|
||||||
global.__HUGO_AURA__.plsSettings = plsSettings;
|
|
||||||
return plsSettings;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updatePlsRulesFromLocal = async () => {
|
|
||||||
const plsRules = (
|
|
||||||
await global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.getPlsRules`)
|
|
||||||
).data;
|
|
||||||
global.__HUGO_AURA__.plsRules = plsRules;
|
|
||||||
return plsRules;
|
|
||||||
};
|
|
||||||
|
|
||||||
const { genRandomHex } = require("../../utils/crypto");
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {string} configKey
|
|
||||||
* @param {any} configValue
|
|
||||||
*/
|
|
||||||
const updatePlsConfigToRemote = async (configKey, configValue) => {
|
|
||||||
const configLevels = configKey.split(".");
|
|
||||||
|
|
||||||
const plsConfigUpdateEvent = new CustomEvent("onPLSConfigUpdate", {
|
|
||||||
detail: {
|
|
||||||
path: configLevels,
|
|
||||||
value: configValue,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
document.dispatchEvent(plsConfigUpdateEvent);
|
|
||||||
const settingsEntries = document.getElementsByClassName(
|
|
||||||
"aura-settings-entry"
|
|
||||||
);
|
|
||||||
if (settingsEntries.length > 0) {
|
|
||||||
Array.from(settingsEntries).forEach((entry) => {
|
|
||||||
entry.dispatchEvent(plsConfigUpdateEvent);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {ClientPLSRequest}
|
|
||||||
*/
|
|
||||||
const data = {
|
|
||||||
method: "config.action.updateConfig",
|
|
||||||
data: {
|
|
||||||
key: configKey,
|
|
||||||
value: configValue,
|
|
||||||
},
|
|
||||||
eventId: genRandomHex(), // 不用 crypto, 因为会带来不必要的性能开销
|
|
||||||
};
|
|
||||||
|
|
||||||
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.ws.sendWsMessage`, data);
|
|
||||||
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.syncPlsConfig`, {
|
|
||||||
basic: global.__HUGO_AURA__.plsSettings,
|
|
||||||
rules: global.__HUGO_AURA__.plsRules,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
updatePlsRulesFromLocal,
|
|
||||||
updatePlsStatusFromLocal,
|
|
||||||
updatePlsSettingsFromLocal,
|
|
||||||
updatePlsConfigToRemote,
|
|
||||||
};
|
|
||||||
34
src/aura/ui/composables/rawCmdExec/app.js
Normal file
34
src/aura/ui/composables/rawCmdExec/app.js
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
const childProc = require("child_process");
|
||||||
|
|
||||||
|
const appRawCmds = {
|
||||||
|
checkVcRedistInst: async () => {
|
||||||
|
let deviceArch = process.env.PROCESSOR_ARCHITEW6432
|
||||||
|
? process.env.PROCESSOR_ARCHITEW6432
|
||||||
|
: process.env.PROCESSOR_ARCHITECTURE;
|
||||||
|
// @ts-expect-error
|
||||||
|
deviceArch = deviceArch.toLowerCase();
|
||||||
|
if (deviceArch === "amd64") {
|
||||||
|
deviceArch = "x64";
|
||||||
|
} else if (deviceArch === "arm64") {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
const waitForCmd = new Promise((resolve) => {
|
||||||
|
childProc.exec(
|
||||||
|
`reg query "HKLM\\SOFTWARE\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\${deviceArch}" /v Installed`,
|
||||||
|
(error, stdout, stderr) => {
|
||||||
|
if (error) {
|
||||||
|
console.warn(
|
||||||
|
`[HugoAura / UI / Composables / Raw CMD / APP] Detected VS Redist not installed: ${stderr}`
|
||||||
|
);
|
||||||
|
resolve({ installed: false, arch: deviceArch });
|
||||||
|
} else {
|
||||||
|
resolve({ installed: true, arch: deviceArch });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
return waitForCmd;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = appRawCmds;
|
||||||
28
src/aura/ui/composables/rawCmdExec/fs.js
Normal file
28
src/aura/ui/composables/rawCmdExec/fs.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
const childProc = require("child_process");
|
||||||
|
|
||||||
|
const fileSystemRawCmds = {
|
||||||
|
getDiskCaptions: async () => {
|
||||||
|
const waitForCmd = new Promise((resolve) => {
|
||||||
|
childProc.exec("fsutil fsinfo drives", (error, stdout, stderr) => {
|
||||||
|
if (error) {
|
||||||
|
console.error(
|
||||||
|
`[HugoAura / UI / Composables / Raw CMD / FS] Failed to exec fsutil getCaption: ${error}`
|
||||||
|
);
|
||||||
|
resolve([]);
|
||||||
|
}
|
||||||
|
const finResult = [];
|
||||||
|
stdout
|
||||||
|
.trim()
|
||||||
|
.split(": ")[1]
|
||||||
|
.split(":\\")
|
||||||
|
.forEach((line) => {
|
||||||
|
if (line !== "") finResult.push(line.trim() + ":");
|
||||||
|
});
|
||||||
|
resolve(finResult);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return waitForCmd;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = fileSystemRawCmds;
|
||||||
@@ -18,12 +18,12 @@ const showRelaunchToast = () => {
|
|||||||
if (!toastBs.isShown()) toastBs.show();
|
if (!toastBs.isShown()) toastBs.show();
|
||||||
};
|
};
|
||||||
|
|
||||||
const showRelaunchPLSToast = () => {
|
const showRelaunchAikariToast = () => {
|
||||||
const toast = document.getElementById("relaunchPlsNotifyToast");
|
const toast = document.getElementById("relaunchAikariNotifyToast");
|
||||||
const toastBs = bootstrap.Toast.getOrCreateInstance(toast);
|
const toastBs = bootstrap.Toast.getOrCreateInstance(toast);
|
||||||
|
|
||||||
if (global.__HUGO_AURA__.plsStats.detached) {
|
if (global.__HUGO_AURA__.aikariStats.detached) {
|
||||||
const relaunchBtn = document.getElementById("plsRelaunchBtn");
|
const relaunchBtn = document.getElementById("aikariRelaunchBtn");
|
||||||
relaunchBtn.disabled = true;
|
relaunchBtn.disabled = true;
|
||||||
relaunchBtn.textContent = "分离模式下无法执行";
|
relaunchBtn.textContent = "分离模式下无法执行";
|
||||||
}
|
}
|
||||||
@@ -37,12 +37,6 @@ const showToast = (entry) => {
|
|||||||
} else if (entry.restart) {
|
} else if (entry.restart) {
|
||||||
showRelaunchToast();
|
showRelaunchToast();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
else if (entry.restartPLS) {
|
|
||||||
showRelaunchPLSToast();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const setDisableStatus = (el, isDisable, hint = null) => {
|
const setDisableStatus = (el, isDisable, hint = null) => {
|
||||||
@@ -56,9 +50,9 @@ const setDisableStatus = (el, isDisable, hint = null) => {
|
|||||||
tooltipIns.enable();
|
tooltipIns.enable();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
el.setAttribute("data-bs-toggle", "tooltip");
|
el.removeAttribute("data-bs-toggle");
|
||||||
el.setAttribute("data-bs-placement", "top");
|
el.removeAttribute("data-bs-placement");
|
||||||
el.setAttribute("data-bs-title", "None");
|
el.removeAttribute("data-bs-title");
|
||||||
el.classList.remove("ase-operation-area-disabled");
|
el.classList.remove("ase-operation-area-disabled");
|
||||||
const tooltipIns = bootstrap.Tooltip.getInstance(el);
|
const tooltipIns = bootstrap.Tooltip.getInstance(el);
|
||||||
if (tooltipIns) {
|
if (tooltipIns) {
|
||||||
@@ -106,7 +100,18 @@ const renderInputArea = (entry, operationArea, descriptionArea) => {
|
|||||||
case "radio": {
|
case "radio": {
|
||||||
const elValue = entry.valueGetter();
|
const elValue = entry.valueGetter();
|
||||||
const elArr = [];
|
const elArr = [];
|
||||||
for (const template of entry.templates) {
|
let targetTemplatesArr = [];
|
||||||
|
let targetTemplateLablesArr = [];
|
||||||
|
targetTemplatesArr =
|
||||||
|
typeof entry.templates === "function"
|
||||||
|
? entry.templates()
|
||||||
|
: entry.templates;
|
||||||
|
targetTemplateLablesArr =
|
||||||
|
typeof entry.templateLabels === "function"
|
||||||
|
? entry.templateLabels()
|
||||||
|
: entry.templateLabels;
|
||||||
|
|
||||||
|
for (const template of targetTemplatesArr) {
|
||||||
const inlineContainerEl = document.createElement("div");
|
const inlineContainerEl = document.createElement("div");
|
||||||
inlineContainerEl.classList.add("form-check", "form-check-inline");
|
inlineContainerEl.classList.add("form-check", "form-check-inline");
|
||||||
const radioEl = document.createElement("input");
|
const radioEl = document.createElement("input");
|
||||||
@@ -114,7 +119,7 @@ const renderInputArea = (entry, operationArea, descriptionArea) => {
|
|||||||
radioEl.classList.add("form-check-input");
|
radioEl.classList.add("form-check-input");
|
||||||
radioEl.type = "radio";
|
radioEl.type = "radio";
|
||||||
radioEl.name = `${entry.id}Radios`;
|
radioEl.name = `${entry.id}Radios`;
|
||||||
radioEl.id = `${entry.id}Radio${entry.templates.indexOf(template)}`;
|
radioEl.id = `${entry.id}Radio${targetTemplatesArr.indexOf(template)}`;
|
||||||
radioEl.checked = template === elValue ? true : false;
|
radioEl.checked = template === elValue ? true : false;
|
||||||
radioEl.addEventListener("change", async (event) => {
|
radioEl.addEventListener("change", async (event) => {
|
||||||
if (event.target.checked) {
|
if (event.target.checked) {
|
||||||
@@ -132,7 +137,53 @@ const renderInputArea = (entry, operationArea, descriptionArea) => {
|
|||||||
labelEl.classList.add("form-check-label");
|
labelEl.classList.add("form-check-label");
|
||||||
labelEl.setAttribute("for", radioEl.id);
|
labelEl.setAttribute("for", radioEl.id);
|
||||||
labelEl.textContent =
|
labelEl.textContent =
|
||||||
entry.templateLabels[entry.templates.indexOf(template)];
|
targetTemplateLablesArr[targetTemplatesArr.indexOf(template)];
|
||||||
|
inlineContainerEl.appendChild(labelEl);
|
||||||
|
elArr.push(inlineContainerEl);
|
||||||
|
}
|
||||||
|
return elArr;
|
||||||
|
}
|
||||||
|
case "checkbox": {
|
||||||
|
const elValue = entry.valueGetter();
|
||||||
|
const elArr = [];
|
||||||
|
let targetTemplatesArr = [];
|
||||||
|
let targetTemplateLablesArr = [];
|
||||||
|
targetTemplatesArr =
|
||||||
|
typeof entry.templates === "function"
|
||||||
|
? entry.templates()
|
||||||
|
: entry.templates;
|
||||||
|
targetTemplateLablesArr =
|
||||||
|
typeof entry.templateLabels === "function"
|
||||||
|
? entry.templateLabels()
|
||||||
|
: entry.templateLabels;
|
||||||
|
|
||||||
|
for (const templateName of targetTemplatesArr) {
|
||||||
|
const inlineContainerEl = document.createElement("div");
|
||||||
|
inlineContainerEl.classList.add("form-check", "form-check-inline");
|
||||||
|
const chkBoxEl = document.createElement("input");
|
||||||
|
chkBoxEl.value = templateName;
|
||||||
|
chkBoxEl.classList.add("form-check-input");
|
||||||
|
chkBoxEl.type = "checkbox";
|
||||||
|
chkBoxEl.name = `${entry.id}Checkbox`;
|
||||||
|
chkBoxEl.id = `${entry.id}Checkbox${targetTemplatesArr.indexOf(
|
||||||
|
templateName
|
||||||
|
)}`;
|
||||||
|
chkBoxEl.checked = elValue.includes(templateName) ? true : false;
|
||||||
|
chkBoxEl.addEventListener("change", async (event) => {
|
||||||
|
showToast(entry);
|
||||||
|
await entry.callbackFn(
|
||||||
|
event.target.value,
|
||||||
|
chkBoxEl,
|
||||||
|
operationArea,
|
||||||
|
descriptionArea
|
||||||
|
);
|
||||||
|
});
|
||||||
|
inlineContainerEl.appendChild(chkBoxEl);
|
||||||
|
const labelEl = document.createElement("label");
|
||||||
|
labelEl.classList.add("form-check-label");
|
||||||
|
labelEl.setAttribute("for", chkBoxEl.id);
|
||||||
|
labelEl.textContent =
|
||||||
|
targetTemplateLablesArr[targetTemplatesArr.indexOf(templateName)];
|
||||||
inlineContainerEl.appendChild(labelEl);
|
inlineContainerEl.appendChild(labelEl);
|
||||||
elArr.push(inlineContainerEl);
|
elArr.push(inlineContainerEl);
|
||||||
}
|
}
|
||||||
@@ -145,9 +196,10 @@ const renderInputArea = (entry, operationArea, descriptionArea) => {
|
|||||||
inputEl.value = entry.valueGetter();
|
inputEl.value = entry.valueGetter();
|
||||||
inputEl.placeholder = entry.placeHolder;
|
inputEl.placeholder = entry.placeHolder;
|
||||||
inputEl.id = entry.id;
|
inputEl.id = entry.id;
|
||||||
inputEl.addEventListener("change", async (event) => {
|
|
||||||
|
const handleSubmit = async (event = null) => {
|
||||||
const result = await entry.callbackFn(
|
const result = await entry.callbackFn(
|
||||||
event.target.value,
|
event ? event.target.value : inputEl.value,
|
||||||
inputEl,
|
inputEl,
|
||||||
operationArea,
|
operationArea,
|
||||||
descriptionArea
|
descriptionArea
|
||||||
@@ -166,10 +218,37 @@ const renderInputArea = (entry, operationArea, descriptionArea) => {
|
|||||||
descriptionArea.textContent = result.hint;
|
descriptionArea.textContent = result.hint;
|
||||||
descriptionArea.classList.add("ase-desc-error-hint");
|
descriptionArea.classList.add("ase-desc-error-hint");
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inputEl.addEventListener("change", async (event) => {
|
||||||
|
await handleSubmit(event);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
inputEl.onsubmit = async (evt) => {
|
||||||
|
evt.preventDefault();
|
||||||
|
await handleSubmit();
|
||||||
|
};
|
||||||
|
|
||||||
operationArea.classList.add("ase-operation-area-expanded");
|
operationArea.classList.add("ase-operation-area-expanded");
|
||||||
return inputEl;
|
return inputEl;
|
||||||
}
|
}
|
||||||
|
case "button": {
|
||||||
|
const btnEl = document.createElement("button");
|
||||||
|
btnEl.type = "button";
|
||||||
|
btnEl.classList.add("btn");
|
||||||
|
switch (entry.style) {
|
||||||
|
case "outline":
|
||||||
|
default:
|
||||||
|
btnEl.classList.add("btn-outline-primary");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
btnEl.innerHTML = entry.buttonContent;
|
||||||
|
btnEl.onclick = entry.callbackFn;
|
||||||
|
(async () => {
|
||||||
|
descriptionArea.innerHTML = await entry.valueGetter();
|
||||||
|
})();
|
||||||
|
return btnEl;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -197,29 +276,29 @@ const renderNormalSettingsItem = (entry, formEl) => {
|
|||||||
powerIcon.setAttribute("data-bs-title", "需要重启 Electron 进程");
|
powerIcon.setAttribute("data-bs-title", "需要重启 Electron 进程");
|
||||||
entryTitle.appendChild(powerIcon);
|
entryTitle.appendChild(powerIcon);
|
||||||
}
|
}
|
||||||
if (entry.PLSRequired) {
|
if (entry.aikariRequired) {
|
||||||
const plsIcon = document.createElement("i");
|
const aikariIcon = document.createElement("i");
|
||||||
plsIcon.classList.add(
|
aikariIcon.classList.add(
|
||||||
"layui-icon",
|
"layui-icon",
|
||||||
"layui-icon-component",
|
"layui-icon-component",
|
||||||
"aura-settings-entry-property-icon"
|
"aura-settings-entry-property-icon"
|
||||||
);
|
);
|
||||||
plsIcon.setAttribute("data-bs-toggle", "tooltip");
|
aikariIcon.setAttribute("data-bs-toggle", "tooltip");
|
||||||
plsIcon.setAttribute("data-bs-placement", "top");
|
aikariIcon.setAttribute("data-bs-placement", "top");
|
||||||
plsIcon.setAttribute("data-bs-title", "需要 PLS 支持");
|
aikariIcon.setAttribute("data-bs-title", "需要 Aikari 支持");
|
||||||
entryTitle.appendChild(plsIcon);
|
entryTitle.appendChild(aikariIcon);
|
||||||
}
|
}
|
||||||
if (entry.restartPLS) {
|
if (entry.restartAikari) {
|
||||||
const plsIcon = document.createElement("i");
|
const aikariIcon = document.createElement("i");
|
||||||
plsIcon.classList.add(
|
aikariIcon.classList.add(
|
||||||
"layui-icon",
|
"layui-icon",
|
||||||
"layui-icon-logout",
|
"layui-icon-logout",
|
||||||
"aura-settings-entry-property-icon"
|
"aura-settings-entry-property-icon"
|
||||||
);
|
);
|
||||||
plsIcon.setAttribute("data-bs-toggle", "tooltip");
|
aikariIcon.setAttribute("data-bs-toggle", "tooltip");
|
||||||
plsIcon.setAttribute("data-bs-placement", "top");
|
aikariIcon.setAttribute("data-bs-placement", "top");
|
||||||
plsIcon.setAttribute("data-bs-title", "需要重启 PLS 进程");
|
aikariIcon.setAttribute("data-bs-title", "需要重启 Aikari 进程");
|
||||||
entryTitle.appendChild(plsIcon);
|
entryTitle.appendChild(aikariIcon);
|
||||||
}
|
}
|
||||||
if (entry.reload) {
|
if (entry.reload) {
|
||||||
const reloadIcon = document.createElement("i");
|
const reloadIcon = document.createElement("i");
|
||||||
@@ -280,33 +359,14 @@ const renderNormalSettingsItem = (entry, formEl) => {
|
|||||||
insertOrRemoveEl(entryOperationArea, targetEl, true);
|
insertOrRemoveEl(entryOperationArea, targetEl, true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const channel = entry.PLSRequired
|
const channel = entry.aikariRequired
|
||||||
? "onPLSConfigUpdate"
|
? "onAikariConfigUpdate"
|
||||||
: "onHugoAuraConfigUpdate";
|
: "onHugoAuraConfigUpdate";
|
||||||
entryContainerEl.addEventListener(channel, evtListener);
|
entryContainerEl.addEventListener(channel, evtListener);
|
||||||
// createOnLeaveEvtListener(channel, evtListener);
|
// createOnLeaveEvtListener(channel, evtListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.PLSRequired) {
|
const updateDisableStatus = (entry) => {
|
||||||
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");
|
|
||||||
|
|
||||||
const updateDisableStatus = () => {
|
|
||||||
const isDisabledRet = entry.auraDisable();
|
const isDisabledRet = entry.auraDisable();
|
||||||
setDisableStatus(
|
setDisableStatus(
|
||||||
entryOperationArea,
|
entryOperationArea,
|
||||||
@@ -316,9 +376,34 @@ const renderNormalSettingsItem = (entry, formEl) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (entry.auraDisable) {
|
if (entry.auraDisable) {
|
||||||
updateDisableStatus();
|
updateDisableStatus(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (entry.aikariRequired) {
|
||||||
|
if (!global.__HUGO_AURA__.aikariStats.connected && !entry.alwaysEnable) {
|
||||||
|
setDisableStatus(entryOperationArea, true, "连接至 Aikari 以继续");
|
||||||
|
}
|
||||||
|
|
||||||
|
const evtListener = (event) => {
|
||||||
|
if (event.detail.connected) {
|
||||||
|
try {
|
||||||
|
updateDisableStatus(entry);
|
||||||
|
} catch {
|
||||||
|
setDisableStatus(entryOperationArea, false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!entry.alwaysEnable) {
|
||||||
|
setDisableStatus(entryOperationArea, true, "连接至 Aikari 以继续");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
entryContainerEl.addEventListener("onAikariStatsUpdate", evtListener);
|
||||||
|
// createOnLeaveEvtListener("onAikariStatsUpdate", evtListener);
|
||||||
|
}
|
||||||
|
entryContainerEl.appendChild(entryOperationArea);
|
||||||
|
const isShow = entry.auraIf();
|
||||||
|
if (!isShow) entryContainerEl.classList.add("aura-settings-entry-hidden");
|
||||||
|
|
||||||
if (entry.associateVal) {
|
if (entry.associateVal) {
|
||||||
const evtListener = (event) => {
|
const evtListener = (event) => {
|
||||||
if (!entry.associateVal.includes(event.detail.path.join("."))) return;
|
if (!entry.associateVal.includes(event.detail.path.join("."))) return;
|
||||||
@@ -328,12 +413,12 @@ const renderNormalSettingsItem = (entry, formEl) => {
|
|||||||
? cls.remove("aura-settings-entry-hidden")
|
? cls.remove("aura-settings-entry-hidden")
|
||||||
: cls.add("aura-settings-entry-hidden");
|
: cls.add("aura-settings-entry-hidden");
|
||||||
|
|
||||||
if (entry.auraDisable) {
|
if (entry.auraDisable && !entry.alwaysEnable) {
|
||||||
updateDisableStatus();
|
updateDisableStatus(entry);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const channel = entry.PLSRequired
|
const channel = entry.aikariRequired
|
||||||
? "onPLSConfigUpdate"
|
? "onAikariConfigUpdate"
|
||||||
: "onHugoAuraConfigUpdate";
|
: "onHugoAuraConfigUpdate";
|
||||||
entryContainerEl.addEventListener(channel, evtListener);
|
entryContainerEl.addEventListener(channel, evtListener);
|
||||||
// createOnLeaveEvtListener(channel, evtListener);
|
// createOnLeaveEvtListener(channel, evtListener);
|
||||||
@@ -375,7 +460,9 @@ const renderPreviewItem = (entry, formEl) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener(
|
document.addEventListener(
|
||||||
eventChannel === "pls" ? "onPLSConfigUpdate" : "onHugoAuraConfigUpdate",
|
eventChannel === "aikari"
|
||||||
|
? "onAikariConfigUpdate"
|
||||||
|
: "onHugoAuraConfigUpdate",
|
||||||
eventListener
|
eventListener
|
||||||
);
|
);
|
||||||
createOnLeaveEvtListener(eventListener); // Clean up
|
createOnLeaveEvtListener(eventListener); // Clean up
|
||||||
|
|||||||
@@ -41,13 +41,13 @@ const def = {
|
|||||||
selectorMode: "appendChild",
|
selectorMode: "appendChild",
|
||||||
pageCSS: "ui/pages/configSubPages/behaviourCtrl/behaviourCtrl.css",
|
pageCSS: "ui/pages/configSubPages/behaviourCtrl/behaviourCtrl.css",
|
||||||
childs: {
|
childs: {
|
||||||
PlsStatus: {
|
AikariStatus: {
|
||||||
active: false,
|
active: false,
|
||||||
pageURI: "ui/pages/configSubPages/behaviourCtrl/plsStatus.html",
|
pageURI: "ui/pages/configSubPages/behaviourCtrl/aikariStatus.html",
|
||||||
pageScript: "ui/pages/configSubPages/behaviourCtrl/plsStatus.js",
|
pageScript: "ui/pages/configSubPages/behaviourCtrl/aikariStatus.js",
|
||||||
pageSelector: "#status-subpage",
|
pageSelector: "#status-subpage",
|
||||||
selectorMode: "appendChild",
|
selectorMode: "appendChild",
|
||||||
pageCSS: "ui/pages/configSubPages/behaviourCtrl/plsStatus.css",
|
pageCSS: "ui/pages/configSubPages/behaviourCtrl/aikariStatus.css",
|
||||||
},
|
},
|
||||||
DeviceSecurity: {
|
DeviceSecurity: {
|
||||||
childs: {
|
childs: {
|
||||||
@@ -86,7 +86,7 @@ const def = {
|
|||||||
],
|
],
|
||||||
globalJS: [
|
globalJS: [
|
||||||
"ui/js/global.js",
|
"ui/js/global.js",
|
||||||
"ui/js/plsListener.js",
|
"ui/js/aikariListener.js",
|
||||||
"ui/bootstrap/bootstrap.bundle.min.js",
|
"ui/bootstrap/bootstrap.bundle.min.js",
|
||||||
],
|
],
|
||||||
onLoaded: `
|
onLoaded: `
|
||||||
|
|||||||
2
src/aura/ui/hookDefinitions/desktopAssistant.js
Executable file → Normal file
2
src/aura/ui/hookDefinitions/desktopAssistant.js
Executable file → Normal file
@@ -6,7 +6,7 @@
|
|||||||
const def = {
|
const def = {
|
||||||
targets: {},
|
targets: {},
|
||||||
globalStyles: ["ui/css/global.css"],
|
globalStyles: ["ui/css/global.css"],
|
||||||
globalJS: ["ui/js/global.js", "ui/js/plsConnectionManager.js"],
|
globalJS: ["ui/js/global.js", "ui/js/pageGlobal/desktopAssistant.js"],
|
||||||
onLoaded: `
|
onLoaded: `
|
||||||
console.log('[HugoAura / UI / Hooks / Desktop Assistant] Page loaded.');
|
console.log('[HugoAura / UI / Hooks / Desktop Assistant] Page loaded.');
|
||||||
`,
|
`,
|
||||||
|
|||||||
402
src/aura/ui/js/aikariConnectionManager.js
Normal file
402
src/aura/ui/js/aikariConnectionManager.js
Normal file
@@ -0,0 +1,402 @@
|
|||||||
|
// @ts-check
|
||||||
|
(() => {
|
||||||
|
if (!global.__HUGO_AURA__)
|
||||||
|
global.__HUGO_AURA__ = {
|
||||||
|
configInit: true,
|
||||||
|
auraDir: "",
|
||||||
|
version: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!global.__HUGO_AURA__.aikariStats)
|
||||||
|
global.__HUGO_AURA__.aikariStats = {
|
||||||
|
installed: false,
|
||||||
|
detached: false,
|
||||||
|
connected: false,
|
||||||
|
launched: false,
|
||||||
|
status: "dead",
|
||||||
|
version: "unknown",
|
||||||
|
authToken: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
const IPC_METHOD_BASE = "$aura.aikari";
|
||||||
|
const REQUIRE_BASE = "../../..";
|
||||||
|
const __SCOPE = "auraWsKeepAlive";
|
||||||
|
|
||||||
|
const AIKARI_RPC_CONFIG_REG_PATH = "Aikari\\RPC";
|
||||||
|
|
||||||
|
const { pushMsgHandler } = require(`${REQUIRE_BASE}/aikari/pushHandler`);
|
||||||
|
const {
|
||||||
|
onAikariConnectedMsgSeq,
|
||||||
|
} = require(`${REQUIRE_BASE}/aikari/onConnectedSeq`);
|
||||||
|
const RegistryManager = require(`${REQUIRE_BASE}/../init/shared/registryManager`);
|
||||||
|
|
||||||
|
const registryManager = new RegistryManager();
|
||||||
|
|
||||||
|
/** @type {number} */
|
||||||
|
let failedCounter = 0;
|
||||||
|
/** @type {boolean} */
|
||||||
|
let isErrorOccurred = false;
|
||||||
|
|
||||||
|
/** @type {number} */
|
||||||
|
let aikariPort = 22077;
|
||||||
|
/** @type {"wss" | "ws"} */
|
||||||
|
let aikariProtocol = "wss";
|
||||||
|
|
||||||
|
/** @type {boolean} */
|
||||||
|
let isRetrying = false;
|
||||||
|
|
||||||
|
/** @type {any} */
|
||||||
|
let curSendListener = null;
|
||||||
|
let curSendGetListener = null;
|
||||||
|
|
||||||
|
const sendRetryStatusToMain = (
|
||||||
|
/** @type {Boolean} */ status,
|
||||||
|
/** @type {string?} */ message = null
|
||||||
|
) => {
|
||||||
|
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.post.updateRetryStatus`, {
|
||||||
|
success: status,
|
||||||
|
message: message,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearReqSendIpcListener = () => {
|
||||||
|
if (curSendListener) {
|
||||||
|
global.ipcRenderer.off(
|
||||||
|
`${IPC_METHOD_BASE}.ws.post.onReqSendMsg`,
|
||||||
|
curSendListener
|
||||||
|
);
|
||||||
|
curSendListener = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearSendGetIpcListener = () => {
|
||||||
|
if (curSendGetListener) {
|
||||||
|
global.ipcRenderer.off(
|
||||||
|
`${IPC_METHOD_BASE}.ws.post.onSendGetMsg`,
|
||||||
|
curSendListener
|
||||||
|
);
|
||||||
|
curSendGetListener = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAuthToken = async () => {
|
||||||
|
const authTokenRet = await registryManager.readRegKey(
|
||||||
|
AIKARI_RPC_CONFIG_REG_PATH,
|
||||||
|
"authToken",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
return authTokenRet;
|
||||||
|
};
|
||||||
|
|
||||||
|
const startConnAikariProc = async (updatedAikariStats) => {
|
||||||
|
let authTokenTries = 0;
|
||||||
|
let GET_AUTH_TOKEN_MAX_TRIES = 3;
|
||||||
|
let getAuthTokenSuccess = false;
|
||||||
|
while (authTokenTries < GET_AUTH_TOKEN_MAX_TRIES) {
|
||||||
|
const authTokenRet = await getAuthToken();
|
||||||
|
if (authTokenRet.success) {
|
||||||
|
updatedAikariStats.authToken = authTokenRet.data;
|
||||||
|
// @ts-expect-error
|
||||||
|
global.__HUGO_AURA__.aikariStats.authToken = authTokenRet.data;
|
||||||
|
getAuthTokenSuccess = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
await window.__HUGO_AURA_GLOBAL__.utils.sleep(1000);
|
||||||
|
authTokenTries += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!getAuthTokenSuccess) {
|
||||||
|
sendRetryStatusToMain(false, "E_AUTH_TOKEN_GET_FAILED");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const portRet = await registryManager.readRegKey(
|
||||||
|
AIKARI_RPC_CONFIG_REG_PATH,
|
||||||
|
"wsPort",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
if (portRet.success) {
|
||||||
|
try {
|
||||||
|
aikariPort = Number(portRet.data);
|
||||||
|
} catch {
|
||||||
|
console.warn(
|
||||||
|
`[HugoAura / UI / Aikari Conn Manager] Invalid Aikari port: ${portRet.data}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: wsHost
|
||||||
|
createAikariConnection(
|
||||||
|
updatedAikariStats.authToken,
|
||||||
|
connectionResultCallback
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} authToken
|
||||||
|
* @param {any} callback
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
const createAikariConnection = (authToken, callback) => {
|
||||||
|
if (failedCounter >= 3) {
|
||||||
|
console.error(
|
||||||
|
`[HugoAura / UI / Aikari Conn Manager / ERROR] Failed connecting to Aikari WebSocket server, please check the status of Aikari process.`
|
||||||
|
);
|
||||||
|
sendRetryStatusToMain(false, "E_WS_CONN_FAILED_AFT_MULTIPLE_TRIES");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {WebSocket} */
|
||||||
|
const aikariWs = new WebSocket(
|
||||||
|
`${aikariProtocol}://aikari.hugoaura.local:${aikariPort}/?auth=${authToken}`
|
||||||
|
);
|
||||||
|
|
||||||
|
aikariWs.onopen = () => {
|
||||||
|
callback(true, aikariWs);
|
||||||
|
};
|
||||||
|
|
||||||
|
aikariWs.onerror = () => {
|
||||||
|
isErrorOccurred = true;
|
||||||
|
failedCounter += 1;
|
||||||
|
callback(false, aikariWs);
|
||||||
|
};
|
||||||
|
|
||||||
|
aikariWs.onclose = () => {
|
||||||
|
clearReqSendIpcListener();
|
||||||
|
if (global.__HUGO_AURA__.aikariStats) {
|
||||||
|
if (global.__HUGO_AURA__.aikariStats.status === "notReady") {
|
||||||
|
if (isRetrying) {
|
||||||
|
sendRetryStatusToMain(false, "E_IS_LOADING");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.warn(
|
||||||
|
"[HugoAura / UI / Aikari Conn Manager / WARN] Aikari not ready, try again after 10s..."
|
||||||
|
);
|
||||||
|
isRetrying = true;
|
||||||
|
setTimeout(async () => {
|
||||||
|
isRetrying = false;
|
||||||
|
startConnAikariProc(global.__HUGO_AURA__.aikariStats);
|
||||||
|
}, 10000);
|
||||||
|
sendRetryStatusToMain(false, "E_START_WAIT_FOR_LOADING");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (global.__HUGO_AURA__.aikariStats.launched === false) {
|
||||||
|
console.warn(
|
||||||
|
"[HugoAura / UI / Aikari Conn Manager / WARN] Aikari stopped, closing WebSocket connection."
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error(
|
||||||
|
"[HugoAura / UI / Aikari Conn Manager / ERROR] WebSocket connection closed."
|
||||||
|
);
|
||||||
|
if (isErrorOccurred) return;
|
||||||
|
failedCounter += 1;
|
||||||
|
callback(false, aikariWs);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {WebSocket} wsObj
|
||||||
|
*/
|
||||||
|
const registerSendReqListener = (wsObj) => {
|
||||||
|
clearReqSendIpcListener();
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("electron").IpcRendererEvent} _evt
|
||||||
|
* @param {any} arg
|
||||||
|
*/
|
||||||
|
curSendListener = (_evt, arg) => {
|
||||||
|
wsObj.send(JSON.stringify(arg));
|
||||||
|
};
|
||||||
|
global.ipcRenderer.on(
|
||||||
|
`${IPC_METHOD_BASE}.ws.post.onReqSendMsg`,
|
||||||
|
curSendListener
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {boolean} result
|
||||||
|
* @param {WebSocket} wsObj
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
const connectionResultCallback = async (result, wsObj) => {
|
||||||
|
if (!global.__HUGO_AURA__.aikariStats) return; // 😅 typescript
|
||||||
|
|
||||||
|
global.__HUGO_AURA__.aikariStats.launched = result;
|
||||||
|
global.__HUGO_AURA__.aikariStats.connected = result;
|
||||||
|
global.ipcRenderer.invoke(
|
||||||
|
`${IPC_METHOD_BASE}.updateAikariStatus`,
|
||||||
|
global.__HUGO_AURA__.aikariStats
|
||||||
|
);
|
||||||
|
if (!result) {
|
||||||
|
console.error(
|
||||||
|
`[HugoAura / UI / Aikari Conn Manager / ERROR] Failed connecting to Aikari WebSocket server, retrying ...`
|
||||||
|
);
|
||||||
|
createAikariConnection(
|
||||||
|
global.__HUGO_AURA__.aikariStats.authToken,
|
||||||
|
connectionResultCallback
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wsObj.onmessage = aikariPushHandler;
|
||||||
|
|
||||||
|
registerSendReqListener(wsObj);
|
||||||
|
|
||||||
|
global.__HUGO_AURA__.aikariWs = wsObj;
|
||||||
|
|
||||||
|
global.__HUGO_AURA__.aikariStats = await onAikariConnectedMsgSeq({
|
||||||
|
curAikariStates: global.__HUGO_AURA__.aikariStats,
|
||||||
|
wsObj,
|
||||||
|
});
|
||||||
|
global.ipcRenderer.invoke(
|
||||||
|
`${IPC_METHOD_BASE}.updateAikariStatus`,
|
||||||
|
global.__HUGO_AURA__.aikariStats
|
||||||
|
);
|
||||||
|
|
||||||
|
sendRetryStatusToMain(true, "SUCCESS");
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {MessageEvent} event
|
||||||
|
*/
|
||||||
|
const aikariPushHandler = (event) => {
|
||||||
|
try {
|
||||||
|
/** @type {Record<any, any>} */
|
||||||
|
const parsedEvent = JSON.parse(event.data);
|
||||||
|
console.debug(
|
||||||
|
"[HugoAura / UI / Aikari Conn Manager / DEBUG] Received new server message: "
|
||||||
|
);
|
||||||
|
if (!parsedEvent.eventId || parsedEvent.eventId === "N/A") {
|
||||||
|
// Push
|
||||||
|
pushMsgHandler(parsedEvent);
|
||||||
|
} else {
|
||||||
|
// Not push
|
||||||
|
global.ipcRenderer.send(
|
||||||
|
`${IPC_METHOD_BASE}.ws.broadcastMessageRecv`,
|
||||||
|
parsedEvent
|
||||||
|
);
|
||||||
|
|
||||||
|
const msgRecvEvent = new CustomEvent("onAikariMessageRecv", {
|
||||||
|
detail: parsedEvent,
|
||||||
|
});
|
||||||
|
document.dispatchEvent(msgRecvEvent);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
console.error(
|
||||||
|
"[HugoAura / UI / Aikari Conn Manager / ERROR] Failed to resolve server message: ",
|
||||||
|
event.data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const initAikariWebSocketConnection = async () => {
|
||||||
|
if (!global.__HUGO_AURA__.aikariStats) return;
|
||||||
|
|
||||||
|
if (isRetrying) {
|
||||||
|
sendRetryStatusToMain(false, "E_RETRY_PENDING");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
failedCounter = 0;
|
||||||
|
isErrorOccurred = false;
|
||||||
|
|
||||||
|
const curAikariStats = await global.ipcRenderer.invoke(
|
||||||
|
`${IPC_METHOD_BASE}.getAikariStatus`
|
||||||
|
);
|
||||||
|
let updatedAikariStats = {};
|
||||||
|
if (
|
||||||
|
(curAikariStats === null || !curAikariStats.success) &&
|
||||||
|
curAikariStats.status !== "downloading" &&
|
||||||
|
curAikariStats.status !== "installing"
|
||||||
|
) {
|
||||||
|
updatedAikariStats = {
|
||||||
|
installed: false,
|
||||||
|
launched: false,
|
||||||
|
detached: false,
|
||||||
|
connected: false,
|
||||||
|
version: "unknown",
|
||||||
|
status: "dead",
|
||||||
|
authToken: "",
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
updatedAikariStats = curAikariStats.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isAikariBinExists = (
|
||||||
|
await global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.getIfAikariBinExists`)
|
||||||
|
).data.isExists;
|
||||||
|
updatedAikariStats.installed = isAikariBinExists;
|
||||||
|
// @ts-expect-error
|
||||||
|
global.__HUGO_AURA__.aikariStats = updatedAikariStats;
|
||||||
|
console.debug(
|
||||||
|
"[HugoAura / UI / Aikari Conn Manager / DEBUG] Updated early aikariStats:",
|
||||||
|
global.__HUGO_AURA__.aikariStats
|
||||||
|
);
|
||||||
|
|
||||||
|
global.ipcRenderer.invoke(
|
||||||
|
`${IPC_METHOD_BASE}.updateAikariStatus`,
|
||||||
|
updatedAikariStats
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (updatedPlsStats.detached && updatedPlsStats.installed) {
|
||||||
|
*/
|
||||||
|
if (updatedAikariStats.installed || updatedAikariStats.detached) {
|
||||||
|
await startConnAikariProc(updatedAikariStats);
|
||||||
|
} else {
|
||||||
|
sendRetryStatusToMain(false, "E_NOT_INSTALLED");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
global.ipcRenderer.on(`${IPC_METHOD_BASE}.post.onPlsLaunched`, (_event) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
startConnPls();
|
||||||
|
}, 5000);
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSetup = () => {
|
||||||
|
if (!global.ipcRenderer) {
|
||||||
|
// @ts-ignore
|
||||||
|
global.ipcRenderer = require("electron").ipcRenderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
initAikariWebSocketConnection();
|
||||||
|
|
||||||
|
global.ipcRenderer.on(
|
||||||
|
`${IPC_METHOD_BASE}.retryAikariConnect`,
|
||||||
|
(_evt, _arg) => {
|
||||||
|
if (!global.__HUGO_AURA__.aikariStats) return;
|
||||||
|
if (global.__HUGO_AURA__.aikariStats.connected) return;
|
||||||
|
initAikariWebSocketConnection();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
global.ipcRenderer.on(
|
||||||
|
`${IPC_METHOD_BASE}.post.onForceReloadRequested`,
|
||||||
|
(_evt, _arg) => {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
global.ipcRenderer.on(
|
||||||
|
`${IPC_METHOD_BASE}.post.aikariStopped`,
|
||||||
|
(_evt, _arg) => {
|
||||||
|
if (!global.__HUGO_AURA__.aikariStats) return;
|
||||||
|
global.__HUGO_AURA__.aikariStats.launched = false;
|
||||||
|
global.__HUGO_AURA__.aikariStats.connected = false;
|
||||||
|
global.__HUGO_AURA__.aikariStats.version = "unknown";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
onSetup();
|
||||||
|
}, 1500);
|
||||||
|
})();
|
||||||
28
src/aura/ui/js/plsListener.js → src/aura/ui/js/aikariListener.js
Executable file → Normal file
28
src/aura/ui/js/plsListener.js → src/aura/ui/js/aikariListener.js
Executable file → Normal file
@@ -1,21 +1,21 @@
|
|||||||
(() => {
|
(() => {
|
||||||
const IPC_METHOD_BASE = "$aura.pls";
|
const IPC_METHOD_BASE = "$aura.aikari";
|
||||||
const REQUIRE_BASE = "../../aura/ui";
|
const REQUIRE_BASE = "../../aura/ui";
|
||||||
const __SCOPE = "assistant";
|
const __SCOPE = "assistant";
|
||||||
const {
|
const {
|
||||||
updatePlsStatusFromLocal,
|
updateAikariStatusFromLocal,
|
||||||
} = require(`${REQUIRE_BASE}/composables/plsConfigManager`);
|
} = require(`${REQUIRE_BASE}/composables/aikariConfigManager`);
|
||||||
|
|
||||||
const setupListeners = () => {
|
const setupListeners = () => {
|
||||||
if (!global.ipcRenderer)
|
if (!global.ipcRenderer)
|
||||||
global.ipcRenderer = require("electron").ipcRenderer;
|
global.ipcRenderer = require("electron").ipcRenderer;
|
||||||
|
|
||||||
ipcRenderer.on(
|
ipcRenderer.on(
|
||||||
`${IPC_METHOD_BASE}.post.onPlsStatsUpdate`,
|
`${IPC_METHOD_BASE}.post.onAikariStatsUpdate`,
|
||||||
(_event, arg) => {
|
(_event, arg) => {
|
||||||
global.__HUGO_AURA__.plsStats = arg;
|
global.__HUGO_AURA__.aikariStats = arg;
|
||||||
|
|
||||||
const event = new CustomEvent("onPLSStatsUpdate", {
|
const event = new CustomEvent("onAikariStatsUpdate", {
|
||||||
detail: {
|
detail: {
|
||||||
connected: arg.connected,
|
connected: arg.connected,
|
||||||
},
|
},
|
||||||
@@ -35,11 +35,11 @@
|
|||||||
);
|
);
|
||||||
|
|
||||||
ipcRenderer.on(
|
ipcRenderer.on(
|
||||||
`${IPC_METHOD_BASE}.post.onPlsSettingsUpdate`,
|
`${IPC_METHOD_BASE}.post.onAikariSettingsUpdate`,
|
||||||
(_event, arg) => {
|
(_event, arg) => {
|
||||||
global.__HUGO_AURA__.plsSettings = arg;
|
global.__HUGO_AURA__.aikariSettings = arg;
|
||||||
|
|
||||||
const event = new CustomEvent("onPLSConfigUpdate", {
|
const event = new CustomEvent("onAikariConfigUpdate", {
|
||||||
detail: {
|
detail: {
|
||||||
path: ["root", "settings"],
|
path: ["root", "settings"],
|
||||||
value: arg,
|
value: arg,
|
||||||
@@ -60,11 +60,11 @@
|
|||||||
);
|
);
|
||||||
|
|
||||||
ipcRenderer.on(
|
ipcRenderer.on(
|
||||||
`${IPC_METHOD_BASE}.post.onPlsRulesUpdate`,
|
`${IPC_METHOD_BASE}.post.onAikariRulesUpdate`,
|
||||||
(_event, arg) => {
|
(_event, arg) => {
|
||||||
global.__HUGO_AURA__.plsRules = arg;
|
global.__HUGO_AURA__.aikariRules = arg;
|
||||||
|
|
||||||
const event = new CustomEvent("onPLSConfigUpdate", {
|
const event = new CustomEvent("onAikariConfigUpdate", {
|
||||||
detail: {
|
detail: {
|
||||||
path: ["root", "ruleSettings"],
|
path: ["root", "ruleSettings"],
|
||||||
value: arg,
|
value: arg,
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
ipcRenderer.on(
|
ipcRenderer.on(
|
||||||
`${IPC_METHOD_BASE}.post.updateRetryStatus`,
|
`${IPC_METHOD_BASE}.post.updateRetryStatus`,
|
||||||
(_event, arg) => {
|
(_event, arg) => {
|
||||||
const event = new CustomEvent("onPLSStatsUpdate", {
|
const event = new CustomEvent("onAikariStatsUpdate", {
|
||||||
detail: {
|
detail: {
|
||||||
connected: arg.success,
|
connected: arg.success,
|
||||||
},
|
},
|
||||||
@@ -107,6 +107,6 @@
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
updatePlsStatusFromLocal();
|
updateAikariStatusFromLocal();
|
||||||
setupListeners();
|
setupListeners();
|
||||||
})();
|
})();
|
||||||
@@ -6,9 +6,11 @@
|
|||||||
let tooltipTriggerCache = null;
|
let tooltipTriggerCache = null;
|
||||||
const refreshBsTooltip = (selector = '[data-bs-toggle="tooltip"]') => {
|
const refreshBsTooltip = (selector = '[data-bs-toggle="tooltip"]') => {
|
||||||
if (tooltipTriggerCache) {
|
if (tooltipTriggerCache) {
|
||||||
[...tooltipTriggerCache].map((el) =>
|
[...tooltipTriggerCache].map((el) => {
|
||||||
bootstrap.Tooltip.getInstance(el).disable()
|
if (bootstrap.Tooltip.getInstance(el)) {
|
||||||
);
|
bootstrap.Tooltip.getInstance(el).disable();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const tooltipTriggerList = document.querySelectorAll(selector);
|
const tooltipTriggerList = document.querySelectorAll(selector);
|
||||||
|
|||||||
23
src/aura/ui/js/pageGlobal/desktopAssistant.js
Normal file
23
src/aura/ui/js/pageGlobal/desktopAssistant.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
(() => {
|
||||||
|
const applyHideSettings = () => {
|
||||||
|
if (global.__HUGO_AURA_CONFIG__.ssa.ux.easiAssistant.autoHide) {
|
||||||
|
const minimizeBtnEl = document.getElementsByClassName(
|
||||||
|
"index__button2__2mhwC3oY"
|
||||||
|
)[0].children[0];
|
||||||
|
// @ts-expect-error
|
||||||
|
minimizeBtnEl.click();
|
||||||
|
} else if (global.__HUGO_AURA_CONFIG__.ssa.ux.easiAssistant.notDisplay) {
|
||||||
|
const rootEl = document.getElementById("root");
|
||||||
|
// @ts-expect-error
|
||||||
|
rootEl.style["display"] = "none";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onMounted = () => {
|
||||||
|
applyHideSettings();
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted();
|
||||||
|
})();
|
||||||
@@ -1,334 +0,0 @@
|
|||||||
// @ts-check
|
|
||||||
(() => {
|
|
||||||
if (!global.__HUGO_AURA__.plsStats)
|
|
||||||
global.__HUGO_AURA__.plsStats = {
|
|
||||||
installed: false,
|
|
||||||
detached: false,
|
|
||||||
connected: false,
|
|
||||||
launched: false,
|
|
||||||
status: "dead",
|
|
||||||
version: "未知",
|
|
||||||
authToken: "",
|
|
||||||
};
|
|
||||||
|
|
||||||
const IPC_METHOD_BASE = "$aura.pls";
|
|
||||||
const REQUIRE_BASE = "../../aura/ui";
|
|
||||||
const __SCOPE = "desktopAssistant";
|
|
||||||
|
|
||||||
const PLS_REG_PATH = "ProxyLayerServices";
|
|
||||||
|
|
||||||
const { pushMsgHandler } = require(`${REQUIRE_BASE}/pls/pushHandler`);
|
|
||||||
const RegistryManager = require(`${REQUIRE_BASE}/../init/shared/registryManager`);
|
|
||||||
|
|
||||||
const registryManager = new RegistryManager();
|
|
||||||
|
|
||||||
/** @type {number} */
|
|
||||||
let failedCounter = 0;
|
|
||||||
/** @type {boolean} */
|
|
||||||
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) => {
|
|
||||||
global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.post.updateRetryStatus`, {
|
|
||||||
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 {any} callback
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
const createPlsConnection = (authToken, callback) => {
|
|
||||||
if (failedCounter >= 3) {
|
|
||||||
console.error(
|
|
||||||
`[HugoAura / UI / PLS Manager / ERROR] Failed connecting to PLS WebSocket server, please check the status of PLS process.`
|
|
||||||
);
|
|
||||||
sendRetryStatusToMain(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fullAuthToken = calcFullAuthToken(authToken);
|
|
||||||
|
|
||||||
/** @type {WebSocket} */
|
|
||||||
const plsWs = new WebSocket(
|
|
||||||
`${plsProtocol}://pls.hugoaura.local:${plsPort}/?auth=${fullAuthToken}`
|
|
||||||
);
|
|
||||||
|
|
||||||
plsWs.onopen = () => {
|
|
||||||
callback(true, plsWs);
|
|
||||||
};
|
|
||||||
|
|
||||||
plsWs.onerror = () => {
|
|
||||||
isErrorOccurred = true;
|
|
||||||
failedCounter += 1;
|
|
||||||
callback(false, plsWs);
|
|
||||||
};
|
|
||||||
|
|
||||||
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(
|
|
||||||
"[HugoAura / UI / PLS Manager / ERROR] WebSocket connection closed."
|
|
||||||
);
|
|
||||||
if (isErrorOccurred) return;
|
|
||||||
failedCounter += 1;
|
|
||||||
callback(false, plsWs);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {WebSocket} wsObj
|
|
||||||
*/
|
|
||||||
const registerSendReqListener = (wsObj) => {
|
|
||||||
clearIpcListener();
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {import("electron").IpcRendererEvent} _evt
|
|
||||||
* @param {any} arg
|
|
||||||
*/
|
|
||||||
curSendListener = (_evt, arg) => {
|
|
||||||
wsObj.send(JSON.stringify(arg));
|
|
||||||
};
|
|
||||||
global.ipcRenderer.on(
|
|
||||||
`${IPC_METHOD_BASE}.ws.post.onReqSendMsg`,
|
|
||||||
curSendListener
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {boolean} result
|
|
||||||
* @param {WebSocket} wsObj
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
const connectionResultCallback = (result, wsObj) => {
|
|
||||||
if (!global.__HUGO_AURA__.plsStats) return; // 😅 typescript
|
|
||||||
|
|
||||||
global.__HUGO_AURA__.plsStats.launched = result;
|
|
||||||
global.__HUGO_AURA__.plsStats.connected = result;
|
|
||||||
global.ipcRenderer.invoke(
|
|
||||||
`${IPC_METHOD_BASE}.updatePlsStats`,
|
|
||||||
global.__HUGO_AURA__.plsStats
|
|
||||||
);
|
|
||||||
if (!result) {
|
|
||||||
console.error(
|
|
||||||
`[HugoAura / UI / PLS Manager / ERROR] Failed connecting to PLS WebSocket server, retrying ...`
|
|
||||||
);
|
|
||||||
createPlsConnection(
|
|
||||||
global.__HUGO_AURA__.plsStats.authToken,
|
|
||||||
connectionResultCallback
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendRetryStatusToMain(true);
|
|
||||||
|
|
||||||
global.__HUGO_AURA__.plsWs = wsObj;
|
|
||||||
registerSendReqListener(wsObj);
|
|
||||||
wsObj.onmessage = plsPushHandler;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {MessageEvent} event
|
|
||||||
*/
|
|
||||||
const plsPushHandler = (event) => {
|
|
||||||
try {
|
|
||||||
/** @type {Record<any, any>} */
|
|
||||||
const parsedEvent = JSON.parse(event.data);
|
|
||||||
console.debug(
|
|
||||||
"[HugoAura / UI / PLS Manager / DEBUG] Received new server message: "
|
|
||||||
);
|
|
||||||
if (!parsedEvent.eventId) {
|
|
||||||
// Push
|
|
||||||
pushMsgHandler(parsedEvent);
|
|
||||||
} else {
|
|
||||||
// Not push
|
|
||||||
global.ipcRenderer.send(
|
|
||||||
`${IPC_METHOD_BASE}.ws.broadcastMessageRecv`,
|
|
||||||
parsedEvent
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
console.error(
|
|
||||||
"[HugoAura / UI / PLS Manager / ERROR] Failed to resolve server message: ",
|
|
||||||
event.data
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const initPlsConnection = async () => {
|
|
||||||
if (!global.__HUGO_AURA__.plsStats) return;
|
|
||||||
|
|
||||||
if (isRetrying) {
|
|
||||||
sendRetryStatusToMain(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
failedCounter = 0;
|
|
||||||
isErrorOccurred = false;
|
|
||||||
|
|
||||||
const curPlsStats = await global.ipcRenderer.invoke(
|
|
||||||
`${IPC_METHOD_BASE}.getPlsStats`
|
|
||||||
);
|
|
||||||
let updatedPlsStats = {};
|
|
||||||
if (
|
|
||||||
(curPlsStats === null || !curPlsStats.success) &&
|
|
||||||
curPlsStats.status !== "downloading"
|
|
||||||
) {
|
|
||||||
updatedPlsStats = {
|
|
||||||
installed: false,
|
|
||||||
launched: false,
|
|
||||||
detached: false,
|
|
||||||
connected: false,
|
|
||||||
version: "未知",
|
|
||||||
status: "dead",
|
|
||||||
authToken: "66ccff0d000721114514191981023333",
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
updatedPlsStats = curPlsStats.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
const isPlsFolderExists = (
|
|
||||||
await global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.getPlsBinExists`)
|
|
||||||
).data.isExists;
|
|
||||||
updatedPlsStats.installed = isPlsFolderExists;
|
|
||||||
// @ts-expect-error
|
|
||||||
global.__HUGO_AURA__.plsStats = updatedPlsStats;
|
|
||||||
console.debug(
|
|
||||||
"[HugoAura / UI / PLS Manager / DEBUG] Updated early plsStats:",
|
|
||||||
global.__HUGO_AURA__.plsStats
|
|
||||||
);
|
|
||||||
|
|
||||||
global.ipcRenderer.invoke(
|
|
||||||
`${IPC_METHOD_BASE}.updatePlsStats`,
|
|
||||||
updatedPlsStats
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (updatedPlsStats.detached && updatedPlsStats.installed) {
|
|
||||||
*/
|
|
||||||
if (updatedPlsStats.installed) {
|
|
||||||
await startConnPlsProc(updatedPlsStats);
|
|
||||||
} else {
|
|
||||||
sendRetryStatusToMain(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
global.ipcRenderer.on(`${IPC_METHOD_BASE}.post.onPlsLaunched`, (_event) => {
|
|
||||||
setTimeout(() => {
|
|
||||||
startConnPls();
|
|
||||||
}, 5000);
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSetup = () => {
|
|
||||||
if (!global.ipcRenderer) {
|
|
||||||
// @ts-ignore
|
|
||||||
global.ipcRenderer = require("electron").global.ipcRenderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
initPlsConnection();
|
|
||||||
|
|
||||||
global.ipcRenderer.on(
|
|
||||||
`${IPC_METHOD_BASE}.retryPlsConnect`,
|
|
||||||
(_evt, _arg) => {
|
|
||||||
if (!global.__HUGO_AURA__.plsStats) return;
|
|
||||||
if (global.__HUGO_AURA__.plsStats.connected) return;
|
|
||||||
initPlsConnection();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
onSetup();
|
|
||||||
}, 1500);
|
|
||||||
})();
|
|
||||||
@@ -13,18 +13,27 @@
|
|||||||
<!-- Chevron Left Icon -->
|
<!-- Chevron Left Icon -->
|
||||||
</div>
|
</div>
|
||||||
<p>雨光之环</p>
|
<p>雨光之环</p>
|
||||||
<div class="aura-config-page-app-bar-hr-vertical"></div>
|
<div
|
||||||
|
class="aura-config-page-app-bar-hr-vertical"
|
||||||
|
id="auraConfigPageAppBarVerticalHr"
|
||||||
|
></div>
|
||||||
|
<div class="aura-config-page-app-bar-spacer space-none"></div>
|
||||||
<div
|
<div
|
||||||
onclick="global.__HUGO_AURA_UI_FUNCTIONS__.config.handleNavHome()"
|
onclick="global.__HUGO_AURA_UI_FUNCTIONS__.config.handleNavHome()"
|
||||||
style="-webkit-app-region: no-drag; z-index: 2000; margin-left: 6px"
|
style="
|
||||||
|
-webkit-app-region: no-drag;
|
||||||
|
z-index: 2000;
|
||||||
|
margin-left: 6px;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="21"
|
width="22"
|
||||||
height="21"
|
height="22"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
class="iconfont"
|
class="iconfont"
|
||||||
style="margin-top: -1.5px"
|
style="margin-top: -1.35px"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
@@ -136,8 +145,8 @@
|
|||||||
<div class="aura-config-page-operation-body">
|
<div class="aura-config-page-operation-body">
|
||||||
<img src="../../aura/ui/static/config/no_limitations.svg" />
|
<img src="../../aura/ui/static/config/no_limitations.svg" />
|
||||||
<div>
|
<div>
|
||||||
<p class="config-operation-title">限制解除</p>
|
<p class="config-operation-title">行为改写</p>
|
||||||
<p class="config-operation-description">禁用密码、关闭功能</p>
|
<p class="config-operation-description">覆写密码、禁用能力</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -149,7 +158,7 @@
|
|||||||
<div class="aura-config-page-operation-body">
|
<div class="aura-config-page-operation-body">
|
||||||
<img src="../../aura/ui/static/config/behaviour_mon.svg" />
|
<img src="../../aura/ui/static/config/behaviour_mon.svg" />
|
||||||
<div>
|
<div>
|
||||||
<p class="config-operation-title">行为管控</p>
|
<p class="config-operation-title">操作管控</p>
|
||||||
<p class="config-operation-description">窥屏提醒、数据欺骗</p>
|
<p class="config-operation-description">窥屏提醒、数据欺骗</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -284,14 +293,14 @@
|
|||||||
|
|
||||||
<div class="toast-container position-fixed bottom-0 end-0 p-3">
|
<div class="toast-container position-fixed bottom-0 end-0 p-3">
|
||||||
<div
|
<div
|
||||||
id="relaunchPlsNotifyToast"
|
id="relaunchAikariNotifyToast"
|
||||||
class="toast acp-toast-emerg"
|
class="toast acp-toast-emerg"
|
||||||
aria-atomic="true"
|
aria-atomic="true"
|
||||||
data-bs-autohide="false"
|
data-bs-autohide="false"
|
||||||
>
|
>
|
||||||
<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">重启 Aikari 进程以应用设置</strong>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn-close"
|
class="btn-close"
|
||||||
@@ -299,13 +308,13 @@
|
|||||||
></button>
|
></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="toast-body">
|
<div class="toast-body">
|
||||||
<p>请重启 PLS 进程以应用修改的设置</p>
|
<p>请重启 Aikari 进程以应用修改的设置</p>
|
||||||
<p>已修改的配置将自动保存</p>
|
<p>已修改的配置将自动保存</p>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn btn-primary btn-sm"
|
class="btn btn-primary btn-sm"
|
||||||
id="plsRelaunchBtn"
|
id="aikariRelaunchBtn"
|
||||||
onclick="ipcRenderer.invoke('$aura.pls.relaunchPls')"
|
onclick="ipcRenderer.invoke('$aura.aikari.relaunchPls')"
|
||||||
>
|
>
|
||||||
重启进程
|
重启进程
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ global.__HUGO_AURA_UI_FUNCTIONS__.config = {
|
|||||||
if (!side) {
|
if (!side) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
global.__HUGO_AURA_LOADER__[
|
global.__HUGO_AURA_LOADER__[
|
||||||
"Aura.UI.Assistant.Config.BehaviourCtrl.PlsStatus"
|
"Aura.UI.Assistant.Config.BehaviourCtrl.AikariStatus"
|
||||||
].active = false;
|
].active = false;
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
@@ -235,6 +235,11 @@ global.__HUGO_AURA_UI_FUNCTIONS__.config = {
|
|||||||
inputEl.value = "";
|
inputEl.value = "";
|
||||||
inputEl.classList.remove("invalid");
|
inputEl.classList.remove("invalid");
|
||||||
inputEl.classList.remove("is-invalid");
|
inputEl.classList.remove("is-invalid");
|
||||||
|
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.config.resetAuthDialogInputElOnSubmit(
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.config.verifyAuthPassword
|
||||||
|
);
|
||||||
|
|
||||||
acpDialogConfirmBtnEl.onclick = (_evt) => {
|
acpDialogConfirmBtnEl.onclick = (_evt) => {
|
||||||
global.__HUGO_AURA_UI_FUNCTIONS__.config.verifyAuthPassword();
|
global.__HUGO_AURA_UI_FUNCTIONS__.config.verifyAuthPassword();
|
||||||
};
|
};
|
||||||
@@ -243,6 +248,16 @@ global.__HUGO_AURA_UI_FUNCTIONS__.config = {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
resetAuthDialogInputElOnSubmit: (func) => {
|
||||||
|
const inputEl = document.getElementById("acp-auth-user-input");
|
||||||
|
inputEl.onsubmit = (evt) => evt.preventDefault();
|
||||||
|
inputEl.onkeydown = (event) => {
|
||||||
|
if (event.key === "Enter") {
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
handleACSNShow: async () => {
|
handleACSNShow: async () => {
|
||||||
const acsnRootEl = document.getElementsByClassName(
|
const acsnRootEl = document.getElementsByClassName(
|
||||||
"acp-config-status-notify"
|
"acp-config-status-notify"
|
||||||
@@ -294,6 +309,27 @@ global.__HUGO_AURA_UI_FUNCTIONS__.config = {
|
|||||||
// TODO: Error handling
|
// TODO: Error handling
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
initCustomUIProps: async (refresh = false) => {
|
||||||
|
const verticalHrEl = document.getElementById(
|
||||||
|
"auraConfigPageAppBarVerticalHr"
|
||||||
|
);
|
||||||
|
const spacerElArr = document.getElementsByClassName(
|
||||||
|
"aura-config-page-app-bar-spacer"
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
global.__HUGO_AURA_CONFIG__.auraSettings.appearance.appBar
|
||||||
|
.actionBtnsOnRight
|
||||||
|
) {
|
||||||
|
verticalHrEl.classList.add("hidden");
|
||||||
|
spacerElArr[0].classList.remove("space-none");
|
||||||
|
spacerElArr[1].classList.add("space-none");
|
||||||
|
} else if (refresh) {
|
||||||
|
verticalHrEl.classList.remove("hidden");
|
||||||
|
spacerElArr[0].classList.add("space-none");
|
||||||
|
spacerElArr[1].classList.remove("space-none");
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
(() => {
|
(() => {
|
||||||
@@ -338,7 +374,8 @@ global.__HUGO_AURA_UI_FUNCTIONS__.config = {
|
|||||||
let timeout = 0;
|
let timeout = 0;
|
||||||
Array.from(operationElArr).forEach((el) => {
|
Array.from(operationElArr).forEach((el) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
el.className = "operation-el-show aura-config-page-operation-el";
|
el.classList.remove("operation-el-hidden");
|
||||||
|
el.classList.add("operation-el-show");
|
||||||
}, timeout);
|
}, timeout);
|
||||||
timeout += 150;
|
timeout += 150;
|
||||||
});
|
});
|
||||||
@@ -364,6 +401,9 @@ global.__HUGO_AURA_UI_FUNCTIONS__.config = {
|
|||||||
"aura-config-page-header-area"
|
"aura-config-page-header-area"
|
||||||
)[0];
|
)[0];
|
||||||
acsDialogAreaEl.style = "";
|
acsDialogAreaEl.style = "";
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.config.resetAuthDialogInputElOnSubmit(
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.config.verifyAuthPassword
|
||||||
|
);
|
||||||
await window.__HUGO_AURA_GLOBAL__.utils.sleep(500);
|
await window.__HUGO_AURA_GLOBAL__.utils.sleep(500);
|
||||||
acsDialogAreaEl.classList.remove("acp-ada-hidden");
|
acsDialogAreaEl.classList.remove("acp-ada-hidden");
|
||||||
acpAppBarEl.classList.add("color-reverse");
|
acpAppBarEl.classList.add("color-reverse");
|
||||||
@@ -391,6 +431,7 @@ global.__HUGO_AURA_UI_FUNCTIONS__.config = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onMounted = () => {
|
const onMounted = () => {
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.config.initCustomUIProps();
|
||||||
applyVersionInfo();
|
applyVersionInfo();
|
||||||
|
|
||||||
showAnimation();
|
showAnimation();
|
||||||
|
|||||||
@@ -58,6 +58,10 @@
|
|||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.aura-config-page-app-bar-spacer.space-none {
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.aura-config-page-app-bar-hr-vertical {
|
.aura-config-page-app-bar-hr-vertical {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
@@ -66,3 +70,7 @@
|
|||||||
height: 12px;
|
height: 12px;
|
||||||
transition: background 0.5s;
|
transition: background 0.5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.aura-config-page-app-bar-hr-vertical.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|||||||
52
src/aura/ui/pages/configSubPages/behaviourCtrl/plsStatus.css → src/aura/ui/pages/configSubPages/behaviourCtrl/aikariStatus.css
Executable file → Normal file
52
src/aura/ui/pages/configSubPages/behaviourCtrl/plsStatus.css → src/aura/ui/pages/configSubPages/behaviourCtrl/aikariStatus.css
Executable file → Normal file
@@ -1,15 +1,15 @@
|
|||||||
.acs-behaviour-control-pls-status-page {
|
.acs-behaviour-control-aikari-status-page {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.acs-behaviour-control-pls-status-page p {
|
.acs-behaviour-control-aikari-status-page p {
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.acs-bc-pls-status-page-pls-description {
|
.acs-bc-aikari-status-page-aikari-description {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
max-width: 80%;
|
max-width: 80%;
|
||||||
opacity: 0.35;
|
opacity: 0.35;
|
||||||
@@ -17,11 +17,11 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.acs-bc-pls-status-page-main-logo {
|
.acs-bc-aikari-status-page-main-logo {
|
||||||
max-width: 11%;
|
max-width: 15%;
|
||||||
opacity: 0.45;
|
opacity: 0.45;
|
||||||
margin-top: 1.5rem;
|
margin-top: 1rem;
|
||||||
margin-bottom: 1.5rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.acs-bc-psp-operations-container {
|
.acs-bc-psp-operations-container {
|
||||||
@@ -133,7 +133,7 @@
|
|||||||
margin-top: 1px;
|
margin-top: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.acs-bc-pls-status-page-status-el {
|
.acs-bc-aikari-status-page-status-el {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 40%;
|
width: 40%;
|
||||||
@@ -141,17 +141,17 @@
|
|||||||
border-bottom: 1px solid rgba(0, 0, 0, 0.25);
|
border-bottom: 1px solid rgba(0, 0, 0, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
.acs-bc-pls-status-page-status-el div {
|
.acs-bc-aikari-status-page-status-el div {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.acs-bc-pls-status-page-status-area {
|
.acs-bc-aikari-status-page-status-area {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.acs-bc-pls-status-page-status-area-circle {
|
.acs-bc-aikari-status-page-status-area-circle {
|
||||||
height: 10px;
|
height: 10px;
|
||||||
width: 10px;
|
width: 10px;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
@@ -159,48 +159,48 @@
|
|||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.acs-bc-pls-status-page-status-area.pending
|
.acs-bc-aikari-status-page-status-area.pending
|
||||||
.acs-bc-pls-status-page-status-area-circle {
|
.acs-bc-aikari-status-page-status-area-circle {
|
||||||
background-color: rgba(0, 0, 0, 0.375);
|
background-color: rgba(0, 0, 0, 0.375);
|
||||||
}
|
}
|
||||||
|
|
||||||
.acs-bc-pls-status-page-status-area.pending p {
|
.acs-bc-aikari-status-page-status-area.pending p {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.acs-bc-pls-status-page-status-area.success
|
.acs-bc-aikari-status-page-status-area.success
|
||||||
.acs-bc-pls-status-page-status-area-circle {
|
.acs-bc-aikari-status-page-status-area-circle {
|
||||||
background-color: rgb(0, 175, 38);
|
background-color: rgb(0, 175, 38);
|
||||||
}
|
}
|
||||||
|
|
||||||
.acs-bc-pls-status-page-status-area.success p {
|
.acs-bc-aikari-status-page-status-area.success p {
|
||||||
color: rgb(0, 150, 33);
|
color: rgb(0, 150, 33);
|
||||||
}
|
}
|
||||||
|
|
||||||
.acs-bc-pls-status-page-status-area.failed
|
.acs-bc-aikari-status-page-status-area.failed
|
||||||
.acs-bc-pls-status-page-status-area-circle {
|
.acs-bc-aikari-status-page-status-area-circle {
|
||||||
background-color: rgb(175, 0, 0);
|
background-color: rgb(175, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.acs-bc-pls-status-page-status-area.failed p {
|
.acs-bc-aikari-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-aikari-status-page-status-area.warning
|
||||||
.acs-bc-pls-status-page-status-area-circle {
|
.acs-bc-aikari-status-page-status-area-circle {
|
||||||
background-color: rgb(212, 127, 0);
|
background-color: rgb(212, 127, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.acs-bc-pls-status-page-status-area.warning p {
|
.acs-bc-aikari-status-page-status-area.warning p {
|
||||||
color: rgb(212, 127, 0);
|
color: rgb(212, 127, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.acs-bc-pls-status-page-status-area.info
|
.acs-bc-aikari-status-page-status-area.info
|
||||||
.acs-bc-pls-status-page-status-area-circle {
|
.acs-bc-aikari-status-page-status-area-circle {
|
||||||
background-color: #3d78ff;
|
background-color: #3d78ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.acs-bc-pls-status-page-status-area.info p {
|
.acs-bc-aikari-status-page-status-area.info p {
|
||||||
color: #3d78ff;
|
color: #3d78ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
49
src/aura/ui/pages/configSubPages/behaviourCtrl/plsStatus.html → src/aura/ui/pages/configSubPages/behaviourCtrl/aikariStatus.html
Executable file → Normal file
49
src/aura/ui/pages/configSubPages/behaviourCtrl/plsStatus.html → src/aura/ui/pages/configSubPages/behaviourCtrl/aikariStatus.html
Executable file → Normal file
@@ -1,12 +1,11 @@
|
|||||||
<div class="acs-behaviour-control-pls-status-page">
|
<div class="acs-behaviour-control-aikari-status-page">
|
||||||
<p class="acs-bc-pls-status-page-pls-description">
|
<p class="acs-bc-aikari-status-page-aikari-description">
|
||||||
HugoAura ProxyLayerServices (Aura-PLS) 是基于 Python + MITMProxy
|
HugoAura Aikari 是基于 C++ 实现的 HugoAura 特权访问服务, 集成篡改 MQTT
|
||||||
实现的代理服务, 用于解密并修改希沃基础服务 (SeewoCore) 的 MQTT 数据包,
|
数据包、冰点穿透增强等功能, 实现行为监控、伪造上报
|
||||||
实现行为监控、伪造上报等功能
|
|
||||||
</p>
|
</p>
|
||||||
<img
|
<img
|
||||||
src="../../aura/ui/static/aura_pls.png"
|
src="../../aura/ui/static/aikari_color_reversed.png"
|
||||||
class="acs-bc-pls-status-page-main-logo"
|
class="acs-bc-aikari-status-page-main-logo"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="acs-bc-psp-operations-container">
|
<div class="acs-bc-psp-operations-container">
|
||||||
@@ -28,7 +27,7 @@
|
|||||||
<div
|
<div
|
||||||
class="acs-bc-psp-operation-btn"
|
class="acs-bc-psp-operation-btn"
|
||||||
aura-disabled="true"
|
aura-disabled="true"
|
||||||
id="acsBcPsp-operBtn-Download"
|
id="acsBcPsp-operBtn-Install"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
@@ -45,10 +44,10 @@
|
|||||||
d="M17 26.17V14h-2v12.17l-2.59-2.58L11 25l5 5l5-5l-1.41-1.41z"
|
d="M17 26.17V14h-2v12.17l-2.59-2.58L11 25l5 5l5-5l-1.41-1.41z"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
<p>下载内核</p>
|
<p>下载应用</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="acs-bc-psp-operation-btn" id="acsBcPsp-operBtn-Install">
|
<div class="acs-bc-psp-operation-btn" id="acsBcPsp-operBtn-InstallSvc">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="32"
|
width="32"
|
||||||
@@ -73,7 +72,7 @@
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
class="acs-bc-psp-operation-btn acs-bc-psp-o-btn-dangerous"
|
class="acs-bc-psp-operation-btn acs-bc-psp-o-btn-dangerous"
|
||||||
id="acsBcPsp-operBtn-Uninstall"
|
id="acsBcPsp-operBtn-UninstallSvc"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
@@ -155,61 +154,61 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="acs-bc-pls-status-page-status-el">
|
<div class="acs-bc-aikari-status-page-status-el">
|
||||||
<p>安装状态</p>
|
<p>安装状态</p>
|
||||||
<div
|
<div
|
||||||
class="acs-bc-pls-status-page-status-area pending"
|
class="acs-bc-aikari-status-page-status-area pending"
|
||||||
id="acs-bc-psp-installStatus-container"
|
id="acs-bc-psp-installStatus-container"
|
||||||
>
|
>
|
||||||
<span class="acs-bc-pls-status-page-status-area-circle"></span>
|
<span class="acs-bc-aikari-status-page-status-area-circle"></span>
|
||||||
<p id="acs-bc-psp-installStatus-text">未安装</p>
|
<p id="acs-bc-psp-installStatus-text">未安装</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="acs-bc-pls-status-page-status-el">
|
<div class="acs-bc-aikari-status-page-status-el">
|
||||||
<p>启动状态</p>
|
<p>启动状态</p>
|
||||||
<div
|
<div
|
||||||
class="acs-bc-pls-status-page-status-area pending"
|
class="acs-bc-aikari-status-page-status-area pending"
|
||||||
id="acs-bc-psp-launchStatus-container"
|
id="acs-bc-psp-launchStatus-container"
|
||||||
>
|
>
|
||||||
<span class="acs-bc-pls-status-page-status-area-circle"></span>
|
<span class="acs-bc-aikari-status-page-status-area-circle"></span>
|
||||||
<p id="acs-bc-psp-launchStatus-text">未启动</p>
|
<p id="acs-bc-psp-launchStatus-text">未启动</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="acs-bc-pls-status-page-status-el">
|
<div class="acs-bc-aikari-status-page-status-el">
|
||||||
<p>连接状态</p>
|
<p>连接状态</p>
|
||||||
<div
|
<div
|
||||||
class="acs-bc-pls-status-page-status-area pending"
|
class="acs-bc-aikari-status-page-status-area pending"
|
||||||
id="acs-bc-psp-connStatus-container"
|
id="acs-bc-psp-connStatus-container"
|
||||||
>
|
>
|
||||||
<span class="acs-bc-pls-status-page-status-area-circle"></span>
|
<span class="acs-bc-aikari-status-page-status-area-circle"></span>
|
||||||
<p id="acs-bc-psp-connStatus-text">已断开</p>
|
<p id="acs-bc-psp-connStatus-text">已断开</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="acs-bc-pls-status-page-status-el" style="border-bottom: none">
|
<div class="acs-bc-aikari-status-page-status-el" style="border-bottom: none">
|
||||||
<p>版本</p>
|
<p>版本</p>
|
||||||
<div class="acs-bc-pls-status-page-status-area">
|
<div class="acs-bc-aikari-status-page-status-area">
|
||||||
<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 class="toast-container position-fixed bottom-0 end-0 p-3">
|
||||||
<div
|
<div
|
||||||
id="plsStatusNotifyToast"
|
id="aikariStatusNotifyToast"
|
||||||
class="acs-bc-psp-toast toast"
|
class="acs-bc-psp-toast toast"
|
||||||
data-bs-autohide="false"
|
data-bs-autohide="false"
|
||||||
>
|
>
|
||||||
<div class="toast-header">
|
<div class="toast-header">
|
||||||
<strong class="me-auto" id="plsStatusNotifyToastTitle"></strong>
|
<strong class="me-auto" id="aikariStatusNotifyToastTitle"></strong>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn-close"
|
class="btn-close"
|
||||||
data-bs-dismiss="toast"
|
data-bs-dismiss="toast"
|
||||||
></button>
|
></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="toast-body" id="plsStatusNotifyToastBody"></div>
|
<div class="toast-body" id="aikariStatusNotifyToastBody"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
1094
src/aura/ui/pages/configSubPages/behaviourCtrl/aikariStatus.js
Normal file
1094
src/aura/ui/pages/configSubPages/behaviourCtrl/aikariStatus.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -36,13 +36,13 @@
|
|||||||
class="nav-link"
|
class="nav-link"
|
||||||
id="security-config-tab"
|
id="security-config-tab"
|
||||||
data-bs-toggle="pill"
|
data-bs-toggle="pill"
|
||||||
data-bs-target="#security-config-subpage"
|
data-bs-target="#device-info-post-config-subpage"
|
||||||
type="button"
|
type="button"
|
||||||
role="tab"
|
role="tab"
|
||||||
aria-controls="security-config-subpage"
|
aria-controls="device-info-post-config-subpage"
|
||||||
aria-selected="false"
|
aria-selected="false"
|
||||||
>
|
>
|
||||||
设备安全
|
信息上报
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
class="tab-pane fade"
|
class="tab-pane fade"
|
||||||
id="security-config-subpage"
|
id="device-info-post-config-subpage"
|
||||||
role="tabpanel"
|
role="tabpanel"
|
||||||
aria-labelledby="security-config-tab"
|
aria-labelledby="security-config-tab"
|
||||||
></div>
|
></div>
|
||||||
|
|||||||
@@ -7,45 +7,58 @@
|
|||||||
} = 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 { deviceInfoPostSettings } = require(`${REQUIRE_BASE}/deviceInfoPost`);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
updatePlsSettingsFromLocal,
|
updateAikariSettingsFromLocal,
|
||||||
updatePlsRulesFromLocal,
|
updateAikariRulesFromLocal,
|
||||||
} = require(`${REQUIRE_BASE}/../../../../composables/plsConfigManager`);
|
} = require(`${REQUIRE_BASE}/../../../../composables/aikariConfigManager`);
|
||||||
|
|
||||||
|
const fileSystemRawCmds = require(`${REQUIRE_BASE}/../../../../composables/rawCmdExec/fs`);
|
||||||
|
|
||||||
const initStatusPage = () => {
|
const initStatusPage = () => {
|
||||||
global.__HUGO_AURA_LOADER__[
|
global.__HUGO_AURA_LOADER__[
|
||||||
"Aura.UI.Assistant.Config.BehaviourCtrl.PlsStatus"
|
"Aura.UI.Assistant.Config.BehaviourCtrl.AikariStatus"
|
||||||
].active = true;
|
].active = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const preInitUIReactives = async () => {
|
||||||
|
if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig)
|
||||||
|
global.__HUGO_AURA_UI_REACTIVES__.subConfig = {};
|
||||||
|
if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrlShared)
|
||||||
|
global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrlShared = {};
|
||||||
|
|
||||||
|
global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrlShared.diskCaptions =
|
||||||
|
await fileSystemRawCmds.getDiskCaptions();
|
||||||
|
};
|
||||||
|
|
||||||
const initBasicSettingsPage = () => {
|
const initBasicSettingsPage = () => {
|
||||||
const basicSubPageEl = document.getElementById("basic-config-subpage");
|
const basicSubPageEl = document.getElementById("basic-config-subpage");
|
||||||
settingsRenderer(basicSubPageEl, basicSettings);
|
settingsRenderer(basicSubPageEl, basicSettings);
|
||||||
};
|
};
|
||||||
|
|
||||||
const initDeviceSecuritySettingsPage = () => {
|
const initDeviceInfoPostSettingsPage = () => {
|
||||||
const deviceSecuritySubPageEl = document.getElementById(
|
const deviceInfoPostSubPageEl = document.getElementById(
|
||||||
"security-config-subpage"
|
"device-info-post-config-subpage"
|
||||||
);
|
);
|
||||||
settingsRenderer(deviceSecuritySubPageEl, deviceSecuritySettings);
|
settingsRenderer(deviceInfoPostSubPageEl, deviceInfoPostSettings);
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderSubPages = async () => {
|
const renderSubPages = async () => {
|
||||||
await updatePlsSettingsFromLocal();
|
await updateAikariSettingsFromLocal();
|
||||||
await updatePlsRulesFromLocal();
|
await updateAikariRulesFromLocal();
|
||||||
|
|
||||||
initBasicSettingsPage();
|
initBasicSettingsPage();
|
||||||
initDeviceSecuritySettingsPage();
|
initDeviceInfoPostSettingsPage();
|
||||||
};
|
};
|
||||||
|
|
||||||
const onMounted = () => {
|
const onMounted = () => {
|
||||||
const rootEl = document.getElementById("acs-behaviour-control-el");
|
const rootEl = document.getElementById("acs-behaviour-control-el");
|
||||||
|
preInitUIReactives();
|
||||||
initStatusPage();
|
initStatusPage();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
rootEl.classList.remove("acs-behaviour-control-hidden");
|
rootEl.classList.remove("acs-behaviour-control-hidden");
|
||||||
renderSubPages(); // 如果立即渲染子页面, 此时 plsRules 还未初始化, 会导致子页面 auraIf 失效
|
renderSubPages();
|
||||||
}, 500);
|
}, 500);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,883 +0,0 @@
|
|||||||
if (!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 IPC_METHOD_BASE = "$aura.pls";
|
|
||||||
|
|
||||||
const lifecycleStatus = {
|
|
||||||
installed: false,
|
|
||||||
detached: false,
|
|
||||||
svcInstalled: false,
|
|
||||||
svcRunning: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
global.__HUGO_AURA_UI_REACTIVES__.subConfig.plsStatus = {
|
|
||||||
toastAutoHideTimeout: null,
|
|
||||||
curDlTaskId: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus = {
|
|
||||||
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}`);
|
|
||||||
if (!btnEl) return false;
|
|
||||||
btnEl.setAttribute("aura-disabled", isDisabled ? "true" : "false");
|
|
||||||
if (btnContent) {
|
|
||||||
const btnPEl = btnEl.getElementsByTagName("p")[0];
|
|
||||||
btnPEl.textContent = btnContent;
|
|
||||||
}
|
|
||||||
if (isDisabled) {
|
|
||||||
btnEl.onclick = () => {};
|
|
||||||
} else {
|
|
||||||
switch (btnName) {
|
|
||||||
case "Refresh":
|
|
||||||
btnEl.onclick = () => {
|
|
||||||
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
|
||||||
"warning",
|
|
||||||
"正在更新",
|
|
||||||
null,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
null
|
|
||||||
);
|
|
||||||
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.refreshPlsStatus();
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case "Download":
|
|
||||||
btnEl.onclick = async () => {
|
|
||||||
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.downloadPLSBin();
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
|
|
||||||
// ↓ 这边的确可以把这些全都合并到一个可复用 fn 里去, 但没必要
|
|
||||||
// 如果后续要引入错误视觉反馈, 合并到单个 fn 反而会增加实现复杂度
|
|
||||||
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>${ret.errorObj}</p>`,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateStatusContent();
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
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__.plsStats.installed = false;
|
|
||||||
global.__HUGO_AURA__.plsStats.connected = false;
|
|
||||||
global.__HUGO_AURA__.plsStats.launched = false;
|
|
||||||
ipcRenderer.invoke(
|
|
||||||
`${IPC_METHOD_BASE}.updatePlsStats`,
|
|
||||||
global.__HUGO_AURA__.plsStats
|
|
||||||
);
|
|
||||||
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
|
||||||
"success",
|
|
||||||
"内核已删除",
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
2000
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
|
||||||
"error",
|
|
||||||
"内核删除失败",
|
|
||||||
`<p>
|
|
||||||
${ret.errorObj ? ret.errorObj : "检查日志以获取详细信息"}
|
|
||||||
</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>${
|
|
||||||
stopRet.errorObj
|
|
||||||
? stopRet.errorObj
|
|
||||||
: "检查日志以获取详细信息"
|
|
||||||
}</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;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
updateStatusContent: async () => {
|
|
||||||
const curPlsStats = await updatePlsStatusFromLocal();
|
|
||||||
|
|
||||||
if (curPlsStats.status === "downloading") {
|
|
||||||
GLOBAL_FUNCTIONS.downloadPLSBin(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
const acIdInst = "acs-bc-psp-installStatus-container";
|
|
||||||
const atIdInst = "acs-bc-psp-installStatus-text";
|
|
||||||
switch (lifecycleStatus.installed) {
|
|
||||||
case true:
|
|
||||||
if (!lifecycleStatus.svcInstalled) {
|
|
||||||
updateStatusEl(acIdInst, atIdInst, "WARNING", "已下载, 服务未安装");
|
|
||||||
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;
|
|
||||||
case false:
|
|
||||||
updateStatusEl(acIdInst, atIdInst, "PENDING", "未下载");
|
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Download", false);
|
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Install", true);
|
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Uninstall", true);
|
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Start", true);
|
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Stop", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
const acIdLaunch = "acs-bc-psp-launchStatus-container";
|
|
||||||
const atIdLaunch = "acs-bc-psp-launchStatus-text";
|
|
||||||
|
|
||||||
if (lifecycleStatus.detached) {
|
|
||||||
updateStatusEl(acIdLaunch, atIdLaunch, "INFO", "已分离");
|
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Start", true);
|
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Stop", true);
|
|
||||||
} else if (lifecycleStatus.svcInstalled && lifecycleStatus.installed) {
|
|
||||||
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 atIdConn = "acs-bc-psp-connStatus-text";
|
|
||||||
switch (curPlsStats.connected) {
|
|
||||||
case true:
|
|
||||||
updateStatusEl(acIdConn, atIdConn, "SUCCESS", "已连接");
|
|
||||||
break;
|
|
||||||
case false:
|
|
||||||
if (curPlsStats.status !== "notReady") {
|
|
||||||
updateStatusEl(acIdConn, atIdConn, "FAILED", "连接失败");
|
|
||||||
} else {
|
|
||||||
updateStatusEl(acIdConn, atIdConn, "PENDING", "等待启动");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (curPlsStats.version && curPlsStats.version !== "未知") {
|
|
||||||
const versionTextEl = document.getElementById(
|
|
||||||
"acs-bc-psp-version-text"
|
|
||||||
);
|
|
||||||
versionTextEl.textContent = "v" + curPlsStats.version;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
refreshPlsStatus: async (init = false) => {
|
|
||||||
const binExistsRet = await ipcRenderer.invoke(
|
|
||||||
`${IPC_METHOD_BASE}.getPlsBinExists`
|
|
||||||
);
|
|
||||||
if (binExistsRet.success && binExistsRet.data.isExists) {
|
|
||||||
lifecycleStatus.installed = true;
|
|
||||||
global.__HUGO_AURA__.plsStats.installed = true;
|
|
||||||
ipcRenderer.invoke(
|
|
||||||
`${IPC_METHOD_BASE}.updatePlsStats`,
|
|
||||||
global.__HUGO_AURA__.plsStats
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
lifecycleStatus.installed = false;
|
|
||||||
global.__HUGO_AURA__.plsStats.installed = false;
|
|
||||||
ipcRenderer.invoke(
|
|
||||||
`${IPC_METHOD_BASE}.updatePlsStats`,
|
|
||||||
global.__HUGO_AURA__.plsStats
|
|
||||||
);
|
|
||||||
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 =
|
|
||||||
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus
|
|
||||||
.updateOperationBtnStatus;
|
|
||||||
updateOperationBtnStatus("Refresh", true);
|
|
||||||
const result = await ipcRenderer.invoke(
|
|
||||||
`${IPC_METHOD_BASE}.retryPlsConnect`
|
|
||||||
);
|
|
||||||
if (result.success && result.status === "Retrying") {
|
|
||||||
updateOperationBtnStatus("Refresh", true, "正在重连");
|
|
||||||
|
|
||||||
ipcRenderer.once(
|
|
||||||
`${IPC_METHOD_BASE}.post.updateRetryStatus`,
|
|
||||||
async (_evt, arg) => {
|
|
||||||
await global.__HUGO_AURA_GLOBAL__.utils.sleep(50);
|
|
||||||
updateOperationBtnStatus("Refresh", false, "刷新状态");
|
|
||||||
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") {
|
|
||||||
updateOperationBtnStatus("Refresh", false, "刷新状态");
|
|
||||||
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus.updateToast(
|
|
||||||
"success",
|
|
||||||
"更新成功",
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
3000
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {boolean} isShow
|
|
||||||
*/
|
|
||||||
switchPBarShowStatus: (isShow) => {
|
|
||||||
const operAreaEl = document.getElementsByClassName(
|
|
||||||
"acs-bc-psp-operations-container"
|
|
||||||
)[0];
|
|
||||||
const pBarAreaEl = document.getElementsByClassName(
|
|
||||||
"acs-bc-psp-download-progress-area"
|
|
||||||
)[0];
|
|
||||||
const pBarDescEl = document.getElementById("acsBcPspDownloadPbarDesc");
|
|
||||||
const pBarSelfEl = document.getElementById("acsBcPspDownloadPbarEl");
|
|
||||||
|
|
||||||
if (isShow) {
|
|
||||||
pBarAreaEl.classList.remove("acs-bc-psp-dl-pbar-hidden");
|
|
||||||
operAreaEl.classList.add("acs-bc-psp-oper-ctnr-hidden");
|
|
||||||
pBarDescEl.textContent = "等待中...";
|
|
||||||
pBarSelfEl.style["width"] = "0";
|
|
||||||
} else {
|
|
||||||
pBarAreaEl.classList.add("acs-bc-psp-dl-pbar-hidden");
|
|
||||||
operAreaEl.classList.remove("acs-bc-psp-oper-ctnr-hidden");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
updatePBarStatus: async (
|
|
||||||
progress = null,
|
|
||||||
desc = null,
|
|
||||||
type = null,
|
|
||||||
isCancelShown = null
|
|
||||||
) => {
|
|
||||||
const pBarDescEl = document.getElementById("acsBcPspDownloadPbarDesc");
|
|
||||||
const pBarSelfEl = document.getElementById("acsBcPspDownloadPbarEl");
|
|
||||||
const pBarBtnEl = document.getElementById(
|
|
||||||
"acsBcPspDownloadPbarCancelBtn"
|
|
||||||
);
|
|
||||||
if (progress) {
|
|
||||||
pBarSelfEl.style["width"] = `${progress}%`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type) {
|
|
||||||
pBarSelfEl.classList.remove("bg-success");
|
|
||||||
pBarSelfEl.classList.remove("bg-warning");
|
|
||||||
pBarSelfEl.classList.remove("bg-danger");
|
|
||||||
if (type !== "normal") {
|
|
||||||
pBarSelfEl.classList.add(`bg-${type}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desc) {
|
|
||||||
pBarDescEl.innerHTML = desc;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCancelShown !== null) {
|
|
||||||
if (isCancelShown) {
|
|
||||||
pBarBtnEl.classList.remove("hidden");
|
|
||||||
} else {
|
|
||||||
pBarBtnEl.classList.add("hidden");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
downloadPLSBin: async (retrieveMode = false) => {
|
|
||||||
const GLOBAL_FUNCTIONS =
|
|
||||||
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus;
|
|
||||||
const CUR_CHANNEL = `${IPC_METHOD_BASE}.post.reportPlsDownloadStatus`;
|
|
||||||
|
|
||||||
if (!retrieveMode) {
|
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Download", true, "正在检查");
|
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Refresh", true);
|
|
||||||
await ipcRenderer.invoke(`${IPC_METHOD_BASE}.ensurePlsInstallDir`);
|
|
||||||
GLOBAL_FUNCTIONS.updateToast(
|
|
||||||
"info",
|
|
||||||
"准备开始下载...",
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
2000
|
|
||||||
);
|
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Download", true);
|
|
||||||
} else {
|
|
||||||
GLOBAL_FUNCTIONS.updateToast(
|
|
||||||
"info",
|
|
||||||
"正在恢复下载状态",
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
2000
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLOBAL_FUNCTIONS.switchPBarShowStatus(true);
|
|
||||||
GLOBAL_FUNCTIONS.updatePBarStatus(0, "等待中...", "normal", false);
|
|
||||||
|
|
||||||
const callbackFn = (_evt, info) => {
|
|
||||||
switch (info.status) {
|
|
||||||
case "failed":
|
|
||||||
GLOBAL_FUNCTIONS.updateToast(
|
|
||||||
"error",
|
|
||||||
"下载失败",
|
|
||||||
`<p>${
|
|
||||||
info.message ? info.message : "检查日志以获取错误信息"
|
|
||||||
}</p><p>
|
|
||||||
${info.errorObj ? info.errorObj : ""}
|
|
||||||
</p>`,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
5000
|
|
||||||
);
|
|
||||||
|
|
||||||
GLOBAL_FUNCTIONS.updatePBarStatus(
|
|
||||||
100,
|
|
||||||
"下载时发生错误",
|
|
||||||
"danger",
|
|
||||||
false
|
|
||||||
);
|
|
||||||
setTimeout(() => {
|
|
||||||
GLOBAL_FUNCTIONS.switchPBarShowStatus(false);
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
ipcRenderer.off(CUR_CHANNEL, callbackFn);
|
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Refresh", false);
|
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus(
|
|
||||||
"Download",
|
|
||||||
false,
|
|
||||||
"下载内核"
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case "done":
|
|
||||||
GLOBAL_FUNCTIONS.updateToast(
|
|
||||||
"success",
|
|
||||||
"下载成功",
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
2500
|
|
||||||
);
|
|
||||||
|
|
||||||
GLOBAL_FUNCTIONS.updatePBarStatus(
|
|
||||||
100,
|
|
||||||
"下载成功",
|
|
||||||
"success",
|
|
||||||
false
|
|
||||||
);
|
|
||||||
setTimeout(() => {
|
|
||||||
GLOBAL_FUNCTIONS.switchPBarShowStatus(false);
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
ipcRenderer.off(CUR_CHANNEL, callbackFn);
|
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Refresh", false);
|
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus(
|
|
||||||
"Download",
|
|
||||||
true,
|
|
||||||
"下载内核"
|
|
||||||
);
|
|
||||||
lifecycleStatus.installed = true;
|
|
||||||
global.__HUGO_AURA__.plsStats.installed = true;
|
|
||||||
ipcRenderer.invoke(
|
|
||||||
`${IPC_METHOD_BASE}.updatePlsStats`,
|
|
||||||
global.__HUGO_AURA__.plsStats
|
|
||||||
);
|
|
||||||
GLOBAL_FUNCTIONS.updateStatusContent();
|
|
||||||
break;
|
|
||||||
case "waiting":
|
|
||||||
GLOBAL_FUNCTIONS.updatePBarStatus(0, "正在连接", "normal");
|
|
||||||
if (
|
|
||||||
!global.__HUGO_AURA_UI_REACTIVES__.subConfig.plsStatus
|
|
||||||
.curDlTaskId ||
|
|
||||||
global.__HUGO_AURA_UI_REACTIVES__.subConfig.plsStatus
|
|
||||||
.curDlTaskId !== info.id
|
|
||||||
) {
|
|
||||||
global.__HUGO_AURA_UI_REACTIVES__.subConfig.plsStatus.curDlTaskId =
|
|
||||||
info.id;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "progressing":
|
|
||||||
const roundProgress = Math.round(info.progress);
|
|
||||||
GLOBAL_FUNCTIONS.updatePBarStatus(
|
|
||||||
roundProgress,
|
|
||||||
`正在下载中... ${roundProgress}% (${(
|
|
||||||
info.curBytes /
|
|
||||||
1024 /
|
|
||||||
1024
|
|
||||||
).toFixed(2)}MB / ${(info.totalBytes / 1024 / 1024).toFixed(
|
|
||||||
2
|
|
||||||
)}MB)`, // POWERED BY PRETTIER
|
|
||||||
"normal",
|
|
||||||
true
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case "struggling":
|
|
||||||
GLOBAL_FUNCTIONS.updatePBarStatus(100, info.message, "warning");
|
|
||||||
break;
|
|
||||||
case "cancelled":
|
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Refresh", false);
|
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus(
|
|
||||||
"Download",
|
|
||||||
false,
|
|
||||||
"下载内核"
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ipcRenderer.on(CUR_CHANNEL, callbackFn);
|
|
||||||
|
|
||||||
ipcRenderer.invoke(`${IPC_METHOD_BASE}.downloadPls`, {
|
|
||||||
channel: "stable",
|
|
||||||
reportTo: "assistant",
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
cancelDownloadTask: async () => {
|
|
||||||
const taskId =
|
|
||||||
global.__HUGO_AURA_UI_REACTIVES__.subConfig.plsStatus.curDlTaskId;
|
|
||||||
|
|
||||||
if (!taskId) {
|
|
||||||
GLOBAL_FUNCTIONS.updateToast(
|
|
||||||
"error",
|
|
||||||
"操作取消失败",
|
|
||||||
"<p>未能获取当前的下载任务 ID</p>",
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
3000
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await ipcRenderer.invoke(
|
|
||||||
"$aura.fs.dl.cancelDownloadTask",
|
|
||||||
{ targetTaskId: taskId }
|
|
||||||
);
|
|
||||||
|
|
||||||
if (result.success) {
|
|
||||||
GLOBAL_FUNCTIONS.updateToast(
|
|
||||||
"success",
|
|
||||||
"操作取消成功",
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
2000
|
|
||||||
);
|
|
||||||
GLOBAL_FUNCTIONS.switchPBarShowStatus(false);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
GLOBAL_FUNCTIONS.updateToast(
|
|
||||||
"error",
|
|
||||||
"操作取消失败",
|
|
||||||
`<p>错误代码: ${result.error}</p>`,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
3000
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const GLOBAL_FUNCTIONS =
|
|
||||||
global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.plsStatus;
|
|
||||||
|
|
||||||
const {
|
|
||||||
updatePlsStatusFromLocal,
|
|
||||||
} = require(`${REQUIRE_BASE}/../../../composables/plsConfigManager`);
|
|
||||||
|
|
||||||
const initBsTooltip = () => {
|
|
||||||
const tooltipTriggerList = document.querySelectorAll(
|
|
||||||
'[data-bs-toggle="tooltip"]'
|
|
||||||
);
|
|
||||||
const _tooltipList = [...tooltipTriggerList].map(
|
|
||||||
(tooltipTriggerEl) => new bootstrap.Tooltip(tooltipTriggerEl)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateStatusEl = (
|
|
||||||
areaContainerId,
|
|
||||||
areaTextId,
|
|
||||||
target,
|
|
||||||
text = false
|
|
||||||
) => {
|
|
||||||
const areaContainerEl = document.getElementById(areaContainerId);
|
|
||||||
const areaContainerText = document.getElementById(areaTextId);
|
|
||||||
switch (target) {
|
|
||||||
case "PENDING":
|
|
||||||
areaContainerEl.className =
|
|
||||||
"acs-bc-pls-status-page-status-area pending";
|
|
||||||
break;
|
|
||||||
case "SUCCESS":
|
|
||||||
areaContainerEl.className =
|
|
||||||
"acs-bc-pls-status-page-status-area success";
|
|
||||||
break;
|
|
||||||
case "FAILED":
|
|
||||||
areaContainerEl.className = "acs-bc-pls-status-page-status-area failed";
|
|
||||||
break;
|
|
||||||
case "WARNING":
|
|
||||||
areaContainerEl.className =
|
|
||||||
"acs-bc-pls-status-page-status-area warning";
|
|
||||||
break;
|
|
||||||
case "INFO":
|
|
||||||
areaContainerEl.className = "acs-bc-pls-status-page-status-area info";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
areaContainerText.textContent = text ? text : "";
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const onMounted = () => {
|
|
||||||
initBsTooltip();
|
|
||||||
GLOBAL_FUNCTIONS.updateOperationBtnStatus("Refresh", false);
|
|
||||||
GLOBAL_FUNCTIONS.refreshPlsStatus(true);
|
|
||||||
|
|
||||||
const eventListener = () => {
|
|
||||||
GLOBAL_FUNCTIONS.updateStatusContent();
|
|
||||||
};
|
|
||||||
document.addEventListener("onPLSStatsUpdate", eventListener);
|
|
||||||
global.__HUGO_AURA_GLOBAL__.utils.createOnLeaveEvtListener(
|
|
||||||
"onPLSStatsUpdate",
|
|
||||||
eventListener
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted();
|
|
||||||
})();
|
|
||||||
@@ -1,30 +1,13 @@
|
|||||||
const REQUIRE_BASE = ".";
|
const REQUIRE_BASE = ".";
|
||||||
|
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
const AIKARI_ROOT_DIR = path.join("C:\\ProgramData", "HugoAura", "Aikari");
|
||||||
|
|
||||||
const {
|
const {
|
||||||
updatePlsConfigToRemote,
|
updateAikariConfigToRemote,
|
||||||
} = require(`${REQUIRE_BASE}/../../../../composables/plsConfigManager`);
|
updateAikariTelemetryConfigToRemote,
|
||||||
|
} = require(`${REQUIRE_BASE}/../../../../composables/aikariConfigManager`);
|
||||||
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 = [
|
||||||
{
|
{
|
||||||
@@ -33,142 +16,204 @@ const basicSettings = [
|
|||||||
child: [
|
child: [
|
||||||
{
|
{
|
||||||
index: 0,
|
index: 0,
|
||||||
id: "plsListenPort",
|
id: "aikarWsPreferPort",
|
||||||
type: "input",
|
type: "input",
|
||||||
subType: "number",
|
subType: "number",
|
||||||
name: "PLS WS 默认监听端口",
|
name: "Aikari WS 默认监听端口",
|
||||||
description: "PLS 的 WebSocket 服务器将默认监听指定的端口",
|
description: "Aikari WebSocket 服务器默认监听的端口",
|
||||||
reactive: true,
|
reactive: true,
|
||||||
reactiveVal: ["root.settings"],
|
reactiveVal: ["root.settings"],
|
||||||
restart: false,
|
restart: false,
|
||||||
reload: false,
|
reload: false,
|
||||||
PLSRequired: true,
|
aikariRequired: true,
|
||||||
restartPLS: false,
|
restartAikari: false,
|
||||||
warning: true,
|
warning: true,
|
||||||
warningContent: "PLS 仍会在默认端口被占用时, 自动随机端口重试",
|
warningContent: "Aikari 仍会在默认端口被占用时, 自动随机端口重试",
|
||||||
associateVal: null,
|
associateVal: null,
|
||||||
auraIf: () => true,
|
auraIf: () => true,
|
||||||
defaultValue: "",
|
defaultValue: "",
|
||||||
placeHolder: "输入端口号 (10000 ~ 65535)",
|
placeHolder: "输入端口号 (10000 ~ 65535)",
|
||||||
valueGetter: () => {
|
valueGetter: () => {
|
||||||
if (!global.__HUGO_AURA__.plsSettings) return "";
|
if (!global.__HUGO_AURA__.aikariSettings) return "";
|
||||||
return global.__HUGO_AURA__.plsSettings.wsPort;
|
return global.__HUGO_AURA__.aikariSettings.wsPreferPort;
|
||||||
},
|
},
|
||||||
callbackFn: (newVal) => {
|
callbackFn: (newVal) => {
|
||||||
if (newVal === "" || !newVal)
|
if (newVal === "" || !newVal)
|
||||||
return { valid: false, hint: "请输入端口号" };
|
return { valid: false, hint: "请输入端口号" };
|
||||||
|
|
||||||
const numberNewVal = Number(newVal);
|
const numberNewVal = Number(newVal);
|
||||||
if (numberNewVal === NaN || !(10000 <= numberNewVal) || !(newVal <= 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__.aikariSettings.wsPreferPort = numberNewVal;
|
||||||
updatePlsConfigToRemote("wsPort", numberNewVal);
|
updateAikariConfigToRemote("wsPreferPort", numberNewVal);
|
||||||
return { valid: true };
|
return { valid: true };
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
index: 1,
|
index: 1,
|
||||||
id: "plsCertPath",
|
id: "aikariForceRegenWsTlsCert",
|
||||||
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",
|
type: "switch",
|
||||||
name: "重新生成 TLS 证书",
|
name: "重新生成 WS TLS 证书",
|
||||||
description: "PLS 将在下次启动时重新生成 TLS 证书",
|
description: "Aikari 将在下次启动时重新生成用于 WebSocket 的 TLS 证书",
|
||||||
reactive: true,
|
reactive: true,
|
||||||
reactiveVal: ["root.settings"],
|
reactiveVal: ["root.settings"],
|
||||||
restart: false,
|
restart: false,
|
||||||
reload: false,
|
reload: false,
|
||||||
PLSRequired: true,
|
aikariRequired: true,
|
||||||
restartPLS: true,
|
restartAikari: true,
|
||||||
associateVal: null,
|
associateVal: null,
|
||||||
auraIf: () => true,
|
auraIf: () => true,
|
||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
valueGetter: () => {
|
valueGetter: () => {
|
||||||
if (!global.__HUGO_AURA__.plsSettings) return "";
|
if (!global.__HUGO_AURA__.aikariSettings) return "";
|
||||||
return global.__HUGO_AURA__.plsSettings.regenCert;
|
return global.__HUGO_AURA__.aikariSettings.tls.regenWsCertNextLaunch;
|
||||||
},
|
},
|
||||||
callbackFn: (newVal) => {
|
callbackFn: (newVal) => {
|
||||||
if (typeof newVal !== "boolean") return false;
|
if (typeof newVal !== "boolean") return false;
|
||||||
|
|
||||||
global.__HUGO_AURA__.plsSettings.regenCert = newVal;
|
global.__HUGO_AURA__.aikariSettings.tls.regenWsCertNextLaunch =
|
||||||
updatePlsConfigToRemote("regenCert", newVal);
|
newVal;
|
||||||
|
updateAikariConfigToRemote("tls.regenWsCertNextLaunch", newVal);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
categoryName: "分析",
|
||||||
|
child: [
|
||||||
|
{
|
||||||
|
index: 0,
|
||||||
|
id: "aikariTelemetryCtrl",
|
||||||
|
type: "switch",
|
||||||
|
name: "启用错误收集与分析",
|
||||||
|
description: "启用后, Aikari 将在发生错误时上报自托管 Sentry",
|
||||||
|
reactive: true,
|
||||||
|
reactiveVal: ["root.settings"],
|
||||||
|
restart: false,
|
||||||
|
reload: false,
|
||||||
|
aikariRequired: false,
|
||||||
|
restartAikari: false,
|
||||||
|
warning: true,
|
||||||
|
warningContent:
|
||||||
|
"我们不会收集您的设备用户名、管家内的学校名等信息, 也不会保存您的 IP 地址, 所有上传的数据仅供调试使用, 不会与任何第三方共享",
|
||||||
|
associateVal: null,
|
||||||
|
auraIf: () => true,
|
||||||
|
defaultValue: false,
|
||||||
|
valueGetter: () => {
|
||||||
|
if (
|
||||||
|
!global.__HUGO_AURA__.aikariSettings ||
|
||||||
|
!global.__HUGO_AURA__.aikariStats.connected
|
||||||
|
) {
|
||||||
|
const fs = require("fs");
|
||||||
|
return fs.existsSync(
|
||||||
|
path.join(AIKARI_ROOT_DIR, ".telemetryEnabled")
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return global.__HUGO_AURA__.aikariSettings.telemetryEnabled;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
callbackFn: (newVal) => {
|
||||||
|
if (
|
||||||
|
!global.__HUGO_AURA__.aikariSettings ||
|
||||||
|
!global.__HUGO_AURA__.aikariStats.connected
|
||||||
|
) {
|
||||||
|
if (newVal) {
|
||||||
|
const fs = require("fs");
|
||||||
|
fs.appendFile(
|
||||||
|
path.join(AIKARI_ROOT_DIR, ".telemetryEnabled"),
|
||||||
|
"",
|
||||||
|
(err) => {
|
||||||
|
if (err) console.warn(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
const fs = require("fs");
|
||||||
|
try {
|
||||||
|
fs.unlinkSync(path.join(AIKARI_ROOT_DIR, ".telemetryEnabled"));
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error removing telemetry flag: ", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
global.__HUGO_AURA__.aikariSettings.telemetryEnabled = newVal;
|
||||||
|
updateAikariTelemetryConfigToRemote(newVal);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 1,
|
||||||
|
id: "aikariTelemetryId",
|
||||||
|
type: "button",
|
||||||
|
style: "outline",
|
||||||
|
name: "Aikari Telemetry ID",
|
||||||
|
reactive: true,
|
||||||
|
reactiveVal: ["telemetry"],
|
||||||
|
restart: false,
|
||||||
|
reload: false,
|
||||||
|
aikariRequired: true,
|
||||||
|
restartAikari: false,
|
||||||
|
warning: true,
|
||||||
|
warningContent: "此标识符完全在初始化时随机生成, 与设备特征无关",
|
||||||
|
associateVal: ["telemetry"],
|
||||||
|
auraIf: () => true,
|
||||||
|
alwaysEnable: true,
|
||||||
|
buttonContent: "复制",
|
||||||
|
valueGetter: async () => {
|
||||||
|
if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrl)
|
||||||
|
global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrl = {};
|
||||||
|
const getIdPromise = new Promise((resolve) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const fs = require("fs");
|
||||||
|
const telemetryIdPath = path.join(
|
||||||
|
AIKARI_ROOT_DIR,
|
||||||
|
".telemetryId"
|
||||||
|
);
|
||||||
|
if (fs.existsSync(telemetryIdPath)) {
|
||||||
|
const fileContent = fs
|
||||||
|
.readFileSync(telemetryIdPath, { encoding: "utf-8" })
|
||||||
|
.trim();
|
||||||
|
|
||||||
|
global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrl.telemetryId =
|
||||||
|
fileContent;
|
||||||
|
resolve("标识符: " + fileContent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrl.telemetryId =
|
||||||
|
null;
|
||||||
|
resolve("未能获取标识符, Aikari 未安装或未初始化");
|
||||||
|
return;
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
|
return await getIdPromise;
|
||||||
|
},
|
||||||
|
callbackFn: async (event) => {
|
||||||
|
if (
|
||||||
|
global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrl
|
||||||
|
.telemetryId
|
||||||
|
) {
|
||||||
|
await navigator.clipboard.writeText(
|
||||||
|
global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrl
|
||||||
|
.telemetryId
|
||||||
|
);
|
||||||
|
event.target.textContent = "已复制";
|
||||||
|
} else {
|
||||||
|
event.target.textContent = "复制失败";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
module.exports = { basicSettings };
|
module.exports = { basicSettings };
|
||||||
|
|||||||
@@ -0,0 +1,259 @@
|
|||||||
|
// [!] Will be deprecated
|
||||||
|
|
||||||
|
const REQUIRE_BASE = ".";
|
||||||
|
|
||||||
|
const {
|
||||||
|
updateAikariPLSRulesToRemote,
|
||||||
|
} = require(`${REQUIRE_BASE}/../../../../composables/aikariConfigManager`);
|
||||||
|
|
||||||
|
const composables = {};
|
||||||
|
|
||||||
|
const deviceInfoPostSettings = [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
categoryName: "冰点管理",
|
||||||
|
child: [
|
||||||
|
{
|
||||||
|
index: 0,
|
||||||
|
id: "enableFreezeInfoReportOverride",
|
||||||
|
type: "switch",
|
||||||
|
name: "启用冰冻状态篡改",
|
||||||
|
description: "篡改上报的冰冻数据, 可自定义集控端显示的状态",
|
||||||
|
reactive: true,
|
||||||
|
reactiveVal: ["root.ruleSettings"],
|
||||||
|
restart: false,
|
||||||
|
reload: false,
|
||||||
|
aikariRequired: true,
|
||||||
|
restartAikari: false,
|
||||||
|
associateVal: null,
|
||||||
|
auraIf: () => true,
|
||||||
|
defaultValue: false,
|
||||||
|
valueGetter: () => {
|
||||||
|
if (!global.__HUGO_AURA__.aikariRules) return "";
|
||||||
|
return global.__HUGO_AURA__.aikariRules.ssaFeatures.securityPolicies
|
||||||
|
.freezeManagement.freezeDiskInfoPost.enabled;
|
||||||
|
},
|
||||||
|
callbackFn: (newVal) => {
|
||||||
|
if (typeof newVal !== "boolean") return;
|
||||||
|
if (!global.__HUGO_AURA__.aikariRules) return;
|
||||||
|
|
||||||
|
global.__HUGO_AURA__.aikariRules.ssaFeatures.securityPolicies.freezeManagement.freezeDiskInfoPost.enabled =
|
||||||
|
newVal;
|
||||||
|
updateAikariPLSRulesToRemote(
|
||||||
|
"ssaFeatures.securityPolicies.freezeManagement.freezeDiskInfoPost.enabled",
|
||||||
|
newVal,
|
||||||
|
"ssaFeatures.securityPolicies.freezeManagement.freezeDiskInfoPost"
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 1,
|
||||||
|
id: "freezeInfoReportFrozenDisks",
|
||||||
|
type: "checkbox",
|
||||||
|
name: "被冻结的磁盘",
|
||||||
|
description: "选中的磁盘会<b>被上报</b>为冻结 (不是实际行为)",
|
||||||
|
restart: false,
|
||||||
|
reload: false,
|
||||||
|
aikariRequired: true,
|
||||||
|
restartAikari: false,
|
||||||
|
warning: true,
|
||||||
|
warningContent:
|
||||||
|
"如果可选的磁盘盘符与下方预览不一致, 则多出的盘符可能为 DVD 驱动器 / 软盘 / 可移动磁盘, 忽略即可",
|
||||||
|
reactive: true,
|
||||||
|
reactiveVal: ["root.ruleSettings"],
|
||||||
|
associateVal: [
|
||||||
|
"ssaFeatures.securityPolicies.freezeManagement.freezeDiskInfoPost.enabled",
|
||||||
|
],
|
||||||
|
auraIf: () => true,
|
||||||
|
auraDisable: () => {
|
||||||
|
if (!global.__HUGO_AURA__.aikariRules) return { value: true };
|
||||||
|
if (
|
||||||
|
!global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrlShared
|
||||||
|
.diskCaptions
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
value: true,
|
||||||
|
tooltip: "发生错误, 请上报至 HugoAura GitHub Issues",
|
||||||
|
};
|
||||||
|
if (
|
||||||
|
!global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrlShared
|
||||||
|
.diskCaptions.length === 0
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
value: true,
|
||||||
|
tooltip: "发生错误, 请上报至 HugoAura GitHub Issues",
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
value:
|
||||||
|
!global.__HUGO_AURA__.aikariRules.ssaFeatures.securityPolicies
|
||||||
|
.freezeManagement.freezeDiskInfoPost.enabled,
|
||||||
|
tooltip: "启用冰冻状态篡改以继续",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
defaultValue: [],
|
||||||
|
templates: () => {
|
||||||
|
try {
|
||||||
|
if (
|
||||||
|
global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrlShared
|
||||||
|
.diskCaptions.length === 0
|
||||||
|
) {
|
||||||
|
return ["error"];
|
||||||
|
} else {
|
||||||
|
return global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrlShared.diskCaptions.map(
|
||||||
|
(element) => {
|
||||||
|
return element.toLowerCase().replace(/:/g, "");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return ["error"];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
templateLabels: () => {
|
||||||
|
try {
|
||||||
|
if (
|
||||||
|
global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrlShared
|
||||||
|
.diskCaptions.length === 0
|
||||||
|
) {
|
||||||
|
return ["获取盘符时发生错误, 请上报至 GitHub Issues"];
|
||||||
|
} else {
|
||||||
|
return global.__HUGO_AURA_UI_REACTIVES__.subConfig.behaviourCtrlShared.diskCaptions.map(
|
||||||
|
(element) => {
|
||||||
|
return element.replace(/:/g, " 盘");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return ["发生未知错误"];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
valueGetter: () => {
|
||||||
|
if (!global.__HUGO_AURA__.aikariRules) return [];
|
||||||
|
|
||||||
|
return global.__HUGO_AURA__.aikariRules.ssaFeatures.securityPolicies
|
||||||
|
.freezeManagement.freezeDiskInfoPost.frozenDisks;
|
||||||
|
},
|
||||||
|
callbackFn: (affectedData, affectedEl) => {
|
||||||
|
const targetArr =
|
||||||
|
global.__HUGO_AURA__.aikariRules.ssaFeatures.securityPolicies
|
||||||
|
.freezeManagement.freezeDiskInfoPost.frozenDisks;
|
||||||
|
if (affectedEl.checked) {
|
||||||
|
targetArr.push(affectedData);
|
||||||
|
} else {
|
||||||
|
targetArr.splice(targetArr.indexOf(affectedData), 1);
|
||||||
|
}
|
||||||
|
updateAikariPLSRulesToRemote(
|
||||||
|
"ssaFeatures.securityPolicies.freezeManagement.freezeDiskInfoPost.frozenDisks",
|
||||||
|
targetArr,
|
||||||
|
"ssaFeatures.securityPolicies.freezeManagement.freezeDiskInfoPost"
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 2,
|
||||||
|
id: "freezeInfoReportOverridePreview",
|
||||||
|
type: "preview",
|
||||||
|
loaderTarget:
|
||||||
|
"Aura.UI.Assistant.Config.BehaviourCtrl.DeviceSecurity.FreezeOverridePreview",
|
||||||
|
associateVal: [
|
||||||
|
"ssaFeatures.securityPolicies.freezeManagement.freezeDiskInfoPost.frozenDisks",
|
||||||
|
],
|
||||||
|
listenerType: "aikari",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
categoryName: "软件信息",
|
||||||
|
child: [
|
||||||
|
{
|
||||||
|
index: 0,
|
||||||
|
id: "enableSoftwareReportPostOverride",
|
||||||
|
type: "switch",
|
||||||
|
name: "启用软件信息上报覆写",
|
||||||
|
description:
|
||||||
|
'覆写上报的软件信息, 可自定义集控端 "设备管控" - <设备名> - "软件列表" 下的信息显示',
|
||||||
|
reactive: true,
|
||||||
|
reactiveVal: ["root.ruleSettings"],
|
||||||
|
restart: false,
|
||||||
|
reload: false,
|
||||||
|
aikariRequired: true,
|
||||||
|
restartAikari: false,
|
||||||
|
warning: true,
|
||||||
|
warningContent: '此功能与 "弹窗拦截" 等无关',
|
||||||
|
associateVal: null,
|
||||||
|
auraIf: () => true,
|
||||||
|
defaultValue: false,
|
||||||
|
valueGetter: () => {
|
||||||
|
if (!global.__HUGO_AURA__.aikariRules) return false;
|
||||||
|
return global.__HUGO_AURA__.aikariRules.deviceInfo.software
|
||||||
|
.softwareReportPost.enabled;
|
||||||
|
},
|
||||||
|
callbackFn: (newVal) => {
|
||||||
|
if (typeof newVal !== "boolean") return;
|
||||||
|
if (!global.__HUGO_AURA__.aikariRules) return;
|
||||||
|
|
||||||
|
global.__HUGO_AURA__.aikariRules.deviceInfo.software.softwareReportPost.enabled =
|
||||||
|
newVal;
|
||||||
|
updateAikariPLSRulesToRemote(
|
||||||
|
"deviceInfo.software.softwareReportPost.enabled",
|
||||||
|
newVal,
|
||||||
|
"deviceInfo.software.softwareReportPost"
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 1,
|
||||||
|
id: "enableSoftwareReportPostSetAsEmpty",
|
||||||
|
type: "switch",
|
||||||
|
name: "清空软件上报列表",
|
||||||
|
description: "将上报列表置空, 集控端将无法看到任何已安装应用",
|
||||||
|
reactive: true,
|
||||||
|
reactiveVal: ["root.ruleSettings"],
|
||||||
|
restart: false,
|
||||||
|
reload: false,
|
||||||
|
aikariRequired: true,
|
||||||
|
restartAikari: false,
|
||||||
|
associateVal: ["deviceInfo.software.softwareReportPost.enabled"],
|
||||||
|
auraIf: () => true,
|
||||||
|
auraDisable: () => {
|
||||||
|
if (!global.__HUGO_AURA__.aikariRules) return { value: true };
|
||||||
|
|
||||||
|
return {
|
||||||
|
value:
|
||||||
|
!global.__HUGO_AURA__.aikariRules.deviceInfo.software
|
||||||
|
.softwareReportPost.enabled,
|
||||||
|
tooltip: "启用软件信息上报覆写以继续",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
defaultValue: true,
|
||||||
|
valueGetter: () => {
|
||||||
|
if (!global.__HUGO_AURA__.aikariRules) return true;
|
||||||
|
return global.__HUGO_AURA__.aikariRules.deviceInfo.software
|
||||||
|
.softwareReportPost.setAsEmpty;
|
||||||
|
},
|
||||||
|
callbackFn: (newVal) => {
|
||||||
|
if (typeof newVal !== "boolean") return;
|
||||||
|
if (!global.__HUGO_AURA__.aikariRules) return;
|
||||||
|
|
||||||
|
global.__HUGO_AURA__.aikariRules.deviceInfo.software.softwareReportPost.setAsEmpty =
|
||||||
|
newVal;
|
||||||
|
updateAikariPLSRulesToRemote(
|
||||||
|
"deviceInfo.software.softwareReportPost.setAsEmpty",
|
||||||
|
newVal,
|
||||||
|
"deviceInfo.software.softwareReportPost"
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
module.exports = { deviceInfoPostSettings };
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
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 };
|
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
<path fill="currentColor" d="M20.59 22L15 16.41V7h2v8.58l5 5.01z" />
|
<path fill="currentColor" d="M20.59 22L15 16.41V7h2v8.58l5 5.01z" />
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
<p>请稍候...</p>
|
<p>无数据可用, 检查 Aikari 连接</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="acs-bc-dsc-fop-on-req-error" auraIf="false">
|
<div class="acs-bc-dsc-fop-on-req-error" auraIf="false">
|
||||||
|
|||||||
@@ -36,8 +36,8 @@
|
|||||||
resolve({
|
resolve({
|
||||||
success: true,
|
success: true,
|
||||||
data: null,
|
data: null,
|
||||||
status: response.status
|
status: response.status,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const parsedData = await response.json();
|
const parsedData = await response.json();
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
|
|
||||||
const diskElTemplate = document.createElement("p");
|
const diskElTemplate = document.createElement("p");
|
||||||
diskElTemplate.classList.add("acs-bc-dsc-fop-disk-el");
|
diskElTemplate.classList.add("acs-bc-dsc-fop-disk-el");
|
||||||
if (!curConfig.enable) {
|
if (!curConfig.enabled) {
|
||||||
for (const disk of curDisks) {
|
for (const disk of curDisks) {
|
||||||
const curDiskEl = diskElTemplate.cloneNode();
|
const curDiskEl = diskElTemplate.cloneNode();
|
||||||
if (disk.status !== 0) {
|
if (disk.status !== 0) {
|
||||||
@@ -95,44 +95,16 @@
|
|||||||
diskContainerEl.appendChild(curDiskEl);
|
diskContainerEl.appendChild(curDiskEl);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (curConfig.rewriteMode) {
|
let idx = 0;
|
||||||
case "allFreeze":
|
for (const disk of curDisks) {
|
||||||
{
|
const curDiskEl = diskElTemplate.cloneNode();
|
||||||
for (const disk of curDisks) {
|
if (curConfig.frozenDisks.includes(disk.name.toLowerCase())) {
|
||||||
const curDiskEl = diskElTemplate.cloneNode();
|
// @ts-expect-error
|
||||||
// @ts-expect-error
|
curDiskEl.classList.add("active");
|
||||||
curDiskEl.classList.add("active");
|
}
|
||||||
curDiskEl.textContent = `${disk.name.toUpperCase()} 盘`;
|
curDiskEl.textContent = `${disk.name.toUpperCase()} 盘`;
|
||||||
diskContainerEl.appendChild(curDiskEl);
|
diskContainerEl.appendChild(curDiskEl);
|
||||||
}
|
idx += 1;
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,9 +120,10 @@
|
|||||||
)[0];
|
)[0];
|
||||||
|
|
||||||
const eventListener = (_event) => {
|
const eventListener = (_event) => {
|
||||||
if (!global.__HUGO_AURA__.plsRules) return;
|
if (!global.__HUGO_AURA__.aikariRules) return;
|
||||||
composables.getAndUpdateDiskInfo(
|
composables.getAndUpdateDiskInfo(
|
||||||
global.__HUGO_AURA__.plsRules.client.security.uploadFreezeInfo
|
global.__HUGO_AURA__.aikariRules.ssaFeatures.securityPolicies
|
||||||
|
.freezeManagement.freezeDiskInfoPost
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
rootEl.addEventListener("onAssociateValueUpdated", eventListener);
|
rootEl.addEventListener("onAssociateValueUpdated", eventListener);
|
||||||
|
|||||||
@@ -31,6 +31,20 @@
|
|||||||
上报屏蔽
|
上报屏蔽
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<button
|
||||||
|
class="nav-link"
|
||||||
|
id="appearance-ctl-tab"
|
||||||
|
data-bs-toggle="pill"
|
||||||
|
data-bs-target="#appearance-ctl-subpage"
|
||||||
|
type="button"
|
||||||
|
role="tab"
|
||||||
|
aria-controls="appearance-ctl-subpage"
|
||||||
|
aria-selected="false"
|
||||||
|
>
|
||||||
|
外观与体验
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div
|
<div
|
||||||
@@ -45,5 +59,11 @@
|
|||||||
role="tabpanel"
|
role="tabpanel"
|
||||||
aria-labelledby="disable-audit-tab"
|
aria-labelledby="disable-audit-tab"
|
||||||
></div>
|
></div>
|
||||||
|
<div
|
||||||
|
class="tab-pane fade"
|
||||||
|
id="appearance-ctl-subpage"
|
||||||
|
role="tabpanel"
|
||||||
|
aria-labelledby="appearance-ctl-tab"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
} = require("../../aura/ui/composables/settingsRenderer");
|
} = require("../../aura/ui/composables/settingsRenderer");
|
||||||
const { authSettings } = require(`${pathBase}/auth`);
|
const { authSettings } = require(`${pathBase}/auth`);
|
||||||
const { banAuditSettings } = require(`${pathBase}/audit`);
|
const { banAuditSettings } = require(`${pathBase}/audit`);
|
||||||
|
const { uxAndAppearanceSettings } = require(`${pathBase}/uxAppearance`);
|
||||||
|
|
||||||
const initAuthSubPage = () => {
|
const initAuthSubPage = () => {
|
||||||
const authSubPageEl = document.getElementById("auth-subpage");
|
const authSubPageEl = document.getElementById("auth-subpage");
|
||||||
@@ -18,9 +19,17 @@
|
|||||||
settingsRenderer(banAuditSubPageEl, banAuditSettings);
|
settingsRenderer(banAuditSubPageEl, banAuditSettings);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const initUxAndAppearanceSubPage = () => {
|
||||||
|
const uxAndAppearancePageEl = document.getElementById(
|
||||||
|
"appearance-ctl-subpage"
|
||||||
|
);
|
||||||
|
settingsRenderer(uxAndAppearancePageEl, uxAndAppearanceSettings);
|
||||||
|
};
|
||||||
|
|
||||||
const onMounted = () => {
|
const onMounted = () => {
|
||||||
initAuthSubPage();
|
initAuthSubPage();
|
||||||
initBanAuditSubPage();
|
initBanAuditSubPage();
|
||||||
|
initUxAndAppearanceSubPage();
|
||||||
|
|
||||||
const rootEl = document.getElementById("acs-disable-limit-root-el");
|
const rootEl = document.getElementById("acs-disable-limit-root-el");
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|||||||
@@ -183,17 +183,130 @@ const authSettings = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
index: 2,
|
index: 2,
|
||||||
id: "screenLockAuthOverrideType",
|
id: "fastfailScreenLock",
|
||||||
type: "radio",
|
type: "switch",
|
||||||
name: "覆写模式",
|
name: "禁用屏幕锁",
|
||||||
description: "选择一个认证覆写模式",
|
description: "启用本功能后, 屏幕锁将完全无法使用, <b>请注意风险</b>",
|
||||||
restart: false,
|
restart: false,
|
||||||
reload: false,
|
reload: false,
|
||||||
associateVal: ["rewrite.vendor/screenLock.enabled"],
|
warning: true,
|
||||||
|
warningContent: "本功能存在极大的被发现风险, 启用前请自估风险",
|
||||||
|
associateVal: ["rewrite.vendor/screenLock.fastfail"],
|
||||||
auraIf: () => {
|
auraIf: () => {
|
||||||
return global.__HUGO_AURA_CONFIG__.rewrite["vendor/screenLock"]
|
return global.__HUGO_AURA_CONFIG__.rewrite["vendor/screenLock"]
|
||||||
.enabled;
|
.enabled;
|
||||||
},
|
},
|
||||||
|
defaultValue: false,
|
||||||
|
valueGetter: () => {
|
||||||
|
return global.__HUGO_AURA_CONFIG__.rewrite["vendor/screenLock"]
|
||||||
|
.fastfail;
|
||||||
|
},
|
||||||
|
callbackFn: (newVal) => {
|
||||||
|
if (typeof newVal !== "boolean") return;
|
||||||
|
global.__HUGO_AURA_CONFIG__.rewrite["vendor/screenLock"].fastfail =
|
||||||
|
newVal;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 3,
|
||||||
|
id: "showDirectUnlock",
|
||||||
|
type: "switch",
|
||||||
|
name: '显示 "直接解锁" 按钮',
|
||||||
|
description: '启用后, 屏幕锁下方的解锁类型选择区域可选择 "直接解锁"',
|
||||||
|
restart: false,
|
||||||
|
reload: false,
|
||||||
|
warning: true,
|
||||||
|
warningContent: "本功能存在极大的被发现风险, 启用前请自估风险",
|
||||||
|
associateVal: [
|
||||||
|
"rewrite.vendor/screenLock.enabled",
|
||||||
|
"rewrite.vendor/screenLock.fastfail",
|
||||||
|
],
|
||||||
|
auraIf: () => {
|
||||||
|
return global.__HUGO_AURA_CONFIG__.rewrite["vendor/screenLock"]
|
||||||
|
.enabled;
|
||||||
|
},
|
||||||
|
auraDisable: () => {
|
||||||
|
if (
|
||||||
|
global.__HUGO_AURA_CONFIG__.rewrite["vendor/screenLock"].fastfail
|
||||||
|
) {
|
||||||
|
return { value: true, tooltip: '关闭 "禁用屏幕锁" 以继续' };
|
||||||
|
}
|
||||||
|
return { value: false };
|
||||||
|
},
|
||||||
|
defaultValue: false,
|
||||||
|
valueGetter: () => {
|
||||||
|
return global.__HUGO_AURA_CONFIG__.rewrite["vendor/screenLock"]
|
||||||
|
.showDirectUnlock;
|
||||||
|
},
|
||||||
|
callbackFn: (newVal) => {
|
||||||
|
if (typeof newVal !== "boolean") return;
|
||||||
|
global.__HUGO_AURA_CONFIG__.rewrite[
|
||||||
|
"vendor/screenLock"
|
||||||
|
].showDirectUnlock = newVal;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 4,
|
||||||
|
id: "clickActBtnToExit",
|
||||||
|
type: "switch",
|
||||||
|
name: "连击紧急解锁",
|
||||||
|
description: '启用后, 连击 10 次 "激活码解锁" 按钮可紧急解锁',
|
||||||
|
restart: false,
|
||||||
|
reload: false,
|
||||||
|
tip: true,
|
||||||
|
tipTitle: "不建议关闭本功能, 至少给自己留条出路",
|
||||||
|
associateVal: [
|
||||||
|
"rewrite.vendor/screenLock.enabled",
|
||||||
|
"rewrite.vendor/screenLock.fastfail",
|
||||||
|
],
|
||||||
|
auraIf: () => {
|
||||||
|
return global.__HUGO_AURA_CONFIG__.rewrite["vendor/screenLock"]
|
||||||
|
.enabled;
|
||||||
|
},
|
||||||
|
auraDisable: () => {
|
||||||
|
if (
|
||||||
|
global.__HUGO_AURA_CONFIG__.rewrite["vendor/screenLock"].fastfail
|
||||||
|
) {
|
||||||
|
return { value: true, tooltip: '关闭 "禁用屏幕锁" 以继续' };
|
||||||
|
}
|
||||||
|
return { value: false };
|
||||||
|
},
|
||||||
|
defaultValue: true,
|
||||||
|
valueGetter: () => {
|
||||||
|
return global.__HUGO_AURA_CONFIG__.rewrite["vendor/screenLock"]
|
||||||
|
.clickBtnToExit;
|
||||||
|
},
|
||||||
|
callbackFn: (newVal) => {
|
||||||
|
if (typeof newVal !== "boolean") return;
|
||||||
|
global.__HUGO_AURA_CONFIG__.rewrite[
|
||||||
|
"vendor/screenLock"
|
||||||
|
].clickBtnToExit = newVal;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 5,
|
||||||
|
id: "screenLockAuthOverrideType",
|
||||||
|
type: "radio",
|
||||||
|
name: "认证覆写模式",
|
||||||
|
description: "选择一个认证覆写模式, 或不修改认证策略",
|
||||||
|
restart: false,
|
||||||
|
reload: false,
|
||||||
|
associateVal: [
|
||||||
|
"rewrite.vendor/screenLock.enabled",
|
||||||
|
"rewrite.vendor/screenLock.fastfail",
|
||||||
|
],
|
||||||
|
auraIf: () => {
|
||||||
|
return global.__HUGO_AURA_CONFIG__.rewrite["vendor/screenLock"]
|
||||||
|
.enabled;
|
||||||
|
},
|
||||||
|
auraDisable: () => {
|
||||||
|
if (
|
||||||
|
global.__HUGO_AURA_CONFIG__.rewrite["vendor/screenLock"].fastfail
|
||||||
|
) {
|
||||||
|
return { value: true, tooltip: '关闭 "禁用屏幕锁" 以继续' };
|
||||||
|
}
|
||||||
|
return { value: false };
|
||||||
|
},
|
||||||
defaultValue: "none",
|
defaultValue: "none",
|
||||||
templates: ["customActivationCode", "none"],
|
templates: ["customActivationCode", "none"],
|
||||||
templateLabels: ["自定义激活码", "不修改"],
|
templateLabels: ["自定义激活码", "不修改"],
|
||||||
@@ -208,7 +321,7 @@ const authSettings = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
index: 3,
|
index: 6,
|
||||||
id: "customActivationCode",
|
id: "customActivationCode",
|
||||||
type: "input",
|
type: "input",
|
||||||
subType: "password",
|
subType: "password",
|
||||||
@@ -221,6 +334,7 @@ const authSettings = [
|
|||||||
associateVal: [
|
associateVal: [
|
||||||
"rewrite.vendor/screenLock.enabled",
|
"rewrite.vendor/screenLock.enabled",
|
||||||
"rewrite.vendor/screenLock.authRewriteType",
|
"rewrite.vendor/screenLock.authRewriteType",
|
||||||
|
"rewrite.vendor/screenLock.fastfail",
|
||||||
],
|
],
|
||||||
auraIf: () => {
|
auraIf: () => {
|
||||||
return (
|
return (
|
||||||
@@ -229,6 +343,14 @@ const authSettings = [
|
|||||||
.authRewriteType === "customActivationCode"
|
.authRewriteType === "customActivationCode"
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
auraDisable: () => {
|
||||||
|
if (
|
||||||
|
global.__HUGO_AURA_CONFIG__.rewrite["vendor/screenLock"].fastfail
|
||||||
|
) {
|
||||||
|
return { value: true, tooltip: '关闭 "禁用屏幕锁" 以继续' };
|
||||||
|
}
|
||||||
|
return { value: false };
|
||||||
|
},
|
||||||
defaultValue: "",
|
defaultValue: "",
|
||||||
placeHolder: "留空表示不修改, 保留已设置值",
|
placeHolder: "留空表示不修改, 保留已设置值",
|
||||||
valueGetter: () => {
|
valueGetter: () => {
|
||||||
|
|||||||
@@ -0,0 +1,202 @@
|
|||||||
|
const uxAndAppearanceSettings = [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
categoryName: "管家助手",
|
||||||
|
child: [
|
||||||
|
{
|
||||||
|
index: 0,
|
||||||
|
id: "autoHideEasiAssistant",
|
||||||
|
type: "switch",
|
||||||
|
name: "自动最小化管家助手",
|
||||||
|
description: "管家启动后, 自动将桌面右下角管家助手最小化至 Fab 形态",
|
||||||
|
restart: true,
|
||||||
|
reload: false,
|
||||||
|
associateVal: ["ssa.ux.easiAssistant.notDisplay"],
|
||||||
|
auraIf: () => true,
|
||||||
|
defaultValue: false,
|
||||||
|
auraDisable: () => {
|
||||||
|
if (global.__HUGO_AURA_CONFIG__.ssa.ux.easiAssistant.notDisplay) {
|
||||||
|
return { value: true, tooltip: '禁用 "隐藏管家助手" 以继续' };
|
||||||
|
} else {
|
||||||
|
return { value: false };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
valueGetter: () => {
|
||||||
|
return global.__HUGO_AURA_CONFIG__.ssa.ux.easiAssistant.autoHide;
|
||||||
|
},
|
||||||
|
callbackFn: (newVal) => {
|
||||||
|
if (typeof newVal !== "boolean") return;
|
||||||
|
global.__HUGO_AURA_CONFIG__.ssa.ux.easiAssistant.autoHide = newVal;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 1,
|
||||||
|
id: "notDisplayEasiAssistant",
|
||||||
|
type: "switch",
|
||||||
|
name: "隐藏管家助手",
|
||||||
|
description: "管家启动后, 管家助手窗口将不再显示",
|
||||||
|
restart: true,
|
||||||
|
reload: false,
|
||||||
|
associateVal: ["ssa.ux.easiAssistant.autoHide"],
|
||||||
|
auraIf: () => true,
|
||||||
|
defaultValue: false,
|
||||||
|
auraDisable: () => {
|
||||||
|
if (global.__HUGO_AURA_CONFIG__.ssa.ux.easiAssistant.autoHide) {
|
||||||
|
return { value: true, tooltip: '禁用 "自动最小化管家助手" 以继续' };
|
||||||
|
} else {
|
||||||
|
return { value: false };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
valueGetter: () => {
|
||||||
|
return global.__HUGO_AURA_CONFIG__.ssa.ux.easiAssistant.notDisplay;
|
||||||
|
},
|
||||||
|
callbackFn: (newVal) => {
|
||||||
|
if (typeof newVal !== "boolean") return;
|
||||||
|
global.__HUGO_AURA_CONFIG__.ssa.ux.easiAssistant.notDisplay = newVal;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
categoryName: "U 盘提示",
|
||||||
|
child: [
|
||||||
|
{
|
||||||
|
index: 0,
|
||||||
|
id: "switchUsbInsertPromptButton",
|
||||||
|
type: "switch",
|
||||||
|
name: '隐藏 U 盘插入提示悬浮窗的 "开始查杀" 按钮',
|
||||||
|
description: '启用后, "打开 U 盘" 将成为悬浮窗中的 Primary 按钮',
|
||||||
|
restart: true,
|
||||||
|
reload: false,
|
||||||
|
associateVal: [
|
||||||
|
"networkRewrite.appearance/switchUsbInsertPromptBtn.enabled",
|
||||||
|
],
|
||||||
|
auraIf: () => true,
|
||||||
|
defaultValue: false,
|
||||||
|
auraDisable: () => {
|
||||||
|
if (
|
||||||
|
global.__HUGO_AURA_CONFIG__.networkRewrite[
|
||||||
|
"appearance/switchUsbInsertPromptBtn"
|
||||||
|
].mode === "hide" &&
|
||||||
|
global.__HUGO_AURA_CONFIG__.networkRewrite[
|
||||||
|
"appearance/switchUsbInsertPromptBtn"
|
||||||
|
].enabled
|
||||||
|
) {
|
||||||
|
return { value: true, tooltip: '禁用 "隐藏 U 盘插入提示" 以继续' };
|
||||||
|
} else {
|
||||||
|
return { value: false };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
valueGetter: () => {
|
||||||
|
return (
|
||||||
|
global.__HUGO_AURA_CONFIG__.networkRewrite[
|
||||||
|
"appearance/switchUsbInsertPromptBtn"
|
||||||
|
].mode === "switch" &&
|
||||||
|
global.__HUGO_AURA_CONFIG__.networkRewrite[
|
||||||
|
"appearance/switchUsbInsertPromptBtn"
|
||||||
|
].enabled
|
||||||
|
);
|
||||||
|
},
|
||||||
|
callbackFn: (newVal) => {
|
||||||
|
if (typeof newVal !== "boolean") return;
|
||||||
|
if (newVal === true) {
|
||||||
|
global.__HUGO_AURA_CONFIG__.networkRewrite[
|
||||||
|
"appearance/switchUsbInsertPromptBtn"
|
||||||
|
].mode = "switch";
|
||||||
|
}
|
||||||
|
global.__HUGO_AURA_CONFIG__.networkRewrite[
|
||||||
|
"appearance/switchUsbInsertPromptBtn"
|
||||||
|
].enabled = newVal;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 1,
|
||||||
|
id: "hideUsbInsertPrompt",
|
||||||
|
type: "switch",
|
||||||
|
name: "隐藏 U 盘插入提示",
|
||||||
|
description: "启用后, 插入 U 盘将不再显示悬浮窗",
|
||||||
|
restart: true,
|
||||||
|
reload: false,
|
||||||
|
associateVal: [
|
||||||
|
"networkRewrite.appearance/switchUsbInsertPromptBtn.enabled",
|
||||||
|
],
|
||||||
|
auraIf: () => true,
|
||||||
|
defaultValue: false,
|
||||||
|
auraDisable: () => {
|
||||||
|
if (
|
||||||
|
global.__HUGO_AURA_CONFIG__.networkRewrite[
|
||||||
|
"appearance/switchUsbInsertPromptBtn"
|
||||||
|
].mode === "switch" &&
|
||||||
|
global.__HUGO_AURA_CONFIG__.networkRewrite[
|
||||||
|
"appearance/switchUsbInsertPromptBtn"
|
||||||
|
].enabled
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
value: true,
|
||||||
|
tooltip:
|
||||||
|
'禁用 "隐藏 U 盘插入提示悬浮窗的 "开始查杀" 按钮" 以继续',
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return { value: false };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
valueGetter: () => {
|
||||||
|
return (
|
||||||
|
global.__HUGO_AURA_CONFIG__.networkRewrite[
|
||||||
|
"appearance/switchUsbInsertPromptBtn"
|
||||||
|
].mode === "hide" &&
|
||||||
|
global.__HUGO_AURA_CONFIG__.networkRewrite[
|
||||||
|
"appearance/switchUsbInsertPromptBtn"
|
||||||
|
].enabled
|
||||||
|
);
|
||||||
|
},
|
||||||
|
callbackFn: (newVal) => {
|
||||||
|
if (typeof newVal !== "boolean") return;
|
||||||
|
if (newVal === true) {
|
||||||
|
global.__HUGO_AURA_CONFIG__.networkRewrite[
|
||||||
|
"appearance/switchUsbInsertPromptBtn"
|
||||||
|
].mode = "hide";
|
||||||
|
}
|
||||||
|
global.__HUGO_AURA_CONFIG__.networkRewrite[
|
||||||
|
"appearance/switchUsbInsertPromptBtn"
|
||||||
|
].enabled = newVal;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
categoryName: "广告拦截",
|
||||||
|
child: [
|
||||||
|
{
|
||||||
|
index: 0,
|
||||||
|
id: "banAdBlockPrompt",
|
||||||
|
type: "switch",
|
||||||
|
name: "隐藏广告拦截悬浮窗",
|
||||||
|
description: "启用后, 管家检测到未拦截广告弹窗时, 将不会再显示悬浮窗",
|
||||||
|
restart: true,
|
||||||
|
reload: false,
|
||||||
|
warning: true,
|
||||||
|
warningContent:
|
||||||
|
'此功能不会完全禁用 "广告拦截" 功能, 已被拦截的广告弹窗依然会被拦截。如果您希望彻底禁用广告拦截, 请参阅 Aikari 的相关设置项 (WIP)',
|
||||||
|
associateVal: [],
|
||||||
|
auraIf: () => true,
|
||||||
|
defaultValue: false,
|
||||||
|
valueGetter: () => {
|
||||||
|
return global.__HUGO_AURA_CONFIG__.networkRewrite[
|
||||||
|
"appearance/banAdBlockPrompt"
|
||||||
|
].enabled;
|
||||||
|
},
|
||||||
|
callbackFn: (newVal) => {
|
||||||
|
if (typeof newVal !== "boolean") return;
|
||||||
|
global.__HUGO_AURA_CONFIG__.networkRewrite[
|
||||||
|
"appearance/banAdBlockPrompt"
|
||||||
|
].enabled = newVal;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
module.exports = { uxAndAppearanceSettings };
|
||||||
@@ -17,6 +17,20 @@
|
|||||||
Aura 设置
|
Aura 设置
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<button
|
||||||
|
class="nav-link"
|
||||||
|
id="debug-subpage-tab"
|
||||||
|
data-bs-toggle="pill"
|
||||||
|
data-bs-target="#debug-subpage"
|
||||||
|
type="button"
|
||||||
|
role="tab"
|
||||||
|
aria-controls="debug-subpage"
|
||||||
|
aria-selected="false"
|
||||||
|
>
|
||||||
|
调试选项
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<button
|
<button
|
||||||
class="nav-link"
|
class="nav-link"
|
||||||
@@ -26,7 +40,7 @@
|
|||||||
type="button"
|
type="button"
|
||||||
role="tab"
|
role="tab"
|
||||||
aria-controls="about-subpage"
|
aria-controls="about-subpage"
|
||||||
aria-selected="true"
|
aria-selected="false"
|
||||||
>
|
>
|
||||||
关于项目
|
关于项目
|
||||||
</button>
|
</button>
|
||||||
@@ -39,6 +53,12 @@
|
|||||||
role="tabpanel"
|
role="tabpanel"
|
||||||
aria-labelledby="aura-subpage-tab"
|
aria-labelledby="aura-subpage-tab"
|
||||||
></div>
|
></div>
|
||||||
|
<div
|
||||||
|
class="tab-pane fade"
|
||||||
|
id="debug-subpage"
|
||||||
|
role="tabpanel"
|
||||||
|
aria-labelledby="debug-subpage-tab"
|
||||||
|
></div>
|
||||||
<div
|
<div
|
||||||
class="tab-pane fade"
|
class="tab-pane fade"
|
||||||
id="about-subpage"
|
id="about-subpage"
|
||||||
|
|||||||
@@ -5,13 +5,21 @@
|
|||||||
settingsRenderer,
|
settingsRenderer,
|
||||||
} = require("../../aura/ui/composables/settingsRenderer");
|
} = require("../../aura/ui/composables/settingsRenderer");
|
||||||
const { auraSettings } = require(`${pathBase}/aura`);
|
const { auraSettings } = require(`${pathBase}/aura`);
|
||||||
|
const { debugSettings } = require(`${pathBase}/debug`);
|
||||||
|
|
||||||
const initAuraSubPage = () => {
|
const initAuraSubPage = () => {
|
||||||
const auraSettingsSubPageEl = document.getElementById("aura-subpage");
|
const auraSettingsSubPageEl = document.getElementById("aura-subpage");
|
||||||
settingsRenderer(auraSettingsSubPageEl, auraSettings);
|
settingsRenderer(auraSettingsSubPageEl, auraSettings);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const initDebugSubPage = () => {
|
||||||
|
const debugSubPageEl = document.getElementById("debug-subpage");
|
||||||
|
settingsRenderer(debugSubPageEl, debugSettings);
|
||||||
|
};
|
||||||
|
|
||||||
const onMounted = () => {
|
const onMounted = () => {
|
||||||
initAuraSubPage();
|
initAuraSubPage();
|
||||||
|
initDebugSubPage();
|
||||||
|
|
||||||
const rootEl = document.getElementById("acs-preferences-root-el");
|
const rootEl = document.getElementById("acs-preferences-root-el");
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|||||||
@@ -142,6 +142,10 @@ const functions = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.config.resetAuthDialogInputElOnSubmit(
|
||||||
|
verifyPassword
|
||||||
|
);
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
acpDialogConfirmBtnEl.onclick = verifyPassword;
|
acpDialogConfirmBtnEl.onclick = verifyPassword;
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@@ -441,6 +445,35 @@ const auraSettings = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
categoryName: "外观",
|
||||||
|
child: [
|
||||||
|
{
|
||||||
|
index: 0,
|
||||||
|
id: "actionBtnsOnRight",
|
||||||
|
type: "switch",
|
||||||
|
name: "顶栏操作类按钮右置",
|
||||||
|
description: "启用后, 顶栏的<b>返回首页按钮</b>将靠右放置",
|
||||||
|
restart: false,
|
||||||
|
reload: false,
|
||||||
|
auraIf: () => {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
defaultValue: false,
|
||||||
|
valueGetter: () => {
|
||||||
|
return global.__HUGO_AURA_CONFIG__.auraSettings.appearance.appBar
|
||||||
|
.actionBtnsOnRight;
|
||||||
|
},
|
||||||
|
callbackFn: async (newVal) => {
|
||||||
|
if (typeof newVal !== "boolean") return;
|
||||||
|
global.__HUGO_AURA_CONFIG__.auraSettings.appearance.appBar.actionBtnsOnRight =
|
||||||
|
newVal;
|
||||||
|
global.__HUGO_AURA_UI_FUNCTIONS__.config.initCustomUIProps(true);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
module.exports = { auraSettings };
|
module.exports = { auraSettings };
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
const IPC_METHOD_BASE = "$aura.debug";
|
||||||
|
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
const debugSettings = [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
categoryName: "日志与输出",
|
||||||
|
child: [
|
||||||
|
{
|
||||||
|
index: 0,
|
||||||
|
id: "openHugoAuraLogDir",
|
||||||
|
type: "button",
|
||||||
|
style: "outline",
|
||||||
|
name: "HugoAura 日志目录",
|
||||||
|
description: "",
|
||||||
|
restart: false,
|
||||||
|
reload: false,
|
||||||
|
associateVal: null,
|
||||||
|
auraIf: () => true,
|
||||||
|
buttonContent: "打开",
|
||||||
|
valueGetter: async () => {
|
||||||
|
if (
|
||||||
|
global.__HUGO_AURA__.auraDir &&
|
||||||
|
global.__HUGO_AURA__.auraDir !== ""
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
"目录位置: " + path.join(global.__HUGO_AURA__.auraDir, "logs")
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return "未能获取日志目录位置";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
callbackFn: async (event) => {
|
||||||
|
const childProc = require("child_process");
|
||||||
|
childProc.spawn(`explorer.exe`, [
|
||||||
|
`${path.join(global.__HUGO_AURA__.auraDir, "logs")}`,
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
module.exports = { debugSettings };
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
transition: opacity 0.25s;
|
transition: opacity 0.25s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.aura-header-icon.aura-header-icon-hidden {
|
#root.aura-header-icon-hidden .aura-header-icon {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,15 +9,19 @@ global.__HUGO_AURA_UI_FUNCTIONS__.headerIcon = {
|
|||||||
let clickCounter = 0;
|
let clickCounter = 0;
|
||||||
let clickTimeout = null;
|
let clickTimeout = null;
|
||||||
|
|
||||||
const onMounted = () => {
|
const onMounted = (revive = false) => {
|
||||||
if (!global.__HUGO_AURA_CONFIG__.auraSettings.uiAccessMethod.showEntryIcon) {
|
if (
|
||||||
const iconEl = document.getElementsByClassName("aura-header-icon")[0];
|
!global.__HUGO_AURA_CONFIG__.auraSettings.uiAccessMethod.showEntryIcon &&
|
||||||
iconEl.classList.add("aura-header-icon-hidden");
|
!revive
|
||||||
|
) {
|
||||||
|
const rootEl = document.getElementById("root");
|
||||||
|
rootEl.classList.add("aura-header-icon-hidden");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
global.__HUGO_AURA_CONFIG__.auraSettings.uiAccessMethod
|
global.__HUGO_AURA_CONFIG__.auraSettings.uiAccessMethod
|
||||||
.fallbackAccessMethods.hotkey
|
.fallbackAccessMethods.hotkey &&
|
||||||
|
!revive
|
||||||
) {
|
) {
|
||||||
document.addEventListener("keydown", (event) => {
|
document.addEventListener("keydown", (event) => {
|
||||||
if (event.ctrlKey && event.shiftKey && event.key === "A") {
|
if (event.ctrlKey && event.shiftKey && event.key === "A") {
|
||||||
@@ -51,4 +55,11 @@ global.__HUGO_AURA_UI_FUNCTIONS__.headerIcon = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onMounted();
|
onMounted();
|
||||||
|
|
||||||
|
document.addEventListener(
|
||||||
|
"onLoaderElRevive:Aura.UI.Assistant.HeaderEntry",
|
||||||
|
() => {
|
||||||
|
onMounted(true);
|
||||||
|
}
|
||||||
|
);
|
||||||
})();
|
})();
|
||||||
|
|||||||
19
src/aura/ui/pages/windows/auraWsKeepAlive/index.html
Normal file
19
src/aura/ui/pages/windows/auraWsKeepAlive/index.html
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Aura WebSocket KeepAlive Window</title>
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
opacity: 0;
|
||||||
|
display: none;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
let global = window;
|
||||||
|
</script>
|
||||||
|
<script src="../../../js/global.js"></script>
|
||||||
|
<script src="../../../js/aikariConnectionManager.js"></script>
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
</html>
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
// @ts-check
|
|
||||||
|
|
||||||
const IPC_METHOD_BASE = "$aura.pls";
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {PLSPush} parsedWsMsg
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
const basicRouteHandler = (parsedWsMsg) => {
|
|
||||||
const target = parsedWsMsg.type.split(".").slice(-1)[0];
|
|
||||||
switch (target) {
|
|
||||||
case "pushPlsInfo":
|
|
||||||
if (global.__HUGO_AURA__.plsStats) {
|
|
||||||
global.__HUGO_AURA__.plsStats.status = parsedWsMsg.data.status;
|
|
||||||
global.__HUGO_AURA__.plsStats.version = parsedWsMsg.data.version;
|
|
||||||
}
|
|
||||||
|
|
||||||
global.ipcRenderer.invoke(
|
|
||||||
`${IPC_METHOD_BASE}.updatePlsStats`,
|
|
||||||
global.__HUGO_AURA__.plsStats
|
|
||||||
);
|
|
||||||
|
|
||||||
console.debug(
|
|
||||||
"[HugoAura / UI / PLS Routes / DEBUG] Updated plsStats basic info:",
|
|
||||||
global.__HUGO_AURA__.plsStats
|
|
||||||
);
|
|
||||||
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:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = { basicRouteHandler };
|
|
||||||
BIN
src/aura/ui/static/aikari_color_reversed.png
Normal file
BIN
src/aura/ui/static/aikari_color_reversed.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 21 KiB |
40
src/aura/utils/pls.js
Normal file
40
src/aura/utils/pls.js
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Electron} electron
|
||||||
|
*/
|
||||||
|
const createWsWindow = (electron) => {
|
||||||
|
const path = require("path");
|
||||||
|
const { BrowserWindow } = electron;
|
||||||
|
const window = new BrowserWindow({
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
frame: false,
|
||||||
|
skipTaskbar: true,
|
||||||
|
transparent: true,
|
||||||
|
alwaysOnTop: false,
|
||||||
|
webPreferences: {
|
||||||
|
nodeIntegration: true,
|
||||||
|
contextIsolation: false,
|
||||||
|
devTools: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
window.setIgnoreMouseEvents(true);
|
||||||
|
window.minimize();
|
||||||
|
window.loadFile(
|
||||||
|
path.join(
|
||||||
|
__dirname,
|
||||||
|
"..",
|
||||||
|
"ui",
|
||||||
|
"pages",
|
||||||
|
"windows",
|
||||||
|
"auraWsKeepAlive",
|
||||||
|
"index.html"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return window;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = { createWsWindow };
|
||||||
5
src/aura/utils/string.js
Normal file
5
src/aura/utils/string.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
const checkIfNonAscii = (str) => {
|
||||||
|
return Buffer.byteLength(str) !== str.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = { checkIfNonAscii };
|
||||||
@@ -6,6 +6,7 @@ if (!global.__HUGO_AURA__) {
|
|||||||
configInit: false,
|
configInit: false,
|
||||||
central: () => {},
|
central: () => {},
|
||||||
ipcInit: false,
|
ipcInit: false,
|
||||||
|
auraDir: "",
|
||||||
plsStats: null,
|
plsStats: null,
|
||||||
plsSettings: null,
|
plsSettings: null,
|
||||||
plsRules: null,
|
plsRules: null,
|
||||||
@@ -24,9 +25,9 @@ if (!global.__HUGO_AURA_API__) {
|
|||||||
"https://api-aura.asaka.site",
|
"https://api-aura.asaka.site",
|
||||||
"https://api.hugoaura.dpdns.org",
|
"https://api.hugoaura.dpdns.org",
|
||||||
"https://api-aura-projekts.minorice.moe",
|
"https://api-aura-projekts.minorice.moe",
|
||||||
"https://api.aura.vim.moe"
|
"https://api.aura.vim.moe",
|
||||||
],
|
],
|
||||||
plsUpdate: "/api/getPLSLatestVersion",
|
aikariUpdate: "/api/getAikariLatestVersion",
|
||||||
auraUpdate: "/api/getAuraLatestVersion",
|
auraUpdate: "/api/getAuraLatestVersion",
|
||||||
};
|
};
|
||||||
global.__HUGO_AURA_API__ = __HUGO_AURA_API__;
|
global.__HUGO_AURA_API__ = __HUGO_AURA_API__;
|
||||||
@@ -36,15 +37,55 @@ if (!global.__HUGO_AURA_CONFIG__) {
|
|||||||
global.__HUGO_AURA_CONFIG__ = {};
|
global.__HUGO_AURA_CONFIG__ = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const path = require("path");
|
||||||
|
const os = require("os");
|
||||||
|
|
||||||
const MainProcessHooksManager = require("../aura/init/main/windowHooksManager");
|
const MainProcessHooksManager = require("../aura/init/main/windowHooksManager");
|
||||||
const RendererHooksManager = require("../aura/init/rendererHook/uiHooksManager");
|
const RendererHooksManager = require("../aura/init/rendererHook/uiHooksManager");
|
||||||
const EventBus = require("../aura/utils/eventBus");
|
const EventBus = require("../aura/utils/eventBus");
|
||||||
const NetworkHook = require("../aura/init/rendererHook/networkHook");
|
const NetworkHook = require("../aura/init/rendererHook/networkHook");
|
||||||
const ConfigManager = require("../aura/init/shared/configManager");
|
const ConfigManager = require("../aura/init/shared/configManager");
|
||||||
|
const RegistryManager = require("../aura/init/shared/registryManager");
|
||||||
const { buildIpcMain } = require("../aura/init/main/ipcHandler");
|
const { buildIpcMain } = require("../aura/init/main/ipcHandler");
|
||||||
|
const plsUtils = require("../aura/utils/pls");
|
||||||
|
const stringUtils = require("../aura/utils/string");
|
||||||
|
|
||||||
const { initLogger } = require("../aura/init/main/logger");
|
const { initLogger } = require("../aura/init/main/logger");
|
||||||
|
|
||||||
|
const getUserDocumentsDirPath = () => {
|
||||||
|
const registryManager = new RegistryManager();
|
||||||
|
const pathInfo = registryManager.readRegKeySync(
|
||||||
|
'"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders"',
|
||||||
|
"Personal",
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
/REG_EXPAND_SZ\s+(.+)/
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
if (pathInfo.success && pathInfo.data) {
|
||||||
|
const resolvedPath = pathInfo.data.replace(
|
||||||
|
/%([^%]+)%/g,
|
||||||
|
(match, varName) => {
|
||||||
|
return process.env[varName] || match;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (stringUtils.checkIfNonAscii(resolvedPath)) {
|
||||||
|
console.warn("[HugoAura / Init] Detected non-ASCII char in resolved user personal folder: ", resolvedPath);
|
||||||
|
throw new Error("Non-ASCII char detected");
|
||||||
|
}
|
||||||
|
return resolvedPath;
|
||||||
|
} else {
|
||||||
|
throw new Error("Registry data failed to get");
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[HugoAura / Init / Logger] Failed to get the path of documents dir, using default val. | Error: ", err
|
||||||
|
);
|
||||||
|
return path.join(os.homedir(), "Documents");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {import("../aura/types/main/core").LauncherArgs} param0
|
* @param {import("../aura/types/main/core").LauncherArgs} param0
|
||||||
@@ -66,6 +107,11 @@ const launcher = ({ central, windowName, config }) => {
|
|||||||
app.exit(0);
|
app.exit(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
global.__HUGO_AURA__.auraDir = path.join(
|
||||||
|
getUserDocumentsDirPath(),
|
||||||
|
"HugoAura"
|
||||||
|
);
|
||||||
|
|
||||||
// >>> Init Logger <<< //
|
// >>> Init Logger <<< //
|
||||||
initLogger(windowName);
|
initLogger(windowName);
|
||||||
|
|
||||||
@@ -79,6 +125,7 @@ const launcher = ({ central, windowName, config }) => {
|
|||||||
// >>> Init Config <<< //
|
// >>> Init Config <<< //
|
||||||
const configManager = new ConfigManager();
|
const configManager = new ConfigManager();
|
||||||
configManager.side = "main";
|
configManager.side = "main";
|
||||||
|
configManager.migrateOldConfigFile();
|
||||||
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;
|
||||||
@@ -112,6 +159,13 @@ const launcher = ({ central, windowName, config }) => {
|
|||||||
config.canOpenDevTool = true;
|
config.canOpenDevTool = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// >>> Create WebSocket KeepAlive Window <<< //
|
||||||
|
if (!global.__HUGO_AURA__.hookedWindows?.has("auraWsKeepAlive")) {
|
||||||
|
const wsKaWin = plsUtils.createWsWindow(electron);
|
||||||
|
// @ts-expect-error
|
||||||
|
global.__HUGO_AURA__.hookedWindows.set("auraWsKeepAlive", wsKaWin);
|
||||||
|
}
|
||||||
|
|
||||||
// >>> Listeners <<< //
|
// >>> Listeners <<< //
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
const __AURA_VERSION__ = "0.1.1-pre-IV";
|
const __AURA_VERSION__ = "0.2.0-rc1-p3";
|
||||||
|
|
||||||
(() => {
|
(() => {
|
||||||
if (require.main) return; // 如果只是导入 Aura Version, 不运行闭包逻辑
|
if (require.main) return; // 如果只是导入 Aura Version, 不运行闭包逻辑
|
||||||
|
|
||||||
|
const auraDir = require("electron").ipcRenderer.sendSync(
|
||||||
|
"$aura.base.getAuraDirSync"
|
||||||
|
);
|
||||||
|
|
||||||
// >>> Init Global Vars <<< //
|
// >>> Init Global Vars <<< //
|
||||||
if (!global.__HUGO_AURA__) {
|
if (!global.__HUGO_AURA__) {
|
||||||
global.__HUGO_AURA__ = {
|
global.__HUGO_AURA__ = {
|
||||||
|
auraDir: auraDir.data,
|
||||||
configInit: true, // preload 始终比 hook 晚, 默认 config 已初始化
|
configInit: true, // preload 始终比 hook 晚, 默认 config 已初始化
|
||||||
// ↑ 保留此参数的目的 -> 用于 configManager 中, configManager 的行为在 Renderer 和 Main 中是一致的
|
// ↑ 保留此参数的目的 -> 用于 configManager 中, configManager 的行为在 Renderer 和 Main 中是一致的
|
||||||
version: __AURA_VERSION__,
|
version: __AURA_VERSION__,
|
||||||
|
|||||||
Reference in New Issue
Block a user