diff --git a/Nebula.Launcher/CurrentConVar.cs b/Nebula.Launcher/CurrentConVar.cs index 06cb901..e528fac 100644 --- a/Nebula.Launcher/CurrentConVar.cs +++ b/Nebula.Launcher/CurrentConVar.cs @@ -17,7 +17,7 @@ public static class CurrentConVar "https://hub.spacestation14.com/api/servers" ]); public static readonly ConVar AuthServers = ConVarBuilder.Build("launcher.authServers", [ - "https://auth.spacestation14.com/api/auth" + "https://auth.spacestation14.com/" ]); public static readonly ConVar AuthProfiles = ConVarBuilder.Build("auth.profiles", []); diff --git a/Nebula.Launcher/FileApis/FileApi.cs b/Nebula.Launcher/FileApis/FileApi.cs index 5cc6a58..f2a7c45 100644 --- a/Nebula.Launcher/FileApis/FileApi.cs +++ b/Nebula.Launcher/FileApis/FileApi.cs @@ -35,7 +35,7 @@ public class FileApi : IReadWriteFileApi using var stream = File.OpenWrite(currPath); input.CopyTo(stream); - stream.Flush(true); + stream.Flush(); stream.Close(); return true; } diff --git a/Nebula.Launcher/Models/RobustUrl.cs b/Nebula.Launcher/Models/RobustUrl.cs index d4e024c..1c4a31d 100644 --- a/Nebula.Launcher/Models/RobustUrl.cs +++ b/Nebula.Launcher/Models/RobustUrl.cs @@ -22,7 +22,7 @@ public class RobustUrl public override string ToString() { - return HttpUri.ToString(); + return Uri.ToString(); } public static implicit operator Uri(RobustUrl url) diff --git a/Nebula.Launcher/Services/AuthService.cs b/Nebula.Launcher/Services/AuthService.cs index 2389bd5..56c603a 100644 --- a/Nebula.Launcher/Services/AuthService.cs +++ b/Nebula.Launcher/Services/AuthService.cs @@ -33,9 +33,9 @@ public partial class AuthService : ObservableObject var login = authLoginPassword.Login; var password = authLoginPassword.Password; - _debugService.Debug($"Auth to {authServer}/authenticate {login}"); + _debugService.Debug($"Auth to {authServer}api/auth/authenticate {login}"); - var authUrl = new Uri($"{authServer}/authenticate"); + var authUrl = new Uri($"{authServer}api/auth/authenticate"); var result = await _restService.PostAsync( @@ -57,7 +57,7 @@ public partial class AuthService : ObservableObject { if (SelectedAuth is null) return false; - var authUrl = new Uri($"{SelectedAuth.AuthLoginPassword.AuthServer}/ping"); + var authUrl = new Uri($"{SelectedAuth.AuthLoginPassword.AuthServer}api/auth/ping"); using var requestMessage = new HttpRequestMessage(HttpMethod.Get, authUrl); requestMessage.Headers.Authorization = new AuthenticationHeaderValue("SS14Auth", SelectedAuth.Token.Token); diff --git a/Nebula.Launcher/Services/ConfigurationService.cs b/Nebula.Launcher/Services/ConfigurationService.cs index ec04a43..d3b31cf 100644 --- a/Nebula.Launcher/Services/ConfigurationService.cs +++ b/Nebula.Launcher/Services/ConfigurationService.cs @@ -2,8 +2,6 @@ using System; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Text.Json; -using System.Text.Json.Serialization.Metadata; -using Nebula.Launcher.FileApis; namespace Nebula.Launcher.Services; @@ -12,10 +10,10 @@ public class ConVar public string Name { get; } public Type Type => typeof(T); public T? DefaultValue { get; } - - public ConVar(string name, T? defaultValue) + + public ConVar(string name, T? defaultValue = default) { - Name = name; + Name = name ?? throw new ArgumentNullException(nameof(name)); DefaultValue = defaultValue; } } @@ -24,6 +22,9 @@ public static class ConVarBuilder { public static ConVar Build(string name, T? defaultValue = default) { + if (string.IsNullOrWhiteSpace(name)) + throw new ArgumentException("ConVar name cannot be null or whitespace.", nameof(name)); + return new ConVar(name, defaultValue); } } @@ -36,78 +37,83 @@ public class ConfigurationService public ConfigurationService(FileService fileService, DebugService debugService) { - _fileService = fileService; - _debugService = debugService; + _fileService = fileService ?? throw new ArgumentNullException(nameof(fileService)); + _debugService = debugService ?? throw new ArgumentNullException(nameof(debugService)); } public T? GetConfigValue(ConVar conVar) { - if(!_fileService.ConfigurationApi.TryOpen(GetFileName(conVar), out var stream) || - !ReadStream(stream, out var obj)) - return conVar.DefaultValue; + ArgumentNullException.ThrowIfNull(conVar); - _debugService.Log("Loading config file: " + conVar.Name); - - return obj; - } - - public void SetConfigValue(ConVar conVar, object value) - { - if(conVar.Type != value.GetType()) - { - _debugService.Error("Error config file " + conVar.Name + ": Type is not equals " + value.GetType() + " " + conVar.Type); - return; - } - - _debugService.Log("Saving config file: " + conVar.Name); - WriteStream(conVar, value); - } - - private bool ReadStream(Stream stream,[NotNullWhen(true)] out T? obj) - { - obj = default; try { - obj = JsonSerializer.Deserialize(stream); - return obj != null; + if (_fileService.ConfigurationApi.TryOpen(GetFileName(conVar), out var stream)) + { + using (stream) + { + var obj = JsonSerializer.Deserialize(stream); + if (obj != null) + { + _debugService.Log($"Successfully loaded config: {conVar.Name}"); + return obj; + } + } + } } catch (Exception e) { - _debugService.Error(e); - return false; + _debugService.Error($"Error loading config for {conVar.Name}: {e.Message}"); } + + _debugService.Log($"Using default value for config: {conVar.Name}"); + return conVar.DefaultValue; } - private void WriteStream(ConVar conVar, object value) + public void SetConfigValue(ConVar conVar, T value) { - using var stream = new MemoryStream(); + ArgumentNullException.ThrowIfNull(conVar); + if (value == null) throw new ArgumentNullException(nameof(value)); + if (!conVar.Type.IsInstanceOfType(value)) + { + _debugService.Error($"Type mismatch for config {conVar.Name}. Expected {conVar.Type}, got {value.GetType()}."); + return; + } + try { - using var st = new StreamWriter(stream); - var ser = JsonSerializer.Serialize(value); - st.Write(ser); - st.Flush(); - stream.Seek(0, SeekOrigin.Begin); + _debugService.Log($"Saving config: {conVar.Name}"); + var serializedData = JsonSerializer.Serialize(value); + + using var stream = new MemoryStream(); + using (var writer = new StreamWriter(stream)) + { + writer.Write(serializedData); + writer.Flush(); + stream.Seek(0, SeekOrigin.Begin); + } + _fileService.ConfigurationApi.Save(GetFileName(conVar), stream); } catch (Exception e) { - _debugService.Error(e); + _debugService.Error($"Error saving config for {conVar.Name}: {e.Message}"); } } - private string GetFileName(ConVar conVar) + private static string GetFileName(ConVar conVar) { - return conVar.Name + ".json"; + return $"{conVar.Name}.json"; } } -public static class ConfigExt +public static class ConfigExtensions { - - public static bool TryGetConfigValue(this ConfigurationService configurationService,ConVar conVar, [NotNullWhen(true)] out T? value) + public static bool TryGetConfigValue(this ConfigurationService configurationService, ConVar conVar, [NotNullWhen(true)] out T? value) { + ArgumentNullException.ThrowIfNull(configurationService); + ArgumentNullException.ThrowIfNull(conVar); + value = configurationService.GetConfigValue(conVar); return value != null; } diff --git a/Nebula.Launcher/Services/RestService.cs b/Nebula.Launcher/Services/RestService.cs index c1ce229..87b5d24 100644 --- a/Nebula.Launcher/Services/RestService.cs +++ b/Nebula.Launcher/Services/RestService.cs @@ -8,6 +8,7 @@ using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using Nebula.Launcher.Utils; namespace Nebula.Launcher.Services; @@ -151,17 +152,4 @@ public class RawResult { return result.Result; } -} - - -public static class HttpExt -{ - public static readonly JsonSerializerOptions JsonWebOptions = new(JsonSerializerDefaults.Web); - - public static async Task AsJson(this HttpContent content) where T : notnull - { - var str = await content.ReadAsStringAsync(); - return JsonSerializer.Deserialize(str, JsonWebOptions) ?? - throw new JsonException("AsJson: did not expect null response"); - } } \ No newline at end of file diff --git a/Nebula.Launcher/Services/RunnerService.cs b/Nebula.Launcher/Services/RunnerService.cs index 213c999..711ae35 100644 --- a/Nebula.Launcher/Services/RunnerService.cs +++ b/Nebula.Launcher/Services/RunnerService.cs @@ -112,7 +112,7 @@ public class RunnerService: IRedialApi args.Add("--ss14-address"); args.Add(url.ToString()); - _debugService.Debug("Connect to " + url.ToString()); + _debugService.Debug("Connect to " + url.ToString() + " " + account.AuthLoginPassword.AuthServer); await Run(args.ToArray(), buildInfo, this, cancelTokenSource.Token); } diff --git a/Nebula.Launcher/Utils/Helper.cs b/Nebula.Launcher/Utils/Helper.cs new file mode 100644 index 0000000..4568cf6 --- /dev/null +++ b/Nebula.Launcher/Utils/Helper.cs @@ -0,0 +1,39 @@ +using System.Diagnostics; +using System.Net.Http; +using System.Runtime.InteropServices; +using System.Text.Json; +using System.Threading.Tasks; + +namespace Nebula.Launcher.Utils; + +public static class Helper +{ + public static readonly JsonSerializerOptions JsonWebOptions = new(JsonSerializerDefaults.Web); + + public static void OpenBrowser(string url) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Process.Start(new ProcessStartInfo("cmd", $"/c start {url}")); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + Process.Start("xdg-open", url); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + Process.Start("open", url); + } + else + { + + } + } + + public static async Task AsJson(this HttpContent content) where T : notnull + { + var str = await content.ReadAsStringAsync(); + return JsonSerializer.Deserialize(str, JsonWebOptions) ?? + throw new JsonException("AsJson: did not expect null response"); + } +} \ No newline at end of file diff --git a/Nebula.Launcher/ViewModels/MainViewModel.cs b/Nebula.Launcher/ViewModels/MainViewModel.cs index 11b7e59..910c2ca 100644 --- a/Nebula.Launcher/ViewModels/MainViewModel.cs +++ b/Nebula.Launcher/ViewModels/MainViewModel.cs @@ -7,6 +7,7 @@ using CommunityToolkit.Mvvm.Input; using JetBrains.Annotations; using Nebula.Launcher.Models; using Nebula.Launcher.Services; +using Nebula.Launcher.Utils; using Nebula.Launcher.ViewHelper; using Nebula.Launcher.Views; @@ -105,6 +106,11 @@ public partial class MainViewModel : ViewModelBase Popup = true; } + public void OpenLink() + { + Helper.OpenBrowser("https://cinka.ru/nebula-launcher/"); + } + private void OnPopupRequired(PopupViewModelBase? viewModelBase) { if (viewModelBase is null) diff --git a/Nebula.Launcher/Views/MainView.axaml b/Nebula.Launcher/Views/MainView.axaml index 5ea0102..c95ddcc 100644 --- a/Nebula.Launcher/Views/MainView.axaml +++ b/Nebula.Launcher/Views/MainView.axaml @@ -85,8 +85,10 @@ Padding="5">