mirror of
https://github.com/OpenListTeam/OpenList-Desktop.git
synced 2025-11-25 11:18:32 +08:00
feat: optimize service control (#2)
* refactor: remove unused flags from RcloneConfig and related components; update monitoring intervals to use dynamic settings * fix: update auto-launch title to indicate immediate effect * refactor: remove service API token and port from AppConfig and related components * refactor: remove auto_mount property from RcloneConfig and related components * refactor: rename service to OpenList Core and update related components
This commit is contained in:
@@ -1,11 +1,15 @@
|
||||
use crate::core::service::check_service_status as check_service_status_impl;
|
||||
use crate::core::service::install_service as install_service_impl;
|
||||
use crate::core::service::restart_service as restart_service_impl;
|
||||
use crate::core::service::stop_service as stop_service_impl;
|
||||
use crate::core::service::start_service as start_service_impl;
|
||||
|
||||
use crate::core::service::uninstall_service as uninstall_service_impl;
|
||||
use crate::object::structs::AppState;
|
||||
use crate::utils::api::{get_api_key, get_server_port};
|
||||
use reqwest;
|
||||
use tauri::State;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn check_service_status() -> Result<bool, String> {
|
||||
pub async fn check_service_status() -> Result<String, String> {
|
||||
check_service_status_impl().await.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
@@ -20,16 +24,24 @@ pub async fn uninstall_service() -> Result<bool, String> {
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn stop_service() -> Result<bool, String> {
|
||||
stop_service_impl().await.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn restart_service() -> Result<bool, String> {
|
||||
restart_service_impl().await.map_err(|e| e.to_string())
|
||||
pub async fn stop_service(state: State<'_, AppState>) -> Result<bool, String> {
|
||||
let api_key = get_api_key(state);
|
||||
let port = get_server_port();
|
||||
let client = reqwest::Client::new();
|
||||
let response = client
|
||||
.post(format!("http://127.0.0.1:{}/api/v1/service/stop", port))
|
||||
.header("Authorization", format!("Bearer {}", api_key))
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| format!("Failed to send request: {}", e))?;
|
||||
if response.status().is_success() {
|
||||
Ok(true)
|
||||
} else {
|
||||
Err(format!("Failed to stop service: {}", response.status()))
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn start_service() -> Result<bool, String> {
|
||||
check_service_status_impl().await.map_err(|e| e.to_string())
|
||||
start_service_impl().await.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
@@ -4,18 +4,14 @@ use serde::{Deserialize, Serialize};
|
||||
pub struct AppConfig {
|
||||
pub theme: Option<String>,
|
||||
pub monitor_interval: Option<u64>,
|
||||
pub service_api_token: Option<String>,
|
||||
pub service_port: Option<u64>,
|
||||
pub auto_update_enabled: Option<bool>,
|
||||
}
|
||||
|
||||
impl AppConfig {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
theme: Some("zh".into()),
|
||||
theme: Some("light".to_string()),
|
||||
monitor_interval: Some(5),
|
||||
service_api_token: Some("yeM6PCcZGaCpapyBKAbjTp2YAhcku6cUr".into()),
|
||||
service_port: Some(53211),
|
||||
auto_update_enabled: Some(true),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::conf::rclone::RcloneConfig;
|
||||
use crate::{conf::core::OpenListCoreConfig, utils::path::app_config_file_path};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::app::AppConfig;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -25,20 +26,67 @@ impl MergedSettings {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_data_config_path() -> Result<PathBuf, String> {
|
||||
let app_dir = std::env::current_exe()
|
||||
.map_err(|e| format!("Failed to get current exe path: {}", e))?
|
||||
.parent()
|
||||
.ok_or("Failed to get parent directory")?
|
||||
.to_path_buf();
|
||||
Ok(app_dir.join("data").join("config.json"))
|
||||
}
|
||||
|
||||
fn read_data_config() -> Result<serde_json::Value, String> {
|
||||
let path = Self::get_data_config_path()?;
|
||||
if !path.exists() {
|
||||
return Err("data/config.json does not exist".to_string());
|
||||
}
|
||||
|
||||
let content = std::fs::read_to_string(path).map_err(|e| e.to_string())?;
|
||||
serde_json::from_str(&content).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
fn get_port_from_data_config() -> Result<Option<u16>, String> {
|
||||
let config = Self::read_data_config()?;
|
||||
Ok(config
|
||||
.get("scheme")
|
||||
.and_then(|scheme| scheme.get("http_port"))
|
||||
.and_then(|port| port.as_u64())
|
||||
.map(|port| port as u16))
|
||||
}
|
||||
|
||||
pub fn save(&self) -> Result<(), String> {
|
||||
let path = app_config_file_path().map_err(|e| e.to_string())?;
|
||||
std::fs::create_dir_all(path.parent().unwrap()).map_err(|e| e.to_string())?;
|
||||
let json = serde_json::to_string_pretty(self).map_err(|e| e.to_string())?;
|
||||
std::fs::write(&path, json).map_err(|e| e.to_string())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn load() -> Result<Self, String> {
|
||||
let path = app_config_file_path().map_err(|e| e.to_string())?;
|
||||
if !path.exists() {
|
||||
let mut merged_settings = if !path.exists() {
|
||||
std::fs::create_dir_all(path.parent().unwrap()).map_err(|e| e.to_string())?;
|
||||
let new_settings = Self::new();
|
||||
std::fs::write(
|
||||
&path,
|
||||
serde_json::to_string_pretty(&Self::new()).map_err(|e| e.to_string())?,
|
||||
serde_json::to_string_pretty(&new_settings).map_err(|e| e.to_string())?,
|
||||
)
|
||||
.map_err(|e| e.to_string())?;
|
||||
return Ok(Self::new());
|
||||
new_settings
|
||||
} else {
|
||||
let config = std::fs::read_to_string(path).map_err(|e| e.to_string())?;
|
||||
serde_json::from_str(&config).map_err(|e| e.to_string())?
|
||||
};
|
||||
|
||||
if let Ok(data_port) = Self::get_port_from_data_config() {
|
||||
if let Some(port) = data_port {
|
||||
if merged_settings.openlist.port != port {
|
||||
merged_settings.openlist.port = port;
|
||||
merged_settings.save()?;
|
||||
}
|
||||
}
|
||||
}
|
||||
let config = std::fs::read_to_string(path).map_err(|e| e.to_string())?;
|
||||
let merged_settings: MergedSettings =
|
||||
serde_json::from_str(&config).map_err(|e| e.to_string())?;
|
||||
|
||||
Ok(merged_settings)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,6 @@ use serde::{Deserialize, Serialize};
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct RcloneConfig {
|
||||
pub config: serde_json::Value,
|
||||
pub flags: Option<Vec<String>>,
|
||||
pub auto_mount: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
@@ -62,8 +60,6 @@ impl RcloneConfig {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
config: serde_json::Value::Object(Default::default()),
|
||||
flags: None,
|
||||
auto_mount: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,63 +203,8 @@ fn start_service_with_elevation(service_name: &str) -> Result<bool, Box<dyn std:
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub async fn start_service() -> Result<bool, Box<dyn std::error::Error>> {
|
||||
log::info!("Service start not implemented for this platform");
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub async fn install_service() -> Result<bool, Box<dyn std::error::Error>> {
|
||||
let app_dir = env::current_exe()?.parent().unwrap().to_path_buf();
|
||||
let install_path = app_dir.join("install-openlist-service");
|
||||
|
||||
if !install_path.exists() {
|
||||
error!("Service installer not found at {}", install_path.display());
|
||||
return Err(Box::from(format!(
|
||||
"Service installer not found at {}",
|
||||
install_path.display()
|
||||
)));
|
||||
}
|
||||
|
||||
let status = StdCommand::new(&install_path).status()?;
|
||||
|
||||
if status.success() {
|
||||
Ok(true)
|
||||
} else {
|
||||
Err(Box::from(format!(
|
||||
"Failed to install service, exit status: {}",
|
||||
status
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub async fn uninstall_service() -> Result<bool, Box<dyn std::error::Error>> {
|
||||
let app_dir = env::current_exe()?.parent().unwrap().to_path_buf();
|
||||
let uninstall_path = app_dir.join("uninstall-openlist-service");
|
||||
|
||||
if !uninstall_path.exists() {
|
||||
error!("Uninstaller not found: {:?}", uninstall_path);
|
||||
return Err(Box::from(format!(
|
||||
"Uninstaller not found: {:?}",
|
||||
uninstall_path
|
||||
)));
|
||||
}
|
||||
let status = StdCommand::new(&uninstall_path).status()?;
|
||||
|
||||
if status.success() {
|
||||
Ok(true)
|
||||
} else {
|
||||
Err(Box::from(format!(
|
||||
"Failed to uninstall service, exit status: {}",
|
||||
status
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub async fn check_service_status() -> Result<bool, Box<dyn std::error::Error>> {
|
||||
pub async fn start_service() -> Result<bool, Box<dyn std::error::Error>> {
|
||||
use windows_service::service::{ServiceAccess, ServiceState};
|
||||
use windows_service::service_manager::{ServiceManager, ServiceManagerAccess};
|
||||
let service_name = "openlist_desktop_service";
|
||||
@@ -325,7 +270,7 @@ pub async fn check_service_status() -> Result<bool, Box<dyn std::error::Error>>
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub async fn check_service_status() -> Result<bool, Box<dyn std::error::Error>> {
|
||||
pub async fn start_service() -> Result<bool, Box<dyn std::error::Error>> {
|
||||
const SERVICE_NAME: &str = "openlist-desktop-service";
|
||||
|
||||
log::info!("Checking Linux service status for: {}", SERVICE_NAME);
|
||||
@@ -333,42 +278,17 @@ pub async fn check_service_status() -> Result<bool, Box<dyn std::error::Error>>
|
||||
let init_system = detect_linux_init_system();
|
||||
|
||||
match init_system.as_str() {
|
||||
"systemd" => check_systemd_service_status(SERVICE_NAME).await,
|
||||
"openrc" => check_openrc_service_status(SERVICE_NAME).await,
|
||||
"systemd" => start_systemd_service_with_check(SERVICE_NAME).await,
|
||||
"openrc" => start_openrc_service_with_check(SERVICE_NAME).await,
|
||||
_ => {
|
||||
log::warn!("Unknown init system: {}, assuming systemd", init_system);
|
||||
check_systemd_service_status(SERVICE_NAME).await
|
||||
start_systemd_service_with_check(SERVICE_NAME).await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn detect_linux_init_system() -> String {
|
||||
if std::path::Path::new("/run/systemd/system").exists() {
|
||||
return "systemd".to_string();
|
||||
}
|
||||
|
||||
if std::path::Path::new("/run/openrc").exists() {
|
||||
return "openrc".to_string();
|
||||
}
|
||||
|
||||
if let Ok(output) = StdCommand::new("which").arg("systemctl").output() {
|
||||
if output.status.success() && !output.stdout.is_empty() {
|
||||
return "systemd".to_string();
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(output) = StdCommand::new("which").arg("rc-service").output() {
|
||||
if output.status.success() && !output.stdout.is_empty() {
|
||||
return "openrc".to_string();
|
||||
}
|
||||
}
|
||||
|
||||
"systemd".to_string()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
async fn check_systemd_service_status(
|
||||
async fn start_systemd_service_with_check(
|
||||
service_name: &str,
|
||||
) -> Result<bool, Box<dyn std::error::Error>> {
|
||||
log::info!("Checking systemd service status for: {}", service_name);
|
||||
@@ -429,6 +349,249 @@ async fn check_systemd_service_status(
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
async fn start_openrc_service_with_check(
|
||||
service_name: &str,
|
||||
) -> Result<bool, Box<dyn std::error::Error>> {
|
||||
log::info!("Checking OpenRC service status for: {}", service_name);
|
||||
|
||||
let status_output = StdCommand::new("rc-service")
|
||||
.args(&[service_name, "status"])
|
||||
.output();
|
||||
|
||||
match status_output {
|
||||
Ok(output) => {
|
||||
let status_str = String::from_utf8_lossy(&output.stdout).to_lowercase();
|
||||
let stderr_str = String::from_utf8_lossy(&output.stderr).to_lowercase();
|
||||
|
||||
log::info!("OpenRC service status output: {}", status_str);
|
||||
|
||||
if status_str.contains("started") || status_str.contains("running") {
|
||||
log::info!("Service is running");
|
||||
return Ok(true);
|
||||
} else if status_str.contains("stopped") || status_str.contains("inactive") {
|
||||
log::info!("Service is stopped, attempting to start");
|
||||
return start_openrc_service(service_name).await;
|
||||
} else if stderr_str.contains("does not exist") {
|
||||
log::error!("Service {} does not exist", service_name);
|
||||
return Ok(false);
|
||||
} else {
|
||||
log::warn!("Unknown service status, attempting to start");
|
||||
return start_openrc_service(service_name).await;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Failed to check OpenRC service status: {}", e);
|
||||
return start_openrc_service(service_name).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub async fn install_service() -> Result<bool, Box<dyn std::error::Error>> {
|
||||
let app_dir = env::current_exe()?.parent().unwrap().to_path_buf();
|
||||
let install_path = app_dir.join("install-openlist-service");
|
||||
|
||||
if !install_path.exists() {
|
||||
error!("Service installer not found at {}", install_path.display());
|
||||
return Err(Box::from(format!(
|
||||
"Service installer not found at {}",
|
||||
install_path.display()
|
||||
)));
|
||||
}
|
||||
|
||||
let status = StdCommand::new(&install_path).status()?;
|
||||
|
||||
if status.success() {
|
||||
Ok(true)
|
||||
} else {
|
||||
Err(Box::from(format!(
|
||||
"Failed to install service, exit status: {}",
|
||||
status
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub async fn uninstall_service() -> Result<bool, Box<dyn std::error::Error>> {
|
||||
let app_dir = env::current_exe()?.parent().unwrap().to_path_buf();
|
||||
let uninstall_path = app_dir.join("uninstall-openlist-service");
|
||||
|
||||
if !uninstall_path.exists() {
|
||||
error!("Uninstaller not found: {:?}", uninstall_path);
|
||||
return Err(Box::from(format!(
|
||||
"Uninstaller not found: {:?}",
|
||||
uninstall_path
|
||||
)));
|
||||
}
|
||||
let status = StdCommand::new(&uninstall_path).status()?;
|
||||
|
||||
if status.success() {
|
||||
Ok(true)
|
||||
} else {
|
||||
Err(Box::from(format!(
|
||||
"Failed to uninstall service, exit status: {}",
|
||||
status
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub async fn check_service_status() -> Result<String, Box<dyn std::error::Error>> {
|
||||
use windows_service::service::{ServiceAccess, ServiceState};
|
||||
use windows_service::service_manager::{ServiceManager, ServiceManagerAccess};
|
||||
let service_name = "openlist_desktop_service";
|
||||
|
||||
let manager = match ServiceManager::local_computer(
|
||||
None::<&str>,
|
||||
ServiceManagerAccess::CONNECT | ServiceManagerAccess::ENUMERATE_SERVICE,
|
||||
) {
|
||||
Ok(mgr) => mgr,
|
||||
Err(_) => ServiceManager::local_computer(None::<&str>, ServiceManagerAccess::CONNECT)?,
|
||||
};
|
||||
let service = match manager.open_service(service_name, ServiceAccess::QUERY_STATUS) {
|
||||
Ok(svc) => svc,
|
||||
Err(e) => {
|
||||
log::error!("Failed to open service '{}': {:?}", service_name, e);
|
||||
return Ok("not-installed".to_string());
|
||||
}
|
||||
};
|
||||
match service.query_status() {
|
||||
Ok(status) => match status.current_state {
|
||||
ServiceState::Running | ServiceState::StartPending => {
|
||||
return Ok("running".to_string());
|
||||
}
|
||||
ServiceState::StopPending => {
|
||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||
return Ok("stopped".to_string());
|
||||
}
|
||||
_ => {
|
||||
log::info!("Service is in state: {:?}.", status.current_state);
|
||||
return Ok("stopped".to_string());
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!("Failed to query service status: {:?}", e);
|
||||
match start_service_with_elevation(service_name) {
|
||||
Ok(true) => Ok("running".to_string()),
|
||||
Ok(false) => {
|
||||
log::error!("Failed to start service with elevation.");
|
||||
Ok("stopped".to_string())
|
||||
}
|
||||
Err(elev_err) => {
|
||||
log::error!("Error during service elevation: {:?}", elev_err);
|
||||
Ok("error".to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub async fn check_service_status() -> Result<String, Box<dyn std::error::Error>> {
|
||||
const SERVICE_NAME: &str = "openlist-desktop-service";
|
||||
|
||||
log::info!("Checking Linux service status for: {}", SERVICE_NAME);
|
||||
|
||||
let init_system = detect_linux_init_system();
|
||||
|
||||
match init_system.as_str() {
|
||||
"systemd" => check_systemd_service_status(SERVICE_NAME).await,
|
||||
"openrc" => check_openrc_service_status(SERVICE_NAME).await,
|
||||
_ => {
|
||||
log::warn!("Unknown init system: {}, assuming systemd", init_system);
|
||||
check_systemd_service_status(SERVICE_NAME).await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn detect_linux_init_system() -> String {
|
||||
if std::path::Path::new("/run/systemd/system").exists() {
|
||||
return "systemd".to_string();
|
||||
}
|
||||
|
||||
if std::path::Path::new("/run/openrc").exists() {
|
||||
return "openrc".to_string();
|
||||
}
|
||||
|
||||
if let Ok(output) = StdCommand::new("which").arg("systemctl").output() {
|
||||
if output.status.success() && !output.stdout.is_empty() {
|
||||
return "systemd".to_string();
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(output) = StdCommand::new("which").arg("rc-service").output() {
|
||||
if output.status.success() && !output.stdout.is_empty() {
|
||||
return "openrc".to_string();
|
||||
}
|
||||
}
|
||||
|
||||
"systemd".to_string()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
async fn check_systemd_service_status(
|
||||
service_name: &str,
|
||||
) -> Result<String, Box<dyn std::error::Error>> {
|
||||
log::info!("Checking systemd service status for: {}", service_name);
|
||||
|
||||
let status_output = StdCommand::new("systemctl")
|
||||
.args(&["is-active", service_name])
|
||||
.output();
|
||||
|
||||
match status_output {
|
||||
Ok(output) => {
|
||||
let status = String::from_utf8_lossy(&output.stdout)
|
||||
.trim()
|
||||
.to_lowercase();
|
||||
log::info!("Service {} status: {}", service_name, status);
|
||||
|
||||
match status.as_str() {
|
||||
"active" | "activating" => {
|
||||
log::info!("Service is active and running");
|
||||
return Ok("running".to_string());
|
||||
}
|
||||
"inactive" | "failed" => {
|
||||
log::info!("Service is {}", status);
|
||||
return Ok("stopped".to_string());
|
||||
}
|
||||
"unknown" => {
|
||||
log::warn!("Service status unknown, checking if service exists");
|
||||
let exists_output = StdCommand::new("systemctl")
|
||||
.args(&["list-unit-files", &format!("{}.service", service_name)])
|
||||
.output();
|
||||
|
||||
match exists_output {
|
||||
Ok(output) if output.status.success() => {
|
||||
let output_str = String::from_utf8_lossy(&output.stdout);
|
||||
if output_str.contains(service_name) {
|
||||
log::info!("Service exists and not active");
|
||||
return Ok("stopped".to_string());
|
||||
} else {
|
||||
log::error!("Service {} not found", service_name);
|
||||
return Ok("not-installed".to_string());
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
log::error!("Failed to check if service exists");
|
||||
return Ok("error".to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
log::warn!("Unknown service status: {}", status);
|
||||
return Ok("error".to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Failed to check systemd service status: {}", e);
|
||||
return Ok("error".to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
async fn start_systemd_service(service_name: &str) -> Result<bool, Box<dyn std::error::Error>> {
|
||||
use users::get_effective_uid;
|
||||
@@ -480,7 +643,7 @@ async fn start_systemd_service(service_name: &str) -> Result<bool, Box<dyn std::
|
||||
#[cfg(target_os = "linux")]
|
||||
async fn check_openrc_service_status(
|
||||
service_name: &str,
|
||||
) -> Result<bool, Box<dyn std::error::Error>> {
|
||||
) -> Result<String, Box<dyn std::error::Error>> {
|
||||
log::info!("Checking OpenRC service status for: {}", service_name);
|
||||
|
||||
let status_output = StdCommand::new("rc-service")
|
||||
@@ -496,21 +659,21 @@ async fn check_openrc_service_status(
|
||||
|
||||
if status_str.contains("started") || status_str.contains("running") {
|
||||
log::info!("Service is running");
|
||||
return Ok(true);
|
||||
return Ok("running".to_string());
|
||||
} else if status_str.contains("stopped") || status_str.contains("inactive") {
|
||||
log::info!("Service is stopped, attempting to start");
|
||||
return start_openrc_service(service_name).await;
|
||||
log::info!("Service is stopped");
|
||||
return Ok("stopped".to_string());
|
||||
} else if stderr_str.contains("does not exist") {
|
||||
log::error!("Service {} does not exist", service_name);
|
||||
return Ok(false);
|
||||
return Ok("not-installed".to_string());
|
||||
} else {
|
||||
log::warn!("Unknown service status, attempting to start");
|
||||
return start_openrc_service(service_name).await;
|
||||
return Ok("error".to_string());
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Failed to check OpenRC service status: {}", e);
|
||||
return start_openrc_service(service_name).await;
|
||||
return Ok("error".to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -562,7 +725,7 @@ async fn start_openrc_service(service_name: &str) -> Result<bool, Box<dyn std::e
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub async fn check_service_status() -> Result<bool, Box<dyn std::error::Error>> {
|
||||
pub async fn start_service() -> Result<bool, Box<dyn std::error::Error>> {
|
||||
const SERVICE_IDENTIFIER: &str = "io.github.openlistteam.openlist.service";
|
||||
|
||||
log::info!("Checking macOS service status for: {}", SERVICE_IDENTIFIER);
|
||||
@@ -624,6 +787,64 @@ pub async fn check_service_status() -> Result<bool, Box<dyn std::error::Error>>
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub async fn check_service_status() -> Result<String, Box<dyn std::error::Error>> {
|
||||
const SERVICE_IDENTIFIER: &str = "io.github.openlistteam.openlist.service";
|
||||
|
||||
log::info!("Checking macOS service status for: {}", SERVICE_IDENTIFIER);
|
||||
|
||||
let status_output = StdCommand::new("launchctl")
|
||||
.args(&["list", SERVICE_IDENTIFIER])
|
||||
.output();
|
||||
|
||||
match status_output {
|
||||
Ok(output) => {
|
||||
if output.status.success() {
|
||||
let output_str = String::from_utf8_lossy(&output.stdout);
|
||||
log::info!("launchctl list output: {}", output_str);
|
||||
|
||||
if let Some(pid_value) = extract_plist_value(&output_str, "PID") {
|
||||
log::info!("Extracted PID value: {}", pid_value);
|
||||
if let Ok(pid) = pid_value.parse::<i32>() {
|
||||
if pid > 0 {
|
||||
log::info!("Service is running with PID: {}", pid);
|
||||
return Ok("running".to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(exit_status) = extract_plist_value(&output_str, "LastExitStatus") {
|
||||
if let Ok(status) = exit_status.parse::<i32>() {
|
||||
if status == 0 {
|
||||
log::info!("Service is loaded but not running (clean exit)");
|
||||
return Ok("stopped".to_string());
|
||||
} else {
|
||||
log::warn!("Service has non-zero exit status: {}", status);
|
||||
return Ok("stopped".to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log::info!("Service appears to be loaded but status unclear");
|
||||
return Ok("error".to_string());
|
||||
} else {
|
||||
let stderr_str = String::from_utf8_lossy(&output.stderr);
|
||||
if stderr_str.contains("Could not find service") {
|
||||
log::error!("Service {} is not loaded", SERVICE_IDENTIFIER);
|
||||
return Ok("not-installed".to_string());
|
||||
} else {
|
||||
log::warn!("launchctl list failed");
|
||||
return Ok("error".to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Failed to check macOS service status: {}", e);
|
||||
return Ok("error".to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
async fn start_macos_service(service_identifier: &str) -> Result<bool, Box<dyn std::error::Error>> {
|
||||
log::info!("Attempting to start macOS service: {}", service_identifier);
|
||||
@@ -694,412 +915,3 @@ fn extract_plist_value(plist_output: &str, key: &str) -> Option<String> {
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
async fn restart_macos_service(
|
||||
service_identifier: &str,
|
||||
) -> Result<bool, Box<dyn std::error::Error>> {
|
||||
log::info!(
|
||||
"Attempting to restart macOS service: {}",
|
||||
service_identifier
|
||||
);
|
||||
|
||||
let _ = StdCommand::new("launchctl")
|
||||
.args(&["stop", service_identifier])
|
||||
.status();
|
||||
|
||||
std::thread::sleep(std::time::Duration::from_millis(500));
|
||||
|
||||
start_macos_service(service_identifier).await
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub async fn stop_service() -> Result<bool, Box<dyn std::error::Error>> {
|
||||
use deelevate::{PrivilegeLevel, Token};
|
||||
use runas::Command as RunasCommand;
|
||||
use std::os::windows::process::CommandExt;
|
||||
|
||||
let service_name = "openlist_desktop_service";
|
||||
log::info!("Attempting to stop Windows service: {}", service_name);
|
||||
|
||||
let token = Token::with_current_process()?;
|
||||
let level = token.privilege_level()?;
|
||||
|
||||
let powershell_cmd = format!("Stop-Service -Name '{}' -Force", service_name);
|
||||
|
||||
let status = match level {
|
||||
PrivilegeLevel::NotPrivileged => {
|
||||
log::info!("Running without admin privileges, using runas for elevation");
|
||||
RunasCommand::new("powershell.exe")
|
||||
.args(&["-Command", &powershell_cmd])
|
||||
.show(false)
|
||||
.status()?
|
||||
}
|
||||
_ => {
|
||||
log::info!("Already have admin privileges, running directly");
|
||||
StdCommand::new("powershell.exe")
|
||||
.args(&["-Command", &powershell_cmd])
|
||||
.creation_flags(0x08000000)
|
||||
.status()?
|
||||
}
|
||||
};
|
||||
|
||||
if status.success() {
|
||||
log::info!("Service stopped successfully");
|
||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||
Ok(true)
|
||||
} else {
|
||||
log::error!("Failed to stop service, exit code: {}", status);
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub async fn stop_service() -> Result<bool, Box<dyn std::error::Error>> {
|
||||
const SERVICE_NAME: &str = "openlist-desktop-service";
|
||||
|
||||
log::info!("Attempting to stop Linux service: {}", SERVICE_NAME);
|
||||
|
||||
let init_system = detect_linux_init_system();
|
||||
|
||||
match init_system.as_str() {
|
||||
"systemd" => stop_systemd_service(SERVICE_NAME).await,
|
||||
"openrc" => stop_openrc_service(SERVICE_NAME).await,
|
||||
_ => {
|
||||
log::warn!("Unknown init system: {}, assuming systemd", init_system);
|
||||
stop_systemd_service(SERVICE_NAME).await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
async fn stop_systemd_service(service_name: &str) -> Result<bool, Box<dyn std::error::Error>> {
|
||||
use users::get_effective_uid;
|
||||
|
||||
log::info!("Attempting to stop systemd service: {}", service_name);
|
||||
|
||||
let status = match get_effective_uid() {
|
||||
0 => StdCommand::new("systemctl")
|
||||
.args(&["stop", service_name])
|
||||
.status()?,
|
||||
_ => {
|
||||
let elevator = linux_elevator();
|
||||
log::info!("Using {} for elevation", elevator);
|
||||
|
||||
StdCommand::new(&elevator)
|
||||
.args(&["systemctl", "stop", service_name])
|
||||
.status()?
|
||||
}
|
||||
};
|
||||
|
||||
if status.success() {
|
||||
log::info!("Service stop command completed");
|
||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||
|
||||
let verify_output = StdCommand::new("systemctl")
|
||||
.args(&["is-active", service_name])
|
||||
.output()?;
|
||||
|
||||
let verify_status_str = String::from_utf8_lossy(&verify_output.stdout);
|
||||
let verify_status = verify_status_str.trim();
|
||||
let is_stopped = verify_status == "inactive" || verify_status == "failed";
|
||||
|
||||
if is_stopped {
|
||||
log::info!("Service verified as stopped");
|
||||
} else {
|
||||
log::warn!(
|
||||
"Service stop command succeeded but service is still active: {}",
|
||||
verify_status
|
||||
);
|
||||
}
|
||||
|
||||
Ok(is_stopped)
|
||||
} else {
|
||||
log::error!("Failed to stop systemd service, exit code: {}", status);
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
async fn stop_openrc_service(service_name: &str) -> Result<bool, Box<dyn std::error::Error>> {
|
||||
use users::get_effective_uid;
|
||||
|
||||
log::info!("Attempting to stop OpenRC service: {}", service_name);
|
||||
let status = match get_effective_uid() {
|
||||
0 => StdCommand::new("rc-service")
|
||||
.args(&[service_name, "stop"])
|
||||
.status()?,
|
||||
_ => {
|
||||
let elevator = linux_elevator();
|
||||
log::info!("Using {} for elevation", elevator);
|
||||
|
||||
StdCommand::new(&elevator)
|
||||
.args(&["rc-service", service_name, "stop"])
|
||||
.status()?
|
||||
}
|
||||
};
|
||||
|
||||
if status.success() {
|
||||
log::info!("Service stop command completed");
|
||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||
|
||||
let verify_output = StdCommand::new("rc-service")
|
||||
.args(&[service_name, "status"])
|
||||
.output()?;
|
||||
|
||||
let verify_status = String::from_utf8_lossy(&verify_output.stdout).to_lowercase();
|
||||
let is_stopped = verify_status.contains("stopped") || verify_status.contains("inactive");
|
||||
|
||||
if is_stopped {
|
||||
log::info!("Service verified as stopped");
|
||||
} else {
|
||||
log::warn!(
|
||||
"Service stop command succeeded but service is still running: {}",
|
||||
verify_status
|
||||
);
|
||||
}
|
||||
|
||||
Ok(is_stopped)
|
||||
} else {
|
||||
log::error!("Failed to stop OpenRC service, exit code: {}", status);
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub async fn stop_service() -> Result<bool, Box<dyn std::error::Error>> {
|
||||
const SERVICE_IDENTIFIER: &str = "io.github.openlistteam.openlist.service";
|
||||
|
||||
log::info!("Attempting to stop macOS service: {}", SERVICE_IDENTIFIER);
|
||||
|
||||
let status = StdCommand::new("launchctl")
|
||||
.args(&["stop", SERVICE_IDENTIFIER])
|
||||
.status()?;
|
||||
|
||||
if status.success() {
|
||||
log::info!("Service stop command completed");
|
||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||
|
||||
let verify_output = StdCommand::new("launchctl")
|
||||
.args(&["list", SERVICE_IDENTIFIER])
|
||||
.output()?;
|
||||
|
||||
if verify_output.status.success() {
|
||||
let output_str = String::from_utf8_lossy(&verify_output.stdout);
|
||||
log::info!("Verification output after stop: {}", output_str);
|
||||
|
||||
if let Some(pid_value) = extract_plist_value(&output_str, "PID") {
|
||||
if let Ok(pid) = pid_value.parse::<i32>() {
|
||||
let is_stopped = pid <= 0;
|
||||
|
||||
if is_stopped {
|
||||
log::info!("Service verified as stopped");
|
||||
} else {
|
||||
log::warn!(
|
||||
"Service stop command succeeded but service is still running with PID: {}",
|
||||
pid
|
||||
);
|
||||
}
|
||||
|
||||
return Ok(is_stopped);
|
||||
}
|
||||
}
|
||||
|
||||
log::info!("No PID found in output, service appears to be stopped");
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
log::info!("Could not verify service status after stop, assuming success");
|
||||
Ok(true)
|
||||
} else {
|
||||
log::error!("Failed to stop macOS service, exit code: {}", status);
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub async fn restart_service() -> Result<bool, Box<dyn std::error::Error>> {
|
||||
use deelevate::{PrivilegeLevel, Token};
|
||||
use runas::Command as RunasCommand;
|
||||
use std::os::windows::process::CommandExt;
|
||||
|
||||
let service_name = "openlist_desktop_service";
|
||||
log::info!("Attempting to restart Windows service: {}", service_name);
|
||||
|
||||
let powershell_cmd = format!("Restart-Service -Name '{}' -Force", service_name);
|
||||
|
||||
let status = {
|
||||
let token = Token::with_current_process()?;
|
||||
let level = token.privilege_level()?;
|
||||
|
||||
match level {
|
||||
PrivilegeLevel::NotPrivileged => {
|
||||
log::info!("Running without admin privileges, using runas for elevation");
|
||||
RunasCommand::new("powershell.exe")
|
||||
.args(&["-Command", &powershell_cmd])
|
||||
.show(false)
|
||||
.status()?
|
||||
}
|
||||
_ => {
|
||||
log::info!("Already have admin privileges, running directly");
|
||||
StdCommand::new("powershell.exe")
|
||||
.args(&["-Command", &powershell_cmd])
|
||||
.creation_flags(0x08000000)
|
||||
.status()?
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if status.success() {
|
||||
log::info!("Service restart command completed");
|
||||
std::thread::sleep(std::time::Duration::from_secs(2));
|
||||
|
||||
match check_service_status().await {
|
||||
Ok(true) => {
|
||||
log::info!("Service verified as running after restart");
|
||||
Ok(true)
|
||||
}
|
||||
Ok(false) => {
|
||||
log::warn!("Service restart command succeeded but service is not running");
|
||||
Ok(false)
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Error verifying service status after restart: {}", e);
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log::error!("Failed to restart service, exit code: {}", status);
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub async fn restart_service() -> Result<bool, Box<dyn std::error::Error>> {
|
||||
const SERVICE_NAME: &str = "openlist-desktop-service";
|
||||
|
||||
log::info!("Attempting to restart Linux service: {}", SERVICE_NAME);
|
||||
|
||||
let init_system = detect_linux_init_system();
|
||||
|
||||
match init_system.as_str() {
|
||||
"systemd" => restart_systemd_service(SERVICE_NAME).await,
|
||||
"openrc" => restart_openrc_service(SERVICE_NAME).await,
|
||||
_ => {
|
||||
log::warn!("Unknown init system: {}, assuming systemd", init_system);
|
||||
restart_systemd_service(SERVICE_NAME).await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
async fn restart_systemd_service(service_name: &str) -> Result<bool, Box<dyn std::error::Error>> {
|
||||
use users::get_effective_uid;
|
||||
|
||||
log::info!("Attempting to restart systemd service: {}", service_name);
|
||||
let status = match get_effective_uid() {
|
||||
0 => StdCommand::new("systemctl")
|
||||
.args(&["restart", service_name])
|
||||
.status()?,
|
||||
_ => {
|
||||
let elevator = linux_elevator();
|
||||
log::info!("Using {} for elevation", elevator);
|
||||
|
||||
StdCommand::new(&elevator)
|
||||
.args(&["systemctl", "restart", service_name])
|
||||
.status()?
|
||||
}
|
||||
};
|
||||
|
||||
if status.success() {
|
||||
log::info!("Service restart command completed");
|
||||
std::thread::sleep(std::time::Duration::from_secs(2));
|
||||
|
||||
let verify_output = StdCommand::new("systemctl")
|
||||
.args(&["is-active", service_name])
|
||||
.output()?;
|
||||
|
||||
let verify_status_str = String::from_utf8_lossy(&verify_output.stdout);
|
||||
let verify_status = verify_status_str.trim();
|
||||
let is_running = verify_status == "active" || verify_status == "activating";
|
||||
|
||||
if is_running {
|
||||
log::info!("Service verified as running after restart");
|
||||
} else {
|
||||
log::warn!(
|
||||
"Service restart command succeeded but service is not active: {}",
|
||||
verify_status
|
||||
);
|
||||
}
|
||||
|
||||
Ok(is_running)
|
||||
} else {
|
||||
log::error!("Failed to restart systemd service, exit code: {}", status);
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
async fn restart_openrc_service(service_name: &str) -> Result<bool, Box<dyn std::error::Error>> {
|
||||
use users::get_effective_uid;
|
||||
|
||||
log::info!("Attempting to restart OpenRC service: {}", service_name);
|
||||
let status = match get_effective_uid() {
|
||||
0 => StdCommand::new("rc-service")
|
||||
.args(&[service_name, "restart"])
|
||||
.status()?,
|
||||
_ => {
|
||||
let elevator = linux_elevator();
|
||||
log::info!("Using {} for elevation", elevator);
|
||||
|
||||
StdCommand::new(&elevator)
|
||||
.args(&["rc-service", service_name, "restart"])
|
||||
.status()?
|
||||
}
|
||||
};
|
||||
|
||||
if status.success() {
|
||||
log::info!("Service restart command completed");
|
||||
std::thread::sleep(std::time::Duration::from_secs(2));
|
||||
|
||||
let verify_output = StdCommand::new("rc-service")
|
||||
.args(&[service_name, "status"])
|
||||
.output()?;
|
||||
|
||||
let verify_status = String::from_utf8_lossy(&verify_output.stdout).to_lowercase();
|
||||
let is_running = verify_status.contains("started") || verify_status.contains("running");
|
||||
|
||||
if is_running {
|
||||
log::info!("Service verified as running after restart");
|
||||
} else {
|
||||
log::warn!(
|
||||
"Service restart command succeeded but service is not running: {}",
|
||||
verify_status
|
||||
);
|
||||
}
|
||||
|
||||
Ok(is_running)
|
||||
} else {
|
||||
log::error!("Failed to restart OpenRC service, exit code: {}", status);
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub async fn restart_service() -> Result<bool, Box<dyn std::error::Error>> {
|
||||
const SERVICE_IDENTIFIER: &str = "io.github.openlistteam.openlist.service";
|
||||
|
||||
log::info!(
|
||||
"Attempting to restart macOS service: {}",
|
||||
SERVICE_IDENTIFIER
|
||||
);
|
||||
|
||||
let stop_result = stop_service().await?;
|
||||
if !stop_result {
|
||||
log::warn!("Failed to stop service, but continuing with restart attempt");
|
||||
}
|
||||
|
||||
std::thread::sleep(std::time::Duration::from_millis(500));
|
||||
|
||||
start_macos_service(SERVICE_IDENTIFIER).await
|
||||
}
|
||||
|
||||
@@ -34,8 +34,7 @@ use cmd::http_api::{
|
||||
};
|
||||
|
||||
use cmd::service::{
|
||||
check_service_status, install_service, restart_service, start_service, stop_service,
|
||||
uninstall_service,
|
||||
check_service_status, install_service, start_service, stop_service, uninstall_service,
|
||||
};
|
||||
|
||||
use object::structs::*;
|
||||
@@ -160,7 +159,6 @@ pub fn run() {
|
||||
check_service_status,
|
||||
stop_service,
|
||||
start_service,
|
||||
restart_service,
|
||||
check_for_updates,
|
||||
download_update,
|
||||
install_update_and_restart,
|
||||
|
||||
@@ -15,21 +15,31 @@ pub fn create_tray(app_handle: &AppHandle) -> tauri::Result<()> {
|
||||
let hide_i = MenuItem::with_id(app_handle, "hide", "隐藏窗口", true, None::<&str>)?;
|
||||
let restart_i = MenuItem::with_id(app_handle, "restart", "重启应用", true, None::<&str>)?;
|
||||
|
||||
let start_service_i =
|
||||
MenuItem::with_id(app_handle, "start_service", "启动服务", true, None::<&str>)?;
|
||||
let stop_service_i =
|
||||
MenuItem::with_id(app_handle, "stop_service", "停止服务", true, None::<&str>)?;
|
||||
let start_service_i = MenuItem::with_id(
|
||||
app_handle,
|
||||
"start_service",
|
||||
"启动OpenList",
|
||||
true,
|
||||
None::<&str>,
|
||||
)?;
|
||||
let stop_service_i = MenuItem::with_id(
|
||||
app_handle,
|
||||
"stop_service",
|
||||
"停止OpenList",
|
||||
true,
|
||||
None::<&str>,
|
||||
)?;
|
||||
let restart_service_i = MenuItem::with_id(
|
||||
app_handle,
|
||||
"restart_service",
|
||||
"重启服务",
|
||||
"重启OpenList",
|
||||
true,
|
||||
None::<&str>,
|
||||
)?;
|
||||
let service_submenu = Submenu::with_id_and_items(
|
||||
app_handle,
|
||||
"service",
|
||||
"服务控制",
|
||||
"核心控制",
|
||||
true,
|
||||
&[&start_service_i, &stop_service_i, &restart_service_i],
|
||||
)?;
|
||||
@@ -113,15 +123,15 @@ fn handle_menu_event(app_handle: &AppHandle, event: tauri::menu::MenuEvent) {
|
||||
}
|
||||
"start_service" => {
|
||||
log::info!("Start service menu item clicked");
|
||||
handle_service_action(app_handle, "start");
|
||||
handle_core_action(app_handle, "start");
|
||||
}
|
||||
"stop_service" => {
|
||||
log::info!("Stop service menu item clicked");
|
||||
handle_service_action(app_handle, "stop");
|
||||
handle_core_action(app_handle, "stop");
|
||||
}
|
||||
"restart_service" => {
|
||||
log::info!("Restart service menu item clicked");
|
||||
handle_service_action(app_handle, "restart");
|
||||
handle_core_action(app_handle, "restart");
|
||||
}
|
||||
_ => {
|
||||
log::debug!("Unknown menu item clicked: {:?}", event.id());
|
||||
@@ -144,21 +154,21 @@ pub fn update_tray_menu(app_handle: &AppHandle, service_running: bool) -> tauri:
|
||||
let start_service_i = MenuItem::with_id(
|
||||
app_handle,
|
||||
"start_service",
|
||||
"启动服务",
|
||||
"启动OpenList",
|
||||
!service_running,
|
||||
None::<&str>,
|
||||
)?;
|
||||
let stop_service_i = MenuItem::with_id(
|
||||
app_handle,
|
||||
"stop_service",
|
||||
"停止服务",
|
||||
"停止OpenList",
|
||||
service_running,
|
||||
None::<&str>,
|
||||
)?;
|
||||
let restart_service_i = MenuItem::with_id(
|
||||
app_handle,
|
||||
"restart_service",
|
||||
"重启服务",
|
||||
"重启OpenList",
|
||||
service_running,
|
||||
None::<&str>,
|
||||
)?;
|
||||
@@ -166,7 +176,7 @@ pub fn update_tray_menu(app_handle: &AppHandle, service_running: bool) -> tauri:
|
||||
let service_submenu = Submenu::with_id_and_items(
|
||||
app_handle,
|
||||
"service",
|
||||
"服务控制",
|
||||
"核心控制",
|
||||
true,
|
||||
&[&start_service_i, &stop_service_i, &restart_service_i],
|
||||
)?;
|
||||
@@ -212,14 +222,14 @@ pub fn update_tray_menu_delayed(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_service_action(app_handle: &AppHandle, action: &str) {
|
||||
log::info!("Handling service action from tray: {}", action);
|
||||
fn handle_core_action(app_handle: &AppHandle, action: &str) {
|
||||
log::info!("Handling core action from tray: {}", action);
|
||||
|
||||
if let Err(e) = app_handle.emit("tray-service-action", action) {
|
||||
log::error!("Failed to emit tray service action event: {}", e);
|
||||
if let Err(e) = app_handle.emit("tray-core-action", action) {
|
||||
log::error!("Failed to emit tray core action event: {}", e);
|
||||
}
|
||||
|
||||
log::debug!("Service action '{}' dispatched to frontend", action);
|
||||
log::debug!("Core action '{}' dispatched to frontend", action);
|
||||
}
|
||||
|
||||
pub fn force_update_tray_menu(app_handle: &AppHandle, service_running: bool) -> tauri::Result<()> {
|
||||
@@ -227,21 +237,21 @@ pub fn force_update_tray_menu(app_handle: &AppHandle, service_running: bool) ->
|
||||
let start_service_i = MenuItem::with_id(
|
||||
app_handle,
|
||||
"start_service",
|
||||
"启动服务",
|
||||
"启动OpenList",
|
||||
!service_running,
|
||||
None::<&str>,
|
||||
)?;
|
||||
let stop_service_i = MenuItem::with_id(
|
||||
app_handle,
|
||||
"stop_service",
|
||||
"停止服务",
|
||||
"停止OpenList",
|
||||
service_running,
|
||||
None::<&str>,
|
||||
)?;
|
||||
let restart_service_i = MenuItem::with_id(
|
||||
app_handle,
|
||||
"restart_service",
|
||||
"重启服务",
|
||||
"重启OpenList",
|
||||
service_running,
|
||||
None::<&str>,
|
||||
)?;
|
||||
@@ -249,7 +259,7 @@ pub fn force_update_tray_menu(app_handle: &AppHandle, service_running: bool) ->
|
||||
let service_submenu = Submenu::with_id_and_items(
|
||||
app_handle,
|
||||
"service",
|
||||
"服务控制",
|
||||
"核心控制",
|
||||
true,
|
||||
&[&start_service_i, &stop_service_i, &restart_service_i],
|
||||
)?;
|
||||
|
||||
Reference in New Issue
Block a user