Skip to content

Commit fd532c4

Browse files
committed
Layout changes
1 parent 6f5319c commit fd532c4

5 files changed

Lines changed: 121 additions & 41 deletions

File tree

downloader.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ type Update struct {
2323
}
2424

2525
type Downloader struct {
26-
RateLimit *int
26+
RateLimit int
27+
bufferSize int
2728
state *InstallerState
2829
ctx context.Context
2930
cancel context.CancelFunc
@@ -42,7 +43,8 @@ type Downloader struct {
4243

4344
func NewDownloader(state *InstallerState) *Downloader {
4445
d := &Downloader{
45-
RateLimit: nil,
46+
RateLimit: 0,
47+
bufferSize: 32 * 1024,
4648
state: state,
4749
client: grab.NewClient(),
4850
workerWg: sync.WaitGroup{},
@@ -183,7 +185,8 @@ func (d *Downloader) Resume() error {
183185
bytePerSecondRecords := make([]float64, 0)
184186

185187
queue := func(bytesPerSecond float64) {
186-
if len(bytePerSecondRecords) > 6 {
188+
// Allow average over 7 records (roughly 3 to 4 seconds)
189+
if len(bytePerSecondRecords) > 7 {
187190
// Remove first element
188191
bytePerSecondRecords = bytePerSecondRecords[1:]
189192
}
@@ -275,7 +278,7 @@ func (d *Downloader) Resume() error {
275278
for idx, f := range uifiles {
276279
if f.Filepath == update.IndexFile.Filepath {
277280
// Send bytes update to speed handler
278-
bytesDiff := f.Bytes - update.Bytes
281+
bytesDiff := update.Bytes - f.Bytes
279282
speedch <- bytesDiff
280283
// Update ui file
281284
f.Progress = update.Progress
@@ -290,7 +293,7 @@ func (d *Downloader) Resume() error {
290293
for idx, f := range uifiles {
291294
if f.Done == true {
292295
// Send bytes update to speed handler
293-
bytesDiff := f.Bytes
296+
bytesDiff := update.Bytes
294297
speedch <- bytesDiff
295298
// Update ui file
296299
f.Filepath = update.IndexFile.Filepath
@@ -432,6 +435,10 @@ func (d *Downloader) NewRequest(f *IndexedFile) (*grab.Request, error) {
432435
req.SetChecksum(sha1.New(), sum, true)
433436
req.Size = f.Size
434437
req = req.WithContext(d.ctx)
438+
req.BufferSize = d.bufferSize
439+
if d.RateLimit != 0 {
440+
req.RateLimiter = &DownloadRateLimiter{rate: d.RateLimit / 4}
441+
}
435442

436443
// Add indexed file as tag
437444
req.Tag = f

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ require (
3434
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
3535
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
3636
golang.org/x/text v0.6.0 // indirect
37+
golang.org/x/time v0.3.0 // indirect
3738
gopkg.in/yaml.v3 v3.0.1 // indirect
3839
honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2 // indirect
3940
)

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,8 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
487487
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
488488
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
489489
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
490+
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
491+
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
490492
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
491493
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
492494
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=

main.go

Lines changed: 84 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"image/color"
1414
"os"
1515
"path/filepath"
16+
"strconv"
1617
)
1718

1819
func main() {
@@ -26,7 +27,7 @@ func main() {
2627
defer closeDb()
2728

2829
w.SetContent(setupLayout(w, state))
29-
w.Resize(fyne.Size{Width: 500, Height: 400})
30+
w.Resize(fyne.Size{Width: 700, Height: 400})
3031

3132
// Show the window
3233
w.ShowAndRun()
@@ -54,6 +55,8 @@ func NewInstallState(w fyne.Window) *InstallerState {
5455
fileProgress2: binding.NewFloat(),
5556
fileProgress3: binding.NewFloat(),
5657
fileProgress4: binding.NewFloat(),
58+
rateLimitEntry: binding.NewString(),
59+
formatRateLimit: binding.NewString(),
5760
baseUrl: "",
5861
}
5962
_ = state.folderPath.Set("Not Set")
@@ -70,6 +73,8 @@ func NewInstallState(w fyne.Window) *InstallerState {
7073
_ = state.fileProgress2.Set(0)
7174
_ = state.fileProgress3.Set(0)
7275
_ = state.fileProgress4.Set(0)
76+
_ = state.rateLimitEntry.Set("")
77+
_ = state.formatRateLimit.Set("Unlimited")
7378

7479
state.Grabber = NewDownloader(&state)
7580
return &state
@@ -181,34 +186,85 @@ func mainLayout(w fyne.Window, state *InstallerState) *fyne.Container {
181186
// Create active file bars
182187
fileLabel := widget.NewLabel("File: ")
183188
fileHeader1 := widget.NewLabelWithData(state.fileTitle1)
184-
fileContainer1 := container.New(layout.NewHBoxLayout(),
185-
fileLabel,
186-
fileHeader1)
189+
fileHeader1.Alignment = fyne.TextAlignLeading
190+
fileHeader1.Wrapping = fyne.TextTruncate
191+
fileContainer1 := container.NewBorder(nil, nil, fileLabel, nil, fileHeader1)
187192
fileProgressBar1 := widget.NewProgressBarWithData(state.fileProgress1)
188193

189194
fileHeader2 := widget.NewLabelWithData(state.fileTitle2)
190-
fileContainer2 := container.New(layout.NewHBoxLayout(),
191-
fileLabel,
192-
fileHeader2)
195+
fileHeader2.Alignment = fyne.TextAlignLeading
196+
fileHeader2.Wrapping = fyne.TextTruncate
197+
fileContainer2 := container.NewBorder(nil, nil, fileLabel, nil, fileHeader2)
193198
fileProgressBar2 := widget.NewProgressBarWithData(state.fileProgress2)
194199

195200
fileHeader3 := widget.NewLabelWithData(state.fileTitle3)
196-
fileContainer3 := container.New(layout.NewHBoxLayout(),
197-
fileLabel,
198-
fileHeader3)
201+
fileHeader3.Alignment = fyne.TextAlignLeading
202+
fileHeader3.Wrapping = fyne.TextTruncate
203+
fileContainer3 := container.NewBorder(nil, nil, fileLabel, nil, fileHeader3)
199204
fileProgressBar3 := widget.NewProgressBarWithData(state.fileProgress3)
200205

201206
fileHeader4 := widget.NewLabelWithData(state.fileTitle4)
202-
fileContainer4 := container.New(layout.NewHBoxLayout(),
203-
fileLabel,
204-
fileHeader4)
207+
fileHeader4.Alignment = fyne.TextAlignLeading
208+
fileHeader4.Wrapping = fyne.TextTruncate
209+
fileContainer4 := container.NewBorder(nil, nil, fileLabel, nil, fileHeader4)
205210
fileProgressBar4 := widget.NewProgressBarWithData(state.fileProgress4)
206211

207212
progressBarTotal := widget.NewProgressBarWithData(state.progressBarTotal)
208213
totalLabel := canvas.NewText("Total Progress...", color.White)
209214

210-
//rateLimitLabel := widget.NewLabel("Download Speed Limit:")
211-
//rateLimitEntry := widget.NewEntry()
215+
rateLimitLabel := widget.NewLabel("Download Speed Limit:")
216+
rateLimitCurrentLabel := widget.NewLabelWithData(state.formatRateLimit)
217+
rateLimitEntry := widget.NewEntryWithData(state.rateLimitEntry)
218+
rateLimitSet := widget.NewButton("Set (KB/s)", func() {
219+
// Turn entry into number
220+
entryLimit, err := state.rateLimitEntry.Get()
221+
if err != nil {
222+
dialog.NewError(err, w).Show()
223+
return
224+
}
225+
rateLimit, err := strconv.Atoi(entryLimit)
226+
if err != nil {
227+
dialog.NewError(&BadRateLimit{}, w).Show()
228+
return
229+
}
230+
231+
if rateLimit < 200 {
232+
rateLimit = 0
233+
}
234+
235+
// Save to downloader and update UI
236+
if rateLimit == 0 {
237+
err = state.formatRateLimit.Set("Unlimited")
238+
if err != nil {
239+
dialog.NewError(err, w).Show()
240+
return
241+
}
242+
} else {
243+
err = state.formatRateLimit.Set(fmt.Sprintf("%dKB/s", rateLimit))
244+
if err != nil {
245+
dialog.NewError(err, w).Show()
246+
return
247+
}
248+
}
249+
250+
state.Grabber.RateLimit = rateLimit * 1024
251+
252+
// Restart downloader
253+
if state.Grabber.running {
254+
state.Grabber.Stop()
255+
err = state.Grabber.Resume()
256+
if err != nil {
257+
dialog.NewError(&FatalDownloadFailure{err}, w).Show()
258+
return
259+
}
260+
}
261+
})
262+
263+
rateLimContainer := container.New(layout.NewVBoxLayout(),
264+
container.New(layout.NewHBoxLayout(),
265+
rateLimitLabel,
266+
rateLimitCurrentLabel),
267+
container.NewBorder(nil, nil, nil, rateLimitSet, rateLimitEntry))
212268

213269
// Create buttons
214270
button1 := widget.NewButton("Start", func() {
@@ -250,9 +306,6 @@ func mainLayout(w fyne.Window, state *InstallerState) *fyne.Container {
250306
// Create a row with buttons
251307
buttonsRow := container.NewHBox(button1, button2, button3)
252308

253-
// Create a sidebar label
254-
sidebarLabel := widget.NewLabel("Ultimate Updater")
255-
256309
// Create 3 additional labels
257310
downloadedHeaderLabel := widget.NewLabel("Downloaded:")
258311
downloadedLabel := widget.NewLabelWithData(state.formatDownloadedSize)
@@ -278,6 +331,7 @@ func mainLayout(w fyne.Window, state *InstallerState) *fyne.Container {
278331
totalLabel,
279332
progressBarTotal,
280333
layout.NewSpacer(),
334+
rateLimContainer,
281335
buttonsRow,
282336
)
283337

@@ -291,30 +345,24 @@ func mainLayout(w fyne.Window, state *InstallerState) *fyne.Container {
291345
fileContainer4,
292346
fileProgressBar4)
293347

294-
mainContent := container.New(layout.NewHBoxLayout(),
295-
leftMainContent,
296-
rightMainContent)
297-
298-
leftSideContent := container.New(layout.NewVBoxLayout(),
299-
sidebarLabel,
300-
layout.NewSpacer(),
301-
downloadedHeaderLabel,
302-
downloadedContainer,
303-
speedHeaderLabel,
304-
speedLabel)
348+
mainContent := container.NewBorder(nil, nil, leftMainContent, nil, rightMainContent)
305349

306350
line := canvas.NewLine(color.Gray{Y: 0x55})
307351
line.StrokeWidth = 2
308352

309-
// Combine the grid layout and sidebar label in a horizontal box
310-
mainLayout := container.New(layout.NewVBoxLayout(),
311-
topBarLayout("install"),
312-
container.New(layout.NewHBoxLayout(),
313-
leftSideContent,
314-
line,
315-
mainContent),
353+
leftSideContent := container.New(layout.NewHBoxLayout(),
354+
container.New(layout.NewVBoxLayout(),
355+
layout.NewSpacer(),
356+
downloadedHeaderLabel,
357+
downloadedContainer,
358+
speedHeaderLabel,
359+
speedLabel),
360+
line,
316361
)
317362

363+
// Combine the grid layout and sidebar label in a horizontal box
364+
mainLayout := container.NewBorder(topBarLayout("install"), nil, leftSideContent, nil, mainContent)
365+
318366
return mainLayout
319367
}
320368

types.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package main
22

33
import (
4+
"context"
45
"fmt"
56
"fyne.io/fyne/v2"
67
"fyne.io/fyne/v2/data/binding"
8+
"time"
79
)
810

911
type UiFile struct {
@@ -52,6 +54,8 @@ type InstallerState struct {
5254
fileTitle2 binding.String
5355
fileTitle3 binding.String
5456
fileTitle4 binding.String
57+
rateLimitEntry binding.String
58+
formatRateLimit binding.String
5559
}
5660

5761
type NoValidPathFoundError struct{}
@@ -83,3 +87,21 @@ type DatabaseError struct {
8387
func (e *DatabaseError) Error() string {
8488
return fmt.Sprintf("Fatal database error\n%s", e.err.Error())
8589
}
90+
91+
type BadRateLimit struct{}
92+
93+
func (e *BadRateLimit) Error() string {
94+
return "Invalid rate limit"
95+
}
96+
97+
type DownloadRateLimiter struct {
98+
rate int
99+
total int64
100+
}
101+
102+
func (c *DownloadRateLimiter) WaitN(_ context.Context, bytes int) (err error) {
103+
c.total += int64(bytes)
104+
time.Sleep(
105+
time.Duration(1.00 / float64(c.rate) * float64(bytes) * float64(time.Second)))
106+
return
107+
}

0 commit comments

Comments
 (0)