feat: 增强桌面启动失败提示与测试覆盖
This commit is contained in:
@@ -3,8 +3,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@@ -12,56 +13,99 @@ type dialogToolType int
|
||||
|
||||
const (
|
||||
toolNone dialogToolType = iota
|
||||
toolZenity
|
||||
toolKdialog
|
||||
toolNotifySend
|
||||
toolKdialogPassive
|
||||
toolZenity
|
||||
toolKdialogError
|
||||
toolXmessage
|
||||
)
|
||||
|
||||
var (
|
||||
dialogTool dialogToolType
|
||||
dialogToolOnce sync.Once
|
||||
dialogTools map[string]bool
|
||||
dialogToolOnce sync.Once
|
||||
dialogToolNames = []string{"notify-send", "kdialog", "zenity", "xmessage"}
|
||||
)
|
||||
|
||||
func init() {
|
||||
dialogToolOnce.Do(detectDialogTool)
|
||||
dialogToolOnce.Do(func() { detectDialogTools(defaultCommandRunner{}) })
|
||||
}
|
||||
|
||||
func detectDialogTool() {
|
||||
tools := []struct {
|
||||
name string
|
||||
typ dialogToolType
|
||||
}{
|
||||
{"zenity", toolZenity},
|
||||
{"kdialog", toolKdialog},
|
||||
{"notify-send", toolNotifySend},
|
||||
{"xmessage", toolXmessage},
|
||||
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)}
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
for _, tool := range tools {
|
||||
if _, err := exec.LookPath(tool.name); err == nil {
|
||||
dialogTool = tool.typ
|
||||
return
|
||||
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)
|
||||
}
|
||||
|
||||
dialogTool = toolNone
|
||||
_, err := runner.LookPath(name)
|
||||
return err
|
||||
}
|
||||
|
||||
func showError(title, message string) {
|
||||
switch dialogTool {
|
||||
case toolZenity:
|
||||
exec.Command("zenity", "--error",
|
||||
fmt.Sprintf("--title=%s", title),
|
||||
fmt.Sprintf("--text=%s", message)).Run()
|
||||
case toolKdialog:
|
||||
exec.Command("kdialog", "--error", message, "--title", title).Run()
|
||||
case toolNotifySend:
|
||||
exec.Command("notify-send", "-u", "critical", title, message).Run()
|
||||
case toolXmessage:
|
||||
exec.Command("xmessage", "-center",
|
||||
fmt.Sprintf("%s: %s", title, message)).Run()
|
||||
default:
|
||||
dialogLogger().Error("无法显示错误对话框")
|
||||
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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user