Skip to content

Commit

Permalink
feat(styles): [Android] [iOS] Allow MessageDialog.ShowAsync() from ba…
Browse files Browse the repository at this point in the history
…ckground

UWP allows this method to be called from a background thread. This fixes the existing MessageDialog.xaml sample.
  • Loading branch information
davidjohnoliver committed Jun 3, 2020
1 parent c25177d commit 43a2189
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 43 deletions.
28 changes: 11 additions & 17 deletions src/Uno.UWP/UI/Popups/MessageDialog.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,16 @@
using Android.Widget;
using Windows.UI.Core;
using Windows.Foundation;
using System.Threading;

namespace Windows.UI.Popups
{
public partial class MessageDialog
{
const int MaximumCommands = 3;

public IAsyncOperation<IUICommand> ShowAsync()
private void ShowInner(CancellationToken ct, TaskCompletionSource<IUICommand> invokedCommand)
{
var invokedCommand = new TaskCompletionSource<IUICommand>();

// Android recommends placing buttons in this order:
// 1) positive (default accept)
// 2) negative (default cancel)
Expand All @@ -35,7 +34,7 @@ public IAsyncOperation<IUICommand> ShowAsync()
.Where(command => !(command is UICommandSeparator)) // Not supported on Android
.DefaultIfEmpty(new UICommand("Close")) // TODO: Localize (PBI 28711)
.Reverse()
.Select((command, index) =>
.Select((command, index) =>
new
{
Command = command,
Expand All @@ -62,20 +61,15 @@ public IAsyncOperation<IUICommand> ShowAsync()
}
);

return new AsyncOperation<IUICommand>(async ct =>
using (ct.Register(() =>
{
using (ct.Register(() =>
{
// If the cancellation token itself gets cancelled, we cancel as well.
invokedCommand.TrySetCanceled();
dialog.Dismiss();
}))
{
dialog.Show();
return await invokedCommand.Task;
}
});
// If the cancellation token itself gets cancelled, we cancel as well.
invokedCommand.TrySetCanceled();
dialog.Dismiss();
}))
{
dialog.Show();
}
}

partial void ValidateCommands()
Expand Down
51 changes: 50 additions & 1 deletion src/Uno.UWP/UI/Popups/MessageDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI.Core;

namespace Windows.UI.Popups
{
Expand All @@ -14,7 +16,7 @@ public sealed partial class MessageDialog
/// Creates a new instance of the MessageDialog class, using the specified message content and no title.
/// </summary>
/// <param name="content"></param>
public MessageDialog(string content)
public MessageDialog(string content)
: this(content, "")
{
}
Expand Down Expand Up @@ -46,6 +48,53 @@ public MessageDialog(string content, string title)
Commands = collection;
}

#if __ANDROID__ || __IOS__

public IAsyncOperation<IUICommand> ShowAsync()
{
var invokedCommand = new TaskCompletionSource<IUICommand>();

return new AsyncOperation<IUICommand>(async ct =>
{
if (CoreDispatcher.Main.HasThreadAccess)
{
try
{
ShowInner(ct, invokedCommand);
}
catch (Exception e)
{
invokedCommand.TrySetException(e);
}
}
else
{
Exception ex = null;
await CoreDispatcher.Main.RunAsync(CoreDispatcherPriority.Normal, CallShow);
if (ex != null)
{
invokedCommand.TrySetException(ex);
}
void CallShow()
{
try
{
ShowInner(ct, invokedCommand);
}
catch (Exception e)
{
ex = e;
}
}
}
return await invokedCommand.Task;
});
}
#endif

public uint CancelCommandIndex { get; set; } = uint.MaxValue;
public IList<IUICommand> Commands { get; }
public string Content { get; set; }
Expand Down
43 changes: 18 additions & 25 deletions src/Uno.UWP/UI/Popups/MessageDialog.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@ public partial class MessageDialog
{
private static readonly SemaphoreSlim _viewControllerAccess = new SemaphoreSlim(1, 1);

public IAsyncOperation<IUICommand> ShowAsync()
private async void ShowInner(CancellationToken ct, TaskCompletionSource<IUICommand> invokedCommand)
{
var invokedCommand = new TaskCompletionSource<IUICommand>();

var alertActions = Commands
.Where(command => !(command is UICommandSeparator)) // Not supported on iOS
.DefaultIfEmpty(new UICommand("OK")) // TODO: Localize (PBI 28711)
Expand Down Expand Up @@ -51,36 +49,31 @@ public IAsyncOperation<IUICommand> ShowAsync()
alertController.PreferredAction = alertActions.ElementAtOrDefault((int)DefaultCommandIndex);
}

return new AsyncOperation<IUICommand>(async ct =>
{
using (ct.Register(() =>
{
// If the cancellation token itself gets cancelled, we cancel as well.
invokedCommand.TrySetCanceled();
UIApplication.SharedApplication.KeyWindow?.RootViewController?.DismissViewController(false, () => { });
}))
using (ct.Register(() =>
{
await _viewControllerAccess.WaitAsync(ct);
// If the cancellation token itself gets cancelled, we cancel as well.
invokedCommand.TrySetCanceled();
UIApplication.SharedApplication.KeyWindow?.RootViewController?.DismissViewController(false, () => { });
}))
{
await _viewControllerAccess.WaitAsync(ct);

try
{
try
{
try
{
await UIApplication.SharedApplication.KeyWindow?.RootViewController?.PresentViewControllerAsync(alertController, animated: true);
}
catch (Exception error)
{
invokedCommand.TrySetException(error);
}
return await invokedCommand.Task;
await UIApplication.SharedApplication.KeyWindow?.RootViewController?.PresentViewControllerAsync(alertController, animated: true);
}
finally
catch (Exception error)
{
_viewControllerAccess.Release();
invokedCommand.TrySetException(error);
}
}
});
finally
{
_viewControllerAccess.Release();
}
}
}

partial void ValidateCommands()
Expand Down

0 comments on commit 43a2189

Please sign in to comment.