changeset 584:0a06cf833f5a

browser_side: various improvements, especially for MUC
author souliane <souliane@mailoo.org>
date Wed, 22 Oct 2014 19:03:55 +0200
parents 4c6c61696ba0
children bade589dbd5a
files setup.py src/browser/libervia_main.py src/browser/sat_browser/base_panels.py src/browser/sat_browser/jid.py src/browser/sat_browser/panels.py src/browser/sat_browser/plugin_sec_otr.py
diffstat 6 files changed, 93 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- a/setup.py	Wed Oct 22 14:19:25 2014 +0200
+++ b/setup.py	Wed Oct 22 19:03:55 2014 +0200
@@ -119,7 +119,7 @@
         os.symlink(os.path.dirname(sat.__file__), os.path.join(tmp_dir,"sat")) # FIXME: only work on unixes
         os.symlink(os.path.dirname(sat_frontends.__file__), os.path.join(tmp_dir,"sat_frontends")) # FIXME: only work on unixes
         os.symlink(os.path.dirname(libervia.__file__), os.path.join(tmp_dir,"libervia")) # FIXME: only work on unixes
-        result = subprocess.call(['pyjsbuild', 'libervia_main', '--no-compile-inplace', '-I', tmp_dir, '-o', self.pyjamas_output_dir])
+        result = subprocess.call(['pyjsbuild', 'libervia_main', '-d', '--no-compile-inplace', '-I', tmp_dir, '-o', self.pyjamas_output_dir])
         shutil.rmtree(tmp_dir)
         os.chdir(cwd)
         return result
--- a/src/browser/libervia_main.py	Wed Oct 22 14:19:25 2014 +0200
+++ b/src/browser/libervia_main.py	Wed Oct 22 19:03:55 2014 +0200
@@ -722,6 +722,44 @@
             lib_wid.refresh()
         return lib_wid
 
+    def getRoomWidget(self, target):
+        """Get the MUC widget for the given target.
+
+        @param target (jid.JID): BARE jid of the MUC
+        @return: panels.ChatPanel instance or None
+        """
+        entity = {'item': target, 'type_': 'group'}
+        if target.full() in self.room_list or target in self.room_list:  # as JID is a string-based class, we don't know what will please Pyjamas...
+            return self.getLiberviaWidget(panels.ChatPanel, entity, ignoreOtherTabs=False)
+        return None
+
+    def getOrCreateRoomWidget(self, target):
+        """Get the MUC widget for the given target, create it if necessary.
+
+        @param target (jid.JID): BARE jid of the MUC
+        @return: panels.ChatPanel instance
+        """
+        lib_wid = self.getRoomWidget(target)
+        if lib_wid:
+            return lib_wid
+
+        # XXX: target.node.startwith(...) raises an error "startswith is not a function"
+        # This happens when node a is property defined in the JID class
+        # FIXME: pyjamas doesn't handle the properties well
+        node = target.node
+
+        # XXX: it's not really beautiful, but it works :)
+        if node.startswith('sat_tarot_'):
+            tab_name = "Tarot"
+        elif node.startswith('sat_radiocol_'):
+            tab_name = "Radio collective"
+        else:
+            tab_name = target.node
+
+        self.room_list.append(target)
+        entity = {'item': target, 'type_': 'group'}
+        return self.getOrCreateLiberviaWidget(panels.ChatPanel, entity, new_tab=tab_name)
+
     def _newMessageCb(self, from_jid_s, msg, msg_type, to_jid_s, extra):
         from_jid = jid.JID(from_jid_s)
         to_jid = jid.JID(to_jid_s)
@@ -766,8 +804,9 @@
             if statuses:
                 self.status_panel.setStatus(statuses.values()[0])  # pylint: disable=E1103
         else:
