Skip to content

Commit 327a2ee

Browse files
committed
[FEATURE] Add auto updating
1 parent 40c5e33 commit 327a2ee

File tree

9 files changed

+413
-9
lines changed

9 files changed

+413
-9
lines changed

FyneApp.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ Website = "https://github.com/Sharrnah/whispering"
55
Name = "Whispering Tiger"
66
ID = "tiger.whispering"
77
Version = "1.0.0"
8-
Build = 16
8+
Build = 17

Pages/Profiles.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ func CreateProfileWindow(onClose func()) fyne.CanvasObject {
402402
println(err)
403403
}
404404
for _, file := range files {
405-
if !file.IsDir() && (strings.HasSuffix(file.Name(), ".yaml") || strings.HasSuffix(file.Name(), ".yml")) {
405+
if !file.IsDir() && !strings.HasPrefix(file.Name(), ".") && (strings.HasSuffix(file.Name(), ".yaml") || strings.HasSuffix(file.Name(), ".yml")) {
406406
settingsFiles = append(settingsFiles, file.Name())
407407
}
408408
}
@@ -454,9 +454,11 @@ func CreateProfileWindow(onClose func()) fyne.CanvasObject {
454454
Pause: 0.8,
455455
Energy: 300,
456456
}
457-
err = profileSettings.LoadYamlSettings(settingsFiles[id])
458-
if err != nil {
459-
dialog.ShowError(err, fyne.CurrentApp().Driver().AllWindows()[1])
457+
if Utilities.FileExists(settingsFiles[id]) {
458+
err = profileSettings.LoadYamlSettings(settingsFiles[id])
459+
if err != nil {
460+
dialog.ShowError(err, fyne.CurrentApp().Driver().AllWindows()[1])
461+
}
460462
}
461463
profileForm := profileListContent.Content.(*widget.Form)
462464
profileForm.SubmitText = "Save and Load Profile"

Updater/Downloader.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package Updater
2+
3+
import (
4+
"fmt"
5+
"io"
6+
"net/http"
7+
"os"
8+
)
9+
10+
type OnProgress func(bytesWritten, contentLength uint64)
11+
12+
type WriteCounter struct {
13+
Total uint64
14+
ContentLength uint64
15+
OnProgress OnProgress
16+
}
17+
18+
type Download struct {
19+
Url string
20+
Filepath string
21+
WriteCounter WriteCounter
22+
}
23+
24+
func (wc *WriteCounter) Write(p []byte) (int, error) {
25+
n := len(p)
26+
wc.Total += uint64(n)
27+
wc.OnProgress(wc.Total, wc.ContentLength)
28+
return n, nil
29+
}
30+
31+
// DownloadFile will download a url to a local file. It's efficient because it will
32+
// write as it downloads and not load the whole file into memory. We pass an io.TeeReader
33+
// into Copy() to report progress on the download.
34+
func (d *Download) DownloadFile() error {
35+
36+
// Create the file, but give it a tmp file extension, this means we won't overwrite a
37+
// file until it's downloaded, but we'll remove the tmp extension once downloaded.
38+
out, err := os.Create(d.Filepath + ".tmp")
39+
if err != nil {
40+
return err
41+
}
42+
43+
// Get the data
44+
resp, err := http.Get(d.Url)
45+
if err != nil {
46+
out.Close()
47+
return err
48+
}
49+
defer resp.Body.Close()
50+
51+
d.WriteCounter.ContentLength = uint64(resp.ContentLength)
52+
53+
// Create our progress reporter and pass it to be used alongside our writer
54+
if _, err = io.Copy(out, io.TeeReader(resp.Body, &d.WriteCounter)); err != nil {
55+
out.Close()
56+
return err
57+
}
58+
59+
// The progress use the same line so print a new line once it's finished downloading
60+
fmt.Print("\n")
61+
62+
// Close the file without defer so it can happen before Rename()
63+
out.Close()
64+
65+
if err = os.Rename(d.Filepath+".tmp", d.Filepath); err != nil {
66+
return err
67+
}
68+
return nil
69+
}

Updater/Unzip.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package Updater
2+
3+
import (
4+
"archive/zip"
5+
"fmt"
6+
"io"
7+
"os"
8+
"path/filepath"
9+
"strings"
10+
)
11+
12+
func Unzip(src, dest string) error {
13+
r, err := zip.OpenReader(src)
14+
if err != nil {
15+
return err
16+
}
17+
defer func() {
18+
if err := r.Close(); err != nil {
19+
panic(err)
20+
}
21+
}()
22+
23+
os.MkdirAll(dest, 0755)
24+
25+
// Closure to address file descriptors issue with all the deferred .Close() methods
26+
extractAndWriteFile := func(f *zip.File) error {
27+
rc, err := f.Open()
28+
if err != nil {
29+
return err
30+
}
31+
defer func() {
32+
if err := rc.Close(); err != nil {
33+
panic(err)
34+
}
35+
}()
36+
37+
path := filepath.Join(dest, f.Name)
38+
39+
// Check for ZipSlip (Directory traversal)
40+
if !strings.HasPrefix(path, filepath.Clean(dest)+string(os.PathSeparator)) {
41+
return fmt.Errorf("illegal file path: %s", path)
42+
}
43+
44+
if f.FileInfo().IsDir() {
45+
os.MkdirAll(path, f.Mode())
46+
} else {
47+
os.MkdirAll(filepath.Dir(path), f.Mode())
48+
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
49+
if err != nil {
50+
return err
51+
}
52+
defer func() {
53+
if err := f.Close(); err != nil {
54+
panic(err)
55+
}
56+
}()
57+
58+
_, err = io.Copy(f, rc)
59+
if err != nil {
60+
return err
61+
}
62+
}
63+
return nil
64+
}
65+
66+
for _, f := range r.File {
67+
err := extractAndWriteFile(f)
68+
if err != nil {
69+
return err
70+
}
71+
}
72+
73+
return nil
74+
}

Updater/UpdateInfo.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package Updater
2+
3+
import (
4+
"fmt"
5+
"gopkg.in/yaml.v3"
6+
"io"
7+
"log"
8+
"net/http"
9+
"os"
10+
)
11+
12+
/* example yaml
13+
packages:
14+
app:
15+
version: 1.0.0.16
16+
urls:
17+
- https://eu2.someurl.com/app1.0.0.16_win.zip
18+
19+
data:
20+
version: 1.0.0.3
21+
urls:
22+
- https://eu2.someurl.com/data1.0.0.3_win.zip
23+
- https://usc1.someurl.com/data1.0.0.3_win.zip
24+
*/
25+
26+
type UpdateInfo struct {
27+
Version string `yaml:"version"`
28+
Urls []string `yaml:"urls"`
29+
}
30+
31+
func (i *UpdateInfo) WriteYaml(fileName string) {
32+
// marshal the struct to yaml and save as file
33+
yamlFile, err := yaml.Marshal(i)
34+
if err != nil {
35+
log.Printf("error: %v", err)
36+
}
37+
err = os.WriteFile(fileName, yamlFile, 0644)
38+
if err != nil {
39+
log.Printf("error: %v", err)
40+
}
41+
}
42+
43+
func (i *UpdateInfo) ReadYaml(data []byte) error {
44+
// read the yaml file and unmarshal it to the struct
45+
var err error
46+
err = yaml.Unmarshal(data, i)
47+
if err != nil {
48+
log.Printf("Unmarshal: %v", err)
49+
}
50+
return err
51+
}
52+
53+
type UpdatePackages struct {
54+
Packages map[string]UpdateInfo `yaml:"packages"`
55+
//DoNotAskAgain bool `yaml:"doNotAskAgain,omitempty"`
56+
}
57+
58+
func (u *UpdatePackages) parsePackagesFromYaml(data []byte) error {
59+
var err error
60+
err = yaml.Unmarshal(data, u)
61+
if err != nil {
62+
log.Printf("Unmarshal: %v", err)
63+
}
64+
return err
65+
}
66+
67+
func (u *UpdatePackages) getYaml(url string) ([]byte, error) {
68+
resp, err := http.Get(url)
69+
if err != nil {
70+
return []byte{}, fmt.Errorf("GET error: %v", err)
71+
}
72+
defer resp.Body.Close()
73+
74+
if resp.StatusCode != http.StatusOK {
75+
return []byte{}, fmt.Errorf("status error: %v", resp.StatusCode)
76+
}
77+
78+
data, err := io.ReadAll(resp.Body)
79+
if err != nil {
80+
return []byte{}, fmt.Errorf("read body: %v", err)
81+
}
82+
83+
return data, nil
84+
}
85+
86+
func (u *UpdatePackages) WriteYaml(fileName string) {
87+
// marshal the struct to yaml and save as file
88+
yamlFile, err := yaml.Marshal(u)
89+
if err != nil {
90+
log.Printf("error: %v", err)
91+
}
92+
err = os.WriteFile(fileName, yamlFile, 0644)
93+
if err != nil {
94+
log.Printf("error: %v", err)
95+
}
96+
}
97+
98+
func (u *UpdatePackages) GetUpdateInfo(url string) error {
99+
data, err := u.getYaml(url)
100+
if err != nil {
101+
return err
102+
}
103+
return u.parsePackagesFromYaml(data)
104+
}

Websocket/messageHandler.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,15 @@ func (c *MessageStruct) HandleReceiveMessage() {
113113
case "processing_start":
114114
var processingStarted = false
115115
err = json.Unmarshal(c.Data, &processingStarted)
116-
Fields.Field.ProcessingStatus.Start()
117-
go func() {
118-
time.Sleep(5 * time.Second)
116+
if processingStarted {
117+
Fields.Field.ProcessingStatus.Start()
118+
go func() {
119+
time.Sleep(10 * time.Second)
120+
Fields.Field.ProcessingStatus.Stop()
121+
}()
122+
} else {
119123
Fields.Field.ProcessingStatus.Stop()
120-
}()
124+
}
121125
}
122126
if err != nil {
123127
log.Printf("Unmarshal: %v", err)

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.18
44

55
require (
66
fyne.io/fyne/v2 v2.2.4
7+
github.com/dustin/go-humanize v1.0.0
78
github.com/gen2brain/malgo v0.11.10
89
github.com/gorilla/websocket v1.5.0
910
github.com/hajimehoshi/oto/v2 v2.3.1

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
6666
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
6767
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
6868
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
69+
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
70+
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
6971
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
7072
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
7173
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=

0 commit comments

Comments
 (0)