Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…to dev
  • Loading branch information
vnbaaij committed Sep 18, 2024
2 parents 1956910 + 35f3e04 commit 4cc0e0c
Show file tree
Hide file tree
Showing 14 changed files with 928 additions and 162 deletions.
126 changes: 126 additions & 0 deletions examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15319,6 +15319,12 @@
</code>
</remarks>
</member>
<member name="T:Microsoft.FluentUI.AspNetCore.Components.Utilities.Debounce">
<summary>
The DebounceTask dispatcher delays the invocation of an action until a predetermined interval has elapsed since the last call.
This ensures that the action is only invoked once after the calls have stopped for the specified duration.
</summary>
</member>
<member name="M:Microsoft.FluentUI.AspNetCore.Components.Utilities.InlineStyleBuilder.#ctor">
<summary>
Initializes a new instance of the <see cref="T:Microsoft.FluentUI.AspNetCore.Components.Utilities.InlineStyleBuilder"/> class.
Expand Down Expand Up @@ -15374,6 +15380,126 @@
<param name="value"></param>
<returns>StyleBuilder</returns>
</member>
<member name="T:Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce.DebounceAction">
<summary>
The DebounceTask dispatcher delays the invocation of an action until a predetermined interval has elapsed since the last call.
This ensures that the action is only invoked once after the calls have stopped for the specified duration.
</summary>
</member>
<member name="P:Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce.DebounceAction.Busy">
<summary>
Gets a value indicating whether the DebounceTask dispatcher is busy.
</summary>
</member>
<member name="P:Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce.DebounceAction.CurrentTask">
<summary>
Gets the current task.
</summary>
</member>
<member name="M:Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce.DebounceAction.Run(System.Int32,System.Func{System.Threading.Tasks.Task})">
<summary>
Delays the invocation of an action until a predetermined interval has elapsed since the last call.
</summary>
<param name="milliseconds"></param>
<param name="action"></param>
<exception cref="T:System.ArgumentOutOfRangeException"></exception>
</member>
<member name="M:Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce.DebounceAction.RunAsync(System.Int32,System.Func{System.Threading.Tasks.Task})">
<summary>
Delays the invocation of an action until a predetermined interval has elapsed since the last call.
</summary>
<param name="milliseconds"></param>
<param name="action"></param>
<exception cref="T:System.ArgumentOutOfRangeException"></exception>
</member>
<member name="M:Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce.DebounceAction.Dispose">
<summary>
Releases all resources used by the DebounceTask dispatcher.
</summary>
</member>
<member name="T:Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce.DebounceTask">
<summary>
The DebounceTask dispatcher delays the invocation of an action until a predetermined interval has elapsed since the last call.
This ensures that the action is only invoked once after the calls have stopped for the specified duration.
</summary>
</member>
<member name="P:Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce.DebounceTask.Busy">
<summary>
Gets a value indicating whether the DebounceTask dispatcher is busy.
</summary>
</member>
<member name="P:Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce.DebounceTask.CurrentTask">
<summary>
Gets the current task.
</summary>
</member>
<member name="M:Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce.DebounceTask.Run(System.Int32,System.Func{System.Threading.Tasks.Task})">
<summary>
Delays the invocation of an action until a predetermined interval has elapsed since the last call.
</summary>
<param name="milliseconds"></param>
<param name="action"></param>
<exception cref="T:System.ArgumentOutOfRangeException"></exception>
</member>
<member name="M:Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce.DebounceTask.RunAsync(System.Int32,System.Func{System.Threading.Tasks.Task})">
<summary>
Delays the invocation of an action until a predetermined interval has elapsed since the last call.
</summary>
<param name="milliseconds"></param>
<param name="action"></param>
<exception cref="T:System.ArgumentOutOfRangeException"></exception>
</member>
<member name="M:Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce.DebounceTask.Dispose">
<summary>
Releases all resources used by the DebounceTask dispatcher.
</summary>
</member>
<member name="T:Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce.DispatcherTimerExtensions">
<summary>
Extension methods for <see cref="T:System.Timers.Timer"/>.
</summary>
<remarks>
Inspired from Microsoft.Toolkit.Uwp.UI.DispatcherQueueTimerExtensions
</remarks>
</member>
<member name="M:Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce.DispatcherTimerExtensions.Debounce(System.Timers.Timer,System.Func{System.Threading.Tasks.Task},System.Double)">
<summary>
Delays the invocation of an action until a predetermined interval has elapsed since the last call.
</summary>
<param name="timer"></param>
<param name="action"></param>
<param name="interval"></param>
<returns></returns>
</member>
<member name="M:Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce.DispatcherTimerExtensions.Timer_Elapsed(System.Object,System.Timers.ElapsedEventArgs)">
<summary>
Timer elapsed event handler.
</summary>
<param name="sender"></param>
<param name="e"></param>
</member>
<member name="T:Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce.DispatcherTimerExtensions.TimerDebounceItem">
<summary>
Timer debounce item.
</summary>
</member>
<member name="P:Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce.DispatcherTimerExtensions.TimerDebounceItem.Status">
<summary>
Gets the task completion source.
</summary>
</member>
<member name="P:Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce.DispatcherTimerExtensions.TimerDebounceItem.Action">
<summary>
Gets or sets the action to execute.
</summary>
</member>
<member name="M:Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce.DispatcherTimerExtensions.TimerDebounceItem.UpdateAction(System.Func{System.Threading.Tasks.Task})">
<summary>
Updates the action to execute.
</summary>
<param name="action"></param>
<returns></returns>
</member>
<member name="F:Microsoft.FluentUI.AspNetCore.Components.Utilities.LinkerFlags.JsonSerialized">
<summary>
Flags for a member that is JSON (de)serialized.
Expand Down
8 changes: 5 additions & 3 deletions examples/Demo/Shared/Pages/BlazorHybrid.razor
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
included in the general library script and needs to be included with a script tag <strong>before</strong> the <code>_framework/blazor.webview.js</code> script tag.
</p>

