Skip to content

Commit

Permalink
🆕 feat(PageStack): add support for current active tab change event
Browse files Browse the repository at this point in the history
  • Loading branch information
capdiem committed Nov 6, 2024
1 parent 2dae275 commit 2528e45
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 12 deletions.
7 changes: 6 additions & 1 deletion docs/Masa.Blazor.Docs/Shared/PageStackLayout.razor
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@

@code {

private string[] _tabbedPatterns = ["/blazor/examples/page-stack/tab*"];
private string[] _tabbedPatterns =
[
"/blazor/examples/page-stack/tab1",
"/blazor/examples/page-stack/tab2",
"/blazor/examples/page-stack/tab3"
];

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class PageStackNavController()
public event EventHandler<PageStackPopEventArgs>? StackPop;

/// <summary>
/// Occurs when a page is replaced by a new page.
/// Occurs when a new page replaces a page.
/// </summary>
public event EventHandler<PageStackReplaceEventArgs>? StackReplace;

Expand All @@ -39,6 +39,11 @@ public class PageStackNavController()
/// </summary>
internal event EventHandler<PageStackGoBackToPageEventArgs>? StackGoBackTo;

/// <summary>
/// Occurs when the active tab is changed.
/// </summary>
public event EventHandler<PageStackTabChangedEventArgs>? TabChanged;

/// <summary>
/// Push a new page onto the page stack.
/// </summary>
Expand Down Expand Up @@ -126,7 +131,7 @@ public void Clear()
}

/// <summary>
/// Clear current page stack and navigate to a tab.
/// Clear the current page stack and navigate to a tab.
/// </summary>
/// <param name="relativeUri"></param>
[Obsolete("Use GoBackToTab instead.")]
Expand All @@ -136,7 +141,7 @@ public void GoToTab(string relativeUri)
}

/// <summary>
/// Clear current page stack and navigate to a tab.
/// Clear the current page stack and navigate to a tab.
/// </summary>
/// <param name="relativeUri"></param>
public void GoBackToTab(string relativeUri)
Expand All @@ -149,6 +154,11 @@ internal void NotifyPageClosed(string relativeUri)
PageClosed?.Invoke(this, new PageStackPageClosedEventArgs(relativeUri));
}

internal void NotifyTabChanged(string currentTabPath, Regex currentTabPattern)
{
TabChanged?.Invoke(this, new PageStackTabChangedEventArgs(currentTabPath, currentTabPattern.IsMatch));
}

private void ExecuteIfTimeElapsed(Action action)
{
var now = DateTimeOffset.Now.ToUnixTimeMilliseconds();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace Masa.Blazor.Presets.PageStack.NavController;

public class PageStackTabChangedEventArgs(string currentTab, Func<string, bool> isMatch) : EventArgs
{
/// <summary>
/// The absolute path of the current tab.
/// </summary>
public string CurrentTab { get; init; } = currentTab;

/// <summary>
/// Checks whether the given path matches the current tab.
/// </summary>
/// <returns>
/// True if the path matches the current tab; otherwise, false.
/// </returns>
public Func<string, bool> IsMatch { get; init; } = isMatch;
}
40 changes: 32 additions & 8 deletions src/Masa.Blazor/Presets/PageStack/PPageStack.razor.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Masa.Blazor.Presets.PageStack;
using Masa.Blazor.Presets.PageStack.NavController;
using Microsoft.AspNetCore.Components.Routing;

namespace Masa.Blazor.Presets;

Expand All @@ -25,16 +26,18 @@ public partial class PPageStack : PatternPathComponentBase
internal readonly StackPages Pages = new();

/// <summary>
/// Determines whether the popstate event is triggered by user action,
/// Determines whether user action triggers the popstate event,
/// different from the browser's back button.
/// </summary>
private bool _popstateByUserAction;

private string? _lastVisitedTabPath;
private PageType _targetPageType;
private string? _latestTabPath;
private long _lastOnPreviousClickTimestamp;

// just for knowing whether the tab has been changed
private (Regex Pattern, string AbsolutePath) _lastVisitedTab;

private HashSet<string> _prevTabbedPatterns = new();
private HashSet<Regex> _cachedTabbedPatterns = new();

Expand All @@ -54,13 +57,17 @@ protected override void OnInitialized()
{
_lastVisitedTabPath = targetPath;
_targetPageType = PageType.Tab;

_lastVisitedTab = (tabbedPattern, targetPath);
}
else
{
_targetPageType = PageType.Stack;
Push(NavigationManager.Uri);
}

NavigationManager.LocationChanged += NavigationManagerOnLocationChanged;

InternalPageStackNavManager = PageStackNavControllerFactory.Create(Name ?? string.Empty);
InternalPageStackNavManager.StackPush += InternalStackStackNavManagerOnStackPush;
InternalPageStackNavManager.StackPop += InternalPageStackNavManagerOnStackPop;
Expand All @@ -71,6 +78,20 @@ protected override void OnInitialized()
_dotNetObjectReference = DotNetObjectReference.Create(this);
}

private void NavigationManagerOnLocationChanged(object? sender, LocationChangedEventArgs e)
{
var currentPath = NavigationManager.GetAbsolutePath();
var tabbedPattern = _cachedTabbedPatterns.FirstOrDefault(u => u.IsMatch(currentPath));

if (tabbedPattern is not null && _lastVisitedTab.Pattern != tabbedPattern)
{
Console.Out.WriteLine($"Tab {_lastVisitedTab.AbsolutePath} to Tab {currentPath}");
_lastVisitedTab = (tabbedPattern, currentPath);

InternalPageStackNavManager?.NotifyTabChanged(currentPath, tabbedPattern);
}
}

protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
Expand Down Expand Up @@ -171,7 +192,8 @@ private async void InternalStackStackNavManagerOnStackClear(object? sender, Page
{
await Js.InvokeVoidAsync(JsInteropConstants.HistoryGo, -Pages.Count);

var backToLastVisitTab = string.IsNullOrWhiteSpace(e.RelativeUri) || _lastVisitedTabPath == GetAbsolutePath(e.RelativeUri);
var backToLastVisitTab = string.IsNullOrWhiteSpace(e.RelativeUri) ||
_lastVisitedTabPath == GetAbsolutePath(e.RelativeUri);

if (backToLastVisitTab)
{
Expand Down Expand Up @@ -278,11 +300,7 @@ private void DisableRootScrollbar(bool disable)

protected override async ValueTask DisposeAsyncCore()
{
if (_module is not null)
{
await _module.InvokeVoidAsync("detachListener", _dotnetObjectId);
await _module.DisposeAsync();
}
NavigationManager.LocationChanged -= NavigationManagerOnLocationChanged;

if (InternalPageStackNavManager is not null)
{
Expand All @@ -292,6 +310,12 @@ protected override async ValueTask DisposeAsyncCore()
InternalPageStackNavManager.StackClear -= InternalStackStackNavManagerOnStackClear;
InternalPageStackNavManager.StackGoBackTo -= InternalPageStackNavManagerOnStackGoBackTo;
}

if (_module is not null)
{
await _module.InvokeVoidAsync("detachListener", _dotnetObjectId);
await _module.DisposeAsync();
}
}

private enum PageType
Expand Down

0 comments on commit 2528e45

Please sign in to comment.