Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
a96ef13
DirectConnectDialog
Visne Feb 11, 2025
fe4811e
Flip!!!
Visne Feb 11, 2025
ad9376b
AddFavoriteDialog
Visne Feb 11, 2025
aa41dcb
NewsTab
Visne Feb 11, 2025
0cf4242
DevelopmentTab
Visne Feb 11, 2025
d180e59
Replace some [Reactive] with [ObservableProperty]
Visne Feb 11, 2025
57fbb83
Nuke in-launcher registration since it was unused
Visne Feb 11, 2025
6b1a5a9
LoginView
Visne Feb 11, 2025
9389e0b
ForgotPassword
Visne Feb 11, 2025
7f6d9fd
MainWindow
Visne Feb 11, 2025
79c1ecf
LoginInfo
Visne Feb 11, 2025
f185c30
BaseLoginViewModel
Visne Feb 11, 2025
dbce1bd
ExpiredLogin
Visne Feb 11, 2025
dcf087c
AuthTfa
Visne Feb 13, 2025
9eee95b
Remove ResendConfirmation
Visne Feb 13, 2025
988b21f
LoggedInAccount
Visne Feb 14, 2025
80e7177
nvm
Visne Feb 14, 2025
df24aac
MainWindowLogin
Visne Feb 14, 2025
1129574
ServerListTab
Visne Feb 14, 2025
9bbb336
FavoriteServer
Visne Feb 14, 2025
315454c
ServerListCache
Visne Feb 14, 2025
c655b2d
DataManager
Visne Feb 14, 2025
963bcc0
Connector
Visne Feb 14, 2025
76119a9
Connecting
Visne Feb 14, 2025
1a6acbb
Updater
Visne Feb 14, 2025
61fa674
LoginManager
Visne Feb 14, 2025
2718a03
Add ObservableList, which is just ObservableCollection with appropria…
Visne Feb 17, 2025
bd2ec96
Use ObservableList instead of ObservableCollection where appropriate …
Visne Feb 17, 2025
8be609e
woke
Visne Feb 17, 2025
2c975ba
AvailableAccount
Visne Feb 17, 2025
014eda8
small changes
Visne Feb 17, 2025
bbe16a9
AccountDropDown
Visne Feb 17, 2025
f42daed
ViewModelBase
Visne Feb 17, 2025
2f3a946
Bye!!!!!!!!
Visne Feb 17, 2025
7a060c7
Fix merge conflicts
Visne Mar 31, 2025
f6e4904
Fix
Visne Mar 31, 2025
159b2e9
Fix merge conflicts
Visne Sep 14, 2025
80239b3
Fix conflicts
Visne Sep 15, 2025
0cde839
Fix conflicts
Visne Sep 16, 2025
e233519
Merge branch 'master' into byereactive
Visne Sep 26, 2025
b3b84da
Merge branch 'master' into byereactive
Visne Sep 27, 2025
54e8b75
Fix
Visne Sep 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<ItemGroup>
<!-- Launcher-loader shared stuff -->
<PackageVersion Include="Microsoft.Data.Sqlite.Core" Version="7.0.4" />
<PackageVersion Include="Splat" Version="15.3.1" />
<PackageVersion Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.4" Condition="'$(UseSystemSqlite)' != 'True'" />
<PackageVersion Include="SQLitePCLRaw.provider.sqlite3" Version="2.1.4" Condition="'$(UseSystemSqlite)' == 'True'" />
<PackageVersion Include="NSec.Cryptography" Version="25.4.0"/>
Expand All @@ -17,15 +18,12 @@
<!-- Launcher -->
<PackageVersion Include="Avalonia" Version="11.2.4"/>
<PackageVersion Include="Avalonia.Desktop" Version="11.2.4"/>
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.2.4"/>
<PackageVersion Include="Avalonia.Diagnostics" Version="11.2.4"/>
<PackageVersion Include="Avalonia.Themes.Simple" Version="11.2.4"/>
<PackageVersion Include="CodeHollow.FeedReader" Version="1.2.6"/>
<PackageVersion Include="Dapper" Version="2.0.123"/>
<PackageVersion Include="DynamicData" Version="8.4.1"/>
<PackageVersion Include="Microsoft.Toolkit.Mvvm" Version="7.1.2"/>
<PackageVersion Include="ReactiveUI" Version="20.1.1"/>
<PackageVersion Include="ReactiveUI.Fody" Version="18.4.26"/>
<PackageVersion Include="Robust.Shared.AuthLib" Version="0.1.2"/>
<PackageVersion Include="Serilog" Version="2.12.0"/>
<PackageVersion Include="Serilog.Sinks.Console" Version="4.1.0"/>
Expand Down
2 changes: 1 addition & 1 deletion SS14.Launcher/ConfigConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public static class ConfigConstants
// Refresh login tokens if they're within <this much> 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.
Expand Down
3 changes: 0 additions & 3 deletions SS14.Launcher/FodyWeavers.xml

