Merge pull request 'Refactoring, namespace-imports and small improvements' (#18) from Schrader/SPT-AKI-Installer:refactoring/namespace-imports into master

Reviewed-on: CWX/SPT-AKI-Installer#18
This commit is contained in:
IsWaffle 2023-07-16 17:58:18 +00:00
commit 886770253a
46 changed files with 1964 additions and 2008 deletions

57
.editorconfig Normal file
View File

@ -0,0 +1,57 @@

[*]
charset = utf-8-bom
end_of_line = crlf
trim_trailing_whitespace = false
insert_final_newline = false
indent_style = space
indent_size = 4
# Microsoft .NET properties
csharp_style_namespace_declarations=file_scoped:error
csharp_new_line_before_members_in_object_initializers = false
csharp_preferred_modifier_order = public, private, protected, internal, file, new, static, abstract, virtual, sealed, readonly, override, extern, unsafe, volatile, async, required:warning
csharp_style_prefer_utf8_string_literals = true:suggestion
csharp_style_var_elsewhere = true:suggestion
csharp_style_var_for_built_in_types = true:warning
csharp_style_var_when_type_is_apparent = true:warning
dotnet_naming_style.lower_camel_case_style.capitalization = camel_case
dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:none
dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion
dotnet_style_qualification_for_event = false:suggestion
dotnet_style_qualification_for_field = false:suggestion
dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_property = false:suggestion
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
# ReSharper properties
resharper_autodetect_indent_settings = true
resharper_enforce_line_ending_style = true
resharper_formatter_off_tag = @formatter:off
resharper_formatter_on_tag = @formatter:on
resharper_formatter_tags_enabled = true
resharper_use_indent_from_vs = false
resharper_wrap_lines = true
# ReSharper inspection severities
resharper_arrange_redundant_parentheses_highlighting = hint
resharper_arrange_this_qualifier_highlighting = hint
resharper_arrange_type_member_modifiers_highlighting = hint
resharper_arrange_type_modifiers_highlighting = hint
resharper_built_in_type_reference_style_for_member_access_highlighting = hint
resharper_built_in_type_reference_style_highlighting = hint
resharper_redundant_base_qualifier_highlighting = warning
resharper_suggest_var_or_type_built_in_types_highlighting = hint
resharper_suggest_var_or_type_elsewhere_highlighting = hint
resharper_suggest_var_or_type_simple_types_highlighting = hint
resharper_web_config_module_not_resolved_highlighting = warning
resharper_web_config_type_not_resolved_highlighting = warning
resharper_web_config_wrong_module_highlighting = warning
[*.{appxmanifest,asax,ascx,aspx,axaml,build,c,c++,cc,cginc,compute,cp,cpp,cppm,cs,cshtml,cu,cuh,cxx,dtd,fs,fsi,fsscript,fsx,fx,fxh,h,hh,hlsl,hlsli,hlslinc,hpp,hxx,inc,inl,ino,ipp,ixx,master,ml,mli,mpp,mq4,mq5,mqh,nuspec,paml,razor,resw,resx,shader,skin,tpp,usf,ush,vb,xaml,xamlx,xoml,xsd}]
indent_style = space
indent_size = 4
tab_width = 4

View File

@ -4,10 +4,10 @@ using Avalonia.Markup.Xaml;
using SPTInstaller.ViewModels; using SPTInstaller.ViewModels;
using SPTInstaller.Views; using SPTInstaller.Views;
namespace SPTInstaller namespace SPTInstaller;
public partial class App : Application
{ {
public partial class App : Application
{
public override void Initialize() public override void Initialize()
{ {
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
@ -25,5 +25,4 @@ namespace SPTInstaller
base.OnFrameworkInitializationCompleted(); base.OnFrameworkInitializationCompleted();
} }
}
} }

View File

@ -1,10 +1,10 @@
using Avalonia; using Avalonia;
using Avalonia.Interactivity; using Avalonia.Interactivity;
namespace SPTInstaller.Behaviors namespace SPTInstaller.Behaviors;
public class SpanBehavior : AvaloniaObject
{ {
public class SpanBehavior : AvaloniaObject
{
public static readonly AttachedProperty<bool> SpanProperty = AvaloniaProperty.RegisterAttached<SpanBehavior, Interactive, bool>("Span"); public static readonly AttachedProperty<bool> SpanProperty = AvaloniaProperty.RegisterAttached<SpanBehavior, Interactive, bool>("Span");
public static void SetSpan(AvaloniaObject element, bool value) public static void SetSpan(AvaloniaObject element, bool value)
@ -16,5 +16,4 @@ namespace SPTInstaller.Behaviors
{ {
return element.GetValue(SpanProperty); return element.GetValue(SpanProperty);
} }
}
} }

View File

@ -2,14 +2,14 @@
using SharpCompress; using SharpCompress;
using SPTInstaller.Interfaces; using SPTInstaller.Interfaces;
using SPTInstaller.Models; using SPTInstaller.Models;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace SPTInstaller.Controllers namespace SPTInstaller.Controllers;
public class InstallController
{ {
public class InstallController
{
public event EventHandler<IProgressableTask> TaskChanged = delegate { }; public event EventHandler<IProgressableTask> TaskChanged = delegate { };
private IPreCheck[] _preChecks { get; set; } private IPreCheck[] _preChecks { get; set; }
@ -40,9 +40,8 @@ namespace SPTInstaller.Controllers
} }
} }
foreach(var result in requiredResults) if (requiredResults.Any(result => !result.Succeeded))
{ {
if (!result.Succeeded)
return Result.FromError("Some required checks have failed"); return Result.FromError("Some required checks have failed");
} }
@ -64,5 +63,4 @@ namespace SPTInstaller.Controllers
return Result.FromSuccess("Install Complete. Happy Playing!"); return Result.FromSuccess("Install Complete. Happy Playing!");
} }
}
} }

