aboutsummaryrefslogtreecommitdiff
path: root/libdino/src/service
diff options
context:
space:
mode:
Diffstat (limited to 'libdino/src/service')
-rw-r--r--libdino/src/service/database.vala31
-rw-r--r--libdino/src/service/roster_manager.vala110
2 files changed, 119 insertions, 22 deletions
diff --git a/libdino/src/service/database.vala b/libdino/src/service/database.vala
index 021d1c21..2836751f 100644
--- a/libdino/src/service/database.vala
+++ b/libdino/src/service/database.vala
@@ -115,6 +115,31 @@ public class Database : Qlite.Database {
}
}
+ public class RosterTable : Table {
+ public Column<int> account_id = new Column.Integer("account_id");
+ public Column<string> jid = new Column.Text("jid");
+ public Column<string> name = new Column.Text("name");
+ public Column<string> subscription = new Column.Text("subscription");
+
+ internal RosterTable(Database db) {
+ base(db, "roster");
+ init({account_id, jid, name, subscription});
+ unique({account_id, jid}, "IGNORE");
+ }
+ }
+
+ public class AccountKeyValueTable : Table {
+ public Column<int> account_id = new Column.Integer("account_id");
+ public Column<string> key = new Column.Text("key");
+ public Column<string> value = new Column.Text("value");
+
+ internal AccountKeyValueTable(Database db) {
+ base(db, "account_key_value");
+ init({account_id, key, value});
+ unique({account_id, key}, "IGNORE");
+ }
+ }
+
public AccountTable account { get; private set; }
public JidTable jid { get; private set; }
public MessageTable message { get; private set; }
@@ -122,6 +147,8 @@ public class Database : Qlite.Database {
public ConversationTable conversation { get; private set; }
public AvatarTable avatar { get; private set; }
public EntityFeatureTable entity_feature { get; private set; }
+ public RosterTable roster { get; private set; }
+ public AccountKeyValueTable account_key_value { get; private set; }
public Map<int, string> jid_table_cache = new HashMap<int, string>();
public Map<string, int> jid_table_reverse = new HashMap<string, int>();
@@ -136,7 +163,9 @@ public class Database : Qlite.Database {
conversation = new ConversationTable(this);
avatar = new AvatarTable(this);
entity_feature = new EntityFeatureTable(this);
- init({ account, jid, message, real_jid, conversation, avatar, entity_feature });
+ roster = new RosterTable(this);
+ account_key_value = new AccountKeyValueTable(this);
+ init({ account, jid, message, real_jid, conversation, avatar, entity_feature, roster, account_key_value });
exec("PRAGMA synchronous=0");
}
diff --git a/libdino/src/service/roster_manager.vala b/libdino/src/service/roster_manager.vala
index bb9fbd3a..91da7579 100644
--- a/libdino/src/service/roster_manager.vala
+++ b/libdino/src/service/roster_manager.vala
@@ -13,32 +13,30 @@ public class RosterManager : StreamInteractionModule, Object {
public signal void updated_roster_item(Account account, Jid jid, Roster.Item roster_item);
private StreamInteractor stream_interactor;
+ private Database db;
+ private Gee.Map<Account, RosterStoreImpl> roster_stores = new HashMap<Account, RosterStoreImpl>(Account.hash_func, Account.equals_func);
- public static void start(StreamInteractor stream_interactor) {
- RosterManager m = new RosterManager(stream_interactor);
+ public static void start(StreamInteractor stream_interactor, Database db) {
+ RosterManager m = new RosterManager(stream_interactor, db);
stream_interactor.add_module(m);
}
- public RosterManager(StreamInteractor stream_interactor) {
+ public RosterManager(StreamInteractor stream_interactor, Database db) {
this.stream_interactor = stream_interactor;
+ this.db = db;
stream_interactor.account_added.connect(on_account_added);
+ stream_interactor.module_manager.initialize_account_modules.connect((account, modules) => {
+ if (!roster_stores.has_key(account)) roster_stores[account] = new RosterStoreImpl(account, db);
+ modules.add(new Roster.VersioningModule(roster_stores[account]));
+ });
}
- public ArrayList<Roster.Item> get_roster(Account account) {
- Core.XmppStream? stream = stream_interactor.get_stream(account);
- ArrayList<Roster.Item> ret = new ArrayList<Roster.Item>();
- if (stream != null) {
- ret.add_all(stream.get_flag(Roster.Flag.IDENTITY).get_roster());
- }
- return ret;
+ public Collection<Roster.Item> get_roster(Account account) {
+ return roster_stores[account].get_roster();
}
public Roster.Item? get_roster_item(Account account, Jid jid) {
- Core.XmppStream? stream = stream_interactor.get_stream(account);
- if (stream == null) return null;
- Xmpp.Roster.Flag? flag = stream.get_flag(Xmpp.Roster.Flag.IDENTITY);
- if (flag == null) return null;
- return flag.get_item(jid.bare_jid.to_string());
+ return roster_stores[account].get_item(jid);
}
public void remove_jid(Account account, Jid jid) {
@@ -53,7 +51,9 @@ public class RosterManager : StreamInteractionModule, Object {
private void on_account_added(Account account) {
stream_interactor.module_manager.get_module(account, Roster.Module.IDENTITY).received_roster.connect( (stream, roster) => {
- on_roster_received(account, roster);
+ foreach (Roster.Item roster_item in roster) {
+ on_roster_item_updated(account, roster_item);
+ }
});
stream_interactor.module_manager.get_module(account, Roster.Module.IDENTITY).item_removed.connect( (stream, roster_item) => {
removed_roster_item(account, new Jid(roster_item.jid), roster_item);
@@ -63,14 +63,82 @@ public class RosterManager : StreamInteractionModule, Object {
});
}
- private void on_roster_received(Account account, Collection<Roster.Item> roster_items) {
- foreach (Roster.Item roster_item in roster_items) {
- on_roster_item_updated(account, roster_item);
+ private void on_roster_item_updated(Account account, Roster.Item roster_item) {
+ updated_roster_item(account, new Jid(roster_item.jid), roster_item);
+ }
+}
+
+public class RosterStoreImpl : Roster.Storage, Object {
+ private Account account;
+ private Database db;
+
+ private string version = "";
+ private HashMap<string, Roster.Item> items = new HashMap<string, Roster.Item>();
+
+ public class RosterStoreImpl(Account account, Database db) {
+ this.account = account;
+ this.db = db;
+
+ version = db_get_roster_version() ?? "";
+ foreach (Qlite.Row row in db.roster.select().with(db.roster.account_id, "=", account.id)) {
+ Roster.Item item = new Roster.Item();
+ item.jid = row[db.roster.jid];
+ item.name = row[db.roster.name];
+ item.subscription = row[db.roster.subscription];
+ items[item.jid] = item;
}
}
- private void on_roster_item_updated(Account account, Roster.Item roster_item) {
- updated_roster_item(account, new Jid(roster_item.jid), roster_item);
+ public string? get_roster_version() {
+ return version;
+ }
+
+ public Collection<Roster.Item> get_roster() {
+ return items.values;
+ }
+
+ public Roster.Item? get_item(Jid jid) {
+ return items.has_key(jid.bare_jid.to_string()) ? items[jid.bare_jid.to_string()] : null;
+ }
+
+ public void set_roster_version(string version) {
+ db.account_key_value.insert().or("REPLACE")
+ .value(db.account_key_value.account_id, account.id)
+ .value(db.account_key_value.key, "roster_version")
+ .value(db.account_key_value.value, version)
+ .perform();
+ }
+
+ public void set_roster(Collection<Roster.Item> items) {
+ db.roster.delete().with(db.roster.account_id, "=", account.id).perform();
+ foreach (Roster.Item item in items) {
+ set_item(item);
+ }
+ }
+
+ public void set_item(Roster.Item item) {
+ items[item.jid] = item;
+ db.roster.insert().or("REPLACE")
+ .value(db.roster.account_id, account.id)
+ .value(db.roster.jid, item.jid)
+ .value(db.roster.name, item.name)
+ .value(db.roster.subscription, item.subscription)
+ .perform();
+ }
+
+ public void remove_item(Roster.Item item) {
+ items.unset(item.jid);
+ db.roster.delete()
+ .with(db.roster.account_id, "=", account.id)
+ .with(db.roster.jid, "=", item.jid);
+ }
+
+ private string? db_get_roster_version() {
+ Qlite.Row? row = db.account_key_value.select()
+ .with(db.account_key_value.account_id, "=", account.id)
+ .with(db.account_key_value.key, "=", "roster_version").iterator().get_next();
+ if (row != null) return row[db.account_key_value.value];
+ return null;
}
}