Skip to content

Commit

Permalink
Introduce behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
albyrock87 committed Sep 24, 2024
1 parent 5759a7b commit 6cb895b
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ public interface INavigationConfiguration
/// </summary>
ImageSource? BackImage { get; }

/// <summary>
/// Gets the navigation intent behavior.
/// </summary>
NavigationIntentBehavior NavigationIntentBehavior { get; }

/// <summary>
/// Gets a dictionary which maps a page model type to corresponding page type.
/// </summary>
Expand Down
31 changes: 31 additions & 0 deletions Source/Nalu.Maui.Navigation/Interfaces/NavigationIntentBehavior.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
namespace Nalu;

/// <summary>
/// Defines how lifecycle events are triggered when a navigation intent is detected.
/// </summary>
public enum NavigationIntentBehavior
{
/// <summary>
/// When a navigation intent is detected, only intent-related navigation lifecycle events will be triggered.
/// </summary>
/// <example>
/// In the following example, if <c>MyIntent</c> is detected, the navigation will invoke only <c>OnAppearingAsync(MyIntent)</c>.
/// <code>
/// public ValueTask OnEnteringAsync()
/// public ValueTask OnAppearingAsync(MyIntent)
/// </code>
/// </example>
Strict,

/// <summary>
/// When a navigation intent is detected, if the corresponding intent-related navigation lifecycle event is not defined, the navigation will fall through to the generic one.
/// </summary>
/// <example>
/// In the following example, if <c>MyIntent</c> is detected, the navigation will invoke <c>OnEnteringAsync</c> and <c>OnAppearingAsync(MyIntent)</c> in sequence.
/// <code>
/// public ValueTask OnEnteringAsync()
/// public ValueTask OnAppearingAsync(MyIntent)
/// </code>
/// </example>
Fallthrough,
}
14 changes: 10 additions & 4 deletions Source/Nalu.Maui.Navigation/Internals/NavigationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ internal static class NavigationHelper
private static readonly MethodInfo _sendEnteringWithIntentAsyncMethod = typeof(NavigationHelper).GetMethod(nameof(SendEnteringWithIntentAsync), BindingFlags.NonPublic | BindingFlags.Static)!;
private static readonly MethodInfo _sendAppearingWithIntentAsyncMethod = typeof(NavigationHelper).GetMethod(nameof(SendAppearingWithIntentAsync), BindingFlags.NonPublic | BindingFlags.Static)!;

public static ValueTask SendEnteringAsync(Page page, object? intent)
public static ValueTask SendEnteringAsync(Page page, object? intent, INavigationConfiguration configuration)
{
var context = PageNavigationContext.Get(page);
if (context.Entered)
Expand All @@ -30,7 +30,10 @@ public static ValueTask SendEnteringAsync(Page page, object? intent)
return (ValueTask)_sendEnteringWithIntentAsyncMethod.MakeGenericMethod(intentType).Invoke(null, [target, intent])!;
}

return ValueTask.CompletedTask;
if (configuration.NavigationIntentBehavior == NavigationIntentBehavior.Strict)
{
return ValueTask.CompletedTask;
}
}

if (target is IEnteringAware enteringAware)
Expand Down Expand Up @@ -67,7 +70,7 @@ public static ValueTask SendLeavingAsync(Page page)
return ValueTask.CompletedTask;
}

public static ValueTask SendAppearingAsync(Page page, object? intent)
public static ValueTask SendAppearingAsync(Page page, object? intent, INavigationConfiguration configuration)
{
var context = PageNavigationContext.Get(page);
if (context.Appeared)
Expand All @@ -91,7 +94,10 @@ public static ValueTask SendAppearingAsync(Page page, object? intent)
return (ValueTask)_sendAppearingWithIntentAsyncMethod.MakeGenericMethod(intentType).Invoke(null, [target, intent])!;
}

return ValueTask.CompletedTask;
if (configuration.NavigationIntentBehavior == NavigationIntentBehavior.Strict)
{
return ValueTask.CompletedTask;
}
}

