feat(settings): add auto-launch on system startup feature

Implement auto-launch functionality with proper state synchronization
and error handling across Windows, macOS, and Linux platforms.

Key changes:
- Add auto_launch module using auto-launch crate 0.5
- Define typed errors (AutoLaunchPathError, AutoLaunchEnableError, etc.)
- Sync system state with settings.json on app startup
- Only call system API when auto-launch state actually changes
- Add UI toggle in Window Settings panel
- Add i18n support for auto-launch settings (en/zh)

Implementation details:
- Settings file (settings.json) is the single source of truth
- On startup, system state is synced to match settings.json
- Error handling uses Rust type system with proper error propagation
- Frontend optimized to avoid unnecessary system API calls

Platform support:
- Windows: HKEY_CURRENT_USER registry modification
- macOS: AppleScript-based launch item (configurable to Launch Agent)
- Linux: XDG autostart desktop file
This commit is contained in:
Jason
2025-11-21 23:23:35 +08:00
parent 7fa0a7b166
commit ba336fc416
14 changed files with 178 additions and 0 deletions

View File

@@ -126,6 +126,7 @@ export function useSettings(): UseSettingsResult {
const previousClaudeDir = sanitizeDir(data?.claudeConfigDir);
const previousCodexDir = sanitizeDir(data?.codexConfigDir);
const previousGeminiDir = sanitizeDir(data?.geminiConfigDir);
const previousAutoLaunch = data?.launchOnStartup ?? false;
const payload: Settings = {
...settings,
@@ -139,6 +140,20 @@ export function useSettings(): UseSettingsResult {
await settingsApi.setAppConfigDirOverride(sanitizedAppDir ?? null);
// 如果开机自启状态改变,调用系统 API
if (payload.launchOnStartup !== previousAutoLaunch) {
try {
await settingsApi.setAutoLaunch(payload.launchOnStartup);
} catch (error) {
console.error("Failed to update auto-launch:", error);
toast.error(
t("settings.autoLaunchFailed", {
defaultValue: "设置开机自启失败",
}),
);
}
}
try {
if (payload.enableClaudePluginIntegration) {
await settingsApi.applyClaudePluginConfig({ official: false });