Refactor bootstrapper dialog property changing

Directly interacting with the dialog via an interface instead of using events, cuts down on a lot of boilerplate
This commit is contained in:
pizzaboxer 2022-08-21 23:37:26 +01:00
parent 92b159d682
commit 0da759d1f4
10 changed files with 110 additions and 327 deletions

View File

@ -20,7 +20,6 @@ namespace Bloxstrap
private string VersionGuid;
private PackageManifest VersionPackageManifest;
private FileManifest VersionFileManifest;
private string VersionFolder;
private readonly bool FreshInstall;
@ -83,80 +82,7 @@ namespace Bloxstrap
// TODO: reduce reliance on event handlers for signalling property changes to the bootstrapper dialog
// i mean, chances are we can just use IBootstrapperDialog now?
// public IBootstrapperDialog BootstrapperDialog;
public event EventHandler CloseDialogEvent;
public event EventHandler PromptShutdownEvent;
public event ChangeEventHandler<string> ShowSuccessEvent;
public event ChangeEventHandler<string> MessageChanged;
public event ChangeEventHandler<int> ProgressBarValueChanged;
public event ChangeEventHandler<ProgressBarStyle> ProgressBarStyleChanged;
public event ChangeEventHandler<bool> CancelEnabledChanged;
private string _message;
private int _progress = 0;
private ProgressBarStyle _progressStyle = ProgressBarStyle.Marquee;
private bool _cancelEnabled = false;
public string Message
{
get => _message;
private set
{
if (_message == value)
return;
MessageChanged.Invoke(this, new ChangeEventArgs<string>(value));
_message = value;
}
}
public int Progress
{
get => _progress;
private set
{
if (_progress == value)
return;
ProgressBarValueChanged.Invoke(this, new ChangeEventArgs<int>(value));
_progress = value;
}
}
public ProgressBarStyle ProgressStyle
{
get => _progressStyle;
private set
{
if (_progressStyle == value)
return;
ProgressBarStyleChanged.Invoke(this, new ChangeEventArgs<ProgressBarStyle>(value));
_progressStyle = value;
}
}
public bool CancelEnabled
{
get => _cancelEnabled;
private set
{
if (_cancelEnabled == value)
return;
CancelEnabledChanged.Invoke(this, new ChangeEventArgs<bool>(value));
_cancelEnabled = value;
}
}
public IBootstrapperDialog Dialog;
#endregion
#region Core
@ -196,18 +122,6 @@ namespace Bloxstrap
public async Task Run()
{
/* Message = "hi";
Progress = 42;
ProgressStyle = ProgressBarStyle.Blocks;
CancelEnabled = true;
BootstrapperDialog.Message = "hi";
BootstrapperDialog.ProgressValue = 42;
BootstrapperDialog.ProgressStyle = ProgressBarStyle.Blocks;
BootstrapperDialog.CancelEnabled = true;
return; */
if (LaunchCommandLine == "-uninstall")
{
Uninstall();
@ -243,12 +157,11 @@ namespace Bloxstrap
private async Task CheckLatestVersion()
{
Message = "Connecting to Roblox...";
Dialog.Message = "Connecting to Roblox...";
VersionGuid = await Client.GetStringAsync($"{Program.BaseUrlSetup}/version");
VersionFolder = Path.Combine(Directories.Versions, VersionGuid);
VersionPackageManifest = await PackageManifest.Get(VersionGuid);
VersionFileManifest = await FileManifest.Get(VersionGuid);
}
private void CheckIfRunning()
@ -256,7 +169,7 @@ namespace Bloxstrap
Process[] processes = Process.GetProcessesByName("RobloxPlayerBeta");
if (processes.Length > 0)
PromptShutdown();
Dialog.PromptShutdown();
try
{
@ -275,7 +188,7 @@ namespace Bloxstrap
{
string startEventName = Program.ProjectName.Replace(" ", "") + "StartEvent";
Message = "Starting Roblox...";
Dialog.Message = "Starting Roblox...";
// launch time isn't really required for all launches, but it's usually just safest to do this
LaunchCommandLine += " --launchtime=" + DateTimeOffset.Now.ToUnixTimeSeconds() + " -startEvent " + startEventName;
@ -334,7 +247,7 @@ namespace Bloxstrap
return;
// keep bloxstrap open in the background
CloseDialog();
Dialog.CloseDialog();
await gameClient.WaitForExitAsync();
if (richPresence is not null)
@ -347,7 +260,7 @@ namespace Bloxstrap
public void CancelButtonClicked()
{
if (!CancelEnabled)
if (!Dialog.CancelEnabled)
{
Program.Exit();
return;
@ -366,21 +279,6 @@ namespace Bloxstrap
Program.Exit();
}
private void ShowSuccess(string message)
{
ShowSuccessEvent.Invoke(this, new ChangeEventArgs<string>(message));
}
private void PromptShutdown()
{
PromptShutdownEvent.Invoke(this, new EventArgs());
}
private void CloseDialog()
{
CloseDialogEvent.Invoke(this, new EventArgs());
}
#endregion
#region App Install
@ -454,7 +352,7 @@ namespace Bloxstrap
{
CheckIfRunning();
Message = $"Uninstalling {Program.ProjectName}...";
Dialog.Message = $"Uninstalling {Program.ProjectName}...";
Program.SettingsManager.ShouldSave = false;
@ -492,7 +390,7 @@ namespace Bloxstrap
}
catch (Exception) { }
ShowSuccess($"{Program.ProjectName} has been uninstalled");
Dialog.ShowSuccess($"{Program.ProjectName} has been uninstalled");
}
#endregion
@ -502,18 +400,18 @@ namespace Bloxstrap
CheckIfRunning();
if (FreshInstall)
Message = "Installing Roblox...";
Dialog.Message = "Installing Roblox...";
else
Message = "Upgrading Roblox...";
Dialog.Message = "Upgrading Roblox...";
Directory.CreateDirectory(Directories.Base);
CancelEnabled = true;
Dialog.CancelEnabled = true;
// i believe the original bootstrapper bases the progress bar off zip
// extraction progress, but here i'm doing package download progress
ProgressStyle = ProgressBarStyle.Continuous;
Dialog.ProgressStyle = ProgressBarStyle.Continuous;
ProgressIncrement = (int)Math.Floor((decimal)1 / VersionPackageManifest.Count * 100);
@ -529,14 +427,14 @@ namespace Bloxstrap
{
// wait for download to finish (and also round off the progress bar if needed)
if (Progress == ProgressIncrement * VersionPackageManifest.Count)
Progress = 100;
if (Dialog.ProgressValue == ProgressIncrement * VersionPackageManifest.Count)
Dialog.ProgressValue = 100;
await Task.Delay(1000);
}
while (Progress != 100);
while (Dialog.ProgressValue != 100);
ProgressStyle = ProgressBarStyle.Marquee;
Dialog.ProgressStyle = ProgressBarStyle.Marquee;
Debug.WriteLine("Finished downloading");
@ -550,7 +448,7 @@ namespace Bloxstrap
Debug.WriteLine("Finished extracting packages");
Message = "Configuring Roblox...";
Dialog.Message = "Configuring Roblox...";
string appSettingsLocation = Path.Combine(VersionFolder, "AppSettings.xml");
await File.WriteAllTextAsync(appSettingsLocation, AppSettings);
@ -571,7 +469,7 @@ namespace Bloxstrap
}
}
CancelEnabled = false;
Dialog.CancelEnabled = false;
Program.Settings.VersionGuid = VersionGuid;
}
@ -660,12 +558,11 @@ namespace Bloxstrap
{
string modFolderLocation = Path.Combine(Directories.Modifications, location);
Directory.CreateDirectory(Path.GetDirectoryName(modFolderLocation));
if (condition)
{
if (!File.Exists(modFolderLocation))
{
Directory.CreateDirectory(Path.GetDirectoryName(modFolderLocation));
File.WriteAllBytes(modFolderLocation, Convert.FromBase64String(base64Contents));
}
}
@ -694,7 +591,7 @@ namespace Bloxstrap
else
{
Debug.WriteLine($"{package.Name} is already downloaded, skipping...");
Progress += ProgressIncrement;
Dialog.ProgressValue += ProgressIncrement;
return;
}
}
@ -705,7 +602,7 @@ namespace Bloxstrap
Debug.WriteLine($"Found existing version of {package.Name} ({robloxPackageLocation})! Copying to Downloads folder...");
File.Copy(robloxPackageLocation, packageLocation);
Progress += ProgressIncrement;
Dialog.ProgressValue += ProgressIncrement;
return;
}
@ -724,7 +621,7 @@ namespace Bloxstrap
}
Debug.WriteLine($"Finished downloading {package.Name}!");
Progress += ProgressIncrement;
Dialog.ProgressValue += ProgressIncrement;
}
}

