golang.zx2c4.com/wireguard/windows@v0.5.4-0.20230123132234-dcc0eb72a04b/ui/updatepage.go (about) 1 /* SPDX-License-Identifier: MIT 2 * 3 * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. 4 */ 5 6 package ui 7 8 import ( 9 "github.com/lxn/walk" 10 11 "golang.zx2c4.com/wireguard/windows/l18n" 12 "golang.zx2c4.com/wireguard/windows/manager" 13 "golang.zx2c4.com/wireguard/windows/updater" 14 ) 15 16 type UpdatePage struct { 17 *walk.TabPage 18 } 19 20 func NewUpdatePage() (*UpdatePage, error) { 21 var err error 22 var disposables walk.Disposables 23 defer disposables.Treat() 24 25 up := &UpdatePage{} 26 27 if up.TabPage, err = walk.NewTabPage(); err != nil { 28 return nil, err 29 } 30 disposables.Add(up) 31 32 up.SetTitle(l18n.Sprintf("An Update is Available!")) 33 34 tabIcon, _ := loadShieldIcon(16) 35 up.SetImage(tabIcon) 36 37 up.SetLayout(walk.NewVBoxLayout()) 38 39 instructions, err := walk.NewTextLabel(up) 40 if err != nil { 41 return nil, err 42 } 43 instructions.SetText(l18n.Sprintf("An update to WireGuard is available. It is highly advisable to update without delay.")) 44 instructions.SetMinMaxSize(walk.Size{1, 0}, walk.Size{0, 0}) 45 46 status, err := walk.NewTextLabel(up) 47 if err != nil { 48 return nil, err 49 } 50 status.SetText(l18n.Sprintf("Status: Waiting for user")) 51 status.SetMinMaxSize(walk.Size{1, 0}, walk.Size{0, 0}) 52 53 bar, err := walk.NewProgressBar(up) 54 if err != nil { 55 return nil, err 56 } 57 bar.SetVisible(false) 58 59 button, err := walk.NewPushButton(up) 60 if err != nil { 61 return nil, err 62 } 63 updateIcon, _ := loadSystemIcon("shell32", -47, 32) 64 button.SetImage(updateIcon) 65 button.SetText(l18n.Sprintf("Update Now")) 66 67 if !IsAdmin { 68 button.SetText(l18n.Sprintf("Please ask the system administrator to update.")) 69 button.SetEnabled(false) 70 status.SetText(l18n.Sprintf("Status: Waiting for administrator")) 71 } 72 73 walk.NewVSpacer(up) 74 75 switchToUpdatingState := func() { 76 if !bar.Visible() { 77 up.SetSuspended(true) 78 button.SetEnabled(false) 79 button.SetVisible(false) 80 bar.SetVisible(true) 81 bar.SetMarqueeMode(true) 82 up.SetSuspended(false) 83 status.SetText(l18n.Sprintf("Status: Waiting for updater service")) 84 } 85 } 86 87 switchToReadyState := func() { 88 if bar.Visible() { 89 up.SetSuspended(true) 90 bar.SetVisible(false) 91 bar.SetValue(0) 92 bar.SetRange(0, 1) 93 bar.SetMarqueeMode(false) 94 button.SetVisible(true) 95 button.SetEnabled(true) 96 up.SetSuspended(false) 97 } 98 } 99 100 button.Clicked().Attach(func() { 101 switchToUpdatingState() 102 err := manager.IPCClientUpdate() 103 if err != nil { 104 switchToReadyState() 105 status.SetText(l18n.Sprintf("Error: %v. Please try again.", err)) 106 } 107 }) 108 109 manager.IPCClientRegisterUpdateProgress(func(dp updater.DownloadProgress) { 110 up.Synchronize(func() { 111 switchToUpdatingState() 112 if dp.Error != nil { 113 switchToReadyState() 114 err := dp.Error 115 status.SetText(l18n.Sprintf("Error: %v. Please try again.", err)) 116 return 117 } 118 if len(dp.Activity) > 0 { 119 stateText := dp.Activity 120 status.SetText(l18n.Sprintf("Status: %s", stateText)) 121 } 122 if dp.BytesTotal > 0 { 123 bar.SetMarqueeMode(false) 124 bar.SetRange(0, int(dp.BytesTotal)) 125 bar.SetValue(int(dp.BytesDownloaded)) 126 } else { 127 bar.SetMarqueeMode(true) 128 bar.SetValue(0) 129 bar.SetRange(0, 1) 130 } 131 if dp.Complete { 132 switchToReadyState() 133 status.SetText(l18n.Sprintf("Status: Complete!")) 134 return 135 } 136 }) 137 }) 138 139 disposables.Spare() 140 141 return up, nil 142 }