99 lines
2.4 KiB
Go
99 lines
2.4 KiB
Go
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) + `"`
|
|
}
|