Skip to content

Commit

Permalink
Fix hanged node search when the user types faster than serach
Browse files Browse the repository at this point in the history
  • Loading branch information
chubakueno committed Dec 19, 2024
1 parent 6d5ea68 commit 104e63d
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 8 deletions.
1 change: 1 addition & 0 deletions src/DynamoCoreWpf/DynamoCoreWpf.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@
<Compile Include="Utilities\CrashReportTool.cs" />
<Compile Include="Utilities\CrashUtilities.cs" />
<Compile Include="Utilities\GroupStyleItemSelector.cs" />
<Compile Include="Utilities\JobDebouncer.cs" />
<Compile Include="Utilities\LibraryDragAndDrop.cs" />
<Compile Include="Utilities\MessageBoxUtilities.cs" />
<Compile Include="Utilities\NodeContextMenuBuilder.cs" />
Expand Down
6 changes: 6 additions & 0 deletions src/DynamoCoreWpf/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3671,6 +3671,10 @@ Dynamo.Wpf.Utilities.DynamoWebView2
Dynamo.Wpf.Utilities.DynamoWebView2.DynamoWebView2() -> void
Dynamo.Wpf.Utilities.GroupStyleItemSelector
Dynamo.Wpf.Utilities.GroupStyleItemSelector.GroupStyleItemSelector() -> void
Dynamo.Wpf.Utilities.JobDebouncer
Dynamo.Wpf.Utilities.JobDebouncer.DebounceQueueToken
Dynamo.Wpf.Utilities.JobDebouncer.DebounceQueueToken.DebounceQueueToken() -> void
Dynamo.Wpf.Utilities.JobDebouncer.DebounceQueueToken.IsDirty -> bool
Dynamo.Wpf.Utilities.LibraryDragAndDrop
Dynamo.Wpf.Utilities.LibraryDragAndDrop.LibraryDragAndDrop() -> void
Dynamo.Wpf.Utilities.MessageBoxService
Expand Down Expand Up @@ -4340,6 +4344,7 @@ readonly Dynamo.ViewModels.PortViewModel.node -> Dynamo.ViewModels.NodeViewModel
readonly Dynamo.ViewModels.PortViewModel.port -> Dynamo.Graph.Nodes.PortModel
readonly Dynamo.ViewModels.WorkspaceViewModel.Model -> Dynamo.Graph.Workspaces.WorkspaceModel
readonly Dynamo.Wpf.Extensions.ViewLoadedParams.dynamoMenu -> System.Windows.Controls.Menu
readonly Dynamo.Wpf.Utilities.JobDebouncer.DebounceQueueToken.JobLock -> object
readonly Dynamo.Wpf.ViewModels.Watch3D.DefaultWatch3DViewModel.dynamoModel -> Dynamo.Interfaces.IDynamoModel
readonly Dynamo.Wpf.ViewModels.Watch3D.DefaultWatch3DViewModel.engineManager -> Dynamo.Models.IEngineControllerManager
readonly Dynamo.Wpf.ViewModels.Watch3D.DefaultWatch3DViewModel.logger -> Dynamo.Logging.ILogger
Expand Down Expand Up @@ -5614,6 +5619,7 @@ static Dynamo.Wpf.UI.VisualConfigurations.ErrorTextFontWeight -> System.Windows.
static Dynamo.Wpf.UI.VisualConfigurations.LibraryTooltipTextFontWeight -> System.Windows.FontWeight
static Dynamo.Wpf.UI.VisualConfigurations.NodeTooltipTextFontWeight -> System.Windows.FontWeight
static Dynamo.Wpf.Utilities.CompactBubbleHandler.Process(ProtoCore.Mirror.MirrorData value) -> Dynamo.ViewModels.CompactBubbleViewModel
static Dynamo.Wpf.Utilities.JobDebouncer.EnqueueJobAsync(System.Action job, Dynamo.Wpf.Utilities.JobDebouncer.DebounceQueueToken token) -> System.Threading.Tasks.Task
static Dynamo.Wpf.Utilities.MessageBoxService.Show(string msg, string title, bool showRichTextBox, System.Windows.MessageBoxButton button, System.Windows.MessageBoxImage img) -> System.Windows.MessageBoxResult
static Dynamo.Wpf.Utilities.MessageBoxService.Show(string msg, string title, System.Windows.MessageBoxButton button, System.Collections.Generic.IEnumerable<string> buttonNames, System.Windows.MessageBoxImage img) -> System.Windows.MessageBoxResult
static Dynamo.Wpf.Utilities.MessageBoxService.Show(string msg, string title, System.Windows.MessageBoxButton button, System.Windows.MessageBoxImage img) -> System.Windows.MessageBoxResult
Expand Down
36 changes: 36 additions & 0 deletions src/DynamoCoreWpf/Utilities/JobDebouncer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;
using System.Threading.Tasks;

