Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix default path for game #1

Merged
merged 1 commit into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 5 additions & 26 deletions backend/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"runtime"

"github.com/cabaalexander/save-manager/backend/utils"
rt "github.com/wailsapp/wails/v2/pkg/runtime"
)

Expand All @@ -27,34 +28,12 @@ func (a *App) ToggleFullScreen() {
}
}

func (a *App) OpenDirectoryDialog() string {
path, err := rt.OpenDirectoryDialog(a.ctx, a.getDefaultFileOrDirPath())
if err != nil {
return ""
}
return path
}

func (a *App) OpenFileDialog() string {
path, err := rt.OpenFileDialog(a.ctx, a.getDefaultFileOrDirPath())
if err != nil {
return ""
}
return path
func (a *App) OpenDialogDirApp() (string, error) {
return utils.OpenDialogDir(a.ctx, a.Settings.DefaultSavePath, false)
}

func (a *App) getDefaultFileOrDirPath() rt.OpenDialogOptions {
defaultPath := a.Settings.DefaultSavePath
if a.Settings.JsonSettings.DefaultSavePathIsFile {
return rt.OpenDialogOptions{
DefaultFilename: defaultPath,
Title: "Select File",
}
}
return rt.OpenDialogOptions{
DefaultDirectory: defaultPath,
Title: "Select Directory",
}
func (a *App) OpenDialogFileApp() (string, error) {
return utils.OpenDialogFile(a.ctx, a.Settings.DefaultSavePath, true)
}

func (a *App) GetOS() string {
Expand Down
26 changes: 19 additions & 7 deletions backend/game.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ import (
)

type GameSingle struct {
ID uuid.UUID
Name string
SavePath string
ID uuid.UUID
Name string
SavePath string
SavePathIsFile bool
}

type JsonGame struct {
Expand All @@ -39,9 +40,9 @@ func (g *Game) Startup(ctx context.Context) {
g.JsonGame = *game
}

func (g *Game) AddGame(name string, savePath string) uuid.UUID {
func (g *Game) AddGame(name, savePath string, isFile bool) uuid.UUID {
id := uuid.New()
game := GameSingle{ID: id, Name: name, SavePath: savePath}
game := GameSingle{ID: id, Name: name, SavePath: savePath, SavePathIsFile: isFile}
g.JsonGame.Data = append(g.JsonGame.Data, game)
g.updateJson()
CreateGameDir(id)
Expand Down Expand Up @@ -81,10 +82,10 @@ func (g *Game) FindGame(id uuid.UUID) GameSingle {
return GameSingle{}
}

func (g *Game) OpenGameDir(gameID uuid.UUID) {
func (g *Game) BrowseGameDir(gameID uuid.UUID) {
for _, game := range g.JsonGame.Data {
if game.ID == gameID {
utils.OpenPath(g.ctx, game.SavePath)
utils.BrowsePath(g.ctx, game.SavePath)
}
}
}
Expand All @@ -99,13 +100,24 @@ func (g *Game) UpdateGame(props GameSingle) {
if props.SavePath != "" {
gm.SavePath = props.SavePath
}
gm.SavePathIsFile = props.SavePathIsFile
}
gameList = append(gameList, gm)
}
g.JsonGame.Data = gameList
g.updateJson()
}

func (g *Game) OpenDialogDirGame(gameID uuid.UUID) (string, error) {
game := g.FindGame(gameID)
return utils.OpenDialogDir(g.ctx, game.SavePath, game.SavePathIsFile)
}

func (g *Game) OpenDialogFileGame(gameID uuid.UUID) (string, error) {
game := g.FindGame(gameID)
return utils.OpenDialogFile(g.ctx, game.SavePath, game.SavePathIsFile)
}

func (g *Game) removeGameDir(gameID uuid.UUID) error {
gameDir, err := GetGameDir(gameID)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion backend/save-quicksave.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (s *Save) OpenQuickSaveDir(gameID uuid.UUID) error {
if err != nil {
return err
}
if err = utils.OpenPath(s.ctx, quickSaveDir); err != nil {
if err = utils.BrowsePath(s.ctx, quickSaveDir); err != nil {
return err
}
return nil
Expand Down
2 changes: 1 addition & 1 deletion backend/save.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func (s *Save) OpenSaveDir(saveID, gameID uuid.UUID) error {
if err != nil {
return err
}
utils.OpenPath(s.ctx, saveDir)
utils.BrowsePath(s.ctx, saveDir)
return nil
}

Expand Down
4 changes: 2 additions & 2 deletions backend/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ func (s *Settings) ReadSettings() (*JsonSettings, error) {
return settingsJson, nil
}

func (s *Settings) SetDefaultSavePath(text string, isFile bool) {
s.JsonSettings.DefaultSavePath = text
func (s *Settings) SetDefaultSavePath(path string, isFile bool) {
s.JsonSettings.DefaultSavePath = path
s.JsonSettings.DefaultSavePathIsFile = isFile
s.updateJson()
}
Expand Down
61 changes: 60 additions & 1 deletion backend/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io/fs"
"os"
"path"
"path/filepath"

rt "github.com/wailsapp/wails/v2/pkg/runtime"
)
Expand Down Expand Up @@ -158,7 +159,14 @@ type StartAble interface {
Startup(ctx context.Context)
}

func OpenPath(ctx context.Context, path string) error {
func BrowsePath(ctx context.Context, path string) error {
pathIsFile, err := isPathFile(path)
if err != nil {
return err
}
if pathIsFile {
path = filepath.Dir(path)
}
rt.BrowserOpenURL(ctx, path)
return nil
}
Expand All @@ -170,3 +178,54 @@ func StartApps(l []StartAble) func(ctx context.Context) {
}
}
}

func OpenDialogFile(ctx context.Context, path string, isFile bool) (string, error) {
path, err := rt.OpenFileDialog(ctx, getFileOrDirOptions(path, isFile))
if err != nil {
return "", err
}
return path, nil
}

func OpenDialogDir(ctx context.Context, path string, isFile bool) (string, error) {
pathIsFile, err := isPathFile(path)
if err != nil {
return "", err
}
// if path is a file get parent dir (so this opens a directory efectively)
if pathIsFile {
path = filepath.Dir(path)
}
path, err = rt.OpenDirectoryDialog(
ctx,
getFileOrDirOptions(path, isFile),
)
if err != nil {
return "", err
}
return path, nil
}

func getFileOrDirOptions(path string, isFile bool) rt.OpenDialogOptions {
if isFile {
return rt.OpenDialogOptions{
DefaultFilename: path,
Title: "Select File",
}
}
return rt.OpenDialogOptions{
DefaultDirectory: path,
Title: "Select Directory",
}
}

func isPathFile(path string) (bool, error) {
fileInfo, err := os.Stat(path)
if err != nil {
return false, err
}
if fileInfo.IsDir() {
return false, nil
}
return true, nil
}
1 change: 1 addition & 0 deletions frontend/src/components/AddGame.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const AddGame = () => {
const gameID = (await addGame({
Name: data.Name,
SavePath: data.SavePath,
SavePathIsFile: data.SavePathIsFile,
})) as string;
navigate(`/game/${gameID}`);
}}
Expand Down
77 changes: 60 additions & 17 deletions frontend/src/components/DialogGameForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
Input,
Typography,
} from "@material-tailwind/react";
import { OpenDirectoryDialog, OpenFileDialog } from "@wailsjs/go/backend/App";
import clsx from "clsx";
import {
type Dispatch,
Expand All @@ -21,28 +20,34 @@ import {
import { type SubmitHandler, useForm } from "react-hook-form";
import { FaDirections } from "react-icons/fa";
import { FaX } from "react-icons/fa6";
import { OpenDialogDirApp, OpenDialogFileApp } from "@wailsjs/go/backend/App";
import {
OpenDialogDirGame,
OpenDialogFileGame,
} from "@wailsjs/go/backend/Game";
import { type GameSingle } from "@/hooks/useGame";
import useSettings from "@/hooks/useSettings";

const TRANSITION_TIMEOUT = 300;

type FormInputs = Pick<GameSingle, "Name" | "SavePath">;
type FormInputs = Pick<GameSingle, "Name" | "SavePath" | "SavePathIsFile">;

type DialogGameFormDefaultValues = {
formInputs: Partial<FormInputs>;
gameID: string;
};

type DialogGameFormProps = {
open: boolean;
handler: Dispatch<SetStateAction<boolean>>;
title: string;
bodyTitle?: string;
required?: Partial<Record<keyof FormInputs, boolean>>;
defaultValues?: Partial<Record<keyof FormInputs, string>>;
defaultValues?: Partial<DialogGameFormDefaultValues>;
submit: (data: FormInputs) => unknown;
};

const DialogGameForm: FC<DialogGameFormProps> = (props) => {
const { querySettings } = useSettings();
const [isFileDialog, setIsFileDialog] = useState<boolean>(
querySettings.data?.DefaultSavePathIsFile ?? false,
);
const {
register,
handleSubmit,
Expand All @@ -53,19 +58,42 @@ const DialogGameForm: FC<DialogGameFormProps> = (props) => {
formState: { errors: formErrors },
} = useForm<FormInputs>();
const { defaultValues } = props;
const { querySettings } = useSettings();

const defaultIsFile =
defaultValues?.formInputs?.SavePathIsFile ??
querySettings.data?.DefaultSavePathIsFile ??
false;

const [isFileDialog, setIsFileDialog] = useState<boolean>(defaultIsFile);

const onSubmit: SubmitHandler<FormInputs> = (data) => props.submit(data);

const handlePath = async () => {
const path = isFileDialog
? await OpenFileDialog()
: await OpenDirectoryDialog();
let path = "";

if (defaultValues?.formInputs?.SavePath === "") {
path = isFileDialog
? await OpenDialogFileApp()
: await OpenDialogDirApp();
} else {
path = isFileDialog
? await OpenDialogFileGame(defaultValues?.gameID)
: await OpenDialogDirGame(defaultValues?.gameID);
}

if (path === "") return;

setValue("SavePath", path);
clearErrors("SavePath");
setFocus("Name");
};

const handleIsFile = () => {
setIsFileDialog(!isFileDialog);
setValue("SavePathIsFile", !isFileDialog);
};

useEffect(() => {
if (props.open) {
setTimeout(() => {
Expand All @@ -75,13 +103,17 @@ const DialogGameForm: FC<DialogGameFormProps> = (props) => {
});

useEffect(() => {
if (defaultValues) {
Object.entries(defaultValues).forEach(([key, value]) => {
if (defaultValues?.formInputs) {
Object.entries(defaultValues.formInputs).forEach(([key, value]) => {
setValue(key as keyof FormInputs, value);
});
}
}, [defaultValues, setValue]);

useEffect(() => {
setIsFileDialog(defaultIsFile);
}, [defaultIsFile]);

const toggleDialog = () => {
props.handler(!props.open);
setTimeout(() => {
Expand Down Expand Up @@ -151,11 +183,15 @@ const DialogGameForm: FC<DialogGameFormProps> = (props) => {

<Checkbox
checked={isFileDialog}
onChange={() => {
setIsFileDialog(!isFileDialog);
}}
onChange={handleIsFile}
label="File"
/>
<input
className="hidden"
{...register("SavePathIsFile", {
required: props.required?.SavePathIsFile,
})}
/>
</div>
</div>
</DialogBody>
Expand All @@ -166,7 +202,8 @@ const DialogGameForm: FC<DialogGameFormProps> = (props) => {
</Button>

<Button type="submit" variant="gradient" color="gray">
Create Game
{defaultValues?.formInputs?.SavePath === "" ? "CREATE" : "SAVE"}
<span> GAME</span>
</Button>
</DialogFooter>
</form>
Expand All @@ -177,7 +214,13 @@ const DialogGameForm: FC<DialogGameFormProps> = (props) => {
DialogGameForm.defaultProps = {
bodyTitle: "",
required: { Name: false, SavePath: false },
defaultValues: { Name: "", SavePath: "" },
defaultValues: {
formInputs: {
Name: "",
SavePath: "",
},
gameID: "",
},
};

export default DialogGameForm;
Loading