View File

@ -1,14 +1,13 @@
using Avalonia.Data.Converters; using System.Globalization;
using System; using Avalonia.Data.Converters;
using System.Globalization;
namespace SPTInstaller.Converters namespace SPTInstaller.Converters;
public class InvertedProgressConverter : IValueConverter
{ {
public class InvertedProgressConverter : IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{ {
if( value is int progress) if (value is int progress)
{ {
return 100 - progress; return 100 - progress;
} }
@ -18,12 +17,11 @@ namespace SPTInstaller.Converters
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{ {
if ( value is int invertedProgress) if (value is int invertedProgress)
{ {
return 100 - invertedProgress; return 100 - invertedProgress;
} }
return value; return value;
} }
}
} }

View File

@ -1,13 +1,12 @@
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using SPTInstaller.Behaviors; using SPTInstaller.Behaviors;
using System;
using System.Linq; using System.Linq;
namespace SPTInstaller.CustomControls namespace SPTInstaller.CustomControls;
public class DistributedSpacePanel : Panel
{ {
public class DistributedSpacePanel : Panel
{
protected override Size MeasureOverride(Size availableSize) protected override Size MeasureOverride(Size availableSize)
{ {
var children = Children; var children = Children;
@ -73,5 +72,4 @@ namespace SPTInstaller.CustomControls
return finalSize; return finalSize;
} }
}
} }

View File

@ -1,14 +1,10 @@
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Threading;
using ReactiveUI;
using System.Windows.Input;
namespace SPTInstaller.CustomControls namespace SPTInstaller.CustomControls;
public partial class PreCheckItem : UserControl
{ {
public partial class PreCheckItem : UserControl
{
public PreCheckItem() public PreCheckItem()
{ {
InitializeComponent(); InitializeComponent();
@ -58,5 +54,4 @@ namespace SPTInstaller.CustomControls
public static readonly StyledProperty<bool> IsRequiredProperty = public static readonly StyledProperty<bool> IsRequiredProperty =
AvaloniaProperty.Register<PreCheckItem, bool>(nameof(IsRequired)); AvaloniaProperty.Register<PreCheckItem, bool>(nameof(IsRequired));
}
} }

View File

@ -2,10 +2,10 @@ using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Media; using Avalonia.Media;
namespace SPTInstaller.CustomControls namespace SPTInstaller.CustomControls;
public partial class ProgressableTaskItem : UserControl
{ {
public partial class ProgressableTaskItem : UserControl
{
public ProgressableTaskItem() public ProgressableTaskItem()
{ {
InitializeComponent(); InitializeComponent();
@ -73,5 +73,4 @@ namespace SPTInstaller.CustomControls
public static readonly StyledProperty<IBrush> CompletedColorProperty = public static readonly StyledProperty<IBrush> CompletedColorProperty =
AvaloniaProperty.Register<ProgressableTaskItem, IBrush>(nameof(PendingColor)); AvaloniaProperty.Register<ProgressableTaskItem, IBrush>(nameof(PendingColor));
}
} }

View File

@ -2,18 +2,16 @@ using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Threading; using Avalonia.Threading;
using DynamicData;
using DynamicData.Binding; using DynamicData.Binding;
using SPTInstaller.Models; using SPTInstaller.Models;
using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace SPTInstaller.CustomControls namespace SPTInstaller.CustomControls;
public partial class ProgressableTaskList : UserControl
{ {
public partial class ProgressableTaskList : UserControl
{
public ProgressableTaskList() public ProgressableTaskList()
{ {
InitializeComponent(); InitializeComponent();
@ -93,5 +91,4 @@ namespace SPTInstaller.CustomControls
.Subscribe(x => UpdateTaskProgress()); .Subscribe(x => UpdateTaskProgress());
} }
} }
}
} }

View File

@ -1,10 +1,10 @@
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
namespace SPTInstaller.CustomControls namespace SPTInstaller.CustomControls;
public partial class TaskDetails : UserControl
{ {
public partial class TaskDetails : UserControl
{
public TaskDetails() public TaskDetails()
{ {
InitializeComponent(); InitializeComponent();
@ -54,5 +54,4 @@ namespace SPTInstaller.CustomControls
public static readonly StyledProperty<bool> IndeterminateProgressProperty = public static readonly StyledProperty<bool> IndeterminateProgressProperty =
AvaloniaProperty.Register<TaskDetails, bool>(nameof(IndeterminateProgress)); AvaloniaProperty.Register<TaskDetails, bool>(nameof(IndeterminateProgress));
}
} }

View File

@ -4,10 +4,10 @@ using Avalonia.Markup.Xaml;
using Avalonia.Media; using Avalonia.Media;
using System.Windows.Input; using System.Windows.Input;
namespace SPTInstaller.CustomControls namespace SPTInstaller.CustomControls;
public partial class TitleBar : UserControl
{ {
public partial class TitleBar : UserControl
{
public TitleBar() public TitleBar()
{ {
InitializeComponent(); InitializeComponent();
@ -73,5 +73,4 @@ namespace SPTInstaller.CustomControls
get => GetValue(MinButtonCommandProperty); get => GetValue(MinButtonCommandProperty);
set => SetValue(MinButtonCommandProperty, value); set => SetValue(MinButtonCommandProperty, value);
} }
}
} }

View File

@ -1,16 +1,13 @@
using HttpClientProgress; using System.Net.Http;
using System.Threading.Tasks;
using Serilog; using Serilog;
using SPTInstaller.Models; using SPTInstaller.Models;
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
namespace SPTInstaller.Aki.Helper namespace SPTInstaller.Helpers;
public static class DownloadCacheHelper
{ {
public static class DownloadCacheHelper private static HttpClient _httpClient = new() { Timeout = TimeSpan.FromHours(1) };
{
private static HttpClient _httpClient = new HttpClient() { Timeout = TimeSpan.FromHours(1) };
private static string _cachePath = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "spt-installer/cache"); private static string _cachePath = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "spt-installer/cache");
@ -111,7 +108,7 @@ namespace SPTInstaller.Aki.Helper
public static async Task<FileInfo?> GetOrDownloadFileAsync(string fileName, string targetLink, IProgress<double> progress, string expectedHash = null) public static async Task<FileInfo?> GetOrDownloadFileAsync(string fileName, string targetLink, IProgress<double> progress, string expectedHash = null)
{ {
FileInfo cacheFile = new FileInfo(Path.Join(_cachePath, fileName)); var cacheFile = new FileInfo(Path.Join(_cachePath, fileName));
try try
{ {
@ -128,7 +125,7 @@ namespace SPTInstaller.Aki.Helper
public static async Task<FileInfo?> GetOrDownloadFileAsync(string fileName, Stream fileDownloadStream, string expectedHash = null) public static async Task<FileInfo?> GetOrDownloadFileAsync(string fileName, Stream fileDownloadStream, string expectedHash = null)
{ {
FileInfo cacheFile = new FileInfo(Path.Join(_cachePath, fileName)); var cacheFile = new FileInfo(Path.Join(_cachePath, fileName));
try try
{ {
@ -142,5 +139,4 @@ namespace SPTInstaller.Aki.Helper
return null; return null;
} }
} }
}
} }

View File

@ -1,15 +1,13 @@
using Gitea.Model; using System.Linq;
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Gitea.Model;
namespace SPTInstaller.Aki.Helper namespace SPTInstaller.Helpers;
public static class FileHashHelper
{ {
public static class FileHashHelper public static string? GetGiteaReleaseHash(Release release)
{
public static string GetGiteaReleaseHash(Release release)
{ {
var regex = Regex.Match(release.Body, @"Release Hash: (?<hash>\S+)"); var regex = Regex.Match(release.Body, @"Release Hash: (?<hash>\S+)");
@ -23,16 +21,14 @@ namespace SPTInstaller.Aki.Helper
public static bool CheckHash(FileInfo file, string expectedHash) public static bool CheckHash(FileInfo file, string expectedHash)
{ {
using (MD5 md5Service = MD5.Create()) using var md5Service = MD5.Create();
using (var sourceStream = file.OpenRead()) using var sourceStream = file.OpenRead();
{
byte[] sourceHash = md5Service.ComputeHash(sourceStream);
byte[] expectedHashBytes = Convert.FromBase64String(expectedHash);
bool matched = Enumerable.SequenceEqual(sourceHash, expectedHashBytes); var sourceHash = md5Service.ComputeHash(sourceStream);
var expectedHashBytes = Convert.FromBase64String(expectedHash);
var matched = Enumerable.SequenceEqual(sourceHash, expectedHashBytes);
return matched; return matched;
} }
}
}
} }

View File

@ -1,14 +1,11 @@
using ReactiveUI; using System.Text.RegularExpressions;
using Serilog; using Serilog;
using SPTInstaller.Models; using SPTInstaller.Models;
using System;
using System.IO;
using System.Text.RegularExpressions;
namespace SPTInstaller.Aki.Helper namespace SPTInstaller.Helpers;
public static class FileHelper
{ {
public static class FileHelper
{
private static Result IterateDirectories(DirectoryInfo sourceDir, DirectoryInfo targetDir) private static Result IterateDirectories(DirectoryInfo sourceDir, DirectoryInfo targetDir)
{ {
try try
@ -86,5 +83,4 @@ namespace SPTInstaller.Aki.Helper
return Result.FromError(ex.Message); return Result.FromError(ex.Message);
} }
} }
}
} }

View File

@ -1,13 +1,11 @@
using System; using System.Net.Http;
using System.IO;
using System.Net.Http;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace HttpClientProgress namespace SPTInstaller.Helpers;
public static class HttpClientProgressExtensions
{ {
public static class HttpClientProgressExtensions
{
public static async Task DownloadDataAsync(this HttpClient client, string requestUrl, Stream destination, IProgress<double> progress = null, CancellationToken cancellationToken = default(CancellationToken)) public static async Task DownloadDataAsync(this HttpClient client, string requestUrl, Stream destination, IProgress<double> progress = null, CancellationToken cancellationToken = default(CancellationToken))
{ {
using (var response = await client.GetAsync(requestUrl, HttpCompletionOption.ResponseHeadersRead)) using (var response = await client.GetAsync(requestUrl, HttpCompletionOption.ResponseHeadersRead))
@ -53,5 +51,4 @@ namespace HttpClientProgress
progress?.Report(totalBytesRead); progress?.Report(totalBytesRead);
} }
} }
}
} }

View File

@ -1,14 +1,12 @@
using Microsoft.Win32; using System.Diagnostics;
using SPTInstaller.Models;
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Microsoft.Win32;
using SPTInstaller.Models;
namespace SPTInstaller.Aki.Helper namespace SPTInstaller.Helpers;
public static class PreCheckHelper
{ {
public static class PreCheckHelper
{
private const string registryInstall = @"Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\EscapeFromTarkov"; private const string registryInstall = @"Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\EscapeFromTarkov";
public static string DetectOriginalGamePath() public static string DetectOriginalGamePath()
@ -36,5 +34,4 @@ namespace SPTInstaller.Aki.Helper
return Result.FromError($"File not found: {ex.Message}"); return Result.FromError($"File not found: {ex.Message}");
} }
} }
}
} }

View File

@ -1,11 +1,10 @@
using SPTInstaller.Models; using System.Diagnostics;
using System.Diagnostics; using SPTInstaller.Models;
using System.IO;
namespace SPTInstaller.Aki.Helper namespace SPTInstaller.Helpers;
public enum PatcherExitCode
{ {
public enum PatcherExitCode
{
ProgramClosed = 0, ProgramClosed = 0,
Success = 10, Success = 10,
EftExeNotFound = 11, EftExeNotFound = 11,
@ -13,15 +12,16 @@ namespace SPTInstaller.Aki.Helper
MissingFile = 13, MissingFile = 13,
MissingDir = 14, MissingDir = 14,
PatchFailed = 15 PatchFailed = 15
} }
public static class ProcessHelper public static class ProcessHelper
{ {
public static Result PatchClientFiles(FileInfo executable, DirectoryInfo workingDir) public static Result PatchClientFiles(FileInfo executable, DirectoryInfo workingDir)
{ {
if (!executable.Exists || !workingDir.Exists) if (!executable.Exists || !workingDir.Exists)
{ {
return Result.FromError($"Could not find executable ({executable.Name}) or working directory ({workingDir.Name})"); return Result.FromError(
$"Could not find executable ({executable.Name}) or working directory ({workingDir.Name})");
} }
var process = new Process(); var process = new Process();
@ -57,5 +57,4 @@ namespace SPTInstaller.Aki.Helper
return Result.FromError("an unknown error occurred in the patcher"); return Result.FromError("an unknown error occurred in the patcher");
} }
} }
}
} }

