Bump release version and snapshot startup state
This commit is contained in:
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "proxywarden",
|
"name": "proxywarden",
|
||||||
"version": "0.1.0",
|
"version": "1.0.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "proxywarden",
|
"name": "proxywarden",
|
||||||
"version": "0.1.0",
|
"version": "1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource-variable/jetbrains-mono": "^5.2.8",
|
"@fontsource-variable/jetbrains-mono": "^5.2.8",
|
||||||
"@tauri-apps/api": "^2.0.0",
|
"@tauri-apps/api": "^2.0.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "proxywarden",
|
"name": "proxywarden",
|
||||||
"version": "0.1.0",
|
"version": "1.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Standalone Windows desktop proxy management app for ProxyWarden.",
|
"description": "Standalone Windows desktop proxy management app for ProxyWarden.",
|
||||||
|
|||||||
@@ -353,13 +353,12 @@ function New-ReleaseDirectory {
|
|||||||
|
|
||||||
$releaseDir = Join-Path $root "proxywarden-v$TargetVersion"
|
$releaseDir = Join-Path $root "proxywarden-v$TargetVersion"
|
||||||
|
|
||||||
if ((Test-Path -LiteralPath $releaseDir) -and $Force) {
|
if (Test-Path -LiteralPath $releaseDir) {
|
||||||
if (-not (Test-IsSubPath -Parent $root -Child $releaseDir)) {
|
if (-not (Test-IsSubPath -Parent $root -Child $releaseDir)) {
|
||||||
throw "Refusing to remove release directory outside OutputRoot: $releaseDir"
|
throw "Refusing to remove release directory outside OutputRoot: $releaseDir"
|
||||||
}
|
}
|
||||||
|
Write-Host "Replacing existing release directory: $releaseDir"
|
||||||
Remove-Item -LiteralPath $releaseDir -Recurse -Force
|
Remove-Item -LiteralPath $releaseDir -Recurse -Force
|
||||||
} elseif (Test-Path -LiteralPath $releaseDir) {
|
|
||||||
throw "Release directory already exists: $releaseDir. Use -Force to replace it."
|
|
||||||
}
|
}
|
||||||
|
|
||||||
New-Item -ItemType Directory -Path (Join-Path $releaseDir "artifacts") -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $releaseDir "artifacts") -Force | Out-Null
|
||||||
@@ -409,10 +408,6 @@ function Invoke-ReleaseBuild {
|
|||||||
function Copy-ReleaseArtifacts {
|
function Copy-ReleaseArtifacts {
|
||||||
param([string]$ReleaseDir)
|
param([string]$ReleaseDir)
|
||||||
|
|
||||||
if ($SkipBuild) {
|
|
||||||
return @()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (-not (Test-Path -LiteralPath $BundleRoot)) {
|
if (-not (Test-Path -LiteralPath $BundleRoot)) {
|
||||||
throw "Tauri bundle output was not found: $BundleRoot"
|
throw "Tauri bundle output was not found: $BundleRoot"
|
||||||
}
|
}
|
||||||
|
|||||||
2
src-tauri/Cargo.lock
generated
2
src-tauri/Cargo.lock
generated
@@ -2314,7 +2314,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proxywarden"
|
name = "proxywarden"
|
||||||
version = "0.1.0"
|
version = "1.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"reqwest 0.12.28",
|
"reqwest 0.12.28",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "proxywarden"
|
name = "proxywarden"
|
||||||
version = "0.1.0"
|
version = "1.0.0"
|
||||||
description = "Standalone Windows desktop proxy management app for ProxyWarden."
|
description = "Standalone Windows desktop proxy management app for ProxyWarden."
|
||||||
authors = ["ProxyWarden"]
|
authors = ["ProxyWarden"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use crate::models::{LocalSingBoxConfig, SubscriptionCache};
|
use crate::models::{LocalSingBoxConfig, SubscriptionCache};
|
||||||
|
use crate::process::command_no_window;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
use std::{
|
use std::{
|
||||||
env, fs,
|
env, fs,
|
||||||
path::Path,
|
path::Path,
|
||||||
process::Command,
|
|
||||||
time::{SystemTime, UNIX_EPOCH},
|
time::{SystemTime, UNIX_EPOCH},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -215,7 +215,7 @@ impl SingBoxConfigChecker for SingBoxCommandChecker {
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let output = Command::new(binary_path)
|
let output = command_no_window(binary_path)
|
||||||
.arg("check")
|
.arg("check")
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
.arg(&config_path)
|
.arg(&config_path)
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ use crate::models::{
|
|||||||
Profile, ProfileInput, ProfileItem, ProfileItemInput, ProfileItemType, Protocol, ProxyProtocol,
|
Profile, ProfileInput, ProfileItem, ProfileItemInput, ProfileItemType, Protocol, ProxyProtocol,
|
||||||
SubscriptionCache, SubscriptionServer, Target, TargetInput, TargetKind,
|
SubscriptionCache, SubscriptionServer, Target, TargetInput, TargetKind,
|
||||||
};
|
};
|
||||||
|
use crate::process::command_no_window;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use crate::proxifyre::{ProxiFyreAdapter, ProxiFyreConfig, ProxiFyreProxy};
|
use crate::proxifyre::{ProxiFyreAdapter, ProxiFyreConfig, ProxiFyreProxy};
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -185,6 +186,17 @@ pub struct SavedStateResponse {
|
|||||||
pub generated_config_path: String,
|
pub generated_config_path: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct StartupSnapshotResponse {
|
||||||
|
pub admin_status: AdminStatusResponse,
|
||||||
|
pub saved_state: SavedStateResponse,
|
||||||
|
pub components: Vec<ComponentStatusDto>,
|
||||||
|
pub proxifyre_setup_status: ProxiFyreSetupStatusDto,
|
||||||
|
pub singbox_status: LocalSingBoxStatusResponse,
|
||||||
|
pub singbox_setup_status: SingBoxSetupStatusDto,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct ProxiFyreSetupStatusDto {
|
pub struct ProxiFyreSetupStatusDto {
|
||||||
@@ -563,6 +575,16 @@ pub fn restart_as_admin(app: tauri::AppHandle) -> Result<(), CommandError> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn get_startup_snapshot(
|
||||||
|
state: tauri::State<'_, CommandState>,
|
||||||
|
) -> Result<StartupSnapshotResponse, CommandError> {
|
||||||
|
let storage = state.storage();
|
||||||
|
tauri::async_runtime::spawn_blocking(move || read_startup_snapshot(&storage))
|
||||||
|
.await
|
||||||
|
.map_err(background_task_error)?
|
||||||
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn get_saved_state(
|
pub fn get_saved_state(
|
||||||
state: tauri::State<'_, CommandState>,
|
state: tauri::State<'_, CommandState>,
|
||||||
@@ -1011,6 +1033,41 @@ pub fn read_components(storage: &JsonStorage) -> Result<Vec<ComponentStatusDto>,
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn read_startup_snapshot(
|
||||||
|
storage: &JsonStorage,
|
||||||
|
) -> Result<StartupSnapshotResponse, CommandError> {
|
||||||
|
let detected_proxyfier = detect_proxyfier_install();
|
||||||
|
let detected_singbox = detect_singbox_install();
|
||||||
|
let saved_state = read_saved_state_with_proxifyre_config(
|
||||||
|
storage,
|
||||||
|
detected_proxyfier
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|detected| detected.config_path.as_deref()),
|
||||||
|
)?;
|
||||||
|
let stored_components = storage.read_components().map_err(storage_error)?;
|
||||||
|
let components = resolve_component_statuses(
|
||||||
|
stored_components,
|
||||||
|
detected_proxyfier.clone(),
|
||||||
|
detected_singbox.clone(),
|
||||||
|
)
|
||||||
|
.iter()
|
||||||
|
.map(ComponentStatusDto::from)
|
||||||
|
.collect();
|
||||||
|
let proxifyre_setup_status =
|
||||||
|
build_proxifyre_setup_status_with_detection(detected_proxyfier.as_ref());
|
||||||
|
let singbox_status = read_singbox_status_with_detection(storage, detected_singbox.as_ref())?;
|
||||||
|
let singbox_setup_status = build_singbox_setup_status(detected_singbox.as_ref());
|
||||||
|
|
||||||
|
Ok(StartupSnapshotResponse {
|
||||||
|
admin_status: admin_status(),
|
||||||
|
saved_state,
|
||||||
|
components,
|
||||||
|
proxifyre_setup_status,
|
||||||
|
singbox_status,
|
||||||
|
singbox_setup_status,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn read_activity(storage: &JsonStorage) -> Result<Vec<ActivityEntryDto>, CommandError> {
|
pub fn read_activity(storage: &JsonStorage) -> Result<Vec<ActivityEntryDto>, CommandError> {
|
||||||
storage
|
storage
|
||||||
.read_activity()
|
.read_activity()
|
||||||
@@ -1315,13 +1372,20 @@ pub fn apply_profiles_with_services(
|
|||||||
|
|
||||||
pub fn read_singbox_status(
|
pub fn read_singbox_status(
|
||||||
storage: &JsonStorage,
|
storage: &JsonStorage,
|
||||||
|
) -> Result<LocalSingBoxStatusResponse, CommandError> {
|
||||||
|
let detected = detect_singbox_install();
|
||||||
|
read_singbox_status_with_detection(storage, detected.as_ref())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_singbox_status_with_detection(
|
||||||
|
storage: &JsonStorage,
|
||||||
|
detected: Option<&DetectedSingBox>,
|
||||||
) -> Result<LocalSingBoxStatusResponse, CommandError> {
|
) -> Result<LocalSingBoxStatusResponse, CommandError> {
|
||||||
let config = storage.read_local_singbox_config().map_err(storage_error)?;
|
let config = storage.read_local_singbox_config().map_err(storage_error)?;
|
||||||
let cache = storage
|
let cache = storage
|
||||||
.read_singbox_subscription_cache()
|
.read_singbox_subscription_cache()
|
||||||
.map_err(storage_error)?;
|
.map_err(storage_error)?;
|
||||||
let detected = detect_singbox_install();
|
let component = singbox_component_from_detection(detected);
|
||||||
let component = singbox_component_from_detection(detected.as_ref());
|
|
||||||
|
|
||||||
Ok(LocalSingBoxStatusResponse {
|
Ok(LocalSingBoxStatusResponse {
|
||||||
config: LocalSingBoxConfigDto::from(&config),
|
config: LocalSingBoxConfigDto::from(&config),
|
||||||
@@ -1968,7 +2032,7 @@ fn control_singbox_service(
|
|||||||
config_source,
|
config_source,
|
||||||
config_target.as_deref(),
|
config_target.as_deref(),
|
||||||
);
|
);
|
||||||
let output = Command::new("powershell")
|
let output = command_no_window("powershell")
|
||||||
.args([
|
.args([
|
||||||
"-NoProfile",
|
"-NoProfile",
|
||||||
"-NonInteractive",
|
"-NonInteractive",
|
||||||
@@ -2824,7 +2888,7 @@ Write-ServiceResult $false 'stop_failed' $status $processId
|
|||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
|
|
||||||
let output = Command::new("powershell")
|
let output = command_no_window("powershell")
|
||||||
.args([
|
.args([
|
||||||
"-NoProfile",
|
"-NoProfile",
|
||||||
"-NonInteractive",
|
"-NonInteractive",
|
||||||
@@ -3086,9 +3150,15 @@ fn uninstall_proxifyre_component() -> Result<ComponentStatusDto, CommandError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn build_proxifyre_setup_status() -> ProxiFyreSetupStatusDto {
|
fn build_proxifyre_setup_status() -> ProxiFyreSetupStatusDto {
|
||||||
|
let proxifyre = detect_proxyfier_install();
|
||||||
|
build_proxifyre_setup_status_with_detection(proxifyre.as_ref())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_proxifyre_setup_status_with_detection(
|
||||||
|
proxifyre: Option<&DetectedProxyfier>,
|
||||||
|
) -> ProxiFyreSetupStatusDto {
|
||||||
let vc_runtime = detect_vc_runtime();
|
let vc_runtime = detect_vc_runtime();
|
||||||
let packet_filter = detect_windows_packet_filter();
|
let packet_filter = detect_windows_packet_filter();
|
||||||
let proxifyre = detect_proxyfier_install();
|
|
||||||
|
|
||||||
let vc_runtime_item = setup_item_from_program(
|
let vc_runtime_item = setup_item_from_program(
|
||||||
"vc-runtime",
|
"vc-runtime",
|
||||||
@@ -3199,7 +3269,7 @@ if ($null -ne $program) {{
|
|||||||
escape_powershell_single(pattern)
|
escape_powershell_single(pattern)
|
||||||
);
|
);
|
||||||
|
|
||||||
let output = Command::new("powershell")
|
let output = command_no_window("powershell")
|
||||||
.args([
|
.args([
|
||||||
"-NoProfile",
|
"-NoProfile",
|
||||||
"-NonInteractive",
|
"-NonInteractive",
|
||||||
@@ -3379,7 +3449,7 @@ fn write_powershell_script(path: &Path, script: &str) -> std::io::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run_powershell_command(script: &str) -> std::io::Result<Output> {
|
fn run_powershell_command(script: &str) -> std::io::Result<Output> {
|
||||||
Command::new("powershell")
|
command_no_window("powershell")
|
||||||
.args([
|
.args([
|
||||||
"-NoProfile",
|
"-NoProfile",
|
||||||
"-NonInteractive",
|
"-NonInteractive",
|
||||||
@@ -3392,7 +3462,7 @@ fn run_powershell_command(script: &str) -> std::io::Result<Output> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run_powershell_file(script_path: &Path) -> std::io::Result<Output> {
|
fn run_powershell_file(script_path: &Path) -> std::io::Result<Output> {
|
||||||
Command::new("powershell")
|
command_no_window("powershell")
|
||||||
.args([
|
.args([
|
||||||
"-NoProfile",
|
"-NoProfile",
|
||||||
"-NonInteractive",
|
"-NonInteractive",
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ use crate::models::{
|
|||||||
ComponentId, ComponentState, ComponentStatus, DEFAULT_LOCAL_SINGBOX_INSTALL_ROOT,
|
ComponentId, ComponentState, ComponentStatus, DEFAULT_LOCAL_SINGBOX_INSTALL_ROOT,
|
||||||
DEFAULT_LOCAL_SINGBOX_SERVICE_NAME,
|
DEFAULT_LOCAL_SINGBOX_SERVICE_NAME,
|
||||||
};
|
};
|
||||||
|
use crate::process::command_no_window;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
process::Command,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
@@ -460,7 +460,7 @@ fn same_path(left: &Path, right: &Path) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn powershell_bool(script: &str) -> bool {
|
fn powershell_bool(script: &str) -> bool {
|
||||||
Command::new("powershell")
|
command_no_window("powershell")
|
||||||
.args(["-NoProfile", "-NonInteractive", "-Command", script])
|
.args(["-NoProfile", "-NonInteractive", "-Command", script])
|
||||||
.output()
|
.output()
|
||||||
.ok()
|
.ok()
|
||||||
@@ -492,7 +492,7 @@ $items |
|
|||||||
ConvertTo-Json -Compress
|
ConvertTo-Json -Compress
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let Ok(output) = Command::new("powershell")
|
let Ok(output) = command_no_window("powershell")
|
||||||
.args(["-NoProfile", "-NonInteractive", "-Command", script])
|
.args(["-NoProfile", "-NonInteractive", "-Command", script])
|
||||||
.output()
|
.output()
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ mod activity;
|
|||||||
mod commands;
|
mod commands;
|
||||||
mod component_detection;
|
mod component_detection;
|
||||||
mod models;
|
mod models;
|
||||||
|
mod process;
|
||||||
mod singbox_service;
|
mod singbox_service;
|
||||||
mod storage;
|
mod storage;
|
||||||
mod subscription;
|
mod subscription;
|
||||||
@@ -38,6 +39,7 @@ fn main() {
|
|||||||
commands::get_status,
|
commands::get_status,
|
||||||
commands::get_admin_status,
|
commands::get_admin_status,
|
||||||
commands::restart_as_admin,
|
commands::restart_as_admin,
|
||||||
|
commands::get_startup_snapshot,
|
||||||
commands::get_profiles,
|
commands::get_profiles,
|
||||||
commands::get_saved_state,
|
commands::get_saved_state,
|
||||||
commands::save_profile,
|
commands::save_profile,
|
||||||
|
|||||||
18
src-tauri/src/process.rs
Normal file
18
src-tauri/src/process.rs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
use std::{ffi::OsStr, process::Command};
|
||||||
|
|
||||||
|
pub fn command_no_window(program: impl AsRef<OsStr>) -> Command {
|
||||||
|
let mut command = Command::new(program);
|
||||||
|
hide_console_window(&mut command);
|
||||||
|
command
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn hide_console_window(command: &mut Command) {
|
||||||
|
use std::os::windows::process::CommandExt;
|
||||||
|
|
||||||
|
const CREATE_NO_WINDOW: u32 = 0x08000000;
|
||||||
|
command.creation_flags(CREATE_NO_WINDOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
fn hide_console_window(_command: &mut Command) {}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "ProxyWarden",
|
"productName": "ProxyWarden",
|
||||||
"version": "0.1.0",
|
"version": "1.0.0",
|
||||||
"identifier": "ru.dokops.proxywarden.windows",
|
"identifier": "ru.dokops.proxywarden.windows",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "npm run dev",
|
"beforeDevCommand": "npm run dev",
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ mod commands;
|
|||||||
mod component_detection;
|
mod component_detection;
|
||||||
#[path = "../src/models.rs"]
|
#[path = "../src/models.rs"]
|
||||||
mod models;
|
mod models;
|
||||||
|
#[path = "../src/process.rs"]
|
||||||
|
mod process;
|
||||||
#[path = "../src/adapters/proxifyre.rs"]
|
#[path = "../src/adapters/proxifyre.rs"]
|
||||||
mod proxifyre;
|
mod proxifyre;
|
||||||
#[path = "../src/adapters/proxy_router.rs"]
|
#[path = "../src/adapters/proxy_router.rs"]
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
mod component_detection;
|
mod component_detection;
|
||||||
#[path = "../src/models.rs"]
|
#[path = "../src/models.rs"]
|
||||||
mod models;
|
mod models;
|
||||||
|
#[path = "../src/process.rs"]
|
||||||
|
mod process;
|
||||||
|
|
||||||
use component_detection::{
|
use component_detection::{
|
||||||
detect_proxyfier_install_with_host, detect_singbox_install_with_host,
|
detect_proxyfier_install_with_host, detect_singbox_install_with_host,
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#[path = "../src/models.rs"]
|
#[path = "../src/models.rs"]
|
||||||
mod models;
|
mod models;
|
||||||
|
#[path = "../src/process.rs"]
|
||||||
|
mod process;
|
||||||
#[path = "../src/adapters/proxifyre.rs"]
|
#[path = "../src/adapters/proxifyre.rs"]
|
||||||
mod proxifyre;
|
mod proxifyre;
|
||||||
#[path = "../src/adapters/proxy_router.rs"]
|
#[path = "../src/adapters/proxy_router.rs"]
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ mod commands;
|
|||||||
mod component_detection;
|
mod component_detection;
|
||||||
#[path = "../src/models.rs"]
|
#[path = "../src/models.rs"]
|
||||||
mod models;
|
mod models;
|
||||||
|
#[path = "../src/process.rs"]
|
||||||
|
mod process;
|
||||||
#[path = "../src/adapters/proxifyre.rs"]
|
#[path = "../src/adapters/proxifyre.rs"]
|
||||||
mod proxifyre;
|
mod proxifyre;
|
||||||
#[path = "../src/adapters/proxy_router.rs"]
|
#[path = "../src/adapters/proxy_router.rs"]
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
mod component_detection;
|
mod component_detection;
|
||||||
#[path = "../src/models.rs"]
|
#[path = "../src/models.rs"]
|
||||||
mod models;
|
mod models;
|
||||||
|
#[path = "../src/process.rs"]
|
||||||
|
mod process;
|
||||||
#[path = "../src/singbox_service.rs"]
|
#[path = "../src/singbox_service.rs"]
|
||||||
mod singbox_service;
|
mod singbox_service;
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,15 @@ export interface SavedStateResponse {
|
|||||||
generatedConfigPath: string;
|
generatedConfigPath: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface StartupSnapshotResponse {
|
||||||
|
adminStatus: AdminStatusResponse;
|
||||||
|
savedState: SavedStateResponse;
|
||||||
|
components: ComponentStatus[];
|
||||||
|
proxifyreSetupStatus: ProxiFyreSetupStatus;
|
||||||
|
singboxStatus: LocalSingBoxStatusResponse;
|
||||||
|
singboxSetupStatus: SingBoxSetupStatus;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ProxiFyreSetupItem {
|
export interface ProxiFyreSetupItem {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
@@ -150,6 +159,10 @@ export function restartAsAdmin(): Promise<void> {
|
|||||||
return invoke<void>('restart_as_admin');
|
return invoke<void>('restart_as_admin');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getStartupSnapshot(): Promise<StartupSnapshotResponse> {
|
||||||
|
return invoke<StartupSnapshotResponse>('get_startup_snapshot');
|
||||||
|
}
|
||||||
|
|
||||||
export function getSavedState(): Promise<SavedStateResponse> {
|
export function getSavedState(): Promise<SavedStateResponse> {
|
||||||
return invoke<SavedStateResponse>('get_saved_state');
|
return invoke<SavedStateResponse>('get_saved_state');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ import {
|
|||||||
fetchSingBoxSubscription,
|
fetchSingBoxSubscription,
|
||||||
forgetSingBoxSubscription,
|
forgetSingBoxSubscription,
|
||||||
generateSingBoxConfig,
|
generateSingBoxConfig,
|
||||||
getAdminStatus,
|
|
||||||
getComponents,
|
getComponents,
|
||||||
getProxiFyreSetupStatus,
|
getProxiFyreSetupStatus,
|
||||||
getSavedState,
|
getSavedState,
|
||||||
getSingBoxSetupStatus,
|
getSingBoxSetupStatus,
|
||||||
getSingBoxStatus,
|
getSingBoxStatus,
|
||||||
|
getStartupSnapshot,
|
||||||
installProxiFyre,
|
installProxiFyre,
|
||||||
installSingBox,
|
installSingBox,
|
||||||
pingAllSingBoxServers,
|
pingAllSingBoxServers,
|
||||||
@@ -268,11 +268,21 @@ export function App() {
|
|||||||
}, [activeLogId]);
|
}, [activeLogId]);
|
||||||
|
|
||||||
async function refresh() {
|
async function refresh() {
|
||||||
void refreshAdminStatus();
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
setIsDetectingComponents(true);
|
||||||
try {
|
try {
|
||||||
const saved = await getSavedState();
|
const snapshot = await getStartupSnapshot();
|
||||||
applySavedState(saved.profiles, saved.targets, saved.generatedConfigPath);
|
setAdminStatus(snapshot.adminStatus);
|
||||||
|
setComponents(snapshot.components);
|
||||||
|
setSetupStatus(snapshot.proxifyreSetupStatus);
|
||||||
|
setSingBoxStatus(snapshot.singboxStatus);
|
||||||
|
setSingBoxSetupStatus(snapshot.singboxSetupStatus);
|
||||||
|
applySavedState(
|
||||||
|
snapshot.savedState.profiles,
|
||||||
|
snapshot.savedState.targets,
|
||||||
|
snapshot.savedState.generatedConfigPath,
|
||||||
|
snapshot.singboxStatus,
|
||||||
|
);
|
||||||
} catch {
|
} catch {
|
||||||
showNotice({
|
showNotice({
|
||||||
kind: 'info',
|
kind: 'info',
|
||||||
@@ -281,17 +291,7 @@ export function App() {
|
|||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
setIsDetectingComponents(false);
|
||||||
|
|
||||||
void refreshComponents();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function refreshAdminStatus() {
|
|
||||||
try {
|
|
||||||
const status = await getAdminStatus();
|
|
||||||
setAdminStatus(status);
|
|
||||||
} catch {
|
|
||||||
setAdminStatus(null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,37 +310,6 @@ export function App() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function refreshComponents() {
|
|
||||||
setIsDetectingComponents(true);
|
|
||||||
try {
|
|
||||||
const [detectedComponents, detectedSetupStatus, detectedSingBoxStatus, detectedSingBoxSetupStatus] = await Promise.all([
|
|
||||||
getComponents(),
|
|
||||||
getProxiFyreSetupStatus(),
|
|
||||||
getSingBoxStatus(),
|
|
||||||
getSingBoxSetupStatus(),
|
|
||||||
]);
|
|
||||||
setComponents(detectedComponents);
|
|
||||||
setSetupStatus(detectedSetupStatus);
|
|
||||||
setSingBoxStatus(detectedSingBoxStatus);
|
|
||||||
setSingBoxSetupStatus(detectedSingBoxSetupStatus);
|
|
||||||
setAppliedSnapshot((current) => {
|
|
||||||
if (!current || current.routeMode !== 'local-singbox' || current.selectedServerTag) return current;
|
|
||||||
return {
|
|
||||||
...current,
|
|
||||||
selectedServerTag: normalizeServerTag(detectedSingBoxStatus.config.selectedServerTag),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
showNotice({
|
|
||||||
kind: 'error',
|
|
||||||
title: 'Компоненты не проверены',
|
|
||||||
text: errorMessage(error),
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
setIsDetectingComponents(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function applySavedState(
|
function applySavedState(
|
||||||
profiles: Profile[],
|
profiles: Profile[],
|
||||||
targets: Target[],
|
targets: Target[],
|
||||||
|
|||||||
Reference in New Issue
Block a user