feat: add portable mode support and improve update handling
- Add portable.ini marker file creation in GitHub Actions for portable builds - Implement is_portable_mode() command to detect portable execution - Redirect portable users to GitHub releases page for manual updates - Change update URL to point to latest releases page - Integrate portable mode detection in Settings UI
This commit is contained in:
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
@@ -226,6 +226,12 @@ jobs:
|
||||
$portableDir = 'release-assets/CC-Switch-Portable'
|
||||
New-Item -ItemType Directory -Force -Path $portableDir | Out-Null
|
||||
Copy-Item $exePath $portableDir
|
||||
$portableIniPath = Join-Path $portableDir 'portable.ini'
|
||||
$portableContent = @(
|
||||
'# CC Switch portable build marker',
|
||||
'portable=true'
|
||||
)
|
||||
$portableContent | Set-Content -Path $portableIniPath -Encoding UTF8
|
||||
Compress-Archive -Path "$portableDir/*" -DestinationPath 'release-assets/CC-Switch-Windows-Portable.zip' -Force
|
||||
Remove-Item -Recurse -Force $portableDir
|
||||
Write-Host 'Windows portable zip created'
|
||||
|
||||
@@ -674,7 +674,7 @@ pub async fn check_for_updates(handle: tauri::AppHandle) -> Result<bool, String>
|
||||
handle
|
||||
.opener()
|
||||
.open_url(
|
||||
"https://github.com/farion1231/cc-switch/releases",
|
||||
"https://github.com/farion1231/cc-switch/releases/latest",
|
||||
None::<String>,
|
||||
)
|
||||
.map_err(|e| format!("打开更新页面失败: {}", e))?;
|
||||
@@ -682,6 +682,17 @@ pub async fn check_for_updates(handle: tauri::AppHandle) -> Result<bool, String>
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
/// 判断是否为便携版(绿色版)运行
|
||||
#[tauri::command]
|
||||
pub async fn is_portable_mode() -> Result<bool, String> {
|
||||
let exe_path = std::env::current_exe().map_err(|e| format!("获取可执行路径失败: {}", e))?;
|
||||
if let Some(dir) = exe_path.parent() {
|
||||
Ok(dir.join("portable.ini").is_file())
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
/// VS Code: 获取用户 settings.json 状态
|
||||
#[tauri::command]
|
||||
pub async fn get_vscode_settings_status() -> Result<ConfigStatus, String> {
|
||||
|
||||
@@ -377,6 +377,7 @@ pub fn run() {
|
||||
commands::get_settings,
|
||||
commands::save_settings,
|
||||
commands::check_for_updates,
|
||||
commands::is_portable_mode,
|
||||
commands::get_vscode_settings_status,
|
||||
commands::read_vscode_settings,
|
||||
commands::write_vscode_settings,
|
||||
|
||||
@@ -35,6 +35,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) {
|
||||
const [showUpToDate, setShowUpToDate] = useState(false);
|
||||
const [resolvedClaudeDir, setResolvedClaudeDir] = useState<string>("");
|
||||
const [resolvedCodexDir, setResolvedCodexDir] = useState<string>("");
|
||||
const [isPortable, setIsPortable] = useState(false);
|
||||
const { hasUpdate, updateInfo, updateHandle, checkUpdate, resetDismiss } =
|
||||
useUpdate();
|
||||
|
||||
@@ -43,6 +44,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) {
|
||||
loadConfigPath();
|
||||
loadVersion();
|
||||
loadResolvedDirs();
|
||||
loadPortableFlag();
|
||||
}, []);
|
||||
|
||||
const loadVersion = async () => {
|
||||
@@ -103,6 +105,15 @@ export default function SettingsModal({ onClose }: SettingsModalProps) {
|
||||
}
|
||||
};
|
||||
|
||||
const loadPortableFlag = async () => {
|
||||
try {
|
||||
const portable = await window.api.isPortable();
|
||||
setIsPortable(portable);
|
||||
} catch (error) {
|
||||
console.error("检测便携模式失败:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const saveSettings = async () => {
|
||||
try {
|
||||
const payload: Settings = {
|
||||
@@ -126,6 +137,10 @@ export default function SettingsModal({ onClose }: SettingsModalProps) {
|
||||
|
||||
const handleCheckUpdate = async () => {
|
||||
if (hasUpdate && updateHandle) {
|
||||
if (isPortable) {
|
||||
await window.api.checkForUpdates();
|
||||
return;
|
||||
}
|
||||
// 已检测到更新:直接复用 updateHandle 下载并安装,避免重复检查
|
||||
setIsDownloading(true);
|
||||
try {
|
||||
|
||||
@@ -246,6 +246,16 @@ export const tauriAPI = {
|
||||
}
|
||||
},
|
||||
|
||||
// 判断是否为便携模式
|
||||
isPortable: async (): Promise<boolean> => {
|
||||
try {
|
||||
return await invoke<boolean>("is_portable_mode");
|
||||
} catch (error) {
|
||||
console.error("检测便携模式失败:", error);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
// 获取应用配置文件路径
|
||||
getAppConfigPath: async (): Promise<string> => {
|
||||
try {
|
||||
|
||||
1
src/vite-env.d.ts
vendored
1
src/vite-env.d.ts
vendored
@@ -39,6 +39,7 @@ declare global {
|
||||
getSettings: () => Promise<Settings>;
|
||||
saveSettings: (settings: Settings) => Promise<boolean>;
|
||||
checkForUpdates: () => Promise<void>;
|
||||
isPortable: () => Promise<boolean>;
|
||||
getAppConfigPath: () => Promise<string>;
|
||||
openAppConfigFolder: () => Promise<void>;
|
||||
// VS Code settings.json 能力
|
||||
|
||||
Reference in New Issue
Block a user