if (target is IAppearingAware appearingAware)
Expand Down
16 changes: 8 additions & 8 deletions Source/Nalu.Maui.Navigation/Internals/NavigationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public async Task InitializeAsync(IShellProxy shellProxy, string contentSegmentN

NavigationHelper.AssertIntent(page, intent, content.DestroyContent);

var enteringTask = NavigationHelper.SendEnteringAsync(page, intent).AsTask();
var enteringTask = NavigationHelper.SendEnteringAsync(page, intent, Configuration).AsTask();
if (!enteringTask.IsCompleted)
{
throw new NotSupportedException($"OnEnteringAsync() must not be async for the initial page {page.BindingContext!.GetType().FullName}.");
Expand All @@ -56,7 +56,7 @@ public async Task InitializeAsync(IShellProxy shellProxy, string contentSegmentN
await _shellProxy.SelectContentAsync(contentSegmentName).ConfigureAwait(true);
#pragma warning restore VSTHRD002

await NavigationHelper.SendAppearingAsync(page, intent).ConfigureAwait(true);
await NavigationHelper.SendAppearingAsync(page, intent, Configuration).ConfigureAwait(true);
}

public async Task<bool> GoToAsync(INavigationInfo navigation)
Expand Down Expand Up @@ -186,7 +186,7 @@ private async Task<bool> ExecuteRelativeNavigationAsync(
await shellProxy.CommitNavigationAsync().ConfigureAwait(true);
shellProxy.BeginNavigation();

await NavigationHelper.SendAppearingAsync(stackPage.Page, null).ConfigureAwait(true);
await NavigationHelper.SendAppearingAsync(stackPage.Page, null, Configuration).ConfigureAwait(true);
var canLeave = await NavigationHelper.CanLeaveAsync(stackPage.Page).ConfigureAwait(true);
if (!canLeave)
{
Expand All @@ -211,7 +211,7 @@ private async Task<bool> ExecuteRelativeNavigationAsync(
var page = CreatePage(pageType, stackPage.Page, Configuration.BackImage);

var isModal = Shell.GetPresentationMode(page).HasFlag(PresentationMode.Modal);
await NavigationHelper.SendEnteringAsync(page, intent).ConfigureAwait(true);
await NavigationHelper.SendEnteringAsync(page, intent, Configuration).ConfigureAwait(true);
await shellProxy.PushAsync(segmentName, page).ConfigureAwait(true);
stack.Add(new NavigationStackPage($"{stackPage.Route}/{segmentName}", segmentName, page, isModal));
}
Expand All @@ -226,7 +226,7 @@ private async Task<bool> ExecuteRelativeNavigationAsync(
shellProxy.BeginNavigation();

NavigationHelper.AssertIntent(page, intent);
await NavigationHelper.SendAppearingAsync(page, intent).ConfigureAwait(true);
await NavigationHelper.SendAppearingAsync(page, intent, Configuration).ConfigureAwait(true);
}

return true;
Expand Down Expand Up @@ -373,7 +373,7 @@ private async Task<bool> ExecuteCrossContentNavigationAsync(
await shellProxy.CommitNavigationAsync().ConfigureAwait(true);
shellProxy.BeginNavigation();

await NavigationHelper.SendAppearingAsync(contentPage, null).ConfigureAwait(true);
await NavigationHelper.SendAppearingAsync(contentPage, null, Configuration).ConfigureAwait(true);
if (!await NavigationHelper.CanLeaveAsync(contentPage).ConfigureAwait(true))
{
return false;
Expand Down Expand Up @@ -408,7 +408,7 @@ Task EnsureContentIsSelectedAsync()
var targetContentPage = targetContent.GetOrCreateContent();
var targetIsShellContent = navigation.Count == 1;
var intent = targetIsShellContent ? navigation.Intent : null;
await NavigationHelper.SendEnteringAsync(targetContentPage, intent).ConfigureAwait(true);
await NavigationHelper.SendEnteringAsync(targetContentPage, intent, Configuration).ConfigureAwait(true);
await ShellProxy.SelectContentAsync(targetContent.SegmentName).ConfigureAwait(true);

if (!targetIsShellContent)
Expand All @@ -422,7 +422,7 @@ Task EnsureContentIsSelectedAsync()
}

await shellProxy.CommitNavigationAsync().ConfigureAwait(true);
await NavigationHelper.SendAppearingAsync(targetContentPage, intent).ConfigureAwait(true);
await NavigationHelper.SendAppearingAsync(targetContentPage, intent, Configuration).ConfigureAwait(true);
return true;
}

Expand Down
13 changes: 13 additions & 0 deletions Source/Nalu.Maui.Navigation/NavigationConfigurator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ public class NavigationConfigurator : INavigationConfiguration
/// <inheritdoc />
public ImageSource? BackImage { get; private set; }

/// <inheritdoc />
public NavigationIntentBehavior NavigationIntentBehavior { get; private set; }

/// <inheritdoc />
public IReadOnlyDictionary<Type, Type> Mapping => _mapping;

Expand Down Expand Up @@ -61,6 +64,16 @@ public NavigationConfigurator WithMenuImage(ImageSource imageSource)
return this;
}

/// <summary>
/// Defines how lifecycle events should be handled when an intent is detected.
/// </summary>
/// <param name="behavior">The behavior to use.</param>
public NavigationConfigurator WithNavigationIntentBehavior(NavigationIntentBehavior behavior)
{
NavigationIntentBehavior = behavior;
return this;
}

/// <summary>
/// Registers <typeparamref name="TPage"/> as the view for <typeparamref name="TPageModel"/>.
/// Adds <typeparamref name="TPage"/> and <typeparamref name="TPageModel"/> as scoped services.
Expand Down

0 comments on commit 6cb895b

Please sign in to comment.