package main import ( "fmt" "io/fs" "os" "path/filepath" "strings" "fyne.io/fyne/v2" "fyne.io/fyne/v2/app" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" "gopkg.in/yaml.v3" cp "github.com/otiai10/copy" ) type Config struct { ProfilesRoot string `yaml:"profiles_root"` ArchiveRoot string `yaml:"archive_root"` } func saveConfig(cfg Config) { d, err := yaml.Marshal(cfg) if err != nil { fmt.Println(err) } err = os.WriteFile("config.yaml", d, 0775) if err != nil { fmt.Println(err) } } func loadConfig() *Config { _, err := os.Stat("config.yaml") if err != nil { fmt.Println(err) saveConfig(Config{ProfilesRoot: "", ArchiveRoot: ""}) } d, err := os.ReadFile("config.yaml") if err != nil { fmt.Println(err) } cfg := Config{} err = yaml.Unmarshal(d, &cfg) if err != nil { fmt.Println(err) return &Config{} } return &cfg } var cfg = loadConfig() func main() { ap := app.New() wp := ap.NewWindow("Cyberpunk Mod Switcher") wp.Resize(fyne.NewSize(1024, 768)) wp.CenterOnScreen() grid := container.NewAdaptiveGrid(4) //load grid fillGrid(grid, wp) profilesrootentry := widget.NewEntry() profilesrootentry.Text = cfg.ProfilesRoot archiverootentry := widget.NewEntry() archiverootentry.Text = cfg.ArchiveRoot container := container.NewBorder(nil, nil, nil, nil, widget.NewButtonWithIcon("", ap.Settings().Theme().Icon(theme.IconNameSettings), func() { dialog.NewForm("Settings", "Confirm", "Cancel", []*widget.FormItem{ widget.NewFormItem("Profiles Root Folder", profilesrootentry), widget.NewFormItem("Archive Root Folder", archiverootentry), }, func(b bool) { if b { cfg.ArchiveRoot = archiverootentry.Text cfg.ProfilesRoot = profilesrootentry.Text saveConfig(*cfg) fillGrid(grid, wp) } else { cfg.ArchiveRoot = archiverootentry.Text cfg.ProfilesRoot = profilesrootentry.Text fillGrid(grid, wp) } }, wp).Show() }), widget.NewButton("Reload", func() { //reload grid fillGrid(grid, wp) }), container.NewHScroll(grid), ) wp.SetContent(container) wp.ShowAndRun() } func fillGrid(grid *fyne.Container, parent fyne.Window) { profiles := scanProfiles(cfg.ProfilesRoot) archive := cfg.ArchiveRoot grid.Hide() defer grid.Show() grid.RemoveAll() for _, profile := range profiles { profilename := strings.TrimSuffix(filepath.Base(profile), ".cpms") grid.Add(widget.NewButton(profilename, makeIFunc(profile, archive, parent))) } } func scanProfiles(profilesroot string) []string { dir := filepath.Join(profilesroot, "*.cpms/") m, err := filepath.Glob(dir) if err != nil { fmt.Println(err) } return m } func makeIFunc(profile, archive string, parent fyne.Window) func() { return func() { dialog.NewConfirm("Are You Sure?", fmt.Sprintf("the current contents of %s will be lost", archive), func(b bool) { if b { err := walk(archive, func(path string, info fs.FileInfo, err error) error { err = os.Remove(path) if err != nil { fmt.Println(err) } return nil }) if err != nil { fmt.Println(err) } err = cp.Copy(profile, archive) if err != nil { fmt.Println(err) } dialog.NewInformation("Success", fmt.Sprintf("copied all files from %s to %s", filepath.Base(profile), archive), parent).Show() } }, parent).Show() } } func walk(root string, fn filepath.WalkFunc) error { initial := false return filepath.Walk(root, func(path string, info fs.FileInfo, err error) error { if !initial { initial = true return nil } return fn(path, info, err) }) }