Commit c5192f8a authored by JC Brand's avatar JC Brand

Bugfix. Updates #32

Users without roster contacts didn't have XMPPStatus.initStatus called and
therefore had a default status of offline.

Fixed this by setting the status to online from the start. The fetch command
will get the true status from localStorage (if available).

Made sure that the rest of converse's onConnected code is called in the
callback from fetch (so that we know the user's status is correct).

Updated and fixed tests.
parent f0a2f259
...@@ -4,6 +4,7 @@ Changelog ...@@ -4,6 +4,7 @@ Changelog
0.5.1 (Unreleased) 0.5.1 (Unreleased)
------------------ ------------------
- #32: Default status was offline when user didn't have contacts. [jcbrand]
- Attach panels to the DOM upon initialize. [jcbrand] - Attach panels to the DOM upon initialize. [jcbrand]
0.5.0 (2013-07-30) 0.5.0 (2013-07-30)
......
...@@ -1046,21 +1046,6 @@ ...@@ -1046,21 +1046,6 @@
this.$el.html(this.template(this.model.toJSON())); this.$el.html(this.template(this.model.toJSON()));
this.contactspanel = new converse.ContactsPanel({'$parent': this.$el.find('#controlbox-panes')}); this.contactspanel = new converse.ContactsPanel({'$parent': this.$el.find('#controlbox-panes')});
this.contactspanel.render(); this.contactspanel.render();
converse.xmppstatus = new converse.XMPPStatus();
converse.xmppstatus.localStorage = new Backbone.LocalStorage(
hex_sha1('converse.xmppstatus-'+converse.bare_jid));
converse.xmppstatus.fetch({
success: function (xmppstatus, resp) {
if (!xmppstatus.get('fullname')) {
converse.getVCard(
null, // No 'to' attr when getting one's own vCard
function (jid, fullname, image, image_type, url) {
converse.xmppstatus.save({'fullname': fullname});
}
);
}
}
});
converse.xmppstatusview = new converse.XMPPStatusView({'model': converse.xmppstatus}); converse.xmppstatusview = new converse.XMPPStatusView({'model': converse.xmppstatus});
converse.xmppstatusview.render(); converse.xmppstatusview.render();
this.roomspanel = new converse.RoomsPanel({'$parent': this.$el.find('#controlbox-panes')}); this.roomspanel = new converse.RoomsPanel({'$parent': this.$el.find('#controlbox-panes')});
...@@ -2029,7 +2014,7 @@ ...@@ -2029,7 +2014,7 @@
item; item;
if (this.isSelf(bare_jid)) { if (this.isSelf(bare_jid)) {
if ((converse.connection.jid !== jid)&&(presence_type !== 'unavailabe')) { if ((converse.connection.jid !== jid)&&(presence_type !== 'unavailable')) {
// Another resource has changed it's status, we'll update ours as well. // Another resource has changed it's status, we'll update ours as well.
// FIXME: We should ideally differentiate between converse.js using // FIXME: We should ideally differentiate between converse.js using
// resources and other resources (i.e Pidgin etc.) // resources and other resources (i.e Pidgin etc.)
...@@ -2127,8 +2112,20 @@ ...@@ -2127,8 +2112,20 @@
this.model.on("destroy", function (item) { this.removeRosterItem(item); }, this); this.model.on("destroy", function (item) { this.removeRosterItem(item); }, this);
this.$el.hide().html(this.template()); this.$el.hide().html(this.template());
this.model.fetch({add: true}); // Get the cached roster items from localstorage this.model.fetch({
// XXX: is this necessary? this.initialSort(); add: true,
success: function (model, resp, options) {
if (resp.length === 0) {
// The presence stanza is sent out once all
// roster contacts have been added and rendered.
// See RosterView's render method.
//
// If there aren't any roster contacts, we still
// want to send a presence stanza, so we do it here.
converse.xmppstatus.sendPresence();
}
},
}); // Get the cached roster items from localstorage
}, },
updateChatBox: function (item, changed) { updateChatBox: function (item, changed) {
...@@ -2195,9 +2192,8 @@ ...@@ -2195,9 +2192,8 @@
// options where all of the items are offline and now we can show the rosterView // options where all of the items are offline and now we can show the rosterView
item.set('sorted', true); item.set('sorted', true);
this.initialSort(); this.initialSort();
this.$el.show(function () { this.$el.show();
converse.xmppstatus.initStatus(); converse.xmppstatus.sendPresence();
});
} }
} }
// Hide the headings if there are no contacts under them // Hide the headings if there are no contacts under them
...@@ -2228,22 +2224,24 @@ ...@@ -2228,22 +2224,24 @@
this.XMPPStatus = Backbone.Model.extend({ this.XMPPStatus = Backbone.Model.extend({
initialize: function () { initialize: function () {
this.set({ this.set({
'status' : this.get('status'), 'status' : this.get('status') || 'online',
'status_message' : this.get('status_message'),
'fullname' : this.get('fullname')
}); });
}, this.on('change', $.proxy(function () {
if (this.get('fullname') === undefined) {
initStatus: function () { converse.getVCard(
var stat = this.get('status'); null, // No 'to' attr when getting one's own vCard
if (stat === undefined) { $.proxy(function (jid, fullname, image, image_type, url) {
stat = 'online'; this.save({'fullname': fullname});
this.save({status: stat}); }, this)
);
} }
this.sendPresence(stat); }, this));
}, },
sendPresence: function (type) { sendPresence: function (type) {
if (type === undefined) {
type = this.get('status') || 'online';
}
var status_message = this.get('status_message'), var status_message = this.get('status_message'),
presence; presence;
// Most of these presence types are actually not explicitly sent, // Most of these presence types are actually not explicitly sent,
...@@ -2390,7 +2388,7 @@ ...@@ -2390,7 +2388,7 @@
this.$el.html(this.choose_template()); this.$el.html(this.choose_template());
this.$el.find('#fancy-xmpp-status-select') this.$el.find('#fancy-xmpp-status-select')
.html(this.status_template({ .html(this.status_template({
'status_message': __("I am %1$s", this.getPrettyStatus(chat_status)), 'status_message': this.model.get('status_message') || __("I am %1$s", this.getPrettyStatus(chat_status)),
'chat_status': chat_status 'chat_status': chat_status
})); }));
// iterate through all the <option> elements and add option values // iterate through all the <option> elements and add option values
...@@ -2595,14 +2593,15 @@ ...@@ -2595,14 +2593,15 @@
} }
}; };
this.onConnected = function (connection) { this.initStatus = function (callback) {
this.connection = connection; this.xmppstatus = new this.XMPPStatus();
this.connection.xmlInput = function (body) { console.log(body); }; var id = hex_sha1('converse.xmppstatus-'+this.bare_jid);
this.connection.xmlOutput = function (body) { console.log(body); }; this.xmppstatus.id = id; // This appears to be necessary for backbone.localStorage
this.bare_jid = Strophe.getBareJidFromJid(this.connection.jid); this.xmppstatus.localStorage = new Backbone.LocalStorage(id);
this.domain = Strophe.getDomainFromJid(this.connection.jid); this.xmppstatus.fetch({success: callback, error: callback});
this.features = new this.Features(); };
this.initRoster = function () {
// Set up the roster // Set up the roster
this.roster = new this.RosterItems(); this.roster = new this.RosterItems();
this.roster.localStorage = new Backbone.LocalStorage( this.roster.localStorage = new Backbone.LocalStorage(
...@@ -2611,9 +2610,18 @@ ...@@ -2611,9 +2610,18 @@
$.proxy(this.roster.rosterHandler, this.roster), $.proxy(this.roster.rosterHandler, this.roster),
null, 'presence', null); null, 'presence', null);
this.rosterview = new this.RosterView({'model':this.roster}); this.rosterview = new this.RosterView({'model':this.roster});
}
this.onConnected = function (connection, callback) {
this.connection = connection;
this.connection.xmlInput = function (body) { console.log(body); };
this.connection.xmlOutput = function (body) { console.log(body); };
this.bare_jid = Strophe.getBareJidFromJid(this.connection.jid);
this.domain = Strophe.getDomainFromJid(this.connection.jid);
this.features = new this.Features();
this.initStatus($.proxy(function () {
this.initRoster();
this.chatboxes.onConnected(); this.chatboxes.onConnected();
this.connection.addHandler( this.connection.addHandler(
$.proxy(this.roster.subscribeToSuggestedItems, this.roster), $.proxy(this.roster.subscribeToSuggestedItems, this.roster),
'http://jabber.org/protocol/rosterx', 'message', null); 'http://jabber.org/protocol/rosterx', 'message', null);
...@@ -2630,7 +2638,6 @@ ...@@ -2630,7 +2638,6 @@
return true; return true;
}, this), null, 'message', 'chat'); }, this), null, 'message', 'chat');
}, this)); }, this));
$(window).on("blur focus", $.proxy(function(e) { $(window).on("blur focus", $.proxy(function(e) {
if ((this.windowState != e.type) && (e.type == 'focus')) { if ((this.windowState != e.type) && (e.type == 'focus')) {
converse.clearMsgCounter(); converse.clearMsgCounter();
...@@ -2638,6 +2645,10 @@ ...@@ -2638,6 +2645,10 @@
this.windowState = e.type; this.windowState = e.type;
},this)); },this));
this.giveFeedback(__('Online Contacts')); this.giveFeedback(__('Online Contacts'));
if (callback) {
callback();
}
}, this));
}; };
// This is the end of the initialize method. // This is the end of the initialize method.
......
...@@ -56,6 +56,12 @@ ...@@ -56,6 +56,12 @@
it("can be opened by clicking a DOM element with class 'toggle-online-users'", open_controlbox); it("can be opened by clicking a DOM element with class 'toggle-online-users'", open_controlbox);
describe("The Status Widget", $.proxy(function () { describe("The Status Widget", $.proxy(function () {
it("shows the user's chat status, which is online by default", $.proxy(function () {
var view = this.xmppstatusview;
expect(view.$el.find('a.choose-xmpp-status').hasClass('online')).toBe(true);
expect(view.$el.find('a.choose-xmpp-status').attr('data-value')).toBe('I am online');
}, converse));
it("can be used to set the current user's chat status", $.proxy(function () { it("can be used to set the current user's chat status", $.proxy(function () {
var view = this.xmppstatusview; var view = this.xmppstatusview;
spyOn(view, 'toggleOptions').andCallThrough(); spyOn(view, 'toggleOptions').andCallThrough();
...@@ -64,25 +70,26 @@ ...@@ -64,25 +70,26 @@
runs(function () { runs(function () {
view.$el.find('a.choose-xmpp-status').click(); view.$el.find('a.choose-xmpp-status').click();
expect(view.toggleOptions).toHaveBeenCalled(); expect(view.toggleOptions).toHaveBeenCalled();
expect(view.$el.find('a.choose-xmpp-status').hasClass('online')).toBe(false);
}); });
waits(250); waits(250);
runs(function () { runs(function () {
spyOn(view, 'updateStatusUI').andCallThrough(); spyOn(view, 'updateStatusUI').andCallThrough();
view.initialize(); // Rebind events for spy view.initialize(); // Rebind events for spy
view.$el.find('.dropdown dd ul li a').first().click(); $(view.$el.find('.dropdown dd ul li a')[1]).click();
expect(view.setStatus).toHaveBeenCalled(); expect(view.setStatus).toHaveBeenCalled();
}); });
waits(250); waits(250);
runs($.proxy(function () { runs($.proxy(function () {
expect(view.updateStatusUI).toHaveBeenCalled(); expect(view.updateStatusUI).toHaveBeenCalled();
expect(view.$el.find('a.choose-xmpp-status').hasClass('online')).toBe(true); expect(view.$el.find('a.choose-xmpp-status').hasClass('online')).toBe(false);
expect(view.$el.find('a.choose-xmpp-status').attr('data-value')).toBe('I am online'); expect(view.$el.find('a.choose-xmpp-status').hasClass('dnd')).toBe(true);
expect(view.$el.find('a.choose-xmpp-status').attr('data-value')).toBe('I am busy');
}, converse)); }, converse));
}, converse)); }, converse));
it("can be used to set a custom status message", $.proxy(function () { it("can be used to set a custom status message", $.proxy(function () {
var view = this.xmppstatusview; var view = this.xmppstatusview;
this.xmppstatus.save({'status': 'online'});
spyOn(view, 'setStatusMessage').andCallThrough(); spyOn(view, 'setStatusMessage').andCallThrough();
spyOn(view, 'renderStatusChangeForm').andCallThrough(); spyOn(view, 'renderStatusChangeForm').andCallThrough();
view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
...@@ -120,6 +127,7 @@ ...@@ -120,6 +127,7 @@
it("can be added to the roster and they will be sorted alphabetically", $.proxy(function () { it("can be added to the roster and they will be sorted alphabetically", $.proxy(function () {
var i, t, is_last; var i, t, is_last;
spyOn(this.rosterview, 'render').andCallThrough(); spyOn(this.rosterview, 'render').andCallThrough();
spyOn(this.xmppstatus, 'sendPresence');
for (i=0; i<pend_names.length; i++) { for (i=0; i<pend_names.length; i++) {
is_last = i===(pend_names.length-1); is_last = i===(pend_names.length-1);
this.roster.create({ this.roster.create({
...@@ -133,6 +141,7 @@ ...@@ -133,6 +141,7 @@
// the last contact has been added. // the last contact has been added.
if (is_last) { if (is_last) {
expect(this.rosterview.$el.is(':visible')).toEqual(true); expect(this.rosterview.$el.is(':visible')).toEqual(true);
expect(this.xmppstatus.sendPresence).toHaveBeenCalled();
} else { } else {
expect(this.rosterview.$el.is(':visible')).toEqual(false); expect(this.rosterview.$el.is(':visible')).toEqual(false);
} }
......
...@@ -75,7 +75,6 @@ require([ ...@@ -75,7 +75,6 @@ require([
auto_subscribe: false, auto_subscribe: false,
animate: false animate: false
}); });
converse.onConnected(mock_connection);
// Jasmine stuff // Jasmine stuff
var jasmineEnv = jasmine.getEnv(); var jasmineEnv = jasmine.getEnv();
...@@ -93,5 +92,5 @@ require([ ...@@ -93,5 +92,5 @@ require([
}; };
jasmineEnv.updateInterval = 200; jasmineEnv.updateInterval = 200;
} }
jasmineEnv.execute(); converse.onConnected(mock_connection, $.proxy(jasmineEnv.execute, jasmineEnv));
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment