diff --git a/index.html b/index.html
index 5ddea75e..1f1ea90f 100644
--- a/index.html
+++ b/index.html
@@ -155,6 +155,7 @@
+
diff --git a/js/background.js b/js/background.js
index 63caefcf..94bdc9f0 100644
--- a/js/background.js
+++ b/js/background.js
@@ -138,6 +138,14 @@
avatar : pushMessageContent.group.avatar,
members : pushMessageContent.group.members,
};
+ var group_update = conversation.changedAttributes(_.pick(pushMessageContent.group, 'name', 'avatar'));
+ var difference = _.difference(pushMessageContent.group.members, conversation.get('members'));
+ if (difference.length > 0) {
+ group_update.joined = difference;
+ }
+ if (_.keys(group_update).length > 0) {
+ message.set({group_update: group_update});
+ }
}
attributes.active_at = now;
conversation.set(attributes);
diff --git a/js/views/group_update_view.js b/js/views/group_update_view.js
new file mode 100644
index 00000000..7f3bde17
--- /dev/null
+++ b/js/views/group_update_view.js
@@ -0,0 +1,40 @@
+/* vim: ts=4:sw=4:expandtab
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+(function () {
+ 'use strict';
+
+ window.Whisper = window.Whisper || {};
+
+ Whisper.GroupUpdateView = Backbone.View.extend({
+ tagName: "div",
+ className: "group-update",
+ render: function() {
+ //TODO l10n
+ var messages = ['Updated the group.'];
+ if (this.model.name) {
+ messages.push("Title is now '" + this.model.name + "'.");
+ }
+ if (this.model.joined) {
+ messages.push(this.model.joined + ' joined the group');
+ }
+
+ this.$el.text(messages.join(' '));
+
+ return this;
+ }
+ });
+
+})();
diff --git a/js/views/message_view.js b/js/views/message_view.js
index a64cf8d5..ab9d1c0e 100644
--- a/js/views/message_view.js
+++ b/js/views/message_view.js
@@ -61,7 +61,13 @@
initialize: function() {
this.$el.addClass(this.model.get('type'));
- this.template = $('#message').html();
+ if (this.model.get('group_update')) {
+ this.group_update_view = new Whisper.GroupUpdateView({
+ model: this.model.get('group_update')
+ }).render();
+ } else {
+ this.template = $('#message').html();
+ }
Mustache.parse(this.template);
this.listenTo(this.model, 'change', this.render); // auto update
@@ -70,32 +76,36 @@
},
render: function() {
- this.$el.html(
- Mustache.render(this.template, {
- message: this.model.get('body'),
- timestamp: moment(this.model.get('received_at')).fromNow(),
- bubble_class: this.model.get('type') === 'outgoing' ? 'sent' : 'incoming',
- sender: this.model.get('source')
- })
- );
-
- this.$el.find('.attachments').append(
- this.model.get('attachments').map(function(attachment) {
- return new AttachmentView({model: attachment}).render().el;
- })
- );
-
- if (this.model.get('delivered')) {
- this.$el.addClass('delivered');
- }
-
- var errors = this.model.get('errors');
- if (errors && errors.length) {
- this.$el.find('.message').append(
- errors.map(function(error) {
- return new ErrorView({model: error}).render().el;
+ if (this.group_update_view) {
+ this.$el.append(this.group_update_view.$el);
+ } else {
+ this.$el.html(
+ Mustache.render(this.template, {
+ message: this.model.get('body'),
+ timestamp: moment(this.model.get('received_at')).fromNow(),
+ bubble_class: this.model.get('type') === 'outgoing' ? 'sent' : 'incoming',
+ sender: this.model.get('source')
})
);
+
+ this.$el.find('.attachments').append(
+ this.model.get('attachments').map(function(attachment) {
+ return new AttachmentView({model: attachment}).render().el;
+ })
+ );
+
+ if (this.model.get('delivered')) {
+ this.$el.addClass('delivered');
+ }
+
+ var errors = this.model.get('errors');
+ if (errors && errors.length) {
+ this.$el.find('.message').append(
+ errors.map(function(error) {
+ return new ErrorView({model: error}).render().el;
+ })
+ );
+ }
}
return this;
diff --git a/test/index.html b/test/index.html
index 15bc3e98..b97d1f1b 100644
--- a/test/index.html
+++ b/test/index.html
@@ -149,6 +149,7 @@
+
@@ -164,6 +165,7 @@
+
diff --git a/test/views/group_update_view_test.js b/test/views/group_update_view_test.js
new file mode 100644
index 00000000..e49eeed6
--- /dev/null
+++ b/test/views/group_update_view_test.js
@@ -0,0 +1,16 @@
+describe('GroupUpdateView', function() {
+ it('should show new group members', function() {
+ var view = new Whisper.GroupUpdateView({model: {joined: ['Alice', 'Bob']}}).render();
+ assert.match(view.$el.text(), /Alice.*Bob.*joined the group/);
+ });
+
+ it('should note updates to the title', function() {
+ var view = new Whisper.GroupUpdateView({model: {name: 'New name'}}).render();
+ assert.match(view.$el.text(), /Title is now 'New name'/);
+ });
+
+ it('should say "Updated the group"', function() {
+ var view = new Whisper.GroupUpdateView({model: {avatar: 'New avatar'}}).render();
+ assert.match(view.$el.text(), /Updated the group/);
+ });
+});