Skip to content

Commit 2659aea

Browse files
fix: fix a few errors, mainly with missing names
notes: majority of errors arise from Frontend.MessageBox, I have no idea where that is we have to fix that and most errors will go away
1 parent 53ae275 commit 2659aea

288 files changed

Lines changed: 65791 additions & 70 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Froststrap.AvaloniaUI/App.axaml.cs

Lines changed: 139 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,169 @@
11
using Avalonia;
22
using Avalonia.Controls.ApplicationLifetimes;
3-
using Avalonia.Data.Core.Plugins;
43
using Avalonia.Markup.Xaml;
5-
using Froststrap.AvaloniaUI.ViewModels;
4+
using Avalonia.Threading;
5+
using Microsoft.Win32;
6+
using System.Reflection;
7+
using System.Security.Cryptography;
8+
using System.Text;
69
using Froststrap.AvaloniaUI.Views;
10+
using Froststrap.AvaloniaUI.ViewModels;
11+
using Froststrap.Integrations;
12+
13+
namespace Froststrap;
714

8-
namespace Froststrap.AvaloniaUI;
15+
16+
/*
17+
* shits currently broken right now
18+
* - WPF-only Base Types
19+
* - WPF UI Libraries
20+
* - Global Exception Handling (we gonna have fun fixing that one)
21+
* - Fonts (Avalonia uses asset based font loading)
22+
* - Rendering & GPU Control
23+
* - Message Boxes (MessageBox.Avalonia comes in clutch)
24+
* - Taskbar Integration (Does anyone even realize we have this????)
25+
* - Window Enumeration & Lifetime
26+
* - WPF Resource System (Probably easy to fix)
27+
* - WPF Startup & Exit Hooks (Also probably easy to fix)
28+
* - Dispatcher-Based Threading (Use: Dispatcher.UIThread)
29+
* - Windows-Only UX APIs. Backdrop, Transparency etc. (Probably just make these Windows exclusive)
30+
*
31+
* This is just ONE file, alebit a fairly big and important one.
32+
*/
933

1034
public partial class App : Application
1135
{
36+
#if QA_BUILD
37+
public const string ProjectName = "Froststrap-QA";
38+
#else
39+
public const string ProjectName = "Froststrap";
40+
#endif
41+
42+
public const string ProjectOwner = "RealMeddsam";
43+
public const string ProjectRepository = "RealMeddsam/Froststrap";
44+
public const string ProjectDownloadLink = "https://github.com/RealMeddsam/Froststrap/releases";
45+
public const string ProjectHelpLink = "https://github.com/bloxstraplabs/bloxstrap/wiki"; // Most likely need to make our own wiki after we finish rewrite
46+
public const string ProjectSupportLink = "https://github.com/RealMeddsam/Froststrap/issues/new";
47+
public const string ProjectRemoteDataLink = "https://raw.githubusercontent.com/RealMeddsam/config/refs/heads/main/Data.json";
48+
49+
// Windows only for now
50+
public const string RobloxPlayerAppName = "RobloxPlayerBeta.exe";
51+
public const string RobloxStudioAppName = "RobloxStudioBeta.exe";
52+
53+
// one day ill add studio support
54+
// edit: are you sure about that?
55+
public const string RobloxAnselAppName = "eurotrucks2.exe";
56+
57+
// Not yet sure whats the point of this but ok
58+
public const string UninstallKey = $@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{ProjectName}";
59+
public const string ApisKey = $"Software\\{ProjectName}";
60+
61+
62+
public static LaunchSettings LaunchSettings { get; private set; } = null!;
63+
public static readonly MD5 MD5Provider = MD5.Create();
64+
public static readonly Logger Logger = new();
65+
66+
public static Bootstrapper? Bootstrapper { get; set; } = null!;
67+
public FroststrapRichPresence RichPresence { get; private set; } = null!;
68+
public static MemoryCleaner MemoryCleaner { get; private set; } = null!; // doubt this is necessary on Linux
69+
70+
public static bool IsActionBuild => !String.IsNullOrEmpty(BuildMetadata.CommitRef);
71+
public static bool IsProductionBuild => IsActionBuild && BuildMetadata.CommitRef.StartsWith("tag", StringComparison.Ordinal);
72+
public static bool IsPlayerInstalled => App.PlayerState.IsSaved && !String.IsNullOrEmpty(App.PlayerState.Prop.VersionGuid);
73+
public static bool IsStudioInstalled => App.StudioState.IsSaved && !String.IsNullOrEmpty(App.StudioState.Prop.VersionGuid);
74+
75+
76+
// Disambiguate Settings so we use the persistable Settings (Bloxstrap.Models.Persistable.Settings),
77+
// not the auto-generated Properties.Settings which doesn't contain the clicker fields.
78+
public static readonly JsonManager<Settings> Settings = new();
79+
public static readonly JsonManager<State> State = new();
80+
public static readonly LazyJsonManager<DistributionState> PlayerState = new(nameof(PlayerState));
81+
public static readonly LazyJsonManager<DistributionState> StudioState = new(nameof(StudioState));
82+
public static readonly RemoteDataManager RemoteData = new();
83+
public static readonly FastFlagManager FastFlags = new();
84+
public static readonly GBSEditor GlobalSettings = new();
85+
public static readonly CookiesManager Cookies = new();
86+
public static readonly HttpClient HttpClient = new(new HttpClientLoggingHandler(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.All }));
87+
88+
public static BuildMetadataAttribute BuildMetadata =
89+
Assembly.GetExecutingAssembly().GetCustomAttribute<BuildMetadataAttribute>()!;
90+
91+
public static string Version =
92+
Assembly.GetExecutingAssembly().GetName().Version!.ToString();
93+
94+
private static bool _showingExceptionDialog;
95+
1296
public override void Initialize()
1397
{
1498
AvaloniaXamlLoader.Load(this);
99+
100+
// Global exception handlers (Avalonia replacement)
101+
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
102+
TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;
15103
}
16104

