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

Fixes for Android Back #3085

Merged
merged 2 commits into from
Feb 24, 2024
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
21 changes: 19 additions & 2 deletions src/Maui/Prism.Maui/Dialogs/DialogService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Prism.Commands;
using Prism.Commands;
using Prism.Common;
using Prism.Ioc;
using Prism.Navigation;
Expand Down Expand Up @@ -29,6 +29,7 @@
/// <inheritdoc/>
public void ShowDialog(string name, IDialogParameters parameters, DialogCallback callback)
{
IDialogContainer? dialogModal = null;

Check warning on line 32 in src/Maui/Prism.Maui/Dialogs/DialogService.cs

View workflow job for this annotation

GitHub Actions / build-prism-maui / Build Prism.Maui

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
try
{
parameters = UriParsingHelper.GetSegmentParameters(name, parameters ?? new DialogParameters());
Expand All @@ -39,16 +40,19 @@
var view = registry.CreateView(_container, UriParsingHelper.GetSegmentName(name)) as View;

var currentPage = _pageAccessor.Page;
var dialogModal = _container.Resolve<IDialogContainer>();
dialogModal = _container.Resolve<IDialogContainer>();
IDialogContainer.DialogStack.Add(dialogModal);
var dialogAware = GetDialogController(view);

async Task DialogAware_RequestClose(IDialogResult outResult)
{
bool didCloseDialog = true;
try
{
var result = await CloseDialogAsync(outResult ?? new DialogResult(), currentPage, dialogModal);
if (result.Exception is DialogException de && de.Message == DialogException.CanCloseIsFalse)
{
didCloseDialog = false;
return;
}

Expand All @@ -57,6 +61,12 @@
}
catch (DialogException dex)
{
if (dex.Message == DialogException.CanCloseIsFalse)
{
didCloseDialog = false;
return;
}

var result = new DialogResult
{
Exception = dex,
Expand All @@ -73,6 +83,13 @@
{
await InvokeError(callback, ex, parameters);
}
finally
{
if (didCloseDialog && dialogModal is not null)
{
IDialogContainer.DialogStack.Remove(dialogModal);
}
}
}

DialogUtilities.InitializeListener(dialogAware, DialogAware_RequestClose);
Expand Down
37 changes: 36 additions & 1 deletion src/Maui/Prism.Maui/Dialogs/IDialogContainer.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,46 @@
using System.Windows.Input;
using System.Windows.Input;

#nullable enable
namespace Prism.Dialogs;

/// <summary>
/// Interface representing a container for managing dialogs.
/// </summary>
public interface IDialogContainer
{
/// <summary>
/// Gets a stack of currently active dialog containers.
/// </summary>
/// <remarks>
/// This property provides access to the list of dialogs currently displayed, typically in the order they were presented.
/// </remarks>
static IList<IDialogContainer> DialogStack { get; } = [];

/// <summary>
/// Gets the view associated with the currently displayed dialog.
/// </summary>
View DialogView { get; }

/// <summary>
/// Gets a command that can be used to dismiss the currently displayed dialog.
/// </summary>
ICommand Dismiss { get; }

/// <summary>
/// Configures the layout and behavior of the dialog.
/// </summary>
/// <param name="currentPage">The page on which the dialog is being displayed.</param>
/// <param name="dialogView">The view representing the dialog content.</param>
/// <param name="hideOnBackgroundTapped">True if the dialog should close when the background is tapped, false otherwise.</param>
/// <param name="dismissCommand">The command to execute when the dialog is dismissed.</param>
/// <param name="parameters">Optional parameters to pass to the dialog.</param>
/// <returns>A task representing the completion of the configuration process.</returns>
Task ConfigureLayout(Page currentPage, View dialogView, bool hideOnBackgroundTapped, ICommand dismissCommand, IDialogParameters parameters);

/// <summary>
/// Performs the internal logic to display or dismiss the dialog.
/// </summary>
/// <param name="currentPage">The page on which the dialog is being displayed.</param>
/// <returns>A task representing the completion of the pop operation.</returns>
Task DoPop(Page currentPage);
}
4 changes: 2 additions & 2 deletions src/Maui/Prism.Maui/Dialogs/RelativeContentSizeConverter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Globalization;
using System.Globalization;

namespace Prism.Dialogs;

Expand All @@ -12,7 +12,7 @@ public double RelativeSize
{
if (value == 0)
{
relativeSize = 1;
relativeSize = -1;
}
else if (value > 1)
{
Expand Down
15 changes: 12 additions & 3 deletions src/Maui/Prism.Maui/Navigation/PrismWindow.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.ComponentModel;
using System.ComponentModel;
using Prism.AppModel;
using Prism.Common;
using Prism.Dialogs;
Expand Down Expand Up @@ -79,8 +79,17 @@ private async void PrismWindow_ModalPopping(object sender, ModalPoppingEventArgs
if (PageNavigationService.NavigationSource == PageNavigationSource.Device)
{
e.Cancel = true;
var navService = Xaml.Navigation.GetNavigationService(e.Modal);
await navService.GoBackAsync();
var dialogModal = IDialogContainer.DialogStack.LastOrDefault();
if (dialogModal is not null)
{
if (dialogModal.Dismiss.CanExecute(null))
dialogModal.Dismiss.Execute(null);
}
else
{
var navService = Xaml.Navigation.GetNavigationService(e.Modal);
await navService.GoBackAsync();
}
}
}

Expand Down
22 changes: 17 additions & 5 deletions src/Maui/Prism.Maui/PrismAppBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ internal PrismAppBuilder(IContainerExtension containerExtension, MauiAppBuilder
return $"View is not a BindableObject: '{view.GetType().FullName}";
});

// Ensure that the DialogStack is cleared when the Application is started.
// This is primarily to help with Unit Tests
IDialogContainer.DialogStack.Clear();
MauiBuilder = builder;
MauiBuilder.ConfigureContainer(new PrismServiceProviderFactory(RegistrationCallback));
MauiBuilder.ConfigureLifecycleEvents(lifecycle =>
Expand All @@ -55,19 +58,28 @@ internal PrismAppBuilder(IContainerExtension containerExtension, MauiAppBuilder
{
android.OnBackPressed(activity =>
{
var dialogModal = IDialogContainer.DialogStack.LastOrDefault();
if (dialogModal is not null)
{
if (dialogModal.Dismiss.CanExecute(null))
dialogModal.Dismiss.Execute(null);

return true;
}

var root = ContainerLocator.Container;
if (root is null)
return false;

var app = root.Resolve<IApplication>();
var windows = app.Windows.OfType<PrismWindow>();
if (!windows.Any(x => x.IsActive))
var window = app.Windows.OfType<PrismWindow>()
.FirstOrDefault(x => x.IsActive);

if (window is null)
return false;

var window = windows.First(x => x.IsActive);
if(window.IsRootPage && app is Application application)
if(window.IsRootPage)
{
application.Quit();
return false;
}

Expand Down
Loading