diff --git a/src/DynamoCoreWpf/Properties/Resources.Designer.cs b/src/DynamoCoreWpf/Properties/Resources.Designer.cs
index 0dca72d3572..0bfe73c24ca 100644
--- a/src/DynamoCoreWpf/Properties/Resources.Designer.cs
+++ b/src/DynamoCoreWpf/Properties/Resources.Designer.cs
@@ -6540,6 +6540,15 @@ public static string PackageManagerPackageSettingsTab {
}
}
+ ///
+ /// Looks up a localized string similar to New version available.
+ ///
+ public static string PackageManagerPackageUpdateAvailable {
+ get {
+ return ResourceManager.GetString("PackageManagerPackageUpdateAvailable", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Updated.
///
@@ -6675,6 +6684,24 @@ public static string PackageManagerTitle {
}
}
+ ///
+ /// Looks up a localized string similar to Uninstall.
+ ///
+ public static string PackageManagerUninstall {
+ get {
+ return ResourceManager.GetString("PackageManagerUninstall", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Update.
+ ///
+ public static string PackageManagerUpdate {
+ get {
+ return ResourceManager.GetString("PackageManagerUpdate", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Once signed in, you can find your published packages here..
///
diff --git a/src/DynamoCoreWpf/Properties/Resources.en-US.resx b/src/DynamoCoreWpf/Properties/Resources.en-US.resx
index 3e4a9f28836..4875701090a 100644
--- a/src/DynamoCoreWpf/Properties/Resources.en-US.resx
+++ b/src/DynamoCoreWpf/Properties/Resources.en-US.resx
@@ -3034,10 +3034,22 @@ This package will be unloaded after the next Dynamo restart.
Install
Used on the package manager search result card. If the package is not installed, the button will say 'Install'.
+
+ Update
+ Used on the package manager search result card when a different version is selected.
+
+
+ Uninstall
+ Used on the package manager search result card when the installed version is selected.
+
Updated
Displays next to the package name in the Package Search window if the package has been updated in the last 30 days.
+
+ New version available
+ Displays next to the package name in the Package Search window if a newer version of the package is available.
+
New
Displays next to the package name in the Package Search window if the package has been added in the last 30 days.
diff --git a/src/DynamoCoreWpf/Properties/Resources.resx b/src/DynamoCoreWpf/Properties/Resources.resx
index 8f20115172f..6fa168fc2b2 100644
--- a/src/DynamoCoreWpf/Properties/Resources.resx
+++ b/src/DynamoCoreWpf/Properties/Resources.resx
@@ -1291,10 +1291,22 @@ Don't worry, you'll have the option to save your work.
Install
Used on the package manager search result card. If the package is not installed, the button will say 'Install'.
+
+ Update
+ Used on the package manager search result card when a different version is selected.
+
+
+ Uninstall
+ Used on the package manager search result card when the installed version is selected.
+
Updated
Displays next to the package name in the Package Search window if the package has been updated in the last 30 days.
+
+ New version available
+ Displays next to the package name in the Package Search window if a newer version of the package is available.
+
New
Displays next to the package name in the Package Search window if the package has been added in the last 30 days.
diff --git a/src/DynamoCoreWpf/PublicAPI.Unshipped.txt b/src/DynamoCoreWpf/PublicAPI.Unshipped.txt
index 7ad7160276a..0036df78e18 100644
--- a/src/DynamoCoreWpf/PublicAPI.Unshipped.txt
+++ b/src/DynamoCoreWpf/PublicAPI.Unshipped.txt
@@ -1364,13 +1364,20 @@ Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.DownloadLa
Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.DownloadLatestToCustomPathCommand.set -> void
Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.Downloads.get -> int
Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.Equals(Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel other) -> bool
+Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.HasUpdateAvailable.get -> bool
+Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.HasUpdateAvailable.set -> void
Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.HasUpvote.get -> bool
Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.Hosts.get -> System.Collections.Generic.List
+Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.InstallActionCommand.get -> System.Windows.Input.ICommand
+Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.InstallActionText.get -> string
Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.IsDeprecated.get -> bool
Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.IsEnabledForInstall.get -> bool
+Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.IsInstalledFallback.get -> bool
+Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.IsInstalledVersionSelected.get -> bool
Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.IsOnwer.get -> bool
Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.IsSelectedVersionCompatible.get -> bool?
Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.IsSelectedVersionCompatible.set -> void
+Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.IsUninstallState.get -> bool
Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.LatestVersion.get -> string
Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.LatestVersionCreated.get -> string
Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.Maintainers.get -> string
@@ -5160,6 +5167,9 @@ static Dynamo.Wpf.Properties.Resources.NodeAutoCompleteToolTip.get -> string
static Dynamo.Wpf.Properties.Resources.OfflineStatusTooltip.get -> string
static Dynamo.Wpf.Properties.Resources.OnlineStatusTooltip.get -> string
static Dynamo.Wpf.Properties.Resources.PackageDuplicateAssembliesFoundMessage.get -> string
+static Dynamo.Wpf.Properties.Resources.PackageManagerPackageUpdateAvailable.get -> string
+static Dynamo.Wpf.Properties.Resources.PackageManagerUninstall.get -> string
+static Dynamo.Wpf.Properties.Resources.PackageManagerUpdate.get -> string
static Dynamo.Wpf.Properties.Resources.PreferencesViewEnableNodeAutoCompleteNewUI.get -> string
static Dynamo.Wpf.Properties.Resources.PreferencesViewEnableNodeAutoCompleteNewUITooltipText.get -> string
static Dynamo.Wpf.Properties.Resources.NodeContextMenuEnablePeriodicUpdate.get -> string
diff --git a/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerSearchElementViewModel.cs b/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerSearchElementViewModel.cs
index fecf1340d3c..2f016eefa59 100644
--- a/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerSearchElementViewModel.cs
+++ b/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerSearchElementViewModel.cs
@@ -7,6 +7,7 @@
using System.Windows.Data;
using System.Windows.Input;
using Dynamo.ViewModels;
+using Dynamo.Wpf.Properties;
using Dynamo.Wpf.ViewModels;
using Greg.Responses;
using Prism.Commands;
@@ -20,6 +21,10 @@ public class PackageManagerSearchElementViewModel : BrowserItemViewModel, IEquat
public ICommand VisitSiteCommand { get; set; }
public ICommand VisitRepositoryCommand { get; set; }
public ICommand DownloadLatestToCustomPathCommand { get; set; }
+ public ICommand InstallActionCommand
+ {
+ get { return IsInstalledVersionSelected ? uninstallCommand : DownloadLatestCommand; }
+ }
///
/// VM IsDeprecated property
@@ -69,6 +74,24 @@ public class PackageManagerSearchElementViewModel : BrowserItemViewModel, IEquat
/// The currently selected version of a package
///
private VersionInformation selectedVersion;
+ private string installedVersion;
+ private bool hasUpdateAvailable;
+ private readonly DelegateCommand uninstallCommand;
+ private Func canUninstall;
+ private bool HasInstalledVersion => !string.IsNullOrEmpty(installedVersion);
+
+ ///
+ /// True when the selected version is installed.
+ ///
+ public bool IsInstalledVersionSelected => SelectedVersion?.IsInstalled == true;
+ ///
+ /// True when the selected installed version cannot be uninstalled.
+ ///
+ public bool IsInstalledFallback => IsInstalledVersionSelected && canUninstall == null;
+ ///
+ /// True when the selected installed version can be uninstalled.
+ ///
+ public bool IsUninstallState => IsInstalledVersionSelected && canUninstall != null;
public bool? IsSelectedVersionCompatible
{
@@ -96,8 +119,71 @@ public VersionInformation SelectedVersion
selectedVersion = value;
// Update the compatibility info so the icon of the currently selected version is updated
- IsSelectedVersionCompatible = selectedVersion.IsCompatible;
+ IsSelectedVersionCompatible = selectedVersion?.IsCompatible;
SearchElementModel.SelectedVersion = selectedVersion;
+ RaisePropertyChanged(nameof(SelectedVersion));
+ RaisePropertyChanged(nameof(InstallActionText));
+ RaisePropertyChanged(nameof(InstallActionCommand));
+ RaisePropertyChanged(nameof(IsInstalledVersionSelected));
+ RaisePropertyChanged(nameof(IsInstalledFallback));
+ RaisePropertyChanged(nameof(IsUninstallState));
+ RefreshUninstallCommandCanExecute();
+ }
+ }
+ }
+
+ ///
+ /// The text to display for the install action button, which changes based on the package's installation state.
+ ///
+ public string InstallActionText
+ {
+ get
+ {
+ if (HasInstalledVersion)
+ {
+ if (IsInstalledVersionSelected)
+ {
+ return IsInstalledFallback
+ ? Resources.PackageDownloadStateInstalled
+ : Resources.PackageManagerUninstall;
+ }
+
+ return Resources.PackageManagerUpdate;
+ }
+
+ return Resources.PackageManagerInstall;
+ }
+ }
+
+ ///
+ /// True if newer version is available for an installed package
+ ///
+ public bool HasUpdateAvailable
+ {
+ get { return hasUpdateAvailable; }
+ set
+ {
+ if (hasUpdateAvailable != value)
+ {
+ hasUpdateAvailable = value;
+ RaisePropertyChanged(nameof(HasUpdateAvailable));
+ }
+ }
+ }
+
+ internal ICommand UninstallCommand => uninstallCommand;
+ internal Func CanUninstall
+ {
+ get { return canUninstall; }
+ set
+ {
+ if (canUninstall != value)
+ {
+ canUninstall = value;
+ RaisePropertyChanged(nameof(InstallActionText));
+ RaisePropertyChanged(nameof(IsInstalledFallback));
+ RaisePropertyChanged(nameof(IsUninstallState));
+ RefreshUninstallCommandCanExecute();
}
}
}
@@ -116,6 +202,7 @@ public PackageManagerSearchElementViewModel(PackageManagerSearchElement element,
this.SearchElementModel = element;
CanInstall = install;
IsEnabledForInstall = isEnabledForInstall;
+ uninstallCommand = new DelegateCommand(OnRequestUninstall, () => CanUninstall?.Invoke() == true);
// Attempts to show the latest compatible version. If no compatible, will return the latest instead.
this.SelectedVersion = this.SearchElementModel.LatestCompatibleVersion;
@@ -128,7 +215,7 @@ public PackageManagerSearchElementViewModel(PackageManagerSearchElement element,
this.DownloadLatestCommand = new DelegateCommand(
() => OnRequestDownload(false),
- () => !SearchElementModel.IsDeprecated && CanInstall);
+ () => !SearchElementModel.IsDeprecated);
this.DownloadLatestToCustomPathCommand = new DelegateCommand(() => OnRequestDownload(true));
this.UpvoteCommand = new DelegateCommand(SearchElementModel.Upvote, () => canLogin);
@@ -143,11 +230,11 @@ private void OnSearchElementModelPropertyChanged(object sender, PropertyChangedE
{
if (e.PropertyName == nameof(SearchElementModel.LatestCompatibleVersion))
{
- this.SelectedVersion = this.SearchElementModel.LatestCompatibleVersion;
+ SetDefaultSelectedVersion();
}
if (e.PropertyName == nameof(SearchElementModel.VersionDetails))
{
- this.VersionInformationList = this.SearchElementModel.VersionDetails;
+ SetDefaultSelectedVersion();
}
}
@@ -191,8 +278,11 @@ public bool CanInstall
internal set
{
- canInstall = value;
- RaisePropertyChanged(nameof(CanInstall));
+ if (canInstall != value)
+ {
+ canInstall = value;
+ RaisePropertyChanged(nameof(CanInstall));
+ }
}
}
@@ -262,6 +352,7 @@ public List VersionInformationList
{
versionInformationList = value;
RaisePropertyChanged(nameof(VersionInformationList));
+ UpdateInstalledVersionFlags();
}
}
}
@@ -278,13 +369,75 @@ public ICollectionView ReversedVersionInformationList
}
}
+ internal void UpdateInstalledVersion(string version, bool setDefaultSelection)
+ {
+ installedVersion = version;
+ UpdateInstalledVersionFlags();
+
+ if (setDefaultSelection)
+ {
+ SetDefaultSelectedVersion();
+ }
+ RaisePropertyChanged(nameof(InstallActionText));
+ RaisePropertyChanged(nameof(InstallActionCommand));
+ RaisePropertyChanged(nameof(IsInstalledVersionSelected));
+ RaisePropertyChanged(nameof(IsInstalledFallback));
+ RaisePropertyChanged(nameof(IsUninstallState));
+ RefreshUninstallCommandCanExecute();
+ }
+
+ private void SetDefaultSelectedVersion()
+ {
+ var defaultVersion = GetDefaultSelectedVersion();
+ if (defaultVersion != null && SelectedVersion != defaultVersion)
+ {
+ SelectedVersion = defaultVersion;
+ }
+ }
+
+ private VersionInformation GetDefaultSelectedVersion()
+ {
+ if (!string.IsNullOrEmpty(installedVersion))
+ {
+ var installedInfo = VersionInformationList?.FirstOrDefault(v => v.Version == installedVersion);
+ if (installedInfo != null)
+ {
+ return installedInfo;
+ }
+ }
+
+ return SearchElementModel?.LatestCompatibleVersion;
+ }
+
+ private void UpdateInstalledVersionFlags()
+ {
+ if (VersionInformationList == null) return;
+
+ foreach (var versionInfo in VersionInformationList)
+ {
+ versionInfo.IsInstalled = !string.IsNullOrEmpty(installedVersion) &&
+ string.Equals(versionInfo.Version, installedVersion, StringComparison.OrdinalIgnoreCase);
+ }
+
+ RaisePropertyChanged(nameof(ReversedVersionInformationList));
+ }
+
+ private void RefreshUninstallCommandCanExecute()
+ {
+ if (uninstallCommand is DelegateCommand delegateCommand)
+ {
+ delegateCommand.RaiseCanExecuteChanged();
+ }
+ }
+
private List CustomPackageFolders;
private bool? isSelectedVersionCompatible;
public delegate void PackageSearchElementDownloadHandler(
PackageManagerSearchElement element, PackageVersion version, string downloadPath = null);
public event PackageSearchElementDownloadHandler RequestDownload;
-
+ internal event Action RequestUninstall;
+
public void OnRequestDownload(PackageVersion version, bool downloadToCustomPath)
{
string downloadPath = String.Empty;
@@ -301,9 +454,19 @@ public void OnRequestDownload(PackageVersion version, bool downloadToCustomPath)
RequestDownload(this.SearchElementModel, version, downloadPath);
}
+ private void OnRequestUninstall()
+ {
+ if (RequestUninstall != null)
+ {
+ RequestUninstall(this);
+ }
+ }
+
private void OnRequestDownload(bool downloadToCustomPath)
{
- var version = this.SearchElementModel.Header.versions.First(x => x.version.Equals(SelectedVersion.Version));
+ var version = this.SearchElementModel?.Header?.versions
+ ?.FirstOrDefault(x => x.version.Equals(SelectedVersion.Version));
+ if (version == null) return;
string downloadPath = String.Empty;
diff --git a/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerSearchViewModel.cs b/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerSearchViewModel.cs
index 1ea7c92f3be..eb9d0fbb5c3 100644
--- a/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerSearchViewModel.cs
+++ b/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerSearchViewModel.cs
@@ -496,6 +496,203 @@ internal bool CanInstallPackage(PackageDownloadHandle dh)
}
}
+ private void UpdateInstallState(PackageManagerSearchElementViewModel element, bool setDefaultSelection = false)
+ {
+ if (element?.SearchElementModel == null)
+ {
+ return;
+ }
+
+ var installedPackages = PackageManagerClientViewModel.PackageManagerExtension.PackageLoader.LocalPackages
+ .Where(x => (x.Name == element.SearchElementModel.Name) && !x.BuiltInPackage)
+ .ToList();
+
+ var installedVersion = installedPackages.Any() ? GetNewestInstalledVersion(installedPackages) : null;
+ element.UpdateInstalledVersion(installedVersion, setDefaultSelection);
+ element.HasUpdateAvailable = IsUpdateAvailable(installedVersion, element.VersionInformationList);
+
+ var hasBlockingDownload = PackageManagerClientViewModel.Downloads.Any(handle =>
+ handle.Name == element.SearchElementModel.Name &&
+ (handle.DownloadState == PackageDownloadHandle.State.Downloaded ||
+ handle.DownloadState == PackageDownloadHandle.State.Downloading ||
+ handle.DownloadState == PackageDownloadHandle.State.Installing));
+ if (hasBlockingDownload)
+ {
+ element.CanInstall = false;
+ return;
+ }
+ if (!installedPackages.Any())
+ {
+ element.CanInstall = true;
+ return;
+ }
+ element.CanInstall = false;
+ }
+
+ private void UninstallPackage(PackageManagerSearchElementViewModel element)
+ {
+ var installedPackage = GetInstalledPackageForSelectedVersion(element);
+ if (installedPackage == null)
+ {
+ return;
+ }
+
+ var dynamoViewModel = PackageManagerClientViewModel?.DynamoViewModel;
+ if (dynamoViewModel == null)
+ {
+ return;
+ }
+
+ if (installedPackage.LoadedAssemblies.Any())
+ {
+ var message = string.Format(Resources.MessageNeedToRestartAfterDelete,
+ dynamoViewModel.BrandingResourceProvider.ProductName);
+ var title = Resources.MessageNeedToRestartAfterDeleteTitle;
+ var result = MessageBoxService.Show(dynamoViewModel.Owner, message, title,
+ MessageBoxButton.OKCancel, MessageBoxImage.Exclamation);
+ if (result == MessageBoxResult.Cancel || result == MessageBoxResult.None)
+ {
+ return;
+ }
+ }
+
+ var confirmResult = MessageBoxService.Show(dynamoViewModel.Owner,
+ string.Format(Resources.MessageConfirmToDeletePackage, installedPackage.Name),
+ Resources.MessageNeedToRestartAfterDeleteTitle,
+ MessageBoxButton.YesNo, MessageBoxImage.Question);
+
+ if (confirmResult == MessageBoxResult.No || confirmResult == MessageBoxResult.None)
+ {
+ return;
+ }
+
+ try
+ {
+ installedPackage.UninstallCore(dynamoViewModel.Model.CustomNodeManager,
+ PackageManagerClientViewModel.PackageManagerExtension.PackageLoader,
+ dynamoViewModel.Model.PreferenceSettings);
+ }
+ catch (Exception ex)
+ {
+ var baseMessage = string.Format(Resources.MessageFailedToDelete,
+ dynamoViewModel.BrandingResourceProvider.ProductName);
+ var detailedMessage = baseMessage + Environment.NewLine + ex.Message;
+
+ MessageBoxService.Show(dynamoViewModel.Owner,
+ detailedMessage,
+ Resources.DeleteFailureMessageBoxTitle,
+ MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ finally
+ {
+ UpdateInstallState(element);
+ }
+ }
+
+ private bool CanUninstallPackage(PackageManagerSearchElementViewModel element)
+ {
+ var installedPackage = GetInstalledPackageForSelectedVersion(element);
+ if (installedPackage == null)
+ {
+ return false;
+ }
+
+ var dynamoModel = PackageManagerClientViewModel?.DynamoViewModel?.Model;
+ if (dynamoModel == null)
+ {
+ return false;
+ }
+
+ if (!installedPackage.InUse(dynamoModel) || installedPackage.LoadedAssemblies.Any())
+ {
+ return IsLoadedWithNoScheduledOperation(installedPackage);
+ }
+
+ return false;
+ }
+
+ private static bool IsLoadedWithNoScheduledOperation(Package package)
+ {
+ return package.BuiltInPackage
+ ? package.LoadState.State != PackageLoadState.StateTypes.Unloaded &&
+ package.LoadState.ScheduledState != PackageLoadState.ScheduledTypes.ScheduledForUnload
+ : package.LoadState.ScheduledState != PackageLoadState.ScheduledTypes.ScheduledForDeletion;
+ }
+
+ private Package GetInstalledPackageForSelectedVersion(PackageManagerSearchElementViewModel element)
+ {
+ if (element?.SelectedVersion?.IsInstalled != true || element.SearchElementModel == null)
+ {
+ return null;
+ }
+
+ var installedPackages = PackageManagerClientViewModel.PackageManagerExtension.PackageLoader.LocalPackages
+ .Where(x => x.Name == element.SearchElementModel.Name && !x.BuiltInPackage)
+ .ToList();
+
+ if (!installedPackages.Any())
+ {
+ return null;
+ }
+
+ return installedPackages.FirstOrDefault(pkg =>
+ string.Equals(pkg.VersionName, element.SelectedVersion.Version, StringComparison.OrdinalIgnoreCase));
+ }
+
+ private static string GetNewestInstalledVersion(IEnumerable installedPackages)
+ {
+ if (installedPackages == null)
+ {
+ return null;
+ }
+
+ var parsedVersions = installedPackages
+ .Select(pkg => new { Version = pkg.VersionName, Parsed = VersionUtilities.Parse(pkg.VersionName) })
+ .Where(x => x.Parsed != null)
+ .OrderBy(x => x.Parsed)
+ .LastOrDefault();
+
+ if (parsedVersions != null)
+ {
+ return parsedVersions.Version;
+ }
+
+ return installedPackages.Select(pkg => pkg.VersionName).FirstOrDefault();
+ }
+
+ private static bool IsUpdateAvailable(string installedVersion, IEnumerable availableVersions)
+ {
+ if (string.IsNullOrEmpty(installedVersion) || availableVersions == null)
+ {
+ return false;
+ }
+
+ var parsedInstalledVersion = VersionUtilities.Parse(installedVersion);
+ if (parsedInstalledVersion == null)
+ {
+ return false;
+ }
+
+ var newestAvailableVersion = availableVersions
+ .Select(version => VersionUtilities.Parse(version.Version))
+ .Where(parsedVersion => parsedVersion != null)
+ .OrderBy(parsedVersion => parsedVersion)
+ .LastOrDefault();
+
+ if (newestAvailableVersion == null)
+ {
+ return false;
+ }
+
+ return newestAvailableVersion > parsedInstalledVersion;
+ }
+
+ private PackageManagerSearchElementViewModel GetSearchElementViewModelByName(string name)
+ {
+ return SearchResults?.FirstOrDefault(x => x.SearchElementModel.Name == name)
+ ?? SearchMyResults?.FirstOrDefault(x => x.SearchElementModel.Name == name);
+ }
+
public PackageSearchState _searchState; // TODO: Set private for 3.0.
///
@@ -724,6 +921,7 @@ private void PopulateMyPackages()
var p = GetSearchElementViewModel(pkg, true);
p.RequestDownload += this.PackageOnExecuted;
+ p.RequestUninstall += SearchElementViewModelOnRequestUninstall;
p.IsOnwer = true;
myPackages.Add(p);
@@ -739,6 +937,8 @@ private void ClearMySearchResults()
{
ele.RequestDownload -= PackageOnExecuted;
ele.RequestShowFileDialog -= OnRequestShowFileDialog;
+ ele.PropertyChanged -= SearchElementViewModelOnPropertyChanged;
+ ele.RequestUninstall -= SearchElementViewModelOnRequestUninstall;
}
this.SearchMyResults = null;
@@ -1239,6 +1439,8 @@ internal void AddToSearchResults(PackageManagerSearchElementViewModel element)
{
element.RequestDownload += this.PackageOnExecuted;
element.RequestShowFileDialog += this.OnRequestShowFileDialog;
+ element.PropertyChanged += SearchElementViewModelOnPropertyChanged;
+ element.RequestUninstall += SearchElementViewModelOnRequestUninstall;
this.SearchResults.Add(element);
}
@@ -1250,10 +1452,26 @@ internal void ClearSearchResults()
{
ele.RequestDownload -= PackageOnExecuted;
ele.RequestShowFileDialog -= OnRequestShowFileDialog;
+ ele.PropertyChanged -= SearchElementViewModelOnPropertyChanged;
+ ele.RequestUninstall -= SearchElementViewModelOnRequestUninstall;
+
ele?.Dispose();
}
this.SearchResults.Clear();
}
+ private void SearchElementViewModelOnRequestUninstall(PackageManagerSearchElementViewModel element)
+ {
+ UninstallPackage(element);
+ }
+
+ private void SearchElementViewModelOnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (sender is PackageManagerSearchElementViewModel element &&
+ e.PropertyName == nameof(PackageManagerSearchElementViewModel.SelectedVersion))
+ {
+ UpdateInstallState(element);
+ }
+ }
internal void PackageOnExecuted(PackageManagerSearchElement element, PackageVersion version, string downloadPath)
{
@@ -1297,10 +1515,9 @@ void canInstallHandler(object o, PropertyChangedEventArgs eArgs)
// the Downloads collection before Download/Install begins.
if (eArgs.PropertyName == nameof(PackageDownloadHandle.DownloadState))
{
- PackageManagerSearchElementViewModel sr = SearchResults.FirstOrDefault(x => x.SearchElementModel.Name == handle.Name);
- if (sr == null) return;
-
- sr.CanInstall = CanInstallPackage(o as PackageDownloadHandle);
+ var searchElement = GetSearchElementViewModelByName(handle.Name);
+ if (searchElement == null) return;
+ UpdateInstallState(searchElement);
}
}
@@ -1649,10 +1866,15 @@ private PackageManagerSearchElementViewModel GetViewModelForPackageSearchElement
private PackageManagerSearchElementViewModel GetSearchElementViewModel(PackageManagerSearchElement package, bool bypassCustomPackageLocations = false)
{
var isEnabledForInstall = bypassCustomPackageLocations || !(Preferences as IDisablePackageLoadingPreferences).DisableCustomPackageLocations;
- return new PackageManagerSearchElementViewModel(package,
+ var viewModel = new PackageManagerSearchElementViewModel(package,
PackageManagerClientViewModel.AuthenticationManager.HasAuthProvider,
CanInstallPackage(package.Name),
isEnabledForInstall);
+
+ viewModel.CanUninstall = () => CanUninstallPackage(viewModel);
+ UpdateInstallState(viewModel, true);
+
+ return viewModel;
}
///
diff --git a/src/DynamoCoreWpf/Views/PackageManager/Controls/PackageManagerPackagesControl.xaml b/src/DynamoCoreWpf/Views/PackageManager/Controls/PackageManagerPackagesControl.xaml
index 91f81833522..55c11334742 100644
--- a/src/DynamoCoreWpf/Views/PackageManager/Controls/PackageManagerPackagesControl.xaml
+++ b/src/DynamoCoreWpf/Views/PackageManager/Controls/PackageManagerPackagesControl.xaml
@@ -116,6 +116,25 @@
+
+
+
+
+
@@ -306,13 +325,15 @@
public bool? IsCompatible { get; set; }
+ ///
+ /// Indicates whether this version is currently installed locally.
+ ///
+ public bool IsInstalled { get; set; }
+
///
/// A helper method to determine the compatibility of a specific package version from the provided version details.
///