1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
*/
package ui
import (
"fmt"
"github.com/lxn/walk"
"golang.zx2c4.com/wireguard/windows/service"
"golang.zx2c4.com/wireguard/windows/updater"
)
type UpdatePage struct {
*walk.TabPage
}
func NewUpdatePage() (*UpdatePage, error) {
up := &UpdatePage{}
var err error
if up.TabPage, err = walk.NewTabPage(); err != nil {
return nil, err
}
up.SetTitle("An Update is Available!")
font, err := walk.NewFont("Segoe UI", 9, walk.FontBold)
if err != nil {
return nil, err
}
up.AddDisposable(font)
up.SetTitleFont(font)
iconSize := up.DPI() / 6
tabIcon, _ := loadSystemIcon("imageres", 1, iconSize)
defer tabIcon.Dispose()
bitmap, _ := walk.NewBitmapFromIcon(tabIcon, walk.Size{iconSize, iconSize}) //TODO: this should use dynamic DPI
up.SetImage(bitmap)
//TODO: make title bold
up.SetLayout(walk.NewVBoxLayout())
instructions, _ := walk.NewTextLabel(up)
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.SetText("Status: Waiting for user")
status.SetMinMaxSize(walk.Size{1, 0}, walk.Size{0, 0})
bar, _ := walk.NewProgressBar(up)
bar.SetVisible(false)
button, _ := walk.NewPushButton(up)
updateIcon, _ := loadSystemIcon("shell32", 46, bar.HeightPixels())
button.SetImage(updateIcon)
button.SetText("Update Now")
walk.NewVSpacer(up)
switchToUpdatingState := func() {
if !bar.Visible() {
up.SetSuspended(true)
button.SetEnabled(false)
button.SetVisible(false)
bar.SetVisible(true)
bar.SetMarqueeMode(true)
up.SetSuspended(false)
status.SetText("Status: Waiting for updater service")
}
}
switchToReadyState := func() {
if bar.Visible() {
up.SetSuspended(true)
bar.SetVisible(false)
bar.SetValue(0)
bar.SetRange(0, 1)
bar.SetMarqueeMode(false)
button.SetVisible(true)
button.SetEnabled(true)
up.SetSuspended(false)
}
}
button.Clicked().Attach(func() {
switchToUpdatingState()
err := service.IPCClientUpdate()
if err != nil {
switchToReadyState()
status.SetText(fmt.Sprintf("Error: %v. Please try again.", err))
}
})
service.IPCClientRegisterUpdateProgress(func(dp updater.DownloadProgress) {
up.Synchronize(func() {
switchToUpdatingState()
if dp.Error != nil {
switchToReadyState()
status.SetText(fmt.Sprintf("Error: %v. Please try again.", dp.Error))
return
}
if len(dp.Activity) > 0 {
status.SetText(fmt.Sprintf("Status: %s", dp.Activity))
}
if dp.BytesTotal > 0 {
bar.SetMarqueeMode(false)
bar.SetRange(0, int(dp.BytesTotal))
bar.SetValue(int(dp.BytesDownloaded))
} else {
bar.SetMarqueeMode(true)
bar.SetValue(0)
bar.SetRange(0, 1)
}
if dp.Complete {
switchToReadyState()
status.SetText("Status: Complete!")
return
}
})
})
return up, nil
}
|