switch back to qt
Some checks failed
CloudSave/pipeline/head There was a failure building this commit
Some checks failed
CloudSave/pipeline/head There was a failure building this commit
This commit is contained in:
@@ -1,46 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"cloudsave/cmd/gui/window/mainwindow"
|
||||
"cloudsave/pkg/data"
|
||||
"cloudsave/pkg/repository"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"fyne.io/fyne/v2/app"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
a := app.NewWithID("com.thelilfrog.CloudSave")
|
||||
|
||||
roaming, err := os.UserConfigDir()
|
||||
if err != nil {
|
||||
panic("failed to get user config path: " + err.Error())
|
||||
}
|
||||
|
||||
datastorepath := filepath.Join(roaming, "cloudsave", "data")
|
||||
err = os.MkdirAll(datastorepath, 0740)
|
||||
if err != nil {
|
||||
d := dialog.NewError(fmt.Errorf("cannot make the datastore: %w", err), a.NewWindow("CloudSave"))
|
||||
d.Show()
|
||||
d.SetOnClosed(func() {
|
||||
os.Exit(1)
|
||||
})
|
||||
}
|
||||
|
||||
repo, err := repository.NewLazyRepository(datastorepath)
|
||||
if err != nil {
|
||||
d := dialog.NewError(fmt.Errorf("cannot make the datastore: %w", err), a.NewWindow("CloudSave"))
|
||||
d.Show()
|
||||
d.SetOnClosed(func() {
|
||||
os.Exit(1)
|
||||
})
|
||||
}
|
||||
|
||||
s := data.NewService(repo)
|
||||
|
||||
w := mainwindow.Make(a, s)
|
||||
w.ShowAndRun()
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package about
|
||||
|
||||
import (
|
||||
"cloudsave/pkg/constants"
|
||||
"image/color"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/layout"
|
||||
)
|
||||
|
||||
func Make(a fyne.App) fyne.Window {
|
||||
w := a.NewWindow("About CloudSave")
|
||||
w.Resize(fyne.NewSize(400, 200))
|
||||
w.CenterOnScreen()
|
||||
w.SetFixedSize(true)
|
||||
|
||||
title := canvas.NewText("CloudSave", color.Black)
|
||||
title.Alignment = fyne.TextAlignCenter
|
||||
title.TextSize = 32
|
||||
|
||||
version := canvas.NewText("v"+constants.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
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package credential
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
type (
|
||||
CredentialDialog struct {
|
||||
*dialog.FormDialog
|
||||
inputUsername *widget.Entry
|
||||
inputPassword *widget.Entry
|
||||
}
|
||||
)
|
||||
|
||||
func Make(remoteHostname string, callback func(ok bool, username, password string), w fyne.Window) *CredentialDialog {
|
||||
label := canvas.NewText(remoteHostname, color.Black)
|
||||
|
||||
inputUsername := widget.NewEntry()
|
||||
inputUsername.SetPlaceHolder("Username")
|
||||
|
||||
inputPassword := widget.NewEntry()
|
||||
inputPassword.Password = true
|
||||
inputPassword.SetPlaceHolder("Password")
|
||||
|
||||
formItems := []*widget.FormItem{
|
||||
{
|
||||
Text: "Connexion to ",
|
||||
Widget: label,
|
||||
},
|
||||
{
|
||||
Text: "Username",
|
||||
Widget: inputUsername,
|
||||
},
|
||||
{
|
||||
Text: "Password",
|
||||
Widget: inputPassword,
|
||||
},
|
||||
}
|
||||
|
||||
d := &CredentialDialog{
|
||||
inputUsername: inputUsername,
|
||||
inputPassword: inputPassword,
|
||||
}
|
||||
d.FormDialog = dialog.NewForm("Syncing", "Connexion", "Cancel", formItems, func(b bool) {
|
||||
callback(b, d.inputUsername.Text, d.inputPassword.Text)
|
||||
}, w)
|
||||
return d
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package loading
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
"fyne.io/fyne/v2/layout"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
func Make(msg string, w fyne.Window) *dialog.CustomDialog {
|
||||
title := canvas.NewText(msg, color.Black)
|
||||
title.Alignment = fyne.TextAlignCenter
|
||||
|
||||
pg := widget.NewProgressBarInfinite()
|
||||
|
||||
c := container.New(layout.NewVBoxLayout(), title, pg)
|
||||
d := dialog.NewCustomWithoutButtons("Loading", c, w)
|
||||
|
||||
return d
|
||||
}
|
||||
@@ -1,285 +0,0 @@
|
||||
package mainwindow
|
||||
|
||||
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"
|
||||
"cloudsave/pkg/remote"
|
||||
"cloudsave/pkg/remote/client"
|
||||
"cloudsave/pkg/repository"
|
||||
"cloudsave/pkg/sync"
|
||||
"cloudsave/pkg/tools/iterator"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
type (
|
||||
ExtraLabel struct {
|
||||
*widget.Label
|
||||
id string
|
||||
}
|
||||
)
|
||||
|
||||
func (e *ExtraLabel) SetID(id string) {
|
||||
e.id = id
|
||||
}
|
||||
|
||||
func Make(a fyne.App, d *data.Service) fyne.Window {
|
||||
w := a.NewWindow("CloudSave")
|
||||
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 {
|
||||
d := dialog.NewError(fmt.Errorf("failed to load datastore: %w", err), w)
|
||||
d.Show()
|
||||
d.SetOnClosed(func() {
|
||||
os.Exit(1)
|
||||
})
|
||||
}
|
||||
|
||||
list := widget.NewList(
|
||||
func() int {
|
||||
return len(games)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
return &ExtraLabel{Label: widget.NewLabel("")}
|
||||
},
|
||||
func(i widget.ListItemID, o fyne.CanvasObject) {
|
||||
o.(*ExtraLabel).SetText(games[i].Name)
|
||||
o.(*ExtraLabel).SetID(games[i].ID)
|
||||
})
|
||||
|
||||
list.OnSelected = func(id widget.ListItemID) {
|
||||
properties.Make(a, games[id]).Show()
|
||||
}
|
||||
|
||||
toolbar := widget.NewToolbar(
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
aboutWindow.Show()
|
||||
}),
|
||||
)
|
||||
|
||||
content := container.NewBorder(toolbar, nil, nil, nil, list)
|
||||
w.SetContent(content)
|
||||
return w
|
||||
}
|
||||
|
||||
func doSync(d *data.Service, w fyne.Window) {
|
||||
rs, err := remote.All()
|
||||
if err != nil {
|
||||
d := dialog.NewError(fmt.Errorf("failed to load datastore: %w", err), w)
|
||||
d.Show()
|
||||
return
|
||||
}
|
||||
|
||||
it := iterator.New(rs)
|
||||
if it.IsEmpty() {
|
||||
dialog.NewInformation("Sync", "no remote configured", w).Show()
|
||||
return
|
||||
}
|
||||
dialog := credential.Make(it.Value().URL, syncing(it, d, w), w)
|
||||
dialog.Show()
|
||||
}
|
||||
|
||||
func syncing(it *iterator.Iterator[remote.Remote], d *data.Service, w fyne.Window) func(bool, string, string) {
|
||||
return func(b bool, username, password string) {
|
||||
if b {
|
||||
r := it.Value()
|
||||
|
||||
cli := client.New(r.URL, username, password)
|
||||
|
||||
if err := cli.Ping(); err != nil {
|
||||
dialog.NewError(fmt.Errorf("failed to connect to the server: %w", err), w).Show()
|
||||
return
|
||||
}
|
||||
|
||||
syncDialog := syncdialog.Make(0, w)
|
||||
syncDialog.Show()
|
||||
|
||||
s := sync.NewSyncer(cli, d)
|
||||
|
||||
var errg error
|
||||
s.SetStateCallback(func(s sync.State, g repository.Metadata) {
|
||||
switch s {
|
||||
case sync.FetchingMetdata:
|
||||
fyne.Do(func() {
|
||||
syncDialog.UpdateLabel(fmt.Sprintf("%s: fetching metadata from repository", g.Name))
|
||||
})
|
||||
case sync.Pushing:
|
||||
fyne.Do(func() {
|
||||
syncDialog.UpdateLabel(fmt.Sprintf("%s: pushing data to the server", g.Name))
|
||||
})
|
||||
case sync.Pulling:
|
||||
fyne.Do(func() {
|
||||
syncDialog.UpdateLabel(fmt.Sprintf("%s: pull data from the server", g.Name))
|
||||
})
|
||||
case sync.UpToDate:
|
||||
fyne.Do(func() {
|
||||
syncDialog.UpdateLabel(fmt.Sprintf("%s: already up-to-date", g.Name))
|
||||
})
|
||||
case sync.Pushed:
|
||||
fyne.Do(func() {
|
||||
syncDialog.UpdateLabel(fmt.Sprintf("%s: pushed", g.Name))
|
||||
})
|
||||
case sync.Pulled:
|
||||
fyne.Do(func() {
|
||||
syncDialog.UpdateLabel(fmt.Sprintf("%s: pulled", g.Name))
|
||||
})
|
||||
case sync.Done:
|
||||
fyne.Do(func() {
|
||||
syncDialog.Dismiss()
|
||||
if errg == nil {
|
||||
dialog.NewInformation("Sync", "The sync ended sucessfully!", w).Show()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
s.SetErrorCallback(func(err error, g repository.Metadata) {
|
||||
errg = err
|
||||
fyne.Do(func() {
|
||||
dialog.NewError(err, w).Show()
|
||||
})
|
||||
})
|
||||
|
||||
go s.Sync()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
})
|
||||
}()
|
||||
})
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
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
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package sync
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
"fyne.io/fyne/v2/layout"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
type (
|
||||
SyncDialog struct {
|
||||
*dialog.CustomDialog
|
||||
label *canvas.Text
|
||||
pg *widget.ProgressBarInfinite
|
||||
}
|
||||
)
|
||||
|
||||
func Make(total int, w fyne.Window) *SyncDialog {
|
||||
|
||||
title := canvas.NewText("Warming up...", color.Black)
|
||||
title.Alignment = fyne.TextAlignCenter
|
||||
|
||||
pg := widget.NewProgressBarInfinite()
|
||||
|
||||
c := container.New(layout.NewVBoxLayout(), title, pg)
|
||||
d := &SyncDialog{
|
||||
CustomDialog: dialog.NewCustomWithoutButtons("Syncing", c, w),
|
||||
label: title,
|
||||
pg: pg,
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func (s *SyncDialog) UpdateLabel(msg string) {
|
||||
s.label.Text = msg
|
||||
s.label.Refresh()
|
||||
}
|
||||
Reference in New Issue
Block a user