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

fix: App blanks out when navigating to invalid route #2517

Merged
merged 7 commits into from
Aug 22, 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
59 changes: 34 additions & 25 deletions src/Uno.Extensions.Navigation.UI/RouteResolverDefault.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,7 @@ private RouteInfo[] DefaultMapping(string? path = null, Type? view = null, Type?

protected virtual RouteInfo? InternalDefaultMapping(string? path = null, Type? view = null, Type? viewModel = null)
{
if (path is null &&
view is null &&
viewModel is null)
if (path is null && view is null && viewModel is null)
{
return default;
}
Expand All @@ -71,17 +69,17 @@ view is null &&
// Trim any qualifiers
path = path.ExtractBase(out _, out _);

// If no path is provided, attempt to get a path
// from the view or viewmodel type provided
// If no path is provided, attempt to get a path from the view or viewmodel type provided
if (string.IsNullOrWhiteSpace(path))
{
path = PathFromTypes(view, viewModel);
}

// If path is still null, we can't build a mapping, so just return
if (path is null ||
string.IsNullOrWhiteSpace(path))
if (path is null || string.IsNullOrWhiteSpace(path))
{
if (Logger.IsEnabled(LogLevel.Warning))
Logger.LogWarningMessage($"Unable to resolve path from types. Path: '{path}', View: '{view?.Name}', ViewModel: '{viewModel?.Name}'");
return default;
}

Expand All @@ -96,32 +94,40 @@ view is null &&
if (viewMap is not null)
{
var viewFunc = (viewMap.View is not null) ?
() => viewMap.View :
viewMap.ViewSelector;
() => viewMap.View :
viewMap.ViewSelector;
var defaultMapFromViewMap = new RouteInfo(
Path: path,
View: viewFunc,
ViewAttributes: viewMap.ViewAttributes,
ViewModel: viewMap.ViewModel,
Data: viewMap.Data?.Data,
ToQuery: viewMap?.Data?.UntypedToQuery,
FromQuery: viewMap?.Data?.UntypedFromQuery,
ResultData: viewMap?.ResultData,
IsDialogViewType: () =>
{
return IsDialogViewType(viewFunc?.Invoke());
});
Path: path,
View: viewFunc,
ViewAttributes: viewMap.ViewAttributes,
ViewModel: viewMap.ViewModel,
Data: viewMap.Data?.Data,
ToQuery: viewMap?.Data?.UntypedToQuery,
FromQuery: viewMap?.Data?.UntypedFromQuery,
ResultData: viewMap?.ResultData,
IsDialogViewType: () =>
{
return IsDialogViewType(viewFunc?.Invoke());
});
Mappings.Add(defaultMapFromViewMap);
if (Logger.IsEnabled(LogLevel.Debug)) Logger.LogDebugMessage($"Created default mapping from viewmap - Path '{defaultMapFromViewMap.Path}'");
return defaultMapFromViewMap;
}

if (Logger.IsEnabled(LogLevel.Information)) Logger.LogInformationMessage($"For better performance (avoid reflection), create mapping for for path '{path}', view '{view?.Name}', view model '{viewModel?.Name}'");
if (Logger.IsEnabled(LogLevel.Information))
Logger.LogInformationMessage($"For better performance (avoid reflection), create mapping for path '{path}', view '{view?.Name}', view model '{viewModel?.Name}'");

if (view is null)
{
var trimmedPath = TrimSuffices(path, ViewModelSuffixes);
view = TypeFromPath(trimmedPath, true, ViewSuffixes, type => type.IsSubclassOf(typeof(FrameworkElement)));

if (view is not null)
{
if (Logger.IsEnabled(LogLevel.Information))
Logger.LogInformationMessage($"Potential conflict detected: The route '{path}' resolved to a common control or class name '{view.Name}'. This could lead to unexpected behavior.");
}

}

if (viewModel is null)
Expand All @@ -130,8 +136,7 @@ view is null &&
viewModel = TypeFromPath(trimmedPath, false, ViewModelSuffixes);
}

if (path is not null &&
!string.IsNullOrWhiteSpace(path))
if (path is not null && !string.IsNullOrWhiteSpace(path))
{
var defaultMap = new RouteInfo(path, View: () => view, ViewModel: viewModel, IsDialogViewType: () =>
{
Expand All @@ -142,14 +147,16 @@ view is null &&
return defaultMap;
}

if (Logger.IsEnabled(LogLevel.Warning)) Logger.LogWarningMessage($"Unable to create default mapping");
if (Logger.IsEnabled(LogLevel.Warning)) Logger.LogWarningMessage($"Unable to create default mapping for path '{path}', view '{view?.Name}', view model '{viewModel?.Name}'");
return default;
}

private Type? TypeFromPath(string path, bool allowMatchExact, IEnumerable<string> suffixes, Func<Type, bool>? condition = null)
{
if (string.IsNullOrWhiteSpace(path))
{
if (Logger.IsEnabled(LogLevel.Warning))
Logger.LogWarningMessage($"Navigation failed: Empty or null path provided.");
return default;
}

Expand All @@ -168,6 +175,8 @@ view is null &&
}
}
}
if (Logger.IsEnabled(LogLevel.Warning))
Logger.LogWarningMessage($"Navigation failed: Could not resolve type for path '{path}'.");