<CodeSnippet Language="language-html">
&lt;script app-name=&quot;{NAME OF YOUR APP}&quot; src=&quot;./_content/Microsoft.FluentUI.AspNetCore.Components/js/initializersLoader.webview.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;_framework/blazor.webview.js&quot;&gt;&lt;/script&gt;
<CodeSnippet Language="html">
@(
@"<script app-name=""{NAME OF YOUR APP}"" src=""./_content/Microsoft.FluentUI.AspNetCore.Components/js/initializersLoader.webview.js""></script>
<script src=""_framework/blazor.webview.js""></script>"
)
</CodeSnippet>

<p>
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Components/Base/FluentInputBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ void IDisposable.Dispose()
EditContext.OnValidationStateChanged -= _validationStateChangedHandler;
}

_debouncer.Dispose();
_debounce.Dispose();

Dispose(disposing: true);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Core/Components/Base/FluentInputBaseHandlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Microsoft.FluentUI.AspNetCore.Components;

public partial class FluentInputBase<TValue>
{
private readonly Debouncer _debouncer = new();
private readonly Debounce _debounce = new();

/// <summary>
/// Change the content of this input field when the user write text (based on 'OnInput' HTML event).
Expand Down Expand Up @@ -64,7 +64,7 @@ protected virtual async Task InputHandlerAsync(ChangeEventArgs e) // TODO: To up
}
if (ImmediateDelay > 0)
{
await _debouncer.DebounceAsync(ImmediateDelay, async () => await ChangeHandlerAsync(e));
await _debounce.RunAsync(ImmediateDelay, async () => await ChangeHandlerAsync(e));
}
else
{
Expand Down
6 changes: 4 additions & 2 deletions src/Core/Components/List/FluentAutocomplete.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public partial class FluentAutocomplete<TOption> : ListComponentBase<TOption> wh

public new FluentTextField? Element { get; set; } = default!;
private Virtualize<TOption>? VirtualizationContainer { get; set; }
private readonly Debouncer _debouncer = new();
private readonly Debounce _debounce = new();

/// <summary>
/// Initializes a new instance of the <see cref="FluentAutocomplete{TOption}"/> class.
Expand Down Expand Up @@ -295,13 +295,15 @@ protected override async Task InputHandlerAsync(ChangeEventArgs e)

if (ImmediateDelay > 0)
{
await _debouncer.DebounceAsync(ImmediateDelay, () => InvokeAsync(() => OnOptionsSearch.InvokeAsync(args)));
await _debounce.RunAsync(ImmediateDelay, () => InvokeAsync(() => OnOptionsSearch.InvokeAsync(args)));
}
else
{
await OnOptionsSearch.InvokeAsync(args);
}

Console.WriteLine($"args.Items: {args.Items?.Count()}");

Items = args.Items?.Take(MaximumOptionsSearch);

SelectableItem = Items != null
Expand Down
6 changes: 3 additions & 3 deletions src/Core/Components/TreeView/FluentTreeView.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Microsoft.FluentUI.AspNetCore.Components;
public partial class FluentTreeView : FluentComponentBase, IDisposable
{
private readonly Dictionary<string, FluentTreeItem> _allItems = [];
private readonly Debouncer _currentSelectedChangedDebouncer = new();
private readonly Debounce _currentSelectedChangedDebounce = new();
private bool _disposed;

public static string LoadingMessage = "Loading...";
Expand Down Expand Up @@ -154,7 +154,7 @@ internal async Task HandleCurrentSelectedChangeAsync(TreeChangeEventArgs args)
}

var previouslySelected = CurrentSelected;
await _currentSelectedChangedDebouncer.DebounceAsync(50, () => InvokeAsync(async () =>
await _currentSelectedChangedDebounce.RunAsync(50, () => InvokeAsync(async () =>
{
CurrentSelected = treeItem?.Selected == true ? treeItem : null;
if (CurrentSelected != previouslySelected && CurrentSelectedChanged.HasDelegate)
Expand Down Expand Up @@ -190,7 +190,7 @@ protected virtual void Dispose(bool disposing)

if (disposing)
{
_currentSelectedChangedDebouncer?.Dispose();
_currentSelectedChangedDebounce?.Dispose();
_allItems.Clear();
}

Expand Down
13 changes: 13 additions & 0 deletions src/Core/Utilities/Debounce.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// ------------------------------------------------------------------------
// MIT License - Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------------------

namespace Microsoft.FluentUI.AspNetCore.Components.Utilities;

/// <summary>
/// The DebounceTask dispatcher delays the invocation of an action until a predetermined interval has elapsed since the last call.
/// This ensures that the action is only invoked once after the calls have stopped for the specified duration.
/// </summary>
public sealed class Debounce : InternalDebounce.DebounceTask
{
}
64 changes: 0 additions & 64 deletions src/Core/Utilities/Debouncer.cs

This file was deleted.

75 changes: 75 additions & 0 deletions src/Core/Utilities/InternalDebounce/DebounceAction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// ------------------------------------------------------------------------
// MIT License - Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------------------

namespace Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce;

/// <summary>
/// The DebounceTask dispatcher delays the invocation of an action until a predetermined interval has elapsed since the last call.
/// This ensures that the action is only invoked once after the calls have stopped for the specified duration.
/// </summary>
[Obsolete("Use Debounce, which inherits from DebounceTask.")]
internal class DebounceAction : IDisposable
{
private bool _disposed;
private readonly System.Timers.Timer _timer = new();
private TaskCompletionSource? _taskCompletionSource;

/// <summary>
/// Gets a value indicating whether the DebounceTask dispatcher is busy.
/// </summary>
public bool Busy => _taskCompletionSource?.Task.Status == TaskStatus.Running && !_disposed;

/// <summary>
/// Gets the current task.
/// </summary>
public Task CurrentTask => _taskCompletionSource?.Task ?? Task.CompletedTask;

/// <summary>
/// Delays the invocation of an action until a predetermined interval has elapsed since the last call.
/// </summary>
/// <param name="milliseconds"></param>
/// <param name="action"></param>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public void Run(int milliseconds, Func<Task> action)
{
// Check arguments
if (milliseconds <= 0)
{
throw new ArgumentOutOfRangeException(nameof(milliseconds), milliseconds, "The milliseconds must be greater than to zero.");
}

ArgumentNullException.ThrowIfNull(action);

// DebounceTask
if (!_disposed)
{
_taskCompletionSource = _timer.Debounce(action, milliseconds);
}
}

/// <summary>
/// Delays the invocation of an action until a predetermined interval has elapsed since the last call.
/// </summary>
/// <param name="milliseconds"></param>
/// <param name="action"></param>
/// <exception cref="ArgumentOutOfRangeException"></exception>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD003:Avoid awaiting foreign Tasks", Justification = "Required to return the current Task.")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "MA0042:Do not use blocking calls in an async method", Justification = "Special case using CurrentTask")]
public Task RunAsync(int milliseconds, Func<Task> action)
{
Run(milliseconds, action);
return CurrentTask;
}

/// <summary>
/// Releases all resources used by the DebounceTask dispatcher.
/// </summary>
public void Dispose()
{
_taskCompletionSource = null;
_timer.Dispose();
_disposed = true;
GC.SuppressFinalize(this);
}
}
Loading

0 comments on commit 4cc0e0c

Please sign in to comment.