From df7d01c35e029ffdc24024f104add38d6ea61260 Mon Sep 17 00:00:00 2001 From: Salvador Cipolla Date: Fri, 13 Sep 2024 20:09:39 -0300 Subject: [PATCH 1/7] Advanced mod upload, UI work --- Knossos.NET/App.axaml | 1 + Knossos.NET/Knossos.NET.csproj | 4 + .../Templates/DevModVersionsViewModel.cs | 31 +++ .../Windows/DevModAdvancedUploadViewModel.cs | 251 ++++++++++++++++++ .../Views/Templates/DevModVersionsView.axaml | 5 +- .../Windows/DevModAdvancedUploadView.axaml | 66 +++++ .../Windows/DevModAdvancedUploadView.axaml.cs | 11 + 7 files changed, 367 insertions(+), 2 deletions(-) create mode 100644 Knossos.NET/ViewModels/Windows/DevModAdvancedUploadViewModel.cs create mode 100644 Knossos.NET/Views/Windows/DevModAdvancedUploadView.axaml create mode 100644 Knossos.NET/Views/Windows/DevModAdvancedUploadView.axaml.cs diff --git a/Knossos.NET/App.axaml b/Knossos.NET/App.axaml index 86cf03f5..07fbaa99 100644 --- a/Knossos.NET/App.axaml +++ b/Knossos.NET/App.axaml @@ -15,6 +15,7 @@ + diff --git a/Knossos.NET/Knossos.NET.csproj b/Knossos.NET/Knossos.NET.csproj index cec9d8d6..501faaaf 100644 --- a/Knossos.NET/Knossos.NET.csproj +++ b/Knossos.NET/Knossos.NET.csproj @@ -70,6 +70,7 @@ + @@ -90,6 +91,9 @@ DeveloperModsView.axaml + + DevModAdvancedUploadView.axaml + MessageBox.axaml diff --git a/Knossos.NET/ViewModels/Templates/DevModVersionsViewModel.cs b/Knossos.NET/ViewModels/Templates/DevModVersionsViewModel.cs index bd9aa9bb..8c89e692 100644 --- a/Knossos.NET/ViewModels/Templates/DevModVersionsViewModel.cs +++ b/Knossos.NET/ViewModels/Templates/DevModVersionsViewModel.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading.Tasks; namespace Knossos.NET.ViewModels { @@ -217,7 +218,37 @@ public void HackUpdateModList() Mods = Mods.ToList(); } + internal async void UploadModAdvanced() + { + var mod = editor?.ActiveVersion; + if (mod != null) + { + if (!mod.inNebula) + { + if (mod.type == ModType.mod || mod.type == ModType.tc) + { + var dialog = new DevModAdvancedUploadView(); + dialog.DataContext = new DevModAdvancedUploadViewModel(mod, dialog); + await dialog.ShowDialog(MainWindow.instance!); + } + else + { + _ = MessageBox.Show(MainWindow.instance!, "Advanced uploading is only available for Mods and TCs.", "Unsupported for type: " + mod.type, MessageBox.MessageBoxButtons.OK); + } + } + else + { + _ = MessageBox.Show(MainWindow.instance!, "This mod version is already uploaded to nebula, if you want to update the metadata use the basic upload", "Mod already uploaded", MessageBox.MessageBoxButtons.OK); + } + } + } + internal async void UploadMod() + { + await UploadProcess(); + } + + internal async Task UploadProcess() { /* * Pre-Upload Checks: diff --git a/Knossos.NET/ViewModels/Windows/DevModAdvancedUploadViewModel.cs b/Knossos.NET/ViewModels/Windows/DevModAdvancedUploadViewModel.cs new file mode 100644 index 00000000..864348a8 --- /dev/null +++ b/Knossos.NET/ViewModels/Windows/DevModAdvancedUploadViewModel.cs @@ -0,0 +1,251 @@ +using Avalonia.Controls; +using Avalonia.Media; +using Avalonia.Threading; +using CommunityToolkit.Mvvm.ComponentModel; +using Knossos.NET.Models; +using Knossos.NET.Views; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using static System.Net.Mime.MediaTypeNames; + +namespace Knossos.NET.ViewModels +{ + public partial class DevModAdvancedUploadData : ObservableObject + { + [ObservableProperty] + internal List otherVersions = new List(); + + internal int otherVersionsSelectedIndex = 0; + internal int OtherVersionsSelectedIndex + { + get { return otherVersionsSelectedIndex; } + set + { + if (otherVersionsSelectedIndex != value) + { + this.SetProperty(ref otherVersionsSelectedIndex, value); + if (value <= 1 ) //Manual Input // Auto + { + CustomHash = ""; + } + else + { + try + { + //Mod class is saved in the datacontext for each version + if (OtherVersions[value].DataContext != null) + { + var modPackage = (ModPackage)OtherVersions[value].DataContext!; + if (modPackage != null && modPackage.files != null) + { + CustomHash = modPackage.files.FirstOrDefault()!.checksum![1].ToString(); + } + else + { + CustomHash = "Error getting hash"; + } + } + else + { + CustomHash = "Error getting hash"; + } + } + catch (Exception ex) + { + CustomHash = "Error getting hash"; + Log.Add(Log.LogSeverity.Error, "DevModAdvancedUploadData(OtherVersionsSelectedIndex.Setter)", ex); + } + } + } + } + } + + internal bool upload = true; + internal bool Upload + { + get { return upload; } + set + { + if (upload != value) + { + this.SetProperty(ref upload, value); + try + { + if (value == false) + { + //Enable all Versions listed in the combobox + OtherVersions.ForEach(o => o.IsEnabled = true); + OtherVersions[0].IsEnabled = false; // Disable "auto" + CustomHash = ""; + //Select what should be the latest version of a mod id + OtherVersionsSelectedIndex = OtherVersions.Count() - 1; + } + else + { + //Disable all versions listed in the combobox + OtherVersions.ForEach(o => o.IsEnabled = false); + OtherVersions[0].IsEnabled = true; //Enable Auto + //Select Auto + OtherVersionsSelectedIndex = 0; + } + } + catch (Exception ex) + { + Log.Add(Log.LogSeverity.Error, "DevModAdvancedUploadData(Upload.Setter)", ex); + } + } + } + } + + [ObservableProperty] + internal string customHash = ""; + + public ModPackage? package; + public string PackageName + { + get + { + if (package != null) + return package.name; + else + return "package is null"; + } + } + + + public DevModAdvancedUploadData(ModPackage package, Mod mod) + { + this.package = package; + + //Fill Get Hash Combobox + var auto = new ComboBoxItem(); + auto.Content = "Auto"; + auto.IsEnabled = true; + OtherVersions.Add(auto); + + var manual = new ComboBoxItem(); + manual.Content = "Manual Input"; + manual.IsEnabled = false; + OtherVersions.Add(manual); + + //Get all local versions of this ID that are uploaded to nebula, that devmode is enabled and contains this package name + var versions = Knossos.GetInstalledModList(mod.id).Where( m => m.devMode && m.inNebula && m.packages != null && m.packages.FirstOrDefault(p => p.name == package.name) != null); + + if (versions != null) + { + //Reload json data to get the hashes + versions.ForEach(m => m.ReLoadJson()); + foreach (var o in versions) + { + if (o != mod) + { + try + { + //List version in the combobox + var p = o.packages.FirstOrDefault(p => p.name == package.name); + if (p != null && p.files != null && p.files.Any() && p.files.FirstOrDefault()?.checksum?.Length > 0) + { + var item = new ComboBoxItem(); + item.DataContext = p; + item.Content = o.version.ToString(); + item.IsEnabled = false; + item.Foreground = o.isPrivate ? Brushes.Red : Brushes.Cyan; + OtherVersions.Add(item); + } + } + catch (Exception ex) + { + Log.Add(Log.LogSeverity.Error, "DevModAdvancedUploadData(contructor)", ex); + } + } + } + } + OtherVersionsSelectedIndex = 0; + } + } + + /********************************************************************************/ + + public partial class DevModAdvancedUploadViewModel : ViewModelBase + { + [ObservableProperty] + internal string title = string.Empty; + [ObservableProperty] + internal bool loading = true; + [ObservableProperty] + internal int parallelCompressing = 1; + [ObservableProperty] + internal int parallelUploads = 1; + [ObservableProperty] + internal List modPackagesData = new List(); + + private Mod? uploadMod = null; + private DevModAdvancedUploadView? dialog = null; + + public DevModAdvancedUploadViewModel() + { + } + + public DevModAdvancedUploadViewModel(Mod mod, DevModAdvancedUploadView dialog) + { + this.dialog = dialog; + Title = "Advanced Nebula Upload: " + mod; + uploadMod = mod; + _ = Task.Run(() => { LazyLoading(); }); + } + + private void LazyLoading() + { + if (uploadMod != null && uploadMod.packages != null) + { + foreach (var package in uploadMod.packages) + { + Dispatcher.UIThread.Invoke(() => + { + var data = new DevModAdvancedUploadData(package, uploadMod); + ModPackagesData.Add(data); + }); + } + } + Loading = false; + } + + internal async void UploadMod() + { + //We have to check that all packages we arent going to upload has a valid sha256 and that they had been uploaded to nebula + //Basic check + foreach (var data in ModPackagesData) + { + if (!data.upload) + { + if (String.IsNullOrWhiteSpace(data.CustomHash) || data.CustomHash.Length == 0) + { + _ = MessageBox.Show(MainWindow.instance!, "Package: " + data.PackageName + " is not set to upload but it lacks a defined sha256. Operation cancelled.", "Missing hash data", MessageBox.MessageBoxButtons.OK); + return; + } + else + { + //ensure it is in lowercase + data.CustomHash = data.CustomHash.ToLower(); + } + } + } + + //Check with nebula + foreach (var data in ModPackagesData) + { + if (!data.upload) + { + if(await Nebula.IsFileUploaded(data.CustomHash) == false) + { + _ = MessageBox.Show(MainWindow.instance!, "The provided sha256 hash for package: " + data.PackageName + " is not valid or not uploaded to Nebula, operation cancelled. Passed hash:" + data.CustomHash, "File hash is not uploaded to nebula (or it is incorrect)", MessageBox.MessageBoxButtons.OK); + Log.Add(Log.LogSeverity.Error,"DevModAdvancedUploadViewModel.UploadMod", "The provided sha256 hash for package: " + data.PackageName + " is not valid or not uploaded to Nebula, operation cancelled. Passed hash:"+data.CustomHash); + } + await Task.Delay(1000); + } + } + } + } +} diff --git a/Knossos.NET/Views/Templates/DevModVersionsView.axaml b/Knossos.NET/Views/Templates/DevModVersionsView.axaml index 0d497f37..b52a072c 100644 --- a/Knossos.NET/Views/Templates/DevModVersionsView.axaml +++ b/Knossos.NET/Views/Templates/DevModVersionsView.axaml @@ -48,9 +48,10 @@ - + - + + + + + diff --git a/Knossos.NET/Views/Windows/DevModAdvancedUploadView.axaml.cs b/Knossos.NET/Views/Windows/DevModAdvancedUploadView.axaml.cs new file mode 100644 index 00000000..3b8cd273 --- /dev/null +++ b/Knossos.NET/Views/Windows/DevModAdvancedUploadView.axaml.cs @@ -0,0 +1,11 @@ +using Avalonia.Controls; + +namespace Knossos.NET.Views; + +public partial class DevModAdvancedUploadView : Window +{ + public DevModAdvancedUploadView() + { + InitializeComponent(); + } +} \ No newline at end of file From 00739a2f6fdb181a1f02e4c919431a6e79287dec Mon Sep 17 00:00:00 2001 From: Salvador Cipolla Date: Sat, 14 Sep 2024 20:27:45 -0300 Subject: [PATCH 2/7] Backend implementation and correction to UI implementation of advanced uploads a basic upload test was also performed. --- Knossos.NET/ViewModels/TaskViewModel.cs | 7 +- .../Templates/DevModVersionsViewModel.cs | 13 +- .../ViewModels/Templates/TaskItemViewModel.cs | 55 ++++++-- .../Windows/DevModAdvancedUploadViewModel.cs | 124 +++++++++++------- .../Windows/DevModAdvancedUploadView.axaml | 2 +- 5 files changed, 135 insertions(+), 66 deletions(-) diff --git a/Knossos.NET/ViewModels/TaskViewModel.cs b/Knossos.NET/ViewModels/TaskViewModel.cs index 9daf2131..bcd7725c 100644 --- a/Knossos.NET/ViewModels/TaskViewModel.cs +++ b/Knossos.NET/ViewModels/TaskViewModel.cs @@ -436,7 +436,10 @@ public async void CreateModVersion(Mod oldMod, string newVersion, Action hackCal /// /// /// - public async void UploadModVersion(Mod mod, bool isNewMod, bool metadataonly = false) + /// + /// + /// + public async void UploadModVersion(Mod mod, bool isNewMod, bool metadataonly = false, int parallelCompression = 1, int parallelUploads = 1, List? advData = null ) { using (var cancelSource = new CancellationTokenSource()) { @@ -446,7 +449,7 @@ public async void UploadModVersion(Mod mod, bool isNewMod, bool metadataonly = f TaskList.Add(newTask); taskQueue.Enqueue(newTask); }); - await newTask.UploadModVersion(mod, isNewMod, metadataonly, cancelSource).ConfigureAwait(false); + await newTask.UploadModVersion(mod, isNewMod, metadataonly, cancelSource, parallelCompression, parallelUploads, advData).ConfigureAwait(false); } } diff --git a/Knossos.NET/ViewModels/Templates/DevModVersionsViewModel.cs b/Knossos.NET/ViewModels/Templates/DevModVersionsViewModel.cs index 8c89e692..4b95cf28 100644 --- a/Knossos.NET/ViewModels/Templates/DevModVersionsViewModel.cs +++ b/Knossos.NET/ViewModels/Templates/DevModVersionsViewModel.cs @@ -228,7 +228,7 @@ internal async void UploadModAdvanced() if (mod.type == ModType.mod || mod.type == ModType.tc) { var dialog = new DevModAdvancedUploadView(); - dialog.DataContext = new DevModAdvancedUploadViewModel(mod, dialog); + dialog.DataContext = new DevModAdvancedUploadViewModel(mod, dialog, this); await dialog.ShowDialog(MainWindow.instance!); } else @@ -243,12 +243,19 @@ internal async void UploadModAdvanced() } } + //For UI button internal async void UploadMod() { await UploadProcess(); } - internal async Task UploadProcess() + //for the advanced upload window + public void AdvancedUpload(List advData, int parallelCompression, int parallelUploads) + { + _ = UploadProcess(advData, parallelCompression, parallelUploads); + } + + private async Task UploadProcess(List? advData = null, int parallelCompression = 1, int parallelUploads = 1) { /* * Pre-Upload Checks: @@ -533,7 +540,7 @@ await MessageBox.Show(MainWindow.instance!, "Your mod depends on mod id: " + dep //Basic check finish, create task ButtonsEnabled = true; - TaskViewModel.Instance!.UploadModVersion(mod, isNewMod, metaUpdOnly); + TaskViewModel.Instance!.UploadModVersion(mod, isNewMod, metaUpdOnly, parallelCompression, parallelUploads, advData); } } catch(Exception ex) diff --git a/Knossos.NET/ViewModels/Templates/TaskItemViewModel.cs b/Knossos.NET/ViewModels/Templates/TaskItemViewModel.cs index 1c2a5cb4..6f773ea0 100644 --- a/Knossos.NET/ViewModels/Templates/TaskItemViewModel.cs +++ b/Knossos.NET/ViewModels/Templates/TaskItemViewModel.cs @@ -1522,7 +1522,7 @@ private async Task PrepareModPkg(ModPackage pkg, string modFullPath, Cance } } - public async Task UploadModVersion(Mod mod, bool isNewMod, bool metaOnly, CancellationTokenSource? cancelSource = null) + public async Task UploadModVersion(Mod mod, bool isNewMod, bool metaOnly, CancellationTokenSource? cancelSource = null, int parallelCompression = 1, int parallelUploads = 1, List? advData = null ) { try { @@ -1607,13 +1607,37 @@ public async Task UploadModVersion(Mod mod, bool isNewMod, bool metaOnly, Info = "Prepare Packages"; Directory.CreateDirectory(mod.fullPath + Path.DirectorySeparatorChar + "kn_upload"); //Prepare packages, update data on mod - await Parallel.ForEachAsync(mod.packages, new ParallelOptions { MaxDegreeOfParallelism = Knossos.globalSettings.compressionMaxParallelism }, async (pkg, token) => + await Parallel.ForEachAsync(mod.packages, new ParallelOptions { MaxDegreeOfParallelism = parallelCompression }, async (pkg, token) => { - if (mod.type != ModType.mod && mod.type != ModType.tc) //Just to be sure - pkg.isVp = false; - var newTask = new TaskItemViewModel(); - await Dispatcher.UIThread.InvokeAsync(() => TaskList.Insert(0, newTask)); - await newTask.PrepareModPkg(pkg, mod.fullPath, cancellationTokenSource); + bool skipPkg = false; + //We should skip this? + if(advData != null) + { + var uploadedPkg = advData.FirstOrDefault(p => p.packageInNebula!.name == pkg.name)?.packageInNebula; + if (uploadedPkg != null) + { + pkg.notes = uploadedPkg.notes; + pkg.isVp = uploadedPkg.isVp; + pkg.status = uploadedPkg.status; + pkg.filelist = uploadedPkg.filelist; + pkg.files = uploadedPkg.files; + pkg.dependencies = uploadedPkg.dependencies; + pkg.environment = uploadedPkg.environment; + pkg.executables = uploadedPkg.executables; + pkg.folder = uploadedPkg.folder; + pkg.checkNotes = uploadedPkg.checkNotes; + pkg.files?.ForEach(f => f.urls = null); //Cant send urls to Nebula or it gets rejected + skipPkg = true; + } + } + if (!skipPkg) + { + if (mod.type != ModType.mod && mod.type != ModType.tc) //Just to be sure + pkg.isVp = false; + var newTask = new TaskItemViewModel(); + await Dispatcher.UIThread.InvokeAsync(() => TaskList.Insert(0, newTask)); + await newTask.PrepareModPkg(pkg, mod.fullPath, cancellationTokenSource); + } ProgressCurrent++; if (cancellationTokenSource.IsCancellationRequested) throw new TaskCanceledException(); @@ -1621,11 +1645,20 @@ public async Task UploadModVersion(Mod mod, bool isNewMod, bool metaOnly, Info = "Upload Packages"; //Upload Packages - await Parallel.ForEachAsync(mod.packages, new ParallelOptions { MaxDegreeOfParallelism = 1 }, async (pkg, token) => + await Parallel.ForEachAsync(mod.packages, new ParallelOptions { MaxDegreeOfParallelism = parallelUploads }, async (pkg, token) => { - var newTask = new TaskItemViewModel(); - await Dispatcher.UIThread.InvokeAsync(() => TaskList.Insert(0, newTask)); - await newTask.UploadModPkg(pkg, mod.fullPath, cancellationTokenSource); + bool skipPkg = false; + //We should skip this? + if (advData != null && advData.FirstOrDefault(p => p.packageInNebula!.name == pkg.name) != null) + { + skipPkg = true; + } + if (!skipPkg) + { + var newTask = new TaskItemViewModel(); + await Dispatcher.UIThread.InvokeAsync(() => TaskList.Insert(0, newTask)); + await newTask.UploadModPkg(pkg, mod.fullPath, cancellationTokenSource); + } ProgressCurrent++; if (cancellationTokenSource.IsCancellationRequested) throw new TaskCanceledException(); diff --git a/Knossos.NET/ViewModels/Windows/DevModAdvancedUploadViewModel.cs b/Knossos.NET/ViewModels/Windows/DevModAdvancedUploadViewModel.cs index 864348a8..76386130 100644 --- a/Knossos.NET/ViewModels/Windows/DevModAdvancedUploadViewModel.cs +++ b/Knossos.NET/ViewModels/Windows/DevModAdvancedUploadViewModel.cs @@ -26,36 +26,63 @@ internal int OtherVersionsSelectedIndex if (otherVersionsSelectedIndex != value) { this.SetProperty(ref otherVersionsSelectedIndex, value); - if (value <= 1 ) //Manual Input // Auto + if (value == 0 ) // Auto { CustomHash = ""; } else { + if(package == null) + { + CustomHash = "Error: Local package was null, this should not happen."; + return; + } try { - //Mod class is saved in the datacontext for each version - if (OtherVersions[value].DataContext != null) + //Get package data from nebula and let the cache do its thing + if (packageInNebula == null) { - var modPackage = (ModPackage)OtherVersions[value].DataContext!; - if (modPackage != null && modPackage.files != null) + if (OtherVersions[value].DataContext == null) { - CustomHash = modPackage.files.FirstOrDefault()!.checksum![1].ToString(); + CustomHash = "Error: Datacontext was null"; + return; } - else + CustomHash = "Loading..."; + var m = (Mod)OtherVersions[value].DataContext!; + Task.Run(async () => { - CustomHash = "Error getting hash"; - } + try + { + var modTask = await Nebula.GetModData(mod!.id, m.version); + if (modTask == null) + { + CustomHash = "Error: Unable to get data from Nebula"; + return; + } + packageInNebula = modTask.packages.FirstOrDefault(p => p.name == package.name); + if (packageInNebula == null) + { + CustomHash = "Error: Package was not found on selected version, or Nebula error."; + return; + } + CustomHash = packageInNebula!.files!.FirstOrDefault()!.checksum![1].ToString(); + } + catch (Exception ex) + { + Log.Add(Log.LogSeverity.Error, "DevModAdvancedUploadData(OtherVersionsSelectedIndex.Setter2)", ex); + CustomHash = "Error in getting data from Nebula"; + }; + }); } else { - CustomHash = "Error getting hash"; + CustomHash = packageInNebula!.files!.FirstOrDefault()!.checksum![1].ToString(); } } catch (Exception ex) { CustomHash = "Error getting hash"; - Log.Add(Log.LogSeverity.Error, "DevModAdvancedUploadData(OtherVersionsSelectedIndex.Setter)", ex); + Log.Add(Log.LogSeverity.Error, "DevModAdvancedUploadData(OtherVersionsSelectedIndex.Setter3)", ex); } } } @@ -103,6 +130,9 @@ internal bool Upload internal string customHash = ""; public ModPackage? package; + public ModPackage? packageInNebula = null; + private Mod? mod; + public string PackageName { get @@ -115,9 +145,10 @@ public string PackageName } - public DevModAdvancedUploadData(ModPackage package, Mod mod) + public DevModAdvancedUploadData(ModPackage package, Mod mod, List allVersionsOfMod) { this.package = package; + this.mod = mod; //Fill Get Hash Combobox var auto = new ComboBoxItem(); @@ -125,41 +156,17 @@ public DevModAdvancedUploadData(ModPackage package, Mod mod) auto.IsEnabled = true; OtherVersions.Add(auto); - var manual = new ComboBoxItem(); - manual.Content = "Manual Input"; - manual.IsEnabled = false; - OtherVersions.Add(manual); - - //Get all local versions of this ID that are uploaded to nebula, that devmode is enabled and contains this package name - var versions = Knossos.GetInstalledModList(mod.id).Where( m => m.devMode && m.inNebula && m.packages != null && m.packages.FirstOrDefault(p => p.name == package.name) != null); - - if (versions != null) + foreach (var o in allVersionsOfMod) { - //Reload json data to get the hashes - versions.ForEach(m => m.ReLoadJson()); - foreach (var o in versions) + if (o.version != mod.version) { - if (o != mod) - { - try - { - //List version in the combobox - var p = o.packages.FirstOrDefault(p => p.name == package.name); - if (p != null && p.files != null && p.files.Any() && p.files.FirstOrDefault()?.checksum?.Length > 0) - { - var item = new ComboBoxItem(); - item.DataContext = p; - item.Content = o.version.ToString(); - item.IsEnabled = false; - item.Foreground = o.isPrivate ? Brushes.Red : Brushes.Cyan; - OtherVersions.Add(item); - } - } - catch (Exception ex) - { - Log.Add(Log.LogSeverity.Error, "DevModAdvancedUploadData(contructor)", ex); - } - } + //List version in the combobox + var item = new ComboBoxItem(); + item.DataContext = o; + item.Content = o.version.ToString(); + item.IsEnabled = false; + item.Foreground = o.isPrivate ? Brushes.Red : Brushes.Cyan; + OtherVersions.Add(item); } } OtherVersionsSelectedIndex = 0; @@ -183,28 +190,31 @@ public partial class DevModAdvancedUploadViewModel : ViewModelBase private Mod? uploadMod = null; private DevModAdvancedUploadView? dialog = null; - + private DevModVersionsViewModel? versionsViewModel = null; public DevModAdvancedUploadViewModel() { } - public DevModAdvancedUploadViewModel(Mod mod, DevModAdvancedUploadView dialog) + public DevModAdvancedUploadViewModel(Mod mod, DevModAdvancedUploadView? dialog, DevModVersionsViewModel? versionsViewModel) { this.dialog = dialog; + this.versionsViewModel = versionsViewModel; Title = "Advanced Nebula Upload: " + mod; uploadMod = mod; _ = Task.Run(() => { LazyLoading(); }); + this.versionsViewModel = versionsViewModel; } - private void LazyLoading() + private async void LazyLoading() { if (uploadMod != null && uploadMod.packages != null) { + var allVersionsOfThisMod = await Nebula.GetAllModsWithID(uploadMod.id); foreach (var package in uploadMod.packages) { Dispatcher.UIThread.Invoke(() => { - var data = new DevModAdvancedUploadData(package, uploadMod); + var data = new DevModAdvancedUploadData(package, uploadMod, allVersionsOfThisMod); ModPackagesData.Add(data); }); } @@ -230,10 +240,18 @@ internal async void UploadMod() //ensure it is in lowercase data.CustomHash = data.CustomHash.ToLower(); } + + if(data.packageInNebula == null) + { + _ = MessageBox.Show(MainWindow.instance!, "Package: " + data.PackageName + " is not set to upload but it lacks the package data from Nebula. Operation cancelled.", "Missing package data", MessageBox.MessageBoxButtons.OK); + return; + } } } //Check with nebula + //Disabled, moved to PerPackage + /* foreach (var data in ModPackagesData) { if (!data.upload) @@ -242,10 +260,18 @@ internal async void UploadMod() { _ = MessageBox.Show(MainWindow.instance!, "The provided sha256 hash for package: " + data.PackageName + " is not valid or not uploaded to Nebula, operation cancelled. Passed hash:" + data.CustomHash, "File hash is not uploaded to nebula (or it is incorrect)", MessageBox.MessageBoxButtons.OK); Log.Add(Log.LogSeverity.Error,"DevModAdvancedUploadViewModel.UploadMod", "The provided sha256 hash for package: " + data.PackageName + " is not valid or not uploaded to Nebula, operation cancelled. Passed hash:"+data.CustomHash); + return; } await Task.Delay(1000); } } + */ + + //Send to upload and close window + await Dispatcher.UIThread.InvokeAsync( ()=> { + versionsViewModel?.AdvancedUpload(ModPackagesData, ParallelCompressing, ParallelUploads); + dialog?.Close(); + }); } } } diff --git a/Knossos.NET/Views/Windows/DevModAdvancedUploadView.axaml b/Knossos.NET/Views/Windows/DevModAdvancedUploadView.axaml index f220033e..8ccc80ac 100644 --- a/Knossos.NET/Views/Windows/DevModAdvancedUploadView.axaml +++ b/Knossos.NET/Views/Windows/DevModAdvancedUploadView.axaml @@ -56,7 +56,7 @@ - + From 8b322b85be6a11b410b87260f76535fc822f89c6 Mon Sep 17 00:00:00 2001 From: Salvador Cipolla Date: Sat, 14 Sep 2024 21:34:17 -0300 Subject: [PATCH 3/7] Actually consider if we are skipping a pkg or not --- .../ViewModels/Templates/TaskItemViewModel.cs | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/Knossos.NET/ViewModels/Templates/TaskItemViewModel.cs b/Knossos.NET/ViewModels/Templates/TaskItemViewModel.cs index 6f773ea0..c34e543c 100644 --- a/Knossos.NET/ViewModels/Templates/TaskItemViewModel.cs +++ b/Knossos.NET/ViewModels/Templates/TaskItemViewModel.cs @@ -1613,21 +1613,25 @@ public async Task UploadModVersion(Mod mod, bool isNewMod, bool metaOnly, //We should skip this? if(advData != null) { - var uploadedPkg = advData.FirstOrDefault(p => p.packageInNebula!.name == pkg.name)?.packageInNebula; - if (uploadedPkg != null) + var advDataPkg = advData.FirstOrDefault(p => p.packageInNebula != null && p.packageInNebula!.name == pkg.name); + if (advDataPkg != null && !advDataPkg.Upload) { - pkg.notes = uploadedPkg.notes; - pkg.isVp = uploadedPkg.isVp; - pkg.status = uploadedPkg.status; - pkg.filelist = uploadedPkg.filelist; - pkg.files = uploadedPkg.files; - pkg.dependencies = uploadedPkg.dependencies; - pkg.environment = uploadedPkg.environment; - pkg.executables = uploadedPkg.executables; - pkg.folder = uploadedPkg.folder; - pkg.checkNotes = uploadedPkg.checkNotes; - pkg.files?.ForEach(f => f.urls = null); //Cant send urls to Nebula or it gets rejected - skipPkg = true; + var uploadedPkg = advDataPkg.packageInNebula; + if (uploadedPkg != null) + { + pkg.notes = uploadedPkg.notes; + pkg.isVp = uploadedPkg.isVp; + pkg.status = uploadedPkg.status; + pkg.filelist = uploadedPkg.filelist; + pkg.files = uploadedPkg.files; + pkg.dependencies = uploadedPkg.dependencies; + pkg.environment = uploadedPkg.environment; + pkg.executables = uploadedPkg.executables; + pkg.folder = uploadedPkg.folder; + pkg.checkNotes = uploadedPkg.checkNotes; + pkg.files?.ForEach(f => f.urls = null); //Cant send urls to Nebula or it gets rejected + skipPkg = true; + } } } if (!skipPkg) @@ -1649,7 +1653,7 @@ public async Task UploadModVersion(Mod mod, bool isNewMod, bool metaOnly, { bool skipPkg = false; //We should skip this? - if (advData != null && advData.FirstOrDefault(p => p.packageInNebula!.name == pkg.name) != null) + if (advData != null && advData.FirstOrDefault(p => p.packageInNebula != null && p.packageInNebula!.name == pkg.name) != null && !advData.FirstOrDefault(p => p.packageInNebula != null && p.packageInNebula!.name == pkg.name)!.Upload) { skipPkg = true; } From df0f3f312973ecf8ca7cdcf7751fb844aa5edc8c Mon Sep 17 00:00:00 2001 From: Salvador Cipolla Date: Sun, 15 Sep 2024 10:54:56 -0300 Subject: [PATCH 4/7] Add log data on pkg skipping --- .../ViewModels/Templates/TaskItemViewModel.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Knossos.NET/ViewModels/Templates/TaskItemViewModel.cs b/Knossos.NET/ViewModels/Templates/TaskItemViewModel.cs index c34e543c..44786f3f 100644 --- a/Knossos.NET/ViewModels/Templates/TaskItemViewModel.cs +++ b/Knossos.NET/ViewModels/Templates/TaskItemViewModel.cs @@ -1631,6 +1631,7 @@ public async Task UploadModVersion(Mod mod, bool isNewMod, bool metaOnly, pkg.checkNotes = uploadedPkg.checkNotes; pkg.files?.ForEach(f => f.urls = null); //Cant send urls to Nebula or it gets rejected skipPkg = true; + Log.Add(Log.LogSeverity.Information, "TaskItemViewModel.UploadModVersion()", "Skipping package preparation for :" + pkg.name + ". Data was loaded from Nebula."); } } } @@ -1653,9 +1654,18 @@ public async Task UploadModVersion(Mod mod, bool isNewMod, bool metaOnly, { bool skipPkg = false; //We should skip this? - if (advData != null && advData.FirstOrDefault(p => p.packageInNebula != null && p.packageInNebula!.name == pkg.name) != null && !advData.FirstOrDefault(p => p.packageInNebula != null && p.packageInNebula!.name == pkg.name)!.Upload) + if (advData != null) { - skipPkg = true; + var advDataPkg = advData.FirstOrDefault(p => p.packageInNebula != null && p.packageInNebula!.name == pkg.name); + if (advDataPkg != null && !advDataPkg.Upload) + { + var uploadedPkg = advDataPkg.packageInNebula; + if (uploadedPkg != null) + { + skipPkg = true; + Log.Add(Log.LogSeverity.Information, "TaskItemViewModel.UploadModVersion()", "Skipping package upload for :" + pkg.name + ". Used the one in Nebula instead, file hash: " + advDataPkg.CustomHash ); + } + } } if (!skipPkg) { From 52d27ef65c4ab58753bb4c55664ff1fe5fa88760 Mon Sep 17 00:00:00 2001 From: Salvador Cipolla Date: Sun, 15 Sep 2024 10:57:35 -0300 Subject: [PATCH 5/7] fix comment --- .../ViewModels/Windows/DevModAdvancedUploadViewModel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Knossos.NET/ViewModels/Windows/DevModAdvancedUploadViewModel.cs b/Knossos.NET/ViewModels/Windows/DevModAdvancedUploadViewModel.cs index 76386130..8c6cf861 100644 --- a/Knossos.NET/ViewModels/Windows/DevModAdvancedUploadViewModel.cs +++ b/Knossos.NET/ViewModels/Windows/DevModAdvancedUploadViewModel.cs @@ -249,8 +249,8 @@ internal async void UploadMod() } } - //Check with nebula - //Disabled, moved to PerPackage + //Check with nebula if the file is uploaded + //Disabled, no need since we are getting the file hash from nebula the file HAS to be uploaded. /* foreach (var data in ModPackagesData) { From 12a05d3ae29b78aab03dacfd78ed936e7916123a Mon Sep 17 00:00:00 2001 From: Salvador Cipolla Date: Sat, 5 Oct 2024 16:55:49 -0300 Subject: [PATCH 6/7] Add experimental feature warning --- Knossos.NET/Views/Windows/DevModAdvancedUploadView.axaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Knossos.NET/Views/Windows/DevModAdvancedUploadView.axaml b/Knossos.NET/Views/Windows/DevModAdvancedUploadView.axaml index 8ccc80ac..b3cf77b4 100644 --- a/Knossos.NET/Views/Windows/DevModAdvancedUploadView.axaml +++ b/Knossos.NET/Views/Windows/DevModAdvancedUploadView.axaml @@ -20,6 +20,7 @@ + From 902f8625b1e8e99c58493bdb17cc73fedbb6c082 Mon Sep 17 00:00:00 2001 From: Salvador Cipolla Date: Sat, 5 Oct 2024 17:12:48 -0300 Subject: [PATCH 7/7] sort the list of mods in the combobox from newer to older --- Knossos.NET/Models/Mod.cs | 13 +++++++++++++ .../Windows/DevModAdvancedUploadViewModel.cs | 1 + 2 files changed, 14 insertions(+) diff --git a/Knossos.NET/Models/Mod.cs b/Knossos.NET/Models/Mod.cs index 77c24543..9eab44c1 100644 --- a/Knossos.NET/Models/Mod.cs +++ b/Knossos.NET/Models/Mod.cs @@ -779,6 +779,7 @@ public async Task LoadFulLNebulaData() /// /// To use with the List .Sort() + /// Retuns a list that is sort from older to newer /// /// /// @@ -788,6 +789,18 @@ public static int CompareVersion(Mod mod1, Mod mod2) return SemanticVersion.Compare(mod1.version, mod2.version); } + /// + /// To use with the List .Sort() + /// Retuns a list that is sort from newer to older + /// + /// + /// + public static int CompareVersionNewerToOlder(Mod mod1, Mod mod2) + { + //inverted + return SemanticVersion.Compare(mod2.version, mod1.version); + } + /// /// Compares two mods and determines if the metadata is different /// Full data must be loaded on both mods for this to work properly diff --git a/Knossos.NET/ViewModels/Windows/DevModAdvancedUploadViewModel.cs b/Knossos.NET/ViewModels/Windows/DevModAdvancedUploadViewModel.cs index 8c6cf861..d73db93c 100644 --- a/Knossos.NET/ViewModels/Windows/DevModAdvancedUploadViewModel.cs +++ b/Knossos.NET/ViewModels/Windows/DevModAdvancedUploadViewModel.cs @@ -210,6 +210,7 @@ private async void LazyLoading() if (uploadMod != null && uploadMod.packages != null) { var allVersionsOfThisMod = await Nebula.GetAllModsWithID(uploadMod.id); + allVersionsOfThisMod.Sort(Mod.CompareVersionNewerToOlder); foreach (var package in uploadMod.packages) { Dispatcher.UIThread.Invoke(() =>