diff --git a/src/UniGetUI.Core.LanguageEngine/Assets/Data/LanguagesReference.json b/src/UniGetUI.Core.LanguageEngine/Assets/Data/LanguagesReference.json
index 940c63b497..8a5c5b44fb 100644
--- a/src/UniGetUI.Core.LanguageEngine/Assets/Data/LanguagesReference.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Data/LanguagesReference.json
@@ -12,10 +12,12 @@
"et": "Estonian - Eesti",
"en": "English - English",
"es": "Spanish - Castellano",
+ "es-MX": "Spanish (Mexico)",
"fa": "Persian - فارسی",
"fi": "Finnish - Suomi",
"fil": "Filipino - Filipino",
"fr": "French - Français",
+ "gl": "Galician - Galego",
"gu": "Gujarati - ગુજરાતી",
"hi": "Hindi - हिंदी",
"hr": "Croatian - Hrvatski",
diff --git a/src/UniGetUI.PAckageEngine.Interfaces/IInstallationOptions.cs b/src/UniGetUI.PAckageEngine.Interfaces/IInstallationOptions.cs
index 5f16e55490..1718e6ea7e 100644
--- a/src/UniGetUI.PAckageEngine.Interfaces/IInstallationOptions.cs
+++ b/src/UniGetUI.PAckageEngine.Interfaces/IInstallationOptions.cs
@@ -17,44 +17,23 @@ public interface IInstallationOptions
public bool RemoveDataOnUninstall { get; set; }
public bool PreRelease { get; set; }
public string CustomInstallLocation { get; set; }
- public IPackage Package { get; }
+ public bool OverridesNextLevelOpts { get; set; }
///
/// Loads and applies the options from the given SerializableInstallationOptions object to the current object.
///
- public void FromSerializable(SerializableInstallationOptions options);
+ public void GetValuesFromSerializable(SerializableInstallationOptions options);
///
/// Returns a SerializableInstallationOptions object containing the options of the current instance.
///
- public SerializableInstallationOptions AsSerializable();
-
- ///
- /// Saves the current options to disk, asynchronously.
- ///
- public async Task SaveToDiskAsync()
- {
- await Task.Run(SaveToDisk);
- }
-
- ///
- /// Loads the options from disk, asynchronously.
- ///
- public async Task LoadFromDiskAsync()
- {
- await Task.Run(LoadFromDisk);
- }
+ public SerializableInstallationOptions ToSerializable();
///
/// Saves the current options to disk.
///
public void SaveToDisk();
- ///
- /// Loads the options from disk.
- ///
- protected void LoadFromDisk();
-
///
/// Returns a string representation of the current options.
///
diff --git a/src/UniGetUI.PackageEngine.Managers.Cargo/Helpers/CargoPkgOperationHelper.cs b/src/UniGetUI.PackageEngine.Managers.Cargo/Helpers/CargoPkgOperationHelper.cs
index e4da839cc0..23beae6bf2 100644
--- a/src/UniGetUI.PackageEngine.Managers.Cargo/Helpers/CargoPkgOperationHelper.cs
+++ b/src/UniGetUI.PackageEngine.Managers.Cargo/Helpers/CargoPkgOperationHelper.cs
@@ -4,7 +4,7 @@
namespace UniGetUI.PackageEngine.Managers.CargoManager;
-internal sealed class CargoPkgOperationHelper(Cargo cargo) : PackagePkgOperationHelper(cargo)
+internal sealed class CargoPkgOperationHelper(Cargo cargo) : BasePkgOperationHelper(cargo)
{
protected override IReadOnlyList _getOperationParameters(IPackage package, IInstallationOptions options, OperationType operation)
{
diff --git a/src/UniGetUI.PackageEngine.Managers.Chocolatey/Helpers/ChocolateyPkgOperationHelper.cs b/src/UniGetUI.PackageEngine.Managers.Chocolatey/Helpers/ChocolateyPkgOperationHelper.cs
index 54de0ebabd..897a421f0a 100644
--- a/src/UniGetUI.PackageEngine.Managers.Chocolatey/Helpers/ChocolateyPkgOperationHelper.cs
+++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/Helpers/ChocolateyPkgOperationHelper.cs
@@ -4,7 +4,7 @@
using UniGetUI.PackageEngine.Interfaces;
namespace UniGetUI.PackageEngine.Managers.ChocolateyManager;
-internal sealed class ChocolateyPkgOperationHelper : PackagePkgOperationHelper
+internal sealed class ChocolateyPkgOperationHelper : BasePkgOperationHelper
{
public ChocolateyPkgOperationHelper(Chocolatey manager) : base(manager) { }
diff --git a/src/UniGetUI.PackageEngine.Managers.Dotnet/Helpers/DotNetPkgOperationHelper.cs b/src/UniGetUI.PackageEngine.Managers.Dotnet/Helpers/DotNetPkgOperationHelper.cs
index 4541eaed9d..b360d7a74f 100644
--- a/src/UniGetUI.PackageEngine.Managers.Dotnet/Helpers/DotNetPkgOperationHelper.cs
+++ b/src/UniGetUI.PackageEngine.Managers.Dotnet/Helpers/DotNetPkgOperationHelper.cs
@@ -4,7 +4,7 @@
using UniGetUI.PackageEngine.Interfaces;
namespace UniGetUI.PackageEngine.Managers.DotNetManager;
-internal sealed class DotNetPkgOperationHelper : PackagePkgOperationHelper
+internal sealed class DotNetPkgOperationHelper : BasePkgOperationHelper
{
public DotNetPkgOperationHelper(DotNet manager) : base(manager) { }
diff --git a/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/BaseNuGet.cs b/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/BaseNuGet.cs
index 5cac161458..5d6d2d437c 100644
--- a/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/BaseNuGet.cs
+++ b/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/BaseNuGet.cs
@@ -59,9 +59,18 @@ protected sealed override IReadOnlyList FindPackages_UnSafe(string quer
sources = [ Properties.DefaultSource ];
}
+ bool canPrerelease = InstallationOptions.LoadForManager(this).PreRelease;
+
foreach(IManagerSource source in sources)
{
- Uri? SearchUrl = new($"{source.Url}/Search()?$filter=IsLatestVersion&$orderby=Id&searchTerm='{HttpUtility.UrlEncode(query)}'&targetFramework=''&includePrerelease=false&$skip=0&$top=50&semVerLevel=2.0.0");
+ Uri? SearchUrl = new($"{source.Url}/Search()" +
+ $"?$filter=IsLatestVersion" +
+ $"&$orderby=Id&searchTerm='{HttpUtility.UrlEncode(query)}'" +
+ $"&targetFramework=''" +
+ $"&includePrerelease={(canPrerelease? "true": "false")}" +
+ $"&$skip=0" +
+ $"&$top=50" +
+ $"&semVerLevel=2.0.0");
// Uri SearchUrl = new($"{source.Url}/Search()?$filter=IsLatestVersion&searchTerm=%27{HttpUtility.UrlEncode(query)}%27&targetFramework=%27%27&includePrerelease=false");
logger.Log($"Begin package search with url={SearchUrl} on manager {Name}");
Dictionary AlreadyProcessedPackages = [];
@@ -145,6 +154,7 @@ protected override IReadOnlyList GetAvailableUpdates_UnSafe()
if (!sourceMapping.ContainsKey(uri)) sourceMapping[uri] = new();
sourceMapping[uri].Add(package);
}
+ bool canPrerelease = InstallationOptions.LoadForManager(this).PreRelease;
foreach (var pair in sourceMapping)
{
@@ -161,7 +171,8 @@ protected override IReadOnlyList GetAvailableUpdates_UnSafe()
var SearchUrl = $"{pair.Key.Url.ToString().Trim('/')}/GetUpdates()" +
$"?packageIds=%27{HttpUtility.UrlEncode(packageIds.ToString().Trim('|'))}%27" +
$"&versions=%27{HttpUtility.UrlEncode(packageVers.ToString().Trim('|'))}%27" +
- $"&includePrerelease=0&includeAllVersions=0";
+ $"&includePrerelease={(canPrerelease ? "true" : "false")}" +
+ $"&includeAllVersions=0";
using HttpClient client = new(CoreTools.GenericHttpClientParameters);
client.DefaultRequestHeaders.UserAgent.ParseAdd(CoreData.UserAgentString);
diff --git a/src/UniGetUI.PackageEngine.Managers.Npm/Helpers/NpmPkgOperationHelper.cs b/src/UniGetUI.PackageEngine.Managers.Npm/Helpers/NpmPkgOperationHelper.cs
index 49f57608a4..ec718e7786 100644
--- a/src/UniGetUI.PackageEngine.Managers.Npm/Helpers/NpmPkgOperationHelper.cs
+++ b/src/UniGetUI.PackageEngine.Managers.Npm/Helpers/NpmPkgOperationHelper.cs
@@ -3,7 +3,7 @@
using UniGetUI.PackageEngine.Interfaces;
namespace UniGetUI.PackageEngine.Managers.NpmManager;
-internal sealed class NpmPkgOperationHelper : PackagePkgOperationHelper
+internal sealed class NpmPkgOperationHelper : BasePkgOperationHelper
{
public NpmPkgOperationHelper(Npm manager) : base(manager) { }
diff --git a/src/UniGetUI.PackageEngine.Managers.Pip/Helpers/PipPkgOperationHelper.cs b/src/UniGetUI.PackageEngine.Managers.Pip/Helpers/PipPkgOperationHelper.cs
index 8f9e8c8c2b..10be39572d 100644
--- a/src/UniGetUI.PackageEngine.Managers.Pip/Helpers/PipPkgOperationHelper.cs
+++ b/src/UniGetUI.PackageEngine.Managers.Pip/Helpers/PipPkgOperationHelper.cs
@@ -3,7 +3,7 @@
using UniGetUI.PackageEngine.Interfaces;
namespace UniGetUI.PackageEngine.Managers.PipManager;
-internal sealed class PipPkgOperationHelper : PackagePkgOperationHelper
+internal sealed class PipPkgOperationHelper : BasePkgOperationHelper
{
public PipPkgOperationHelper(Pip manager) : base(manager) { }
diff --git a/src/UniGetUI.PackageEngine.Managers.PowerShell/Helpers/PowerShellPkgOperationHelper.cs b/src/UniGetUI.PackageEngine.Managers.PowerShell/Helpers/PowerShellPkgOperationHelper.cs
index f23005f14e..d7bfa540e6 100644
--- a/src/UniGetUI.PackageEngine.Managers.PowerShell/Helpers/PowerShellPkgOperationHelper.cs
+++ b/src/UniGetUI.PackageEngine.Managers.PowerShell/Helpers/PowerShellPkgOperationHelper.cs
@@ -3,7 +3,7 @@
using UniGetUI.PackageEngine.Interfaces;
namespace UniGetUI.PackageEngine.Managers.PowerShellManager;
-internal sealed class PowerShellPkgOperationHelper : PackagePkgOperationHelper
+internal sealed class PowerShellPkgOperationHelper : BasePkgOperationHelper
{
public PowerShellPkgOperationHelper(PowerShell manager) : base(manager) { }
diff --git a/src/UniGetUI.PackageEngine.Managers.PowerShell7/Helpers/PowerShell7PkgOperationHelper.cs b/src/UniGetUI.PackageEngine.Managers.PowerShell7/Helpers/PowerShell7PkgOperationHelper.cs
index 6bdcbd6ef4..56bc0a32ea 100644
--- a/src/UniGetUI.PackageEngine.Managers.PowerShell7/Helpers/PowerShell7PkgOperationHelper.cs
+++ b/src/UniGetUI.PackageEngine.Managers.PowerShell7/Helpers/PowerShell7PkgOperationHelper.cs
@@ -3,7 +3,7 @@
using UniGetUI.PackageEngine.Interfaces;
namespace UniGetUI.PackageEngine.Managers.PowerShell7Manager;
-internal sealed class PowerShell7PkgOperationHelper : PackagePkgOperationHelper
+internal sealed class PowerShell7PkgOperationHelper : BasePkgOperationHelper
{
public PowerShell7PkgOperationHelper(PowerShell7 manager) : base(manager) { }
diff --git a/src/UniGetUI.PackageEngine.Managers.Scoop/Helpers/ScoopPkgOperationHelper.cs b/src/UniGetUI.PackageEngine.Managers.Scoop/Helpers/ScoopPkgOperationHelper.cs
index 34529da319..c3c6ae2033 100644
--- a/src/UniGetUI.PackageEngine.Managers.Scoop/Helpers/ScoopPkgOperationHelper.cs
+++ b/src/UniGetUI.PackageEngine.Managers.Scoop/Helpers/ScoopPkgOperationHelper.cs
@@ -4,7 +4,7 @@
using UniGetUI.PackageEngine.Interfaces;
namespace UniGetUI.PackageEngine.Managers.ScoopManager;
-internal sealed class ScoopPkgOperationHelper : PackagePkgOperationHelper
+internal sealed class ScoopPkgOperationHelper : BasePkgOperationHelper
{
public ScoopPkgOperationHelper(Scoop manager) : base(manager) { }
diff --git a/src/UniGetUI.PackageEngine.Managers.Vcpkg/Helpers/VcpkgPkgOperationHelper.cs b/src/UniGetUI.PackageEngine.Managers.Vcpkg/Helpers/VcpkgPkgOperationHelper.cs
index 876094dac7..a005acc842 100644
--- a/src/UniGetUI.PackageEngine.Managers.Vcpkg/Helpers/VcpkgPkgOperationHelper.cs
+++ b/src/UniGetUI.PackageEngine.Managers.Vcpkg/Helpers/VcpkgPkgOperationHelper.cs
@@ -3,7 +3,7 @@
using UniGetUI.PackageEngine.Interfaces;
namespace UniGetUI.PackageEngine.Managers.VcpkgManager;
-internal sealed class VcpkgPkgOperationHelper : PackagePkgOperationHelper
+internal sealed class VcpkgPkgOperationHelper : BasePkgOperationHelper
{
public VcpkgPkgOperationHelper(Vcpkg manager) : base(manager) { }
diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/Helpers/WinGetPkgOperationHelper.cs b/src/UniGetUI.PackageEngine.Managers.WinGet/Helpers/WinGetPkgOperationHelper.cs
index dde8e83c8e..9b9e98a936 100644
--- a/src/UniGetUI.PackageEngine.Managers.WinGet/Helpers/WinGetPkgOperationHelper.cs
+++ b/src/UniGetUI.PackageEngine.Managers.WinGet/Helpers/WinGetPkgOperationHelper.cs
@@ -9,7 +9,7 @@
using UniGetUI.PackageEngine.Interfaces;
namespace UniGetUI.PackageEngine.Managers.WingetManager;
-internal sealed class WinGetPkgOperationHelper : PackagePkgOperationHelper
+internal sealed class WinGetPkgOperationHelper : BasePkgOperationHelper
{
public static string GetIdNamePiece(IPackage package)
{
diff --git a/src/UniGetUI.PackageEngine.PackageLoader/UpgradablePackagesLoader.cs b/src/UniGetUI.PackageEngine.PackageLoader/UpgradablePackagesLoader.cs
index 2fa5040f70..e2f6c53634 100644
--- a/src/UniGetUI.PackageEngine.PackageLoader/UpgradablePackagesLoader.cs
+++ b/src/UniGetUI.PackageEngine.PackageLoader/UpgradablePackagesLoader.cs
@@ -37,7 +37,7 @@ protected override async Task IsPackageValid(IPackage package)
IgnoredPackages[package.Id] = package;
return false;
}
- if ((await InstallationOptions.FromPackageAsync(package)).SkipMinorUpdates && package.IsUpdateMinor())
+ if ((await InstallationOptions.LoadApplicableAsync(package)).SkipMinorUpdates && package.IsUpdateMinor())
{
Logger.Info($"Ignoring package {package.Id} because it is a minor update ({package.VersionString} -> {package.NewVersionString}) and SkipMinorUpdates is set to true.");
return false;
diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Helpers/PackagePkgOperationHelper.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Helpers/BasePkgOperationHelper.cs
similarity index 69%
rename from src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Helpers/PackagePkgOperationHelper.cs
rename to src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Helpers/BasePkgOperationHelper.cs
index 168949683a..2b44f013d3 100644
--- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Helpers/PackagePkgOperationHelper.cs
+++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Helpers/BasePkgOperationHelper.cs
@@ -5,11 +5,11 @@
namespace UniGetUI.PackageEngine.Classes.Manager.BaseProviders;
-public abstract class PackagePkgOperationHelper : IPackageOperationHelper
+public abstract class BasePkgOperationHelper : IPackageOperationHelper
{
protected IPackageManager Manager;
- public PackagePkgOperationHelper(IPackageManager manager)
+ public BasePkgOperationHelper(IPackageManager manager)
{
Manager = manager;
}
@@ -30,10 +30,21 @@ public IReadOnlyList GetParameters(
IInstallationOptions options,
OperationType operation)
{
- var parameters = _getOperationParameters(package, options, operation);
- Logger.Info(
- $"Loaded operation parameters for package id={package.Id} on manager {Manager.Name} and operation {operation}: " +
- string.Join(' ', parameters));
+ var parameters = _getOperationParameters(package, options, operation).ToArray();
+
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ parameters[i] = parameters[i]
+ .Replace("&", "")
+ .Replace("|", "")
+ .Replace(";", "")
+ .Replace("<", "")
+ .Replace(">", "")
+ .Replace("\n", "");
+ }
+
+ Logger.Info($"Loaded operation parameters for package id={package.Id} on manager {Manager.Name} and operation {operation}: " +
+ string.Join(' ', parameters));
return parameters;
}
diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallationOptions.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallationOptions.cs
index 03881b8822..eefc240669 100644
--- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallationOptions.cs
+++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallationOptions.cs
@@ -17,7 +17,7 @@ namespace UniGetUI.PackageEngine.PackageClasses
///
public class InstallationOptions : IInstallationOptions
{
- private static readonly ConcurrentDictionary OptionsCache = [];
+ // private static readonly ConcurrentDictionary OptionsCache = [];
public bool SkipHashCheck { get; set; }
public bool InteractiveInstallation { get; set; }
@@ -30,90 +30,105 @@ public class InstallationOptions : IInstallationOptions
public bool RemoveDataOnUninstall { get; set; }
public bool PreRelease { get; set; }
public string CustomInstallLocation { get; set; } = "";
-
- public IPackage Package { get; }
+ public bool OverridesNextLevelOpts { get; set; }
private readonly string __save_filename;
- private InstallationOptions(IPackage package)
+ private InstallationOptions(string filename)
{
- Package = package;
- __save_filename = package.Manager.Name.Replace(" ", "").Replace(".", "") + "." + package.Id;
+ __save_filename = Path.Join(CoreData.UniGetUIInstallationOptionsDirectory, filename);
}
- ///
- /// Returns the InstallationOptions object associated with the given package.
- ///
- /// The package's InstallationOptions instance
- public static InstallationOptions FromPackage(IPackage package, bool? elevated = null, bool?
- interactive = null, bool? no_integrity = null, bool? remove_data = null)
+ private static class StoragePath
{
- InstallationOptions instance;
- if (OptionsCache.TryGetValue(package.GetHash(), out InstallationOptions? cached_instance) && cached_instance is not null)
- {
- instance = cached_instance;
- }
- else
- {
- instance = new(package);
- instance.LoadFromDisk();
- OptionsCache.TryAdd(package.GetHash(), instance);
- }
+ public static string Get(IPackageManager manager)
+ => "GlobalValues." + manager.Name.Replace(" ", "").Replace(".", "");
- if (elevated is not null)
- {
- instance.RunAsAdministrator = (bool)elevated;
- }
+ public static string Get(IPackage package)
+ => package.Manager.Name.Replace(" ", "").Replace(".", "") + "." + package.Id;
+ }
- if (interactive is not null)
- {
- instance.InteractiveInstallation = (bool)interactive;
- }
+ public static InstallationOptions CreateEmpty(IPackage package)
+ {
+ var pkg_path = StoragePath.Get(package);
+ return new(pkg_path);
+ }
- if (no_integrity is not null)
- {
- instance.SkipHashCheck = (bool)no_integrity;
- }
+ public static InstallationOptions CreateEmpty(IPackageManager manager)
+ {
+ var mgr_path = StoragePath.Get(manager);
+ return new(mgr_path);
+ }
- if (remove_data is not null)
- {
- instance.RemoveDataOnUninstall = (bool)remove_data;
- }
+ public static InstallationOptions FromSerialized(SerializableInstallationOptions options, IPackage package)
+ {
+ var instance = CreateEmpty(package);
+ instance.GetValuesFromSerializable(options);
+ return instance;
+ }
+ public static InstallationOptions FromSerialized(SerializableInstallationOptions options, IPackageManager manager)
+ {
+ var instance = CreateEmpty(manager);
+ instance.GetValuesFromSerializable(options);
return instance;
}
- ///
- /// Returns the InstallationOptions object associated with the given package.
- ///
- /// The package from which to load the InstallationOptions
- /// The package's InstallationOptions instance
- public static async Task FromPackageAsync(IPackage package, bool? elevated = null,
- bool? interactive = null, bool? no_integrity = null, bool? remove_data = null)
+ public static InstallationOptions LoadForPackage(IPackage package)
{
- return await Task.Run(() => FromPackage(package, elevated, interactive, no_integrity, remove_data));
+ InstallationOptions instance = CreateEmpty(package);
+ instance.LoadFromDisk();
+ return instance;
}
- ///
- /// Returns a new InstallationOptions object from a given SerializableInstallationOptions and a package.
- ///
- public static InstallationOptions FromSerialized(SerializableInstallationOptions options, IPackage package)
+ public static async Task LoadForPackageAsync(IPackage package)
{
- InstallationOptions instance = new(package);
- instance.FromSerializable(options);
+ InstallationOptions instance = CreateEmpty(package);
+ await Task.Run(instance.LoadFromDisk);
return instance;
}
- public static InstallationOptions CreateEmpty(IPackage package)
+ public static InstallationOptions LoadForManager(IPackageManager manager)
+ {
+ InstallationOptions instance = CreateEmpty(manager);
+ instance.LoadFromDisk();
+ return instance;
+ }
+
+ public static InstallationOptions LoadApplicable(
+ IPackage package,
+ bool? elevated = null,
+ bool? interactive = null,
+ bool? no_integrity = null,
+ bool? remove_data = null)
{
- InstallationOptions instance = new(package);
+ InstallationOptions instance = LoadForPackage(package);
+ if (!instance.OverridesNextLevelOpts)
+ {
+ instance = LoadForManager(package.Manager);
+ Logger.Debug($"Package {package.Id} does not override options, will use package manager's default...");
+ }
+
+ if (elevated is not null) instance.RunAsAdministrator = (bool)elevated;
+ if (interactive is not null) instance.InteractiveInstallation = (bool)interactive;
+ if (no_integrity is not null) instance.SkipHashCheck = (bool)no_integrity;
+ if (remove_data is not null) instance.RemoveDataOnUninstall = (bool)remove_data;
+
return instance;
}
+ public static Task LoadApplicableAsync(
+ IPackage package,
+ bool? elevated = null,
+ bool? interactive = null,
+ bool? no_integrity = null,
+ bool? remove_data = null)
+ => Task.Run(() => LoadApplicable(package, elevated, interactive, no_integrity, remove_data));
+
///
/// Loads and applies the options from the given SerializableInstallationOptions object to the current object.
///
- public void FromSerializable(SerializableInstallationOptions options)
+ public void GetValuesFromSerializable(SerializableInstallationOptions options)
{
SkipHashCheck = options.SkipHashCheck;
InteractiveInstallation = options.InteractiveInstallation;
@@ -122,24 +137,21 @@ public void FromSerializable(SerializableInstallationOptions options)
Version = options.Version;
SkipMinorUpdates = options.SkipMinorUpdates;
PreRelease = options.PreRelease;
+ OverridesNextLevelOpts = options.OverridesNextLevelOpts;
- if (options.Architecture != "" && CommonTranslations.InvertedArchNames.TryGetValue(options.Architecture, out var name))
+ Architecture = null;
+ if (options.Architecture.Any() &&
+ CommonTranslations.InvertedArchNames.TryGetValue(options.Architecture, out var name))
{
Architecture = name;
}
- else
- {
- Architecture = null;
- }
- if (options.InstallationScope != "" && CommonTranslations.InvertedScopeNames_NonLang.TryGetValue(options.InstallationScope, out var value))
+ InstallationScope = null;
+ if (options.InstallationScope.Any() &&
+ CommonTranslations.InvertedScopeNames_NonLang.TryGetValue(options.InstallationScope, out var value))
{
InstallationScope = value;
}
- else
- {
- InstallationScope = null;
- }
CustomParameters = options.CustomParameters;
}
@@ -147,7 +159,7 @@ public void FromSerializable(SerializableInstallationOptions options)
///
/// Returns a SerializableInstallationOptions object containing the options of the current instance.
///
- public SerializableInstallationOptions AsSerializable()
+ public SerializableInstallationOptions ToSerializable()
{
SerializableInstallationOptions options = new()
{
@@ -157,36 +169,22 @@ public SerializableInstallationOptions AsSerializable()
CustomInstallLocation = CustomInstallLocation,
PreRelease = PreRelease,
Version = Version,
- SkipMinorUpdates = SkipMinorUpdates
+ SkipMinorUpdates = SkipMinorUpdates,
+ OverridesNextLevelOpts = OverridesNextLevelOpts
};
+
if (Architecture is not null)
- {
options.Architecture = CommonTranslations.ArchNames[Architecture.Value];
- }
if (InstallationScope is not null)
- {
options.InstallationScope = CommonTranslations.ScopeNames_NonLang[InstallationScope.Value];
- }
options.CustomParameters = CustomParameters;
return options;
}
- private FileInfo GetPackageOptionsFile()
- {
- string optionsFileName = Package.Manager.Name + "." + Package.Id.Split(":")[0] + ".json";
- return new FileInfo(Path.Join(CoreData.UniGetUIInstallationOptionsDirectory, optionsFileName));
- }
-
- ///
- /// Saves the current options to disk, asynchronously.
- ///
- public async Task SaveToDiskAsync()
- {
- await Task.Run(SaveToDisk);
- }
+ private static ConcurrentDictionary _optionsCache = new();
///
/// Saves the current options to disk.
///
@@ -194,52 +192,66 @@ public void SaveToDisk()
{
try
{
- FileInfo optionsFile = GetPackageOptionsFile();
- if (optionsFile.Directory?.Exists == false)
+ var dir = Path.GetDirectoryName(__save_filename);
+ ArgumentException.ThrowIfNullOrEmpty(dir);
+ if (!Directory.Exists(dir))
{
- optionsFile.Directory.Create();
+ Directory.CreateDirectory(dir);
}
+ var serialized = ToSerializable();
+ _optionsCache[__save_filename] = serialized;
+
string fileContents = JsonSerializer.Serialize(
- AsSerializable(),
+ serialized,
SerializationHelpers.DefaultOptions
);
- File.WriteAllText(optionsFile.FullName, fileContents);
+ File.WriteAllText(__save_filename, fileContents);
}
catch (Exception ex)
{
- Logger.Error($"Could not save {Package.Id} options to disk");
+ Logger.Error($"Could not save {__save_filename} options to disk");
Logger.Error(ex);
}
}
+ ///
+ /// Saves the current options to disk.
+ ///
+ public Task SaveToDiskAsync() => Task.Run(SaveToDisk);
+
///
/// Loads the options from disk.
///
- public void LoadFromDisk()
+ private void LoadFromDisk()
{
- FileInfo optionsFile = GetPackageOptionsFile();
try
{
- if (!optionsFile.Exists)
- return;
-
- var rawData = File.ReadAllText(optionsFile.FullName);
- JsonNode? jsonData = JsonNode.Parse(rawData);
- if (jsonData is null)
- return;
+ SerializableInstallationOptions serializedOptions;
+ if (_optionsCache.TryGetValue(__save_filename, out var cached))
+ {
+ serializedOptions = cached;
+ }
+ else
+ {
+ if (!File.Exists(__save_filename)) return;
- var serializedOptions = new SerializableInstallationOptions(jsonData);
- FromSerializable(serializedOptions);
+ var rawData = File.ReadAllText(__save_filename);
+ JsonNode? jsonData = JsonNode.Parse(rawData);
+ ArgumentNullException.ThrowIfNull(jsonData);
+ serializedOptions = new SerializableInstallationOptions(jsonData);
+ _optionsCache[__save_filename] = serializedOptions;
+ }
+ GetValuesFromSerializable(serializedOptions);
}
catch (JsonException)
{
- Logger.Warn("An error occurred while parsing package " + optionsFile + ". The file will be overwritten");
- File.WriteAllText(optionsFile.FullName, "{}");
+ Logger.Warn("An error occurred while parsing package " + __save_filename + ". The file will be overwritten");
+ File.WriteAllText(__save_filename, "{}");
}
catch (Exception e)
{
- Logger.Error("Loading installation options for file " + optionsFile + " have failed: ");
+ Logger.Error("Loading installation options for file " + __save_filename + " have failed: ");
Logger.Error(e);
}
}
@@ -249,7 +261,7 @@ public void LoadFromDisk()
///
public override string ToString()
{
- string customparams = CustomParameters is not null ? string.Join(",", CustomParameters) : "[]";
+ string customparams = CustomParameters.Any() ? string.Join(",", CustomParameters) : "[]";
return $" RegisterAndGetPackageAsync()
{
- var options = await InstallationOptions.FromPackageAsync(this);
- options.FromSerializable(installation_options);
- await options.SaveToDiskAsync();
+ await Task.Run(() =>
+ {
+ InstallationOptions.FromSerialized(installation_options, this).SaveToDisk();
+ });
if (updates_options.UpdatesIgnored)
{
diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Package.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Package.cs
index 5f099f5709..56e54d2a7e 100644
--- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Package.cs
+++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Package.cs
@@ -310,7 +310,7 @@ public virtual SerializablePackage AsSerializable()
Version = VersionString,
Source = Source.Name,
ManagerName = Manager.Name,
- InstallationOptions = InstallationOptions.FromPackage(this).AsSerializable(),
+ InstallationOptions = InstallationOptions.LoadForPackage(this).ToSerializable(),
Updates = new SerializableUpdatesOptions
{
IgnoredVersion = GetIgnoredUpdatesVersionAsync().GetAwaiter().GetResult(),
diff --git a/src/UniGetUI.PackageEngine.Serializable.Tests/TestSerializableInstallationOptions.cs b/src/UniGetUI.PackageEngine.Serializable.Tests/TestSerializableInstallationOptions.cs
index dd02ab6692..d20cd968a4 100644
--- a/src/UniGetUI.PackageEngine.Serializable.Tests/TestSerializableInstallationOptions.cs
+++ b/src/UniGetUI.PackageEngine.Serializable.Tests/TestSerializableInstallationOptions.cs
@@ -45,7 +45,7 @@ public void ToAndFromJsonNode(bool a, bool b, string c, string d, string e, stri
}
[Theory]
- [InlineData("{}", false, false, "", "", "", "", "", "", false, false, false, "")]
+ [InlineData("{}", false, false, "", "", "", "", "", "", false, false, false, "", false)]
[InlineData("""
{
"SkipHashCheck": true,
@@ -57,7 +57,7 @@ public void ToAndFromJsonNode(bool a, bool b, string c, string d, string e, stri
"a"
]
}
- """, true, true, "", "a", "", "", "", "lol", false, false, false, "")]
+ """, true, true, "", "a", "", "", "", "lol", false, false, false, "", true)]
[InlineData("""
{
@@ -71,8 +71,8 @@ public void ToAndFromJsonNode(bool a, bool b, string c, string d, string e, stri
"UNKNOWN_VAL4": "hehe"
}
""", false, false, "", "", "", "",
- "", "", false, false, true, "heyheyhey")]
- public void FromJson(string JSON, bool hash, bool inter, string installLoc, string arg1, string arg2, string arg3, string scope, string arch, bool pre, bool admin, bool skipMin, string ver)
+ "", "", false, false, true, "heyheyhey", true)]
+ public void FromJson(string JSON, bool hash, bool inter, string installLoc, string arg1, string arg2, string arg3, string scope, string arch, bool pre, bool admin, bool skipMin, string ver, bool mod)
{
Assert.NotEmpty(JSON);
var jsonContent = JsonNode.Parse(JSON);
@@ -81,6 +81,8 @@ public void FromJson(string JSON, bool hash, bool inter, string installLoc, stri
var list = new List() { arg1, arg2, arg3 }.Where(x => x.Any());
+ Assert.Equal(mod, o2.OverridesNextLevelOpts);
+ Assert.Equal(mod, o2.DiffersFromDefault());
Assert.Equal(hash, o2.SkipHashCheck);
Assert.Equal(arch, o2.Architecture);
Assert.Equal(installLoc, o2.CustomInstallLocation);
diff --git a/src/UniGetUI.PackageEngine.Serializable/SerializableInstallationOptions.cs b/src/UniGetUI.PackageEngine.Serializable/SerializableInstallationOptions.cs
index 2b02e2363a..7a78272847 100644
--- a/src/UniGetUI.PackageEngine.Serializable/SerializableInstallationOptions.cs
+++ b/src/UniGetUI.PackageEngine.Serializable/SerializableInstallationOptions.cs
@@ -15,6 +15,7 @@ public class SerializableInstallationOptions: SerializableComponent() ?? "";
this.Version = data[nameof(Version)]?.GetVal() ?? "";
this.SkipMinorUpdates = data[nameof(SkipMinorUpdates)]?.GetVal() ?? false;
+
+ // if OverridesNextLevelOpts is not found on the JSON, set it to true or false depending
+ // on whether the current settings instances are different from the default values.
+ // This entry shall be checked the last one, to ensure all other properties are set
+ this.OverridesNextLevelOpts =
+ data[nameof(OverridesNextLevelOpts)]?.GetValue() ?? DiffersFromDefault();
}
public bool DiffersFromDefault()
@@ -63,6 +71,8 @@ SkipMinorUpdates is not false ||
CustomParameters.Where(x => x != "").Any() ||
CustomInstallLocation.Any() ||
Version.Any();
+ // OverridesNextLevelOpts does not need to be checked here, since
+ // this method is invoked before this property has been set
}
public SerializableInstallationOptions() : base()
diff --git a/src/UniGetUI/AppOperationHelper.cs b/src/UniGetUI/AppOperationHelper.cs
index 9b08b250fc..771072ec27 100644
--- a/src/UniGetUI/AppOperationHelper.cs
+++ b/src/UniGetUI/AppOperationHelper.cs
@@ -124,7 +124,7 @@ public static void Remove(AbstractOperation op)
{
if (package is null) return null;
- var options = await InstallationOptions.FromPackageAsync(package, elevated, interactive, no_integrity);
+ var options = await InstallationOptions.LoadApplicableAsync(package, elevated, interactive, no_integrity);
var op = new InstallPackageOperation(package, options, ignoreParallel, req);
op.OperationSucceeded += (_, _) => TelemetryHandler.InstallPackage(package, TEL_OP_RESULT.SUCCESS, referral);
op.OperationFailed += (_, _) => TelemetryHandler.InstallPackage(package, TEL_OP_RESULT.FAILED, referral);
@@ -148,7 +148,7 @@ public static void Install(IReadOnlyList packages, TEL_InstallReferral
{
if (package is null) return null;
- var options = await InstallationOptions.FromPackageAsync(package, elevated, interactive, no_integrity);
+ var options = await InstallationOptions.LoadApplicableAsync(package, elevated, interactive, no_integrity);
var op = new UpdatePackageOperation(package, options, ignoreParallel, req);
op.OperationSucceeded += (_, _) => TelemetryHandler.UpdatePackage(package, TEL_OP_RESULT.SUCCESS);
op.OperationFailed += (_, _) => TelemetryHandler.UpdatePackage(package, TEL_OP_RESULT.FAILED);
@@ -221,7 +221,7 @@ public static async void ConfirmAndUninstall(IPackage? package, bool? elevated =
{
if (package is null) return null;
- var options = await InstallationOptions.FromPackageAsync(package, elevated, interactive, remove_data: remove_data);
+ var options = await InstallationOptions.LoadApplicableAsync(package, elevated, interactive, remove_data: remove_data);
var op = new UninstallPackageOperation(package, options, ignoreParallel, req);
op.OperationSucceeded += (_, _) => TelemetryHandler.UninstallPackage(package, TEL_OP_RESULT.SUCCESS);
op.OperationFailed += (_, _) => TelemetryHandler.UninstallPackage(package, TEL_OP_RESULT.FAILED);
diff --git a/src/UniGetUI/Pages/DialogPages/DialogHelper_Packages.cs b/src/UniGetUI/Pages/DialogPages/DialogHelper_Packages.cs
index 2d22ef5a05..a7cad147c0 100644
--- a/src/UniGetUI/Pages/DialogPages/DialogHelper_Packages.cs
+++ b/src/UniGetUI/Pages/DialogPages/DialogHelper_Packages.cs
@@ -20,13 +20,13 @@ public static partial class DialogHelper
///
public static async Task ShowInstallatOptions_Continue(IPackage package, OperationType operation)
{
- var options = (await InstallationOptions.FromPackageAsync(package)).AsSerializable();
+ var options = (await InstallationOptions.LoadForPackageAsync(package)).ToSerializable();
var (dialogOptions, dialogResult) = await ShowInstallOptions(package, operation, options);
if (dialogResult != ContentDialogResult.None)
{
- InstallationOptions newOptions = await InstallationOptions.FromPackageAsync(package);
- newOptions.FromSerializable(dialogOptions);
+ InstallationOptions newOptions = await InstallationOptions.LoadForPackageAsync(package);
+ newOptions.GetValuesFromSerializable(dialogOptions);
await newOptions.SaveToDiskAsync();
}
@@ -68,7 +68,7 @@ public static async Task ShowInstallOptions_ImportedPackage
};
OptionsDialog.PrimaryButtonText = CoreTools.Translate("Save and close");
OptionsDialog.DefaultButton = ContentDialogButton.Secondary;
- OptionsDialog.Title = CoreTools.Translate("{0} installation options", package.Name);
+ // OptionsDialog.Title = CoreTools.Translate("{0} installation options", package.Name);
OptionsDialog.Content = OptionsPage;
OptionsPage.Close += (_, _) => { OptionsDialog.Hide(); };
diff --git a/src/UniGetUI/Pages/DialogPages/InstallOptions.xaml b/src/UniGetUI/Pages/DialogPages/InstallOptions.xaml
deleted file mode 100644
index f899415471..0000000000
--- a/src/UniGetUI/Pages/DialogPages/InstallOptions.xaml
+++ /dev/null
@@ -1,231 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/UniGetUI/Pages/DialogPages/InstallOptions_Manager.xaml b/src/UniGetUI/Pages/DialogPages/InstallOptions_Manager.xaml
new file mode 100644
index 0000000000..2fad9d1f16
--- /dev/null
+++ b/src/UniGetUI/Pages/DialogPages/InstallOptions_Manager.xaml
@@ -0,0 +1,176 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UniGetUI/Pages/DialogPages/InstallOptions_Manager.xaml.cs b/src/UniGetUI/Pages/DialogPages/InstallOptions_Manager.xaml.cs
new file mode 100644
index 0000000000..8f6ac1e929
--- /dev/null
+++ b/src/UniGetUI/Pages/DialogPages/InstallOptions_Manager.xaml.cs
@@ -0,0 +1,279 @@
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using Microsoft.Extensions.Options;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using UniGetUI.Core.Language;
+using UniGetUI.Core.Tools;
+using UniGetUI.PackageEngine.Enums;
+using UniGetUI.PackageEngine.Interfaces;
+using UniGetUI.PackageEngine.PackageClasses;
+using UniGetUI.PackageEngine.Serializable;
+using Windows.ApplicationModel;
+using Windows.Gaming.XboxLive.Storage;
+
+// To learn more about WinUI, the WinUI project structure,
+// and more about our project templates, see: http://aka.ms/winui-project-info.
+
+namespace UniGetUI.Pages.DialogPages;
+
+public sealed partial class InstallOptions_Manager : UserControl
+{
+ private readonly IPackageManager Manager;
+ private static string DefaultLocationLabel = null!;
+ public InstallOptions_Manager(IPackageManager manager)
+ {
+ Manager = manager;
+ InitializeComponent();
+ AdminCheckBox.Content = CoreTools.Translate("Run as admin");
+ InteractiveCheckBox.Content = CoreTools.Translate("Interactive installation");
+ HashCheckBox.Content = CoreTools.Translate("Skip hash check");
+ PreReleaseCheckBox.Content = CoreTools.Translate("Allow pre-release versions");
+ ArchLabel.Text = CoreTools.Translate("Architecture to install:");
+ ScopeLabel.Text = CoreTools.Translate("Installation scope:");
+ LocationLabel.Text = CoreTools.Translate("Install location:");
+ SelectDir.Content = CoreTools.Translate("Select");
+ ResetDir.Content = CoreTools.Translate("Reset");
+ CustomCommandsLabel.Text = CoreTools.Translate("Custom arguments:");
+ DefaultLocationLabel ??= CoreTools.Translate("Package's default");
+ ResetButton.Content = CoreTools.Translate("Reset");
+ ApplyButton.Content = CoreTools.Translate("Apply");
+ HeaderLabel.Text = CoreTools.Translate("The following options will be applied by default each time a {0} package is installed, upgraded or uninstalled.", Manager.DisplayName);
+
+ DisableAllInput();
+ _ = LoadOptions();
+ }
+
+ private async Task LoadOptions()
+ {
+ LoadingIndicator.Visibility = Visibility.Visible;
+ var options = await Task.Run(() => InstallationOptions.LoadForManager(Manager).ToSerializable());
+
+ // This delay allows the spinner to show,
+ // and give the user the sensation that things have worked
+ await Task.Delay(500);
+
+ // Administrator checkbox
+ AdminCheckBox.IsEnabled = true;
+ AdminCheckBox.IsChecked = options.RunAsAdministrator;
+
+ // interactive checkbox
+ if (Manager.Capabilities.CanRunInteractively)
+ {
+ InteractiveCheckBox.IsEnabled = true;
+ InteractiveCheckBox.IsChecked = options.InteractiveInstallation;
+ }
+
+ // skip hash checkbox
+ if (Manager.Capabilities.CanSkipIntegrityChecks)
+ {
+ HashCheckBox.IsEnabled = true;
+ HashCheckBox.IsChecked = options.SkipHashCheck;
+ }
+
+ // prerelease support
+ if (Manager.Capabilities.SupportsPreRelease)
+ {
+ PreReleaseCheckBox.IsEnabled = true;
+ PreReleaseCheckBox.IsChecked = options.PreRelease;
+ }
+
+ // Architecture combobox
+ ArchitectureCombo.Items.Clear();
+ ArchitectureCombo.Items.Add(CoreTools.Translate("Default"));
+ ArchitectureCombo.SelectedIndex = 0;
+ if (Manager.Capabilities.SupportsCustomArchitectures)
+ {
+ ArchitectureCombo.IsEnabled = true;
+ foreach (Architecture arch in Manager.Capabilities.SupportedCustomArchitectures)
+ {
+ ArchitectureCombo.Items.Add(CommonTranslations.ArchNames[arch]);
+ if (options.Architecture == CommonTranslations.ArchNames[arch])
+ {
+ ArchitectureCombo.SelectedValue = CommonTranslations.ArchNames[arch];
+ }
+ }
+ }
+
+ // Scope combobox
+ ScopeCombo.Items.Clear();
+ ScopeCombo.Items.Add(CoreTools.Translate("Default"));
+ ScopeCombo.SelectedIndex = 0;
+ if (Manager.Capabilities.SupportsCustomScopes)
+ {
+ ScopeCombo.IsEnabled = true;
+ ScopeCombo.Items.Add(CoreTools.Translate(CommonTranslations.ScopeNames[PackageScope.Local]));
+ if (options.InstallationScope == CommonTranslations.ScopeNames_NonLang[PackageScope.Local])
+ {
+ ScopeCombo.SelectedValue = CommonTranslations.ScopeNames[PackageScope.Local];
+ }
+
+ ScopeCombo.Items.Add(CoreTools.Translate(CommonTranslations.ScopeNames[PackageScope.Global]));
+ if (options.InstallationScope == CommonTranslations.ScopeNames_NonLang[PackageScope.Global])
+ {
+ ScopeCombo.SelectedValue = CommonTranslations.ScopeNames[PackageScope.Global];
+ }
+ }
+
+ // Install location
+ if(Manager.Capabilities.SupportsCustomLocations)
+ {
+ SelectDir.IsEnabled = true;
+ if (options.CustomInstallLocation.Any())
+ {
+ CustomInstallLocation.Text = options.CustomInstallLocation;
+ ResetDir.IsEnabled = true;
+ }
+ else
+ {
+ CustomInstallLocation.Text = DefaultLocationLabel;
+ ResetDir.IsEnabled = false;
+ }
+ }
+ else
+ {
+ CustomInstallLocation.Text = CoreTools.Translate("Install location can't be changed for {0} packages", Manager.DisplayName);
+ }
+
+ CustomParameters.IsEnabled = true;
+ CustomParameters.Text = string.Join(' ', options.CustomParameters);
+
+ ResetButton.IsEnabled = true;
+ ApplyButton.IsEnabled = true;
+ ApplyButton.Style = (Style)Application.Current.Resources["DefaultButtonStyle"];
+
+ LoadingIndicator.Visibility = Visibility.Collapsed;
+ }
+
+ private async Task SaveOptions()
+ {
+ LoadingIndicator.Visibility = Visibility.Visible;
+ DisableAllInput();
+
+ SerializableInstallationOptions options = new();
+ // Checkboxes
+ options.RunAsAdministrator = AdminCheckBox.IsChecked ?? false;
+ options.SkipHashCheck = HashCheckBox.IsChecked ?? false;
+ options.InteractiveInstallation = InteractiveCheckBox.IsChecked ?? false;
+ options.PreRelease = PreReleaseCheckBox.IsChecked ?? false;
+
+ // Administrator
+ options.Architecture = "";
+ string candidateValue = ArchitectureCombo.SelectedValue.ToString() ?? "";
+ if (CommonTranslations.InvertedArchNames.ContainsKey(candidateValue))
+ {
+ options.Architecture = candidateValue;
+ }
+
+ // Scope
+ options.InstallationScope = "";
+ candidateValue = ScopeCombo.SelectedValue.ToString() ?? "";
+ if (CommonTranslations.InvertedScopeNames.TryGetValue(candidateValue, out PackageScope result))
+ {
+ options.InstallationScope = CommonTranslations.ScopeNames_NonLang[result];
+ }
+
+ // Location
+ options.CustomInstallLocation = "";
+ if(CustomInstallLocation.Text != DefaultLocationLabel && Manager.Capabilities.SupportsCustomLocations)
+ {
+ options.CustomInstallLocation = CustomInstallLocation.Text;
+ }
+
+ // Command-line parameters
+ options.CustomParameters = CustomParameters.Text.Split(' ').Where(x => x.Any()).ToList();
+
+ var temp = InstallationOptions.FromSerialized(options, Manager);
+ await temp.SaveToDiskAsync();
+ await LoadOptions();
+ }
+
+ private async Task ResetOptions()
+ {
+ LoadingIndicator.Visibility = Visibility.Visible;
+ DisableAllInput();
+
+ var opts = InstallationOptions.CreateEmpty(Manager);
+ await opts.SaveToDiskAsync();
+ await LoadOptions();
+ }
+
+ private void DisableAllInput()
+ {
+ PreReleaseCheckBox.IsEnabled = false;
+ AdminCheckBox.IsEnabled = false;
+ InteractiveCheckBox.IsEnabled = false;
+ HashCheckBox.IsEnabled = false;
+ ArchitectureCombo.IsEnabled = false;
+ ScopeCombo.IsEnabled = false;
+ SelectDir.IsEnabled = false;
+ ResetDir.IsEnabled = false;
+ CustomParameters.IsEnabled = false;
+ ResetButton.IsEnabled = false;
+ ApplyButton.IsEnabled = false;
+ }
+
+ private void CustomParameters_TextChanged(object sender, TextChangedEventArgs e)
+ {
+ ApplyButton.Style = (Style)Application.Current.Resources["AccentButtonStyle"];
+ }
+
+ private void ResetDir_Click(object sender, RoutedEventArgs e)
+ {
+ CustomInstallLocation.Text = DefaultLocationLabel;
+ ResetDir.IsEnabled = false;
+ ApplyButton.Style = (Style)Application.Current.Resources["AccentButtonStyle"];
+ }
+
+ private void SelectDir_Click(object sender, RoutedEventArgs e)
+ {
+ ExternalLibraries.Pickers.FolderPicker openPicker = new(MainApp.Instance.MainWindow.GetWindowHandle());
+ string folder = openPicker.Show();
+ if (folder != string.Empty)
+ {
+ CustomInstallLocation.Text = folder;
+ ResetDir.IsEnabled = true;
+ ApplyButton.Style = (Style)Application.Current.Resources["AccentButtonStyle"];
+ }
+ }
+
+ private void ScopeCombo_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ ApplyButton.Style = (Style)Application.Current.Resources["AccentButtonStyle"];
+ }
+
+ private void HashCheckbox_Click(object sender, RoutedEventArgs e)
+ {
+ ApplyButton.Style = (Style)Application.Current.Resources["AccentButtonStyle"];
+ }
+
+ private void InteractiveCheckBox_Click(object sender, RoutedEventArgs e)
+ {
+ ApplyButton.Style = (Style)Application.Current.Resources["AccentButtonStyle"];
+ }
+
+ private void AdminCheckBox_Click(object sender, RoutedEventArgs e)
+ {
+ ApplyButton.Style = (Style)Application.Current.Resources["AccentButtonStyle"];
+ }
+
+ private void ArchitectureComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ ApplyButton.Style = (Style)Application.Current.Resources["AccentButtonStyle"];
+ }
+
+ private void PreReleaseCheckBox_Click(object sender, RoutedEventArgs e)
+ {
+ ApplyButton.Style = (Style)Application.Current.Resources["AccentButtonStyle"];
+ }
+
+ private void ResetButton_Click(object sender, RoutedEventArgs e)
+ {
+ _ = ResetOptions();
+ }
+
+ private void ApplyButton_Click(object sender, RoutedEventArgs e)
+ {
+ _ = SaveOptions();
+ }
+}
diff --git a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml
new file mode 100644
index 0000000000..6ad6c0e867
--- /dev/null
+++ b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml
@@ -0,0 +1,312 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UniGetUI/Pages/DialogPages/InstallOptions.xaml.cs b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs
similarity index 72%
rename from src/UniGetUI/Pages/DialogPages/InstallOptions.xaml.cs
rename to src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs
index 676c951dd9..e5194ae49f 100644
--- a/src/UniGetUI/Pages/DialogPages/InstallOptions.xaml.cs
+++ b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs
@@ -1,6 +1,9 @@
+using System.Data;
using System.Runtime.InteropServices;
+using Microsoft.Extensions.Options;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Media.Imaging;
using UniGetUI.Core.Language;
using UniGetUI.Core.Tools;
using UniGetUI.PackageEngine.Enums;
@@ -33,18 +36,54 @@ public InstallOptionsPage(IPackage package, OperationType operation, Serializabl
Operation = operation;
Options = options;
+ ProfileComboBox.Items.Add(CoreTools.Translate("Install"));
+ ProfileComboBox.Items.Add(CoreTools.Translate("Update"));
+ ProfileComboBox.Items.Add(CoreTools.Translate("Uninstall"));
+ ProfileComboBox.SelectedIndex = operation switch { OperationType.Update => 1, OperationType.Uninstall => 2, _ => 0 };
+ ProfileComboBox.SelectionChanged += (_, _) =>
+ {
+ EnableDisableControls(ProfileComboBox.SelectedIndex switch
+ {
+ 1 => OperationType.Update,
+ 2 => OperationType.Uninstall,
+ _ => OperationType.Install,
+ });
+ };
+
+ FollowGlobalOptionsSwitch.IsOn = !options.OverridesNextLevelOpts;
+ FollowGlobalOptionsSwitch.Toggled += (_, _) =>
+ {
+ EnableDisableControls(ProfileComboBox.SelectedIndex switch
+ {
+ 1 => OperationType.Update,
+ 2 => OperationType.Uninstall,
+ _ => OperationType.Install,
+ });
+ };
+
+ var iconSource = new BitmapImage()
+ {
+ UriSource = package.GetIconUrl(),
+ DecodePixelHeight = 32,
+ DecodePixelWidth = 32,
+ DecodePixelType =
+ DecodePixelType.Logical
+ };
+
+ PackageIcon.Source = iconSource;
+ async Task LoadImage()
+ {
+ iconSource.UriSource = await Task.Run(package.GetIconUrl);
+ }
+ _ = LoadImage();
+ DialogTitle.Text = CoreTools.Translate("{0} installation options", package.Name);
+
packageInstallLocation = Package.Manager.DetailsHelper.GetInstallLocation(package) ?? CoreTools.Translate("Unset or unknown");
AdminCheckBox.IsChecked = Options.RunAsAdministrator;
- AdminCheckBox.IsEnabled = Package.Manager.Capabilities.CanRunAsAdmin;
-
InteractiveCheckBox.IsChecked = Options.InteractiveInstallation;
- InteractiveCheckBox.IsEnabled = Package.Manager.Capabilities.CanRunInteractively;
-
HashCheckbox.IsChecked = Options.SkipHashCheck;
- HashCheckbox.IsEnabled = operation != OperationType.Uninstall && Package.Manager.Capabilities.CanSkipIntegrityChecks;
- ArchitectureComboBox.IsEnabled = operation != OperationType.Uninstall && Package.Manager.Capabilities.SupportsCustomArchitectures;
ArchitectureComboBox.Items.Add(CoreTools.Translate("Default"));
ArchitectureComboBox.SelectedIndex = 0;
@@ -60,12 +99,6 @@ public InstallOptionsPage(IPackage package, OperationType operation, Serializabl
}
}
- VersionComboBox.IsEnabled =
- (operation == OperationType.Install
- || operation == OperationType.None)
- && (Package.Manager.Capabilities.SupportsCustomVersions
- || Package.Manager.Capabilities.SupportsPreRelease);
-
VersionComboBox.SelectionChanged += (_, _) =>
{
IgnoreUpdatesCheckbox.IsChecked =
@@ -99,7 +132,6 @@ public InstallOptionsPage(IPackage package, OperationType operation, Serializabl
VersionProgress.Visibility = Visibility.Collapsed;
}
- ScopeCombo.IsEnabled = Package.Manager.Capabilities.SupportsCustomScopes;
ScopeCombo.Items.Add(CoreTools.Translate("Default"));
ScopeCombo.SelectedIndex = 0;
if (package.Manager.Capabilities.SupportsCustomScopes)
@@ -117,8 +149,6 @@ public InstallOptionsPage(IPackage package, OperationType operation, Serializabl
}
}
- ResetDir.IsEnabled = Package.Manager.Capabilities.SupportsCustomLocations;
- SelectDir.IsEnabled = Package.Manager.Capabilities.SupportsCustomLocations;
if (Options.CustomInstallLocation == "") CustomInstallLocation.Text = packageInstallLocation;
else CustomInstallLocation.Text = Options.CustomInstallLocation;
@@ -129,10 +159,44 @@ public InstallOptionsPage(IPackage package, OperationType operation, Serializabl
}
_uiLoaded = true;
- GenerateCommand();
+ EnableDisableControls(operation);
LoadIgnoredUpdates();
}
+ private void EnableDisableControls(OperationType operation)
+ {
+ if(FollowGlobalOptionsSwitch.IsOn)
+ {
+ OptionsPanel0.Opacity = 0.6;
+ OptionsPanel1.Opacity = 0.6;
+ OptionsPanel2.Opacity = 0.6;
+ OptionsPanelBase.IsEnabled = false;
+ PlaceholderBanner.Visibility = Visibility.Visible;
+ }
+ else
+ {
+ OptionsPanel0.Opacity = 1;
+ OptionsPanel1.Opacity = 1;
+ OptionsPanel2.Opacity = 1;
+ OptionsPanelBase.IsEnabled = true;
+ PlaceholderBanner.Visibility = Visibility.Collapsed;
+
+ AdminCheckBox.IsEnabled = Package.Manager.Capabilities.CanRunAsAdmin;
+ InteractiveCheckBox.IsEnabled = Package.Manager.Capabilities.CanRunInteractively;
+ HashCheckbox.IsEnabled = operation != OperationType.Uninstall && Package.Manager.Capabilities.CanSkipIntegrityChecks;
+ ArchitectureComboBox.IsEnabled = operation != OperationType.Uninstall && Package.Manager.Capabilities.SupportsCustomArchitectures;
+ VersionComboBox.IsEnabled =
+ (operation == OperationType.Install
+ || operation == OperationType.None)
+ && (Package.Manager.Capabilities.SupportsCustomVersions
+ || Package.Manager.Capabilities.SupportsPreRelease);
+ ScopeCombo.IsEnabled = Package.Manager.Capabilities.SupportsCustomScopes;
+ ResetDir.IsEnabled = Package.Manager.Capabilities.SupportsCustomLocations;
+ SelectDir.IsEnabled = Package.Manager.Capabilities.SupportsCustomLocations;
+ }
+ GenerateCommand();
+ }
+
private async void LoadIgnoredUpdates()
{
IgnoreUpdatesCheckbox.IsChecked = await Package.GetIgnoredUpdatesVersionAsync() == "*";
@@ -166,6 +230,7 @@ public async Task GetUpdatedOptions(bool update
Options.RunAsAdministrator = AdminCheckBox?.IsChecked ?? false;
Options.InteractiveInstallation = InteractiveCheckBox?.IsChecked ?? false;
Options.SkipHashCheck = HashCheckbox?.IsChecked ?? false;
+ Options.OverridesNextLevelOpts = !FollowGlobalOptionsSwitch.IsOn;
if (CommonTranslations.InvertedArchNames.ContainsKey(ArchitectureComboBox.SelectedValue.ToString() ?? ""))
{
@@ -253,8 +318,12 @@ private async void GenerateCommand()
{
if (!_uiLoaded) return;
InstallationOptions io = InstallationOptions.FromSerialized(await GetUpdatedOptions(updateIgnoredUpdates: false), Package);
- var op = Operation;
- if (op is OperationType.None) op = OperationType.Install;
+ var op = ProfileComboBox.SelectedIndex switch
+ {
+ 1 => OperationType.Update,
+ 2 => OperationType.Uninstall,
+ _ => OperationType.Install,
+ };
var commandline = await Task.Run(() => Package.Manager.OperationHelper.GetParameters(Package, io, op));
CommandBox.Text = Package.Manager.Properties.ExecutableFriendlyName + " " + string.Join(" ", commandline);
}
@@ -263,5 +332,10 @@ private void LayoutGrid_SizeChanged(object sender, SizeChangedEventArgs e)
{
if(LayoutGrid.ActualSize.Y > 1 && LayoutGrid.ActualSize.Y < double.PositiveInfinity) MaxHeight = LayoutGrid.ActualSize.Y;
}
+
+ private void ProfileComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+
+ }
}
}
diff --git a/src/UniGetUI/Pages/DialogPages/PackageDetailsPage.xaml.cs b/src/UniGetUI/Pages/DialogPages/PackageDetailsPage.xaml.cs
index 1666c56639..3c25199e3c 100644
--- a/src/UniGetUI/Pages/DialogPages/PackageDetailsPage.xaml.cs
+++ b/src/UniGetUI/Pages/DialogPages/PackageDetailsPage.xaml.cs
@@ -102,7 +102,7 @@ public PackageDetailsPage(IPackage package, OperationType role, TEL_InstallRefer
UpgradablePackage = Package.GetUpgradablePackage();
InstalledPackage = UpgradablePackage?.GetInstalledPackage() ?? Package.GetInstalledPackage();
- var options = InstallationOptions.FromPackage(package).AsSerializable();
+ var options = InstallationOptions.LoadApplicable(package).ToSerializable();
InstallOptionsPage = new InstallOptionsPage(package, OperationRole, options);
InstallOptionsExpander.Content = InstallOptionsPage;
@@ -578,8 +578,11 @@ public async void DoAction(
{
Close?.Invoke(this, EventArgs.Empty);
- var newOptions = await InstallationOptions.FromPackageAsync(package);
- newOptions.FromSerializable(await InstallOptionsPage.GetUpdatedOptions());
+ var newOptions = await Task.Run(
+ () => InstallationOptions.FromSerialized(
+ InstallOptionsPage.GetUpdatedOptions().GetAwaiter().GetResult(),
+ package)
+ );
newOptions.SaveToDisk();
if (AsAdmin is not null) newOptions.RunAsAdministrator = (bool)AsAdmin;
diff --git a/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml b/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml
index 8377e80299..3265be3212 100644
--- a/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml
+++ b/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml
@@ -78,6 +78,16 @@
+
+
+
+
+
@@ -73,6 +74,7 @@
+
@@ -177,6 +179,9 @@
Always
+
+ MSBuild:Compile
+
MSBuild:Compile
diff --git a/src/UniGetUI/UniGetUI.csproj.user b/src/UniGetUI/UniGetUI.csproj.user
index db883f356c..0cd5b6bf1c 100644
--- a/src/UniGetUI/UniGetUI.csproj.user
+++ b/src/UniGetUI/UniGetUI.csproj.user
@@ -16,6 +16,9 @@
Designer
+
+ Designer
+
Designer