[folks] telepathy: Preserve Tpf.Persona avatars from the cache for online contacts



commit c2338c651edd3fcdc3ef28c94d87351b8c6bae27
Author: Philip Withnall <philip tecnocode co uk>
Date:   Fri Jun 22 19:17:42 2012 +0100

    telepathy: Preserve Tpf.Persona avatars from the cache for online contacts
    
    This is a fairly hacky way of fixing the problem in bug #660128: maintaining
    a map of IIDs to avatar files for all personas in the Telepathy backend, and
    referring to it in case Telepathy doesnât know the current avatar for a
    TpContact. This can happen if that contact is currently offline while weâre
    online, for example. This allows use of the avatars cached from last time
    contacts were online, even though those contacts are now offline.
    
    A more comprehensive fix, which I would have implemented if I hadnât just got
    my degree classification and werenât just heading out to celebrate, would
    involve rearchitecting the caching of the Telepathy backend so that the
    Tpf.Personas werenât destroyed and re-created whenever the backend went
    offline/online; instead, they would have their properties updated from the
    cache/online contact list. This would eliminate spurious personas-changed
    signals, unify the code implementing the different properties (currently itâs
    split between the properties and separate implementations in
    Tpf.Persona.from_cache()), and allow property values to persist from offline
    to online without the need for hacks like this.
    
    Closes: https://bugzilla.gnome.org/show_bug.cgi?id=660128

 backends/telepathy/lib/tpf-persona-store.vala |   35 +++++++++++++++++++
 backends/telepathy/lib/tpf-persona.vala       |   46 ++++++++++++++++++++++---
 2 files changed, 76 insertions(+), 5 deletions(-)
---
diff --git a/backends/telepathy/lib/tpf-persona-store.vala b/backends/telepathy/lib/tpf-persona-store.vala
index cc2bfd1..c7eff9b 100644
--- a/backends/telepathy/lib/tpf-persona-store.vala
+++ b/backends/telepathy/lib/tpf-persona-store.vala
@@ -57,6 +57,11 @@ public class Tpf.PersonaStore : Folks.PersonaStore
    * See bgo#630822. */
   private HashSet<string> _favourite_ids = new HashSet<string> ();
 
+  /* Mapping from Persona IIDs to their avatars. This allows avatars to persist
+   * between the cached (offline) personas and the online personas. Note that
+   * this should *not* be cleared in _reset(). */
+  private HashMap<string, File> _avatars = new HashMap<string, File> ();
+
   private Connection _conn;
   private AccountManager? _account_manager; /* only null before prepare() */
   private Logger _logger;
@@ -364,6 +369,17 @@ public class Tpf.PersonaStore : Folks.PersonaStore
 
       debug.unindent ();
 
+      debug.print_line (domain, level, "Cached avatars for %u personas:",
+          this._avatars.size);
+      debug.indent ();
+
+      foreach (var id in this._avatars.keys)
+        {
+          debug.print_line (domain, level, "%s", id);
+        }
+
+      debug.unindent ();
+
       debug.print_line (domain, level, "");
     }
 
@@ -499,6 +515,8 @@ public class Tpf.PersonaStore : Folks.PersonaStore
               Internal.profiling_point ("created account manager in " +
                   "Tpf.PersonaStore (ID: %s)", this.id);
 
+              this._avatars.clear ();
+
               this._favourite_ids.clear ();
               this._logger = new Logger (this.id);
               this._logger.invalidated.connect (
@@ -971,6 +989,23 @@ public class Tpf.PersonaStore : Folks.PersonaStore
       this._reset ();
     }
 
+  internal void _update_avatar_cache (string persona_iid, File? avatar_file)
+    {
+      if (avatar_file == null)
+        {
+          this._avatars.unset (persona_iid);
+        }
+      else
+        {
+          this._avatars.set (persona_iid, (!) avatar_file);
+        }
+    }
+
+  internal File? _query_avatar_cache (string persona_iid)
+    {
+      return this._avatars.get (persona_iid);
+    }
+
   private bool _add_persona (Persona p)
     {
       if (this._persona_set.add (p))
diff --git a/backends/telepathy/lib/tpf-persona.vala b/backends/telepathy/lib/tpf-persona.vala
index 8f994b3..d397fd4 100644
--- a/backends/telepathy/lib/tpf-persona.vala
+++ b/backends/telepathy/lib/tpf-persona.vala
@@ -1092,10 +1092,15 @@ public class Tpf.Persona : Folks.Persona,
       this._alias = alias;
       this._is_favourite = is_favourite;
       this.is_in_contact_list = is_in_contact_list;
-      this._avatar = avatar;
       this._birthday = birthday;
       this._full_name = full_name;
 
+      // Avatars
+      this._avatar = avatar;
+      var avatar_file =
+          (avatar != null) ? ((FileIcon) avatar).get_file () : null;
+      ((Tpf.PersonaStore) store)._update_avatar_cache (iid, avatar_file);
+
       // Make the persona appear offline
       this.presence_type = PresenceType.OFFLINE;
       this.presence_message = "";
@@ -1161,17 +1166,48 @@ public class Tpf.Persona : Folks.Persona,
   private void _contact_notify_avatar ()
     {
       var file = this.contact.avatar_file;
+      var token = this.contact.avatar_token;
       Icon? icon = null;
+      var from_cache = false;
+
+      /* Handle all the different cases of avatars. */
+      if (token == "")
+        {
+          /* Definitely know there's no avatar. */
+          file = null;
+          from_cache = false;
+        }
+      else if (token != null && file != null)
+        {
+          /* Definitely know there's some avatar, so leave the file alone. */
+          from_cache = false;
+        }
+      else
+        {
+          /* Not sure about the avatar; fall back to any cached avatar. */
+          file = ((Tpf.PersonaStore) this.store)._query_avatar_cache (this.iid);
+          from_cache = true;
+        }
 
       if (file != null)
-        icon = new FileIcon (file);
+        {
+          icon = new FileIcon (file);
+        }
 
-      if (this._avatar == null || icon == null || !this._avatar.equal (icon))
+      if ((this._avatar == null) != (icon == null) || !this._avatar.equal (icon))
         {
           this._avatar = (LoadableIcon) icon;
           this.notify_property ("avatar");
-          /* Mark the persona cache as needing to be updated. */
-          ((Tpf.PersonaStore) this.store)._set_cache_needs_update ();
+
+          if (from_cache == false)
+            {
+              /* Mark the persona cache as needing to be updated. */
+              ((Tpf.PersonaStore) this.store)._set_cache_needs_update ();
+
+              /* Update the avatar cache. */
+              ((Tpf.PersonaStore) this.store)._update_avatar_cache (this.iid,
+                  file);
+            }
         }
     }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]