diff --git a/.editorconfig b/.editorconfig index 24eda6c4..655a6ab3 100644 --- a/.editorconfig +++ b/.editorconfig @@ -115,79 +115,22 @@ csharp_space_between_method_call_empty_parameter_list_parentheses = false # Wrapping preferences csharp_preserve_single_line_statements = true csharp_preserve_single_line_blocks = true + ############################### # C# Async Rules # ############################### # CS4014: Task not awaited dotnet_diagnostic.CS4014.severity = error + # CS1998: Async function does not contain await dotnet_diagnostic.CS1998.severity = silent ############################### -# C# Nullability # +# Other # ############################### -# CS8602: Dereference of a possibly null reference. -dotnet_diagnostic.CS8602.severity = error -# CS8600: Converting null literal or possible null value to non-nullable type. -dotnet_diagnostic.CS8600.severity = error +# CS1591: Missing XML comment for publicly visible type or member +dotnet_diagnostic.CS1591.severity = silent -# CS8619: Nullability of reference types in value doesn't match target type. -dotnet_diagnostic.CS8619.severity = error - -# CS8603: Possible null reference return. -dotnet_diagnostic.CS8603.severity = error - -# CS8625: Cannot convert null literal to non-nullable reference type. -dotnet_diagnostic.CS8625.severity = error - -# CS8653: A default expression introduces a null value for a type parameter. -dotnet_diagnostic.CS8653.severity = silent - -# CS8601: Possible null reference assignment. -dotnet_diagnostic.CS8601.severity = error - -# CS8604: Possible null reference argument. -dotnet_diagnostic.CS8604.severity = error - -# CS8622: Nullability of reference types in type of parameter doesn't match the target delegate. -dotnet_diagnostic.CS8622.severity = error - -# CS8610: Nullability of reference types in type of parameter doesn't match overridden member. -dotnet_diagnostic.CS8610.severity = error - -# CS8618: Non-nullable field is uninitialized. Consider declaring as nullable. -dotnet_diagnostic.CS8618.severity = error - -# CS8629: Nullable value type may be null. -dotnet_diagnostic.CS8629.severity = error - -# CS8620: Argument cannot be used for parameter due to differences in the nullability of reference types. -dotnet_diagnostic.CS8620.severity = error - -# CS8614: Nullability of reference types in type of parameter doesn't match implicitly implemented member. -dotnet_diagnostic.CS8614.severity = error - -# CS8617: Nullability of reference types in type of parameter doesn't match implemented member. -dotnet_diagnostic.CS8617.severity = error - -# CS8611: Nullability of reference types in type of parameter doesn't match partial method declaration. -dotnet_diagnostic.CS8611.severity = error - -# CS8597: Thrown value may be null. -dotnet_diagnostic.CS8597.severity = error - -# CS8609: Nullability of reference types in return type doesn't match overridden member. -dotnet_diagnostic.CS8609.severity = error - -# CS8714: The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'notnull' constraint. -dotnet_diagnostic.CS8714.severity = error - -# CS8605: Unboxing a possibly null value. -dotnet_diagnostic.CS8605.severity = error - -# CS8613: Nullability of reference types in return type doesn't match implicitly implemented member. -dotnet_diagnostic.CS8613.severity = error - -# CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. -dotnet_diagnostic.CS8632.severity = error \ No newline at end of file +dotnet_diagnostic.CS1701.severity = silent +dotnet_diagnostic.CS1702.severity = silent diff --git a/.gitignore b/.gitignore index 79d51ade..be0bef12 100644 --- a/.gitignore +++ b/.gitignore @@ -366,3 +366,9 @@ MigrationBackup/ # Ionide (cross platform F# VS Code tools) working folder .ionide/ /.idea + +Compression.BSA/Compression.BSA.xml + +Wabbajack.Common/Wabbajack.Common.xml + +Wabbajack.VirtualFileSystem/Wabbajack.VirtualFileSystem.xml diff --git a/Compression.BSA.Test/BSATests.cs b/Compression.BSA.Test/BSATests.cs index 5f8a7036..92d1aa63 100644 --- a/Compression.BSA.Test/BSATests.cs +++ b/Compression.BSA.Test/BSATests.cs @@ -93,10 +93,11 @@ namespace Compression.BSA.Test _tempDir.CreateDirectory(); TestContext.WriteLine($"Reading {bsa}"); - var tempFile = ((RelativePath)"tmp.bsa").RelativeToEntryPoint(); + await using var tempFolder = await TempFolder.Create(); + var tempFile = tempFolder.Dir.Combine("test.bsa"); var size = bsa.Size; - await using var a = await BSADispatch.OpenRead(bsa); + var a = await BSADispatch.OpenRead(bsa); await a.Files.PMap(Queue, async file => { var absName = _tempDir.Combine(file.Path); @@ -132,7 +133,7 @@ namespace Compression.BSA.Test } TestContext.WriteLine($"Verifying {bsa}"); - await using var b = await BSADispatch.OpenRead(tempFile); + var b = await BSADispatch.OpenRead(tempFile); TestContext.WriteLine($"Performing A/B tests on {bsa}"); Assert.Equal(a.State.ToJson(), b.State.ToJson()); diff --git a/Compression.BSA/BSADispatch.cs b/Compression.BSA/BSADispatch.cs index a208b03c..fec3073c 100644 --- a/Compression.BSA/BSADispatch.cs +++ b/Compression.BSA/BSADispatch.cs @@ -19,7 +19,7 @@ namespace Compression.BSA if (fourcc == TES3Reader.TES3_MAGIC) return await TES3Reader.Load(filename); if (fourcc == "BSA\0") - return await BSAReader.Load(filename); + return await BSAReader.LoadWithRetry(filename); if (fourcc == "BTDX") return await BA2Reader.Load(filename); throw new InvalidDataException("Filename is not a .bsa or .ba2, magic " + fourcc); diff --git a/Compression.BSA/BSAReader.cs b/Compression.BSA/BSAReader.cs index ff1e7cea..6858c4a8 100644 --- a/Compression.BSA/BSAReader.cs +++ b/Compression.BSA/BSAReader.cs @@ -50,7 +50,7 @@ namespace Compression.BSA Miscellaneous = 0x100 } - public class BSAReader : IAsyncDisposable, IBSAReader + public class BSAReader : IBSAReader { internal uint _archiveFlags; internal uint _fileCount; @@ -60,8 +60,6 @@ namespace Compression.BSA internal uint _folderRecordOffset; private List _folders; internal string _magic; - private BinaryReader _rdr; - private Stream _stream; internal uint _totalFileNameLength; internal uint _totalFolderNameLength; internal uint _version; @@ -79,15 +77,21 @@ namespace Compression.BSA } } - - public static async ValueTask Load(AbsolutePath filename) + public static async ValueTask LoadWithRetry(AbsolutePath filename) { using var stream = await filename.OpenRead(); using var br = new BinaryReader(stream); - var bsa = new BSAReader {_rdr = br, _stream = stream, _fileName = filename}; - await bsa.LoadHeaders(); - bsa._rdr = null; - bsa._stream = null; + var bsa = new BSAReader { _fileName = filename }; + bsa.LoadHeaders(br); + return bsa; + } + + public static BSAReader Load(AbsolutePath filename) + { + using var stream = File.Open(filename.ToString(), FileMode.Open, FileAccess.Read, FileShare.Read); + using var br = new BinaryReader(stream); + var bsa = new BSAReader { _fileName = filename }; + bsa.LoadHeaders(br); return bsa; } @@ -107,7 +111,7 @@ namespace Compression.BSA public ArchiveFlags ArchiveFlags => (ArchiveFlags) _archiveFlags; - public FileFlags FileFlags => (FileFlags) _archiveFlags; + public FileFlags FileFlags => (FileFlags)_fileFlags; public bool HasFolderNames => (_archiveFlags & 0x1) > 0; @@ -127,42 +131,38 @@ namespace Compression.BSA } } - public async ValueTask DisposeAsync() + private void LoadHeaders(BinaryReader rdr) { - } - - private async ValueTask LoadHeaders() - { - var fourcc = Encoding.ASCII.GetString(_rdr.ReadBytes(4)); + var fourcc = Encoding.ASCII.GetString(rdr.ReadBytes(4)); if (fourcc != "BSA\0") throw new InvalidDataException("Archive is not a BSA"); _magic = fourcc; - _version = _rdr.ReadUInt32(); - _folderRecordOffset = _rdr.ReadUInt32(); - _archiveFlags = _rdr.ReadUInt32(); - _folderCount = _rdr.ReadUInt32(); - _fileCount = _rdr.ReadUInt32(); - _totalFolderNameLength = _rdr.ReadUInt32(); - _totalFileNameLength = _rdr.ReadUInt32(); - _fileFlags = _rdr.ReadUInt32(); + _version = rdr.ReadUInt32(); + _folderRecordOffset = rdr.ReadUInt32(); + _archiveFlags = rdr.ReadUInt32(); + _folderCount = rdr.ReadUInt32(); + _fileCount = rdr.ReadUInt32(); + _totalFolderNameLength = rdr.ReadUInt32(); + _totalFileNameLength = rdr.ReadUInt32(); + _fileFlags = rdr.ReadUInt32(); - LoadFolderRecords(); + LoadFolderRecords(rdr); } - private void LoadFolderRecords() + private void LoadFolderRecords(BinaryReader rdr) { _folders = new List(); for (var idx = 0; idx < _folderCount; idx += 1) - _folders.Add(new FolderRecord(this, _rdr)); + _folders.Add(new FolderRecord(this, rdr)); foreach (var folder in _folders) - folder.LoadFileRecordBlock(this, _rdr); + folder.LoadFileRecordBlock(this, rdr); foreach (var folder in _folders) foreach (var file in folder._files) - file.LoadFileRecord(this, folder, file, _rdr); + file.LoadFileRecord(this, folder, file, rdr); } } diff --git a/Compression.BSA/Compression.BSA.csproj b/Compression.BSA/Compression.BSA.csproj index df9cbff7..cf206971 100644 --- a/Compression.BSA/Compression.BSA.csproj +++ b/Compression.BSA/Compression.BSA.csproj @@ -1,10 +1,15 @@  - netcoreapp3.1 - true - x64 - win10-x64 + netstandard2.1 + true + x64 + win10-x64 + 3.0 + true + + + Compression.BSA.xml diff --git a/Compression.BSA/IBSAReader.cs b/Compression.BSA/IBSAReader.cs index 77071005..46f6ca4b 100644 --- a/Compression.BSA/IBSAReader.cs +++ b/Compression.BSA/IBSAReader.cs @@ -6,7 +6,7 @@ using Wabbajack.Common; namespace Compression.BSA { - public interface IBSAReader : IAsyncDisposable + public interface IBSAReader { /// /// The files defined by the archive diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 00000000..0aa2a398 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,5 @@ + + + nullable + + diff --git a/Wabbajack.CLI/Verbs/BSADump.cs b/Wabbajack.CLI/Verbs/BSADump.cs index 49519f6f..0c1c55ca 100644 --- a/Wabbajack.CLI/Verbs/BSADump.cs +++ b/Wabbajack.CLI/Verbs/BSADump.cs @@ -14,7 +14,7 @@ namespace Wabbajack.CLI.Verbs protected override async Task Run() { - await using var bsa = await BSADispatch.OpenRead(Input.RelativeTo(AbsolutePath.GetCurrentDirectory())); + var bsa = await BSADispatch.OpenRead(Input.RelativeTo(AbsolutePath.GetCurrentDirectory())); bsa.Dump(Console.WriteLine); return ExitCode.Ok; } diff --git a/Wabbajack.Common/Extensions/TaskExt.cs b/Wabbajack.Common/Extensions/TaskExt.cs index 35a8a177..8eb4624a 100644 --- a/Wabbajack.Common/Extensions/TaskExt.cs +++ b/Wabbajack.Common/Extensions/TaskExt.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using Wabbajack.Common; namespace Wabbajack { @@ -12,9 +13,15 @@ namespace Wabbajack await task.ConfigureAwait(false); } catch (Exception ex) - when (onException != null) { - onException(ex); + if (onException == null) + { + Utils.Error(ex); + } + else + { + onException(ex); + } } } diff --git a/Wabbajack.Common/Json.cs b/Wabbajack.Common/Json.cs index d91ff8ae..78c6b611 100644 --- a/Wabbajack.Common/Json.cs +++ b/Wabbajack.Common/Json.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Reflection; @@ -52,7 +53,7 @@ namespace Wabbajack.Common public static void ToJson(this T obj, Stream stream) { - using var tw = new StreamWriter(stream, Encoding.UTF8, leaveOpen: true); + using var tw = new StreamWriter(stream, Encoding.UTF8, bufferSize: 1024, leaveOpen: true); using var writer = new JsonTextWriter(tw); var ser = JsonSerializer.Create(JsonSettings); ser.Serialize(writer, obj); @@ -81,7 +82,7 @@ namespace Wabbajack.Common public static T FromJson(this Stream stream, bool genericReader = false) { - using var tr = new StreamReader(stream, Encoding.UTF8, leaveOpen: true); + using var tr = new StreamReader(stream, Encoding.UTF8, bufferSize: 1024, detectEncodingFromByteOrderMarks: false, leaveOpen: true); using var reader = new JsonTextReader(tr); var ser = JsonSerializer.Create(genericReader ? GenericJsonSettings : JsonSettings); var result = ser.Deserialize(reader); @@ -244,14 +245,12 @@ namespace Wabbajack.Common public class IPathConverter : JsonConverter { - public override void WriteJson(JsonWriter writer, IPath value, JsonSerializer serializer) + public override void WriteJson(JsonWriter writer, [AllowNull] IPath value, JsonSerializer serializer) { writer.WriteValue(Enum.GetName(typeof(Game), value)); } - public override IPath ReadJson(JsonReader reader, Type objectType, IPath existingValue, - bool hasExistingValue, - JsonSerializer serializer) + public override IPath ReadJson(JsonReader reader, Type objectType, [AllowNull] IPath existingValue, bool hasExistingValue, JsonSerializer serializer) { // Backwards compatibility support var str = reader.Value?.ToString(); @@ -260,7 +259,6 @@ namespace Wabbajack.Common if (Path.IsPathRooted(str)) return (AbsolutePath)str; return (RelativePath)str; - } } diff --git a/Wabbajack.Common/Utils.cs b/Wabbajack.Common/Utils.cs index 591356d9..06394170 100644 --- a/Wabbajack.Common/Utils.cs +++ b/Wabbajack.Common/Utils.cs @@ -439,7 +439,8 @@ namespace Wabbajack.Common /// /// /// - public static IEnumerable Keep(this IEnumerable coll, Func func) where TOut : IComparable + public static IEnumerable Keep(this IEnumerable coll, Func func) + where TOut : struct, IComparable { return coll.Select(func).Where(v => v.CompareTo(default) != 0); } diff --git a/Wabbajack.Common/Wabbajack.Common.csproj b/Wabbajack.Common/Wabbajack.Common.csproj index 8184d06c..247751cb 100644 --- a/Wabbajack.Common/Wabbajack.Common.csproj +++ b/Wabbajack.Common/Wabbajack.Common.csproj @@ -1,12 +1,12 @@  - netcoreapp3.1 + netstandard2.1 x64 win10-x64 enable true - 2.0.9.1 + 3.0 Wabbajack Common Lib Wabbajack Team 2020 @@ -14,6 +14,11 @@ https://raw.githubusercontent.com/wabbajack-tools/wabbajack/master/LICENSE.txt https://www.wabbajack.org/favicon.ico https://github.com/wabbajack-tools/wabbajack + 3.0 + + + Wabbajack.Common.xml + diff --git a/Wabbajack.Lib/AuthorApi/Client.cs b/Wabbajack.Lib/AuthorApi/Client.cs index 8c64c826..a129ea89 100644 --- a/Wabbajack.Lib/AuthorApi/Client.cs +++ b/Wabbajack.Lib/AuthorApi/Client.cs @@ -18,20 +18,20 @@ namespace Wabbajack.Lib.AuthorApi return new Client(client); } - private Client(Common.Http.Client client) + private Client(Wabbajack.Lib.Http.Client client) { _client = client; } - public static async Task GetAuthorizedClient(string? apiKey = null) + public static async Task GetAuthorizedClient(string? apiKey = null) { - var client = new Common.Http.Client(); + var client = new Wabbajack.Lib.Http.Client(); client.Headers.Add(("X-API-KEY", await GetAPIKey(apiKey))); return client; } public static string? ApiKeyOverride = null; - private Common.Http.Client _client; + private Wabbajack.Lib.Http.Client _client; public static async ValueTask GetAPIKey(string? apiKey = null) { diff --git a/Wabbajack.Lib/ClientAPI.cs b/Wabbajack.Lib/ClientAPI.cs index 37b75759..bfa1356a 100644 --- a/Wabbajack.Lib/ClientAPI.cs +++ b/Wabbajack.Lib/ClientAPI.cs @@ -45,9 +45,9 @@ using Wabbajack.Lib.Downloaders; public class ClientAPI { - public static async Task GetClient() + public static async Task GetClient() { - var client = new Common.Http.Client(); + var client = new Wabbajack.Lib.Http.Client(); client.Headers.Add((Consts.MetricsKeyHeader, await Metrics.GetMetricsKey())); return client; } diff --git a/Wabbajack.Lib/CompilationSteps/DeconstructBSAs.cs b/Wabbajack.Lib/CompilationSteps/DeconstructBSAs.cs index b6e1f36c..daa6abc9 100644 --- a/Wabbajack.Lib/CompilationSteps/DeconstructBSAs.cs +++ b/Wabbajack.Lib/CompilationSteps/DeconstructBSAs.cs @@ -20,7 +20,7 @@ namespace Wabbajack.Lib.CompilationSteps public DeconstructBSAs(ACompiler compiler) : base(compiler) { - _mo2Compiler = (MO2Compiler) compiler; + _mo2Compiler = (MO2Compiler)compiler; _includeDirectly = _mo2Compiler.ModInis.Where(kv => { var general = kv.Value.General; @@ -60,10 +60,10 @@ namespace Wabbajack.Lib.CompilationSteps if (_includeDirectly.Any(path => source.Path.StartsWith(path))) defaultInclude = true; - if (source.AbsolutePath.Size >= (long) 2 << 31) + if (source.AbsolutePath.Size >= (long)2 << 31) { - await using var bsa = await BSADispatch.OpenRead(source.AbsolutePath); - if (bsa.State is BSAStateObject) + var bsaTest = await BSADispatch.OpenRead(source.AbsolutePath); + if (bsaTest.State is BSAStateObject) { Utils.Error( $"BSA {source.AbsolutePath.FileName} is over 2GB in size, very few programs (Including Wabbajack) can create BSA files this large without causing CTD issues." + @@ -83,7 +83,7 @@ namespace Wabbajack.Lib.CompilationSteps { _cleanup = await source.File.Context.Stage(source.File.Children); } - + var matches = await sourceFiles.PMap(_mo2Compiler.Queue, e => _mo2Compiler.RunStack(stack, new RawSourceFile(e, Consts.BSACreationDir.Combine((RelativePath)id, (RelativePath)e.Name)))); @@ -95,16 +95,14 @@ namespace Wabbajack.Lib.CompilationSteps } CreateBSA directive; - await using (var bsa = await BSADispatch.OpenRead(source.AbsolutePath)) + var bsa = await BSADispatch.OpenRead(source.AbsolutePath); + directive = new CreateBSA( + state: bsa.State, + items: bsa.Files.Select(f => f.State).ToList()) { - directive = new CreateBSA( - state: bsa.State, - items: bsa.Files.Select(f => f.State).ToList()) - { - To = source.Path, - TempID = (RelativePath)id, - }; - } + To = source.Path, + TempID = (RelativePath)id, + }; if (_cleanup != null) await _cleanup(); diff --git a/Wabbajack.Lib/Downloaders/AbstractNeedsLoginDownloader.cs b/Wabbajack.Lib/Downloaders/AbstractNeedsLoginDownloader.cs index 4f197f3c..7e16c014 100644 --- a/Wabbajack.Lib/Downloaders/AbstractNeedsLoginDownloader.cs +++ b/Wabbajack.Lib/Downloaders/AbstractNeedsLoginDownloader.cs @@ -26,7 +26,7 @@ namespace Wabbajack.Lib.Downloaders // ToDo // Remove null assignment. Either add nullability to type, or figure way to prepare it safely - public Common.Http.Client AuthedClient { get; private set; } = null!; + public Wabbajack.Lib.Http.Client AuthedClient { get; private set; } = null!; public ReactiveCommand TriggerLogin { get; } public ReactiveCommand ClearLogin { get; } @@ -57,8 +57,8 @@ namespace Wabbajack.Lib.Downloaders TriggerLogin = ReactiveCommand.CreateFromTask( execute: () => Utils.CatchAndLog(async () => await Utils.Log(new RequestSiteLogin(this)).Task), canExecute: IsLoggedIn.Select(b => !b).ObserveOnGuiThread()); - ClearLogin = ReactiveCommand.Create( - execute: () => Utils.CatchAndLog(() => Utils.DeleteEncryptedJson(_encryptedKeyName)), + ClearLogin = ReactiveCommand.CreateFromTask( + execute: () => Utils.CatchAndLog(async () => await Utils.DeleteEncryptedJson(_encryptedKeyName)), canExecute: IsLoggedIn.ObserveOnGuiThread()); } @@ -86,7 +86,7 @@ namespace Wabbajack.Lib.Downloaders return cookies; } - public async Task GetAuthedClient() + public async Task GetAuthedClient() { Helpers.Cookie[] cookies; try diff --git a/Wabbajack.Lib/Downloaders/BethesdaNetDownloader.cs b/Wabbajack.Lib/Downloaders/BethesdaNetDownloader.cs index 60a76337..86dd905c 100644 --- a/Wabbajack.Lib/Downloaders/BethesdaNetDownloader.cs +++ b/Wabbajack.Lib/Downloaders/BethesdaNetDownloader.cs @@ -43,7 +43,7 @@ namespace Wabbajack.Lib.Downloaders public BethesdaNetDownloader() { TriggerLogin = ReactiveCommand.CreateFromTask(() => Utils.CatchAndLog(RequestLoginAndCache), IsLoggedIn.Select(b => !b).ObserveOn(RxApp.MainThreadScheduler)); - ClearLogin = ReactiveCommand.Create(() => Utils.CatchAndLog(() =>Utils.DeleteEncryptedJson(DataName)), IsLoggedIn.ObserveOn(RxApp.MainThreadScheduler)); + ClearLogin = ReactiveCommand.CreateFromTask(() => Utils.CatchAndLog(async () => await Utils.DeleteEncryptedJson(DataName)), IsLoggedIn.ObserveOn(RxApp.MainThreadScheduler)); } private static async Task RequestLoginAndCache() @@ -216,13 +216,13 @@ namespace Wabbajack.Lib.Downloaders return true; } - private async Task<(Common.Http.Client, CDPTree, CollectedBNetInfo)> ResolveDownloadInfo() + private async Task<(Wabbajack.Lib.Http.Client, CDPTree, CollectedBNetInfo)> ResolveDownloadInfo() { var info = new CollectedBNetInfo(); var login_info = await Utils.FromEncryptedJson(DataName); - var client = new Common.Http.Client(); + var client = new Wabbajack.Lib.Http.Client(); client.Headers.Add(("User-Agent", "bnet")); foreach (var header in login_info.headers.Where(h => h.Key.ToLower().StartsWith("x-"))) diff --git a/Wabbajack.Lib/Downloaders/GoogleDriveDownloader.cs b/Wabbajack.Lib/Downloaders/GoogleDriveDownloader.cs index 76a5b2f6..1c8f0d3f 100644 --- a/Wabbajack.Lib/Downloaders/GoogleDriveDownloader.cs +++ b/Wabbajack.Lib/Downloaders/GoogleDriveDownloader.cs @@ -59,7 +59,7 @@ namespace Wabbajack.Lib.Downloaders private async Task ToHttpState() { var initialURL = $"https://drive.google.com/uc?id={Id}&export=download"; - var client = new Common.Http.Client(); + var client = new Wabbajack.Lib.Http.Client(); using var response = await client.GetAsync(initialURL); if (!response.IsSuccessStatusCode) throw new HttpException((int)response.StatusCode, response.ReasonPhrase); diff --git a/Wabbajack.Lib/Downloaders/HTTPDownloader.cs b/Wabbajack.Lib/Downloaders/HTTPDownloader.cs index 3f0df7a2..92e33807 100644 --- a/Wabbajack.Lib/Downloaders/HTTPDownloader.cs +++ b/Wabbajack.Lib/Downloaders/HTTPDownloader.cs @@ -54,7 +54,7 @@ namespace Wabbajack.Lib.Downloaders public List Headers { get; } = new List(); [JsonIgnore] - public Common.Http.Client? Client { get; set; } + public Wabbajack.Lib.Http.Client? Client { get; set; } [JsonIgnore] public override object[] PrimaryKey => new object[] { Url }; diff --git a/Wabbajack.Lib/Downloaders/INeedsLogin.cs b/Wabbajack.Lib/Downloaders/INeedsLogin.cs index b9aae38e..38dad7f5 100644 --- a/Wabbajack.Lib/Downloaders/INeedsLogin.cs +++ b/Wabbajack.Lib/Downloaders/INeedsLogin.cs @@ -1,6 +1,7 @@ using System; using System.Reactive; using System.Security; +using System.Threading.Tasks; using ReactiveUI; namespace Wabbajack.Lib.Downloaders @@ -39,6 +40,6 @@ namespace Wabbajack.Lib.Downloaders public interface INeedsLoginCredentials : INeedsLogin { - LoginReturnMessage LoginWithCredentials(string username, SecureString password, string? mfa); + Task LoginWithCredentials(string username, SecureString password, string? mfa); } } diff --git a/Wabbajack.Lib/Downloaders/MEGADownloader.cs b/Wabbajack.Lib/Downloaders/MEGADownloader.cs index 4a1fb2c0..4c928d74 100644 --- a/Wabbajack.Lib/Downloaders/MEGADownloader.cs +++ b/Wabbajack.Lib/Downloaders/MEGADownloader.cs @@ -49,7 +49,7 @@ namespace Wabbajack.Lib.Downloaders } } - public LoginReturnMessage LoginWithCredentials(string username, SecureString password, string? mfa) + public async Task LoginWithCredentials(string username, SecureString password, string? mfa) { MegaApiClient.AuthInfos authInfos; @@ -57,7 +57,7 @@ namespace Wabbajack.Lib.Downloaders { MegaApiClient.Logout(); } - catch (NotSupportedException ex) + catch (NotSupportedException) { // Not logged in, so ignore } @@ -101,7 +101,7 @@ namespace Wabbajack.Lib.Downloaders if (MegaApiClient.IsLoggedIn) { var infos = MEGAAuthInfos.ToMEGAAuthInfos(authInfos); - infos.ToEcryptedJson(DataName); + await infos.ToEcryptedJson(DataName); } return new LoginReturnMessage("Logged in successfully, you can now close this window.", @@ -115,7 +115,7 @@ namespace Wabbajack.Lib.Downloaders TriggerLogin = ReactiveCommand.Create(() => { }, IsLoggedIn.Select(b => !b).ObserveOnGuiThread()); - ClearLogin = ReactiveCommand.Create(() => Utils.CatchAndLog(() => Utils.DeleteEncryptedJson(DataName)), + ClearLogin = ReactiveCommand.CreateFromTask(() => Utils.CatchAndLog(async () => await Utils.DeleteEncryptedJson(DataName)), IsLoggedIn.ObserveOnGuiThread()); } diff --git a/Wabbajack.Lib/Downloaders/MediaFireDownloader.cs b/Wabbajack.Lib/Downloaders/MediaFireDownloader.cs index 2cbb4757..6bb1ad90 100644 --- a/Wabbajack.Lib/Downloaders/MediaFireDownloader.cs +++ b/Wabbajack.Lib/Downloaders/MediaFireDownloader.cs @@ -50,7 +50,7 @@ namespace Wabbajack.Lib.Downloaders private async Task Resolve() { - var client = new Common.Http.Client(); + var client = new Wabbajack.Lib.Http.Client(); var body = await client.GetHtmlAsync(Url); var node = body.DocumentNode.DescendantsAndSelf().First(d => d.HasClass("input") && d.HasClass("popsok") && d.GetAttributeValue("aria-label", "") == "Download file"); diff --git a/Wabbajack.Lib/Downloaders/NexusDownloader.cs b/Wabbajack.Lib/Downloaders/NexusDownloader.cs index 9235e458..9f83853f 100644 --- a/Wabbajack.Lib/Downloaders/NexusDownloader.cs +++ b/Wabbajack.Lib/Downloaders/NexusDownloader.cs @@ -46,8 +46,8 @@ namespace Wabbajack.Lib.Downloaders TriggerLogin = ReactiveCommand.CreateFromTask( execute: () => Utils.CatchAndLog(NexusApiClient.RequestAndCacheAPIKey), canExecute: IsLoggedIn.Select(b => !b).ObserveOnGuiThread()); - ClearLogin = ReactiveCommand.Create( - execute: () => Utils.CatchAndLog(() => Utils.DeleteEncryptedJson("nexusapikey")), + ClearLogin = ReactiveCommand.CreateFromTask( + execute: () => Utils.CatchAndLog(async () => await Utils.DeleteEncryptedJson("nexusapikey")), canExecute: IsLoggedIn.ObserveOnGuiThread()); } diff --git a/Wabbajack.Lib/Downloaders/UrlDownloaders/YoutubeInferencer.cs b/Wabbajack.Lib/Downloaders/UrlDownloaders/YoutubeInferencer.cs index a1c19239..fd34d2d8 100644 --- a/Wabbajack.Lib/Downloaders/UrlDownloaders/YoutubeInferencer.cs +++ b/Wabbajack.Lib/Downloaders/UrlDownloaders/YoutubeInferencer.cs @@ -16,7 +16,7 @@ namespace Wabbajack.Lib.Downloaders.UrlDownloaders var state = YouTubeDownloader.UriToState(uri) as YouTubeDownloader.State; if (state == null) return null; - var client = new YoutubeClient(Common.Http.ClientFactory.Client); + var client = new YoutubeClient(Wabbajack.Lib.Http.ClientFactory.Client); var video = await client.Videos.GetAsync(state.Key); var desc = video.Description; diff --git a/Wabbajack.Lib/Downloaders/WabbajackCDNDownloader.cs b/Wabbajack.Lib/Downloaders/WabbajackCDNDownloader.cs index 1f14b7c6..452381fe 100644 --- a/Wabbajack.Lib/Downloaders/WabbajackCDNDownloader.cs +++ b/Wabbajack.Lib/Downloaders/WabbajackCDNDownloader.cs @@ -59,7 +59,7 @@ namespace Wabbajack.Lib.Downloaders var definition = await GetDefinition(); await using var fs = await destination.Create(); using var mmfile = MemoryMappedFile.CreateFromFile(fs, null, definition.Size, MemoryMappedFileAccess.ReadWrite, HandleInheritability.None, false); - var client = new Common.Http.Client(); + var client = new Wabbajack.Lib.Http.Client(); using var queue = new WorkQueue(); await definition.Parts.PMap(queue, async part => { @@ -81,7 +81,7 @@ namespace Wabbajack.Lib.Downloaders private async Task GetDefinition() { - var client = new Common.Http.Client(); + var client = new Wabbajack.Lib.Http.Client(); using var data = await client.GetAsync(Url + "/definition.json.gz"); await using var gz = new GZipStream(await data.Content.ReadAsStreamAsync(), CompressionMode.Decompress); return gz.FromJson(); diff --git a/Wabbajack.Lib/Downloaders/YandexDownloader.cs b/Wabbajack.Lib/Downloaders/YandexDownloader.cs index 1bc5acfd..b309495f 100644 --- a/Wabbajack.Lib/Downloaders/YandexDownloader.cs +++ b/Wabbajack.Lib/Downloaders/YandexDownloader.cs @@ -61,7 +61,7 @@ namespace Wabbajack.Lib.Downloaders public override async Task Verify(Archive archive) { - var client = new Common.Http.Client(); + var client = new Wabbajack.Lib.Http.Client(); var result = await client.GetAsync(Url, errorsAsExceptions: false); return result.IsSuccessStatusCode; } diff --git a/Wabbajack.Lib/Downloaders/YouTubeDownloader.cs b/Wabbajack.Lib/Downloaders/YouTubeDownloader.cs index 0462b04b..13fae83d 100644 --- a/Wabbajack.Lib/Downloaders/YouTubeDownloader.cs +++ b/Wabbajack.Lib/Downloaders/YouTubeDownloader.cs @@ -104,7 +104,7 @@ namespace Wabbajack.Lib.Downloaders using var queue = new WorkQueue(); await using var folder = await TempFolder.Create(); folder.Dir.Combine("tracks").CreateDirectory(); - var client = new YoutubeClient(Common.Http.ClientFactory.Client); + var client = new YoutubeClient(Wabbajack.Lib.Http.ClientFactory.Client); var meta = await client.Videos.GetAsync(Key); var video = await client.Videos.Streams.GetManifestAsync(Key); var stream = video.Streams.OfType().Where(f => f.AudioCodec.StartsWith("mp4a")).OrderByDescending(a => a.Bitrate) @@ -210,7 +210,7 @@ namespace Wabbajack.Lib.Downloaders { try { - var client = new YoutubeClient(Common.Http.ClientFactory.Client); + var client = new YoutubeClient(Wabbajack.Lib.Http.ClientFactory.Client); var video = await client.Videos.GetAsync(Key); return true; } diff --git a/Wabbajack.Lib/FileUploader/AuthorAPI.cs b/Wabbajack.Lib/FileUploader/AuthorAPI.cs index 4c75364c..0a24f6ac 100644 --- a/Wabbajack.Lib/FileUploader/AuthorAPI.cs +++ b/Wabbajack.Lib/FileUploader/AuthorAPI.cs @@ -29,9 +29,9 @@ namespace Wabbajack.Lib.FileUploader return apiKey ?? (await Consts.LocalAppDataPath.Combine(Consts.AuthorAPIKeyFile).ReadAllTextAsync()).Trim(); } - public static async Task GetAuthorizedClient(string? apiKey = null) + public static async Task GetAuthorizedClient(string? apiKey = null) { - var client = new Common.Http.Client(); + var client = new Wabbajack.Lib.Http.Client(); client.Headers.Add(("X-API-KEY", await GetAPIKey(apiKey))); return client; } diff --git a/Wabbajack.Common/Http/Client.cs b/Wabbajack.Lib/Http/Client.cs similarity index 99% rename from Wabbajack.Common/Http/Client.cs rename to Wabbajack.Lib/Http/Client.cs index 05192dd4..0f8fcc55 100644 --- a/Wabbajack.Common/Http/Client.cs +++ b/Wabbajack.Lib/Http/Client.cs @@ -6,9 +6,10 @@ using System.Net; using System.Net.Http; using System.Threading.Tasks; using HtmlAgilityPack; +using Wabbajack.Common; using Wabbajack.Common.Exceptions; -namespace Wabbajack.Common.Http +namespace Wabbajack.Lib.Http { public class Client { diff --git a/Wabbajack.Common/Http/ClientFactory.cs b/Wabbajack.Lib/Http/ClientFactory.cs similarity index 96% rename from Wabbajack.Common/Http/ClientFactory.cs rename to Wabbajack.Lib/Http/ClientFactory.cs index 29cb1936..0ec211bb 100644 --- a/Wabbajack.Common/Http/ClientFactory.cs +++ b/Wabbajack.Lib/Http/ClientFactory.cs @@ -1,7 +1,8 @@ using System; using System.Net; using SysHttp = System.Net.Http; -namespace Wabbajack.Common.Http + +namespace Wabbajack.Lib.Http { public static class ClientFactory { diff --git a/Wabbajack.Lib/LibCefHelpers/Init.cs b/Wabbajack.Lib/LibCefHelpers/Init.cs index 5976b180..67695563 100644 --- a/Wabbajack.Lib/LibCefHelpers/Init.cs +++ b/Wabbajack.Lib/LibCefHelpers/Init.cs @@ -18,9 +18,9 @@ namespace Wabbajack.Lib.LibCefHelpers { public static class Helpers { - public static Common.Http.Client GetClient(IEnumerable cookies, string referer) + public static Wabbajack.Lib.Http.Client GetClient(IEnumerable cookies, string referer) { - var client = new Common.Http.Client(); + var client = new Wabbajack.Lib.Http.Client(); client.Headers.Add(("Referrer", referer)); client.Cookies.AddRange(cookies.Select(cookie => new System.Net.Cookie(cookie.Name, cookie.Value, cookie.Path, cookie.Domain))); return client; diff --git a/Wabbajack.Lib/MO2Compiler.cs b/Wabbajack.Lib/MO2Compiler.cs index e4c1c3e6..2cbfb1ea 100644 --- a/Wabbajack.Lib/MO2Compiler.cs +++ b/Wabbajack.Lib/MO2Compiler.cs @@ -521,7 +521,7 @@ namespace Wabbajack.Lib var bsaId = (RelativePath)((string)to).Split('\\')[1]; var bsa = InstallDirectives.OfType().First(b => b.TempID == bsaId); - await using var a = await BSADispatch.OpenRead(MO2Folder.Combine(bsa.To)); + var a = await BSADispatch.OpenRead(MO2Folder.Combine(bsa.To)); var find = (RelativePath)Path.Combine(((string)to).Split('\\').Skip(2).ToArray()); var file = a.Files.First(e => e.Path == find); var returnStream = new TempStream(); diff --git a/Wabbajack.Common/Metrics.cs b/Wabbajack.Lib/Metrics.cs similarity index 98% rename from Wabbajack.Common/Metrics.cs rename to Wabbajack.Lib/Metrics.cs index bd11580f..623e5a23 100644 --- a/Wabbajack.Common/Metrics.cs +++ b/Wabbajack.Lib/Metrics.cs @@ -7,9 +7,10 @@ using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using Microsoft.Win32; +using Wabbajack.Common; using Wabbajack.Common.Exceptions; -namespace Wabbajack.Common +namespace Wabbajack.Lib { public class Metrics { diff --git a/Wabbajack.Lib/ModListRegistry/ModListMetadata.cs b/Wabbajack.Lib/ModListRegistry/ModListMetadata.cs index d1513bc4..f8516ec4 100644 --- a/Wabbajack.Lib/ModListRegistry/ModListMetadata.cs +++ b/Wabbajack.Lib/ModListRegistry/ModListMetadata.cs @@ -62,7 +62,7 @@ namespace Wabbajack.Lib.ModListRegistry public static async Task> LoadFromGithub() { - var client = new Common.Http.Client(); + var client = new Wabbajack.Lib.Http.Client(); Utils.Log("Loading ModLists from GitHub"); var metadataResult = client.GetStringAsync(Consts.ModlistMetadataURL); var summaryResult = client.GetStringAsync(Consts.ModlistSummaryURL); diff --git a/Wabbajack.Lib/NexusApi/NexusApi.cs b/Wabbajack.Lib/NexusApi/NexusApi.cs index 349d1b57..72dd7864 100644 --- a/Wabbajack.Lib/NexusApi/NexusApi.cs +++ b/Wabbajack.Lib/NexusApi/NexusApi.cs @@ -11,7 +11,6 @@ using Wabbajack.Common; using Wabbajack.Lib.Downloaders; using System.Threading; using Wabbajack.Common.Exceptions; -using Wabbajack.Common.Http; using Wabbajack.Lib.WebAutomation; namespace Wabbajack.Lib.NexusApi @@ -20,7 +19,7 @@ namespace Wabbajack.Lib.NexusApi { private static readonly string API_KEY_CACHE_FILE = "nexus.key_cache"; - public Common.Http.Client HttpClient { get; } = new Common.Http.Client(); + public Wabbajack.Lib.Http.Client HttpClient { get; } = new Wabbajack.Lib.Http.Client(); #region Authentication @@ -255,7 +254,7 @@ namespace Wabbajack.Lib.NexusApi return new NexusApiClient(apiKey); } - public async Task Get(string url, Client? client = null) + public async Task Get(string url, Wabbajack.Lib.Http.Client? client = null) { client ??= HttpClient; int retries = 0; diff --git a/Wabbajack.Lib/NexusApi/NexusUpdatesFeeds.cs b/Wabbajack.Lib/NexusApi/NexusUpdatesFeeds.cs index f2f4c98c..becc90ee 100644 --- a/Wabbajack.Lib/NexusApi/NexusUpdatesFeeds.cs +++ b/Wabbajack.Lib/NexusApi/NexusUpdatesFeeds.cs @@ -46,7 +46,7 @@ namespace Wabbajack.Lib.NexusApi private static async Task> GetFeed(Uri uri) { - var client = new Common.Http.Client(); + var client = new Wabbajack.Lib.Http.Client(); var data = await client.GetStringAsync(uri); var reader = XmlReader.Create(new StringReader(data)); var results = SyndicationFeed.Load(reader); diff --git a/Wabbajack.Lib/StatusMessages/ManuallyDownloadFile.cs b/Wabbajack.Lib/StatusMessages/ManuallyDownloadFile.cs index ee02101d..d189e4c9 100644 --- a/Wabbajack.Lib/StatusMessages/ManuallyDownloadFile.cs +++ b/Wabbajack.Lib/StatusMessages/ManuallyDownloadFile.cs @@ -12,8 +12,8 @@ namespace Wabbajack.Lib public override string ShortDescription { get; } = string.Empty; public override string ExtendedDescription { get; } = string.Empty; - private TaskCompletionSource<(Uri, Common.Http.Client)> _tcs = new TaskCompletionSource<(Uri, Common.Http.Client)>(); - public Task<(Uri, Common.Http.Client)> Task => _tcs.Task; + private TaskCompletionSource<(Uri, Wabbajack.Lib.Http.Client)> _tcs = new TaskCompletionSource<(Uri, Wabbajack.Lib.Http.Client)>(); + public Task<(Uri, Wabbajack.Lib.Http.Client)> Task => _tcs.Task; private ManuallyDownloadFile(ManualDownloader.State state) { @@ -30,7 +30,7 @@ namespace Wabbajack.Lib _tcs.SetCanceled(); } - public void Resume(Uri s, Common.Http.Client client) + public void Resume(Uri s, Wabbajack.Lib.Http.Client client) { _tcs.SetResult((s, client)); } diff --git a/Wabbajack.Lib/Validation/ValidateModlist.cs b/Wabbajack.Lib/Validation/ValidateModlist.cs index 9dafa939..43ac949b 100644 --- a/Wabbajack.Lib/Validation/ValidateModlist.cs +++ b/Wabbajack.Lib/Validation/ValidateModlist.cs @@ -24,7 +24,7 @@ namespace Wabbajack.Lib.Validation public async Task LoadListsFromGithub() { - var client = new Common.Http.Client(); + var client = new Wabbajack.Lib.Http.Client(); Utils.Log("Loading server whitelist"); using (var response = await client.GetAsync(Consts.ServerWhitelistURL)) diff --git a/Wabbajack.Server.Test/ABuildServerSystemTest.cs b/Wabbajack.Server.Test/ABuildServerSystemTest.cs index 607d360d..55770ca4 100644 --- a/Wabbajack.Server.Test/ABuildServerSystemTest.cs +++ b/Wabbajack.Server.Test/ABuildServerSystemTest.cs @@ -7,7 +7,6 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Hosting; using Wabbajack.Common; -using Wabbajack.Common.Http; using Wabbajack.Common.StatusFeed; using Wabbajack.Lib; using Wabbajack.Lib.Downloaders; @@ -145,10 +144,10 @@ namespace Wabbajack.BuildServer.Test [Collection("ServerTests")] public class ABuildServerSystemTest : XunitContextBase, IClassFixture> { - protected readonly Client _client; + protected readonly Wabbajack.Lib.Http.Client _client; private readonly IDisposable _unsubMsgs; private readonly IDisposable _unsubErr; - protected Client _authedClient; + protected Wabbajack.Lib.Http.Client _authedClient; protected WorkQueue _queue; private Random _random; @@ -159,8 +158,8 @@ namespace Wabbajack.BuildServer.Test _unsubMsgs = Utils.LogMessages.OfType().Subscribe(onNext: msg => XunitContext.WriteLine(msg.ShortDescription)); _unsubErr = Utils.LogMessages.OfType().Subscribe(msg => XunitContext.WriteLine("ERROR: User intervention required: " + msg.ShortDescription)); - _client = new Client(); - _authedClient = new Client(); + _client = new Wabbajack.Lib.Http.Client(); + _authedClient = new Wabbajack.Lib.Http.Client(); Fixture = fixture.Deref(); _authedClient.Headers.Add(("x-api-key", Fixture.APIKey)); AuthorAPI.ApiKeyOverride = Fixture.APIKey; diff --git a/Wabbajack.Server.Test/MetricsTests.cs b/Wabbajack.Server.Test/MetricsTests.cs index 22df2628..9a80ee81 100644 --- a/Wabbajack.Server.Test/MetricsTests.cs +++ b/Wabbajack.Server.Test/MetricsTests.cs @@ -1,7 +1,7 @@ using System; using System.Threading.Tasks; using Dapper; -using Wabbajack.Common; +using Wabbajack.Lib; using Wabbajack.Server.DataLayer; using Wabbajack.Server.DTOs; using Xunit; diff --git a/Wabbajack.Server/Services/DiscordWebHook.cs b/Wabbajack.Server/Services/DiscordWebHook.cs index 2172b44d..1c7b794b 100644 --- a/Wabbajack.Server/Services/DiscordWebHook.cs +++ b/Wabbajack.Server/Services/DiscordWebHook.cs @@ -49,7 +49,7 @@ namespace Wabbajack.Server.Services }; if (url == null) return; - var client = new Common.Http.Client(); + var client = new Wabbajack.Lib.Http.Client(); await client.PostAsync(url, new StringContent(message.ToJson(true), Encoding.UTF8, "application/json")); } catch (Exception ex) diff --git a/Wabbajack.VirtualFileSystem/ExtractedFiles.cs b/Wabbajack.VirtualFileSystem/ExtractedFiles.cs index f0e8afc3..81d68c41 100644 --- a/Wabbajack.VirtualFileSystem/ExtractedFiles.cs +++ b/Wabbajack.VirtualFileSystem/ExtractedFiles.cs @@ -13,7 +13,7 @@ namespace Wabbajack.VirtualFileSystem private IAsyncDisposable _disposable; private AbsolutePath _tempFolder; - public ExtractedFiles(Dictionary files, IAsyncDisposable disposeOther) + public ExtractedFiles(Dictionary files, IAsyncDisposable disposeOther = null) { _files = files; _disposable = disposeOther; diff --git a/Wabbajack.VirtualFileSystem/FileExtractor.cs b/Wabbajack.VirtualFileSystem/FileExtractor.cs index d0e99f1c..41bc64bd 100644 --- a/Wabbajack.VirtualFileSystem/FileExtractor.cs +++ b/Wabbajack.VirtualFileSystem/FileExtractor.cs @@ -114,9 +114,9 @@ namespace Wabbajack.VirtualFileSystem { try { - await using var arch = await BSADispatch.OpenRead(source); + var arch = await BSADispatch.OpenRead(source); var files = arch.Files.ToDictionary(f => f.Path, f => (IExtractedFile)new ExtractedBSAFile(f)); - return new ExtractedFiles(files, arch); + return new ExtractedFiles(files); } catch (Exception ex) { diff --git a/Wabbajack.VirtualFileSystem/Wabbajack.VirtualFileSystem.csproj b/Wabbajack.VirtualFileSystem/Wabbajack.VirtualFileSystem.csproj index c6ad089c..8fe0e7fc 100644 --- a/Wabbajack.VirtualFileSystem/Wabbajack.VirtualFileSystem.csproj +++ b/Wabbajack.VirtualFileSystem/Wabbajack.VirtualFileSystem.csproj @@ -1,9 +1,12 @@  - netcoreapp3.1 - x64 - win10-x64 + netstandard2.1 + x64 + win10-x64 + + + Wabbajack.VirtualFileSystem.xml diff --git a/Wabbajack/View Models/Settings/CredentialsLoginVM.cs b/Wabbajack/View Models/Settings/CredentialsLoginVM.cs index 38715a39..366bc234 100644 --- a/Wabbajack/View Models/Settings/CredentialsLoginVM.cs +++ b/Wabbajack/View Models/Settings/CredentialsLoginVM.cs @@ -2,6 +2,7 @@ using System.Net.Mail; using System.Reactive.Linq; using System.Security; +using System.Threading.Tasks; using ReactiveUI; using ReactiveUI.Fody.Helpers; using Wabbajack.Common; @@ -21,6 +22,9 @@ namespace Wabbajack [Reactive] public LoginReturnMessage ReturnMessage { get; set; } + [Reactive] + public bool LoggingIn { get; private set; } + private readonly ObservableAsPropertyHelper _loginEnabled; public bool LoginEnabled => _loginEnabled.Value; @@ -35,6 +39,12 @@ namespace Wabbajack _loginEnabled = this.WhenAny(x => x.Username) .Select(IsValidAddress) + .CombineLatest( + this.WhenAny(x => x.LoggingIn), + (valid, loggingIn) => + { + return valid && !loggingIn; + }) .ToGuiProperty(this, nameof(LoginEnabled)); @@ -43,17 +53,19 @@ namespace Wabbajack .ToGuiProperty(this, nameof(MFAVisible)); } - public void Login(SecureString password) + public async Task Login(SecureString password) { try { + LoggingIn = true; + if (password == null || password.Length == 0) { ReturnMessage = new LoginReturnMessage("You need to input a password!", LoginReturnCode.BadInput); return; } - ReturnMessage = _downloader.LoginWithCredentials(Username, password, string.IsNullOrWhiteSpace(MFAKey) ? null : MFAKey); + ReturnMessage = await _downloader.LoginWithCredentials(Username, password, string.IsNullOrWhiteSpace(MFAKey) ? null : MFAKey); password.Clear(); } catch (Exception e) @@ -61,6 +73,10 @@ namespace Wabbajack Utils.Error(e, "Exception while trying to login"); ReturnMessage = new LoginReturnMessage($"Unhandled exception: {e.Message}", LoginReturnCode.InternalError); } + finally + { + LoggingIn = false; + } } private static bool IsValidAddress(string s) diff --git a/Wabbajack/View Models/Settings/LoginManagerVM.cs b/Wabbajack/View Models/Settings/LoginManagerVM.cs index fa0a03ee..66af9521 100644 --- a/Wabbajack/View Models/Settings/LoginManagerVM.cs +++ b/Wabbajack/View Models/Settings/LoginManagerVM.cs @@ -84,7 +84,7 @@ namespace Wabbajack { if (Login.IconUri == null) return; - using var img = await new Common.Http.Client().GetAsync(Login.IconUri, errorsAsExceptions:false); + using var img = await new Wabbajack.Lib.Http.Client().GetAsync(Login.IconUri, errorsAsExceptions:false); if (!img.IsSuccessStatusCode) return; var icoData = new MemoryStream(await img.Content.ReadAsByteArrayAsync()); diff --git a/Wabbajack/Views/Settings/CredentialsLoginView.xaml.cs b/Wabbajack/Views/Settings/CredentialsLoginView.xaml.cs index f369c2bf..9061dd96 100644 --- a/Wabbajack/Views/Settings/CredentialsLoginView.xaml.cs +++ b/Wabbajack/Views/Settings/CredentialsLoginView.xaml.cs @@ -1,5 +1,6 @@ using System.Reactive.Disposables; using System.Windows; +using MahApps.Metro.Controls; using ReactiveUI; using Wabbajack.Lib.Downloaders; @@ -35,9 +36,9 @@ namespace Wabbajack }); } - private void LoginButton_OnClick(object sender, RoutedEventArgs e) + private async void LoginButton_OnClick(object sender, RoutedEventArgs e) { - ViewModel.Login(Password.SecurePassword); + ViewModel.Login(Password.SecurePassword).FireAndForget(); } } }