//go:build darwin package filedialog import ( "os/exec" "strings" ) func appleScriptQuote(s string) string { s = strings.ReplaceAll(s, `\`, `\\`) return strings.ReplaceAll(s, `"`, `\"`) } // SaveJSON shows a Save As dialog for a .json file. func SaveJSON(title, defaultName string) (string, error) { if title == "" { title = "Сохранить список серверов" } if defaultName == "" { defaultName = "navis-servers.json" } script := `try set thePath to POSIX path of (choose file name with prompt "` + appleScriptQuote(title) + `" default name "` + appleScriptQuote(defaultName) + `") return thePath on error number -128 error "canceled" end try` out, err := exec.Command("osascript", "-e", script).Output() if err != nil { if strings.Contains(string(out), "canceled") || strings.Contains(err.Error(), "canceled") { return "", ErrCanceled } // osascript writes AppleScript errors to stderr; treat cancel-ish exits as cancel. if exit, ok := err.(*exec.ExitError); ok && exit.ExitCode() != 0 { msg := strings.ToLower(string(exit.Stderr) + string(out) + err.Error()) if strings.Contains(msg, "cancel") || strings.Contains(msg, "-128") { return "", ErrCanceled } } return "", err } path := strings.TrimSpace(string(out)) if path == "" { return "", ErrCanceled } if !strings.HasSuffix(strings.ToLower(path), ".json") { path += ".json" } return path, nil } // OpenJSON shows an Open dialog for a .json file. func OpenJSON(title string) (string, error) { if title == "" { title = "Загрузить список серверов" } script := `try set theFile to choose file with prompt "` + appleScriptQuote(title) + `" of type {"public.json", "json", "public.plain-text"} return POSIX path of theFile on error number -128 error "canceled" end try` out, err := exec.Command("osascript", "-e", script).Output() if err != nil { if exit, ok := err.(*exec.ExitError); ok { msg := strings.ToLower(string(exit.Stderr) + string(out) + err.Error()) if strings.Contains(msg, "cancel") || strings.Contains(msg, "-128") { return "", ErrCanceled } } return "", err } path := strings.TrimSpace(string(out)) if path == "" { return "", ErrCanceled } return path, nil }