From 809b8dacfe6caaa96035b161adda82267e37bb4e Mon Sep 17 00:00:00 2001 From: floribe2000 Date: Mon, 22 Jan 2024 22:12:42 +0100 Subject: [PATCH 01/10] update project to dotnet 8 --- .editorconfig | 7 ++- Directory.Build.props | 9 ++- .../BallisticCharts/DispersionPlotHelper.cs | 2 +- .../Features/Builds/BuildValidation.cs | 2 +- .../Aircraft/CvAircraftDataContainer.cs | 2 +- .../Armament/PingerGunDataContainer.cs | 2 +- .../Ship/ConsumableDataContainer.cs | 6 +- .../ShipComparison/ShipComparisonViewModel.cs | 56 ++++++------------- .../CaptainSkillSelectorViewModel.cs | 6 +- .../ViewModels/SignalSelectorViewModel.cs | 3 +- .../WoWsShipBuilder.Common.csproj | 2 +- .../WoWsShipBuilder.Desktop.Test.csproj | 2 +- WoWsShipBuilder.Desktop/App.axaml.cs | 3 +- .../Features/Updater/LocalDataUpdater.cs | 14 ++--- .../Infrastructure/LocalizeConverter.cs | 5 +- .../Infrastructure/WebView/BlazorWebView.cs | 19 ++----- .../PublishProfiles/PublishWindows.pubxml | 2 +- .../WoWsShipBuilder.Desktop.csproj | 4 +- WoWsShipBuilder.Web/Dockerfile | 36 +++++------- .../Authentication/AuthenticationService.cs | 6 +- global.json | 2 +- installer/Tools/SquirrelBuildAndRelease.ps1 | 2 +- 22 files changed, 77 insertions(+), 115 deletions(-) diff --git a/.editorconfig b/.editorconfig index 3ed917775..071ab9e50 100644 --- a/.editorconfig +++ b/.editorconfig @@ -43,7 +43,7 @@ dotnet_naming_symbols.private_static_readonly_symbols.required_modifiers = stati csharp_new_line_before_members_in_object_initializers = false csharp_preferred_modifier_order = public, private, protected, internal, new, static, abstract, virtual, sealed, readonly, override, extern, unsafe, volatile, async:suggestion -csharp_style_var_elsewhere = false:suggestion +csharp_style_var_elsewhere = true:suggestion csharp_style_var_for_built_in_types = true:suggestion csharp_style_var_when_type_is_apparent = true:suggestion dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:suggestion @@ -71,8 +71,8 @@ resharper_csharp_keep_blank_lines_in_code = 1 resharper_csharp_keep_blank_lines_in_declarations = 1 resharper_csharp_wrap_after_declaration_lpar = true resharper_csharp_wrap_parameters_style = chop_if_long -resharper_for_built_in_types = use_var_when_evident -resharper_for_other_types = use_var_when_evident +resharper_for_built_in_types = use_var +resharper_for_other_types = use_var resharper_for_simple_types = use_var resharper_object_creation_when_type_not_evident = target_typed resharper_parentheses_redundancy_style = remove_if_not_clarifies_precedence @@ -149,6 +149,7 @@ dotnet_diagnostic.CA1304.severity = suggestion # Specify cultureInfo dotnet_diagnostic.CA1309.severity = suggestion # Use ordinal StringComparison dotnet_diagnostic.CA1311.severity = suggestion # Specify a culture or use an invariant version dotnet_diagnostic.CA1822.severity = suggestion # Mark member as static +dotnet_diagnostic.CA1859.severity = suggestion # Use concrete types when possible for improved performance [*.axaml] max_line_length = 160 diff --git a/Directory.Build.props b/Directory.Build.props index b3e429f57..cba5fd1ff 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,8 +1,13 @@  - net7.0 + net8.0 + net8.0-windows + + + + $(CommonTargetFramework) enable - 11 + 12 Recommended diff --git a/WoWsShipBuilder.Common/Features/BallisticCharts/DispersionPlotHelper.cs b/WoWsShipBuilder.Common/Features/BallisticCharts/DispersionPlotHelper.cs index a5314140b..2d140a737 100644 --- a/WoWsShipBuilder.Common/Features/BallisticCharts/DispersionPlotHelper.cs +++ b/WoWsShipBuilder.Common/Features/BallisticCharts/DispersionPlotHelper.cs @@ -32,7 +32,7 @@ private static (double waterLineProjection, double perpendicularToWaterProjectio { double impactAngle; List> ballistic = BallisticHelper.CalculateBallistic(shell, maxRange, shell.Penetration).Where(x => x.Key >= aimingRange).ToList(); - if (ballistic.Any()) + if (ballistic.Count != 0) { impactAngle = ballistic[0].Value.ImpactAngle; } diff --git a/WoWsShipBuilder.Common/Features/Builds/BuildValidation.cs b/WoWsShipBuilder.Common/Features/Builds/BuildValidation.cs index 4fb9f166c..465393671 100644 --- a/WoWsShipBuilder.Common/Features/Builds/BuildValidation.cs +++ b/WoWsShipBuilder.Common/Features/Builds/BuildValidation.cs @@ -62,7 +62,7 @@ public static async Task ValidateBuildString(string List invalidChars = Path.GetInvalidFileNameChars().ToList(); invalidChars.Add(';'); List invalidCharsInBuildName = invalidChars.FindAll(buildName.Contains); - return invalidCharsInBuildName.Any() ? $"Invalid characters {string.Join(' ', invalidCharsInBuildName)}" : null; + return invalidCharsInBuildName.Count != 0 ? $"Invalid characters {string.Join(' ', invalidCharsInBuildName)}" : null; } public static async Task RetrieveLongUrlFromShortLink(string shortUrl) diff --git a/WoWsShipBuilder.Common/Features/DataContainers/Aircraft/CvAircraftDataContainer.cs b/WoWsShipBuilder.Common/Features/DataContainers/Aircraft/CvAircraftDataContainer.cs index 07a6f4c88..ef687f15a 100644 --- a/WoWsShipBuilder.Common/Features/DataContainers/Aircraft/CvAircraftDataContainer.cs +++ b/WoWsShipBuilder.Common/Features/DataContainers/Aircraft/CvAircraftDataContainer.cs @@ -110,7 +110,7 @@ public partial record CvAircraftDataContainer : DataContainerBase public static List? FromShip(Ship ship, List shipConfiguration, List modifiers) { - if (!ship.CvPlanes.Any()) + if (ship.CvPlanes.IsEmpty) { return null; } diff --git a/WoWsShipBuilder.Common/Features/DataContainers/Armament/PingerGunDataContainer.cs b/WoWsShipBuilder.Common/Features/DataContainers/Armament/PingerGunDataContainer.cs index f0395c8cc..a4c1a86fb 100644 --- a/WoWsShipBuilder.Common/Features/DataContainers/Armament/PingerGunDataContainer.cs +++ b/WoWsShipBuilder.Common/Features/DataContainers/Armament/PingerGunDataContainer.cs @@ -38,7 +38,7 @@ public partial record PingerGunDataContainer : DataContainerBase public static PingerGunDataContainer? FromShip(Ship ship, IEnumerable shipConfiguration, List modifiers) { - if (!ship.PingerGunList.Any()) + if (ship.PingerGunList.IsEmpty) { return null; } diff --git a/WoWsShipBuilder.Common/Features/DataContainers/Ship/ConsumableDataContainer.cs b/WoWsShipBuilder.Common/Features/DataContainers/Ship/ConsumableDataContainer.cs index b0c32dc13..bb638e460 100644 --- a/WoWsShipBuilder.Common/Features/DataContainers/Ship/ConsumableDataContainer.cs +++ b/WoWsShipBuilder.Common/Features/DataContainers/Ship/ConsumableDataContainer.cs @@ -52,7 +52,7 @@ private static ConsumableDataContainer FromTypeAndVariant(string name, string va { var consumableIdentifier = $"{name} {variant}"; var usingFallback = false; - if (!(AppData.ConsumableList?.TryGetValue(consumableIdentifier, out var consumable) ?? false)) + if (!AppData.ConsumableList.TryGetValue(consumableIdentifier, out var consumable)) { Logging.Logger.LogError("Consumable {Identifier} not found in cached consumable list. Using dummy consumable instead", consumableIdentifier); usingFallback = true; @@ -99,7 +99,7 @@ private static ConsumableDataContainer FromTypeAndVariant(string name, string va consumableModifiers.UpdateConsumableModifierValue(modifiers, "ConsumableDataContainer.TimeDelayAttack.PCY035", "timeDelayAttack"); consumableModifiers.UpdateConsumableModifierValue(modifiers, "ConsumableDataContainer.TimeDelayAppear.PCY035", "timeFromHeaven"); - var plane = AppData.FindAircraft(consumable.PlaneName[..consumable.PlaneName.IndexOf("_", StringComparison.Ordinal)]); + var plane = AppData.FindAircraft(consumable.PlaneName[..consumable.PlaneName.IndexOf('_', StringComparison.Ordinal)]); var oldCruisingSpeed = consumableModifiers.Find(x => x.Name.Equals("cruisingSpeed", StringComparison.Ordinal)); if (oldCruisingSpeed is not null) { @@ -257,7 +257,7 @@ private static ConsumableDataContainer FromTypeAndVariant(string name, string va consumableModifiers.UpdateConsumableModifierValue(modifiers, "ConsumableDataContainer.ExtraFighters.PCY012.PCY03", "fightersNum"); var maxKills = consumableModifiers.First(x => x.Name.Equals("fightersNum", StringComparison.Ordinal)).Value; - var plane = AppData.FindAircraft(consumable.PlaneName[..consumable.PlaneName.IndexOf("_", StringComparison.Ordinal)]); + var plane = AppData.FindAircraft(consumable.PlaneName[..consumable.PlaneName.IndexOf('_', StringComparison.Ordinal)]); var oldCruisingModifier = consumableModifiers.Find(x => x.Name.Equals("cruisingSpeed", StringComparison.Ordinal)); if (oldCruisingModifier is not null) diff --git a/WoWsShipBuilder.Common/Features/ShipComparison/ShipComparisonViewModel.cs b/WoWsShipBuilder.Common/Features/ShipComparison/ShipComparisonViewModel.cs index 2e83616cf..4adc728a5 100644 --- a/WoWsShipBuilder.Common/Features/ShipComparison/ShipComparisonViewModel.cs +++ b/WoWsShipBuilder.Common/Features/ShipComparison/ShipComparisonViewModel.cs @@ -71,7 +71,7 @@ private Dictionary FilteredShipList public Dictionary PinnedShipList { get; } = new(); - public List DataSections { get; private set; } = new() { ShipComparisonDataSections.General }; + public List DataSections { get; private set; } = [ShipComparisonDataSections.General]; public ShipComparisonDataSections SelectedDataSection { get; set; } = ShipComparisonDataSections.General; @@ -163,11 +163,7 @@ public void ToggleShowPinnedShipOnly() public async Task ToggleTierSelection(int value) { - if (this.SelectedTiers.Contains(value)) - { - this.SelectedTiers.Remove(value); - } - else + if (!this.SelectedTiers.Remove(value)) { this.SelectedTiers.Add(value); } @@ -177,11 +173,7 @@ public async Task ToggleTierSelection(int value) public async Task ToggleClassSelection(ShipClass value) { - if (this.SelectedClasses.Contains(value)) - { - this.SelectedClasses.Remove(value); - } - else + if (!this.SelectedClasses.Remove(value)) { this.SelectedClasses.Add(value); } @@ -191,11 +183,7 @@ public async Task ToggleClassSelection(ShipClass value) public async Task ToggleNationSelection(Nation value) { - if (this.SelectedNations.Contains(value)) - { - this.SelectedNations.Remove(value); - } - else + if (!this.SelectedNations.Remove(value)) { this.SelectedNations.Add(value); } @@ -205,11 +193,7 @@ public async Task ToggleNationSelection(Nation value) public async Task ToggleCategorySelection(ShipCategory value) { - if (this.SelectedCategories.Contains(value)) - { - this.SelectedCategories.Remove(value); - } - else + if (!this.SelectedCategories.Remove(value)) { this.SelectedCategories.Add(value); } @@ -293,7 +277,7 @@ public Dictionary RemoveBuilds(IEnumerable x.Key, x => x.Value); foreach (var wrapper in buildList) { - if (this.FilteredShipList.Count(x => x.Value.Ship.Index.Equals(wrapper.Value.Ship.Index)) > 1) + if (this.FilteredShipList.Count(x => x.Value.Ship.Index.Equals(wrapper.Value.Ship.Index, StringComparison.Ordinal)) > 1) { this.FilteredShipList.Remove(wrapper.Key); @@ -341,11 +325,7 @@ public void ResetAllBuilds() public async Task AddPinnedShip(GridDataWrapper wrapper) { - if (!this.PinnedShipList.ContainsKey(wrapper.Id)) - { - this.PinnedShipList.Add(wrapper.Id, wrapper); - } - else + if (!this.PinnedShipList.TryAdd(wrapper.Id, wrapper)) { await this.RemovePinnedShip(wrapper); } @@ -355,11 +335,7 @@ public async Task AddPinnedShip(GridDataWrapper wrapper) public void AddSelectedShip(GridDataWrapper wrapper) { - if (!this.SelectedShipList.ContainsKey(wrapper.Id)) - { - this.SelectedShipList.Add(wrapper.Id, wrapper); - } - else + if (!this.SelectedShipList.TryAdd(wrapper.Id, wrapper)) { this.RemoveSelectedShip(wrapper); } @@ -438,14 +414,14 @@ public void DuplicateSelectedShips() this.PinnedShipList.Add(newWrapper.Id, newWrapper); } - if (this.MainBatteryDispersionCache.ContainsKey(selectedShip.Key)) + if (this.MainBatteryDispersionCache.TryGetValue(selectedShip.Key, out var value)) { - this.MainBatteryDispersionCache[newWrapper.Id] = this.MainBatteryDispersionCache[selectedShip.Key]; + this.MainBatteryDispersionCache[newWrapper.Id] = value; } - if (this.SecondaryBatteryDispersionCache.ContainsKey(selectedShip.Key)) + if (this.SecondaryBatteryDispersionCache.TryGetValue(selectedShip.Key, out var secondaryValue)) { - this.SecondaryBatteryDispersionCache[newWrapper.Id] = this.SecondaryBatteryDispersionCache[selectedShip.Key]; + this.SecondaryBatteryDispersionCache[newWrapper.Id] = secondaryValue; } } @@ -515,7 +491,7 @@ public void SetFiringRange(double value, bool isMainBattery) private Dictionary GetShipsToBeDisplayed(bool disableHideShipsIfNoSelectedSection) { - Dictionary list = this.ShowPinnedShipsOnly ? this.PinnedShipList : this.FilteredShipList; + var list = this.ShowPinnedShipsOnly ? this.PinnedShipList : this.FilteredShipList; if (!disableHideShipsIfNoSelectedSection) { @@ -582,7 +558,7 @@ private void ChangeModulesBatch() private List GetShipConfiguration(Ship ship) { - List shipConfiguration = this.UseUpgradedModules + var shipConfiguration = this.UseUpgradedModules ? ShipModuleHelper.GroupAndSortUpgrades(ship.ShipUpgradeInfo.ShipUpgrades) .OrderBy(entry => entry.Key) .Select(entry => entry.Value) @@ -608,7 +584,7 @@ private Dictionary HideShipsIfNoSelectedSection(IEnumerab return list.ToDictionary(x => x.Key, x => x.Value); } - Dictionary newList = this.SelectedDataSection switch + var newList = this.SelectedDataSection switch { ShipComparisonDataSections.MainBattery => list.Where(x => x.Value.ShipDataContainer.MainBatteryDataContainer is not null).ToDictionary(x => x.Key, x => x.Value), ShipComparisonDataSections.He => list.Where(x => x.Value.HeShell?.Damage is not null).ToDictionary(x => x.Key, x => x.Value), @@ -637,7 +613,7 @@ private Dictionary HideShipsIfNoSelectedSection(IEnumerab private void GetDataSectionsToDisplay() { var displayedShipList = this.GetShipsToBeDisplayed(true); - this.DataSections = !displayedShipList.Any() ? new() { ShipComparisonDataSections.General } : this.HideEmptyDataSections(displayedShipList); + this.DataSections = displayedShipList.Count == 0 ? [ShipComparisonDataSections.General] : this.HideEmptyDataSections(displayedShipList); } [SuppressMessage("Performance", "CA1822", Justification = "not static to preserve file structure")] diff --git a/WoWsShipBuilder.Common/Features/ShipStats/ViewModels/CaptainSkillSelectorViewModel.cs b/WoWsShipBuilder.Common/Features/ShipStats/ViewModels/CaptainSkillSelectorViewModel.cs index 2d4b3909a..7bec2be6f 100644 --- a/WoWsShipBuilder.Common/Features/ShipStats/ViewModels/CaptainSkillSelectorViewModel.cs +++ b/WoWsShipBuilder.Common/Features/ShipStats/ViewModels/CaptainSkillSelectorViewModel.cs @@ -105,7 +105,7 @@ public Captain? SelectedCaptain this.SkillList = this.ConvertSkillToViewModel(this.currentClass, newCaptain); this.CaptainTalentsList.Clear(); - if (newCaptain!.UniqueSkills.Any()) + if (!newCaptain!.UniqueSkills.IsEmpty) { this.CaptainWithTalents = true; foreach ((string _, UniqueSkill talent) in newCaptain.UniqueSkills) @@ -265,7 +265,7 @@ public void AddSkill(Skill skill) public List GetModifiersList() { var modifiers = this.SkillOrderList.ToList() - .Where(skill => skill.Modifiers.Any() && skill.SkillNumber != ArSkillNumber && skill.SkillNumber != ArSkillNumberSubs && skill.SkillNumber != FuriousSkillNumber && skill.SkillNumber != ImprovedRepairPartyReadinessSkillNumber && skill.SkillNumber != ManualSecondaryBatteryAimingSkillNumber) + .Where(skill => !skill.Modifiers.IsEmpty && skill.SkillNumber != ArSkillNumber && skill.SkillNumber != ArSkillNumberSubs && skill.SkillNumber != FuriousSkillNumber && skill.SkillNumber != ImprovedRepairPartyReadinessSkillNumber && skill.SkillNumber != ManualSecondaryBatteryAimingSkillNumber) .SelectMany(m => m.Modifiers) .ToList(); @@ -414,7 +414,7 @@ private IEnumerable CollectTalentModifiers() .SelectMany(talent => talent.Modifiers.Select(modifier => new Modifier(modifier.Name, float.Pow(modifier.Value, talent.ActivationNumbers), "", modifier))); modifiers.AddRange(talentMultipleActivationModifiers); - var talentFireChanceModifier = this.CaptainTalentsList.Where(talent => talent.Status && talent.Modifiers.Any(modifier => modifier.Name.Equals("burnProbabilityBonus", StringComparison.Ordinal))) + var talentFireChanceModifier = this.CaptainTalentsList.Where(talent => talent.Status && talent.Modifiers.Exists(modifier => modifier.Name.Equals("burnProbabilityBonus", StringComparison.Ordinal))) .SelectMany(talent => talent.Modifiers.Select(modifier => new Modifier(modifier.Name, float.Round(modifier.Value * talent.ActivationNumbers, 2), "", modifier))); modifiers.AddRange(talentFireChanceModifier); diff --git a/WoWsShipBuilder.Common/Features/ShipStats/ViewModels/SignalSelectorViewModel.cs b/WoWsShipBuilder.Common/Features/ShipStats/ViewModels/SignalSelectorViewModel.cs index 5160117a2..929f13fb2 100644 --- a/WoWsShipBuilder.Common/Features/ShipStats/ViewModels/SignalSelectorViewModel.cs +++ b/WoWsShipBuilder.Common/Features/ShipStats/ViewModels/SignalSelectorViewModel.cs @@ -49,9 +49,8 @@ private static List> LoadSignalList() public void SignalCommandExecute(Exterior flag) { - if (this.SelectedSignals.Contains(flag)) + if (this.SelectedSignals.Remove(flag)) { - this.SelectedSignals.Remove(flag); this.SignalsNumber--; } else diff --git a/WoWsShipBuilder.Common/WoWsShipBuilder.Common.csproj b/WoWsShipBuilder.Common/WoWsShipBuilder.Common.csproj index fe9486dfa..f10b5bf9c 100644 --- a/WoWsShipBuilder.Common/WoWsShipBuilder.Common.csproj +++ b/WoWsShipBuilder.Common/WoWsShipBuilder.Common.csproj @@ -11,7 +11,7 @@ - + diff --git a/WoWsShipBuilder.Desktop.Test/WoWsShipBuilder.Desktop.Test.csproj b/WoWsShipBuilder.Desktop.Test/WoWsShipBuilder.Desktop.Test.csproj index 2fced84e8..dbf78b23e 100644 --- a/WoWsShipBuilder.Desktop.Test/WoWsShipBuilder.Desktop.Test.csproj +++ b/WoWsShipBuilder.Desktop.Test/WoWsShipBuilder.Desktop.Test.csproj @@ -1,7 +1,7 @@ - net7.0-windows + $(DesktopTargetFramework) enable enable diff --git a/WoWsShipBuilder.Desktop/App.axaml.cs b/WoWsShipBuilder.Desktop/App.axaml.cs index 4e4fffec6..c0a2b3cb7 100644 --- a/WoWsShipBuilder.Desktop/App.axaml.cs +++ b/WoWsShipBuilder.Desktop/App.axaml.cs @@ -1,6 +1,5 @@ using System; using System.Diagnostics.CodeAnalysis; -using System.Linq; using System.Reflection; using System.Runtime.Versioning; using System.Threading; @@ -140,7 +139,7 @@ private async Task UpdateCheck(AppNotificationService notificationService) { // Can throw a null-reference-exception, no idea why. var updateInfo = await updateManager.CheckForUpdate(); - if (!updateInfo.ReleasesToApply.Any()) + if (updateInfo.ReleasesToApply.Count == 0) { this.logger.LogInformation("No app update found"); return; diff --git a/WoWsShipBuilder.Desktop/Features/Updater/LocalDataUpdater.cs b/WoWsShipBuilder.Desktop/Features/Updater/LocalDataUpdater.cs index a5620aa8f..b3174db60 100644 --- a/WoWsShipBuilder.Desktop/Features/Updater/LocalDataUpdater.cs +++ b/WoWsShipBuilder.Desktop/Features/Updater/LocalDataUpdater.cs @@ -206,7 +206,7 @@ public async Task CheckJsonFileVersions(ServerType serverType shouldLocalizationUpdate = false; } - if (filesToDownload.Any()) + if (filesToDownload.Count != 0) { filesToDownload.Add((string.Empty, "VersionInfo.json")); } @@ -267,7 +267,7 @@ public async Task ValidateData(ServerType serverType, string d } } - if (!missingFiles.Any()) + if (missingFiles.Count == 0) { return new(true); } @@ -290,12 +290,12 @@ public async Task ShouldUpdaterRun(ServerType serverType) public async Task CheckInstalledLocalizations(ServerType serverType) { - List installedLocales = await this.appDataService.GetInstalledLocales(serverType, false); + var installedLocales = await this.appDataService.GetInstalledLocales(serverType, false); if (!installedLocales.Contains(this.appSettings.SelectedLanguage.LocalizationFileName)) { this.logger.LogInformation("Selected localization is not installed. Downloading file..."); string localizationFile = this.appSettings.SelectedLanguage.LocalizationFileName + ".json"; - await this.awsClient.DownloadFiles(serverType, new() { ("Localization", localizationFile) }); + await this.awsClient.DownloadFiles(serverType, [("Localization", localizationFile)]); this.logger.LogInformation("Downloaded localization file for selected localization. Updating localizer data..."); } else @@ -311,8 +311,8 @@ public async Task CheckInstalledLocalizations(ServerType serverType) /// An used to monitor the progress of the update. private async Task CheckFilesAndDownloadUpdates(ServerType serverType, IProgress<(int, string)> progressTracker) { - UpdateCheckResult checkResult = await this.CheckJsonFileVersions(serverType); - if (checkResult.AvailableFileUpdates.Any()) + var checkResult = await this.CheckJsonFileVersions(serverType); + if (checkResult.AvailableFileUpdates.Count != 0) { this.logger.LogInformation("Updating {AvailableUpdateCount} files...", checkResult.AvailableFileUpdates.Count); progressTracker.Report((1, nameof(Translation.SplashScreen_Json))); @@ -342,7 +342,7 @@ private async Task ImageUpdate(IProgress<(int, string)> progressTracker, bool ca { string imageBasePath = this.appDataService.AppDataImageDirectory; var shipImageDirectory = this.fileSystem.DirectoryInfo.New(this.fileSystem.Path.Combine(imageBasePath, "Ships")); - if (!shipImageDirectory.Exists || !shipImageDirectory.GetFiles().Any() || !canDeltaUpdate) + if (!shipImageDirectory.Exists || shipImageDirectory.GetFiles().Length == 0 || !canDeltaUpdate) { progressTracker.Report((2, nameof(Translation.SplashScreen_ShipImages))); await this.awsClient.DownloadImages(this.fileSystem); diff --git a/WoWsShipBuilder.Desktop/Infrastructure/LocalizeConverter.cs b/WoWsShipBuilder.Desktop/Infrastructure/LocalizeConverter.cs index 901ef4e6d..9bd385cb7 100644 --- a/WoWsShipBuilder.Desktop/Infrastructure/LocalizeConverter.cs +++ b/WoWsShipBuilder.Desktop/Infrastructure/LocalizeConverter.cs @@ -98,10 +98,7 @@ public object ConvertBack(object? value, Type targetType, object? parameter, Cul private static string ToSnakeCase(string camelCaseString) { - if (camelCaseString == null) - { - throw new ArgumentNullException(nameof(camelCaseString)); - } + ArgumentNullException.ThrowIfNull(camelCaseString); if (camelCaseString.Length < 2) { diff --git a/WoWsShipBuilder.Desktop/Infrastructure/WebView/BlazorWebView.cs b/WoWsShipBuilder.Desktop/Infrastructure/WebView/BlazorWebView.cs index 856af3be5..f92b7ba27 100644 --- a/WoWsShipBuilder.Desktop/Infrastructure/WebView/BlazorWebView.cs +++ b/WoWsShipBuilder.Desktop/Infrastructure/WebView/BlazorWebView.cs @@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis; using Avalonia; using Avalonia.Controls; +using Avalonia.Interactivity; using Avalonia.Platform; using DynamicData; using Microsoft.AspNetCore.Components.WebView.WindowsForms; @@ -184,17 +185,8 @@ protected override IPlatformHandle CreateNativeControlCore(IPlatformHandle paren return base.CreateNativeControlCore(parent); } - private void CoreWebView2OnIsDefaultDownloadDialogOpenChanged(object? sender, object e) - { - if (this.blazorWebView?.WebView.CoreWebView2.IsDefaultDownloadDialogOpen == true) - { - this.blazorWebView.WebView.CoreWebView2.CloseDefaultDownloadDialog(); - } - } - private void WebViewOnCoreWebView2InitializationCompleted(object? sender, CoreWebView2InitializationCompletedEventArgs e) { - // blazorWebView!.WebView.CoreWebView2.IsDefaultDownloadDialogOpenChanged += CoreWebView2OnIsDefaultDownloadDialogOpenChanged; this.DefaultDownloadFolderPath = this.defaultDownloadPath; this.blazorWebView!.WebView.CoreWebView2InitializationCompleted -= this.WebViewOnCoreWebView2InitializationCompleted; } @@ -203,7 +195,6 @@ protected override void DestroyNativeControlCore(IPlatformHandle control) { if (OperatingSystem.IsWindows()) { - // blazorWebView!.WebView.CoreWebView2.IsDefaultDownloadDialogOpenChanged -= CoreWebView2OnIsDefaultDownloadDialogOpenChanged; this.blazorWebView?.Dispose(); this.blazorWebView = null; } @@ -213,14 +204,14 @@ protected override void DestroyNativeControlCore(IPlatformHandle control) } } - protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) + protected override void OnUnloaded(RoutedEventArgs e) { - base.OnDetachedFromVisualTree(e); if (OperatingSystem.IsWindows()) { - // Do not use until dotnet 8 because disposing the webview will deadlock. see https://github.com/dotnet/maui/issues/7997#issuecomment-1258681003 - // blazorWebView?.Dispose(); + this.blazorWebView?.Dispose(); this.blazorWebView = null; } + + base.OnUnloaded(e); } } diff --git a/WoWsShipBuilder.Desktop/Properties/PublishProfiles/PublishWindows.pubxml b/WoWsShipBuilder.Desktop/Properties/PublishProfiles/PublishWindows.pubxml index c319c4a44..030c0bca6 100644 --- a/WoWsShipBuilder.Desktop/Properties/PublishProfiles/PublishWindows.pubxml +++ b/WoWsShipBuilder.Desktop/Properties/PublishProfiles/PublishWindows.pubxml @@ -7,7 +7,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121. Any CPU bin\$(Configuration)\publish\ FileSystem - net7.0-windows + net8.0-windows true win-x64 true diff --git a/WoWsShipBuilder.Desktop/WoWsShipBuilder.Desktop.csproj b/WoWsShipBuilder.Desktop/WoWsShipBuilder.Desktop.csproj index 5d552172f..812608dbf 100644 --- a/WoWsShipBuilder.Desktop/WoWsShipBuilder.Desktop.csproj +++ b/WoWsShipBuilder.Desktop/WoWsShipBuilder.Desktop.csproj @@ -1,7 +1,7 @@ WinExe - net7.0-windows + $(DesktopTargetFramework) Assets/ShipBuilderIcon_bg.ico false @@ -33,7 +33,7 @@ - + diff --git a/WoWsShipBuilder.Web/Dockerfile b/WoWsShipBuilder.Web/Dockerfile index 6dbfb13ed..74874c05d 100644 --- a/WoWsShipBuilder.Web/Dockerfile +++ b/WoWsShipBuilder.Web/Dockerfile @@ -1,30 +1,24 @@ -FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base -WORKDIR /app -EXPOSE 80 -EXPOSE 443 - -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env WORKDIR /src -COPY . . + +# Copy all project files +COPY . ./ + +# Restore only projects needed for ShipBuilder Web RUN dotnet restore "WoWsShipBuilder.Web/WoWsShipBuilder.Web.csproj" -WORKDIR "/src/WoWsShipBuilder.Web" -RUN dotnet build "WoWsShipBuilder.Web.csproj" -c Release -o /app/build -FROM build AS publish -RUN dotnet publish "WoWsShipBuilder.Web.csproj" -c Release -o /app/publish /p:UseAppHost=false +# Publish ShipBuilder Web +RUN dotnet publish "WoWsShipBuilder.Web/WoWsShipBuilder.Web.csproj" -c Release -o /app/publish /p:UseAppHost=false -FROM base AS final -ENV APPLICATION_USER_ID 1001 -ENV APPLICATION_USER appuser -LABEL org.opencontainers.image.source=https://github.com/WoWs-Builder-Team/WoWs-ShipBuilder +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS deploy-env +WORKDIR /app + +LABEL org.opencontainers.image.source="https://github.com/WoWs-Builder-Team/WoWs-ShipBuilder" LABEL org.opencontainers.image.description="Container image for ShipBuilder Web" LABEL org.opencontainers.image.licenses=MIT +LABEL org.opencontainers.image.authors="WoWs Builder Team" -RUN groupadd --gid $APPLICATION_USER_ID $APPLICATION_USER \ - && useradd --uid $APPLICATION_USER_ID --gid $APPLICATION_USER_ID -m $APPLICATION_USER - -WORKDIR /app -COPY --from=publish --chown=$APPLICATION_USER /app/publish . +COPY --from=build-env --chown=app /app/publish . -USER $APPLICATION_USER +USER app ENTRYPOINT ["dotnet", "WoWsShipBuilder.Web.dll"] diff --git a/WoWsShipBuilder.Web/Features/Authentication/AuthenticationService.cs b/WoWsShipBuilder.Web/Features/Authentication/AuthenticationService.cs index 93bcc7221..26a97c4a2 100644 --- a/WoWsShipBuilder.Web/Features/Authentication/AuthenticationService.cs +++ b/WoWsShipBuilder.Web/Features/Authentication/AuthenticationService.cs @@ -39,11 +39,11 @@ public async Task VerifyToken(string accountId, string accessToken) if (response.IsSuccessStatusCode) { var responseData = await response.Content.ReadFromJsonAsync(); - if (responseData is not null && responseData.Status.Equals("ok")) + if (responseData is not null && responseData.Status.Equals("ok", StringComparison.Ordinal)) { - Dictionary? privateData = responseData.Data.FirstOrDefault().Value?.Private; + var privateData = responseData.Data.FirstOrDefault().Value?.Private; this.logger.LogInformation("Token-verification for account {} successful", accountId); - return privateData is not null && privateData.Any(); + return privateData is not null && privateData.Count != 0; } } diff --git a/global.json b/global.json index b69e1fe54..88c19ffc0 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "7.0.400", + "version": "8.0.100", "rollForward": "latestFeature", "allowPrerelease": false }, diff --git a/installer/Tools/SquirrelBuildAndRelease.ps1 b/installer/Tools/SquirrelBuildAndRelease.ps1 index 69fd2ac33..d638ccf84 100644 --- a/installer/Tools/SquirrelBuildAndRelease.ps1 +++ b/installer/Tools/SquirrelBuildAndRelease.ps1 @@ -5,7 +5,7 @@ [string][Parameter(Mandatory=$false)]$signingPassword ) -$frameworkVersion="net7.0-windows" +$frameworkVersion="net8.0-windows" if ($skipBuild) { Write-Output "Skipping build" From a7c417a869ec0fd81f05a61c0dbc1158a8279a22 Mon Sep 17 00:00:00 2001 From: floribe2000 Date: Mon, 22 Jan 2024 22:59:05 +0100 Subject: [PATCH 02/10] fix failing unit tests after dotnet update --- .../DataElementGeneratorTests/DataElementGeneratorTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WoWsShipBuilder.Data.Generator.Test/DataElementGeneratorTests/DataElementGeneratorTest.cs b/WoWsShipBuilder.Data.Generator.Test/DataElementGeneratorTests/DataElementGeneratorTest.cs index 45f6ae3c7..2221ad118 100644 --- a/WoWsShipBuilder.Data.Generator.Test/DataElementGeneratorTests/DataElementGeneratorTest.cs +++ b/WoWsShipBuilder.Data.Generator.Test/DataElementGeneratorTests/DataElementGeneratorTest.cs @@ -50,7 +50,7 @@ protected static bool ShouldAdd(object? value) (typeof(DataElementGenerator.DataElementGenerator), "DataElementFilteringAttribute.g.cs", AttributeHelper.DataElementFilteringAttribute), (typeof(DataElementGenerator.DataElementGenerator), "TestRecord.g.cs", expected), }, - ReferenceAssemblies = ReferenceAssemblies.Net.Net70, + ReferenceAssemblies = ReferenceAssemblies.Net.Net80, AdditionalReferences = { MetadataReference.CreateFromFile(typeof(IDataElement).GetTypeInfo().Assembly.Location) }, }, }; From e1d9e2910b30ffbe62b91a1de2801c2b0ef663d7 Mon Sep 17 00:00:00 2001 From: iTTou <13366390+iTTou@users.noreply.github.com> Date: Tue, 23 Jan 2024 00:31:02 +0100 Subject: [PATCH 03/10] fix saved build not being saved into browser local storage --- WoWsShipBuilder.Web/Infrastructure/Data/WebUserDataService.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/WoWsShipBuilder.Web/Infrastructure/Data/WebUserDataService.cs b/WoWsShipBuilder.Web/Infrastructure/Data/WebUserDataService.cs index 532f5d0ff..ece6a8bc6 100644 --- a/WoWsShipBuilder.Web/Infrastructure/Data/WebUserDataService.cs +++ b/WoWsShipBuilder.Web/Infrastructure/Data/WebUserDataService.cs @@ -176,6 +176,7 @@ private async Task AddOrUpdateBuilds(List buildsList) var buildsUpdated = 0; var buildsNotNeedingUpdate = 0; + var buildAdded = false; foreach (var build in buildsList) { @@ -210,10 +211,11 @@ private async Task AddOrUpdateBuilds(List buildsList) else { this.savedBuilds.Insert(0, build); + buildAdded = true; } } - if (buildsUpdated == 0 || buildsNotNeedingUpdate == buildsList.Count) + if (!buildAdded && (buildsUpdated == 0 || buildsNotNeedingUpdate == buildsList.Count)) { return -1; } From 104604eb3a807a582eb276c36f10209c50b620b2 Mon Sep 17 00:00:00 2001 From: floribe2000 Date: Tue, 23 Jan 2024 22:15:31 +0100 Subject: [PATCH 04/10] update Dockerfile for smaller images --- WoWsShipBuilder.Web/Dockerfile | 29 ++++++++++++++++++++--------- WoWsShipBuilder.sln | 1 + 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/WoWsShipBuilder.Web/Dockerfile b/WoWsShipBuilder.Web/Dockerfile index 74874c05d..39f73d740 100644 --- a/WoWsShipBuilder.Web/Dockerfile +++ b/WoWsShipBuilder.Web/Dockerfile @@ -1,24 +1,35 @@ -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env +FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build-env +ARG TARGETARCH WORKDIR /src # Copy all project files COPY . ./ # Restore only projects needed for ShipBuilder Web -RUN dotnet restore "WoWsShipBuilder.Web/WoWsShipBuilder.Web.csproj" +RUN dotnet restore "WoWsShipBuilder.Web/WoWsShipBuilder.Web.csproj" -a $TARGETARCH # Publish ShipBuilder Web -RUN dotnet publish "WoWsShipBuilder.Web/WoWsShipBuilder.Web.csproj" -c Release -o /app/publish /p:UseAppHost=false +RUN dotnet publish "WoWsShipBuilder.Web/WoWsShipBuilder.Web.csproj" -a $TARGETARCH --no-restore -c Release -o /app -FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS deploy-env -WORKDIR /app +FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine AS deploy-env +EXPOSE 8080 + +# Enable globalization and time zones: +# https://github.com/dotnet/dotnet-docker/blob/main/samples/enable-globalization.md +ENV \ + DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false \ + LC_ALL=en_US.UTF-8 \ + LANG=en_US.UTF-8 +RUN apk add --no-cache \ + icu-data-full \ + icu-libs LABEL org.opencontainers.image.source="https://github.com/WoWs-Builder-Team/WoWs-ShipBuilder" LABEL org.opencontainers.image.description="Container image for ShipBuilder Web" LABEL org.opencontainers.image.licenses=MIT LABEL org.opencontainers.image.authors="WoWs Builder Team" -COPY --from=build-env --chown=app /app/publish . - -USER app -ENTRYPOINT ["dotnet", "WoWsShipBuilder.Web.dll"] +WORKDIR /app +COPY --from=build-env /app . +USER $APP_UID +ENTRYPOINT ["./WoWsShipBuilder.Web"] diff --git a/WoWsShipBuilder.sln b/WoWsShipBuilder.sln index b171abfb2..c3f3d79dc 100644 --- a/WoWsShipBuilder.sln +++ b/WoWsShipBuilder.sln @@ -13,6 +13,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Configs", "Configs", "{0F12 WoWsShipBuilder.sln.DotSettings = WoWsShipBuilder.sln.DotSettings global.json = global.json Directory.Build.props = Directory.Build.props + .dockerignore = .dockerignore EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{43EE144D-CA52-44D5-B761-A27C0A37E1C5}" From f112d96ce4b1cb3a75d6f2decd6b386696ae168c Mon Sep 17 00:00:00 2001 From: floribe2000 Date: Sun, 28 Jan 2024 23:56:55 +0100 Subject: [PATCH 05/10] temporary fix for webview issues and missing dialog --- .../Infrastructure/HostApplicationBuilderExtensions.cs | 2 +- WoWsShipBuilder.Desktop/WoWsShipBuilder.Desktop.csproj | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/WoWsShipBuilder.Desktop/Infrastructure/HostApplicationBuilderExtensions.cs b/WoWsShipBuilder.Desktop/Infrastructure/HostApplicationBuilderExtensions.cs index 2869dde6e..8675fc8e6 100644 --- a/WoWsShipBuilder.Desktop/Infrastructure/HostApplicationBuilderExtensions.cs +++ b/WoWsShipBuilder.Desktop/Infrastructure/HostApplicationBuilderExtensions.cs @@ -27,7 +27,7 @@ public static HostApplicationBuilder UseShipBuilderDesktop(this HostApplicationB builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); - builder.Services.AddSingleton(); + builder.Services.AddScoped(); builder.Services.AddSingleton(); builder.Services.AddSingleton(x => x.GetRequiredService()); builder.Services.AddSingleton(x => x.GetRequiredService()); diff --git a/WoWsShipBuilder.Desktop/WoWsShipBuilder.Desktop.csproj b/WoWsShipBuilder.Desktop/WoWsShipBuilder.Desktop.csproj index 812608dbf..500bec051 100644 --- a/WoWsShipBuilder.Desktop/WoWsShipBuilder.Desktop.csproj +++ b/WoWsShipBuilder.Desktop/WoWsShipBuilder.Desktop.csproj @@ -33,13 +33,14 @@ - + + From 825bc0851ab47fd7bd0eea5846b341643fda79b5 Mon Sep 17 00:00:00 2001 From: floribe2000 Date: Sun, 4 Feb 2024 19:29:18 +0100 Subject: [PATCH 06/10] fix image link in main README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4c20e0169..47b40c1c7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # WoWs-ShipBuilder