namespace Dynamo.Wpf.Utilities
{
public static class JobDebouncer
{
public class DebounceQueueToken
{
public bool IsDirty = false;
public readonly object JobLock = new();
};
/// <summary>
/// Action <paramref name="job"/> is guaranteed to run at most once for every call, and exactly once after the last call.
/// Execution is sequential, and jobs that share a <see cref="DebounceQueueToken"/> with a newer job will be ignored.
/// </summary>
/// <param name="job"></param>
/// <param name="token"></param>
/// <returns></returns>
public static Task EnqueueJobAsync(Action job, DebounceQueueToken token)
{
token.IsDirty = true;
return Task.Run(() =>
{
lock (token.JobLock)
{
while (token.IsDirty)
{
token.IsDirty = false;
job();
}
}
});
}
}
}
28 changes: 20 additions & 8 deletions src/DynamoCoreWpf/ViewModels/Search/SearchViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;
using Dynamo.Configuration;
using Dynamo.Engine;
using Dynamo.Graph.Nodes;
Expand All @@ -18,6 +19,7 @@
using Dynamo.UI;
using Dynamo.Utilities;
using Dynamo.Wpf.Services;
using Dynamo.Wpf.Utilities;
using Dynamo.Wpf.ViewModels;

namespace Dynamo.ViewModels
Expand Down Expand Up @@ -861,14 +863,16 @@ private static string MakeFullyQualifiedName(string path, string addition)
/// </summary>
internal void SearchAndUpdateResults()
{
searchResults.Clear();
//Unit tests don't have an Application.Current
(Application.Current?.Dispatcher ?? Dispatcher.CurrentDispatcher).Invoke(() =>
{
searchResults.Clear();
});

if (!String.IsNullOrEmpty(SearchText.Trim()))
{
SearchAndUpdateResults(SearchText);
}

RaisePropertyChanged("IsAnySearchResult");
}

/// <summary>
Expand All @@ -886,13 +890,20 @@ public void SearchAndUpdateResults(string query)

//Passing the second parameter as true will search using Lucene.NET
var foundNodes = Search(query);
searchResults = new List<NodeSearchElementViewModel>(foundNodes);

FilteredResults = searchResults;
//Unit tests don't have an Application.Current
(Application.Current?.Dispatcher ?? Dispatcher.CurrentDispatcher).Invoke(() =>
{
searchResults = new List<NodeSearchElementViewModel>(foundNodes);

UpdateSearchCategories();
FilteredResults = searchResults;

RaisePropertyChanged("FilteredResults");
UpdateSearchCategories();

RaisePropertyChanged("FilteredResults");

RaisePropertyChanged("IsAnySearchResult");
});
}

/// <summary>
Expand Down Expand Up @@ -1164,9 +1175,10 @@ public void OnSearchElementClicked(NodeModel nodeModel, Point position)

#region Commands

private static readonly JobDebouncer.DebounceQueueToken DebounceQueueToken = new();
public void Search(object parameter)
{
SearchAndUpdateResults();
JobDebouncer.EnqueueJobAsync(SearchAndUpdateResults, DebounceQueueToken);
}

internal bool CanSearch(object parameter)
Expand Down

0 comments on commit 104e63d

Please sign in to comment.