Skip to content

Commit

Permalink
Add form validation
Browse files Browse the repository at this point in the history
  • Loading branch information
suchmememanyskill committed Jun 12, 2024
1 parent 2f8e755 commit 0012fce
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 46 deletions.
2 changes: 2 additions & 0 deletions Launcher/Forms/FormTemplates/TextBox.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public TextBox()

public TextBox(FormEntry entry) : this()
{
TextBlock.IsVisible = !string.IsNullOrEmpty(entry.Name);

TextBlock.Text = entry.Name;
TextBlock.HorizontalAlignment = entry.Alignment.ToAvaloniaAlignment();
if (!string.IsNullOrWhiteSpace(entry.Value))
Expand Down
25 changes: 23 additions & 2 deletions LauncherGamePlugin/Forms/Form.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,27 @@ public class Form

public Func<Task<byte[]?>>? Background { get; set; } = null;
public IGame? Game { get; set; } = null;

public TextBoxElement? ValidationFailureField { get; set; }

public bool Validate(IApp app)
{
try
{
FormEntries.ForEach(x => x.Validate());
}
catch (Exception ex)
{
if (ValidationFailureField != null)
{
ValidationFailureField.Name = ex.Message;
}
app.ShowForm(this);
return false;
}

return true;
}

public Form(List<FormEntry> entries)
{
Expand Down Expand Up @@ -48,9 +69,9 @@ public static Form CreateDismissibleTextPrompt(string text, IApp app)
public static FormEntry TextInput(string label, string value = "")
=> new TextInputElement(label, value);

public static FormEntry TextBox(string text, FormAlignment alignment = FormAlignment.Default,
public static TextBoxElement TextBox(string text, FormAlignment alignment = FormAlignment.Default,
string fontWeight = "")
=> new TextBoxElement(text, fontWeight, alignment: alignment);
=> new(text, fontWeight, alignment: alignment);

public static FormEntry ClickableLinkBox(string text, Action<Form> action,
FormAlignment alignment = FormAlignment.Default, string fontWeight = "")
Expand Down
4 changes: 4 additions & 0 deletions LauncherGamePlugin/Forms/FormEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ public abstract class FormEntry
public string Value { get; set; }
public bool Enabled { get; set; }
public Form ContainingForm { get; set; }
public List<IFormValidator> Validators { get; } = new();
public FormAlignment Alignment;
public event Action<FormEntry>? OnChange;
public void InvokeOnChange() => OnChange?.Invoke(this);
Expand All @@ -171,4 +172,7 @@ public FormEntry(string name = "", string value = "", FormAlignment alignment =
Enabled = enabled;
Alignment = alignment;
}

public void Validate()
=> Validators.ForEach(x => x.Validate(this));
}
71 changes: 71 additions & 0 deletions LauncherGamePlugin/Forms/FormValidator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
namespace LauncherGamePlugin.Forms;

public interface IFormValidator
{
// Throws on failed validation
public void Validate(FormEntry entry);
}

public class NotEmptyValidation : IFormValidator
{
public void Validate(FormEntry entry)
{
if (string.IsNullOrWhiteSpace(entry.Value))
throw new Exception($"{Utils.OnlyLetters(entry.Name)} is empty");
}
}

public class ExistsValidation : IFormValidator
{
public void Validate(FormEntry entry)
{
if (entry is FilePickerElement filePickerElement)
{
if (!File.Exists(entry.Value))
throw new Exception($"{Utils.OnlyLetters(filePickerElement.Name)} file does not exist on disk");
}

if (entry is FolderPickerElement folderPickerElement)
{
if (!Directory.Exists(entry.Value))
throw new Exception($"{Utils.OnlyLetters(folderPickerElement.Name)} folder does not exist on disk");
}
}
}

public class ContainsValidation : IFormValidator
{
private string _contians;

public ContainsValidation(string contains)
{
_contians = contains;
}

public void Validate(FormEntry entry)
{
if (!entry.Value.Contains(_contians))
throw new Exception($"{Utils.OnlyLetters(entry.Name)} does not contain {_contians}");
}
}

public static class FormEntryExtensions
{
public static FormEntry NotEmpty(this FormEntry formEntry)
{
formEntry.Validators.Add(new NotEmptyValidation());
return formEntry;
}

public static FormEntry Exists(this FormEntry formEntry)
{
formEntry.Validators.Add(new ExistsValidation());
return formEntry;
}

public static FormEntry Contains(this FormEntry formEntry, string contains)
{
formEntry.Validators.Add(new ContainsValidation(contains));
return formEntry;
}
}
4 changes: 4 additions & 0 deletions LauncherGamePlugin/Utils.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using LauncherGamePlugin.Enums;

namespace LauncherGamePlugin;
Expand Down Expand Up @@ -220,4 +221,7 @@ public static string TimeSpanAsTimeEstimate(TimeSpan estimatedTime)

return estimatedDisplay;
}

public static string OnlyLetters(string input)
=> new(input.Where(char.IsLetter).ToArray());
}
63 changes: 19 additions & 44 deletions RemoteDownloaderPlugin/Gui/AddOrEditEmuProfileGui.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ public class AddOrEditEmuProfileGui
private string _args;
private string _workDir;
private readonly bool _addOrUpdate;
private string _error;