View File

@ -1,17 +1,16 @@
using Serilog; using Serilog;
using Splat; using Splat;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace SPTInstaller.Helpers namespace SPTInstaller.Helpers;
/// <summary>
/// A helper class to handle simple service registration to Splat with constructor parameter injection
/// </summary>
/// <remarks>Splat only recognizes the registered types and doesn't account for interfaces :(</remarks>
internal static class ServiceHelper
{ {
/// <summary>
/// A helper class to handle simple service registration to Splat with constructor parameter injection
/// </summary>
/// <remarks>Splat only recognizes the registered types and doesn't account for interfaces :(</remarks>
internal static class ServiceHelper
{
private static bool TryRegisterInstance<T, T2>(object[] parameters = null) private static bool TryRegisterInstance<T, T2>(object[] parameters = null)
{ {
var instance = Activator.CreateInstance(typeof(T2), parameters); var instance = Activator.CreateInstance(typeof(T2), parameters);
@ -125,5 +124,4 @@ namespace SPTInstaller.Helpers
return services; return services;
} }
}
} }

View File

@ -1,15 +1,13 @@
using SharpCompress.Archives; using System.Linq;
using SharpCompress.Archives;
using SharpCompress.Archives.Zip; using SharpCompress.Archives.Zip;
using SharpCompress.Common; using SharpCompress.Common;
using SPTInstaller.Models; using SPTInstaller.Models;
using System;
using System.IO;
using System.Linq;
namespace SPTInstaller.Aki.Helper namespace SPTInstaller.Helpers;
public static class ZipHelper
{ {
public static class ZipHelper
{
public static Result Decompress(FileInfo ArchivePath, DirectoryInfo OutputFolderPath, IProgress<double> progress = null) public static Result Decompress(FileInfo ArchivePath, DirectoryInfo OutputFolderPath, IProgress<double> progress = null)
{ {
try try
@ -20,7 +18,7 @@ namespace SPTInstaller.Aki.Helper
using var archive = ZipArchive.Open(ArchivePath); using var archive = ZipArchive.Open(ArchivePath);
var totalEntries = archive.Entries.Where(entry => !entry.IsDirectory); var totalEntries = archive.Entries.Where(entry => !entry.IsDirectory);
int processedEntries = 0; var processedEntries = 0;
foreach (var entry in totalEntries) foreach (var entry in totalEntries)
{ {
@ -52,5 +50,4 @@ namespace SPTInstaller.Aki.Helper
return Result.FromError(ex.Message); return Result.FromError(ex.Message);
} }
} }
}
} }

