Skip to content

Commit

Permalink
Add shell pages via controller instead of handler (#13332)
Browse files Browse the repository at this point in the history
* Add shell pages via controller instead of handler

* Auto-format source code

* - cleanup

* - add wait

* - push test into modal to isolate better

---------

Co-authored-by: GitHub Actions Autoformatter <autoformat@example.com>
  • Loading branch information
PureWeen and GitHub Actions Autoformatter authored Feb 17, 2023
1 parent 05417d2 commit 0c6a2aa
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ protected virtual void LoadRenderers()

if (item == currentItem)
{
_containerArea.AddSubview(renderer.PlatformView);
_containerArea.AddSubview(renderer.ViewController.View);
_currentContent = currentItem;
_currentIndex = i;
}
Expand Down
65 changes: 31 additions & 34 deletions src/Controls/tests/DeviceTests/ControlsHandlerTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,26 +41,8 @@ protected override MauiAppBuilder ConfigureBuilder(MauiAppBuilder mauiAppBuilder
return mauiAppBuilder.ConfigureTestBuilder();
}

protected void SetupShellHandlers(IMauiHandlersCollection handlers)
{
handlers.TryAddHandler(typeof(Controls.Shell), typeof(ShellHandler));
handlers.TryAddHandler<Layout, LayoutHandler>();
handlers.TryAddHandler<Image, ImageHandler>();
handlers.TryAddHandler<Label, LabelHandler>();
handlers.TryAddHandler<Page, PageHandler>();
handlers.TryAddHandler(typeof(Toolbar), typeof(ToolbarHandler));
handlers.TryAddHandler(typeof(MenuBar), typeof(MenuBarHandler));
handlers.TryAddHandler(typeof(MenuBarItem), typeof(MenuBarItemHandler));
handlers.TryAddHandler(typeof(MenuFlyoutItem), typeof(MenuFlyoutItemHandler));
handlers.TryAddHandler(typeof(MenuFlyoutSubItem), typeof(MenuFlyoutSubItemHandler));
handlers.TryAddHandler<ScrollView, ScrollViewHandler>();

#if WINDOWS
handlers.TryAddHandler(typeof(ShellItem), typeof(ShellItemHandler));
handlers.TryAddHandler(typeof(ShellSection), typeof(ShellSectionHandler));
handlers.TryAddHandler(typeof(ShellContent), typeof(ShellContentHandler));
#endif
}
protected void SetupShellHandlers(IMauiHandlersCollection handlers) =>
handlers.SetupShellHandlers();

protected THandler CreateHandler<THandler>(IElement view)
where THandler : IElementHandler, new()
Expand Down Expand Up @@ -99,6 +81,29 @@ protected Task<TValue> GetValueAsync<TValue>(IElement view, Func<IPlatformViewHa
});
}

IWindow CreateWindowForContent(IElement view)
{
IWindow window;

if (view is IWindow w)
window = w;
else if (view is Page page)
window = new Controls.Window(page);
else
window = new Controls.Window(new ContentPage() { Content = (View)view });

return window;
}

protected Task CreateHandlerAndAddToWindow(IElement view, Action action)
{
return CreateHandlerAndAddToWindow<IWindowHandler>(CreateWindowForContent(view), handler =>
{
action();
return Task.CompletedTask;
});
}

