195 lines
4.4 KiB
Go
195 lines
4.4 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"s1d3sw1ped/swipedmodswitcher/admin"
|
|
"slices"
|
|
"strconv"
|
|
"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"
|
|
)
|
|
|
|
var Version = ""
|
|
|
|
type Config struct {
|
|
ModProfilesDirectory string `yaml:"mod_profiles_dir"`
|
|
GameModsDirectory string `yaml:"game_mods_dir"`
|
|
}
|
|
|
|
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{ModProfilesDirectory: "", GameModsDirectory: ""})
|
|
}
|
|
|
|
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 *Config
|
|
|
|
func main() {
|
|
if !admin.Admin() {
|
|
fmt.Println("not running as administrator relaunching")
|
|
if err := admin.RunSelfElevated(); err != nil {
|
|
panic(err)
|
|
}
|
|
os.Exit(0)
|
|
return // just incase
|
|
}
|
|
|
|
cfg = loadConfig()
|
|
|
|
ap := app.New()
|
|
wp := ap.NewWindow(ap.Metadata().Name + " v" + ap.Metadata().Version + "." + strconv.Itoa(ap.Metadata().Build))
|
|
wp.Resize(fyne.NewSize(600, 1))
|
|
wp.CenterOnScreen()
|
|
|
|
grid := container.NewVBox()
|
|
scroll := container.NewVScroll(grid)
|
|
scroll.SetMinSize(fyne.NewSize(-1, 400))
|
|
|
|
//load grid
|
|
fillGrid(grid, wp)
|
|
|
|
profilesrootentry := widget.NewEntry()
|
|
profilesrootentry.SetText(cfg.ModProfilesDirectory)
|
|
profilesrootentry.Disable()
|
|
|
|
archiverootentry := widget.NewEntry()
|
|
archiverootentry.SetText(cfg.GameModsDirectory)
|
|
archiverootentry.Disable()
|
|
|
|
container := container.NewVBox(
|
|
widget.NewForm(widget.NewFormItem("Mod Profiles Directory", profilesrootentry)),
|
|
widget.NewButtonWithIcon("Select", theme.FolderIcon(), func() {
|
|
dialog.NewFolderOpen(func(lu fyne.ListableURI, err error) {
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
if lu == nil {
|
|
return
|
|
}
|
|
profilesrootentry.SetText(lu.Path())
|
|
cfg.ModProfilesDirectory = lu.Path()
|
|
saveConfig(*cfg)
|
|
fillGrid(grid, wp)
|
|
}, wp).Show()
|
|
}),
|
|
widget.NewForm(widget.NewFormItem("Game Mod Directory", archiverootentry)),
|
|
widget.NewButtonWithIcon("Select", theme.FolderIcon(), func() {
|
|
dialog.NewFolderOpen(func(lu fyne.ListableURI, err error) {
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
if lu == nil {
|
|
return
|
|
}
|
|
archiverootentry.SetText(lu.Path())
|
|
cfg.GameModsDirectory = lu.Path()
|
|
saveConfig(*cfg)
|
|
fillGrid(grid, wp)
|
|
}, wp).Show()
|
|
}),
|
|
widget.NewSeparator(),
|
|
widget.NewButton("Reload Mod Profiles", func() {
|
|
fillGrid(grid, wp)
|
|
}),
|
|
scroll,
|
|
)
|
|
wp.SetContent(container)
|
|
wp.ShowAndRun()
|
|
}
|
|
|
|
func fillGrid(grid *fyne.Container, parent fyne.Window) {
|
|
profiles := scanProfiles(cfg.ModProfilesDirectory)
|
|
archive := cfg.GameModsDirectory
|
|
grid.Hide()
|
|
defer grid.Show()
|
|
grid.RemoveAll()
|
|
if admin.Admin() {
|
|
for _, profile := range profiles {
|
|
profilename := filepath.Base(profile)
|
|
grid.Add(widget.NewButton(profilename, makeIFunc(profile, archive, parent)))
|
|
}
|
|
} else {
|
|
grid.Add(widget.NewLabel("not running as administrator"))
|
|
}
|
|
}
|
|
|
|
func scanProfiles(profilesroot string) []string {
|
|
dir := filepath.Join(profilesroot, "*/")
|
|
m, err := filepath.Glob(dir)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
|
|
mm := []string{}
|
|
|
|
for _, path := range m {
|
|
if s, err := os.Stat(path); err == nil && !strings.HasPrefix(s.Name(), ".") && s.IsDir() {
|
|
mm = append(mm, path)
|
|
}
|
|
}
|
|
|
|
slices.SortStableFunc(mm, func(a, b string) int {
|
|
return strings.Compare(a, b)
|
|
})
|
|
|
|
return mm
|
|
}
|
|
|
|
func makeIFunc(profile, archive string, parent fyne.Window) func() {
|
|
return func() {
|
|
if cfg.GameModsDirectory == "" || cfg.ModProfilesDirectory == "" {
|
|
dialog.NewInformation("Notice", "you must select a game mod directory and mod profiles directory before", parent).Show()
|
|
return
|
|
}
|
|
|
|
// delete any existing archive folder
|
|
_ = os.RemoveAll(archive)
|
|
|
|
// link the profile to the archive
|
|
err := os.Symlink(profile, archive)
|
|
if err != nil {
|
|
dialog.NewInformation("Error", "error linking most likely issue is Swiped Mod Switcher is not running as admin", parent).Show()
|
|
return
|
|
}
|
|
|
|
dialog.NewInformation("Success", fmt.Sprintf("filinked files from %s to %s", filepath.Base(profile), archive), parent).Show()
|
|
}
|
|
}
|