feat(v0.2.0): config UI panel + folder picker + S3 bucket lister/tester
- Panel Reglages dans l'UI (modal) - Folder picker natif Wails pour dossier local - ListS3Buckets via aws-cli (profile-aware) - TestS3Access pour verifier acces bucket - Config persistee user config dir (cross-OS): %APPDATA%/field-sync ou ~/.config/field-sync - Header affiche bucket + dest visibles - Auto-open modal si bucket vide au premier run Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
59
app.go
59
app.go
@@ -3,6 +3,8 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
@@ -66,12 +68,67 @@ func NewApp() *App {
|
||||
// startup is called by Wails when the app starts
|
||||
func (a *App) startup(ctx context.Context) {
|
||||
a.ctx = ctx
|
||||
a.cfg = config.Load(".env")
|
||||
a.cfg = config.LoadFromFile()
|
||||
for i, letter := range []string{"A", "B", "C", "D"} {
|
||||
a.slots[i] = SlotState{Slot: letter, Status: "idle"}
|
||||
}
|
||||
}
|
||||
|
||||
// SaveConfig persists config to user config dir and updates in-memory config
|
||||
func (a *App) SaveConfig(cfg config.Config) error {
|
||||
if err := config.Save(cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
a.mu.Lock()
|
||||
a.cfg = cfg
|
||||
a.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetConfigPath returns where the config is stored (for display)
|
||||
func (a *App) GetConfigPath() string {
|
||||
return config.Path()
|
||||
}
|
||||
|
||||
// PickLocalDest opens native folder picker, returns selected path or "" if cancelled
|
||||
func (a *App) PickLocalDest() (string, error) {
|
||||
path, err := runtime.OpenDirectoryDialog(a.ctx, runtime.OpenDialogOptions{
|
||||
Title: "Dossier de destination locale",
|
||||
})
|
||||
return path, err
|
||||
}
|
||||
|
||||
// ListS3Buckets runs `aws s3api list-buckets --profile <p>` returns []string
|
||||
func (a *App) ListS3Buckets(profile string) ([]string, error) {
|
||||
args := []string{"s3api", "list-buckets", "--query", "Buckets[].Name", "--output", "text"}
|
||||
if profile != "" {
|
||||
args = append(args, "--profile", profile)
|
||||
}
|
||||
out, err := exec.Command("aws", args...).CombinedOutput()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("aws error: %s", strings.TrimSpace(string(out)))
|
||||
}
|
||||
raw := strings.TrimSpace(string(out))
|
||||
if raw == "" || raw == "None" {
|
||||
return []string{}, nil
|
||||
}
|
||||
parts := strings.Fields(raw)
|
||||
return parts, nil
|
||||
}
|
||||
|
||||
// TestS3Access checks bucket reachable: `aws s3 ls s3://<bucket>/ --profile <p>`
|
||||
func (a *App) TestS3Access(bucket, profile string) error {
|
||||
args := []string{"s3", "ls", "s3://" + bucket + "/"}
|
||||
if profile != "" {
|
||||
args = append(args, "--profile", profile)
|
||||
}
|
||||
out, err := exec.Command("aws", args...).CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("accès refusé: %s", strings.TrimSpace(string(out)))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ScanCards returns up to 4 detected SD cards
|
||||
func (a *App) ScanCards() []detect.SDCard {
|
||||
cards := detect.Detect()
|
||||
|
||||
Reference in New Issue
Block a user