diff --git a/converse.js b/converse.js index 23ff739c8..61aaf75b9 100644 --- a/converse.js +++ b/converse.js @@ -2264,6 +2264,7 @@ 'online': __('This contact is online'), 'offline': __('This contact is offline'), 'unavailable': __('This contact is unavailable'), + 'xa': __('This contact is away for an extended period'), 'away': __('This contact is away') }[item.get('chat_status')||'offline']; this.$el.html(this.template( @@ -2650,7 +2651,7 @@ } changed_presence = view.model.changed.chat_status; if (changed_presence) { - this.sortRoster(changed_presence) + this.sortRoster(changed_presence); sorted = true; } if (item.get('is_last')) { @@ -2689,6 +2690,7 @@ $my_contacts.siblings('dd.current-xmpp-contact.'+chat_status).tsort('a', {order:'asc'}); $my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.offline')); $my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.unavailable')); + $my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.xa')); $my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.away')); $my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.dnd')); $my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.online')); diff --git a/fonticons/style.css b/fonticons/style.css index c6d69ad81..39dfe4a93 100644 --- a/fonticons/style.css +++ b/fonticons/style.css @@ -28,7 +28,7 @@ Instead of a list of all class selectors, you can use the generic selector below, but it's slower: [class*="icon-"] { */ -.icon-home, .icon-pencil, .icon-camera, .icon-camera-2, .icon-play, .icon-music, .icon-headphones, .icon-phone, .icon-phone-hang-up, .icon-address-book, .icon-notebook, .icon-envelop, .icon-pushpin, .icon-online, .icon-away, .icon-bubbles, .icon-bubbles-2, .icon-bubbles-3, .icon-user, .icon-users, .icon-quotes-left, .icon-spinner, .icon-search, .icon-cogs, .icon-wrench, .icon-unlocked, .icon-lock, .icon-lock-2, .icon-key, .icon-key-2, .icon-zoom-out, .icon-zoom-in, .icon-cog, .icon-remove, .icon-remove-2, .icon-eye, .icon-eye-blocked, .icon-attachment, .icon-globe, .icon-heart, .icon-happy, .icon-thumbs-up, .icon-smiley, .icon-tongue, .icon-sad, .icon-wink, .icon-wondering, .icon-confused, .icon-shocked, .icon-evil, .icon-angry, .icon-cool, .icon-grin, .icon-info, .icon-notification, .icon-warning, .icon-spell-check, .icon-volume-high, .icon-volume-medium, .icon-volume-low, .icon-volume-mute, .icon-volume-mute-2, .icon-volume-decrease, .icon-volume-increase, .icon-bold, .icon-underline, .icon-italic, .icon-strikethrough, .icon-new-tab, .icon-youtube, .icon-close, .icon-blocked, .icon-cancel-circle, .icon-minus, .icon-plus, .icon-checkbox-checked, .icon-checkbox-unchecked, .icon-checkbox-partial, .icon-radio-checked, .icon-radio-unchecked, .icon-room-info, .icon-newspaper, .icon-image, .icon-offline, .icon-unavailable, .icon-dnd { +.icon-home, .icon-pencil, .icon-camera, .icon-camera-2, .icon-play, .icon-music, .icon-headphones, .icon-phone, .icon-phone-hang-up, .icon-address-book, .icon-notebook, .icon-envelop, .icon-pushpin, .icon-online, .icon-away, .icon-xa, .icon-bubbles, .icon-bubbles-2, .icon-bubbles-3, .icon-user, .icon-users, .icon-quotes-left, .icon-spinner, .icon-search, .icon-cogs, .icon-wrench, .icon-unlocked, .icon-lock, .icon-lock-2, .icon-key, .icon-key-2, .icon-zoom-out, .icon-zoom-in, .icon-cog, .icon-remove, .icon-remove-2, .icon-eye, .icon-eye-blocked, .icon-attachment, .icon-globe, .icon-heart, .icon-happy, .icon-thumbs-up, .icon-smiley, .icon-tongue, .icon-sad, .icon-wink, .icon-wondering, .icon-confused, .icon-shocked, .icon-evil, .icon-angry, .icon-cool, .icon-grin, .icon-info, .icon-notification, .icon-warning, .icon-spell-check, .icon-volume-high, .icon-volume-medium, .icon-volume-low, .icon-volume-mute, .icon-volume-mute-2, .icon-volume-decrease, .icon-volume-increase, .icon-bold, .icon-underline, .icon-italic, .icon-strikethrough, .icon-new-tab, .icon-youtube, .icon-close, .icon-blocked, .icon-cancel-circle, .icon-minus, .icon-plus, .icon-checkbox-checked, .icon-checkbox-unchecked, .icon-checkbox-partial, .icon-radio-checked, .icon-radio-unchecked, .icon-room-info, .icon-newspaper, .icon-image, .icon-offline, .icon-unavailable, .icon-dnd { font-family: 'Converse-js'; speak: none; font-style: normal; @@ -287,6 +287,7 @@ you can use the generic selector below, but it's slower: .icon-image:before { content: "\2b14"; } +.icon-xa:before, .icon-unavailable:before, .icon-offline:before { content: "\e002"; diff --git a/spec/MainSpec.js b/spec/MainSpec.js index f7fabc3d8..041fba814 100644 --- a/spec/MainSpec.js +++ b/spec/MainSpec.js @@ -17,7 +17,8 @@ var cur_names = [ 'Max Frankfurter', 'Candice van der Knijff', 'Irini Vlastuin', 'Rinse Sommer', 'Annegreet Gomez', 'Robin Schook', 'Marcel Eberhardt', 'Simone Brauer', 'Asmaa Haakman', 'Felix Amsel', - 'Lena Grunewald', 'Laura Grunewald', 'Mandy Seiler', 'Sven Bosch', 'Nuriye Cuypers' + 'Lena Grunewald', 'Laura Grunewald', 'Mandy Seiler', 'Sven Bosch', 'Nuriye Cuypers', + 'Staal Burger', 'Brenner Brand', 'Vleis Visagie' ]; var num_contacts = req_names.length + pend_names.length + cur_names.length; var open_controlbox; @@ -280,10 +281,28 @@ } }, converse)); - it("can change their status to unavailable and be sorted alphabetically", $.proxy(function () { + it("can change their status to xa and be sorted alphabetically", $.proxy(function () { var item, view, jid, t; spyOn(this.rosterview, 'render').andCallThrough(); for (i=9; i<12; i++) { + jid = cur_names[i].replace(' ','.').toLowerCase() + '@localhost'; + view = this.rosterview.rosteritemviews[jid]; + spyOn(view, 'render').andCallThrough(); + item = view.model; + item.set('chat_status', 'xa'); + expect(view.render).toHaveBeenCalled(); + expect(this.rosterview.render).toHaveBeenCalled(); + + // Check that they are sorted alphabetically + t = this.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact.xa').find('a.open-chat').text(); + expect(t).toEqual(cur_names.slice(9,i+1).sort().join('')); + } + }, converse)); + + it("can change their status to unavailable and be sorted alphabetically", $.proxy(function () { + var item, view, jid, t; + spyOn(this.rosterview, 'render').andCallThrough(); + for (i=12; i<15; i++) { jid = cur_names[i].replace(' ','.').toLowerCase() + '@localhost'; view = this.rosterview.rosteritemviews[jid]; spyOn(view, 'render').andCallThrough(); @@ -294,31 +313,29 @@ // Check that they are sorted alphabetically t = this.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact.unavailable').find('a.open-chat').text(); - expect(t).toEqual(cur_names.slice(9, i+1).sort().join('')); + expect(t).toEqual(cur_names.slice(12, i+1).sort().join('')); } }, converse)); - it("are ordered according to status: online, busy, away, unavailable, offline", $.proxy(function () { + it("are ordered according to status: online, busy, away, xa, unavailable, offline", $.proxy(function () { var contacts = this.rosterview.$el.find('dd.current-xmpp-contact'); var i; - // The first five contacts are online. for (i=0; i<3; i++) { expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('online'); } - // The next five are busy for (i=3; i<6; i++) { expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('dnd'); } - // The next five are away for (i=6; i<9; i++) { expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('away'); } - // The next five are unavailable for (i=9; i<12; i++) { + expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('xa'); + } + for (i=12; i<15; i++) { expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('unavailable'); } - // The next 20 are offline - for (i=12; i