Fix+optimize contact-to-avatar storage and loading
This commit is contained in:
parent
4a08c8061d
commit
2eb72d5dad
|
@ -1,5 +1,6 @@
|
||||||
using Gdk;
|
using Gdk;
|
||||||
using Gee;
|
using Gee;
|
||||||
|
using Qlite;
|
||||||
|
|
||||||
using Xmpp;
|
using Xmpp;
|
||||||
using Dino.Entities;
|
using Dino.Entities;
|
||||||
|
@ -120,7 +121,6 @@ public class AvatarManager : StreamInteractionModule, Object {
|
||||||
XmppStream stream = stream_interactor.get_stream(account);
|
XmppStream stream = stream_interactor.get_stream(account);
|
||||||
if (stream != null) {
|
if (stream != null) {
|
||||||
stream.get_module(Xep.UserAvatars.Module.IDENTITY).publish_png(stream, buffer, pixbuf.width, pixbuf.height);
|
stream.get_module(Xep.UserAvatars.Module.IDENTITY).publish_png(stream, buffer, pixbuf.width, pixbuf.height);
|
||||||
on_user_avatar_received(account, account.bare_jid, Base64.encode(buffer));
|
|
||||||
}
|
}
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
warning(e.message);
|
warning(e.message);
|
||||||
|
@ -129,52 +129,61 @@ public class AvatarManager : StreamInteractionModule, Object {
|
||||||
|
|
||||||
private void on_account_added(Account account) {
|
private void on_account_added(Account account) {
|
||||||
stream_interactor.module_manager.get_module(account, Xep.UserAvatars.Module.IDENTITY).received_avatar.connect((stream, jid, id) =>
|
stream_interactor.module_manager.get_module(account, Xep.UserAvatars.Module.IDENTITY).received_avatar.connect((stream, jid, id) =>
|
||||||
on_user_avatar_received(account, jid, id)
|
on_user_avatar_received.begin(account, jid, id)
|
||||||
);
|
);
|
||||||
stream_interactor.module_manager.get_module(account, Xep.VCard.Module.IDENTITY).received_avatar.connect((stream, jid, id) =>
|
stream_interactor.module_manager.get_module(account, Xep.VCard.Module.IDENTITY).received_avatar.connect((stream, jid, id) =>
|
||||||
on_vcard_avatar_received(account, jid, id)
|
on_vcard_avatar_received.begin(account, jid, id)
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach (var entry in db.get_avatar_hashes(Source.USER_AVATARS).entries) {
|
foreach (var entry in get_avatar_hashes(account, Source.USER_AVATARS).entries) {
|
||||||
on_user_avatar_received(account, entry.key, entry.value);
|
user_avatars[entry.key] = entry.value;
|
||||||
}
|
}
|
||||||
foreach (var entry in db.get_avatar_hashes(Source.VCARD).entries) {
|
foreach (var entry in get_avatar_hashes(account, Source.VCARD).entries) {
|
||||||
// FIXME: remove. temporary to remove falsely saved avatars.
|
vcard_avatars[entry.key] = entry.value;
|
||||||
if (stream_interactor.get_module(MucManager.IDENTITY).is_groupchat(entry.key, account)) {
|
|
||||||
db.avatar.delete().with(db.avatar.jid, "=", entry.key.to_string()).perform();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
on_vcard_avatar_received(account, entry.key, entry.value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void on_user_avatar_received(Account account, Jid jid, string id) {
|
private async void on_user_avatar_received(Account account, Jid jid, string id) {
|
||||||
if (!user_avatars.has_key(jid) || user_avatars[jid] != id) {
|
if (!user_avatars.has_key(jid) || user_avatars[jid] != id) {
|
||||||
user_avatars[jid] = id;
|
user_avatars[jid] = id;
|
||||||
db.set_avatar_hash(jid, id, Source.USER_AVATARS);
|
set_avatar_hash(account, jid, id, Source.USER_AVATARS);
|
||||||
|
}
|
||||||
|
Pixbuf? avatar = yield get_avatar_by_hash(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) {
|
private async void on_vcard_avatar_received(Account account, Jid jid, string id) {
|
||||||
if (!vcard_avatars.has_key(jid) || vcard_avatars[jid] != id) {
|
if (!vcard_avatars.has_key(jid) || vcard_avatars[jid] != id) {
|
||||||
vcard_avatars[jid] = id;
|
vcard_avatars[jid] = id;
|
||||||
if (!jid.is_full()) { // don't save MUC occupant avatars
|
if (!jid.is_full()) { // don't save MUC occupant avatars
|
||||||
db.set_avatar_hash(jid, id, Source.VCARD);
|
set_avatar_hash(account, jid, id, Source.VCARD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
avatar_storage.get_image.begin(id, (obj, res) => {
|
Pixbuf? avatar = yield get_avatar_by_hash(id);
|
||||||
Pixbuf? avatar = avatar_storage.get_image.end(res);
|
if (avatar != null) {
|
||||||
if (avatar != null) {
|
received_avatar(avatar, jid, account);
|
||||||
received_avatar(avatar, jid, account);
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
public void set_avatar_hash(Account account, Jid jid, string hash, int type) {
|
||||||
|
db.avatar.insert()
|
||||||
|
.value(db.avatar.jid_id, db.get_jid_id(jid))
|
||||||
|
.value(db.avatar.account_id, account.id)
|
||||||
|
.value(db.avatar.hash, hash)
|
||||||
|
.value(db.avatar.type_, type)
|
||||||
|
.perform();
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMap<Jid, string> get_avatar_hashes(Account account, int type) {
|
||||||
|
HashMap<Jid, string> ret = new HashMap<Jid, string>(Jid.hash_func, Jid.equals_func);
|
||||||
|
foreach (Row row in db.avatar.select({db.avatar.jid_id, db.avatar.hash})
|
||||||
|
.with(db.avatar.type_, "=", type)
|
||||||
|
.with(db.avatar.account_id, "=", account.id)) {
|
||||||
|
ret[db.get_jid_by_id(row[db.avatar.jid_id])] = row[db.avatar.hash];
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ using Dino.Entities;
|
||||||
namespace Dino {
|
namespace Dino {
|
||||||
|
|
||||||
public class Database : Qlite.Database {
|
public class Database : Qlite.Database {
|
||||||
private const int VERSION = 11;
|
private const int VERSION = 12;
|
||||||
|
|
||||||
public class AccountTable : Table {
|
public class AccountTable : Table {
|
||||||
public Column<int> id = new Column.Integer("id") { primary_key = true, auto_increment = true };
|
public Column<int> id = new Column.Integer("id") { primary_key = true, auto_increment = true };
|
||||||
|
@ -150,13 +150,15 @@ public class Database : Qlite.Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AvatarTable : Table {
|
public class AvatarTable : Table {
|
||||||
public Column<string> jid = new Column.Text("jid");
|
public Column<int> jid_id = new Column.Integer("jid_id");
|
||||||
|
public Column<int> account_id = new Column.Integer("account_id");
|
||||||
public Column<string> hash = new Column.Text("hash");
|
public Column<string> hash = new Column.Text("hash");
|
||||||
public Column<int> type_ = new Column.Integer("type");
|
public Column<int> type_ = new Column.Integer("type");
|
||||||
|
|
||||||
internal AvatarTable(Database db) {
|
internal AvatarTable(Database db) {
|
||||||
base(db, "avatar");
|
base(db, "contact_avatar");
|
||||||
init({jid, hash, type_});
|
init({jid_id, account_id, hash, type_});
|
||||||
|
unique({jid_id, account_id}, "REPLACE");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,6 +311,13 @@ public class Database : Qlite.Database {
|
||||||
error("Failed to upgrade to database version 11: %s", e.message);
|
error("Failed to upgrade to database version 11: %s", e.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (oldVersion < 12) {
|
||||||
|
try {
|
||||||
|
exec("delete from avatar");
|
||||||
|
} catch (Error e) {
|
||||||
|
error("Failed to upgrade to database version 12: %s", e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<Account> get_accounts() {
|
public ArrayList<Account> get_accounts() {
|
||||||
|
@ -424,26 +433,6 @@ public class Database : Qlite.Database {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set_avatar_hash(Jid jid, string hash, int type) {
|
|
||||||
avatar.insert().or("REPLACE")
|
|
||||||
.value(avatar.jid, jid.to_string())
|
|
||||||
.value(avatar.hash, hash)
|
|
||||||
.value(avatar.type_, type)
|
|
||||||
.perform();
|
|
||||||
}
|
|
||||||
|
|
||||||
public HashMap<Jid, string> get_avatar_hashes(int type) {
|
|
||||||
HashMap<Jid, string> ret = new HashMap<Jid, string>(Jid.hash_func, Jid.equals_func);
|
|
||||||
foreach (Row row in avatar.select({avatar.jid, avatar.hash}).with(avatar.type_, "=", type)) {
|
|
||||||
try {
|
|
||||||
ret[new Jid(row[avatar.jid])] = row[avatar.hash];
|
|
||||||
} catch (InvalidJidError e) {
|
|
||||||
warning("Ignoring avatar of invalid Jid: %s", e.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add_entity_features(string entity, Gee.List<string> features) {
|
public void add_entity_features(string entity, Gee.List<string> features) {
|
||||||
foreach (string feature in features) {
|
foreach (string feature in features) {
|
||||||
entity_feature.insert()
|
entity_feature.insert()
|
||||||
|
|
|
@ -29,8 +29,8 @@ public class Database {
|
||||||
error(@"SQLite error: %d - %s", db.errcode(), db.errmsg());
|
error(@"SQLite error: %d - %s", db.errcode(), db.errmsg());
|
||||||
}
|
}
|
||||||
this.tables = tables;
|
this.tables = tables;
|
||||||
start_migration();
|
|
||||||
if (debug) db.trace((message) => print(@"Qlite trace: $message\n"));
|
if (debug) db.trace((message) => print(@"Qlite trace: $message\n"));
|
||||||
|
start_migration();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ensure_init() {
|
public void ensure_init() {
|
||||||
|
|
Loading…
Reference in a new issue