Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e3fb926
initial dynamo changes
Chloepeg Feb 16, 2026
7aec4f3
Add NewWorkspaceWithTemplate method to open templates in new workspace
Chloepeg Feb 24, 2026
7fde2d7
Merge branch 'DynamoDS:master' into DYN-9702-templates-to-home-screen
Chloepeg Feb 24, 2026
cb1454c
Merge upstream/master into DYN-9702-templates-to-home-screen
Chloepeg Mar 2, 2026
2189df6
Merge branch 'DYN-9702-templates-to-home-screen' of https://github.co…
Chloepeg Mar 2, 2026
1739ed2
initial dynamo changes
Chloepeg Feb 16, 2026
e8ecae4
Add NewWorkspaceWithTemplate method to open templates in new workspace
Chloepeg Feb 24, 2026
d445a53
Fix DynamoHome bundle file
Chloepeg Mar 3, 2026
3236104
Merge branch 'DYN-9702-templates-to-home-screen' of https://github.co…
Chloepeg Mar 3, 2026
09b9a97
Adds the missing TemplateFiles property to StartPageViewModel
Chloepeg Mar 3, 2026
36f0768
Fixes build error
Chloepeg Mar 3, 2026
99a0538
Revert "Add NewWorkspaceWithTemplate method to open templates in new …
Chloepeg Mar 3, 2026
eec3510
Merge remote-tracking branch 'upstream/master' into DYN-9702-template…
Chloepeg Mar 10, 2026
4e7fd6b
Fix build
Chloepeg Mar 10, 2026
533156c
remove merge conflict marker
Chloepeg Mar 20, 2026
7c38dd6
Merge fix
Chloepeg Mar 27, 2026
8fb554c
Merge remote-tracking branch 'upstream/master' into DYN-9702-template…
Chloepeg Mar 27, 2026
859da9d
Fix DynamoHome embedded path and remove duplicate XAML code-behind co…
Chloepeg Mar 27, 2026
6689e5c
Fix Sonar issues
Chloepeg Mar 27, 2026
f83703f
Address SonarQube cloud issues in StartPage and HomePage
Chloepeg Mar 29, 2026
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
86 changes: 79 additions & 7 deletions src/DynamoCoreWpf/Controls/StartPage.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
using Dynamo.Configuration;
using Dynamo.Logging;
using Dynamo.Utilities;
using Dynamo.ViewModels;
using Dynamo.Wpf.Properties;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
Expand All @@ -10,12 +16,7 @@
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Dynamo.Configuration;
using Dynamo.Logging;
using Dynamo.Utilities;
using Dynamo.ViewModels;
using Dynamo.Wpf.Properties;
using Newtonsoft.Json;
using static Dynamo.Wpf.Interfaces.ResourceNames;
using NotificationObject = Dynamo.Core.NotificationObject;

namespace Dynamo.UI.Controls
Expand Down Expand Up @@ -119,6 +120,7 @@ public class StartPageViewModel : ViewModelBase
ObservableCollection<SampleFileEntry> sampleFiles = null;
ObservableCollection<StartPageListItem> recentFiles = null;
ObservableCollection<StartPageListItem> backupFiles = null;
readonly ObservableCollection<StartPageListItem> templateFiles;
internal readonly DynamoViewModel DynamoViewModel;
private readonly bool isFirstRun;

Expand All @@ -130,6 +132,7 @@ internal StartPageViewModel(DynamoViewModel dynamoViewModel, bool isFirstRun)
this.recentFiles = new ObservableCollection<StartPageListItem>();
this.sampleFiles = new ObservableCollection<SampleFileEntry>();
this.backupFiles = new ObservableCollection<StartPageListItem>();
this.templateFiles = new ObservableCollection<StartPageListItem>();


