浏览代码

Add the logic for toggling minimized chats

JC Brand 11 年之前
父节点
当前提交
7d6595435e

+ 120 - 62
converse.js

@@ -569,6 +569,7 @@
             }
             this.bare_jid = Strophe.getBareJidFromJid(this.connection.jid);
             this.domain = Strophe.getDomainFromJid(this.connection.jid);
+            this.minimized_chats = new converse.MinimizedChats({model: this.chatboxes});
             this.features = new this.Features();
             this.enableCarbons();
             this.initStatus($.proxy(function () {
@@ -653,17 +654,31 @@
                         '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().format(),
+                        'time_opened': this.get('time_opened') || moment().valueOf(),
                         'height': height
                     });
                 } else {
                     this.set({
                         'height': height,
-                        'time_opened': moment(0).format()
+                        'time_opened': moment(0).valueOf()
                     });
                 }
             },
 
+            maximize: function () {
+                this.save({
+                    'minimized': false,
+                    'time_opened': moment().valueOf()
+                });
+            },
+
+            minimize: function () {
+                this.save({
+                    'minimized': true,
+                    'time_minimized': moment().format()
+                });
+            },
+
             getSession: function (callback) {
                 var cipher = CryptoJS.lib.PasswordBasedCipher;
                 var result, pass, instance_tag, saved_key, pass_check;
@@ -1305,22 +1320,18 @@
             },
 
             maximize: function () {
-                /* Restores a minimized chat box
-                 */
-                this.$el.insertAfter(converse.chatboxviews.get("controlbox").$el).show();
-                this.focus();
-                converse.refreshWebkit();
-                converse.emit('onChatBoxMaximized', this);
+                // Restores a minimized chat box
                 this.model.trigger('maximized', this.model);
+                this.$el.insertAfter(converse.chatboxviews.get("controlbox").$el).show('fast', $.proxy(function () {
+                    converse.refreshWebkit();
+                    this.focus();
+                    converse.emit('onChatBoxMaximized', this);
+                }, this));
             },
 
             minimize: function (ev) {
-                /* Minimizes a chat box
-                 */
-                this.model.save({
-                    'minimized': true,
-                    'time_minimized': moment().format()
-                });
+                // Minimizes a chat box
+                this.model.minimize();
                 this.$el.hide('fast', converse.refreshwebkit);
                 converse.emit('onChatBoxMinimized', this);
             },
