Skip to content

Instantly share code, notes, and snippets.

@tim-evans
Created December 21, 2011 19:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tim-evans/1507264 to your computer and use it in GitHub Desktop.
Save tim-evans/1507264 to your computer and use it in GitHub Desktop.
SC.MultiplexedDataSource
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();
}
});
@tim-evans
Copy link
Author

This is an example showing off a viable use case for sproutcore/sproutcore#664

@tim-evans
Copy link
Author

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