Browse Source

Add tests for contact removal via modal

JC Brand 7 years ago
parent
commit
09db3eddb0

+ 6 - 6
css/converse.css

@@ -7055,9 +7055,6 @@ body.reset {
     opacity: 0; }
     opacity: 0; }
   100% {
   100% {
     opacity: 1; } }
     opacity: 1; } }
-  #conversejs .fade {
-    opacity: 0;
-    transition: opacity 0.20s linear; }
   #conversejs .fade-in {
   #conversejs .fade-in {
     opacity: 0;
     opacity: 0;
     /* make things invisible upon start */
     /* make things invisible upon start */
@@ -7273,7 +7270,7 @@ body.reset {
   border-radius: 25%;
   border-radius: 25%;
   border: none;
   border: none;
   cursor: pointer;
   cursor: pointer;
-  font-size: 16px;
+  font-size: 14px;
   margin: 0 0.2em;
   margin: 0 0.2em;
   padding: 0 0 0 0.5em;
   padding: 0 0 0 0.5em;
   text-decoration: none; }
   text-decoration: none; }
@@ -7299,8 +7296,8 @@ body.reset {
     min-height: 1px;
     min-height: 1px;
     padding-right: 15px;
     padding-right: 15px;
     padding-left: 15px;
     padding-left: 15px;
-    flex: 0 0 25%;
-    max-width: 25%;
+    flex: 0 0 33.3333333333%;
+    max-width: 33.3333333333%;
     padding: 0; }
     padding: 0; }
   #conversejs .chat-head .user-custom-message {
   #conversejs .chat-head .user-custom-message {
     color: white;
     color: white;
@@ -7585,6 +7582,9 @@ body.reset {
       top: 0;
       top: 0;
       left: 0; }
       left: 0; }
 
 
+#conversejs.converse-fullscreen .chatbox-btn {
+  font-size: 16px; }
+
 @media screen and (max-width: 767px) {
 @media screen and (max-width: 767px) {
   #conversejs:not(.converse-embedded) > .row {
   #conversejs:not(.converse-embedded) > .row {
     flex-direction: row-reverse; }
     flex-direction: row-reverse; }

+ 6 - 6
css/inverse.css

@@ -7055,9 +7055,6 @@ body.reset {
     opacity: 0; }
     opacity: 0; }
   100% {
   100% {
     opacity: 1; } }
     opacity: 1; } }
-  #conversejs .fade {
-    opacity: 0;
-    transition: opacity 0.20s linear; }
   #conversejs .fade-in {
   #conversejs .fade-in {
     opacity: 0;
     opacity: 0;
     /* make things invisible upon start */
     /* make things invisible upon start */
@@ -7324,7 +7321,7 @@ body {
   border-radius: 25%;
   border-radius: 25%;
   border: none;
   border: none;
   cursor: pointer;
   cursor: pointer;
-  font-size: 16px;
+  font-size: 14px;
   margin: 0 0.2em;
   margin: 0 0.2em;
   padding: 0 0 0 0.5em;
   padding: 0 0 0 0.5em;
   text-decoration: none; }
   text-decoration: none; }
@@ -7350,8 +7347,8 @@ body {
     min-height: 1px;
     min-height: 1px;
     padding-right: 15px;
     padding-right: 15px;
     padding-left: 15px;
     padding-left: 15px;
-    flex: 0 0 25%;
-    max-width: 25%;
+    flex: 0 0 33.3333333333%;
+    max-width: 33.3333333333%;
     padding: 0; }
     padding: 0; }
   #conversejs .chat-head .user-custom-message {
   #conversejs .chat-head .user-custom-message {
     color: white;
     color: white;
@@ -7636,6 +7633,9 @@ body {
       top: 0;
       top: 0;
       left: 0; }
       left: 0; }
 
 
