Commit b4822d10 authored by Niels De Graef's avatar Niels De Graef

Avatar: lazily load the Pixbuf of the avatar.

This should again decrease our memory usage in most cases.
parent 6c65b72e
......@@ -82,14 +82,7 @@ public class Contacts.AvatarSelector : Dialog {
this.contact = contact;
// Load the current avatar
this.current_avatar = new Avatar (MAIN_SIZE);
if (contact != null) {
contact.keep_widget_uptodate (this.current_avatar, (w) => {
(w as Avatar).set_image.begin (contact.individual, contact);
});
} else {
this.current_avatar.set_image.begin (null, null);
}
this.current_avatar = new Avatar (MAIN_SIZE, contact);
this.current_avatar.set_hexpand (false);
this.current_avatar.show ();
this.grid.attach (this.current_avatar, 0, 0);
......
......@@ -26,45 +26,65 @@ using Gee;
public class Contacts.Avatar : DrawingArea {
private int size;
private Gdk.Pixbuf? pixbuf = null;
private Contact? contact = null;
// We want to lazily load the Pixbuf to make sure we don't draw all contact avatars at once.
// As long as there is no need for it to be drawn, keep this to false.
private bool avatar_loaded = false;
// The background color used in case of a fallback avatar
private Gdk.RGBA? bg_color = null;
// The color used for an initial or the fallback icon
private const Gdk.RGBA fg_color = { 0, 0, 0, 0.25 };
public Avatar (int size) {
public Avatar (int size, Contact? contact = null) {
this.contact = contact;
if (contact != null) {
contact.individual.notify["avatar"].connect ( (s, p) => {
load_avatar.begin ();
});
}
this.size = size;
set_size_request (size, size);
get_style_context ().add_class ("contacts-avatar");
// If we don't have an avatar, don't try to load it later
this.avatar_loaded = (contact == null || contact.individual == null
|| contact.individual.avatar == null);
show ();
}
/**
* Manually set the avatar to the given pixbuf, even if the contact has an avatar.
*/
public void set_pixbuf (Gdk.Pixbuf? a_pixbuf) {
this.pixbuf = a_pixbuf;
queue_draw ();
}
public async void set_image (AvatarDetails? details, Contact? contact = null) {
this.contact = contact;
// FIXME listen for changes in the Individual's avatar
private async void load_avatar () {
assert (this.contact != null);
if (details != null && details.avatar != null) {
try {
var stream = yield details.avatar.load_async (size, null);
this.pixbuf = yield new Gdk.Pixbuf.from_stream_at_scale_async (stream, size, size, true);
queue_draw ();
} catch {
}
this.avatar_loaded = true;
try {
var stream = yield this.contact.individual.avatar.load_async (this.size);
this.pixbuf = yield new Gdk.Pixbuf.from_stream_at_scale_async (stream, this.size, this.size, true);
queue_draw ();
} catch (Error e) {
debug ("Couldn't load avatar of contact %s. Reason: %s", this.contact.individual.display_name, e.message);
}
}
public override bool draw (Cairo.Context cr) {
cr.save ();
// This exists to implement lazy loading: i.e. only load the avatar on the first draw()
if (!this.avatar_loaded)
load_avatar.begin ();
if (this.pixbuf != null)
draw_contact_avatar (cr);
else // No avatar available, draw a fallback
......
......@@ -942,21 +942,13 @@ public class Contacts.ContactEditor : Grid {
// Creates the contact's current avatar in a big button on top of the Editor
private void create_avatar_button () {
this.avatar = new Avatar (PROFILE_SIZE);
this.avatar = new Avatar (PROFILE_SIZE, this.contact);
var button = new Button ();
button.get_accessible ().set_name (_("Change avatar"));
button.image = this.avatar;
button.clicked.connect (on_avatar_button_clicked);
if (this.contact != null) {
this.contact.keep_widget_uptodate (this.avatar, (w) => {
this.avatar.set_image.begin (this.contact.individual, this.contact);
});
} else {
this.avatar.set_image.begin (null, null);
}
this.container_grid.attach (button, 0, 0, 1, 3);
}
......
......@@ -44,7 +44,7 @@ public class Contacts.ContactList : ListBox {
grid.margin = 3;
grid.margin_start = 9;
grid.set_column_spacing (10);
this.avatar = new Avatar (LIST_AVATAR_SIZE);
this.avatar = new Avatar (LIST_AVATAR_SIZE, this.contact);
this.label = new Label (c.individual.display_name);
this.label.ellipsize = Pango.EllipsizeMode.END;
......@@ -71,7 +71,6 @@ public class Contacts.ContactList : ListBox {
public void update () {
// Update widgets
this.label.set_text (this.contact.individual.display_name);
this.avatar.set_image.begin (this.contact.individual, this.contact);
}
// Sets whether the checbox should always be shown (and not only on hover)
......
......@@ -96,12 +96,9 @@ public class Contacts.ContactSheet : Grid {
}
public void update (Contact c) {
var image_frame = new Avatar (PROFILE_SIZE);
var image_frame = new Avatar (PROFILE_SIZE, c);
image_frame.set_vexpand (false);
image_frame.set_valign (Align.START);
c.keep_widget_uptodate (image_frame, (w) => {
(w as Avatar).set_image.begin (c.individual, c);
});
attach (image_frame, 0, 0, 1, 3);
var name_label = new Label (null);
......
......@@ -43,16 +43,13 @@ public class Contacts.LinkSuggestionGrid : Grid {
public LinkSuggestionGrid (Contact contact) {
get_style_context ().add_class ("contacts-suggestion");
var image_frame = new Avatar (AVATAR_SIZE);
var image_frame = new Avatar (AVATAR_SIZE, contact);
image_frame.hexpand = false;
image_frame.margin = 12;
contact.keep_widget_uptodate (image_frame, (w) => {
(w as Avatar).set_image.begin (contact.individual, contact);
});
image_frame.show ();
attach (image_frame, 0, 0, 1, 2);
this.description_label.xalign = 0; // FIXME: hack to make it actually align left.
this.description_label.xalign = 0;
this.description_label.label = contact.is_main?
_("Is this the same person as %s from %s?").printf (contact.individual.display_name, contact.format_persona_stores ())
: _("Is this the same person as %s?").printf (contact.individual.display_name);
......
......@@ -80,13 +80,10 @@ public class Contacts.LinkedAccountsDialog : Dialog {
var row_grid = new Grid ();
var image_frame = new Avatar (AVATAR_SIZE);
var image_frame = new Avatar (AVATAR_SIZE, contact);
image_frame.set_hexpand (false);
image_frame.margin = 6;
image_frame.margin_end = 12;
contact.keep_widget_uptodate (image_frame, (w) => {
(w as Avatar).set_image.begin (contact.individual, contact);
});
row_grid.attach (image_frame, 0, 0, 1, 2);
var display_name = new Label ("");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment