plugin XEP-0085, quick_frontends, primitivus: chat states are working again

This commit is contained in:
Goffi 2016-07-17 16:47:33 +02:00
commit cc160e03d7
7 changed files with 59 additions and 24 deletions

View file

@ -151,6 +151,10 @@ class OccupantWidget(urwid.WidgetWrap):
def __lt__(self, other):
return self.occupant_data.nick.lower() < other.occupant_data.nick.lower()
@property
def markup(self):
return self._generateMarkup()
@property
def parent(self):
return self.mess_data.parent
@ -159,6 +163,10 @@ class OccupantWidget(urwid.WidgetWrap):
def nick(self):
return self.occupant_data.nick
def redraw(self):
self._w.set_text(self.markup)
self.occupant_data.parent.host.redraw() # FIXME: should not be necessary
def selectable(self):
return True
@ -181,13 +189,19 @@ class OccupantWidget(urwid.WidgetWrap):
# should be more intuitive and themable
o = self.occupant_data
markup = []
markup.append(('info_msg', '{}{} '.format(
markup.append(('info_msg', u'{}{} '.format(
o.role[0].upper(),
o.affiliation[0].upper(),
)))
markup.append(o.nick)
if o.state is not None:
markup.append(u' {}'.format(C.CHAT_STATE_ICON[o.state]))
return markup
# events
def updated(self, attributes):
self.redraw()
class OccupantsWidget(urwid.WidgetWrap):
@ -572,6 +586,11 @@ class Chat(PrimitivusWidget, quick_chat.QuickChat):
if self.type == C.CHAT_GROUP:
self.host.removeListener('presence', self.presenceListener)
def onChatState(self, from_jid, state, profile):
super(Chat, self).onChatState(from_jid, state, profile)
if self.type == C.CHAT_ONE2ONE:
self.title_dynamic = C.CHAT_STATE_ICON[state]
self.host.redraw() # FIXME: should not be necessary
quick_widgets.register(quick_chat.QuickChat, Chat)
quick_widgets.register(quick_games.Tarot, game_tarot.TarotGame)

View file

@ -55,12 +55,13 @@ class Const(constants.Const):
# Chats
CHAT_ONE2ONE = 'one2one'
CHAT_GROUP = 'group'
USER_CHAT_STATES = {
CHAT_STATE_ICON = {
"": u" ",
"active": u'✔',
"inactive": u'☄',
"gone": u'✈',
"composing": u'✎',
"paused": u"⦷"
"paused": u"…"
}
# Blogs

View file

@ -569,20 +569,9 @@ class QuickApp(object):
@param state (unicode): new state
@param profile (unicode): current profile
"""
# log.debug(_(u"Received new chat state {} from {} [{}]").format(state, from_jid_s, profile))
# from_jid = jid.JID(from_jid_s) if from_jid_s != C.ENTITY_ALL else C.ENTITY_ALL
# contact_list = self.contact_lists[profile]
# for widget in self.widgets.getWidgets(quick_chat.QuickChat):
# if profile != widget.profile:
# continue
# to_display = C.USER_CHAT_STATES[state] if (state and widget.type == C.CHAT_GROUP) else state
# if widget.type == C.CHAT_GROUP and from_jid_s == C.ENTITY_ALL:
# for occupant in [jid.newResource(widget.target, nick) for nick in widget.occupants]:
# contact_list.setCache(occupant, 'chat_state', to_display)
# widget.update(occupant)
# elif from_jid.bare == widget.target.bare: # roster contact or MUC occupant
# contact_list.setCache(from_jid, 'chat_state', to_display)
# widget.update(from_jid)
from_jid = jid.JID(from_jid_s)
for widget in self.widgets.getWidgets(quick_chat.QuickChat, profiles=(profile,)):
widget.onChatState(from_jid, state, profile)
def notify(self, type_, entity=None, message=None, subject=None, callback=None, cb_args=None, widget=None, profile=C.PROF_KEY_NONE):
"""Trigger an event notification

View file

@ -126,11 +126,22 @@ class Occupant(object):
self.affiliation = data['affiliation']
self.role = data['role']
self.widgets = set() # widgets linked to this occupant
self._state = None
@property
def host(self):
return self.parent.host
@property
def state(self):
return self._state
@state.setter
def state(self, new_state):
self._state = new_state
for w in self.widgets:
w.updated(["state"])
class QuickChat(quick_widgets.QuickWidget):
@ -407,5 +418,17 @@ class QuickChat(quick_widgets.QuickWidget):
"""
raise NotImplementedError
## events ##
def onChatState(self, from_jid, state, profile):
"""A chat state has been received"""
if self.type == C.CHAT_GROUP:
nick = from_jid.resource
try:
self.occupants[nick].state = state
except KeyError:
log.warning(u"{nick} not found in {room}, ignoring new chat state".format(
nick=nick, room=self.target.bare))
quick_widgets.register(QuickChat)

View file

@ -79,19 +79,22 @@ class QuickWidgetsManager(object):
raise exceptions.InternalError("There is not class registered for {}".format(class_))
return cls
def getWidgets(self, class_):
"""Get all subclassed widgets
def getWidgets(self, class_, profiles=None):
"""Get all subclassed widgets instances
@param class_: subclass of QuickWidget, same parameter as used in [getOrCreateWidget]
@param profiles(iterable, None): if not None, filter on instances linked to these profiles
@return: iterator on widgets
"""
class_ = self.getRealClass(class_)
try:
widgets_map = self._widgets[class_.__name__]
except KeyError:
return iter([])
return
else:
return widgets_map.itervalues()
for w in widgets_map.itervalues():
if profiles is None or w.profiles.intersection(profiles):
yield w
def getWidget(self, class_, target=None, profiles=None):
"""Get a widget without creating it if it doesn't exist.

View file

@ -520,7 +520,7 @@ class SAT(service.Service):
## XMPP methods ##
def getWaitingConf(self, profile_key=None):
assert(profile_key)
assert profile_key
client = self.getClient(profile_key)
ret = []
for conf_id in client._waiting_conf:

View file

@ -96,7 +96,7 @@ class XEP_0085(object):
def __init__(self, host):
log.info(_("Chat State Notifications plugin initialization"))
self.host = host
self.map = {}
self.map = {} # FIXME: would be better to use client instead of mapping profile to data
# parameter value is retrieved before each use
host.memory.updateParams(self.params)
@ -141,7 +141,7 @@ class XEP_0085(object):
self.host.memory.updateEntityData(entity_jid, ENTITY_KEY, value, profile_key=profile)
if not value or value == DELETE_VALUE:
# reinit chat state UI for this or these contact(s)
self.host.bridge.chatStateReceived(unicode(entity_jid), "", profile)
self.host.bridge.chatStateReceived(entity_jid.full(), "", profile)
def paramUpdateTrigger(self, name, value, category, type_, profile):
"""Reset all the existing chat state entity data associated with this profile after a parameter modification.