-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TIMOB-5994 - Facebook #722
Changes from 6 commits
7a9748c
1170111
b81ab59
fbdd6de
c1cdd80
59e8079
3b64152
ec249d7
f91735c
443c61e
c4bc042
516b395
f72b309
b0b7236
1d7348c
2a510f8
c6374ed
bdd9c1c
b34efd2
f587c7d
57356e3
0f715e6
fbe3379
2d3cce4
a28bc55
4fcd118
c5ca33e
6c194a0
41ec287
ecd76a9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,13 +21,12 @@ | |
set: function(val){return _expirationDate = val;} | ||
}); | ||
|
||
var _forceDialogAuth = null; | ||
Object.defineProperty(api, 'forceDialogAuth', { | ||
get: function(){return _forceDialogAuth;}, | ||
set: function(val){return _forceDialogAuth = val;} | ||
get: function(){return true;}, | ||
set: function(val){return true;} | ||
}); | ||
|
||
var _loggedIn = null; | ||
var _loggedIn = false; | ||
Object.defineProperty(api, 'loggedIn', { | ||
get: function(){return _loggedIn;}, | ||
set: function(val){return _loggedIn = val;} | ||
|
@@ -45,31 +44,138 @@ | |
set: function(val){return _uid = val;} | ||
}); | ||
|
||
// Setup the Facebook initialization callback | ||
var _facebookInitialized = false; | ||
var _authAfterInitialized = false; | ||
window.fbAsyncInit = function() { | ||
FB.init({ | ||
appId : _appid, // App ID | ||
status : true, // check login status | ||
cookie : true, // enable cookies to allow the server to access the session | ||
oauth : true, // enable OAuth 2.0 | ||
xfbml : true // parse XFBML | ||
}); | ||
_facebookInitialized = true; | ||
if (_authAfterInitialized) { | ||
api.authorize(); | ||
} | ||
}; | ||
|
||
// Create the div required by Facebook | ||
fbDiv = document.createElement('div'); | ||
fbDiv.id = 'fb-root'; | ||
document.getElementsByTagName('body')[0].appendChild(fbDiv); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should be able to reliably do document.body.appendChild(fbDiv); |
||
|
||
// Load the Facebook SDK Asynchronously. | ||
var fbScriptTag, id = 'facebook-jssdk'; | ||
if (!document.getElementById(id)) { | ||
fbScriptTag = document.createElement('script'); | ||
fbScriptTag.id = id; | ||
fbScriptTag.async = true; | ||
fbScriptTag.src = "//connect.facebook.net/en_US/all.js"; | ||
document.getElementsByTagName('head')[0].appendChild(fbScriptTag); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this Facebooks recommended way? The best way to ensure async script loading in all browsers is to do something like:
This is the recommend way that Google Analytics does it. It's the way Steve Souders recommends. It's the way Dojo does it. It's the way my require() loader does it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, so my loader is super rad. I almost forgot that it could do this. You can use require to asynchronously load scripts regardless of domain.
Note, I'm using the async version by wrapping the URL in an array. Now you can rip out that huge chunk of code. If you require() the script twice, it does nothing. Pretty cool huh? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I'll get it implemented. The current code was copied from the Facebook JS SDK example. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You probably don't need to pass in a callback to require() since FB uses window.fbAsyncInit to notify when things are loaded. |
||
} | ||
|
||
// Methods | ||
api.authorize = function(){ | ||
console.debug('Method "Titanium.Facebook.authorize" is not implemented yet.'); | ||
|
||
// Sanity check | ||
if (_appid == null) { | ||
console.debug('App ID not set. Facebook authorization cancelled.'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems like this should be logged as an error and probably an exception thrown since it's a programmer error, not a runtime error. |
||
return; | ||
} | ||
|
||
// Check if facebook is still initializing, and if so queue the auth request | ||
if (!_facebookInitialized) { | ||
_authAfterInitialized = true; | ||
return; | ||
} | ||
|
||
// Authorize | ||
FB.login(function(response) { | ||
var undef; | ||
var oEvent = { | ||
cancelled : false, | ||
data : response, | ||
error : undef, | ||
source : undef, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't source have a value? What is the source on Android and iOS? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, source should not have a value. I based this code on the Android code in fact because I wasn't sure at first either. Facebook is a non-instantiatable class (think static class in Java), so there is no source to set. |
||
success : false, | ||
type : undef, | ||
uid : response.id | ||
}; | ||
if (response.authResponse) { | ||
_expirationDate = new Date((new Date()).getTime() + response.authResponse.expiresIn * 1000); | ||
FB.api('/me', function(response) { | ||
if (!response) { | ||
oEvent.error = "An unknown error occured."; | ||
} else if (response.error) { | ||
oEvent.error = response.error; | ||
} else { | ||
_loggedIn = true; | ||
_uid = response.id; | ||
oEvent.success = true; | ||
oEvent.uid = _uid; | ||
} | ||
api.fireEvent('login', oEvent); | ||
}); | ||
} else { | ||
oEvent.cancelled = true | ||
oEvent.error = "The user cancelled or an internal error occured." | ||
api.fireEvent('login', oEvent); | ||
} | ||
}, {'scope':_permissions.join()}); | ||
}; | ||
api.createLoginButton = function(){ | ||
api.createLoginButton = function(parameters){ | ||
console.debug('Method "Titanium.Facebook.createLoginButton" is not implemented yet.'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warn level and/or exception (fail fast) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can do that, but it's important to note that this is the current convention in mobile web for unimplemented methods. There are hundreds of these things scattered throughout the codebase. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. kk. we should fix them as we find them. Doesn't have to be a mass effort. |
||
}; | ||
api.dialog = function(){ | ||
console.debug('Method "Titanium.Facebook.dialog" is not implemented yet.'); | ||
api.dialog = function(action,params,callback){ | ||
params.method = action; | ||
FB.ui(params,function(response){ | ||
if (!response) { | ||
var undef; | ||
callback({'success':false,'error':undef,'path':path}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IIRC we set source and type on all event objects sent back as a titanium standard. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Related to the above mention about source, there is no source to set. Also, the API docs don't mention a source object anywhere (is this a problem with the docs?) |
||
} else if (response.error) { | ||
callback({'success':false,'error':response.error,'path':path}); | ||
} else { | ||
callback({'success':true,'result':response,'path':path}); | ||
} | ||
}); | ||
}; | ||
api.logout = function(){ | ||
console.debug('Method "Titanium.Facebook.logout" is not implemented yet.'); | ||
FB.logout(function(response) { | ||
_loggedIn = false; | ||
var undef; | ||
var oEvent = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. check parity w/ other platforms. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you give me some more feedback? Parity of what? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On events, which we talked about. So nothing to do now. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No sense creating the oEvent variable, I would prefer passing the object directly into fireEvent(). Saves 17 bytes and 1 less variable in the scope. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Easy enough, although it's worth noting that this code was copied from another class. These types of declarations are all over the codebase. |
||
source : undef, | ||
type : undef | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You do not need to pass in a type here and you can get rid of undef. fireEvent() will set the type for you. In this case it will automatically set type to "logout". Even if you set type to "hello", it gets clobbered. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So this is true of all events being passed through fireEvent then, correct? I think there are a few other areas where we can get rid of this. |
||
}; | ||
api.fireEvent('logout', oEvent); | ||
}); | ||
}; | ||
api.request = function(){ | ||
console.debug('Method "Titanium.Facebook.request" is not implemented yet.'); | ||
api.request = function(method,params,callback){ | ||
params.method = method; | ||
params.urls = 'facebook.com,developers.facebook.com'; | ||
FB.api(params,function(response){ | ||
if (!response) { | ||
var undef; | ||
callback({'success':false,'error':undef,'method':method}); | ||
} else if (response.error) { | ||
callback({'success':false,'error':response.error,'method':method}); | ||
} else { | ||
callback({'success':true,'result':JSON.stringify(response),'method':method}); | ||
} | ||
}); | ||
}; | ||
api.requestWithGraphPath = function(){ | ||
console.debug('Method "Titanium.Facebook.requestWithGraphPath" is not implemented yet.'); | ||
api.requestWithGraphPath = function(path,params,httpMethod,callback){ | ||
FB.api(path,httpMethod,params,function(response){ | ||
if (!response) { | ||
var undef; | ||
callback({'success':false,'error':undef,'path':path}); | ||
} else if (response.error) { | ||
callback({'success':false,'error':response.error,'path':path}); | ||
} else { | ||
callback({'success':true,'result':JSON.stringify(response),'path':path}); | ||
} | ||
}); | ||
}; | ||
|
||
// Events | ||
api.addEventListener('login', function(){ | ||
console.debug('Event "login" is not implemented yet.'); | ||
}); | ||
api.addEventListener('logout', function(){ | ||
console.debug('Event "logout" is not implemented yet.'); | ||
}); | ||
})(Ti._5.createClass('Titanium.Facebook')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to initialize this variable correctly. That's fine to default to false, but then later after Facebook's API is loaded, query it to see if you're logged in. If I log in, then reload, I can't query because it thinks I'm not logged in. However, I still have a valid session and I'm able to post status updates.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Read my new comment for line 76 below...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately it doesn't work that way. "Logged in" is something of a misnomer, and a bad choice of words IMO on the part of Appcelerator. It's not that the user is logged in, but rather that the application is authorized. This must be done every time because the application must have an access token to make queries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, but updating a status message does not require a token? We need things to work across reloads.