This repository has been archived by the owner on May 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
989 additions
and
389 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
using System; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using NUnit.Framework; | ||
using Xamarin.Forms.Internals; | ||
|
||
namespace Xamarin.Forms.Core.UnitTests | ||
{ | ||
[TestFixture] | ||
public class ShellNavigationTests : ShellTestBase | ||
{ | ||
[Test] | ||
public async Task NavigationWithQueryStringWhenPageMatchesBindingContext() | ||
{ | ||
var shell = new Shell(); | ||
|
||
var one = new ShellItem { Route = "one" }; | ||
var two = new ShellItem { Route = "two" }; | ||
|
||
var tabone = MakeSimpleShellSection("tabone", "content"); | ||
var tabfour = MakeSimpleShellSection("tabfour", "content", null); | ||
|
||
one.Items.Add(tabone); | ||
two.Items.Add(tabfour); | ||
|
||
shell.Items.Add(one); | ||
shell.Items.Add(two); | ||
|
||
ShellTestPage pagetoTest = new ShellTestPage(); | ||
await shell.GoToAsync(new ShellNavigationState($"//two/tabfour/content?{nameof(ShellTestPage.SomeQueryParameter)}=1234&two.rabbit=monkey")); | ||
two.CurrentItem.CurrentItem.ContentTemplate = new DataTemplate(() => | ||
{ | ||
pagetoTest = new ShellTestPage(); | ||
pagetoTest.BindingContext = pagetoTest; | ||
return pagetoTest; | ||
}); | ||
|
||
|
||
var page = (two.CurrentItem.CurrentItem as IShellContentController).GetOrCreateContent(); | ||
Assert.AreEqual("1234", (page as ShellTestPage).SomeQueryParameter); | ||
|
||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
|
||
namespace Xamarin.Forms | ||
{ | ||
/// <summary> | ||
/// This attempts to locate the intended route trying to be navigated to | ||
/// </summary> | ||
internal class RouteRequestBuilder | ||
{ | ||
readonly List<string> _globalRouteMatches = new List<string>(); | ||
readonly List<string> _matchedSegments = new List<string>(); | ||
readonly List<string> _fullSegments = new List<string>(); | ||
readonly string[] _allSegments = null; | ||
readonly static string _uriSeparator = "/"; | ||
public Shell Shell { get; private set; } | ||
public ShellItem Item { get; private set; } | ||
public ShellSection Section { get; private set; } | ||
public ShellContent Content { get; private set; } | ||
public object LowestChild => | ||
(object)Content ?? (object)Section ?? (object)Item ?? (object)Shell; | ||
|
||
public RouteRequestBuilder(string shellSegment, string userSegment, object node, string[] allSegments) | ||
{ | ||
_allSegments = allSegments; | ||
if (node != null) | ||
AddMatch(shellSegment, userSegment, node); | ||
else | ||
AddGlobalRoute(userSegment, shellSegment); | ||
} | ||
|
||
public RouteRequestBuilder(RouteRequestBuilder builder) | ||
{ | ||
_allSegments = builder._allSegments; | ||
_matchedSegments.AddRange(builder._matchedSegments); | ||
_fullSegments.AddRange(builder._fullSegments); | ||
_globalRouteMatches.AddRange(builder._globalRouteMatches); | ||
Shell = builder.Shell; | ||
Item = builder.Item; | ||
Section = builder.Section; | ||
Content = builder.Content; | ||
} | ||
|
||
public void AddGlobalRoute(string routeName, string segment) | ||
{ | ||
_globalRouteMatches.Add(routeName); | ||
_fullSegments.Add(segment); | ||
_matchedSegments.Add(segment); | ||
} | ||
|
||
|
||
public void AddMatch(string shellSegment, string userSegment, object node) | ||
{ | ||
if (node == null) | ||
throw new ArgumentNullException(nameof(node)); | ||
|
||
switch (node) | ||
{ | ||
case ShellUriHandler.GlobalRouteItem globalRoute: | ||
if (globalRoute.IsFinished) | ||
{ | ||
_globalRouteMatches.Add(globalRoute.SourceRoute); | ||
} | ||
break; | ||
case Shell shell: | ||
Shell = shell; | ||
break; | ||
case ShellItem item: | ||
Item = item; | ||
break; | ||
case ShellSection section: | ||
Section = section; | ||
|
||
if (Item == null) | ||
{ | ||
Item = Section.Parent as ShellItem; | ||
_fullSegments.Add(Item.Route); | ||
} | ||
|
||
break; | ||
case ShellContent content: | ||
Content = content; | ||
if (Section == null) | ||
{ | ||
Section = Content.Parent as ShellSection; | ||
_fullSegments.Add(Section.Route); | ||
} | ||
|
||
if (Item == null) | ||
{ | ||
Item = Section.Parent as ShellItem; | ||
_fullSegments.Insert(0, Item.Route); | ||
} | ||
|
||
break; | ||
|
||
} | ||
|
||
// if shellSegment == userSegment it means the implicit route is part of the request | ||
if (!Routing.IsImplicit(shellSegment) || shellSegment == userSegment) | ||
_matchedSegments.Add(shellSegment); | ||
|
||
_fullSegments.Add(shellSegment); | ||
} | ||
|
||
public string NextSegment | ||
{ | ||
get | ||
{ | ||
var nextMatch = _matchedSegments.Count; | ||
if (nextMatch >= _allSegments.Length) | ||
return null; | ||
|
||
return _allSegments[nextMatch]; | ||
} | ||
} | ||
|
||
public string RemainingPath | ||
{ | ||
get | ||
{ | ||
var nextMatch = _matchedSegments.Count; | ||
if (nextMatch >= _allSegments.Length) | ||
return null; | ||
|
||
return Routing.FormatRoute(String.Join(_uriSeparator, _allSegments.Skip(nextMatch))); | ||
} | ||
} | ||
public string[] RemainingSegments | ||
{ | ||
get | ||
{ | ||
var nextMatch = _matchedSegments.Count; | ||
if (nextMatch >= _allSegments.Length) | ||
return null; | ||
|
||
return _allSegments.Skip(nextMatch).ToArray(); | ||
} | ||
} | ||
|
||
string MakeUriString(List<string> segments) | ||
{ | ||
if (segments[0].StartsWith(_uriSeparator, StringComparison.Ordinal) || segments[0].StartsWith("\\", StringComparison.Ordinal)) | ||
return String.Join(_uriSeparator, segments); | ||
|
||
return $"//{String.Join(_uriSeparator, segments)}"; | ||
} | ||
|
||
public string PathNoImplicit => MakeUriString(_matchedSegments); | ||
public string PathFull => MakeUriString(_fullSegments); | ||
|
||
public bool IsFullMatch => _matchedSegments.Count == _allSegments.Length; | ||
public List<string> GlobalRouteMatches => _globalRouteMatches; | ||
public List<string> SegmentsMatched => _matchedSegments; | ||
} | ||
} |
Oops, something went wrong.