From 1828d3036ff0d0fcadafa7304d4914e1e90190f2 Mon Sep 17 00:00:00 2001 From: bluepilledgreat <97983689+bluepilledgreat@users.noreply.github.com> Date: Tue, 31 Dec 2024 01:44:10 +0000 Subject: [PATCH 01/18] bump version --- Bloxstrap/Bloxstrap.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Bloxstrap/Bloxstrap.csproj b/Bloxstrap/Bloxstrap.csproj index 29525fb..9c9b70c 100644 --- a/Bloxstrap/Bloxstrap.csproj +++ b/Bloxstrap/Bloxstrap.csproj @@ -7,8 +7,8 @@ true True Bloxstrap.ico - 2.8.5 - 2.8.5 + 2.8.6 + 2.8.6 app.manifest true false From ef69d29388566af3c4cd0f99342553c36bf3f871 Mon Sep 17 00:00:00 2001 From: Ryan Date: Tue, 31 Dec 2024 12:44:31 +0800 Subject: [PATCH 02/18] ci(winget): `vedantmgoyal2009/winget-releaser@v2` -> `vedantmgoyal9/winget-releaser@main` --- .github/workflows/winget.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/winget.yml b/.github/workflows/winget.yml index 7e9e09d..e76a433 100644 --- a/.github/workflows/winget.yml +++ b/.github/workflows/winget.yml @@ -8,7 +8,7 @@ jobs: publish: runs-on: ubuntu-latest steps: - - uses: vedantmgoyal2009/winget-releaser@v2 + - uses: vedantmgoyal9/winget-releaser@main with: identifier: pizzaboxer.Bloxstrap token: ${{ secrets.WINGET_TOKEN }} From 5d1aa50753002be94748e2394898042bc2bf0bcd Mon Sep 17 00:00:00 2001 From: bluepilledgreat <97983689+bluepilledgreat@users.noreply.github.com> Date: Tue, 31 Dec 2024 09:23:31 +0000 Subject: [PATCH 03/18] prevent value from being parsed as an argument --- Bloxstrap/LaunchSettings.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Bloxstrap/LaunchSettings.cs b/Bloxstrap/LaunchSettings.cs index f2ae908..f8492f7 100644 --- a/Bloxstrap/LaunchSettings.cs +++ b/Bloxstrap/LaunchSettings.cs @@ -113,6 +113,7 @@ namespace Bloxstrap if (i < Args.Length - 1 && Args[i+1] is string nextArg && !nextArg.StartsWith('-')) { flag.Data = nextArg; + i++; App.Logger.WriteLine(LOG_IDENT, $"Identifier '{identifier}' is active with data"); } else From 478546433290ac9a0c125637edd016918c8c3db3 Mon Sep 17 00:00:00 2001 From: Matt <97983689+bluepilledgreat@users.noreply.github.com> Date: Thu, 23 Jan 2025 22:55:37 +0000 Subject: [PATCH 04/18] fix client-version fallback not handling channel errors (#4378) --- Bloxstrap/RobloxInterfaces/Deployment.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Bloxstrap/RobloxInterfaces/Deployment.cs b/Bloxstrap/RobloxInterfaces/Deployment.cs index da88c14..5be0d21 100644 --- a/Bloxstrap/RobloxInterfaces/Deployment.cs +++ b/Bloxstrap/RobloxInterfaces/Deployment.cs @@ -176,7 +176,15 @@ App.Logger.WriteLine(LOG_IDENT, "Failed to contact clientsettingscdn! Falling back to clientsettings..."); App.Logger.WriteException(LOG_IDENT, ex); - clientVersion = await Http.GetJson("https://clientsettings.roblox.com" + path); + try + { + clientVersion = await Http.GetJson("https://clientsettings.roblox.com" + path); + } + catch (HttpRequestException httpEx) + when (!isDefaultChannel && BadChannelCodes.Contains(httpEx.StatusCode)) + { + throw new InvalidChannelException(httpEx.StatusCode); + } } // check if channel is behind LIVE From 7977dba498c1755efdd0243d9b0006c6b2db9fda Mon Sep 17 00:00:00 2001 From: Matt <97983689+bluepilledgreat@users.noreply.github.com> Date: Sat, 1 Mar 2025 13:59:42 +0000 Subject: [PATCH 05/18] Add Windows 7 & 8.1 deprecation message (#4365) * add windows 7 & 8.1 deprecation message * remove deprecation bypass setting --- Bloxstrap/App.xaml.cs | 19 +++++++++++++++++++ Bloxstrap/Bootstrapper.cs | 2 ++ Bloxstrap/Resources/Strings.Designer.cs | 9 +++++++++ Bloxstrap/Resources/Strings.resx | 3 +++ 4 files changed, 33 insertions(+) diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index 5083121..691d868 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -181,6 +181,22 @@ namespace Bloxstrap } } + public static void AssertWindowsOSVersion() + { + const string LOG_IDENT = "App::AssertWindowsOSVersion"; + + int major = Environment.OSVersion.Version.Major; + if (major < 10) // Windows 10 and newer only + { + Logger.WriteLine(LOG_IDENT, $"Detected unsupported Windows version ({Environment.OSVersion.Version})."); + + if (!LaunchSettings.QuietFlag.Active) + Frontend.ShowMessageBox(Strings.App_OSDeprecation_Win7_81, MessageBoxImage.Error); + + Terminate(ErrorCode.ERROR_INVALID_FUNCTION); + } + } + protected override void OnStartup(StartupEventArgs e) { const string LOG_IDENT = "App::OnStartup"; @@ -213,6 +229,8 @@ namespace Bloxstrap #endif } + Logger.WriteLine(LOG_IDENT, $"OSVersion: {Environment.OSVersion}"); + Logger.WriteLine(LOG_IDENT, $"Loaded from {Paths.Process}"); Logger.WriteLine(LOG_IDENT, $"Temp path is {Paths.Temp}"); Logger.WriteLine(LOG_IDENT, $"WindowsStartMenu path is {Paths.WindowsStartMenu}"); @@ -292,6 +310,7 @@ namespace Bloxstrap { Logger.Initialize(true); Logger.WriteLine(LOG_IDENT, "Not installed, launching the installer"); + AssertWindowsOSVersion(); // prevent new installs from unsupported operating systems LaunchHandler.LaunchInstaller(); } else diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index ea0cd74..e42ff98 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -179,6 +179,8 @@ namespace Bloxstrap } #endif + App.AssertWindowsOSVersion(); + // ensure only one instance of the bootstrapper is running at the time // so that we don't have stuff like two updates happening simultaneously diff --git a/Bloxstrap/Resources/Strings.Designer.cs b/Bloxstrap/Resources/Strings.Designer.cs index fd14b8f..d1277a1 100644 --- a/Bloxstrap/Resources/Strings.Designer.cs +++ b/Bloxstrap/Resources/Strings.Designer.cs @@ -151,6 +151,15 @@ namespace Bloxstrap.Resources { } } + /// + /// Looks up a localized string similar to Roblox no longer supports Windows 7 or 8.1. To continue playing Roblox, please upgrade to Windows 10 or newer.. + /// + public static string App_OSDeprecation_Win7_81 { + get { + return ResourceManager.GetString("App.OSDeprecation.Win7_81", resourceCulture); + } + } + /// /// Looks up a localized string similar to Bloxstrap was unable to automatically update to version {0}. Please update it manually by downloading and running it from the website.. /// diff --git a/Bloxstrap/Resources/Strings.resx b/Bloxstrap/Resources/Strings.resx index c8a5479..4f3dadb 100644 --- a/Bloxstrap/Resources/Strings.resx +++ b/Bloxstrap/Resources/Strings.resx @@ -1267,4 +1267,7 @@ Please close any applications that may be using Roblox's files, and relaunch.All Bloxstrap logs Label that appears next to a checkbox + + Roblox no longer supports Windows 7 or 8.1. To continue playing Roblox, please upgrade to Windows 10 or newer. + \ No newline at end of file From 1258dc3589979857a6e4e757b2f0f06bb8e9bd0f Mon Sep 17 00:00:00 2001 From: Matt <97983689+bluepilledgreat@users.noreply.github.com> Date: Sat, 1 Mar 2025 15:44:06 +0000 Subject: [PATCH 06/18] remove behind production check for channels (#4730) --- Bloxstrap/Bootstrapper.cs | 8 -------- Bloxstrap/Models/APIs/Roblox/ClientVersion.cs | 2 -- Bloxstrap/RobloxInterfaces/Deployment.cs | 9 --------- 3 files changed, 19 deletions(-) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index e42ff98..da21e53 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -305,14 +305,6 @@ namespace Bloxstrap clientVersion = await Deployment.GetInfo(); } - if (clientVersion.IsBehindDefaultChannel) - { - App.Logger.WriteLine(LOG_IDENT, $"Resetting channel from {Deployment.Channel} because it's behind production"); - - Deployment.Channel = Deployment.DefaultChannel; - clientVersion = await Deployment.GetInfo(); - } - key.SetValueSafe("www.roblox.com", Deployment.IsDefaultChannel ? "" : Deployment.Channel); _latestVersionGuid = clientVersion.VersionGuid; diff --git a/Bloxstrap/Models/APIs/Roblox/ClientVersion.cs b/Bloxstrap/Models/APIs/Roblox/ClientVersion.cs index 9fa405e..5e584f4 100644 --- a/Bloxstrap/Models/APIs/Roblox/ClientVersion.cs +++ b/Bloxstrap/Models/APIs/Roblox/ClientVersion.cs @@ -12,7 +12,5 @@ public string BootstrapperVersion { get; set; } = null!; public DateTime? Timestamp { get; set; } - - public bool IsBehindDefaultChannel { get; set; } } } diff --git a/Bloxstrap/RobloxInterfaces/Deployment.cs b/Bloxstrap/RobloxInterfaces/Deployment.cs index 5be0d21..10fae6c 100644 --- a/Bloxstrap/RobloxInterfaces/Deployment.cs +++ b/Bloxstrap/RobloxInterfaces/Deployment.cs @@ -187,15 +187,6 @@ } } - // check if channel is behind LIVE - if (!isDefaultChannel) - { - var defaultClientVersion = await GetInfo(DefaultChannel); - - if (Utilities.CompareVersions(clientVersion.Version, defaultClientVersion.Version) == VersionComparison.LessThan) - clientVersion.IsBehindDefaultChannel = true; - } - ClientVersionCache[cacheKey] = clientVersion; } From f0df6153e369170bd01cee475ec1f405a3920d2a Mon Sep 17 00:00:00 2001 From: Ryan Luu Date: Sat, 1 Mar 2025 07:46:24 -0800 Subject: [PATCH 07/18] Add repro section to bug report (#3765) --- .github/ISSUE_TEMPLATE/bug_report.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 00cd191..a52add6 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -45,6 +45,16 @@ body: description: Provide a comprehensive description of the problem you're facing. Don't forget to attach any additional resources you may have, such as log files and screenshots. validations: required: true + - type: textarea + id: repro-steps + attributes: + label: How do you reproduce the problem? + description: Include the steps to reproduce the problem from start to finish. Include details such as FastFlags you added and settings you changed. + placeholder: | + 1. Go to '...' + 2. Click on '...' + 3. Scroll down to '...' + 4. See error - type: textarea id: log attributes: From 12af23b261cc2083ba96006d5141103b2185e3d5 Mon Sep 17 00:00:00 2001 From: Matt <97983689+bluepilledgreat@users.noreply.github.com> Date: Sun, 2 Mar 2025 13:06:48 +0000 Subject: [PATCH 08/18] bump package versions (#4739) --- Bloxstrap/Bloxstrap.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Bloxstrap/Bloxstrap.csproj b/Bloxstrap/Bloxstrap.csproj index 9c9b70c..6b065ac 100644 --- a/Bloxstrap/Bloxstrap.csproj +++ b/Bloxstrap/Bloxstrap.csproj @@ -49,10 +49,10 @@ - + - - + + all From 552f2a52a6a8e21a892a7b0bea11c1a5f799a566 Mon Sep 17 00:00:00 2001 From: bluepilledgreat <97983689+bluepilledgreat@users.noreply.github.com> Date: Sun, 2 Mar 2025 13:07:52 +0000 Subject: [PATCH 09/18] bump version --- Bloxstrap/Bloxstrap.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Bloxstrap/Bloxstrap.csproj b/Bloxstrap/Bloxstrap.csproj index 6b065ac..8e88aa5 100644 --- a/Bloxstrap/Bloxstrap.csproj +++ b/Bloxstrap/Bloxstrap.csproj @@ -7,8 +7,8 @@ true True Bloxstrap.ico - 2.8.6 - 2.8.6 + 2.9.0 + 2.9.0 app.manifest true false From 2acd0162fbd740f94cc65c10c93d9824e744aead Mon Sep 17 00:00:00 2001 From: Matt <97983689+bluepilledgreat@users.noreply.github.com> Date: Tue, 11 Mar 2025 10:14:44 +0000 Subject: [PATCH 10/18] Fix font related crashes (#4729) * don't crash if mod or package extraction fails * add to strings --- Bloxstrap/Bootstrapper.cs | 52 ++++++++++++++++++++----- Bloxstrap/Resources/Strings.Designer.cs | 36 +++++++++++++++++ Bloxstrap/Resources/Strings.resx | 12 ++++++ Bloxstrap/UI/Frontend.cs | 12 ++++++ 4 files changed, 103 insertions(+), 9 deletions(-) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index da21e53..bc6e36d 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -58,6 +58,7 @@ namespace Bloxstrap private double _taskbarProgressIncrement; private double _taskbarProgressMaximum; private long _totalDownloadedBytes = 0; + private bool _packageExtractionSuccess = true; private bool _mustUpgrade => String.IsNullOrEmpty(AppData.State.VersionGuid) || !File.Exists(AppData.ExecutablePath); private bool _noConnection = false; @@ -78,7 +79,15 @@ namespace Bloxstrap // https://github.com/icsharpcode/SharpZipLib/blob/master/src/ICSharpCode.SharpZipLib/Zip/FastZip.cs/#L669-L680 // exceptions don't get thrown if we define events without actually binding to the failure events. probably a bug. ¯\_(ツ)_/¯ - _fastZipEvents.FileFailure += (_, e) => throw e.Exception; + _fastZipEvents.FileFailure += (_, e) => + { + // only give a pass to font files (no idea whats wrong with them) + if (!e.Name.EndsWith(".ttf")) + throw e.Exception; + + App.Logger.WriteLine("FastZipEvents::OnFileFailure", $"Failed to extract {e.Name}"); + _packageExtractionSuccess = false; + }; _fastZipEvents.DirectoryFailure += (_, e) => throw e.Exception; _fastZipEvents.ProcessFile += (_, e) => e.ContinueRunning = !_cancelTokenSource.IsCancellationRequested; @@ -223,6 +232,8 @@ namespace Bloxstrap } } + bool allModificationsApplied = true; + if (!_noConnection) { if (AppData.State.VersionGuid != _latestVersionGuid || _mustUpgrade) @@ -233,7 +244,7 @@ namespace Bloxstrap // we require deployment details for applying modifications for a worst case scenario, // where we'd need to restore files from a package that isn't present on disk and needs to be redownloaded - await ApplyModifications(); + allModificationsApplied = await ApplyModifications(); } // check registry entries for every launch, just in case the stock bootstrapper changes it back @@ -247,7 +258,15 @@ namespace Bloxstrap await mutex.ReleaseAsync(); if (!App.LaunchSettings.NoLaunchFlag.Active && !_cancelTokenSource.IsCancellationRequested) + { + // show some balloon tips + if (!_packageExtractionSuccess) + Frontend.ShowBalloonTip(Strings.Bootstrapper_ExtractionFailed_Title, Strings.Bootstrapper_ExtractionFailed_Message, ToolTipIcon.Warning); + else if (!allModificationsApplied) + Frontend.ShowBalloonTip(Strings.Bootstrapper_ModificationsFailed_Title, Strings.Bootstrapper_ModificationsFailed_Message, ToolTipIcon.Warning); + StartRoblox(); + } await mutex.ReleaseAsync(); @@ -921,10 +940,12 @@ namespace Bloxstrap _isInstalling = false; } - private async Task ApplyModifications() + private async Task ApplyModifications() { const string LOG_IDENT = "Bootstrapper::ApplyModifications"; + bool success = true; + SetStatus(Strings.Bootstrapper_Status_ApplyingModifications); // handle file mods @@ -1000,7 +1021,7 @@ namespace Bloxstrap foreach (string file in Directory.GetFiles(Paths.Modifications, "*.*", SearchOption.AllDirectories)) { if (_cancelTokenSource.IsCancellationRequested) - return; + return true; // get relative directory path string relativeFile = file.Substring(Paths.Modifications.Length + 1); @@ -1032,10 +1053,18 @@ namespace Bloxstrap Directory.CreateDirectory(Path.GetDirectoryName(fileVersionFolder)!); Filesystem.AssertReadOnly(fileVersionFolder); - File.Copy(fileModFolder, fileVersionFolder, true); - Filesystem.AssertReadOnly(fileVersionFolder); - - App.Logger.WriteLine(LOG_IDENT, $"{relativeFile} has been copied to the version folder"); + try + { + File.Copy(fileModFolder, fileVersionFolder, true); + Filesystem.AssertReadOnly(fileVersionFolder); + App.Logger.WriteLine(LOG_IDENT, $"{relativeFile} has been copied to the version folder"); + } + catch (Exception ex) + { + App.Logger.WriteLine(LOG_IDENT, $"Failed to apply modification ({relativeFile})"); + App.Logger.WriteException(LOG_IDENT, ex); + success = false; + } } // the manifest is primarily here to keep track of what files have been @@ -1082,7 +1111,7 @@ namespace Bloxstrap if (package is not null) { if (_cancelTokenSource.IsCancellationRequested) - return; + return true; await DownloadPackage(package); ExtractPackage(package, entry.Value); @@ -1093,6 +1122,11 @@ namespace Bloxstrap App.State.Save(); App.Logger.WriteLine(LOG_IDENT, $"Finished checking file mods"); + + if (!success) + App.Logger.WriteLine(LOG_IDENT, "Failed to apply all modifications"); + + return success; } private async Task DownloadPackage(Package package) diff --git a/Bloxstrap/Resources/Strings.Designer.cs b/Bloxstrap/Resources/Strings.Designer.cs index d1277a1..e80603d 100644 --- a/Bloxstrap/Resources/Strings.Designer.cs +++ b/Bloxstrap/Resources/Strings.Designer.cs @@ -178,6 +178,24 @@ namespace Bloxstrap.Resources { } } + /// + /// Looks up a localized string similar to Some content may be missing. Force a Roblox reinstallation in settings to fix this.. + /// + public static string Bootstrapper_ExtractionFailed_Message { + get { + return ResourceManager.GetString("Bootstrapper.ExtractionFailed.Message", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to extract all files. + /// + public static string Bootstrapper_ExtractionFailed_Title { + get { + return ResourceManager.GetString("Bootstrapper.ExtractionFailed.Title", resourceCulture); + } + } + /// /// Looks up a localized string similar to Bloxstrap tried to upgrade Roblox but can't because Roblox's files are still in use. /// @@ -207,6 +225,24 @@ namespace Bloxstrap.Resources { } } + /// + /// Looks up a localized string similar to Not all modifications will be present in the current launch.. + /// + public static string Bootstrapper_ModificationsFailed_Message { + get { + return ResourceManager.GetString("Bootstrapper.ModificationsFailed.Message", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to apply all modifications. + /// + public static string Bootstrapper_ModificationsFailed_Title { + get { + return ResourceManager.GetString("Bootstrapper.ModificationsFailed.Title", resourceCulture); + } + } + /// /// Looks up a localized string similar to Bloxstrap does not have enough disk space to download and install Roblox. Please free up some disk space and try again.. /// diff --git a/Bloxstrap/Resources/Strings.resx b/Bloxstrap/Resources/Strings.resx index 4f3dadb..9048916 100644 --- a/Bloxstrap/Resources/Strings.resx +++ b/Bloxstrap/Resources/Strings.resx @@ -1270,4 +1270,16 @@ Please close any applications that may be using Roblox's files, and relaunch. Roblox no longer supports Windows 7 or 8.1. To continue playing Roblox, please upgrade to Windows 10 or newer. + + Failed to extract all files + + + Some content may be missing. Force a Roblox reinstallation in settings to fix this. + + + Failed to apply all modifications + + + Not all modifications will be present in the current launch. + \ No newline at end of file diff --git a/Bloxstrap/UI/Frontend.cs b/Bloxstrap/UI/Frontend.cs index cb069fc..d195906 100644 --- a/Bloxstrap/UI/Frontend.cs +++ b/Bloxstrap/UI/Frontend.cs @@ -83,5 +83,17 @@ namespace Bloxstrap.UI return messagebox.Result; })); } + + public static void ShowBalloonTip(string title, string message, System.Windows.Forms.ToolTipIcon icon = System.Windows.Forms.ToolTipIcon.None, int timeout = 5) + { + var notifyIcon = new System.Windows.Forms.NotifyIcon + { + Icon = Properties.Resources.IconBloxstrap, + Text = App.ProjectName, + Visible = true + }; + + notifyIcon.ShowBalloonTip(timeout, title, message, icon); + } } } From 33243bfd0a942de4ad151343f468e9d77e5fc1d3 Mon Sep 17 00:00:00 2001 From: Matt <97983689+bluepilledgreat@users.noreply.github.com> Date: Tue, 11 Mar 2025 11:00:23 +0000 Subject: [PATCH 11/18] Improve version cleanup (#4810) * more safely delete the roblox instance * assertreadonly the whole directory --- Bloxstrap/Bootstrapper.cs | 30 +++++++++++++++++++++++++++++- Bloxstrap/Utility/Filesystem.cs | 10 ++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index bc6e36d..3bf0cff 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -662,7 +662,28 @@ namespace Bloxstrap #endregion #region Roblox Install - private void CleanupVersionsFolder() + private static bool TryDeleteRobloxInDirectory(string dir) + { + string clientPath = Path.Combine(dir, "RobloxPlayerBeta.exe"); + if (!File.Exists(dir)) + { + clientPath = Path.Combine(dir, "RobloxStudioBeta.exe"); + if (!File.Exists(dir)) + return true; // ok??? + } + + try + { + File.Delete(clientPath); + return true; + } + catch (Exception) + { + return false; + } + } + + public static void CleanupVersionsFolder() { const string LOG_IDENT = "Bootstrapper::CleanupVersionsFolder"; @@ -672,6 +693,13 @@ namespace Bloxstrap if (dirName != App.State.Prop.Player.VersionGuid && dirName != App.State.Prop.Studio.VersionGuid) { + Filesystem.AssertReadOnlyDirectory(dir); + + // check if it's still being used first + // we dont want to accidentally delete the files of a running roblox instance + if (!TryDeleteRobloxInDirectory(dir)) + continue; + try { Directory.Delete(dir, true); diff --git a/Bloxstrap/Utility/Filesystem.cs b/Bloxstrap/Utility/Filesystem.cs index 77bd284..13a9d7f 100644 --- a/Bloxstrap/Utility/Filesystem.cs +++ b/Bloxstrap/Utility/Filesystem.cs @@ -31,5 +31,15 @@ namespace Bloxstrap.Utility fileInfo.IsReadOnly = false; App.Logger.WriteLine("Filesystem::AssertReadOnly", $"The following file was set as read-only: {filePath}"); } + + internal static void AssertReadOnlyDirectory(string directoryPath) + { + var directory = new DirectoryInfo(directoryPath) { Attributes = FileAttributes.Normal }; + + foreach (var info in directory.GetFileSystemInfos("*", SearchOption.AllDirectories)) + info.Attributes = FileAttributes.Normal; + + App.Logger.WriteLine("Filesystem::AssertReadOnlyDirectory", $"The following directory was set as read-only: {directoryPath}"); + } } } From 9d356b0b71b6154efa09dd51560570147a2f6c60 Mon Sep 17 00:00:00 2001 From: Matt <97983689+bluepilledgreat@users.noreply.github.com> Date: Tue, 11 Mar 2025 19:18:54 +0000 Subject: [PATCH 12/18] Custom bootstrapper themes (#4380) * add custom bootstrappers * add avalonedit to licenses page * add gif support * add stretch & stretchdirection to images * dont create a bitmapimage for gifs * remove maxheight and maxwidth sets * remove comment * add isenabled * add more textblock properties * add markdowntextblocks * update how transform elements are stored * overhaul textbox content * dont set fontsize if not set * fix warnings * add foreground property to control * add background property to textblock * count descendants and increase element cap * add auto complete * dont display completion window if there is no data * sort schema elements and types * make ! close the completion window * add end tag auto complete * fix pos being wrong * dont treat comments as elements * add imagebrushes * follow same conventions as brushes * fix exception messages * fix them again * update schema * fix crash * now it works * wrong attribute name * add solidcolorbrush * move converters into a separate file * add lineargradientbrushes * unify handlers * update schema * add fake BloxstrapCustomBootstrapper * stop adding an extra end character * add property element auto-complete * add title attribute to custombloxstrapbootstrapper * add shapes * add string translation support * use default wpf size instead of 100x100 * update min height of window * fix verticalalignment not working * uncap height and width * add effects * move transformation handler inside frameworkelement * fix title bar effect & transformation removal * add more frameworkelement properties * add layout transform * add font properties to control * improve window border stuff * make sure file contents are in CRLF * add cornerradius to progress bar * add progressring * Update wpfui * update schema * update function names * add children check to content * make sure only one content is defined * add fontfamily * update schema * only allow file uris for images * disable backdrop * move text setter to textblock handler from base * split up creator into multiple files * turn version into a constant * add grids * cleanup converters * add IgnoreTitleBarInset * add Version to schema * reveal custom bootstrapper stuff on selection * increase listbox height * only set statustext binding in textblock * update ui * rename ZIndex to Panel.ZIndex * add stackpanel * add border * fix being unable to apply transforms on grids * rearrange and add new editor button * use snackbars for saving * add close confirmation message * use viewmodel variable * remove pointless onpropertychanged call * add version string format * start editor window in the centre * update licenses page also resized the about window so everything could fit nicely * fix border not inheriting frameworkelement * add WindowCornerPreference * add the import dialog * add an export theme button * update version number * localise CustomDialog exceptions * localise custom theme editor * localise custom theme add dialog * localise frontend * localise appearance menu page * change customtheme error strings namespace * change icons on appearance page * update button margin on appearance page --- Bloxstrap/App.xaml | 2 + Bloxstrap/Bloxstrap.csproj | 7 + Bloxstrap/Enums/BootstrapperStyle.cs | 3 +- Bloxstrap/Enums/CustomThemeTemplate.cs | 8 + Bloxstrap/Exceptions/CustomThemeException.cs | 60 ++ Bloxstrap/Extensions/BootstrapperStyleEx.cs | 3 +- Bloxstrap/Extensions/CustomThemeTemplateEx.cs | 10 + Bloxstrap/Models/Persistable/Settings.cs | 1 + Bloxstrap/Paths.cs | 2 + Bloxstrap/Resource.cs | 5 + .../Resources/CustomBootstrapperSchema.json | 521 ++++++++++++ .../CustomBootstrapperTemplate_Blank.xml | 4 + .../CustomBootstrapperTemplate_Simple.xml | 9 + Bloxstrap/Resources/Strings.Designer.cs | 487 +++++++++++ Bloxstrap/Resources/Strings.resx | 163 ++++ Bloxstrap/UI/Elements/About/MainWindow.xaml | 4 +- .../UI/Elements/About/Pages/LicensesPage.xaml | 20 +- Bloxstrap/UI/Elements/Base/WpfUiWindow.cs | 6 + .../Bootstrapper/CustomDialog.Converters.cs | 90 ++ .../Bootstrapper/CustomDialog.Creator.cs | 151 ++++ .../Bootstrapper/CustomDialog.Elements.cs | 772 ++++++++++++++++++ .../Bootstrapper/CustomDialog.Utilities.cs | 300 +++++++ .../Elements/Bootstrapper/CustomDialog.xaml | 55 ++ .../Bootstrapper/CustomDialog.xaml.cs | 122 +++ .../Dialogs/AddCustomThemeDialog.xaml | 165 ++++ .../Dialogs/AddCustomThemeDialog.xaml.cs | 230 ++++++ .../Editor/BootstrapperEditorWindow.xaml | 84 ++ .../Editor/BootstrapperEditorWindow.xaml.cs | 580 +++++++++++++ .../Settings/Pages/AppearancePage.xaml | 90 +- .../Settings/Pages/AppearancePage.xaml.cs | 13 + Bloxstrap/UI/Frontend.cs | 27 + Bloxstrap/UI/Style/Dark.xaml | 5 + Bloxstrap/UI/Style/Default.xaml | 189 +++++ Bloxstrap/UI/Style/Editor-Theme-Dark.xshd | 63 ++ Bloxstrap/UI/Style/Editor-Theme-Light.xshd | 63 ++ Bloxstrap/UI/Style/Light.xaml | 5 + .../Dialogs/AddCustomThemeViewModel.cs | 68 ++ .../BootstrapperEditorWindowViewModel.cs | 84 ++ .../Settings/AppearanceViewModel.cs | 197 ++++- Bloxstrap/Utility/PathValidator.cs | 104 +++ wpfui | 2 +- 41 files changed, 4753 insertions(+), 21 deletions(-) create mode 100644 Bloxstrap/Enums/CustomThemeTemplate.cs create mode 100644 Bloxstrap/Exceptions/CustomThemeException.cs create mode 100644 Bloxstrap/Extensions/CustomThemeTemplateEx.cs create mode 100644 Bloxstrap/Resources/CustomBootstrapperSchema.json create mode 100644 Bloxstrap/Resources/CustomBootstrapperTemplate_Blank.xml create mode 100644 Bloxstrap/Resources/CustomBootstrapperTemplate_Simple.xml create mode 100644 Bloxstrap/UI/Elements/Bootstrapper/CustomDialog.Converters.cs create mode 100644 Bloxstrap/UI/Elements/Bootstrapper/CustomDialog.Creator.cs create mode 100644 Bloxstrap/UI/Elements/Bootstrapper/CustomDialog.Elements.cs create mode 100644 Bloxstrap/UI/Elements/Bootstrapper/CustomDialog.Utilities.cs create mode 100644 Bloxstrap/UI/Elements/Bootstrapper/CustomDialog.xaml create mode 100644 Bloxstrap/UI/Elements/Bootstrapper/CustomDialog.xaml.cs create mode 100644 Bloxstrap/UI/Elements/Dialogs/AddCustomThemeDialog.xaml create mode 100644 Bloxstrap/UI/Elements/Dialogs/AddCustomThemeDialog.xaml.cs create mode 100644 Bloxstrap/UI/Elements/Editor/BootstrapperEditorWindow.xaml create mode 100644 Bloxstrap/UI/Elements/Editor/BootstrapperEditorWindow.xaml.cs create mode 100644 Bloxstrap/UI/Style/Dark.xaml create mode 100644 Bloxstrap/UI/Style/Default.xaml create mode 100644 Bloxstrap/UI/Style/Editor-Theme-Dark.xshd create mode 100644 Bloxstrap/UI/Style/Editor-Theme-Light.xshd create mode 100644 Bloxstrap/UI/Style/Light.xaml create mode 100644 Bloxstrap/UI/ViewModels/Dialogs/AddCustomThemeViewModel.cs create mode 100644 Bloxstrap/UI/ViewModels/Editor/BootstrapperEditorWindowViewModel.cs create mode 100644 Bloxstrap/Utility/PathValidator.cs diff --git a/Bloxstrap/App.xaml b/Bloxstrap/App.xaml index ae4bfac..2029b34 100644 --- a/Bloxstrap/App.xaml +++ b/Bloxstrap/App.xaml @@ -11,6 +11,8 @@ + + pack://application:,,,/Resources/Fonts/#Rubik Light diff --git a/Bloxstrap/Bloxstrap.csproj b/Bloxstrap/Bloxstrap.csproj index 8e88aa5..bb30ff6 100644 --- a/Bloxstrap/Bloxstrap.csproj +++ b/Bloxstrap/Bloxstrap.csproj @@ -25,9 +25,14 @@ + + + + + @@ -49,6 +54,7 @@ + @@ -59,6 +65,7 @@ + diff --git a/Bloxstrap/Enums/BootstrapperStyle.cs b/Bloxstrap/Enums/BootstrapperStyle.cs index 5c5f6fd..c638858 100644 --- a/Bloxstrap/Enums/BootstrapperStyle.cs +++ b/Bloxstrap/Enums/BootstrapperStyle.cs @@ -10,6 +10,7 @@ ByfronDialog, [EnumName(StaticName = "Bloxstrap")] FluentDialog, - FluentAeroDialog + FluentAeroDialog, + CustomDialog } } diff --git a/Bloxstrap/Enums/CustomThemeTemplate.cs b/Bloxstrap/Enums/CustomThemeTemplate.cs new file mode 100644 index 0000000..6497907 --- /dev/null +++ b/Bloxstrap/Enums/CustomThemeTemplate.cs @@ -0,0 +1,8 @@ +namespace Bloxstrap.Enums +{ + public enum CustomThemeTemplate + { + Blank, + Simple + } +} diff --git a/Bloxstrap/Exceptions/CustomThemeException.cs b/Bloxstrap/Exceptions/CustomThemeException.cs new file mode 100644 index 0000000..68ad0a1 --- /dev/null +++ b/Bloxstrap/Exceptions/CustomThemeException.cs @@ -0,0 +1,60 @@ +using Bloxstrap.Extensions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Bloxstrap.Exceptions +{ + internal class CustomThemeException : Exception + { + /// + /// The exception message in English (for logging) + /// + public string EnglishMessage { get; } = null!; + + public CustomThemeException(string translationString) + : base(Strings.ResourceManager.GetStringSafe(translationString)) + { + EnglishMessage = Strings.ResourceManager.GetStringSafe(translationString, new CultureInfo("en-GB")); + } + + public CustomThemeException(Exception innerException, string translationString) + : base(Strings.ResourceManager.GetStringSafe(translationString), innerException) + { + EnglishMessage = Strings.ResourceManager.GetStringSafe(translationString, new CultureInfo("en-GB")); + } + + public CustomThemeException(string translationString, params object?[] args) + : base(string.Format(Strings.ResourceManager.GetStringSafe(translationString), args)) + { + EnglishMessage = string.Format(Strings.ResourceManager.GetStringSafe(translationString, new CultureInfo("en-GB")), args); + } + + public CustomThemeException(Exception innerException, string translationString, params object?[] args) + : base(string.Format(Strings.ResourceManager.GetStringSafe(translationString), args), innerException) + { + EnglishMessage = string.Format(Strings.ResourceManager.GetStringSafe(translationString, new CultureInfo("en-GB")), args); + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(GetType().ToString()); + + if (!string.IsNullOrEmpty(Message)) + sb.Append($": {Message}"); + + if (!string.IsNullOrEmpty(EnglishMessage) && Message != EnglishMessage) + sb.Append($" ({EnglishMessage})"); + + if (InnerException != null) + sb.Append($"\r\n ---> {InnerException}\r\n "); + + if (StackTrace != null) + sb.Append($"\r\n{StackTrace}"); + + return sb.ToString(); + } + } +} diff --git a/Bloxstrap/Extensions/BootstrapperStyleEx.cs b/Bloxstrap/Extensions/BootstrapperStyleEx.cs index 3802264..693c78e 100644 --- a/Bloxstrap/Extensions/BootstrapperStyleEx.cs +++ b/Bloxstrap/Extensions/BootstrapperStyleEx.cs @@ -13,7 +13,8 @@ BootstrapperStyle.ProgressDialog, BootstrapperStyle.LegacyDialog2011, BootstrapperStyle.LegacyDialog2008, - BootstrapperStyle.VistaDialog + BootstrapperStyle.VistaDialog, + BootstrapperStyle.CustomDialog }; } } diff --git a/Bloxstrap/Extensions/CustomThemeTemplateEx.cs b/Bloxstrap/Extensions/CustomThemeTemplateEx.cs new file mode 100644 index 0000000..4088f02 --- /dev/null +++ b/Bloxstrap/Extensions/CustomThemeTemplateEx.cs @@ -0,0 +1,10 @@ +namespace Bloxstrap.Extensions +{ + static class CustomThemeTemplateEx + { + public static string GetFileName(this CustomThemeTemplate template) + { + return $"CustomBootstrapperTemplate_{template}.xml"; + } + } +} diff --git a/Bloxstrap/Models/Persistable/Settings.cs b/Bloxstrap/Models/Persistable/Settings.cs index d640fc3..a239f31 100644 --- a/Bloxstrap/Models/Persistable/Settings.cs +++ b/Bloxstrap/Models/Persistable/Settings.cs @@ -17,6 +17,7 @@ namespace Bloxstrap.Models.Persistable public bool UseFastFlagManager { get; set; } = true; public bool WPFSoftwareRender { get; set; } = false; public bool EnableAnalytics { get; set; } = true; + public string? SelectedCustomTheme { get; set; } = null; // integration configuration public bool EnableActivityTracking { get; set; } = true; diff --git a/Bloxstrap/Paths.cs b/Bloxstrap/Paths.cs index 43d4a1c..1205d67 100644 --- a/Bloxstrap/Paths.cs +++ b/Bloxstrap/Paths.cs @@ -22,6 +22,7 @@ public static string Integrations { get; private set; } = ""; public static string Versions { get; private set; } = ""; public static string Modifications { get; private set; } = ""; + public static string CustomThemes { get; private set; } = ""; public static string Application { get; private set; } = ""; @@ -37,6 +38,7 @@ Integrations = Path.Combine(Base, "Integrations"); Versions = Path.Combine(Base, "Versions"); Modifications = Path.Combine(Base, "Modifications"); + CustomThemes = Path.Combine(Base, "CustomThemes"); Application = Path.Combine(Base, $"{App.ProjectName}.exe"); } diff --git a/Bloxstrap/Resource.cs b/Bloxstrap/Resource.cs index 46c8e82..612d846 100644 --- a/Bloxstrap/Resource.cs +++ b/Bloxstrap/Resource.cs @@ -21,5 +21,10 @@ namespace Bloxstrap await stream.CopyToAsync(memoryStream); return memoryStream.ToArray(); } + + public static async Task GetString(string name) + { + return Encoding.UTF8.GetString(await Get(name)); + } } } diff --git a/Bloxstrap/Resources/CustomBootstrapperSchema.json b/Bloxstrap/Resources/CustomBootstrapperSchema.json new file mode 100644 index 0000000..44b6631 --- /dev/null +++ b/Bloxstrap/Resources/CustomBootstrapperSchema.json @@ -0,0 +1,521 @@ +{ + "Elements": { + "FrameworkElement": { + "IsCreatable": false, + "Attributes": { + "Name": "string", + "Visibility": "Visibility", + "IsEnabled": "bool", + "Margin": "Thickness", + "Height": "double", + "Width": "double", + "HorizontalAlignment": "HorizontalAlignment", + "VerticalAlignment": "VerticalAlignment", + "RenderTransform": "Transform", + "LayoutTransform": "Transform", + "Opacity": "double", + "OpacityMask": "Brush", + "RenderTransformOrigin": "Point", + "Panel.ZIndex": "int", + "Grid.Row": "int", + "Grid.RowSpan": "int", + "Grid.Column": "int", + "Grid.ColumnSpan": "int" + } + }, + "Control": { + "SuperClass": "FrameworkElement", + "IsCreatable": false, + "Attributes": { + "Padding": "Thickness", + "BorderThickness": "Thickness", + "Foreground": "Brush", + "Background": "Brush", + "BorderBrush": "Brush", + "FontSize": "double", + "FontWeight": "FontWeight", + "FontStyle": "FontStyle", + "FontFamily": "FontFamily" + } + }, + "BloxstrapCustomBootstrapper": { + "SuperClass": "Control", + "IsCreatable": true, + "Attributes": { + "Version": "int", + "Theme": "Theme", + "Title": "string", + "IgnoreTitleBarInset": "bool", + "WindowCornerPreference": "WindowCornerPreference" + } + }, + "TitleBar": { + "SuperClass": "Control", + "IsCreatable": true, + "Attributes": { + "ShowMinimize": "bool", + "ShowClose": "bool", + "Title": "string" + } + }, + "Button": { + "SuperClass": "Control", + "IsCreatable": true, + "Attributes": { + "Content": "object" + } + }, + "RangeBase": { + "SuperClass": "Control", + "IsCreatable": false, + "Attributes": { + "Value": "double", + "Maximum": "double" + } + }, + "ProgressBar": { + "SuperClass": "RangeBase", + "IsCreatable": true, + "Attributes": { + "IsIndeterminate": "bool", + "CornerRadius": "CornerRadius", + "IndicatorCornerRadius": "CornerRadius" + } + }, + "ProgressRing": { + "SuperClass": "RangeBase", + "IsCreatable": true, + "Attributes": { + "IsIndeterminate": "bool" + } + }, + "TextBlock": { + "SuperClass": "FrameworkElement", + "IsCreatable": true, + "Attributes": { + "Text": "string", + "Foreground": "Brush", + "Background": "Brush", + "FontSize": "double", + "FontWeight": "FontWeight", + "FontStyle": "FontStyle", + "FontFamily": "FontFamily", + "LineHeight": "double", + "LineStackingStrategy": "LineStackingStrategy", + "TextAlignment": "TextAlignment", + "TextTrimming": "TextTrimming", + "TextWrapping": "TextWrapping", + "TextDecorations": "TextDecorations", + "IsHyphenationEnabled": "bool", + "BaselineOffset": "double", + "Padding": "Thickness" + } + }, + "MarkdownTextBlock": { + "SuperClass": "TextBlock", + "IsCreatable": true, + "Attributes": {} + }, + "Image": { + "SuperClass": "FrameworkElement", + "IsCreatable": true, + "Attributes": { + "Stretch": "Stretch", + "StretchDirection": "StretchDirection", + "Source": "ImageSource", + "IsAnimated": "bool" + } + }, + "Grid": { + "SuperClass": "FrameworkElement", + "IsCreatable": true, + "Attributes": { + "RowDefinitions": "object", + "ColumnDefinitions": "object" + } + }, + "StackPanel": { + "SuperClass": "FrameworkElement", + "IsCreatable": true, + "Attributes": { + "Orientation": "Orientation" + } + }, + "Border": { + "SuperClass": "FrameworkElement", + "IsCreatable": true, + "Attributes": { + "Background": "Brush", + "BorderBrush": "Brush", + "BorderThickness": "Thickness", + "Padding": "Thickness", + "CornerRadius": "CornerRadius" + } + }, + "RowDefinition": { + "IsCreatable": true, + "Attributes": { + "Height": "GridLength", + "MinHeight": "double", + "MaxHeight": "double" + } + }, + "ColumnDefinition": { + "IsCreatable": true, + "Attributes": { + "Width": "GridLength", + "MinWidth": "double", + "MaxWidth": "double" + } + }, + "ScaleTransform": { + "IsCreatable": true, + "Attributes": { + "ScaleX": "double", + "ScaleY": "double", + "CenterX": "double", + "CenterY": "double" + } + }, + "SkewTransform": { + "IsCreatable": true, + "Attributes": { + "AngleX": "double", + "AngleY": "double", + "CenterX": "double", + "CenterY": "double" + } + }, + "RotateTransform": { + "IsCreatable": true, + "Attributes": { + "Angle": "double", + "CenterX": "double", + "CenterY": "double" + } + }, + "TranslateTransform": { + "IsCreatable": true, + "Attributes": { + "X": "double", + "Y": "double" + } + }, + "Brush": { + "IsCreatable": false, + "Attributes": { + "Opacity": "double" + } + }, + "SolidColorBrush": { + "SuperClass": "Brush", + "IsCreatable": true, + "Attributes": { + "Color": "Color" + } + }, + "ImageBrush": { + "SuperClass": "Brush", + "IsCreatable": true, + "Attributes": { + "AlignmentX": "AlignmentX", + "AlignmentY": "AlignmentY", + "Stretch": "Stretch", + "TileMode": "TileMode", + "ViewboxUnits": "BrushMappingMode", + "ViewportUnits": "BrushMappingMode", + "Viewbox": "Rect", + "Viewport": "Rect", + "ImageSource": "ImageSource" + } + }, + "LinearGradientBrush": { + "SuperClass": "Brush", + "IsCreatable": true, + "Attributes": { + "StartPoint": "Point", + "EndPoint": "Point", + "ColorInterpolationMode": "ColorInterpolationMode", + "MappingMode": "BrushMappingMode", + "SpreadMethod": "GradientSpreadMethod" + } + }, + "GradientStop": { + "IsCreatable": true, + "Attributes": { + "Color": "Color", + "Offset": "double" + } + }, + "Shape": { + "SuperClass": "FrameworkElement", + "IsCreatable": false, + "Attributes": { + "Fill": "Brush", + "Stroke": "Brush", + "Stretch": "Stretch", + "StrokeDashCap": "PenLineCap", + "StrokeDashOffset": "double", + "StrokeEndLineCap": "PenLineCap", + "StrokeLineJoin": "PenLineJoin", + "StrokeMiterLimit": "double", + "StrokeStartLineCap": "PenLineCap", + "StrokeThickness": "double" + } + }, + "Ellipse": { + "SuperClass": "Shape", + "IsCreatable": true, + "Attributes": {} + }, + "Line": { + "SuperClass": "Shape", + "IsCreatable": true, + "Attributes": { + "X1": "double", + "X2": "double", + "Y1": "double", + "Y2": "double" + } + }, + "Rectangle": { + "SuperClass": "Shape", + "IsCreatable": true, + "Attributes": { + "RadiusX": "double", + "RadiusY": "double" + } + }, + "BlurEffect": { + "IsCreatable": true, + "Attributes": { + "KernelType": "KernelType", + "Radius": "double", + "RenderingBias": "RenderingBias" + } + }, + "DropShadowEffect": { + "IsCreatable": true, + "Attributes": { + "BlurRadius": "double", + "Direction": "double", + "Opacity": "double", + "ShadowDepth": "double", + "RenderingBias": "RenderingBias", + "Color": "Color" + } + } + }, + "Types": { + "string": {}, + "bool": { + "Values": [ + "True", + "False" + ] + }, + "int": {}, + "double": {}, + "object": { "CanHaveElement": true }, + "Thickness": {}, + "Rect": {}, + "Point": {}, + "CornerRadius": {}, + "Brush": { "CanHaveElement": true }, + "Color": {}, + "ImageSource": {}, + "Transform": { "CanHaveElement": true }, + "FontFamily": {}, + "GridLength": {}, + "Visibility": { + "Values": [ + "Visible", + "Hidden", + "Collapsed" + ] + }, + "HorizontalAlignment": { + "Values": [ + "Left", + "Center", + "Right", + "Stretch" + ] + }, + "VerticalAlignment": { + "Values": [ + "Top", + "Center", + "Bottom", + "Stretch" + ] + }, + "Theme": { + "Values": [ + "Default", + "Dark", + "Light" + ] + }, + "FontWeight": { + "Values": [ + "Thin", + "ExtraLight", + "UltraLight", + "Medium", + "Normal", + "Regular", + "DemiBold", + "SemiBold", + "Bold", + "ExtraBold", + "UltraBold", + "Black", + "Heavy", + "ExtraBlack", + "ExtraHeavy" + ] + }, + "FontStyle": { + "Values": [ + "Normal", + "Italic", + "Oblique" + ] + }, + "LineStackingStrategy": { + "Values": [ + "BlockLineHeight", + "MaxHeight" + ] + }, + "TextAlignment": { + "Values": [ + "Left", + "Right", + "Center", + "Justify" + ] + }, + "TextTrimming": { + "Values": [ + "None", + "CharacterEllipsis", + "WordEllipsis" + ] + }, + "TextWrapping": { + "Values": [ + "WrapWithOverflow", + "NoWrap", + "Wrap" + ] + }, + "TextDecorations": { + "Values": [ + "Baseline", + "OverLine", + "Strikethrough", + "Underline" + ] + }, + "Stretch": { + "Values": [ + "None", + "Fill", + "Uniform", + "UniformToFill" + ] + }, + "StretchDirection": { + "Values": [ + "UpOnly", + "DownOnly", + "Both" + ] + }, + "AlignmentX": { + "Values": [ + "Left", + "Center", + "Right" + ] + }, + "AlignmentY": { + "Values": [ + "Top", + "Center", + "Bottom" + ] + }, + "TileMode": { + "Values": [ + "None", + "FlipX", + "FlipY", + "FlipXY", + "Tile" + ] + }, + "BrushMappingMode": { + "Values": [ + "Absolute", + "RelativeToBoundingBox" + ] + }, + "ColorInterpolationMode": { + "Values": [ + "ScRgbLinearInterpolation", + "SRgbLinearInterpolation" + ] + }, + "GradientSpreadMethod": { + "Values": [ + "Pad", + "Reflect", + "Repeat" + ] + }, + "PenLineCap": { + "Values": [ + "Flat", + "Square", + "Round", + "Triangle" + ] + }, + "PenLineJoin": { + "Values": [ + "Miter", + "Bevel", + "Round" + ] + }, + "KernelType": { + "Values": [ + "Gaussian", + "Box" + ] + }, + "RenderingBias": { + "Values": [ + "Performance", + "Quality" + ] + }, + "Orientation": { + "Values": [ + "Horizontal", + "Vertical" + ] + }, + "WindowCornerPreference": { + "Values": [ + "Default", + "DoNotRound", + "Round", + "RoundSmall" + ] + } + } +} \ No newline at end of file diff --git a/Bloxstrap/Resources/CustomBootstrapperTemplate_Blank.xml b/Bloxstrap/Resources/CustomBootstrapperTemplate_Blank.xml new file mode 100644 index 0000000..99efce9 --- /dev/null +++ b/Bloxstrap/Resources/CustomBootstrapperTemplate_Blank.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Bloxstrap/Resources/CustomBootstrapperTemplate_Simple.xml b/Bloxstrap/Resources/CustomBootstrapperTemplate_Simple.xml new file mode 100644 index 0000000..7664806 --- /dev/null +++ b/Bloxstrap/Resources/CustomBootstrapperTemplate_Simple.xml @@ -0,0 +1,9 @@ + + + + + + + +