Skip to content

Commit

Permalink
Merge pull request PrismLibrary#3085 from PrismLibrary/dev/ds/android…
Browse files Browse the repository at this point in the history
…-back

Fixes for Android Back
  • Loading branch information
dansiegel authored Feb 24, 2024
2 parents f43e579 + 27f9103 commit 2338a75
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 13 deletions.
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 @@ public DialogService(IContainerProvider container, IPageAccessor pageAccessor)
/// <inheritdoc/>
public void ShowDialog(string name, IDialogParameters parameters, DialogCallback callback)
{
IDialogContainer? dialogModal = null;
try
{
parameters = UriParsingHelper.GetSegmentParameters(name, parameters ?? new DialogParameters());
Expand All @@ -39,16 +40,19 @@ public void ShowDialog(string name, IDialogParameters parameters, DialogCallback
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 @@ async Task DialogAware_RequestClose(IDialogResult outResult)
}
catch (DialogException dex)
{
if (dex.Message == DialogException.CanCloseIsFalse)
{
didCloseDialog = false;
return;
}

var result = new DialogResult
{
Exception = dex,
Expand All @@ -73,6 +83,13 @@ async Task DialogAware_RequestClose(IDialogResult outResult)
{
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

0 comments on commit 2338a75

Please sign in to comment.