From 0cb3180be9a14ba882d3e2c8bf66b6e5d5bf08c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Mon, 1 Sep 2025 20:49:32 +0200 Subject: [PATCH 01/20] improvements to package manager initialization process, separe steps in different methods --- .../IPackageManager.cs | 1 - .../ManagerStatus.cs | 8 +- .../Manager/Helpers/BaseSourceHelper.cs | 18 ++- .../Manager/PackageManager.cs | 147 +++++++++++------- 4 files changed, 106 insertions(+), 68 deletions(-) diff --git a/src/UniGetUI.PAckageEngine.Interfaces/IPackageManager.cs b/src/UniGetUI.PAckageEngine.Interfaces/IPackageManager.cs index 50735edd75..cb898fc0dd 100644 --- a/src/UniGetUI.PAckageEngine.Interfaces/IPackageManager.cs +++ b/src/UniGetUI.PAckageEngine.Interfaces/IPackageManager.cs @@ -14,7 +14,6 @@ public interface IPackageManager public string Name { get; } public string DisplayName { get; } public IManagerSource DefaultSource { get; } - public bool ManagerReady { get; } public IManagerLogger TaskLogger { get; } public IMultiSourceHelper SourcesHelper { get; } public IPackageDetailsHelper DetailsHelper { get; } diff --git a/src/UniGetUI.PackageEngine.Enums/ManagerStatus.cs b/src/UniGetUI.PackageEngine.Enums/ManagerStatus.cs index 5596a77766..d645b7c7b3 100644 --- a/src/UniGetUI.PackageEngine.Enums/ManagerStatus.cs +++ b/src/UniGetUI.PackageEngine.Enums/ManagerStatus.cs @@ -1,12 +1,10 @@ namespace UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers { - public struct ManagerStatus + public class ManagerStatus { public string Version = ""; - public bool Found = false; + public bool Found; public string ExecutablePath = ""; - public string ExecutableCallArgs { get; set; } = "Unset"; - public ManagerStatus() - { } + public string ExecutableCallArgs = "Unset"; } } diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Helpers/BaseSourceHelper.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Helpers/BaseSourceHelper.cs index f439e606eb..153f91b0a1 100644 --- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Helpers/BaseSourceHelper.cs +++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Helpers/BaseSourceHelper.cs @@ -1,5 +1,6 @@ using UniGetUI.Core.Classes; using UniGetUI.Core.Logging; +using UniGetUI.Core.SettingsEngine; using UniGetUI.PackageEngine.Enums; using UniGetUI.PackageEngine.Interfaces; using UniGetUI.PackageEngine.Interfaces.ManagerProviders; @@ -8,6 +9,9 @@ namespace UniGetUI.PackageEngine.Classes.Manager.Providers { public abstract class BaseSourceHelper : IMultiSourceHelper { + private const int PackageListingTaskTimeout = 60; + + public ISourceFactory Factory { get; } protected IPackageManager Manager; @@ -54,11 +58,19 @@ public virtual IReadOnlyList GetSources() public virtual IReadOnlyList _getSources() { - if (!Manager.IsReady()) { Logger.Warn($"Manager {Manager.Name} is disabled but yet GetSources was called"); return []; } - try { - IReadOnlyList sources = GetSources_UnSafe().ToArray(); + var task = Task.Run(GetSources_UnSafe); + if (!task.Wait(TimeSpan.FromSeconds(PackageListingTaskTimeout))) + { + if (!Settings.Get(Settings.K.DisableTimeoutOnPackageListingTasks)) + throw new TimeoutException($"Task _getInstalledPackages for manager {Manager.Name} did not finish after " + + $"{PackageListingTaskTimeout} seconds, aborting. You may disable " + + $"timeouts from UniGetUI Advanced Settings"); + task.Wait(); + } + + var sources = task.Result; Factory.Reset(); foreach (IManagerSource source in sources) diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs index eaebd60a26..b48a04fe77 100644 --- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs +++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs @@ -1,6 +1,8 @@ +using ABI.Windows.UI.Text.Core; using UniGetUI.Core.Logging; using UniGetUI.Core.SettingsEngine; using UniGetUI.Core.SettingsEngine.SecureSettings; +using UniGetUI.Core.Tools; using UniGetUI.PackageEngine.Classes.Manager; using UniGetUI.PackageEngine.Classes.Manager.Classes; using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers; @@ -22,7 +24,6 @@ public abstract class PackageManager : IPackageManager public string Name { get => Properties.Name; } public string DisplayName { get => Properties.DisplayName ?? Name; } public IManagerSource DefaultSource { get => Properties.DefaultSource; } - public bool ManagerReady { get; set; } public IManagerLogger TaskLogger { get; } public IReadOnlyList Dependencies { get; protected set; } = []; public IMultiSourceHelper SourcesHelper { get; protected set; } = new NullSourceHelper(); @@ -30,6 +31,7 @@ public abstract class PackageManager : IPackageManager public IPackageOperationHelper OperationHelper { get; protected set; } = null!; private readonly bool _baseConstructorCalled; + private bool _ready; public PackageManager() { @@ -42,12 +44,65 @@ private static void Throw(string message) throw new InvalidDataException(message); } + protected abstract void _loadManagerExecutableFile(out bool found, out string path, out string callArguments); + protected abstract void _loadManagerVersion(out string version); + protected abstract void _performExtraLoadingSteps(); + + public void Initialize() + { + try + { + _ready = false; + _ensurePropertlyConstructed(); + + if (IsEnabled()) + { + // Do NOT initialise disabled package managers + Status = new() { Version = CoreTools.Translate("{0} is disabled", DisplayName) }; + Logger.Info($"{Name} is not enabled"); + return; + } + + // Find package manager executable + _loadManagerExecutableFile(out bool found, out string path, out string callArguments); + Status = new ManagerStatus(); + Status.Found = found; + Status.ExecutablePath = path; + Status.ExecutableCallArgs = callArguments; + + if (!Status.Found) + { + // Do not load version of managers that were not found + Status.Version = CoreTools.Translate("{pm} was not found!").Replace("{pm}", DisplayName).Trim('!'); + Logger.Warn($"{Name} was not found on the system!"); + return; + } + + Logger.Info($"{Name} is enabled and was found on {path}"); + + // Load manager version + _loadManagerVersion(out string version); + Status.Version = version; + _logManagerInfo(); + + // Finish initialization + _initializeSources(); + _performExtraLoadingSteps(); + _ready = true; + } + catch (Exception ex) + { + Logger.Error($"An error occurred while initialising package manager {Name}"); + Logger.Error(ex); + } + } + /// - /// Initializes the Package Manager (asynchronously). Must be run before using any other method of the manager. + /// This serves to ensure that the implemented hasn't messed up any crucial + /// details on the implementation /// - public virtual void Initialize() + private void _ensurePropertlyConstructed() { - // BEGIN integrity check if (!_baseConstructorCalled) Throw($"The Manager {Properties.Name} has not called the base constructor."); if (Capabilities.IsDummy) Throw($"The current instance of PackageManager with name ${Properties.Name} does not have a valid Capabilities object"); if (Properties.IsDummy) Throw($"The current instance of PackageManager with name ${Properties.Name} does not have a valid Properties object"); @@ -57,66 +112,45 @@ public virtual void Initialize() if (Capabilities.SupportsCustomSources && SourcesHelper is NullSourceHelper) Throw($"Manager {Name} has been declared as SupportsCustomSources but has no helper associated with it"); - // END integrity check + } + /// + /// Load and prepare manager sources sources + /// + private void _initializeSources() + { + // Sources that are instantiated before Manager's DisplayName property will have invalid DisplayName + // To prevent loading it on runtime, the string is cached internally and will only be reloaded when needed to Properties.DefaultSource.RefreshSourceNames(); foreach (var source in Properties.KnownSources) { source.RefreshSourceNames(); } - try - { - Status = LoadManager(); - - if (IsReady() && Capabilities.SupportsCustomSources) - { - Task> sourcesTask = Task.Run(SourcesHelper.GetSources); - - if (sourcesTask.Wait(TimeSpan.FromSeconds(15))) - { - foreach (var source in sourcesTask.Result) - { - SourcesHelper?.Factory.AddSource(source); - } - } - else - { - Logger.Warn(Name + " sources took too long to load, using known sources as default"); - } - } - ManagerReady = true; - - string LogData = "▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄" + - "\n█▀▀▀▀▀▀▀▀▀▀▀▀▀ MANAGER LOADED ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀" + - "\n█ Name: " + Name + - "\n█ Enabled: " + IsEnabled().ToString() + - (IsEnabled() ? - "\n█ Found: " + Status.Found.ToString() + - (Status.Found ? - "\n█ Fancy exe name: " + Properties.ExecutableFriendlyName + - "\n█ Executable path: " + Status.ExecutablePath + - "\n█ Call arguments: " + Status.ExecutableCallArgs + - "\n█ Version: \n" + "█ " + Status.Version.Replace("\n", "\n█ ") - : - "\n█ THE MANAGER WAS NOT FOUND. PERHAPS IT IS NOT " + - "\n█ INSTALLED OR IT HAS BEEN MISCONFIGURED " - ) - : - "\n█ THE MANAGER IS DISABLED" - ) + - "\n▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀"; - - Logger.Info(LogData); - } - catch (Exception e) + if (Capabilities.SupportsCustomSources) { - ManagerReady = true; // We need this to unblock the main thread - Logger.Error("Could not initialize Package Manager " + Name); - Logger.Error(e); + // SourcesHelper.GetSources() will handle saving the found sources to the internal registry + SourcesHelper.GetSources(); } } + private void _logManagerInfo() + { + string LogData = $""" + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + █▀▀▀▀▀▀▀▀▀▀▀▀▀ MANAGER LOADED ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ + █ Name: {DisplayName} (aka {Name}) + █ Executable name: "{Properties.ExecutableFriendlyName}" + █ Executable path: "{Status.ExecutablePath}" + █ Call arguments: "{Status.ExecutableCallArgs}" + █ Version: {Status.Version.Trim().Replace("\n", "\n█ ")} + █ + █ {DisplayName} is enabled and ready to go. + ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ + """; + Logger.Info(LogData); + } + /// /// Returns a list of paths that could be used for this package manager. /// For example, if you have three Pythons installed on your system, this would return those three Pythons. @@ -170,11 +204,6 @@ public Tuple GetExecutableFile() } } - /// - /// Returns a ManagerStatus object representing the current status of the package manager. This method runs asynchronously. - /// - protected abstract ManagerStatus LoadManager(); - /// /// Returns true if the manager is enabled, false otherwise /// @@ -188,7 +217,7 @@ public bool IsEnabled() /// public bool IsReady() { - return IsEnabled() && Status.Found; + return _ready && IsEnabled() && Status.Found; } /// From b136c3e40d7022f1aa27137ea7f995316963e3e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Mon, 1 Sep 2025 20:49:48 +0200 Subject: [PATCH 02/20] migrate cargo and dotnet to new initialization --- .../Cargo.cs | 31 +++++------ .../DotNet.cs | 51 ++++++++----------- 2 files changed, 34 insertions(+), 48 deletions(-) diff --git a/src/UniGetUI.PackageEngine.Managers.Cargo/Cargo.cs b/src/UniGetUI.PackageEngine.Managers.Cargo/Cargo.cs index 07c43c3c4d..6a40275053 100644 --- a/src/UniGetUI.PackageEngine.Managers.Cargo/Cargo.cs +++ b/src/UniGetUI.PackageEngine.Managers.Cargo/Cargo.cs @@ -138,32 +138,27 @@ protected override IReadOnlyList GetInstalledPackages_UnSafe() } public override IReadOnlyList FindCandidateExecutableFiles() + => CoreTools.WhichMultiple("cargo.exe"); + + protected override void _loadManagerExecutableFile(out bool found, out string path, out string callArguments) { - return CoreTools.WhichMultiple("cargo.exe"); + var (_found, _executablePath) = GetExecutableFile(); + found = _found; + path = _executablePath; + callArguments = ""; } - protected override ManagerStatus LoadManager() + protected override void _loadManagerVersion(out string version) { - var (found, executablePath) = GetExecutableFile(); - if (!found) - { - return new(){ ExecutablePath = executablePath, Found = false, Version = ""}; - } - - Status = new() { ExecutablePath = executablePath, Found = found, Version = "", ExecutableCallArgs = ""}; - - using Process p = GetProcess(executablePath, "--version"); + using Process p = GetProcess(Status.ExecutablePath, "--version"); p.Start(); - string version = p.StandardOutput.ReadToEnd().Trim(); + version = p.StandardOutput.ReadToEnd().Trim(); string error = p.StandardError.ReadToEnd(); - if (!string.IsNullOrEmpty(error)) - { - Logger.Error("cargo version error: " + error); - } - - return new() { ExecutablePath = executablePath, Found = found, Version = version, ExecutableCallArgs = ""}; + if (!string.IsNullOrEmpty(error)) Logger.Error("cargo version error: " + error); } + protected override void _performExtraLoadingSteps() { } + private IReadOnlyList GetPackages(LoggableTaskType taskType) { List Packages = []; diff --git a/src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs b/src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs index fd5ef25d2f..1798a5a8a4 100644 --- a/src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs +++ b/src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs @@ -126,31 +126,23 @@ protected override IReadOnlyList _getInstalledPackages_UnSafe() } public override IReadOnlyList FindCandidateExecutableFiles() - { - return CoreTools.WhichMultiple("dotnet.exe"); - } + => CoreTools.WhichMultiple("dotnet.exe"); - protected override ManagerStatus LoadManager() + protected override void _loadManagerExecutableFile(out bool found, out string path, out string callArguments) { - var (found, path) = GetExecutableFile(); - ManagerStatus status = new() - { - ExecutablePath = path, - Found = found, - ExecutableCallArgs = "tool " - }; - - if (!status.Found) - { - return status; - } - - Process process = new() + var (_found, _path) = GetExecutableFile(); + found = _found; + path = _path; + callArguments = "tool "; + + // Ensure .NET SDK is installed + if (!found) return; + var process = new Process() { StartInfo = new ProcessStartInfo { - FileName = status.ExecutablePath, - Arguments = status.ExecutableCallArgs + "-h", + FileName = path, + Arguments = callArguments + "-h", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, @@ -160,17 +152,16 @@ protected override ManagerStatus LoadManager() }; process.Start(); process.WaitForExit(); - if (process.ExitCode != 0) - { - status.Found = false; - return status; - } + found = process.ExitCode is 0; + } - process = new() + protected override void _loadManagerVersion(out string version) + { + var process = new Process() { StartInfo = new ProcessStartInfo { - FileName = status.ExecutablePath, + FileName = Status.ExecutablePath, Arguments = "--version", UseShellExecute = false, RedirectStandardOutput = true, @@ -181,9 +172,9 @@ protected override ManagerStatus LoadManager() }; process.Start(); - status.Version = process.StandardOutput.ReadToEnd().Trim(); - - return status; + version = process.StandardOutput.ReadToEnd().Trim(); } + + protected override void _performExtraLoadingSteps() { } } } From 8cc8f892f7bee9f9b5fab99af318c023eece3565 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Mon, 1 Sep 2025 23:23:42 +0200 Subject: [PATCH 03/20] Migrate Pip, PowerShell, PowerShell7 --- .../Cargo.cs | 2 - .../DotNet.cs | 2 - .../Npm.cs | 33 ++++------ .../Pip.cs | 64 +++++++++++-------- .../PowerShell.cs | 31 ++++----- .../PowerShell7.cs | 32 +++------- .../Manager/PackageManager.cs | 2 +- 7 files changed, 72 insertions(+), 94 deletions(-) diff --git a/src/UniGetUI.PackageEngine.Managers.Cargo/Cargo.cs b/src/UniGetUI.PackageEngine.Managers.Cargo/Cargo.cs index 6a40275053..bc5db70d04 100644 --- a/src/UniGetUI.PackageEngine.Managers.Cargo/Cargo.cs +++ b/src/UniGetUI.PackageEngine.Managers.Cargo/Cargo.cs @@ -157,8 +157,6 @@ protected override void _loadManagerVersion(out string version) if (!string.IsNullOrEmpty(error)) Logger.Error("cargo version error: " + error); } - protected override void _performExtraLoadingSteps() { } - private IReadOnlyList GetPackages(LoggableTaskType taskType) { List Packages = []; diff --git a/src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs b/src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs index 1798a5a8a4..9180fbf470 100644 --- a/src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs +++ b/src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs @@ -174,7 +174,5 @@ protected override void _loadManagerVersion(out string version) process.Start(); version = process.StandardOutput.ReadToEnd().Trim(); } - - protected override void _performExtraLoadingSteps() { } } } diff --git a/src/UniGetUI.PackageEngine.Managers.Npm/Npm.cs b/src/UniGetUI.PackageEngine.Managers.Npm/Npm.cs index ffc10c742a..002eba0338 100644 --- a/src/UniGetUI.PackageEngine.Managers.Npm/Npm.cs +++ b/src/UniGetUI.PackageEngine.Managers.Npm/Npm.cs @@ -189,32 +189,25 @@ protected override IReadOnlyList GetInstalledPackages_UnSafe() } public override IReadOnlyList FindCandidateExecutableFiles() - { - return CoreTools.WhichMultiple("npm.ps1"); - } + => CoreTools.WhichMultiple("npm.ps1"); - protected override ManagerStatus LoadManager() + protected override void _loadManagerExecutableFile(out bool found, out string path, out string callArguments) { - var (found, executable) = GetExecutableFile(); - - ManagerStatus status = new() - { - ExecutablePath = CoreData.PowerShell5, - ExecutableCallArgs = $"-NoProfile -ExecutionPolicy Bypass -Command \"{executable.Replace(" ", "` ")}\" ", - Found = found - }; + var (_found, _executable) = GetExecutableFile(); - if (!status.Found) - { - return status; - } + found = _found; + path = CoreData.PowerShell5; + callArguments = $"-NoProfile -ExecutionPolicy Bypass -Command \"{_executable.Replace(" ", "` ")}\" "; + } + protected override void _loadManagerVersion(out string version) + { Process process = new() { StartInfo = new ProcessStartInfo { - FileName = status.ExecutablePath, - Arguments = status.ExecutableCallArgs + "--version", + FileName = Status.ExecutablePath, + Arguments = Status.ExecutableCallArgs + "--version", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, @@ -225,10 +218,8 @@ protected override ManagerStatus LoadManager() } }; process.Start(); - status.Version = process.StandardOutput.ReadToEnd().Trim(); + version = process.StandardOutput.ReadToEnd().Trim(); process.WaitForExit(); - - return status; } } } diff --git a/src/UniGetUI.PackageEngine.Managers.Pip/Pip.cs b/src/UniGetUI.PackageEngine.Managers.Pip/Pip.cs index 2edf6ebbe3..e21ef40bb3 100644 --- a/src/UniGetUI.PackageEngine.Managers.Pip/Pip.cs +++ b/src/UniGetUI.PackageEngine.Managers.Pip/Pip.cs @@ -58,7 +58,9 @@ public Pip() Properties = new ManagerProperties { Name = "Pip", - Description = CoreTools.Translate("Python's library manager. Full of python libraries and other python-related utilities
Contains: Python libraries and related utilities"), + Description = + CoreTools.Translate( + "Python's library manager. Full of python libraries and other python-related utilities
Contains: Python libraries and related utilities"), IconId = IconType.Python, ColorIconId = "pip_color", ExecutableFriendlyName = "pip", @@ -84,11 +86,12 @@ public static string GetProxyArgument() return $"--proxy {proxyUri.ToString()}"; var creds = Settings.GetProxyCredentials(); - if(creds is null) + if (creds is null) return $"--proxy {proxyUri.ToString()}"; - return $"--proxy {proxyUri.Scheme}://{Uri.EscapeDataString(creds.UserName)}:{Uri.EscapeDataString(creds.Password)}" + - $"@{proxyUri.AbsoluteUri.Replace($"{proxyUri.Scheme}://", "")}"; + return + $"--proxy {proxyUri.Scheme}://{Uri.EscapeDataString(creds.UserName)}:{Uri.EscapeDataString(creds.Password)}" + + $"@{proxyUri.AbsoluteUri.Replace($"{proxyUri.Scheme}://", "")}"; } protected override IReadOnlyList FindPackages_UnSafe(string query) @@ -169,9 +172,11 @@ protected override IReadOnlyList FindPackages_UnSafe(string query) continue; } - Packages.Add(new Package(CoreTools.FormatAsName(elements[0]), elements[0], elements[1], DefaultSource, this, new(PackageScope.Global))); + Packages.Add(new Package(CoreTools.FormatAsName(elements[0]), elements[0], elements[1], + DefaultSource, this, new(PackageScope.Global))); } } + logger.AddToStdErr(p.StandardError.ReadToEnd()); p.WaitForExit(); logger.Close(p.ExitCode); @@ -230,9 +235,11 @@ protected override IReadOnlyList GetAvailableUpdates_UnSafe() continue; } - Packages.Add(new Package(CoreTools.FormatAsName(elements[0]), elements[0], elements[1], elements[2], DefaultSource, this, new(PackageScope.Global))); + Packages.Add(new Package(CoreTools.FormatAsName(elements[0]), elements[0], elements[1], elements[2], + DefaultSource, this, new(PackageScope.Global))); } } + logger.AddToStdErr(p.StandardError.ReadToEnd()); p.WaitForExit(); logger.Close(p.ExitCode); @@ -292,9 +299,11 @@ protected override IReadOnlyList GetInstalledPackages_UnSafe() continue; } - Packages.Add(new Package(CoreTools.FormatAsName(elements[0]), elements[0], elements[1], DefaultSource, this, new(PackageScope.Global))); + Packages.Add(new Package(CoreTools.FormatAsName(elements[0]), elements[0], elements[1], + DefaultSource, this, new(PackageScope.Global))); } } + logger.AddToStdErr(p.StandardError.ReadToEnd()); p.WaitForExit(); logger.Close(p.ExitCode); @@ -307,7 +316,9 @@ public override IReadOnlyList FindCandidateExecutableFiles() var FoundPaths = CoreTools.WhichMultiple("python"); List Paths = []; - if (FoundPaths.Any()) foreach (var Path in FoundPaths) Paths.Add(Path); + if (FoundPaths.Any()) + foreach (var Path in FoundPaths) + Paths.Add(Path); try { @@ -330,28 +341,29 @@ public override IReadOnlyList FindCandidateExecutableFiles() Paths.Add(PythonPath); } } - catch (Exception) { } + catch (Exception) + { + } return Paths; } - protected override ManagerStatus LoadManager() + protected override void _loadManagerExecutableFile(out bool found, out string path, out string callArguments) { - var (found, path) = GetExecutableFile(); - - ManagerStatus status = new() { ExecutablePath = path, Found = found, ExecutableCallArgs = "-m pip " }; - - if (!status.Found) - { - return status; - } + var (_found, _path) = GetExecutableFile(); + found = _found; + path = _path; + callArguments = "-m pip "; + } + protected override void _loadManagerVersion(out string version) + { Process process = new() { StartInfo = new ProcessStartInfo { - FileName = status.ExecutablePath, - Arguments = status.ExecutableCallArgs + "--version " + GetProxyArgument(), + FileName = Status.ExecutablePath, + Arguments = Status.ExecutableCallArgs + "--version " + GetProxyArgument(), UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, @@ -360,17 +372,17 @@ protected override ManagerStatus LoadManager() } }; process.Start(); - status.Version = process.StandardOutput.ReadToEnd().Trim(); + version = process.StandardOutput.ReadToEnd().Trim(); - if (process.ExitCode == 9009) + if (process.ExitCode is 9009) { - status.Found = false; - return status; + throw new Exception("Microsoft Store python alias is not a valid python install"); } + } - + protected override void _performExtraLoadingSteps() + { Environment.SetEnvironmentVariable("PIP_REQUIRE_VIRTUALENV", "false", EnvironmentVariableTarget.Process); - return status; } } } diff --git a/src/UniGetUI.PackageEngine.Managers.PowerShell/PowerShell.cs b/src/UniGetUI.PackageEngine.Managers.PowerShell/PowerShell.cs index 226daea319..f6d910280f 100644 --- a/src/UniGetUI.PackageEngine.Managers.PowerShell/PowerShell.cs +++ b/src/UniGetUI.PackageEngine.Managers.PowerShell/PowerShell.cs @@ -124,27 +124,22 @@ public override List FindCandidateExecutableFiles() return candidates; } - protected override ManagerStatus LoadManager() + protected override void _loadManagerExecutableFile(out bool found, out string path, out string callArguments) { - var (found, path) = GetExecutableFile(); - ManagerStatus status = new() - { - ExecutablePath = path, - Found = found, - ExecutableCallArgs = " -NoProfile -Command", - }; - - if (!status.Found) - { - return status; - } + var (_found, _path) = GetExecutableFile(); + found = _found; + path = _path; + callArguments = " -NoProfile -Command"; + } + protected override void _loadManagerVersion(out string version) + { Process process = new() { StartInfo = new ProcessStartInfo { - FileName = status.ExecutablePath, - Arguments = status.ExecutableCallArgs + " \"echo $PSVersionTable\"", + FileName = Status.ExecutablePath, + Arguments = Status.ExecutableCallArgs + " \"echo $PSVersionTable\"", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, @@ -153,11 +148,7 @@ protected override ManagerStatus LoadManager() } }; process.Start(); - status.Version = process.StandardOutput.ReadToEnd().Trim(); - - return status; + version = process.StandardOutput.ReadToEnd().Trim(); } - } - } diff --git a/src/UniGetUI.PackageEngine.Managers.PowerShell7/PowerShell7.cs b/src/UniGetUI.PackageEngine.Managers.PowerShell7/PowerShell7.cs index 28a88538b4..0627f76400 100644 --- a/src/UniGetUI.PackageEngine.Managers.PowerShell7/PowerShell7.cs +++ b/src/UniGetUI.PackageEngine.Managers.PowerShell7/PowerShell7.cs @@ -118,31 +118,23 @@ protected override IReadOnlyList _getInstalledPackages_UnSafe() } public override IReadOnlyList FindCandidateExecutableFiles() + => CoreTools.WhichMultiple("pwsh.exe"); + + protected override void _loadManagerExecutableFile(out bool found, out string path, out string callArguments) { - return CoreTools.WhichMultiple("pwsh.exe"); + var (_found, _path) = GetExecutableFile(); + found = _found; + path = _path; + callArguments = " -NoProfile -Command"; } - protected override ManagerStatus LoadManager() + protected override void _loadManagerVersion(out string version) { - var (found, path) = GetExecutableFile(); - - ManagerStatus status = new() - { - ExecutablePath = path, - Found = found, - ExecutableCallArgs = " -NoProfile -Command", - }; - - if (!status.Found) - { - return status; - } - Process process = new() { StartInfo = new ProcessStartInfo { - FileName = status.ExecutablePath, + FileName = Status.ExecutablePath, Arguments = "-NoProfile -Version", UseShellExecute = false, RedirectStandardOutput = true, @@ -152,11 +144,7 @@ protected override ManagerStatus LoadManager() } }; process.Start(); - status.Version = process.StandardOutput.ReadToEnd().Trim(); - - return status; + version = process.StandardOutput.ReadToEnd().Trim(); } - } - } diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs index b48a04fe77..276f435252 100644 --- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs +++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs @@ -46,7 +46,7 @@ private static void Throw(string message) protected abstract void _loadManagerExecutableFile(out bool found, out string path, out string callArguments); protected abstract void _loadManagerVersion(out string version); - protected abstract void _performExtraLoadingSteps(); + protected virtual void _performExtraLoadingSteps() { } public void Initialize() { From 2262d0db19f26e8d26e246f7e1916b9c61af7881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Mon, 1 Sep 2025 23:27:12 +0200 Subject: [PATCH 04/20] Update Chocolatey.cs --- .../Chocolatey.cs | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs b/src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs index 1a6364e06b..582f681a16 100644 --- a/src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs +++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs @@ -204,7 +204,7 @@ public override IReadOnlyList FindCandidateExecutableFiles() return candidates; } - protected override ManagerStatus LoadManager() + protected override void _loadManagerExecutableFile(out bool found, out string path, out string callArguments) { if (!Directory.Exists(OldChocoPath)) { @@ -293,19 +293,19 @@ protected override ManagerStatus LoadManager() } } - var (found, executable) = GetExecutableFile(); - ManagerStatus status = new() { Found = found, ExecutablePath = executable, ExecutableCallArgs = "", }; - - if (!status.Found) - { - return status; - } + var (_found, _path) = GetExecutableFile(); + found = _found; + path = _path; + callArguments = ""; + } + protected override void _loadManagerVersion(out string version) + { Process process = new() { StartInfo = new ProcessStartInfo { - FileName = status.ExecutablePath, + FileName = Status.ExecutablePath, Arguments = "--version " + GetProxyArgument(), UseShellExecute = false, RedirectStandardOutput = true, @@ -315,19 +315,21 @@ protected override ManagerStatus LoadManager() } }; process.Start(); - status.Version = process.StandardOutput.ReadToEnd().Trim(); + version = process.StandardOutput.ReadToEnd().Trim(); + } + protected override void _performExtraLoadingSteps() + { // If the user is running bundled chocolatey and chocolatey is not in path, add chocolatey to path - if (!Settings.Get(Settings.K.UseSystemChocolatey) - && !File.Exists("C:\\ProgramData\\Chocolatey\\bin\\choco.exe")) - /* && Settings.Get(Settings.K.ShownWelcomeWizard)) */ + if (!Settings.Get(Settings.K.UseSystemChocolatey) && !File.Exists("C:\\ProgramData\\Chocolatey\\bin\\choco.exe")) + /* && Settings.Get(Settings.K.ShownWelcomeWizard)) */ { string? path = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.User); - if (!path?.Contains(status.ExecutablePath.Replace("\\choco.exe", "\\bin")) ?? false) + if (!path?.Contains(Status.ExecutablePath.Replace("\\choco.exe", "\\bin")) ?? false) { Logger.ImportantInfo("Adding chocolatey to path since it was not on path."); - Environment.SetEnvironmentVariable("PATH", $"{status.ExecutablePath.Replace("\\choco.exe", "\\bin")};{path}", EnvironmentVariableTarget.User); - Environment.SetEnvironmentVariable("chocolateyinstall", Path.GetDirectoryName(status.ExecutablePath), EnvironmentVariableTarget.User); + Environment.SetEnvironmentVariable("PATH", $"{Status.ExecutablePath.Replace("\\choco.exe", "\\bin")};{path}", EnvironmentVariableTarget.User); + Environment.SetEnvironmentVariable("chocolateyinstall", Path.GetDirectoryName(Status.ExecutablePath), EnvironmentVariableTarget.User); } else { @@ -336,14 +338,12 @@ protected override ManagerStatus LoadManager() } // Trick chocolatey into using the wanted installation - var choco_dir = Path.GetDirectoryName(status.ExecutablePath)?.Replace('/', '\\').Trim('\\') ?? ""; + var choco_dir = Path.GetDirectoryName(Status.ExecutablePath)?.Replace('/', '\\').Trim('\\') ?? ""; if (choco_dir.EndsWith("bin")) { choco_dir = choco_dir[..^3].Trim('\\'); } Environment.SetEnvironmentVariable("chocolateyinstall", choco_dir, EnvironmentVariableTarget.Process); - - return status; } } } From 8416a36c23dce47936c08fe6b54c8dc59856241d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Mon, 1 Sep 2025 23:31:40 +0200 Subject: [PATCH 05/20] Update Scoop.cs --- .../Scoop.cs | 50 +++++++------------ 1 file changed, 18 insertions(+), 32 deletions(-) diff --git a/src/UniGetUI.PackageEngine.Managers.Scoop/Scoop.cs b/src/UniGetUI.PackageEngine.Managers.Scoop/Scoop.cs index 9022bcddf5..ec0f193e4a 100644 --- a/src/UniGetUI.PackageEngine.Managers.Scoop/Scoop.cs +++ b/src/UniGetUI.PackageEngine.Managers.Scoop/Scoop.cs @@ -374,41 +374,27 @@ public override void RefreshPackageIndexes() } public override IReadOnlyList FindCandidateExecutableFiles() - { - return CoreTools.WhichMultiple("scoop.ps1"); - } - + => CoreTools.WhichMultiple("scoop.ps1"); - protected override ManagerStatus LoadManager() + protected override void _loadManagerExecutableFile(out bool found, out string path, out string callArguments) { - string path = CoreData.PowerShell5; - var pwsh7 = CoreTools.Which("pwsh.exe"); - - if (pwsh7.Item1) - { - Logger.Info("Scoop found PowerShell7, PowerShell7 will be used..."); - path = pwsh7.Item2; - } - - var (found, executable) = GetExecutableFile(); - ManagerStatus status = new() - { - ExecutablePath = path, - ExecutableCallArgs = $"-NoProfile -ExecutionPolicy Bypass -Command \"{executable.Replace(" ", "` ")}\" ", - Found = found, - }; + path = CoreData.PowerShell5; + var (pwshFound, pwshPath) = CoreTools.Which("pwsh.exe"); + if (pwshFound) path = pwshPath; - if (!status.Found) - { - return status; - } + var (_found, executable) = GetExecutableFile(); + found = _found; + callArguments = $"-NoProfile -ExecutionPolicy Bypass -Command \"{executable.Replace(" ", "` ")}\" "; + } + protected override void _loadManagerVersion(out string version) + { Process process = new() { StartInfo = new ProcessStartInfo { - FileName = status.ExecutablePath, - Arguments = status.ExecutableCallArgs + "--version", + FileName = Status.ExecutablePath, + Arguments = Status.ExecutableCallArgs + "--version", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, @@ -417,15 +403,15 @@ protected override ManagerStatus LoadManager() } }; process.Start(); - status.Version = process.StandardOutput.ReadToEnd().Trim(); + version = process.StandardOutput.ReadToEnd().Trim(); + } - Status = status; // Wee need this for the RunCleanup method to get the executable path - if (status.Found && IsEnabled() && Settings.Get(Settings.K.EnableScoopCleanup)) + protected override void _performExtraLoadingSteps() + { + if(Settings.Get(Settings.K.EnableScoopCleanup)) { RunCleanup(); } - - return status; } private void RunCleanup() => _ = _runCleanup(); From 696279e2805c5e871449c2925456edbf2d2abdb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Mon, 1 Sep 2025 23:42:59 +0200 Subject: [PATCH 06/20] migrate vcpkg --- .../Vcpkg.cs | 50 ++++++------------- 1 file changed, 15 insertions(+), 35 deletions(-) diff --git a/src/UniGetUI.PackageEngine.Managers.Vcpkg/Vcpkg.cs b/src/UniGetUI.PackageEngine.Managers.Vcpkg/Vcpkg.cs index 07bef3111a..dcd204aa78 100644 --- a/src/UniGetUI.PackageEngine.Managers.Vcpkg/Vcpkg.cs +++ b/src/UniGetUI.PackageEngine.Managers.Vcpkg/Vcpkg.cs @@ -302,45 +302,30 @@ public override IReadOnlyList FindCandidateExecutableFiles() return candidates; } - protected override ManagerStatus LoadManager() + protected override void _loadManagerExecutableFile(out bool found, out string path, out string callArguments) { var (exeFound, exePath) = GetExecutableFile(); - var (rootFound, rootPath) = GetVcpkgRoot(); + var (rootFound, _) = GetVcpkgRoot(); - if (!exeFound) - { - return new() - { - Found = false, - ExecutablePath = exePath, - Version = CoreTools.Translate( - "Vcpkg was not found on your system."), - }; - } + Logger.Error("Vcpkg root was not found. Please define the %VCPKG_ROOT% environment variable or define it from UniGetUI Settings"); - if (!rootFound) - { - return new() - { - Found = false, - ExecutablePath = CoreTools.Translate( - "Vcpkg root was not found. Please define the %VCPKG_ROOT% environment variable or define it from UniGetUI Settings"), - }; - } + found = exeFound && rootFound; + path = exePath; - ManagerStatus status = new ManagerStatus { Found = exeFound, ExecutablePath = exePath, }; + string vcpkgRoot = Settings.GetValue(Settings.K.CustomVcpkgRoot); + callArguments = vcpkgRoot == "" ? "" : $" --vcpkg-root=\"{vcpkgRoot}\""; + } - if (!status.Found) - { - return status; - } + protected override void _loadManagerVersion(out string version) + { + var (_, rootPath) = GetVcpkgRoot(); Process process = new() { StartInfo = new ProcessStartInfo { - FileName = status.ExecutablePath, - Arguments = status.ExecutableCallArgs + " version", + FileName = Status.ExecutablePath, + Arguments = Status.ExecutableCallArgs + " version", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, @@ -350,13 +335,8 @@ protected override ManagerStatus LoadManager() } }; process.Start(); - status.Version = process.StandardOutput.ReadLine()?.Trim() ?? ""; - status.Version += $"\n%VCPKG_ROOT% = {rootPath}"; - - string vcpkgRoot = Settings.GetValue(Settings.K.CustomVcpkgRoot); - status.ExecutableCallArgs = vcpkgRoot == "" ? "" : $" --vcpkg-root=\"{vcpkgRoot}\""; - - return status; + version = process.StandardOutput.ReadLine()?.Trim() ?? ""; + version += $"\n%VCPKG_ROOT% = {rootPath}"; } public override void RefreshPackageIndexes() From 4e1864c09e1b792c2b47b633889aa1aa78801597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Mon, 1 Sep 2025 23:44:48 +0200 Subject: [PATCH 07/20] move bootstrap to _performExtraLoadingSteps --- .../Vcpkg.cs | 46 ++++++++----------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/src/UniGetUI.PackageEngine.Managers.Vcpkg/Vcpkg.cs b/src/UniGetUI.PackageEngine.Managers.Vcpkg/Vcpkg.cs index dcd204aa78..039978da46 100644 --- a/src/UniGetUI.PackageEngine.Managers.Vcpkg/Vcpkg.cs +++ b/src/UniGetUI.PackageEngine.Managers.Vcpkg/Vcpkg.cs @@ -23,8 +23,6 @@ public class Vcpkg : PackageManager public Dictionary TripletSourceMap; public static Uri URI_VCPKG_IO = new Uri("https://vcpkg.io/"); - private bool hasBeenBootstrapped; - public Vcpkg() { Dependencies = [ @@ -339,6 +337,26 @@ protected override void _loadManagerVersion(out string version) version += $"\n%VCPKG_ROOT% = {rootPath}"; } + protected override void _performExtraLoadingSteps() + { + var (_, rootPath) = GetVcpkgRoot(); + using Process p2 = new() + { + StartInfo = new ProcessStartInfo + { + FileName = "cmd.exe", + WorkingDirectory = rootPath, + Arguments = "/C .\\bootstrap-vcpkg.bat", + UseShellExecute = false, + CreateNoWindow = true + } + }; + IProcessTaskLogger processLogger2 = TaskLogger.CreateNew(LoggableTaskType.RefreshIndexes, p); + p2.Start(); + p2.WaitForExit(); + processLogger2.Close(p2.ExitCode); + } + public override void RefreshPackageIndexes() { var (vcpkgRootFound, vcpkgRoot) = GetVcpkgRoot(); @@ -374,30 +392,6 @@ public override void RefreshPackageIndexes() processLogger.AddToStdOut(p.StandardOutput.ReadToEnd()); processLogger.AddToStdErr(p.StandardError.ReadToEnd()); processLogger.Close(p.ExitCode); - - if (!hasBeenBootstrapped) - { - using Process p2 = new() - { - StartInfo = new ProcessStartInfo - { - FileName = "cmd.exe", - WorkingDirectory = vcpkgRoot, - Arguments = "/C .\\bootstrap-vcpkg.bat", - UseShellExecute = false, - // RedirectStandardOutput = true, - // RedirectStandardError = true, - CreateNoWindow = true - } - }; - IProcessTaskLogger processLogger2 = TaskLogger.CreateNew(LoggableTaskType.RefreshIndexes, p); - p2.Start(); - p2.WaitForExit(); - // processLogger2.AddToStdOut(p2.StandardOutput.ReadToEnd()); - // processLogger2.AddToStdErr(p2.StandardError.ReadToEnd()); - processLogger2.Close(p2.ExitCode); - hasBeenBootstrapped = true; - } } public static Tuple GetVcpkgRoot() From 1e24bdce3a8db06e717028e7b4a2fb891b5d0a63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Mon, 1 Sep 2025 23:57:55 +0200 Subject: [PATCH 08/20] migrate WinGet --- .../WinGet.cs | 84 ++++++++----------- .../Manager/PackageManager.cs | 2 +- 2 files changed, 37 insertions(+), 49 deletions(-) diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs index 528fa4ae7d..94e53971ef 100644 --- a/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs +++ b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs @@ -185,38 +185,46 @@ public override IReadOnlyList FindCandidateExecutableFiles() return candidates; } - protected override ManagerStatus LoadManager() + protected override void _loadManagerExecutableFile(out bool found, out string path, out string callArguments) { - bool FORCE_BUNDLED = Settings.Get(Settings.K.ForceLegacyBundledWinGet); - var (found, path) = GetExecutableFile(); - - ManagerStatus status = new() - { - ExecutablePath = path, - ExecutableCallArgs = "", - Found = found, - }; + var (_found, _path) = GetExecutableFile(); - if (found && status.ExecutablePath == BundledWinGetPath && !FORCE_BUNDLED) + if (_found && _path == BundledWinGetPath && !FORCE_BUNDLED) { Logger.Error("User does not have WinGet installed, forcing bundled WinGet..."); FORCE_BUNDLED = true; } - if (!status.Found) + found = _found; + path = _path; + callArguments = ""; + + try { - return status; + if (FORCE_BUNDLED) WinGetHelper.Instance = new BundledWinGetHelper(this); + else WinGetHelper.Instance = new NativeWinGetHelper(this); } + catch (Exception ex) + { + Logger.Warn($"Cannot instantiate {(FORCE_BUNDLED ? "Bundled" : "Native")} WinGet Helper due to error: {ex.Message}"); + Logger.Warn(ex); + Logger.Warn("WinGet will resort to using BundledWinGetHelper()"); + WinGetHelper.Instance = new BundledWinGetHelper(this); - TryRepairTempFolderPermissions(); + } + } + + protected override void _loadManagerVersion(out string version) + { + bool IS_BUNDLED = WinGetHelper.Instance is BundledWinGetHelper; Process process = new() { StartInfo = new ProcessStartInfo { - FileName = status.ExecutablePath, - Arguments = status.ExecutableCallArgs + " --version", + FileName = Status.ExecutablePath, + Arguments = Status.ExecutableCallArgs + " --version", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, @@ -232,41 +240,22 @@ protected override ManagerStatus LoadManager() process.StartInfo.Environment["TEMP"] = WinGetTemp; process.StartInfo.Environment["TMP"] = WinGetTemp; } - process.Start(); - status.Version = $"{(FORCE_BUNDLED ? "Bundled" : "System")} WinGet CLI Version: {process.StandardOutput.ReadToEnd().Trim()}"; - string error = process.StandardError.ReadToEnd(); - if (error != "") - { - Logger.Error("WinGet STDERR not empty: " + error); - } - try - { - if (FORCE_BUNDLED) - { - WinGetHelper.Instance = new BundledWinGetHelper(this); - status.Version += "\nUsing bundled WinGet helper (CLI parsing)"; - } - else - { - WinGetHelper.Instance = new NativeWinGetHelper(this); - status.Version += "\nUsing Native WinGet helper (COM Api)"; - } - } - catch (Exception ex) - { - Logger.Warn($"Cannot instantiate {(FORCE_BUNDLED? "Bundled" : "Native")} WinGet Helper due to error: {ex.Message}"); - Logger.Warn(ex); - Logger.Warn("WinGet will resort to using BundledWinGetHelper()"); - WinGetHelper.Instance = new BundledWinGetHelper(this); - status.Version += "\nUsing bundled WinGet helper (CLI parsing, caused by exception)"; - } + version = $"{(IS_BUNDLED ? "Bundled" : "System")} WinGet (CLI) Version: {process.StandardOutput.ReadToEnd().Trim()}"; + + if(IS_BUNDLED) version += "\nUsing bundled WinGet helper (CLI parsing)"; + else version += "\nUsing Native WinGet helper (COM Api)"; + + string error = process.StandardError.ReadToEnd(); + if (error != "") Logger.Error("WinGet STDERR not empty: " + error); + } - return status; + protected override void _performExtraLoadingSteps() + { + TryRepairTempFolderPermissions(); } - // For future usage private void ReRegisterCOMServer() { WinGetHelper.Instance = new NativeWinGetHelper(this); @@ -277,13 +266,12 @@ public override void AttemptFastRepair() { try { + TryRepairTempFolderPermissions(); if (WinGetHelper.Instance is NativeWinGetHelper) { Logger.ImportantInfo("Attempting to reconnect to WinGet COM Server..."); ReRegisterCOMServer(); - TryRepairTempFolderPermissions(); NO_PACKAGES_HAVE_BEEN_LOADED = false; - } else { diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs index 276f435252..b9c1621fd8 100644 --- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs +++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs @@ -86,9 +86,9 @@ public void Initialize() _logManagerInfo(); // Finish initialization - _initializeSources(); _performExtraLoadingSteps(); _ready = true; + _initializeSources(); } catch (Exception ex) { From ebcda9d3ba2b0a2d006dd5e52fe3af1a66ef414c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Tue, 2 Sep 2025 00:00:25 +0200 Subject: [PATCH 09/20] fix build errors --- src/UniGetUI.PackageEngine.Managers.Vcpkg/Vcpkg.cs | 2 +- .../Manager/PackageManager.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/UniGetUI.PackageEngine.Managers.Vcpkg/Vcpkg.cs b/src/UniGetUI.PackageEngine.Managers.Vcpkg/Vcpkg.cs index 039978da46..6251c6c89c 100644 --- a/src/UniGetUI.PackageEngine.Managers.Vcpkg/Vcpkg.cs +++ b/src/UniGetUI.PackageEngine.Managers.Vcpkg/Vcpkg.cs @@ -351,7 +351,7 @@ protected override void _performExtraLoadingSteps() CreateNoWindow = true } }; - IProcessTaskLogger processLogger2 = TaskLogger.CreateNew(LoggableTaskType.RefreshIndexes, p); + IProcessTaskLogger processLogger2 = TaskLogger.CreateNew(LoggableTaskType.RefreshIndexes, p2); p2.Start(); p2.WaitForExit(); processLogger2.Close(p2.ExitCode); diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs index b9c1621fd8..a69345ae5b 100644 --- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs +++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs @@ -48,7 +48,7 @@ private static void Throw(string message) protected abstract void _loadManagerVersion(out string version); protected virtual void _performExtraLoadingSteps() { } - public void Initialize() + public virtual void Initialize() { try { From 6058b1fd56d9efb485dbfdf1f468a793bfcc4d17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Tue, 2 Sep 2025 00:23:08 +0200 Subject: [PATCH 10/20] fix small issues --- src/UniGetUI.PackageEngine.Managers.Vcpkg/Vcpkg.cs | 2 +- .../PEInterface.cs | 12 ++---------- .../Manager/PackageManager.cs | 14 ++++++-------- 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/src/UniGetUI.PackageEngine.Managers.Vcpkg/Vcpkg.cs b/src/UniGetUI.PackageEngine.Managers.Vcpkg/Vcpkg.cs index 6251c6c89c..93131fab84 100644 --- a/src/UniGetUI.PackageEngine.Managers.Vcpkg/Vcpkg.cs +++ b/src/UniGetUI.PackageEngine.Managers.Vcpkg/Vcpkg.cs @@ -305,8 +305,8 @@ protected override void _loadManagerExecutableFile(out bool found, out string pa var (exeFound, exePath) = GetExecutableFile(); var (rootFound, _) = GetVcpkgRoot(); - Logger.Error("Vcpkg root was not found. Please define the %VCPKG_ROOT% environment variable or define it from UniGetUI Settings"); + if(!rootFound) Logger.Error("Vcpkg root was not found. Please define the %VCPKG_ROOT% environment variable or define it from UniGetUI Settings"); found = exeFound && rootFound; path = exePath; diff --git a/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs b/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs index 0c8417176d..38d50c6cee 100644 --- a/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs +++ b/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs @@ -51,17 +51,9 @@ public static void Initialize() initializeTasks.Add(Task.Run(manager.Initialize)); } - Task ManagersMetaTask = Task.WhenAll(initializeTasks); - try - { - ManagersMetaTask.Wait(TimeSpan.FromSeconds(ManagerLoadTimeout)); - } - catch (Exception e) - { - Logger.Error(e); - } + Task ManagersMegaTask = Task.WhenAll(initializeTasks); - if (ManagersMetaTask.IsCompletedSuccessfully == false) + if (!ManagersMegaTask.Wait(TimeSpan.FromSeconds(ManagerLoadTimeout))) { Logger.Warn("Timeout: Not all package managers have finished initializing."); } diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs index a69345ae5b..36c8a0cbe7 100644 --- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs +++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs @@ -55,11 +55,10 @@ public virtual void Initialize() _ready = false; _ensurePropertlyConstructed(); - if (IsEnabled()) - { - // Do NOT initialise disabled package managers + if (!IsEnabled()) + { // Do NOT initialise disabled package managers Status = new() { Version = CoreTools.Translate("{0} is disabled", DisplayName) }; - Logger.Info($"{Name} is not enabled"); + Logger.ImportantInfo($"{Name} is not enabled"); return; } @@ -71,14 +70,13 @@ public virtual void Initialize() Status.ExecutableCallArgs = callArguments; if (!Status.Found) - { - // Do not load version of managers that were not found + { // Do not load version of managers that were not found Status.Version = CoreTools.Translate("{pm} was not found!").Replace("{pm}", DisplayName).Trim('!'); - Logger.Warn($"{Name} was not found on the system!"); + Logger.Error($"{Name} is enabled but was not found on the system!"); return; } - Logger.Info($"{Name} is enabled and was found on {path}"); + Logger.ImportantInfo($"{Name} is enabled and was found on {path}"); // Load manager version _loadManagerVersion(out string version); From a6a8d098418814f59473f66700931cdc06c9c17a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Tue, 2 Sep 2025 22:21:13 +0200 Subject: [PATCH 11/20] Change how package loaders are accessed --- .../BackgroundApi.cs | 11 ++++++----- .../PEInterface.cs | 10 ++++++---- src/UniGetUI/AppOperationHelper.cs | 11 ++++++----- .../OperationWidgets/OperationControl.cs | 5 +++-- src/UniGetUI/MainWindow.xaml.cs | 5 +++-- .../Pages/DialogPages/DialogHelper_Generic.cs | 5 +++-- .../Pages/DialogPages/DialogHelper_Packages.cs | 3 ++- .../Pages/DialogPages/IgnoredUpdates.xaml.cs | 11 ++++++----- src/UniGetUI/Pages/MainView.xaml.cs | 12 ++++++------ .../ManagersPages/PackageManager.xaml.cs | 5 +++-- .../Pages/SoftwarePages/DiscoverSoftwarePage.cs | 4 ++-- .../SoftwarePages/InstalledPackagesPage.cs | 11 ++++++----- .../Pages/SoftwarePages/PackageBundlesPage.cs | 6 +++--- .../Pages/SoftwarePages/SoftwareUpdatesPage.cs | 17 +++++++++-------- 14 files changed, 64 insertions(+), 52 deletions(-) diff --git a/src/UniGetUI.Interface.BackgroundApi/BackgroundApi.cs b/src/UniGetUI.Interface.BackgroundApi/BackgroundApi.cs index 86726c67d3..c597865397 100644 --- a/src/UniGetUI.Interface.BackgroundApi/BackgroundApi.cs +++ b/src/UniGetUI.Interface.BackgroundApi/BackgroundApi.cs @@ -12,6 +12,7 @@ using UniGetUI.Interface.Enums; using UniGetUI.PackageEngine; using UniGetUI.PackageEngine.Interfaces; +using UniGetUI.PackageEngine.PackageLoader; namespace UniGetUI.Interface { @@ -128,18 +129,18 @@ private async Task WIDGETS_V1_GetUpdates(HttpContext context) return; } - if (!PEInterface.UpgradablePackagesLoader.IsLoaded && !PEInterface.UpgradablePackagesLoader.IsLoading) + if (!UpgradablePackagesLoader.Instance.IsLoaded && !UpgradablePackagesLoader.Instance.IsLoading) { - _ = PEInterface.UpgradablePackagesLoader.ReloadPackages(); + _ = UpgradablePackagesLoader.Instance.ReloadPackages(); } - while (PEInterface.UpgradablePackagesLoader.IsLoading) + while (UpgradablePackagesLoader.Instance.IsLoading) { await Task.Delay(100); } StringBuilder packages = new(); - foreach (IPackage package in PEInterface.UpgradablePackagesLoader.Packages) + foreach (IPackage package in UpgradablePackagesLoader.Instance.Packages) { if (package.Tag is PackageTag.OnQueue or PackageTag.BeingProcessed) continue; @@ -247,7 +248,7 @@ private async Task WIDGETS_V2_GetIconForPackage(HttpContext context) string iconPath = Path.Join(CoreData.UniGetUIExecutableDirectory, "Assets", "Images", "package_color.png"); - IPackage? package = PEInterface.UpgradablePackagesLoader.GetPackageForId(packageId, packageSource); + IPackage? package = UpgradablePackagesLoader.Instance.GetPackageForId(packageId, packageSource); if (package != null) { var iconUrl = await Task.Run(package.GetIconUrl); diff --git a/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs b/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs index 38d50c6cee..3538d77791 100644 --- a/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs +++ b/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs @@ -35,10 +35,12 @@ public static class PEInterface public static readonly IPackageManager[] Managers = [WinGet, Scoop, Chocolatey, Npm, Pip, Cargo, Vcpkg, DotNet, PowerShell, PowerShell7]; - public static readonly DiscoverablePackagesLoader DiscoveredPackagesLoader = new(Managers); - public static readonly UpgradablePackagesLoader UpgradablePackagesLoader = new(Managers); - public static readonly InstalledPackagesLoader InstalledPackagesLoader = new(Managers); - public static readonly PackageBundlesLoader PackageBundlesLoader = new(Managers); +#pragma warning disable CA1823 + private static readonly DiscoverablePackagesLoader DiscoveredPackagesLoader = new(Managers); + private static readonly UpgradablePackagesLoader UpgradablePackagesLoader = new(Managers); + private static readonly InstalledPackagesLoader InstalledPackagesLoader = new(Managers); + private static readonly PackageBundlesLoader PackageBundlesLoader = new(Managers); +#pragma warning restore CA1823 public static void Initialize() { diff --git a/src/UniGetUI/AppOperationHelper.cs b/src/UniGetUI/AppOperationHelper.cs index cfefa02b35..4a2ed395f8 100644 --- a/src/UniGetUI/AppOperationHelper.cs +++ b/src/UniGetUI/AppOperationHelper.cs @@ -17,6 +17,7 @@ using UniGetUI.Pages.DialogPages; using UniGetUI.Interface.Enums; using UniGetUI.PackageEngine; +using UniGetUI.PackageEngine.PackageLoader; namespace UniGetUI; @@ -229,8 +230,8 @@ public static void Install(IReadOnlyList packages, TEL_InstallReferral if (package.NewerVersionIsInstalled()) { Logger.Warn($"A newer version of {package.Id} has been detected, the update will not be performed!"); - PEInterface.UpgradablePackagesLoader.Remove(package); - foreach (var eq in PEInterface.InstalledPackagesLoader.GetEquivalentPackages(package)) + UpgradablePackagesLoader.Instance.Remove(package); + foreach (var eq in InstalledPackagesLoader.Instance.GetEquivalentPackages(package)) { // Remove upgradable tag from all installed packages eq.Tag = PackageTag.Default; } @@ -257,14 +258,14 @@ public static void Update(IReadOnlyList packages, bool? elevated = nul public static async Task UpdateAll() { - foreach (IPackage package in PEInterface.UpgradablePackagesLoader.Packages) + foreach (IPackage package in UpgradablePackagesLoader.Instance.Packages) if (package.Tag is not PackageTag.BeingProcessed and not PackageTag.OnQueue) await Update(package); } public static async Task UpdateAllForManager(string managerName) { - foreach (IPackage package in PEInterface.UpgradablePackagesLoader.Packages) + foreach (IPackage package in UpgradablePackagesLoader.Instance.Packages) { if (package.Tag is not PackageTag.OnQueue and not PackageTag.BeingProcessed && package.Manager.Name == managerName || package.Manager.DisplayName == managerName) @@ -274,7 +275,7 @@ public static async Task UpdateAllForManager(string managerName) public static async Task UpdateForId(string packageId) { - foreach (IPackage package in PEInterface.UpgradablePackagesLoader.Packages) + foreach (IPackage package in UpgradablePackagesLoader.Instance.Packages) { if (package.Id == packageId) { diff --git a/src/UniGetUI/Controls/OperationWidgets/OperationControl.cs b/src/UniGetUI/Controls/OperationWidgets/OperationControl.cs index 451333cd39..55875767b7 100644 --- a/src/UniGetUI/Controls/OperationWidgets/OperationControl.cs +++ b/src/UniGetUI/Controls/OperationWidgets/OperationControl.cs @@ -21,6 +21,7 @@ using System.Diagnostics; using UniGetUI.Interface.Telemetry; using UniGetUI.PackageEngine; +using UniGetUI.PackageEngine.PackageLoader; namespace UniGetUI.Controls.OperationWidgets; @@ -573,7 +574,7 @@ public List GetRetryOptions(Action callback) { callback(); await packageOp.Package.AddToIgnoredUpdatesAsync(packageOp.Package.VersionString); - PEInterface.UpgradablePackagesLoader.Remove(packageOp.Package); + UpgradablePackagesLoader.Instance.Remove(packageOp.Package); Close(); }; retryOptionsMenu.Add(skipThisVersion); @@ -584,7 +585,7 @@ public List GetRetryOptions(Action callback) { callback(); await packageOp.Package.AddToIgnoredUpdatesAsync(); - PEInterface.UpgradablePackagesLoader.Remove(packageOp.Package); + UpgradablePackagesLoader.Instance.Remove(packageOp.Package); Close(); }; retryOptionsMenu.Add(ignoreUpdates); diff --git a/src/UniGetUI/MainWindow.xaml.cs b/src/UniGetUI/MainWindow.xaml.cs index 8754509a3b..2117b4813f 100644 --- a/src/UniGetUI/MainWindow.xaml.cs +++ b/src/UniGetUI/MainWindow.xaml.cs @@ -27,6 +27,7 @@ using WindowExtensions = H.NotifyIcon.WindowExtensions; using System.Diagnostics; using Windows.UI.Text.Core; +using UniGetUI.PackageEngine.PackageLoader; namespace UniGetUI.Interface { @@ -430,9 +431,9 @@ public void ProcessCommandLineParameters() } NativeHelpers.SetForegroundWindow(GetWindowHandle()); - if (!PEInterface.InstalledPackagesLoader.IsLoading) + if (!InstalledPackagesLoader.Instance.IsLoading) { - _ = PEInterface.InstalledPackagesLoader.ReloadPackagesSilently(); + _ = InstalledPackagesLoader.Instance.ReloadPackagesSilently(); } (this as Window).Activate(); diff --git a/src/UniGetUI/Pages/DialogPages/DialogHelper_Generic.cs b/src/UniGetUI/Pages/DialogPages/DialogHelper_Generic.cs index e6780c97d0..80d0557e99 100644 --- a/src/UniGetUI/Pages/DialogPages/DialogHelper_Generic.cs +++ b/src/UniGetUI/Pages/DialogPages/DialogHelper_Generic.cs @@ -17,6 +17,7 @@ using UniGetUI.Interface.Enums; using UniGetUI.PackageEngine; using UniGetUI.PackageEngine.Classes.Packages.Classes; +using UniGetUI.PackageEngine.PackageLoader; namespace UniGetUI.Pages.DialogPages; @@ -366,8 +367,8 @@ public static async Task HandleBrokenWinGet() } else { - _ = PEInterface.UpgradablePackagesLoader.ReloadPackages(); - _ = PEInterface.InstalledPackagesLoader.ReloadPackages(); + _ = UpgradablePackagesLoader.Instance.ReloadPackages(); + _ = InstalledPackagesLoader.Instance.ReloadPackages(); } } catch (Exception ex) diff --git a/src/UniGetUI/Pages/DialogPages/DialogHelper_Packages.cs b/src/UniGetUI/Pages/DialogPages/DialogHelper_Packages.cs index 2adf26f969..936af460b1 100644 --- a/src/UniGetUI/Pages/DialogPages/DialogHelper_Packages.cs +++ b/src/UniGetUI/Pages/DialogPages/DialogHelper_Packages.cs @@ -16,6 +16,7 @@ using UniGetUI.PackageEngine.Enums; using UniGetUI.PackageEngine.Interfaces; using UniGetUI.PackageEngine.PackageClasses; +using UniGetUI.PackageEngine.PackageLoader; using UniGetUI.PackageEngine.Serializable; using UniGetUI.Pages.SettingsPages.GeneralPages; @@ -177,7 +178,7 @@ private static async Task GetPackageFromIdAndManager(string id, string managerNa { Window.Activate(); - var findResult = await Task.Run(() => PEInterface.DiscoveredPackagesLoader.GetPackageFromIdAndManager(id, managerName, sourceName)); + var findResult = await Task.Run(() => DiscoverablePackagesLoader.Instance.GetPackageFromIdAndManager(id, managerName, sourceName)); HideLoadingDialog(loadingId); diff --git a/src/UniGetUI/Pages/DialogPages/IgnoredUpdates.xaml.cs b/src/UniGetUI/Pages/DialogPages/IgnoredUpdates.xaml.cs index 2f5aec1dfb..65baf27936 100644 --- a/src/UniGetUI/Pages/DialogPages/IgnoredUpdates.xaml.cs +++ b/src/UniGetUI/Pages/DialogPages/IgnoredUpdates.xaml.cs @@ -7,6 +7,7 @@ using UniGetUI.PackageEngine.Classes.Packages.Classes; using UniGetUI.PackageEngine.Interfaces; using UniGetUI.PackageEngine.Managers.WingetManager; +using UniGetUI.PackageEngine.PackageLoader; // To learn more about WinUI, the WinUI project structure, // and more about our project templates, see: http://aka.ms/winui-project-info. @@ -107,9 +108,9 @@ public IgnoredPackageEntry(string id, string version, IPackageManager manager, O Version = version; } - string CurrentVersion = PEInterface.InstalledPackagesLoader.GetPackageForId(id)?.VersionString ?? "Unknown"; + string CurrentVersion = InstalledPackagesLoader.Instance.GetPackageForId(id)?.VersionString ?? "Unknown"; - if (PEInterface.UpgradablePackagesLoader.IgnoredPackages.TryGetValue(Id, out IPackage? package) + if (UpgradablePackagesLoader.Instance.IgnoredPackages.TryGetValue(Id, out IPackage? package) && package.NewVersionString != package.VersionString) { NewVersion = CurrentVersion + " \u27a4 " + package.NewVersionString; @@ -133,13 +134,13 @@ public async Task RemoveFromIgnoredUpdates() await Task.Run(() => IgnoredUpdatesDatabase.Remove(ignoredId)); // If possible, add the package to the software updates tab again - if (PEInterface.UpgradablePackagesLoader.IgnoredPackages.TryRemove(Id, out IPackage? nativePackage) + if (UpgradablePackagesLoader.Instance.IgnoredPackages.TryRemove(Id, out IPackage? nativePackage) && nativePackage.NewVersionString != nativePackage.VersionString) { - await PEInterface.UpgradablePackagesLoader.AddForeign(nativePackage); + await UpgradablePackagesLoader.Instance.AddForeign(nativePackage); } - foreach (IPackage package in PEInterface.InstalledPackagesLoader.Packages) + foreach (IPackage package in InstalledPackagesLoader.Instance.Packages) { if (Manager == package.Manager && package.Id == Id) { diff --git a/src/UniGetUI/Pages/MainView.xaml.cs b/src/UniGetUI/Pages/MainView.xaml.cs index d0ff141883..4543af9fab 100644 --- a/src/UniGetUI/Pages/MainView.xaml.cs +++ b/src/UniGetUI/Pages/MainView.xaml.cs @@ -116,9 +116,9 @@ public MainView(AutoSuggestBox mainTextBlock) */ foreach(var pair in new Dictionary { - { DiscoverNavBtn, PEInterface.DiscoveredPackagesLoader }, - { UpdatesNavBtn, PEInterface.UpgradablePackagesLoader }, - { InstalledNavBtn, PEInterface.InstalledPackagesLoader }, + { DiscoverNavBtn, DiscoverablePackagesLoader.Instance }, + { UpdatesNavBtn, UpgradablePackagesLoader.Instance }, + { InstalledNavBtn, InstalledPackagesLoader.Instance }, }) { pair.Value.FinishedLoading += (_, _) => MainApp.Dispatcher.TryEnqueue(() => pair.Key.IsLoading = false); @@ -126,12 +126,12 @@ public MainView(AutoSuggestBox mainTextBlock) pair.Key.IsLoading = pair.Value.IsLoading; } - PEInterface.UpgradablePackagesLoader.PackagesChanged += (_, _) => MainApp.Dispatcher.TryEnqueue(() => + UpgradablePackagesLoader.Instance.PackagesChanged += (_, _) => MainApp.Dispatcher.TryEnqueue(() => { - UpdatesBadge.Value = PEInterface.UpgradablePackagesLoader.Count(); + UpdatesBadge.Value = UpgradablePackagesLoader.Instance.Count(); UpdatesBadge.Visibility = UpdatesBadge.Value > 0 ? Visibility.Visible : Visibility.Collapsed; }); - UpdatesBadge.Value = PEInterface.UpgradablePackagesLoader.Count(); + UpdatesBadge.Value = UpgradablePackagesLoader.Instance.Count(); UpdatesBadge.Visibility = UpdatesBadge.Value > 0 ? Visibility.Visible : Visibility.Collapsed; BundlesPage.UnsavedChangesStateChanged += (_, _) => MainApp.Dispatcher.TryEnqueue(() => diff --git a/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml.cs b/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml.cs index 31e54d79df..f71b3d03e8 100644 --- a/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml.cs +++ b/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml.cs @@ -22,6 +22,7 @@ using UniGetUI.Pages.DialogPages; using UniGetUI.Core.SettingsEngine; using UniGetUI.Core.SettingsEngine.SecureSettings; +using UniGetUI.PackageEngine.PackageLoader; // To learn more about WinUI, the WinUI project structure, // and more about our project templates, see: http://aka.ms/winui-project-info. @@ -164,7 +165,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e) WinGet_EnableTroubleshooter.StateChanged += (_, _) => { MainApp.Instance.MainWindow.WinGetWarningBanner.IsOpen = false; - _ = PEInterface.InstalledPackagesLoader.ReloadPackages(); + _ = InstalledPackagesLoader.Instance.ReloadPackages(); }; ExtraControls.Children.Add(WinGet_EnableTroubleshooter); @@ -179,7 +180,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e) WinGet_EnableTroubleshooter_v2.StateChanged += (_, _) => { MainApp.Instance.MainWindow.WinGetWarningBanner.IsOpen = false; - _ = PEInterface.InstalledPackagesLoader.ReloadPackages(); + _ = InstalledPackagesLoader.Instance.ReloadPackages(); }; ExtraControls.Children.Add(WinGet_EnableTroubleshooter_v2); diff --git a/src/UniGetUI/Pages/SoftwarePages/DiscoverSoftwarePage.cs b/src/UniGetUI/Pages/SoftwarePages/DiscoverSoftwarePage.cs index 981a4ecfb0..bb18944e7d 100644 --- a/src/UniGetUI/Pages/SoftwarePages/DiscoverSoftwarePage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/DiscoverSoftwarePage.cs @@ -35,7 +35,7 @@ public DiscoverSoftwarePage() DisableSuggestedResultsRadio = false, PageName = "Discover", - Loader = PEInterface.DiscoveredPackagesLoader, + Loader = DiscoverablePackagesLoader.Instance, PageRole = OperationType.Install, NoPackages_BackgroundText = CoreTools.Translate("No results were found matching the input criteria"), @@ -269,7 +269,7 @@ private async Task _exportSelection_Click() { MainApp.Instance.MainWindow.NavigationPage.NavigateTo(PageType.Bundles); int loadingId = DialogHelper.ShowLoadingDialog(CoreTools.Translate("Please wait...")); - await PEInterface.PackageBundlesLoader.AddPackagesAsync(FilteredPackages.GetCheckedPackages()); + await PackageBundlesLoader.Instance.AddPackagesAsync(FilteredPackages.GetCheckedPackages()); DialogHelper.HideLoadingDialog(loadingId); } diff --git a/src/UniGetUI/Pages/SoftwarePages/InstalledPackagesPage.cs b/src/UniGetUI/Pages/SoftwarePages/InstalledPackagesPage.cs index a71b6a36ab..a2af9b56de 100644 --- a/src/UniGetUI/Pages/SoftwarePages/InstalledPackagesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/InstalledPackagesPage.cs @@ -13,6 +13,7 @@ using UniGetUI.PackageEngine.Enums; using UniGetUI.PackageEngine.Interfaces; using UniGetUI.PackageEngine.Managers.WingetManager; +using UniGetUI.PackageEngine.PackageLoader; using UniGetUI.Pages.DialogPages; using UniGetUI.Services; @@ -46,7 +47,7 @@ public InstalledPackagesPage() DisableSuggestedResultsRadio = true, PageName = "Installed", - Loader = PEInterface.InstalledPackagesLoader, + Loader = InstalledPackagesLoader.Instance, PageRole = OperationType.Uninstall, NoPackages_BackgroundText = CoreTools.Translate("No results were found matching the input criteria"), @@ -264,7 +265,7 @@ public override void GenerateToolBar() { if (!package.Source.IsVirtualManager) { - PEInterface.UpgradablePackagesLoader.Remove(package); + UpgradablePackagesLoader.Instance.Remove(package); await package.AddToIgnoredUpdatesAsync(); } } @@ -366,7 +367,7 @@ private async Task _exportSelection_Click() { MainApp.Instance.MainWindow.NavigationPage.NavigateTo(PageType.Bundles); int loadingId = DialogHelper.ShowLoadingDialog(CoreTools.Translate("Please wait...")); - await PEInterface.PackageBundlesLoader.AddPackagesAsync(FilteredPackages.GetCheckedPackages()); + await PackageBundlesLoader.Instance.AddPackagesAsync(FilteredPackages.GetCheckedPackages()); DialogHelper.HideLoadingDialog(loadingId); } @@ -374,7 +375,7 @@ public static Task GenerateBackupContents() { Logger.Debug("Starting package backup"); List packagesToExport = []; - foreach (IPackage package in PEInterface.InstalledPackagesLoader.Packages) + foreach (IPackage package in InstalledPackagesLoader.Instance.Packages) { packagesToExport.Add(package); } @@ -472,7 +473,7 @@ private async Task _menuIgnorePackage_Invoked() else { await package.AddToIgnoredUpdatesAsync(); - PEInterface.UpgradablePackagesLoader.Remove(package); + UpgradablePackagesLoader.Instance.Remove(package); } } diff --git a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs index b271708cc1..f8f724231a 100644 --- a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs @@ -62,7 +62,7 @@ public PackageBundlesPage() DisableSuggestedResultsRadio = true, PageName = "Bundles", - Loader = PEInterface.PackageBundlesLoader, + Loader = PackageBundlesLoader.Instance, PageRole = OperationType.Install, NoPackages_BackgroundText = CoreTools.Translate("Add packages or open an existing package bundle"), @@ -277,7 +277,7 @@ public override void GenerateToolBar() RemoveSelected.Click += (_, _) => { HasUnsavedChanges = true; - PEInterface.PackageBundlesLoader.RemoveRange(FilteredPackages.GetCheckedPackages()); + PackageBundlesLoader.Instance.RemoveRange(FilteredPackages.GetCheckedPackages()); }; IReadOnlyList GetCheckedNonInstalledPackages() @@ -703,7 +703,7 @@ static int Comparison(IPackage x, IPackage y) foreach (var pkg in DeserializedData.incompatible_packages) packages.Add(DeserializeIncompatiblePackage(pkg, NullSource.Instance)); - await PEInterface.PackageBundlesLoader.AddPackagesAsync(packages); + await PackageBundlesLoader.Instance.AddPackagesAsync(packages); return (DeserializedData.export_version, report); } diff --git a/src/UniGetUI/Pages/SoftwarePages/SoftwareUpdatesPage.cs b/src/UniGetUI/Pages/SoftwarePages/SoftwareUpdatesPage.cs index c274f410a7..ab9a50b6cc 100644 --- a/src/UniGetUI/Pages/SoftwarePages/SoftwareUpdatesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/SoftwareUpdatesPage.cs @@ -17,6 +17,7 @@ using UniGetUI.PackageEngine.Classes.Packages.Classes; using UniGetUI.PackageEngine.Enums; using UniGetUI.PackageEngine.Interfaces; +using UniGetUI.PackageEngine.PackageLoader; using UniGetUI.Pages.DialogPages; namespace UniGetUI.Interface.SoftwarePages @@ -41,7 +42,7 @@ public SoftwareUpdatesPage() DisableSuggestedResultsRadio = true, PageName = "Updates", - Loader = PEInterface.UpgradablePackagesLoader, + Loader = UpgradablePackagesLoader.Instance, PageRole = OperationType.Update, NoPackages_BackgroundText = CoreTools.Translate("Hooray! No updates were found."), @@ -173,7 +174,7 @@ public override BetterMenu GenerateContextMenu() if (SelectedItem != null) { SelectedItem.AddToIgnoredUpdatesAsync("<" + menuTime.GetDateFromNow()); - PEInterface.UpgradablePackagesLoader.IgnoredPackages[SelectedItem.Id] = SelectedItem; + UpgradablePackagesLoader.Instance.IgnoredPackages[SelectedItem.Id] = SelectedItem; Loader.Remove(SelectedItem); } }; @@ -311,8 +312,8 @@ public override void GenerateToolBar() foreach (IPackage package in FilteredPackages.GetCheckedPackages()) { await package.AddToIgnoredUpdatesAsync(); - PEInterface.UpgradablePackagesLoader.Remove(package); - PEInterface.UpgradablePackagesLoader.IgnoredPackages[package.Id] = package; + UpgradablePackagesLoader.Instance.Remove(package); + UpgradablePackagesLoader.Instance.IgnoredPackages[package.Id] = package; } }; @@ -512,8 +513,8 @@ private void MenuIgnorePackage_Invoked(object sender, RoutedEventArgs e) } _ = package.AddToIgnoredUpdatesAsync(); - PEInterface.UpgradablePackagesLoader.Remove(package); - PEInterface.UpgradablePackagesLoader.IgnoredPackages[package.Id] = package; + UpgradablePackagesLoader.Instance.Remove(package); + UpgradablePackagesLoader.Instance.IgnoredPackages[package.Id] = package; } private void MenuSkipVersion_Invoked(object sender, RoutedEventArgs e) @@ -525,8 +526,8 @@ private void MenuSkipVersion_Invoked(object sender, RoutedEventArgs e) } _ = package.AddToIgnoredUpdatesAsync(package.NewVersionString); - PEInterface.UpgradablePackagesLoader.Remove(package); - PEInterface.UpgradablePackagesLoader.IgnoredPackages[package.Id] = package; + UpgradablePackagesLoader.Instance.Remove(package); + UpgradablePackagesLoader.Instance.IgnoredPackages[package.Id] = package; } From 9ae9607ecd09065532b9c3d941bc03b544b5fe8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Tue, 2 Sep 2025 22:45:50 +0200 Subject: [PATCH 12/20] Change PackageLoader initialization procedure --- .../PEInterface.cs | 26 +++++++++---------- .../PackageBundlesLoader.cs | 6 ++--- src/UniGetUI/App.xaml.cs | 5 +++- .../Pages/SoftwarePages/PackageBundlesPage.cs | 1 + 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs b/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs index 3538d77791..5df649111b 100644 --- a/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs +++ b/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using UniGetUI.Core.Logging; using UniGetUI.PackageEngine.Interfaces; using UniGetUI.PackageEngine.Managers.CargoManager; @@ -35,14 +36,15 @@ public static class PEInterface public static readonly IPackageManager[] Managers = [WinGet, Scoop, Chocolatey, Npm, Pip, Cargo, Vcpkg, DotNet, PowerShell, PowerShell7]; -#pragma warning disable CA1823 - private static readonly DiscoverablePackagesLoader DiscoveredPackagesLoader = new(Managers); - private static readonly UpgradablePackagesLoader UpgradablePackagesLoader = new(Managers); - private static readonly InstalledPackagesLoader InstalledPackagesLoader = new(Managers); - private static readonly PackageBundlesLoader PackageBundlesLoader = new(Managers); -#pragma warning restore CA1823 + public static void LoadLoaders() + { + DiscoverablePackagesLoader.Instance = new DiscoverablePackagesLoader(Managers); + InstalledPackagesLoader.Instance = new InstalledPackagesLoader(Managers); + UpgradablePackagesLoader.Instance = new UpgradablePackagesLoader(Managers); + PackageBundlesLoader.Instance = new PackageBundlesLoader_I(Managers); + } - public static void Initialize() + public static void LoadManagers() { try { @@ -60,8 +62,8 @@ public static void Initialize() Logger.Warn("Timeout: Not all package managers have finished initializing."); } - _ = InstalledPackagesLoader.ReloadPackages(); - _ = UpgradablePackagesLoader.ReloadPackages(); + _ = InstalledPackagesLoader.Instance.ReloadPackages(); + _ = UpgradablePackagesLoader.Instance.ReloadPackages(); } catch (Exception ex) { @@ -71,11 +73,9 @@ public static void Initialize() } - - - public class PackageBundlesLoader : PackageBundlesLoader_A + public class PackageBundlesLoader_I : PackageBundlesLoader { - public PackageBundlesLoader(IReadOnlyList managers): base(managers) + public PackageBundlesLoader_I(IReadOnlyList managers): base(managers) { } diff --git a/src/UniGetUI.PackageEngine.PackageLoader/PackageBundlesLoader.cs b/src/UniGetUI.PackageEngine.PackageLoader/PackageBundlesLoader.cs index 1fc4ff0e3b..f1f1c84c20 100644 --- a/src/UniGetUI.PackageEngine.PackageLoader/PackageBundlesLoader.cs +++ b/src/UniGetUI.PackageEngine.PackageLoader/PackageBundlesLoader.cs @@ -3,11 +3,11 @@ namespace UniGetUI.PackageEngine.PackageLoader { - public abstract class PackageBundlesLoader_A : AbstractPackageLoader + public abstract class PackageBundlesLoader : AbstractPackageLoader { - public static PackageBundlesLoader_A Instance = null!; + public static PackageBundlesLoader Instance = null!; - public PackageBundlesLoader_A(IReadOnlyList managers) + public PackageBundlesLoader(IReadOnlyList managers) : base(managers, identifier: "PACKAGE_BUNDLES", AllowMultiplePackageVersions: true, diff --git a/src/UniGetUI/App.xaml.cs b/src/UniGetUI/App.xaml.cs index 575300f6cf..714e1f8c18 100644 --- a/src/UniGetUI/App.xaml.cs +++ b/src/UniGetUI/App.xaml.cs @@ -292,6 +292,9 @@ private async Task LoadComponentsAsync() { RegisterErrorHandling(); + // MainWindow depends on this + await Task.Run(PEInterface.LoadLoaders); + // Create MainWindow InitializeMainWindow(); await MainWindow.DoEntryTextAnimationAsync(); @@ -314,7 +317,7 @@ private async Task LoadComponentsAsync() Task.Run(RegisterNotificationService), Task.Run(LoadGSudo), Task.Run(InitializeBackgroundAPI), - Task.Run(PEInterface.Initialize), + Task.Run(PEInterface.LoadManagers), ]; // Load essential components diff --git a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs index f8f724231a..d0e40598cb 100644 --- a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs @@ -22,6 +22,7 @@ using UniGetUI.PackageEngine.Enums; using UniGetUI.PackageEngine.Interfaces; using UniGetUI.PackageEngine.PackageClasses; +using UniGetUI.PackageEngine.PackageLoader; using UniGetUI.Pages.DialogPages; namespace UniGetUI.Interface.SoftwarePages From c77abfa531c565263176c9b2afedc0484e57ce4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Tue, 2 Sep 2025 22:48:45 +0200 Subject: [PATCH 13/20] Less awful instance creation --- src/UniGetUI.Core.IconStore/IconDatabase.cs | 38 +++++++-------------- src/UniGetUI/App.xaml.cs | 13 +------ 2 files changed, 14 insertions(+), 37 deletions(-) diff --git a/src/UniGetUI.Core.IconStore/IconDatabase.cs b/src/UniGetUI.Core.IconStore/IconDatabase.cs index 4d4d270060..946f77b618 100644 --- a/src/UniGetUI.Core.IconStore/IconDatabase.cs +++ b/src/UniGetUI.Core.IconStore/IconDatabase.cs @@ -19,25 +19,11 @@ public struct IconCount public IconCount() { } } - private static IconDatabase? __instance; + private static IconDatabase? __instance; public static IconDatabase Instance { - get - { - if (__instance is null) - { - Logger.Error("IconStore.Instance was not initialized, creating an empty instance."); - InitializeInstance(); - return Instance; - } - return __instance; - } - } - - public static void InitializeInstance() - { - __instance = new(); + get => __instance ??= new(); } /// @@ -51,10 +37,12 @@ public static void InitializeInstance() /// public async Task LoadIconAndScreenshotsDatabaseAsync() { - string IconsAndScreenshotsFile = Path.Join(CoreData.UniGetUICacheDirectory_Data, "Icon Database.json"); try { - Uri DownloadUrl = new("https://github.com/marticliment/UniGetUI/raw/refs/heads/main/WebBasedData/screenshot-database-v2.json"); + string IconsAndScreenshotsFile = Path.Join(CoreData.UniGetUICacheDirectory_Data, "Icon Database.json"); + Uri DownloadUrl = + new( + "https://github.com/marticliment/UniGetUI/raw/refs/heads/main/WebBasedData/screenshot-database-v2.json"); if (Settings.Get(Settings.K.IconDataBaseURL)) { DownloadUrl = new Uri(Settings.GetValue(Settings.K.IconDataBaseURL)); @@ -69,6 +57,12 @@ public async Task LoadIconAndScreenshotsDatabaseAsync() Logger.ImportantInfo("Downloaded new icons and screenshots successfully!"); + + if (!File.Exists(IconsAndScreenshotsFile)) + { + Logger.Error("Icon Database file not found"); + return; + } } catch (Exception e) { @@ -76,12 +70,6 @@ public async Task LoadIconAndScreenshotsDatabaseAsync() Logger.Warn(e); } - if (!File.Exists(IconsAndScreenshotsFile)) - { - Logger.Error("Icon Database file not found"); - return; - } - // Update data with new cached file await LoadFromCacheAsync(); } @@ -89,9 +77,9 @@ public async Task LoadIconAndScreenshotsDatabaseAsync() public async Task LoadFromCacheAsync() { - string IconsAndScreenshotsFile = Path.Join(CoreData.UniGetUICacheDirectory_Data, "Icon Database.json"); try { + string IconsAndScreenshotsFile = Path.Join(CoreData.UniGetUICacheDirectory_Data, "Icon Database.json"); IconScreenshotDatabase_v2 JsonData = JsonSerializer.Deserialize( await File.ReadAllTextAsync(IconsAndScreenshotsFile), SerializationHelpers.DefaultOptions diff --git a/src/UniGetUI/App.xaml.cs b/src/UniGetUI/App.xaml.cs index 714e1f8c18..f9ecc69a3d 100644 --- a/src/UniGetUI/App.xaml.cs +++ b/src/UniGetUI/App.xaml.cs @@ -302,18 +302,7 @@ private async Task LoadComponentsAsync() IEnumerable iniTasks = [ Task.Run(SetUpWebViewUserDataFolder), - Task.Run(async () => - { - try - { - IconDatabase.InitializeInstance(); - await IconDatabase.Instance.LoadFromCacheAsync(); - } - catch (Exception ex) - { - Logger.Error(ex); - } - }), + Task.Run(IconDatabase.Instance.LoadFromCacheAsync), Task.Run(RegisterNotificationService), Task.Run(LoadGSudo), Task.Run(InitializeBackgroundAPI), From 059869bd76a1592421deec358512638475a0568b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Thu, 4 Sep 2025 00:27:54 +0200 Subject: [PATCH 14/20] Hot-reload package managers from settings window --- .../Controls/SettingsWidgets/CheckboxCard.cs | 4 + .../ManagersPages/PackageManager.xaml | 1 + .../ManagersPages/PackageManager.xaml.cs | 118 ++++++++++-------- 3 files changed, 74 insertions(+), 49 deletions(-) diff --git a/src/UniGetUI/Controls/SettingsWidgets/CheckboxCard.cs b/src/UniGetUI/Controls/SettingsWidgets/CheckboxCard.cs index f2356409d7..cced0f7bba 100644 --- a/src/UniGetUI/Controls/SettingsWidgets/CheckboxCard.cs +++ b/src/UniGetUI/Controls/SettingsWidgets/CheckboxCard.cs @@ -107,6 +107,7 @@ public partial class CheckboxCard_Dict : CheckboxCard public override event EventHandler? StateChanged; private Settings.K _dictName = Settings.K.Unset; + private bool _disableStateChangedEvent = false; private string _keyName = ""; public string KeyName { set @@ -114,8 +115,10 @@ public string KeyName { set _keyName = value; if (_dictName != Settings.K.Unset && _keyName.Any()) { + _disableStateChangedEvent = true; _checkbox.IsOn = Settings.GetDictionaryItem(_dictName, _keyName) ^ IS_INVERTED ^ ForceInversion; _textblock.Opacity = _checkbox.IsOn ? 1 : 0.7; + _disableStateChangedEvent = false; } } } @@ -139,6 +142,7 @@ public CheckboxCard_Dict() : base() protected override void _checkbox_Toggled(object sender, RoutedEventArgs e) { + if (_disableStateChangedEvent) return; Settings.SetDictionaryItem(_dictName, _keyName, _checkbox.IsOn ^ IS_INVERTED ^ ForceInversion); StateChanged?.Invoke(this, EventArgs.Empty); _textblock.Opacity = _checkbox.IsOn ? 1 : 0.7; diff --git a/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml b/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml index 00cedaa0fd..e2dcd7905d 100644 --- a/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml +++ b/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml @@ -25,6 +25,7 @@ x:Name="EnableManager" CornerRadius="8" DictionaryName="DisabledManagers" + StateChanged="EnableManager_OnStateChanged" FontSize="18" FontWeight="SemiBold" /> diff --git a/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml.cs b/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml.cs index f71b3d03e8..b39500514b 100644 --- a/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml.cs +++ b/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml.cs @@ -40,11 +40,11 @@ public sealed partial class PackageManagerPage : Page, ISettingsPage public event EventHandler? ReapplyProperties; public bool CanGoBack => true; public string ShortTitle => Manager is null ? "" : CoreTools.Translate("{0} settings", Manager.DisplayName); + private bool _isLoading = false; public PackageManagerPage() { this.InitializeComponent(); - EnableManager.StateChanged += (_, _) => SetManagerStatus(); } protected override void OnNavigatedTo(NavigationEventArgs e) @@ -66,11 +66,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e) ReapplyProperties?.Invoke(this, new()); - LongVersionTextBlock.Text = Manager.Status.Version + "\n"; - SetManagerStatus(false); - - LocationLabel.Text = Manager.Status.ExecutablePath + " " + Manager.Status.ExecutableCallArgs.Trim(); - if (LocationLabel.Text == "") LocationLabel.Text = CoreTools.Translate("The executable file for {0} was not found", Manager.DisplayName); + ApplyManagerState(); EnableManager.KeyName = Manager.Name; EnableManager.Text = CoreTools.Translate("Enable {pm}").Replace("{pm}", Manager.DisplayName); InstallOptionsTitle.Text = CoreTools.Translate("Default installation options for {0} packages", Manager.DisplayName); @@ -92,21 +88,6 @@ protected override void OnNavigatedTo(NavigationEventArgs e) ExeFileWarningText.Visibility = SecureSettings.Get(SecureSettings.K.AllowCustomManagerPaths) ? Visibility.Collapsed : Visibility.Visible; GoToSecureSettingsBtn.Visibility = SecureSettings.Get(SecureSettings.K.AllowCustomManagerPaths) ? Visibility.Collapsed : Visibility.Visible; ExecutableComboBox.IsEnabled = SecureSettings.Get(SecureSettings.K.AllowCustomManagerPaths); - ExecutableComboBox.Items.Clear(); - foreach(var path in Manager.FindCandidateExecutableFiles()) - { - ExecutableComboBox.Items.Add(path); - } - - string selectedValue = Settings.GetDictionaryItem(Settings.K.ManagerPaths, Manager.Name) ?? ""; - if (string.IsNullOrEmpty(selectedValue)) - { - var exe = Manager.GetExecutableFile(); - selectedValue = exe.Item1? exe.Item2: ""; - } - - ExecutableComboBox.SelectedValue = selectedValue; - ExecutableComboBox.SelectionChanged += ExecutableComboBox_SelectionChanged; InstallOptionsPanel.Description = new InstallOptions_Manager(Manager); @@ -153,7 +134,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e) CornerRadius = new CornerRadius(0), BorderThickness = new Thickness(1, 0, 1, 0), }; - WinGet_UseBundled.StateChanged += (_, _) => RestartRequired?.Invoke(this, new()); + WinGet_UseBundled.StateChanged += (_, _) => _ = ReloadPackageManager(); ExtraControls.Children.Add(WinGet_UseBundled); CheckboxCard WinGet_EnableTroubleshooter = new() @@ -269,7 +250,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e) SettingName = Settings.K.UseSystemChocolatey, CornerRadius = new CornerRadius(0, 0, 8, 8) }; - Chocolatey_SystemChoco.StateChanged += (_, _) => RestartRequired?.Invoke(this, new()); + Chocolatey_SystemChoco.StateChanged += (_, _) => _ = ReloadPackageManager(); ExtraControls.Children.Add(Chocolatey_SystemChoco); } @@ -346,7 +327,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e) p.Children.Add(ResetVcPkgRootLabel); p.Children.Add(OpenVcPkgRootLabel); Vcpkg_CustomVcpkgRoot.Description = p; - Vcpkg_CustomVcpkgRoot.Click += (_, _) => RestartRequired?.Invoke(this, new()); + Vcpkg_CustomVcpkgRoot.Click += (_, _) => _ = ReloadPackageManager(); ExtraControls.Children.Add(Vcpkg_CustomVcpkgRoot); } @@ -372,28 +353,62 @@ protected override void OnNavigatedTo(NavigationEventArgs e) base.OnNavigatedTo(e); } - private void ShowVersionHyperlink_Click(object sender, RoutedEventArgs e) - => SetManagerStatus(true); + private void ShowVersionHyperlink_Click(object sender, RoutedEventArgs e) => ApplyManagerState(true); - void SetManagerStatus(bool ShowVersion = false) + void ApplyManagerState(bool ShowVersion = false) { if (Manager is null) throw new InvalidDataException(); + // Load version and manager path ShowVersionHyperlink.Visibility = Visibility.Collapsed; LongVersionTextBlock.Visibility = Visibility.Collapsed; - if (Manager.IsEnabled() && Manager.Status.Found) + LongVersionTextBlock.Text = Manager.Status.Version + "\n"; + LocationLabel.Text = Manager.Status.ExecutablePath + " " + Manager.Status.ExecutableCallArgs.Trim(); + if (Manager.Status.ExecutablePath == "") LocationLabel.Text = CoreTools.Translate("The executable file for {0} was not found", Manager.DisplayName); + + // Load executable selection + ExecutableComboBox.SelectionChanged -= ExecutableComboBox_SelectionChanged; + ExecutableComboBox.Items.Clear(); + foreach(var path in Manager.FindCandidateExecutableFiles()) + { + ExecutableComboBox.Items.Add(path); + } + string selectedValue = Settings.GetDictionaryItem(Settings.K.ManagerPaths, Manager.Name) ?? ""; + if (string.IsNullOrEmpty(selectedValue)) + { + var exe = Manager.GetExecutableFile(); + selectedValue = exe.Item1? exe.Item2: ""; + } + + ExecutableComboBox.SelectedValue = selectedValue; + ExecutableComboBox.SelectionChanged += ExecutableComboBox_SelectionChanged; + + + // Load version block text and style + if (_isLoading) + { + ManagerStatusBar.Severity = InfoBarSeverity.Informational; + ManagerStatusBar.Title = CoreTools.Translate("Please wait..."); + ManagerStatusBar.Message = ""; + } + else if (!Manager.IsEnabled()) + { + ManagerStatusBar.Severity = InfoBarSeverity.Warning; + ManagerStatusBar.Title = CoreTools.Translate("{pm} is disabled").Replace("{pm}", Manager.DisplayName); + ManagerStatusBar.Message = CoreTools.Translate("Enable it to install packages from {pm}.").Replace("{pm}", Manager.DisplayName); + } + else if (Manager.Status.Found) { ManagerStatusBar.Severity = InfoBarSeverity.Success; - ManagerStatusBar.Title = CoreTools.Translate("{pm} is enabled and ready to go", new Dictionary { { "pm", Manager.DisplayName } }); + ManagerStatusBar.Title = CoreTools.Translate("{pm} is enabled and ready to go").Replace("{pm}", Manager.DisplayName); if (!Manager.Status.Version.Contains('\n')) { - ManagerStatusBar.Message = - CoreTools.Translate("{pm} version:", new Dictionary { { "pm", Manager.DisplayName } }) + $" {Manager.Status.Version}"; + ManagerStatusBar.Message = CoreTools.Translate( + "{pm} version:").Replace("{pm}", Manager.DisplayName) + $" {Manager.Status.Version}"; } else if (ShowVersion) { - ManagerStatusBar.Message = CoreTools.Translate("{pm} version:", - new Dictionary { { "pm", Manager.DisplayName } }); + ManagerStatusBar.Message = CoreTools.Translate("{pm} version:").Replace("{pm}", Manager.DisplayName); LongVersionTextBlock.Visibility = Visibility.Visible; } else @@ -402,22 +417,12 @@ void SetManagerStatus(bool ShowVersion = false) ShowVersionHyperlink.Visibility = Visibility.Visible; } } - else if (Manager.IsEnabled() && !Manager.Status.Found) + else // manager was not found { ManagerStatusBar.Severity = InfoBarSeverity.Error; - ManagerStatusBar.Title = CoreTools.Translate("{pm} was not found!", - new Dictionary { { "pm", Manager.DisplayName } }); - ManagerStatusBar.Message = CoreTools.Translate( - "You may need to install {pm} in order to use it with WingetUI.", - new Dictionary { { "pm", Manager.DisplayName } }); - } - else if (!Manager.IsEnabled()) - { - ManagerStatusBar.Severity = InfoBarSeverity.Informational; - ManagerStatusBar.Title = CoreTools.Translate("{pm} is disabled", - new Dictionary { { "pm", Manager.DisplayName } }); - ManagerStatusBar.Message = CoreTools.Translate("Enable it to install packages from {pm}.", - new Dictionary { { "pm", Manager.DisplayName } }); + ManagerStatusBar.Title = CoreTools.Translate("{pm} was not found!").Replace("{pm}", Manager.DisplayName); + ManagerStatusBar.Message = CoreTools.Translate("You may need to install {pm} in order to use it with WingetUI.") + .Replace("{pm}", Manager.DisplayName); } } @@ -432,7 +437,7 @@ private async Task _managerPath_Click() private void ManagerLogs_Click(object sender, RoutedEventArgs e) { - MainApp.Instance.MainWindow.NavigationPage.OpenManagerLogs(Manager as IPackageManager); + MainApp.Instance.MainWindow.NavigationPage.OpenManagerLogs(Manager); } private void ExecutableComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) @@ -441,12 +446,27 @@ private void ExecutableComboBox_SelectionChanged(object sender, SelectionChanged return; Settings.SetDictionaryItem(Settings.K.ManagerPaths, Manager!.Name, ExecutableComboBox.SelectedValue.ToString()); - RestartRequired?.Invoke(this, EventArgs.Empty); + _ = ReloadPackageManager(); } private void GoToSecureSettingsBtn_Click(object sender, RoutedEventArgs e) { MainApp.Instance.MainWindow.NavigationPage.OpenSettingsPage(typeof(Administrator)); } + + private void EnableManager_OnStateChanged(object? sender, EventArgs e) + => _ = ReloadPackageManager(); + + private async Task ReloadPackageManager() + { + if (Manager is null) return; + int loadingId = DialogHelper.ShowLoadingDialog(CoreTools.Translate("Please wait...")); + _isLoading = true; + ApplyManagerState(); + await Task.Run(Manager.Initialize); + _isLoading = false; + ApplyManagerState(); + DialogHelper.HideLoadingDialog(loadingId); + } } } From 01d6a7fdabd7aaf0cd1c21086d021bd7844aed3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Thu, 4 Sep 2025 00:34:00 +0200 Subject: [PATCH 15/20] allow hot-reloading from package managers homepage --- .../ManagersPages/ManagersHomepage.xaml.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/UniGetUI/Pages/SettingsPages/ManagersPages/ManagersHomepage.xaml.cs b/src/UniGetUI/Pages/SettingsPages/ManagersPages/ManagersHomepage.xaml.cs index 334fa4c2b3..ff68d6851f 100644 --- a/src/UniGetUI/Pages/SettingsPages/ManagersPages/ManagersHomepage.xaml.cs +++ b/src/UniGetUI/Pages/SettingsPages/ManagersPages/ManagersHomepage.xaml.cs @@ -6,6 +6,7 @@ using UniGetUI.Pages.SettingsPages.GeneralPages; using UniGetUI.PackageEngine; using UniGetUI.Core.SettingsEngine; +using UniGetUI.Pages.DialogPages; // To learn more about WinUI, the WinUI project structure, // and more about our project templates, see: http://aka.ms/winui-project-info. @@ -26,6 +27,7 @@ public sealed partial class ManagersHomepage : Page, ISettingsPage private List managerControls = new(); + private bool _isLoadingToggles = false; public ManagersHomepage() { this.InitializeComponent(); @@ -44,7 +46,16 @@ public ManagersHomepage() button.Click += (_, _) => NavigationRequested?.Invoke(this, manager.GetType()); var toggle = new ToggleSwitch(); - toggle.Toggled += (_, _) => Settings.SetDictionaryItem(Settings.K.DisabledManagers, manager.Name, !toggle.IsOn); + toggle.Toggled += async (_, _) => + { + if (_isLoadingToggles) return; + + bool disabled = !toggle.IsOn; + int loadingId = DialogHelper.ShowLoadingDialog(CoreTools.Translate("Please wait...")); + Settings.SetDictionaryItem(Settings.K.DisabledManagers, manager.Name, disabled); + await Task.Run(manager.Initialize); + DialogHelper.HideLoadingDialog(loadingId); + }; button.Content = toggle; first = false; @@ -57,12 +68,13 @@ public ManagersHomepage() protected override void OnNavigatedTo(NavigationEventArgs e) { + _isLoadingToggles = true; for(int i = 0; i < managerControls.Count; i++) { var toggle = (ToggleSwitch)managerControls[i].Content; toggle.IsOn = !Settings.GetDictionaryItem(Settings.K.DisabledManagers, PEInterface.Managers[i].Name); } - + _isLoadingToggles = false; base.OnNavigatedTo(e); } From cc92a7d23e93f8b859683fd0e410e79b7d221dbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Thu, 4 Sep 2025 00:38:45 +0200 Subject: [PATCH 16/20] Remove experimental winget toggles from settings, add missing translatable strings --- src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs | 2 +- .../Pages/SettingsPages/GeneralPages/Updates.xaml | 4 ++-- .../Pages/SettingsPages/ManagersPages/PackageManager.xaml | 4 ++-- .../SettingsPages/ManagersPages/PackageManager.xaml.cs | 8 ++++---- src/UniGetUI/Pages/SoftwarePages/InstalledPackagesPage.cs | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs index 94e53971ef..46addc2523 100644 --- a/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs +++ b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs @@ -287,7 +287,7 @@ public override void AttemptFastRepair() private static void TryRepairTempFolderPermissions() { - if (Settings.Get(Settings.K.DisableNewWinGetTroubleshooter)) return; + // if (Settings.Get(Settings.K.DisableNewWinGetTroubleshooter)) return; try { diff --git a/src/UniGetUI/Pages/SettingsPages/GeneralPages/Updates.xaml b/src/UniGetUI/Pages/SettingsPages/GeneralPages/Updates.xaml index ef683a930d..f5a0f2f870 100644 --- a/src/UniGetUI/Pages/SettingsPages/GeneralPages/Updates.xaml +++ b/src/UniGetUI/Pages/SettingsPages/GeneralPages/Updates.xaml @@ -20,7 +20,7 @@ HorizontalContentAlignment="Center" VerticalContentAlignment="Center"> - @@ -40,7 +40,7 @@ Text="Check for updates every:" ValueChanged="ShowRestartBanner" /> - diff --git a/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml b/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml index e2dcd7905d..2fa822d0ad 100644 --- a/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml +++ b/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml @@ -61,7 +61,7 @@ ContentAlignment="Vertical" CornerRadius="0,0,0,0"> - + @@ -128,7 +128,7 @@ Symbol="Copy" /> - _ = ReloadPackageManager(); ExtraControls.Children.Add(WinGet_UseBundled); - CheckboxCard WinGet_EnableTroubleshooter = new() + /*CheckboxCard WinGet_EnableTroubleshooter = new() { Text = CoreTools.Translate("Enable the automatic WinGet troubleshooter"), SettingName = Settings.K.DisableWinGetMalfunctionDetector, @@ -163,7 +163,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e) MainApp.Instance.MainWindow.WinGetWarningBanner.IsOpen = false; _ = InstalledPackagesLoader.Instance.ReloadPackages(); }; - ExtraControls.Children.Add(WinGet_EnableTroubleshooter_v2); + ExtraControls.Children.Add(WinGet_EnableTroubleshooter_v2);*/ /*CheckboxCard WinGet_HideNonApplicableUpdates = new() { diff --git a/src/UniGetUI/Pages/SoftwarePages/InstalledPackagesPage.cs b/src/UniGetUI/Pages/SoftwarePages/InstalledPackagesPage.cs index a2af9b56de..a3df50ffd8 100644 --- a/src/UniGetUI/Pages/SoftwarePages/InstalledPackagesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/InstalledPackagesPage.cs @@ -298,7 +298,7 @@ protected override void WhenPackagesLoaded(ReloadReason reason) } } - if (WinGet.NO_PACKAGES_HAVE_BEEN_LOADED && !Settings.Get(Settings.K.DisableWinGetMalfunctionDetector)) + if (WinGet.NO_PACKAGES_HAVE_BEEN_LOADED/* && !Settings.Get(Settings.K.DisableWinGetMalfunctionDetector)*/) { var infoBar = MainApp.Instance.MainWindow.WinGetWarningBanner; infoBar.IsOpen = true; From 20c1ad2ca3c8e901ed593a209101852d0e6286d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Thu, 4 Sep 2025 00:44:24 +0200 Subject: [PATCH 17/20] fix runtime crash due to invalid styles --- .../Pages/SettingsPages/GeneralPages/Updates.xaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/UniGetUI/Pages/SettingsPages/GeneralPages/Updates.xaml b/src/UniGetUI/Pages/SettingsPages/GeneralPages/Updates.xaml index f5a0f2f870..6f46e0eca0 100644 --- a/src/UniGetUI/Pages/SettingsPages/GeneralPages/Updates.xaml +++ b/src/UniGetUI/Pages/SettingsPages/GeneralPages/Updates.xaml @@ -21,8 +21,8 @@ VerticalContentAlignment="Center"> Date: Fri, 5 Sep 2025 01:09:02 +0200 Subject: [PATCH 18/20] Add new status badges to Package Managers page --- .../ManagersPages/ManagersHomepage.xaml.cs | 65 ++++++++++++++++++- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/src/UniGetUI/Pages/SettingsPages/ManagersPages/ManagersHomepage.xaml.cs b/src/UniGetUI/Pages/SettingsPages/ManagersPages/ManagersHomepage.xaml.cs index ff68d6851f..1984cd20c1 100644 --- a/src/UniGetUI/Pages/SettingsPages/ManagersPages/ManagersHomepage.xaml.cs +++ b/src/UniGetUI/Pages/SettingsPages/ManagersPages/ManagersHomepage.xaml.cs @@ -1,5 +1,7 @@ +using Windows.UI.Text; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Media; using Microsoft.UI.Xaml.Navigation; using UniGetUI.Core.Tools; using UniGetUI.Interface.Widgets; @@ -7,6 +9,7 @@ using UniGetUI.PackageEngine; using UniGetUI.Core.SettingsEngine; using UniGetUI.Pages.DialogPages; +using CommunityToolkit.WinUI; // To learn more about WinUI, the WinUI project structure, // and more about our project templates, see: http://aka.ms/winui-project-info. @@ -40,12 +43,54 @@ public ManagersHomepage() Text = manager.DisplayName, Description = manager.Properties.Description.Split("
")[0], HeaderIcon = new LocalIcon(manager.Properties.IconId), + Padding = new Thickness(16, 2, 16, 2) }; button.CornerRadius = first ? new CornerRadius(8, 8, 0, 0) : new CornerRadius(0); button.BorderThickness = first ? new Thickness(1) : new Thickness(1,0,1,1); button.Click += (_, _) => NavigationRequested?.Invoke(this, manager.GetType()); - var toggle = new ToggleSwitch(); + var statusIcon = new FontIcon() { FontSize = 12, VerticalAlignment = VerticalAlignment.Center }; + var statusText = new TextBlock() { FontSize = 12, FontWeight = new FontWeight(600), VerticalAlignment = VerticalAlignment.Center }; + var statusBorder = new Border() + { + CornerRadius = new CornerRadius(4), + Padding = new Thickness(6, 3, 6, 3) + }; + + void loadStatusBadge() + { + if (!manager.IsEnabled()) + { + statusText.Text = CoreTools.Translate("Disabled"); + statusIcon.Glyph = "\uE814"; + statusIcon.Foreground = (Brush)Application.Current.Resources["SystemFillColorCautionBrush"]; + statusBorder.Background = (Brush)Application.Current.Resources["SystemFillColorCautionBackgroundBrush"]; + } + else if (manager.Status.Found) + { + statusText.Text = CoreTools.Translate("Ready"); + statusIcon.Glyph = "\uEC61"; + statusIcon.Foreground = (Brush)Application.Current.Resources["SystemFillColorSuccessBrush"]; + statusBorder.Background = (Brush)Application.Current.Resources["SystemFillColorSuccessBackgroundBrush"]; + } + else + { + statusText.Text = CoreTools.Translate("Not found"); + statusIcon.Glyph = "\uEB90"; + statusIcon.Foreground = (Brush)Application.Current.Resources["SystemFillColorCriticalBrush"]; + statusBorder.Background = (Brush)Application.Current.Resources["SystemFillColorCriticalBackgroundBrush"]; + } + } + + loadStatusBadge(); + var toggle = new ToggleSwitch() + { + Height = 22, + OnContent = "", + HorizontalAlignment = HorizontalAlignment.Right, + OffContent = "", + Margin = new Thickness(-10, 0, 0, 0), + }; toggle.Toggled += async (_, _) => { if (_isLoadingToggles) return; @@ -54,9 +99,23 @@ public ManagersHomepage() int loadingId = DialogHelper.ShowLoadingDialog(CoreTools.Translate("Please wait...")); Settings.SetDictionaryItem(Settings.K.DisabledManagers, manager.Name, disabled); await Task.Run(manager.Initialize); + loadStatusBadge(); DialogHelper.HideLoadingDialog(loadingId); }; - button.Content = toggle; + + var status = new StackPanel() + { + Orientation = Orientation.Horizontal, + Spacing = 4, HorizontalAlignment = HorizontalAlignment.Center, + Children = { statusIcon, statusText } + }; + statusBorder.Child = status; + button.Content = new StackPanel() + { + Orientation = Orientation.Vertical, + Spacing = 4, + Children = { toggle, statusBorder } + }; first = false; SettingsEntries.Children.Add(button); @@ -71,7 +130,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e) _isLoadingToggles = true; for(int i = 0; i < managerControls.Count; i++) { - var toggle = (ToggleSwitch)managerControls[i].Content; + var toggle = (ToggleSwitch)((StackPanel)managerControls[i].Content).Children.First(); toggle.IsOn = !Settings.GetDictionaryItem(Settings.K.DisabledManagers, PEInterface.Managers[i].Name); } _isLoadingToggles = false; From e22f81625012256e8705554fbcf1af54551aff27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Fri, 5 Sep 2025 01:13:38 +0200 Subject: [PATCH 19/20] minor tweaks to PackageManagers settings page --- .../SettingsPages/ManagersPages/PackageManager.xaml | 9 ++++++--- .../ManagersPages/PackageManager.xaml.cs | 12 ++++++++++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml b/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml index 2fa822d0ad..8533ae8743 100644 --- a/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml +++ b/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml @@ -25,9 +25,9 @@ x:Name="EnableManager" CornerRadius="8" DictionaryName="DisabledManagers" - StateChanged="EnableManager_OnStateChanged" FontSize="18" - FontWeight="SemiBold" /> + FontWeight="SemiBold" + StateChanged="EnableManager_OnStateChanged" />
- + diff --git a/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml.cs b/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml.cs index 2bc7551523..e4cec83712 100644 --- a/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml.cs +++ b/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml.cs @@ -90,6 +90,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e) ExecutableComboBox.IsEnabled = SecureSettings.Get(SecureSettings.K.AllowCustomManagerPaths); InstallOptionsPanel.Description = new InstallOptions_Manager(Manager); + InstallOptionsPanel.Padding = new(18, 24, 18, 24); // ----------------------- SOURCES CONTROL ------------------- @@ -99,13 +100,20 @@ protected override void OnNavigatedTo(NavigationEventArgs e) { SettingsCard SourceManagerCard = new() { - Resources = { ["SettingsCardLeftIndention"] = 10 }, CornerRadius = new CornerRadius(8), - Margin = new Thickness(0, 0, 0, 16) + Margin = new Thickness(0, 0, 0, 16), + Padding = new(24, 24, 0, 24), }; var man = new SourceManager(Manager); SourceManagerCard.Description = man; ExtraControls.Children.Add(SourceManagerCard); + + ExtraControls.Children.Add(new TextBlock() + { + Margin = new(4, 24, 4, 8), + FontWeight = new Windows.UI.Text.FontWeight(600), + Text=CoreTools.Translate("Advanced options") + }); } // ------------------------- WINGET EXTRA SETTINGS ----------------------- From 2f6675ff69f508cc212a5baddb657de5c1085db2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Fri, 5 Sep 2025 01:17:24 +0200 Subject: [PATCH 20/20] fix UI update bug --- .../Pages/SettingsPages/ManagersPages/ManagersHomepage.xaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/UniGetUI/Pages/SettingsPages/ManagersPages/ManagersHomepage.xaml.cs b/src/UniGetUI/Pages/SettingsPages/ManagersPages/ManagersHomepage.xaml.cs index 1984cd20c1..0fa7a5e54d 100644 --- a/src/UniGetUI/Pages/SettingsPages/ManagersPages/ManagersHomepage.xaml.cs +++ b/src/UniGetUI/Pages/SettingsPages/ManagersPages/ManagersHomepage.xaml.cs @@ -82,7 +82,6 @@ void loadStatusBadge() } } - loadStatusBadge(); var toggle = new ToggleSwitch() { Height = 22, @@ -91,6 +90,7 @@ void loadStatusBadge() OffContent = "", Margin = new Thickness(-10, 0, 0, 0), }; + toggle.Loaded += (_, _) => loadStatusBadge(); toggle.Toggled += async (_, _) => { if (_isLoadingToggles) return;