-            if entity_jid.bare in self.room_list:
-                wid = self.getLiberviaWidget(panels.ChatPanel, {'item': entity_jid, 'type_': 'group'}, ignoreOtherTabs=False)
+            bare_jid = entity_jid.bareJID()
+            if bare_jid.full() in self.room_list or bare_jid in self.room_list:  # as JID is a string-based class, we don't know what will please Pyjamas...
+                wid = self.getRoomWidget(bare_jid)
             else:
                 wid = self.contact_panel
                 if show == 'unavailable':  # XXX: save some resources as for now we only need 'unavailable'
@@ -777,75 +816,56 @@
             if wid:
                 wid.setConnected(entity_jid.bare, entity_jid.resource, show, priority, statuses)
 
-    def _roomJoinedCb(self, room_jid, room_nicks, user_nick):
-        _target = jid.JID(room_jid)
-
-        # XXX: _target.node.startwith(...) raises an error "startswith is not a function"
-        # This happens when node a is property defined in the JID class
-        # FIXME: pyjamas doesn't handle the properties well
-        node = _target.node
-
-        if _target not in self.room_list:
-            self.room_list.append(_target)
-
-        # XXX: it's not really beautiful, but it works :)
-        if node.startswith('sat_tarot_'):
-            tab_name = "Tarot"
-        elif node.startswith('sat_radiocol_'):
-            tab_name = "Radio collective"
-        else:
-            tab_name = _target.node
-
-        chat_panel = self.getOrCreateLiberviaWidget(panels.ChatPanel, {'item': _target, 'type_': 'group'}, new_tab=tab_name)
+    def _roomJoinedCb(self, room_jid_s, room_nicks, user_nick):
+        chat_panel = self.getOrCreateRoomWidget(jid.JID(room_jid_s))
         chat_panel.setUserNick(user_nick)
         chat_panel.setPresents(room_nicks)
-        chat_panel.historyPrint()
         chat_panel.refresh()
 
-    def _roomLeftCb(self, room_jid, room_nicks, user_nick):
-        # FIXME: room_list contains jid.JID instances so why MUST we do
-        # 'remove(room_jid)' and not 'remove(jid.JID(room_jid))' ????!!
-        # This looks like a pyjamas bug --> check/report
+    def _roomLeftCb(self, room_jid_s, room_nicks, user_nick):
         try:
-            self.room_list.remove(room_jid)
+            del self.room_list[room_jid_s]
         except KeyError:
-            pass
+            try:  # as JID is a string-based class,  we don't know what will please Pyjamas...
+                del self.room_list[jid.JID(room_jid_s)]
+            except KeyError:
+                pass
 
     def _roomUserJoinedCb(self, room_jid_s, user_nick, user_data):
-        for lib_wid in self.libervia_widgets:
-            if isinstance(lib_wid, panels.ChatPanel) and lib_wid.type == 'group' and lib_wid.target.bare == room_jid_s:
-                lib_wid.userJoined(user_nick, user_data)
+        lib_wid = self.getOrCreateRoomWidget(jid.JID(room_jid_s))
+        if lib_wid:
+            lib_wid.userJoined(user_nick, user_data)
 
     def _roomUserLeftCb(self, room_jid_s, user_nick, user_data):
-        for lib_wid in self.libervia_widgets:
-            if isinstance(lib_wid, panels.ChatPanel) and lib_wid.type == 'group' and lib_wid.target.bare == room_jid_s:
-                lib_wid.userLeft(user_nick, user_data)
+        lib_wid = self.getRoomWidget(jid.JID(room_jid_s))
+        if lib_wid:
+            lib_wid.userLeft(user_nick, user_data)
 
     def _roomUserChangedNickCb(self, room_jid_s, old_nick, new_nick):
         """Called when an user joined a MUC room"""
-        for lib_wid in self.libervia_widgets:
-            if isinstance(lib_wid, panels.ChatPanel) and lib_wid.type == 'group' and lib_wid.target.bare == room_jid_s:
-                lib_wid.changeUserNick(old_nick, new_nick)
+        lib_wid = self.getRoomWidget(jid.JID(room_jid_s))
+        if lib_wid:
+            lib_wid.changeUserNick(old_nick, new_nick)
 
     def _tarotGameStartedCb(self, waiting, room_jid_s, referee, players):
