diff frontends/src/quick_frontend/quick_app.py @ 2123:c42aab22c2c0

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
author Goffi <goffi@goffi.org>
date Sun, 15 Jan 2017 17:51:37 +0100
parents b44558286bbb
children 2f264f3df280
line wrap: on
line diff
--- a/frontends/src/quick_frontend/quick_app.py	Sun Jan 15 16:00:41 2017 +0100
+++ b/frontends/src/quick_frontend/quick_app.py	Sun Jan 15 17:51:37 2017 +0100
@@ -50,7 +50,7 @@
     #       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 @@
 
     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 @@
             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 @@
 
         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):