View File

@ -1,15 +1,12 @@
using Serilog; using SPTInstaller.Interfaces;
using SPTInstaller.Aki.Helper;
using SPTInstaller.Interfaces;
using SPTInstaller.Models; using SPTInstaller.Models;
using System;
using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using SPTInstaller.Helpers;
namespace SPTInstaller.Installer_Tasks namespace SPTInstaller.Installer_Tasks;
public class CopyClientTask : InstallerTaskBase
{ {
public class CopyClientTask : InstallerTaskBase
{
private InternalData _data; private InternalData _data;
public CopyClientTask(InternalData data) : base("Copy Client Files") public CopyClientTask(InternalData data) : base("Copy Client Files")
@ -26,5 +23,4 @@ namespace SPTInstaller.Installer_Tasks
return FileHelper.CopyDirectoryWithProgress(originalGameDirInfo, targetInstallDirInfo, (message, progress) => { SetStatus(null, message, progress, null, true); }); return FileHelper.CopyDirectoryWithProgress(originalGameDirInfo, targetInstallDirInfo, (message, progress) => { SetStatus(null, message, progress, null, true); });
} }
}
} }

View File

@ -1,17 +1,15 @@
using CG.Web.MegaApiClient; using CG.Web.MegaApiClient;
using Newtonsoft.Json; using Newtonsoft.Json;
using SPTInstaller.Aki.Helper;
using SPTInstaller.Interfaces; using SPTInstaller.Interfaces;
using SPTInstaller.Models; using SPTInstaller.Models;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using SPTInstaller.Helpers;
namespace SPTInstaller.Installer_Tasks namespace SPTInstaller.Installer_Tasks;
public class DownloadTask : InstallerTaskBase
{ {
public class DownloadTask : InstallerTaskBase
{
private InternalData _data; private InternalData _data;
public DownloadTask(InternalData data) : base("Download Files") public DownloadTask(InternalData data) : base("Download Files")
@ -122,5 +120,4 @@ namespace SPTInstaller.Installer_Tasks
return Result.FromSuccess(); return Result.FromSuccess();
} }
}
} }

