Skip to content

Instantly share code, notes, and snippets.

@eksahin
Forked from luca-barbieri/Facebook.cs
Created July 13, 2017 11:39
Show Gist options
  • Save eksahin/1b09843fd434bdf0792e51b5e87fea1f to your computer and use it in GitHub Desktop.
Save eksahin/1b09843fd434bdf0792e51b5e87fea1f to your computer and use it in GitHub Desktop.
Facebook Login button for Xamarin Forms
// This code has been placed in the public domain.
// NO WARRANTY OF ANY KIND
// WORK IN PROGRESS AND ONLY LIMITED TESTING, MIGHT BE PARTIALLY BROKEN
// Note that you need to setup both your iOS and Android projects to include your app id and so on for this to actually work (see the Facebook docs for each platform)
// Common
public class FacebookLoginEventArgs : EventArgs
{
public string AccessToken {get; set;}
}
public class FacebookLoginButton : View
{
public static readonly BindableProperty ReadPermissionsProperty = BindableProperty.Create<FacebookLoginButton, string[]>(p => p.ReadPermissions, null);
public string[] ReadPermissions {get {return (string[])GetValue(ReadPermissionsProperty); } set {SetValue(ReadPermissionsProperty, value);}}
public static readonly BindableProperty PublishPermissionsProperty = BindableProperty.Create<FacebookLoginButton, string[]>(p => p.PublishPermissions, null);
public string[] PublishPermissions {get {return (string[])GetValue(PublishPermissionsProperty); } set {SetValue(PublishPermissionsProperty, value);}}
public static readonly BindableProperty LoggedInProperty = BindableProperty.Create<FacebookLoginButton, bool>(p => p.LoggedIn, false, BindingMode.OneWayToSource);
public bool LoggedIn {get {return (bool)GetValue(LoggedInProperty); } internal set { SetValue (LoggedInProperty, value); }}
public event EventHandler<FacebookLoginEventArgs> ShowingLoggedInUser;
public event EventHandler ShowingLoggedOutUser;
internal void SendShowingLoggedInUser(string accessToken) {
LoggedIn = true;
var eh = ShowingLoggedInUser;
if (eh != null)
eh (this, new FacebookLoginEventArgs {AccessToken = accessToken});
}
internal void SendShowingLoggedOutUser() {
LoggedIn = false;
var eh = ShowingLoggedOutUser;
if (eh != null)
eh (this, EventArgs.Empty);
}
public void Login()
{
MessagingCenter.Send(this, "Login");
}
public void Logout()
{
MessagingCenter.Send(this, "Logout");
}
}
// iOS
class FacebookLoginButtonRenderer : ViewRenderer<FacebookLoginButton, FBLoginView>
{
protected override void OnElementChanged (ElementChangedEventArgs<FacebookLoginButton> e)
{
base.OnElementChanged (e);
var element = Element;
var session = FBSession.ActiveSession;
element.LoggedIn = session != null && session.IsOpen;
var control = new FBLoginView (element.ReadPermissions);
SetNativeControl(control);
control.ShowingLoggedInUser += (s, ea) => {
var session2 = FBSession.ActiveSession;
var accessToken = (session2 != null && session2.IsOpen) ? session2.AccessTokenData.AccessToken : null;
element.SendShowingLoggedInUser (accessToken);
};
control.ShowingLoggedOutUser += (s, ea) => {element.SendShowingLoggedOutUser ();};
if (element.PublishPermissions != null)
control.PublishPermissions = element.PublishPermissions;
if (element.ReadPermissions != null)
control.ReadPermissions = element.ReadPermissions;
MessagingCenter.Subscribe(this, "Login", (s) => {
Login();
}, element);
MessagingCenter.Subscribe(this, "Logout", (s) => {
Logout();
}, element);
}
void Login()
{
var session = FBSession.ActiveSession;
if (session != null && session.IsOpen)
return;
var button = Control.Subviews.Select (x => x as UIButton).FirstOrDefault (x => x != null);
if (button == null)
throw new Exception ("cannot find FB login button");
button.SendActionForControlEvents (UIControlEvent.TouchUpInside);
}
void Logout()
{
var session = FBSession.ActiveSession;
if (session == null)
return;
session.CloseAndClearTokenInformation ();
}
protected override void OnElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged (sender, e);
if(e.PropertyName == FacebookLoginButton.ReadPermissionsProperty.PropertyName)
Control.ReadPermissions = Element.ReadPermissions;
else if(e.PropertyName == FacebookLoginButton.PublishPermissionsProperty.PropertyName)
Control.PublishPermissions = Element.PublishPermissions;
}
}
// Android
public class SessionStatusCallback : Java.Lang.Object, Session.IStatusCallback
{
Action<Session, SessionState, Java.Lang.Exception> _call;
public void Call (Session p0, SessionState p1, Java.Lang.Exception p2)
{
_call (p0, p1, p2);
}
public SessionStatusCallback (Action<Session, SessionState, Java.Lang.Exception> call)
{
_call = call;
}
}
public class FacebookLoginButtonRenderer : ViewRenderer<FacebookLoginButton, LoginButton>
{
protected override void OnElementChanged (ElementChangedEventArgs<FacebookLoginButton> ec)
{
base.OnElementChanged (ec);
var element = ec.NewElement;
{
var session = Session.ActiveSession;
element.LoggedIn = session != null && session.IsOpened;
}
var control = new LoginButton (base.Context);
control.SessionStatusCallback = new SessionStatusCallback((session, state, error) => {
if(session != null && session.IsOpened)
element.SendShowingLoggedInUser (session.AccessToken);
else
element.SendShowingLoggedOutUser();
});
if(element.ReadPermissions != null)
control.SetReadPermissions (element.ReadPermissions);
if(element.PublishPermissions != null)
control.SetPublishPermissions (element.PublishPermissions);
MessagingCenter.Subscribe(this, "Login", (s) => {
Login();
}, element);
MessagingCenter.Subscribe(this, "Logout", (s) => {
Logout();
}, element);
bool sentInitialEvent = false;
control.ViewAttachedToWindow += (s, e) => {
if (!sentInitialEvent && Element != null) {
sentInitialEvent = true;
var session = Session.ActiveSession;
if (session != null && session.IsOpened)
Element.SendShowingLoggedInUser (session.AccessToken);
else
Element.SendShowingLoggedOutUser ();
}
};
var oldControl = Control;
SetNativeControl (control);
if(oldControl != null)
oldControl.Dispose(); // collect Java Objects on Android
}
void Login()
{
var session = Session.ActiveSession;
if (session != null && session.IsOpened)
return;
// TODO: not sure if this works, might need to call it on a button subview
Control.PerformClick ();
}
void Logout()
{
var session = Session.ActiveSession;
if (session == null)
return;
session.CloseAndClearTokenInformation ();
}
protected override void OnElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged (sender, e);
if(e.PropertyName == FacebookLoginButton.ReadPermissionsProperty.PropertyName)
Control.SetReadPermissions(Element.ReadPermissions);
else if(e.PropertyName == FacebookLoginButton.PublishPermissionsProperty.PropertyName)
Control.SetPublishPermissions(Element.PublishPermissions);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment