plugin XEP-0054, quick frontend(app): various improvments:
- memory.cache is now used
- getAvatar and setAvatar has been renamed to avatarGet and avatarSet to follow new convention
- getAvatar now return (optionally) full path, and may request vCard or only return avatar in cache
- getAvatarFile has been removed as it is not needed anymore (avatarGet can return full path)
- getCard has been removed from bridge as it was only used to request avatar
- new internal method getBareOfFull return jid to use depending of the jid being part of a MUC or not
- cache is now set per profile in client, instead of a general one for all profiles
- thanks to the use of memory.cache, correct extension is now used in saved file, according to MIME type
- fixed and better cache handling
- a warning message is shown if given avatar hash differs from computed one
- empty hash value is now in a constant, and ignored if received
- QuickApp has been updated to follow new behaviour
- Primitivus has been fixed (it was not declaring not using avatars correclty)
- jp has been updated to follow new methods name
This commit is contained in:
parent
1a33c3389f
commit
4eaf5d626f
5 changed files with 326 additions and 217 deletions
|
|
@ -46,7 +46,7 @@ class Set(base.CommandBase):
|
|||
self.disp(_(u"file [{}] doesn't exist !").format(path), error=True)
|
||||
self.host.quit(1)
|
||||
path = os.path.abspath(path)
|
||||
self.host.bridge.setAvatar(path, self.profile, callback=self._avatarCb, errback=self._avatarEb)
|
||||
self.host.bridge.avatarSet(path, self.profile, callback=self._avatarCb, errback=self._avatarEb)
|
||||
|
||||
def _avatarCb(self):
|
||||
self.disp(_("avatar has been set"), 1)
|
||||
|
|
@ -85,7 +85,7 @@ class Get(base.CommandBase):
|
|||
import webbrowser
|
||||
webbrowser.open(path)
|
||||
|
||||
def _getAvatarCb(self, avatar_path):
|
||||
def _avatarGetCb(self, avatar_path):
|
||||
if not avatar_path:
|
||||
self.disp(_(u"No avatar found."), 1)
|
||||
self.host.quit(C.EXIT_NOT_FOUND)
|
||||
|
|
@ -96,12 +96,12 @@ class Get(base.CommandBase):
|
|||
|
||||
self.host.quit()
|
||||
|
||||
def _getAvatarEb(self, failure_):
|
||||
def _avatarGetEb(self, failure_):
|
||||
self.disp(_("error while getting avatar: {msg}").format(msg=failure_), error=True)
|
||||
self.host.quit(C.EXIT_ERROR)
|
||||
|
||||
def start(self):
|
||||
self.host.bridge.getAvatar(self.args.jid, self.profile, callback=self._getAvatarCb, errback=self._getAvatarEb)
|
||||
self.host.bridge.avatarGet(self.args.jid, False, False, self.profile, callback=self._avatarGetCb, errback=self._avatarGetEb)
|
||||
|
||||
|
||||
class Avatar(base.CommandBase):
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ class PrimitivusTopWidget(sat_widgets.FocusPile):
|
|||
|
||||
class PrimitivusApp(QuickApp, InputHistory):
|
||||
MB_HANDLER = False
|
||||
AVATAR_HANDLER = False
|
||||
AVATARS_HANDLER = False
|
||||
|
||||
def __init__(self):
|
||||
bridge_module = dynamic_import.bridge(bridge_name, 'sat_frontends.bridge')
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ class ProfileManager(object):
|
|||
# and a way to keep some XMLUI request between sessions is expected in backend
|
||||
host = None
|
||||
bridge = None
|
||||
cache_keys_to_get = ['avatar']
|
||||
# cache_keys_to_get = ['avatar']
|
||||
|
||||
def __init__(self, profile):
|
||||
self.profile = profile
|
||||
|
|
@ -106,7 +106,10 @@ class ProfileManager(object):
|
|||
|
||||
def _plug_profile_getFeaturesCb(self, features):
|
||||
self.host.features = features
|
||||
self.host.bridge.getEntitiesData([], ProfileManager.cache_keys_to_get, profile=self.profile, callback=self._plug_profile_gotCachedValues, errback=self._plug_profile_failedCachedValues)
|
||||
# FIXME: we don't use cached value at the moment, but keep the code for later use
|
||||
# it was previously used for avatars, but as we don't get full path here, it's better to request later
|
||||
# self.host.bridge.getEntitiesData([], ProfileManager.cache_keys_to_get, profile=self.profile, callback=self._plug_profile_gotCachedValues, errback=self._plug_profile_failedCachedValues)
|
||||
self._plug_profile_gotCachedValues({})
|
||||
|
||||
def _plug_profile_failedCachedValues(self, failure):
|
||||
log.error(u"Couldn't get cached values: {}".format(failure))
|
||||
|
|
@ -817,15 +820,9 @@ class QuickApp(object):
|
|||
if entity in self.contact_lists[profile]:
|
||||
self.contact_lists[profile].setCache(entity, 'nick', value)
|
||||
self.callListeners('nick', entity, value, profile=profile)
|
||||
elif key == "avatar":
|
||||
if value: # and entity in self.contact_lists[profile]:
|
||||
# FIXME: contact_list check is removed to work around 'avatar' issues
|
||||
# (avatar can't be requested if we don't save them here)
|
||||
# avatar need to be refactored properly in backend and here
|
||||
def gotFilename(filename):
|
||||
self.contact_lists[profile].setCache(entity, 'avatar', filename)
|
||||
self.callListeners('avatar', entity, filename, profile=profile)
|
||||
self.bridge.getAvatarFile(value, callback=gotFilename)
|
||||
elif key == "avatar" and self.AVATARS_HANDLER:
|
||||
if value and entity in self.contact_lists[profile]:
|
||||
self.getAvatar(entity, ignore_cache=True, profile=profile)
|
||||
|
||||
def actionManager(self, action_data, callback=None, ui_show_cb=None, user_action=True, profile=C.PROF_KEY_NONE):
|
||||
"""Handle backend action
|
||||
|
|
@ -886,15 +883,42 @@ class QuickApp(object):
|
|||
|
||||
self.bridge.launchAction(callback_id, data, profile, callback=action_cb, errback=self.dialogFailure)
|
||||
|
||||
def getAvatar(self, entity, profile):
|
||||
"""return avatar path for an entity"""
|
||||
def _avatarGetCb(self, avatar_path, entity, contact_list, profile):
|
||||
path = avatar_path or self.getDefaultAvatar(entity)
|
||||
contact_list.setCache(entity, "avatar", path)
|
||||
self.callListeners('avatar', entity, path, profile=profile)
|
||||
|
||||
def _avatarGetEb(self, failure, entity, contact_list):
|
||||
log.warning(u"Can't get avatar: {}".format(failure))
|
||||
contact_list.setCache(entity, "avatar", self.getDefaultAvatar(entity))
|
||||
|
||||
def getAvatar(self, entity, cache_only=True, hash_only=False, ignore_cache=False, profile=C.PROF_KEY_NONE):
|
||||
"""return avatar path for an entity
|
||||
|
||||
@param entity(jid.JID): entity to get avatar from
|
||||
@param cache_only(bool): if False avatar will be requested if not in cache
|
||||
with current vCard based implementation, it's better to keep True
|
||||
except if we request avatars for roster items
|
||||
@param hash_only(bool): if True avatar hash is returned, else full path
|
||||
@param ignore_cache(bool): if False, won't check local cache and will request backend in every case
|
||||
@return (unicode, None): avatar full path (None if no avatar found)
|
||||
"""
|
||||
contact_list = self.contact_lists[profile]
|
||||
avatar = contact_list.getCache(entity, "avatar")
|
||||
if ignore_cache:
|
||||
avatar = None
|
||||
else:
|
||||
avatar = contact_list.getCache(entity, "avatar", bare_default=None)
|
||||
if avatar is None:
|
||||
self.bridge.getCard(unicode(entity), profile)
|
||||
self.bridge.avatarGet(
|
||||
unicode(entity),
|
||||
cache_only,
|
||||
hash_only,
|
||||
profile=profile,
|
||||
callback=lambda path: self._avatarGetCb(path, entity, contact_list, profile),
|
||||
errback=lambda failure: self._avatarGetEb(failure, entity, contact_list))
|
||||
# we set avatar to empty string to avoid requesting several time the same avatar
|
||||
# while we are waiting for avatarGet result
|
||||
contact_list.setCache(entity, "avatar", "")
|
||||
if not avatar:
|
||||
avatar = self.getDefaultAvatar(entity)
|
||||
return avatar
|
||||
|
||||
def getDefaultAvatar(self, entity=None):
|
||||
|
|
|
|||
|
|
@ -126,7 +126,9 @@ class Message(object):
|
|||
|
||||
@property
|
||||
def avatar(self):
|
||||
return self.host.getAvatar(self.from_jid, self.profile)
|
||||
"""avatar full path or None if no avatar is found"""
|
||||
ret = self.host.getAvatar(self.from_jid, profile=self.profile)
|
||||
return ret
|
||||
|
||||
def getNick(self, entity):
|
||||
"""Return nick of an entity when possible"""
|
||||
|
|
@ -583,16 +585,25 @@ class QuickChat(quick_widgets.QuickWidget):
|
|||
|
||||
def onAvatar(self, entity, filename, profile):
|
||||
if self.type == C.CHAT_GROUP:
|
||||
if entity.bare == self.target and entity.resource in self.occupants:
|
||||
self.occupants[entity.resource].update({'avatar': filename})
|
||||
if entity.bare == self.target:
|
||||
try:
|
||||
self.occupants[entity.resource].update({'avatar': filename})
|
||||
except KeyError:
|
||||
# can happen for a message in history where the
|
||||
# entity is not here anymore
|
||||
pass
|
||||
|
||||
for m in self.messages.values():
|
||||
if m.nick == entity.resource:
|
||||
for w in m.widgets:
|
||||
w.update({'avatar': filename})
|
||||
else:
|
||||
if entity.bare == self.target.bare:
|
||||
log.info("entity avatar updated")
|
||||
# TODO: call a specific method
|
||||
if entity.bare == self.target.bare or entity.bare == self.host.profiles[profile].whoami.bare:
|
||||
log.info(u"avatar updated for {}".format(entity))
|
||||
for m in self.messages.values():
|
||||
if m.from_jid.bare == entity.bare:
|
||||
for w in m.widgets:
|
||||
w.update({'avatar': filename})
|
||||
|
||||
|
||||
quick_widgets.register(QuickChat)
|
||||
|
|
|
|||
|
|
@ -219,6 +219,9 @@ class ProfileContactList(object):
|
|||
@return: full cache if no name is given, or value of "name", or None
|
||||
"""
|
||||
# FIXME: resource handling need to be reworked
|
||||
# FIXME: bare_default work for requesting full jid to get bare jid, but not the other way
|
||||
# e.g.: if we have set an avatar for user@server.tld/resource and we request user@server.tld
|
||||
# we won't get the avatar set in the resource
|
||||
try:
|
||||
cache = self._cache[entity.bare]
|
||||
except KeyError:
|
||||
|
|
|
|||
Loading…
Reference in a new issue