#region File Operations
Expand Down Expand Up @@ -213,7 +216,67 @@ internal StartPageViewModel(DynamoViewModel dynamoViewModel, bool isFirstRun)
var dvm = this.DynamoViewModel;
RefreshRecentFileList(dvm.RecentFiles, true);
RefreshBackupFileList(dvm.Model.PreferenceSettings.BackupFiles);
LoadTemplates();
dvm.RecentFiles.CollectionChanged += OnRecentFilesChanged;


}


private void LoadTemplates()
{
// Retrieve the current Temlates location from Dynamo properties
var templatesDirectory = DynamoViewModel.Model.PathManager.TemplatesDirectory;

if (Directory.Exists(templatesDirectory))
{
var rootDynPaths = new List<string>();
string[] filePaths = Directory.GetFiles(templatesDirectory, "*.dyn"); // This could change if we move to *dyt

// We only collect the files in the root
if (filePaths.Length != 0)
{
foreach (string path in filePaths)
{
rootDynPaths.Add(path);
}
}

// Make comment on legacy use of StartPage.xaml.cs
if (rootDynPaths.Any())
{
foreach (var filePath in rootDynPaths)
{
AddTemplateListItemFromPath(filePath);
}
}
}
}

private void AddTemplateListItemFromPath(string filePath)
{
var extension = Path.GetExtension(filePath).ToUpper();
// If not extension specified and code reach here, this means this is still a valid file
// only without file type. Otherwise, simply take extension substring skipping the 'dot'.
var subScript = extension.StartsWith('.') ? extension.Substring(1) : "";
var caption = Path.GetFileNameWithoutExtension(filePath);

// deserializes the file only once
var properties = GetFileProperties(filePath);

var templateItem = new StartPageListItem(caption)
{
ContextData = filePath,
ToolTip = filePath,
SubScript = subScript,
Description = properties.description,
Thumbnail = properties.thumbnail,
Author = properties.author,
DateModified = properties.date,
ClickAction = StartPageListItem.Action.FilePath,
};

this.TemplateFiles.Add(templateItem);
}

internal void WalkDirectoryTree(System.IO.DirectoryInfo root, SampleFileEntry rootProperty)
Expand Down Expand Up @@ -385,6 +448,15 @@ public ObservableCollection<SampleFileEntry> SampleFiles
get { return this.sampleFiles; }
}

/// <summary>
/// A collection of Dynamo Template files
/// Fetched at load time from the current Dynamo Templates Propoerties location
/// </summary>
public ObservableCollection<StartPageListItem> TemplateFiles
{
get { return this.templateFiles; }
}

