Remove avatars with missmatch between supposed and actual sha1 hash on load, make loading async
This commit is contained in:
parent
cbe0ff2c1d
commit
b6799e59bb
|
@ -46,29 +46,48 @@ public class AvatarManager : StreamInteractionModule, Object {
|
|||
modules.add(new Xep.VCard.Module(avatar_storage));
|
||||
}
|
||||
|
||||
private Pixbuf? get_avatar_by_hash(string hash) {
|
||||
private async Pixbuf? get_avatar_by_hash(string hash) {
|
||||
if (cached_pixbuf.has_key(hash)) {
|
||||
return cached_pixbuf[hash];
|
||||
}
|
||||
Pixbuf? image = avatar_storage.get_image(hash);
|
||||
Pixbuf? image = yield avatar_storage.get_image(hash);
|
||||
if (image != null) {
|
||||
cached_pixbuf[hash] = image;
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
public Pixbuf? get_avatar(Account account, Jid jid) {
|
||||
public bool has_avatar(Account account, Jid jid) {
|
||||
string? hash = get_avatar_hash(account, jid);
|
||||
if (hash != null) {
|
||||
if (cached_pixbuf.has_key(hash)) {
|
||||
return true;
|
||||
}
|
||||
return avatar_storage.has_image(hash);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Pixbuf? get_avatar(Account account, Jid jid) {
|
||||
string? hash = get_avatar_hash(account, jid);
|
||||
if (hash != null) {
|
||||
return yield get_avatar_by_hash(hash);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? get_avatar_hash(Account account, Jid jid) {
|
||||
Jid jid_ = jid;
|
||||
if (!stream_interactor.get_module(MucManager.IDENTITY).is_groupchat_occupant(jid, account)) {
|
||||
jid_ = jid.bare_jid;
|
||||
}
|
||||
string? user_avatars_id = user_avatars[jid_];
|
||||
if (user_avatars_id != null) {
|
||||
return get_avatar_by_hash(user_avatars_id);
|
||||
return user_avatars_id;
|
||||
}
|
||||
string? vcard_avatars_id = vcard_avatars[jid_];
|
||||
if (vcard_avatars_id != null) {
|
||||
return get_avatar_by_hash(vcard_avatars_id);
|
||||
return vcard_avatars_id;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -118,10 +137,12 @@ public class AvatarManager : StreamInteractionModule, Object {
|
|||
user_avatars[jid] = id;
|
||||
db.set_avatar_hash(jid, id, Source.USER_AVATARS);
|
||||
}
|
||||
Pixbuf? avatar = avatar_storage.get_image(id);
|
||||
if (avatar != null) {
|
||||
received_avatar(avatar, jid, account);
|
||||
}
|
||||
avatar_storage.get_image.begin(id, (obj, res) => {
|
||||
Pixbuf? avatar = avatar_storage.get_image.end(res);
|
||||
if (avatar != null) {
|
||||
received_avatar(avatar, jid, account);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void on_vcard_avatar_received(Account account, Jid jid, string id) {
|
||||
|
@ -131,10 +152,12 @@ public class AvatarManager : StreamInteractionModule, Object {
|
|||
db.set_avatar_hash(jid, id, Source.VCARD);
|
||||
}
|
||||
}
|
||||
Pixbuf? avatar = avatar_storage.get_image(id);
|
||||
if (avatar != null) {
|
||||
received_avatar(avatar, jid, account);
|
||||
}
|
||||
avatar_storage.get_image.begin(id, (obj, res) => {
|
||||
Pixbuf? avatar = avatar_storage.get_image.end(res);
|
||||
if (avatar != null) {
|
||||
received_avatar(avatar, jid, account);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,9 +28,24 @@ public class AvatarStorage : Xep.PixbufStorage, Object {
|
|||
return file.query_exists();
|
||||
}
|
||||
|
||||
public Pixbuf? get_image(string id) {
|
||||
public async Pixbuf? get_image(string id) {
|
||||
try {
|
||||
return new Pixbuf.from_file(Path.build_filename(folder, id));
|
||||
File file = File.new_for_path(Path.build_filename(folder, id));
|
||||
FileInputStream stream = yield file.read_async();
|
||||
|
||||
uint8 fbuf[100];
|
||||
size_t size;
|
||||
|
||||
Checksum checksum = new Checksum (ChecksumType.SHA1);
|
||||
while ((size = yield stream.read_async(fbuf)) > 0) {
|
||||
checksum.update(fbuf, size);
|
||||
}
|
||||
|
||||
if (checksum.get_string() != id) {
|
||||
FileUtils.remove(file.get_path());
|
||||
}
|
||||
stream.seek(0, SeekType.SET);
|
||||
return yield new Pixbuf.from_stream_async(stream);
|
||||
} catch (Error e) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -26,31 +26,31 @@ public class AvatarGenerator {
|
|||
this.scale_factor = scale_factor;
|
||||
}
|
||||
|
||||
public ImageSurface draw_jid(StreamInteractor stream_interactor, Jid jid_, Account account) {
|
||||
public async ImageSurface draw_jid(StreamInteractor stream_interactor, Jid jid_, Account account) {
|
||||
Jid? jid = jid_;
|
||||
this.stream_interactor = stream_interactor;
|
||||
Jid? real_jid = stream_interactor.get_module(MucManager.IDENTITY).get_real_jid(jid, account);
|
||||
if (real_jid != null && stream_interactor.get_module(AvatarManager.IDENTITY).get_avatar(account, real_jid) != null) {
|
||||
if (real_jid != null && stream_interactor.get_module(AvatarManager.IDENTITY).has_avatar(account, real_jid)) {
|
||||
jid = real_jid;
|
||||
}
|
||||
ImageSurface surface = crop_corners(draw_tile(jid, account, width * scale_factor, height * scale_factor), 3 * scale_factor);
|
||||
ImageSurface surface = crop_corners(yield draw_tile(jid, account, width * scale_factor, height * scale_factor), 3 * scale_factor);
|
||||
surface.set_device_scale(scale_factor, scale_factor);
|
||||
return surface;
|
||||
}
|
||||
|
||||
public ImageSurface draw_message(StreamInteractor stream_interactor, Message message) {
|
||||
if (message.real_jid != null && stream_interactor.get_module(AvatarManager.IDENTITY).get_avatar(message.account, message.real_jid) != null) {
|
||||
return draw_jid(stream_interactor, message.real_jid, message.account);
|
||||
public async ImageSurface draw_message(StreamInteractor stream_interactor, Message message) {
|
||||
if (message.real_jid != null && stream_interactor.get_module(AvatarManager.IDENTITY).has_avatar(message.account, message.real_jid)) {
|
||||
return yield draw_jid(stream_interactor, message.real_jid, message.account);
|
||||
}
|
||||
return draw_jid(stream_interactor, message.from, message.account);
|
||||
return yield draw_jid(stream_interactor, message.from, message.account);
|
||||
}
|
||||
|
||||
public ImageSurface draw_conversation(StreamInteractor stream_interactor, Conversation conversation) {
|
||||
return draw_jid(stream_interactor, conversation.counterpart, conversation.account);
|
||||
public async ImageSurface draw_conversation(StreamInteractor stream_interactor, Conversation conversation) {
|
||||
return yield draw_jid(stream_interactor, conversation.counterpart, conversation.account);
|
||||
}
|
||||
|
||||
public ImageSurface draw_account(StreamInteractor stream_interactor, Account account) {
|
||||
return draw_jid(stream_interactor, account.bare_jid, account);
|
||||
public async ImageSurface draw_account(StreamInteractor stream_interactor, Account account) {
|
||||
return yield draw_jid(stream_interactor, account.bare_jid, account);
|
||||
}
|
||||
|
||||
public ImageSurface draw_text(string text) {
|
||||
|
@ -76,23 +76,23 @@ public class AvatarGenerator {
|
|||
return (int)Math.ceil(scale_factor/2.0);
|
||||
}
|
||||
|
||||
private void add_tile_to_pixbuf(Pixbuf pixbuf, Jid jid, Account account, int width, int height, int x, int y) {
|
||||
Pixbuf tile = pixbuf_get_from_surface(draw_chat_tile(jid, account, width, height), 0, 0, width, height);
|
||||
private async void add_tile_to_pixbuf(Pixbuf pixbuf, Jid jid, Account account, int width, int height, int x, int y) {
|
||||
Pixbuf tile = pixbuf_get_from_surface(yield draw_chat_tile(jid, account, width, height), 0, 0, width, height);
|
||||
tile.copy_area(0, 0, width, height, pixbuf, x, y);
|
||||
}
|
||||
|
||||
private ImageSurface draw_tile(Jid jid, Account account, int width, int height) {
|
||||
private async ImageSurface draw_tile(Jid jid, Account account, int width, int height) {
|
||||
ImageSurface surface;
|
||||
if (stream_interactor.get_module(MucManager.IDENTITY).is_groupchat(jid, account)) {
|
||||
surface = draw_groupchat_tile(jid, account, width, height);
|
||||
surface = yield draw_groupchat_tile(jid, account, width, height);
|
||||
} else {
|
||||
surface = draw_chat_tile(jid, account, width, height);
|
||||
surface = yield draw_chat_tile(jid, account, width, height);
|
||||
}
|
||||
return surface;
|
||||
}
|
||||
|
||||
private ImageSurface draw_chat_tile(Jid jid, Account account, int width, int height) {
|
||||
Pixbuf? pixbuf = stream_interactor.get_module(AvatarManager.IDENTITY).get_avatar(account, jid);
|
||||
private async ImageSurface draw_chat_tile(Jid jid, Account account, int width, int height) {
|
||||
Pixbuf? pixbuf = yield stream_interactor.get_module(AvatarManager.IDENTITY).get_avatar(account, jid);
|
||||
if (pixbuf != null) {
|
||||
double desired_ratio = (double) width / height;
|
||||
double avatar_ratio = (double) pixbuf.width / pixbuf.height;
|
||||
|
@ -117,35 +117,35 @@ public class AvatarGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
private ImageSurface draw_groupchat_tile(Jid jid, Account account, int width, int height) {
|
||||
private async ImageSurface draw_groupchat_tile(Jid jid, Account account, int width, int height) {
|
||||
Gee.List<Jid>? occupants = stream_interactor.get_module(MucManager.IDENTITY).get_other_occupants(jid, account);
|
||||
if (stateless || occupants == null || occupants.size == 0) {
|
||||
return draw_chat_tile(jid, account, width, height);
|
||||
return yield draw_chat_tile(jid, account, width, height);
|
||||
}
|
||||
|
||||
for (int i = 0; i < occupants.size && i < 4; i++) {
|
||||
Jid? real_jid = stream_interactor.get_module(MucManager.IDENTITY).get_real_jid(occupants[i], account);
|
||||
if (real_jid != null && stream_interactor.get_module(AvatarManager.IDENTITY).get_avatar(account, real_jid) != null) {
|
||||
if (real_jid != null && stream_interactor.get_module(AvatarManager.IDENTITY).has_avatar(account, real_jid)) {
|
||||
occupants[i] = real_jid;
|
||||
}
|
||||
}
|
||||
Pixbuf pixbuf = initialize_pixbuf(width, height);
|
||||
if (occupants.size == 1 || occupants.size == 2 || occupants.size == 3) {
|
||||
add_tile_to_pixbuf(pixbuf, occupants[0], account, width / 2 - get_right_border(), height, 0, 0);
|
||||
yield add_tile_to_pixbuf(pixbuf, occupants[0], account, width / 2 - get_right_border(), height, 0, 0);
|
||||
if (occupants.size == 1) {
|
||||
add_tile_to_pixbuf(pixbuf, account.bare_jid, account, width / 2 - get_left_border(), height, width / 2 + get_left_border(), 0);
|
||||
yield add_tile_to_pixbuf(pixbuf, account.bare_jid, account, width / 2 - get_left_border(), height, width / 2 + get_left_border(), 0);
|
||||
} else if (occupants.size == 2) {
|
||||
add_tile_to_pixbuf(pixbuf, occupants[1], account, width / 2 - get_left_border(), height, width / 2 + get_left_border(), 0);
|
||||
yield add_tile_to_pixbuf(pixbuf, occupants[1], account, width / 2 - get_left_border(), height, width / 2 + get_left_border(), 0);
|
||||
} else if (occupants.size == 3) {
|
||||
add_tile_to_pixbuf(pixbuf, occupants[1], account, width / 2 - get_left_border(), height / 2 - get_right_border(), width / 2 + get_left_border(), 0);
|
||||
add_tile_to_pixbuf(pixbuf, occupants[2], account, width / 2 - get_left_border(), height / 2 - get_left_border(), width / 2 + get_left_border(), height / 2 + get_left_border());
|
||||
yield add_tile_to_pixbuf(pixbuf, occupants[1], account, width / 2 - get_left_border(), height / 2 - get_right_border(), width / 2 + get_left_border(), 0);
|
||||
yield add_tile_to_pixbuf(pixbuf, occupants[2], account, width / 2 - get_left_border(), height / 2 - get_left_border(), width / 2 + get_left_border(), height / 2 + get_left_border());
|
||||
}
|
||||
} else if (occupants.size >= 4) {
|
||||
add_tile_to_pixbuf(pixbuf, occupants[0], account, width / 2 - get_right_border(), height / 2 - get_right_border(), 0, 0);
|
||||
add_tile_to_pixbuf(pixbuf, occupants[1], account, width / 2 - get_left_border(), height / 2 - get_right_border(), width / 2 + get_left_border(), 0);
|
||||
add_tile_to_pixbuf(pixbuf, occupants[2], account, width / 2 - get_right_border(), height / 2 - get_left_border(), 0, height / 2 + get_left_border());
|
||||
yield add_tile_to_pixbuf(pixbuf, occupants[0], account, width / 2 - get_right_border(), height / 2 - get_right_border(), 0, 0);
|
||||
yield add_tile_to_pixbuf(pixbuf, occupants[1], account, width / 2 - get_left_border(), height / 2 - get_right_border(), width / 2 + get_left_border(), 0);
|
||||
yield add_tile_to_pixbuf(pixbuf, occupants[2], account, width / 2 - get_right_border(), height / 2 - get_left_border(), 0, height / 2 + get_left_border());
|
||||
if (occupants.size == 4) {
|
||||
add_tile_to_pixbuf(pixbuf, occupants[3], account, width / 2 - get_left_border(), height / 2 - get_left_border(), width / 2 + get_left_border(), height / 2 + get_left_border());
|
||||
yield add_tile_to_pixbuf(pixbuf, occupants[3], account, width / 2 - get_left_border(), height / 2 - get_left_border(), width / 2 + get_left_border(), height / 2 + get_left_border());
|
||||
} else if (occupants.size > 4) {
|
||||
ImageSurface plus_surface = draw_colored_rectangle_text("555753", "+", width / 2 - get_left_border(), height / 2 - get_left_border());
|
||||
if (greyscale) plus_surface = convert_to_greyscale(plus_surface);
|
||||
|
|
|
@ -208,7 +208,7 @@ public class AvatarImage : Misc {
|
|||
stream_interactor.get_module(RosterManager.IDENTITY).updated_roster_item.connect(on_roster_updated);
|
||||
stream_interactor.get_module(MucManager.IDENTITY).private_room_occupant_updated.connect(on_occupant_updated);
|
||||
}
|
||||
if (muc_manager.is_groupchat(jid_, account) && avatar_manager.get_avatar(account, jid_) == null) {
|
||||
if (muc_manager.is_groupchat(jid_, account) && !avatar_manager.has_avatar(account, jid_)) {
|
||||
// Groupchat without avatar
|
||||
Gee.List<Jid>? occupants;
|
||||
if (muc_manager.is_private_room(account, jid_)) {
|
||||
|
@ -321,19 +321,27 @@ public class AvatarImage : Misc {
|
|||
this.text_only = null;
|
||||
this.gray = gray && allow_gray;
|
||||
this.with_plus = with_plus;
|
||||
this.current_jids = jids;
|
||||
this.current_avatars = new Gdk.Pixbuf[jids.length];
|
||||
for (int i = 0; i < current_jids.length; ++i) {
|
||||
Jid? real_jid = muc_manager.get_real_jid(current_jids[i], account);
|
||||
|
||||
set_jids_async.begin(jids);
|
||||
}
|
||||
|
||||
public async void set_jids_async(Jid[] jids) {
|
||||
Jid[] jids_ = jids;
|
||||
Gdk.Pixbuf[] avatars = new Gdk.Pixbuf[jids.length];
|
||||
for (int i = 0; i < jids_.length; ++i) {
|
||||
Jid? real_jid = muc_manager.get_real_jid(jids_[i], account);
|
||||
if (real_jid != null) {
|
||||
current_avatars[i] = avatar_manager.get_avatar(account, real_jid);
|
||||
if (current_avatars[i] != null) {
|
||||
current_jids[i] = real_jid;
|
||||
avatars[i] = yield avatar_manager.get_avatar(account, real_jid);
|
||||
if (avatars[i] != null) {
|
||||
jids_[i] = real_jid;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
current_avatars[i] = avatar_manager.get_avatar(account, current_jids[i]);
|
||||
avatars[i] = yield avatar_manager.get_avatar(account, jids_[i]);
|
||||
}
|
||||
this.current_avatars = avatars;
|
||||
this.current_jids = jids_;
|
||||
|
||||
queue_draw();
|
||||
}
|
||||
|
||||
|
|
|
@ -41,12 +41,12 @@ public class Notifications : Object {
|
|||
}
|
||||
|
||||
public void start() {
|
||||
stream_interactor.get_module(NotificationEvents.IDENTITY).notify_content_item.connect(notify_content_item);
|
||||
stream_interactor.get_module(NotificationEvents.IDENTITY).notify_content_item.connect((content_item, conversation) => notify_content_item.begin(content_item, conversation));
|
||||
stream_interactor.get_module(NotificationEvents.IDENTITY).notify_subscription_request.connect(notify_subscription_request);
|
||||
stream_interactor.get_module(NotificationEvents.IDENTITY).notify_connection_error.connect(notify_connection_error);
|
||||
}
|
||||
|
||||
private void notify_content_item(ContentItem content_item, Conversation conversation) {
|
||||
private async void notify_content_item(ContentItem content_item, Conversation conversation) {
|
||||
if (!notifications.has_key(conversation)) {
|
||||
notifications[conversation] = new Notification("");
|
||||
notifications[conversation].set_default_action_and_target_value("app.open-conversation", new Variant.int32(conversation.id));
|
||||
|
@ -77,18 +77,20 @@ public class Notifications : Object {
|
|||
notifications[conversation].set_title(display_name);
|
||||
notifications[conversation].set_body(text);
|
||||
try {
|
||||
notifications[conversation].set_icon(get_pixbuf_icon((new AvatarGenerator(40, 40)).draw_conversation(stream_interactor, conversation)));
|
||||
Cairo.ImageSurface conversation_avatar = yield (new AvatarGenerator(40, 40)).draw_conversation(stream_interactor, conversation);
|
||||
notifications[conversation].set_icon(get_pixbuf_icon(conversation_avatar));
|
||||
} catch (Error e) { }
|
||||
window.get_application().send_notification(conversation.id.to_string(), notifications[conversation]);
|
||||
active_conversation_ids.add(conversation.id.to_string());
|
||||
window.urgency_hint = true;
|
||||
}
|
||||
|
||||
private void notify_subscription_request(Conversation conversation) {
|
||||
private async void notify_subscription_request(Conversation conversation) {
|
||||
Notification notification = new Notification(_("Subscription request"));
|
||||
notification.set_body(conversation.counterpart.to_string());
|
||||
try {
|
||||
notification.set_icon(get_pixbuf_icon((new AvatarGenerator(40, 40)).draw_jid(stream_interactor, conversation.counterpart, conversation.account)));
|
||||
Cairo.ImageSurface jid_avatar = yield (new AvatarGenerator(40, 40)).draw_jid(stream_interactor, conversation.counterpart, conversation.account);
|
||||
notification.set_icon(get_pixbuf_icon(jid_avatar));
|
||||
} catch (Error e) { }
|
||||
notification.set_default_action_and_target_value("app.open-conversation", new Variant.int32(conversation.id));
|
||||
notification.add_button_with_target_value(_("Accept"), "app.accept-subscription", conversation.id);
|
||||
|
|
|
@ -4,6 +4,6 @@ namespace Xmpp.Xep {
|
|||
public interface PixbufStorage : Object {
|
||||
public abstract void store(string id, Bytes data);
|
||||
public abstract bool has_image(string id);
|
||||
public abstract Pixbuf? get_image(string id);
|
||||
public abstract async Pixbuf? get_image(string id);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue