ソースを参照

Add method trimOpenChats. Updates #61

JC Brand 11 年 前
コミット
aa52ba5b94
3 ファイル変更57 行追加21 行削除
  1. 47 19
      converse.js
  2. 8 2
      spec/chatbox.js
  3. 2 0
      spec/chatroom.js

+ 47 - 19
converse.js

@@ -650,6 +650,7 @@
                         'otr_status': this.get('otr_status') || UNENCRYPTED,
                         'minimized': this.get('minimized') || false,
                         'time_minimized': this.get('time_minimized') || moment(),
+                        'time_opened': this.get('time_opened') || moment(),
                         'height': height
                     });
                 } else {
@@ -900,7 +901,6 @@
             },
 
             render: function () {
-                converse.emit('beforeChatBoxOpens', this);
                 this.$el.attr('id', this.model.get('box_id'))
                     .html(converse.templates.chatbox(
                             _.extend(this.model.toJSON(), {
@@ -1434,7 +1434,7 @@
 
             hide: function () {
                 if (this.$el.is(':visible') && this.$el.css('opacity') == "1") {
-                    this.$el.hide('fast', converse.refreshWebkit);
+                    this.$el.fadeOut('fast', converse.refreshWebkit);
                     converse.emit('onChatBoxClosed', this);
                 }
                 return this;
@@ -1444,7 +1444,7 @@
                 if (this.$el.is(':visible') && this.$el.css('opacity') == "1") {
                     return this.focus();
                 }
-                this.$el.show(callback);
+                this.$el.fadeIn(callback);
                 if (converse.connection) {
                     // Without a connection, we haven't yet initialized
                     // localstorage
@@ -2477,8 +2477,10 @@
                 var views = {};
                 this.get = function (id) { return views[id]; };
                 this.set = function (id, view) { views[id] = view; };
+                this.getAll = function () { return views; };
 
                 this.model.on("add", function (item) {
+                    this.trimOpenChats();
                     var view = this.get(item.get('id'));
                     if (!view) {
                         if (item.get('chatroom')) {
@@ -2496,25 +2498,51 @@
                         view.initialize();
                     }
                 }, this);
+            },
 
-                converse.on('beforeChatBoxOpens', function (ev, view) {
-                    var total_width = this.$el.width();
-                    var box_width = view.$el.outerWidth();
-                    var num_views = _.keys(views).length;
-                    var toggle_width = 0; // TODO
-                    var num_visible_views = 1; // Include view about to be opened
+            trimOpenChats: function () {
+                /* This method is called before a new chat box will be opened.
+                 *
+                 * Check whether there is enough space in the page to show
+                 * another chat box. Otherwise, close the oldest chat box.
+                 */
+                var toggle_width = 0;
+                var controlbox = this.get('controlbox');
+                if (!controlbox || !controlbox.$el.is(':visible')) {
+                    toggle_width = converse.controlboxtoggle.$el.width();
+                }
+                var views = this.getAll();
+                var oldest = moment();
+                var oldest_view;
+                var total_width = this.$el.width();
+                var view_list = _.values(views);
+                if (view_list.length === 0) {
+                    return;
+                }
+                var box_width = view_list[0].$el.outerWidth();
+                var num_visible_views = 1; // Include view about to be opened
+                _.each(views, function (v) {
+                    if (v.$el.is(':visible')) {
+                        num_visible_views += 1;
+                    }
+                });
+                if (num_visible_views === 1) {
+                    return;
+                }
+                if ((num_visible_views*box_width + toggle_width) > total_width) {
                     _.each(views, function (v) {
-                        if (v.$el.is(':visible')) {
-                            num_visible_views += 1;
+                        if (v.id === 'controlbox' || !v.$el.is(':visible')) {
+                            return;
+                        }
+                        var opened = v.model.get('time_opened');
+                        if (moment(opened).isBefore(oldest)) {
+                            oldest = opened;
+                            oldest_view = v;
                         }
                     });
-                    if (num_visible_views === 1) {
-                        return;
-                    }
-                    if ((num_visible_views*box_width + toggle_width) > total_width) {
-                        // TODO: close the oldest checkbox
-                    }
-                }.bind(this));
+                    oldest_view.$el.hide(); // Hide it immediately to avoid flashes on the screen
+                    oldest_view.closeChat();
+                }
             },
 
             showChatBox: function (attrs) {
@@ -3447,7 +3475,7 @@
             },
 
             hide: function (callback) {
-                this.$el.hide('fast', callback);
+                this.$el.fadeOut('fast', callback);
             },
 
             show: function (callback) {

+ 8 - 2
spec/chatbox.js

@@ -34,6 +34,7 @@
                 // openControlBox was called earlier, so the controlbox is
                 // visible, but no other chat boxes have been created.
                 expect(this.chatboxes.length).toEqual(1);
+                spyOn(this.chatboxviews, 'trimOpenChats');
 
                 var online_contacts = this.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact').find('a.open-chat');
                 for (i=0; i<online_contacts.length; i++) {
@@ -45,6 +46,7 @@
                     $el.click();
                     expect(view.openChat).toHaveBeenCalled();
                     expect(this.chatboxes.length).toEqual(i+2);
+                    expect(this.chatboxviews.trimOpenChats).toHaveBeenCalled();
                 }
             }, converse));
 
@@ -70,12 +72,14 @@
 
             it("can be saved to, and retrieved from, localStorage", $.proxy(function () {
                 spyOn(converse, 'emit');
+                spyOn(this.chatboxviews, 'trimOpenChats');
                 runs(function () {
-                utils.openControlBox();
+                    utils.openControlBox();
                 });
                 waits(250);
                 runs(function () {
                     utils.openChatBoxes(6);
+                    expect(this.chatboxviews.trimOpenChats).toHaveBeenCalled();
                     // We instantiate a new ChatBoxes collection, which by default
                     // will be empty.
                     var newchatboxes = new this.ChatBoxes();
@@ -162,6 +166,7 @@
 
             it("will be removed from localStorage when closed", $.proxy(function () {
                 spyOn(converse, 'emit');
+                spyOn(converse.chatboxviews, 'trimOpenChats');
                 this.chatboxes.localStorage._clear();
                 runs(function () {
                     utils.closeControlBox();
@@ -171,6 +176,7 @@
                     expect(converse.emit).toHaveBeenCalledWith('onChatBoxClosed', jasmine.any(Object));
                     expect(converse.chatboxes.length).toEqual(0);
                     utils.openChatBoxes(6);
+                    expect(converse.chatboxviews.trimOpenChats).toHaveBeenCalled();
                     expect(converse.chatboxes.length).toEqual(6);
                     expect(converse.emit).toHaveBeenCalledWith('onChatBoxOpened', jasmine.any(Object));
                     utils.closeAllChatBoxes();
@@ -470,7 +476,7 @@
                     var contact_jid = contact_name.replace(' ','.').toLowerCase() + '@localhost';
                     utils.openChatBoxFor(contact_jid);
                     utils.clearChatBoxMessages(contact_jid);
-                    var one_day_ago = moment()
+                    var one_day_ago = moment();
                     one_day_ago.subtract('days', 1);
                     var message = 'This is a day old message';
                     var chatbox = this.chatboxes.get(contact_jid);

+ 2 - 0
spec/chatroom.js

@@ -115,12 +115,14 @@
             it("can be saved to, and retrieved from, localStorage", $.proxy(function () {
                 // We instantiate a new ChatBoxes collection, which by default
                 // will be empty.
+                spyOn(this.chatboxviews, 'trimOpenChats');
                 utils.openControlBox();
                 var newchatboxes = new this.ChatBoxes();
                 expect(newchatboxes.length).toEqual(0);
                 // The chatboxes will then be fetched from localStorage inside the
                 // onConnected method
                 newchatboxes.onConnected();
+                expect(this.chatboxviews.trimOpenChats).toHaveBeenCalled();
                 expect(newchatboxes.length).toEqual(2); // XXX: Includes controlbox, is this a bug?
                 // Check that the chatrooms retrieved from localStorage
                 // have the same attributes values as the original ones.