public string BackupTitle
{
get
Expand Down Expand Up @@ -470,7 +542,7 @@ private void RefreshFileList(ObservableCollection<StartPageListItem> files,
var extension = Path.GetExtension(filePath).ToUpper();
// If not extension specified and code reach here, this means this is still a valid file
// only without file type. Otherwise, simply take extension substring skipping the 'dot'.
var subScript = extension.StartsWith(".") ? extension.Substring(1) : "";
var subScript = extension.StartsWith('.') ? extension.Substring(1) : "";
var caption = Path.GetFileNameWithoutExtension(filePath);

// deserializes the file only once
Expand Down
2 changes: 0 additions & 2 deletions src/DynamoCoreWpf/DynamoCoreWpf.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -799,9 +799,7 @@
<Compile Include="Views\GuidedTour\SurveyPopupWindow.xaml.cs">
<DependentUpon>SurveyPopupWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Views\HomePage\HomePage.xaml.cs" />
<Compile Include="Views\Input\ParameterEditor.cs" />
<Compile Include="Views\PackageManager\Components\PackageManagerWizard\PackageManagerWizard.xaml.cs" />
<Compile Include="Views\PackageManager\Controls\CustomBrowserControl.xaml.cs" />
<Compile Include="Views\PackageManager\Controls\FilterTagControl.xaml.cs" />
<Compile Include="Views\PackageManager\Controls\LoadingAnimationStripeControl.xaml.cs" />
Expand Down
1 change: 1 addition & 0 deletions src/DynamoCoreWpf/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.IsInstalle
Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.IsInstalledVersionSelected.get -> bool
Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.IsPublishedByDynamoTeam.get -> bool
Dynamo.PackageManager.ViewModels.PackageManagerSearchElementViewModel.IsUninstallState.get -> bool
Dynamo.UI.Controls.StartPageViewModel.TemplateFiles.get -> System.Collections.ObjectModel.ObservableCollection<Dynamo.UI.Controls.StartPageListItem>
Dynamo.UI.Views.ScriptObject.ResetSettings() -> void
Dynamo.UI.Views.ScriptObject.ScriptObject(System.Action<bool> requestLaunchDynamo, System.Action<string> requestImportSettings, System.Func<bool> requestSignIn, System.Func<bool> requestSignOut, System.Action requestResetSettings) -> void
Dynamo.ViewModels.DynamoViewModel.OnlineAccess.get -> bool
Expand Down
46 changes: 38 additions & 8 deletions src/DynamoCoreWpf/Views/HomePage/HomePage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Runtime.InteropServices;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using Autodesk.DesignScript.Runtime;
Expand Down Expand Up @@ -272,24 +273,25 @@ internal void LoadingDone()
if (startPage == null) { return; }

SendGuidesData();
SendSamplesData();
SendRecentGraphsData();
_ = SendSamplesData();
_ = SendTemplateData();
_ = SendRecentGraphsData();
SendVideoData();
SetLocale();
}

private void RecentFiles_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
var recentFiles = startPage.RecentFiles?.DistinctBy(x => x.ContextData).ToList();
LoadGraphs(recentFiles);
_ = LoadGraphs(recentFiles);
}

#region FrontEnd Initialization Calls
/// <summary>
/// Sends graph data to react app
/// </summary>
/// <param name="data"></param>
private async void LoadGraphs(List<StartPageListItem> data)
private async Task LoadGraphs(List<StartPageListItem> data)
{
if (data == null) { return; }
string jsonData = JsonSerializer.Serialize(data);
Expand All @@ -300,10 +302,26 @@ private async void LoadGraphs(List<StartPageListItem> data)
}
}


/// <summary>
/// Sends graph data to react app
/// </summary>
/// <param name="data"></param>
private async Task LoadTemplates(List<StartPageListItem> data)
{
if (data == null) { return; }
string jsonData = JsonSerializer.Serialize(data);

if (dynWebView?.CoreWebView2 != null)
{
await dynWebView.CoreWebView2.ExecuteScriptAsync(@$"window.receiveTemplatesDataFromDotNet({jsonData})");
}
}

/// <summary>
/// Sends samples data to react app
/// </summary>
private async void SendSamplesData()
private async Task SendSamplesData()
{
if (!this.startPage.SampleFiles.Any()) return;

Expand All @@ -315,9 +333,21 @@ private async void SendSamplesData()
}
}

private async void SendRecentGraphsData()
/// <summary>
/// Sends samples data to react app
/// </summary>
private async Task SendTemplateData()
{
var items = startPage.TemplateFiles?.DistinctBy(x => x.ContextData).ToList();
if (items != null && items.Any())
{
await LoadTemplates(items);
}
}

private async Task SendRecentGraphsData()
{
// Send user preferences
// Send user preferences (could be split to a separate call later instead of coupling with recent files).
if (dynWebView?.CoreWebView2 != null)
{
if (startPage.DynamoViewModel.PreferenceSettings.HomePageSettings != null)
Expand All @@ -334,7 +364,7 @@ private async void SendRecentGraphsData()
var recentFiles = startPage.RecentFiles?.DistinctBy(x => x.ContextData).ToList();
if (recentFiles != null && recentFiles.Any())
{
LoadGraphs(recentFiles);
await LoadGraphs(recentFiles);
}

if (startPage.DynamoViewModel != null && startPage.DynamoViewModel.RecentFiles != null)
Expand Down
Loading