Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Expand Up @@ -104,7 +104,7 @@ public PackageDetailsWindow(
UpdatePips();
}, DispatcherPriority.Loaded);

MainActionButton.Click += (_, _) => OnMainAction();
MainActionButton.Click += (_, _) => _ = OnMainActionAsync();
ActionVariantsButton.Flyout = BuildActionFlyout();
InstallOptionsSaveButton.Click += (_, _) => _ = SaveInstallOptionsAndRefreshAsync();
ContributeButton.Click += (_, _) => OpenUrl(ContributeUrl);
Expand Down Expand Up @@ -1093,19 +1093,28 @@ private MenuFlyout BuildActionFlyout()
return flyout;
}

private void OnMainAction()
private async Task OnMainActionAsync()
{
if (!await ConfirmUninstallAsync(_vm.OperationRole)) return;
ShouldProceedWithOperation = true;
Close();
}

// Uninstalling cannot be undone: confirm on top of this dialog (the main window stacks them), which
// stays open on Cancel. Covers every caller (Installed page, catalog) and the as-admin / interactive /
// remove-data variants.
private async Task<bool> ConfirmUninstallAsync(OperationType role)
=> role is not OperationType.Uninstall
|| (MainWindow.Instance is { } window && await UninstallConfirmationDialog.ConfirmAsync(window, _vm.Package));

private async Task LaunchAndClose(
OperationType role,
bool? elevated = null,
bool? interactive = null,
bool? no_integrity = null,
bool? remove_data = null)
{
if (!await ConfirmUninstallAsync(role)) return;
Close();

var pkg = _vm.Package;
Expand Down
34 changes: 25 additions & 9 deletions src/UniGetUI.Avalonia/Views/SoftwarePages/InstalledPackagesPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,15 @@ protected override void GenerateToolBar(PackagesPageViewModel vm)
var downloadInstallers = new MenuItem { Header = CoreTools.Translate("Download selected installers") };

SetMainButton("delete", CoreTools.Translate("Uninstall selection"), () =>
_ = LaunchUninstall(vm.FilteredPackages.GetCheckedPackages()));
_ = ConfirmAndLaunchUninstall(vm.FilteredPackages.GetCheckedPackages()));

SetMainButtonDropdown(new MenuFlyout
{
Items = { uninstallAsAdmin, uninstallInteractive, new Separator(), downloadInstallers },
});

uninstallAsAdmin.Click += (_, _) => _ = LaunchUninstall(vm.FilteredPackages.GetCheckedPackages(), elevated: true);
uninstallInteractive.Click += (_, _) => _ = LaunchUninstall(vm.FilteredPackages.GetCheckedPackages(), interactive: true);
uninstallAsAdmin.Click += (_, _) => _ = ConfirmAndLaunchUninstall(vm.FilteredPackages.GetCheckedPackages(), elevated: true);
uninstallInteractive.Click += (_, _) => _ = ConfirmAndLaunchUninstall(vm.FilteredPackages.GetCheckedPackages(), interactive: true);
downloadInstallers.Click += (_, _) => _ = AvaloniaPackageOperationHelper.DownloadSelectedAsync(
vm.FilteredPackages.GetCheckedPackages(), TEL_InstallReferral.ALREADY_INSTALLED);

Expand Down Expand Up @@ -144,7 +144,7 @@ protected override void GenerateToolBar(PackagesPageViewModel vm)
Header = ShortcutHeader(CoreTools.Translate("Uninstall"), MainActionShortcut),
Icon = LoadMenuIcon("delete"),
};
menuUninstall.Click += (_, _) => _ = LaunchUninstall([SelectedItem!]);
menuUninstall.Click += (_, _) => _ = ConfirmAndLaunchUninstall([SelectedItem!]);

_menuInstallationOptions = new MenuItem
{
Expand All @@ -169,21 +169,21 @@ protected override void GenerateToolBar(PackagesPageViewModel vm)
Icon = LoadMenuIcon("uac"),
IsVisible = OperatingSystem.IsWindows(),
};
_menuAsAdmin.Click += (_, _) => _ = LaunchUninstall([SelectedItem!], elevated: true);
_menuAsAdmin.Click += (_, _) => _ = ConfirmAndLaunchUninstall([SelectedItem!], elevated: true);

_menuInteractive = new MenuItem
{
Header = CoreTools.Translate("Interactive uninstall"),
Icon = LoadMenuIcon("interactive"),
};
_menuInteractive.Click += (_, _) => _ = LaunchUninstall([SelectedItem!], interactive: true);
_menuInteractive.Click += (_, _) => _ = ConfirmAndLaunchUninstall([SelectedItem!], interactive: true);

_menuRemoveData = new MenuItem
{
Header = CoreTools.Translate("Uninstall and remove data"),
Icon = LoadMenuIcon("close_round"),
};
_menuRemoveData.Click += (_, _) => _ = LaunchUninstall([SelectedItem!], remove_data: true);
_menuRemoveData.Click += (_, _) => _ = ConfirmAndLaunchUninstall([SelectedItem!], remove_data: true);

_menuUpdate = new MenuItem
{
Expand Down Expand Up @@ -310,7 +310,7 @@ protected override void WhenShowingContextMenu(IPackage package)
protected override void PerformMainPackageAction(IPackage? package)
{
if (package is null) return;
_ = LaunchUninstall([package]);
_ = ConfirmAndLaunchUninstall([package]);
}

protected override async Task ShowDetailsForPackage(IPackage? package)
Expand All @@ -337,7 +337,7 @@ protected override async Task ShowInstallationOptionsForPackage(IPackage? packag
await InstallOptionsFactory.SaveForPackageAsync(opts, package);

if (dialog.ShouldProceedWithOperation)
await LaunchUninstall([package]);
await ConfirmAndLaunchUninstall([package]);
}

// ─── WinGet malfunction banner ────────────────────────────────────────────
Expand Down Expand Up @@ -383,6 +383,22 @@ private static async Task ExportSelectionToBundleAsync(PackagesPageViewModel vm)
await PackageBundlesLoader.Instance.AddPackagesAsync(packages);
}

// Uninstalling cannot be undone, so every page entry point confirms first: toolbar, context menu,
// Ctrl+Enter, double-click and the options dialog. The details window confirms in its own window,
// and the catalog before calling LaunchUninstall, so neither asks twice.
private static async Task ConfirmAndLaunchUninstall(
IEnumerable<IPackage> packages,
bool? elevated = null,
bool? interactive = null,
bool? remove_data = null)
{
var list = packages.ToList();
if (list.Count == 0 || MainWindow.Instance is not { } window) return;
if (!await UninstallConfirmationDialog.ConfirmAsync(window, list)) return;

await LaunchUninstall(list, elevated, interactive, remove_data);
}

internal static async Task LaunchUninstall(
IEnumerable<IPackage> packages,
bool? elevated = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,9 +356,14 @@ private static async Task LaunchUpdate(
}
}

// Every row on this page is checked by default, so one click here could uninstall every package with an update.
private static async Task LaunchUninstallFromUpdates(IEnumerable<IPackage> packages)
{
foreach (var pkg in packages)
var list = packages.ToList();
if (list.Count == 0 || MainWindow.Instance is not { } window) return;
if (!await UninstallConfirmationDialog.ConfirmAsync(window, list)) return;

foreach (var pkg in list)
{
var opts = await InstallOptionsFactory.LoadApplicableAsync(pkg);
if (PackageOperation.HasPendingOperation(pkg, OperationType.Uninstall)) continue;
Expand Down
Loading