17105
public override void OnFrameworkInitializationCompleted()
18106
{
19107
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
20108
{
21-
// Avoid duplicate validations from both Avalonia and the CommunityToolkit.
22-
// More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins
23-
DisableAvaloniaDataAnnotationValidation();
109+
LaunchSettings = new LaunchSettings(Environment.GetCommandLineArgs());
110+
111+
Logger.WriteLine("App::Startup", $"Starting {ProjectName} v{Version}");
112+
24113
desktop.MainWindow = new MainWindow
25114
{
26-
DataContext = new MainWindowViewModel(),
115+
DataContext = new MainWindowViewModel()
27116
};
28117
}
29118

30119
base.OnFrameworkInitializationCompleted();
31120
}
32121

33-
private void DisableAvaloniaDataAnnotationValidation()
122+
private void OnUnhandledException(object? sender, UnhandledExceptionEventArgs e)
34123
{
35-
// Get an array of plugins to remove
36-
var dataValidationPluginsToRemove =
37-
BindingPlugins.DataValidators.OfType<DataAnnotationsValidationPlugin>().ToArray();
124+
if (e.ExceptionObject is Exception ex)
125+
FinalizeExceptionHandling(ex);
126+
}
38127

39-
// remove each entry found
40-
foreach (var plugin in dataValidationPluginsToRemove)
128+
private void OnUnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
129+
{
130+
e.SetObserved();
131+
FinalizeExceptionHandling(e.Exception);
132+
}
133+
134+
public static void FinalizeExceptionHandling(Exception ex)
135+
{
136+
if (_showingExceptionDialog)
137+
return;
138+
139+
_showingExceptionDialog = true;
140+
141+
Logger.WriteException("App::Fatal", ex);
142+
143+
Dispatcher.UIThread.Post(() =>
144+
{
145+
// TODO: replace with MessageBox.Avalonia dialog
146+
// Frontend.ShowExceptionDialog(ex);
147+
148+
Environment.Exit((int)ErrorCode.ERROR_INSTALL_FAILURE);
149+
});
150+
}
151+
152+
public static void Terminate(ErrorCode exitCode = ErrorCode.ERROR_SUCCESS)
153+
{
154+
Logger.WriteLine("App::Terminate", exitCode.ToString());
155+
Environment.Exit((int)exitCode);
156+
}
157+
158+
public static void SoftTerminate(ErrorCode exitCode = ErrorCode.ERROR_SUCCESS)
159+
{
160+
if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
161+
{
162+
desktop.Shutdown((int)exitCode);
163+
}
164+
else
41165
{
42-
BindingPlugins.DataValidators.Remove(plugin);
166+
Environment.Exit((int)exitCode);
43167
}
44168
}
45-
}
169+
}

Froststrap.AvaloniaUI/Bootstrapper.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
// - Launch Roblox (for testing web launches, run it from the command prompt)
66
// - To re-test the same executable, delete it from the installation folder
77

8+
// Brother why does this file have both core AND UI logic in it
9+
// TODO: Split this file into Core and UI parts
10+
811
// #define DEBUG_UPDATER
912

1013
#if DEBUG_UPDATER

