1
0
Files
nex/backend/cmd/desktop/dialog_linux.go

112 lines
3.1 KiB
Go

//go:build linux
package main
import (
"errors"
"fmt"
"os"
"sync"
)
type dialogToolType int
const (
toolNone dialogToolType = iota
toolNotifySend
toolKdialogPassive
toolZenity
toolKdialogError
toolXmessage
)
var (
dialogTools map[string]bool
dialogToolOnce sync.Once
dialogToolNames = []string{"notify-send", "kdialog", "zenity", "xmessage"}
)
func init() {
dialogToolOnce.Do(func() { detectDialogTools(defaultCommandRunner{}) })
}
func platformStartupChannels(runner commandRunner) []promptChannel {
return []promptChannel{
linuxCommandChannel("notify-send", toolNotifySend, runner, linuxHasGraphicalSessionAndDBus, func(req promptRequest) []string {
return []string{"-u", "critical", "-a", appName, "-i", "nex", req.title, req.message}
}),
linuxCommandChannel("kdialog", toolKdialogPassive, runner, linuxHasGraphicalSession, func(req promptRequest) []string {
return []string{"--title", req.title, "--passivepopup", req.message, "10"}
}),
linuxCommandChannel("zenity", toolZenity, runner, linuxHasGraphicalSession, func(req promptRequest) []string {
return []string{"--error", fmt.Sprintf("--title=%s", req.title), fmt.Sprintf("--text=%s", req.message)}
}),
linuxCommandChannel("kdialog", toolKdialogError, runner, linuxHasGraphicalSession, func(req promptRequest) []string {
return []string{"--title", req.title, "--error", req.message}
}),
linuxCommandChannel("xmessage", toolXmessage, runner, linuxHasX11Display, func(req promptRequest) []string {
return []string{"-center", "-buttons", "OK:0", "-default", "OK", fmt.Sprintf("%s: %s", req.title, req.message)}
}),
}
}
func detectDialogTools(runner commandRunner) {
dialogTools = make(map[string]bool, len(dialogToolNames))
for _, name := range dialogToolNames {
_, err := runner.LookPath(name)
dialogTools[name] = err == nil
}
}
func linuxCommandChannel(name string, typ dialogToolType, runner commandRunner, environmentOK func() error, args func(promptRequest) []string) promptChannel {
return promptChannel{
name: fmt.Sprintf("linux-%s-%d", name, typ),
available: func() error {
if err := linuxCommandAvailable(runner, name); err != nil {
return err
}
return environmentOK()
},
run: func(req promptRequest) error {
return runner.Run(promptCommandTimeout, nil, name, args(req)...)
},
}
}
func linuxCommandAvailable(runner commandRunner, name string) error {
if _, ok := runner.(defaultCommandRunner); ok {
dialogToolOnce.Do(func() { detectDialogTools(runner) })
if dialogTools[name] {
return nil
}
return fmt.Errorf("%s 不可用", name)
}
_, err := runner.LookPath(name)
return err
}
func linuxHasGraphicalSession() error {
if os.Getenv("DISPLAY") == "" && os.Getenv("WAYLAND_DISPLAY") == "" {
return errors.New("缺少图形会话")
}
return nil
}
func linuxHasGraphicalSessionAndDBus() error {
if err := linuxHasGraphicalSession(); err != nil {
return err
}
if os.Getenv("DBUS_SESSION_BUS_ADDRESS") == "" {
return errors.New("缺少 DBus session bus")
}
return nil
}
func linuxHasX11Display() error {
if os.Getenv("DISPLAY") == "" {
return errors.New("缺少 X11 DISPLAY")
}
return nil
}