Skip to content
5 changes: 5 additions & 0 deletions doc/distrib/xml/en-US/DSCoreNodes.xml

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

1 change: 1 addition & 0 deletions src/DynamoCore/Configuration/ExecutionSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public ExecutionSession(Scheduler.UpdateGraphAsyncTask updateTask, DynamoModel m
parameters[ParameterKeys.LastExecutionDuration] = new TimeSpan(updateTask.ExecutionEndTime.TickCount - updateTask.ExecutionStartTime.TickCount);
parameters[ParameterKeys.PackagePaths] = pathManager.PackagesDirectories;
parameters[ParameterKeys.Logger] = model.Logger;
parameters[ParameterKeys.NoNetworkMode] = model.NoNetworkMode;
}

/// <summary>
Expand Down
4 changes: 2 additions & 2 deletions src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2810,12 +2810,12 @@ internal void ShowPackageManager(object parameters)

internal bool CanShowPackageManagerSearch(object parameters)
{
return !model.IsServiceMode;
return !model.IsServiceMode && !model.NoNetworkMode;
}

internal bool CanShowPackageManager(object parameters)
{
return !model.IsServiceMode;
return !model.IsServiceMode && !model.NoNetworkMode;
}

/// <summary>
Expand Down
17 changes: 17 additions & 0 deletions src/DynamoCoreWpf/ViewModels/Menu/PreferencesViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1346,6 +1346,21 @@ private void AddPythonEnginesOptions()
/// </summary>
public TrustedPathViewModel TrustedPathsViewModel { get; set; }

//public bool NoNetworkMode => dynamoViewModel.Model.NoNetworkMode;
Comment thread
aparajit-pratap marked this conversation as resolved.
Outdated
private bool noNetworkMode;
public bool NoNetworkMode
{
get => noNetworkMode;
private set
{
if (noNetworkMode != value)
{
noNetworkMode = value;
RaisePropertyChanged(nameof(NoNetworkMode));
}
}
}

/// <summary>
/// Returns a boolean value indicating if the Settings importing was successful or not
/// </summary>
Expand Down Expand Up @@ -1469,6 +1484,8 @@ public PreferencesViewModel(DynamoViewModel dynamoViewModel)
this.pythonScriptEditorTextOptions = dynamoViewModel.PythonScriptEditorTextOptions;
this.dynamoViewModel = dynamoViewModel;

NoNetworkMode = dynamoViewModel.Model.NoNetworkMode;

if (dynamoViewModel.PackageManagerClientViewModel != null)
{
installedPackagesViewModel = new InstalledPackagesViewModel(dynamoViewModel, dynamoViewModel.PackageManagerClientViewModel.PackageManagerExtension.PackageLoader);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ public void PublishCurrentWorkspace(object m)

public bool CanPublishCurrentWorkspace(object m)
{
return DynamoViewModel.Model.CurrentWorkspace is CustomNodeWorkspaceModel && AuthenticationManager.HasAuthProvider;
return DynamoViewModel.Model.CurrentWorkspace is CustomNodeWorkspaceModel && AuthenticationManager.HasAuthProvider && !Model.NoNetworkMode;
}

public void PublishNewPackage(object m)
Expand All @@ -363,7 +363,7 @@ public void PublishNewPackage(object m)

public bool CanPublishNewPackage(object m)
{
return AuthenticationManager.HasAuthProvider;
return AuthenticationManager.HasAuthProvider && !Model.NoNetworkMode;
}

public void PublishCustomNode(Function m)
Expand Down Expand Up @@ -393,7 +393,7 @@ public void PublishCustomNode(Function m)

public bool CanPublishCustomNode(Function m)
{
return AuthenticationManager.HasAuthProvider && m != null;
return AuthenticationManager.HasAuthProvider && m != null && !Model.NoNetworkMode;
}

public void PublishSelectedNodes(object m)
Expand Down Expand Up @@ -453,7 +453,7 @@ public void PublishSelectedNodes(object m)
public bool CanPublishSelectedNodes(object m)
{
return DynamoSelection.Instance.Selection.Count > 0 &&
DynamoSelection.Instance.Selection.All(x => x is Function) && AuthenticationManager.HasAuthProvider; ;
DynamoSelection.Instance.Selection.All(x => x is Function) && AuthenticationManager.HasAuthProvider && !Model.NoNetworkMode;
}

private void ShowNodePublishInfo()
Expand Down
15 changes: 14 additions & 1 deletion src/DynamoCoreWpf/Views/Menu/PreferencesView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
xmlns:fa="clr-namespace:FontAwesome5;assembly=FontAwesome5.Net"
xmlns:packagemanager="clr-namespace:Dynamo.Wpf.Views.PackageManager"
xmlns:trustedpaths="clr-namespace:Dynamo.Wpf.Views"
xmlns:converters="clr-namespace:Dynamo.Controls;assembly=DynamoCoreWpf"
xmlns:wpfControls="clr-namespace:Dynamo.Wpf.Controls"
d:DataContext="{d:DesignInstance Type=viewModels:PreferencesViewModel}"
WindowStartupLocation="CenterOwner"
Expand Down Expand Up @@ -1949,7 +1950,19 @@
<Hyperlink Click="OnInstalledPackagesHyperlinkClicked"
Foreground="{StaticResource TextBlockLinkForegroundColor}">
<TextBlock Name="PackageManagerLink"
Text="{x:Static p:Resources.InstalledPackagePartialHyperlinkMessage}" />
Text="{x:Static p:Resources.InstalledPackagePartialHyperlinkMessage}"
IsHitTestVisible="{Binding NoNetworkMode, Converter={StaticResource InverseBooleanConverter}}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<!--<Setter Property="Foreground" Value="Black" />-->
<Style.Triggers>
<DataTrigger Binding="{Binding NoNetworkMode}" Value="True">
<Setter Property="Foreground" Value="Gray" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Hyperlink>
<Run>.</Run>
</TextBlock>
Expand Down
42 changes: 38 additions & 4 deletions src/DynamoPackages/PackageManagerClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,24 @@ public string BaseUrl
get { return this.client.BaseUrl; }
}