Froststrap.AvaloniaUI/CookiesManager.cs

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
1-
using System.Security.Cryptography;
2-
1+
using System;
2+
using System.IO;
3+
using System.Net.Http;
4+
using System.Text;
5+
using System.Text.Json;
6+
using System.Text.RegularExpressions;
7+
using System.Threading.Tasks;
8+
9+
#if WINDOWS
10+
using System.Security.Cryptography;
11+
#endif
12+
13+
// TODO: Make Linux equivalent for reading Cookie (Sober puts your cookie in plain text so its not that hard)
314
namespace Froststrap
415
{
516
public class CookiesManager
@@ -16,6 +27,7 @@ public CookieState State
1627
StateChanged?.Invoke(this, value);
1728
}
1829
}
30+
1931
public bool Loaded => Enabled && State == CookieState.Success;
2032
private bool Enabled => App.Settings.Prop.AllowCookieAccess;
2133

@@ -28,56 +40,49 @@ public CookieState State
2840
public async Task<HttpResponseMessage> AuthRequest(HttpRequestMessage request)
2941
{
3042
string? host = request.RequestUri?.Host;
31-
3243
if (host is null)
3344
throw new ArgumentNullException("Host cannot be null");
3445

35-
if (
36-
!host.Equals("roblox.com", StringComparison.OrdinalIgnoreCase) &&
37-
!host.EndsWith(".roblox.com", StringComparison.OrdinalIgnoreCase)
38-
)
46+
if (!host.Equals("roblox.com", StringComparison.OrdinalIgnoreCase) &&
47+
!host.EndsWith(".roblox.com", StringComparison.OrdinalIgnoreCase))
3948
throw new HttpRequestException("Host must end with roblox.com");
4049

4150
if (!Enabled)
4251
throw new NullReferenceException("Cookie access is not enabled");
4352

4453
request.Headers.Add("Cookie", $".ROBLOSECURITY={AuthCookie}");
45-
var response = await App.HttpClient.SendAsync(request);
46-
47-
return response;
54+
return await App.HttpClient.SendAsync(request);
4855
}
4956

50-
public async Task<HttpResponseMessage> AuthGet(string uri) => await AuthRequest(new HttpRequestMessage { RequestUri = new Uri(uri), Method = HttpMethod.Get });
51-
public async Task<HttpResponseMessage> AuthPost(string uri, HttpContent? content) => await AuthRequest(new HttpRequestMessage { RequestUri = new Uri(uri), Content = content, Method = HttpMethod.Post });
57+
public async Task<HttpResponseMessage> AuthGet(string uri) =>
58+
await AuthRequest(new HttpRequestMessage { RequestUri = new Uri(uri), Method = HttpMethod.Get });
59+
60+
public async Task<HttpResponseMessage> AuthPost(string uri, HttpContent? content) =>
61+
await AuthRequest(new HttpRequestMessage { RequestUri = new Uri(uri), Content = content, Method = HttpMethod.Post });
5262

5363
public async Task<AuthenticatedUser?> GetAuthenticated()
5464
{
5565
const string LOG_IDENT = "CookiesManager::GetAuthenticated";
56-
5766
try
5867
{
5968
HttpResponseMessage response = await AuthGet("https://users.roblox.com/v1/users/authenticated");
6069
response.EnsureSuccessStatusCode();
6170

6271
string content = await response.Content.ReadAsStringAsync();
63-
AuthenticatedUser user = JsonSerializer.Deserialize<AuthenticatedUser>(content)!;
64-
65-
return user;
72+
return JsonSerializer.Deserialize<AuthenticatedUser>(content);
6673
}
6774
catch (HttpRequestException ex)
6875
{
6976
App.Logger.WriteLine(LOG_IDENT, "Failed to get authenticated user");
7077
App.Logger.WriteException(LOG_IDENT, ex);
7178
}
72-
7379
return null;
7480
}
7581