-        for lib_wid in self.libervia_widgets:
-            if isinstance(lib_wid, panels.ChatPanel) and lib_wid.type == 'group' and lib_wid.target.bare == room_jid_s:
-                lib_wid.startGame("Tarot", waiting, referee, players)
+        lib_wid = self.getRoomWidget(jid.JID(room_jid_s))
+        if lib_wid:
+            lib_wid.startGame("Tarot", waiting, referee, players)
 
     def _tarotGameGenericCb(self, event_name, room_jid_s, args):
-        for lib_wid in self.libervia_widgets:
-            if isinstance(lib_wid, panels.ChatPanel) and lib_wid.type == 'group' and lib_wid.target.bare == room_jid_s:
-                getattr(lib_wid.getGame("Tarot"), event_name)(*args)
+        lib_wid = self.getRoomWidget(jid.JID(room_jid_s))
+        if lib_wid:
+            getattr(lib_wid.getGame("Tarot"), event_name)(*args)
 
     def _radioColStartedCb(self, waiting, room_jid_s, referee, players, queue_data):
-        for lib_wid in self.libervia_widgets:
-            if isinstance(lib_wid, panels.ChatPanel) and lib_wid.type == 'group' and lib_wid.target.bare == room_jid_s:
-                lib_wid.startGame("RadioCol", waiting, referee, players, queue_data)
+        lib_wid = self.getRoomWidget(jid.JID(room_jid_s))
+        if lib_wid:
+            lib_wid.startGame("RadioCol", waiting, referee, players, queue_data)
 
     def _radioColGenericCb(self, event_name, room_jid_s, args):
-        for lib_wid in self.libervia_widgets:
-            if isinstance(lib_wid, panels.ChatPanel) and lib_wid.type == 'group' and lib_wid.target.bare == room_jid_s:
-                getattr(lib_wid.getGame("RadioCol"), event_name)(*args)
+        lib_wid = self.getRoomWidget(jid.JID(room_jid_s))
+        if lib_wid:
+            getattr(lib_wid.getGame("RadioCol"), event_name)(*args)
 
     def _getPresenceStatusesCb(self, presence_data):
         for entity in presence_data:
@@ -909,17 +929,13 @@
         @param state: new state (string)
         """
         if from_jid_s == '@ALL@':
-            target = '@ALL@'
-            nick = C.ALL_OCCUPANTS
-        else:
-            from_jid = jid.JID(from_jid_s)
-            target = from_jid.bare
-            nick = from_jid.resource
-
-        for lib_wid in self.libervia_widgets:
-            if isinstance(lib_wid, panels.ChatPanel):
-                if target == '@ALL@' or lib_wid.matchEntity(target):
-                    lib_wid.setState(state, nick=nick)
+            for lib_wid in self.libervia_widgets:
+                if isinstance(lib_wid, panels.ChatPanel):
+                    lib_wid.setState(state, nick=C.ALL_OCCUPANTS)
+            return
+        from_jid = jid.JID(from_jid_s)
+        lib_wid = self.getLiberviaWidget(panels.ChatPanel, {'item': from_jid}, ignoreOtherTabs=False)
+        lib_wid.setState(state, nick=from_jid.resource)
 
     def _askConfirmation(self, confirmation_id, confirmation_type, data):
         answer_data = {}
--- a/src/browser/sat_browser/base_panels.py	Wed Oct 22 14:19:25 2014 +0200
+++ b/src/browser/sat_browser/base_panels.py	Wed Oct 22 19:03:55 2014 +0200
@@ -113,6 +113,8 @@
         self.setStyleName('occupantsList')
 
     def addOccupant(self, nick):
+        if nick in self.occupants_list:
+            return
         _occupant = Occupant(nick)
         self.occupants_list[nick] = _occupant
         self.add(_occupant)
--- a/src/browser/sat_browser/jid.py	Wed Oct 22 14:19:25 2014 +0200
+++ b/src/browser/sat_browser/jid.py	Wed Oct 22 19:03:55 2014 +0200
@@ -113,3 +113,6 @@
 
     def full(self):
         return str(self)
+
+    def bareJID(self):
+        return JID(self.bare)
--- a/src/browser/sat_browser/panels.py	Wed Oct 22 14:19:25 2014 +0200
+++ b/src/browser/sat_browser/panels.py	Wed Oct 22 19:03:55 2014 +0200
@@ -1133,6 +1133,7 @@
         chat_area.setStyleName('chatArea')
         if type_ == 'group':
             self.occupants_list = base_panels.OccupantsList()
+            self.occupants_initialised = False
             chat_area.add(self.occupants_list)
         self.__body.add(chat_area)
         self.content = AbsolutePanel()
@@ -1157,7 +1158,8 @@
         _contact = item if isinstance(item, jid.JID) else jid.JID(item)
         host.contact_panel.setContactMessageWaiting(_contact.bare, False)
         _new_panel = ChatPanel(host, _contact, type_)  # XXX: pyjamas doesn't seems to support creating with cls directly
-        _new_panel.historyPrint()
+        if type == 'one2one':
+            _new_panel.historyPrint()
         host.setSelected(_new_panel)
         _new_panel.refresh()
         return _new_panel
@@ -1187,7 +1189,6 @@
     def matchEntity(self, item, type_=None):
         """
         @param entity: target jid as a string or jid.JID instance.
