package desktop import ( "context" "fmt" "os" "path/filepath" "runtime" "strings" "github.com/Apale7/opencode-provider-switch/internal/app" "github.com/Apale7/opencode-provider-switch/internal/config" ) // AutoStart manages real launch-at-login integration where the platform permits // it. This implementation currently targets Linux XDG autostart. type AutoStart struct { service *app.Service ctx context.Context } func NewAutoStart(service *app.Service) *AutoStart { return &AutoStart{service: service} } func (a *AutoStart) Attach(ctx context.Context) { a.ctx = ctx } func (a *AutoStart) Detach() { a.ctx = nil } func (a *AutoStart) Sync(ctx context.Context, prefs app.DesktopPrefsView) error { _ = ctx if runtime.GOOS != "linux" { return nil } entryPath, err := a.entryPath() if err != nil { return err } if prefs.LaunchAtLogin { return a.writeLinuxEntry(entryPath) } if err := os.Remove(entryPath); err != nil && !os.IsNotExist(err) { return fmt.Errorf("remove autostart entry: %w", err) } return nil } func (a *AutoStart) entryPath() (string, error) { base := strings.TrimSpace(os.Getenv("XDG_CONFIG_HOME")) if base == "" { home, err := os.UserHomeDir() if err != nil { return "", fmt.Errorf("resolve home for autostart: %w", err) } base = filepath.Join(home, ".config") } return filepath.Join(base, "autostart", "ocswitch-desktop.desktop"), nil } func (a *AutoStart) writeLinuxEntry(path string) error { if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { return fmt.Errorf("mkdir autostart dir: %w", err) } execPath, err := os.Executable() if err != nil { return fmt.Errorf("resolve desktop executable: %w", err) } configPath := config.DefaultPath() if a.service != nil { configPath = a.service.ConfigPath() } content := strings.Join([]string{ "[Desktop Entry]", "Type=Application", "Version=1.0", "Name=ocswitch desktop", "Comment=OpenCode provider switch desktop shell", fmt.Sprintf("Exec=%s --config %s", shellQuote(execPath), shellQuote(configPath)), "Terminal=false", "X-GNOME-Autostart-enabled=true", "Categories=Network;Development;", "StartupNotify=false", "", }, "\n") if err := os.WriteFile(path, []byte(content), 0o644); err != nil { return fmt.Errorf("write autostart entry: %w", err) } return nil } func shellQuote(value string) string { replacer := strings.NewReplacer("\\", "\\\\", `"`, `\\"`) return `"` + replacer.Replace(value) + `"` }