From a96ef132e89cda6f4ea699fffb9c451f2b066a50 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Tue, 11 Feb 2025 02:29:28 +0100
Subject: [PATCH 01/36] DirectConnectDialog
---
SS14.Launcher/Views/DirectConnectDialog.xaml | 2 +-
.../Views/DirectConnectDialog.xaml.cs | 33 +++++--------------
2 files changed, 10 insertions(+), 25 deletions(-)
diff --git a/SS14.Launcher/Views/DirectConnectDialog.xaml b/SS14.Launcher/Views/DirectConnectDialog.xaml
index 74af1f1e6..8d248ef34 100644
--- a/SS14.Launcher/Views/DirectConnectDialog.xaml
+++ b/SS14.Launcher/Views/DirectConnectDialog.xaml
@@ -16,7 +16,7 @@
Text="{loc:Loc direct-connect-text}" />
-
+
diff --git a/SS14.Launcher/Views/DirectConnectDialog.xaml.cs b/SS14.Launcher/Views/DirectConnectDialog.xaml.cs
index bcd339bed..b72db96bd 100644
--- a/SS14.Launcher/Views/DirectConnectDialog.xaml.cs
+++ b/SS14.Launcher/Views/DirectConnectDialog.xaml.cs
@@ -1,45 +1,30 @@
using System;
using System.Diagnostics.CodeAnalysis;
-using System.Reactive.Linq;
using Avalonia.Controls;
using Avalonia.Input;
-using ReactiveUI;
+using Avalonia.Interactivity;
namespace SS14.Launcher.Views;
public partial class DirectConnectDialog : Window
{
- private readonly TextBox _addressBox;
-
public DirectConnectDialog()
{
InitializeComponent();
- _addressBox = AddressBox;
- _addressBox.KeyDown += (_, args) =>
+ AddressBox.TextChanged += (_, _) =>
{
- if (args.Key == Key.Enter)
- {
- TrySubmit();
- }
+ var valid = IsAddressValid(AddressBox.Text);
+ InvalidLabel.IsVisible = !valid;
+ SubmitButton.IsEnabled = valid;
};
-
- SubmitButton.Command = ReactiveCommand.Create(TrySubmit);
-
- this.WhenAnyValue(x => x._addressBox.Text)
- .Select(IsAddressValid)
- .Subscribe(b =>
- {
- InvalidLabel.IsVisible = !b;
- SubmitButton.IsEnabled = b;
- });
}
protected override void OnOpened(EventArgs e)
{
base.OnOpened(e);
- _addressBox.Focus();
+ AddressBox.Focus();
}
protected override void OnKeyDown(KeyEventArgs e)
@@ -52,14 +37,14 @@ protected override void OnKeyDown(KeyEventArgs e)
base.OnKeyDown(e);
}
- private void TrySubmit()
+ private void TrySubmit(object? sender, RoutedEventArgs routedEventArgs)
{
- if (!IsAddressValid(_addressBox.Text))
+ if (!IsAddressValid(AddressBox.Text))
{
return;
}
- Close(_addressBox.Text.Trim());
+ Close(AddressBox.Text.Trim());
}
internal static bool IsAddressValid([NotNullWhen(true)] string? address)
From fe4811ee2162a3386c3a90942bcaf97658b40348 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Tue, 11 Feb 2025 02:32:48 +0100
Subject: [PATCH 02/36] Flip!!!
---
.../Views/MainWindowTabs/OptionsTabView.xaml | 2 +-
.../Views/MainWindowTabs/OptionsTabView.xaml.cs | 17 ++++++++---------
2 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/SS14.Launcher/Views/MainWindowTabs/OptionsTabView.xaml b/SS14.Launcher/Views/MainWindowTabs/OptionsTabView.xaml
index 1d12c675a..0e9015be6 100644
--- a/SS14.Launcher/Views/MainWindowTabs/OptionsTabView.xaml
+++ b/SS14.Launcher/Views/MainWindowTabs/OptionsTabView.xaml
@@ -14,7 +14,7 @@
-
+
-
+
From 0cf424259c64457ddd0d6a320f48e4f8257c0d5a Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Tue, 11 Feb 2025 04:28:46 +0100
Subject: [PATCH 05/36] DevelopmentTab
---
.../MainWindowTabs/DevelopmentTabViewModel.cs | 31 +++++++++----------
1 file changed, 15 insertions(+), 16 deletions(-)
diff --git a/SS14.Launcher/ViewModels/MainWindowTabs/DevelopmentTabViewModel.cs b/SS14.Launcher/ViewModels/MainWindowTabs/DevelopmentTabViewModel.cs
index 3d06d516a..afed7bed6 100644
--- a/SS14.Launcher/ViewModels/MainWindowTabs/DevelopmentTabViewModel.cs
+++ b/SS14.Launcher/ViewModels/MainWindowTabs/DevelopmentTabViewModel.cs
@@ -1,4 +1,4 @@
-using ReactiveUI;
+using System.ComponentModel;
using Splat;
using SS14.Launcher.Localization;
using SS14.Launcher.Models.Data;
@@ -9,50 +9,49 @@ namespace SS14.Launcher.ViewModels.MainWindowTabs;
public sealed class DevelopmentTabViewModel : MainWindowTabViewModel
{
private readonly LocalizationManager _loc = LocalizationManager.Instance;
- public DataManager Cfg { get; }
+ private readonly DataManager _cfg = Locator.Current.GetRequiredService();
public DevelopmentTabViewModel()
{
- Cfg = Locator.Current.GetRequiredService();
-
// TODO: This sucks and leaks.
- Cfg.GetCVarEntry(CVars.EngineOverrideEnabled).PropertyChanged += (sender, args) =>
+ _cfg.GetCVarEntry(CVars.EngineOverrideEnabled).PropertyChanged += (_, _) =>
{
- this.RaisePropertyChanged(nameof(Name));
+ OnPropertyChanged(new PropertyChangedEventArgs(nameof(Name)));
};
}
- public override string Name => Cfg.GetCVar(CVars.EngineOverrideEnabled)
+ public override string Name
+ => _cfg.GetCVar(CVars.EngineOverrideEnabled)
? _loc.GetString("tab-development-title-override")
: _loc.GetString("tab-development-title");
public bool DisableSigning
{
- get => Cfg.GetCVar(CVars.DisableSigning);
+ get => _cfg.GetCVar(CVars.DisableSigning);
set
{
- Cfg.SetCVar(CVars.DisableSigning, value);
- Cfg.CommitConfig();
+ _cfg.SetCVar(CVars.DisableSigning, value);
+ _cfg.CommitConfig();
}
}
public bool EngineOverrideEnabled
{
- get => Cfg.GetCVar(CVars.EngineOverrideEnabled);
+ get => _cfg.GetCVar(CVars.EngineOverrideEnabled);
set
{
- Cfg.SetCVar(CVars.EngineOverrideEnabled, value);
- Cfg.CommitConfig();
+ _cfg.SetCVar(CVars.EngineOverrideEnabled, value);
+ _cfg.CommitConfig();
}
}
public string EngineOverridePath
{
- get => Cfg.GetCVar(CVars.EngineOverridePath);
+ get => _cfg.GetCVar(CVars.EngineOverridePath);
set
{
- Cfg.SetCVar(CVars.EngineOverridePath, value);
- Cfg.CommitConfig();
+ _cfg.SetCVar(CVars.EngineOverridePath, value);
+ _cfg.CommitConfig();
}
}
}
From d180e59dbf2956bc01f203247e22f5f1e01e2580 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Tue, 11 Feb 2025 04:35:44 +0100
Subject: [PATCH 06/36] Replace some [Reactive] with [ObservableProperty]
---
.../ViewModels/MainWindowTabs/HomePageViewModel.cs | 7 +++----
.../ViewModels/MainWindowTabs/ServerListTabViewModel.cs | 6 +++---
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/SS14.Launcher/ViewModels/MainWindowTabs/HomePageViewModel.cs b/SS14.Launcher/ViewModels/MainWindowTabs/HomePageViewModel.cs
index 363c6aac5..826aa2774 100644
--- a/SS14.Launcher/ViewModels/MainWindowTabs/HomePageViewModel.cs
+++ b/SS14.Launcher/ViewModels/MainWindowTabs/HomePageViewModel.cs
@@ -1,5 +1,4 @@
using System;
-using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
@@ -7,7 +6,7 @@
using Avalonia.VisualTree;
using DynamicData;
using DynamicData.Alias;
-using ReactiveUI.Fody.Helpers;
+using Microsoft.Toolkit.Mvvm.ComponentModel;
using Splat;
using SS14.Launcher.Localization;
using SS14.Launcher.Models.Data;
@@ -17,7 +16,7 @@
namespace SS14.Launcher.ViewModels.MainWindowTabs;
-public class HomePageViewModel : MainWindowTabViewModel
+public partial class HomePageViewModel : MainWindowTabViewModel
{
public MainWindowViewModel MainWindowViewModel { get; }
private readonly DataManager _cfg;
@@ -60,7 +59,7 @@ public HomePageViewModel(MainWindowViewModel mainWindowViewModel)
public ReadOnlyObservableCollection Favorites { get; }
public ObservableCollection Suggestions { get; } = new();
- [Reactive] public bool FavoritesEmpty { get; private set; } = true;
+ [ObservableProperty] private bool _favoritesEmpty = true;
public override string Name => LocalizationManager.Instance.GetString("tab-home-title");
public Control? Control { get; set; }
diff --git a/SS14.Launcher/ViewModels/MainWindowTabs/ServerListTabViewModel.cs b/SS14.Launcher/ViewModels/MainWindowTabs/ServerListTabViewModel.cs
index 8d06e116a..293199820 100644
--- a/SS14.Launcher/ViewModels/MainWindowTabs/ServerListTabViewModel.cs
+++ b/SS14.Launcher/ViewModels/MainWindowTabs/ServerListTabViewModel.cs
@@ -2,8 +2,8 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
+using Microsoft.Toolkit.Mvvm.ComponentModel;
using ReactiveUI;
-using ReactiveUI.Fody.Helpers;
using Splat;
using SS14.Launcher.Localization;
using SS14.Launcher.Models.ServerStatus;
@@ -11,7 +11,7 @@
namespace SS14.Launcher.ViewModels.MainWindowTabs;
-public class ServerListTabViewModel : MainWindowTabViewModel
+public partial class ServerListTabViewModel : MainWindowTabViewModel
{
private readonly LocalizationManager _loc = LocalizationManager.Instance;
private readonly MainWindowViewModel _windowVm;
@@ -65,7 +65,7 @@ public string ListText
}
}
- [Reactive] public bool FiltersVisible { get; set; }
+ [ObservableProperty] private bool _filtersVisible;
public ServerListFiltersViewModel Filters { get; }
From 57fbb83bff6a3d4521cb8d130da831526d5f6b63 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Tue, 11 Feb 2025 18:27:23 +0100
Subject: [PATCH 07/36] Nuke in-launcher registration since it was unused
---
.../RegisterNeedsConfirmationViewModel.cs | 96 -------------
.../ViewModels/Login/RegisterViewModel.cs | 136 ------------------
.../ViewModels/MainWindowLoginViewModel.cs | 15 --
.../Login/RegisterNeedsConfirmationView.xaml | 27 ----
.../RegisterNeedsConfirmationView.xaml.cs | 12 --
SS14.Launcher/Views/Login/RegisterView.xaml | 40 ------
.../Views/Login/RegisterView.xaml.cs | 27 ----
7 files changed, 353 deletions(-)
delete mode 100644 SS14.Launcher/ViewModels/Login/RegisterNeedsConfirmationViewModel.cs
delete mode 100644 SS14.Launcher/ViewModels/Login/RegisterViewModel.cs
delete mode 100644 SS14.Launcher/Views/Login/RegisterNeedsConfirmationView.xaml
delete mode 100644 SS14.Launcher/Views/Login/RegisterNeedsConfirmationView.xaml.cs
delete mode 100644 SS14.Launcher/Views/Login/RegisterView.xaml
delete mode 100644 SS14.Launcher/Views/Login/RegisterView.xaml.cs
diff --git a/SS14.Launcher/ViewModels/Login/RegisterNeedsConfirmationViewModel.cs b/SS14.Launcher/ViewModels/Login/RegisterNeedsConfirmationViewModel.cs
deleted file mode 100644
index bcf1549ec..000000000
--- a/SS14.Launcher/ViewModels/Login/RegisterNeedsConfirmationViewModel.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-using System;
-using Avalonia.Threading;
-using ReactiveUI;
-using ReactiveUI.Fody.Helpers;
-using SS14.Launcher.Api;
-using SS14.Launcher.Localization;
-using SS14.Launcher.Models.Data;
-using SS14.Launcher.Models.Logins;
-
-namespace SS14.Launcher.ViewModels.Login;
-
-public class RegisterNeedsConfirmationViewModel : BaseLoginViewModel
-{
- private const int TimeoutSeconds = 5;
-
- private readonly AuthApi _authApi;
- private readonly LocalizationManager _loc = LocalizationManager.Instance;
-
- private readonly string _loginUsername;
- private readonly string _loginPassword;
- private readonly LoginManager _loginMgr;
- private readonly DataManager _dataManager;
-
- public bool ConfirmButtonEnabled => TimeoutSecondsLeft == 0;
-
- public string ConfirmButtonText
- {
- get
- {
- var text = _loc.GetString("login-confirmation-button-confirm");
- if (TimeoutSecondsLeft != 0)
- {
- text = $"{text} ({TimeoutSecondsLeft})";
- }
-
- return text;
- }
- }
-
- [Reactive] private int TimeoutSecondsLeft { get; set; }
-
- public RegisterNeedsConfirmationViewModel(
- MainWindowLoginViewModel parentVm,
- AuthApi authApi, string username, string password, LoginManager loginMgr, DataManager dataManager)
- : base(parentVm)
- {
- BusyText = _loc.GetString("login-confirmation-busy");
- _authApi = authApi;
-
- _loginUsername = username;
- _loginPassword = password;
- _loginMgr = loginMgr;
- _dataManager = dataManager;
-
- this.WhenAnyValue(p => p.TimeoutSecondsLeft)
- .Subscribe(_ =>
- {
- this.RaisePropertyChanged(nameof(ConfirmButtonText));
- this.RaisePropertyChanged(nameof(ConfirmButtonEnabled));
- });
- }
-
- public override void Activated()
- {
- TimeoutSecondsLeft = TimeoutSeconds;
- DispatcherTimer.Run(TimerTick, TimeSpan.FromSeconds(1));
- }
-
- private bool TimerTick()
- {
- TimeoutSecondsLeft -= 1;
- return TimeoutSecondsLeft != 0;
- }
-
- public async void ConfirmButtonPressed()
- {
- if (Busy)
- return;
-
- Busy = true;
-
- try
- {
- var request = new AuthApi.AuthenticateRequest(_loginUsername, _loginPassword);
- var resp = await _authApi.AuthenticateAsync(request);
-
- await LoginViewModel.DoLogin(this, request, resp, _loginMgr, _authApi);
-
- _dataManager.CommitConfig();
- }
- finally
- {
- Busy = false;
- }
- }
-}
diff --git a/SS14.Launcher/ViewModels/Login/RegisterViewModel.cs b/SS14.Launcher/ViewModels/Login/RegisterViewModel.cs
deleted file mode 100644
index 25d2aac8e..000000000
--- a/SS14.Launcher/ViewModels/Login/RegisterViewModel.cs
+++ /dev/null
@@ -1,136 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.Net.Mail;
-using ReactiveUI;
-using ReactiveUI.Fody.Helpers;
-using Robust.Shared.AuthLib;
-using SS14.Launcher.Api;
-using SS14.Launcher.Models.Data;
-using SS14.Launcher.Models.Logins;
-
-namespace SS14.Launcher.ViewModels.Login;
-
-public class RegisterViewModel : BaseLoginViewModel
-{
- private readonly DataManager _cfg;
- private readonly AuthApi _authApi;
- private readonly LoginManager _loginMgr;
-
- [Reactive] public string EditingUsername { get; set; } = "";
- [Reactive] public string EditingPassword { get; set; } = "";
- [Reactive] public string EditingPasswordConfirm { get; set; } = "";
- [Reactive] public string EditingEmail { get; set; } = "";
-
- [Reactive] public bool IsInputValid { get; private set; }
- [Reactive] public string InvalidReason { get; private set; } = " ";
-
- [Reactive] public bool Is13OrOlder { get; set; }
-
-
- public RegisterViewModel(MainWindowLoginViewModel parentVm, DataManager cfg, AuthApi authApi, LoginManager loginMgr)
- : base(parentVm)
- {
- _cfg = cfg;
- _authApi = authApi;
- _loginMgr = loginMgr;
-
- this.WhenAnyValue(x => x.EditingUsername, x => x.EditingPassword, x => x.EditingPasswordConfirm,
- x => x.EditingEmail, x => x.Is13OrOlder)
- .Subscribe(UpdateInputValid);
- }
-
- private void UpdateInputValid((string user, string pass, string passConfirm, string email, bool is13OrOlder) s)
- {
- var (user, pass, passConfirm, email, is13OrOlder) = s;
-
- IsInputValid = false;
- if (!UsernameHelpers.IsNameValid(user, out var reason))
- {
- InvalidReason = reason switch
- {
- UsernameHelpers.UsernameInvalidReason.Empty => "Username is empty",
- UsernameHelpers.UsernameInvalidReason.TooLong => "Username is too long",
- UsernameHelpers.UsernameInvalidReason.TooShort => "Username is too short",
- UsernameHelpers.UsernameInvalidReason.InvalidCharacter => "Username contains an invalid character",
- _ => "???"
- };
- return;
- }
-
- if (string.IsNullOrEmpty(email))
- {
- InvalidReason = "Email is empty";
- return;
- }
-
- if (!MailAddress.TryCreate(email, out _))
- {
- InvalidReason = "Email is invalid";
- return;
- }
-
- if (string.IsNullOrEmpty(pass))
- {
- InvalidReason = "Password is empty";
- return;
- }
-
- if (pass != passConfirm)
- {
- InvalidReason = "Confirm password does not match";
- return;
- }
-
- if (!is13OrOlder)
- {
- InvalidReason = "You must be 13 or older";
- return;
- }
-
- InvalidReason = " ";
- IsInputValid = true;
- }
-
- public async void OnRegisterInButtonPressed()
- {
- if (!IsInputValid || Busy)
- {
- return;
- }
-
- BusyText = "Registering account...";
- Busy = true;
- try
- {
- var result = await _authApi.RegisterAsync(EditingUsername, EditingEmail, EditingPassword);
- if (!result.IsSuccess)
- {
- OverlayControl = new AuthErrorsOverlayViewModel(this, "Unable to register", result.Errors);
- return;
- }
-
- var status = result.Status;
- if (status == RegisterResponseStatus.Registered)
- {
- BusyText = "Logging in...";
- // No confirmation needed, log in immediately.
- var request = new AuthApi.AuthenticateRequest(EditingUsername, EditingPassword);
- var resp = await _authApi.AuthenticateAsync(request);
-
- await LoginViewModel.DoLogin(this, request, resp, _loginMgr, _authApi);
-
- _cfg.CommitConfig();
- }
- else
- {
- Debug.Assert(status == RegisterResponseStatus.RegisteredNeedConfirmation);
-
- ParentVM.SwitchToRegisterNeedsConfirmation(EditingUsername, EditingPassword);
- }
- }
- finally
- {
- Busy = false;
- }
- }
-}
diff --git a/SS14.Launcher/ViewModels/MainWindowLoginViewModel.cs b/SS14.Launcher/ViewModels/MainWindowLoginViewModel.cs
index 4fe3dd9ce..a284fd81e 100644
--- a/SS14.Launcher/ViewModels/MainWindowLoginViewModel.cs
+++ b/SS14.Launcher/ViewModels/MainWindowLoginViewModel.cs
@@ -47,11 +47,6 @@ public void SwitchToExpiredLogin(LoggedInAccount account)
Screen = new ExpiredLoginViewModel(this, _cfg, _authApi, _loginMgr, account);
}
- public void SwitchToRegister()
- {
- Screen = new RegisterViewModel(this, _cfg, _authApi, _loginMgr);
- }
-
public void SwitchToForgotPassword()
{
Screen = new ForgotPasswordViewModel(this, _authApi);
@@ -62,16 +57,6 @@ public void SwitchToAuthTfa(AuthApi.AuthenticateRequest request)
Screen = new AuthTfaViewModel(this, request, _loginMgr, _authApi, _cfg);
}
- public void SwitchToResendConfirmation()
- {
- Screen = new ResendConfirmationViewModel(this, _authApi);
- }
-
- public void SwitchToRegisterNeedsConfirmation(string username, string password)
- {
- Screen = new RegisterNeedsConfirmationViewModel(this, _authApi, username, password, _loginMgr, _cfg);
- }
-
public bool LogLauncher
{
// This not a clean solution, replace it with something better.
diff --git a/SS14.Launcher/Views/Login/RegisterNeedsConfirmationView.xaml b/SS14.Launcher/Views/Login/RegisterNeedsConfirmationView.xaml
deleted file mode 100644
index c776f510f..000000000
--- a/SS14.Launcher/Views/Login/RegisterNeedsConfirmationView.xaml
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/SS14.Launcher/Views/Login/RegisterNeedsConfirmationView.xaml.cs b/SS14.Launcher/Views/Login/RegisterNeedsConfirmationView.xaml.cs
deleted file mode 100644
index 55b85eca5..000000000
--- a/SS14.Launcher/Views/Login/RegisterNeedsConfirmationView.xaml.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using Avalonia.Controls;
-using Avalonia.Markup.Xaml;
-
-namespace SS14.Launcher.Views.Login;
-
-public partial class RegisterNeedsConfirmationView : UserControl
-{
- public RegisterNeedsConfirmationView()
- {
- InitializeComponent();
- }
-}
diff --git a/SS14.Launcher/Views/Login/RegisterView.xaml b/SS14.Launcher/Views/Login/RegisterView.xaml
deleted file mode 100644
index 4871bc036..000000000
--- a/SS14.Launcher/Views/Login/RegisterView.xaml
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/SS14.Launcher/Views/Login/RegisterView.xaml.cs b/SS14.Launcher/Views/Login/RegisterView.xaml.cs
deleted file mode 100644
index b8a6c982a..000000000
--- a/SS14.Launcher/Views/Login/RegisterView.xaml.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using Avalonia.Controls;
-using Avalonia.Input;
-using Avalonia.Markup.Xaml;
-using SS14.Launcher.ViewModels.Login;
-
-namespace SS14.Launcher.Views.Login;
-
-public partial class RegisterView : UserControl
-{
- public RegisterView()
- {
- InitializeComponent();
-
- NameBox.KeyDown += OnTextBoxKeyDown;
- EmailBox.KeyDown += OnTextBoxKeyDown;
- PasswordBox.KeyDown += OnTextBoxKeyDown;
- PasswordConfirmBox.KeyDown += OnTextBoxKeyDown;
- }
-
- private void OnTextBoxKeyDown(object? sender, KeyEventArgs args)
- {
- if (args.Key == Key.Enter && DataContext is RegisterViewModel vm)
- {
- vm.OnRegisterInButtonPressed();
- }
- }
-}
From 6b1a5a92a86ad3c02153509101c220fc143f2dc3 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Tue, 11 Feb 2025 21:37:02 +0100
Subject: [PATCH 08/36] LoginView
---
.../ViewModels/Login/LoginViewModel.cs | 28 +++++++++++--------
SS14.Launcher/Views/Login/LoginView.xaml | 8 +++---
SS14.Launcher/Views/Login/LoginView.xaml.cs | 14 ++--------
3 files changed, 23 insertions(+), 27 deletions(-)
diff --git a/SS14.Launcher/ViewModels/Login/LoginViewModel.cs b/SS14.Launcher/ViewModels/Login/LoginViewModel.cs
index a5e7ce605..34be73ef1 100644
--- a/SS14.Launcher/ViewModels/Login/LoginViewModel.cs
+++ b/SS14.Launcher/ViewModels/Login/LoginViewModel.cs
@@ -1,7 +1,5 @@
-using System;
using System.Threading.Tasks;
-using ReactiveUI;
-using ReactiveUI.Fody.Helpers;
+using Microsoft.Toolkit.Mvvm.ComponentModel;
using SS14.Launcher.Api;
using SS14.Launcher.Localization;
using SS14.Launcher.Models.Data;
@@ -9,18 +7,16 @@
namespace SS14.Launcher.ViewModels.Login;
-public class LoginViewModel : BaseLoginViewModel
+public partial class LoginViewModel : BaseLoginViewModel
{
private readonly AuthApi _authApi;
private readonly LoginManager _loginMgr;
private readonly DataManager _dataManager;
private readonly LocalizationManager _loc = LocalizationManager.Instance;
- [Reactive] public string EditingUsername { get; set; } = "";
- [Reactive] public string EditingPassword { get; set; } = "";
-
- [Reactive] public bool IsInputValid { get; private set; }
- [Reactive] public bool IsPasswordVisible { get; set; }
+ [ObservableProperty] private string _username = "";
+ [ObservableProperty] private string _password = "";
+ [ObservableProperty] private bool _isInputValid;
public LoginViewModel(MainWindowLoginViewModel parentVm, AuthApi authApi,
LoginManager loginMgr, DataManager dataManager) : base(parentVm)
@@ -30,8 +26,16 @@ public LoginViewModel(MainWindowLoginViewModel parentVm, AuthApi authApi,
_loginMgr = loginMgr;
_dataManager = dataManager;
- this.WhenAnyValue(x => x.EditingUsername, x => x.EditingPassword)
- .Subscribe(s => { IsInputValid = !string.IsNullOrEmpty(s.Item1) && !string.IsNullOrEmpty(s.Item2); });
+ PropertyChanged += (_, e) =>
+ {
+ switch (e)
+ {
+ case { PropertyName: nameof(Username) }:
+ case { PropertyName: nameof(Password) }:
+ IsInputValid = !string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password);
+ break;
+ }
+ };
}
public async void OnLogInButtonPressed()
@@ -44,7 +48,7 @@ public async void OnLogInButtonPressed()
Busy = true;
try
{
- var request = new AuthApi.AuthenticateRequest(EditingUsername, EditingPassword);
+ var request = new AuthApi.AuthenticateRequest(Username, Password);
var resp = await _authApi.AuthenticateAsync(request);
await DoLogin(this, request, resp, _loginMgr, _authApi);
diff --git a/SS14.Launcher/Views/Login/LoginView.xaml b/SS14.Launcher/Views/Login/LoginView.xaml
index 20f78a466..4d588974e 100644
--- a/SS14.Launcher/Views/Login/LoginView.xaml
+++ b/SS14.Launcher/Views/Login/LoginView.xaml
@@ -16,19 +16,19 @@
+ Text="{Binding Username}" IsEnabled="{Binding !Busy}" />
+ Name="ShowPassword" IsCheckedChanged="ToggleShowPassword" Content="{loc:Loc login-login-show-password}" />
-
diff --git a/SS14.Launcher/Views/Login/LoginView.xaml.cs b/SS14.Launcher/Views/Login/LoginView.xaml.cs
index a8f10b366..c5db976dc 100644
--- a/SS14.Launcher/Views/Login/LoginView.xaml.cs
+++ b/SS14.Launcher/Views/Login/LoginView.xaml.cs
@@ -1,7 +1,5 @@
using Avalonia.Controls;
-using Avalonia.Input;
-using Avalonia.Markup.Xaml;
-using SS14.Launcher.ViewModels.Login;
+using Avalonia.Interactivity;
namespace SS14.Launcher.Views.Login;
@@ -10,16 +8,10 @@ public partial class LoginView : UserControl
public LoginView()
{
InitializeComponent();
-
- NameBox.KeyDown += InputBoxOnKeyDown;
- PasswordBox.KeyDown += InputBoxOnKeyDown;
}
- private void InputBoxOnKeyDown(object? sender, KeyEventArgs args)
+ private void ToggleShowPassword(object? sender, RoutedEventArgs e)
{
- if (args.Key == Key.Enter && DataContext is LoginViewModel vm)
- {
- vm.OnLogInButtonPressed();
- }
+ PasswordBox.RevealPassword = ShowPassword.IsChecked ?? false;
}
}
From 9389e0bb4089f1545338026689a2ddd6800fab7e Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Tue, 11 Feb 2025 21:54:31 +0100
Subject: [PATCH 09/36] ForgotPassword
---
.../Login/ForgotPasswordViewModel.cs | 27 ++++++-------------
.../Views/Login/ForgotPasswordView.xaml | 5 ++--
.../Views/Login/ForgotPasswordView.xaml.cs | 13 +--------
3 files changed, 11 insertions(+), 34 deletions(-)
diff --git a/SS14.Launcher/ViewModels/Login/ForgotPasswordViewModel.cs b/SS14.Launcher/ViewModels/Login/ForgotPasswordViewModel.cs
index 7ebe3ac28..9d27662fe 100644
--- a/SS14.Launcher/ViewModels/Login/ForgotPasswordViewModel.cs
+++ b/SS14.Launcher/ViewModels/Login/ForgotPasswordViewModel.cs
@@ -1,26 +1,16 @@
-using ReactiveUI.Fody.Helpers;
+using Microsoft.Toolkit.Mvvm.ComponentModel;
using SS14.Launcher.Api;
using SS14.Launcher.Localization;
namespace SS14.Launcher.ViewModels.Login;
-public sealed class ForgotPasswordViewModel : BaseLoginViewModel
+public sealed partial class ForgotPasswordViewModel(MainWindowLoginViewModel parentVM, AuthApi authApi)
+ : BaseLoginViewModel(parentVM)
{
- private readonly AuthApi _authApi;
private readonly LocalizationManager _loc = LocalizationManager.Instance;
-
- [Reactive] public string EditingEmail { get; set; } = "";
-
+ [ObservableProperty] private string _email = "";
private bool _errored;
- public ForgotPasswordViewModel(
- MainWindowLoginViewModel parentVM,
- AuthApi authApi)
- : base(parentVM)
- {
- _authApi = authApi;
- }
-
public async void SubmitPressed()
{
if (Busy)
@@ -30,17 +20,16 @@ public async void SubmitPressed()
try
{
BusyText = "Sending email...";
- var errors = await _authApi.ForgotPasswordAsync(EditingEmail);
+ var errors = await authApi.ForgotPasswordAsync(Email);
_errored = errors != null;
if (!_errored)
{
// This isn't an error lol but that's what I called the control.
- OverlayControl = new AuthErrorsOverlayViewModel(this, _loc.GetString("login-forgot-success-title"), new[]
- {
- _loc.GetString("login-forgot-success-message")
- });
+ OverlayControl = new AuthErrorsOverlayViewModel(this, _loc.GetString("login-forgot-success-title"), [
+ _loc.GetString("login-forgot-success-message"),
+ ]);
}
else
{
diff --git a/SS14.Launcher/Views/Login/ForgotPasswordView.xaml b/SS14.Launcher/Views/Login/ForgotPasswordView.xaml
index caf824f37..46d0148fb 100644
--- a/SS14.Launcher/Views/Login/ForgotPasswordView.xaml
+++ b/SS14.Launcher/Views/Login/ForgotPasswordView.xaml
@@ -19,11 +19,10 @@
Text="{loc:Loc login-forgot-message}" />
+ Text="{Binding Email}" Name="EmailBox" />
+ Command="{Binding SubmitPressed}" IsDefault="True" Name="SubmitButton" />
diff --git a/SS14.Launcher/Views/Login/ForgotPasswordView.xaml.cs b/SS14.Launcher/Views/Login/ForgotPasswordView.xaml.cs
index 40be1701f..f481a8e4c 100644
--- a/SS14.Launcher/Views/Login/ForgotPasswordView.xaml.cs
+++ b/SS14.Launcher/Views/Login/ForgotPasswordView.xaml.cs
@@ -1,7 +1,4 @@
using Avalonia.Controls;
-using Avalonia.Input;
-using Avalonia.Markup.Xaml;
-using SS14.Launcher.ViewModels.Login;
namespace SS14.Launcher.Views.Login;
@@ -11,14 +8,6 @@ public ForgotPasswordView()
{
InitializeComponent();
- EmailBox.KeyDown += InputBoxOnKeyDown;
- }
-
- private void InputBoxOnKeyDown(object? sender, KeyEventArgs args)
- {
- if (args.Key == Key.Enter && DataContext is ForgotPasswordViewModel vm)
- {
- vm.SubmitPressed();
- }
+ EmailBox.TextChanged += (_, _) => SubmitButton.IsEnabled = EmailBox.Text?.Contains('@') ?? false;
}
}
From 7f6d9fd4a2f899d9114a4c6e32b01b44ab976670 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Tue, 11 Feb 2025 23:26:14 +0100
Subject: [PATCH 10/36] MainWindow
---
.../ViewModels/Login/LoginViewModel.cs | 6 +-
.../ViewModels/MainWindowViewModel.cs | 76 ++++++++-----------
2 files changed, 36 insertions(+), 46 deletions(-)
diff --git a/SS14.Launcher/ViewModels/Login/LoginViewModel.cs b/SS14.Launcher/ViewModels/Login/LoginViewModel.cs
index 34be73ef1..768ecda45 100644
--- a/SS14.Launcher/ViewModels/Login/LoginViewModel.cs
+++ b/SS14.Launcher/ViewModels/Login/LoginViewModel.cs
@@ -28,10 +28,10 @@ public LoginViewModel(MainWindowLoginViewModel parentVm, AuthApi authApi,
PropertyChanged += (_, e) =>
{
- switch (e)
+ switch (e.PropertyName)
{
- case { PropertyName: nameof(Username) }:
- case { PropertyName: nameof(Password) }:
+ case nameof(Username):
+ case nameof(Password):
IsInputValid = !string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password);
break;
}
diff --git a/SS14.Launcher/ViewModels/MainWindowViewModel.cs b/SS14.Launcher/ViewModels/MainWindowViewModel.cs
index 82f9cb612..bbb1fdf4d 100644
--- a/SS14.Launcher/ViewModels/MainWindowViewModel.cs
+++ b/SS14.Launcher/ViewModels/MainWindowViewModel.cs
@@ -1,14 +1,13 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Net.Http;
-using System.Reactive.Linq;
using System.Threading.Tasks;
using Avalonia.Platform.Storage;
using DynamicData;
-using ReactiveUI;
-using ReactiveUI.Fody.Helpers;
+using Microsoft.Toolkit.Mvvm.ComponentModel;
using Serilog;
using Splat;
using SS14.Launcher.Api;
@@ -23,18 +22,17 @@
namespace SS14.Launcher.ViewModels;
-public sealed class MainWindowViewModel : ViewModelBase, IErrorOverlayOwner
+public sealed partial class MainWindowViewModel : ViewModelBase, IErrorOverlayOwner
{
private readonly DataManager _cfg;
private readonly LoginManager _loginMgr;
- private readonly HttpClient _http;
private readonly LauncherInfoManager _infoManager;
private readonly LocalizationManager _loc;
private int _selectedIndex;
public DataManager Cfg => _cfg;
- [Reactive] public bool OutOfDate { get; private set; }
+ [ObservableProperty] private bool _outOfDate;
public HomePageViewModel HomeTab { get; }
public ServerListTabViewModel ServersTab { get; }
@@ -45,7 +43,6 @@ public MainWindowViewModel()
{
_cfg = Locator.Current.GetRequiredService();
_loginMgr = Locator.Current.GetRequiredService();
- _http = Locator.Current.GetRequiredService();
_infoManager = Locator.Current.GetRequiredService();
_loc = LocalizationManager.Instance;
@@ -54,45 +51,34 @@ public MainWindowViewModel()
HomeTab = new HomePageViewModel(this);
OptionsTab = new OptionsTabViewModel();
- var tabs = new List();
- tabs.Add(HomeTab);
- tabs.Add(ServersTab);
- tabs.Add(NewsTab);
- tabs.Add(OptionsTab);
+ Tabs = new List
+ {
+ HomeTab,
+ ServersTab,
+ NewsTab,
+ OptionsTab,
#if DEVELOPMENT
- tabs.Add(new DevelopmentTabViewModel());
+ new DevelopmentTabViewModel(),
#endif
- Tabs = tabs;
+ };
AccountDropDown = new AccountDropDownViewModel(this);
LoginViewModel = new MainWindowLoginViewModel();
- this.WhenAnyValue(x => x._loginMgr.ActiveAccount)
- .Subscribe(s =>
- {
- this.RaisePropertyChanged(nameof(Username));
- this.RaisePropertyChanged(nameof(LoggedIn));
- });
+ PropertyChanged += (_, e) =>
+ {
+ if (e.PropertyName is nameof(LoggedIn) && LoggedIn)
+ RunSelectedOnTab();
+ };
- _cfg.Logins.Connect()
- .Subscribe(_ => { this.RaisePropertyChanged(nameof(AccountDropDownVisible)); });
+ _loginMgr.PropertyChanged += (_, e) =>
+ {
+ if (e.PropertyName is nameof(_loginMgr.ActiveAccount))
+ OnPropertyChanged(new PropertyChangedEventArgs(nameof(LoggedIn)));
+ };
- // If we leave the login view model (by an account getting selected)
- // we reset it to login state
- this.WhenAnyValue(x => x.LoggedIn)
- .DistinctUntilChanged() // Only when change.
- .Subscribe(x =>
- {
- if (x)
- {
- // "Switch" to main window.
- RunSelectedOnTab();
- }
- else
- {
- LoginViewModel.SwitchToLogin();
- }
- });
+ _cfg.Logins.Connect()
+ .Subscribe(_ => OnPropertyChanged(new PropertyChangedEventArgs(nameof(AccountDropDownVisible))));
}
public MainWindow? Control { get; set; }
@@ -100,17 +86,16 @@ public MainWindowViewModel()
public IReadOnlyList Tabs { get; }
public bool LoggedIn => _loginMgr.ActiveAccount != null;
- private string? Username => _loginMgr.ActiveAccount?.Username;
public bool AccountDropDownVisible => _loginMgr.Logins.Count != 0;
public AccountDropDownViewModel AccountDropDown { get; }
public MainWindowLoginViewModel LoginViewModel { get; }
- [Reactive] public ConnectingViewModel? ConnectingVM { get; set; }
+ [ObservableProperty] private ConnectingViewModel? _connectingVM;
- [Reactive] public string? BusyTask { get; private set; }
- [Reactive] public ViewModelBase? OverlayViewModel { get; private set; }
+ [ObservableProperty] private string? _busyTask;
+ [ObservableProperty] private ViewModelBase? _overlayViewModel;
public int SelectedIndex
{
@@ -120,7 +105,12 @@ public int SelectedIndex
var previous = Tabs[_selectedIndex];
previous.IsSelected = false;
- this.RaiseAndSetIfChanged(ref _selectedIndex, value);
+ if (!EqualityComparer.Default.Equals(_selectedIndex, value))
+ {
+ OnPropertyChanging(new PropertyChangingEventArgs(nameof(SelectedIndex)));
+ _selectedIndex = value;
+ OnPropertyChanged(new PropertyChangedEventArgs(nameof(SelectedIndex)));
+ }
RunSelectedOnTab();
}
From 79c1ecf8b2c4ef56f8db678e36dd2d2ec324c840 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Tue, 11 Feb 2025 23:56:12 +0100
Subject: [PATCH 11/36] LoginInfo
---
SS14.Launcher/Models/Data/LoginInfo.cs | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/SS14.Launcher/Models/Data/LoginInfo.cs b/SS14.Launcher/Models/Data/LoginInfo.cs
index ccd43f5bc..7f39b6f31 100644
--- a/SS14.Launcher/Models/Data/LoginInfo.cs
+++ b/SS14.Launcher/Models/Data/LoginInfo.cs
@@ -1,17 +1,13 @@
using System;
-using ReactiveUI;
-using ReactiveUI.Fody.Helpers;
+using Microsoft.Toolkit.Mvvm.ComponentModel;
namespace SS14.Launcher.Models.Data;
-public class LoginInfo : ReactiveObject
+public partial class LoginInfo : ObservableObject
{
- [Reactive]
- public Guid UserId { get; set; }
- [Reactive]
- public string Username { get; set; } = default!;
- [Reactive]
- public LoginToken Token { get; set; }
+ public Guid UserId;
+ public string? Username;
+ [ObservableProperty] private LoginToken _token;
public override string ToString()
{
From f185c309dba2cbf20cdd3a9a7f22faf98d8f93f3 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Wed, 12 Feb 2025 00:01:18 +0100
Subject: [PATCH 12/36] BaseLoginViewModel
---
.../ViewModels/Login/BaseLoginViewModel.cs | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
diff --git a/SS14.Launcher/ViewModels/Login/BaseLoginViewModel.cs b/SS14.Launcher/ViewModels/Login/BaseLoginViewModel.cs
index 1d4c817d3..15d5dbd13 100644
--- a/SS14.Launcher/ViewModels/Login/BaseLoginViewModel.cs
+++ b/SS14.Launcher/ViewModels/Login/BaseLoginViewModel.cs
@@ -1,22 +1,16 @@
-using ReactiveUI.Fody.Helpers;
+using Microsoft.Toolkit.Mvvm.ComponentModel;
namespace SS14.Launcher.ViewModels.Login;
-public abstract class BaseLoginViewModel : ViewModelBase, IErrorOverlayOwner
+public abstract partial class BaseLoginViewModel(MainWindowLoginViewModel parentVM) : ViewModelBase, IErrorOverlayOwner
{
- [Reactive] public bool Busy { get; protected set; }
- [Reactive] public string? BusyText { get; protected set; }
- [Reactive] public ViewModelBase? OverlayControl { get; set; }
- public MainWindowLoginViewModel ParentVM { get; }
-
- protected BaseLoginViewModel(MainWindowLoginViewModel parentVM)
- {
- ParentVM = parentVM;
- }
+ [ObservableProperty] private bool _busy;
+ [ObservableProperty] private string? _busyText;
+ [ObservableProperty] private ViewModelBase? _overlayControl;
+ public MainWindowLoginViewModel ParentVM { get; } = parentVM;
public virtual void Activated()
{
-
}
public virtual void OverlayOk()
From dbce1bd93d050e8f5dcbc56fd47cdbb590f0e73a Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Wed, 12 Feb 2025 00:11:31 +0100
Subject: [PATCH 13/36] ExpiredLogin
---
.../ViewModels/Login/ExpiredLoginViewModel.cs | 44 +++++++------------
.../Views/Login/ExpiredLoginView.xaml | 4 +-
2 files changed, 18 insertions(+), 30 deletions(-)
diff --git a/SS14.Launcher/ViewModels/Login/ExpiredLoginViewModel.cs b/SS14.Launcher/ViewModels/Login/ExpiredLoginViewModel.cs
index 19e0e0c39..6b9c3466f 100644
--- a/SS14.Launcher/ViewModels/Login/ExpiredLoginViewModel.cs
+++ b/SS14.Launcher/ViewModels/Login/ExpiredLoginViewModel.cs
@@ -1,32 +1,20 @@
-using ReactiveUI.Fody.Helpers;
+using Microsoft.Toolkit.Mvvm.ComponentModel;
using SS14.Launcher.Api;
using SS14.Launcher.Models.Data;
using SS14.Launcher.Models.Logins;
namespace SS14.Launcher.ViewModels.Login;
-public class ExpiredLoginViewModel : BaseLoginViewModel
+public partial class ExpiredLoginViewModel (
+ MainWindowLoginViewModel parentVm,
+ DataManager cfg,
+ AuthApi authApi,
+ LoginManager loginMgr,
+ LoggedInAccount account)
+ : BaseLoginViewModel(parentVm)
{
- private readonly DataManager _cfg;
- private readonly AuthApi _authApi;
- private readonly LoginManager _loginMgr;
-
- public ExpiredLoginViewModel(
- MainWindowLoginViewModel parentVm,
- DataManager cfg,
- AuthApi authApi,
- LoginManager loginMgr,
- LoggedInAccount account)
- : base(parentVm)
- {
- _cfg = cfg;
- _authApi = authApi;
- _loginMgr = loginMgr;
- Account = account;
- }
-
- [Reactive] public string EditingPassword { get; set; } = "";
- public LoggedInAccount Account { get; }
+ [ObservableProperty] private string _password = "";
+ public LoggedInAccount Account { get; } = account;
public async void OnLogInButtonPressed()
{
@@ -36,12 +24,12 @@ public async void OnLogInButtonPressed()
Busy = true;
try
{
- var request = new AuthApi.AuthenticateRequest(Account.UserId, EditingPassword);
- var resp = await _authApi.AuthenticateAsync(request);
+ var request = new AuthApi.AuthenticateRequest(Account.UserId, Password);
+ var resp = await authApi.AuthenticateAsync(request);
- await LoginViewModel.DoLogin(this, request, resp, _loginMgr, _authApi);
+ await LoginViewModel.DoLogin(this, request, resp, loginMgr, authApi);
- _cfg.CommitConfig();
+ cfg.CommitConfig();
}
finally
{
@@ -51,8 +39,8 @@ public async void OnLogInButtonPressed()
public void OnLogOutButtonPressed()
{
- _cfg.RemoveLogin(Account.LoginInfo);
- _cfg.CommitConfig();
+ cfg.RemoveLogin(Account.LoginInfo);
+ cfg.CommitConfig();
ParentVM.SwitchToLogin();
}
diff --git a/SS14.Launcher/Views/Login/ExpiredLoginView.xaml b/SS14.Launcher/Views/Login/ExpiredLoginView.xaml
index d0a587f2d..4b08ef1f3 100644
--- a/SS14.Launcher/Views/Login/ExpiredLoginView.xaml
+++ b/SS14.Launcher/Views/Login/ExpiredLoginView.xaml
@@ -21,12 +21,12 @@
Text="{Binding Account.Username}" IsEnabled="False" />
+ Text="{Binding Password}" PasswordChar="•" />
+ IsEnabled="{Binding Password, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" />
From dcf087c478fbd614dc972881db2a3cd39a961b7e Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Thu, 13 Feb 2025 14:22:49 +0100
Subject: [PATCH 14/36] AuthTfa
---
.../ViewModels/Login/AuthTfaViewModel.cs | 21 ++++++++++---------
SS14.Launcher/Views/Login/AuthTfaView.xaml | 4 ++--
SS14.Launcher/Views/Login/AuthTfaView.xaml.cs | 10 ---------
3 files changed, 13 insertions(+), 22 deletions(-)
diff --git a/SS14.Launcher/ViewModels/Login/AuthTfaViewModel.cs b/SS14.Launcher/ViewModels/Login/AuthTfaViewModel.cs
index 294f90c7d..221744d12 100644
--- a/SS14.Launcher/ViewModels/Login/AuthTfaViewModel.cs
+++ b/SS14.Launcher/ViewModels/Login/AuthTfaViewModel.cs
@@ -1,22 +1,20 @@
using System;
-using ReactiveUI;
-using ReactiveUI.Fody.Helpers;
+using Microsoft.Toolkit.Mvvm.ComponentModel;
using SS14.Launcher.Api;
using SS14.Launcher.Models.Data;
using SS14.Launcher.Models.Logins;
namespace SS14.Launcher.ViewModels.Login;
-public sealed class AuthTfaViewModel : BaseLoginViewModel
+public sealed partial class AuthTfaViewModel : BaseLoginViewModel
{
private readonly AuthApi.AuthenticateRequest _request;
private readonly LoginManager _loginMgr;
private readonly AuthApi _authApi;
private readonly DataManager _cfg;
- [Reactive] public string Code { get; set; } = "";
-
- [Reactive] public bool IsInputValid { get; private set; }
+ [ObservableProperty] private string _code = "";
+ [ObservableProperty] private bool _isInputValid;
public AuthTfaViewModel(
MainWindowLoginViewModel parentVm,
@@ -30,13 +28,16 @@ public AuthTfaViewModel(
_authApi = authApi;
_cfg = cfg;
- this.WhenAnyValue(x => x.Code)
- .Subscribe(s => { IsInputValid = CheckInputValid(s); });
+ PropertyChanged += (_, e) =>
+ {
+ if (e.PropertyName is nameof(Code))
+ IsInputValid = CheckInputValid();
+ };
}
- private static bool CheckInputValid(string code)
+ private bool CheckInputValid()
{
- var trimmed = code.AsSpan().Trim();
+ var trimmed = Code.AsSpan().Trim();
if (trimmed.Length != 6)
return false;
diff --git a/SS14.Launcher/Views/Login/AuthTfaView.xaml b/SS14.Launcher/Views/Login/AuthTfaView.xaml
index 0e7e9d73a..fff78e809 100644
--- a/SS14.Launcher/Views/Login/AuthTfaView.xaml
+++ b/SS14.Launcher/Views/Login/AuthTfaView.xaml
@@ -18,10 +18,10 @@
+ Text="{Binding Code}" IsEnabled="{Binding !Busy}" />
-
diff --git a/SS14.Launcher/Views/Login/AuthTfaView.xaml.cs b/SS14.Launcher/Views/Login/AuthTfaView.xaml.cs
index a2d593e19..ad928c9c9 100644
--- a/SS14.Launcher/Views/Login/AuthTfaView.xaml.cs
+++ b/SS14.Launcher/Views/Login/AuthTfaView.xaml.cs
@@ -9,15 +9,5 @@ public sealed partial class AuthTfaView : UserControl
public AuthTfaView()
{
InitializeComponent();
-
- CodeBox.KeyDown += InputBoxOnKeyDown;
- }
-
- private void InputBoxOnKeyDown(object? sender, KeyEventArgs e)
- {
- if (e.Key == Key.Enter && DataContext is AuthTfaViewModel vm && vm.IsInputValid)
- {
- vm.ConfirmTfa();
- }
}
}
From 9eee95b4c1b80aef6e69e6276de32ef3b0b63fb3 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Thu, 13 Feb 2025 14:32:55 +0100
Subject: [PATCH 15/36] Remove ResendConfirmation
---
.../Login/ResendConfirmationViewModel.cs | 63 -------------------
.../Views/Login/ExpiredLoginView.xaml | 3 +-
.../Views/Login/ResendConfirmationView.xaml | 31 ---------
.../Login/ResendConfirmationView.xaml.cs | 24 -------
4 files changed, 2 insertions(+), 119 deletions(-)
delete mode 100644 SS14.Launcher/ViewModels/Login/ResendConfirmationViewModel.cs
delete mode 100644 SS14.Launcher/Views/Login/ResendConfirmationView.xaml
delete mode 100644 SS14.Launcher/Views/Login/ResendConfirmationView.xaml.cs
diff --git a/SS14.Launcher/ViewModels/Login/ResendConfirmationViewModel.cs b/SS14.Launcher/ViewModels/Login/ResendConfirmationViewModel.cs
deleted file mode 100644
index 1c04a7567..000000000
--- a/SS14.Launcher/ViewModels/Login/ResendConfirmationViewModel.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-using ReactiveUI.Fody.Helpers;
-using SS14.Launcher.Api;
-
-namespace SS14.Launcher.ViewModels.Login;
-
-public class ResendConfirmationViewModel : BaseLoginViewModel
-{
- private readonly AuthApi _authApi;
-
- [Reactive] public string EditingEmail { get; set; } = "";
-
- private bool _errored;
-
- public ResendConfirmationViewModel(MainWindowLoginViewModel parentVM, AuthApi authApi) : base(parentVM)
- {
- _authApi = authApi;
- }
-
- public async void SubmitPressed()
- {
- if (Busy)
- return;
-
- Busy = true;
- try
- {
- BusyText = "Resending email...";
- var errors = await _authApi.ResendConfirmationAsync(EditingEmail);
-
- _errored = errors != null;
-
- if (!_errored)
- {
- // This isn't an error lol but that's what I called the control.
- OverlayControl = new AuthErrorsOverlayViewModel(this, "Confirmation email sent", new []
- {
- "A confirmation email has been sent to your email address."
- });
- }
- else
- {
- OverlayControl = new AuthErrorsOverlayViewModel(this, "Error", errors!);
- }
- }
- finally
- {
- Busy = false;
- }
- }
-
- public override void OverlayOk()
- {
- if (_errored)
- {
- base.OverlayOk();
- }
- else
- {
- // If the overlay was a success overlay, switch back to login.
- ParentVM.SwitchToLogin();
- }
- }
-}
diff --git a/SS14.Launcher/Views/Login/ExpiredLoginView.xaml b/SS14.Launcher/Views/Login/ExpiredLoginView.xaml
index 4b08ef1f3..c38529644 100644
--- a/SS14.Launcher/Views/Login/ExpiredLoginView.xaml
+++ b/SS14.Launcher/Views/Login/ExpiredLoginView.xaml
@@ -26,7 +26,8 @@
+ IsEnabled="{Binding Password, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
+ IsDefault="True" />
diff --git a/SS14.Launcher/Views/Login/ResendConfirmationView.xaml b/SS14.Launcher/Views/Login/ResendConfirmationView.xaml
deleted file mode 100644
index cbc558649..000000000
--- a/SS14.Launcher/Views/Login/ResendConfirmationView.xaml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/SS14.Launcher/Views/Login/ResendConfirmationView.xaml.cs b/SS14.Launcher/Views/Login/ResendConfirmationView.xaml.cs
deleted file mode 100644
index 8f72d6387..000000000
--- a/SS14.Launcher/Views/Login/ResendConfirmationView.xaml.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using Avalonia.Controls;
-using Avalonia.Input;
-using Avalonia.Markup.Xaml;
-using SS14.Launcher.ViewModels.Login;
-
-namespace SS14.Launcher.Views.Login;
-
-public sealed partial class ResendConfirmationView : UserControl
-{
- public ResendConfirmationView()
- {
- InitializeComponent();
-
- EmailBox.KeyDown += InputBoxOnKeyDown;
- }
-
- private void InputBoxOnKeyDown(object? sender, KeyEventArgs args)
- {
- if (args.Key == Key.Enter && DataContext is ResendConfirmationViewModel vm)
- {
- vm.SubmitPressed();
- }
- }
-}
From 988b21f91d0961435ac6363e5f305c5e46f61348 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Fri, 14 Feb 2025 16:46:55 +0100
Subject: [PATCH 16/36] LoggedInAccount
---
SS14.Launcher/Models/Logins/LoggedInAccount.cs | 6 +++---
SS14.Launcher/ViewModels/MainWindowViewModel.cs | 4 ++--
SS14.Launcher/ViewModels/ViewModelBase.cs | 3 +++
3 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/SS14.Launcher/Models/Logins/LoggedInAccount.cs b/SS14.Launcher/Models/Logins/LoggedInAccount.cs
index c5724116a..2ba0861e3 100644
--- a/SS14.Launcher/Models/Logins/LoggedInAccount.cs
+++ b/SS14.Launcher/Models/Logins/LoggedInAccount.cs
@@ -1,10 +1,10 @@
using System;
-using ReactiveUI;
+using Microsoft.Toolkit.Mvvm.ComponentModel;
using SS14.Launcher.Models.Data;
namespace SS14.Launcher.Models.Logins;
-public abstract class LoggedInAccount : ReactiveObject
+public abstract class LoggedInAccount : ObservableObject
{
public string Username => LoginInfo.Username;
public Guid UserId => LoginInfo.UserId;
@@ -17,4 +17,4 @@ protected LoggedInAccount(LoginInfo loginInfo)
public LoginInfo LoginInfo { get; }
public abstract AccountLoginStatus Status { get; }
-}
\ No newline at end of file
+}
diff --git a/SS14.Launcher/ViewModels/MainWindowViewModel.cs b/SS14.Launcher/ViewModels/MainWindowViewModel.cs
index bbb1fdf4d..64d590a8f 100644
--- a/SS14.Launcher/ViewModels/MainWindowViewModel.cs
+++ b/SS14.Launcher/ViewModels/MainWindowViewModel.cs
@@ -107,9 +107,9 @@ public int SelectedIndex
if (!EqualityComparer.Default.Equals(_selectedIndex, value))
{
- OnPropertyChanging(new PropertyChangingEventArgs(nameof(SelectedIndex)));
+ OnPropertyChanging(nameof(SelectedIndex));
_selectedIndex = value;
- OnPropertyChanged(new PropertyChangedEventArgs(nameof(SelectedIndex)));
+ OnPropertyChanged(nameof(SelectedIndex));
}
RunSelectedOnTab();
diff --git a/SS14.Launcher/ViewModels/ViewModelBase.cs b/SS14.Launcher/ViewModels/ViewModelBase.cs
index 44868dc4f..3f9bbeda8 100644
--- a/SS14.Launcher/ViewModels/ViewModelBase.cs
+++ b/SS14.Launcher/ViewModels/ViewModelBase.cs
@@ -7,6 +7,9 @@ public class ViewModelBase : ReactiveObject, IViewModelBase
{
protected void OnPropertyChanged(PropertyChangedEventArgs e) => this.RaisePropertyChanged(e.PropertyName);
protected void OnPropertyChanging(PropertyChangingEventArgs e) => this.RaisePropertyChanging(e.PropertyName);
+
+ protected void OnPropertyChanged(string name) => this.RaisePropertyChanged(name);
+ protected void OnPropertyChanging(string name) => this.RaisePropertyChanging(name);
}
///
From 80e7177fc097cf653fd5b43711dc62ec033df50d Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Fri, 14 Feb 2025 17:04:06 +0100
Subject: [PATCH 17/36] nvm
---
SS14.Launcher/Models/Logins/LoggedInAccount.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/SS14.Launcher/Models/Logins/LoggedInAccount.cs b/SS14.Launcher/Models/Logins/LoggedInAccount.cs
index 2ba0861e3..07b486292 100644
--- a/SS14.Launcher/Models/Logins/LoggedInAccount.cs
+++ b/SS14.Launcher/Models/Logins/LoggedInAccount.cs
@@ -1,10 +1,10 @@
using System;
-using Microsoft.Toolkit.Mvvm.ComponentModel;
+using ReactiveUI;
using SS14.Launcher.Models.Data;
namespace SS14.Launcher.Models.Logins;
-public abstract class LoggedInAccount : ObservableObject
+public abstract class LoggedInAccount : ReactiveObject
{
public string Username => LoginInfo.Username;
public Guid UserId => LoginInfo.UserId;
From df24aac6a8c81532659c1978c6284dbfa06775f0 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Fri, 14 Feb 2025 17:04:27 +0100
Subject: [PATCH 18/36] MainWindowLogin
---
SS14.Launcher/ViewModels/MainWindowLoginViewModel.cs | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/SS14.Launcher/ViewModels/MainWindowLoginViewModel.cs b/SS14.Launcher/ViewModels/MainWindowLoginViewModel.cs
index a284fd81e..9b7f0c609 100644
--- a/SS14.Launcher/ViewModels/MainWindowLoginViewModel.cs
+++ b/SS14.Launcher/ViewModels/MainWindowLoginViewModel.cs
@@ -1,4 +1,3 @@
-using ReactiveUI;
using Splat;
using SS14.Launcher.Api;
using SS14.Launcher.Models.Data;
@@ -22,7 +21,13 @@ public BaseLoginViewModel Screen
get => _screen;
set
{
- this.RaiseAndSetIfChanged(ref _screen, value);
+ if (_screen == value)
+ return;
+
+ OnPropertyChanging(nameof(Screen));
+ _screen = value;
+ OnPropertyChanged(nameof(Screen));
+
value.Activated();
}
}
From 11295745c2240b3566baa28be5295ac59a743fee Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Fri, 14 Feb 2025 17:10:25 +0100
Subject: [PATCH 19/36] ServerListTab
---
.../MainWindowTabs/ServerListTabViewModel.cs | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/SS14.Launcher/ViewModels/MainWindowTabs/ServerListTabViewModel.cs b/SS14.Launcher/ViewModels/MainWindowTabs/ServerListTabViewModel.cs
index 293199820..aa41e95ea 100644
--- a/SS14.Launcher/ViewModels/MainWindowTabs/ServerListTabViewModel.cs
+++ b/SS14.Launcher/ViewModels/MainWindowTabs/ServerListTabViewModel.cs
@@ -3,7 +3,6 @@
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using Microsoft.Toolkit.Mvvm.ComponentModel;
-using ReactiveUI;
using Splat;
using SS14.Launcher.Localization;
using SS14.Launcher.Models.ServerStatus;
@@ -28,7 +27,13 @@ public string? SearchString
get => _searchString;
set
{
- this.RaiseAndSetIfChanged(ref _searchString, value);
+ if (_searchString == value)
+ return;
+
+ OnPropertyChanging(nameof(SearchString));
+ _searchString = value;
+ OnPropertyChanged(nameof(SearchString));
+
UpdateSearchedList();
}
}
@@ -84,9 +89,9 @@ public ServerListTabViewModel(MainWindowViewModel windowVm)
switch (args.PropertyName)
{
case nameof(ServerListCache.Status):
- this.RaisePropertyChanged(nameof(ListText));
- this.RaisePropertyChanged(nameof(ListTextVisible));
- this.RaisePropertyChanged(nameof(SpinnerVisible));
+ OnPropertyChanged(nameof(ListText));
+ OnPropertyChanged(nameof(ListTextVisible));
+ OnPropertyChanged(nameof(SpinnerVisible));
break;
}
};
From 9bbb336c1435830fd09d27192db5c7cfb1f14f8d Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Fri, 14 Feb 2025 17:30:25 +0100
Subject: [PATCH 20/36] FavoriteServer
---
SS14.Launcher/Models/Data/FavoriteServer.cs | 41 +++++----------------
1 file changed, 10 insertions(+), 31 deletions(-)
diff --git a/SS14.Launcher/Models/Data/FavoriteServer.cs b/SS14.Launcher/Models/Data/FavoriteServer.cs
index eca1fa16a..8e69b63dd 100644
--- a/SS14.Launcher/Models/Data/FavoriteServer.cs
+++ b/SS14.Launcher/Models/Data/FavoriteServer.cs
@@ -1,19 +1,19 @@
using System;
-using System.Text.Json.Serialization;
-using ReactiveUI;
+using Microsoft.Toolkit.Mvvm.ComponentModel;
namespace SS14.Launcher.Models.Data;
-public sealed class FavoriteServer : ReactiveObject
+public sealed partial class FavoriteServer : ObservableObject
{
- private string? _name;
- private DateTimeOffset _raiseTime;
+ public readonly string? Name;
- // For serialization.
- public FavoriteServer()
- {
- Address = default!;
- }
+ public readonly string Address;
+
+ ///
+ /// Used to infer an exact ordering for servers in a simple, compatible manner.
+ /// Defaults to 0, this is fine.
+ ///
+ [ObservableProperty] private DateTimeOffset _raiseTime;
public FavoriteServer(string? name, string address)
{
@@ -27,25 +27,4 @@ public FavoriteServer(string? name, string address, DateTimeOffset raiseTime)
Address = address;
RaiseTime = raiseTime;
}
-
- [JsonPropertyName("name")]
- public string? Name
- {
- get => _name;
- set => this.RaiseAndSetIfChanged(ref _name, value);
- }
-
- [JsonPropertyName("address")]
- public string Address { get; private set; } // Need private set for JSON.NET to work.
-
- ///
- /// Used to infer an exact ordering for servers in a simple, compatible manner.
- /// Defaults to 0, this is fine.
- /// This isn't saved in JSON because the launcher apparently doesn't use JSON for these anymore.
- ///
- public DateTimeOffset RaiseTime
- {
- get => _raiseTime;
- set => this.RaiseAndSetIfChanged(ref _raiseTime, value);
- }
}
From 315454c29807295aefbec654ae3895e184867bd6 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Fri, 14 Feb 2025 17:35:50 +0100
Subject: [PATCH 21/36] ServerListCache
---
.../Models/ServerStatus/ServerListCache.cs | 18 +++++-------------
1 file changed, 5 insertions(+), 13 deletions(-)
diff --git a/SS14.Launcher/Models/ServerStatus/ServerListCache.cs b/SS14.Launcher/Models/ServerStatus/ServerListCache.cs
index 1b43efc31..64c2a2600 100644
--- a/SS14.Launcher/Models/ServerStatus/ServerListCache.cs
+++ b/SS14.Launcher/Models/ServerStatus/ServerListCache.cs
@@ -5,11 +5,10 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.Toolkit.Mvvm.ComponentModel;
using Serilog;
using Splat;
using SS14.Launcher.Utility;
-using ReactiveUI;
-using ReactiveUI.Fody.Helpers;
using SS14.Launcher.Api;
using SS14.Launcher.Models.Data;
using static SS14.Launcher.Api.HubApi;
@@ -19,24 +18,17 @@ namespace SS14.Launcher.Models.ServerStatus;
///
/// Caches the Hub's server list.
///
-public sealed class ServerListCache : ReactiveObject, IServerSource
+public sealed partial class ServerListCache : ObservableObject, IServerSource
{
- private readonly HubApi _hubApi;
- private readonly DataManager _dataManager;
+ private readonly HubApi _hubApi = Locator.Current.GetRequiredService();
+ private readonly DataManager _dataManager = Locator.Current.GetRequiredService();
private CancellationTokenSource? _refreshCancel;
public ObservableCollection AllServers => _allServers;
private readonly ServerListCollection _allServers = new();
- [Reactive]
- public RefreshListStatus Status { get; private set; } = RefreshListStatus.NotUpdated;
-
- public ServerListCache()
- {
- _hubApi = Locator.Current.GetRequiredService();
- _dataManager = Locator.Current.GetRequiredService();
- }
+ [ObservableProperty] private RefreshListStatus _status = RefreshListStatus.NotUpdated;
///
/// This function requests the initial update from the server if one hasn't already been requested.
From c655b2d8c67c1ab848cd777d4dc230f5f3de76a2 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Fri, 14 Feb 2025 17:38:09 +0100
Subject: [PATCH 22/36] DataManager
---
SS14.Launcher/Models/Data/DataManager.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/SS14.Launcher/Models/Data/DataManager.cs b/SS14.Launcher/Models/Data/DataManager.cs
index 4e62ce933..7f5f26eaf 100644
--- a/SS14.Launcher/Models/Data/DataManager.cs
+++ b/SS14.Launcher/Models/Data/DataManager.cs
@@ -13,8 +13,8 @@
using DynamicData;
using JetBrains.Annotations;
using Microsoft.Data.Sqlite;
+using Microsoft.Toolkit.Mvvm.ComponentModel;
using Microsoft.Toolkit.Mvvm.Messaging;
-using ReactiveUI;
using Serilog;
using SS14.Launcher.Utility;
@@ -37,7 +37,7 @@ public interface ICVarEntry : INotifyPropertyChanged
/// All data is stored in an SQLite DB. Simple config variables are stored K/V in a single table.
/// More complex things like logins is stored in individual tables.
///
-public sealed class DataManager : ReactiveObject
+public sealed class DataManager : ObservableObject
{
private delegate void DbCommand(SqliteConnection connection);
From 963bcc04407b8d5c8e2b1fb0acd06b4bc090cd49 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Fri, 14 Feb 2025 17:48:12 +0100
Subject: [PATCH 23/36] Connector
---
SS14.Launcher/Models/Connector.cs | 53 ++++++++-----------------------
1 file changed, 13 insertions(+), 40 deletions(-)
diff --git a/SS14.Launcher/Models/Connector.cs b/SS14.Launcher/Models/Connector.cs
index f26645565..25dcbca63 100644
--- a/SS14.Launcher/Models/Connector.cs
+++ b/SS14.Launcher/Models/Connector.cs
@@ -13,7 +13,7 @@
using System.Threading.Tasks;
using Avalonia.Platform.Storage;
using DynamicData;
-using ReactiveUI;
+using Microsoft.Toolkit.Mvvm.ComponentModel;
using Serilog;
using Splat;
using SS14.Launcher.Models.Data;
@@ -27,48 +27,21 @@ namespace SS14.Launcher.Models;
/// Responsible for actually launching the game.
/// Either by connecting to a game server, or by launching a local content bundle.
///
-public class Connector : ReactiveObject
+public partial class Connector : ObservableObject
{
- private readonly Updater _updater;
- private readonly DataManager _cfg;
- private readonly LoginManager _loginManager;
- private readonly IEngineManager _engineManager;
+ private readonly Updater _updater = Locator.Current.GetRequiredService();
+ private readonly DataManager _cfg = Locator.Current.GetRequiredService();
+ private readonly LoginManager _loginManager = Locator.Current.GetRequiredService();
+ private readonly IEngineManager _engineManager = Locator.Current.GetRequiredService();
- private ConnectionStatus _status = ConnectionStatus.None;
- private bool _clientExitedBadly;
- private readonly HttpClient _http;
+ private readonly HttpClient _http = Locator.Current.GetRequiredService();
private TaskCompletionSource? _acceptPrivacyPolicyTcs;
- private ServerPrivacyPolicyInfo? _serverPrivacyPolicyInfo;
- private bool _privacyPolicyDifferentVersion;
- public Connector()
- {
- _updater = Locator.Current.GetRequiredService();
- _cfg = Locator.Current.GetRequiredService();
- _loginManager = Locator.Current.GetRequiredService();
- _engineManager = Locator.Current.GetRequiredService();
- _http = Locator.Current.GetRequiredService();
- }
-
- public ConnectionStatus Status
- {
- get => _status;
- private set => this.RaiseAndSetIfChanged(ref _status, value);
- }
-
- public bool ClientExitedBadly
- {
- get => _clientExitedBadly;
- private set => this.RaiseAndSetIfChanged(ref _clientExitedBadly, value);
- }
-
- public ServerPrivacyPolicyInfo? PrivacyPolicyInfo => _serverPrivacyPolicyInfo;
- public bool PrivacyPolicyDifferentVersion
- {
- get => _privacyPolicyDifferentVersion;
- private set => this.RaiseAndSetIfChanged(ref _privacyPolicyDifferentVersion, value);
- }
+ [ObservableProperty] private ConnectionStatus _status = ConnectionStatus.None;
+ [ObservableProperty] private bool _clientExitedBadly;
+ [ObservableProperty] private bool _privacyPolicyDifferentVersion;
+ public ServerPrivacyPolicyInfo? PrivacyPolicyInfo { get; private set; }
public async void Connect(string address, CancellationToken cancel = default)
{
@@ -168,7 +141,7 @@ private async Task HandlePrivacyPolicyAsync(ServerInfo info, CancellationToken c
// Ask user for privacy policy acceptance by waiting here.
Log.Debug("Prompting user for privacy policy acceptance: {Identifer} version {Version}", identifier, version);
- _serverPrivacyPolicyInfo = info.PrivacyPolicy;
+ PrivacyPolicyInfo = info.PrivacyPolicy;
_acceptPrivacyPolicyTcs = new TaskCompletionSource();
Status = ConnectionStatus.AwaitingPrivacyPolicyAcceptance;
@@ -203,7 +176,7 @@ public void ConfirmPrivacyPolicy(PrivacyPolicyAcceptResult result)
private void Cleanup()
{
- _serverPrivacyPolicyInfo = null;
+ PrivacyPolicyInfo = null;
_acceptPrivacyPolicyTcs = null;
PrivacyPolicyDifferentVersion = default;
}
From 76119a9d159b243fc858b45503d932357a2dcbc1 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Fri, 14 Feb 2025 19:16:17 +0100
Subject: [PATCH 24/36] Connecting
---
.../ViewModels/ConnectingViewModel.cs | 174 ++++++++----------
1 file changed, 78 insertions(+), 96 deletions(-)
diff --git a/SS14.Launcher/ViewModels/ConnectingViewModel.cs b/SS14.Launcher/ViewModels/ConnectingViewModel.cs
index 9036838fa..b102362f2 100644
--- a/SS14.Launcher/ViewModels/ConnectingViewModel.cs
+++ b/SS14.Launcher/ViewModels/ConnectingViewModel.cs
@@ -1,12 +1,11 @@
using System;
-using System.Reactive.Linq;
using System.Threading;
using Avalonia.Platform.Storage;
-using ReactiveUI;
using Splat;
using SS14.Launcher.Localization;
using SS14.Launcher.Models;
using SS14.Launcher.Utility;
+using static SS14.Launcher.Models.Connector.ConnectionStatus;
namespace SS14.Launcher.ViewModels;
@@ -22,16 +21,11 @@ public class ConnectingViewModel : ViewModelBase
private string? _reasonSuffix;
- private Connector.ConnectionStatus _connectorStatus;
- private Updater.UpdateStatus _updaterStatus;
- private (long downloaded, long total, Updater.ProgressUnit unit)? _updaterProgress;
- private long? _updaterSpeed;
-
- public bool IsErrored => _connectorStatus == Connector.ConnectionStatus.ConnectionFailed ||
- _connectorStatus == Connector.ConnectionStatus.UpdateError ||
- _connectorStatus == Connector.ConnectionStatus.NotAContentBundle ||
- _connectorStatus == Connector.ConnectionStatus.ClientExited &&
- _connector.ClientExitedBadly;
+ public bool IsErrored
+ => _connector.Status == ConnectionFailed ||
+ _connector.Status == UpdateError ||
+ _connector.Status == NotAContentBundle ||
+ _connector is { Status: ClientExited, ClientExitedBadly: true };
public static event Action? StartedConnecting;
@@ -44,81 +38,67 @@ public ConnectingViewModel(Connector connector, MainWindowViewModel windowVm, st
_connectionType = connectionType;
_reasonSuffix = (givenReason != null) ? ("\n" + givenReason) : "";
- this.WhenAnyValue(x => x._updater.Progress)
- .ObserveOn(RxApp.MainThreadScheduler)
- .Subscribe(progress =>
- {
- _updaterProgress = progress;
-
- this.RaisePropertyChanged(nameof(Progress));
- this.RaisePropertyChanged(nameof(ProgressIndeterminate));
- this.RaisePropertyChanged(nameof(ProgressText));
- });
-
- this.WhenAnyValue(x => x._updater.Speed)
- .ObserveOn(RxApp.MainThreadScheduler)
- .Subscribe(speed =>
- {
- _updaterSpeed = speed;
-
- this.RaisePropertyChanged(nameof(SpeedText));
- this.RaisePropertyChanged(nameof(SpeedIndeterminate));
- });
-
- this.WhenAnyValue(x => x._updater.Status)
- .ObserveOn(RxApp.MainThreadScheduler)
- .Subscribe(status =>
- {
- _updaterStatus = status;
- this.RaisePropertyChanged(nameof(StatusText));
- });
-
- this.WhenAnyValue(x => x._connector.Status)
- .ObserveOn(RxApp.MainThreadScheduler)
- .Subscribe(val =>
- {
- _connectorStatus = val;
-
- this.RaisePropertyChanged(nameof(ProgressIndeterminate));
- this.RaisePropertyChanged(nameof(StatusText));
- this.RaisePropertyChanged(nameof(ProgressBarVisible));
- this.RaisePropertyChanged(nameof(IsErrored));
- this.RaisePropertyChanged(nameof(IsAskingPrivacyPolicy));
-
- if (val == Connector.ConnectionStatus.ClientRunning
- || val == Connector.ConnectionStatus.Cancelled
- || val == Connector.ConnectionStatus.ClientExited && !_connector.ClientExitedBadly)
- {
- CloseOverlay();
- }
- });
-
- this.WhenAnyValue(x => x._connector.PrivacyPolicyDifferentVersion)
- .ObserveOn(RxApp.MainThreadScheduler)
- .Subscribe(_ =>
+ _updater.PropertyChanged += (_, e) =>
+ {
+ switch (e.PropertyName)
{
- this.RaisePropertyChanged(nameof(PrivacyPolicyText));
- });
+ case nameof(_updater.Progress):
+ OnPropertyChanged(nameof(Progress));
+ OnPropertyChanged(nameof(ProgressIndeterminate));
+ OnPropertyChanged(nameof(ProgressText));
+ break;
+
+ case nameof(_updater.Speed):
+ OnPropertyChanged(nameof(SpeedText));
+ OnPropertyChanged(nameof(SpeedIndeterminate));
+ break;
+
+ case nameof(_updater.Status):
+ OnPropertyChanged(nameof(StatusText));
+ break;
+ }
+ };
- this.WhenAnyValue(x => x._connector.ClientExitedBadly)
- .ObserveOn(RxApp.MainThreadScheduler)
- .Subscribe(_ =>
+ _connector.PropertyChanged += (_, e) =>
+ {
+ switch (e.PropertyName)
{
- this.RaisePropertyChanged(nameof(StatusText));
- this.RaisePropertyChanged(nameof(IsErrored));
- });
+ case nameof(_connector.Status):
+ OnPropertyChanged(nameof(ProgressIndeterminate));
+ OnPropertyChanged(nameof(StatusText));
+ OnPropertyChanged(nameof(ProgressBarVisible));
+ OnPropertyChanged(nameof(IsErrored));
+ OnPropertyChanged(nameof(IsAskingPrivacyPolicy));
+
+ if (_connector.Status == ClientRunning
+ || _connector.Status == Cancelled
+ || _connector is { Status: ClientExited, ClientExitedBadly: false })
+ {
+ CloseOverlay();
+ }
+
+ break;
+ case nameof(_connector.PrivacyPolicyDifferentVersion):
+ OnPropertyChanged(nameof(PrivacyPolicyText));
+ break;
+ case nameof(_connector.ClientExitedBadly):
+ OnPropertyChanged(nameof(StatusText));
+ OnPropertyChanged(nameof(IsErrored));
+ break;
+ }
+ };
}
public float Progress
{
get
{
- if (_updaterProgress == null)
+ if (_updater.Progress == null)
{
return 0;
}
- var (downloaded, total, _) = _updaterProgress.Value;
+ var (downloaded, total, _) = _updater.Progress.Value;
return downloaded / (float)total;
}
@@ -128,12 +108,12 @@ public string ProgressText
{
get
{
- if (_updaterProgress == null)
+ if (_updater.Progress == null)
{
return "";
}
- var (downloaded, total, unit) = _updaterProgress.Value;
+ var (downloaded, total, unit) = _updater.Progress.Value;
return unit switch
{
@@ -143,34 +123,36 @@ public string ProgressText
}
}
- public bool ProgressIndeterminate => _connectorStatus != Connector.ConnectionStatus.Updating
- || _updaterProgress == null;
+ public bool ProgressIndeterminate
+ => _connector.Status != Updating
+ || _updater.Progress == null;
- public bool ProgressBarVisible => _connectorStatus != Connector.ConnectionStatus.ClientExited &&
- _connectorStatus != Connector.ConnectionStatus.ClientRunning &&
- _connectorStatus != Connector.ConnectionStatus.ConnectionFailed &&
- _connectorStatus != Connector.ConnectionStatus.UpdateError &&
- _connectorStatus != Connector.ConnectionStatus.NotAContentBundle;
+ public bool ProgressBarVisible
+ => _connector.Status != ClientExited &&
+ _connector.Status != ClientRunning &&
+ _connector.Status != ConnectionFailed &&
+ _connector.Status != UpdateError &&
+ _connector.Status != NotAContentBundle;
- public bool SpeedIndeterminate => _connectorStatus != Connector.ConnectionStatus.Updating || _updaterSpeed == null;
+ public bool SpeedIndeterminate => _connector.Status != Updating || _updater.Speed == null;
public string SpeedText
{
get
{
- if (_updaterSpeed is not { } speed)
+ if (_updater.Speed is not { } speed)
return "";
return $"{Helpers.FormatBytes(speed)}/s";
}
}
- public string StatusText =>
- _connectorStatus switch
+ public string StatusText
+ => _connector.Status switch
{
- Connector.ConnectionStatus.None => _loc.GetString("connecting-status-none") + _reasonSuffix,
- Connector.ConnectionStatus.UpdateError => _loc.GetString("connecting-status-update-error"),
- Connector.ConnectionStatus.Updating => _loc.GetString("connecting-status-updating", ("status", _loc.GetString(_updaterStatus switch
+ None => _loc.GetString("connecting-status-none") + _reasonSuffix,
+ UpdateError => _loc.GetString("connecting-status-update-error"),
+ Updating => _loc.GetString("connecting-status-updating", ("status", _loc.GetString(_updater.Status switch
{
Updater.UpdateStatus.CheckingClientUpdate => "connecting-update-status-checking-client-update",
Updater.UpdateStatus.DownloadingEngineVersion => "connecting-update-status-downloading-engine",
@@ -187,11 +169,11 @@ public string SpeedText
Updater.UpdateStatus.LoadingContentBundle => "connecting-update-status-loading-content-bundle",
_ => "connecting-update-status-unknown"
}))) + _reasonSuffix,
- Connector.ConnectionStatus.Connecting => _loc.GetString("connecting-status-connecting") + _reasonSuffix,
- Connector.ConnectionStatus.ConnectionFailed => _loc.GetString("connecting-status-connection-failed"),
- Connector.ConnectionStatus.StartingClient => _loc.GetString("connecting-status-starting-client") + _reasonSuffix,
- Connector.ConnectionStatus.NotAContentBundle => _loc.GetString("connecting-status-not-a-content-bundle"),
- Connector.ConnectionStatus.ClientExited => _connector.ClientExitedBadly
+ Connecting => _loc.GetString("connecting-status-connecting") + _reasonSuffix,
+ ConnectionFailed => _loc.GetString("connecting-status-connection-failed"),
+ StartingClient => _loc.GetString("connecting-status-starting-client") + _reasonSuffix,
+ NotAContentBundle => _loc.GetString("connecting-status-not-a-content-bundle"),
+ ClientExited => _connector.ClientExitedBadly
? _loc.GetString("connecting-status-client-crashed")
: "",
_ => ""
@@ -204,7 +186,7 @@ public string SpeedText
_ => ""
};
- public bool IsAskingPrivacyPolicy => _connectorStatus == Connector.ConnectionStatus.AwaitingPrivacyPolicyAcceptance;
+ public bool IsAskingPrivacyPolicy => _connector.Status == AwaitingPrivacyPolicyAcceptance;
public string PrivacyPolicyText => _connector.PrivacyPolicyDifferentVersion
? _loc.GetString("connecting-privacy-policy-text-version-changed")
From 1a6acbb8843f828e993851c727b14ed209662a23 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Fri, 14 Feb 2025 21:04:02 +0100
Subject: [PATCH 25/36] Updater
---
SS14.Launcher/Models/Updater.cs | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/SS14.Launcher/Models/Updater.cs b/SS14.Launcher/Models/Updater.cs
index 50d6b963f..8d726a2b7 100644
--- a/SS14.Launcher/Models/Updater.cs
+++ b/SS14.Launcher/Models/Updater.cs
@@ -18,8 +18,7 @@
using Avalonia.Threading;
using Dapper;
using Microsoft.Data.Sqlite;
-using ReactiveUI;
-using ReactiveUI.Fody.Helpers;
+using Microsoft.Toolkit.Mvvm.ComponentModel;
using Serilog;
using SharpZstd.Interop;
using SpaceWizards.Sodium;
@@ -35,7 +34,7 @@
namespace SS14.Launcher.Models;
-public sealed class Updater : ReactiveObject
+public sealed partial class Updater : ObservableObject
{
private const int ManifestDownloadProtocolVersion = 1;
@@ -61,9 +60,9 @@ public Updater()
}
// Note: these get updated from different threads. Observe responsibly.
- [Reactive] public UpdateStatus Status { get; private set; }
- [Reactive] public (long downloaded, long total, ProgressUnit unit)? Progress { get; private set; }
- [Reactive] public long? Speed { get; private set; }
+ [ObservableProperty] private UpdateStatus _status;
+ [ObservableProperty] private (long downloaded, long total, ProgressUnit unit)? _progress;
+ [ObservableProperty] private long? _speed;
public async Task RunUpdateForLaunchAsync(
ServerBuildInformation buildInformation,
From 61fa674552e76b785b8208decc346e59496bc761 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Fri, 14 Feb 2025 21:04:16 +0100
Subject: [PATCH 26/36] LoginManager
---
.../Models/Logins/LoggedInAccount.cs | 4 ++--
SS14.Launcher/Models/Logins/LoginManager.cs | 22 ++++++++++++++-----
2 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/SS14.Launcher/Models/Logins/LoggedInAccount.cs b/SS14.Launcher/Models/Logins/LoggedInAccount.cs
index 07b486292..2ba0861e3 100644
--- a/SS14.Launcher/Models/Logins/LoggedInAccount.cs
+++ b/SS14.Launcher/Models/Logins/LoggedInAccount.cs
@@ -1,10 +1,10 @@
using System;
-using ReactiveUI;
+using Microsoft.Toolkit.Mvvm.ComponentModel;
using SS14.Launcher.Models.Data;
namespace SS14.Launcher.Models.Logins;
-public abstract class LoggedInAccount : ReactiveObject
+public abstract class LoggedInAccount : ObservableObject
{
public string Username => LoginInfo.Username;
public Guid UserId => LoginInfo.UserId;
diff --git a/SS14.Launcher/Models/Logins/LoginManager.cs b/SS14.Launcher/Models/Logins/LoginManager.cs
index 963c5b52a..c6f382959 100644
--- a/SS14.Launcher/Models/Logins/LoginManager.cs
+++ b/SS14.Launcher/Models/Logins/LoginManager.cs
@@ -1,10 +1,9 @@
using System;
-using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Threading;
using DynamicData;
-using ReactiveUI;
+using Microsoft.Toolkit.Mvvm.ComponentModel;
using Serilog;
using SS14.Launcher.Api;
using SS14.Launcher.Models.Data;
@@ -13,7 +12,7 @@ namespace SS14.Launcher.Models.Logins;
// This is different from DataManager in that this class actually manages logic more complex than raw storage.
// Checking and refreshing tokens, marking accounts as "need signing in again", etc...
-public sealed class LoginManager : ReactiveObject
+public sealed class LoginManager : ObservableObject
{
// TODO: If the user tries to connect to a server or such
// on the split second interval that the launcher does a token refresh
@@ -46,8 +45,14 @@ public Guid? ActiveAccountId
}
}
- this.RaiseAndSetIfChanged(ref _activeLoginId, value);
- this.RaisePropertyChanged(nameof(ActiveAccount));
+ if (_activeLoginId != value)
+ {
+ OnPropertyChanging();
+ _activeLoginId = value;
+ OnPropertyChanged();
+ }
+
+ OnPropertyChanged(nameof(ActiveAccount));
_cfg.SelectedLoginId = value;
}
}
@@ -203,7 +208,12 @@ public ActiveLoginData(LoginInfo info) : base(info)
public void SetStatus(AccountLoginStatus status)
{
- this.RaiseAndSetIfChanged(ref _status, status, nameof(Status));
+ if (_status == status)
+ return;
+
+ OnPropertyChanging(nameof(Status));
+ _status = status;
+ OnPropertyChanged(nameof(Status));
Log.Debug("Setting status for login {account} to {status}", LoginInfo, status);
}
}
From 2718a0317ace4c2e926b9ca008a8473c550def18 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Mon, 17 Feb 2025 18:23:23 +0100
Subject: [PATCH 27/36] Add ObservableList, which is just ObservableCollection
with appropriate range operations
---
SS14.Launcher/Utility/ObservableList.cs | 62 +++++++++++++++++++++++++
1 file changed, 62 insertions(+)
create mode 100644 SS14.Launcher/Utility/ObservableList.cs
diff --git a/SS14.Launcher/Utility/ObservableList.cs b/SS14.Launcher/Utility/ObservableList.cs
new file mode 100644
index 000000000..3ec4703f5
--- /dev/null
+++ b/SS14.Launcher/Utility/ObservableList.cs
@@ -0,0 +1,62 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+
+namespace SS14.Launcher.Utility;
+
+///
+/// Represents a dynamic data collection that provides notifications when items get added or removed, or when the whole
+/// list is refreshed.
+///
+/// Unlike , also exposes range operations. These
+/// only trigger events once per range operation.
+///
+/// The type of elements in the collection.
+public class ObservableList : ObservableCollection
+{
+ ///
+ /// Initializes a new instance of the class that contains elements copied from the
+ /// specified collection.
+ ///
+ /// The collection from which the elements are copied.
+ public ObservableList(IEnumerable collection) : base(collection)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ObservableList() : base()
+ {
+ }
+
+ ///
+ /// Replace all elements in the with the elements of the specified collection.
+ ///
+ public void SetItems(IEnumerable collection)
+ {
+ Items.Clear();
+
+ foreach (var item in collection)
+ {
+ Items.Add(item);
+ }
+
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ }
+
+ ///
+ /// Adds the elements of the specified collection to the end of the .
+ ///
+ public void AddRange(IEnumerable collection)
+ {
+ foreach (var item in collection)
+ {
+ Items.Add(item);
+ }
+
+ new List().AddRange(new List());
+
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ }
+}
From bd2ec9622ebe374fe765887f36988b1969b13b82 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Mon, 17 Feb 2025 18:56:12 +0100
Subject: [PATCH 28/36] Use ObservableList instead of ObservableCollection
where appropriate (which turns out to be everywhere)
---
.../Models/ServerStatus/ServerListCache.cs | 24 ++---------
.../ViewModels/HubSettingsViewModel.cs | 4 +-
.../MainWindowTabs/HomePageViewModel.cs | 1 -
.../MainWindowTabs/NewsTabViewModel.cs | 13 ++----
.../ServerListFiltersViewModel.cs | 41 ++++---------------
.../MainWindowTabs/ServerListTabViewModel.cs | 12 ++----
6 files changed, 22 insertions(+), 73 deletions(-)
diff --git a/SS14.Launcher/Models/ServerStatus/ServerListCache.cs b/SS14.Launcher/Models/ServerStatus/ServerListCache.cs
index 64c2a2600..73da6959b 100644
--- a/SS14.Launcher/Models/ServerStatus/ServerListCache.cs
+++ b/SS14.Launcher/Models/ServerStatus/ServerListCache.cs
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Collections.Specialized;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -25,8 +23,7 @@ public sealed partial class ServerListCache : ObservableObject, IServerSource
private CancellationTokenSource? _refreshCancel;
- public ObservableCollection AllServers => _allServers;
- private readonly ServerListCollection _allServers = new();
+ public ObservableList AllServers { get; } = [];
[ObservableProperty] private RefreshListStatus _status = RefreshListStatus.NotUpdated;
@@ -47,14 +44,14 @@ public void RequestInitialUpdate()
public void RequestRefresh()
{
_refreshCancel?.Cancel();
- _allServers.Clear();
+ AllServers.Clear();
_refreshCancel = new CancellationTokenSource(10000);
RefreshServerList(_refreshCancel.Token);
}
public async void RefreshServerList(CancellationToken cancel)
{
- _allServers.Clear();
+ AllServers.Clear();
Status = RefreshListStatus.UpdatingMaster;
try
@@ -121,7 +118,7 @@ public async void RefreshServerList(CancellationToken cancel)
}
}
- _allServers.AddItems(entries.Select(entry =>
+ AllServers.AddRange(entries.Select(entry =>
{
var statusData = new ServerStatusData(entry.Address, entry.HubAddress);
ServerStatusCache.ApplyStatus(statusData, entry.StatusData);
@@ -152,19 +149,6 @@ void IServerSource.UpdateInfoFor(ServerStatusData statusData)
statusData,
async token => await _hubApi.GetServerInfo(statusData.Address, statusData.HubAddress, token));
}
-
- private sealed class ServerListCollection : ObservableCollection
- {
- public void AddItems(IEnumerable items)
- {
- foreach (var item in items)
- {
- Items.Add(item);
- }
-
- OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
- }
- }
}
public class ServerStatusDataWithFallbackName
diff --git a/SS14.Launcher/ViewModels/HubSettingsViewModel.cs b/SS14.Launcher/ViewModels/HubSettingsViewModel.cs
index 63a5fea30..bd1d1a62f 100644
--- a/SS14.Launcher/ViewModels/HubSettingsViewModel.cs
+++ b/SS14.Launcher/ViewModels/HubSettingsViewModel.cs
@@ -1,9 +1,7 @@
using System;
using System.Collections.Generic;
-using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
-using DynamicData;
using Splat;
using SS14.Launcher.Models.Data;
using SS14.Launcher.Utility;
@@ -13,7 +11,7 @@ namespace SS14.Launcher.ViewModels;
public class HubSettingsViewModel : ViewModelBase
{
public Uri[] DefaultHubs => ConfigConstants.DefaultHubUrls;
- public ObservableCollection HubList { get; set; } = new();
+ public ObservableList HubList { get; set; } = [];
private readonly DataManager _dataManager = Locator.Current.GetRequiredService();
diff --git a/SS14.Launcher/ViewModels/MainWindowTabs/HomePageViewModel.cs b/SS14.Launcher/ViewModels/MainWindowTabs/HomePageViewModel.cs
index 826aa2774..3c9f3fc05 100644
--- a/SS14.Launcher/ViewModels/MainWindowTabs/HomePageViewModel.cs
+++ b/SS14.Launcher/ViewModels/MainWindowTabs/HomePageViewModel.cs
@@ -57,7 +57,6 @@ public HomePageViewModel(MainWindowViewModel mainWindowViewModel)
}
public ReadOnlyObservableCollection Favorites { get; }
- public ObservableCollection Suggestions { get; } = new();
[ObservableProperty] private bool _favoritesEmpty = true;
diff --git a/SS14.Launcher/ViewModels/MainWindowTabs/NewsTabViewModel.cs b/SS14.Launcher/ViewModels/MainWindowTabs/NewsTabViewModel.cs
index f8ec68819..f2e001099 100644
--- a/SS14.Launcher/ViewModels/MainWindowTabs/NewsTabViewModel.cs
+++ b/SS14.Launcher/ViewModels/MainWindowTabs/NewsTabViewModel.cs
@@ -1,14 +1,15 @@
using System;
-using System.Collections.ObjectModel;
+using System.Linq;
using CodeHollow.FeedReader;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using SS14.Launcher.Localization;
+using SS14.Launcher.Utility;
namespace SS14.Launcher.ViewModels.MainWindowTabs;
public partial class NewsTabViewModel : MainWindowTabViewModel
{
- public ObservableCollection NewsEntries { get; } = new ([]);
+ public ObservableList NewsEntries { get; } = [];
public override string Name => LocalizationManager.Instance.GetString("tab-news-title");
private bool _startedPullingNews;
@@ -26,18 +27,12 @@ public override void Selected()
private async void PullNews()
{
if (_startedPullingNews)
- {
return;
- }
_startedPullingNews = true;
var feed = await FeedReader.ReadAsync(ConfigConstants.NewsFeedUrl);
- foreach (var feedItem in feed.Items)
- {
- NewsEntries.Add(new NewsEntryViewModel(feedItem.Title, new Uri(feedItem.Link)));
- }
-
+ NewsEntries.AddRange(feed.Items.Select(i => new NewsEntryViewModel(i.Title, new Uri(i.Link))));
NewsPulled = true;
}
}
diff --git a/SS14.Launcher/ViewModels/MainWindowTabs/ServerListFiltersViewModel.cs b/SS14.Launcher/ViewModels/MainWindowTabs/ServerListFiltersViewModel.cs
index 939c5aeb8..e719c87c2 100644
--- a/SS14.Launcher/ViewModels/MainWindowTabs/ServerListFiltersViewModel.cs
+++ b/SS14.Launcher/ViewModels/MainWindowTabs/ServerListFiltersViewModel.cs
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Collections.Specialized;
using System.Globalization;
using System.Linq;
using Microsoft.Toolkit.Mvvm.ComponentModel;
@@ -22,17 +20,11 @@ public sealed partial class ServerListFiltersViewModel : ObservableObject
private int _totalServers;
private int _filteredServers;
- private readonly FilterListCollection _filtersLanguage = new();
- private readonly FilterListCollection _filtersRegion = new();
- private readonly FilterListCollection _filtersRolePlay = new();
- private readonly FilterListCollection _filtersEighteenPlus = new();
- private readonly FilterListCollection _filtersHub = new();
-
- public ObservableCollection FiltersLanguage => _filtersLanguage;
- public ObservableCollection FiltersRegion => _filtersRegion;
- public ObservableCollection FiltersRolePlay => _filtersRolePlay;
- public ObservableCollection FiltersEighteenPlus => _filtersEighteenPlus;
- public ObservableCollection FiltersHub => _filtersHub;
+ public ObservableList FiltersLanguage { get; } = [];
+ public ObservableList FiltersRegion { get; } = [];
+ public ObservableList FiltersRolePlay { get; } = [];
+ public ObservableList FiltersEighteenPlus { get; } = [];
+ public ObservableList FiltersHub { get; } = [];
public ServerFilterViewModel FilterPlayerCountHideEmpty { get; }
public ServerFilterViewModel FilterPlayerCountHideFull { get; }
@@ -204,10 +196,10 @@ public void UpdatePresentFilters(IEnumerable servers)
new ServerFilter(ServerFilterCategory.RolePlay, ServerFilter.DataUnspecified), this));
// Set.
- _filtersLanguage.SetItems(filtersLanguage);
- _filtersRegion.SetItems(filtersRegion);
- _filtersRolePlay.SetItems(filtersRolePlay);
- _filtersHub.SetItems(filtersHub);
+ FiltersLanguage.SetItems(filtersLanguage);
+ FiltersRegion.SetItems(filtersRegion);
+ FiltersRolePlay.SetItems(filtersRolePlay);
+ FiltersHub.SetItems(filtersHub);
}
public bool GetFilter(ServerFilterCategory category, string data) => GetFilter(new ServerFilter(category, data));
@@ -405,19 +397,4 @@ public override int Compare(ServerFilterViewModel x, ServerFilterViewModel y)
return idxX.CompareTo(idxY);
}
}
-
- private sealed class FilterListCollection : ObservableCollection
- {
- public void SetItems(IEnumerable items)
- {
- Items.Clear();
-
- foreach (var item in items)
- {
- Items.Add(item);
- }
-
- OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
- }
- }
}
diff --git a/SS14.Launcher/ViewModels/MainWindowTabs/ServerListTabViewModel.cs b/SS14.Launcher/ViewModels/MainWindowTabs/ServerListTabViewModel.cs
index aa41e95ea..1c6787741 100644
--- a/SS14.Launcher/ViewModels/MainWindowTabs/ServerListTabViewModel.cs
+++ b/SS14.Launcher/ViewModels/MainWindowTabs/ServerListTabViewModel.cs
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
-using System.Collections.ObjectModel;
using System.Collections.Specialized;
+using System.Linq;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Splat;
using SS14.Launcher.Localization;
@@ -16,7 +16,7 @@ public partial class ServerListTabViewModel : MainWindowTabViewModel
private readonly MainWindowViewModel _windowVm;
private readonly ServerListCache _serverListCache;
- public ObservableCollection SearchedServers { get; } = new();
+ public ObservableList SearchedServers { get; } = [];
private string? _searchString;
@@ -135,12 +135,8 @@ private void UpdateSearchedList()
sortList.Sort(ServerSortComparer.Instance);
- SearchedServers.Clear();
- foreach (var server in sortList)
- {
- var vm = new ServerEntryViewModel(_windowVm, server, _serverListCache, _windowVm.Cfg);
- SearchedServers.Add(vm);
- }
+ SearchedServers.SetItems(sortList.Select(server
+ => new ServerEntryViewModel(_windowVm, server, _serverListCache, _windowVm.Cfg)));
}
private bool DoesSearchMatch(ServerStatusData data)
From 8be609e859666162d0f759f91ff885b247c82ad5 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Mon, 17 Feb 2025 19:02:00 +0100
Subject: [PATCH 29/36] woke
---
SS14.Launcher/ConfigConstants.cs | 2 +-
SS14.Launcher/Models/Logins/LoginManager.cs | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/SS14.Launcher/ConfigConstants.cs b/SS14.Launcher/ConfigConstants.cs
index 262cf007c..f0d190b00 100644
--- a/SS14.Launcher/ConfigConstants.cs
+++ b/SS14.Launcher/ConfigConstants.cs
@@ -11,7 +11,7 @@ public static class ConfigConstants
// Refresh login tokens if they're within of expiry.
public static readonly TimeSpan TokenRefreshThreshold = TimeSpan.FromDays(15);
- // If the user leaves the launcher running for absolute ages, this is how often we'll update his login tokens.
+ // If the user leaves the launcher running for absolute ages, this is how often we'll update their login tokens.
public static readonly TimeSpan TokenRefreshInterval = TimeSpan.FromDays(7);
// The amount of time before a server is considered timed out for status checks.
diff --git a/SS14.Launcher/Models/Logins/LoginManager.cs b/SS14.Launcher/Models/Logins/LoginManager.cs
index c6f382959..2f1785263 100644
--- a/SS14.Launcher/Models/Logins/LoginManager.cs
+++ b/SS14.Launcher/Models/Logins/LoginManager.cs
@@ -91,7 +91,7 @@ public LoginManager(DataManager cfg, AuthApi authApi)
public async Task Initialize()
{
// Set up timer so that if the user leaves their launcher open for a month or something
- // his tokens don't expire.
+ // their tokens don't expire.
_timer = DispatcherTimer.Run(() =>
{
async void Impl()
From 2c975baeed1f404143b3a9440d43cda82d3e2673 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Mon, 17 Feb 2025 19:17:36 +0100
Subject: [PATCH 30/36] AvailableAccount
---
.../ViewModels/AccountDropDownViewModel.cs | 21 ++++++++-----------
1 file changed, 9 insertions(+), 12 deletions(-)
diff --git a/SS14.Launcher/ViewModels/AccountDropDownViewModel.cs b/SS14.Launcher/ViewModels/AccountDropDownViewModel.cs
index f5544c78e..6b2efc6ae 100644
--- a/SS14.Launcher/ViewModels/AccountDropDownViewModel.cs
+++ b/SS14.Launcher/ViewModels/AccountDropDownViewModel.cs
@@ -116,23 +116,20 @@ public void AddAccountPressed()
}
}
-public sealed class AvailableAccountViewModel : ViewModelBase
+public sealed partial class AvailableAccountViewModel : ViewModelBase
{
- public extern string StatusText { [ObservableAsProperty] get; }
+ [ObservableProperty] private LoggedInAccount _account;
- public LoggedInAccount Account { get; }
+ public string StatusText
+ => Account.Username + Account.Status switch
+ {
+ AccountLoginStatus.Available => "",
+ AccountLoginStatus.Expired => " (!)",
+ _ => " (?)",
+ };
public AvailableAccountViewModel(LoggedInAccount account)
{
Account = account;
-
- this.WhenAnyValue(p => p.Account.Status, p => p.Account.Username)
- .Select(p => p.Item1 switch
- {
- AccountLoginStatus.Available => $"{p.Item2}",
- AccountLoginStatus.Expired => $"{p.Item2} (!)",
- _ => $"{p.Item2} (?)"
- })
- .ToPropertyEx(this, x => x.StatusText);
}
}
From 014eda85ab590e1f2db7b5668d918fc0a24a7a1a Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Mon, 17 Feb 2025 19:19:12 +0100
Subject: [PATCH 31/36] small changes
---
SS14.Launcher/ViewModels/AccountDropDownViewModel.cs | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/SS14.Launcher/ViewModels/AccountDropDownViewModel.cs b/SS14.Launcher/ViewModels/AccountDropDownViewModel.cs
index 6b2efc6ae..ea4046c56 100644
--- a/SS14.Launcher/ViewModels/AccountDropDownViewModel.cs
+++ b/SS14.Launcher/ViewModels/AccountDropDownViewModel.cs
@@ -1,10 +1,12 @@
using System;
using System.Collections.ObjectModel;
using System.Reactive.Linq;
+using System.Linq;
using DynamicData;
using JetBrains.Annotations;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
+using Microsoft.Toolkit.Mvvm.ComponentModel;
using Serilog;
using Splat;
using SS14.Launcher.Api;
@@ -15,7 +17,7 @@
namespace SS14.Launcher.ViewModels;
-public class AccountDropDownViewModel : ViewModelBase
+public partial class AccountDropDownViewModel : ViewModelBase
{
private readonly MainWindowViewModel _mainVm;
private readonly DataManager _cfg;
@@ -48,8 +50,8 @@ public AccountDropDownViewModel(MainWindowViewModel mainVm)
_loginMgr.Logins.Connect().Subscribe(_ =>
{
- this.RaisePropertyChanged(nameof(LogoutText));
- this.RaisePropertyChanged(nameof(AccountSwitchVisible));
+ OnPropertyChanged(nameof(LogoutText));
+ OnPropertyChanged(nameof(AccountSwitchVisible));
});
var filterObservable = this.WhenAnyValue(x => x._loginMgr.ActiveAccount)
@@ -82,7 +84,7 @@ public AccountDropDownViewModel(MainWindowViewModel mainVm)
public bool AccountControlsVisible => _loginMgr.ActiveAccount != null;
- [Reactive] public bool IsDropDownOpen { get; set; }
+ [ObservableProperty] private bool _isDropDownOpen;
public async void LogoutPressed()
{
From bbe16a9d00c2849263c169d95967f22b11d66fe8 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Mon, 17 Feb 2025 19:33:09 +0100
Subject: [PATCH 32/36] AccountDropDown
---
.../ViewModels/AccountDropDownViewModel.cs | 50 ++++++++-----------
1 file changed, 22 insertions(+), 28 deletions(-)
diff --git a/SS14.Launcher/ViewModels/AccountDropDownViewModel.cs b/SS14.Launcher/ViewModels/AccountDropDownViewModel.cs
index ea4046c56..4a205cdb5 100644
--- a/SS14.Launcher/ViewModels/AccountDropDownViewModel.cs
+++ b/SS14.Launcher/ViewModels/AccountDropDownViewModel.cs
@@ -1,11 +1,7 @@
using System;
-using System.Collections.ObjectModel;
-using System.Reactive.Linq;
+using System.Collections.Generic;
using System.Linq;
-using DynamicData;
using JetBrains.Annotations;
-using ReactiveUI;
-using ReactiveUI.Fody.Helpers;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Serilog;
using Splat;
@@ -23,10 +19,9 @@ public partial class AccountDropDownViewModel : ViewModelBase
private readonly DataManager _cfg;
private readonly AuthApi _authApi;
private readonly LoginManager _loginMgr;
- private readonly ReadOnlyObservableCollection _accounts;
private readonly LocalizationManager _loc;
- public ReadOnlyObservableCollection Accounts => _accounts;
+ private ObservableList Accounts { get; }
public bool EnableMultiAccounts => _cfg.ActuallyMultiAccounts;
@@ -38,36 +33,35 @@ public AccountDropDownViewModel(MainWindowViewModel mainVm)
_loginMgr = Locator.Current.GetRequiredService();
_loc = LocalizationManager.Instance;
- this.WhenAnyValue(x => x._loginMgr.ActiveAccount)
- .Subscribe(_ =>
- {
- this.RaisePropertyChanged(nameof(LoginText));
- this.RaisePropertyChanged(nameof(AccountSwitchText));
- this.RaisePropertyChanged(nameof(LogoutText));
- this.RaisePropertyChanged(nameof(AccountControlsVisible));
- this.RaisePropertyChanged(nameof(AccountSwitchVisible));
- });
+ Accounts = new(GetInactiveAccounts());
- _loginMgr.Logins.Connect().Subscribe(_ =>
+ _loginMgr.PropertyChanged += (_, e) =>
{
+ if (e.PropertyName is not nameof(_loginMgr.ActiveAccount))
+ return;
+
+ OnPropertyChanged(nameof(LoginText));
+ OnPropertyChanged(nameof(AccountSwitchText));
OnPropertyChanged(nameof(LogoutText));
+ OnPropertyChanged(nameof(AccountControlsVisible));
OnPropertyChanged(nameof(AccountSwitchVisible));
- });
- var filterObservable = this.WhenAnyValue(x => x._loginMgr.ActiveAccount)
- .Select(MakeFilter);
+ Accounts.SetItems(GetInactiveAccounts());
+ };
- _loginMgr.Logins
- .Connect()
- .Filter(filterObservable)
- .Transform(p => new AvailableAccountViewModel(p))
- .Bind(out _accounts)
- .Subscribe();
+ _loginMgr.Logins.Connect().Subscribe(_ =>
+ {
+ OnPropertyChanged(nameof(LogoutText));
+ OnPropertyChanged(nameof(AccountSwitchVisible));
+ });
}
- private static Func MakeFilter(LoggedInAccount? selected)
+ private IEnumerable GetInactiveAccounts()
{
- return l => l != selected;
+ return _loginMgr.Logins
+ .Items
+ .Where(a => a != _loginMgr.ActiveAccount)
+ .Select(a => new AvailableAccountViewModel(a));
}
public string LoginText => _loginMgr.ActiveAccount?.Username ??
From f42daed183255bb35143a5886dc3d9bdca279e43 Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Mon, 17 Feb 2025 19:37:45 +0100
Subject: [PATCH 33/36] ViewModelBase
---
.../ViewModels/MainWindowLoginViewModel.cs | 4 ++--
.../MainWindowTabs/DevelopmentTabViewModel.cs | 5 ++---
.../MainWindowTabs/ServerListTabViewModel.cs | 4 ++--
SS14.Launcher/ViewModels/MainWindowViewModel.cs | 4 ++--
SS14.Launcher/ViewModels/ViewModelBase.cs | 16 +++-------------
5 files changed, 11 insertions(+), 22 deletions(-)
diff --git a/SS14.Launcher/ViewModels/MainWindowLoginViewModel.cs b/SS14.Launcher/ViewModels/MainWindowLoginViewModel.cs
index 9b7f0c609..c017dbdf3 100644
--- a/SS14.Launcher/ViewModels/MainWindowLoginViewModel.cs
+++ b/SS14.Launcher/ViewModels/MainWindowLoginViewModel.cs
@@ -24,9 +24,9 @@ public BaseLoginViewModel Screen
if (_screen == value)
return;
- OnPropertyChanging(nameof(Screen));
+ OnPropertyChanging();
_screen = value;
- OnPropertyChanged(nameof(Screen));
+ OnPropertyChanged();
value.Activated();
}
diff --git a/SS14.Launcher/ViewModels/MainWindowTabs/DevelopmentTabViewModel.cs b/SS14.Launcher/ViewModels/MainWindowTabs/DevelopmentTabViewModel.cs
index afed7bed6..3f281b03c 100644
--- a/SS14.Launcher/ViewModels/MainWindowTabs/DevelopmentTabViewModel.cs
+++ b/SS14.Launcher/ViewModels/MainWindowTabs/DevelopmentTabViewModel.cs
@@ -1,5 +1,4 @@
-using System.ComponentModel;
-using Splat;
+using Splat;
using SS14.Launcher.Localization;
using SS14.Launcher.Models.Data;
using SS14.Launcher.Utility;
@@ -16,7 +15,7 @@ public DevelopmentTabViewModel()
// TODO: This sucks and leaks.
_cfg.GetCVarEntry(CVars.EngineOverrideEnabled).PropertyChanged += (_, _) =>
{
- OnPropertyChanged(new PropertyChangedEventArgs(nameof(Name)));
+ OnPropertyChanged(nameof(Name));
};
}
diff --git a/SS14.Launcher/ViewModels/MainWindowTabs/ServerListTabViewModel.cs b/SS14.Launcher/ViewModels/MainWindowTabs/ServerListTabViewModel.cs
index 1c6787741..6d0c013ad 100644
--- a/SS14.Launcher/ViewModels/MainWindowTabs/ServerListTabViewModel.cs
+++ b/SS14.Launcher/ViewModels/MainWindowTabs/ServerListTabViewModel.cs
@@ -30,9 +30,9 @@ public string? SearchString
if (_searchString == value)
return;
- OnPropertyChanging(nameof(SearchString));
+ OnPropertyChanging();
_searchString = value;
- OnPropertyChanged(nameof(SearchString));
+ OnPropertyChanged();
UpdateSearchedList();
}
diff --git a/SS14.Launcher/ViewModels/MainWindowViewModel.cs b/SS14.Launcher/ViewModels/MainWindowViewModel.cs
index 64d590a8f..38db0c339 100644
--- a/SS14.Launcher/ViewModels/MainWindowViewModel.cs
+++ b/SS14.Launcher/ViewModels/MainWindowViewModel.cs
@@ -107,9 +107,9 @@ public int SelectedIndex
if (!EqualityComparer.Default.Equals(_selectedIndex, value))
{
- OnPropertyChanging(nameof(SelectedIndex));
+ OnPropertyChanging();
_selectedIndex = value;
- OnPropertyChanged(nameof(SelectedIndex));
+ OnPropertyChanged();
}
RunSelectedOnTab();
diff --git a/SS14.Launcher/ViewModels/ViewModelBase.cs b/SS14.Launcher/ViewModels/ViewModelBase.cs
index 3f9bbeda8..35049669d 100644
--- a/SS14.Launcher/ViewModels/ViewModelBase.cs
+++ b/SS14.Launcher/ViewModels/ViewModelBase.cs
@@ -1,20 +1,10 @@
-using System.ComponentModel;
-using ReactiveUI;
+using Microsoft.Toolkit.Mvvm.ComponentModel;
namespace SS14.Launcher.ViewModels;
-public class ViewModelBase : ReactiveObject, IViewModelBase
-{
- protected void OnPropertyChanged(PropertyChangedEventArgs e) => this.RaisePropertyChanged(e.PropertyName);
- protected void OnPropertyChanging(PropertyChangingEventArgs e) => this.RaisePropertyChanging(e.PropertyName);
-
- protected void OnPropertyChanged(string name) => this.RaisePropertyChanged(name);
- protected void OnPropertyChanging(string name) => this.RaisePropertyChanging(name);
-}
+public class ViewModelBase : ObservableObject, IViewModelBase;
///
/// Signifies to that this viewmodel can be automatically located.
///
-public interface IViewModelBase
-{
-}
+public interface IViewModelBase;
From 2f3a946e8116f8ccba1e245ae202140374c95c1f Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Mon, 17 Feb 2025 19:45:40 +0100
Subject: [PATCH 34/36] Bye!!!!!!!!
---
Directory.Packages.props | 4 +---
SS14.Launcher/FodyWeavers.xml | 3 ---
SS14.Launcher/Program.cs | 4 +---
SS14.Launcher/SS14.Launcher.csproj | 4 +---
4 files changed, 3 insertions(+), 12 deletions(-)
delete mode 100644 SS14.Launcher/FodyWeavers.xml
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 65587268e..c36a23ae4 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -5,6 +5,7 @@
+
@@ -16,15 +17,12 @@
-
-
-
diff --git a/SS14.Launcher/FodyWeavers.xml b/SS14.Launcher/FodyWeavers.xml
deleted file mode 100644
index 63fc14848..000000000
--- a/SS14.Launcher/FodyWeavers.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/SS14.Launcher/Program.cs b/SS14.Launcher/Program.cs
index dea3b6836..418717c84 100644
--- a/SS14.Launcher/Program.cs
+++ b/SS14.Launcher/Program.cs
@@ -9,7 +9,6 @@
using Avalonia.Controls;
using Avalonia.Logging;
using Avalonia.Media;
-using Avalonia.ReactiveUI;
using Microsoft.Win32;
using Serilog;
using Serilog.Sinks.SystemConsole.Themes;
@@ -256,8 +255,7 @@ private static AppBuilder BuildAvaloniaApp(DataManager cfg)
{
// Necessary workaround for #84 on Linux
DefaultFamilyName = "avares://SS14.Launcher/Assets/Fonts/noto_sans/*.ttf#Noto Sans"
- })
- .UseReactiveUI();
+ });
}
// Your application's entry point. Here you can initialize your MVVM framework, DI
diff --git a/SS14.Launcher/SS14.Launcher.csproj b/SS14.Launcher/SS14.Launcher.csproj
index d95c28835..73a100ced 100644
--- a/SS14.Launcher/SS14.Launcher.csproj
+++ b/SS14.Launcher/SS14.Launcher.csproj
@@ -39,18 +39,16 @@
-
+
-
-
From f6e4904eb9d7b48c21da4ea23f2117547328217e Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Tue, 1 Apr 2025 01:20:14 +0200
Subject: [PATCH 35/36] Fix
---
SS14.Launcher/Models/ServerStatus/ServerListCache.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/SS14.Launcher/Models/ServerStatus/ServerListCache.cs b/SS14.Launcher/Models/ServerStatus/ServerListCache.cs
index 44c5b1443..ac507a5e9 100644
--- a/SS14.Launcher/Models/ServerStatus/ServerListCache.cs
+++ b/SS14.Launcher/Models/ServerStatus/ServerListCache.cs
@@ -124,7 +124,7 @@ public async void RefreshServerList(CancellationToken cancel)
return statusData;
}));
- if (_allServers.Count == 0)
+ if (AllServers.Count == 0)
// We did not get any servers
Status = RefreshListStatus.Error;
else if (!allSucceeded)
From 54e8b751d1cbbb6ca07873685f41290cd0e0362a Mon Sep 17 00:00:00 2001
From: Visne <39844191+Visne@users.noreply.github.com>
Date: Sun, 28 Sep 2025 14:33:50 +0200
Subject: [PATCH 36/36] Fix
---
SS14.Launcher/ViewModels/MainWindowViewModel.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/SS14.Launcher/ViewModels/MainWindowViewModel.cs b/SS14.Launcher/ViewModels/MainWindowViewModel.cs
index f9be49fa8..8512c1915 100644
--- a/SS14.Launcher/ViewModels/MainWindowViewModel.cs
+++ b/SS14.Launcher/ViewModels/MainWindowViewModel.cs
@@ -204,14 +204,14 @@ public void DismissIntelDegradationPressed()
{
Cfg.SetCVar(CVars.HasDismissedIntelDegradation, true);
Cfg.CommitConfig();
- this.RaisePropertyChanged(nameof(ShouldShowIntelDegradationWarning));
+ OnPropertyChanged(nameof(ShouldShowIntelDegradationWarning));
}
public void DismissAppleSiliconRosettaPressed()
{
Cfg.SetCVar(CVars.HasDismissedRosettaWarning, true);
Cfg.CommitConfig();
- this.RaisePropertyChanged(nameof(ShouldShowRosettaWarning));
+ OnPropertyChanged(nameof(ShouldShowRosettaWarning));
}
public void SelectTabServers()