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.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.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.Managers.Cargo/Cargo.cs b/src/UniGetUI.PackageEngine.Managers.Cargo/Cargo.cs index 07c43c3c4d..bc5db70d04 100644 --- a/src/UniGetUI.PackageEngine.Managers.Cargo/Cargo.cs +++ b/src/UniGetUI.PackageEngine.Managers.Cargo/Cargo.cs @@ -138,30 +138,23 @@ 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); } private IReadOnlyList GetPackages(LoggableTaskType taskType) 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; } } } diff --git a/src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs b/src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs index fd5ef25d2f..9180fbf470 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,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.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.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(); diff --git a/src/UniGetUI.PackageEngine.Managers.Vcpkg/Vcpkg.cs b/src/UniGetUI.PackageEngine.Managers.Vcpkg/Vcpkg.cs index 07bef3111a..93131fab84 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 = [ @@ -302,45 +300,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."), - }; - } - 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"), - }; - } + 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; - 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 +333,28 @@ 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}\""; + version = process.StandardOutput.ReadLine()?.Trim() ?? ""; + version += $"\n%VCPKG_ROOT% = {rootPath}"; + } - return status; + 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, p2); + p2.Start(); + p2.WaitForExit(); + processLogger2.Close(p2.ExitCode); } public override void RefreshPackageIndexes() @@ -394,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() diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs index 528fa4ae7d..46addc2523 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 { @@ -299,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.PackageEngine.PackageEngine/PEInterface.cs b/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs index 0c8417176d..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,12 +36,15 @@ 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); + 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 { @@ -51,23 +55,15 @@ 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."); } - _ = InstalledPackagesLoader.ReloadPackages(); - _ = UpgradablePackagesLoader.ReloadPackages(); + _ = InstalledPackagesLoader.Instance.ReloadPackages(); + _ = UpgradablePackagesLoader.Instance.ReloadPackages(); } catch (Exception ex) { @@ -77,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.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..36c8a0cbe7 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,63 @@ 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 virtual void _performExtraLoadingSteps() { } + + public virtual void Initialize() + { + try + { + _ready = false; + _ensurePropertlyConstructed(); + + if (!IsEnabled()) + { // Do NOT initialise disabled package managers + Status = new() { Version = CoreTools.Translate("{0} is disabled", DisplayName) }; + Logger.ImportantInfo($"{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.Error($"{Name} is enabled but was not found on the system!"); + return; + } + + Logger.ImportantInfo($"{Name} is enabled and was found on {path}"); + + // Load manager version + _loadManagerVersion(out string version); + Status.Version = version; + _logManagerInfo(); + + // Finish initialization + _performExtraLoadingSteps(); + _ready = true; + _initializeSources(); + } + 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 +110,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 + if (Capabilities.SupportsCustomSources) { - 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) - { - 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 +202,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 +215,7 @@ public bool IsEnabled() /// public bool IsReady() { - return IsEnabled() && Status.Found; + return _ready && IsEnabled() && Status.Found; } /// diff --git a/src/UniGetUI/App.xaml.cs b/src/UniGetUI/App.xaml.cs index 5df8f7d9e9..33540ce2b7 100644 --- a/src/UniGetUI/App.xaml.cs +++ b/src/UniGetUI/App.xaml.cs @@ -294,6 +294,9 @@ private async Task LoadComponentsAsync() { RegisterErrorHandling(); + // MainWindow depends on this + await Task.Run(PEInterface.LoadLoaders); + // Create MainWindow InitializeMainWindow(); await MainWindow.DoEntryTextAnimationAsync(); @@ -301,22 +304,11 @@ 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), - Task.Run(PEInterface.Initialize), + Task.Run(PEInterface.LoadManagers), ]; // Load essential components 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/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/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/GeneralPages/Updates.xaml b/src/UniGetUI/Pages/SettingsPages/GeneralPages/Updates.xaml index ef683a930d..6f46e0eca0 100644 --- a/src/UniGetUI/Pages/SettingsPages/GeneralPages/Updates.xaml +++ b/src/UniGetUI/Pages/SettingsPages/GeneralPages/Updates.xaml @@ -20,9 +20,9 @@ HorizontalContentAlignment="Center" VerticalContentAlignment="Center"> - - managerControls = new(); + private bool _isLoadingToggles = false; public ManagersHomepage() { this.InitializeComponent(); @@ -38,14 +43,79 @@ 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(); - toggle.Toggled += (_, _) => Settings.SetDictionaryItem(Settings.K.DisabledManagers, manager.Name, !toggle.IsOn); - button.Content = toggle; + 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"]; + } + } + + var toggle = new ToggleSwitch() + { + Height = 22, + OnContent = "", + HorizontalAlignment = HorizontalAlignment.Right, + OffContent = "", + Margin = new Thickness(-10, 0, 0, 0), + }; + toggle.Loaded += (_, _) => loadStatusBadge(); + 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); + loadStatusBadge(); + DialogHelper.HideLoadingDialog(loadingId); + }; + + 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); @@ -57,12 +127,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; + var toggle = (ToggleSwitch)((StackPanel)managerControls[i].Content).Children.First(); toggle.IsOn = !Settings.GetDictionaryItem(Settings.K.DisabledManagers, PEInterface.Managers[i].Name); } - + _isLoadingToggles = false; base.OnNavigatedTo(e); } diff --git a/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml b/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml index 00cedaa0fd..8533ae8743 100644 --- a/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml +++ b/src/UniGetUI/Pages/SettingsPages/ManagersPages/PackageManager.xaml @@ -26,7 +26,8 @@ CornerRadius="8" DictionaryName="DisabledManagers" FontSize="18" - FontWeight="SemiBold" /> + FontWeight="SemiBold" + StateChanged="EnableManager_OnStateChanged" /> - + - + @@ -127,7 +131,7 @@ Symbol="Copy" /> - 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) @@ -65,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); @@ -91,23 +88,9 @@ 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); + InstallOptionsPanel.Padding = new(18, 24, 18, 24); // ----------------------- SOURCES CONTROL ------------------- @@ -117,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 ----------------------- @@ -149,13 +139,13 @@ protected override void OnNavigatedTo(NavigationEventArgs e) Text = $"{CoreTools.Translate("Use bundled WinGet instead of system WinGet")} ({CoreTools.Translate("This may help if WinGet packages are not shown")})", SettingName = Settings.K.ForceLegacyBundledWinGet, - CornerRadius = new CornerRadius(0), - BorderThickness = new Thickness(1, 0, 1, 0), + CornerRadius = new CornerRadius(0, 0, 8, 8), + BorderThickness = new Thickness(1, 0, 1, 1), }; - WinGet_UseBundled.StateChanged += (_, _) => RestartRequired?.Invoke(this, new()); + WinGet_UseBundled.StateChanged += (_, _) => _ = 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, @@ -164,7 +154,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,9 +169,9 @@ 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); + ExtraControls.Children.Add(WinGet_EnableTroubleshooter_v2);*/ /*CheckboxCard WinGet_HideNonApplicableUpdates = new() { @@ -268,7 +258,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); } @@ -345,7 +335,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); } @@ -371,28 +361,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 @@ -401,22 +425,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); } } @@ -431,7 +445,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) @@ -440,12 +454,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); + } } } 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..a3df50ffd8 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(); } } @@ -297,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; @@ -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..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 @@ -62,7 +63,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 +278,7 @@ public override void GenerateToolBar() RemoveSelected.Click += (_, _) => { HasUnsavedChanges = true; - PEInterface.PackageBundlesLoader.RemoveRange(FilteredPackages.GetCheckedPackages()); + PackageBundlesLoader.Instance.RemoveRange(FilteredPackages.GetCheckedPackages()); }; IReadOnlyList GetCheckedNonInstalledPackages() @@ -703,7 +704,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; }