@@ -2478,18 +2489,12 @@
         this.ChatBoxViews = Backbone.Overview.extend({
 
             initialize: function () {
-                this.trimmed_chatboxes_view = new converse.MinimizedChatBoxesView({model: this.model});
-                this.render();
                 this.model.on("add", this.onChatAdded, this);
                 this.model.on("maximized", function (item) {
                     this.trimChats(this.get(item.get('id')));
                 }, this);
             },
 
-            render: function () {
-                this.$el.html(this.trimmed_chatboxes_view.render());
-            },
-
             _ensureElement: function() {
                 /* Override method from backbone.js
                  * If the #conversejs element doesn't exist, create it.
@@ -2500,6 +2505,7 @@
                         $el = $('<div id="conversejs">');
                         $('body').append($el);
                     }
+                    $el.html(converse.templates.chats_panel());
                     this.setElement($el, false);
                 } else {
                     this.setElement(_.result(this, 'el'), false);
@@ -2525,34 +2531,38 @@
                 this.trimChats(view);
             },
 
-            trimChats: function (view) {
-                /* This method is called before a new chat box will be opened.
+            trimChats: function (newchat) {
+                /* This method is called when a newly created chat box will
+                 * be shown.
                  *
-                 * Check whether there is enough space in the page to show
-                 * another chat box. Otherwise, close the oldest chat box.
+                 * It checks whether there is enough space on the page to show
+                 * another chat box. Otherwise it minimize the oldest chat box
+                 * to create space.
                  */
-                if (converse.no_trimming) {
+                if (converse.no_trimming || (this.model.length <= 1)) {
                     return;
                 }
-                var toggle_width = 0,
-                    trimmed_chats_width,
-                    boxes_width = view.$el.outerWidth(true),
+                var controlbox_width = 0,
+                    $minimized = converse.minimized_chats.$el,
+                    minimized_width = $minimized.is(':visible') ? $minimized.outerWidth(true) : 0,
+                    boxes_width = newchat.$el.outerWidth(true),
                     controlbox = this.get('controlbox');
+
                 if (!controlbox || !controlbox.$el.is(':visible')) {
-                    toggle_width = converse.controlboxtoggle.$el.width();
+                    controlbox_width = converse.controlboxtoggle.$el.outerWidth(true);
+                } else {
+                    controlbox_width = controlbox.$el.outerWidth(true);
                 }
-                this.$el.find('.chatbox').addBack('.chatroom').each(function (idx, el) {
-                    var $el = $(el);
-                    if ($el.is(':visible')) {
-                        boxes_width += $el.outerWidth(true);
+
+                _.each(this.getAll(), function (view) {
+                    var id = view.model.get('id');
+                    if (view.$el.is(':visible') && (id !== 'controlbox') && (id !== newchat.model.get('id'))) { 
+                        boxes_width += view.$el.outerWidth(true);
                     }
                 });
-                if (this.model.length <= 1) {
-                    return;
-                }
-                trimmed_chats_width = this.trimmed_chatboxes_view.$('.box-flyout').outerWidth(true) || 0;
-                if ((trimmed_chats_width + boxes_width + toggle_width) > this.$el.width()) {
-                    this.getOldestMaximizedChat().set('minimized', true);
+
+                if ((minimized_width + boxes_width + controlbox_width) > this.$el.outerWidth(true)) {
+                    this.getOldestMaximizedChat().minimize();
                 }
             },
 
@@ -2560,6 +2570,9 @@
                 // Get oldest view (which is not controlbox)
                 var i = 0;
                 var model = this.model.sort().at(i);
+                console.log(this.model.pluck('time_opened'));
+                console.log(this.model.pluck('id'));
+                console.log(this.model.pluck('minimized'));
                 while (model.get('id') === 'controlbox' || model.get('minimized') === true) {
                     i++;
                     model = this.model.at(i);
@@ -2571,7 +2584,7 @@
                 var chatbox  = this.model.get(attrs.jid);
                 if (chatbox) {
                     if (chatbox.get('minimized')) {
-                        chatbox.set({'minimized': false});
+                        chatbox.maximize();
                     } else {
                         chatbox.trigger('show');
                     }
@@ -2605,7 +2618,10 @@
             },
 
             render: function () {
-                var data = this.model.toJSON();
+                var data = _.extend(
+                    this.model.toJSON(),
+                    { 'tooltip': __('Click to restore this chat') }
+                );
                 if (this.model.get('chatroom')) {
                     data.title = this.model.get('name');
                     this.$el.addClass('chat-head-chatroom');
@@ -2650,60 +2666,102 @@
                     ev.preventDefault();
                 }
                 this.$el.remove();
-                this.model.set({
-                    'time_opened': moment().format(),
-                    'minimized': false
-                });
+                this.model.maximize();
                 return this;
             }
         });
 
-        this.MinimizedChatBoxesView = Backbone.Overview.extend({
+        this.MinimizedChats = Backbone.Overview.extend({
+            el: "#minimized-chats",
+
+            events: {
+                "click #toggle-minimized-chats": "toggle"
+            },
 
             initialize: function () {
+                this.chats_toggle = new converse.MinimizedChatsToggle();
+                this.chats_toggle_view = new converse.MinimizedChatsToggleView({model: this.chats_toggle});
+
                 this.model.on("add", function (item) {
                     if (item.get('minimized')) {
                         this.addChat(item);
                     }
                 }, this);
+                this.model.on("destroy", function (item) {
+                    this.remove(item.get('id'));
+                    this.render();
+                }, this);
                 this.model.on("change:minimized", function (item) {
                     this.onChanged(item);
                 }, this);
             },
 
             render: function () {
+                if (this.keys().length === 0) {
+                    this.$el.hide('fast');
+                } else if (this.keys().length === 1) {
+                    this.$el.show('fast');
+                }
                 return this.$el;
             },
 
-            _ensureElement: function () {
-                /* Override method from backbone.js
-                * Make sure that the el and $el attributes point to a DOM snippet
-                * from src/templates/trimmed_chats.html
-                */
-                if (!this.el) {
-                    var $el = $(converse.templates.trimmed_chats());
-                    this.setElement($el, false);
-                } else {
-                    this.setElement(_.result(this, 'el'), false);
-                }
+            toggle: function () {
+                this.chats_toggle.set({'visible': !this.chats_toggle.get('visible')})
+                this.$('.minimized-chats-flyout').toggle();
             },
 
             onChanged: function (item) {
-                var view;
                 if (item.get('minimized')) {
                     this.addChat(item);
                 } else {
-                    view = this.get(item.get('id'));
-                    view.restore();
+                    this.removeChat(item);
                 }
             },
 
             addChat: function (item) {
+                if (this.get(item.get('id'))) {
+                    return;
+                }
                 var view = new converse.MinimizedChatBoxView({model: item});
-                this.$('.box-flyout').append(view.render());
+                this.$('.minimized-chats-flyout').append(view.render());
                 this.add(item.get('id'), view);
+                this.chats_toggle.set({'num_minimized': this.keys().length});
+                this.render();
+            },
+
+            removeChat: function (item) {
+                this.remove(item.get('id')).restore();
+                this.chats_toggle.set({'num_minimized': this.keys().length});
+                this.render();
+            }
+        });
+
+        this.MinimizedChatsToggle = Backbone.Model.extend({
+            localStorage: new Backbone.LocalStorage(
+                b64_sha1('converse.minimized-chats-toggle'+converse.bare_jid)),
+
+            initialize: function () {
+                this.set({
+                    'visible': this.get('visible') || false,
+                    'num_minimized': 0
+                });
             }
+        });
+
+        this.MinimizedChatsToggleView = Backbone.View.extend({
+            el: '#toggle-minimized-chats',
+
+            initialize: function () {
+                this.model.on('change:num_minimized', this.render, this);
+            },
 
+            render: function () {
+                this.$el.html(converse.templates.toggle_chats({
+                    'Minimized': __('Minimized'),
+                    'num_minimized': this.model.get('num_minimized')
+                }));
+                return this.$el;
+            },
         });
 
         this.RosterItem = Backbone.Model.extend({
@@ -3461,7 +3519,7 @@
             }
         });
 
-        this.Feature = Backbone.Model.extend();
+        this.Feature = Backbone.Model;
         this.Features = Backbone.Collection.extend({
             /* Service Discovery
             * -----------------

+ 29 - 18
css/converse.css

@@ -559,14 +559,14 @@ span.spinner.centered {
 span.spinner.hor_centered {
   text-align: center;
 }
-#conversejs #trimmed-chatboxes .box-flyout {
+#conversejs #minimized-chats .box-flyout {
   position: absolute;
   display: block;
   height: auto;
   bottom: 25px;
   margin-left: 0;
 }
-#conversejs #trimmed-chatboxes .box-flyout .chat-head {
+#conversejs #minimized-chats .box-flyout .chat-head {
   font-size: 100%;
   border-radius: 4px;
   padding: 3px 0 0 5px;
@@ -575,10 +575,7 @@ span.spinner.hor_centered {
   height: 24px;
   width: 130px;
 }
-#conversejs #trimmed-chatboxes .chat-head-chatroom {
-  width: 100px;
-}
-#conversejs #trimmed-chatboxes,
+#conversejs #minimized-chats,
 #conversejs .toggle-controlbox {
   float: right;
   font-size: 90%;
@@ -591,7 +588,12 @@ span.spinner.hor_centered {
   font-weight: bold;
   height: 100%;
 }
-#conversejs .toggle-minimized-chats {
+#conversejs #minimized-chats {
+  width: 130px;
+  padding: 0;
+  display: none;
+}
+#conversejs #toggle-minimized-chats {
   position: relative;
   padding: 4px 0 0 4px;
   display: block;
@@ -599,6 +601,10 @@ span.spinner.hor_centered {
   height: 100%;
   color: #0f0f0f;
 }
+#conversejs #toggle-minimized-chats .unread-message-count {
+  right: 5px;
+  bottom: 5px;
+}
 #conversejs .chat-head {
   color: #ffffff;
   font-size: 100%;
@@ -838,10 +844,6 @@ dl.add-converse-contact {
   background-color: #2D617A;
   padding: 3px 0 0 0;
 }
-#conversejs .toggle-minimized-chats .unread-message-count {
-  right: 5px;
-  bottom: 5px;
-}
 #conversejs .unread-message-count,
 #conversejs .chat-head-message-count {
   font-weight: bold;
@@ -1054,11 +1056,6 @@ dl.add-converse-contact {
   margin-right: 15px;
   display: block;
 }
-#conversejs #trimmed-chatboxes {
-  width: 130px;
-  padding: 0;
-  display: none;
-}
 #conversejs .chatbox {
   width: 200px;
 }
@@ -1377,6 +1374,7 @@ input.custom-xmpp-status {
 #conversejs .set-xmpp-status .dropdown dd ul {
   z-index: 22;
 }
+#conversejs .minimized-chats-flyout,
 #conversejs .box-flyout {
   border-radius: 4px;
   bottom: 6px;
@@ -1385,11 +1383,24 @@ input.custom-xmpp-status {
   height: 324px;
   position: absolute;
 }
-#conversejs .box-flyout.minimized {
+#conversejs .minimized-chats-flyout {
+  border-radius: 4px;
+  bottom: 25px;
+  box-shadow: 1px 3px 5px 3px rgba(0, 0, 0, 0.4);
+  display: block;
+  position: absolute;
+  height: auto;
+  width: 130px;
+}
+#conversejs .minimized-chats-flyout.minimized {
   height: auto;
 }
-#conversejs .box-flyout.minimized .chat-head {
+#conversejs .minimized-chats-flyout .chat-head-chatroom,
+#conversejs .minimized-chats-flyout .chat-head {
   border-radius: 4px;
+  width: 130px;
+  height: 25px;
+  margin-bottom: 1px;
 }
 #conversejs .chatbox .box-flyout {
   width: 200px;

+ 32 - 21
less/converse.less

@@ -588,7 +588,7 @@ span.spinner.hor_centered {
     text-align: center;
 }
 
-#conversejs #trimmed-chatboxes .box-flyout {
+#conversejs #minimized-chats .box-flyout {
     position: absolute;
     display: block;
     height: auto;
@@ -596,7 +596,7 @@ span.spinner.hor_centered {
     margin-left: 0;
 }
 
-#conversejs #trimmed-chatboxes .box-flyout .chat-head {
+#conversejs #minimized-chats .box-flyout .chat-head {
     font-size: 100%;
     border-radius: 4px;
     padding: 3px 0 0 5px;
@@ -606,11 +606,7 @@ span.spinner.hor_centered {
     width: 130px;
 }
 
-#conversejs #trimmed-chatboxes .chat-head-chatroom {
-    width: 100px;
-}
-
-#conversejs #trimmed-chatboxes,
+#conversejs #minimized-chats,
 #conversejs .toggle-controlbox {
     float: right;
     font-size: 90%;
@@ -624,7 +620,13 @@ span.spinner.hor_centered {
     height: 100%;
 }
 
-#conversejs .toggle-minimized-chats {
+#conversejs #minimized-chats {
+    width: 130px;
+    padding: 0;
+    display: none;
+}
+
+#conversejs #toggle-minimized-chats {
     position: relative;
     padding: 4px 0 0 4px;
     display: block;
@@ -633,6 +635,11 @@ span.spinner.hor_centered {
     color: #0f0f0f;
 }
 
+#conversejs #toggle-minimized-chats .unread-message-count {
+    right: 5px;
+    bottom: 5px;
+}
+
 #conversejs .chat-head {
     color: #ffffff;
     font-size: 100%;
@@ -917,11 +924,6 @@ dl.add-converse-contact {
     padding: 3px 0 0 0;
 }
 
-#conversejs .toggle-minimized-chats .unread-message-count {
-    right: 5px;
-    bottom: 5px;
-}
-
 #conversejs .unread-message-count,
 #conversejs .chat-head-message-count {
     font-weight: bold;
@@ -1166,12 +1168,6 @@ dl.add-converse-contact {
     display: block;
 }
 
-#conversejs #trimmed-chatboxes {
-    width: 130px;
-    padding: 0;
-    display: none;
-}
-
 #conversejs .chatbox {
     width: 200px;
 }
@@ -1551,6 +1547,7 @@ input.custom-xmpp-status {
     z-index: 22;
 }
 
+#conversejs .minimized-chats-flyout,
 #conversejs .box-flyout {
     border-radius: 4px;
     bottom: 6px;
@@ -1560,12 +1557,26 @@ input.custom-xmpp-status {
     position: absolute;
 }
 
-#conversejs .box-flyout.minimized {
+#conversejs .minimized-chats-flyout {
+    border-radius: 4px;
+    bottom: 25px;
+    box-shadow: 1px 3px 5px 3px rgba(0,0,0,0.4);
+    display: block;
+    position: absolute;
+    height: auto;
+    width: 130px;
+}
+
+#conversejs .minimized-chats-flyout.minimized {
     height: auto;
 }
 
-#conversejs .box-flyout.minimized .chat-head {
+#conversejs .minimized-chats-flyout .chat-head-chatroom,
+#conversejs .minimized-chats-flyout .chat-head {
     border-radius: 4px;
+    width: 130px;
+    height: 25px;
+    margin-bottom: 1px;
 }
 
 #conversejs .chatbox .box-flyout {

+ 4 - 3
mockup/index.html

@@ -373,11 +373,12 @@
         </div>
     </div>
 
-    <div id="trimmed-chatboxes">
-        <a class="toggle-minimized-chats" href="#">
+    <div id="minimized-chats">
+        <a id="toggle-minimized-chats" href="#">
             <span class="conn-feedback">Minimized</span> <span id="online-count">(0)</span>
+            <span class="unread-message-count" href="#" style="display:block">322</span>
         </a>
-        <div class="box-flyout minimized-chats">
+        <div class="minimized-chats-flyout">
             <div class="chat-head chat-head-chatroom">
                 <a class="close-chatbox-button icon-close"></a>
                 <a class="chat-head-message-count" href="#" style="display:block">3</a>

+ 5 - 5
mockup/minimal.html

@@ -45,12 +45,12 @@
     </div>
 
 
-    <div id="trimmed-chatboxes">
-        <a class="toggle-minimized-chats" href="#">
-            <span class="conn-feedback">Minimized</span> <span id="online-count">(0)</span>
+    <div id="minimized-chats" style="display: block">
+        <a id="toggle-minimized-chats" href="#">
+            <span>Minimized <span id="minimized-count">(0)</span>
             <span class="unread-message-count" href="#" style="display:block">322</span>
         </a>
-        <div class="box-flyout minimized-chats">
+        <div class="minimized-chats-flyout">
             <div class="chat-head chat-head-chatroom">
                 <a class="close-chatbox-button icon-close"></a>
                 <a class="chat-head-message-count" href="#" style="display:block">3</a>
@@ -194,7 +194,7 @@ $(document).ready(function () {
         });
 
         $('.toggle-minimized-chats').click(function(ev) {
-            $('.minimized-chats').toggle();
+            $('.minimized-chats-flyout').toggle();
         });
 
         // Clickable Dropdown

+ 32 - 30
src/templates.js

@@ -8,6 +8,7 @@ define("converse-templates", [
     "tpl!src/templates/chatbox",
     "tpl!src/templates/chatroom",
     "tpl!src/templates/chatrooms_tab",
+    "tpl!src/templates/chats_panel",
     "tpl!src/templates/choose_status",
     "tpl!src/templates/contacts",
     "tpl!src/templates/contacts_panel",
@@ -36,7 +37,7 @@ define("converse-templates", [
     "tpl!src/templates/status_option",
     "tpl!src/templates/toolbar",
     "tpl!src/templates/trimmed_chat",
-    "tpl!src/templates/trimmed_chats"
+    "tpl!src/templates/toggle_chats"
 ], function () {
     return {
         action:                 arguments[0],
@@ -48,34 +49,35 @@ define("converse-templates", [
         chatbox:                arguments[6],
         chatroom:               arguments[7],
         chatrooms_tab:          arguments[8],
-        choose_status:          arguments[9],
-        contacts:               arguments[10],
-        contacts_panel:         arguments[11],
-        contacts_tab:           arguments[12],
-        controlbox:             arguments[13],
-        controlbox_toggle:      arguments[14],
-        field:                  arguments[15],
-        form_checkbox:          arguments[16],
-        form_input:             arguments[17],
-        form_select:            arguments[18],
-        info:                   arguments[19],
-        login_panel:            arguments[20],
-        login_tab:              arguments[21],
-        message:                arguments[22],
-        new_day:                arguments[23],
-        occupant:               arguments[24],
-        pending_contact:        arguments[25],
-        pending_contacts:       arguments[26],
-        requesting_contact:     arguments[27],
-        requesting_contacts:    arguments[28],
-        room_description:       arguments[29],
-        room_item:              arguments[30],
-        room_panel:             arguments[31],
-        roster_item:            arguments[32],
-        select_option:          arguments[33],
-        status_option:          arguments[34],
-        toolbar:                arguments[35],
-        trimmed_chat:           arguments[36],
-        trimmed_chats:          arguments[37]
+        chats_panel:            arguments[9],
+        choose_status:          arguments[10],
+        contacts:               arguments[11],
+        contacts_panel:         arguments[12],
+        contacts_tab:           arguments[13],
+        controlbox:             arguments[14],
+        controlbox_toggle:      arguments[15],
+        field:                  arguments[16],
+        form_checkbox:          arguments[17],
+        form_input:             arguments[18],
+        form_select:            arguments[19],
+        info:                   arguments[20],
+        login_panel:            arguments[21],
+        login_tab:              arguments[22],
+        message:                arguments[23],
+        new_day:                arguments[24],
+        occupant:               arguments[25],
+        pending_contact:        arguments[26],
+        pending_contacts:       arguments[27],
+        requesting_contact:     arguments[28],
+        requesting_contacts:    arguments[29],
+        room_description:       arguments[30],
+        room_item:              arguments[31],
+        room_panel:             arguments[32],
+        roster_item:            arguments[33],
+        select_option:          arguments[34],
+        status_option:          arguments[35],
+        toolbar:                arguments[36],
+        trimmed_chat:           arguments[37],
+        toggle_chats:           arguments[38]
     };
 });

+ 7 - 0
src/templates/chats_panel.html

@@ -0,0 +1,7 @@
+<div id="minimized-chats">
+    <a id="toggle-minimized-chats" href="#">
+        <span>Minimized <span id="minimized-count">(0)</span>
+        <span class="unread-message-count" href="#">0</span>
+    </a>
+    <div class="minimized-chats-flyout"></div>
+</div>

+ 2 - 0
src/templates/toggle_chats.html

@@ -0,0 +1,2 @@
+{{Minimized}} <span id="minimized-count">({{num_minimized}})</span>
+<span class="unread-message-count" href="#">0</span>

+ 2 - 2
src/templates/trimmed_chat.html

@@ -1,7 +1,7 @@
 <a class="close-chatbox-button icon-close"></a>
+<a class="chat-head-message-count" href="#">0</a>
 <div class="chat-title">
-    <a href="#" class="restore-chat">
-        <div class="chat-head-message-count">0</div>
+    <a href="#" class="restore-chat" title="{{tooltip}}">
         {{ title }}
     </a>
 </div>

+ 0 - 1
src/templates/trimmed_chats.html

@@ -1 +0,0 @@
-<div id="trimmed-chatboxes"><div class="box-flyout"></div></div>