-        Could also be a couple with a type in the second element.
         @return: True if self matches the given entity
         """
         if type_ is None:
@@ -1234,13 +1235,16 @@
     def setPresents(self, nicks):
         """Set the users presents in this room
         @param occupants: list of nicks (string)"""
-        self.occupants_list.clear()
         for nick in nicks:
             self.occupants_list.addOccupant(nick)
+        self.occupants_initialised = True
 
     def userJoined(self, nick, data):
+        if self.occupants_list.getOccupantBox(nick):
+            return  # user is already displayed
         self.occupants_list.addOccupant(nick)
-        self.printInfo("=> %s has joined the room" % nick)
+        if self.occupants_initialised:
+            self.printInfo("=> %s has joined the room" % nick)
 
     def userLeft(self, nick, data):
         self.occupants_list.removeOccupant(nick)
@@ -1333,7 +1337,7 @@
         to set the state for a one2one conversation, or give a nickname or
         C.ALL_OCCUPANTS to set the state of a participant within a MUC.
         @param state: the new chat state
-        @param nick: None for one2one, the MUC user nick or ALL_OCCUPANTS
+        @param nick: ignored for one2one, otherwise the MUC user nick or C.ALL_OCCUPANTS
         """
         if self.type == 'group':
             assert(nick)
--- a/src/browser/sat_browser/plugin_sec_otr.py	Wed Oct 22 14:19:25 2014 +0200
+++ b/src/browser/sat_browser/plugin_sec_otr.py	Wed Oct 22 19:03:55 2014 +0200
@@ -344,7 +344,7 @@
         log.debug(u"getContextForUser [%s]" % other_jid)
         if not other_jid.resource:
             log.error("getContextForUser called with a bare jid")
-            running_sessions = [jid.userhostJID() for jid in self.contexts.keys() if self.contexts[jid].state == otr.context.STATE_ENCRYPTED]
+            running_sessions = [jid.bareJID() for jid in self.contexts.keys() if self.contexts[jid].state == otr.context.STATE_ENCRYPTED]
             if start or (other_jid in running_sessions):
                 users_ml = DIALOG_USERS_ML.format(subject=D_("OTR issue in Libervia: getContextForUser called with a bare jid in an encrypted context"))
                 text = RESOURCE_ISSUE.format(eol=DIALOG_EOL, jid=other_jid.full(), users_ml=users_ml)