فهرست منبع

Fixes #820. Inconsistency in displaying room features

JC Brand 8 سال پیش
والد
کامیت
6e94e11dcc
3فایلهای تغییر یافته به همراه107 افزوده شده و 17 حذف شده
  1. 1 0
      docs/CHANGES.md
  2. 50 0
      spec/chatroom.js
  3. 56 17
      src/converse-muc.js

+ 1 - 0
docs/CHANGES.md

@@ -8,6 +8,7 @@
 - #675 Time format made configurable. [smitbose]
 - #806 The `_converse.listen` API event listeners aren't triggered. [jcbrand]
 - #807 Error: Plugin "converse-dragresize" tried to override HeadlinesBoxView but it's not found. [jcbrand]
+- #820 Inconsistency in displaying room features. [jcbrand]
 
 ## 3.0.0 (2017-03-05)
 

+ 50 - 0
spec/chatroom.js

@@ -1330,6 +1330,56 @@
                 expect(view.model.get('nonanonymous')).toBe(true);
             }));
 
+            it("updates the shown features when the room configuration has changed", mock.initConverse(function (_converse) {
+                var sent_IQ, IQ_id;
+                var sendIQ = _converse.connection.sendIQ;
+                test_utils.openAndEnterChatRoom(_converse, 'room', 'conference.example.org', 'dummy');
+                var view = _converse.chatboxviews.get('room@conference.example.org');
+                view.model.set({
+                    'passwordprotected': false,
+                    'unsecured': true,
+                    'hidden': false,
+                    'public': true,
+                    'membersonly': false,
+                    'open': true,
+                    'persistent': false,
+                    'temporary': true,
+                    'nonanonymous': true,
+                    'semianonymous': false,
+                    'moderated': false,
+                    'unmoderated': true
+                });
+                expect(view.model.get('persistent')).toBe(false);
+                expect(view.model.get('temporary')).toBe(true);
+                view.model.set({'persistent': true});
+                expect(view.model.get('persistent')).toBe(true);
+                expect(view.model.get('temporary')).toBe(false);
+
+                expect(view.model.get('unsecured')).toBe(true);
+                expect(view.model.get('passwordprotected')).toBe(false);
+                view.model.set({'passwordprotected': true});
+                expect(view.model.get('unsecured')).toBe(false);
+                expect(view.model.get('passwordprotected')).toBe(true);
+
+                expect(view.model.get('unmoderated')).toBe(true);
+                expect(view.model.get('moderated')).toBe(false);
+                view.model.set({'moderated': true});
+                expect(view.model.get('unmoderated')).toBe(false);
+                expect(view.model.get('moderated')).toBe(true);
+
+                expect(view.model.get('nonanonymous')).toBe(true);
+                expect(view.model.get('semianonymous')).toBe(false);
+                view.model.set({'nonanonymous': false});
+                expect(view.model.get('nonanonymous')).toBe(false);
+                expect(view.model.get('semianonymous')).toBe(true);
+
+                expect(view.model.get('open')).toBe(true);
+                expect(view.model.get('membersonly')).toBe(false);
+                view.model.set({'membersonly': true});
+                expect(view.model.get('open')).toBe(false);
+                expect(view.model.get('membersonly')).toBe(true);
+            }));
+
             it("indicates when a room is no longer anonymous", mock.initConverse(function (_converse) {
                 var sent_IQ, IQ_id;
                 var sendIQ = _converse.connection.sendIQ;

+ 56 - 17
src/converse-muc.js

@@ -81,6 +81,20 @@
         'temporary', 'nonanonymous', 'semianonymous',
         'moderated', 'unmoderated', 'mam_enabled'
     ];
+    var ROOM_FEATURES_MAP = {
+        'passwordprotected': 'unsecured',
+        'unsecured': 'passwordprotected',
+        'hidden': 'public',
+        'public': 'hidden',
+        'membersonly': 'open',
+        'open': 'membersonly',
+        'persistent': 'temporary',
+        'temporary': 'persistent',
+        'nonanonymous': 'semianonymous',
+        'semianonymous': 'nonanonymous',
+        'moderated': 'unmoderated',
+        'unmoderated': 'moderated'
+    };
     var ROOMSTATUS = {
         CONNECTED: 0,
         CONNECTING: 1,
@@ -1967,25 +1981,22 @@
 
                 initialize: function () {
                     this.model.on("add", this.onOccupantAdded, this);
-
                     this.chatroomview = this.model.chatroomview;
                     this.chatroomview.model.on('change:open', this.renderInviteWidget, this);
                     this.chatroomview.model.on('change:affiliation', this.renderInviteWidget, this);
-
-                    var debouncedRenderRoomFeatures = _.debounce(this.renderRoomFeatures, 100);
-                    this.chatroomview.model.on('change:hidden', debouncedRenderRoomFeatures, this);
-                    this.chatroomview.model.on('change:mam_enabled', debouncedRenderRoomFeatures, this);
-                    this.chatroomview.model.on('change:membersonly', debouncedRenderRoomFeatures, this);
-                    this.chatroomview.model.on('change:moderated', debouncedRenderRoomFeatures, this);
-                    this.chatroomview.model.on('change:nonanonymous', debouncedRenderRoomFeatures, this);
-                    this.chatroomview.model.on('change:open', debouncedRenderRoomFeatures, this);
-                    this.chatroomview.model.on('change:passwordprotected', debouncedRenderRoomFeatures, this);
-                    this.chatroomview.model.on('change:persistent', debouncedRenderRoomFeatures, this);
-                    this.chatroomview.model.on('change:public', debouncedRenderRoomFeatures, this);
-                    this.chatroomview.model.on('change:semianonymous', debouncedRenderRoomFeatures, this);
-                    this.chatroomview.model.on('change:temporary', debouncedRenderRoomFeatures, this);
-                    this.chatroomview.model.on('change:unmoderated', debouncedRenderRoomFeatures, this);
-                    this.chatroomview.model.on('change:unsecured', debouncedRenderRoomFeatures, this);
+                    this.chatroomview.model.on('change:hidden', this.onFeatureChanged, this);
+                    this.chatroomview.model.on('change:mam_enabled', this.onFeatureChanged, this);
+                    this.chatroomview.model.on('change:membersonly', this.onFeatureChanged, this);
+                    this.chatroomview.model.on('change:moderated', this.onFeatureChanged, this);
+                    this.chatroomview.model.on('change:nonanonymous', this.onFeatureChanged, this);
+                    this.chatroomview.model.on('change:open', this.onFeatureChanged, this);
+                    this.chatroomview.model.on('change:passwordprotected', this.onFeatureChanged, this);
+                    this.chatroomview.model.on('change:persistent', this.onFeatureChanged, this);
+                    this.chatroomview.model.on('change:public', this.onFeatureChanged, this);
+                    this.chatroomview.model.on('change:semianonymous', this.onFeatureChanged, this);
+                    this.chatroomview.model.on('change:temporary', this.onFeatureChanged, this);
+                    this.chatroomview.model.on('change:unmoderated', this.onFeatureChanged, this);
+                    this.chatroomview.model.on('change:unsecured', this.onFeatureChanged, this);
                 },
 
                 render: function () {
@@ -1997,7 +2008,9 @@
                             }))
                     );
                     if (_converse.allow_muc_invitations) {
-                        _converse.api.waitUntil('rosterContactsFetched').then(this.renderInviteWidget.bind(this));
+                        _converse.api.waitUntil('rosterContactsFetched').then(
+                            this.renderInviteWidget.bind(this)
+                        );
                     }
                     return this.renderRoomFeatures();
                 },
@@ -2061,6 +2074,32 @@
                     return this;
                 },
 
+                onFeatureChanged: function (model) {
+                    /* When a feature has been changed, it's logical opposite
+                     * must be set to the opposite value.
+                     *
+                     * So for example, if "temporary" was set to "false", then
+                     * "persistent" will be set to "true" in this method.
+                     *
+                     * Additionally a debounced render method is called to make
+                     * sure the features widget gets updated.
+                     */
+                    if (_.isUndefined(this.debouncedRenderRoomFeatures)) {
+                        this.debouncedRenderRoomFeatures = _.debounce(
+                            this.renderRoomFeatures, 100, {'leading': false}
+                        );
+                    }
+                    var changed_features = {}
+                    _.each(_.keys(model.changed), function (k) {
+                        if (!_.isNil(ROOM_FEATURES_MAP[k])) {
+                            changed_features[ROOM_FEATURES_MAP[k]] = !model.changed[k];
+                        }
+                    });
+                    this.chatroomview.model.save(changed_features, {'silent': true});
+                    this.debouncedRenderRoomFeatures();
+                },
+
+
                 setOccupantsHeight: function () {
                     var el = this.el.querySelector('.chatroom-features');
                     this.el.querySelector('.occupant-list').style.cssText =