# HG changeset patch # User souliane # Date 1395000230 -3600 # Node ID 6a6551de4414988f31c0f417b62ef9be8b16f6c4 # Parent 63f8469b4ad3171491b4f719034cc1422088b1ac browser_side: display chat states (with symbols) for MUC participants diff -r 63f8469b4ad3 -r 6a6551de4414 browser_side/base_panels.py --- 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("
%s%s
" % (html_sanitize(self.nick), special)) + self.setHTML("
%s%s%s
" % (html_sanitize(self.nick), special, state)) class OccupantsList(AbsolutePanel): diff -r 63f8469b4ad3 -r 6a6551de4414 browser_side/panels.py --- 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 """ diff -r 63f8469b4ad3 -r 6a6551de4414 libervia.py --- 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 = {} diff -r 63f8469b4ad3 -r 6a6551de4414 public/libervia.css --- 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 {