- +

## General Information @@ -24,7 +24,7 @@ Update checks only run on application startup so it won't mess up your system wi ## Telemetry data and error reports -We do not collect any personal data in our application because it's simply not necessary for the app to work. +We do not collect any personal data in our application because it's simply not necessary for the app to work. However, we do automatically collect error reports. If the application encounters an error, it automatically sends a report to [Sentry](https://sentry.io/) containing the error data. This data does not contain IP addresses or other personal information. An error is not always visible for you as most errors should be caught internally and handled using fallback actions. @@ -39,7 +39,7 @@ If you want to see the program translate in your language, you can follow the gu Hosting the server where we store the data used by the program has a monthly cost. If you like the program and would like to help us out, you can donate at https://ko-fi.com/wowsshipbuilder. The app will always be free and with no ads. When you donate, you will also get a special role in our discord server. ## Discord -We have a discord server that you can join by clicking [here](https://discord.gg/C8EaepZJDY) . +We have a discord server that you can join by clicking [here](https://discord.gg/C8EaepZJDY) . ## Sponsorships and Support From f19d8ab254ee98629ef9079f2cd8c76de89e3381 Mon Sep 17 00:00:00 2001 From: floribe2000 Date: Mon, 5 Feb 2024 23:19:46 +0100 Subject: [PATCH 07/10] fix js libraries not being loading on web --- .dockerignore | 1 + WoWsShipBuilder.Common/WoWsShipBuilder.Common.csproj | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/.dockerignore b/.dockerignore index bbbfc1d2a..a47351064 100644 --- a/.dockerignore +++ b/.dockerignore @@ -24,3 +24,4 @@ LICENSE README.md **/appsettings.local.json +**/wwwroot/lib diff --git a/WoWsShipBuilder.Common/WoWsShipBuilder.Common.csproj b/WoWsShipBuilder.Common/WoWsShipBuilder.Common.csproj index f10b5bf9c..93c6caea1 100644 --- a/WoWsShipBuilder.Common/WoWsShipBuilder.Common.csproj +++ b/WoWsShipBuilder.Common/WoWsShipBuilder.Common.csproj @@ -63,4 +63,12 @@
+ + + + + + + + From 939831ae912e1e038225307e46665c7c0731d826 Mon Sep 17 00:00:00 2001 From: floribe2000 Date: Thu, 8 Feb 2024 23:50:52 +0100 Subject: [PATCH 08/10] update ConsumableDataContainer modifier processing for game update 13.1 --- .../Features/DataContainers/Ship/ConsumableDataContainer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/WoWsShipBuilder.Common/Features/DataContainers/Ship/ConsumableDataContainer.cs b/WoWsShipBuilder.Common/Features/DataContainers/Ship/ConsumableDataContainer.cs index bb638e460..83d444090 100644 --- a/WoWsShipBuilder.Common/Features/DataContainers/Ship/ConsumableDataContainer.cs +++ b/WoWsShipBuilder.Common/Features/DataContainers/Ship/ConsumableDataContainer.cs @@ -303,12 +303,15 @@ private static ConsumableDataContainer FromTypeAndVariant(string name, string va else if (name.Contains("PCY045", StringComparison.InvariantCultureIgnoreCase)) { // Hydrophone + // used prior to 13.1 consumableModifiers.UpdateConsumableModifierValue(modifiers, "ConsumableDataContainer.HydrophoneUpdateFrequency.PCY045", "hydrophoneUpdateFrequency"); + cooldown = modifiers.ApplyModifiers("ConsumableDataContainer.Reload.PCY045", cooldown); } else if (name.Contains("PCY048", StringComparison.InvariantCultureIgnoreCase)) { // Submarine Surveillance prepTime = modifiers.ApplyModifiers("ConsumableDataContainer.PrepTime.PCY048", prepTime); + cooldown = modifiers.ApplyModifiers("ConsumableDataContainer.Reload.PCY048", cooldown); } } else if (usingFallback) From c1ccf4f3e17f3b40301dccd908efca7c2d36cdee Mon Sep 17 00:00:00 2001 From: floribe2000 Date: Fri, 9 Feb 2024 00:05:22 +0100 Subject: [PATCH 09/10] fix UpdateConsumableModifierValue method in case of nonexistent modifier values --- .../Features/DataContainers/DataContainerUtility.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/WoWsShipBuilder.Common/Features/DataContainers/DataContainerUtility.cs b/WoWsShipBuilder.Common/Features/DataContainers/DataContainerUtility.cs index 1870938c2..69fb678e9 100644 --- a/WoWsShipBuilder.Common/Features/DataContainers/DataContainerUtility.cs +++ b/WoWsShipBuilder.Common/Features/DataContainers/DataContainerUtility.cs @@ -28,8 +28,13 @@ public static int ApplyModifiers(this List modifierList, string proper public static void UpdateConsumableModifierValue(this List consumableModifierList, List modifierList, string propertySelector, string modifierName) { - var modifier = consumableModifierList.Find(x => x.Name.Equals(modifierName))!; - var newValue = (float)modifierList.ApplyModifiers(propertySelector, (decimal)modifier.Value); + var modifier = consumableModifierList.Find(x => x.Name.Equals(modifierName)); + var newValue = (float)modifierList.ApplyModifiers(propertySelector, (decimal)(modifier?.Value ?? 0)); + if (modifier == null) + { + return; + } + consumableModifierList.Remove(modifier); consumableModifierList.Add(new Modifier(modifier.Name, newValue, "", modifier)); } From 58be1cddeaddf70a267a40c818efa3c43f8a90f4 Mon Sep 17 00:00:00 2001 From: floribe2000 Date: Sat, 10 Feb 2024 22:21:09 +0100 Subject: [PATCH 10/10] update data loading on desktop to only load necessary files --- .../Infrastructure/Data/DesktopAppDataService.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/WoWsShipBuilder.Desktop/Infrastructure/Data/DesktopAppDataService.cs b/WoWsShipBuilder.Desktop/Infrastructure/Data/DesktopAppDataService.cs index 2a2ed1e29..4d11bd745 100644 --- a/WoWsShipBuilder.Desktop/Infrastructure/Data/DesktopAppDataService.cs +++ b/WoWsShipBuilder.Desktop/Infrastructure/Data/DesktopAppDataService.cs @@ -99,21 +99,22 @@ public async Task LoadLocalFilesAsync(ServerType serverType) var localVersionInfo = await this.GetCurrentVersionInfo(serverType) ?? throw new InvalidOperationException("No local data found"); AppData.DataVersion = localVersionInfo.CurrentVersion.MainVersion.ToString(3) + "#" + localVersionInfo.CurrentVersion.DataIteration; - var dataRootInfo = this.fileSystem.DirectoryInfo.New(this.GetDataPath(serverType)); - IDirectoryInfo[] categories = dataRootInfo.GetDirectories(); + var dataRootPath = this.GetDataPath(serverType); // Multiple categories can be loaded simultaneously without concurrency issues because every cache is only used by one category. - await Parallel.ForEachAsync(categories, async (category, ct) => + await Parallel.ForEachAsync(localVersionInfo.Categories, async (category, ct) => { - if (category.Name.Contains("Localization", StringComparison.InvariantCultureIgnoreCase)) + if (category.Key.Contains("Localization", StringComparison.InvariantCultureIgnoreCase)) { return; } - foreach (var file in category.GetFiles()) + var categoryPath = this.fileSystem.Path.Combine(dataRootPath, category.Key); + foreach (var file in category.Value.Select(file => file.FileName)) { - string content = await this.fileSystem.File.ReadAllTextAsync(file.FullName, ct); - await DataCacheHelper.AddToCache(file.Name, category.Name, content); + var filePath = this.fileSystem.Path.Combine(categoryPath, file); + string content = await this.fileSystem.File.ReadAllTextAsync(filePath, ct); + await DataCacheHelper.AddToCache(file, category.Key, content); } });