return null;
}
Expand Down
3 changes: 1 addition & 2 deletions src/Uno.Extensions.Navigation/RouteExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ public static bool IsClearBackstack(this Route route) =>
nextQualifier = qualifierMatch.Value;
}

qualifierMatch = alphaRegex.Match(path);
var routeBase = qualifierMatch.Success ? qualifierMatch.Value : String.Empty;
var routeBase = path.Split("/").FirstOrDefault();
if (routeBase is { Length: > 0 })
{
if (path.Length > routeBase.Length + 1)
Expand Down
1 change: 1 addition & 0 deletions testing/TestHarness/TestHarness.Core/TestSections.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public enum TestSections
Navigation_ContentControl,
Navigation_PageNavigation,
Navigation_PageNavigationRegistered,
Navigation_RoutesNavigation,
Navigation_Dialogs,
Navigation_Responsive,
Navigation_ListToDetails,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
namespace TestHarness.UITest;

public class Given_RoutesNavigation : NavigationTestBase
{
[Test]
public async Task When_Navigate_To_SamplePage()
{
InitTestSection(TestSections.Navigation_RoutesNavigation);

App.WaitThenTap("SamplePageButton");

App.WaitElement("SamplePage");
}

[Test]
public async Task When_Navigate_To_SecondPage()
{
InitTestSection(TestSections.Navigation_RoutesNavigation);

App.WaitThenTap("SecondPageButton");

App.WaitElement("SecondPage");
}

[Test]
public async Task When_Navigate_To_Unregistered_SecondPage()
{
InitTestSection(TestSections.Navigation_RoutesNavigation);

App.WaitThenTap("SecondPageUnregisteredButton");

App.WaitElement("SecondPage");
}

[Test]
public async Task When_Navigate_To_List_Template()
{
InitTestSection(TestSections.Navigation_RoutesNavigation);

App.WaitThenTap("ListTemplateButton");

App.WaitElement("ListTemplate");
}

[Test]
public async Task When_Navigate_To_ItemsPage()
{
InitTestSection(TestSections.Navigation_RoutesNavigation);

App.WaitThenTap("ItemsPageButton");

App.WaitElement("ItemsPage");
}

[Test]
public async Task When_Navigate_To_MyControl()
{
InitTestSection(TestSections.Navigation_RoutesNavigation);

App.WaitThenTap("MyControlButton");

App.WaitElement("MyControlView");
}

[Test]
public async Task When_Navigate_To_MyControlView()
{
InitTestSection(TestSections.Navigation_RoutesNavigation);

App.WaitThenTap("MyControlViewButton");

App.WaitElement("MyControlView");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<Page x:Class="TestHarness.Ext.Navigation.RoutesNavigation.HomePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestHarness.Ext.Navigation.RoutesNavigation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:uen="using:Uno.Extensions.Navigation.UI"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">

<Grid>
<StackPanel Grid.Row="1"
Orientation="Vertical"
HorizontalAlignment="Center">
<Button Content="SamplePage"
uen:Navigation.Request="Sample"
AutomationProperties.AutomationId="SamplePageButton" />
<Button Content="SecondPage"
uen:Navigation.Request="Second"
AutomationProperties.AutomationId="SecondPageButton" />
<Button Content="Second Page (not registered)"
uen:Navigation.Request="SecondPage"
AutomationProperties.AutomationId="SecondPageUnregisteredButton" />
<Button Content="List_Template"
uen:Navigation.Request="List_Template"
AutomationProperties.AutomationId="ListTemplateButton" />
<Button Content="ItemsPage"
uen:Navigation.Request="Items"
AutomationProperties.AutomationId="ItemsPageButton" />
<Button Content="MyControl"
uen:Navigation.Request="MyControl"
AutomationProperties.AutomationId="MyControlButton" />
<Button Content="MyControlView"
uen:Navigation.Request="MyControlView"
AutomationProperties.AutomationId="MyControlViewButton" />

</StackPanel>

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

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

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<utu:NavigationBar Content="Items Page"
AutomationProperties.AutomationId="ItemsPage" />
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center"
Grid.Row="1">
<Button AutomationProperties.AutomationId="BackButton"
Content="Back"
uen:Navigation.Request="-" />
</StackPanel>
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace TestHarness.Ext.Navigation.RoutesNavigation;

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

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<utu:NavigationBar Content="List Template"
AutomationProperties.AutomationId="ListTemplate" />
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center"
Grid.Row="1">
<Button AutomationProperties.AutomationId="BackButton"
Content="Back"
uen:Navigation.Request="-" />
</StackPanel>
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace TestHarness.Ext.Navigation.RoutesNavigation;

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

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<utu:NavigationBar Content="My Control View"
AutomationProperties.AutomationId="MyControlView" />
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center"
Grid.Row="1">
<Button AutomationProperties.AutomationId="BackButton"
Content="Back"
uen:Navigation.Request="-" />
</StackPanel>
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace TestHarness.Ext.Navigation.RoutesNavigation;

public partial class MyControlView : Page
{
public MyControlView()
{
InitializeComponent();
}
}
Loading
Loading