diff --git a/CommunityToolkit.Graph.Uwp/Controls/LoginButton/LoginButton.Properties.cs b/CommunityToolkit.Graph.Uwp/Controls/LoginButton/LoginButton.Properties.cs
index 82374bc..70b63c1 100644
--- a/CommunityToolkit.Graph.Uwp/Controls/LoginButton/LoginButton.Properties.cs
+++ b/CommunityToolkit.Graph.Uwp/Controls/LoginButton/LoginButton.Properties.cs
@@ -18,7 +18,7 @@ public partial class LoginButton
public User UserDetails
{
get { return (User)GetValue(UserDetailsProperty); }
- set { SetValue(UserDetailsProperty, value); }
+ protected set { SetValue(UserDetailsProperty, value); }
}
///
diff --git a/CommunityToolkit.Graph.Uwp/Controls/LoginButton/LoginButton.cs b/CommunityToolkit.Graph.Uwp/Controls/LoginButton/LoginButton.cs
index b69b3d6..991d6fa 100644
--- a/CommunityToolkit.Graph.Uwp/Controls/LoginButton/LoginButton.cs
+++ b/CommunityToolkit.Graph.Uwp/Controls/LoginButton/LoginButton.cs
@@ -17,14 +17,14 @@ namespace CommunityToolkit.Graph.Uwp.Controls
/// The control is a button which can be used to sign the user in or show them profile details.
///
[TemplatePart(Name = LoginButtonPart, Type = typeof(Button))]
- [TemplatePart(Name = SignOutButtonPart, Type = typeof(ButtonBase))]
+ [TemplatePart(Name = LogoutButtonPart, Type = typeof(ButtonBase))]
public partial class LoginButton : Control
{
private const string LoginButtonPart = "PART_LoginButton";
- private const string SignOutButtonPart = "PART_SignOutButton";
+ private const string LogoutButtonPart = "PART_LogoutButton";
private Button _loginButton;
- private ButtonBase _signOutButton;
+ private ButtonBase _logoutButton;
private bool _isLoading;
@@ -48,17 +48,87 @@ public LoginButton()
{
this.DefaultStyleKey = typeof(LoginButton);
- ProviderManager.Instance.ProviderStateChanged += (sender, args) => LoadData();
+ ProviderManager.Instance.ProviderUpdated += OnProviderUpdated;
+ ProviderManager.Instance.ProviderStateChanged += OnProviderStateChanged;
}
///
- /// Update the enablement state of the button in relation to the _isLoading property.
+ /// Initiates logging in with the current registered in the .
///
- protected void UpdateButtonEnablement()
+ /// A representing the asynchronous operation.
+ public async Task SignInAsync()
{
- if (_loginButton != null)
+ if (IsLoading)
{
- _loginButton.IsEnabled = !_isLoading;
+ return;
+ }
+
+ var provider = ProviderManager.Instance.GlobalProvider;
+ if (provider != null)
+ {
+ try
+ {
+ IsLoading = true;
+
+ var cargs = new CancelEventArgs();
+ LoginInitiated?.Invoke(this, cargs);
+ if (cargs.Cancel)
+ {
+ throw new OperationCanceledException();
+ }
+
+ await provider.SignInAsync();
+
+ if (provider.State != ProviderState.SignedIn)
+ {
+ throw new Exception("Login did not complete.");
+ }
+ }
+ catch (Exception e)
+ {
+ IsLoading = false;
+ LoginFailed?.Invoke(this, new LoginFailedEventArgs(e));
+ }
+ }
+ }
+
+ ///
+ /// Log a signed-in user out.
+ ///
+ /// A representing the asynchronous operation.
+ public async Task SignOutAsync()
+ {
+ if (IsLoading)
+ {
+ return;
+ }
+
+ IsLoading = true;
+
+ var cargs = new CancelEventArgs();
+ LogoutInitiated?.Invoke(this, cargs);
+ if (cargs.Cancel)
+ {
+ return;
+ }
+
+ var provider = ProviderManager.Instance.GlobalProvider;
+ if (provider != null)
+ {
+ try
+ {
+ await provider.SignOutAsync();
+
+ if (provider.State != ProviderState.SignedOut)
+ {
+ throw new Exception("Logout did not complete.");
+ }
+ }
+ finally
+ {
+ // There is no LogoutFailed event, so we do nothing.
+ IsLoading = false;
+ }
}
}
@@ -79,171 +149,155 @@ protected override void OnApplyTemplate()
_loginButton.Click += LoginButton_Click;
}
- if (_signOutButton != null)
+ if (_logoutButton != null)
{
- _signOutButton.Click -= LoginButton_Click;
+ _logoutButton.Click -= LogoutButton_Click;
}
- _signOutButton = GetTemplateChild(SignOutButtonPart) as ButtonBase;
+ _logoutButton = GetTemplateChild(LogoutButtonPart) as ButtonBase;
- if (_signOutButton != null)
+ if (_logoutButton != null)
{
- _signOutButton.Click += SignOutButton_Click;
+ _logoutButton.Click += LogoutButton_Click;
}
LoadData();
}
- private async void LoginButton_Click(object sender, RoutedEventArgs e)
+ ///
+ /// Show the user details flyout.
+ ///
+ protected void ShowFlyout()
{
- if (this.UserDetails != null)
+ if (FlyoutBase.GetAttachedFlyout(_loginButton) is FlyoutBase flyout)
{
- if (FlyoutBase.GetAttachedFlyout(_loginButton) is FlyoutBase flyout)
- {
- flyout.ShowAt(_loginButton);
- }
+ flyout.ShowAt(_loginButton);
}
- else
+ }
+
+ ///
+ /// Hide the user details flyout.
+ ///
+ protected void HideFlyout()
+ {
+ if (FlyoutBase.GetAttachedFlyout(_loginButton) is FlyoutBase flyout)
{
- var cargs = new CancelEventArgs();
- LoginInitiated?.Invoke(this, cargs);
+ flyout.Hide();
+ }
+ }
- if (!cargs.Cancel)
- {
- await SignInAsync();
- }
+ ///
+ /// Update the enablement state of the button in relation to the _isLoading property.
+ ///
+ protected void UpdateButtonEnablement()
+ {
+ if (_loginButton != null)
+ {
+ _loginButton.IsEnabled = !_isLoading;
}
}
- private async void SignOutButton_Click(object sender, RoutedEventArgs e)
+ private void OnProviderUpdated(object sender, IProvider e)
{
- await SignOutAsync();
+ if (e == null)
+ {
+ ClearUserDetails();
+ }
}
- private async void LoadData()
+ private async void OnProviderStateChanged(object sender, ProviderStateChangedEventArgs e)
{
var provider = ProviderManager.Instance.GlobalProvider;
- switch (provider?.State)
+ switch (provider.State)
{
- case ProviderState.Loading:
+ case ProviderState.SignedIn:
IsLoading = true;
+ await SetUserDetails();
+ IsLoading = false;
+ LoginCompleted?.Invoke(this, new EventArgs());
break;
- case ProviderState.SignedIn:
- try
- {
- IsLoading = true;
+ case ProviderState.SignedOut:
+ ClearUserDetails();
+ IsLoading = false;
+ LogoutCompleted?.Invoke(this, new EventArgs());
+ break;
- // https://github.com/microsoftgraph/microsoft-graph-toolkit/blob/master/src/components/mgt-login/mgt-login.ts#L139
- // TODO: Batch with photo request later? https://github.com/microsoftgraph/msgraph-sdk-dotnet-core/issues/29
- UserDetails = await provider.GetClient().GetMeAsync();
- }
- catch (Exception e)
- {
- LoginFailed?.Invoke(this, new LoginFailedEventArgs(e));
- }
- finally
- {
- IsLoading = false;
- }
+ case ProviderState.Loading:
+ IsLoading = true;
+ break;
+ }
+ }
+ private async void LoginButton_Click(object sender, RoutedEventArgs e)
+ {
+ var provider = ProviderManager.Instance.GlobalProvider;
+ switch (provider.State)
+ {
+ case ProviderState.SignedIn:
+ ShowFlyout();
break;
case ProviderState.SignedOut:
- default:
- UserDetails = null; // What if this was user provided? Should we not hook into these events then?
- IsLoading = false;
+ await SignInAsync();
break;
}
}
- ///
- /// Initiates logging in with the current registered in the .
- ///
- /// A representing the asynchronous operation.
- public async Task SignInAsync()
+ private async void LogoutButton_Click(object sender, RoutedEventArgs e)
+ {
+ HideFlyout();
+ await SignOutAsync();
+ }
+
+ private async void LoadData()
{
- if (UserDetails != null || IsLoading)
+ if (IsLoading)
{
return;
}
var provider = ProviderManager.Instance.GlobalProvider;
-
- if (provider != null)
+ switch (provider?.State)
{
- try
- {
+ case ProviderState.Loading:
IsLoading = true;
- await provider.SignInAsync();
+ break;
- if (provider.State == ProviderState.SignedIn)
+ case ProviderState.SignedIn:
+ if (UserDetails == null)
{
- // TODO: include user details?
- LoginCompleted?.Invoke(this, new EventArgs());
-
- LoadData();
+ await SignInAsync();
}
- else
+
+ IsLoading = false;
+ break;
+
+ case ProviderState.SignedOut:
+ if (UserDetails != null)
{
- LoginFailed?.Invoke(this, new LoginFailedEventArgs(new TimeoutException("Login did not complete.")));
+ await SignOutAsync();
}
- }
- catch (Exception e)
- {
- LoginFailed?.Invoke(this, new LoginFailedEventArgs(e));
- }
- finally
- {
+
IsLoading = false;
- }
+ break;
}
}
- ///
- /// Log a signed-in user out.
- ///
- /// A representing the asynchronous operation.
- public async Task SignOutAsync()
+ private async Task SetUserDetails()
{
- // Close Menu
- if (FlyoutBase.GetAttachedFlyout(_loginButton) is FlyoutBase flyout)
- {
- flyout.Hide();
- }
-
- if (IsLoading)
- {
- return;
- }
-
- var cargs = new CancelEventArgs();
- LogoutInitiated?.Invoke(this, cargs);
-
- if (cargs.Cancel)
- {
- return;
- }
-
- if (UserDetails != null)
- {
- UserDetails = null;
- }
- else
- {
- return; // No-op
- }
-
var provider = ProviderManager.Instance.GlobalProvider;
-
if (provider != null)
{
- IsLoading = true;
- await provider.SignOutAsync();
- IsLoading = false;
-
- LogoutCompleted?.Invoke(this, new EventArgs());
+ // https://github.com/microsoftgraph/microsoft-graph-toolkit/blob/master/src/components/mgt-login/mgt-login.ts#L139
+ // TODO: Batch with photo request later? https://github.com/microsoftgraph/msgraph-sdk-dotnet-core/issues/29
+ UserDetails = await provider.GetClient().GetMeAsync();
}
}
+
+ private void ClearUserDetails()
+ {
+ UserDetails = null;
+ }
}
}
diff --git a/CommunityToolkit.Graph.Uwp/Controls/LoginButton/LoginButton.xaml b/CommunityToolkit.Graph.Uwp/Controls/LoginButton/LoginButton.xaml
index acbae71..eb5e6fb 100644
--- a/CommunityToolkit.Graph.Uwp/Controls/LoginButton/LoginButton.xaml
+++ b/CommunityToolkit.Graph.Uwp/Controls/LoginButton/LoginButton.xaml
@@ -45,7 +45,7 @@
-
+