internal readonly bool NoNetworkMode;

#endregion

internal PackageManagerClient(IGregClient client, IPackageUploadBuilder builder, string packageUploadDirectory)
internal PackageManagerClient(IGregClient client, IPackageUploadBuilder builder, string packageUploadDirectory,
bool noNetworkMode = false)
{
this.packageUploadDirectory = packageUploadDirectory;
this.uploadBuilder = builder;
this.client = client;
this.packageMaintainers = new Dictionary<string, bool>();
this.NoNetworkMode = noNetworkMode;
}

internal bool Upvote(string packageId)
{
if (NoNetworkMode) return false;

return FailFunc.TryExecute(() =>
{
var pkgResponse = this.client.ExecuteAndDeserialize(new Upvote(packageId));
Expand All @@ -70,6 +76,8 @@ internal bool Upvote(string packageId)

internal List<string> UserVotes()
{
if (NoNetworkMode) return null;

Copilot AI May 22, 2025

Copy link

Choose a reason for hiding this comment

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

Returning null for a list can lead to NullReferenceExceptions. Prefer returning an empty list (new List<string>()) to maintain API consistency.

Suggested change
if (NoNetworkMode) return null;
if (NoNetworkMode) return new List<string>();

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This?


var votes = FailFunc.TryExecute(() =>
{
var nv = new GetUserVotes();
Expand All @@ -82,6 +90,8 @@ internal List<string> UserVotes()

internal List<JObject> CompatibilityMap()
{
if (NoNetworkMode) return null;

var compatibilityMap = FailFunc.TryExecute(() =>
{
var cm = new GetCompatibilityMap();
Expand All @@ -99,6 +109,8 @@ internal PackageManagerResult DownloadPackage(string packageId, string version,
{
try
{
if (NoNetworkMode) throw new Exception(DynamoPackages.Properties.Resources.DownloadPackageDisabled);
Comment thread
aparajit-pratap marked this conversation as resolved.

Copilot AI May 22, 2025

Copy link

Choose a reason for hiding this comment

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

[nitpick] This method throws an exception on offline mode, but other methods return null or defaults. Consider unifying the error-handling strategy across package manager methods.

Suggested change
if (NoNetworkMode) throw new Exception(DynamoPackages.Properties.Resources.DownloadPackageDisabled);
if (NoNetworkMode)
{
pathToPackage = null;
return PackageManagerResult.Failed(DynamoPackages.Properties.Resources.DownloadPackageDisabled);
}

Copilot uses AI. Check for mistakes.

var response = this.client.Execute(new PackageDownload(packageId, version));
pathToPackage = PackageDownload.GetFileFromResponse(response);
return PackageManagerResult.Succeeded();
Expand All @@ -112,6 +124,8 @@ internal PackageManagerResult DownloadPackage(string packageId, string version,

internal IEnumerable<PackageHeader> ListAll()
{
if (NoNetworkMode) return new List<PackageHeader>();

return FailFunc.TryExecute(() => {
var nv = HeaderCollectionDownload.ByEngine("dynamo");
var pkgResponse = this.client.ExecuteAndDeserializeWithContent<List<PackageHeader>>(nv);
Expand Down Expand Up @@ -146,6 +160,8 @@ void CleanPackagesWithWrongVersions(List<PackageHeader> packages)
/// <returns></returns>
internal PackageHeader GetPackageMaintainers(IPackageInfo packageInfo)
{
if (NoNetworkMode) return null;

var header = FailFunc.TryExecute(() =>
{
var nv = new GetMaintainers("dynamo", packageInfo.Name);
Expand All @@ -162,6 +178,8 @@ internal PackageHeader GetPackageMaintainers(IPackageInfo packageInfo)
/// <returns></returns>
internal UserPackages GetUsersLatestPackages()
{
if (NoNetworkMode) return null;

var packages = FailFunc.TryExecute(() =>
{
var nv = new GetMyPackages();
Expand All @@ -179,6 +197,8 @@ internal UserPackages GetUsersLatestPackages()
/// <returns>Package version metadata</returns>
internal PackageVersion GetPackageVersionHeader(IPackageInfo packageInfo)
{
if (NoNetworkMode) return null;

var req = new HeaderVersionDownload("dynamo", packageInfo.Name, packageInfo.Version.ToString());
var pkgResponse = this.client.ExecuteAndDeserializeWithContent<PackageVersion>(req);
if (!pkgResponse.success)
Expand All @@ -196,6 +216,8 @@ internal PackageVersion GetPackageVersionHeader(IPackageInfo packageInfo)
/// <returns>Package version metadata</returns>
internal virtual PackageVersion GetPackageVersionHeader(string id, string version)
{
if (NoNetworkMode) return null;

var req = new HeaderVersionDownload(id, version);
var pkgResponse = this.client.ExecuteAndDeserializeWithContent<PackageVersion>(req);
if (!pkgResponse.success)
Expand All @@ -211,6 +233,8 @@ internal virtual PackageVersion GetPackageVersionHeader(string id, string versio
/// </summary>
internal virtual IEnumerable<string> GetKnownHosts()
{
if (NoNetworkMode) return null;

if (cachedHosts == null)
{
cachedHosts = FailFunc.TryExecute(() =>
Expand All @@ -235,6 +259,8 @@ public bool SetTermsOfUseAcceptanceStatus()

private bool ExecuteTermsOfUseCall(bool queryAcceptanceStatus)
{
if (NoNetworkMode) return false;

return FailFunc.TryExecute(() =>
{
var request = new TermsOfUse(queryAcceptanceStatus);
Expand All @@ -258,6 +284,8 @@ private bool ExecuteTermsOfUseCall(bool queryAcceptanceStatus)
/// <returns>A <see cref="PackageUploadHandle"/> Used to track the upload status.</returns>
internal PackageUploadHandle PublishAsync(Package package, object files, IEnumerable<string> markdownFiles, bool isNewVersion, IEnumerable<string> roots, bool retainFolderStructure)
{
if (NoNetworkMode) return null;

var packageUploadHandle = new PackageUploadHandle(PackageUploadBuilder.NewRequestBody(package));

Task.Factory.StartNew(() =>
Expand Down Expand Up @@ -321,6 +349,8 @@ internal void Publish(Package package, object files, IEnumerable<string> markdow

internal PackageManagerResult Deprecate(string name)
{
if (NoNetworkMode) return null;

return FailFunc.TryExecute(() =>
{
var pkgResponse = this.client.ExecuteAndDeserialize(new Deprecate(name, PackageEngineName));
Expand All @@ -330,6 +360,8 @@ internal PackageManagerResult Deprecate(string name)

internal PackageManagerResult Undeprecate(string name)
{
if (NoNetworkMode) return null;

return FailFunc.TryExecute(() =>
{
var pkgResponse = this.client.ExecuteAndDeserialize(new Undeprecate(name, PackageEngineName));
Expand All @@ -339,14 +371,16 @@ internal PackageManagerResult Undeprecate(string name)

internal bool DoesCurrentUserOwnPackage(Package package,string username)
{
if (NoNetworkMode) return false;

bool value;
if (this.packageMaintainers.Count > 0 && this.packageMaintainers.TryGetValue(package.Name, out value)) {
if (packageMaintainers.Count > 0 && packageMaintainers.TryGetValue(package.Name, out value)) {
return value;
}
var pkg = new PackageInfo(package.Name, new Version(package.VersionName));
var mnt = GetPackageMaintainers(pkg);
value = (mnt != null) && (mnt.maintainers.Any(maintainer => maintainer.username.Equals(username)));
this.packageMaintainers[package.Name] = value;
packageMaintainers[package.Name] = value;
return value;
}

Expand Down Expand Up @@ -386,7 +420,7 @@ internal void LoadCompatibilityMap()
{
compatibilityMap = new Dictionary<string, Dictionary<string, string>>();

var compatibilityMapList = this.CompatibilityMap();
var compatibilityMapList = CompatibilityMap();
PackageManagerClient.compatibilityMapList = compatibilityMapList; // Loads the full CompatibilityMap as a side-effect

foreach (var host in compatibilityMapList)
Expand Down
5 changes: 3 additions & 2 deletions src/DynamoPackages/PackageManagerExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,12 @@ public void Startup(StartupParams startupParams)

var packageUploadDirectory = startupParams.PathManager.DefaultPackagesDirectory;

noNetworkMode = startupParams.NoNetworkMode;

PackageManagerClient = new PackageManagerClient(
new GregClient(startupParams.AuthProvider, url),
uploadBuilder, packageUploadDirectory);
uploadBuilder, packageUploadDirectory, noNetworkMode);

noNetworkMode = startupParams.NoNetworkMode;

//we don't ask dpm for the compatibility map in offline mode.
if (!noNetworkMode)
Expand Down
9 changes: 9 additions & 0 deletions src/DynamoPackages/Properties/Resources.Designer.cs

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

7 changes: 5 additions & 2 deletions src/DynamoPackages/Properties/Resources.cs-CZ.resx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Expand Down Expand Up @@ -123,6 +123,9 @@
<data name="CannotRemovePackageAssemblyTitle" xml:space="preserve">
<value>Sestavu není možné aktualizovat</value>
</data>
<data name="DownloadPackageDisabled" xml:space="preserve">
Comment thread
aparajit-pratap marked this conversation as resolved.
Outdated
<value />
</data>
<data name="InvalidPackageFolderWarning" xml:space="preserve">
<value>Složka {0} neexistuje.</value>
</data>
Expand All @@ -135,4 +138,4 @@
<data name="PackagesDirectorySkipped" xml:space="preserve">
<value>V {0} nebyly vyhledány balíčky, protože nastavením předvoleb bylo zakázáno načítání z tohoto umístění."</value>
</data>
</root>
</root>
7 changes: 5 additions & 2 deletions src/DynamoPackages/Properties/Resources.de-DE.resx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Expand Down Expand Up @@ -123,6 +123,9 @@
<data name="CannotRemovePackageAssemblyTitle" xml:space="preserve">
<value>Assembly kann nicht aktualisiert werden</value>
</data>
<data name="DownloadPackageDisabled" xml:space="preserve">
<value />
</data>
<data name="InvalidPackageFolderWarning" xml:space="preserve">
<value>Der Ordner '{0}' ist nicht vorhanden.</value>
</data>
Expand All @@ -135,4 +138,4 @@
<data name="PackagesDirectorySkipped" xml:space="preserve">
<value>{0} wurde nicht nach Paketen gescannt, da eine Voreinstellung das Laden von Dateien aus diesem Verzeichnis deaktiviert hat.</value>
</data>
</root>
</root>
5 changes: 4 additions & 1 deletion src/DynamoPackages/Properties/Resources.en-US.resx
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@
<data name="CannotRemovePackageAssemblyTitle" xml:space="preserve">
<value>Cannot update assembly</value>
</data>
<data name="DownloadPackageDisabled" xml:space="preserve">
<value>Package download is disabled in no-network mode.</value>
</data>
<data name="InvalidPackageFolderWarning" xml:space="preserve">
<value>The folder '{0}' does not exist</value>
<comment>This warning message is shown (during start up) when user specifies additional folders in DynamoSettings.xml file but the folders do not exist.</comment>
Expand All @@ -140,4 +143,4 @@
<value>{0} was not scanned for packages because a preference setting disabled loading from that location."</value>
<comment>This warning message is shown when a package directory is skipped due to a preference setting disabling loads from that location type.</comment>
</data>
</root>
</root>
Loading
Loading