public AddOrEditEmuProfileGui(IApp app, Plugin instance)
{
Expand All @@ -24,7 +23,6 @@ public AddOrEditEmuProfileGui(IApp app, Plugin instance)
_args = "";
_workDir = "";
_addOrUpdate = false;
_error = "";
}

public AddOrEditEmuProfileGui(IApp app, Plugin instance, EmuProfile profile)
Expand All @@ -42,11 +40,10 @@ public void ShowGui()
List<FormEntry> formEntries = new()
{
Form.TextBox(_addOrUpdate ? "Add new emulation platform" : "Edit emulation platform", FormAlignment.Left, "Bold"),
Form.TextInput("Platform:", _platform),
Form.FilePicker("Executable Path:", _path),
Form.TextInput("CLI Args:", _args),
Form.FolderPicker("Working Directory:", _workDir),

Form.TextInput("Platform:", _platform).NotEmpty(),
Form.FilePicker("Executable Path:", _path).NotEmpty().Exists(),
Form.TextInput("CLI Args:", _args).NotEmpty().Contains("{EXEC}"),
Form.FolderPicker("Working Directory:", _workDir).NotEmpty().Exists(),
};

if (_addOrUpdate)
Expand Down Expand Up @@ -75,51 +72,29 @@ public void ShowGui()
{
formEntries.Add(Form.Button("Cancel", _ => _app.HideForm(), "Save", Process));
}

if (!string.IsNullOrWhiteSpace(_error))
formEntries.Add(Form.TextBox(_error, fontWeight: "Bold"));

_app.ShowForm(formEntries);

var errorEntry = Form.TextBox("", FormAlignment.Center);
formEntries.Add(errorEntry);
var form = new Form(formEntries)
{
ValidationFailureField = errorEntry
};

_app.ShowForm(form);
}

public void Process(Form form)
{
if (!form.Validate(_app))
{
return;
}

_platform = form.GetValue("Platform:");
_path = form.GetValue("Executable Path:");
_args = form.GetValue("CLI Args:");
_workDir = form.GetValue("Working Directory:");

if (string.IsNullOrWhiteSpace(_platform) ||
string.IsNullOrWhiteSpace(_path) ||
string.IsNullOrWhiteSpace(_args) ||
string.IsNullOrWhiteSpace(_workDir))
{
_error = "Not all fields are filled";
ShowGui();
return;
}

if (!File.Exists(_path))
{
_error = "Executable path does not exist";
ShowGui();
return;
}

if (!Directory.Exists(_workDir))
{
_error = "Working directory does not exist";
ShowGui();
return;
}

if (!_args.Contains("{EXEC}"))
{
_error = "Args does not specify an {EXEC} param";
ShowGui();
return;
}


EmuProfile? existingProfile = _instance.Storage.Data.EmuProfiles.FirstOrDefault(x => x.Platform == _platform);
if (existingProfile == null)
{
Expand Down

0 comments on commit 0012fce

Please sign in to comment.