Skip to content

Commit c23c3e0

Browse files
Wrapped UI dependant calls in WindowsProvider with dispatchers (#136)
1 parent 3a3bb1f commit c23c3e0

File tree

1 file changed

+76
-50
lines changed

1 file changed

+76
-50
lines changed

CommunityToolkit.Authentication.Uwp/WindowsProvider.cs

Lines changed: 76 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using Windows.Security.Authentication.Web.Core;
1313
using Windows.Security.Credentials;
1414
using Windows.Storage;
15+
using Windows.System;
1516
using Windows.UI.ApplicationSettings;
1617

1718
namespace CommunityToolkit.Authentication
@@ -197,7 +198,21 @@ public override async Task<string> GetTokenAsync(bool silentOnly = false)
197198
}
198199

199200
// Attempt to authenticate interactively.
200-
authResult = await AuthenticateInteractiveAsync(_scopes);
201+
var tcs = new TaskCompletionSource<WebTokenRequestResult>();
202+
var taskQueued = DispatcherQueue.GetForCurrentThread().TryEnqueue(async () =>
203+
{
204+
var result = await AuthenticateInteractiveAsync(_scopes);
205+
tcs.SetResult(result);
206+
});
207+
208+
if (taskQueued)
209+
{
210+
authResult = await tcs.Task;
211+
}
212+
else
213+
{
214+
tcs.SetCanceled();
215+
}
201216
}
202217

203218
if (authResult?.ResponseStatus == WebTokenRequestStatus.Success)
@@ -241,74 +256,85 @@ public async Task ShowAccountManagementPaneAsync()
241256
throw new InvalidOperationException("A logged in account is required to display the account management pane.");
242257
}
243258

244-
// Build the AccountSettingsPane and configure it with available account commands.
245-
void OnAccountCommandsRequested(AccountsSettingsPane sender, AccountsSettingsPaneCommandsRequestedEventArgs e)
259+
var tcs = new TaskCompletionSource<bool>();
260+
_ = DispatcherQueue.GetForCurrentThread().TryEnqueue(async () =>
246261
{
247-
AccountsSettingsPaneEventDeferral deferral = e.GetDeferral();
248-
249-
// Apply the configured header.
250-
var headerText = _accountsSettingsPaneConfig?.ManageAccountHeaderText;
251-
if (!string.IsNullOrWhiteSpace(headerText))
252-
{
253-
e.HeaderText = headerText;
254-
}
255-
256-
// Generate any account commands.
257-
if (_accountsSettingsPaneConfig?.AccountCommandParameter != null)
262+
AccountsSettingsPane pane = null;
263+
try
258264
{
259-
var commandParameter = _accountsSettingsPaneConfig.Value.AccountCommandParameter;
260-
var webAccountCommand = new WebAccountCommand(
261-
_webAccount,
262-
async (command, args) =>
263-
{
264-
// When the logout command is triggered, we also need to modify the state of the Provider.
265-
if (args.Action == WebAccountAction.Remove)
266-
{
267-
await SignOutAsync();
268-
}
265+
// GetForCurrentView may throw an exception if the current view isn't ready yet.
266+
pane = AccountsSettingsPane.GetForCurrentView();
267+
pane.AccountCommandsRequested += OnAccountCommandsRequested;
269268

270-
commandParameter.Invoked?.Invoke(command, args);
271-
},
272-
commandParameter.Actions);
269+
// Show the AccountSettingsPane and wait for the result.
270+
await AccountsSettingsPane.ShowManageAccountsAsync();
273271

274-
e.WebAccountCommands.Add(webAccountCommand);
272+
tcs.SetResult(true);
275273
}
276-
277-
// Apply any configured setting commands.
278-
var commands = _accountsSettingsPaneConfig?.Commands;
279-
if (commands != null)
274+
catch (Exception e)
275+
{
276+
tcs.SetException(e);
277+
}
278+
finally
280279
{
281-
foreach (var command in commands)
280+
if (pane != null)
282281
{
283-
e.Commands.Add(command);
282+
pane.AccountCommandsRequested -= OnAccountCommandsRequested;
284283
}
285284
}
285+
});
286286

287-
deferral.Complete();
288-
}
287+
await tcs.Task;
288+
}
289289

290-
AccountsSettingsPane pane = null;
291-
try
292-
{
293-
// GetForCurrentView may throw an exception if the current view isn't ready yet.
294-
pane = AccountsSettingsPane.GetForCurrentView();
295-
pane.AccountCommandsRequested += OnAccountCommandsRequested;
290+
/// <summary>
291+
/// Build the AccountSettingsPane and configure it with available account commands.
292+
/// </summary>
293+
/// <param name="sender">The pane that fired the event.</param>
294+
/// <param name="e">Arguments for the AccountCommandsRequested event.</param>
295+
private void OnAccountCommandsRequested(AccountsSettingsPane sender, AccountsSettingsPaneCommandsRequestedEventArgs e)
296+
{
297+
AccountsSettingsPaneEventDeferral deferral = e.GetDeferral();
296298

297-
// Show the AccountSettingsPane and wait for the result.
298-
await AccountsSettingsPane.ShowManageAccountsAsync();
299+
// Apply the configured header.
300+
var headerText = _accountsSettingsPaneConfig?.ManageAccountHeaderText;
301+
if (!string.IsNullOrWhiteSpace(headerText))
302+
{
303+
e.HeaderText = headerText;
299304
}
300-
catch (Exception e)
305+
306+
// Generate any account commands.
307+
if (_accountsSettingsPaneConfig?.AccountCommandParameter != null)
301308
{
302-
// TODO: Log exception
303-
System.Diagnostics.Debug.WriteLine(e.Message);
309+
var commandParameter = _accountsSettingsPaneConfig.Value.AccountCommandParameter;
310+
var webAccountCommand = new WebAccountCommand(
311+
_webAccount,
312+
async (command, args) =>
313+
{
314+
// When the logout command is triggered, we also need to modify the state of the Provider.
315+
if (args.Action == WebAccountAction.Remove)
316+
{
317+
await SignOutAsync();
318+
}
319+
320+
commandParameter.Invoked?.Invoke(command, args);
321+
},
322+
commandParameter.Actions);
323+
324+
e.WebAccountCommands.Add(webAccountCommand);
304325
}
305-
finally
326+
327+
// Apply any configured setting commands.
328+
var commands = _accountsSettingsPaneConfig?.Commands;
329+
if (commands != null)
306330
{
307-
if (pane != null)
331+
foreach (var command in commands)
308332
{
309-
pane.AccountCommandsRequested -= OnAccountCommandsRequested;
333+
e.Commands.Add(command);
310334
}
311335
}
336+
337+
deferral.Complete();
312338
}
313339

314340
private async Task SetAccountAsync(WebAccount account)

0 commit comments

Comments
 (0)