package fsService import ( "fmt" "g-launcher/pkg/sevenzip" "os" "os/exec" "path/filepath" "runtime" "strings" "github.com/wailsapp/wails/v3/pkg/application" "golang.org/x/sys/windows" ) type FSService struct{} func (f *FSService) PickFolder() (string, error) { dialog := application.Get().Dialog.OpenFile(). CanChooseDirectories(true). CanChooseFiles(false). ResolvesAliases(true) if runtime.GOOS == "darwin" { dialog.SetMessage("Select a folder") } else { dialog.SetTitle("Select a folder") } return dialog.PromptForSingleSelection() } func (f *FSService) PickFile(filter string) (string, error) { dialog := application.Get().Dialog.OpenFile(). CanChooseFiles(true). ResolvesAliases(true) if runtime.GOOS == "darwin" { dialog.SetMessage("Select a file") } else { dialog.SetTitle("Select a file") } if filter == "exe" { dialog.AddFilter("Executable Files (*.exe)", "*.exe") } else if filter == "zip" { dialog.AddFilter("ZIP archives (*.zip)", "*.zip") } else if filter == "patch" { dialog.AddFilter("Patch files (*.zip;*.7z;*.ziff)", "*.zip;*.7z;*.ziff") } if path, err := dialog.PromptForSingleSelection(); err == nil { return path, nil } return "", nil } func (f *FSService) DirExists(path string) bool { info, err := os.Stat(path) if err != nil { return false } return info.IsDir() } func (f *FSService) FileExists(path string) bool { if info, err := os.Stat(path); err == nil { return info.Mode().IsRegular() } return false } func (f *FSService) GetDir(path string) string { return filepath.Dir(path) } func (f *FSService) Join(paths ...string) string { return filepath.Join(paths...) } func (f *FSService) RemoveFile(path string) error { return os.Remove(path) } func (f *FSService) StartApp(path string) (bool, string) { dir := filepath.Dir(path) cmd := exec.Command(path) cmd.Dir = dir err := cmd.Start() if err != nil { return false, err.Error() } if strings.HasSuffix(path, "StarRail.exe") || strings.HasSuffix(path, "ZenlessZoneZeroBeta.exe") { go func() { _ = cmd.Wait() application.Get().Event.Emit("game:exit") }() } return true, "" } func (f *FSService) StartWithConsole(path string) (bool, string) { absPath, err := filepath.Abs(path) if err != nil { return false, err.Error() } if _, err := os.Stat(absPath); os.IsNotExist(err) { return false, "file not found: " + absPath } cmd := exec.Command(absPath) cmd.Dir = filepath.Dir(absPath) cmd.Stdin = nil cmd.Stdout = nil cmd.Stderr = nil cmd.SysProcAttr = &windows.SysProcAttr{ CreationFlags: windows.CREATE_NEW_CONSOLE | windows.CREATE_BREAKAWAY_FROM_JOB, NoInheritHandles: true, } err = cmd.Start() if err != nil { return false, err.Error() } go func() { _ = cmd.Wait() base := strings.ToLower(filepath.Base(path)) if base == "launcher.exe" || base == "starrail.exe" { application.Get().Event.Emit("game:exit") } else if base == "firefly-go_win.exe" || base == "gameserver.exe" { application.Get().Event.Emit("server:exit") } else if base == "firefly-go-proxy.exe" || base == "proxy.exe" { application.Get().Event.Emit("proxy:exit") } }() return true, "" } func (f *FSService) OpenFolder(path string) (bool, string) { absPath, err := filepath.Abs(path) if err != nil { return false, "failed to resolve absolute path: " + err.Error() } if !f.DirExists(absPath) { return false, "directory not found: " + absPath } url := "file:///" + filepath.ToSlash(absPath) application.Get().Browser.OpenURL(url) return true, "" } func (f *FSService) FileExistsInZip(archivePath, fileInside string) (bool, string) { exists, err := sevenzip.IsFileIn7z(archivePath, fileInside) if err != nil { return false, err.Error() } return exists, "" } func (f *FSService) ReadConfigFile(gameDir, fileName string) (string, error) { if strings.TrimSpace(gameDir) == "" { return "", fmt.Errorf("select the game folder first") } target := filepath.Join(gameDir, fileName) content, err := os.ReadFile(target) if err != nil { if os.IsNotExist(err) { return "", nil } return "", fmt.Errorf("read file %s: %w", target, err) } return string(content), nil } func (f *FSService) WriteConfigFile(gameDir, fileName, content string) error { if strings.TrimSpace(gameDir) == "" { return fmt.Errorf("select the game folder first") } target := filepath.Join(gameDir, fileName) return os.WriteFile(target, []byte(content), 0644) }