From 3ec7a85868300e847b588c21acf1abf05947f48d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Mon, 3 Feb 2025 11:17:02 +0100 Subject: [PATCH 1/5] Add package/ endpoints --- .../TelemetryHandler.cs | 25 +++++++++++++++++-- src/UniGetUI/AppOperationHelper.cs | 9 ++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/UniGetUI.Interface.Telemetry/TelemetryHandler.cs b/src/UniGetUI.Interface.Telemetry/TelemetryHandler.cs index b59c8b089..4afe481d1 100644 --- a/src/UniGetUI.Interface.Telemetry/TelemetryHandler.cs +++ b/src/UniGetUI.Interface.Telemetry/TelemetryHandler.cs @@ -103,7 +103,27 @@ public static async void Initialize() } } - public static async void PackageInstalled(IPackage package) + public enum OP_RESULT + { + SUCCESS, + FAILED, + CANCELED + } + + public static void InstallPackage(IPackage package, OP_RESULT status) + => PackageEndpoint(package, "install", status); + + public static void UpdatePackage(IPackage package, OP_RESULT status) + => PackageEndpoint(package, "update", status); + + public static void DownloadPackage(IPackage package, OP_RESULT status) + => PackageEndpoint(package, "download", status); + + public static void UninstallPackage(IPackage package, OP_RESULT status) + => PackageEndpoint(package, "uninstall", status); + + + private static async void PackageEndpoint(IPackage package, string endpoint, OP_RESULT result) { try { @@ -118,12 +138,13 @@ public static async void PackageInstalled(IPackage package) string ID = Settings.GetValue("TelemetryClientToken"); - var request = new HttpRequestMessage(HttpMethod.Post, $"{HOST}/install"); + var request = new HttpRequestMessage(HttpMethod.Post, $"{HOST}/package/{endpoint}"); request.Headers.Add("clientId", ID); request.Headers.Add("packageId", package.Id); request.Headers.Add("managerName", package.Manager.Name); request.Headers.Add("sourceName", package.Source.Name); + request.Headers.Add("operationResult", result.ToString()); HttpClient _httpClient = new(CoreData.GenericHttpClientParameters); HttpResponseMessage response = await _httpClient.SendAsync(request); diff --git a/src/UniGetUI/AppOperationHelper.cs b/src/UniGetUI/AppOperationHelper.cs index 840530f10..cc065977a 100644 --- a/src/UniGetUI/AppOperationHelper.cs +++ b/src/UniGetUI/AppOperationHelper.cs @@ -88,6 +88,8 @@ public static void Remove(AbstractOperation op) if (file is not null) { var op = new DownloadOperation(package, file.Path); + op.OperationSucceeded += (_, _) => TelemetryHandler.DownloadPackage(package, TelemetryHandler.OP_RESULT.SUCCESS); + op.OperationFailed += (_, _) => TelemetryHandler.DownloadPackage(package, TelemetryHandler.OP_RESULT.FAILED); Add(op); return op; } @@ -113,7 +115,8 @@ public static void Remove(AbstractOperation op) var options = await InstallationOptions.FromPackageAsync(package, elevated, interactive, no_integrity); var op = new InstallPackageOperation(package, options, ignoreParallel, req); Add(op); - op.OperationSucceeded += (_, _) => TelemetryHandler.PackageInstalled(package); + op.OperationSucceeded += (_, _) => TelemetryHandler.InstallPackage(package, TelemetryHandler.OP_RESULT.SUCCESS); + op.OperationFailed += (_, _) => TelemetryHandler.InstallPackage(package, TelemetryHandler.OP_RESULT.FAILED); return op; } @@ -134,6 +137,8 @@ public static void Install(IReadOnlyList packages, bool? elevated = nu var options = await InstallationOptions.FromPackageAsync(package, elevated, interactive, no_integrity); var op = new UpdatePackageOperation(package, options, ignoreParallel, req); Add(op); + op.OperationSucceeded += (_, _) => TelemetryHandler.UpdatePackage(package, TelemetryHandler.OP_RESULT.SUCCESS); + op.OperationFailed += (_, _) => TelemetryHandler.UpdatePackage(package, TelemetryHandler.OP_RESULT.FAILED); return op; } @@ -171,6 +176,8 @@ public static async void ConfirmAndUninstall(IPackage? package, bool? elevated = var options = await InstallationOptions.FromPackageAsync(package, elevated, interactive, remove_data: remove_data); var op = new UninstallPackageOperation(package, options, ignoreParallel, req); Add(op); + op.OperationSucceeded += (_, _) => TelemetryHandler.UninstallPackage(package, TelemetryHandler.OP_RESULT.SUCCESS); + op.OperationFailed += (_, _) => TelemetryHandler.UninstallPackage(package, TelemetryHandler.OP_RESULT.FAILED); return op; } From b4b67303140205e93235d992d4755e1f194aef6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Mon, 3 Feb 2025 19:31:26 +0100 Subject: [PATCH 2/5] Add new endpoints to telemetry --- .../TelemetryHandler.cs | 128 +++++++++++++----- src/UniGetUI.PackageEngine.Enums/Enums.cs | 3 +- src/UniGetUI/AppOperationHelper.cs | 26 ++-- .../DialogPages/DialogHelper_Packages.cs | 5 +- .../DialogPages/PackageDetailsPage.xaml.cs | 12 +- .../AbstractPackagesPage.xaml.cs | 23 +++- .../SoftwarePages/DiscoverSoftwarePage.cs | 40 ++++-- .../SoftwarePages/InstalledPackagesPage.cs | 13 +- .../Pages/SoftwarePages/PackageBundlesPage.cs | 33 +++-- .../SoftwarePages/SoftwareUpdatesPage.cs | 11 +- ...aries.WindowsPackageManager.Interop.csproj | 2 +- 11 files changed, 198 insertions(+), 98 deletions(-) diff --git a/src/UniGetUI.Interface.Telemetry/TelemetryHandler.cs b/src/UniGetUI.Interface.Telemetry/TelemetryHandler.cs index 4afe481d1..bc11c9d3a 100644 --- a/src/UniGetUI.Interface.Telemetry/TelemetryHandler.cs +++ b/src/UniGetUI.Interface.Telemetry/TelemetryHandler.cs @@ -1,18 +1,35 @@ -using System.Net; +using System.ComponentModel.Design; +using System.Net; using UniGetUI.Core.Data; using UniGetUI.Core.Language; using UniGetUI.Core.Logging; using UniGetUI.Core.SettingsEngine; using UniGetUI.Core.Tools; using UniGetUI.PackageEngine; +using UniGetUI.PackageEngine.Enums; using UniGetUI.PackageEngine.Interfaces; namespace UniGetUI.Interface.Telemetry; +public enum TEL_InstallReferral +{ + DIRECT_SEARCH, + FROM_BUNDLE, + FROM_WEB_SHARE, + ALREADY_INSTALLED, +} + +public enum TEL_OP_RESULT +{ + SUCCESS, + FAILED, + CANCELED +} + public static class TelemetryHandler { - private const string HOST = "https://marticliment.com/unigetui/statistics"; + private const string HOST = "https://marticliment.com/unigetui/statistics"; private static string[] SettingsToSend = { "DisableAutoUpdateWingetUI", @@ -31,19 +48,15 @@ public static class TelemetryHandler "SP2" // UniGetUI was started as daemon }; + // ------------------------------------------------------------------------- + public static async void Initialize() { try { if (Settings.Get("DisableTelemetry")) return; await CoreTools.WaitForInternetConnection(); - - if (Settings.GetValue("TelemetryClientToken").Length != 64) - { - Settings.SetValue("TelemetryClientToken", CoreTools.RandomString(64)); - } - - string ID = Settings.GetValue("TelemetryClientToken"); + string ID = GetRandomizedId(); int mask = 0x1; int ManagerMagicValue = 0; @@ -103,65 +116,114 @@ public static async void Initialize() } } - public enum OP_RESULT - { - SUCCESS, - FAILED, - CANCELED - } + // ------------------------------------------------------------------------- - public static void InstallPackage(IPackage package, OP_RESULT status) - => PackageEndpoint(package, "install", status); + public static void InstallPackage(IPackage package, TEL_OP_RESULT status, TEL_InstallReferral source) + => PackageEndpoint(package, "install", status, source.ToString()); - public static void UpdatePackage(IPackage package, OP_RESULT status) + public static void UpdatePackage(IPackage package, TEL_OP_RESULT status) => PackageEndpoint(package, "update", status); - public static void DownloadPackage(IPackage package, OP_RESULT status) - => PackageEndpoint(package, "download", status); + public static void DownloadPackage(IPackage package, TEL_OP_RESULT status, TEL_InstallReferral source) + => PackageEndpoint(package, "download", status, source.ToString()); - public static void UninstallPackage(IPackage package, OP_RESULT status) + public static void UninstallPackage(IPackage package, TEL_OP_RESULT status) => PackageEndpoint(package, "uninstall", status); + public static void PackageDetails(IPackage package, string eventSource) + => PackageEndpoint(package, "details", eventSource: eventSource); + + public static void SharedPackage(IPackage package, string eventSource) + => PackageEndpoint(package, "share", eventSource: eventSource); - private static async void PackageEndpoint(IPackage package, string endpoint, OP_RESULT result) + private static async void PackageEndpoint(IPackage package, string endpoint, TEL_OP_RESULT? result = null, string? eventSource = null) { + if (result is null && eventSource is null) throw new NullReferenceException("result and eventSource cannot be both null!"); + try { if (Settings.Get("DisableTelemetry")) return; await CoreTools.WaitForInternetConnection(); + string ID = GetRandomizedId(); + + var request = new HttpRequestMessage(HttpMethod.Post, $"{HOST}/package/{endpoint}"); + + request.Headers.Add("clientId", ID); + request.Headers.Add("packageId", package.Id); + request.Headers.Add("managerName", package.Manager.Name); + request.Headers.Add("sourceName", package.Source.Name); + if(result is not null) request.Headers.Add("operationResult", result.ToString()); + if(eventSource is not null) request.Headers.Add("eventSource", eventSource); - if (Settings.GetValue("TelemetryClientToken").Length != 64) + HttpClient _httpClient = new(CoreData.GenericHttpClientParameters); + HttpResponseMessage response = await _httpClient.SendAsync(request); + + if (response.IsSuccessStatusCode) { - Settings.SetValue("TelemetryClientToken", CoreTools.RandomString(64)); + Logger.Debug($"[Telemetry] Call to /package/{endpoint} succeeded"); } + else + { + Logger.Warn($"[Telemetry] Call to /package/{endpoint} failed with error code {response.StatusCode}"); + } + } + catch (Exception ex) + { + Logger.Error($"[Telemetry] Hard crash when calling /package/{endpoint}"); + Logger.Error(ex); + } + } - string ID = Settings.GetValue("TelemetryClientToken"); + // ------------------------------------------------------------------------- - var request = new HttpRequestMessage(HttpMethod.Post, $"{HOST}/package/{endpoint}"); + public static void ImportBundle(BundleFormatType type) + => BundlesEndpoint("import", type); + + public static void ExportBundle(BundleFormatType type) + => BundlesEndpoint("export", type); + + private static async void BundlesEndpoint(string endpoint, BundleFormatType type) + { + try + { + if (Settings.Get("DisableTelemetry")) return; + await CoreTools.WaitForInternetConnection(); + string ID = GetRandomizedId(); + + var request = new HttpRequestMessage(HttpMethod.Post, $"{HOST}/bundles/{endpoint}"); request.Headers.Add("clientId", ID); - request.Headers.Add("packageId", package.Id); - request.Headers.Add("managerName", package.Manager.Name); - request.Headers.Add("sourceName", package.Source.Name); - request.Headers.Add("operationResult", result.ToString()); + request.Headers.Add("bundleType", type.ToString()); HttpClient _httpClient = new(CoreData.GenericHttpClientParameters); HttpResponseMessage response = await _httpClient.SendAsync(request); if (response.IsSuccessStatusCode) { - Logger.Debug("[Telemetry] Call to /install succeeded"); + Logger.Debug($"[Telemetry] Call to /bundles/{endpoint} succeeded"); } else { - Logger.Warn($"[Telemetry] Call to /install failed with error code {response.StatusCode}"); + Logger.Warn($"[Telemetry] Call to /bundles/{endpoint} failed with error code {response.StatusCode}"); } } catch (Exception ex) { - Logger.Error("[Telemetry] Hard crash when calling /install"); + Logger.Error($"[Telemetry] Hard crash when calling /bundles/{endpoint}"); Logger.Error(ex); } } + + private static string GetRandomizedId() + { + string ID = Settings.GetValue("TelemetryClientToken"); + if (ID.Length != 64) + { + ID = CoreTools.RandomString(64); + Settings.SetValue("TelemetryClientToken", ID); + } + + return ID; + } } diff --git a/src/UniGetUI.PackageEngine.Enums/Enums.cs b/src/UniGetUI.PackageEngine.Enums/Enums.cs index 6b8d6305f..5dc8dabcf 100644 --- a/src/UniGetUI.PackageEngine.Enums/Enums.cs +++ b/src/UniGetUI.PackageEngine.Enums/Enums.cs @@ -22,9 +22,10 @@ public enum DeserializedPackageStatus public enum BundleFormatType { + UBUNDLE, JSON, YAML, - XML + XML, } public enum OperationVeredict diff --git a/src/UniGetUI/AppOperationHelper.cs b/src/UniGetUI/AppOperationHelper.cs index cc065977a..41dc26600 100644 --- a/src/UniGetUI/AppOperationHelper.cs +++ b/src/UniGetUI/AppOperationHelper.cs @@ -40,7 +40,7 @@ public static void Remove(AbstractOperation op) * OPERATION CREATION HELPERS * */ - public static async Task AskLocationAndDownload(IPackage? package) + public static async Task AskLocationAndDownload(IPackage? package, TEL_InstallReferral referral) { if (package is null) return null; try @@ -88,8 +88,8 @@ public static void Remove(AbstractOperation op) if (file is not null) { var op = new DownloadOperation(package, file.Path); - op.OperationSucceeded += (_, _) => TelemetryHandler.DownloadPackage(package, TelemetryHandler.OP_RESULT.SUCCESS); - op.OperationFailed += (_, _) => TelemetryHandler.DownloadPackage(package, TelemetryHandler.OP_RESULT.FAILED); + op.OperationSucceeded += (_, _) => TelemetryHandler.DownloadPackage(package, TEL_OP_RESULT.SUCCESS, referral); + op.OperationFailed += (_, _) => TelemetryHandler.DownloadPackage(package, TEL_OP_RESULT.FAILED, referral); Add(op); return op; } @@ -108,21 +108,23 @@ public static void Remove(AbstractOperation op) /* * PACKAGE INSTALLATION */ - public static async Task Install(IPackage? package, bool? elevated = null, bool? interactive = null, bool? no_integrity = null, bool ignoreParallel = false, AbstractOperation? req = null) + public static async Task Install(IPackage? package, TEL_InstallReferral referral, + bool? elevated = null, bool? interactive = null, bool? no_integrity = null, bool ignoreParallel = false, + AbstractOperation? req = null) { if (package is null) return null; var options = await InstallationOptions.FromPackageAsync(package, elevated, interactive, no_integrity); var op = new InstallPackageOperation(package, options, ignoreParallel, req); Add(op); - op.OperationSucceeded += (_, _) => TelemetryHandler.InstallPackage(package, TelemetryHandler.OP_RESULT.SUCCESS); - op.OperationFailed += (_, _) => TelemetryHandler.InstallPackage(package, TelemetryHandler.OP_RESULT.FAILED); + op.OperationSucceeded += (_, _) => TelemetryHandler.InstallPackage(package, TEL_OP_RESULT.SUCCESS, referral); + op.OperationFailed += (_, _) => TelemetryHandler.InstallPackage(package, TEL_OP_RESULT.FAILED, referral); return op; } - public static void Install(IReadOnlyList packages, bool? elevated = null, bool? interactive = null, bool? no_integrity = null) + public static void Install(IReadOnlyList packages, TEL_InstallReferral referral, bool? elevated = null, bool? interactive = null, bool? no_integrity = null) { - foreach (var package in packages) _ = Install(package, elevated, interactive, no_integrity); + foreach (var package in packages) _ = Install(package, referral, elevated, interactive, no_integrity); } @@ -137,8 +139,8 @@ public static void Install(IReadOnlyList packages, bool? elevated = nu var options = await InstallationOptions.FromPackageAsync(package, elevated, interactive, no_integrity); var op = new UpdatePackageOperation(package, options, ignoreParallel, req); Add(op); - op.OperationSucceeded += (_, _) => TelemetryHandler.UpdatePackage(package, TelemetryHandler.OP_RESULT.SUCCESS); - op.OperationFailed += (_, _) => TelemetryHandler.UpdatePackage(package, TelemetryHandler.OP_RESULT.FAILED); + op.OperationSucceeded += (_, _) => TelemetryHandler.UpdatePackage(package, TEL_OP_RESULT.SUCCESS); + op.OperationFailed += (_, _) => TelemetryHandler.UpdatePackage(package, TEL_OP_RESULT.FAILED); return op; } @@ -176,8 +178,8 @@ public static async void ConfirmAndUninstall(IPackage? package, bool? elevated = var options = await InstallationOptions.FromPackageAsync(package, elevated, interactive, remove_data: remove_data); var op = new UninstallPackageOperation(package, options, ignoreParallel, req); Add(op); - op.OperationSucceeded += (_, _) => TelemetryHandler.UninstallPackage(package, TelemetryHandler.OP_RESULT.SUCCESS); - op.OperationFailed += (_, _) => TelemetryHandler.UninstallPackage(package, TelemetryHandler.OP_RESULT.FAILED); + op.OperationSucceeded += (_, _) => TelemetryHandler.UninstallPackage(package, TEL_OP_RESULT.SUCCESS); + op.OperationFailed += (_, _) => TelemetryHandler.UninstallPackage(package, TEL_OP_RESULT.FAILED); return op; } diff --git a/src/UniGetUI/Pages/DialogPages/DialogHelper_Packages.cs b/src/UniGetUI/Pages/DialogPages/DialogHelper_Packages.cs index fdeaae6ea..0ad862e7e 100644 --- a/src/UniGetUI/Pages/DialogPages/DialogHelper_Packages.cs +++ b/src/UniGetUI/Pages/DialogPages/DialogHelper_Packages.cs @@ -7,6 +7,7 @@ using UniGetUI.Interface; using UniGetUI.Interface.Dialogs; using UniGetUI.Interface.Enums; +using UniGetUI.Interface.Telemetry; using UniGetUI.Interface.Widgets; using UniGetUI.PackageEngine.Enums; using UniGetUI.PackageEngine.Interfaces; @@ -90,9 +91,9 @@ public static async Task ShowInstallOptions_ImportedPackage } - public static async void ShowPackageDetails(IPackage package, OperationType operation) + public static async void ShowPackageDetails(IPackage package, OperationType operation, TEL_InstallReferral referral) { - PackageDetailsPage DetailsPage = new(package, operation); + PackageDetailsPage DetailsPage = new(package, operation, referral); ContentDialog DetailsDialog = new() { diff --git a/src/UniGetUI/Pages/DialogPages/PackageDetailsPage.xaml.cs b/src/UniGetUI/Pages/DialogPages/PackageDetailsPage.xaml.cs index 163863168..f6f38b8ea 100644 --- a/src/UniGetUI/Pages/DialogPages/PackageDetailsPage.xaml.cs +++ b/src/UniGetUI/Pages/DialogPages/PackageDetailsPage.xaml.cs @@ -19,6 +19,7 @@ using UniGetUI.PackageEngine.Operations; using UniGetUI.PackageEngine.PackageClasses; using UniGetUI.Interface.Enums; +using UniGetUI.Interface.Telemetry; using UniGetUI.Interface.Widgets; using UniGetUI.PackageEngine.ManagerClasses.Manager; using UniGetUI.Pages.DialogPages; @@ -54,12 +55,15 @@ private enum LayoutMode Unset } + private TEL_InstallReferral InstallReferral; + private LayoutMode __layout_mode = LayoutMode.Unset; - public PackageDetailsPage(IPackage package, OperationType role) + public PackageDetailsPage(IPackage package, OperationType role, TEL_InstallReferral referral) { if (role == OperationType.None) role = OperationType.Install; + InstallReferral = referral; OperationRole = role; Package = package; @@ -136,6 +140,8 @@ public PackageDetailsPage(IPackage package, OperationType role) SetUpActionButtonAsUninstall(); } _ = LoadInformation(); + + TelemetryHandler.PackageDetails(package, referral.ToString()); } public void SetUpActionButtonAsInstall() @@ -456,7 +462,7 @@ public void DownloadInstallerButton_Click(object sender, RoutedEventArgs e) { if (!Package.Manager.Capabilities.CanDownloadInstaller) return; Close?.Invoke(this, EventArgs.Empty); - _ = MainApp.Operations.AskLocationAndDownload(Package); + _ = MainApp.Operations.AskLocationAndDownload(Package, InstallReferral); } public void CloseButton_Click(object sender, RoutedEventArgs e) @@ -590,7 +596,7 @@ public async void DoAction( if (action is OperationType.Install) { - _ = MainApp.Operations.Install(package, AsAdmin, Interactive, SkipHash); + _ = MainApp.Operations.Install(package, InstallReferral, AsAdmin, Interactive, SkipHash); } else if (action is OperationType.Uninstall) { diff --git a/src/UniGetUI/Pages/SoftwarePages/AbstractPackagesPage.xaml.cs b/src/UniGetUI/Pages/SoftwarePages/AbstractPackagesPage.xaml.cs index 27ff9707d..f24fa8593 100644 --- a/src/UniGetUI/Pages/SoftwarePages/AbstractPackagesPage.xaml.cs +++ b/src/UniGetUI/Pages/SoftwarePages/AbstractPackagesPage.xaml.cs @@ -15,7 +15,9 @@ using Windows.System; using Windows.UI.Core; using UniGetUI.Interface.Pages; +using UniGetUI.Interface.Telemetry; using UniGetUI.Pages.DialogPages; +using Page = ABI.Microsoft.UI.Xaml.Controls.Page; // To learn more about WinUI, the WinUI project structure, // and more about our project templates, see: http://aka.ms/winui-project-info. @@ -785,14 +787,14 @@ protected void ClearSourceSelectionButton_Click(object sender, RoutedEventArgs e FilterPackages(); } - protected void ShowDetailsForPackage(IPackage? package) + protected void ShowDetailsForPackage(IPackage? package, TEL_InstallReferral referral) { if (package is null || package.Source.IsVirtualManager || package is InvalidImportedPackage) { return; } - DialogHelper.ShowPackageDetails(package, PAGE_ROLE); + DialogHelper.ShowPackageDetails(package, PAGE_ROLE, referral); } protected void OpenPackageInstallLocation(IPackage? package) @@ -863,7 +865,7 @@ protected void PerformMainPackageAction(IPackage? package) if (PAGE_ROLE == OperationType.Install) { - _ = MainApp.Operations.Install(package); + _ = MainApp.Operations.Install(package, TEL_InstallReferral.DIRECT_SEARCH); } else if (PAGE_ROLE == OperationType.Update) { @@ -892,7 +894,11 @@ private void PackageItemContainer_DoubleTapped(object sender, DoubleTappedRouted if (sender is PackageItemContainer container && container.Package is not null) { PackageList.Select(container.Wrapper.Index); - ShowDetailsForPackage(container.Package); + + TEL_InstallReferral referral = TEL_InstallReferral.ALREADY_INSTALLED; + if (PAGE_NAME == "Bundles") referral = TEL_InstallReferral.FROM_BUNDLE; + if (PAGE_NAME == "Discover") referral = TEL_InstallReferral.DIRECT_SEARCH; + ShowDetailsForPackage(container.Package, referral); } } @@ -919,8 +925,13 @@ private void PackageItemContainer_KeyUp(object sender, KeyRoutedEventArgs e) } else { - if(!package.Source.IsVirtualManager && package is not InvalidImportedPackage) - ShowDetailsForPackage(package); + if (!package.Source.IsVirtualManager && package is not InvalidImportedPackage) + { + TEL_InstallReferral referral = TEL_InstallReferral.ALREADY_INSTALLED; + if (PAGE_NAME == "Bundles") referral = TEL_InstallReferral.FROM_BUNDLE; + if (PAGE_NAME == "Discover") referral = TEL_InstallReferral.DIRECT_SEARCH; + ShowDetailsForPackage(package, referral); + } } } else if (e.Key == VirtualKey.Space && package is not null) diff --git a/src/UniGetUI/Pages/SoftwarePages/DiscoverSoftwarePage.cs b/src/UniGetUI/Pages/SoftwarePages/DiscoverSoftwarePage.cs index 88a9051c7..f14d9eec2 100644 --- a/src/UniGetUI/Pages/SoftwarePages/DiscoverSoftwarePage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/DiscoverSoftwarePage.cs @@ -9,6 +9,7 @@ using UniGetUI.PackageEngine.Interfaces; using UniGetUI.PackageEngine.PackageLoader; using Windows.System; +using UniGetUI.Interface.Telemetry; using UniGetUI.Pages.DialogPages; namespace UniGetUI.Interface.SoftwarePages @@ -108,7 +109,7 @@ public override BetterMenu GenerateContextMenu() Text = CoreTools.AutoTranslated("Download installer"), IconName = IconType.Download }; - MenuDownloadInstaller.Click += (_, _) => _ = MainApp.Operations.AskLocationAndDownload(SelectedItem); + MenuDownloadInstaller.Click += (_, _) => _ = MainApp.Operations.AskLocationAndDownload(SelectedItem, TEL_InstallReferral.DIRECT_SEARCH); menu.Items.Add(MenuDownloadInstaller); menu.Items.Add(new MenuFlyoutSeparator { Height = 5 }); @@ -206,15 +207,15 @@ public override void GenerateToolBar() toolButton.Icon = new LocalIcon(Icons[toolButton]); } - PackageDetails.Click += (_, _) => ShowDetailsForPackage(SelectedItem); + PackageDetails.Click += (_, _) => ShowDetailsForPackage(SelectedItem, TEL_InstallReferral.DIRECT_SEARCH); ExportSelection.Click += ExportSelection_Click; HelpButton.Click += (_, _) => MainApp.Instance.MainWindow.NavigationPage.ShowHelp(); InstallationSettings.Click += (_, _) => ShowInstallationOptionsForPackage(SelectedItem); - InstallSelected.Click += (_, _) => MainApp.Operations.Install(FilteredPackages.GetCheckedPackages()); - InstallAsAdmin.Click += (_, _) => MainApp.Operations.Install(FilteredPackages.GetCheckedPackages(), elevated: true); - InstallSkipHash.Click += (_, _) => MainApp.Operations.Install(FilteredPackages.GetCheckedPackages(), no_integrity: true); - InstallInteractive.Click += (_, _) => MainApp.Operations.Install(FilteredPackages.GetCheckedPackages(), interactive: true); + InstallSelected.Click += (_, _) => MainApp.Operations.Install(FilteredPackages.GetCheckedPackages(), TEL_InstallReferral.DIRECT_SEARCH); + InstallAsAdmin.Click += (_, _) => MainApp.Operations.Install(FilteredPackages.GetCheckedPackages(), TEL_InstallReferral.DIRECT_SEARCH, elevated: true); + InstallSkipHash.Click += (_, _) => MainApp.Operations.Install(FilteredPackages.GetCheckedPackages(), TEL_InstallReferral.DIRECT_SEARCH, no_integrity: true); + InstallInteractive.Click += (_, _) => MainApp.Operations.Install(FilteredPackages.GetCheckedPackages(), TEL_InstallReferral.DIRECT_SEARCH, interactive: true); SharePackage.Click += (_, _) => MainApp.Instance.MainWindow.SharePackage(SelectedItem); } @@ -269,7 +270,7 @@ private async void ExportSelection_Click(object sender, RoutedEventArgs e) private void MenuDetails_Invoked(object sender, RoutedEventArgs e) { - ShowDetailsForPackage(SelectedItem); + ShowDetailsForPackage(SelectedItem, TEL_InstallReferral.DIRECT_SEARCH); } private void MenuShare_Invoked(object sender, RoutedEventArgs e) @@ -283,16 +284,16 @@ private void MenuShare_Invoked(object sender, RoutedEventArgs e) } private void MenuInstall_Invoked(object sender, RoutedEventArgs e) - => _ = MainApp.Operations.Install(SelectedItem); + => _ = MainApp.Operations.Install(SelectedItem, TEL_InstallReferral.DIRECT_SEARCH); private void MenuSkipHash_Invoked(object sender, RoutedEventArgs e) - => _ = MainApp.Operations.Install(SelectedItem, no_integrity: true); + => _ = MainApp.Operations.Install(SelectedItem, TEL_InstallReferral.DIRECT_SEARCH, no_integrity: true); private void MenuInteractive_Invoked(object sender, RoutedEventArgs e) - => _ = MainApp.Operations.Install(SelectedItem, interactive: true); + => _ = MainApp.Operations.Install(SelectedItem, TEL_InstallReferral.DIRECT_SEARCH, interactive: true); private void MenuAsAdmin_Invoked(object sender, RoutedEventArgs e) - => _ = MainApp.Operations.Install(SelectedItem, elevated: true); + => _ = MainApp.Operations.Install(SelectedItem, TEL_InstallReferral.DIRECT_SEARCH, elevated: true); private void MenuInstallSettings_Invoked(object sender, RoutedEventArgs e) => ShowInstallationOptionsForPackage(SelectedItem); @@ -303,18 +304,27 @@ public void ShowSharedPackage_ThreadSafe(string id, string combinedSourceName) string managerName = contents[0]; string sourceName = ""; if (contents.Length > 1) sourceName = contents[1]; - ShowSharedPackage_ThreadSafe(id, managerName, sourceName); + _showSharedPackage(id, managerName, sourceName, "LEGACY_COMBINEDSOURCE"); } public void ShowSharedPackage_ThreadSafe(string id, string managerName, string sourceName) { - MainApp.Instance.MainWindow.DispatcherQueue.TryEnqueue(async () => + MainApp.Instance.MainWindow.DispatcherQueue.TryEnqueue(() => { - IPackage? package = await GetPackageFromIdAndManager(id, managerName, sourceName); - if (package is not null) ShowDetailsForPackage(package); + _showSharedPackage(id, managerName, sourceName, "DEFAULT"); }); } + private async void _showSharedPackage(string id, string manager, string source, string eventSource) + { + IPackage? package = await GetPackageFromIdAndManager(id, manager, source); + if (package is not null) + { + TelemetryHandler.SharedPackage(package, eventSource); + ShowDetailsForPackage(package, TEL_InstallReferral.FROM_WEB_SHARE); + } + } + private static async Task GetPackageFromIdAndManager(string id, string managerName, string sourceName) { try diff --git a/src/UniGetUI/Pages/SoftwarePages/InstalledPackagesPage.cs b/src/UniGetUI/Pages/SoftwarePages/InstalledPackagesPage.cs index 1f5c8ba22..211697858 100644 --- a/src/UniGetUI/Pages/SoftwarePages/InstalledPackagesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/InstalledPackagesPage.cs @@ -5,6 +5,7 @@ using UniGetUI.Core.SettingsEngine; using UniGetUI.Core.Tools; using UniGetUI.Interface.Enums; +using UniGetUI.Interface.Telemetry; using UniGetUI.Interface.Widgets; using UniGetUI.PackageEngine; using UniGetUI.PackageEngine.Enums; @@ -122,7 +123,7 @@ public override BetterMenu GenerateContextMenu() Text = CoreTools.AutoTranslated("Download installer"), IconName = IconType.Download }; - MenuDownloadInstaller.Click += (_, _) => _ = MainApp.Operations.AskLocationAndDownload(SelectedItem); + MenuDownloadInstaller.Click += (_, _) => _ = MainApp.Operations.AskLocationAndDownload(SelectedItem, TEL_InstallReferral.ALREADY_INSTALLED); menu.Items.Add(MenuDownloadInstaller); menu.Items.Add(new MenuFlyoutSeparator()); @@ -251,7 +252,7 @@ public override void GenerateToolBar() toolButton.Icon = new LocalIcon(Icons[toolButton]); } - PackageDetails.Click += (_, _) => ShowDetailsForPackage(SelectedItem); + PackageDetails.Click += (_, _) => ShowDetailsForPackage(SelectedItem, TEL_InstallReferral.ALREADY_INSTALLED); ExportSelection.Click += ExportSelection_Click; HelpButton.Click += (_, _) => MainApp.Instance.MainWindow.NavigationPage.ShowHelp(); @@ -370,7 +371,7 @@ public async Task BackupPackages() packagesToExport.Add(package); } - string BackupContents = await PackageBundlesPage.CreateBundle(packagesToExport.ToArray(), BundleFormatType.JSON); + string BackupContents = await PackageBundlesPage.CreateBundle(packagesToExport.ToArray(), BundleFormatType.UBUNDLE); string dirName = Settings.GetValue("ChangeBackupOutputDirectory"); if (dirName == "") @@ -421,12 +422,12 @@ private void MenuRemoveData_Invoked(object sender, RoutedEventArgs args) => MainApp.Operations.ConfirmAndUninstall(SelectedItem, remove_data: true); private void MenuReinstall_Invoked(object sender, RoutedEventArgs args) - => _ = MainApp.Operations.Install(SelectedItem); + => _ = MainApp.Operations.Install(SelectedItem, TEL_InstallReferral.ALREADY_INSTALLED); private async void MenuUninstallThenReinstall_Invoked(object sender, RoutedEventArgs args) { var op = await MainApp.Operations.Uninstall(SelectedItem, ignoreParallel: true); - _ = MainApp.Operations.Install(SelectedItem, ignoreParallel: true, req: op); + _ = MainApp.Operations.Install(SelectedItem, TEL_InstallReferral.ALREADY_INSTALLED, ignoreParallel: true, req: op); } private async void MenuIgnorePackage_Invoked(object sender, RoutedEventArgs args) @@ -455,7 +456,7 @@ private void MenuShare_Invoked(object sender, RoutedEventArgs args) private void MenuDetails_Invoked(object sender, RoutedEventArgs args) { - ShowDetailsForPackage(SelectedItem); + ShowDetailsForPackage(SelectedItem, TEL_InstallReferral.ALREADY_INSTALLED); } private void MenuInstallSettings_Invoked(object sender, RoutedEventArgs e) diff --git a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs index 65d574826..37ed55bec 100644 --- a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs @@ -10,6 +10,7 @@ using UniGetUI.Core.Logging; using UniGetUI.Core.Tools; using UniGetUI.Interface.Enums; +using UniGetUI.Interface.Telemetry; using UniGetUI.Interface.Widgets; using UniGetUI.PackageEngine; using UniGetUI.PackageEngine.Classes.Serializable; @@ -131,7 +132,7 @@ public override BetterMenu GenerateContextMenu() Text = CoreTools.AutoTranslated("Download installer"), IconName = IconType.Download }; - MenuDownloadInstaller.Click += (_, _) => _ = MainApp.Operations.AskLocationAndDownload(SelectedItem); + MenuDownloadInstaller.Click += (_, _) => _ = MainApp.Operations.AskLocationAndDownload(SelectedItem, TEL_InstallReferral.FROM_BUNDLE); menu.Items.Add(MenuDownloadInstaller); menu.Items.Add(new MenuFlyoutSeparator()); @@ -239,9 +240,8 @@ public override void GenerateToolBar() PackageDetails.Click += (_, _) => { - IPackage? package = SelectedItem as IPackage; - if (package is not null) - DialogHelper.ShowPackageDetails(package, OperationType.None); + if (SelectedItem is null) return; + DialogHelper.ShowPackageDetails(SelectedItem, OperationType.None, TEL_InstallReferral.FROM_BUNDLE); }; HelpButton.Click += (_, _) => { MainApp.Instance.MainWindow.NavigationPage.ShowHelp(); }; @@ -336,7 +336,7 @@ public async Task ImportAndInstallPackage(IEnumerable packages, bool? } DialogHelper.HideLoadingDialog(); - MainApp.Operations.Install(packages_to_install, elevated, interactive, skiphash); + MainApp.Operations.Install(packages_to_install, TEL_InstallReferral.FROM_BUNDLE, elevated, interactive, skiphash); } protected override void WhenPackageCountUpdated() @@ -404,7 +404,7 @@ private void MenuShare_Invoked(object sender, RoutedEventArgs args) private void MenuDetails_Invoked(object sender, RoutedEventArgs args) { - ShowDetailsForPackage(SelectedItem); + ShowDetailsForPackage(SelectedItem, TEL_InstallReferral.FROM_BUNDLE); } private async void MenuInstallSettings_Invoked(object sender, RoutedEventArgs e) @@ -451,10 +451,12 @@ public async Task OpenFromFile(string? file = null) formatType = BundleFormatType.YAML; else if (EXT == "xml") formatType = BundleFormatType.XML; - else if (EXT == "json" || EXT == "ubundle") + else if (EXT == "json") formatType = BundleFormatType.JSON; + else if (EXT == "ubundle") + formatType = BundleFormatType.UBUNDLE; else - formatType = BundleFormatType.JSON; + formatType = BundleFormatType.UBUNDLE; string fileContent = await File.ReadAllTextAsync(file); @@ -508,13 +510,16 @@ public async Task SaveFile() formatType = BundleFormatType.YAML; else if (EXT == "xml") formatType = BundleFormatType.XML; - else if (EXT == "json" || EXT == "ubundle") + else if (EXT == "json") formatType = BundleFormatType.JSON; + else if (EXT == "ubundle") + formatType = BundleFormatType.UBUNDLE; else - formatType = BundleFormatType.JSON; + formatType = BundleFormatType.UBUNDLE; // Save serialized data await File.WriteAllTextAsync(file, await CreateBundle(Loader.Packages, formatType)); + TelemetryHandler.ExportBundle(formatType); DialogHelper.HideLoadingDialog(); @@ -548,7 +553,7 @@ public async Task SaveFile() } } - public static async Task CreateBundle(IEnumerable unsorted_packages, BundleFormatType formatType = BundleFormatType.JSON) + public static async Task CreateBundle(IEnumerable unsorted_packages, BundleFormatType formatType = BundleFormatType.UBUNDLE) { SerializableBundle_v1 exportable = new(); exportable.export_version = 2.1; @@ -572,12 +577,12 @@ int Comparison(IPackage x, IPackage y) Logger.Debug("Finished loading serializable objects. Serializing with format " + formatType); string ExportableData; - if (formatType == BundleFormatType.JSON) + if (formatType is BundleFormatType.JSON or BundleFormatType.UBUNDLE) ExportableData = JsonSerializer.Serialize( exportable, CoreData.SerializingOptions); - else if (formatType == BundleFormatType.YAML) + else if (formatType is BundleFormatType.YAML) { ISerializer serializer = new SerializerBuilder() .Build(); @@ -603,7 +608,7 @@ public async Task AddFromBundle(string content, BundleFormatType format) { // Deserialize data SerializableBundle_v1? DeserializedData; - if (format is BundleFormatType.JSON) + if (format is BundleFormatType.JSON or BundleFormatType.UBUNDLE) { DeserializedData = await Task.Run(() => JsonSerializer.Deserialize(content, CoreData.SerializingOptions)); } diff --git a/src/UniGetUI/Pages/SoftwarePages/SoftwareUpdatesPage.cs b/src/UniGetUI/Pages/SoftwarePages/SoftwareUpdatesPage.cs index c121abbfb..bff92ac3b 100644 --- a/src/UniGetUI/Pages/SoftwarePages/SoftwareUpdatesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/SoftwareUpdatesPage.cs @@ -7,6 +7,7 @@ using UniGetUI.Core.SettingsEngine; using UniGetUI.Core.Tools; using UniGetUI.Interface.Enums; +using UniGetUI.Interface.Telemetry; using UniGetUI.Interface.Widgets; using UniGetUI.PackageEngine; using UniGetUI.PackageEngine.Classes.Packages.Classes; @@ -105,7 +106,7 @@ public override BetterMenu GenerateContextMenu() Text = CoreTools.AutoTranslated("Download installer"), IconName = IconType.Download }; - MenuDownloadInstaller.Click += (_, _) => _ = MainApp.Operations.AskLocationAndDownload(SelectedItem); + MenuDownloadInstaller.Click += (_, _) => _ = MainApp.Operations.AskLocationAndDownload(SelectedItem, TEL_InstallReferral.ALREADY_INSTALLED); BetterMenuItem menuUpdateAfterUninstall = new() { @@ -148,7 +149,7 @@ public override BetterMenu GenerateContextMenu() IconName = IconType.Info_Round, KeyboardAcceleratorTextOverride = "Enter" }; - menuDetails.Click += (_, _) => ShowDetailsForPackage(SelectedItem); + menuDetails.Click += (_, _) => ShowDetailsForPackage(SelectedItem, TEL_InstallReferral.ALREADY_INSTALLED); MenuFlyoutSubItem menuPause = new() { @@ -296,7 +297,7 @@ public override void GenerateToolBar() toolButton.Icon = new LocalIcon(Icons[toolButton]); } - PackageDetails.Click += (_, _) => ShowDetailsForPackage(SelectedItem); + PackageDetails.Click += (_, _) => ShowDetailsForPackage(SelectedItem, TEL_InstallReferral.ALREADY_INSTALLED); HelpButton.Click += (_, _) => MainApp.Instance.MainWindow.NavigationPage.ShowHelp(); InstallationSettings.Click += (_, _) => ShowInstallationOptionsForPackage(SelectedItem); ManageIgnored.Click += async (_, _) => await DialogHelper.ManageIgnoredUpdates(); @@ -458,8 +459,8 @@ private void MenuAsAdmin_Invoked(object sender, RoutedEventArgs e) private async void MenuUpdateAfterUninstall_Invoked(object sender, RoutedEventArgs e) { - var op = await MainApp.Operations.Uninstall(SelectedItem, elevated: true, ignoreParallel: true); - _ = MainApp.Operations.Install(SelectedItem, elevated: true, ignoreParallel: true, req: op); + var op = await MainApp.Operations.Uninstall(SelectedItem); + _ = MainApp.Operations.Install(SelectedItem, TEL_InstallReferral.ALREADY_INSTALLED, req: op); } private void MenuUninstall_Invoked(object sender, RoutedEventArgs e) diff --git a/src/WindowsPackageManager.Interop/ExternalLibraries.WindowsPackageManager.Interop.csproj b/src/WindowsPackageManager.Interop/ExternalLibraries.WindowsPackageManager.Interop.csproj index 3caa74e90..27a183edd 100644 --- a/src/WindowsPackageManager.Interop/ExternalLibraries.WindowsPackageManager.Interop.csproj +++ b/src/WindowsPackageManager.Interop/ExternalLibraries.WindowsPackageManager.Interop.csproj @@ -4,7 +4,7 @@ net8.0-windows10.0.26100.0 enable 10.0.19041.0 - 10.0.26100.56 + 10.0.26100.57 x64 true WindowsPackageManager.Interop From 0b310d55bd8b786cf243d5a9eed7b5e5bce94768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Mon, 3 Feb 2025 19:58:34 +0100 Subject: [PATCH 3/5] More improvements --- src/UniGetUI/Controls/OperationWidgets/OperationControl.cs | 3 ++- src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/UniGetUI/Controls/OperationWidgets/OperationControl.cs b/src/UniGetUI/Controls/OperationWidgets/OperationControl.cs index b316a2dc2..5f4ce836f 100644 --- a/src/UniGetUI/Controls/OperationWidgets/OperationControl.cs +++ b/src/UniGetUI/Controls/OperationWidgets/OperationControl.cs @@ -24,6 +24,7 @@ using UniGetUI.PackageEngine.Operations; using System.Collections.ObjectModel; using System.Diagnostics; +using UniGetUI.Interface.Telemetry; namespace UniGetUI.Controls.OperationWidgets; @@ -543,7 +544,7 @@ public List GetOperationOptions() details.IconName = IconType.Info_Round; details.Click += (_, _) => { - DialogHelper.ShowPackageDetails(packageOp.Package, OperationType.None); + DialogHelper.ShowPackageDetails(packageOp.Package, OperationType.None, TEL_InstallReferral.DIRECT_SEARCH); }; optionsMenu.Add(details); diff --git a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs index 37ed55bec..323550ce4 100644 --- a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs @@ -461,6 +461,7 @@ public async Task OpenFromFile(string? file = null) string fileContent = await File.ReadAllTextAsync(file); double open_version = await AddFromBundle(fileContent, formatType); + TelemetryHandler.ExportBundle(formatType); HasUnsavedChanges = false; DialogHelper.HideLoadingDialog(); From 8a348c8f16b1565082e754df764c17d012c8fd81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Tue, 4 Feb 2025 11:16:24 +0100 Subject: [PATCH 4/5] Update PackageBundlesPage.cs --- src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs index 323550ce4..813cd7bb6 100644 --- a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs @@ -461,7 +461,7 @@ public async Task OpenFromFile(string? file = null) string fileContent = await File.ReadAllTextAsync(file); double open_version = await AddFromBundle(fileContent, formatType); - TelemetryHandler.ExportBundle(formatType); + TelemetryHandler.ImportBundle(formatType); HasUnsavedChanges = false; DialogHelper.HideLoadingDialog(); From dde95ef6dd02c3c15ed7f7734f65c955e7a2e01c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Tue, 4 Feb 2025 11:37:38 +0100 Subject: [PATCH 5/5] Allow closing when all ops are done (fix #3233) --- src/UniGetUI/MainWindow.xaml.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/UniGetUI/MainWindow.xaml.cs b/src/UniGetUI/MainWindow.xaml.cs index 228b376c9..d1d9cd636 100644 --- a/src/UniGetUI/MainWindow.xaml.cs +++ b/src/UniGetUI/MainWindow.xaml.cs @@ -21,6 +21,7 @@ using Microsoft.Windows.AppNotifications; using UniGetUI.Core.Classes; using UniGetUI.Interface.Enums; +using UniGetUI.PackageEngine.Enums; using UniGetUI.PackageEngine.PackageClasses; using UniGetUI.Pages.DialogPages; @@ -209,7 +210,8 @@ public async void HandleClosingEvent(AppWindow sender, AppWindowClosingEventArgs } else { - if (MainApp.Operations._operationList.Count > 0) + if (MainApp.Operations._operationList.Any() + && MainApp.Operations._operationList.Where(x => x.Operation.Status is OperationStatus.Running or OperationStatus.InQueue).Any()) { args.Cancel = true; ContentDialog d = new()