diff --git a/cmd/gui/main.go b/cmd/gui/main.go index c9d812d..1da1ee2 100644 --- a/cmd/gui/main.go +++ b/cmd/gui/main.go @@ -42,16 +42,5 @@ func main() { s := data.NewService(repo) w := mainwindow.Make(a, s) - - defer func() { - if r := recover(); r != nil { - d := dialog.NewError(fmt.Errorf("the application crashed: %s", r), w) - d.Show() - d.SetOnClosed(func() { - os.Exit(1) - }) - } - }() - w.ShowAndRun() } diff --git a/cmd/gui/window/credential/credential.go b/cmd/gui/window/credential/credential.go index 9b61a79..d440127 100644 --- a/cmd/gui/window/credential/credential.go +++ b/cmd/gui/window/credential/credential.go @@ -18,7 +18,7 @@ type ( ) func Make(remoteHostname string, callback func(ok bool, username, password string), w fyne.Window) *CredentialDialog { - label := canvas.NewText("Connexion to "+remoteHostname, color.Black) + label := canvas.NewText(remoteHostname, color.Black) inputUsername := widget.NewEntry() inputUsername.SetPlaceHolder("Username") @@ -29,7 +29,7 @@ func Make(remoteHostname string, callback func(ok bool, username, password strin formItems := []*widget.FormItem{ { - Text: "", + Text: "Connexion to ", Widget: label, }, { diff --git a/cmd/gui/window/mainwindow/mainwindow.go b/cmd/gui/window/mainwindow/mainwindow.go index 8358c74..e59284e 100644 --- a/cmd/gui/window/mainwindow/mainwindow.go +++ b/cmd/gui/window/mainwindow/mainwindow.go @@ -4,6 +4,7 @@ import ( "cloudsave/cmd/gui/window/about" "cloudsave/cmd/gui/window/credential" "cloudsave/cmd/gui/window/loading" + "cloudsave/cmd/gui/window/properties" syncdialog "cloudsave/cmd/gui/window/sync" "cloudsave/pkg/data" @@ -36,8 +37,19 @@ func (e *ExtraLabel) SetID(id string) { func Make(a fyne.App, d *data.Service) fyne.Window { w := a.NewWindow("CloudSave") - w.Resize(fyne.NewSize(1000, 700)) + w.Resize(fyne.NewSize(1200, 700)) w.CenterOnScreen() + w.SetFixedSize(true) + + defer func() { + if r := recover(); r != nil { + d := dialog.NewError(fmt.Errorf("the application crashed: %s", r), w) + d.Show() + d.SetOnClosed(func() { + os.Exit(1) + }) + } + }() games, err := d.AllGames() if err != nil { @@ -61,74 +73,29 @@ func Make(a fyne.App, d *data.Service) fyne.Window { }) list.OnSelected = func(id widget.ListItemID) { - fmt.Println(id) + properties.Make(a, games[id]).Show() } toolbar := widget.NewToolbar( - widget.NewToolbarAction(theme.FolderNewIcon(), func() { - folderSelection := dialog.NewFolderOpen(func(lu fyne.ListableURI, err error) { - if err != nil { - d := dialog.NewError(fmt.Errorf("failed to open window: %w", err), w) + makeNewButton(d, w, func() { + games, err = d.AllGames() + if err != nil { + fyne.Do(func() { + d := dialog.NewError(fmt.Errorf("failed to load datastore: %w", err), w) d.Show() - return - } - if lu == nil { - return - } - confirmDialog := dialog.NewConfirm("Add", "Do you want to add and scan '"+lu.Path()+"'?", func(accepted bool) { - if !accepted { - return - } - name := filepath.Base(lu.Path()) + }) + return + } - loadingDialog := loading.Make("Scanning directory", w) - loadingDialog.Show() - - go func() { - gameID, err := d.Add(name, lu.Path(), "") - if err != nil { - fyne.Do(func() { - d := dialog.NewError(fmt.Errorf("failed to create metadata the directory: %w", err), w) - d.Show() - loadingDialog.Hide() - }) - return - } - - _, err = d.Scan(gameID) - if err != nil { - fyne.Do(func() { - d := dialog.NewError(fmt.Errorf("failed to scan the directory: %w", err), w) - d.Show() - loadingDialog.Hide() - }) - return - } - - games, err = d.AllGames() - if err != nil { - fyne.Do(func() { - d := dialog.NewError(fmt.Errorf("failed to load datastore: %w", err), w) - d.Show() - loadingDialog.Hide() - }) - return - } - - fyne.Do(func() { - list.Refresh() - loadingDialog.Hide() - }) - }() - }, w) - confirmDialog.Show() - }, w) - folderSelection.Show() + fyne.Do(func() { + list.Refresh() + }) }), widget.NewToolbarSeparator(), widget.NewToolbarAction(theme.UploadIcon(), func() { doSync(d, w) }), + makeScanButton(d, w), widget.NewToolbarSpacer(), widget.NewToolbarAction(theme.HelpIcon(), func() { aboutWindow := about.Make(a) @@ -223,3 +190,96 @@ func syncing(it *iterator.Iterator[remote.Remote], d *data.Service, w fyne.Windo } } } + +func makeNewButton(d *data.Service, w fyne.Window, callback func()) *widget.ToolbarAction { + return widget.NewToolbarAction(theme.FolderNewIcon(), func() { + folderSelection := dialog.NewFolderOpen(func(lu fyne.ListableURI, err error) { + if err != nil { + d := dialog.NewError(fmt.Errorf("failed to open window: %w", err), w) + d.Show() + return + } + if lu == nil { + return + } + confirmDialog := dialog.NewConfirm("Add", "Do you want to add and scan '"+lu.Path()+"'?", func(accepted bool) { + if !accepted { + return + } + name := filepath.Base(lu.Path()) + + loadingDialog := loading.Make("Scanning directory", w) + loadingDialog.Show() + + go func() { + gameID, err := d.Add(name, lu.Path(), "") + if err != nil { + fyne.Do(func() { + d := dialog.NewError(fmt.Errorf("failed to create metadata the directory: %w", err), w) + d.Show() + loadingDialog.Hide() + }) + return + } + + _, err = d.Scan(gameID) + if err != nil { + fyne.Do(func() { + d := dialog.NewError(fmt.Errorf("failed to scan the directory: %w", err), w) + d.Show() + loadingDialog.Hide() + }) + return + } + + loadingDialog.Hide() + callback() + }() + }, w) + confirmDialog.Show() + }, w) + folderSelection.Show() + }) +} + +func makeScanButton(d *data.Service, w fyne.Window) *widget.ToolbarAction { + return widget.NewToolbarAction(theme.SearchIcon(), func() { + loadingDialog := loading.Make("Scanning directory", w) + loadingDialog.Show() + + go func() { + datastore, err := d.AllGames() + if err != nil { + fyne.Do(func() { + dialog.NewError(fmt.Errorf("failed to load datastore: %w", err), w) + loadingDialog.Hide() + }) + } + + updated := 0 + + for _, metadata := range datastore { + changed, err := d.Scan(metadata.ID) + if err != nil { + fyne.Do(func() { + dialog.NewError(fmt.Errorf("failed to load datastore: %w", err), w) + loadingDialog.Hide() + }) + return + } + if changed { + updated++ + } + } + + fyne.Do(func() { + loadingDialog.Hide() + if updated == 0 { + dialog.NewInformation("Scan", "Everything is up to date", w).Show() + } else { + dialog.NewInformation("Scan", fmt.Sprintf("%d game updated", updated), w).Show() + } + }) + }() + }) +} diff --git a/cmd/gui/window/properties/properties.go b/cmd/gui/window/properties/properties.go new file mode 100644 index 0000000..0ad80ab --- /dev/null +++ b/cmd/gui/window/properties/properties.go @@ -0,0 +1,33 @@ +package properties + +import ( + "cloudsave/pkg/repository" + "image/color" + "strconv" + + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/canvas" + "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2/layout" +) + +func Make(a fyne.App, g repository.Metadata) fyne.Window { + w := a.NewWindow(g.Name) + w.Resize(fyne.NewSize(800, 300)) + w.CenterOnScreen() + w.SetFixedSize(true) + + title := canvas.NewText(g.Name, color.Black) + title.Alignment = fyne.TextAlignCenter + title.TextSize = 32 + + version := canvas.NewText("Version "+strconv.Itoa(g.Version), color.Black) + version.Alignment = fyne.TextAlignCenter + version.TextSize = 18 + + c := container.New(layout.NewVBoxLayout(), title, version) + + centered := container.New(layout.NewHBoxLayout(), layout.NewSpacer(), c, layout.NewSpacer()) + w.SetContent(container.New(layout.NewVBoxLayout(), centered)) + return w +} diff --git a/cmd/gui/window/sync/sync.go b/cmd/gui/window/sync/sync.go index 1958c64..ee433b0 100644 --- a/cmd/gui/window/sync/sync.go +++ b/cmd/gui/window/sync/sync.go @@ -15,7 +15,7 @@ type ( SyncDialog struct { *dialog.CustomDialog label *canvas.Text - pg *widget.ProgressBar + pg *widget.ProgressBarInfinite } ) @@ -24,8 +24,7 @@ func Make(total int, w fyne.Window) *SyncDialog { title := canvas.NewText("Warming up...", color.Black) title.Alignment = fyne.TextAlignCenter - pg := widget.NewProgressBar() - pg.Max = float64(total) + pg := widget.NewProgressBarInfinite() c := container.New(layout.NewVBoxLayout(), title, pg) d := &SyncDialog{ @@ -38,10 +37,5 @@ func Make(total int, w fyne.Window) *SyncDialog { func (s *SyncDialog) UpdateLabel(msg string) { s.label.Text = msg - s.Refresh() -} - -func (s *SyncDialog) UpdateProgressBar(percentage int) { - s.pg.Value = float64(percentage) - s.Refresh() + s.label.Refresh() }