View File

@ -1,12 +1,12 @@
using SPTInstaller.Aki.Helper; using SPTInstaller.Interfaces;
using SPTInstaller.Interfaces;
using SPTInstaller.Models; using SPTInstaller.Models;
using System.Threading.Tasks; using System.Threading.Tasks;
using SPTInstaller.Helpers;
namespace SPTInstaller.Installer_Tasks namespace SPTInstaller.Installer_Tasks;
public class InitializationTask : InstallerTaskBase
{ {
public class InitializationTask : InstallerTaskBase
{
private InternalData _data; private InternalData _data;
public InitializationTask(InternalData data) : base("Startup") public InitializationTask(InternalData data) : base("Startup")
@ -55,5 +55,4 @@ namespace SPTInstaller.Installer_Tasks
return Result.FromSuccess($"Current Game Version: {_data.OriginalGameVersion}"); return Result.FromSuccess($"Current Game Version: {_data.OriginalGameVersion}");
} }
}
} }

View File

@ -1,12 +1,11 @@
using SPTInstaller.Models; using SPTInstaller.Models;
using System;
using System.Diagnostics; using System.Diagnostics;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace SPTInstaller.Installer_Tasks.PreChecks namespace SPTInstaller.Installer_Tasks.PreChecks;
public class NetCore6PreCheck : PreCheckBase
{ {
public class NetCore6PreCheck : PreCheckBase
{
public NetCore6PreCheck() : base(".Net Core 6 Desktop Runtime", false) public NetCore6PreCheck() : base(".Net Core 6 Desktop Runtime", false)
{ {
} }
@ -54,5 +53,4 @@ namespace SPTInstaller.Installer_Tasks.PreChecks
return false; return false;
} }
}
} }

View File

@ -1,12 +1,11 @@
using Microsoft.Win32; using Microsoft.Win32;
using SPTInstaller.Models; using SPTInstaller.Models;
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace SPTInstaller.Installer_Tasks.PreChecks namespace SPTInstaller.Installer_Tasks.PreChecks;
public class NetFramework472PreCheck : PreCheckBase
{ {
public class NetFramework472PreCheck : PreCheckBase
{
public NetFramework472PreCheck() : base(".Net Framework 4.7.2", false) public NetFramework472PreCheck() : base(".Net Framework 4.7.2", false)
{ {
} }
@ -42,5 +41,4 @@ namespace SPTInstaller.Installer_Tasks.PreChecks
return false; return false;
} }
} }
}
} }

View File

