Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decouple loading and "holding" packages from the UI - Creation of PackageLoaders #2328

Merged
merged 22 commits into from
Jun 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b26a453
Create a base PackageLoader
marticliment Jun 19, 2024
089475e
Disable a test that randomly fails
marticliment Jun 19, 2024
6f25eb5
add base new loaders
marticliment Jun 19, 2024
92153f7
Merge branch 'main' into decouple-ui-from-package-loaders
marticliment Jun 19, 2024
2eb8163
PackageManagers and Packages are initialized and handled by a new cla…
marticliment Jun 20, 2024
ed32777
Remove intermediate PaackagesPage.Packages attribute and use Paackage…
marticliment Jun 20, 2024
cb4412c
Update BackgroundApi.cs
marticliment Jun 20, 2024
5cbcf1f
Simplify package cache structure
marticliment Jun 20, 2024
6e686c8
Better naming
marticliment Jun 20, 2024
e4b6d3d
Decouple the background API from the main interface
marticliment Jun 20, 2024
2247f64
Simplify creation of PackagesPages, move building method to the const…
marticliment Jun 21, 2024
e84d124
Forgot to use overloaded method
marticliment Jun 21, 2024
b642ce5
Allow aborting a package load
marticliment Jun 21, 2024
7217dea
New AppSdk version uses more memory
marticliment Jun 21, 2024
962b95b
Prevent assigning to attributes that shouldn't be touched
marticliment Jun 21, 2024
a44ca43
Handle OnNavigatedFrom event on the AbstractPackagesPage
marticliment Jun 21, 2024
d87038b
call base method
marticliment Jun 21, 2024
3fe8bb1
Move ConfirmUninstallation method to MainWindow
marticliment Jun 22, 2024
279b481
Improvements
marticliment Jun 22, 2024
baf6714
Fix type
marticliment Jun 22, 2024
ad3324e
Allow UpgradablePackagesLoader to handle the autoupdate check (fix #1…
marticliment Jun 22, 2024
6ba6c24
Improvements
marticliment Jun 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using Nancy;
using Nancy.Hosting.Self;
using System.Text;
using UniGetUI.Core.Data;
using UniGetUI.Core.Logging;
using UniGetUI.Core.SettingsEngine;
using UniGetUI.Core.Tools;
using UniGetUI.Interface.Enums;
using UniGetUI.PackageEngine;
using UniGetUI.PackageEngine.PackageClasses;

namespace UniGetUI.Interface
Expand All @@ -16,9 +18,24 @@ internal static class ApiTokenHolder

public class BackgroundApiRunner
{
public event EventHandler<EventArgs>? OnOpenWindow;
public event EventHandler<EventArgs>? OnOpenUpdatesPage;
public event EventHandler<KeyValuePair<string, string>>? OnShowSharedPackage;
public event EventHandler<EventArgs>? OnUpgradeAll;
public event EventHandler<string>? OnUpgradeAllForManager;
public event EventHandler<string>? OnUpgradePackage;

private bool __running = false;

public BackgroundApiRunner() {
BackgroundApi.OnOpenWindow += (s, e) => OnOpenWindow?.Invoke(s, e);
BackgroundApi.OnOpenUpdatesPage += (s, e) => OnOpenUpdatesPage?.Invoke(s, e);
BackgroundApi.OnShowSharedPackage += (s, e) => OnShowSharedPackage?.Invoke(s, e);
BackgroundApi.OnUpgradeAll += (s, e) => OnUpgradeAll?.Invoke(s, e);
BackgroundApi.OnUpgradeAllForManager += (s, e) => OnUpgradeAllForManager?.Invoke(s, e);
BackgroundApi.OnUpgradePackage += (s, e) => OnUpgradePackage?.Invoke(s, e);
}

public static bool AuthenticateToken(string token)
{
return token == ApiTokenHolder.Token;
Expand All @@ -39,7 +56,6 @@ public async Task Start()
return;
}


ApiTokenHolder.Token = CoreTools.RandomString(64);
Settings.SetValue("CurrentSessionToken", ApiTokenHolder.Token);
Logger.Info("Api auth token: " + ApiTokenHolder.Token);
Expand Down Expand Up @@ -87,12 +103,15 @@ public void Stop()
/// </summary>
public class BackgroundApi : NancyModule
{

static Dictionary<string, string> PackageIconsPathReference = new();
public static event EventHandler<EventArgs>? OnOpenWindow;
public static event EventHandler<EventArgs>? OnOpenUpdatesPage;
public static event EventHandler<KeyValuePair<string, string>>? OnShowSharedPackage;
public static event EventHandler<EventArgs>? OnUpgradeAll;
public static event EventHandler<string>? OnUpgradeAllForManager;
public static event EventHandler<string>? OnUpgradePackage;

public BackgroundApi()
{

// Enable CORS
After.AddItemToEndOfPipeline((ctx) =>
{
Expand All @@ -104,26 +123,20 @@ public BackgroundApi()
BuildV1WidgetsApi();
}



/// <summary>
/// Build the endpoints required for the Share Interface
/// </summary>
public void BuildShareApi()
{
// Show package from https://marticliment.com/unigetui/share
Get("/v2/show-package", async (parameters) =>
Get("/v2/show-package", (parameters) =>
{
try
{
if (Request.Query.@pid == "" || Request.Query.@psource == "")
return 400;

while (MainApp.Instance.MainWindow is null) await Task.Delay(100);
while (MainApp.Instance.MainWindow.NavigationPage is null) await Task.Delay(100);
while (MainApp.Instance.MainWindow.NavigationPage.DiscoverPage is null) await Task.Delay(100);

MainApp.Instance.MainWindow.NavigationPage.DiscoverPage.ShowSharedPackage_ThreadSafe([email protected](), [email protected]());
OnShowSharedPackage?.Invoke(this, new KeyValuePair<string, string>([email protected](), [email protected]()));

return "{\"status\": \"success\"}";
}
Expand Down Expand Up @@ -158,34 +171,46 @@ public void BuildV1WidgetsApi()
});

// Return found updates
Get("/widgets/v1/get_updates", (parameters) =>
Get("/widgets/v1/get_updates", async (parameters) =>
{
if (!BackgroundApiRunner.AuthenticateToken(Request.Query.@token))
return 401;

string packages = "";
foreach (Package package in MainApp.Instance.MainWindow.NavigationPage.UpdatesPage.Packages)
if (!PEInterface.UpgradablePackagesLoader.IsLoaded && !PEInterface.UpgradablePackagesLoader.IsLoading)
{
_ = PEInterface.UpgradablePackagesLoader.ReloadPackages(); // Actually begin loading the updates if not loaded or loading
}

while (PEInterface.UpgradablePackagesLoader.IsLoading)
{
await Task.Delay(500); // Wait for the updates to be reported before showing anything
}

StringBuilder packages = new();
foreach (Package package in PEInterface.UpgradablePackagesLoader.Packages)
{
if (package.Tag == PackageTag.OnQueue || package.Tag == PackageTag.BeingProcessed)
continue; // Do not show already processed packages on queue

string icon = $"http://localhost:7058/widgets/v2/get_icon_for_package?packageId={package.Id}&packageSource={package.Source.Name}&token={ApiTokenHolder.Token}";
packages += $"{package.Name.Replace('|', '-')}|{package.Id}|{package.Version}|{package.NewVersion}|{package.Source}|{package.Manager.Name}|{icon}&&";
packages.Append($"{package.Name.Replace('|', '-')}|{package.Id}|{package.Version}|{package.NewVersion}|{package.Source}|{package.Manager.Name}|{icon}&&");
}

if (packages.Length > 2)
packages = packages[..(packages.Length - 2)];
var pkgs_ = packages.ToString();

if (pkgs_.Length > 2)
pkgs_ = pkgs_[..(pkgs_.Length - 2)];

return packages;
return pkgs_;
});

// Open UniGetUI (as it was)
Get("/widgets/v1/open_wingetui", (parameters) =>
{
if (!BackgroundApiRunner.AuthenticateToken(Request.Query.@token))
return 401;

MainApp.Instance.MainWindow.DispatcherQueue.TryEnqueue(() => { MainApp.Instance.MainWindow.Activate(); });
OnOpenWindow?.Invoke(this, EventArgs.Empty);
return 200;
});

Expand All @@ -195,11 +220,7 @@ public void BuildV1WidgetsApi()
if (!BackgroundApiRunner.AuthenticateToken(Request.Query.@token))
return 401;

MainApp.Instance.MainWindow.DispatcherQueue.TryEnqueue(() =>
{
MainApp.Instance.MainWindow.NavigationPage.UpdatesNavButton.ForceClick();
MainApp.Instance.MainWindow.Activate();
});
OnOpenUpdatesPage?.Invoke(this, EventArgs.Empty);
return 200;
});

Expand All @@ -212,10 +233,7 @@ public void BuildV1WidgetsApi()
if (Request.Query.@id == "")
return 400;

MainApp.Instance.MainWindow.DispatcherQueue.TryEnqueue(() =>
{
MainApp.Instance.MainWindow.NavigationPage.UpdatesPage.UpdatePackageForId(Request.Query.@id);
});
OnUpgradePackage?.Invoke(this, Request.Query.@id);
return 200;
});

Expand All @@ -225,11 +243,8 @@ public void BuildV1WidgetsApi()
if (!BackgroundApiRunner.AuthenticateToken(Request.Query.@token))
return 401;

MainApp.Instance.MainWindow.DispatcherQueue.TryEnqueue(() =>
{
Logger.Info("[WIDGETS] Updating all packages");
MainApp.Instance.MainWindow.NavigationPage.UpdatesPage.UpdateAll();
});
Logger.Info("[WIDGETS] Updating all packages");
OnUpgradeAll?.Invoke(this, EventArgs.Empty);
return 200;
});

Expand All @@ -242,11 +257,8 @@ public void BuildV1WidgetsApi()
if (Request.Query.@source == "")
return 400;

MainApp.Instance.MainWindow.DispatcherQueue.TryEnqueue(() =>
{
Logger.Info($"[WIDGETS] Updating all packages for manager {Request.Query.@source}");
MainApp.Instance.MainWindow.NavigationPage.UpdatesPage.UpdateAllPackagesForManager(Request.Query.@source);
});
OnUpgradeAllForManager?.Invoke(this, Request.Query.@source);
return 200;
});

