From fdc019a2001f8479f7d83718ee576372a45fcaef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lie=20DELHAIE?= Date: Tue, 2 Sep 2025 19:21:03 +0200 Subject: [PATCH] fixes --- cmd/cli/commands/sync/sync.go | 26 ++++++++++++++++---------- cmd/server/main_windows.go | 26 +++++++++++++++++++++++++- cmd/server/res/icon.ico | Bin 0 -> 15689 bytes go.mod | 9 +++++++++ go.sum | 27 +++++++++++++++++++++++++++ pkg/constants/constants.go | 2 +- pkg/data/data.go | 6 ++++++ pkg/remote/client/client.go | 11 +++++++++-- pkg/repository/repository.go | 2 +- 9 files changed, 94 insertions(+), 15 deletions(-) create mode 100644 cmd/server/res/icon.ico diff --git a/cmd/cli/commands/sync/sync.go b/cmd/cli/commands/sync/sync.go index 936aab5..6fcdf8d 100644 --- a/cmd/cli/commands/sync/sync.go +++ b/cmd/cli/commands/sync/sync.go @@ -49,7 +49,7 @@ func (p *SyncCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) r, err := remote.One(g.ID) if err != nil { if errors.Is(err, remote.ErrNoRemote) { - fmt.Println(g.Name + ": no remote configured") + fmt.Println("⬛", g.Name+": no remote configured") continue } fmt.Fprintln(os.Stderr, "error: failed to load datastore:", err) @@ -88,7 +88,7 @@ func (p *SyncCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) slog.Warn("failed to push backup files", "err", err) } destroyPg() - fmt.Println(g.Name + ": pushed") + fmt.Println("⬆️", g.Name+": pushed") continue } @@ -120,7 +120,7 @@ func (p *SyncCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) continue } } - fmt.Println(g.Name + ": already up-to-date") + fmt.Println("🆗", g.Name+": already up-to-date") continue } @@ -132,13 +132,13 @@ func (p *SyncCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) return subcommands.ExitFailure } destroyPg() - fmt.Println(g.Name + ": pushed") + fmt.Println("⬆️", g.Name+": pushed") continue } if g.Version < remoteMetadata.Version { destroyPg() - if err := p.pull(r.GameID, cli); err != nil { + if err := p.pull(g, cli); err != nil { destroyPg() fmt.Fprintln(os.Stderr, "failed to push:", err) return subcommands.ExitFailure @@ -152,7 +152,7 @@ func (p *SyncCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) fmt.Fprintln(os.Stderr, "failed to push:", err) return subcommands.ExitFailure } - fmt.Println(g.Name + ": pulled") + fmt.Println("⬇️", g.Name+": pulled") continue } @@ -179,7 +179,7 @@ func (p *SyncCmd) conflict(gameID string, m, remoteMetadata repository.Metadata, return nil } fmt.Println() - fmt.Println("--- /!\\ CONFLICT ---") + fmt.Println("--- ⚠️ CONFLICT ---") fmt.Println(g.Name, "(", g.Path, ")") fmt.Println("----") fmt.Println("Your version:", g.Date.Format(time.RFC1123)) @@ -198,7 +198,7 @@ func (p *SyncCmd) conflict(gameID string, m, remoteMetadata repository.Metadata, case prompt.Their: { - if err := p.pull(gameID, cli); err != nil { + if err := p.pull(g, cli); err != nil { return fmt.Errorf("failed to push: %w", err) } g.Version = remoteMetadata.Version @@ -266,8 +266,11 @@ func (p *SyncCmd) pullBackup(m repository.Metadata, cli *client.Client) error { return nil } -func (p *SyncCmd) pull(gameID string, cli *client.Client) error { - return p.Service.PullArchive(gameID, "", cli) +func (p *SyncCmd) pull(g repository.Metadata, cli *client.Client) error { + if err := p.Service.PullArchive(g.ID, "", cli); err != nil { + return err + } + return p.Service.ApplyCurrent(g.ID) } func connect(remoteCred map[string]map[string]string, r remote.Remote) (*client.Client, error) { @@ -278,6 +281,9 @@ func connect(remoteCred map[string]map[string]string, r remote.Remote) (*client. return cli, nil } + fmt.Println() + fmt.Println("Connexion to", r.URL) + fmt.Println("============") username, password, err := credentials.Read() if err != nil { return nil, fmt.Errorf("failed to read std output: %w", err) diff --git a/cmd/server/main_windows.go b/cmd/server/main_windows.go index e7e7a85..70b14e0 100644 --- a/cmd/server/main_windows.go +++ b/cmd/server/main_windows.go @@ -2,12 +2,19 @@ package main import ( "cloudsave/pkg/tools/windows" + _ "embed" "os" + + "github.com/getlantern/systray" ) -const defaultDocumentRoot string = "C:/ProgramData/CloudSave" +const defaultDocumentRoot string = "C:\\ProgramData\\CloudSave" + +//go:embed res/icon.ico +var icon []byte func main() { + go systray.Run(onReady, onExit) run() } @@ -15,3 +22,20 @@ func fatal(message string, exitCode int) { windows.MessageBox(windows.NULL, message, "CloudSave", windows.MB_OK) os.Exit(exitCode) } + +func onReady() { + systray.SetTitle("CloudSave") + systray.SetTooltip("CloudSave") + systray.SetIcon(icon) + + mQuit := systray.AddMenuItem("Quit", "Quit") + + go func() { + <-mQuit.ClickedCh + os.Exit(0) + }() +} + +func onExit() { + // clean up here +} diff --git a/cmd/server/res/icon.ico b/cmd/server/res/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b45b20a5a13f371c4d0cf8e0b079a8321ae1dd32 GIT binary patch literal 15689 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