Commit 6e5bf44a authored by JC Brand's avatar JC Brand

This branch marks the start of a significant conceptual change.

Instead of differentiating between trimmed chats and minimized chats, the two
are now combined into the same thing.

This commit contains some initial work, but functionality is still impaired.
parent 88d20d03
...@@ -664,26 +664,6 @@ ...@@ -664,26 +664,6 @@
} }
}, },
save: function(key, val, options) {
/* Override the backbone function and exclude the 'trimmed'
* attribute from being persisted.
*/
var attrs;
// Handle both `"key", value` and `{key: value}` -style arguments.
if (key === null || typeof key === 'object') {
attrs = key;
options = val;
} else {
(attrs = {})[key] = val;
}
if (typeof attrs === 'object' && attrs !== null) {
if (attrs.trimmed) {
delete attrs.trimmed;
}
}
Backbone.Model.prototype.save.call(this, attrs, options);
},
getSession: function (callback) { getSession: function (callback) {
var cipher = CryptoJS.lib.PasswordBasedCipher; var cipher = CryptoJS.lib.PasswordBasedCipher;
var result, pass, instance_tag, saved_key, pass_check; var result, pass, instance_tag, saved_key, pass_check;
...@@ -917,11 +897,14 @@ ...@@ -917,11 +897,14 @@
this.updateVCard(); this.updateVCard();
this.$el.insertAfter(converse.chatboxviews.get("controlbox").$el); this.$el.insertAfter(converse.chatboxviews.get("controlbox").$el);
this.render().show().focus().model.messages.fetch({add: true});
if (this.model.get('status')) { this.model.messages.fetch({add: true});
this.showStatusMessage(this.model.get('status')); this.render().showStatusMessage();
if (this.model.get('minimized')) {
this.hide();
} else {
this.show();
} }
this.initDragResize();
if ((_.contains([UNVERIFIED, VERIFIED], this.model.get('otr_status'))) || converse.use_otr_by_default) { if ((_.contains([UNVERIFIED, VERIFIED], this.model.get('otr_status'))) || converse.use_otr_by_default) {
this.model.initiateOTR(); this.model.initiateOTR();
} }
...@@ -1299,7 +1282,7 @@ ...@@ -1299,7 +1282,7 @@
converse.emit('onBuddyStatusChanged', item.attributes, item.get('chat_status')); converse.emit('onBuddyStatusChanged', item.attributes, item.get('chat_status'));
} }
if (_.has(item.changed, 'status')) { if (_.has(item.changed, 'status')) {
this.showStatusMessage(item.get('status')); this.showStatusMessage();
converse.emit('onBuddyStatusMessageChanged', item.attributes, item.get('status')); converse.emit('onBuddyStatusMessageChanged', item.attributes, item.get('status'));
} }
if (_.has(item.changed, 'image')) { if (_.has(item.changed, 'image')) {
...@@ -1308,18 +1291,21 @@ ...@@ -1308,18 +1291,21 @@
if (_.has(item.changed, 'otr_status')) { if (_.has(item.changed, 'otr_status')) {
this.renderToolbar().informOTRChange(); this.renderToolbar().informOTRChange();
} }
if (_.has(item.changed, 'trimmed')) { if (_.has(item.changed, 'minimized')) {
if (item.get('trimmed')) { if (item.get('minimized')) {
this.trim(); this.hide();
} else { } else {
this.grow(); this.maximize();
} }
} }
// TODO check for changed fullname as well // TODO check for changed fullname as well
}, },
showStatusMessage: function (msg) { showStatusMessage: function (msg) {
this.$el.find('p.user-custom-message').text(msg).attr('title', msg); msg = msg || this.model.get('status');
if (msg) {
this.$el.find('p.user-custom-message').text(msg).attr('title', msg);
}
}, },
close: function () { close: function () {
...@@ -1331,49 +1317,22 @@ ...@@ -1331,49 +1317,22 @@
return this; return this;
}, },
trim: function () { maximize: function () {
this.$el.hide('fast', converse.refreshwebkit);
},
grow: function () {
// the opposite of trim, i.e. restoring a trimmed chat box // the opposite of trim, i.e. restoring a trimmed chat box
this.$el.insertAfter(converse.chatboxviews.get("controlbox").$el).show(); this.$el.insertAfter(converse.chatboxviews.get("controlbox").$el).show();
this.focus(); this.focus();
converse.refreshWebkit(); converse.refreshWebkit();
this.model.trigger('grow', this.model); this.model.trigger('maximized', this.model);
},
saveToggleState: function () {
var flyout = this.$el.find('.box-flyout');
if (flyout.hasClass('minimized')) {
flyout.removeClass('minimized');
this.model.save({'minimized': false});
} else {
flyout.addClass('minimized');
this.model.save({
'minimized': true,
'time_minimized': moment().format()
});
}
return this;
}, },
toggle: function (ev) { toggle: function (ev) {
var $target = $(ev.target), $count; /* Minimizes or maximizes a chat box
this.saveToggleState(); */
this.$el.children('.box-flyout').attr('style', ''); this.model.save({
this.$el.find('div.chat-body').slideToggle('fast'); 'minimized': true,
if ($target.hasClass('icon-minus')) { 'time_minimized': moment().format()
$target.removeClass('icon-minus').addClass('icon-plus'); });
} else { this.$el.hide('fast', converse.refreshwebkit);
$target.removeClass('icon-plus').addClass('icon-minus');
$count = this.$el.find('.chat-head-message-count');
$count.html(0).data('count', 0);
if ($count.is(':visible')) { $count.hide('fast'); }
}
// Toggle drag resize ability
this.$el.find('.dragresize-tm').toggle();
this.setChatBoxHeight(this.height);
converse.emit('onChatBoxToggled', this); converse.emit('onChatBoxToggled', this);
}, },
...@@ -1495,6 +1454,7 @@ ...@@ -1495,6 +1454,7 @@
// Without a connection, we haven't yet initialized // Without a connection, we haven't yet initialized
// localstorage // localstorage
this.model.save(); this.model.save();
this.initDragResize();
} }
return this; return this;
}, },
...@@ -1939,6 +1899,13 @@ ...@@ -1939,6 +1899,13 @@
initialize: function () { initialize: function () {
this.connect(null); this.connect(null);
this.model.messages.on('add', this.onMessageAdded, this); this.model.messages.on('add', this.onMessageAdded, this);
this.model.on('change:minimized', function (item) {
if (item.get('minimized')) {
this.hide();
} else {
this.maximize();
}
}, this);
this.model.on('destroy', function (model, response, options) { this.model.on('destroy', function (model, response, options) {
this.hide(); this.hide();
converse.connection.muc.leave( converse.connection.muc.leave(
...@@ -2516,10 +2483,10 @@ ...@@ -2516,10 +2483,10 @@
this.ChatBoxViews = Backbone.Overview.extend({ this.ChatBoxViews = Backbone.Overview.extend({
initialize: function () { initialize: function () {
this.trimmed_chatboxes_view = new converse.TrimmedChatBoxesView({model: this.model}); this.trimmed_chatboxes_view = new converse.MinimizedChatBoxesView({model: this.model});
this.render(); this.render();
this.model.on("add", this.onChatAdded, this); this.model.on("add", this.onChatAdded, this);
this.model.on("grow", function (item) { this.model.on("maximized", function (item) {
this.trimChats(this.get(item.get('id'))); this.trimChats(this.get(item.get('id')));
}, this); }, this);
}, },
...@@ -2591,15 +2558,15 @@ ...@@ -2591,15 +2558,15 @@
} }
trimmed_chats_width = this.trimmed_chatboxes_view.$('.box-flyout').outerWidth(true) || 0; trimmed_chats_width = this.trimmed_chatboxes_view.$('.box-flyout').outerWidth(true) || 0;
if ((trimmed_chats_width + boxes_width + toggle_width) > this.$el.width()) { if ((trimmed_chats_width + boxes_width + toggle_width) > this.$el.width()) {
this.getOldestNonTrimmedChat().set('trimmed', true); this.getOldestMaximizedChat().set('minimized', true);
} }
}, },
getOldestNonTrimmedChat: function () { getOldestMaximizedChat: function () {
// Get oldest view (which is not controlbox) // Get oldest view (which is not controlbox)
var i = 0; var i = 0;
var model = this.model.sort().at(i); var model = this.model.sort().at(i);
while (model.get('id') === 'controlbox' || model.get('trimmed') === true) { while (model.get('id') === 'controlbox' || model.get('minimized') === true) {
i++; i++;
model = this.model.at(i); model = this.model.at(i);
} }
...@@ -2609,8 +2576,8 @@ ...@@ -2609,8 +2576,8 @@
showChat: function (attrs) { showChat: function (attrs) {
var chatbox = this.model.get(attrs.jid); var chatbox = this.model.get(attrs.jid);
if (chatbox) { if (chatbox) {
if (chatbox.get('trimmed')) { if (chatbox.get('minimized')) {
chatbox.set({'trimmed': false}); chatbox.set({'minimized': false});
} else { } else {
chatbox.trigger('show'); chatbox.trigger('show');
} }
...@@ -2625,7 +2592,7 @@ ...@@ -2625,7 +2592,7 @@
} }
}); });
this.TrimmedChatBoxView = Backbone.View.extend({ this.MinimizedChatBoxView = Backbone.View.extend({
tagName: 'div', tagName: 'div',
className: 'chat-head', className: 'chat-head',
...@@ -2656,16 +2623,21 @@ ...@@ -2656,16 +2623,21 @@
this.$el.remove(); this.$el.remove();
this.model.set({ this.model.set({
'time_opened': moment().format(), 'time_opened': moment().format(),
'trimmed': false 'minimized': false
}); });
return this; return this;
} }
}); });
this.TrimmedChatBoxesView = Backbone.Overview.extend({ this.MinimizedChatBoxesView = Backbone.Overview.extend({
initialize: function () { initialize: function () {
this.model.on("change:trimmed", function (item) { this.model.on("add", function (item) {
if (item.get('minimized')) {
this.addChat(item);
}
}, this);
this.model.on("change:minimized", function (item) {
this.onChanged(item); this.onChanged(item);
}, this); }, this);
}, },
...@@ -2689,15 +2661,20 @@ ...@@ -2689,15 +2661,20 @@
onChanged: function (item) { onChanged: function (item) {
var view; var view;
if (item.get('trimmed')) { if (item.get('minimized')) {
view = new converse.TrimmedChatBoxView({model: item}); this.addChat(item);
this.$('.box-flyout').append(view.render());
this.add(item.get('id'), view);
} else { } else {
view = this.get(item.get('id')); view = this.get(item.get('id'));
view.restore(); view.restore();
} }
},
addChat: function (item) {
var view = new converse.MinimizedChatBoxView({model: item});
this.$('.box-flyout').append(view.render());
this.add(item.get('id'), view);
} }
}); });
this.RosterItem = Backbone.Model.extend({ this.RosterItem = Backbone.Model.extend({
......
...@@ -77,14 +77,14 @@ ...@@ -77,14 +77,14 @@
expect(this.chatboxviews.trimChats).toHaveBeenCalled(); expect(this.chatboxviews.trimChats).toHaveBeenCalled();
chatboxview = this.chatboxviews.get(jid); chatboxview = this.chatboxviews.get(jid);
spyOn(chatboxview, 'trim').andCallThrough(); spyOn(chatboxview, 'hide').andCallThrough();
chatboxview.model.set({'trimmed': true}); chatboxview.model.set({'minimized': true});
expect(trimmed_chatboxes.onChanged).toHaveBeenCalled(); expect(trimmed_chatboxes.onChanged).toHaveBeenCalled();
expect(chatboxview.trim).toHaveBeenCalled(); expect(chatboxview.hide).toHaveBeenCalled();
trimmedview = trimmed_chatboxes.get(jid); trimmedview = trimmed_chatboxes.get(jid);
expect(trimmedview.$el.is(":visible")).toBeTruthy(); expect(trimmedview.$el.is(":visible")).toBeTruthy();
} }
// Test that they can be restored/grown again // Test that they can be maximized again
var chatboxviews = this.chatboxviews.getAll(); var chatboxviews = this.chatboxviews.getAll();
var keys = _.keys(chatboxviews); var keys = _.keys(chatboxviews);
for (i=0; i<keys.length; i++) { for (i=0; i<keys.length; i++) {
...@@ -94,10 +94,10 @@ ...@@ -94,10 +94,10 @@
} }
chatboxview = chatboxviews[key]; chatboxview = chatboxviews[key];
trimmedview = trimmed_chatboxes.get(key); trimmedview = trimmed_chatboxes.get(key);
spyOn(chatboxview, 'grow').andCallThrough(); spyOn(chatboxview, 'maximize').andCallThrough();
trimmedview.$("a.restore-chat").click(); trimmedview.$("a.restore-chat").click();
expect(trimmed_chatboxes.onChanged).toHaveBeenCalled(); expect(trimmed_chatboxes.onChanged).toHaveBeenCalled();
expect(chatboxview.grow).toHaveBeenCalled(); expect(chatboxview.maximize).toHaveBeenCalled();
} }
}, converse)); }, converse));
...@@ -183,35 +183,38 @@ ...@@ -183,35 +183,38 @@
it("can be toggled by clicking a DOM element with class 'toggle-chatbox-button'", function () { it("can be toggled by clicking a DOM element with class 'toggle-chatbox-button'", function () {
var chatbox = utils.openChatBoxes(1)[0], var chatbox = utils.openChatBoxes(1)[0],
chatview = this.chatboxviews.get(chatbox.get('jid')); chatview = this.chatboxviews.get(chatbox.get('jid')),
trimmed_chatboxes = this.chatboxviews.trimmed_chatboxes_view;
spyOn(chatview, 'maximize').andCallThrough();
spyOn(chatview, 'toggle').andCallThrough(); spyOn(chatview, 'toggle').andCallThrough();
spyOn(converse, 'emit'); spyOn(converse, 'emit');
spyOn(trimmed_chatboxes, 'onChanged').andCallThrough();
// We need to rebind all events otherwise our spy won't be called // We need to rebind all events otherwise our spy won't be called
chatview.delegateEvents(); chatview.delegateEvents();
runs(function () { runs(function () {
chatview.$el.find('.toggle-chatbox-button').click(); chatview.$el.find('.toggle-chatbox-button').click();
}); });
waits(250); waits(50);
runs(function () { runs(function () {
expect(chatview.toggle).toHaveBeenCalled(); expect(chatview.toggle).toHaveBeenCalled();
expect(converse.emit).toHaveBeenCalledWith('onChatBoxToggled', jasmine.any(Object)); expect(converse.emit).toHaveBeenCalledWith('onChatBoxToggled', jasmine.any(Object));
expect(converse.emit.callCount, 2); expect(converse.emit.callCount, 2);
expect(chatview.$el.find('.chat-body').is(':visible')).toBeFalsy(); expect(chatview.$el.is(':visible')).toBeFalsy();
expect(chatview.$el.find('.toggle-chatbox-button').hasClass('icon-minus')).toBeFalsy();
expect(chatview.$el.find('.toggle-chatbox-button').hasClass('icon-plus')).toBeTruthy();
expect(chatview.model.get('minimized')).toBeTruthy(); expect(chatview.model.get('minimized')).toBeTruthy();
chatview.$el.find('.toggle-chatbox-button').click(); chatview.$el.find('.toggle-chatbox-button').click();
trimmedview = trimmed_chatboxes.get(chatview.model.get('id'));
trimmedview.$("a.restore-chat").click();
}); });
waits(250); waits(50);
runs(function () { runs(function () {
expect(chatview.toggle).toHaveBeenCalled(); expect(trimmed_chatboxes.onChanged).toHaveBeenCalled();
expect(converse.emit).toHaveBeenCalledWith('onChatBoxToggled', jasmine.any(Object)); expect(chatview.maximize).toHaveBeenCalled();
expect(chatview.$el.find('.chat-body').is(':visible')).toBeTruthy(); expect(chatview.$el.find('.chat-body').is(':visible')).toBeTruthy();
expect(chatview.$el.find('.toggle-chatbox-button').hasClass('icon-minus')).toBeTruthy(); expect(chatview.$el.find('.toggle-chatbox-button').hasClass('icon-minus')).toBeTruthy();
expect(chatview.$el.find('.toggle-chatbox-button').hasClass('icon-plus')).toBeFalsy(); expect(chatview.$el.find('.toggle-chatbox-button').hasClass('icon-plus')).toBeFalsy();
expect(chatview.model.get('minimized')).toBeFalsy(); expect(chatview.model.get('minimized')).toBeFalsy();
expect(converse.emit.callCount, 3);
}); });
}.bind(converse)); }.bind(converse));
......
<div class="box-flyout {[if (minimized) {]} minimized {[}]}" <div class="box-flyout" style="height: {{height}}px">
{[if (!minimized) {]} style="height: {{height}}px" {[}]}> <div class="dragresize dragresize-tm"></div>
<div class="dragresize dragresize-tm" {[ if (minimized) { ]} style="display:none" {[ } ]}></div>
<div class="chat-head chat-head-chatbox"> <div class="chat-head chat-head-chatbox">
<div class="chat-head-message-count">0</div> <div class="chat-head-message-count">0</div>
<a class="close-chatbox-button icon-close"></a> <a class="close-chatbox-button icon-close"></a>
<a class="toggle-chatbox-button <a class="toggle-chatbox-button icon-minus"></a>
{[ if (minimized) { ]} icon-plus {[ } ]}
{[ if (!minimized) { ]} icon-minus {[ } ]}
"></a>
<div class="chat-title"> <div class="chat-title">
{[ if (url) { ]} {[ if (url) { ]}
<a href="{{url}}" target="_blank" class="user"> <a href="{{url}}" target="_blank" class="user">
...@@ -19,7 +15,7 @@ ...@@ -19,7 +15,7 @@
</div> </div>
<p class="user-custom-message"><p/> <p class="user-custom-message"><p/>
</div> </div>
<div class="chat-body" {[ if (minimized) { ]} style="display:none" {[ } ]}> <div class="chat-body">
<div class="chat-content"></div> <div class="chat-content"></div>
<form class="sendXMPPMessage" action="" method="post"> <form class="sendXMPPMessage" action="" method="post">
{[ if (show_toolbar) { ]} {[ if (show_toolbar) { ]}
......
<div class="box-flyout {[if (minimized) {]} minimized {[}]}" <div class="box-flyout" style="height: {{height}}px"
{[if (!minimized) {]} style="height: {{height}}px" {[}]}> {[ if (minimized) { ]} style="display:none" {[ } ]}>
<div class="dragresize dragresize-tm" {[ if (minimized) { ]} style="display:none" {[ } ]}></div> <div class="dragresize dragresize-tm"></div>
<div class="chat-head chat-head-chatroom"> <div class="chat-head chat-head-chatroom">
<div class="chat-head-message-count">0</div> <div class="chat-head-message-count">0</div>
<a class="close-chatbox-button icon-close"></a> <a class="close-chatbox-button icon-close"></a>
<a class="toggle-chatbox-button <a class="toggle-chatbox-button icon-minus"></a>
{[ if (minimized) { ]} icon-plus {[ } ]}
{[ if (!minimized) { ]} icon-minus {[ } ]}
"></a>
<a class="configure-chatroom-button icon-wrench" style="display:none"></a> <a class="configure-chatroom-button icon-wrench" style="display:none"></a>
<div class="chat-title"> {{ name }} </div> <div class="chat-title"> {{ name }} </div>
<p class="chatroom-topic"><p/> <p class="chatroom-topic"><p/>
</div> </div>
<div class="chat-body" {[ if (minimized) { ]} style="display:none" {[ } ]}> <div class="chat-body"><span class="spinner centered"/></div>
<span class="spinner centered"/>
</div>
</div> </div>
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