+#conversejs.converse-fullscreen .chatbox-btn {
+  font-size: 16px; }
+
 @media screen and (max-width: 767px) {
 @media screen and (max-width: 767px) {
   #conversejs:not(.converse-embedded) > .row {
   #conversejs:not(.converse-embedded) > .row {
     flex-direction: row-reverse; }
     flex-direction: row-reverse; }

+ 8 - 2
sass/_chatbox.scss

@@ -23,7 +23,7 @@
         border-radius: 25%;
         border-radius: 25%;
         border: none;
         border: none;
         cursor: pointer;
         cursor: pointer;
-        font-size: $box-close-font-size;
+        font-size: $chatbox-button-size;
         margin: 0 0.2em;
         margin: 0 0.2em;
         padding: 0 0 0 0.5em;
         padding: 0 0 0 0.5em;
         text-decoration: none;
         text-decoration: none;
@@ -54,7 +54,7 @@
         .chatbox-buttons {
         .chatbox-buttons {
             flex-direction: row-reverse;
             flex-direction: row-reverse;
             @include make-col-ready();
             @include make-col-ready();
-            @include make-col(3);
+            @include make-col(4);
             padding: 0;
             padding: 0;
         }
         }
 
 
@@ -431,6 +431,12 @@
     }
     }
 }
 }
 
 
+#conversejs.converse-fullscreen  {
+    .chatbox-btn {
+        font-size: $fullpage-chatbox-button-size;
+    }
+}
+
 @media screen and (max-width: 767px) {
 @media screen and (max-width: 767px) {
     #conversejs:not(.converse-embedded)  {
     #conversejs:not(.converse-embedded)  {
         > .row {
         > .row {

+ 0 - 5
sass/_core.scss

@@ -287,11 +287,6 @@ body.reset {
         100% { opacity: 1 }
         100% { opacity: 1 }
     }
     }
 
 
-    .fade {
-        opacity: 0;
-        transition: opacity 0.20s linear;
-    }
-
     .fade-in {
     .fade-in {
         @include fade-in;
         @include fade-in;
     }
     }

+ 3 - 1
sass/_variables.scss

@@ -116,4 +116,6 @@ $box-close-button-padding-top: 4px !default;
 $box-close-button-padding-bottom: 4px !default;
 $box-close-button-padding-bottom: 4px !default;
 $box-close-button-padding-left: 4px !default;
 $box-close-button-padding-left: 4px !default;
 $box-close-button-padding-right: 4px !default;
 $box-close-button-padding-right: 4px !default;
-$box-close-font-size: 16px !default;
+
+$chatbox-button-size: 14px !default;
+$fullpage-chatbox-button-size: 16px !default;

+ 21 - 2
src/converse-chatboxes.js

@@ -239,9 +239,8 @@
                         this.vcard = _converse.vcards.create({'jid': this.get('jid')});
                         this.vcard = _converse.vcards.create({'jid': this.get('jid')});
                     }
                     }
                     _converse.api.waitUntil('rosterContactsFetched').then(() => {
                     _converse.api.waitUntil('rosterContactsFetched').then(() => {
-                        this.contact = _converse.roster.findWhere({'jid': this.get('jid')});
+                        this.addRelatedContact(_converse.roster.findWhere({'jid': this.get('jid')}));
                     });
                     });
-
                     this.messages = new _converse.Messages();
                     this.messages = new _converse.Messages();
                     this.messages.browserStorage = new Backbone.BrowserStorage[_converse.message_storage](
                     this.messages.browserStorage = new Backbone.BrowserStorage[_converse.message_storage](
                         b64_sha1(`converse.messages${this.get('jid')}${_converse.bare_jid}`));
                         b64_sha1(`converse.messages${this.get('jid')}${_converse.bare_jid}`));
@@ -264,6 +263,13 @@
                     });
                     });
                 },
                 },
 
 