Expand All @@ -260,7 +272,7 @@ public void BuildV1WidgetsApi()
return 400;

string iconPath = Path.Join(CoreData.UniGetUIExecutableDirectory, "Assets", "Images", "package_color.png");
Package? package = MainApp.Instance.MainWindow.NavigationPage.UpdatesPage.GetPackageForId(Request.Query.@packageId, Request.Query.@packageSource);
Package? package = PEInterface.UpgradablePackagesLoader.GetPackageForId(Request.Query.@packageId, Request.Query.@packageSource);
if (package != null)
{
Uri iconUrl = await package.GetIconUrl();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
<RuntimeIdentifier>win-$(Platform)</RuntimeIdentifier>
<Platforms>x64</Platforms>
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
<SdkVersion>8.0.204</SdkVersion>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<PublishSelfContained>true</PublishSelfContained>
<FileVersion>3.1.0.0</FileVersion>
<InformationalVersion>3.1.0-alpha0</InformationalVersion>
<Product>UniGetUI</Product>
<Authors>Martí Climent and the contributors</Authors>
<PublisherName>Martí Climent</PublisherName>
<ApplicationVersion>3.1.0-alpha0</ApplicationVersion>
<Copyright>2024, Martí Climent</Copyright>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Nancy" Version="2.0.0" />
<PackageReference Include="Nancy.Hosting.Self" Version="2.0.0">
<NoWarn>NU1701</NoWarn>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\UniGetUI.Core.Classes\UniGetUI.Core.Classes.csproj" />
<ProjectReference Include="..\UniGetUI.Core.Data\UniGetUI.Core.Data.csproj" />
<ProjectReference Include="..\UniGetUI.Core.IconStore\UniGetUI.Core.IconEngine.csproj" />
<ProjectReference Include="..\UniGetUI.Core.LanguageEngine\UniGetUI.Core.LanguageEngine.csproj" />
<ProjectReference Include="..\UniGetUI.Core.Logger\UniGetUI.Core.Logging.csproj" />
<ProjectReference Include="..\UniGetUI.Core.Settings\UniGetUI.Core.Settings.csproj" />
<ProjectReference Include="..\UniGetUI.Core.Tools\UniGetUI.Core.Tools.csproj" />
<ProjectReference Include="..\UniGetUI.PackageEngine.Enums\UniGetUI.PackageEngine.Enums.csproj" />
<ProjectReference Include="..\UniGetUI.PackageEngine.PackageEngine\UniGetUI.PackageEngine.PEInterface.csproj" />
<ProjectReference Include="..\UniGetUI.PackageEngine.PackageManagerClasses\UniGetUI.PackageEngine.Classes.csproj" />
</ItemGroup>

</Project>
62 changes: 62 additions & 0 deletions src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using UniGetUI.PackageEngine.ManagerClasses.Manager;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UniGetUI.PackageEngine.Managers.WingetManager;
using UniGetUI.PackageEngine.Managers.ScoopManager;
using UniGetUI.PackageEngine.Managers.ChocolateyManager;
using UniGetUI.PackageEngine.Managers.DotNetManager;
using UniGetUI.PackageEngine.Managers.NpmManager;
using UniGetUI.PackageEngine.Managers.PowerShellManager;
using UniGetUI.PackageEngine.Managers.PipManager;
using UniGetUI.PackageEngine.PackageLoader;
using UniGetUI.Core.Logging;

namespace UniGetUI.PackageEngine
{
public static class PEInterface
{
private const int ManagerLoadTimeout = 10000; // 10 seconds timeout for Package Manager initialization

public static readonly WinGet WinGet = new WinGet();
public static readonly Scoop Scoop = new Scoop();
public static readonly Chocolatey Chocolatey = new Chocolatey();
public static readonly Npm Npm = new Npm();
public static readonly Pip Pip = new Pip();
public static readonly DotNet DotNet = new DotNet();
public static readonly PowerShell PowerShell = new PowerShell();

public static readonly PackageManager[] Managers = [WinGet, Scoop, Chocolatey, Npm, Pip, DotNet, PowerShell];

public static readonly DiscoverablePackagesLoader DiscoveredPackagesLoader = new(Managers);
public static readonly UpgradablePackagesLoader UpgradablePackagesLoader = new(Managers);
public static readonly InstalledPackagesLoader InstalledPackagesLoader = new(Managers);

public static async Task Initialize()
{
List<Task> initializeTasks = new();

foreach (PackageManager manager in Managers)
{
initializeTasks.Add(manager.InitializeAsync());
}

Task ManagersMetaTask = Task.WhenAll(initializeTasks);
try
{
await ManagersMetaTask.WaitAsync(TimeSpan.FromMilliseconds(ManagerLoadTimeout));
}
catch (Exception e)
{
Logger.Error(e);
}
if (ManagersMetaTask.IsCompletedSuccessfully == false)
Logger.Warn("Timeout: Not all package managers have finished initializing.");

_ = UpgradablePackagesLoader.ReloadPackages();
_ = InstalledPackagesLoader.ReloadPackages();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
<RuntimeIdentifier>win-$(Platform)</RuntimeIdentifier>
<Platforms>x64</Platforms>
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
<SdkVersion>8.0.204</SdkVersion>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<PublishSelfContained>true</PublishSelfContained>
<FileVersion>3.1.0.0</FileVersion>
<InformationalVersion>3.1.0-alpha0</InformationalVersion>
<Product>UniGetUI</Product>
<Authors>Martí Climent and the contributors</Authors>
<PublisherName>Martí Climent</PublisherName>
<ApplicationVersion>3.1.0-alpha0</ApplicationVersion>
<Copyright>2024, Martí Climent</Copyright>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\UniGetUI.Core.Classes\UniGetUI.Core.Classes.csproj" />
<ProjectReference Include="..\UniGetUI.Core.Data\UniGetUI.Core.Data.csproj" />
<ProjectReference Include="..\UniGetUI.Core.IconStore\UniGetUI.Core.IconEngine.csproj" />
<ProjectReference Include="..\UniGetUI.Core.LanguageEngine\UniGetUI.Core.LanguageEngine.csproj" />
<ProjectReference Include="..\UniGetUI.Core.Logger\UniGetUI.Core.Logging.csproj" />
<ProjectReference Include="..\UniGetUI.Core.Settings\UniGetUI.Core.Settings.csproj" />
<ProjectReference Include="..\UniGetUI.Core.Tools\UniGetUI.Core.Tools.csproj" />
<ProjectReference Include="..\UniGetUI.PackageEngine.Enums\UniGetUI.PackageEngine.Enums.csproj" />
<ProjectReference Include="..\UniGetUI.PackageEngine.Managers.Chocolatey\UniGetUI.PackageEngine.Managers.Chocolatey.csproj" />
<ProjectReference Include="..\UniGetUI.PackageEngine.Managers.Dotnet\UniGetUI.PackageEngine.Managers.Dotnet.csproj" />
<ProjectReference Include="..\UniGetUI.PackageEngine.Managers.Generic.NuGet\UniGetUI.PackageEngine.Managers.Generic.NuGet.csproj" />
<ProjectReference Include="..\UniGetUI.PackageEngine.Managers.Npm\UniGetUI.PackageEngine.Managers.Npm.csproj" />
<ProjectReference Include="..\UniGetUI.PackageEngine.Managers.Pip\UniGetUI.PackageEngine.Managers.Pip.csproj" />
<ProjectReference Include="..\UniGetUI.PackageEngine.Managers.PowerShell\UniGetUI.PackageEngine.Managers.PowerShell.csproj" />
<ProjectReference Include="..\UniGetUI.PackageEngine.Managers.Scoop\UniGetUI.PackageEngine.Managers.Scoop.csproj" />
<ProjectReference Include="..\UniGetUI.PackageEngine.Managers.WinGet\UniGetUI.PackageEngine.Managers.WinGet.csproj" />
<ProjectReference Include="..\UniGetUI.PackageEngine.PackageLoader\UniGetUI.PackageEngine.PackageLoaders.csproj" />
<ProjectReference Include="..\UniGetUI.PackageEngine.PackageManagerClasses\UniGetUI.PackageEngine.Classes.csproj" />
</ItemGroup>

</Project>
Loading