From 5242b0009bf4e05e06a3ecff31460f0ace87e43a Mon Sep 17 00:00:00 2001 From: achiez Date: Fri, 2 Jan 2026 21:23:11 +0200 Subject: [PATCH] Refactor mafile storage: async, modular, bulk rename - Fix crash: Updated SaveMafileAsync to properly update or add to MaFiles collection - Fix naming logic: Added Filename reset logic to adding new mafile to prevent inconsistent and duplicating import - Extracted mafile path and naming logic to MafilesStorageHelper for better modularity - Refactored Storage methods to use MafilesStorageHelper - Replaced all sync mafile save/add calls with async/await versions throughout the codebase - Performed code cleanups and improved maintainability for mafile-related operations --- src/NebulaAuth/App.xaml.cs | 1 + src/NebulaAuth/Model/Entities/Mafile.cs | 1 - src/NebulaAuth/Model/MAAC/MAACStorage.cs | 1 + .../Model/Mafiles/MafilesBulkRenameResult.cs | 11 +++ .../Model/Mafiles/MafilesStorageHelper.cs | 37 +++++++ src/NebulaAuth/Model/{ => Mafiles}/Storage.cs | 99 +++++-------------- src/NebulaAuth/Model/SessionHandler_API.cs | 1 + .../ViewModel/Linker/LinkAccountVM.cs | 3 +- .../ViewModel/MafileMover/MafileMoverVM.cs | 1 + src/NebulaAuth/ViewModel/MainVM.cs | 1 + src/NebulaAuth/ViewModel/MainVM_File.cs | 5 +- src/NebulaAuth/ViewModel/MainVM_Groups.cs | 2 +- src/NebulaAuth/ViewModel/MainVM_Proxy.cs | 1 + .../ViewModel/Other/SetAccountPasswordsVM.cs | 1 + src/NebulaAuth/ViewModel/Other/SettingsVM.cs | 3 +- 15 files changed, 88 insertions(+), 80 deletions(-) create mode 100644 src/NebulaAuth/Model/Mafiles/MafilesBulkRenameResult.cs create mode 100644 src/NebulaAuth/Model/Mafiles/MafilesStorageHelper.cs rename src/NebulaAuth/Model/{ => Mafiles}/Storage.cs (76%) diff --git a/src/NebulaAuth/App.xaml.cs b/src/NebulaAuth/App.xaml.cs index c952ba8..0d90552 100644 --- a/src/NebulaAuth/App.xaml.cs +++ b/src/NebulaAuth/App.xaml.cs @@ -4,6 +4,7 @@ using NebulaAuth.Core; using NebulaAuth.Model; using NebulaAuth.Model.Exceptions; using NebulaAuth.Model.MAAC; +using NebulaAuth.Model.Mafiles; namespace NebulaAuth; diff --git a/src/NebulaAuth/Model/Entities/Mafile.cs b/src/NebulaAuth/Model/Entities/Mafile.cs index c627136..70c5a6a 100644 --- a/src/NebulaAuth/Model/Entities/Mafile.cs +++ b/src/NebulaAuth/Model/Entities/Mafile.cs @@ -28,7 +28,6 @@ public partial class Mafile : MobileDataExtended } private string? _filename; - [JsonIgnore] private PortableMaClient? _linkedClient; public void SetSessionData(MobileSessionData? sessionData) diff --git a/src/NebulaAuth/Model/MAAC/MAACStorage.cs b/src/NebulaAuth/Model/MAAC/MAACStorage.cs index eacb3b2..672254b 100644 --- a/src/NebulaAuth/Model/MAAC/MAACStorage.cs +++ b/src/NebulaAuth/Model/MAAC/MAACStorage.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using NebulaAuth.Core; using NebulaAuth.Model.Entities; +using NebulaAuth.Model.Mafiles; using Newtonsoft.Json; namespace NebulaAuth.Model.MAAC; diff --git a/src/NebulaAuth/Model/Mafiles/MafilesBulkRenameResult.cs b/src/NebulaAuth/Model/Mafiles/MafilesBulkRenameResult.cs new file mode 100644 index 0000000..a18e629 --- /dev/null +++ b/src/NebulaAuth/Model/Mafiles/MafilesBulkRenameResult.cs @@ -0,0 +1,11 @@ +namespace NebulaAuth.Model.Mafiles; + +public class MafilesBulkRenameResult +{ + public int Total { get; set; } + public int Renamed { get; set; } + public int NotRenamed => Errors + Conflict; + public int Errors { get; set; } + public int Conflict { get; set; } + public string BackupFileName { get; set; } +} \ No newline at end of file diff --git a/src/NebulaAuth/Model/Mafiles/MafilesStorageHelper.cs b/src/NebulaAuth/Model/Mafiles/MafilesStorageHelper.cs new file mode 100644 index 0000000..6d50750 --- /dev/null +++ b/src/NebulaAuth/Model/Mafiles/MafilesStorageHelper.cs @@ -0,0 +1,37 @@ +using System.IO; +using NebulaAuth.Model.Entities; + +namespace NebulaAuth.Model.Mafiles; + +internal static class MafilesStorageHelper +{ + /// + /// Returns or creates a new one and updates the property. + /// + /// + /// + public static string GetOrUpdateMafilePath(Mafile data) + { + if (data.Filename != null) + { + return Path.Combine(Storage.MafilesDirectory, data.Filename); + } + + var fileName = CreateMafileFileName(data, Settings.Instance.UseAccountNameAsMafileName); + data.Filename = fileName; + return Path.Combine(Storage.MafilesDirectory, fileName); + } + + /// + /// Creates mafile file name according to the current settings. + /// + /// + /// + /// + public static string CreateMafileFileName(Mafile data, bool useAccountName) + { + return useAccountName + ? MafileNamingStrategy.Login.GetMafileName(data) + : MafileNamingStrategy.SteamId.GetMafileName(data); + } +} \ No newline at end of file diff --git a/src/NebulaAuth/Model/Storage.cs b/src/NebulaAuth/Model/Mafiles/Storage.cs similarity index 76% rename from src/NebulaAuth/Model/Storage.cs rename to src/NebulaAuth/Model/Mafiles/Storage.cs index bae3c2e..8997344 100644 --- a/src/NebulaAuth/Model/Storage.cs +++ b/src/NebulaAuth/Model/Mafiles/Storage.cs @@ -11,12 +11,11 @@ using AchiesUtilities.Extensions; using NebulaAuth.Model.Entities; using NebulaAuth.Model.Exceptions; using NebulaAuth.Model.MAAC; -using NebulaAuth.Model.Mafiles; using SteamLib; using SteamLib.Exceptions.Authorization; using SteamLib.SteamMobile; -namespace NebulaAuth.Model; +namespace NebulaAuth.Model.Mafiles; public static class Storage { @@ -70,12 +69,13 @@ public static class Storage /// /// /// - public static void AddNewMafile(string path, bool overwrite) + public static async Task AddNewMafile(string path, bool overwrite) { Mafile data; try { - data = ReadMafile(path); + data = await ReadMafileAsync(path); + data.Filename = null; } catch (Exception ex) when (ex is not MafileNeedReloginException) @@ -96,19 +96,13 @@ public static class Storage throw new FormatException("Can't generate code on this mafile", ex); } - if (overwrite == false && File.Exists(GetOrCreateMafilePath(data))) + if (!overwrite && File.Exists(MafilesStorageHelper.GetOrUpdateMafilePath(data))) { throw new IOException("File already exist and overwrite is False"); //TODO: Custom Exception } - SaveMafile(data); - } - - public static Mafile ReadMafile(string path) - { - var str = File.ReadAllText(path); - return NebulaSerializer.Deserialize(str, path); + await SaveMafileAsync(data); } public static async Task ReadMafileAsync(string path) @@ -117,59 +111,43 @@ public static class Storage return NebulaSerializer.Deserialize(str, path); } - public static void SaveMafile(Mafile data) - { - var path = GetOrCreateMafilePath(data); - var str = NebulaSerializer.SerializeMafile(data); - File.WriteAllText(Path.GetFullPath(path), str); - - var existed = MaFiles.SingleOrDefault(m => m.AccountName == data.AccountName); - if (existed != null) - { - var index = MaFiles.IndexOf(existed); - MaFiles[index] = data; - } - else - { - MaFiles.Add(data); - } - } - public static async Task SaveMafileAsync(Mafile data) { - var path = GetOrCreateMafilePath(data); + var path = MafilesStorageHelper.GetOrUpdateMafilePath(data); var str = NebulaSerializer.SerializeMafile(data); await File.WriteAllTextAsync(Path.GetFullPath(path), str); - var existed = MaFiles.SingleOrDefault(m => m.AccountName == data.AccountName); - if (existed != null) + // Replace if exist + for (var i = 0; i < MaFiles.Count; i++) { - var index = MaFiles.IndexOf(existed); - MaFiles[index] = data; - } - else - { - MaFiles.Add(data); + var existed = MaFiles[i]; + if (ReferenceEquals(existed, data) || (existed.Filename != null && existed.Filename == data.Filename)) + { + MaFiles[i] = data; + return; + } } + + MaFiles.Add(data); } public static void UpdateMafile(Mafile data) { - var path = GetOrCreateMafilePath(data); + var path = MafilesStorageHelper.GetOrUpdateMafilePath(data); var str = NebulaSerializer.SerializeMafile(data); File.WriteAllText(Path.GetFullPath(path), str); } public static async Task UpdateMafileAsync(Mafile data) { - var path = GetOrCreateMafilePath(data); + var path = MafilesStorageHelper.GetOrUpdateMafilePath(data); var str = NebulaSerializer.SerializeMafile(data); await File.WriteAllTextAsync(Path.GetFullPath(path), str); } public static void MoveToRemoved(Mafile data) { - var sourcePath = GetOrCreateMafilePath(data); + var sourcePath = MafilesStorageHelper.GetOrUpdateMafilePath(data); var destinationPath = Path.Combine(DIR_REMOVED_MAFILES, data.Filename + ".mafile"); var destinationPathFinal = destinationPath; var i = 0; @@ -184,24 +162,6 @@ public static class Storage MaFiles.Remove(data); } - private static string GetOrCreateMafilePath(Mafile data) - { - if (data.Filename != null) - { - return Path.Combine(MafilesDirectory, data.Filename); - } - - var fileName = CreateMafileFileName(data, Settings.Instance.UseAccountNameAsMafileName); - data.Filename = fileName; - return Path.Combine(MafilesDirectory, fileName); - } - - private static string CreateMafileFileName(Mafile data, bool useAccountName) - { - return useAccountName - ? MafileNamingStrategy.Login.GetMafileName(data) - : MafileNamingStrategy.SteamId.GetMafileName(data); - } public static string? TryGetMafilePath(Mafile data) { @@ -221,9 +181,10 @@ public static class Storage File.WriteAllText(Path.Combine(DIR_BACKUP_MAFILES, accountName + MafileNamingStrategy.DEF_EXTENSION), data); } - public static async Task RenameMafiles(bool loginAsFileName, IProgress? progress = null) + public static async Task RenameMafiles(bool loginAsFileName, + IProgress? progress = null) { - if (MaFiles.Count == 0) return new MafileRenameResult(); + if (MaFiles.Count == 0) return new MafilesBulkRenameResult(); var now = DateTime.Now; var backupFileName = $"rename_backup_{now:yyyy-MM-dd_HH-mm-ss}.zip"; var zipPath = Path.Combine(BackupMafilesDirectory, backupFileName); @@ -255,7 +216,7 @@ public static class Storage } var mafiles = MaFiles.ToList(); - var res = new MafileRenameResult + var res = new MafilesBulkRenameResult { Total = mafiles.Count, BackupFileName = backupFileName @@ -266,7 +227,7 @@ public static class Storage { try { - var targetFileName = CreateMafileFileName(mafile, loginAsFileName); + var targetFileName = MafilesStorageHelper.CreateMafileFileName(mafile, loginAsFileName); if (mafile.Filename == targetFileName || mafile.Filename == null) { res.Renamed += 1; @@ -314,14 +275,4 @@ public static class Storage res.Errors += 1; } } - - public class MafileRenameResult - { - public int Total { get; set; } - public int Renamed { get; set; } - public int NotRenamed => Errors + Conflict; - public int Errors { get; set; } - public int Conflict { get; set; } - public string BackupFileName { get; set; } - } } \ No newline at end of file diff --git a/src/NebulaAuth/Model/SessionHandler_API.cs b/src/NebulaAuth/Model/SessionHandler_API.cs index 3c8337b..0b38909 100644 --- a/src/NebulaAuth/Model/SessionHandler_API.cs +++ b/src/NebulaAuth/Model/SessionHandler_API.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; using AchiesUtilities.Web.Models; using NebulaAuth.Model.Entities; +using NebulaAuth.Model.Mafiles; using SteamLib.Api.Mobile; using SteamLib.Authentication; using SteamLib.Authentication.LoginV2; diff --git a/src/NebulaAuth/ViewModel/Linker/LinkAccountVM.cs b/src/NebulaAuth/ViewModel/Linker/LinkAccountVM.cs index 82f5b31..d1c1146 100644 --- a/src/NebulaAuth/ViewModel/Linker/LinkAccountVM.cs +++ b/src/NebulaAuth/ViewModel/Linker/LinkAccountVM.cs @@ -12,6 +12,7 @@ using CommunityToolkit.Mvvm.Input; using NebulaAuth.Core; using NebulaAuth.Model; using NebulaAuth.Model.Entities; +using NebulaAuth.Model.Mafiles; using NebulaAuth.Utility; using NLog; using SteamLib; @@ -224,7 +225,7 @@ public partial class LinkAccountVM : ObservableObject, ISmsCodeProvider, IPhoneN Logger.Error(ex, "Error during saving Nebula data to mafile"); } - Storage.SaveMafile(mafile); + await Storage.SaveMafileAsync(mafile); await Done(mafile.RevocationCode ?? string.Empty, mafile.SteamId.Steam64.ToString(), login); } diff --git a/src/NebulaAuth/ViewModel/MafileMover/MafileMoverVM.cs b/src/NebulaAuth/ViewModel/MafileMover/MafileMoverVM.cs index c6b30aa..4feaa81 100644 --- a/src/NebulaAuth/ViewModel/MafileMover/MafileMoverVM.cs +++ b/src/NebulaAuth/ViewModel/MafileMover/MafileMoverVM.cs @@ -12,6 +12,7 @@ using CommunityToolkit.Mvvm.Input; using NebulaAuth.Core; using NebulaAuth.Model; using NebulaAuth.Model.Entities; +using NebulaAuth.Model.Mafiles; using NebulaAuth.Utility; using NebulaAuth.ViewModel.Linker; using Newtonsoft.Json; diff --git a/src/NebulaAuth/ViewModel/MainVM.cs b/src/NebulaAuth/ViewModel/MainVM.cs index cb05dab..2bcd1da 100644 --- a/src/NebulaAuth/ViewModel/MainVM.cs +++ b/src/NebulaAuth/ViewModel/MainVM.cs @@ -10,6 +10,7 @@ using MaterialDesignThemes.Wpf; using NebulaAuth.Core; using NebulaAuth.Model; using NebulaAuth.Model.Entities; +using NebulaAuth.Model.Mafiles; using NebulaAuth.Utility; using NebulaAuth.View; using NebulaAuth.View.Dialogs; diff --git a/src/NebulaAuth/ViewModel/MainVM_File.cs b/src/NebulaAuth/ViewModel/MainVM_File.cs index 8dd6d3d..3f20fa0 100644 --- a/src/NebulaAuth/ViewModel/MainVM_File.cs +++ b/src/NebulaAuth/ViewModel/MainVM_File.cs @@ -13,6 +13,7 @@ using NebulaAuth.Core; using NebulaAuth.Model; using NebulaAuth.Model.Entities; using NebulaAuth.Model.Exceptions; +using NebulaAuth.Model.Mafiles; using NebulaAuth.Utility; using NebulaAuth.View; using NebulaAuth.View.Dialogs; @@ -78,7 +79,7 @@ public partial class MainVM //File //TODO: Refactor { try { - Storage.AddNewMafile(str, confirmOverwrite ?? false); + await Storage.AddNewMafile(str, confirmOverwrite ?? false); added++; } catch (FormatException) @@ -92,7 +93,7 @@ public partial class MainVM //File //TODO: Refactor if (confirmOverwrite == true) { - Storage.AddNewMafile(str, true); + await Storage.AddNewMafile(str, true); added++; } else if (confirmOverwrite == false) diff --git a/src/NebulaAuth/ViewModel/MainVM_Groups.cs b/src/NebulaAuth/ViewModel/MainVM_Groups.cs index 22d3bdf..30fcb9d 100644 --- a/src/NebulaAuth/ViewModel/MainVM_Groups.cs +++ b/src/NebulaAuth/ViewModel/MainVM_Groups.cs @@ -5,8 +5,8 @@ using AchiesUtilities.Extensions; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using NebulaAuth.Core; -using NebulaAuth.Model; using NebulaAuth.Model.Entities; +using NebulaAuth.Model.Mafiles; namespace NebulaAuth.ViewModel; diff --git a/src/NebulaAuth/ViewModel/MainVM_Proxy.cs b/src/NebulaAuth/ViewModel/MainVM_Proxy.cs index 1453db0..61d97eb 100644 --- a/src/NebulaAuth/ViewModel/MainVM_Proxy.cs +++ b/src/NebulaAuth/ViewModel/MainVM_Proxy.cs @@ -5,6 +5,7 @@ using CommunityToolkit.Mvvm.Input; using NebulaAuth.Core; using NebulaAuth.Model; using NebulaAuth.Model.Entities; +using NebulaAuth.Model.Mafiles; namespace NebulaAuth.ViewModel; diff --git a/src/NebulaAuth/ViewModel/Other/SetAccountPasswordsVM.cs b/src/NebulaAuth/ViewModel/Other/SetAccountPasswordsVM.cs index 2ecaa59..846c8ca 100644 --- a/src/NebulaAuth/ViewModel/Other/SetAccountPasswordsVM.cs +++ b/src/NebulaAuth/ViewModel/Other/SetAccountPasswordsVM.cs @@ -5,6 +5,7 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using NebulaAuth.Core; using NebulaAuth.Model; +using NebulaAuth.Model.Mafiles; using SteamLibForked.Models.SteamIds; namespace NebulaAuth.ViewModel.Other; diff --git a/src/NebulaAuth/ViewModel/Other/SettingsVM.cs b/src/NebulaAuth/ViewModel/Other/SettingsVM.cs index c375892..dd6dbbd 100644 --- a/src/NebulaAuth/ViewModel/Other/SettingsVM.cs +++ b/src/NebulaAuth/ViewModel/Other/SettingsVM.cs @@ -6,6 +6,7 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using NebulaAuth.Core; using NebulaAuth.Model; +using NebulaAuth.Model.Mafiles; namespace NebulaAuth.ViewModel.Other; @@ -53,7 +54,7 @@ public partial class SettingsVM : ObservableObject var targetValue = UseAccountNameAsMafileNamePreview; if (UseAccountNameAsMafileName == targetValue) return; RenameMafilesProgress = 0; - Storage.MafileRenameResult? result = null; + MafilesBulkRenameResult? result = null; try { result = await Storage.RenameMafiles(targetValue, new Progress(p => RenameMafilesProgress = p));