Skip to content

Commit

Permalink
Wait for root page to load before processing modal (#15037)
Browse files Browse the repository at this point in the history
* Wait for root page to load before processing modal

* Update ModalTests.iOS.cs
  • Loading branch information
PureWeen authored May 18, 2023
1 parent edbc7c5 commit 210786b
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ void ClearModalPages(bool xplat = false, bool platform = false)

// Windows and Android have basically the same requirement that
// we need to wait for the current page to finish loading before
// satsifying Modal requests.
// satisfying Modal requests.
// This will most likely change once we switch Android to using dialog fragments
#if WINDOWS || ANDROID
IDisposable? _platformPageWatchingForLoaded;
Expand All @@ -338,22 +338,33 @@ async Task SyncModalStackWhenPlatformIsReadyAsync()
await SyncPlatformModalStackAsync().ConfigureAwait(false);
}
else if (_window.IsActivated &&
_window?.Page?.Handler is not null)
_window?.Page?.Handler is not null)
{
if (CurrentPlatformPage.Handler is null)
{
CurrentPlatformPage.HandlerChanged += OnCurrentPlatformPageHandlerChanged;
;

_platformPageWatchingForLoaded = new ActionDisposable(() =>
{
CurrentPlatformPage.HandlerChanged -= OnCurrentPlatformPageHandlerChanged;
});
}
// This accounts for cases where we swap the root page out
// We want to wait for that to finish loading before processing any modal changes
#if ANDROID
else if (!_window.Page.IsLoadedOnPlatform())
{
var windowPage = _window.Page;
_platformPageWatchingForLoaded =
windowPage.OnLoaded(() => OnCurrentPlatformPageLoaded(windowPage, EventArgs.Empty));
}
#endif
else if (!CurrentPlatformPage.IsLoadedOnPlatform() &&
CurrentPlatformPage.Handler is not null)
CurrentPlatformPage.Handler is not null)
{
var currentPlatformPage = CurrentPlatformPage;
_platformPageWatchingForLoaded =
CurrentPlatformPage.OnLoaded(() => OnCurrentPlatformPageLoaded(_platformPageWatchingForLoaded, EventArgs.Empty));
currentPlatformPage.OnLoaded(() => OnCurrentPlatformPageLoaded(currentPlatformPage, EventArgs.Empty));
}
}
}
Expand Down Expand Up @@ -382,6 +393,7 @@ bool IsModalPlatformReady
bool result =
_window?.Page?.Handler is not null &&
_window.IsActivated
&& _window.Page.IsLoadedOnPlatform()
&& CurrentPlatformPage?.Handler is not null
&& CurrentPlatformPage.IsLoadedOnPlatform();

Expand Down
33 changes: 29 additions & 4 deletions src/Controls/tests/DeviceTests/Elements/Modal/ModalTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Threading.Tasks;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Handlers;
using Microsoft.Maui.Controls.Platform;
using Microsoft.Maui.DeviceTests.Stubs;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Hosting;
Expand Down Expand Up @@ -447,6 +448,23 @@ await CreateHandlerAndAddToWindow<IWindowHandler>(window, async (handler) =>

}

[Theory]
[ClassData(typeof(PageTypes))]
public async Task SwappingRootPageWhileModalPageIsOpenDoesntCrash(Page rootPage, Page newRootPage)
{
SetupBuilder();

await CreateHandlerAndAddToWindow<IWindowHandler>(rootPage,
async (_) =>
{
var modalPage = new NavigationPage(new ContentPage());
await rootPage.Navigation.PushModalAsync(modalPage);
await OnLoadedAsync(modalPage);
rootPage.Window.Page = newRootPage;
await OnLoadedAsync(newRootPage);
});
}

[Theory]
[ClassData(typeof(PageTypes))]
public async Task BasicPushAndPop(Page rootPage, Page modalPage)
Expand All @@ -456,7 +474,8 @@ public async Task BasicPushAndPop(Page rootPage, Page modalPage)
await CreateHandlerAndAddToWindow<IWindowHandler>(rootPage,
async (_) =>
{
var currentPage = (rootPage as IPageContainer<Page>).CurrentPage;
var currentPage = rootPage.GetCurrentPage();
await currentPage.Navigation.PushModalAsync(modalPage);
await OnLoadedAsync(modalPage);
Assert.Equal(1, currentPage.Navigation.ModalStack.Count);
Expand All @@ -465,21 +484,27 @@ await CreateHandlerAndAddToWindow<IWindowHandler>(rootPage,
});


Assert.Equal(0, (rootPage as IPageContainer<Page>).CurrentPage.Navigation.ModalStack.Count);
Assert.Equal(0, rootPage.GetCurrentPage().Navigation.ModalStack.Count);
}

class PageTypes : IEnumerable<object[]>
{
public IEnumerator<object[]> GetEnumerator()
{
for (int i = 0; i < 2; i++)
for (int i = 0; i < 3; i++)
{
Func<Page> rootPage;

if (i == 0)
rootPage = () => new NavigationPage(new ContentPage());
else
else if (i == 1)
rootPage = () => new Shell() { CurrentItem = new ContentPage() };
else
rootPage = () => new FlyoutPage()
{
Flyout = new ContentPage() { Title = "Flyout" },
Detail = new NavigationPage(new ContentPage()) { Title = "Detail" },
};

yield return new object[] {
rootPage(), new NavigationPage(new ContentPage())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Threading.Tasks;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Platform;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
using UIKit;
Expand All @@ -23,7 +24,7 @@ public async Task PushModalUsingTransparencies(Page rootPage, Page modalPage)
await CreateHandlerAndAddToWindow<IWindowHandler>(rootPage,
async (handler) =>
{
var currentPage = (rootPage as IPageContainer<Page>).CurrentPage;
var currentPage = rootPage.GetCurrentPage();
await currentPage.Navigation.PushModalAsync(modalPage);
await OnLoadedAsync(modalPage);
Assert.Equal(1, currentPage.Navigation.ModalStack.Count);
Expand All @@ -37,4 +38,4 @@ await CreateHandlerAndAddToWindow<IWindowHandler>(rootPage,
});
}
}
}
}

0 comments on commit 210786b

Please sign in to comment.