Created
December 21, 2011 19:13
-
-
Save tim-evans/1507264 to your computer and use it in GitHub Desktop.
SC.MultiplexedDataSource
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
XMPP = {}; | |
// ............................................... | |
// Models | |
// | |
XMPP.BOSHConnection = SC.Record.extend({ | |
primaryKey: 'jid', | |
jid: SC.Record.attr(String), | |
password: SC.Record.attr(String), | |
connectionStatus: SC.Record.attr(Number) | |
}); | |
XMPP.ChatMessage = SC.Record.extend({ | |
to: SC.Record.attr(String), | |
from: SC.Record.attr(String), | |
body: SC.Record.attr(String) | |
}); | |
// ............................................... | |
// Data Sources | |
// | |
XMPP.DataSource = SC.MultiplexedDataSource.extend({ | |
bosh: null, | |
jid: function () { | |
return this.get('bosh').jid; | |
}.property('bosh').cacheable(), | |
init: function () { | |
this.set('bosh', new Strophe.Connection('/http-bind/')); | |
return sc_super(); | |
} | |
}); | |
XMPP.BOSHConnectionDataSource = SC.DataSource.extend(SC.DataSourceDelegate, { | |
isDelegateFor: 'XMPP.BOSHConnection', | |
createRecord: function (store, storeKey) { | |
var hash = store.readDataHash(storeKey), | |
self = this; | |
this.get('bosh').connect(hash.jid, hash.password, function () { | |
self.connectionStatusDidChange.apply(self, [store, storeKey].concat(SC.A(arguments))); | |
}); | |
this.get('dataSource').notifyPropertyChange('jid'); | |
return YES; | |
}, | |
destroyRecord: function (store, storeKey) { | |
var hash = store.readDataHash(storeKey); | |
this.get('bosh').disconnect(); | |
if (hash.connectionStatus === Strophe.Status.DISCONNECTED) { | |
store.dataSourceDidDestroy(storeKey); | |
} | |
return YES; | |
}, | |
connectionStatusDidChange: function (store, storeKey, statusCode, errorCondition) { | |
var hash = SC.clone(store.readDataHash(storeKey)), | |
status = store.peekStatus(storeKey), | |
K = SC.Record, | |
S = Strophe.Status; | |
if (hash) { | |
hash.connectionStatus = statusCode; | |
} | |
if (status !== K.ERROR && | |
(statusCode === S.CONNFAIL || | |
statusCode === S.AUTHFAIL || | |
statusCode === S.ERROR)) { | |
var e = SC.Error.create({ | |
label: "Connection error", | |
code: errorCondition, | |
message: "Strophe has encountered a connection level error", | |
errorValue: connection | |
}); | |
if (status & K.BUSY) { | |
store.dataSourceDidError(storeKey, e); | |
} else { | |
store.pushError(XMPP.BOSHConnection, null, e, storeKey); | |
} | |
} else if (status === K.BUSY_CREATING && | |
statusCode === S.CONNECTED) { | |
store.dataSourceDidComplete(storeKey, hash); | |
} else if (statusCode === S.DISCONNECTED) { | |
if (status === K.BUSY_DESTROYING) { | |
store.dataSourceDidDestroy(storeKey); | |
} else { | |
if (status === K.BUSY_CREATING) { | |
store.writeStatus(storeKey, K.READY_CLEAN); | |
} | |
store.pushDestroy(XMPP.BOSHConnection, null, storeKey); | |
} | |
} | |
} | |
}); | |
XMPP.DataSource.plugin(XMPP.BOSHConnectionDataSource); | |
XMPP.ChatMessageDataSource = SC.DataSource.extend(SC.DataSourceDelegate, { | |
isDelegateFor: 'XMPP.ChatMessage', | |
init: function () { | |
var self = this; | |
this.get('bosh').addHandler(function () { | |
self.didRecieveChat.apply(self, arguments); | |
}, null, 'message', 'chat', null, null, null); | |
}, | |
createRecord: function (store, storeKey) { | |
var hash = store.readDataHash(storeKey); | |
this.get('bosh').send( | |
$msg({ | |
to: hash.to, | |
from: this.get('jid'), | |
type: 'chat' | |
}).c('body', hash.body) | |
.tree()); | |
return YES; | |
}, | |
didRecieveChat: function (stanza) { | |
var store = this.get('store'), | |
body = stanza.getElementsByTagName('body'); | |
store.pushRetrieve(XMPP.ChatMessage, { | |
guid: SC.guidFor(stanza), | |
to: stanza.getAttribute('to'), | |
from: stanza.getAttribute('from'), | |
body: body && body.length && Strophe.getText(body[0]) | |
}); | |
} | |
}); | |
XMPP.DataSource.plugin(XMPP.ChatMessageDataSource); | |
// ............................................... | |
// Use it! | |
XMPP.store = SC.Store.create(); | |
XMPP.store.set('dataSource', XMPP.DataSource.create({ store: XMPP.store })); | |
// replace with your own JID & password | |
var bosh = XMPP.store.createRecord(XMPP.BOSHConnection, { | |
jid: 'swedish.chef@muppe.tz', | |
password: 'bork!' | |
}).commitRecord(); | |
bosh.addObserver('status', function () { | |
if (bosh.get('status') === SC.Record.READY_CLEAN) { | |
// replace with another JID (ie. a gmail account!) | |
XMPP.store.createRecord(XMPP.ChatMessage, { | |
to: 'camilla@muppe.tz', | |
body: 'Bork bork bork!' | |
}).commitRecord(); | |
} | |
}); |
I've done some basic testing with this to ensure that this is a working example of a partially implemented data source rather than something contrived. Note that this requires Strophe.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is an example showing off a viable use case for sproutcore/sproutcore#664