This file was deleted.

53 changes: 13 additions & 40 deletions SS14.Launcher/Models/Connector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
/// </summary>
public partial 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<Updater>();
private readonly DataManager _cfg = Locator.Current.GetRequiredService<DataManager>();
private readonly LoginManager _loginManager = Locator.Current.GetRequiredService<LoginManager>();
private readonly IEngineManager _engineManager = Locator.Current.GetRequiredService<IEngineManager>();

private ConnectionStatus _status = ConnectionStatus.None;
private bool _clientExitedBadly;
private readonly HttpClient _http;
private readonly HttpClient _http = Locator.Current.GetRequiredService<HttpClient>();

private TaskCompletionSource<PrivacyPolicyAcceptResult>? _acceptPrivacyPolicyTcs;
private ServerPrivacyPolicyInfo? _serverPrivacyPolicyInfo;
private bool _privacyPolicyDifferentVersion;

public Connector()
{
_updater = Locator.Current.GetRequiredService<Updater>();
_cfg = Locator.Current.GetRequiredService<DataManager>();
_loginManager = Locator.Current.GetRequiredService<LoginManager>();
_engineManager = Locator.Current.GetRequiredService<IEngineManager>();
_http = Locator.Current.GetRequiredService<HttpClient>();
}

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)
{
Expand Down Expand Up @@ -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<PrivacyPolicyAcceptResult>();

Status = ConnectionStatus.AwaitingPrivacyPolicyAcceptance;
Expand Down Expand Up @@ -203,7 +176,7 @@ public void ConfirmPrivacyPolicy(PrivacyPolicyAcceptResult result)

private void Cleanup()
{
_serverPrivacyPolicyInfo = null;
PrivacyPolicyInfo = null;
_acceptPrivacyPolicyTcs = null;
PrivacyPolicyDifferentVersion = default;
}
Expand Down
4 changes: 2 additions & 2 deletions SS14.Launcher/Models/Data/DataManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -37,7 +37,7 @@ public interface ICVarEntry<T> : 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.
/// </remarks>
public sealed class DataManager : ReactiveObject
public sealed class DataManager : ObservableObject
{
private delegate void DbCommand(SqliteConnection connection);

Expand Down
41 changes: 10 additions & 31 deletions SS14.Launcher/Models/Data/FavoriteServer.cs
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// Used to infer an exact ordering for servers in a simple, compatible manner.
/// Defaults to 0, this is fine.
/// </summary>
[ObservableProperty] private DateTimeOffset _raiseTime;

public FavoriteServer(string? name, string address)
{
Expand All @@ -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.

/// <summary>
/// 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.
/// </summary>
public DateTimeOffset RaiseTime
{
get => _raiseTime;
set => this.RaiseAndSetIfChanged(ref _raiseTime, value);
}
}
14 changes: 5 additions & 9 deletions SS14.Launcher/Models/Data/LoginInfo.cs
Original file line number Diff line number Diff line change
@@ -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()
{
Expand Down
6 changes: 3 additions & 3 deletions SS14.Launcher/Models/Logins/LoggedInAccount.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
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;

Check warning on line 9 in SS14.Launcher/Models/Logins/LoggedInAccount.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference return.
public Guid UserId => LoginInfo.UserId;

protected LoggedInAccount(LoginInfo loginInfo)
Expand All @@ -17,4 +17,4 @@
public LoginInfo LoginInfo { get; }

public abstract AccountLoginStatus Status { get; }
}
}
24 changes: 17 additions & 7 deletions SS14.Launcher/Models/Logins/LoginManager.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -86,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()
Expand Down Expand Up @@ -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);
}
}
Expand Down
Loading
Loading