changeset 407:6a6551de4414

browser_side: display chat states (with symbols) for MUC participants
author souliane <souliane@mailoo.org>
date Sun, 16 Mar 2014 21:03:50 +0100
parents 63f8469b4ad3
children ee8ebfe23e16
files browser_side/base_panels.py browser_side/panels.py libervia.py public/libervia.css
diffstat 4 files changed, 59 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/browser_side/base_panels.py	Sun Mar 16 20:55:50 2014 +0100
+++ b/browser_side/base_panels.py	Sun Mar 16 21:03:50 2014 +0100
@@ -39,6 +39,7 @@
 
 from html_tools import html_sanitize, html_strip, inlineRoot, convertNewLinesToXHTML
 
+from constants import Const
 from sat_frontends.tools.strings import addURLToText, addURLToImage
 from sat.core.i18n import _
 
@@ -62,15 +63,25 @@
 class Occupant(HTML):
     """Occupant of a MUC room"""
 
-    def __init__(self, nick, special=""):
+    def __init__(self, nick, state=None, special=""):
+        """
+        @param nick: the user nickname
+        @param state: the user chate state (XEP-0085)
+        @param special: a string of symbols (e.g: for activities) 
+        """
         HTML.__init__(self)
         self.nick = nick
+        self._state = state
         self.special = special
         self._refresh()
 
     def __str__(self):
         return self.nick
 
+    def setState(self, state):
+        self._state = state
+        self._refresh()
+
     def addSpecial(self, special):
         """@param special: unicode"""
         if special not in self.special:
@@ -86,8 +97,9 @@
             self._refresh()
 
     def _refresh(self):
+        state = (' %s' % Const.MUC_USER_STATES[self._state]) if self._state else ''
         special = "" if len(self.special) == 0 else " %s" % self.special
-        self.setHTML("<div class='occupant'>%s%s</div>" % (html_sanitize(self.nick), special))
+        self.setHTML("<div class='occupant'>%s%s%s</div>" % (html_sanitize(self.nick), special, state))
 
 
 class OccupantsList(AbsolutePanel):
--- a/browser_side/panels.py	Sun Mar 16 20:55:50 2014 +0100
+++ b/browser_side/panels.py	Sun Mar 16 21:03:50 2014 +0100
@@ -1047,7 +1047,7 @@
         @param host: SatWebFrontend instance
         @param target: entity (JID) with who we have a conversation (contact's jid for one 2 one chat, or MUC room)
         @param type: one2one for simple conversation, group for MUC"""
-        base_widget.LiberviaWidget.__init__(self, host, target.bare, selectable=True)
+        base_widget.LiberviaWidget.__init__(self, host, title=target.bare, selectable=True)
         self.vpanel = VerticalPanel()
         self.vpanel.setSize('100%', '100%')
         self.type = type_
@@ -1074,16 +1074,7 @@
         self.addStyleName('chatPanel')
         self.setWidget(self.vpanel)
         self.state_machine = ChatStateMachine(self.host, str(self.target))
-
-    """def doDetachChildren(self):
-        #We need to force the use of a panel subclass method here,
-        #for the same reason as doAttachChildren
-        base_widget.ScrollPanelWrapper.doDetachChildren(self)
-
-    def doAttachChildren(self):
-        #We need to force the use of a panel subclass method here, else
-        #the event will not propagate to children
-        base_widget.ScrollPanelWrapper.doAttachChildren(self)"""
+        self._state = None
 
     @classmethod
     def registerClass(cls):
@@ -1242,6 +1233,31 @@
         elif game_type == "RadioCol":
             return self.radiocol_panel
 
+    def setState(self, state, nick=None):
+        """Set the chat state (XEP-0085) of the contact. Leave nick to None
+        to set the state for a one2one conversation, or give a nickname or
+        Const.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
+        """
+        if nick:
+            assert(self.type == 'group')
+            occupants = self.occupants_list.occupants_list.keys() if nick == Const.ALL_OCCUPANTS else [nick]
+            for occupant in occupants:
+                self.occupants_list.occupants_list[occupant].setState(state)
+        else:
+            assert(self.type == 'one2one')
+            self._state = state
+            self.refreshTitle()
+        self.state_machine.started = not not state  # start to send "composing" state from now
+
+    def refreshTitle(self):
+        """Refresh the title of this ChatPanel dialog"""
+        if self._state:
+            self.setTitle(self.target.bare + " (" + self._state + ")")
+        else:
+            self.setTitle(self.target.bare)
+
 
 class WebPanel(base_widget.LiberviaWidget):
     """ (mini)browser like widget """
--- a/libervia.py	Sun Mar 16 20:55:50 2014 +0100
+++ b/libervia.py	Sun Mar 16 21:03:50 2014 +0100
@@ -779,24 +779,24 @@
 
     def _chatStateReceivedCb(self, from_jid_s, state):
         """Callback when a new chat state is received.
-        @param from_jid_s: JID from the contact who sent his state
-        @param state: new state
+        @param from_jid_s: JID of the contact who sent his state, or '@ALL@'
+        @param state: new state (string)
         """
-        _from = JID(from_jid_s).bare if from_jid_s != "@ALL@" else from_jid_s
+        if from_jid_s == '@ALL@':
+            target = '@ALL@'
+            nick = Const.ALL_OCCUPANTS
+        else:
+            from_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):
-                win_from = lib_wid.target.bare
-                good_win = win_from == _from or _from == "@ALL@"
-                if (good_win and lib_wid.type == 'one2one'):
-                    if state:
-                        lib_wid.setTitle(win_from + " (" + state + ")")
-                    else:
-                        lib_wid.setTitle(win_from)
-                    # start to send "composing" state from now
-                    lib_wid.state_machine.started = True
-                elif (lib_wid.type == 'group'):
-                    # TODO: chat state notification for groupchat
-                    pass
+                if target == '@ALL' or target == lib_wid.target.bare:
+                    if lib_wid.type == 'one2one':
+                        lib_wid.setState(state)
+                    elif lib_wid.type == 'group':
+                        lib_wid.setState(state, nick=nick)
 
     def _askConfirmation(self, confirmation_id, confirmation_type, data):
         answer_data = {}
--- a/public/libervia.css	Sun Mar 16 20:55:50 2014 +0100
+++ b/public/libervia.css	Sun Mar 16 21:03:50 2014 +0100
@@ -974,13 +974,14 @@
 }
 
 .occupant {
-	 margin-top: 10px;
-	 margin-right: 4px;
+    margin-top: 10px;
+    margin-right: 4px;
     min-width: 120px;
     padding: 5px 15px 5px 15px;
     font-weight: bold;
     background-color: #eee;
     border: 1px solid #ddd;
+    white-space: nowrap;
 }
 
 .occupantsList {