mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-27 16:26:16 +08:00
2651b65b10
* fix(schema): add missing base columns migration for proxy_config Add compatibility migration for older databases that may be missing the basic proxy_config columns (proxy_enabled, listen_address, listen_port, enable_logging) before adding newer timeout fields. * fix: add proxy_config base column patches for v3.9.0-2 upgrade Add base config column patches in create_tables_on_conn(): - proxy_enabled - listen_address - listen_port - enable_logging Ensures v3.9.0-2 users (user_version=2 but missing columns) can properly upgrade with all required fields added. * fix: migrate proxy_config singleton to per-app on startup for v2 databases Add startup migration for legacy proxy_config tables that still have singleton structure (no app_type column) even with user_version=2. This fixes the issue where v3.9.0-2 databases with v2 schema but legacy proxy_config structure would fail with "no such column: app_type" error. - Call migrate_proxy_config_to_per_app in create_tables_on_conn - Add regression test to verify the fix * style: cargo fmt --------- Co-authored-by: Jason <farion1231@gmail.com>
117 lines
3.9 KiB
Rust
117 lines
3.9 KiB
Rust
use crate::error::AppError;
|
|
use auto_launch::{AutoLaunch, AutoLaunchBuilder};
|
|
|
|
/// 获取 macOS 上的 .app bundle 路径
|
|
/// 将 `/path/to/CC Switch.app/Contents/MacOS/CC Switch` 转换为 `/path/to/CC Switch.app`
|
|
#[cfg(target_os = "macos")]
|
|
fn get_macos_app_bundle_path(exe_path: &std::path::Path) -> Option<std::path::PathBuf> {
|
|
let path_str = exe_path.to_string_lossy();
|
|
// 查找 .app/Contents/MacOS/ 模式
|
|
if let Some(app_pos) = path_str.find(".app/Contents/MacOS/") {
|
|
let app_bundle_end = app_pos + 4; // ".app" 的结束位置
|
|
Some(std::path::PathBuf::from(&path_str[..app_bundle_end]))
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
/// 初始化 AutoLaunch 实例
|
|
fn get_auto_launch() -> Result<AutoLaunch, AppError> {
|
|
let app_name = "CC Switch";
|
|
let exe_path =
|
|
std::env::current_exe().map_err(|e| AppError::Message(format!("无法获取应用路径: {e}")))?;
|
|
|
|
// macOS 需要使用 .app bundle 路径,否则 AppleScript login item 会打开终端
|
|
#[cfg(target_os = "macos")]
|
|
let app_path = get_macos_app_bundle_path(&exe_path).unwrap_or(exe_path);
|
|
|
|
#[cfg(not(target_os = "macos"))]
|
|
let app_path = exe_path;
|
|
|
|
// 使用 AutoLaunchBuilder 消除平台差异
|
|
// macOS: 使用 AppleScript 方式(默认),需要 .app bundle 路径
|
|
// Windows/Linux: 使用注册表/XDG autostart
|
|
let auto_launch = AutoLaunchBuilder::new()
|
|
.set_app_name(app_name)
|
|
.set_app_path(&app_path.to_string_lossy())
|
|
.build()
|
|
.map_err(|e| AppError::Message(format!("创建 AutoLaunch 失败: {e}")))?;
|
|
|
|
Ok(auto_launch)
|
|
}
|
|
|
|
/// 启用开机自启
|
|
pub fn enable_auto_launch() -> Result<(), AppError> {
|
|
let auto_launch = get_auto_launch()?;
|
|
auto_launch
|
|
.enable()
|
|
.map_err(|e| AppError::Message(format!("启用开机自启失败: {e}")))?;
|
|
log::info!("已启用开机自启");
|
|
Ok(())
|
|
}
|
|
|
|
/// 禁用开机自启
|
|
pub fn disable_auto_launch() -> Result<(), AppError> {
|
|
let auto_launch = get_auto_launch()?;
|
|
auto_launch
|
|
.disable()
|
|
.map_err(|e| AppError::Message(format!("禁用开机自启失败: {e}")))?;
|
|
log::info!("已禁用开机自启");
|
|
Ok(())
|
|
}
|
|
|
|
/// 检查是否已启用开机自启
|
|
pub fn is_auto_launch_enabled() -> Result<bool, AppError> {
|
|
let auto_launch = get_auto_launch()?;
|
|
auto_launch
|
|
.is_enabled()
|
|
.map_err(|e| AppError::Message(format!("检查开机自启状态失败: {e}")))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[cfg(target_os = "macos")]
|
|
#[test]
|
|
fn test_get_macos_app_bundle_path_valid() {
|
|
let exe_path = std::path::Path::new("/Applications/CC Switch.app/Contents/MacOS/CC Switch");
|
|
let result = get_macos_app_bundle_path(exe_path);
|
|
assert_eq!(
|
|
result,
|
|
Some(std::path::PathBuf::from("/Applications/CC Switch.app"))
|
|
);
|
|
}
|
|
|
|
#[cfg(target_os = "macos")]
|
|
#[test]
|
|
fn test_get_macos_app_bundle_path_with_spaces() {
|
|
let exe_path =
|
|
std::path::Path::new("/Users/test/My Apps/CC Switch.app/Contents/MacOS/CC Switch");
|
|
let result = get_macos_app_bundle_path(exe_path);
|
|
assert_eq!(
|
|
result,
|
|
Some(std::path::PathBuf::from(
|
|
"/Users/test/My Apps/CC Switch.app"
|
|
))
|
|
);
|
|
}
|
|
|
|
#[cfg(target_os = "macos")]
|
|
#[test]
|
|
fn test_get_macos_app_bundle_path_not_in_bundle() {
|
|
let exe_path = std::path::Path::new("/usr/local/bin/cc-switch");
|
|
let result = get_macos_app_bundle_path(exe_path);
|
|
assert_eq!(result, None);
|
|
}
|
|
|
|
#[cfg(target_os = "macos")]
|
|
#[test]
|
|
fn test_get_macos_app_bundle_path_dev_build() {
|
|
// 开发环境下的路径通常不在 .app bundle 内
|
|
let exe_path = std::path::Path::new("/Users/dev/project/target/debug/cc-switch");
|
|
let result = get_macos_app_bundle_path(exe_path);
|
|
assert_eq!(result, None);
|
|
}
|
|
}
|