View File

@ -7,11 +7,58 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
{
public Bootstrapper? Bootstrapper { get; set; }
public virtual string Message { get; set; }
public virtual ProgressBarStyle ProgressStyle { get; set; }
public virtual int ProgressValue { get; set; }
public virtual bool CancelEnabled { get; set; }
protected virtual string _message { get; set; }
protected virtual ProgressBarStyle _progressStyle { get; set; }
protected virtual int _progressValue { get; set; }
protected virtual bool _cancelEnabled { get; set; }
public string Message
{
get => _message;
set
{
if (this.InvokeRequired)
this.Invoke(new Action(() => { Message = value; }));
else
_message = value;
}
}
public ProgressBarStyle ProgressStyle
{
get => _progressStyle;
set
{
if (this.InvokeRequired)
this.Invoke(new Action(() => { ProgressStyle = value; }));
else
_progressStyle = value;
}
}
public int ProgressValue
{
get => _progressValue;
set
{
if (this.InvokeRequired)
this.Invoke(new Action(() => { ProgressValue = value; }));
else
_progressValue = value;
}
}
public bool CancelEnabled
{
get => _cancelEnabled;
set
{
if (this.InvokeRequired)
this.Invoke(new Action(() => { CancelEnabled = value; }));
else
_cancelEnabled = value;
}
}
public void SetupDialog()
{
@ -25,14 +72,7 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
}
else
{
Bootstrapper.CloseDialogEvent += new EventHandler(CloseDialog);
Bootstrapper.PromptShutdownEvent += new EventHandler(PromptShutdown);
Bootstrapper.ShowSuccessEvent += new ChangeEventHandler<string>(ShowSuccess);
Bootstrapper.MessageChanged += new ChangeEventHandler<string>(MessageChanged);
Bootstrapper.ProgressBarValueChanged += new ChangeEventHandler<int>(ProgressBarValueChanged);
Bootstrapper.ProgressBarStyleChanged += new ChangeEventHandler<ProgressBarStyle>(ProgressBarStyleChanged);
Bootstrapper.CancelEnabledChanged += new ChangeEventHandler<bool>(CancelEnabledChanged);
Bootstrapper.Dialog = this;
Task.Run(() => RunBootstrapper());
}
}
@ -55,10 +95,10 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
}
}
public virtual void ShowSuccess(object sender, ChangeEventArgs<string> e)
public virtual void ShowSuccess(string message)
{
MessageBox.Show(
e.Value,
message,
Program.ProjectName,
MessageBoxButtons.OK,
MessageBoxIcon.Information
@ -79,20 +119,15 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
Program.Exit();
}
public virtual void CloseDialog(object? sender, EventArgs e)
public virtual void CloseDialog()
{
if (this.InvokeRequired)
{
EventHandler handler = new(CloseDialog);
this.Invoke(handler, sender, e);
}
this.Invoke(CloseDialog);
else
{
this.Hide();
}
}
public void PromptShutdown(object? sender, EventArgs e)
public void PromptShutdown()
{
DialogResult result = MessageBox.Show(
"Roblox is currently running, but needs to close. Would you like close Roblox now?",
@ -105,60 +140,6 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
Environment.Exit(0);
}
public void MessageChanged(object sender, ChangeEventArgs<string> e)
{
if (this.InvokeRequired)
{
ChangeEventHandler<string> handler = new(MessageChanged);
this.Invoke(handler, sender, e);
}
else
{
Message = e.Value;
}
}
public void ProgressBarStyleChanged(object sender, ChangeEventArgs<ProgressBarStyle> e)
{
if (this.InvokeRequired)
{
ChangeEventHandler<ProgressBarStyle> handler = new(this.ProgressBarStyleChanged);
this.Invoke(handler, sender, e);
}
else
{
ProgressStyle = e.Value;
}
}
public void ProgressBarValueChanged(object sender, ChangeEventArgs<int> e)
{
if (this.InvokeRequired)
{
ChangeEventHandler<int> handler = new(ProgressBarValueChanged);
this.Invoke(handler, sender, e);
}
else
{
ProgressValue = e.Value;
}
}
public void CancelEnabledChanged(object sender, ChangeEventArgs<bool> e)
{
if (this.InvokeRequired)
{
ChangeEventHandler<bool> handler = new(CancelEnabledChanged);
this.Invoke(handler, sender, e);
}
else
{
this.CancelEnabled = e.Value;
}
}
public void ButtonCancel_Click(object? sender, EventArgs e)
{
if (Bootstrapper is null)

View File

@ -12,16 +12,9 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
bool CancelEnabled { get; set; }
void RunBootstrapper();
void ShowSuccess(string message);
void ShowError(string message);
void ShowSuccess(object sender, ChangeEventArgs<string> e);
void CloseDialog(object? sender, EventArgs e);
void PromptShutdown(object? sender, EventArgs e);
void MessageChanged(object sender, ChangeEventArgs<string> e);
void ProgressBarValueChanged(object sender, ChangeEventArgs<int> e);
void ProgressBarStyleChanged(object sender, ChangeEventArgs<ProgressBarStyle> e);
void CancelEnabledChanged(object sender, ChangeEventArgs<bool> e);
void ButtonCancel_Click(object sender, EventArgs e);
void CloseDialog();
void PromptShutdown();
}
}

View File

@ -5,25 +5,25 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
public partial class LegacyDialog2009 : BootstrapperStyleForm
{
public override string Message
protected override string _message
{
get => labelMessage.Text;
set => labelMessage.Text = value;
}
public override ProgressBarStyle ProgressStyle
protected override ProgressBarStyle _progressStyle
{
get => ProgressBar.Style;
set => ProgressBar.Style = value;
}
public override int ProgressValue
protected override int _progressValue
{
get => ProgressBar.Value;
set => ProgressBar.Value = value;
}
public override bool CancelEnabled
protected override bool _cancelEnabled
{
get => this.buttonCancel.Enabled;
set => this.buttonCancel.Enabled = value;

View File

@ -6,25 +6,25 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
public partial class LegacyDialog2011 : BootstrapperStyleForm
{
public override string Message
protected override string _message
{
get => labelMessage.Text;
set => labelMessage.Text = value;
}
public override ProgressBarStyle ProgressStyle
protected override ProgressBarStyle _progressStyle
{
get => ProgressBar.Style;
set => ProgressBar.Style = value;
}
public override int ProgressValue
protected override int _progressValue
{
get => ProgressBar.Value;
set => ProgressBar.Value = value;
}
public override bool CancelEnabled
protected override bool _cancelEnabled
{
get => this.buttonCancel.Enabled;
set => this.buttonCancel.Enabled = this.buttonCancel.Visible = value;

View File

@ -6,25 +6,25 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
public partial class ProgressDialog : BootstrapperStyleForm
{
public override string Message
protected override string _message
{
get => labelMessage.Text;
set => labelMessage.Text = value;
}
public override ProgressBarStyle ProgressStyle
protected override ProgressBarStyle _progressStyle
{
get => ProgressBar.Style;
set => ProgressBar.Style = value;
}
public override int ProgressValue
protected override int _progressValue
{
get => ProgressBar.Value;
set => ProgressBar.Value = value;
}
public override bool CancelEnabled
protected override bool _cancelEnabled
{
get => this.buttonCancel.Enabled;
set => this.buttonCancel.Enabled = this.buttonCancel.Visible = value;

View File

@ -6,25 +6,25 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
public partial class ProgressDialogDark : BootstrapperStyleForm
{
public override string Message
protected override string _message
{
get => labelMessage.Text;
set => labelMessage.Text = value;
}
public override ProgressBarStyle ProgressStyle
protected override ProgressBarStyle _progressStyle
{
get => ProgressBar.Style;
set => ProgressBar.Style = value;
}
public override int ProgressValue
protected override int _progressValue
{
get => ProgressBar.Value;
set => ProgressBar.Value = value;
}
public override bool CancelEnabled
protected override bool _cancelEnabled
{
get => this.buttonCancel.Enabled;
set => this.buttonCancel.Enabled = this.buttonCancel.Visible = value;

View File

@ -13,13 +13,13 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
{
private TaskDialogPage Dialog;
public override string Message
protected override string _message
{
get => Dialog.Heading ?? "";
set => Dialog.Heading = value;
}
public override ProgressBarStyle ProgressStyle
protected override ProgressBarStyle _progressStyle
{
set
{
@ -40,7 +40,7 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
}
}
public override int ProgressValue
protected override int _progressValue
{
get => Dialog.ProgressBar is null ? 0 : Dialog.ProgressBar.Value;
set
@ -52,7 +52,7 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
}
}
public override bool CancelEnabled
protected override bool _cancelEnabled
{
get => Dialog.Buttons[0].Enabled;
set => Dialog.Buttons[0].Enabled = value;
@ -76,20 +76,19 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
}
};
Message = "Please wait...";
CancelEnabled = false;
_message = "Please wait...";
_cancelEnabled = false;
Dialog.Buttons[0].Click += (sender, e) => ButtonCancel_Click(sender, e);
SetupDialog();
}
public override void ShowSuccess(object sender, ChangeEventArgs<string> e)
public override void ShowSuccess(string message)
{
if (this.InvokeRequired)
{
ChangeEventHandler<string> handler = new(ShowSuccess);
this.Invoke(handler, sender, e);
this.Invoke(ShowSuccess, message);
}
else
{
@ -97,7 +96,7 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
{
Icon = TaskDialogIcon.ShieldSuccessGreenBar,
Caption = Program.ProjectName,
Heading = e.Value,
Heading = message,
Buttons = { TaskDialogButton.OK }
};
@ -108,17 +107,11 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
}
}
private void InvokeShowError(object sender, ChangeEventArgs<string> e)
{
ShowError(e.Value);
}
public override void ShowError(string message)
{
if (this.InvokeRequired)
{
ChangeEventHandler<string> handler = new(InvokeShowError);
this.Invoke(handler, this, new ChangeEventArgs<string>(message));
this.Invoke(ShowError, message);
}
else
{
@ -144,12 +137,11 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
}
}
public override void CloseDialog(object? sender, EventArgs e)
public override void CloseDialog()
{
if (this.InvokeRequired)
{
EventHandler handler = new(CloseDialog);
this.Invoke(handler, sender, e);
this.Invoke(CloseDialog);
}
else
{

View File

@ -1,16 +0,0 @@
// https://github.com/MaximumADHD/Roblox-Studio-Mod-Manager/blob/main/ProjectSrc/Events/ChangeEvent.cs
namespace Bloxstrap.Helpers.RSMM
{
public delegate void ChangeEventHandler<T>(object sender, ChangeEventArgs<T> e);
public class ChangeEventArgs<T>
{
public T Value { get; }
public ChangeEventArgs(T value)
{
Value = value;
}
}
}

View File

@ -1,64 +0,0 @@
// https://github.com/MaximumADHD/Roblox-Studio-Mod-Manager/blob/main/ProjectSrc/Bootstrapper/FileManifest.cs
using System.IO;
using System.Net.Http;
using System.Runtime.Serialization;
namespace Bloxstrap.Helpers.RSMM
{
[Serializable]
internal class FileManifest : Dictionary<string, string>
{
public string RawData { get; set; }
protected FileManifest(SerializationInfo info, StreamingContext context)
: base(info, context) { }
private FileManifest(string data, bool remapExtraContent = false)
{
using (var reader = new StringReader(data))
{
bool eof = false;
var readLine = new Func<string>(() =>
{
string line = reader.ReadLine();
if (line == null)
eof = true;
return line;
});
while (!eof)
{
string path = readLine();
string signature = readLine();
if (eof)
break;
else if (remapExtraContent && path.StartsWith("ExtraContent", Program.StringFormat))
path = path.Replace("ExtraContent", "content");
Add(path, signature);
}
}
RawData = data;
}
public static async Task<FileManifest> Get(string versionGuid, bool remapExtraContent = false)
{
string fileManifestUrl = $"{Program.BaseUrlSetup}/{versionGuid}-rbxManifest.txt";
string fileManifestData;
using (HttpClient http = new())
{
var download = http.GetStringAsync(fileManifestUrl);
fileManifestData = await download.ConfigureAwait(false);
}
return new FileManifest(fileManifestData, remapExtraContent);
}
}
}