diff --git a/README.md b/README.md
index 67a2e070..aee976a7 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
[![Flathub](https://img.shields.io/flathub/v/org.unitystation.StationHub?style=flat-square)](https://flathub.org/apps/details/org.unitystation.StationHub)
[![Discord](https://img.shields.io/discord/273774715741667329?style=flat-square)](https://discord.com/invite/tFcTpBp)
-This is the official launcher for Unitystation, it handles account creation, downloading, updating, and server joining.
+StationHub is the official launcher for Unitystation, it handles downloading, updating, and joining servers.
## Tech-stack
It is cross-platform using .NET 6 as the runtime and [Avalonia MVVM](https://docs.avaloniaui.net/guides/basics/mvvm) for the UI.
diff --git a/UnitystationLauncher/Assets/buttoncontext.png b/UnitystationLauncher/Assets/buttoncontext.png
deleted file mode 100644
index b15a0933..00000000
Binary files a/UnitystationLauncher/Assets/buttoncontext.png and /dev/null differ
diff --git a/UnitystationLauncher/Assets/org.unitystation.StationHub.metainfo.xml b/UnitystationLauncher/Assets/org.unitystation.StationHub.metainfo.xml
index 6d271a87..61a7e027 100644
--- a/UnitystationLauncher/Assets/org.unitystation.StationHub.metainfo.xml
+++ b/UnitystationLauncher/Assets/org.unitystation.StationHub.metainfo.xml
@@ -74,6 +74,7 @@
Adds links to the Unitystation Discord and GitHub issues pages.
The auto update feature has been replaced with a notification.
Adds a placeholder to the News panel, this will be replaced with posts from the Unitystation Blog in the future.
+
Account creation, management, and login is now handled by the game instead of StationHub.
Bug Fixes:
diff --git a/UnitystationLauncher/Assets/userbg.png b/UnitystationLauncher/Assets/userbg.png
deleted file mode 100644
index 2e27f666..00000000
Binary files a/UnitystationLauncher/Assets/userbg.png and /dev/null differ
diff --git a/UnitystationLauncher/Assets/userico.jpg b/UnitystationLauncher/Assets/userico.jpg
deleted file mode 100644
index f90445ba..00000000
Binary files a/UnitystationLauncher/Assets/userico.jpg and /dev/null differ
diff --git a/UnitystationLauncher/Models/Api/Server.cs b/UnitystationLauncher/Models/Api/Server.cs
index ddb524f1..9eca7ab0 100644
--- a/UnitystationLauncher/Models/Api/Server.cs
+++ b/UnitystationLauncher/Models/Api/Server.cs
@@ -6,6 +6,7 @@
namespace UnitystationLauncher.Models.Api
{
+ [Serializable]
public class Server
{
public Server(string forkName, int buildVersion, string serverIp, int serverPort)
diff --git a/UnitystationLauncher/Models/Api/ServerList.cs b/UnitystationLauncher/Models/Api/ServerList.cs
index 52089cf3..0602b225 100644
--- a/UnitystationLauncher/Models/Api/ServerList.cs
+++ b/UnitystationLauncher/Models/Api/ServerList.cs
@@ -1,9 +1,11 @@
+using System;
using System.Collections.Generic;
namespace UnitystationLauncher.Models.Api
{
+ [Serializable]
public class ServerList
{
- public List Servers { get; set; } = new List();
+ public List Servers { get; set; } = new();
}
}
\ No newline at end of file
diff --git a/UnitystationLauncher/Models/Installation.cs b/UnitystationLauncher/Models/Installation.cs
index 197b9370..b0809d4f 100644
--- a/UnitystationLauncher/Models/Installation.cs
+++ b/UnitystationLauncher/Models/Installation.cs
@@ -54,9 +54,9 @@ public Installation(string folderPath)
return exe;
}
- public void LaunchWithArgs(string ip, short port, string? refreshToken, string? uid)
+ public void LaunchWithArgs(string ip, short port)
{
- Start($"--server {ip} --port {port} --refreshtoken {refreshToken} --uid {uid}");
+ Start($"--server {ip} --port {port}");
}
public void LaunchWithoutArgs()
diff --git a/UnitystationLauncher/Services/AuthService.cs b/UnitystationLauncher/Services/AuthService.cs
deleted file mode 100644
index 77b65488..00000000
--- a/UnitystationLauncher/Services/AuthService.cs
+++ /dev/null
@@ -1,247 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Net.Http;
-using System.Net.Mail;
-using System.Text.Json;
-using System.Text.Json.Serialization;
-using System.Threading;
-using System.Threading.Tasks;
-using Firebase.Auth;
-using Serilog;
-using UnitystationLauncher.Constants;
-using UnitystationLauncher.Models.ConfigFile;
-
-namespace UnitystationLauncher.Services
-{
- public class AuthService
- {
- readonly FirebaseAuthProvider _authProvider;
- private readonly HttpClient _http;
- public LoginMsg? LoginMsg { get; set; }
- public bool AttemptingAutoLogin { get; set; }
-
- public AuthService(HttpClient http, FirebaseAuthProvider authProvider)
- {
- _authProvider = authProvider;
- _http = http;
-
- LoadAuthSettings();
- }
-
- public FirebaseAuthLink? AuthLink { get; set; }
- public string? CurrentRefreshToken => AuthLink?.RefreshToken;
-
- public string? Uid => AuthLink?.User.LocalId;
-
- private readonly string AuthSettingsPath = Path.Combine(Config.RootFolder, "authSettings.json");
-
- private void ConvertToNewAuthFileName()
- {
- string oldAuthSettingsPath = Path.Combine(Config.RootFolder, "settings.json");
- if (File.Exists(oldAuthSettingsPath))
- {
- File.Move(oldAuthSettingsPath, AuthSettingsPath);
- }
- }
-
- private void LoadAuthSettings()
- {
- try
- {
- ConvertToNewAuthFileName();
-
- if (File.Exists(AuthSettingsPath))
- {
- var json = File.ReadAllText(AuthSettingsPath);
- var authLink = JsonSerializer.Deserialize(json);
- AuthLink = authLink;
- }
- }
- catch (Exception)
- {
- // Something went wrong reading the auth settings. Just ask the user to log in again.
- // The auth settings file will get overwritten after they do so we don't need to clean it up.
- }
-
- }
-
- public void SaveAuthSettings()
- {
- var json = JsonSerializer.Serialize(AuthLink);
-
- using (StreamWriter writer = File.CreateText(AuthSettingsPath))
- {
- writer.WriteLine(json);
- }
- }
-
- public void ResendVerificationEmail()
- {
- _authProvider.SendEmailVerificationAsync(AuthLink);
- }
-
- public void SendForgotPasswordEmail(string email)
- {
- _authProvider.SendPasswordResetEmailAsync(email);
- }
-
- internal Task SignInWithEmailAndPasswordAsync(string email, string password) =>
- _authProvider.SignInWithEmailAndPasswordAsync(email, password);
-
- internal Task SignInWithCustomTokenAsync(string token) =>
- _authProvider.SignInWithCustomTokenAsync(token);
-
- ///
- /// Asks firebase to create the user's account.
- /// The provided email's domain is checked against a list of disposable email addresses.
- /// If the domain is not in the list (or if GitHub is down) then account creation continues.
- /// Otherwise an exception is thrown.
- ///
- ///
- internal async Task CreateAccountAsync(string username, string email, string password)
- {
- // Client-side check for disposable email address.
- const string url =
- "https://raw.githubusercontent.com/martenson/disposable-email-domains/master/disposable_email_blocklist.conf";
- HttpRequestMessage requestMessage = new(HttpMethod.Get, url);
-
- CancellationToken cancellationToken = new CancellationTokenSource(60000).Token;
- bool isDomainBlacklisted = false;
- try
- {
- HttpResponseMessage response = await _http.SendAsync(requestMessage, cancellationToken);
- string msg = await response.Content.ReadAsStringAsync(cancellationToken);
-
- // Turn msg into a hashset of all domains
- using StringReader stringReader = new(msg);
- List lines = new();
-
- while (await stringReader.ReadLineAsync() is { } line)
- {
- if (!string.IsNullOrWhiteSpace(line) && !line.TrimStart().StartsWith("//"))
- {
- lines.Add(line);
- }
- }
-
- HashSet blacklist = new(lines, StringComparer.OrdinalIgnoreCase);
-
- MailAddress address = new(email);
- if (blacklist.Contains(address.Host))
- {
- // Randomly wait before failing. Might frustrate users who try different disposable emails.
- await Task.Delay(new Random().Next(3000, 12000), cancellationToken);
- isDomainBlacklisted = true;
- }
- }
- catch (Exception e)
- {
- Log.Error(e, "Error or timeout in check for email domain blacklist, check has been skipped");
- }
-
- if (isDomainBlacklisted)
- {
- throw new InvalidOperationException("The email domain provided by the user is on our blacklist.");
- }
-
- return await _authProvider.CreateUserWithEmailAndPasswordAsync(email, password, username, true);
- }
-
- internal Task GetUpdatedUserAsync() => _authProvider.GetUserAsync(AuthLink);
-
- public async Task GetCustomTokenAsync(RefreshToken refreshToken)
- {
- HttpRequestMessage r = new(HttpMethod.Get, ApiUrls.ValidateTokenUrl + Uri.EscapeDataString(JsonSerializer.Serialize(refreshToken)));
- CancellationToken cancellationToken = new CancellationTokenSource(120000).Token;
- HttpResponseMessage res;
-
- try
- {
- res = await _http.SendAsync(r, cancellationToken);
- }
- catch (Exception e)
- {
- Log.Error(e, "Failed when sending token validation request");
- return "";
- }
-
- string msg = await res.Content.ReadAsStringAsync(cancellationToken);
- ApiResponse? response = JsonSerializer.Deserialize(msg, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
-
- if (response == null)
- {
- Log.Error("Error: {Error}", "Response from /validatetoken cannot be deserialized");
- return "";
- }
-
- if (response.ErrorCode != 0)
- {
- Log.Error("Error: {Error}", response.ErrorMsg);
- return "";
- }
-
- return response.Message ?? "";
- }
-
- public async Task SignOutUserAsync()
- {
- if (AuthLink == null || Uid == null || CurrentRefreshToken == null)
- {
- return;
- }
-
- RefreshToken token = new()
- {
- UserId = Uid,
- Token = CurrentRefreshToken
- };
-
- HttpRequestMessage r = new(HttpMethod.Get, ApiUrls.SignOutUrl + Uri.EscapeDataString(JsonSerializer.Serialize(token)));
- CancellationToken cancellationToken = new CancellationTokenSource(120000).Token;
- HttpResponseMessage res;
-
- try
- {
- res = await _http.SendAsync(r, cancellationToken);
- }
- catch (Exception e)
- {
- Log.Error(e, "Http request to sign out failed");
- return;
- }
-
- string msg = await res.Content.ReadAsStringAsync(cancellationToken);
-
- Log.Information("Logout message: {Message}", msg);
- AuthLink = null;
- }
- }
-
-
-
- public class LoginMsg
- {
- public string Email { get; set; } = "";
- public string Pass { get; set; } = "";
- }
-
- [Serializable]
- public class RefreshToken
- {
- [JsonPropertyName("RefreshToken")] public string? Token { get; set; }
- public string? UserId { get; set; }
- }
-
- [Serializable]
- public class ApiResponse
- {
- ///
- /// 0 = all good, read the message variable now, otherwise read errorMsg
- ///
- public int ErrorCode { get; set; }
-
- public string? ErrorMsg { get; set; }
- public string? Message { get; set; }
- }
-}
\ No newline at end of file
diff --git a/UnitystationLauncher/Services/ServerService.cs b/UnitystationLauncher/Services/ServerService.cs
index 3589fd2c..17cc6ade 100644
--- a/UnitystationLauncher/Services/ServerService.cs
+++ b/UnitystationLauncher/Services/ServerService.cs
@@ -3,8 +3,8 @@
using System.Linq;
using System.Net.Http;
using System.Reactive.Linq;
+using System.Text.Json;
using System.Threading.Tasks;
-using Newtonsoft.Json;
using ReactiveUI;
using Serilog;
using UnitystationLauncher.Constants;
@@ -41,7 +41,12 @@ private async Task> GetServerListAsync()
Refreshing = true;
string data = await _http.GetStringAsync(ApiUrls.ServerListUrl);
- List? serverData = JsonConvert.DeserializeObject(data)?.Servers;
+ List? serverData = JsonSerializer.Deserialize(data, options: new()
+ {
+ IgnoreReadOnlyProperties = true,
+ PropertyNameCaseInsensitive = true
+ })?.Servers;
+
Log.Information("Server list fetched");
List servers = new();
diff --git a/UnitystationLauncher/StandardModule.cs b/UnitystationLauncher/StandardModule.cs
index 39a7e5ed..32a96e87 100644
--- a/UnitystationLauncher/StandardModule.cs
+++ b/UnitystationLauncher/StandardModule.cs
@@ -1,6 +1,5 @@
using System.Net.Http;
using Autofac;
-using Firebase.Auth;
using UnitystationLauncher.Models.ConfigFile;
namespace UnitystationLauncher
@@ -18,9 +17,6 @@ protected override void Load(ContainerBuilder builder)
builder.RegisterAssemblyTypes(ThisAssembly)
.Where(t => t.Name.EndsWith("ViewModel"));
-
- builder.Register(c => new FirebaseConfig("AIzaSyB7GorzPgwHYjSV4XaJoszj98tLM4_WZpE")).SingleInstance();
- builder.RegisterType().SingleInstance();
}
}
}
\ No newline at end of file
diff --git a/UnitystationLauncher/UnitystationLauncher.csproj b/UnitystationLauncher/UnitystationLauncher.csproj
index ae3119e7..933221e2 100644
--- a/UnitystationLauncher/UnitystationLauncher.csproj
+++ b/UnitystationLauncher/UnitystationLauncher.csproj
@@ -51,7 +51,6 @@
-
diff --git a/UnitystationLauncher/ViewModels/ForgotPasswordViewModel.cs b/UnitystationLauncher/ViewModels/ForgotPasswordViewModel.cs
deleted file mode 100644
index 6fd56416..00000000
--- a/UnitystationLauncher/ViewModels/ForgotPasswordViewModel.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-using System;
-using System.Reactive;
-using ReactiveUI;
-using UnitystationLauncher.Services;
-
-namespace UnitystationLauncher.ViewModels
-{
- public class ForgotPasswordViewModel : ViewModelBase
- {
- private readonly Lazy _loginVm;
- private readonly AuthService _authService;
- private bool _isFormVisible;
- private bool _isSuccessVisible;
- string _email = "";
-
- public string Email
- {
- get => _email;
- set => this.RaiseAndSetIfChanged(ref _email, value);
- }
-
- public ReactiveCommand Submit { get; }
- public ReactiveCommand DoneButton { get; }
-
- public bool IsFormVisible
- {
- get => _isFormVisible;
- set => this.RaiseAndSetIfChanged(ref _isFormVisible, value);
- }
-
- public bool IsSuccessVisible
- {
- get => _isSuccessVisible;
- set => this.RaiseAndSetIfChanged(ref _isSuccessVisible, value);
- }
-
- public ForgotPasswordViewModel(AuthService authService, Lazy loginVm)
- {
- IsFormVisible = true;
- IsSuccessVisible = false;
- _authService = authService;
- _loginVm = loginVm;
-
- var inputValidation = this.WhenAnyValue(
- x => x.Email,
- (e) => !string.IsNullOrWhiteSpace(e) &&
- e.Contains("@") && e.Contains("."));
-
- Submit = ReactiveCommand.Create(
- TrySendResetPassword, inputValidation);
-
- DoneButton = ReactiveCommand.Create(ReturnToLogin);
- }
-
- void TrySendResetPassword()
- {
- _authService.SendForgotPasswordEmail(Email);
- IsFormVisible = false;
- IsSuccessVisible = true;
- }
-
- public LoginViewModel ReturnToLogin()
- {
- return _loginVm.Value;
- }
- }
-}
diff --git a/UnitystationLauncher/ViewModels/LauncherViewModel.cs b/UnitystationLauncher/ViewModels/LauncherViewModel.cs
index 61dada79..360d27be 100644
--- a/UnitystationLauncher/ViewModels/LauncherViewModel.cs
+++ b/UnitystationLauncher/ViewModels/LauncherViewModel.cs
@@ -13,15 +13,11 @@ namespace UnitystationLauncher.ViewModels
{
public class LauncherViewModel : ViewModelBase
{
- private readonly AuthService _authService;
- private readonly Lazy _logoutVm;
private readonly Lazy _hubUpdateVm;
private readonly Config _config;
PanelBase[] _panels;
ViewModelBase? _selectedPanel;
- public string Username => _authService.AuthLink?.User.DisplayName ?? "";
-
public PanelBase[] Panels
{
get => _panels;
@@ -34,12 +30,9 @@ public ViewModelBase? SelectedPanel
set => this.RaiseAndSetIfChanged(ref _selectedPanel, value);
}
- public ReactiveCommand Logout { get; }
public ReactiveCommand ShowUpdateView { get; }
public LauncherViewModel(
- AuthService authService,
- Lazy logoutVm,
Lazy hubUpdateVm,
NewsPanelViewModel newsPanel,
ServersPanelViewModel serversPanel,
@@ -47,13 +40,10 @@ public LauncherViewModel(
SettingsPanelViewModel settingsPanel,
Config config)
{
- _authService = authService;
- _logoutVm = logoutVm;
_hubUpdateVm = hubUpdateVm;
_config = config;
_panels = GetEnabledPanels(newsPanel, serversPanel, installationsPanel, settingsPanel);
- Logout = ReactiveCommand.CreateFromTask(LogoutAsync);
ShowUpdateView = ReactiveCommand.Create(ShowUpdateImp);
SelectedPanel = serversPanel;
@@ -116,14 +106,6 @@ private async Task ValidateClientVersionAsync()
}
}
- private async Task LogoutAsync()
- {
- await _authService.SignOutUserAsync();
- Preferences prefs = await _config.GetPreferencesAsync();
- prefs.LastLogin = "";
- return _logoutVm.Value;
- }
-
private HubUpdateViewModel ShowUpdateImp()
{
return _hubUpdateVm.Value;
diff --git a/UnitystationLauncher/ViewModels/LoginStatusViewModel.cs b/UnitystationLauncher/ViewModels/LoginStatusViewModel.cs
deleted file mode 100644
index 6146d548..00000000
--- a/UnitystationLauncher/ViewModels/LoginStatusViewModel.cs
+++ /dev/null
@@ -1,175 +0,0 @@
-using System;
-using System.Reactive;
-using System.Reactive.Concurrency;
-using System.Reactive.Linq;
-using System.Threading.Tasks;
-using ReactiveUI;
-using Serilog;
-using UnitystationLauncher.Infrastructure;
-using UnitystationLauncher.Services;
-
-namespace UnitystationLauncher.ViewModels
-{
- public class LoginStatusViewModel : ViewModelBase
- {
- private readonly AuthService _authService;
- private readonly Lazy _launcherVm;
- private readonly LoginViewModel _loginVm;
- private string? _failedMessage;
- private bool _isFailedVisible;
- private bool _isResendEmailVisible;
- private bool _resendClicked;
- private bool _isWaitingVisible;
-
- public LoginStatusViewModel(AuthService authService, Lazy launcherVm,
- LoginViewModel loginVm)
- {
- IsFailedVisible = false;
- IsResendEmailVisible = false;
- ResendClicked = false;
- _authService = authService;
- _loginVm = loginVm;
- _launcherVm = launcherVm;
-
- var hasAlreadyResent = this.WhenAnyValue(
- x => x.ResendClicked,
- (r) => !r);
-
- ResendEmail = ReactiveCommand.Create(OnResend, hasAlreadyResent);
-
- GoBack = ReactiveCommand.Create(GoBackToLogin);
-
- OpenLauncher = ReactiveCommand.Create(SignInComplete);
-
- if (!authService.AttemptingAutoLogin)
- {
- RxApp.MainThreadScheduler.ScheduleAsync((scheduler, ct) => UserLoginAsync());
- }
- else
- {
- IsWaitingVisible = true;
- }
- }
-
- public bool IsFailedVisible
- {
- get => _isFailedVisible;
- set => this.RaiseAndSetIfChanged(ref _isFailedVisible, value);
- }
-
- public bool IsResendEmailVisible
- {
- get => _isResendEmailVisible;
- set => this.RaiseAndSetIfChanged(ref _isResendEmailVisible, value);
- }
-
- public string? FailedMessage
- {
- get => _failedMessage;
- set => this.RaiseAndSetIfChanged(ref _failedMessage, value);
- }
-
- public bool ResendClicked
- {
- get => _resendClicked;
- set => this.RaiseAndSetIfChanged(ref _resendClicked, value);
- }
-
- public bool IsWaitingVisible
- {
- get => _isWaitingVisible;
- set => this.RaiseAndSetIfChanged(ref _isWaitingVisible, value);
- }
-
- public ReactiveCommand GoBack { get; }
- public ReactiveCommand ResendEmail { get; }
- public ReactiveCommand OpenLauncher { get; }
-
- public async Task UserLoginAsync()
- {
- bool signInSuccess = true;
- ResendClicked = false;
- IsResendEmailVisible = false;
- IsWaitingVisible = true;
-
- if (string.IsNullOrEmpty(_authService.LoginMsg?.Email) ||
- string.IsNullOrEmpty(_authService.LoginMsg.Pass))
- {
- Log.Error("Login failed");
- FailedMessage = "Login failed.\r\n" +
- "Check your email and password\r\n" +
- "and try again.";
- return;
- }
-
- try
- {
- await _authService.SignInWithEmailAndPasswordAsync(
- _authService.LoginMsg.Email, _authService.LoginMsg.Pass).AwaitWithTimeout(TimeSpan.FromSeconds(20),
- firebaseAuthLink => _authService.AuthLink = firebaseAuthLink);
- }
- catch (OperationCanceledException)
- {
- Log.Error("Error: {Error}", "Login timed out");
- FailedMessage = "Timed out while trying to log in.\n"
- + "Please check your network connection.";
- signInSuccess = false;
- }
- catch (Exception e)
- {
- Log.Error(e, "Login failed");
- FailedMessage = "Login failed.\r\n" +
- "Check your email and password\r\n" +
- "and try again.";
- signInSuccess = false;
- }
-
- if (signInSuccess)
- {
- var user = await _authService.GetUpdatedUserAsync();
-
- if (!user.IsEmailVerified)
- {
- FailedMessage = "Email not yet verified.\r\n" +
- "Please click on the activation link sent to your\r\n" +
- "email address. Alternatively you can request another verification\r\n" +
- "email by clicking the resend button below.";
- signInSuccess = false;
- IsResendEmailVisible = true;
- }
- }
-
- _authService.LoginMsg = null;
-
- IsWaitingVisible = false;
- if (!signInSuccess)
- {
- IsFailedVisible = true;
- return;
- }
-
- _authService.SaveAuthSettings();
-
- Observable.Start(() => { }).InvokeCommand(this, vm => vm.OpenLauncher);
- }
-
- public void OnResend()
- {
- _authService.ResendVerificationEmail();
- ResendClicked = true;
- FailedMessage = "A new verification email has been sent to:\r\n" +
- $"{_authService.AuthLink?.User.Email ?? "{ no email }"}\r\n" +
- $"Please activate your account by clicking the link\r\n" +
- $"in the email and try again.";
- }
-
- public LoginViewModel GoBackToLogin()
- {
- return _loginVm;
- }
- public LauncherViewModel SignInComplete()
- {
- return _launcherVm.Value;
- }
- }
-}
\ No newline at end of file
diff --git a/UnitystationLauncher/ViewModels/LoginViewModel.cs b/UnitystationLauncher/ViewModels/LoginViewModel.cs
deleted file mode 100644
index 278d2117..00000000
--- a/UnitystationLauncher/ViewModels/LoginViewModel.cs
+++ /dev/null
@@ -1,104 +0,0 @@
-using System;
-using System.Reactive;
-using System.Reactive.Concurrency;
-using System.Threading.Tasks;
-using ReactiveUI;
-using UnitystationLauncher.Models.ConfigFile;
-using UnitystationLauncher.Services;
-
-namespace UnitystationLauncher.ViewModels
-{
- public class LoginViewModel : ViewModelBase
- {
- private readonly Lazy _signUpVm;
- private readonly Lazy _forgotVm;
- private readonly Lazy _loginStatusVm;
- private readonly AuthService _authService;
- private readonly Config _config;
- string _email = "";
- string _password = "";
-
- public LoginViewModel(
- Lazy loginStatusVm,
- Lazy signUpVm,
- Lazy forgotVm,
- AuthService authService,
- Config config)
- {
- _authService = authService;
- _config = config;
- _signUpVm = signUpVm;
- _loginStatusVm = loginStatusVm;
- _forgotVm = forgotVm;
-
- var possibleCredentials = this.WhenAnyValue(
- x => x.Email,
- x => x.Password,
- (u, p) =>
- !string.IsNullOrWhiteSpace(u) &&
- !string.IsNullOrWhiteSpace(p));
-
- Login = ReactiveCommand.CreateFromTask(
- UserLoginAsync,
- possibleCredentials);
-
- Create = ReactiveCommand.Create(
- UserCreate);
-
- ForgotPw = ReactiveCommand.Create(
- ForgotPass);
-
- RxApp.MainThreadScheduler.ScheduleAsync((scheduler, ct) => CheckForLastLoginAsync());
- }
-
- public string Email
- {
- get => _email;
- set => this.RaiseAndSetIfChanged(ref _email, value);
- }
-
- public string Password
- {
- get => _password;
- set => this.RaiseAndSetIfChanged(ref _password, value);
- }
-
- public ReactiveCommand Login { get; }
- public ReactiveCommand Create { get; }
- public ReactiveCommand ForgotPw { get; }
-
- public async Task UserLoginAsync()
- {
- _authService.LoginMsg = new LoginMsg
- {
- Email = Email,
- Pass = Password
- };
-
- await SaveLoginEmailAsync();
-
- return _loginStatusVm.Value;
- }
-
- public SignUpViewModel UserCreate()
- {
- return _signUpVm.Value;
- }
-
- public ForgotPasswordViewModel ForgotPass()
- {
- return _forgotVm.Value;
- }
-
- async Task CheckForLastLoginAsync()
- {
- Email = (await _config.GetPreferencesAsync()).LastLogin ?? "";
- }
-
- async Task SaveLoginEmailAsync()
- {
- var prefs = await _config.GetPreferencesAsync();
- prefs.LastLogin = _email;
- }
- }
-}
diff --git a/UnitystationLauncher/ViewModels/MainWindowViewModel.cs b/UnitystationLauncher/ViewModels/MainWindowViewModel.cs
index 8d093554..3fff4f20 100644
--- a/UnitystationLauncher/ViewModels/MainWindowViewModel.cs
+++ b/UnitystationLauncher/ViewModels/MainWindowViewModel.cs
@@ -13,12 +13,7 @@ namespace UnitystationLauncher.ViewModels
{
public class MainWindowViewModel : ViewModelBase
{
- private readonly Lazy _launcherVm;
- private readonly Lazy _loginStatusVm;
- private readonly AuthService _authService;
- private readonly LoginViewModel _loginVm;
-
- ViewModelBase _content;
+ private ViewModelBase _content;
private Geometry _maximizeIcon;
private string _maximizeToolTip;
@@ -34,18 +29,11 @@ public string MaximizeToolTip
set => this.RaiseAndSetIfChanged(ref _maximizeToolTip, value);
}
- public MainWindowViewModel(LoginViewModel loginVm, Lazy loginStatusVm, Lazy launcherVm,
- AuthService authService)
+ public MainWindowViewModel(LauncherViewModel launcherVm)
{
- _loginStatusVm = loginStatusVm;
- _loginVm = loginVm;
- _authService = authService;
- _launcherVm = launcherVm;
- Content = _content = loginVm;
- authService.AttemptingAutoLogin = false;
_maximizeIcon = Geometry.Parse("M2048 2048v-2048h-2048v2048h2048zM1843 1843h-1638v-1638h1638v1638z");
_maximizeToolTip = "Maximize";
- RxApp.MainThreadScheduler.ScheduleAsync((_, _) => CheckForExistingUserAsync());
+ Content = _content = launcherVm;
}
private void Maximize()
@@ -74,95 +62,17 @@ private set
}
}
- async Task CheckForExistingUserAsync()
- {
- if (_authService.AuthLink != null)
- {
- _authService.AttemptingAutoLogin = true;
- Content = _loginStatusVm.Value;
- await AttemptAuthRefreshAsync();
- }
- }
-
- async Task AttemptAuthRefreshAsync()
- {
- if (_authService.AuthLink == null)
- {
- Log.Error("Login failed");
- Content = _loginVm;
- _authService.AttemptingAutoLogin = false;
- return;
- }
-
- RefreshToken refreshToken = new()
- {
- UserId = _authService.AuthLink.User.LocalId,
- Token = _authService.AuthLink.RefreshToken
- };
-
- string token = await _authService.GetCustomTokenAsync(refreshToken);
-
- if (string.IsNullOrEmpty(token))
- {
- Log.Error("Login failed");
- Content = _loginVm;
- _authService.AttemptingAutoLogin = false;
- return;
- }
-
- try
- {
- _authService.AuthLink = await _authService.SignInWithCustomTokenAsync(token);
- }
- catch (Exception e)
- {
- Log.Error(e, "Login failed");
- Content = _loginVm;
- _authService.AttemptingAutoLogin = false;
- return;
- }
-
- var user = await _authService.GetUpdatedUserAsync();
- if (!user.IsEmailVerified)
- {
- Content = _loginVm;
- _authService.AttemptingAutoLogin = false;
- return;
- }
- _authService.AttemptingAutoLogin = false;
- _authService.SaveAuthSettings();
- Content = _launcherVm.Value;
- }
-
private void ContentChanged()
{
SubscribeToVm(Content switch
{
- LoginViewModel loginVm => Observable.Merge(
- loginVm.Login.Select(vm => (ViewModelBase)vm),
- loginVm.Create.Select(vm => (ViewModelBase)vm),
- loginVm.ForgotPw.Select(vm => (ViewModelBase)vm)),
-
- LoginStatusViewModel loginStatusVm => Observable.Merge(
- loginStatusVm.GoBack.Select(vm => (ViewModelBase)vm),
- loginStatusVm.OpenLauncher.Select(vm => (ViewModelBase)vm)),
-
LauncherViewModel launcherVm => Observable.Merge(
- launcherVm.Logout.Select(vm => (ViewModelBase)vm),
launcherVm.ShowUpdateView.Select(vm => (ViewModelBase)vm)),
- SignUpViewModel signUpViewModel => Observable.Merge(
- signUpViewModel.Cancel,
- signUpViewModel.DoneButton),
-
HubUpdateViewModel hubUpdateViewModel => Observable.Merge(
hubUpdateViewModel.Skip,
hubUpdateViewModel.Ignore),
- ForgotPasswordViewModel forgotPasswordViewModel => Observable.Merge(
- forgotPasswordViewModel.DoneButton),
-
-
_ => throw new ArgumentException($"ViewModel type is not handled and will never be able to change")
});
}
diff --git a/UnitystationLauncher/ViewModels/ServerViewModel.cs b/UnitystationLauncher/ViewModels/ServerViewModel.cs
index b3841d8a..ce1d31f5 100644
--- a/UnitystationLauncher/ViewModels/ServerViewModel.cs
+++ b/UnitystationLauncher/ViewModels/ServerViewModel.cs
@@ -11,7 +11,6 @@
using Serilog;
using UnitystationLauncher.Models;
using UnitystationLauncher.Models.Api;
-using UnitystationLauncher.Services;
namespace UnitystationLauncher.ViewModels
{
@@ -27,14 +26,11 @@ public class ServerViewModel : ViewModelBase
public IObservable Downloading =>
Download?.WhenAnyValue(d => d.Active) ?? Observable.Return(false);
- private readonly AuthService _authService;
-
- public ServerViewModel(Server server, Installation? installation, Download? download, AuthService authService)
+ public ServerViewModel(Server server, Installation? installation, Download? download)
{
Server = server;
Installation = installation;
Download = download;
- _authService = authService;
RoundTrip = new();
try
@@ -81,8 +77,7 @@ private void PingCompletedCallback(object _, PingCompletedEventArgs eventArgs)
public void LaunchGame()
{
- Installation?.LaunchWithArgs(Server.ServerIp, (short)Server.ServerPort,
- _authService.CurrentRefreshToken, _authService.Uid);
+ Installation?.LaunchWithArgs(Server.ServerIp, (short)Server.ServerPort);
}
// Ping does not work in the Flatpak sandbox so we have to reconstruct its functionality in that case.
diff --git a/UnitystationLauncher/ViewModels/ServersPanelViewModel.cs b/UnitystationLauncher/ViewModels/ServersPanelViewModel.cs
index 177ea140..ce486202 100644
--- a/UnitystationLauncher/ViewModels/ServersPanelViewModel.cs
+++ b/UnitystationLauncher/ViewModels/ServersPanelViewModel.cs
@@ -12,19 +12,16 @@ namespace UnitystationLauncher.ViewModels
{
public class ServersPanelViewModel : PanelBase
{
- private readonly AuthService _authService;
private readonly StateService _stateService;
private readonly DownloadService _downloadService;
public override string Name => "Servers";
public override bool IsEnabled => true;
- public ServersPanelViewModel(StateService stateService, DownloadService downloadService,
- AuthService authService)
+ public ServersPanelViewModel(StateService stateService, DownloadService downloadService)
{
_stateService = stateService;
_downloadService = downloadService;
- _authService = authService;
DownloadCommand = ReactiveCommand.CreateFromTask(async server =>
{
@@ -38,8 +35,7 @@ public ServersPanelViewModel(StateService stateService, DownloadService download
public IObservable> ServerList => _stateService.State
.Select(state => state
.SelectMany(installationState => installationState.Value.Servers
- .Select(s => new ServerViewModel(s, installationState.Value.Installation,
- installationState.Value.Download, _authService)))
+ .Select(s => new ServerViewModel(s, installationState.Value.Installation, installationState.Value.Download)))
.ToList());
public IObservable ServersFound => ServerList.Select(sl => sl.Any());
diff --git a/UnitystationLauncher/ViewModels/SignUpViewModel.cs b/UnitystationLauncher/ViewModels/SignUpViewModel.cs
deleted file mode 100644
index d74cab90..00000000
--- a/UnitystationLauncher/ViewModels/SignUpViewModel.cs
+++ /dev/null
@@ -1,146 +0,0 @@
-using System;
-using System.Reactive;
-using System.Threading.Tasks;
-using ReactiveUI;
-using Serilog;
-using UnitystationLauncher.Services;
-
-namespace UnitystationLauncher.ViewModels
-{
- public class SignUpViewModel : ViewModelBase
- {
- private readonly AuthService _authService;
- private readonly Lazy _loginVm;
- string _email = "";
- string _password = "";
- string _username = "";
- private string? _creationMessage;
- private string? _endButtonText;
- private bool _isFormVisible;
- private bool _isWaitingVisible;
- private bool _isCreatedVisible;
-
- public string Username
- {
- get => _username;
- set => this.RaiseAndSetIfChanged(ref _username, value);
- }
-
- public string Email
- {
- get => _email;
- set => this.RaiseAndSetIfChanged(ref _email, value);
- }
-
- public string Password
- {
- get => _password;
- set => this.RaiseAndSetIfChanged(ref _password, value);
- }
-
- public bool IsFormVisible
- {
- get => _isFormVisible;
- set => this.RaiseAndSetIfChanged(ref _isFormVisible, value);
- }
-
- public bool IsCreatedVisible
- {
- get => _isCreatedVisible;
- set => this.RaiseAndSetIfChanged(ref _isCreatedVisible, value);
- }
-
- public bool IsWaitingVisible
- {
- get => _isWaitingVisible;
- set => this.RaiseAndSetIfChanged(ref _isWaitingVisible, value);
- }
-
- public string? CreationMessage
- {
- get => _creationMessage;
- set => this.RaiseAndSetIfChanged(ref _creationMessage, value);
- }
-
- public string? EndButtonText
- {
- get => _endButtonText;
- set => this.RaiseAndSetIfChanged(ref _endButtonText, value);
- }
-
- public ReactiveCommand Cancel { get; }
- public ReactiveCommand DoneButton { get; }
- public ReactiveCommand Submit { get; }
-
- public SignUpViewModel(AuthService authService, Lazy loginVm)
- {
- IsFormVisible = true;
- IsWaitingVisible = false;
- IsCreatedVisible = false;
- _authService = authService;
- _loginVm = loginVm;
- var possibleCredentials = this.WhenAnyValue(
- x => x.Email,
- x => x.Password,
- x => x.Username,
- (u, p, i) =>
- !string.IsNullOrWhiteSpace(u) &&
- !string.IsNullOrWhiteSpace(p) &&
- p.Length > 6 &&
- !string.IsNullOrEmpty(i));
-
- Submit = ReactiveCommand.CreateFromTask(
- UserCreateAsync, possibleCredentials);
-
- Cancel = ReactiveCommand.Create(ReturnToLogin);
-
- DoneButton = ReactiveCommand.Create(CreationEndButton);
- }
-
- public async Task UserCreateAsync()
- {
- IsFormVisible = false;
- var creationSuccess = true;
- IsWaitingVisible = true;
-
- try
- {
- await _authService.CreateAccountAsync(_username, _email, _password);
- }
- catch (Exception e)
- {
- Log.Error(e, "Login failed");
- creationSuccess = false;
- }
-
- if (creationSuccess)
- {
- CreationMessage = $"Success! An email has been sent to \r\n{_email}\r\n" +
- $"Please click the link in the email to verify\r\n" +
- $"your account before signing in.";
- EndButtonText = "Done";
- }
- else
- {
- CreationMessage = $"Something went wrong with the verification email server.\r\n" +
- $"A reset password email has been sent to {_email} as a work around.\r\n" +
- $"Please reset your password and try to log in.";
- _authService.SendForgotPasswordEmail(_email);
- EndButtonText = "Back";
- }
-
- IsWaitingVisible = false;
- IsCreatedVisible = true;
- }
-
- public LoginViewModel ReturnToLogin()
- {
- return _loginVm.Value;
- }
-
- public LoginViewModel CreationEndButton()
- {
- return _loginVm.Value;
- }
- }
-}
\ No newline at end of file
diff --git a/UnitystationLauncher/Views/ForgotPasswordView.xaml b/UnitystationLauncher/Views/ForgotPasswordView.xaml
deleted file mode 100644
index 1816dadf..00000000
--- a/UnitystationLauncher/Views/ForgotPasswordView.xaml
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
-
-
-
-
- Enter your email address:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A reset password email has been sent to your address.
- Please reset your password and try logging in again
-
-
-
-
-
-
\ No newline at end of file
diff --git a/UnitystationLauncher/Views/ForgotPasswordView.xaml.cs b/UnitystationLauncher/Views/ForgotPasswordView.xaml.cs
deleted file mode 100644
index 1f080729..00000000
--- a/UnitystationLauncher/Views/ForgotPasswordView.xaml.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using Avalonia.Controls;
-using Avalonia.Markup.Xaml;
-
-namespace UnitystationLauncher.Views
-{
- public class ForgotPasswordView : UserControl
- {
- public ForgotPasswordView()
- {
- InitializeComponent();
- }
-
- private void InitializeComponent()
- {
- AvaloniaXamlLoader.Load(this);
- }
- }
-}
\ No newline at end of file
diff --git a/UnitystationLauncher/Views/LauncherView.xaml b/UnitystationLauncher/Views/LauncherView.xaml
index 817395ee..aa08a96c 100644
--- a/UnitystationLauncher/Views/LauncherView.xaml
+++ b/UnitystationLauncher/Views/LauncherView.xaml
@@ -7,56 +7,12 @@
TextBlock.FontSize="18"
Background="Transparent"
x:Class="UnitystationLauncher.Views.LauncherView">
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -86,9 +42,9 @@
-
+
diff --git a/UnitystationLauncher/Views/LoginStatusView.xaml b/UnitystationLauncher/Views/LoginStatusView.xaml
deleted file mode 100644
index 1ff71533..00000000
--- a/UnitystationLauncher/Views/LoginStatusView.xaml
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/UnitystationLauncher/Views/LoginStatusView.xaml.cs b/UnitystationLauncher/Views/LoginStatusView.xaml.cs
deleted file mode 100644
index a6343de1..00000000
--- a/UnitystationLauncher/Views/LoginStatusView.xaml.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using Avalonia.Controls;
-using Avalonia.Markup.Xaml;
-
-namespace UnitystationLauncher.Views
-{
- public class LoginStatusView : UserControl
- {
- public LoginStatusView()
- {
- InitializeComponent();
- }
-
- private void InitializeComponent()
- {
- AvaloniaXamlLoader.Load(this);
- }
- }
-}
\ No newline at end of file
diff --git a/UnitystationLauncher/Views/LoginView.xaml b/UnitystationLauncher/Views/LoginView.xaml
deleted file mode 100644
index 56fbca58..00000000
--- a/UnitystationLauncher/Views/LoginView.xaml
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
- Login
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/UnitystationLauncher/Views/LoginView.xaml.cs b/UnitystationLauncher/Views/LoginView.xaml.cs
deleted file mode 100644
index 7cb6e70c..00000000
--- a/UnitystationLauncher/Views/LoginView.xaml.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using Avalonia.Controls;
-using Avalonia.Markup.Xaml;
-
-namespace UnitystationLauncher.Views
-{
- public class LoginView : UserControl
- {
- public LoginView()
- {
- InitializeComponent();
- }
-
- private void InitializeComponent()
- {
- AvaloniaXamlLoader.Load(this);
- }
- }
-}
\ No newline at end of file
diff --git a/UnitystationLauncher/Views/SignUpView.xaml b/UnitystationLauncher/Views/SignUpView.xaml
deleted file mode 100644
index 072aca12..00000000
--- a/UnitystationLauncher/Views/SignUpView.xaml
+++ /dev/null
@@ -1,90 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Create Account:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/UnitystationLauncher/Views/SignUpView.xaml.cs b/UnitystationLauncher/Views/SignUpView.xaml.cs
deleted file mode 100644
index 9445b0e1..00000000
--- a/UnitystationLauncher/Views/SignUpView.xaml.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using Avalonia.Controls;
-using Avalonia.Markup.Xaml;
-
-namespace UnitystationLauncher.Views
-{
- public class SignUpView : UserControl
- {
- public SignUpView()
- {
- InitializeComponent();
- }
-
- private void InitializeComponent()
- {
- AvaloniaXamlLoader.Load(this);
- }
- }
-}
\ No newline at end of file