diff --git a/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellPageRendererTracker.cs b/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellPageRendererTracker.cs index 893531e55110..d0105eba2b84 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellPageRendererTracker.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellPageRendererTracker.cs @@ -141,7 +141,14 @@ protected virtual void UpdateTabBarVisible() void OnToolbarPropertyChanged(object sender, PropertyChangedEventArgs e) { - UpdateTitle(); + if (e.PropertyName == Shell.TitleViewProperty.PropertyName) + { + UpdateTitleView(); + } + else if (e.PropertyName == Page.TitleProperty.PropertyName) + { + UpdateTitle(); + } } protected virtual void UpdateTitle() @@ -168,7 +175,7 @@ protected virtual void OnPageSet(Page oldPage, Page newPage) { oldPage.Appearing -= PageAppearing; oldPage.PropertyChanged -= OnPagePropertyChanged; - newPage.Loaded -= OnPageLoaded; + oldPage.Loaded -= OnPageLoaded; ((INotifyCollectionChanged)oldPage.ToolbarItems).CollectionChanged -= OnToolbarItemsChanged; } @@ -207,7 +214,13 @@ protected virtual void OnRendererSet() protected virtual void UpdateTitleView() { - var titleView = _context.Shell.GetEffectiveValue(Shell.TitleViewProperty, () => Shell.GetTitleView(_context.Shell), null, Page); + var titleView = _context.Shell.Toolbar.TitleView as View; + + if (NavigationItem.TitleView is TitleViewContainer tvc && + tvc.View == titleView) + { + return; + } if (titleView == null) { diff --git a/src/Controls/tests/DeviceTests/Elements/Editor/EditorTests.iOS.cs b/src/Controls/tests/DeviceTests/Elements/Editor/EditorTests.iOS.cs index 88233b8e021b..b5f8da788983 100644 --- a/src/Controls/tests/DeviceTests/Elements/Editor/EditorTests.iOS.cs +++ b/src/Controls/tests/DeviceTests/Elements/Editor/EditorTests.iOS.cs @@ -1,9 +1,11 @@ using System.Threading.Tasks; using Microsoft.Maui.Handlers; using Microsoft.Maui.Platform; +using Xunit; namespace Microsoft.Maui.DeviceTests { + [Collection(HandlerTestBase.RunInNewWindowCollection)] public partial class EditorTests { MauiTextView GetPlatformControl(EditorHandler handler) => diff --git a/src/Controls/tests/DeviceTests/Elements/FlyoutPage/FlyoutPageTests.iOS.cs b/src/Controls/tests/DeviceTests/Elements/FlyoutPage/FlyoutPageTests.iOS.cs new file mode 100644 index 000000000000..0be66c849e6d --- /dev/null +++ b/src/Controls/tests/DeviceTests/Elements/FlyoutPage/FlyoutPageTests.iOS.cs @@ -0,0 +1,9 @@ +using Xunit; + +namespace Microsoft.Maui.DeviceTests +{ + [Collection(HandlerTestBase.RunInNewWindowCollection)] + public partial class FlyoutPageTests + { + } +} \ No newline at end of file diff --git a/src/Controls/tests/DeviceTests/Elements/ListView/ListViewTests.cs b/src/Controls/tests/DeviceTests/Elements/ListView/ListViewTests.cs index 457b3cd13771..e687df8530d3 100644 --- a/src/Controls/tests/DeviceTests/Elements/ListView/ListViewTests.cs +++ b/src/Controls/tests/DeviceTests/Elements/ListView/ListViewTests.cs @@ -8,6 +8,7 @@ namespace Microsoft.Maui.DeviceTests { + [Collection(HandlerTestBase.RunInNewWindowCollection)] [Category(TestCategory.ListView)] public partial class ListViewTests : HandlerTestBase { diff --git a/src/Controls/tests/DeviceTests/Elements/Modal/ModalTests.cs b/src/Controls/tests/DeviceTests/Elements/Modal/ModalTests.cs index 6f6fd446866d..80ea2b5ed651 100644 --- a/src/Controls/tests/DeviceTests/Elements/Modal/ModalTests.cs +++ b/src/Controls/tests/DeviceTests/Elements/Modal/ModalTests.cs @@ -17,7 +17,7 @@ namespace Microsoft.Maui.DeviceTests { [Category(TestCategory.Modal)] -#if ANDROID +#if ANDROID || IOS [Collection(HandlerTestBase.RunInNewWindowCollection)] #endif public partial class ModalTests : HandlerTestBase diff --git a/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.iOS.cs b/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.iOS.cs new file mode 100644 index 000000000000..fbdcc2152bc2 --- /dev/null +++ b/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.iOS.cs @@ -0,0 +1,9 @@ +using Xunit; + +namespace Microsoft.Maui.DeviceTests +{ + [Collection(HandlerTestBase.RunInNewWindowCollection)] + public partial class NavigationPageTests : HandlerTestBase + { + } +} diff --git a/src/Controls/tests/DeviceTests/Elements/PlatformBehaviorTests.cs b/src/Controls/tests/DeviceTests/Elements/PlatformBehaviorTests.cs index 077bd0196714..037007b633e8 100644 --- a/src/Controls/tests/DeviceTests/Elements/PlatformBehaviorTests.cs +++ b/src/Controls/tests/DeviceTests/Elements/PlatformBehaviorTests.cs @@ -21,7 +21,7 @@ namespace Microsoft.Maui.DeviceTests { [Category(TestCategory.Behavior)] -#if ANDROID +#if ANDROID || IOS [Collection(HandlerTestBase.RunInNewWindowCollection)] #endif public partial class PlatformBehaviorTests : HandlerTestBase diff --git a/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs b/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs index 4a6ffaae42e8..5b78c71b941c 100644 --- a/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs +++ b/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs @@ -71,6 +71,7 @@ public async Task FlyoutContentRenderersWhenFlyoutBehaviorStartsAsLocked() }); } +#if !IOS [Fact(DisplayName = "Flyout Starts as Open correctly")] public async Task FlyoutIsPresented() { @@ -88,7 +89,7 @@ public async Task FlyoutIsPresented() await CheckFlyoutState(handler, false); }); } - +#endif [Fact(DisplayName = "Back Button Visibility Changes with push/pop")] public async Task BackButtonVisibilityChangesWithPushPop() @@ -114,12 +115,9 @@ public async Task SetHasBackButton() { SetupBuilder(); - var shell = await InvokeOnMainThreadAsync(() => + var shell = await CreateShellAsync(shell => { - return new Shell() - { - Items = { new ContentPage() } - }; + shell.CurrentItem = new ContentPage(); }); await CreateHandlerAndAddToWindow(shell, async (handler) => diff --git a/src/Controls/tests/DeviceTests/Elements/VisualElementTests.cs b/src/Controls/tests/DeviceTests/Elements/VisualElementTests.cs index e2f04d497ecf..f627967ed2fe 100644 --- a/src/Controls/tests/DeviceTests/Elements/VisualElementTests.cs +++ b/src/Controls/tests/DeviceTests/Elements/VisualElementTests.cs @@ -10,7 +10,7 @@ namespace Microsoft.Maui.DeviceTests { [Category(TestCategory.VisualElement)] -#if ANDROID +#if ANDROID || IOS [Collection(HandlerTestBase.RunInNewWindowCollection)] #endif public partial class VisualElementTests : HandlerTestBase diff --git a/src/Controls/tests/DeviceTests/HandlerTestBase.iOS.cs b/src/Controls/tests/DeviceTests/HandlerTestBase.iOS.cs index 41a6ccde525a..40ff106806f2 100644 --- a/src/Controls/tests/DeviceTests/HandlerTestBase.iOS.cs +++ b/src/Controls/tests/DeviceTests/HandlerTestBase.iOS.cs @@ -59,7 +59,14 @@ Task RunWindowTest(IWindow window, Func action) await controlsWindow.Navigation.PopModalAsync(); } - window.Handler.DisconnectHandler(); + if (window.Handler is WindowHandlerStub whs) + { + window.Handler.DisconnectHandler(); + await whs.FinishedDisconnecting; + } + else + window.Handler.DisconnectHandler(); + } } }); @@ -72,6 +79,28 @@ internal ModalWrapper GetModalWrapper(Page modalPage) } protected bool IsBackButtonVisible(IElementHandler handler) + { + var vcs = GetActiveChildViewControllers(handler); + + if (vcs.Length <= 1) + return false; + + return !vcs[vcs.Length - 1].NavigationItem.HidesBackButton; + } + + protected object GetTitleView(IElementHandler handler) + { + var activeVC = GetVisibleViewController(handler); + if ( activeVC.NavigationItem.TitleView is + ShellPageRendererTracker.TitleViewContainer tvc) + { + return tvc.View.Handler.PlatformView; + } + + return null; + } + + UIViewController[] GetActiveChildViewControllers(IElementHandler handler) { if (handler is ShellRenderer renderer) { @@ -79,14 +108,7 @@ protected bool IsBackButtonVisible(IElementHandler handler) { if (sir.ChildViewControllers[0] is ShellSectionRenderer ssr) { - // Nothing has been pushed to the stack - if (ssr.ChildViewControllers.Length == 1) - return false; - - var activeVC = - ssr.ChildViewControllers[ssr.ChildViewControllers.Length - 1]; - - return !activeVC.NavigationItem.HidesBackButton; + return ssr.ChildViewControllers; } } } @@ -94,9 +116,10 @@ protected bool IsBackButtonVisible(IElementHandler handler) throw new NotImplementedException(); } - protected object GetTitleView(IElementHandler handler) + UIViewController GetVisibleViewController(IElementHandler handler) { - throw new NotImplementedException(); + var vcs = GetActiveChildViewControllers(handler); + return vcs[vcs.Length - 1]; } } } diff --git a/src/Controls/tests/DeviceTests/Stubs/WindowHandlerStub.iOS.cs b/src/Controls/tests/DeviceTests/Stubs/WindowHandlerStub.iOS.cs index 24733e90025e..f0d363214b87 100644 --- a/src/Controls/tests/DeviceTests/Stubs/WindowHandlerStub.iOS.cs +++ b/src/Controls/tests/DeviceTests/Stubs/WindowHandlerStub.iOS.cs @@ -1,5 +1,7 @@ using System; +using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Maui.Controls; using Microsoft.Maui.Handlers; using Microsoft.Maui.Platform; using UIKit; @@ -8,6 +10,9 @@ namespace Microsoft.Maui.DeviceTests { public class WindowHandlerStub : ElementHandler, IWindowHandler { + TaskCompletionSource _finishedDisconnecting = new TaskCompletionSource(); + public Task FinishedDisconnecting => _finishedDisconnecting.Task; + public static IPropertyMapper WindowMapper = new PropertyMapper(WindowHandler.Mapper) { [nameof(IWindow.Content)] = MapContent @@ -16,15 +21,45 @@ public class WindowHandlerStub : ElementHandler, IWindowHandl private static void MapContent(WindowHandlerStub handler, IWindow window) { var view = window.Content.ToPlatform(handler.MauiContext); - handler.PlatformView.RootViewController.View.AddSubview(view); + + if (window.Content is Shell) + { + var vc = + (window.Content.Handler as IPlatformViewHandler) + .ViewController; + + handler.PlatformView.RootViewController.PresentViewController(vc, false, null); + } + else + { + handler.PlatformView.RootViewController.View.AddSubview(view); + } } protected override void DisconnectHandler(UIWindow platformView) { - VirtualView - .Content - .ToPlatform() - .RemoveFromSuperview(); + var vc = (VirtualView.Content.Handler as IPlatformViewHandler) + .ViewController; + + if (VirtualView.Content is Shell) + { + platformView.RootViewController + .PresentedViewController. + DismissViewController(false, + () => + { + _finishedDisconnecting.SetResult(true); + }); + } + else + { + VirtualView + .Content + .ToPlatform() + .RemoveFromSuperview(); + + _finishedDisconnecting.SetResult(true); + } base.DisconnectHandler(platformView); }