mirror of
https://github.com/amnezia-vpn/amneziawg-windows-client.git
synced 2026-06-02 06:23:38 +02:00
ui: improve error handling
Signed-off-by: Alexander Neumann <an2048@gmail.com> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
committed by
Jason A. Donenfeld
parent
ee2c3f5a85
commit
0dce279a89
+44
-8
@@ -20,11 +20,22 @@ import (
|
||||
var easterEggIndex = -1
|
||||
|
||||
func onAbout(owner walk.Form) {
|
||||
showError(runAboutDialog(owner), owner)
|
||||
}
|
||||
|
||||
func runAboutDialog(owner walk.Form) error {
|
||||
vbl := walk.NewVBoxLayout()
|
||||
vbl.SetMargins(walk.Margins{80, 20, 80, 20})
|
||||
vbl.SetSpacing(10)
|
||||
|
||||
dlg, _ := walk.NewDialogWithFixedSize(owner)
|
||||
var disposables walk.Disposables
|
||||
defer disposables.Treat()
|
||||
|
||||
dlg, err := walk.NewDialogWithFixedSize(owner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
disposables.Add(dlg)
|
||||
dlg.SetTitle("About WireGuard")
|
||||
dlg.SetLayout(vbl)
|
||||
if icon, err := loadLogoIcon(32); err == nil {
|
||||
@@ -34,7 +45,10 @@ func onAbout(owner walk.Form) {
|
||||
font, _ := walk.NewFont("Segoe UI", 9, 0)
|
||||
dlg.SetFont(font)
|
||||
|
||||
iv, _ := walk.NewImageView(dlg)
|
||||
iv, err := walk.NewImageView(dlg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
iv.SetCursor(walk.CursorHand())
|
||||
iv.MouseUp().Attach(func(x, y int, button walk.MouseButton) {
|
||||
if button == walk.LeftButton {
|
||||
@@ -55,34 +69,52 @@ func onAbout(owner walk.Form) {
|
||||
iv.SetImage(logo)
|
||||
}
|
||||
|
||||
wgLbl, _ := walk.NewTextLabel(dlg)
|
||||
wgLbl, err := walk.NewTextLabel(dlg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wgFont, _ := walk.NewFont("Segoe UI", 16, walk.FontBold)
|
||||
wgLbl.SetFont(wgFont)
|
||||
wgLbl.SetTextAlignment(walk.AlignHCenterVNear)
|
||||
wgLbl.SetText("WireGuard")
|
||||
|
||||
detailsLbl, _ := walk.NewTextLabel(dlg)
|
||||
detailsLbl, err := walk.NewTextLabel(dlg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
detailsLbl.SetTextAlignment(walk.AlignHCenterVNear)
|
||||
detailsLbl.SetText(fmt.Sprintf("App version: %s\nGo backend version: %s\nGo version: %s\nOperating system: %s\nArchitecture: %s", version.RunningVersion(), device.WireGuardGoVersion, strings.TrimPrefix(runtime.Version(), "go"), version.OsName(), runtime.GOARCH))
|
||||
|
||||
copyrightLbl, _ := walk.NewTextLabel(dlg)
|
||||
copyrightLbl, err := walk.NewTextLabel(dlg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
copyrightFont, _ := walk.NewFont("Segoe UI", 7, 0)
|
||||
copyrightLbl.SetFont(copyrightFont)
|
||||
copyrightLbl.SetTextAlignment(walk.AlignHCenterVNear)
|
||||
copyrightLbl.SetText("Copyright © 2015-2019 Jason A. Donenfeld. All Rights Reserved.")
|
||||
|
||||
buttonCP, _ := walk.NewComposite(dlg)
|
||||
buttonCP, err := walk.NewComposite(dlg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hbl := walk.NewHBoxLayout()
|
||||
hbl.SetMargins(walk.Margins{VNear: 10})
|
||||
buttonCP.SetLayout(hbl)
|
||||
walk.NewHSpacer(buttonCP)
|
||||
closePB, _ := walk.NewPushButton(buttonCP)
|
||||
closePB, err := walk.NewPushButton(buttonCP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
closePB.SetAlignment(walk.AlignHCenterVNear)
|
||||
closePB.SetText("Close")
|
||||
closePB.Clicked().Attach(func() {
|
||||
dlg.Accept()
|
||||
})
|
||||
donatePB, _ := walk.NewPushButton(buttonCP)
|
||||
donatePB, err := walk.NewPushButton(buttonCP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
donatePB.SetAlignment(walk.AlignHCenterVNear)
|
||||
donatePB.SetText("♥ Donate!")
|
||||
donatePB.Clicked().Attach(func() {
|
||||
@@ -97,5 +129,9 @@ func onAbout(owner walk.Form) {
|
||||
dlg.SetDefaultButton(donatePB)
|
||||
dlg.SetCancelButton(closePB)
|
||||
|
||||
disposables.Spare()
|
||||
|
||||
dlg.Run()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
+181
-61
@@ -98,25 +98,46 @@ func (lsl *labelStatusLine) update(state manager.TunnelState) {
|
||||
lsl.statusLabel.SetTextSelection(s, e)
|
||||
}
|
||||
|
||||
func newLabelStatusLine(parent walk.Container) *labelStatusLine {
|
||||
func (lsl *labelStatusLine) Dispose() {
|
||||
lsl.label.Dispose()
|
||||
lsl.statusComposite.Dispose()
|
||||
}
|
||||
|
||||
func newLabelStatusLine(parent walk.Container) (*labelStatusLine, error) {
|
||||
var err error
|
||||
var disposables walk.Disposables
|
||||
defer disposables.Treat()
|
||||
|
||||
lsl := new(labelStatusLine)
|
||||
|
||||
lsl.label, _ = walk.NewTextLabel(parent)
|
||||
if lsl.label, err = walk.NewTextLabel(parent); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disposables.Add(lsl.label)
|
||||
lsl.label.SetText("Status:")
|
||||
lsl.label.SetTextAlignment(walk.AlignHFarVNear)
|
||||
|
||||
lsl.statusComposite, _ = walk.NewComposite(parent)
|
||||
if lsl.statusComposite, err = walk.NewComposite(parent); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disposables.Add(lsl.statusComposite)
|
||||
layout := walk.NewHBoxLayout()
|
||||
layout.SetMargins(walk.Margins{})
|
||||
layout.SetAlignment(walk.AlignHNearVNear)
|
||||
layout.SetSpacing(0)
|
||||
lsl.statusComposite.SetLayout(layout)
|
||||
|
||||
lsl.statusImage, _ = walk.NewImageView(lsl.statusComposite)
|
||||
if lsl.statusImage, err = walk.NewImageView(lsl.statusComposite); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disposables.Add(lsl.statusImage)
|
||||
lsl.statusImage.SetMargin(2)
|
||||
lsl.statusImage.SetMode(walk.ImageViewModeIdeal)
|
||||
|
||||
lsl.statusLabel, _ = walk.NewLineEdit(lsl.statusComposite)
|
||||
if lsl.statusLabel, err = walk.NewLineEdit(lsl.statusComposite); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disposables.Add(lsl.statusLabel)
|
||||
win.SetWindowLong(lsl.statusLabel.Handle(), win.GWL_EXSTYLE, win.GetWindowLong(lsl.statusLabel.Handle(), win.GWL_EXSTYLE)&^win.WS_EX_CLIENTEDGE)
|
||||
lsl.statusLabel.SetReadOnly(true)
|
||||
lsl.statusLabel.SetBackground(walk.NullBrush())
|
||||
@@ -125,7 +146,9 @@ func newLabelStatusLine(parent walk.Container) *labelStatusLine {
|
||||
})
|
||||
lsl.update(manager.TunnelUnknown)
|
||||
|
||||
return lsl
|
||||
disposables.Spare()
|
||||
|
||||
return lsl, nil
|
||||
}
|
||||
|
||||
func (lt *labelTextLine) widgets() (walk.Widget, walk.Widget) {
|
||||
@@ -146,14 +169,30 @@ func (lt *labelTextLine) hide() {
|
||||
lt.text.SetVisible(false)
|
||||
}
|
||||
|
||||
func newLabelTextLine(fieldName string, parent walk.Container) *labelTextLine {
|
||||
func (lt *labelTextLine) Dispose() {
|
||||
lt.label.Dispose()
|
||||
lt.text.Dispose()
|
||||
}
|
||||
|
||||
func newLabelTextLine(fieldName string, parent walk.Container) (*labelTextLine, error) {
|
||||
var err error
|
||||
var disposables walk.Disposables
|
||||
defer disposables.Treat()
|
||||
|
||||
lt := new(labelTextLine)
|
||||
lt.label, _ = walk.NewTextLabel(parent)
|
||||
|
||||
if lt.label, err = walk.NewTextLabel(parent); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disposables.Add(lt.label)
|
||||
lt.label.SetText(fieldName + ":")
|
||||
lt.label.SetTextAlignment(walk.AlignHFarVNear)
|
||||
lt.label.SetVisible(false)
|
||||
|
||||
lt.text, _ = walk.NewTextEdit(parent)
|
||||
if lt.text, err = walk.NewTextEdit(parent); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disposables.Add(lt.text)
|
||||
win.SetWindowLong(lt.text.Handle(), win.GWL_EXSTYLE, win.GetWindowLong(lt.text.Handle(), win.GWL_EXSTYLE)&^win.WS_EX_CLIENTEDGE)
|
||||
lt.text.SetCompactHeight(true)
|
||||
lt.text.SetReadOnly(true)
|
||||
@@ -162,7 +201,10 @@ func newLabelTextLine(fieldName string, parent walk.Container) *labelTextLine {
|
||||
lt.text.FocusedChanged().Attach(func() {
|
||||
lt.text.SetTextSelection(0, 0)
|
||||
})
|
||||
return lt
|
||||
|
||||
disposables.Spare()
|
||||
|
||||
return lt, nil
|
||||
}
|
||||
|
||||
func (tal *toggleActiveLine) widgets() (walk.Widget, walk.Widget) {
|
||||
@@ -191,67 +233,121 @@ func (tal *toggleActiveLine) update(state manager.TunnelState) {
|
||||
tal.button.SetVisible(state != manager.TunnelUnknown)
|
||||
}
|
||||
|
||||
func newToggleActiveLine(parent walk.Container) *toggleActiveLine {
|
||||
func (tal *toggleActiveLine) Dispose() {
|
||||
tal.composite.Dispose()
|
||||
}
|
||||
|
||||
func newToggleActiveLine(parent walk.Container) (*toggleActiveLine, error) {
|
||||
var err error
|
||||
var disposables walk.Disposables
|
||||
defer disposables.Treat()
|
||||
|
||||
tal := new(toggleActiveLine)
|
||||
|
||||
tal.composite, _ = walk.NewComposite(parent)
|
||||
if tal.composite, err = walk.NewComposite(parent); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disposables.Add(tal.composite)
|
||||
layout := walk.NewHBoxLayout()
|
||||
layout.SetMargins(walk.Margins{0, 0, 0, 6})
|
||||
tal.composite.SetLayout(layout)
|
||||
|
||||
tal.button, _ = walk.NewPushButton(tal.composite)
|
||||
if tal.button, err = walk.NewPushButton(tal.composite); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disposables.Add(tal.button)
|
||||
walk.NewHSpacer(tal.composite)
|
||||
tal.update(manager.TunnelStopped)
|
||||
|
||||
return tal
|
||||
disposables.Spare()
|
||||
|
||||
return tal, nil
|
||||
}
|
||||
|
||||
func newInterfaceView(parent walk.Container) *interfaceView {
|
||||
iv := &interfaceView{
|
||||
newLabelStatusLine(parent),
|
||||
newLabelTextLine("Public key", parent),
|
||||
newLabelTextLine("Listen port", parent),
|
||||
newLabelTextLine("MTU", parent),
|
||||
newLabelTextLine("Addresses", parent),
|
||||
newLabelTextLine("DNS servers", parent),
|
||||
newToggleActiveLine(parent),
|
||||
nil,
|
||||
type labelTextLineItem struct {
|
||||
label string
|
||||
ptr **labelTextLine
|
||||
}
|
||||
|
||||
func createLabelTextLines(items []labelTextLineItem, parent walk.Container, disposables *walk.Disposables) ([]widgetsLine, error) {
|
||||
var err error
|
||||
var disps walk.Disposables
|
||||
defer disps.Treat()
|
||||
|
||||
wls := make([]widgetsLine, len(items))
|
||||
for i, item := range items {
|
||||
if *item.ptr, err = newLabelTextLine(item.label, parent); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disps.Add(*item.ptr)
|
||||
if disposables != nil {
|
||||
disposables.Add(*item.ptr)
|
||||
}
|
||||
wls[i] = *item.ptr
|
||||
}
|
||||
iv.lines = []widgetsLine{
|
||||
iv.status,
|
||||
iv.publicKey,
|
||||
iv.listenPort,
|
||||
iv.mtu,
|
||||
iv.addresses,
|
||||
iv.dns,
|
||||
iv.toggleActive,
|
||||
|
||||
disps.Spare()
|
||||
|
||||
return wls, nil
|
||||
}
|
||||
|
||||
func newInterfaceView(parent walk.Container) (*interfaceView, error) {
|
||||
var err error
|
||||
var disposables walk.Disposables
|
||||
defer disposables.Treat()
|
||||
|
||||
iv := new(interfaceView)
|
||||
|
||||
if iv.status, err = newLabelStatusLine(parent); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disposables.Add(iv.status)
|
||||
|
||||
items := []labelTextLineItem{
|
||||
{"Public key", &iv.publicKey},
|
||||
{"Listen port", &iv.listenPort},
|
||||
{"MTU", &iv.mtu},
|
||||
{"Addresses", &iv.addresses},
|
||||
{"DNS servers", &iv.dns},
|
||||
}
|
||||
if iv.lines, err = createLabelTextLines(items, parent, &disposables); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if iv.toggleActive, err = newToggleActiveLine(parent); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disposables.Add(iv.toggleActive)
|
||||
|
||||
iv.lines = append([]widgetsLine{iv.status}, append(iv.lines, iv.toggleActive)...)
|
||||
|
||||
layoutInGrid(iv, parent.Layout().(*walk.GridLayout))
|
||||
return iv
|
||||
|
||||
disposables.Spare()
|
||||
|
||||
return iv, nil
|
||||
}
|
||||
|
||||
func newPeerView(parent walk.Container) *peerView {
|
||||
pv := &peerView{
|
||||
newLabelTextLine("Public key", parent),
|
||||
newLabelTextLine("Preshared key", parent),
|
||||
newLabelTextLine("Allowed IPs", parent),
|
||||
newLabelTextLine("Endpoint", parent),
|
||||
newLabelTextLine("Persistent keepalive", parent),
|
||||
newLabelTextLine("Latest handshake", parent),
|
||||
newLabelTextLine("Transfer", parent),
|
||||
nil,
|
||||
func newPeerView(parent walk.Container) (*peerView, error) {
|
||||
pv := new(peerView)
|
||||
|
||||
items := []labelTextLineItem{
|
||||
{"Public key", &pv.publicKey},
|
||||
{"Preshared key", &pv.presharedKey},
|
||||
{"Allowed IPs", &pv.allowedIPs},
|
||||
{"Endpoint", &pv.endpoint},
|
||||
{"Persistent keepalive", &pv.persistentKeepalive},
|
||||
{"Latest handshake", &pv.latestHandshake},
|
||||
{"Transfer", &pv.transfer},
|
||||
}
|
||||
pv.lines = []widgetsLine{
|
||||
pv.publicKey,
|
||||
pv.presharedKey,
|
||||
pv.allowedIPs,
|
||||
pv.endpoint,
|
||||
pv.persistentKeepalive,
|
||||
pv.latestHandshake,
|
||||
pv.transfer,
|
||||
var err error
|
||||
if pv.lines, err = createLabelTextLines(items, parent, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
layoutInGrid(pv, parent.Layout().(*walk.GridLayout))
|
||||
return pv
|
||||
|
||||
return pv, nil
|
||||
}
|
||||
|
||||
func layoutInGrid(view widgetsLinesView, layout *walk.GridLayout) {
|
||||
@@ -381,18 +477,32 @@ func newPaddedGroupGrid(parent walk.Container) (group *walk.GroupBox, err error)
|
||||
}
|
||||
|
||||
func NewConfView(parent walk.Container) (*ConfView, error) {
|
||||
var err error
|
||||
var disposables walk.Disposables
|
||||
defer disposables.Treat()
|
||||
|
||||
cv := new(ConfView)
|
||||
cv.ScrollView, _ = walk.NewScrollView(parent)
|
||||
if cv.ScrollView, err = walk.NewScrollView(parent); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disposables.Add(cv)
|
||||
vlayout := walk.NewVBoxLayout()
|
||||
vlayout.SetMargins(walk.Margins{5, 0, 5, 0})
|
||||
cv.SetLayout(vlayout)
|
||||
cv.name, _ = newPaddedGroupGrid(cv)
|
||||
cv.interfaze = newInterfaceView(cv.name)
|
||||
if cv.name, err = newPaddedGroupGrid(cv); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cv.interfaze, err = newInterfaceView(cv.name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cv.interfaze.toggleActive.button.Clicked().Attach(cv.onToggleActiveClicked)
|
||||
cv.peers = make(map[conf.Key]*peerView)
|
||||
cv.tunnelChangedCB = manager.IPCClientRegisterTunnelChange(cv.onTunnelChanged)
|
||||
cv.SetTunnel(nil)
|
||||
globalState, _ := manager.IPCClientGlobalState()
|
||||
globalState, err := manager.IPCClientGlobalState()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cv.interfaze.toggleActive.updateGlobal(globalState)
|
||||
|
||||
if err := walk.InitWrapperWindow(cv); err != nil {
|
||||
@@ -421,6 +531,9 @@ func NewConfView(parent walk.Container) (*ConfView, error) {
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
disposables.Spare()
|
||||
|
||||
return cv, nil
|
||||
}
|
||||
|
||||
@@ -443,11 +556,11 @@ func (cv *ConfView) onToggleActiveClicked() {
|
||||
if err != nil {
|
||||
cv.Synchronize(func() {
|
||||
if oldState == manager.TunnelUnknown {
|
||||
walk.MsgBox(cv.Form(), "Failed to determine tunnel state", err.Error(), walk.MsgBoxIconError)
|
||||
showErrorCustom(cv.Form(), "Failed to determine tunnel state", err.Error())
|
||||
} else if oldState == manager.TunnelStopped {
|
||||
walk.MsgBox(cv.Form(), "Failed to activate tunnel", err.Error(), walk.MsgBoxIconError)
|
||||
showErrorCustom(cv.Form(), "Failed to activate tunnel", err.Error())
|
||||
} else if oldState == manager.TunnelStarted {
|
||||
walk.MsgBox(cv.Form(), "Failed to deactivate tunnel", err.Error(), walk.MsgBoxIconError)
|
||||
showErrorCustom(cv.Form(), "Failed to deactivate tunnel", err.Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -543,9 +656,16 @@ func (cv *ConfView) setTunnel(tunnel *manager.Tunnel, config *conf.Config, state
|
||||
pv.apply(&peer)
|
||||
inverse[pv] = false
|
||||
} else {
|
||||
group, _ := newPaddedGroupGrid(cv)
|
||||
group, err := newPaddedGroupGrid(cv)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
group.SetTitle("Peer")
|
||||
pv := newPeerView(group)
|
||||
pv, err := newPeerView(group)
|
||||
if err != nil {
|
||||
group.Dispose()
|
||||
continue
|
||||
}
|
||||
pv.apply(&peer)
|
||||
cv.peers[peer.PublicKey] = pv
|
||||
}
|
||||
|
||||
+62
-22
@@ -28,8 +28,25 @@ type EditDialog struct {
|
||||
blockUntunneledTraficCheckGuard bool
|
||||
}
|
||||
|
||||
func runTunnelEditDialog(owner walk.Form, tunnel *manager.Tunnel) *conf.Config {
|
||||
dlg := &EditDialog{}
|
||||
func runEditDialog(owner walk.Form, tunnel *manager.Tunnel) *conf.Config {
|
||||
dlg, err := newEditDialog(owner, tunnel)
|
||||
if showError(err, owner) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if dlg.Run() == walk.DlgCmdOK {
|
||||
return &dlg.config
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func newEditDialog(owner walk.Form, tunnel *manager.Tunnel) (*EditDialog, error) {
|
||||
var err error
|
||||
var disposables walk.Disposables
|
||||
defer disposables.Treat()
|
||||
|
||||
dlg := new(EditDialog)
|
||||
|
||||
var title string
|
||||
if tunnel == nil {
|
||||
@@ -51,7 +68,10 @@ func runTunnelEditDialog(owner walk.Form, tunnel *manager.Tunnel) *conf.Config {
|
||||
layout.SetMargins(walk.Margins{10, 10, 10, 10})
|
||||
layout.SetColumnStretchFactor(1, 3)
|
||||
|
||||
dlg.Dialog, _ = walk.NewDialog(owner)
|
||||
if dlg.Dialog, err = walk.NewDialog(owner); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disposables.Add(dlg)
|
||||
dlg.SetIcon(owner.Icon())
|
||||
dlg.SetTitle(title)
|
||||
dlg.SetLayout(layout)
|
||||
@@ -60,34 +80,51 @@ func runTunnelEditDialog(owner walk.Form, tunnel *manager.Tunnel) *conf.Config {
|
||||
dlg.SetIcon(icon)
|
||||
}
|
||||
|
||||
nameLabel, _ := walk.NewTextLabel(dlg)
|
||||
nameLabel, err := walk.NewTextLabel(dlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
layout.SetRange(nameLabel, walk.Rectangle{0, 0, 1, 1})
|
||||
nameLabel.SetTextAlignment(walk.AlignHFarVCenter)
|
||||
nameLabel.SetText("Name:")
|
||||
|
||||
dlg.nameEdit, _ = walk.NewLineEdit(dlg)
|
||||
if dlg.nameEdit, err = walk.NewLineEdit(dlg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
layout.SetRange(dlg.nameEdit, walk.Rectangle{1, 0, 1, 1})
|
||||
dlg.nameEdit.SetText(dlg.config.Name)
|
||||
|
||||
pubkeyLabel, _ := walk.NewTextLabel(dlg)
|
||||
pubkeyLabel, err := walk.NewTextLabel(dlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
layout.SetRange(pubkeyLabel, walk.Rectangle{0, 1, 1, 1})
|
||||
pubkeyLabel.SetTextAlignment(walk.AlignHFarVCenter)
|
||||
pubkeyLabel.SetText("Public key:")
|
||||
|
||||
dlg.pubkeyEdit, _ = walk.NewLineEdit(dlg)
|
||||
if dlg.pubkeyEdit, err = walk.NewLineEdit(dlg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
layout.SetRange(dlg.pubkeyEdit, walk.Rectangle{1, 1, 1, 1})
|
||||
dlg.pubkeyEdit.SetReadOnly(true)
|
||||
dlg.pubkeyEdit.SetText("(unknown)")
|
||||
|
||||
dlg.syntaxEdit, _ = syntax.NewSyntaxEdit(dlg)
|
||||
if dlg.syntaxEdit, err = syntax.NewSyntaxEdit(dlg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
layout.SetRange(dlg.syntaxEdit, walk.Rectangle{0, 2, 2, 1})
|
||||
|
||||
buttonsContainer, _ := walk.NewComposite(dlg)
|
||||
buttonsContainer, err := walk.NewComposite(dlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
layout.SetRange(buttonsContainer, walk.Rectangle{0, 3, 2, 1})
|
||||
buttonsContainer.SetLayout(walk.NewHBoxLayout())
|
||||
buttonsContainer.Layout().SetMargins(walk.Margins{})
|
||||
|
||||
dlg.blockUntunneledTrafficCB, _ = walk.NewCheckBox(buttonsContainer)
|
||||
if dlg.blockUntunneledTrafficCB, err = walk.NewCheckBox(buttonsContainer); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dlg.blockUntunneledTrafficCB.SetText("Block untunneled traffic (kill-switch)")
|
||||
dlg.blockUntunneledTrafficCB.SetToolTipText("When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface, with special exceptions for DHCP and NDP.")
|
||||
dlg.blockUntunneledTrafficCB.SetVisible(false)
|
||||
@@ -95,11 +132,16 @@ func runTunnelEditDialog(owner walk.Form, tunnel *manager.Tunnel) *conf.Config {
|
||||
|
||||
walk.NewHSpacer(buttonsContainer)
|
||||
|
||||
dlg.saveButton, _ = walk.NewPushButton(buttonsContainer)
|
||||
if dlg.saveButton, err = walk.NewPushButton(buttonsContainer); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dlg.saveButton.SetText("Save")
|
||||
dlg.saveButton.Clicked().Attach(dlg.onSaveButtonClicked)
|
||||
|
||||
cancelButton, _ := walk.NewPushButton(buttonsContainer)
|
||||
cancelButton, err := walk.NewPushButton(buttonsContainer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cancelButton.SetText("Cancel")
|
||||
cancelButton.Clicked().Attach(dlg.Cancel)
|
||||
|
||||
@@ -118,11 +160,9 @@ func runTunnelEditDialog(owner walk.Form, tunnel *manager.Tunnel) *conf.Config {
|
||||
})
|
||||
}
|
||||
|
||||
if dlg.Run() == walk.DlgCmdOK {
|
||||
return &dlg.config
|
||||
}
|
||||
disposables.Spare()
|
||||
|
||||
return nil
|
||||
return dlg, nil
|
||||
}
|
||||
|
||||
func (dlg *EditDialog) onBlockUntunneledTrafficCBCheckedChanged() {
|
||||
@@ -217,7 +257,7 @@ func (dlg *EditDialog) onBlockUntunneledTrafficCBCheckedChanged() {
|
||||
return
|
||||
|
||||
err:
|
||||
walk.MsgBox(dlg, "Invalid configuration", "Unable to toggle untunneled traffic blocking state.", walk.MsgBoxIconWarning)
|
||||
showErrorCustom(dlg, "Invalid configuration", "Unable to toggle untunneled traffic blocking state.")
|
||||
dlg.blockUntunneledTrafficCB.SetVisible(false)
|
||||
}
|
||||
|
||||
@@ -252,11 +292,11 @@ func (dlg *EditDialog) onSyntaxEditPrivateKeyChanged(privateKey string) {
|
||||
func (dlg *EditDialog) onSaveButtonClicked() {
|
||||
newName := dlg.nameEdit.Text()
|
||||
if newName == "" {
|
||||
walk.MsgBox(dlg, "Invalid name", "A name is required.", walk.MsgBoxIconWarning)
|
||||
showWarningCustom(dlg, "Invalid name", "A name is required.")
|
||||
return
|
||||
}
|
||||
if !conf.TunnelNameIsValid(newName) {
|
||||
walk.MsgBox(dlg, "Invalid name", fmt.Sprintf("Tunnel name ‘%s’ is invalid.", newName), walk.MsgBoxIconWarning)
|
||||
showWarningCustom(dlg, "Invalid name", fmt.Sprintf("Tunnel name ‘%s’ is invalid.", newName))
|
||||
return
|
||||
}
|
||||
newNameLower := strings.ToLower(newName)
|
||||
@@ -264,12 +304,12 @@ func (dlg *EditDialog) onSaveButtonClicked() {
|
||||
if newNameLower != strings.ToLower(dlg.config.Name) {
|
||||
existingTunnelList, err := manager.IPCClientTunnels()
|
||||
if err != nil {
|
||||
walk.MsgBox(dlg, "Unable to list existing tunnels", err.Error(), walk.MsgBoxIconError)
|
||||
showWarningCustom(dlg, "Unable to list existing tunnels", err.Error())
|
||||
return
|
||||
}
|
||||
for _, tunnel := range existingTunnelList {
|
||||
if strings.ToLower(tunnel.Name) == newNameLower {
|
||||
walk.MsgBox(dlg, "Tunnel already exists", fmt.Sprintf("Another tunnel already exists with the name ‘%s’.", newName), walk.MsgBoxIconWarning)
|
||||
showWarningCustom(dlg, "Tunnel already exists", fmt.Sprintf("Another tunnel already exists with the name ‘%s’.", newName))
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -277,7 +317,7 @@ func (dlg *EditDialog) onSaveButtonClicked() {
|
||||
|
||||
cfg, err := conf.FromWgQuick(dlg.syntaxEdit.Text(), newName)
|
||||
if err != nil {
|
||||
walk.MsgBox(dlg, "Unable to create new configuration", err.Error(), walk.MsgBoxIconError)
|
||||
showErrorCustom(dlg, "Unable to create new configuration", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ func writeFileWithOverwriteHandling(owner walk.Form, filePath string, write func
|
||||
return false
|
||||
}
|
||||
|
||||
walk.MsgBox(owner, "Writing file failed", err.Error(), walk.MsgBoxIconError)
|
||||
showErrorCustom(owner, "Writing file failed", err.Error())
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
+6
-3
@@ -24,11 +24,10 @@ const (
|
||||
func NewLogPage() (*LogPage, error) {
|
||||
lp := &LogPage{}
|
||||
|
||||
var err error
|
||||
var disposables walk.Disposables
|
||||
defer disposables.Treat()
|
||||
|
||||
var err error
|
||||
|
||||
if lp.TabPage, err = walk.NewTabPage(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -47,7 +46,11 @@ func NewLogPage() (*LogPage, error) {
|
||||
lp.logView.SetAlternatingRowBGColor(walk.Color(win.GetSysColor(win.COLOR_BTNFACE)))
|
||||
lp.logView.SetLastColumnStretched(true)
|
||||
|
||||
contextMenu, _ := walk.NewMenu()
|
||||
contextMenu, err := walk.NewMenu()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lp.logView.AddDisposable(contextMenu)
|
||||
copyAction := walk.NewAction()
|
||||
copyAction.SetText("&Copy")
|
||||
copyAction.SetShortcut(walk.Shortcut{walk.ModControl, walk.KeyC})
|
||||
|
||||
+9
-3
@@ -40,6 +40,8 @@ func init() {
|
||||
|
||||
func NewManageTunnelsWindow() (*ManageTunnelsWindow, error) {
|
||||
var err error
|
||||
var disposables walk.Disposables
|
||||
defer disposables.Treat()
|
||||
|
||||
font, err := walk.NewFont("Segoe UI", 9, 0)
|
||||
if err != nil {
|
||||
@@ -53,6 +55,7 @@ func NewManageTunnelsWindow() (*ManageTunnelsWindow, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disposables.Add(mtw)
|
||||
win.ChangeWindowMessageFilterEx(mtw.Handle(), raiseMsg, win.MSGFLT_ALLOW, nil)
|
||||
mtw.SetPersistent(true)
|
||||
|
||||
@@ -60,7 +63,6 @@ func NewManageTunnelsWindow() (*ManageTunnelsWindow, error) {
|
||||
mtw.SetIcon(icon)
|
||||
}
|
||||
mtw.SetTitle("WireGuard")
|
||||
mtw.AddDisposable(font)
|
||||
mtw.SetFont(font)
|
||||
mtw.SetSize(walk.Size{670, 525})
|
||||
mtw.SetMinMaxSize(walk.Size{500, 400}, walk.Size{0, 0})
|
||||
@@ -85,7 +87,9 @@ func NewManageTunnelsWindow() (*ManageTunnelsWindow, error) {
|
||||
}
|
||||
})
|
||||
|
||||
mtw.tabs, _ = walk.NewTabWidget(mtw)
|
||||
if mtw.tabs, err = walk.NewTabWidget(mtw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if mtw.tunnelsPage, err = NewTunnelsPage(); err != nil {
|
||||
return nil, err
|
||||
@@ -118,6 +122,8 @@ func NewManageTunnelsWindow() (*ManageTunnelsWindow, error) {
|
||||
})
|
||||
}
|
||||
|
||||
disposables.Spare()
|
||||
|
||||
return mtw, nil
|
||||
}
|
||||
|
||||
@@ -157,7 +163,7 @@ func (mtw *ManageTunnelsWindow) onTunnelChange(tunnel *manager.Tunnel, state man
|
||||
if len(errMsg) > 0 && errMsg[len(errMsg)-1] != '.' {
|
||||
errMsg += "."
|
||||
}
|
||||
walk.MsgBox(mtw, "Tunnel Error", errMsg+"\n\nPlease consult the log for more information.", walk.MsgBoxIconWarning)
|
||||
showWarningCustom(mtw, "Tunnel Error", errMsg+"\n\nPlease consult the log for more information.")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
+1
-2
@@ -10,7 +10,6 @@ import (
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/lxn/walk"
|
||||
"github.com/lxn/win"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
@@ -54,7 +53,7 @@ func WaitForRaiseUIThenQuit() {
|
||||
return 0
|
||||
}, 0, 0, win.WINEVENT_SKIPOWNPROCESS|win.WINEVENT_OUTOFCONTEXT)
|
||||
if err != nil {
|
||||
walk.MsgBox(nil, "WireGuard Detection Error", fmt.Sprintf("Unable to wait for WireGuard window to appear: %v", err), walk.MsgBoxIconError)
|
||||
showErrorCustom(nil, "WireGuard Detection Error", fmt.Sprintf("Unable to wait for WireGuard window to appear: %v", err))
|
||||
}
|
||||
for {
|
||||
var msg win.MSG
|
||||
|
||||
+3
-3
@@ -160,11 +160,11 @@ func (tray *Tray) addTunnelAction(tunnel *manager.Tunnel) {
|
||||
tray.mtw.tunnelsPage.listView.selectTunnel(tclosure.Name)
|
||||
tray.mtw.tabs.SetCurrentIndex(0)
|
||||
if oldState == manager.TunnelUnknown {
|
||||
walk.MsgBox(tray.mtw, "Failed to determine tunnel state", err.Error(), walk.MsgBoxIconError)
|
||||
showErrorCustom(tray.mtw, "Failed to determine tunnel state", err.Error())
|
||||
} else if oldState == manager.TunnelStopped {
|
||||
walk.MsgBox(tray.mtw, "Failed to activate tunnel", err.Error(), walk.MsgBoxIconError)
|
||||
showErrorCustom(tray.mtw, "Failed to activate tunnel", err.Error())
|
||||
} else if oldState == manager.TunnelStarted {
|
||||
walk.MsgBox(tray.mtw, "Failed to deactivate tunnel", err.Error(), walk.MsgBoxIconError)
|
||||
showErrorCustom(tray.mtw, "Failed to deactivate tunnel", err.Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
+45
-22
@@ -36,7 +36,6 @@ type TunnelsPage struct {
|
||||
|
||||
func NewTunnelsPage() (*TunnelsPage, error) {
|
||||
var err error
|
||||
|
||||
var disposables walk.Disposables
|
||||
defer disposables.Treat()
|
||||
|
||||
@@ -55,18 +54,20 @@ func NewTunnelsPage() (*TunnelsPage, error) {
|
||||
vlayout.SetSpacing(0)
|
||||
tp.listContainer.SetLayout(vlayout)
|
||||
|
||||
// TODO: deal with remaining disposables in case the next line fails
|
||||
|
||||
if tp.listView, err = NewListView(tp.listContainer); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tp.currentTunnelContainer, _ = walk.NewComposite(tp)
|
||||
if tp.currentTunnelContainer, err = walk.NewComposite(tp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vlayout = walk.NewVBoxLayout()
|
||||
vlayout.SetMargins(walk.Margins{})
|
||||
tp.currentTunnelContainer.SetLayout(vlayout)
|
||||
|
||||
tp.fillerContainer, _ = walk.NewComposite(tp)
|
||||
if tp.fillerContainer, err = walk.NewComposite(tp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tp.fillerContainer.SetVisible(false)
|
||||
hlayout := walk.NewHBoxLayout()
|
||||
hlayout.SetMargins(walk.Margins{})
|
||||
@@ -79,15 +80,23 @@ func NewTunnelsPage() (*TunnelsPage, error) {
|
||||
}
|
||||
})
|
||||
|
||||
tp.confView, _ = NewConfView(tp.currentTunnelContainer)
|
||||
if tp.confView, err = NewConfView(tp.currentTunnelContainer); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
controlsContainer, _ := walk.NewComposite(tp.currentTunnelContainer)
|
||||
controlsContainer, err := walk.NewComposite(tp.currentTunnelContainer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
controlsContainer.SetLayout(walk.NewHBoxLayout())
|
||||
controlsContainer.Layout().SetMargins(walk.Margins{})
|
||||
|
||||
walk.NewHSpacer(controlsContainer)
|
||||
|
||||
editTunnel, _ := walk.NewPushButton(controlsContainer)
|
||||
editTunnel, err := walk.NewPushButton(controlsContainer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
editTunnel.SetEnabled(false)
|
||||
tp.listView.CurrentIndexChanged().Attach(func() {
|
||||
editTunnel.SetEnabled(tp.listView.CurrentIndex() > -1)
|
||||
@@ -107,22 +116,30 @@ func NewTunnelsPage() (*TunnelsPage, error) {
|
||||
return tp, nil
|
||||
}
|
||||
|
||||
func (tp *TunnelsPage) CreateToolbar() {
|
||||
func (tp *TunnelsPage) CreateToolbar() error {
|
||||
if tp.listToolbar != nil {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
// HACK: Because of https://github.com/lxn/walk/issues/481
|
||||
// we need to put the ToolBar into its own Composite.
|
||||
toolBarContainer, _ := walk.NewComposite(tp.listContainer)
|
||||
toolBarContainer, err := walk.NewComposite(tp.listContainer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
toolBarContainer.SetDoubleBuffering(true)
|
||||
hlayout := walk.NewHBoxLayout()
|
||||
hlayout.SetMargins(walk.Margins{})
|
||||
toolBarContainer.SetLayout(hlayout)
|
||||
|
||||
tp.listToolbar, _ = walk.NewToolBarWithOrientationAndButtonStyle(toolBarContainer, walk.Horizontal, walk.ToolBarButtonImageBeforeText)
|
||||
if tp.listToolbar, err = walk.NewToolBarWithOrientationAndButtonStyle(toolBarContainer, walk.Horizontal, walk.ToolBarButtonImageBeforeText); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addMenu, _ := walk.NewMenu()
|
||||
addMenu, err := walk.NewMenu()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tp.AddDisposable(addMenu)
|
||||
importAction := walk.NewAction()
|
||||
importAction.SetText("Import tunnel(s) from file...")
|
||||
@@ -172,7 +189,11 @@ func (tp *TunnelsPage) CreateToolbar() {
|
||||
fixContainerWidthToToolbarWidth()
|
||||
tp.listToolbar.SizeChanged().Attach(fixContainerWidthToToolbarWidth)
|
||||
|
||||
contextMenu, _ := walk.NewMenu()
|
||||
contextMenu, err := walk.NewMenu()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tp.listView.AddDisposable(contextMenu)
|
||||
toggleAction := walk.NewAction()
|
||||
toggleAction.SetText("&Toggle")
|
||||
toggleAction.SetDefault(true)
|
||||
@@ -238,6 +259,8 @@ func (tp *TunnelsPage) CreateToolbar() {
|
||||
tp.listView.model.RowsRemoved().Attach(setExportRange)
|
||||
tp.listView.model.RowsReset().Attach(setExport)
|
||||
setExport()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tp *TunnelsPage) updateConfView() {
|
||||
@@ -383,7 +406,7 @@ func (tp *TunnelsPage) exportTunnels(filePath string) {
|
||||
func (tp *TunnelsPage) addTunnel(config *conf.Config) {
|
||||
_, err := manager.IPCClientNewTunnel(config)
|
||||
if err != nil {
|
||||
walk.MsgBox(tp.Form(), "Unable to create tunnel", err.Error(), walk.MsgBoxIconError)
|
||||
showErrorCustom(tp.Form(), "Unable to create tunnel", err.Error())
|
||||
}
|
||||
|
||||
}
|
||||
@@ -400,11 +423,11 @@ func (tp *TunnelsPage) onTunnelsViewItemActivated() {
|
||||
if err != nil {
|
||||
tp.Synchronize(func() {
|
||||
if oldState == manager.TunnelUnknown {
|
||||
walk.MsgBox(tp.Form(), "Failed to determine tunnel state", err.Error(), walk.MsgBoxIconError)
|
||||
showErrorCustom(tp.Form(), "Failed to determine tunnel state", err.Error())
|
||||
} else if oldState == manager.TunnelStopped {
|
||||
walk.MsgBox(tp.Form(), "Failed to activate tunnel", err.Error(), walk.MsgBoxIconError)
|
||||
showErrorCustom(tp.Form(), "Failed to activate tunnel", err.Error())
|
||||
} else if oldState == manager.TunnelStarted {
|
||||
walk.MsgBox(tp.Form(), "Failed to deactivate tunnel", err.Error(), walk.MsgBoxIconError)
|
||||
showErrorCustom(tp.Form(), "Failed to deactivate tunnel", err.Error())
|
||||
}
|
||||
})
|
||||
return
|
||||
@@ -418,7 +441,7 @@ func (tp *TunnelsPage) onEditTunnel() {
|
||||
return
|
||||
}
|
||||
|
||||
if config := runTunnelEditDialog(tp.Form(), tunnel); config != nil {
|
||||
if config := runEditDialog(tp.Form(), tunnel); config != nil {
|
||||
go func() {
|
||||
priorState, err := tunnel.State()
|
||||
tunnel.Delete()
|
||||
@@ -432,7 +455,7 @@ func (tp *TunnelsPage) onEditTunnel() {
|
||||
}
|
||||
|
||||
func (tp *TunnelsPage) onAddTunnel() {
|
||||
if config := runTunnelEditDialog(tp.Form(), nil); config != nil {
|
||||
if config := runEditDialog(tp.Form(), nil); config != nil {
|
||||
// Save new
|
||||
tp.addTunnel(config)
|
||||
}
|
||||
@@ -493,9 +516,9 @@ func (tp *TunnelsPage) onDelete() {
|
||||
if len(errors) > 0 {
|
||||
tp.listView.Synchronize(func() {
|
||||
if len(errors) == 1 {
|
||||
walk.MsgBox(tp.Form(), "Unable to delete tunnel", fmt.Sprintf("A tunnel was unable to be removed: %s", errors[0].Error()), walk.MsgBoxIconError)
|
||||
showErrorCustom(tp.Form(), "Unable to delete tunnel", fmt.Sprintf("A tunnel was unable to be removed: %s", errors[0].Error()))
|
||||
} else {
|
||||
walk.MsgBox(tp.Form(), "Unable to delete tunnels", fmt.Sprintf("%d tunnels were unable to be removed.", len(errors)), walk.MsgBoxIconError)
|
||||
showErrorCustom(tp.Form(), "Unable to delete tunnels", fmt.Sprintf("%d tunnels were unable to be removed.", len(errors)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ func RunUI() {
|
||||
runtime.LockOSThread()
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
walk.MsgBox(nil, "Panic", fmt.Sprint(err, "\n\n", string(debug.Stack())), walk.MsgBoxIconError)
|
||||
showErrorCustom(nil, "Panic", fmt.Sprint(err, "\n\n", string(debug.Stack())))
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
@@ -95,7 +95,7 @@ func RunUI() {
|
||||
if shouldQuitManagerWhenExiting {
|
||||
_, err := manager.IPCClientQuit(true)
|
||||
if err != nil {
|
||||
walk.MsgBox(nil, "Error Exiting WireGuard", fmt.Sprintf("Unable to exit service due to: %v. You may want to stop WireGuard from the service manager.", err), walk.MsgBoxIconError)
|
||||
showErrorCustom(nil, "Error Exiting WireGuard", fmt.Sprintf("Unable to exit service due to: %v. You may want to stop WireGuard from the service manager.", err))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,3 +104,21 @@ func onQuit() {
|
||||
shouldQuitManagerWhenExiting = true
|
||||
walk.App().Exit(0)
|
||||
}
|
||||
|
||||
func showError(err error, owner walk.Form) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
showErrorCustom(owner, "Error", err.Error())
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func showErrorCustom(owner walk.Form, title, message string) {
|
||||
walk.MsgBox(owner, title, message, walk.MsgBoxIconError)
|
||||
}
|
||||
|
||||
func showWarningCustom(owner walk.Form, title, message string) {
|
||||
walk.MsgBox(owner, title, message, walk.MsgBoxIconWarning)
|
||||
}
|
||||
|
||||
+23
-5
@@ -19,12 +19,16 @@ type UpdatePage struct {
|
||||
}
|
||||
|
||||
func NewUpdatePage() (*UpdatePage, error) {
|
||||
up := &UpdatePage{}
|
||||
var err error
|
||||
var disposables walk.Disposables
|
||||
defer disposables.Treat()
|
||||
|
||||
up := &UpdatePage{}
|
||||
|
||||
if up.TabPage, err = walk.NewTabPage(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disposables.Add(up)
|
||||
|
||||
up.SetTitle("An Update is Available!")
|
||||
|
||||
@@ -33,18 +37,30 @@ func NewUpdatePage() (*UpdatePage, error) {
|
||||
|
||||
up.SetLayout(walk.NewVBoxLayout())
|
||||
|
||||
instructions, _ := walk.NewTextLabel(up)
|
||||
instructions, err := walk.NewTextLabel(up)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
instructions.SetText("An update to WireGuard is available. It is highly advisable to update without delay.")
|
||||
instructions.SetMinMaxSize(walk.Size{1, 0}, walk.Size{0, 0})
|
||||
|
||||
status, _ := walk.NewTextLabel(up)
|
||||
status, err := walk.NewTextLabel(up)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
status.SetText("Status: Waiting for user")
|
||||
status.SetMinMaxSize(walk.Size{1, 0}, walk.Size{0, 0})
|
||||
|
||||
bar, _ := walk.NewProgressBar(up)
|
||||
bar, err := walk.NewProgressBar(up)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bar.SetVisible(false)
|
||||
|
||||
button, _ := walk.NewPushButton(up)
|
||||
button, err := walk.NewPushButton(up)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
updateIcon, _ := loadSystemIcon("shell32", 46, 32)
|
||||
button.SetImage(updateIcon)
|
||||
button.SetText("Update Now")
|
||||
@@ -113,5 +129,7 @@ func NewUpdatePage() (*UpdatePage, error) {
|
||||
})
|
||||
})
|
||||
|
||||
disposables.Spare()
|
||||
|
||||
return up, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user