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

Add shell pages via controller instead of handler #13332

Merged
merged 5 commits into from
Feb 17, 2023
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
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);
PureWeen marked this conversation as resolved.
Show resolved Hide resolved
_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
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>();
});
}
}
}