@ -1,15 +1,14 @@
using Gitea.Api; using Gitea.Api;
using Gitea.Client; using Gitea.Client;
using SPTInstaller.Aki.Helper;
using SPTInstaller.Interfaces; using SPTInstaller.Interfaces;
using SPTInstaller.Models; using SPTInstaller.Models;
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using SPTInstaller.Helpers;
namespace SPTInstaller.Installer_Tasks namespace SPTInstaller.Installer_Tasks;
public class ReleaseCheckTask : InstallerTaskBase
{ {
public class ReleaseCheckTask : InstallerTaskBase
{
private InternalData _data; private InternalData _data;
public ReleaseCheckTask(InternalData data) : base("Release Checks") public ReleaseCheckTask(InternalData data) : base("Release Checks")
@ -85,5 +84,4 @@ namespace SPTInstaller.Installer_Tasks
return Result.FromError($"Request Failed:\n{ex.Message}"); return Result.FromError($"Request Failed:\n{ex.Message}");
} }
} }
}
} }

View File

@ -1,15 +1,13 @@
using SPTInstaller.Aki.Helper; using SPTInstaller.Interfaces;
using SPTInstaller.Interfaces;
using SPTInstaller.Models; using SPTInstaller.Models;
using System;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using SPTInstaller.Helpers;
namespace SPTInstaller.Installer_Tasks namespace SPTInstaller.Installer_Tasks;
public class SetupClientTask : InstallerTaskBase
{ {
public class SetupClientTask : InstallerTaskBase
{
private InternalData _data; private InternalData _data;
public SetupClientTask(InternalData data) : base("Setup Client") public SetupClientTask(InternalData data) : base("Setup Client")
@ -84,5 +82,4 @@ namespace SPTInstaller.Installer_Tasks
return Result.FromSuccess("SPT is Setup. Happy Playing!"); return Result.FromSuccess("SPT is Setup. Happy Playing!");
} }
}
} }

View File

@ -1,12 +1,11 @@
using SPTInstaller.Interfaces; using SPTInstaller.Interfaces;
using SPTInstaller.Models; using SPTInstaller.Models;
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace SPTInstaller.Installer_Tasks namespace SPTInstaller.Installer_Tasks;
internal class TestTask : InstallerTaskBase
{ {
internal class TestTask : InstallerTaskBase
{
public static TestTask FromRandomName() => new TestTask($"Test Task #{new Random().Next(0, 9999)}"); public static TestTask FromRandomName() => new TestTask($"Test Task #{new Random().Next(0, 9999)}");
public TestTask(string name) : base(name) public TestTask(string name) : base(name)
@ -15,14 +14,14 @@ namespace SPTInstaller.Installer_Tasks
public async override Task<IResult> TaskOperation() public async override Task<IResult> TaskOperation()
{ {
int total = 4; var total = 4;
TimeSpan interval = TimeSpan.FromSeconds(1); var interval = TimeSpan.FromSeconds(1);
for(int i = 0; i < total; i++) for(var i = 0; i < total; i++)
{ {
var count = i + 1; var count = i + 1;
string progressMessage = $"Running Task: {Name}"; var progressMessage = $"Running Task: {Name}";
int progress = (int)Math.Floor((double)count / total * 100); var progress = (int)Math.Floor((double)count / total * 100);
SetStatus(progressMessage, $"Details: ({count}/{total})", progress); SetStatus(progressMessage, $"Details: ({count}/{total})", progress);
@ -31,5 +30,4 @@ namespace SPTInstaller.Installer_Tasks
return Result.FromSuccess(); return Result.FromSuccess();
} }
}
} }

View File

@ -1,9 +1,9 @@
using System.Threading.Tasks; using System.Threading.Tasks;
namespace SPTInstaller.Interfaces namespace SPTInstaller.Interfaces;
public interface IPreCheck
{ {
public interface IPreCheck
{
public string Id { get; } public string Id { get; }
public string Name { get; } public string Name { get; }
public bool IsRequired { get; } public bool IsRequired { get; }
@ -13,5 +13,4 @@ namespace SPTInstaller.Interfaces
public bool Passed { get; } public bool Passed { get; }
public Task<IResult> RunCheck(); public Task<IResult> RunCheck();
}
} }

View File

@ -1,9 +1,9 @@
using System.Threading.Tasks; using System.Threading.Tasks;
namespace SPTInstaller.Interfaces namespace SPTInstaller.Interfaces;
public interface IProgressableTask
{ {
public interface IProgressableTask
{
public string Id { get; } public string Id { get; }
public string Name { get; } public string Name { get; }
@ -20,5 +20,4 @@ namespace SPTInstaller.Interfaces
public bool ShowProgress { get; } public bool ShowProgress { get; }
public Task<IResult> RunAsync(); public Task<IResult> RunAsync();
}
} }

View File

@ -1,14 +1,7 @@
using System; namespace SPTInstaller.Interfaces;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SPTInstaller.Interfaces public interface IResult
{ {
public interface IResult
{
public bool Succeeded { get; } public bool Succeeded { get; }
public string Message { get; } public string Message { get; }
}
} }

View File

@ -1,8 +1,7 @@
namespace SPTInstaller.Models namespace SPTInstaller.Models;
public class DownloadMirror
{ {
public class DownloadMirror
{
public string Link { get; set; } public string Link { get; set; }
public string Hash { get; set; } public string Hash { get; set; }
}
} }

View File

@ -1,16 +1,12 @@
using Avalonia.Threading; using ReactiveUI;
using ReactiveUI;
using Serilog; using Serilog;
using Splat;
using SPTInstaller.Interfaces; using SPTInstaller.Interfaces;
using System;
using System.Security;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace SPTInstaller.Models namespace SPTInstaller.Models;
public abstract class InstallerTaskBase : ReactiveObject, IProgressableTask
{ {
public abstract class InstallerTaskBase : ReactiveObject, IProgressableTask
{
private string _id; private string _id;
public string Id public string Id
{ {
@ -179,5 +175,4 @@ namespace SPTInstaller.Models
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public abstract Task<IResult> TaskOperation(); public abstract Task<IResult> TaskOperation();
}
} }

View File

@ -1,10 +1,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
namespace SPTInstaller.Models namespace SPTInstaller.Models;
public class InternalData
{ {
public class InternalData
{
/// <summary> /// <summary>
/// The folder to install SPT into /// The folder to install SPT into
/// </summary> /// </summary>
@ -54,5 +53,4 @@ namespace SPTInstaller.Models
/// Whether or not a patch is needed to downgrade the client files /// Whether or not a patch is needed to downgrade the client files
/// </summary> /// </summary>
public bool PatchNeeded { get; set; } public bool PatchNeeded { get; set; }
}
} }

View File

@ -1,12 +1,11 @@
using ReactiveUI; using ReactiveUI;
using SPTInstaller.Interfaces; using SPTInstaller.Interfaces;
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace SPTInstaller.Models namespace SPTInstaller.Models;
public abstract class PreCheckBase : ReactiveObject, IPreCheck
{ {
public abstract class PreCheckBase : ReactiveObject, IPreCheck
{
private string _id; private string _id;
public string Id public string Id
{ {
@ -72,5 +71,4 @@ namespace SPTInstaller.Models
} }
public abstract Task<bool> CheckOperation(); public abstract Task<bool> CheckOperation();
}
} }

View File

@ -1,9 +1,9 @@
using SPTInstaller.Interfaces; using SPTInstaller.Interfaces;
namespace SPTInstaller.Models namespace SPTInstaller.Models;
public class Result : IResult
{ {
public class Result : IResult
{
public bool Succeeded { get; private set; } public bool Succeeded { get; private set; }
public string Message { get; private set; } public string Message { get; private set; }
@ -14,7 +14,6 @@ namespace SPTInstaller.Models
Succeeded = succeeded; Succeeded = succeeded;
} }
public static Result FromSuccess(string message = "") => new Result(message, true); public static Result FromSuccess(string message = "") => new(message, true);
public static Result FromError(string message) => new Result(message, false); public static Result FromError(string message) => new(message, false);
}
} }

View File

@ -12,10 +12,10 @@ using SPTInstaller.Models;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
namespace SPTInstaller namespace SPTInstaller;
internal class Program
{ {
internal class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any // Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break. // yet and stuff might break.
@ -71,5 +71,4 @@ namespace SPTInstaller
.LogToTrace() .LogToTrace()
.UseReactiveUI(); .UseReactiveUI();
} }
}
} }

