bloxstrap/Bloxstrap/Dialogs/Menu/Preferences.xaml.cs
pizzaboxer 83f37ee6c3 Rework Preferences menu and file modding
Adds help windows to the Preferences menu, reworked directory structure and allowed files in the root mod directory to be applied to the version folder.
2023-01-17 22:13:51 +00:00

417 lines
14 KiB
C#

using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media.Imaging;
using Microsoft.Win32;
using Bloxstrap.Enums;
using Bloxstrap.Helpers;
using Bloxstrap.Models;
namespace Bloxstrap.Dialogs.Menu
{
/// <summary>
/// Interaction logic for PreferencesWPF.xaml
/// </summary>
public partial class Preferences : Window
{
public readonly PreferencesViewModel ViewModel;
public Preferences()
{
InitializeComponent();
SetTheme();
ViewModel = new(this);
this.DataContext = ViewModel;
Program.SettingsManager.ShouldSave = false;
this.Icon = Imaging.CreateBitmapSourceFromHIcon(
Properties.Resources.IconBloxstrap_ico.Handle,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions()
);
this.Title = Program.ProjectName;
// just in case i guess?
if (!Environment.Is64BitOperatingSystem)
this.CheckBoxRFUEnabled.IsEnabled = false;
}
public void SetTheme()
{
string theme = "Light";
if (Program.Settings.Theme.GetFinal() == Theme.Dark)
theme = "ColourfulDark";
this.Resources.MergedDictionaries[0] = new ResourceDictionary() { Source = new Uri($"Dialogs/Menu/Themes/{theme}Theme.xaml", UriKind.Relative) };
}
private void ButtonOpenReShadeFolder_Click(object sender, EventArgs e)
{
Process.Start("explorer.exe", Directories.ReShade);
}
private void ButtonOpenReShadeHelp_Click(object sender, EventArgs e)
{
new ReShadeHelp().Show();
}
private void ButtonOpenModFolder_Click(object sender, EventArgs e)
{
Process.Start("explorer.exe", Directories.Modifications);
}
private void ButtonOpenModHelp_Click(object sender, EventArgs e)
{
new ModHelp().Show();
}
private void ButtonLocationBrowse_Click(object sender, EventArgs e)
{
using (var dialog = new FolderBrowserDialog())
{
DialogResult result = dialog.ShowDialog();
if (result == System.Windows.Forms.DialogResult.OK)
ViewModel.InstallLocation = dialog.SelectedPath;
}
}
private void ButtonPreview_Click(object sender, EventArgs e)
{
//this.Visible = false;
Program.Settings.BootstrapperStyle.Show();
//this.Visible = true;
}
private void ButtonCancel_Click(object sender, EventArgs e)
{
this.Close();
}
private void ButtonConfirm_Click(object sender, EventArgs e)
{
string installLocation = this.TextBoxInstallLocation.Text;
if (String.IsNullOrEmpty(installLocation))
{
Program.ShowMessageBox("You must set an install location", MessageBoxIcon.Error);
return;
}
try
{
// check if we can write to the directory (a bit hacky but eh)
string testPath = installLocation;
string testFile = Path.Combine(installLocation, "BloxstrapWriteTest.txt");
bool testPathExists = Directory.Exists(testPath);
if (!testPathExists)
Directory.CreateDirectory(testPath);
File.WriteAllText(testFile, "hi");
File.Delete(testFile);
if (!testPathExists)
Directory.Delete(testPath);
}
catch (UnauthorizedAccessException)
{
Program.ShowMessageBox($"{Program.ProjectName} does not have write access to the install location you selected. Please choose another install location.", MessageBoxIcon.Error);
return;
}
catch (Exception ex)
{
Program.ShowMessageBox(ex.Message, MessageBoxIcon.Error);
return;
}
if (Program.IsFirstRun)
{
// this will be set in the registry after first install
Program.BaseDirectory = installLocation;
}
else
{
Program.SettingsManager.ShouldSave = true;
if (Program.BaseDirectory is not null && Program.BaseDirectory != installLocation)
{
Program.ShowMessageBox($"{Program.ProjectName} will install to the new location you've set the next time it runs.", MessageBoxIcon.Information);
Program.Settings.VersionGuid = "";
using (RegistryKey registryKey = Registry.CurrentUser.CreateSubKey($@"Software\{Program.ProjectName}"))
{
registryKey.SetValue("InstallLocation", installLocation);
registryKey.SetValue("OldInstallLocation", Program.BaseDirectory);
}
// preserve settings
// we don't need to copy the bootstrapper over since the install process will do that automatically
Program.SettingsManager.Save();
File.Copy(Path.Combine(Program.BaseDirectory, "Settings.json"), Path.Combine(installLocation, "Settings.json"));
}
}
this.Close();
}
private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
{
Utilities.OpenWebsite(e.Uri.AbsoluteUri);
e.Handled = true;
}
}
public class PreferencesViewModel : INotifyPropertyChanged
{
private readonly Preferences _window;
public event PropertyChangedEventHandler? PropertyChanged;
public string BloxstrapVersion { get; } = $"Version {Program.Version}";
#region Integrations
public bool DRPEnabled
{
get => Program.Settings.UseDiscordRichPresence;
set
{
// if user wants discord rpc, auto-enable buttons by default
_window.CheckBoxDRPButtons.IsChecked = value;
Program.Settings.UseDiscordRichPresence = value;
}
}
public bool DRPButtons
{
get => !Program.Settings.HideRPCButtons;
set => Program.Settings.HideRPCButtons = !value;
}
public bool RFUEnabled
{
get => Program.Settings.RFUEnabled;
set
{
// if user wants to use rbxfpsunlocker, auto-enable autoclosing by default
_window.CheckBoxRFUAutoclose.IsChecked = value;
Program.Settings.RFUEnabled = value;
}
}
public bool RFUAutoclose
{
get => Program.Settings.RFUAutoclose;
set => Program.Settings.RFUAutoclose = value;
}
public bool UseReShade
{
get => Program.Settings.UseReShade;
set
{
// if user wants to use reshade, auto-enable use of extravi's presets by default
_window.CheckBoxUseReShadeExtraviPresets.IsChecked = value;
Program.Settings.UseReShade = value;
}
}
public bool UseReShadeExtraviPresets
{
get => Program.Settings.UseReShadeExtraviPresets;
set => Program.Settings.UseReShadeExtraviPresets = value;
}
public bool ReShadeFolderButtonEnabled { get; } = !Program.IsFirstRun;
public string ReShadeFolderButtonTooltip { get; } = Program.IsFirstRun ? "Bloxstrap must first be installed before managing ReShade" : "This is the folder that contains all your ReShade resources for presets, shaders and textures.";
#endregion
#region Modifications
public bool ModOldDeathSound
{
get => Program.Settings.UseOldDeathSound;
set => Program.Settings.UseOldDeathSound = value;
}
public bool ModOldMouseCursor
{
get => Program.Settings.UseOldMouseCursor;
set => Program.Settings.UseOldMouseCursor = value;
}
public bool ModDisableAppPatch
{
get => Program.Settings.UseDisableAppPatch;
set => Program.Settings.UseDisableAppPatch = value;
}
public bool ModFolderButtonEnabled { get; } = !Program.IsFirstRun;
public string ModFolderButtonTooltip { get; } = Program.IsFirstRun ? "Bloxstrap must first be installed before managing mods" : "This is the folder that contains all your file modifications, including presets and any ReShade files needed.";
#endregion
#region Installation
private string installLocation = Program.IsFirstRun ? Path.Combine(Program.LocalAppData, Program.ProjectName) : Program.BaseDirectory;
public string InstallLocation
{
get => installLocation;
set
{
installLocation = value;
OnPropertyChanged();
}
}
private bool showAllChannels = !DeployManager.ChannelsAbstracted.Contains(Program.Settings.Channel);
public bool ShowAllChannels
{
get => showAllChannels;
set
{
if (value)
{
Channels = DeployManager.ChannelsAll;
}
else
{
Channels = DeployManager.ChannelsAbstracted;
Channel = DeployManager.DefaultChannel;
OnPropertyChanged("Channel");
}
showAllChannels = value;
}
}
private IEnumerable<string> channels = DeployManager.ChannelsAbstracted.Contains(Program.Settings.Channel) ? DeployManager.ChannelsAbstracted : DeployManager.ChannelsAll;
public IEnumerable<string> Channels
{
get => channels;
set
{
channels = value;
OnPropertyChanged();
}
}
public string Channel
{
get => Program.Settings.Channel;
set
{
Task.Run(() => GetChannelInfo(value));
Program.Settings.Channel = value;
}
}
private string channelInfo = "Getting latest version info, please wait...\n";
public string ChannelInfo
{
get => channelInfo;
set
{
channelInfo = value;
OnPropertyChanged();
}
}
public bool PromptChannelChange
{
get => Program.Settings.PromptChannelChange;
set => Program.Settings.PromptChannelChange = value;
}
#endregion
#region Bloxstrap
public IReadOnlyDictionary<string, Theme> Themes { get; set; } = new Dictionary<string, Theme>()
{
{ "System Default", Enums.Theme.Default },
{ "Light", Enums.Theme.Light },
{ "Dark", Enums.Theme.Dark },
};
public string Theme
{
get => Themes.FirstOrDefault(x => x.Value == Program.Settings.Theme).Key;
set
{
Program.Settings.Theme = Themes[value];
_window.SetTheme();
}
}
public IReadOnlyDictionary<string, BootstrapperStyle> Dialogs { get; set; } = new Dictionary<string, BootstrapperStyle>()
{
{ "Vista (2009 - 2011)", BootstrapperStyle.VistaDialog },
{ "Legacy (2009 - 2011)", BootstrapperStyle.LegacyDialog2009 },
{ "Legacy (2011 - 2014)", BootstrapperStyle.LegacyDialog2011 },
{ "Progress (~2014)", BootstrapperStyle.ProgressDialog },
};
public string Dialog
{
get => Dialogs.FirstOrDefault(x => x.Value == Program.Settings.BootstrapperStyle).Key;
set => Program.Settings.BootstrapperStyle = Dialogs[value];
}
public IReadOnlyDictionary<string, BootstrapperIcon> Icons { get; set; } = new Dictionary<string, BootstrapperIcon>()
{
{ "Bloxstrap", BootstrapperIcon.IconBloxstrap },
{ "2009", BootstrapperIcon.Icon2009 },
{ "2011", BootstrapperIcon.Icon2011 },
{ "2015", BootstrapperIcon.IconEarly2015 },
{ "2016", BootstrapperIcon.IconLate2015 },
{ "2017", BootstrapperIcon.Icon2017 },
{ "2019", BootstrapperIcon.Icon2019 },
{ "2022", BootstrapperIcon.Icon2022 }
};
public string Icon
{
get => Icons.FirstOrDefault(x => x.Value == Program.Settings.BootstrapperIcon).Key;
set => Program.Settings.BootstrapperIcon = Icons[value];
}
public bool CheckForUpdates
{
get => Program.Settings.CheckForUpdates;
set => Program.Settings.CheckForUpdates = value;
}
#endregion
public string ConfirmButtonText { get; } = Program.IsFirstRun ? "Install" : "Save";
public PreferencesViewModel(Preferences window)
{
_window = window;
Task.Run(() => GetChannelInfo(Program.Settings.Channel));
}
protected void OnPropertyChanged([CallerMemberName] string? name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
private async Task GetChannelInfo(string channel)
{
ChannelInfo = "Getting latest version info, please wait...\n";
ClientVersion info = await DeployManager.GetLastDeploy(channel, true);
string? strTimestamp = info.Timestamp?.ToString("MM/dd/yyyy h:mm:ss tt", Program.CultureFormat);
ChannelInfo = $"Version: v{info.Version} ({info.VersionGuid})\nDeployed: {strTimestamp}";
}
}
}