7682
public async Task LoadCookies()
7783
{
7884
const string LOG_IDENT = "CookiesManager::LoadCookies";
7985

80-
// we use the status to infrom user about it in the menu
8186
if (!Enabled)
8287
{
8388
State = CookieState.NotAllowed;
@@ -106,11 +111,13 @@ public async Task LoadCookies()
106111
if (cookies.Version != SupportedVersion)
107112
App.Logger.WriteLine(LOG_IDENT, $"Unknown cookie version: {cookies.Version}");
108113

109-
// here we got the raw bytes data which we have to decrypt with user scope
110-
// from that we get raw cookies data in roblox's format
111-
// in our case we will regex it since all we need is auth cookie
112114
byte[] encryptedData = Convert.FromBase64String(cookies.Cookies);
115+
116+
#if WINDOWS
113117
byte[] unencryptedData = ProtectedData.Unprotect(encryptedData, null, DataProtectionScope.CurrentUser);
118+
#else
119+
byte[] unencryptedData = Array.Empty<byte>();
120+
#endif
114121

115122
string rawCookies = Encoding.UTF8.GetString(unencryptedData);
116123
Match authCookieMatch = Regex.Match(rawCookies, AuthPattern);
@@ -122,12 +129,10 @@ public async Task LoadCookies()
122129
return;
123130
}
124131

125-
string authCookie = authCookieMatch.Groups[1].Value;
126-
AuthCookie = authCookie; // could use better naming
132+
AuthCookie = authCookieMatch.Groups[1].Value;
127133

128-
// we test the cookie to see if its valid
129134
AuthenticatedUser? user = await GetAuthenticated();
130-
if (user is null || user?.Id == 0)
135+
if (user is null || user.Id == 0)
131136
{
132137
State = CookieState.Invalid;
133138
App.Logger.WriteLine(LOG_IDENT, "Cookie is invalid");
@@ -140,11 +145,8 @@ public async Task LoadCookies()
140145
{
141146
App.Logger.WriteLine(LOG_IDENT, "Failed to load cookie!");
142147
App.Logger.WriteException(LOG_IDENT, ex);
143-
144148
State = CookieState.Failed;
145149
}
146-
147-
return;
148150
}
149151
}
150-
}
152+
}

Froststrap.AvaloniaUI/Froststrap.AvaloniaUI.csproj

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,38 @@
1212

1313
<!-- Folders for organization -->
1414
<ItemGroup>
15-
<Folder Include="Models\"/>
16-
<Folder Include="ViewModels\"/>
17-
<Folder Include="Views\"/>
15+
<Folder Include="Models\" />
16+
<Folder Include="ViewModels\" />
17+
<Folder Include="Views\" />
1818
</ItemGroup>
1919

2020
<!-- Resources needed by Avalonia -->
2121
<ItemGroup>
22-
<AvaloniaResource Include="Resources\Mods\Sounds\*.mp3"/>
23-
<AvaloniaResource Include="Resources\Mods\Cursor\**\*.*"/>
24-
<AvaloniaResource Include="Resources\PresetFlags\*"/>
25-
<AvaloniaResource Include="Resources\FroststrapPowerPlans\*.pow"/>
22+
<AvaloniaResource Include="Resources\Mods\Sounds\*.mp3" />
23+
<AvaloniaResource Include="Resources\Mods\Cursor\**\*.*" />
24+
<AvaloniaResource Include="Resources\PresetFlags\*" />
25+
<AvaloniaResource Include="Resources\FroststrapPowerPlans\*.pow" />
2626
</ItemGroup>
2727

2828
<!-- NuGet packages -->
2929
<ItemGroup>
30-
<PackageReference Include="Avalonia" Version="11.3.10"/>
31-
<PackageReference Include="Avalonia.Desktop" Version="11.3.10"/>
32-
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.10"/>
33-
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.3.10"/>
30+
<PackageReference Include="Avalonia" Version="11.3.10" />
31+
<PackageReference Include="Avalonia.Desktop" Version="11.3.10" />
32+
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.10" />
33+
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.3.10" />
3434
<PackageReference Include="Avalonia.Diagnostics" Version="11.3.10">
3535
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
3636
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
3737
</PackageReference>
3838

39-
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0"/>
40-
<PackageReference Include="Newtonsoft.Json" Version="13.0.4"/>
41-
<PackageReference Include="SharpZipLib" Version="1.4.2"/>
42-
<PackageReference Include="PuppeteerSharp" Version="20.2.4"/>
43-
<PackageReference Include="PuppeteerExtraSharp" Version="3.0.2"/>
44-
<PackageReference Include="securifybv.ShellLink" Version="0.1.0"/>
39+
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
40+
41+
<PackageReference Include="MessageBox.Avalonia" Version="3.3.1.1" />
42+
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
43+
<PackageReference Include="SharpZipLib" Version="1.4.2" />
44+
<PackageReference Include="PuppeteerSharp" Version="20.2.4" />
45+
<PackageReference Include="PuppeteerExtraSharp" Version="3.0.2" />
46+
<PackageReference Include="securifybv.ShellLink" Version="0.1.0" />
4547
</ItemGroup>
4648

4749
<!-- Shared logic project references -->

Froststrap.AvaloniaUI/Installer.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Windows;
33
using System.Xml.Linq;
44
using Froststrap.AppData;
5+
using Froststrap.AvaloniaUI;
56
using Microsoft.Win32;
67

78
namespace Froststrap

0 commit comments

Comments
 (0)