View File

@ -1,12 +1,11 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Templates; using Avalonia.Controls.Templates;
using SPTInstaller.ViewModels; using SPTInstaller.ViewModels;
using System;
namespace SPTInstaller namespace SPTInstaller;
public class ViewLocator : IDataTemplate
{ {
public class ViewLocator : IDataTemplate
{
public IControl Build(object data) public IControl Build(object data)
{ {
var name = data.GetType().FullName!.Replace("ViewModel", "View"); var name = data.GetType().FullName!.Replace("ViewModel", "View");
@ -24,5 +23,4 @@ namespace SPTInstaller
{ {
return data is ViewModelBase; return data is ViewModelBase;
} }
}
} }

View File

@ -4,13 +4,12 @@ using SPTInstaller.Helpers;
using SPTInstaller.Interfaces; using SPTInstaller.Interfaces;
using SPTInstaller.Models; using SPTInstaller.Models;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace SPTInstaller.ViewModels namespace SPTInstaller.ViewModels;
public class InstallViewModel : ViewModelBase
{ {
public class InstallViewModel : ViewModelBase
{
private IProgressableTask _currentTask; private IProgressableTask _currentTask;
public IProgressableTask CurrentTask public IProgressableTask CurrentTask
{ {
@ -18,8 +17,7 @@ namespace SPTInstaller.ViewModels
set => this.RaiseAndSetIfChanged(ref _currentTask, value); set => this.RaiseAndSetIfChanged(ref _currentTask, value);
} }
public ObservableCollection<InstallerTaskBase> MyTasks { get; set; } public ObservableCollection<InstallerTaskBase> MyTasks { get; set; } = new(ServiceHelper.GetAll<InstallerTaskBase>());
= new ObservableCollection<InstallerTaskBase>(ServiceHelper.GetAll<InstallerTaskBase>());
public InstallViewModel(IScreen host) : base(host) public InstallViewModel(IScreen host) : base(host)
{ {
@ -34,5 +32,4 @@ namespace SPTInstaller.ViewModels
NavigateTo(new MessageViewModel(HostScreen, result)); NavigateTo(new MessageViewModel(HostScreen, result));
}); });
} }
}
} }

