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
27 changes: 27 additions & 0 deletions src/DynamoCoreWpf/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions src/DynamoCoreWpf/Properties/Resources.en-US.resx
Original file line number Diff line number Diff line change
Expand Up @@ -3034,10 +3034,22 @@ This package will be unloaded after the next Dynamo restart.</value>
<value>Install</value>
<comment>Used on the package manager search result card. If the package is not installed, the button will say 'Install'.</comment>
</data>
<data name="PackageManagerUpdate" xml:space="preserve">
<value>Update</value>
<comment>Used on the package manager search result card when a different version is selected.</comment>
</data>
<data name="PackageManagerUninstall" xml:space="preserve">
<value>Uninstall</value>
<comment>Used on the package manager search result card when the installed version is selected.</comment>
</data>
<data name="PackageManagerPackageUpdated" xml:space="preserve">
<value>Updated</value>
<comment>Displays next to the package name in the Package Search window if the package has been updated in the last 30 days.</comment>
</data>
<data name="PackageManagerPackageUpdateAvailable" xml:space="preserve">
<value>New version available</value>
<comment>Displays next to the package name in the Package Search window if a newer version of the package is available.</comment>
</data>
<data name="PackageManagerPackageNew" xml:space="preserve">
<value>New</value>
<comment>Displays next to the package name in the Package Search window if the package has been added in the last 30 days.</comment>
Expand Down
12 changes: 12 additions & 0 deletions src/DynamoCoreWpf/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1291,10 +1291,22 @@ Don't worry, you'll have the option to save your work.</value>
<value>Install</value>
<comment>Used on the package manager search result card. If the package is not installed, the button will say 'Install'.</comment>
</data>
<data name="PackageManagerUpdate" xml:space="preserve">
<value>Update</value>
<comment>Used on the package manager search result card when a different version is selected.</comment>
</data>
<data name="PackageManagerUninstall" xml:space="preserve">
<value>Uninstall</value>
<comment>Used on the package manager search result card when the installed version is selected.</comment>
</data>
<data name="PackageManagerPackageUpdated" xml:space="preserve">
<value>Updated</value>
<comment>Displays next to the package name in the Package Search window if the package has been updated in the last 30 days.</comment>
</data>
<data name="PackageManagerPackageUpdateAvailable" xml:space="preserve">
<value>New version available</value>
<comment>Displays next to the package name in the Package Search window if a newer version of the package is available.</comment>
</data>
<data name="PackageManagerPackageNew" xml:space="preserve">
<value>New</value>
<comment>Displays next to the package name in the Package Search window if the package has been added in the last 30 days.</comment>
Expand Down
10 changes: 10 additions & 0 deletions src/DynamoCoreWpf/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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<string>
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
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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; }
}

/// <summary>
/// VM IsDeprecated property
Expand Down Expand Up @@ -69,6 +74,24 @@ public class PackageManagerSearchElementViewModel : BrowserItemViewModel, IEquat
/// The currently selected version of a package
/// </summary>
private VersionInformation selectedVersion;
private string installedVersion;
private bool hasUpdateAvailable;
private readonly DelegateCommand uninstallCommand;
private Func<bool> canUninstall;
private bool HasInstalledVersion => !string.IsNullOrEmpty(installedVersion);

/// <summary>
/// True when the selected version is installed.
/// </summary>
public bool IsInstalledVersionSelected => SelectedVersion?.IsInstalled == true;
/// <summary>
/// True when the selected installed version cannot be uninstalled.
/// </summary>
public bool IsInstalledFallback => IsInstalledVersionSelected && canUninstall == null;
/// <summary>
/// True when the selected installed version can be uninstalled.
/// </summary>
public bool IsUninstallState => IsInstalledVersionSelected && canUninstall != null;

public bool? IsSelectedVersionCompatible
{
Expand Down Expand Up @@ -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();
}
}
}

/// <summary>
/// The text to display for the install action button, which changes based on the package's installation state.
/// </summary>
public string InstallActionText
{
get
{
if (HasInstalledVersion)
{
if (IsInstalledVersionSelected)
{
return IsInstalledFallback
? Resources.PackageDownloadStateInstalled
: Resources.PackageManagerUninstall;
}

return Resources.PackageManagerUpdate;
}

return Resources.PackageManagerInstall;
}
}

/// <summary>
/// True if newer version is available for an installed package
/// </summary>
public bool HasUpdateAvailable
{
get { return hasUpdateAvailable; }
set
{
if (hasUpdateAvailable != value)
{
hasUpdateAvailable = value;
RaisePropertyChanged(nameof(HasUpdateAvailable));
}
}
}

internal ICommand UninstallCommand => uninstallCommand;
internal Func<bool> CanUninstall
{
get { return canUninstall; }
set
{
if (canUninstall != value)
{
canUninstall = value;
RaisePropertyChanged(nameof(InstallActionText));
RaisePropertyChanged(nameof(IsInstalledFallback));
RaisePropertyChanged(nameof(IsUninstallState));
RefreshUninstallCommandCanExecute();
}
}
}
Expand All @@ -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;
Expand All @@ -128,7 +215,7 @@ public PackageManagerSearchElementViewModel(PackageManagerSearchElement element,

this.DownloadLatestCommand = new DelegateCommand(
() => OnRequestDownload(false),
() => !SearchElementModel.IsDeprecated && CanInstall);
Copy link
Contributor

@zeusongit zeusongit Jan 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we removing CanInstall from this check?
Asking as that may lead to unexpected change somewhere where this may be expected

() => !SearchElementModel.IsDeprecated);
this.DownloadLatestToCustomPathCommand = new DelegateCommand(() => OnRequestDownload(true));

this.UpvoteCommand = new DelegateCommand(SearchElementModel.Upvote, () => canLogin);
Expand All @@ -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();
}
}

Expand Down Expand Up @@ -191,8 +278,11 @@ public bool CanInstall

internal set
{
canInstall = value;
RaisePropertyChanged(nameof(CanInstall));
if (canInstall != value)
{
canInstall = value;
RaisePropertyChanged(nameof(CanInstall));
}
}
}

Expand Down Expand Up @@ -262,6 +352,7 @@ public List<VersionInformation> VersionInformationList
{
versionInformationList = value;
RaisePropertyChanged(nameof(VersionInformationList));
UpdateInstalledVersionFlags();
}
}
}
Expand All @@ -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<String> CustomPackageFolders;
private bool? isSelectedVersionCompatible;

public delegate void PackageSearchElementDownloadHandler(
PackageManagerSearchElement element, PackageVersion version, string downloadPath = null);
public event PackageSearchElementDownloadHandler RequestDownload;

internal event Action<PackageManagerSearchElementViewModel> RequestUninstall;

public void OnRequestDownload(PackageVersion version, bool downloadToCustomPath)
{
string downloadPath = String.Empty;
Expand All @@ -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;

Expand Down
Loading
Loading