Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Adding ClosableNavigator to close dialog/flyout when attempting to navigate to unsupported route #2128

Merged
merged 3 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions src/Uno.Extensions.Navigation.UI/Navigator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,13 @@ await RedirectForDependsOn(request, rm) is { } dependsNavResponse)
request = request with { Route = route };

if (Logger.IsEnabled(LogLevel.Trace)) Logger.LogTraceMessage($"Building fully qualified route for unhandled request. New request: {request.Route}");

if(Region.Navigator() is ClosableNavigator closable)
{
if (Logger.IsEnabled(LogLevel.Trace)) Logger.LogTraceMessage($"Closing navigator and redirecting request");
return closable.CloseAndNavigateAsync(request);
}

return Region.NavigateAsync(request);

}
Expand Down
55 changes: 55 additions & 0 deletions src/Uno.Extensions.Navigation.UI/Navigators/ClosableNavigator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
namespace Uno.Extensions.Navigation.Navigators;

/// <summary>
/// Defines a Navigator that can be closed, with requests being
/// routed to the Navigator that was used to create/launch the Navigator
/// </summary>
public abstract class ClosableNavigator : ControlNavigator
{
private INavigator? Source { get; set; }

/// <summary>
/// Creates new instance of ClosableNavigator
/// </summary>
/// <param name="logger">Logger for logging output</param>
/// <param name="dispatcher">Dispatcher for thread access</param>
/// <param name="region">The corresponding Region</param>
/// <param name="resolver">The route resolver</param>
protected ClosableNavigator(ILogger logger, IDispatcher dispatcher, IRegion region, IRouteResolver resolver) : base(logger, dispatcher, region, resolver)
{
}

/// <inheritdoc/>
protected override async Task<Route?> ExecuteRequestAsync(NavigationRequest request)
{
// Capture the source from the initial navigation, which will open the dialog/flyout
// so that it can be used to forward navigation requests to.
Source ??= request.Source;

return default;
}

/// <summary>
/// Closes the current dialog or flyout and then navigates using the Navigator
/// that originally opened the dialog/flyout
/// </summary>
/// <param name="request">The request to direct to the source Navigator</param>
/// <returns>The navigation response</returns>
public async Task<NavigationResponse?> CloseAndNavigateAsync(NavigationRequest request)
{
await CloseNavigator();

if (Source is null)
{
return default;
}

return await Source.NavigateAsync(request);
}

/// <summary>
/// Closes the current navigator (for use in CloseAndNavigate
/// </summary>
/// <returns>Task that can be awaited</returns>
protected abstract Task CloseNavigator();
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Uno.Extensions.Navigation.Navigators;

public abstract class DialogNavigator : ControlNavigator
public abstract class DialogNavigator : ClosableNavigator
{
public override bool CanGoBack => ShowTask is not null;

Expand All @@ -21,6 +21,9 @@ protected DialogNavigator(

protected override async Task<Route?> ExecuteRequestAsync(NavigationRequest request)
{
// Capture the Source - return value can be ignored
_ = await base.ExecuteRequestAsync(request);

var route = request.Route;

// Make sure any existing dialogs are closed
Expand Down Expand Up @@ -59,4 +62,6 @@ protected void CloseDialog()
}

protected abstract Task<IAsyncInfo?> DisplayDialog(NavigationRequest request, Type? viewType, object? viewModel);
protected override async Task CloseNavigator() => CloseDialog();

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Uno.Extensions.Navigation.Navigators;

public class FlyoutNavigator : ControlNavigator
public class FlyoutNavigator : ClosableNavigator
{
public override bool CanGoBack => _flyout is not null;

Expand Down Expand Up @@ -35,6 +35,9 @@ protected override Task<bool> RegionCanNavigate(Route route, RouteInfo? routeMap

protected override async Task<Route?> ExecuteRequestAsync(NavigationRequest request)
{
// Capture the Source - return value can be ignored
_ = await base.ExecuteRequestAsync(request);

if (Region.Services is null)
{
return default;
Expand Down Expand Up @@ -195,4 +198,6 @@ private void CleanupFlyout()

protected override Task CheckLoadedAsync() => _flyout is not null && _content is not null ? _content.EnsureLoaded() : Task.CompletedTask;

protected override async Task CloseNavigator() => CloseFlyout();

}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
uen:Navigation.Request="!DialogsComplex/DialogsComplexDialogSecond"
Content="Complex Dialog Nav Request - Second Page" />


<Button AutomationProperties.AutomationId="ComplexDialogSecondPageButton"
uen:Navigation.Request="ContentDialogsSecond"
Content="Complex Dialog - Second Page" />
</StackPanel>
</ScrollViewer>
</Grid>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

namespace TestHarness.Ext.Navigation.Dialogs;
namespace TestHarness.Ext.Navigation.Dialogs;

public sealed partial class ContentDialogsPage : Page
{
public ContentDialogsPage()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<Page x:Class="TestHarness.Ext.Navigation.Dialogs.ContentDialogsSecondPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestHarness.Ext.Navigation.Dialogs"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:utu="using:Uno.Toolkit.UI"
xmlns:uen="using:Uno.Extensions.Navigation.UI"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<utu:NavigationBar Content="Content Dialogs - Second Page"
AutomationProperties.AutomationId="DialogsContentDialogsSecondPageNavigationBar" >
<utu:NavigationBar.MainCommand>
<AppBarButton AutomationProperties.AutomationId="DialogsContentDialogsSecondPageBackButton">
<AppBarButton.Icon>
<BitmapIcon UriSource="ms-appx:///Assets/Icons/back.png" />
</AppBarButton.Icon>
</AppBarButton>
</utu:NavigationBar.MainCommand>
</utu:NavigationBar>

<ScrollViewer Grid.Row="1">
<StackPanel>

</StackPanel>
</ScrollViewer>
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace TestHarness.Ext.Navigation.Dialogs;

public sealed partial class ContentDialogsSecondPage : Page
{
public ContentDialogsSecondPage()
{
this.InitializeComponent();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

namespace TestHarness.Ext.Navigation.Dialogs;
namespace TestHarness.Ext.Navigation.Dialogs;

public sealed partial class DialogsBasicFlyout : Page
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

namespace TestHarness.Ext.Navigation.Dialogs;
namespace TestHarness.Ext.Navigation.Dialogs;

public sealed partial class DialogsComplexDialog : ContentDialog
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
<Button AutomationProperties.AutomationId="ComplexDialogFirstPageCloseButton"
Content="Close dialog"
Command="{Binding CloseCommand}" />
<Button AutomationProperties.AutomationId="ComplexDialogFirstPageCloseAndSecondButton"
uen:Navigation.Request="ContentDialogsSecond"
Content="Close dialog and then Second page" />

</StackPanel>
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

namespace TestHarness.Ext.Navigation.Dialogs;
namespace TestHarness.Ext.Navigation.Dialogs;

public sealed partial class DialogsComplexFlyout : Flyout
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

namespace TestHarness.Ext.Navigation.Dialogs;
namespace TestHarness.Ext.Navigation.Dialogs;

public sealed partial class DialogsComplexFlyoutOnePage : Page
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

namespace TestHarness.Ext.Navigation.Dialogs;
namespace TestHarness.Ext.Navigation.Dialogs;

public sealed partial class DialogsComplexFlyoutTwoPage : Page
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

namespace TestHarness.Ext.Navigation.Dialogs;
namespace TestHarness.Ext.Navigation.Dialogs;

public sealed partial class DialogsFlyoutsPage : Page
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

namespace TestHarness.Ext.Navigation.Dialogs;
namespace TestHarness.Ext.Navigation.Dialogs;

public partial class DialogsFlyoutsViewModel
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@


namespace TestHarness.Ext.Navigation.Dialogs;
namespace TestHarness.Ext.Navigation.Dialogs;

public class DialogsHostInit : BaseHostInitialization
{
Expand Down Expand Up @@ -37,6 +35,8 @@ protected override void RegisterRoutes(IViewRegistry views, IRouteRegistry route
);

views.Register(
new ViewMap<ContentDialogsPage>(),
new ViewMap<ContentDialogsSecondPage>(),
new ViewMap<DialogsFlyoutsPage, DialogsFlyoutsViewModel>(),
new ViewMap<DialogsComplexDialog>(),
new ViewMap<DialogsComplexDialogFirstPage, DialogsComplexDialogFirstViewModel>(),
Expand All @@ -54,11 +54,13 @@ protected override void RegisterRoutes(IViewRegistry views, IRouteRegistry route
new RouteMap("",
Nested: new[]
{
new RouteMap("ContentDialogs", View: views.FindByView<ContentDialogsPage>()),
new RouteMap("ContentDialogsSecond", View: views.FindByView<ContentDialogsSecondPage>(), DependsOn:"ContentDialogs"),
new RouteMap("DialogsFlyouts", View: views.FindByViewModel<DialogsFlyoutsViewModel>()),
new RouteMap("DialogsComplex", View: views.FindByView<DialogsComplexDialog>(), Nested: new[]
{
new RouteMap("DialogsComplexDialogFirst", View: views.FindByViewModel<DialogsComplexDialogFirstViewModel>(), IsDefault:true),
new RouteMap("DialogsComplexDialogSecond", View: views.FindByViewModel<DialogsComplexDialogSecondViewModel>())
new RouteMap("DialogsComplexDialogSecond", View: views.FindByViewModel<DialogsComplexDialogSecondViewModel>(), DependsOn: "DialogsComplexDialogFirst")
}),
new RouteMap("DialogsComplexFlyout", View: views.FindByView<DialogsComplexFlyout>(), Nested: new[]
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@


namespace TestHarness.Ext.Navigation.Dialogs;
namespace TestHarness.Ext.Navigation.Dialogs;

[TestSectionRoot("Dialogs", TestSections.Navigation_Dialogs, typeof(DialogsHostInit))]
public sealed partial class DialogsMainPage : BaseTestSectionPage
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

namespace TestHarness.Ext.Navigation.Dialogs;
namespace TestHarness.Ext.Navigation.Dialogs;

public sealed partial class DialogsSimpleDialog : ContentDialog
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

namespace TestHarness.Ext.Navigation.Dialogs;
namespace TestHarness.Ext.Navigation.Dialogs;

public class DialogsSimpleViewModel
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

namespace TestHarness.Ext.Navigation.Dialogs;
namespace TestHarness.Ext.Navigation.Dialogs;

public sealed partial class LocalizedDialogsPage : Page
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,9 @@
<Compile Include="$(MSBuildThisFileDirectory)Ext\Navigation\Dialogs\ContentDialogsPage.xaml.cs">
<DependentUpon>ContentDialogsPage.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Ext\Navigation\Dialogs\ContentDialogsSecondPage.xaml.cs">
<DependentUpon>ContentDialogsSecondPage.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Ext\Navigation\Dialogs\DialogsBasicFlyout.xaml.cs">
<DependentUpon>DialogsBasicFlyout.xaml</DependentUpon>
</Compile>
Expand Down Expand Up @@ -548,6 +551,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Ext\Navigation\Dialogs\ContentDialogsSecondPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Ext\Navigation\Dialogs\DialogsBasicFlyout.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
Expand Down Expand Up @@ -746,7 +753,7 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</_Globbled_Page>
<Page Include="@(_Globbled_Page)">
<Page Include="@(_Globbled_Page)">
<SubType>Designer</SubType>
</Page>
<_Globbed_Compile Include="$(MSBuildThisFileDirectory)**/*.xaml.cs" Exclude="@(Compile)">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,33 @@ public async Task When_ComplexContentDialog()
ImageAssert.AreEqual(screenBefore, screenClosed, tolerance: PixelTolerance.Exclusive(Constants.DefaultPixelTolerance));
}


[Test]
public async Task When_ComplexContentDialogNavigateSecondPage()
{
InitTestSection(TestSections.Navigation_Dialogs);

App.WaitThenTap("ContentDialogsButton");

App.WaitElement("DialogsContentDialogsPage");

var screenBefore = TakeScreenshot("When_Dialog_Before");
App.Tap("ComplexDialogNavRequestButton");
var screenAfter = TakeScreenshot("When_Dialog_After");
ImageAssert.AreNotEqual(screenBefore, screenAfter);

App.WaitElement("ComplexDialogFirstPageNavigationBar");

App.Tap("ComplexDialogFirstPageCloseAndSecondButton");

App.WaitElement("DialogsContentDialogsSecondPageNavigationBar");

App.Tap("DialogsContentDialogsSecondPageBackButton");

await Task.Delay(AppExtensions.UIWaitTimeInMilliseconds);

var screenClosed = TakeScreenshot("When_Dialog_Closed");
ImageAssert.AreEqual(screenBefore, screenClosed, tolerance: PixelTolerance.Exclusive(Constants.DefaultPixelTolerance));
}

}
Loading