View File

@ -1,15 +1,14 @@
using Avalonia; using Avalonia;
using ReactiveUI; using ReactiveUI;
using Serilog; using Serilog;
using System;
using System.Reflection; using System.Reflection;
namespace SPTInstaller.ViewModels namespace SPTInstaller.ViewModels;
public class MainWindowViewModel : ReactiveObject, IActivatableViewModel, IScreen
{ {
public class MainWindowViewModel : ReactiveObject, IActivatableViewModel, IScreen public RoutingState Router { get; } = new();
{ public ViewModelActivator Activator { get; } = new();
public RoutingState Router { get; } = new RoutingState();
public ViewModelActivator Activator { get; } = new ViewModelActivator();
private string _title; private string _title;
public string Title public string Title
@ -46,5 +45,4 @@ namespace SPTInstaller.ViewModels
} }
} }
}
} }

View File

@ -4,10 +4,10 @@ using Serilog;
using SPTInstaller.Interfaces; using SPTInstaller.Interfaces;
using System.Windows.Input; using System.Windows.Input;
namespace SPTInstaller.ViewModels namespace SPTInstaller.ViewModels;
public class MessageViewModel : ViewModelBase
{ {
public class MessageViewModel : ViewModelBase
{
private bool _HasErrors; private bool _HasErrors;
public bool HasErrors public bool HasErrors
{ {
@ -43,5 +43,4 @@ namespace SPTInstaller.ViewModels
HasErrors = true; HasErrors = true;
Log.Error(Message); Log.Error(Message);
} }
}
} }

View File

@ -2,7 +2,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
using ReactiveUI; using ReactiveUI;
using SPTInstaller.Aki.Helper;
using SPTInstaller.Controllers; using SPTInstaller.Controllers;
using SPTInstaller.Helpers; using SPTInstaller.Helpers;
using SPTInstaller.Models; using SPTInstaller.Models;

View File

@ -1,13 +1,12 @@
using Avalonia.Threading; using Avalonia.Threading;
using ReactiveUI; using ReactiveUI;
using System.Threading.Tasks; using System.Threading.Tasks;
using System;
namespace SPTInstaller.ViewModels namespace SPTInstaller.ViewModels;
public class ViewModelBase : ReactiveObject, IActivatableViewModel, IRoutableViewModel
{ {
public class ViewModelBase : ReactiveObject, IActivatableViewModel, IRoutableViewModel public ViewModelActivator Activator { get; } = new();
{
public ViewModelActivator Activator { get; } = new ViewModelActivator();
public string? UrlPathSegment => Guid.NewGuid().ToString().Substring(0, 7); public string? UrlPathSegment => Guid.NewGuid().ToString().Substring(0, 7);
@ -56,6 +55,4 @@ namespace SPTInstaller.ViewModels
{ {
HostScreen = Host; HostScreen = Host;
} }
}
} }

View File

@ -1,14 +1,12 @@
using Avalonia.Controls;
using Avalonia.ReactiveUI; using Avalonia.ReactiveUI;
using SPTInstaller.ViewModels; using SPTInstaller.ViewModels;
namespace SPTInstaller.Views namespace SPTInstaller.Views;
public partial class InstallView : ReactiveUserControl<InstallViewModel>
{ {
public partial class InstallView : ReactiveUserControl<InstallViewModel>
{
public InstallView() public InstallView()
{ {
InitializeComponent(); InitializeComponent();
} }
}
} }

View File

@ -1,12 +1,11 @@
using Avalonia.Controls; using Avalonia.Controls;
namespace SPTInstaller.Views namespace SPTInstaller.Views;
public partial class MainWindow : Window
{ {
public partial class MainWindow : Window
{
public MainWindow() public MainWindow()
{ {
InitializeComponent(); InitializeComponent();
} }
}
} }

View File

@ -1,14 +1,12 @@
using Avalonia.Controls;
using Avalonia.ReactiveUI; using Avalonia.ReactiveUI;
using SPTInstaller.ViewModels; using SPTInstaller.ViewModels;
namespace SPTInstaller.Views namespace SPTInstaller.Views;
public partial class MessageView : ReactiveUserControl<MessageViewModel>
{ {
public partial class MessageView : ReactiveUserControl<MessageViewModel>
{
public MessageView() public MessageView()
{ {
InitializeComponent(); InitializeComponent();
} }
}
} }

View File

@ -1,13 +1,12 @@
using Avalonia.ReactiveUI; using Avalonia.ReactiveUI;
using SPTInstaller.ViewModels; using SPTInstaller.ViewModels;
namespace SPTInstaller.Views namespace SPTInstaller.Views;
public partial class PreChecksView : ReactiveUserControl<PreChecksViewModel>
{ {
public partial class PreChecksView : ReactiveUserControl<PreChecksViewModel>
{
public PreChecksView() public PreChecksView()
{ {
InitializeComponent(); InitializeComponent();
} }
}
} }