protected Task CreateHandlerAndAddToWindow<THandler>(IElement view, Action<THandler> action)
where THandler : class, IElementHandler
{
Expand All @@ -117,23 +122,10 @@ protected Task CreateHandlerAndAddToWindow<THandler>(IElement view, Func<THandle

return InvokeOnMainThreadAsync(async () =>
{
IWindow window = null;
IWindow window = CreateWindowForContent(view);
var application = mauiContext.Services.GetService<IApplication>();
if (view is IWindow w)
{
window = w;
}
else if (view is Page page)
{
window = new Controls.Window(page);
}
else
{
window = new Controls.Window(new ContentPage() { Content = (View)view });
}
if (application is ApplicationStub appStub)
{
appStub.SetWindow((Window)window);
Expand All @@ -150,6 +142,9 @@ await SetupWindowForTests<THandler>(window, async () =>
{
IView content = window.Content;
if (content is FlyoutPage fp)
content = fp.Detail;
if (content is IPageContainer<Page> pc)
{
content = pc.CurrentPage;
Expand Down Expand Up @@ -180,6 +175,8 @@ await SetupWindowForTests<THandler>(window, async () =>
await action((THandler)window.Content.Handler);
else if (window.Content is ContentPage cp && typeof(THandler).IsAssignableFrom(cp.Content.Handler.GetType()))
await action((THandler)cp.Content.Handler);
else if (typeof(THandler).IsAssignableFrom(typeof(WindowHandler)))
throw new Exception($"Use IWindowHandler instead of WindowHandler for CreateHandlerAndAddToWindow");
else
throw new Exception($"I can't work with {typeof(THandler)}");
Expand Down
58 changes: 57 additions & 1 deletion src/Controls/tests/DeviceTests/Elements/Entry/EntryTests.iOS.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
using System.Threading.Tasks;
using Microsoft.Maui.Controls;
using Microsoft.Maui.DeviceTests.TestCases;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Hosting;
using Microsoft.Maui.Platform;
using UIKit;
using Xunit;

namespace Microsoft.Maui.DeviceTests
{
Expand Down Expand Up @@ -36,5 +41,56 @@ int GetPlatformSelectionLength(EntryHandler entryHandler)

return -1;
}

[Category(TestCategory.Entry)]
[Collection(ControlsHandlerTestBase.RunInNewWindowCollection)]
public partial class EntryTestsWithWindow : ControlsHandlerTestBase
{
[Theory]
[ClassData(typeof(ControlsPageTypesTestCases))]
public async Task NextMovesToNextEntry(string page)
{
EnsureHandlerCreated(builder =>
{
ControlsPageTypesTestCases.Setup(builder);
builder.ConfigureMauiHandlers(handlers =>
{
handlers.AddHandler(typeof(Entry), typeof(EntryHandler));
});
});

var entry1 = new Entry
{
Text = "Entry 1",
ReturnType = ReturnType.Next
};

var entry2 = new Entry
{
Text = "Entry 2",
ReturnType = ReturnType.Next
};

ContentPage contentPage = new ContentPage()
{
Content = new VerticalStackLayout()
{
entry1,
entry2
}
};

Page rootPage = ControlsPageTypesTestCases.CreatePageType(page, contentPage);
Page hostPage = new ContentPage();

await CreateHandlerAndAddToWindow(hostPage, async () =>
{
await hostPage.Navigation.PushModalAsync(rootPage);
KeyboardAutoManager.GoToNextResponderOrResign(entry1.ToPlatform());
await AssertionExtensions.Wait(() => entry2.IsFocused);
Assert.True(entry2.IsFocused);
});
}
}
}
}
}
38 changes: 38 additions & 0 deletions src/Controls/tests/DeviceTests/Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,51 @@
using System;
using System.Threading.Tasks;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Handlers;
using Microsoft.Maui.Controls.Hosting;
using Microsoft.Maui.Devices;
using Microsoft.Maui.DeviceTests.Stubs;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Hosting;
using Microsoft.Maui.Platform;
using Xunit;
#if ANDROID || IOS || MACCATALYST
using ShellHandler = Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer;
#endif

namespace Microsoft.Maui.DeviceTests
{
public static class Extensions
{
public static Task Wait(this Image image, int timeout = 1000) =>
AssertionExtensions.Wait(() => !image.IsLoading, timeout);

public static void SetupShellHandlers(this MauiAppBuilder builder)
{
builder.ConfigureMauiHandlers(SetupShellHandlers);
}

public static void SetupShellHandlers(this IMauiHandlersCollection handlers)
{
handlers.TryAddHandler(typeof(Controls.Shell), typeof(ShellHandler));
handlers.TryAddHandler<Layout, LayoutHandler>();
handlers.TryAddHandler<Image, ImageHandler>();
handlers.TryAddHandler<Label, LabelHandler>();
handlers.TryAddHandler<Page, PageHandler>();
handlers.TryAddHandler(typeof(Toolbar), typeof(ToolbarHandler));
handlers.TryAddHandler(typeof(MenuBar), typeof(MenuBarHandler));
handlers.TryAddHandler(typeof(MenuBarItem), typeof(MenuBarItemHandler));
handlers.TryAddHandler(typeof(MenuFlyoutItem), typeof(MenuFlyoutItemHandler));
handlers.TryAddHandler(typeof(MenuFlyoutSubItem), typeof(MenuFlyoutSubItemHandler));
handlers.TryAddHandler<ScrollView, ScrollViewHandler>();

#if WINDOWS
handlers.TryAddHandler(typeof(ShellItem), typeof(ShellItemHandler));
handlers.TryAddHandler(typeof(ShellSection), typeof(ShellSectionHandler));
handlers.TryAddHandler(typeof(ShellContent), typeof(ShellContentHandler));
#endif
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Handlers.Compatibility;
using Microsoft.Maui.DeviceTests.Stubs;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Hosting;

#if IOS || MACCATALYST
using FlyoutViewHandler = Microsoft.Maui.Controls.Handlers.Compatibility.PhoneFlyoutPageRenderer;
#endif

namespace Microsoft.Maui.DeviceTests.TestCases
{
public class ControlsPageTypesTestCases : IEnumerable<object[]>
{
private readonly List<object[]> _data = new()
{
new object[] { nameof(FlyoutPage) },
new object[] { nameof(TabbedPage) },
new object[] { nameof(ContentPage) },
new object[] { nameof(Shell) },
new object[] { nameof(NavigationPage) },
};

public IEnumerator<object[]> GetEnumerator() => _data.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();


public static Page CreatePageType(string name, Page content)
{
switch (name)
{
case nameof(FlyoutPage):
content.Title = content.Title ?? "Detail Title";
return new FlyoutPage() { Flyout = new ContentPage() { Title = "title" }, Detail = content };
case nameof(TabbedPage):
return new TabbedPage() { Children = { content } };
case nameof(ContentPage):
return content;
case nameof(Shell):
return new Shell() { CurrentItem = (ContentPage)content };
case nameof(NavigationPage):
return new NavigationPage(content);
}

throw new Exception($"{name} not found");
}

public static void Setup(MauiAppBuilder builder)
{
builder.ConfigureMauiHandlers(handlers =>
{
handlers.SetupShellHandlers();
handlers.AddHandler(typeof(Controls.Label), typeof(LabelHandler));
handlers.AddHandler(typeof(Controls.Toolbar), typeof(ToolbarHandler));
handlers.AddHandler(typeof(FlyoutPage), typeof(FlyoutViewHandler));
#if IOS || MACCATALYST
handlers.AddHandler(typeof(TabbedPage), typeof(TabbedRenderer));
handlers.AddHandler(typeof(NavigationPage), typeof(NavigationRenderer));
#else
handlers.AddHandler(typeof(TabbedPage), typeof(TabbedViewHandler));
handlers.AddHandler(typeof(NavigationPage), typeof(NavigationViewHandler));
#endif
handlers.AddHandler<Page, PageHandler>();
handlers.AddHandler<Controls.Window, WindowHandlerStub>();
});
}
}
}

0 comments on commit 0c6a2aa

Please sign in to comment.