Skip to content

Commit

Permalink
Modifies NavigateFromAsync to use navigationStack
Browse files Browse the repository at this point in the history
  • Loading branch information
niimima committed Jul 29, 2024
1 parent 86b68a5 commit 41b3270
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 24 deletions.
38 changes: 31 additions & 7 deletions src/Maui/Prism.Maui/Navigation/PageNavigationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -340,22 +340,29 @@ public virtual async Task<INavigationResult> NavigateFromAsync(string viewName,

try
{
if (route.IsAbsoluteUri) throw new NavigationException(NavigationException.UnsupportedAbsoluteUri);

parameters ??= new NavigationParameters();

NavigationSource = PageNavigationSource.NavigationService;

var routeSegments = UriParsingHelper.GetUriSegments(route);
var navigationSegments = UriParsingHelper.GetUriSegments(route);

// Find a page that matches the viewName.
var page = GetCurrentPage();
while (page != null)
var currentPage = GetCurrentPage();
var navigationPages = currentPage.Navigation.NavigationStack.ToList();
navigationPages.Reverse();
var foundPage = navigationPages.FirstOrDefault(page => ViewModelLocator.GetNavigationName(page) == viewName);
var removePageCount = navigationPages.IndexOf(foundPage);

// Insert RemovePageSegment.
var routeString = route.ToString();
for (int i = 0; i < removePageCount; i++)
{
if (page is not null && ViewModelLocator.GetNavigationName(page) == viewName)
break;
page = page.GetParentPage();
AddToFront(navigationSegments, RemovePageSegment);
}

await ProcessNavigation(page, routeSegments, parameters, null, null);
await ProcessNavigation(currentPage, navigationSegments, parameters, null, null);

return Notify(route, parameters);
}
Expand All @@ -371,6 +378,23 @@ public virtual async Task<INavigationResult> NavigateFromAsync(string viewName,
}
}

private static void AddToFront<T>(Queue<T> queue, T element)
{
var tempQueue = new Queue<T>();

while (queue.Count > 0)
{
tempQueue.Enqueue(queue.Dequeue());
}

queue.Enqueue(element);

while (tempQueue.Count > 0)
{
queue.Enqueue(tempQueue.Dequeue());
}
}

/// <summary>
/// Selects a Tab of the TabbedPage parent.
/// </summary>
Expand Down
5 changes: 5 additions & 0 deletions src/Prism.Core/Navigation/NavigationException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ public class NavigationException : Exception
/// </summary>
public const string UnknownException = "An unknown error occurred. You may need to specify whether to Use Modal Navigation or not.";

/// <summary>
/// The <see cref="NavigationException"/> Message returned when an absolute path is specified but not supported.
/// </summary>
public const string UnsupportedAbsoluteUri = "An unsupported absolute uri. Please use a relative URI.";

/// <summary>
/// Initializes a new instance of the <see cref="NavigationException"/>
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -510,29 +510,20 @@ public async Task Navigation_Animation_IsFalse()
}

[Fact]
public async Task Navigation_FromPageUsingRoute()
public async Task Navigation_FromPageUsingRoute_OnNavigationPage()
{
var mauiApp = CreateBuilder(prism => prism.CreateWindow("MockHome/NavigationPage/MockViewA"))
var mauiApp = CreateBuilder(prism => prism.CreateWindow("NavigationPage/MockViewA/MockViewB/MockViewC"))
.Build();
var window = GetWindow(mauiApp);
var navigationService = Prism.Navigation.Xaml.Navigation.GetNavigationService(window.CurrentPage);
var currentNavigationStackUri = string.Join("/", window.CurrentPage.Navigation.NavigationStack.Select(v => v.GetType().Name));
Assert.Equal("MockViewA/MockViewB/MockViewC", currentNavigationStackUri);

var pageNavigatingFrom = (MockHome)window.Page;
var navigationPage = (NavigationPage)pageNavigatingFrom.Detail;
Assert.IsType<MockViewA>(navigationPage.CurrentPage);

var result = await navigationPage.CurrentPage.GetContainerProvider()
.Resolve<INavigationService>()
.NavigateFromAsync("MockHome", UriParsingHelper.Parse("NavigationPage/MockViewB"), null);
var result = await navigationService.NavigateFromAsync("MockViewA", UriParsingHelper.Parse("MockViewD/MockViewE"), null);

Assert.True(result.Success);

// MockHome(FlyoutPage) has not been replaced.
var pageNavigatedFrom = (MockHome)window.Page;
Assert.Equal(pageNavigatingFrom, pageNavigatedFrom);

// Navigation should be succeeded.
navigationPage = (NavigationPage)pageNavigatedFrom.Detail;
Assert.IsType<MockViewB>(navigationPage.CurrentPage);
currentNavigationStackUri = string.Join("/", window.CurrentPage.Navigation.NavigationStack.Select(v => v.GetType().Name));
Assert.Equal("MockViewA/MockViewD/MockViewE", currentNavigationStackUri);
}

[Fact]
Expand Down

0 comments on commit 41b3270

Please sign in to comment.