+                addRelatedContact (contact) {
+                    if (!_.isUndefined(contact)) {
+                        this.contact = contact;
+                        this.trigger('contactAdded', contact);
+                    }
+                },
+
                 getDisplayName () {
                 getDisplayName () {
                     return this.vcard.get('fullname') || this.get('jid');
                     return this.vcard.get('fullname') || this.get('jid');
                 },
                 },
@@ -774,9 +780,22 @@
                 _converse.emit('privateChatsAutoJoined');
                 _converse.emit('privateChatsAutoJoined');
             }
             }
 
 
+
             /************************ BEGIN Event Handlers ************************/
             /************************ BEGIN Event Handlers ************************/
             _converse.on('chatBoxesFetched', autoJoinChats);
             _converse.on('chatBoxesFetched', autoJoinChats);
 
 
+
+            _converse.api.waitUntil('rosterContactsFetched').then(() => {
+                _converse.roster.on('add', (contact) => {
+                    /* When a new contact is added, check if we already have a
+                     * chatbox open for it, and if so attach it to the chatbox.
+                     */
+                    const chatbox = _converse.chatboxes.findWhere({'jid': contact.get('jid')});
+                    chatbox.addRelatedContact(contact);
+                });
+            });
+
+
             _converse.on('addClientFeatures', () => {
             _converse.on('addClientFeatures', () => {
                 _converse.api.disco.addFeature(Strophe.NS.HTTPUPLOAD);
                 _converse.api.disco.addFeature(Strophe.NS.HTTPUPLOAD);
                 _converse.api.disco.addFeature(Strophe.NS.OUTOFBAND);
                 _converse.api.disco.addFeature(Strophe.NS.OUTOFBAND);

+ 26 - 6
src/converse-chatview.js

@@ -240,40 +240,60 @@
                     'click button.remove-contact': 'removeContact'
                     'click button.remove-contact': 'removeContact'
                 },
                 },
 
 
+                initialize () {
+                    _converse.BootstrapModal.prototype.initialize.apply(this, arguments);
+                    this.model.on('contactAdded', this.registerContactEventHandlers, this);
+                    this.registerContactEventHandlers();
+                },
+
                 toHTML () {
                 toHTML () {
                     return tpl_user_details_modal(_.extend(
                     return tpl_user_details_modal(_.extend(
                         this.model.toJSON(),
                         this.model.toJSON(),
                         this.model.vcard.toJSON(), {
                         this.model.vcard.toJSON(), {
+                        'allow_contact_removal': _converse.allow_contact_removal,
                         'alt_profile_image': __("The User's Profile Image"),
                         'alt_profile_image': __("The User's Profile Image"),
                         'display_name': this.model.getDisplayName(),
                         'display_name': this.model.getDisplayName(),
+                        'is_roster_contact': !_.isUndefined(this.model.contact),
                         'label_close': __('Close'),
                         'label_close': __('Close'),
                         'label_email': __('Email'),
                         'label_email': __('Email'),
                         'label_fullname': __('Full Name'),
                         'label_fullname': __('Full Name'),
+                        'label_jid': __('Jabber ID'),
                         'label_nickname': __('Nickname'),
                         'label_nickname': __('Nickname'),
-                        'label_role': __('Role'),
                         'label_remove': __('Remove as contact'),
                         'label_remove': __('Remove as contact'),
-                        'label_url': __('URL'),
-                        'allow_contact_removal': _converse.allow_contact_removal,
-                        'is_roster_contact': !_.isUndefined(this.model.contact)
+                        'label_role': __('Role'),
+                        'label_url': __('URL')
                     }));
                     }));
                 },
                 },
 
 
+                registerContactEventHandlers () {
+                    if (!_.isUndefined(this.model.contact)) {
+                        this.model.contact.on('change', this.render, this);
+                        this.model.contact.vcard.on('change', this.render, this);
+                        this.model.contact.on('destroy', () => {
+                            delete this.model.contact;
+                            this.render();
+                        });
+                    }
+                },
+
                 removeContact (ev) {
                 removeContact (ev) {
                     if (ev && ev.preventDefault) { ev.preventDefault(); }
                     if (ev && ev.preventDefault) { ev.preventDefault(); }
                     if (!_converse.allow_contact_removal) { return; }
                     if (!_converse.allow_contact_removal) { return; }
                     const result = confirm(__("Are you sure you want to remove this contact?"));
                     const result = confirm(__("Are you sure you want to remove this contact?"));
                     if (result === true) {
                     if (result === true) {
+                        this.modal.hide();
                         this.model.contact.removeFromRoster(
                         this.model.contact.removeFromRoster(
                             (iq) => {
                             (iq) => {
                                 this.model.contact.destroy();
                                 this.model.contact.destroy();
-                                delete this.model.contact;
                             },
                             },
                             (err) => {
                             (err) => {
                                 _converse.log(err, Strophe.LogLevel.ERROR);
                                 _converse.log(err, Strophe.LogLevel.ERROR);
                                 _converse.api.alert.show(
                                 _converse.api.alert.show(
                                     Strophe.LogLevel.ERROR,
                                     Strophe.LogLevel.ERROR,
                                     __('Error'),
                                     __('Error'),
-                                    [__('Sorry, there was an error while trying to remove %1$s as a contact.', name)]
+                                    [__('Sorry, there was an error while trying to remove %1$s as a contact.',
+                                        this.model.contact.getDisplayName())
+                                    ]
                                 )
                                 )
                             }
                             }
                         );
                         );

+ 27 - 27
src/converse-roster.js

@@ -401,15 +401,15 @@
 
 
                 addAndSubscribe (jid, name, groups, message, attributes) {
                 addAndSubscribe (jid, name, groups, message, attributes) {
                     /* Add a roster contact and then once we have confirmation from
                     /* Add a roster contact and then once we have confirmation from
-                    * the XMPP server we subscribe to that contact's presence updates.
-                    *  Parameters:
-                    *    (String) jid - The Jabber ID of the user being added and subscribed to.
-                    *    (String) name - The name of that user
-                    *    (Array of Strings) groups - Any roster groups the user might belong to
-                    *    (String) message - An optional message to explain the
-                    *      reason for the subscription request.
-                    *    (Object) attributes - Any additional attributes to be stored on the user's model.
-                    */
+                     * the XMPP server we subscribe to that contact's presence updates.
+                     *  Parameters:
+                     *    (String) jid - The Jabber ID of the user being added and subscribed to.
+                     *    (String) name - The name of that user
+                     *    (Array of Strings) groups - Any roster groups the user might belong to
+                     *    (String) message - An optional message to explain the
+                     *      reason for the subscription request.
+                     *    (Object) attributes - Any additional attributes to be stored on the user's model.
+                     */
                     const handler = (contact) => {
                     const handler = (contact) => {
                         if (contact instanceof _converse.RosterContact) {
                         if (contact instanceof _converse.RosterContact) {
                             contact.subscribe(message);
                             contact.subscribe(message);
@@ -420,14 +420,14 @@
 
 
                 sendContactAddIQ (jid, name, groups, callback, errback) {
                 sendContactAddIQ (jid, name, groups, callback, errback) {
                     /*  Send an IQ stanza to the XMPP server to add a new roster contact.
                     /*  Send an IQ stanza to the XMPP server to add a new roster contact.
-                    *
-                    *  Parameters:
-                    *    (String) jid - The Jabber ID of the user being added
-                    *    (String) name - The name of that user
-                    *    (Array of Strings) groups - Any roster groups the user might belong to
-                    *    (Function) callback - A function to call once the IQ is returned
-                    *    (Function) errback - A function to call if an error occured
-                    */
+                     *
+                     *  Parameters:
+                     *    (String) jid - The Jabber ID of the user being added
+                     *    (String) name - The name of that user
+                     *    (Array of Strings) groups - Any roster groups the user might belong to
+                     *    (Function) callback - A function to call once the IQ is returned
+                     *    (Function) errback - A function to call if an error occured
+                     */
                     name = _.isEmpty(name)? jid: name;
                     name = _.isEmpty(name)? jid: name;
                     const iq = $iq({type: 'set'})
                     const iq = $iq({type: 'set'})
                         .c('query', {xmlns: Strophe.NS.ROSTER})
                         .c('query', {xmlns: Strophe.NS.ROSTER})
@@ -438,16 +438,16 @@
 
 
                 addContactToRoster (jid, name, groups, attributes) {
                 addContactToRoster (jid, name, groups, attributes) {
                     /* Adds a RosterContact instance to _converse.roster and
                     /* Adds a RosterContact instance to _converse.roster and
-                    * registers the contact on the XMPP server.
-                    * Returns a promise which is resolved once the XMPP server has
-                    * responded.
-                    *
-                    *  Parameters:
-                    *    (String) jid - The Jabber ID of the user being added and subscribed to.
-                    *    (String) name - The name of that user
-                    *    (Array of Strings) groups - Any roster groups the user might belong to
-                    *    (Object) attributes - Any additional attributes to be stored on the user's model.
-                    */
+                     * registers the contact on the XMPP server.
+                     * Returns a promise which is resolved once the XMPP server has
+                     * responded.
+                     *
+                     *  Parameters:
+                     *    (String) jid - The Jabber ID of the user being added and subscribed to.
+                     *    (String) name - The name of that user
+                     *    (Array of Strings) groups - Any roster groups the user might belong to
+                     *    (Object) attributes - Any additional attributes to be stored on the user's model.
+                     */
                     return new Promise((resolve, reject) => {
                     return new Promise((resolve, reject) => {
                         groups = groups || [];
                         groups = groups || [];
                         this.sendContactAddIQ(jid, name, groups,
                         this.sendContactAddIQ(jid, name, groups,

+ 4 - 3
src/templates/user_details_modal.html

@@ -7,13 +7,14 @@
             </div>
             </div>
             <div class="modal-body">
             <div class="modal-body">
                 {[ if (o.image) { ]}
                 {[ if (o.image) { ]}
-                    <img alt="{{{o.alt_profile_image}}}"
-                        class="img-thumbnail avatar align-self-center"
-                        height="100" width="100" src="data:{{{o.image_type}}};base64,{{{o.image}}}"/>
+                <img alt="{{{o.alt_profile_image}}}"
+                    class="img-thumbnail avatar align-self-center mb-3"
+                    height="100" width="100" src="data:{{{o.image_type}}};base64,{{{o.image}}}"/>
                 {[ } ]}
                 {[ } ]}
                 {[ if (o.fullname) { ]}
                 {[ if (o.fullname) { ]}
                 <p><label>{{{o.label_fullname}}}:</label>&nbsp;{{{o.fullname}}}</p>
                 <p><label>{{{o.label_fullname}}}:</label>&nbsp;{{{o.fullname}}}</p>
                 {[ } ]}
                 {[ } ]}
+                <p><label>{{{o.label_jid}}}:</label>&nbsp;{{{o.jid}}}</p>
                 {[ if (o.nickname) { ]}
                 {[ if (o.nickname) { ]}
                 <p><label>{{{o.label_nickname}}}:</label>&nbsp;{{{o.nickname}}}</p>
                 <p><label>{{{o.label_nickname}}}:</label>&nbsp;{{{o.nickname}}}</p>
                 {[ } ]}
                 {[ } ]}

+ 1 - 0
tests/runner.js

@@ -51,6 +51,7 @@ var specs = [
     "spec/controlbox",
     "spec/controlbox",
     "spec/roster",
     "spec/roster",
     "spec/chatbox",
     "spec/chatbox",
+    "spec/user-details-modal",
     "spec/messages",
     "spec/messages",
     "spec/chatroom",
     "spec/chatroom",
     "spec/minchats",
     "spec/minchats",