diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs
index 373c7eec..2da5155c 100644
--- a/Bloxstrap/App.xaml.cs
+++ b/Bloxstrap/App.xaml.cs
@@ -66,6 +66,15 @@ public static void Terminate(ErrorCode exitCode = ErrorCode.ERROR_SUCCESS)
Environment.Exit(exitCodeNum);
}
+ public static void SoftTerminate(ErrorCode exitCode = ErrorCode.ERROR_SUCCESS)
+ {
+ int exitCodeNum = (int)exitCode;
+
+ Logger.WriteLine("App::SoftTerminate", $"Terminating with exit code {exitCodeNum} ({exitCode})");
+
+ Current.Dispatcher.Invoke(() => Current.Shutdown(exitCodeNum));
+ }
+
void GlobalExceptionHandler(object sender, DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = true;
diff --git a/Bloxstrap/AppData/RobloxStudioData.cs b/Bloxstrap/AppData/RobloxStudioData.cs
index fca5a631..eb04662f 100644
--- a/Bloxstrap/AppData/RobloxStudioData.cs
+++ b/Bloxstrap/AppData/RobloxStudioData.cs
@@ -21,7 +21,7 @@ public class RobloxStudioData : CommonAppData, IAppData
{ "RobloxStudio.zip", @"" },
{ "redist.zip", @"" },
{ "LibrariesQt5.zip", @"" },
-
+
{ "content-studio_svg_textures.zip", @"content\studio_svg_textures\"},
{ "content-qt_translations.zip", @"content\qt_translations\" },
{ "content-api-docs.zip", @"content\api_docs\" },
@@ -34,7 +34,8 @@ public class RobloxStudioData : CommonAppData, IAppData
{ "ApplicationConfig.zip", @"ApplicationConfig\" },
{ "Plugins.zip", @"Plugins\" },
{ "Qml.zip", @"Qml\" },
- { "StudioFonts.zip", @"StudioFonts\" }
+ { "StudioFonts.zip", @"StudioFonts\" },
+ { "RibbonConfig.zip", @"RibbonConfig\" }
};
}
}
diff --git a/Bloxstrap/Bloxstrap.csproj b/Bloxstrap/Bloxstrap.csproj
index fe9dcbdd..bc697fa4 100644
--- a/Bloxstrap/Bloxstrap.csproj
+++ b/Bloxstrap/Bloxstrap.csproj
@@ -13,7 +13,7 @@
true
false
-
+
@@ -27,6 +27,14 @@
+
+
+
+
+
+
+
+
diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs
index 8cd32f49..a28ce228 100644
--- a/Bloxstrap/Bootstrapper.cs
+++ b/Bloxstrap/Bootstrapper.cs
@@ -252,7 +252,7 @@ and not HttpStatusCode.Forbidden
clientVersion = await RobloxDeployment.GetInfo(channel, AppData.BinaryType);
}
- key.SetValue("www.roblox.com", channel);
+ key.SetValueSafe("www.roblox.com", channel);
_latestVersionGuid = clientVersion.VersionGuid;
@@ -724,7 +724,7 @@ private async Task UpgradeRoblox()
using (var uninstallKey = Registry.CurrentUser.CreateSubKey(App.UninstallKey))
{
- uninstallKey.SetValue("EstimatedSize", totalSize);
+ uninstallKey.SetValueSafe("EstimatedSize", totalSize);
}
App.Logger.WriteLine(LOG_IDENT, $"Registered as {totalSize} KB");
@@ -950,6 +950,9 @@ private async Task DownloadPackage(Package package)
const int maxTries = 5;
+ bool statIsRetrying = false;
+ bool statIsHttp = false;
+
App.Logger.WriteLine(LOG_IDENT, "Downloading...");
var buffer = new byte[4096];
@@ -1002,8 +1005,12 @@ private async Task DownloadPackage(Package package)
App.Logger.WriteLine(LOG_IDENT, $"An exception occurred after downloading {totalBytesRead} bytes. ({i}/{maxTries})");
App.Logger.WriteException(LOG_IDENT, ex);
+ statIsRetrying = true;
+
if (ex.GetType() == typeof(ChecksumFailedException))
{
+ _ = App.HttpClient.GetAsync($"http://bloxstraplabs.com/metrics/post?key=packageDownloadState&value=httpFail");
+
Frontend.ShowConnectivityDialog(
Strings.Dialog_Connectivity_UnableToDownload,
String.Format(Strings.Dialog_Connectivity_UnableToDownloadReason, "[https://github.com/pizzaboxer/bloxstrap/wiki/Bloxstrap-is-unable-to-download-Roblox](https://github.com/pizzaboxer/bloxstrap/wiki/Bloxstrap-is-unable-to-download-Roblox)"),
@@ -1029,9 +1036,16 @@ private async Task DownloadPackage(Package package)
{
App.Logger.WriteLine(LOG_IDENT, "Retrying download over HTTP...");
packageUrl = packageUrl.Replace("https://", "http://");
+ statIsHttp = true;
}
}
}
+
+ if (statIsRetrying)
+ {
+ string stat = statIsHttp ? "httpSuccess" : "retrySuccess";
+ _ = App.HttpClient.GetAsync($"http://bloxstraplabs.com/metrics/post?key=packageDownloadState&value={stat}");
+ }
}
private void ExtractPackage(Package package, List? files = null)
diff --git a/Bloxstrap/Extensions/RegistryKeyEx.cs b/Bloxstrap/Extensions/RegistryKeyEx.cs
new file mode 100644
index 00000000..dd556909
--- /dev/null
+++ b/Bloxstrap/Extensions/RegistryKeyEx.cs
@@ -0,0 +1,21 @@
+using Microsoft.Win32;
+
+namespace Bloxstrap.Extensions
+{
+ public static class RegistryKeyEx
+ {
+ public static void SetValueSafe(this RegistryKey registryKey, string? name, object value)
+ {
+ try
+ {
+ App.Logger.WriteLine("RegistryKeyEx::SetValueSafe", $"Writing '{value}' to {registryKey}\\{name}");
+ registryKey.SetValue(name, value);
+ }
+ catch (UnauthorizedAccessException)
+ {
+ Frontend.ShowMessageBox(Strings.Dialog_RegistryWriteError, System.Windows.MessageBoxImage.Error);
+ App.Terminate(ErrorCode.ERROR_INSTALL_FAILURE);
+ }
+ }
+ }
+}
diff --git a/Bloxstrap/Installer.cs b/Bloxstrap/Installer.cs
index 9e2f6f29..bda9f345 100644
--- a/Bloxstrap/Installer.cs
+++ b/Bloxstrap/Installer.cs
@@ -53,23 +53,23 @@ public void DoInstall()
// TODO: registry access checks, i'll need to look back on issues to see what the error looks like
using (var uninstallKey = Registry.CurrentUser.CreateSubKey(App.UninstallKey))
{
- uninstallKey.SetValue("DisplayIcon", $"{Paths.Application},0");
- uninstallKey.SetValue("DisplayName", App.ProjectName);
+ uninstallKey.SetValueSafe("DisplayIcon", $"{Paths.Application},0");
+ uninstallKey.SetValueSafe("DisplayName", App.ProjectName);
- uninstallKey.SetValue("DisplayVersion", App.Version);
+ uninstallKey.SetValueSafe("DisplayVersion", App.Version);
if (uninstallKey.GetValue("InstallDate") is null)
- uninstallKey.SetValue("InstallDate", DateTime.Now.ToString("yyyyMMdd"));
-
- uninstallKey.SetValue("InstallLocation", Paths.Base);
- uninstallKey.SetValue("NoRepair", 1);
- uninstallKey.SetValue("Publisher", App.ProjectOwner);
- uninstallKey.SetValue("ModifyPath", $"\"{Paths.Application}\" -settings");
- uninstallKey.SetValue("QuietUninstallString", $"\"{Paths.Application}\" -uninstall -quiet");
- uninstallKey.SetValue("UninstallString", $"\"{Paths.Application}\" -uninstall");
- uninstallKey.SetValue("HelpLink", App.ProjectHelpLink);
- uninstallKey.SetValue("URLInfoAbout", App.ProjectSupportLink);
- uninstallKey.SetValue("URLUpdateInfo", App.ProjectDownloadLink);
+ uninstallKey.SetValueSafe("InstallDate", DateTime.Now.ToString("yyyyMMdd"));
+
+ uninstallKey.SetValueSafe("InstallLocation", Paths.Base);
+ uninstallKey.SetValueSafe("NoRepair", 1);
+ uninstallKey.SetValueSafe("Publisher", App.ProjectOwner);
+ uninstallKey.SetValueSafe("ModifyPath", $"\"{Paths.Application}\" -settings");
+ uninstallKey.SetValueSafe("QuietUninstallString", $"\"{Paths.Application}\" -uninstall -quiet");
+ uninstallKey.SetValueSafe("UninstallString", $"\"{Paths.Application}\" -uninstall");
+ uninstallKey.SetValueSafe("HelpLink", App.ProjectHelpLink);
+ uninstallKey.SetValueSafe("URLInfoAbout", App.ProjectSupportLink);
+ uninstallKey.SetValueSafe("URLUpdateInfo", App.ProjectDownloadLink);
}
// only register player, for the scenario where the user installs bloxstrap, closes it,
@@ -426,12 +426,12 @@ public static void HandleUpgrade()
using (var uninstallKey = Registry.CurrentUser.CreateSubKey(App.UninstallKey))
{
- uninstallKey.SetValue("DisplayVersion", App.Version);
+ uninstallKey.SetValueSafe("DisplayVersion", App.Version);
- uninstallKey.SetValue("Publisher", App.ProjectOwner);
- uninstallKey.SetValue("HelpLink", App.ProjectHelpLink);
- uninstallKey.SetValue("URLInfoAbout", App.ProjectSupportLink);
- uninstallKey.SetValue("URLUpdateInfo", App.ProjectDownloadLink);
+ uninstallKey.SetValueSafe("Publisher", App.ProjectOwner);
+ uninstallKey.SetValueSafe("HelpLink", App.ProjectHelpLink);
+ uninstallKey.SetValueSafe("URLInfoAbout", App.ProjectSupportLink);
+ uninstallKey.SetValueSafe("URLUpdateInfo", App.ProjectDownloadLink);
}
// update migrations
@@ -459,14 +459,7 @@ public static void HandleUpgrade()
string configLocation = Path.Combine(Paths.Modifications, "ReShade.ini");
if (File.Exists(injectorLocation))
- {
- Frontend.ShowMessageBox(
- Strings.Bootstrapper_HyperionUpdateInfo,
- MessageBoxImage.Warning
- );
-
File.Delete(injectorLocation);
- }
if (File.Exists(configLocation))
File.Delete(configLocation);
diff --git a/Bloxstrap/LaunchSettings.cs b/Bloxstrap/LaunchSettings.cs
index 05ba45d9..4bd10b19 100644
--- a/Bloxstrap/LaunchSettings.cs
+++ b/Bloxstrap/LaunchSettings.cs
@@ -22,6 +22,8 @@ public class LaunchSettings
public LaunchFlag NoLaunchFlag { get; } = new("nolaunch");
+ public LaunchFlag NoGPUFlag { get; } = new("nogpu");
+
public LaunchFlag UpgradeFlag { get; } = new("upgrade");
public LaunchFlag PlayerFlag { get; } = new("player");
diff --git a/Bloxstrap/Models/APIs/Config/SupporterData.cs b/Bloxstrap/Models/APIs/Config/SupporterData.cs
index 35feb1e9..6a5e37f4 100644
--- a/Bloxstrap/Models/APIs/Config/SupporterData.cs
+++ b/Bloxstrap/Models/APIs/Config/SupporterData.cs
@@ -2,10 +2,10 @@
{
public class SupporterData
{
- [JsonPropertyName("columns")]
- public int Columns { get; set; }
+ [JsonPropertyName("monthly")]
+ public SupporterGroup Monthly { get; set; } = new();
- [JsonPropertyName("supporters")]
- public List Supporters { get; set; } = null!;
+ [JsonPropertyName("oneoff")]
+ public SupporterGroup OneOff { get; set; } = new();
}
}
diff --git a/Bloxstrap/Models/APIs/Config/SupporterGroup.cs b/Bloxstrap/Models/APIs/Config/SupporterGroup.cs
new file mode 100644
index 00000000..822c8edc
--- /dev/null
+++ b/Bloxstrap/Models/APIs/Config/SupporterGroup.cs
@@ -0,0 +1,11 @@
+namespace Bloxstrap.Models.APIs.Config
+{
+ public class SupporterGroup
+ {
+ [JsonPropertyName("columns")]
+ public int Columns { get; set; } = 0;
+
+ [JsonPropertyName("supporters")]
+ public List Supporters { get; set; } = Enumerable.Empty().ToList();
+ }
+}
diff --git a/Bloxstrap/Models/Persistable/Settings.cs b/Bloxstrap/Models/Persistable/Settings.cs
index 0371483f..3b753f0f 100644
--- a/Bloxstrap/Models/Persistable/Settings.cs
+++ b/Bloxstrap/Models/Persistable/Settings.cs
@@ -15,6 +15,7 @@ public class Settings
public string Locale { get; set; } = "nil";
public bool ForceRobloxLanguage { get; set; } = false;
public bool UseFastFlagManager { get; set; } = true;
+ public bool WPFSoftwareRender { get; set; } = false;
// integration configuration
public bool EnableActivityTracking { get; set; } = true;
diff --git a/Bloxstrap/Models/SettingTasks/Base/BaseTask.cs b/Bloxstrap/Models/SettingTasks/Base/BaseTask.cs
index 15f3ec85..70cf788e 100644
--- a/Bloxstrap/Models/SettingTasks/Base/BaseTask.cs
+++ b/Bloxstrap/Models/SettingTasks/Base/BaseTask.cs
@@ -12,7 +12,9 @@ public abstract class BaseTask
public abstract bool Changed { get; }
- public BaseTask(string prefix, string name) => Name = $"{prefix}.{name}";
+ public BaseTask(string prefix, string name) : this($"{prefix}.{name}") { }
+
+ public BaseTask(string name) => Name = name;
public override string ToString() => Name;
diff --git a/Bloxstrap/Models/SettingTasks/Base/BoolBaseTask.cs b/Bloxstrap/Models/SettingTasks/Base/BoolBaseTask.cs
index 5b5adceb..213bafe3 100644
--- a/Bloxstrap/Models/SettingTasks/Base/BoolBaseTask.cs
+++ b/Bloxstrap/Models/SettingTasks/Base/BoolBaseTask.cs
@@ -41,5 +41,7 @@ public virtual bool NewState
public override bool Changed => _newState != OriginalState;
public BoolBaseTask(string prefix, string name) : base(prefix, name) { }
+
+ public BoolBaseTask(string name) : base(name) { }
}
}
diff --git a/Bloxstrap/Models/SettingTasks/ExtractIconsTask.cs b/Bloxstrap/Models/SettingTasks/ExtractIconsTask.cs
new file mode 100644
index 00000000..8b000bc4
--- /dev/null
+++ b/Bloxstrap/Models/SettingTasks/ExtractIconsTask.cs
@@ -0,0 +1,42 @@
+using System.Reflection;
+using System.Windows.Markup;
+
+namespace Bloxstrap.Models.SettingTasks
+{
+ public class ExtractIconsTask : BoolBaseTask
+ {
+ public ExtractIconsTask() : base("ExtractIcons")
+ {
+ OriginalState = Directory.Exists(Paths.Icons);
+ }
+
+ public override void Execute()
+ {
+ if (NewState)
+ {
+ Directory.CreateDirectory(Paths.Icons);
+
+ var assembly = Assembly.GetExecutingAssembly();
+ var resourceNames = assembly.GetManifestResourceNames().Where(x => x.EndsWith(".ico"));
+
+ foreach (string name in resourceNames)
+ {
+ string path = Path.Combine(Paths.Icons, name.Replace("Bloxstrap.Resources.", ""));
+ var stream = assembly.GetManifestResourceStream(name)!;
+
+ using var memoryStream = new MemoryStream();
+ stream.CopyTo(memoryStream);
+
+ Filesystem.AssertReadOnly(path);
+ File.WriteAllBytes(path, memoryStream.ToArray());
+ }
+ }
+ else if (Directory.Exists(Paths.Icons))
+ {
+ Directory.Delete(Paths.Icons, true);
+ }
+
+ OriginalState = NewState;
+ }
+ }
+}
diff --git a/Bloxstrap/Models/SettingTasks/ModPresetTask.cs b/Bloxstrap/Models/SettingTasks/ModPresetTask.cs
index 8aa15925..73fcc222 100644
--- a/Bloxstrap/Models/SettingTasks/ModPresetTask.cs
+++ b/Bloxstrap/Models/SettingTasks/ModPresetTask.cs
@@ -42,7 +42,7 @@ public override void Execute()
using var resourceStream = data.ResourceStream;
using var memoryStream = new MemoryStream();
- data.ResourceStream.CopyTo(memoryStream);
+ resourceStream.CopyTo(memoryStream);
Filesystem.AssertReadOnly(data.FullFilePath);
File.WriteAllBytes(data.FullFilePath, memoryStream.ToArray());
diff --git a/Bloxstrap/Models/SettingTasks/ShortcutTask.cs b/Bloxstrap/Models/SettingTasks/ShortcutTask.cs
index ca14a458..e85fcf1e 100644
--- a/Bloxstrap/Models/SettingTasks/ShortcutTask.cs
+++ b/Bloxstrap/Models/SettingTasks/ShortcutTask.cs
@@ -1,11 +1,9 @@
-using Bloxstrap.Models.SettingTasks.Base;
-
-namespace Bloxstrap.Models.SettingTasks
+namespace Bloxstrap.Models.SettingTasks
{
public class ShortcutTask : BoolBaseTask
{
private string _shortcutPath;
-
+
private string _exeFlags;
public ShortcutTask(string name, string lnkFolder, string lnkName, string exeFlags = "") : base("Shortcut", name)
@@ -26,4 +24,4 @@ public override void Execute()
OriginalState = NewState;
}
}
-}
+}
\ No newline at end of file
diff --git a/Bloxstrap/Paths.cs b/Bloxstrap/Paths.cs
index 36f81361..130d44be 100644
--- a/Bloxstrap/Paths.cs
+++ b/Bloxstrap/Paths.cs
@@ -22,6 +22,7 @@ static class Paths
public static string Integrations { get; private set; } = "";
public static string Modifications { get; private set; } = "";
public static string Roblox { get; private set; } = "";
+ public static string Icons { get; private set; } = "";
public static string Application { get; private set; } = "";
@@ -37,6 +38,7 @@ public static void Initialize(string baseDirectory)
Integrations = Path.Combine(Base, "Integrations");
Modifications = Path.Combine(Base, "Modifications");
Roblox = Path.Combine(Base, "Roblox");
+ Icons = Path.Combine(Base, "Icons");
Application = Path.Combine(Base, $"{App.ProjectName}.exe");
}
diff --git a/Bloxstrap/Resources/Strings.Designer.cs b/Bloxstrap/Resources/Strings.Designer.cs
index 967c55ca..f8464a80 100644
--- a/Bloxstrap/Resources/Strings.Designer.cs
+++ b/Bloxstrap/Resources/Strings.Designer.cs
@@ -78,6 +78,24 @@ public static string About_Supporters_Description {
}
}
+ ///
+ /// Looks up a localized string similar to Monthly.
+ ///
+ public static string About_Supporters_Monthly {
+ get {
+ return ResourceManager.GetString("About.Supporters.Monthly", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to One-off.
+ ///
+ public static string About_Supporters_OneOff {
+ get {
+ return ResourceManager.GetString("About.Supporters.OneOff", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Supporters.
///
@@ -159,17 +177,6 @@ public static string Bootstrapper_FirstRunUninstall {
}
}
- ///
- /// Looks up a localized string similar to Roblox has now finished rolling out the new game client update, featuring 64-bit support and the Hyperion anticheat. ReShade does not work with this update, and so it has now been disabled and removed from Bloxstrap.
- ///
- ///Your ReShade configuration files will still be saved, and you can locate them by opening the folder where Bloxstrap is installed to, and navigating to the Integrations folder. You can choose to delete these if you want..
- ///
- public static string Bootstrapper_HyperionUpdateInfo {
- get {
- return ResourceManager.GetString("Bootstrapper.HyperionUpdateInfo", resourceCulture);
- }
- }
-
///
/// Looks up a localized string similar to Failed to save {0}: {1}.
///
@@ -1032,6 +1039,15 @@ public static string Dialog_PlayerError_HelpInformation {
}
}
+ ///
+ /// Looks up a localized string similar to Bloxstrap is unable to write to the Windows Registry. An antivirus is likely interfering and causing issues. Please check to make sure there isn't anything that would restrict Bloxstrap's operation..
+ ///
+ public static string Dialog_RegistryWriteError {
+ get {
+ return ResourceManager.GetString("Dialog.RegistryWriteError", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Early 2015.
///
@@ -3117,6 +3133,24 @@ public static string Menu_Shortcuts_Description {
}
}
+ ///
+ /// Looks up a localized string similar to To use for your shortcuts, right-click it, open properties, change icon, browse, and pick from the Icons folder..
+ ///
+ public static string Menu_Shortcuts_ExtractIcons_Description {
+ get {
+ return ResourceManager.GetString("Menu.Shortcuts.ExtractIcons.Description", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Extract Roblox icons to folder.
+ ///
+ public static string Menu_Shortcuts_ExtractIcons_Title {
+ get {
+ return ResourceManager.GetString("Menu.Shortcuts.ExtractIcons.Title", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Create shortcuts for quick access to specific functions. These will all be placed on the Desktop..
///
diff --git a/Bloxstrap/Resources/Strings.resx b/Bloxstrap/Resources/Strings.resx
index a8e3a95d..dc3cd26f 100644
--- a/Bloxstrap/Resources/Strings.resx
+++ b/Bloxstrap/Resources/Strings.resx
@@ -138,11 +138,6 @@
You must first install Bloxstrap before uninstalling.
-
- Roblox has now finished rolling out the new game client update, featuring 64-bit support and the Hyperion anticheat. ReShade does not work with this update, and so it has now been disabled and removed from Bloxstrap.
-
-Your ReShade configuration files will still be saved, and you can locate them by opening the folder where Bloxstrap is installed to, and navigating to the Integrations folder. You can choose to delete these if you want.
-
Bloxstrap does not have enough disk space to download and install Roblox. Please free up some disk space and try again.
@@ -1209,4 +1204,19 @@ Please manually delete Bloxstrap.exe from the install location or try restarting
{0}
-
+
+ Extract Roblox icons to folder
+
+
+ To use for your shortcuts, right-click it, open properties, change icon, browse, and pick from the Icons folder.
+
+
+ Bloxstrap is unable to write to the Windows Registry. An antivirus is likely interfering and causing issues. Please check to make sure there isn't anything that would restrict Bloxstrap's operation.
+
+
+ Monthly
+
+
+ One-off
+
+
\ No newline at end of file
diff --git a/Bloxstrap/UI/Elements/About/MainWindow.xaml b/Bloxstrap/UI/Elements/About/MainWindow.xaml
index a334f3a5..5fd1d53d 100644
--- a/Bloxstrap/UI/Elements/About/MainWindow.xaml
+++ b/Bloxstrap/UI/Elements/About/MainWindow.xaml
@@ -37,6 +37,7 @@
+
diff --git a/Bloxstrap/UI/Elements/About/Pages/AboutPage.xaml b/Bloxstrap/UI/Elements/About/Pages/AboutPage.xaml
index 0fdccb29..d35d6bf8 100644
--- a/Bloxstrap/UI/Elements/About/Pages/AboutPage.xaml
+++ b/Bloxstrap/UI/Elements/About/Pages/AboutPage.xaml
@@ -3,7 +3,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:enums="clr-namespace:Bloxstrap.Enums"
xmlns:models="clr-namespace:Bloxstrap.UI.ViewModels"
xmlns:dmodels="clr-namespace:Bloxstrap.UI.ViewModels.About"
xmlns:controls="clr-namespace:Bloxstrap.UI.Elements.Controls"
@@ -81,85 +80,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Bloxstrap/UI/Elements/About/Pages/SupportersPage.xaml b/Bloxstrap/UI/Elements/About/Pages/SupportersPage.xaml
new file mode 100644
index 00000000..925a5204
--- /dev/null
+++ b/Bloxstrap/UI/Elements/About/Pages/SupportersPage.xaml
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Bloxstrap/UI/Elements/About/Pages/SupportersPage.xaml.cs b/Bloxstrap/UI/Elements/About/Pages/SupportersPage.xaml.cs
new file mode 100644
index 00000000..c8245584
--- /dev/null
+++ b/Bloxstrap/UI/Elements/About/Pages/SupportersPage.xaml.cs
@@ -0,0 +1,16 @@
+using Bloxstrap.UI.ViewModels.About;
+
+namespace Bloxstrap.UI.Elements.About.Pages
+{
+ ///
+ /// Interaction logic for SupportersPage.xaml
+ ///
+ public partial class SupportersPage
+ {
+ public SupportersPage()
+ {
+ DataContext = new SupportersViewModel();
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Bloxstrap/UI/Elements/Base/WpfUiWindow.cs b/Bloxstrap/UI/Elements/Base/WpfUiWindow.cs
index 6291d03a..ad2135f3 100644
--- a/Bloxstrap/UI/Elements/Base/WpfUiWindow.cs
+++ b/Bloxstrap/UI/Elements/Base/WpfUiWindow.cs
@@ -1,9 +1,5 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
+using System.Windows;
+using System.Windows.Interop;
using Wpf.Ui.Appearance;
using Wpf.Ui.Controls;
using Wpf.Ui.Mvvm.Contracts;
@@ -25,5 +21,16 @@ public void ApplyTheme()
_themeService.SetTheme(App.Settings.Prop.Theme.GetFinal() == Enums.Theme.Dark ? ThemeType.Dark : ThemeType.Light);
_themeService.SetSystemAccent();
}
+
+ protected override void OnSourceInitialized(EventArgs e)
+ {
+ if (App.Settings.Prop.WPFSoftwareRender || App.LaunchSettings.NoGPUFlag.Active)
+ {
+ if (PresentationSource.FromVisual(this) is HwndSource hwndSource)
+ hwndSource.CompositionTarget.RenderMode = RenderMode.SoftwareOnly;
+ }
+
+ base.OnSourceInitialized(e);
+ }
}
}
diff --git a/Bloxstrap/UI/Elements/Settings/MainWindow.xaml.cs b/Bloxstrap/UI/Elements/Settings/MainWindow.xaml.cs
index fda449fe..37e92376 100644
--- a/Bloxstrap/UI/Elements/Settings/MainWindow.xaml.cs
+++ b/Bloxstrap/UI/Elements/Settings/MainWindow.xaml.cs
@@ -102,7 +102,7 @@ private void WpfUiWindow_Closing(object sender, CancelEventArgs e)
App.State.Save();
if (!e.Cancel)
- App.Terminate();
+ App.SoftTerminate();
}
}
}
diff --git a/Bloxstrap/UI/Elements/Settings/Pages/ShortcutsPage.xaml b/Bloxstrap/UI/Elements/Settings/Pages/ShortcutsPage.xaml
index 6d102501..9d3f3592 100644
--- a/Bloxstrap/UI/Elements/Settings/Pages/ShortcutsPage.xaml
+++ b/Bloxstrap/UI/Elements/Settings/Pages/ShortcutsPage.xaml
@@ -17,6 +17,13 @@
+
+
+
+
diff --git a/Bloxstrap/UI/ViewModels/About/AboutViewModel.cs b/Bloxstrap/UI/ViewModels/About/AboutViewModel.cs
index 6eda400e..8e7177c4 100644
--- a/Bloxstrap/UI/ViewModels/About/AboutViewModel.cs
+++ b/Bloxstrap/UI/ViewModels/About/AboutViewModel.cs
@@ -4,8 +4,6 @@ namespace Bloxstrap.UI.ViewModels.About
{
public class AboutViewModel : NotifyPropertyChangedViewModel
{
- private SupporterData? _supporterData;
-
public string Version => string.Format(Strings.Menu_About_Version, App.Version);
public BuildMetadataAttribute BuildMetadata => App.BuildMetadata;
@@ -15,49 +13,5 @@ public class AboutViewModel : NotifyPropertyChangedViewModel
public Visibility BuildInformationVisibility => App.IsProductionBuild ? Visibility.Collapsed : Visibility.Visible;
public Visibility BuildCommitVisibility => App.IsActionBuild ? Visibility.Visible : Visibility.Collapsed;
-
- public List Supporters => _supporterData?.Supporters ?? Enumerable.Empty().ToList();
-
- public int SupporterColumns => _supporterData?.Columns ?? 0;
-
- public GenericTriState SupportersLoadedState { get; set; } = GenericTriState.Unknown;
-
- public string SupportersLoadError { get; set; } = "";
-
- public AboutViewModel()
- {
- // this will cause momentary freezes only when ran under the debugger
- LoadSupporterData();
- }
-
- public async void LoadSupporterData()
- {
- const string LOG_IDENT = "AboutViewModel::LoadSupporterData";
-
- try
- {
- _supporterData = await Http.GetJson("https://raw.githubusercontent.com/bloxstraplabs/config/main/supporters.json");
- }
- catch (Exception ex)
- {
- App.Logger.WriteLine(LOG_IDENT, "Could not load supporter data");
- App.Logger.WriteException(LOG_IDENT, ex);
-
- SupportersLoadedState = GenericTriState.Failed;
- SupportersLoadError = ex.Message;
-
- OnPropertyChanged(nameof(SupportersLoadError));
- }
-
- if (_supporterData is not null)
- {
- SupportersLoadedState = GenericTriState.Successful;
-
- OnPropertyChanged(nameof(Supporters));
- OnPropertyChanged(nameof(SupporterColumns));
- }
-
- OnPropertyChanged(nameof(SupportersLoadedState));
- }
}
}
diff --git a/Bloxstrap/UI/ViewModels/About/SupportersViewModel.cs b/Bloxstrap/UI/ViewModels/About/SupportersViewModel.cs
new file mode 100644
index 00000000..cc5afbc6
--- /dev/null
+++ b/Bloxstrap/UI/ViewModels/About/SupportersViewModel.cs
@@ -0,0 +1,46 @@
+namespace Bloxstrap.UI.ViewModels.About
+{
+ public class SupportersViewModel : NotifyPropertyChangedViewModel
+ {
+ public SupporterData? SupporterData { get; private set; }
+
+ public GenericTriState LoadedState { get; set; } = GenericTriState.Unknown;
+
+ public string LoadError { get; set; } = "";
+
+ public SupportersViewModel()
+ {
+ // this will cause momentary freezes only when ran under the debugger
+ LoadSupporterData();
+ }
+
+ public async void LoadSupporterData()
+ {
+ const string LOG_IDENT = "AboutViewModel::LoadSupporterData";
+
+ try
+ {
+ SupporterData = await Http.GetJson("https://raw.githubusercontent.com/bloxstraplabs/config/main/supporters.json");
+ }
+ catch (Exception ex)
+ {
+ App.Logger.WriteLine(LOG_IDENT, "Could not load supporter data");
+ App.Logger.WriteException(LOG_IDENT, ex);
+
+ LoadedState = GenericTriState.Failed;
+ LoadError = ex.Message;
+
+ OnPropertyChanged(nameof(LoadError));
+ }
+
+ if (SupporterData is not null)
+ {
+ LoadedState = GenericTriState.Successful;
+
+ OnPropertyChanged(nameof(SupporterData));
+ }
+
+ OnPropertyChanged(nameof(LoadedState));
+ }
+ }
+}
diff --git a/Bloxstrap/UI/ViewModels/Settings/ShortcutsViewModel.cs b/Bloxstrap/UI/ViewModels/Settings/ShortcutsViewModel.cs
index b79d8c8a..cb4cc548 100644
--- a/Bloxstrap/UI/ViewModels/Settings/ShortcutsViewModel.cs
+++ b/Bloxstrap/UI/ViewModels/Settings/ShortcutsViewModel.cs
@@ -12,5 +12,7 @@ public class ShortcutsViewModel : NotifyPropertyChangedViewModel
public ShortcutTask PlayerIconTask { get; } = new("RobloxPlayer", Paths.Desktop, $"{Strings.LaunchMenu_LaunchRoblox}.lnk", "-player");
public ShortcutTask SettingsIconTask { get; } = new("Settings", Paths.Desktop, $"{Strings.Menu_Title}.lnk", "-settings");
+
+ public ExtractIconsTask ExtractIconsTask { get; } = new();
}
}
diff --git a/Bloxstrap/Utility/WindowsRegistry.cs b/Bloxstrap/Utility/WindowsRegistry.cs
index be2981c3..23ca7129 100644
--- a/Bloxstrap/Utility/WindowsRegistry.cs
+++ b/Bloxstrap/Utility/WindowsRegistry.cs
@@ -16,14 +16,14 @@ public static void RegisterProtocol(string key, string name, string handler, str
if (uriKey.GetValue("") is null)
{
- uriKey.SetValue("", $"URL: {name} Protocol");
- uriKey.SetValue("URL Protocol", "");
+ uriKey.SetValueSafe("", $"URL: {name} Protocol");
+ uriKey.SetValueSafe("URL Protocol", "");
}
if (uriCommandKey.GetValue("") as string != handlerArgs)
{
- uriIconKey.SetValue("", handler);
- uriCommandKey.SetValue("", handlerArgs);
+ uriIconKey.SetValueSafe("", handler);
+ uriCommandKey.SetValueSafe("", handlerArgs);
}
}
@@ -85,16 +85,16 @@ public static void RegisterStudioFileClass(string handler, string handlerParam)
using RegistryKey uriCommandKey = uriOpenKey.CreateSubKey(@"command");
if (uriKey.GetValue("") as string != keyValue)
- uriKey.SetValue("", keyValue);
+ uriKey.SetValueSafe("", keyValue);
if (uriCommandKey.GetValue("") as string != handlerArgs)
- uriCommandKey.SetValue("", handlerArgs);
+ uriCommandKey.SetValueSafe("", handlerArgs);
if (uriOpenKey.GetValue("") as string != "Open")
- uriOpenKey.SetValue("", "Open");
+ uriOpenKey.SetValueSafe("", "Open");
if (uriIconKey.GetValue("") as string != iconValue)
- uriIconKey.SetValue("", iconValue);
+ uriIconKey.SetValueSafe("", iconValue);
}
public static void RegisterStudioFileType(string key)
@@ -103,7 +103,7 @@ public static void RegisterStudioFileType(string key)
uriKey.CreateSubKey(RobloxPlaceKey + @"\ShellNew");
if (uriKey.GetValue("") as string != RobloxPlaceKey)
- uriKey.SetValue("", RobloxPlaceKey);
+ uriKey.SetValueSafe("", RobloxPlaceKey);
}
public static void Unregister(string key)