//go:build darwin && !appstore package startup import ( "fmt" "os" "os/exec" "path/filepath" "text/template" ) const plistTemplate = ` Label com.shanghai3168.privatevoicedictation ProgramArguments {{.ExePath}} RunAtLoad ` const launchAgentID = "com.shanghai3168.privatevoicedictation" var legacyLaunchAgentIDs = []string{"com.voicesnap.app"} func plistPath() string { return plistPathForID(launchAgentID) } func plistPathForID(id string) string { home, _ := os.UserHomeDir() return filepath.Join(home, "Library", "LaunchAgents", id+".plist") } func isEnabled() bool { removeLegacyPlists() _, err := os.Stat(plistPath()) return err == nil } func setEnabled(enable bool) error { path := plistPath() if !enable { if err := removePlist(path); err != nil { return err } removeLegacyPlists() return nil } removeLegacyPlists() exe, err := os.Executable() if err != nil { return err } dir := filepath.Dir(path) os.MkdirAll(dir, 0755) f, err := os.Create(path) if err != nil { return fmt.Errorf("failed to create plist: %w", err) } defer f.Close() tmpl := template.Must(template.New("plist").Parse(plistTemplate)) if err := tmpl.Execute(f, struct{ ExePath string }{exe}); err != nil { return err } return exec.Command("launchctl", "load", path).Run() } func removeLegacyPlists() { for _, id := range legacyLaunchAgentIDs { _ = removePlist(plistPathForID(id)) } } func removePlist(path string) error { exec.Command("launchctl", "unload", path).Run() if err := os.Remove(path); err != nil && !os.IsNotExist(err) { return err } return nil }