reworked roster/contact handling. might break some stuff. not sycing to disk yet

This commit is contained in:
Daniel Gultsch 2014-05-19 15:15:09 +02:00
parent 590e2403ab
commit 993477cd83
16 changed files with 332 additions and 566 deletions

View file

@ -1,11 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" > <menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/action_refresh_contacts"
android:orderInCategory="10"
android:showAsAction="always"
android:icon="@drawable/ic_action_refresh"
android:title="@string/action_refresh" />
<item <item
android:id="@+id/action_accounts" android:id="@+id/action_accounts"
android:orderInCategory="90" android:orderInCategory="90"

View file

@ -221,7 +221,6 @@ public class PgpEngine {
return 0; return 0;
} }
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
Log.d("xmppService","openpgp user interaction requeried");
return 0; return 0;
case OpenPgpApi.RESULT_CODE_ERROR: case OpenPgpApi.RESULT_CODE_ERROR:
Log.d("xmppService","openpgp error: "+((OpenPgpError) result Log.d("xmppService","openpgp error: "+((OpenPgpError) result

View file

@ -65,6 +65,8 @@ public class Account extends AbstractEntity{
private String otrFingerprint; private String otrFingerprint;
private Roster roster = null;
public Account() { public Account() {
this.uuid = "0"; this.uuid = "0";
} }
@ -287,4 +289,11 @@ public class Account extends AbstractEntity{
return null; return null;
} }
} }
public Roster getRoster() {
if (this.roster==null) {
this.roster = new Roster(this);
}
return this.roster;
}
} }

View file

@ -4,33 +4,30 @@ import java.io.Serializable;
import java.util.HashSet; import java.util.HashSet;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Set; import java.util.Set;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
import android.content.ContentValues; import android.content.ContentValues;
import android.database.Cursor; import android.database.Cursor;
import android.util.Log;
public class Contact extends AbstractEntity implements Serializable { public class Contact extends AbstractEntity implements Serializable {
private static final long serialVersionUID = -4570817093119419962L; private static final long serialVersionUID = -4570817093119419962L;
public static final String TABLENAME = "contacts"; public static final String TABLENAME = "contacts";
public static final String DISPLAYNAME = "name"; public static final String SYSTEMNAME = "systemname";
public static final String SERVERNAME = "servername";
public static final String JID = "jid"; public static final String JID = "jid";
public static final String SUBSCRIPTION = "subscription"; public static final String OPTIONS = "options";
public static final String SYSTEMACCOUNT = "systemaccount"; public static final String SYSTEMACCOUNT = "systemaccount";
public static final String PHOTOURI = "photouri"; public static final String PHOTOURI = "photouri";
public static final String KEYS = "pgpkey"; public static final String KEYS = "pgpkey";
public static final String PRESENCES = "presences";
public static final String ACCOUNT = "accountUuid"; public static final String ACCOUNT = "accountUuid";
protected String accountUuid; protected String accountUuid;
protected String displayName; protected String systemName;
protected String serverName;
protected String jid; protected String jid;
protected int subscription = 0; protected int subscription = 0;
protected String systemAccount; protected String systemAccount;
@ -42,26 +39,13 @@ public class Contact extends AbstractEntity implements Serializable {
protected boolean inRoster = true; protected boolean inRoster = true;
public Contact(Account account, String displayName, String jid, public Contact(String uuid, String account, String systemName,
String photoUri) { String serverName, String jid, int subscription, String photoUri,
if (account == null) { String systemAccount, String keys) {
this.accountUuid = null;
} else {
this.accountUuid = account.getUuid();
}
this.account = account;
this.displayName = displayName;
this.jid = jid;
this.photoUri = photoUri;
this.uuid = java.util.UUID.randomUUID().toString();
}
public Contact(String uuid, String account, String displayName, String jid,
int subscription, String photoUri, String systemAccount,
String keys, String presences) {
this.uuid = uuid; this.uuid = uuid;
this.accountUuid = account; this.accountUuid = account;
this.displayName = displayName; this.systemName = systemName;
this.serverName = serverName;
this.jid = jid; this.jid = jid;
this.subscription = subscription; this.subscription = subscription;
this.photoUri = photoUri; this.photoUri = photoUri;
@ -74,11 +58,20 @@ public class Contact extends AbstractEntity implements Serializable {
} catch (JSONException e) { } catch (JSONException e) {
this.keys = new JSONObject(); this.keys = new JSONObject();
} }
this.presences = Presences.fromJsonString(presences); }
public Contact(String jid) {
this.jid = jid;
} }
public String getDisplayName() { public String getDisplayName() {
return this.displayName; if (this.systemName != null) {
return this.systemName;
} else if (this.serverName != null) {
return this.serverName;
} else {
return this.jid.split("@")[0];
}
} }
public String getProfilePhoto() { public String getProfilePhoto() {
@ -90,7 +83,7 @@ public class Contact extends AbstractEntity implements Serializable {
} }
public boolean match(String needle) { public boolean match(String needle) {
return (jid.toLowerCase().contains(needle.toLowerCase()) || (displayName return (jid.toLowerCase().contains(needle.toLowerCase()) || (getDisplayName()
.toLowerCase().contains(needle.toLowerCase()))); .toLowerCase().contains(needle.toLowerCase())));
} }
@ -99,26 +92,26 @@ public class Contact extends AbstractEntity implements Serializable {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(UUID, uuid); values.put(UUID, uuid);
values.put(ACCOUNT, accountUuid); values.put(ACCOUNT, accountUuid);
values.put(DISPLAYNAME, displayName); values.put(SYSTEMNAME, systemName);
values.put(SERVERNAME, serverName);
values.put(JID, jid); values.put(JID, jid);
values.put(SUBSCRIPTION, subscription); values.put(OPTIONS, subscription);
values.put(SYSTEMACCOUNT, systemAccount); values.put(SYSTEMACCOUNT, systemAccount);
values.put(PHOTOURI, photoUri); values.put(PHOTOURI, photoUri);
values.put(KEYS, keys.toString()); values.put(KEYS, keys.toString());
values.put(PRESENCES, presences.toJsonString());
return values; return values;
} }
public static Contact fromCursor(Cursor cursor) { public static Contact fromCursor(Cursor cursor) {
return new Contact(cursor.getString(cursor.getColumnIndex(UUID)), return new Contact(cursor.getString(cursor.getColumnIndex(UUID)),
cursor.getString(cursor.getColumnIndex(ACCOUNT)), cursor.getString(cursor.getColumnIndex(ACCOUNT)),
cursor.getString(cursor.getColumnIndex(DISPLAYNAME)), cursor.getString(cursor.getColumnIndex(SYSTEMNAME)),
cursor.getString(cursor.getColumnIndex(SERVERNAME)),
cursor.getString(cursor.getColumnIndex(JID)), cursor.getString(cursor.getColumnIndex(JID)),
cursor.getInt(cursor.getColumnIndex(SUBSCRIPTION)), cursor.getInt(cursor.getColumnIndex(OPTIONS)),
cursor.getString(cursor.getColumnIndex(PHOTOURI)), cursor.getString(cursor.getColumnIndex(PHOTOURI)),
cursor.getString(cursor.getColumnIndex(SYSTEMACCOUNT)), cursor.getString(cursor.getColumnIndex(SYSTEMACCOUNT)),
cursor.getString(cursor.getColumnIndex(KEYS)), cursor.getString(cursor.getColumnIndex(KEYS)));
cursor.getString(cursor.getColumnIndex(PRESENCES)));
} }
public int getSubscription() { public int getSubscription() {
@ -154,8 +147,8 @@ public class Contact extends AbstractEntity implements Serializable {
return (domainParts[0].equals("conf") return (domainParts[0].equals("conf")
|| domainParts[0].equals("conference") || domainParts[0].equals("conference")
|| domainParts[0].equals("muc") || domainParts[0].equals("muc")
|| domainParts[0].equals("sala") || domainParts[0].equals("sala") || domainParts[0]
|| domainParts[0].equals("salas")); .equals("salas"));
} }
} }
} }
@ -188,8 +181,12 @@ public class Contact extends AbstractEntity implements Serializable {
this.photoUri = uri; this.photoUri = uri;
} }
public void setDisplayName(String name) { public void setServerName(String serverName) {
this.displayName = name; this.serverName = serverName;
}
public void setSystemName(String systemName) {
this.systemName = systemName;
} }
public String getSystemAccount() { public String getSystemAccount() {
@ -249,15 +246,15 @@ public class Contact extends AbstractEntity implements Serializable {
} }
} }
public void setSubscriptionOption(int option) { public void setOption(int option) {
this.subscription |= 1 << option; this.subscription |= 1 << option;
} }
public void resetSubscriptionOption(int option) { public void resetOption(int option) {
this.subscription &= ~(1 << option); this.subscription &= ~(1 << option);
} }
public boolean getSubscriptionOption(int option) { public boolean getOption(int option) {
return ((this.subscription & (1 << option)) != 0); return ((this.subscription & (1 << option)) != 0);
} }
@ -267,40 +264,38 @@ public class Contact extends AbstractEntity implements Serializable {
if (subscription != null) { if (subscription != null) {
if (subscription.equals("to")) { if (subscription.equals("to")) {
this.resetSubscriptionOption(Contact.Subscription.FROM); this.resetOption(Contact.Options.FROM);
this.setSubscriptionOption(Contact.Subscription.TO); this.setOption(Contact.Options.TO);
} else if (subscription.equals("from")) { } else if (subscription.equals("from")) {
this.resetSubscriptionOption(Contact.Subscription.TO); this.resetOption(Contact.Options.TO);
this.setSubscriptionOption(Contact.Subscription.FROM); this.setOption(Contact.Options.FROM);
} else if (subscription.equals("both")) { } else if (subscription.equals("both")) {
this.setSubscriptionOption(Contact.Subscription.TO); this.setOption(Contact.Options.TO);
this.setSubscriptionOption(Contact.Subscription.FROM); this.setOption(Contact.Options.FROM);
} }
} }
if ((ask != null) && (ask.equals("subscribe"))) { if ((ask != null) && (ask.equals("subscribe"))) {
this.setSubscriptionOption(Contact.Subscription.ASKING); this.setOption(Contact.Options.ASKING);
} else { } else {
this.resetSubscriptionOption(Contact.Subscription.ASKING); this.resetOption(Contact.Options.ASKING);
} }
} }
public class Subscription { public Element asElement() {
Element item = new Element("item");
item.setAttribute("jid", this.jid);
if (this.serverName != null) {
item.setAttribute("name", this.serverName);
}
return item;
}
public class Options {
public static final int TO = 0; public static final int TO = 0;
public static final int FROM = 1; public static final int FROM = 1;
public static final int ASKING = 2; public static final int ASKING = 2;
public static final int PREEMPTIVE_GRANT = 4; public static final int PREEMPTIVE_GRANT = 4;
} public static final int IN_ROSTER = 8;
public void flagAsNotInRoster() {
this.inRoster = false;
}
public boolean isInRoster() {
return this.inRoster;
}
public String getAccountUuid() {
return this.accountUuid;
} }
} }

View file

@ -49,7 +49,6 @@ public class Conversation extends AbstractEntity {
private transient List<Message> messages = null; private transient List<Message> messages = null;
private transient Account account = null; private transient Account account = null;
private transient Contact contact;
private transient SessionImpl otrSession; private transient SessionImpl otrSession;
@ -129,19 +128,13 @@ public class Conversation extends AbstractEntity {
public String getName(boolean useSubject) { public String getName(boolean useSubject) {
if ((getMode() == MODE_MULTI) && (getMucOptions().getSubject() != null) && useSubject) { if ((getMode() == MODE_MULTI) && (getMucOptions().getSubject() != null) && useSubject) {
return getMucOptions().getSubject(); return getMucOptions().getSubject();
} else if (this.contact != null) {
return this.contact.getDisplayName();
} else { } else {
return this.name; return this.getContact().getDisplayName();
} }
} }
public String getProfilePhotoString() { public String getProfilePhotoString() {
if (this.contact == null) { return this.getContact().getProfilePhoto();
return null;
} else {
return this.contact.getProfilePhoto();
}
} }
public String getAccountUuid() { public String getAccountUuid() {
@ -153,14 +146,7 @@ public class Conversation extends AbstractEntity {
} }
public Contact getContact() { public Contact getContact() {
return this.contact; return this.account.getRoster().getContact(this.contactJid);
}
public void setContact(Contact contact) {
this.contact = contact;
if (contact != null) {
this.contactUuid = contact.getUuid();
}
} }
public void setAccount(Account account) { public void setAccount(Account account) {

View file

@ -4,10 +4,6 @@ import java.util.Hashtable;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
public class Presences { public class Presences {
@ -47,39 +43,6 @@ public class Presences {
return status; return status;
} }
public String toJsonString() {
JSONArray json = new JSONArray();
Iterator<Entry<String, Integer>> it = presences.entrySet().iterator();
while (it.hasNext()) {
Entry<String, Integer> entry = it.next();
JSONObject jObj = new JSONObject();
try {
jObj.put("resource", entry.getKey());
jObj.put("status", entry.getValue());
} catch (JSONException e) {
}
json.put(jObj);
}
return json.toString();
}
public static Presences fromJsonString(String jsonString) {
Presences presences = new Presences();
try {
JSONArray json = new JSONArray(jsonString);
for (int i = 0; i < json.length(); ++i) {
JSONObject jObj = json.getJSONObject(i);
presences.updatePresence(jObj.getString("resource"),
jObj.getInt("status"));
}
} catch (JSONException e1) {
}
return presences;
}
public static int parseShow(Element show) { public static int parseShow(Element show) {
if (show == null) { if (show == null) {
return Presences.ONLINE; return Presences.ONLINE;

View file

@ -0,0 +1,63 @@
package eu.siacs.conversations.entities;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class Roster {
Account account;
HashMap<String, Contact> contacts = new HashMap<String, Contact>();
private String version = null;
public Roster(Account account) {
this.account = account;
}
public boolean hasContact(String jid) {
String cleanJid = jid.split("/")[0];
return contacts.containsKey(cleanJid);
}
public Contact getContact(String jid) {
String cleanJid = jid.split("/")[0];
if (contacts.containsKey(cleanJid)) {
return contacts.get(cleanJid);
} else {
Contact contact = new Contact(cleanJid);
contact.setAccount(account);
contacts.put(cleanJid, contact);
return contact;
}
}
public void clearPresences() {
// TODO Auto-generated method stub
}
public void markAllAsNotInRoster() {
}
public List<Contact> getContacts() {
return new ArrayList<Contact>(this.contacts.values());
}
public void initContact(Contact contact) {
contact.setAccount(account);
contact.setOption(Contact.Options.IN_ROSTER);
contacts.put(contact.getJid(),contact);
}
public void setVersion(String version) {
this.version = version;
}
public String getVersion() {
return this.version;
}
public Account getAccount() {
return this.account;
}
}

View file

@ -10,6 +10,7 @@ import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.Presences; import eu.siacs.conversations.entities.Presences;
import eu.siacs.conversations.entities.Roster;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
@ -23,7 +24,16 @@ public class DatabaseBackend extends SQLiteOpenHelper {
private static DatabaseBackend instance = null; private static DatabaseBackend instance = null;
private static final String DATABASE_NAME = "history"; private static final String DATABASE_NAME = "history";
private static final int DATABASE_VERSION = 3; private static final int DATABASE_VERSION = 5;
private static String CREATE_CONTATCS_STATEMENT = "create table "
+ Contact.TABLENAME + "(" + Contact.UUID + " TEXT PRIMARY KEY, "
+ Contact.ACCOUNT + " TEXT, " + Contact.SERVERNAME + " TEXT, "
+ Contact.SYSTEMNAME + " TEXT," + Contact.JID + " TEXT,"
+ Contact.KEYS + " TEXT," + Contact.PHOTOURI + " TEXT,"
+ Contact.OPTIONS + " NUMBER," + Contact.SYSTEMACCOUNT
+ " NUMBER, " + "FOREIGN KEY(" + Contact.ACCOUNT + ") REFERENCES "
+ Account.TABLENAME + "(" + Account.UUID + ") ON DELETE CASCADE);";
public DatabaseBackend(Context context) { public DatabaseBackend(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION); super(context, DATABASE_NAME, null, DATABASE_VERSION);
@ -36,7 +46,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
+ " TEXT PRIMARY KEY," + Account.USERNAME + " TEXT," + " TEXT PRIMARY KEY," + Account.USERNAME + " TEXT,"
+ Account.SERVER + " TEXT," + Account.PASSWORD + " TEXT," + Account.SERVER + " TEXT," + Account.PASSWORD + " TEXT,"
+ Account.ROSTERVERSION + " TEXT," + Account.OPTIONS + Account.ROSTERVERSION + " TEXT," + Account.OPTIONS
+ " NUMBER, "+Account.KEYS+" TEXT)"); + " NUMBER, " + Account.KEYS + " TEXT)");
db.execSQL("create table " + Conversation.TABLENAME + " (" db.execSQL("create table " + Conversation.TABLENAME + " ("
+ Conversation.UUID + " TEXT PRIMARY KEY, " + Conversation.NAME + Conversation.UUID + " TEXT PRIMARY KEY, " + Conversation.NAME
+ " TEXT, " + Conversation.CONTACT + " TEXT, " + " TEXT, " + Conversation.CONTACT + " TEXT, "
@ -50,31 +60,28 @@ public class DatabaseBackend extends SQLiteOpenHelper {
+ " TEXT PRIMARY KEY, " + Message.CONVERSATION + " TEXT, " + " TEXT PRIMARY KEY, " + Message.CONVERSATION + " TEXT, "
+ Message.TIME_SENT + " NUMBER, " + Message.COUNTERPART + Message.TIME_SENT + " NUMBER, " + Message.COUNTERPART
+ " TEXT, " + Message.BODY + " TEXT, " + Message.ENCRYPTION + " TEXT, " + Message.BODY + " TEXT, " + Message.ENCRYPTION
+ " NUMBER, " + Message.STATUS + " NUMBER," +Message.TYPE +" NUMBER, FOREIGN KEY(" + " NUMBER, " + Message.STATUS + " NUMBER," + Message.TYPE
+ Message.CONVERSATION + ") REFERENCES " + " NUMBER, FOREIGN KEY(" + Message.CONVERSATION
+ Conversation.TABLENAME + "(" + Conversation.UUID + ") REFERENCES " + Conversation.TABLENAME + "("
+ ") ON DELETE CASCADE);"); + Conversation.UUID + ") ON DELETE CASCADE);");
db.execSQL("create table " + Contact.TABLENAME + "(" + Contact.UUID
+ " TEXT PRIMARY KEY, " + Contact.ACCOUNT + " TEXT, " db.execSQL(CREATE_CONTATCS_STATEMENT);
+ Contact.DISPLAYNAME + " TEXT," + Contact.JID + " TEXT,"
+ Contact.PRESENCES + " TEXT, " + Contact.KEYS
+ " TEXT," + Contact.PHOTOURI + " TEXT," + Contact.SUBSCRIPTION
+ " NUMBER," + Contact.SYSTEMACCOUNT + " NUMBER, "
+ "FOREIGN KEY(" + Contact.ACCOUNT + ") REFERENCES "
+ Account.TABLENAME + "(" + Account.UUID
+ ") ON DELETE CASCADE);");
} }
@Override @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < 2 && newVersion >= 2) { if (oldVersion < 2 && newVersion >= 2) {
// enable compression by default. db.execSQL("update " + Account.TABLENAME + " set "
db.execSQL("update " + Account.TABLENAME + Account.OPTIONS + " = " + Account.OPTIONS + " | 8");
+ " set " + Account.OPTIONS + " = " + Account.OPTIONS + " | 8");
} }
if (oldVersion < 3 && newVersion >= 3) { if (oldVersion < 3 && newVersion >= 3) {
//add field type to message db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN "
db.execSQL("ALTER TABLE "+Message.TABLENAME+" ADD COLUMN "+Message.TYPE+" NUMBER");; + Message.TYPE + " NUMBER");
}
if (oldVersion < 5 && newVersion >= 5) {
db.execSQL("DROP TABLE "+Contact.TABLENAME);
db.execSQL(CREATE_CONTATCS_STATEMENT);
db.execSQL("UPDATE "+Account.TABLENAME+ " SET "+Account.ROSTERVERSION+" = NULL");
} }
} }
@ -145,10 +152,10 @@ public class DatabaseBackend extends SQLiteOpenHelper {
public Conversation findConversation(Account account, String contactJid) { public Conversation findConversation(Account account, String contactJid) {
SQLiteDatabase db = this.getReadableDatabase(); SQLiteDatabase db = this.getReadableDatabase();
String[] selectionArgs = { account.getUuid(), contactJid+"%" }; String[] selectionArgs = { account.getUuid(), contactJid + "%" };
Cursor cursor = db.query(Conversation.TABLENAME, null, Cursor cursor = db.query(Conversation.TABLENAME, null,
Conversation.ACCOUNT + "=? AND " + Conversation.CONTACTJID + " like ?", Conversation.ACCOUNT + "=? AND " + Conversation.CONTACTJID
selectionArgs, null, null, null); + " like ?", selectionArgs, null, null, null);
if (cursor.getCount() == 0) if (cursor.getCount() == 0)
return null; return null;
cursor.moveToFirst(); cursor.moveToFirst();
@ -201,86 +208,19 @@ public class DatabaseBackend extends SQLiteOpenHelper {
+ "=?", args); + "=?", args);
} }
public void updateContact(Contact contact, boolean updatePresences) { public void readRoster(Roster roster) {
SQLiteDatabase db = this.getWritableDatabase();
String[] args = { contact.getUuid() };
ContentValues values = contact.getContentValues();
if (!updatePresences) {
values.remove(Contact.PRESENCES);
} else {
values.remove(Contact.DISPLAYNAME);
values.remove(Contact.PHOTOURI);
values.remove(Contact.SYSTEMACCOUNT);
}
db.update(Contact.TABLENAME, contact.getContentValues(), Contact.UUID
+ "=?", args);
}
public void clearPresences(Account account) {
SQLiteDatabase db = this.getWritableDatabase();
String[] args = { account.getUuid() };
ContentValues values = new ContentValues();
values.put(Contact.PRESENCES,"[]");
db.update(Contact.TABLENAME, values, Contact.ACCOUNT
+ "=?", args);
}
public void mergeContacts(List<Contact> contacts) {
SQLiteDatabase db = this.getWritableDatabase();
for (int i = 0; i < contacts.size(); i++) {
Contact contact = contacts.get(i);
String[] columns = {Contact.UUID, Contact.PRESENCES};
String[] args = {contact.getAccount().getUuid(), contact.getJid()};
Cursor cursor = db.query(Contact.TABLENAME, columns,Contact.ACCOUNT+"=? AND "+Contact.JID+"=?", args, null, null, null);
if (cursor.getCount()>=1) {
cursor.moveToFirst();
contact.setUuid(cursor.getString(0));
updateContact(contact,false);
} else {
contact.setUuid(UUID.randomUUID().toString());
createContact(contact);
}
}
}
public List<Contact> getContactsByAccount(Account account) {
List<Contact> list = new ArrayList<Contact>();
SQLiteDatabase db = this.getReadableDatabase(); SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor; Cursor cursor;
if (account==null) { String args[] = { roster.getAccount().getUuid() };
cursor = db.query(Contact.TABLENAME, null, null, null, null, cursor = db.query(Contact.TABLENAME, null, Contact.ACCOUNT + "=?",
null, null); args, null, null, null);
} else {
String args[] = {account.getUuid()};
cursor = db.query(Contact.TABLENAME, null, Contact.ACCOUNT+"=?", args, null,
null, null);
}
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
list.add(Contact.fromCursor(cursor)); roster.initContact(Contact.fromCursor(cursor));
} }
return list;
} }
public List<Contact> getContacts(String where) { public void writeRoster(Roster roster) {
List<Contact> list = new ArrayList<Contact>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(Contact.TABLENAME, null, where, null, null, null, null);
while (cursor.moveToNext()) {
list.add(Contact.fromCursor(cursor));
}
return list;
}
public Contact findContact(Account account, String jid) {
SQLiteDatabase db = this.getReadableDatabase();
String[] selectionArgs = { account.getUuid(), jid };
Cursor cursor = db.query(Contact.TABLENAME, null,
Contact.ACCOUNT + "=? AND " + Contact.JID + "=?",
selectionArgs, null, null, null);
if (cursor.getCount() == 0)
return null;
cursor.moveToFirst();
return Contact.fromCursor(cursor);
} }
public void deleteMessage(Message message) { public void deleteMessage(Message message) {
@ -304,7 +244,8 @@ public class DatabaseBackend extends SQLiteOpenHelper {
public Contact getContact(String uuid) { public Contact getContact(String uuid) {
SQLiteDatabase db = this.getWritableDatabase(); SQLiteDatabase db = this.getWritableDatabase();
String[] args = { uuid }; String[] args = { uuid };
Cursor cursor = db.query(Contact.TABLENAME, null, Contact.UUID + "=?", args, null, null, null); Cursor cursor = db.query(Contact.TABLENAME, null, Contact.UUID + "=?",
args, null, null, null);
if (cursor.getCount() == 0) { if (cursor.getCount() == 0) {
return null; return null;
} }
@ -315,7 +256,8 @@ public class DatabaseBackend extends SQLiteOpenHelper {
public Conversation findConversationByUuid(String conversationUuid) { public Conversation findConversationByUuid(String conversationUuid) {
SQLiteDatabase db = this.getReadableDatabase(); SQLiteDatabase db = this.getReadableDatabase();
String[] selectionArgs = { conversationUuid }; String[] selectionArgs = { conversationUuid };
Cursor cursor = db.query(Conversation.TABLENAME, null, Conversation.UUID + "=?", selectionArgs, null, null, null); Cursor cursor = db.query(Conversation.TABLENAME, null,
Conversation.UUID + "=?", selectionArgs, null, null, null);
if (cursor.getCount() == 0) { if (cursor.getCount() == 0) {
return null; return null;
} }
@ -326,7 +268,8 @@ public class DatabaseBackend extends SQLiteOpenHelper {
public Message findMessageByUuid(String messageUuid) { public Message findMessageByUuid(String messageUuid) {
SQLiteDatabase db = this.getReadableDatabase(); SQLiteDatabase db = this.getReadableDatabase();
String[] selectionArgs = { messageUuid }; String[] selectionArgs = { messageUuid };
Cursor cursor = db.query(Message.TABLENAME, null, Message.UUID + "=?", selectionArgs, null, null, null); Cursor cursor = db.query(Message.TABLENAME, null, Message.UUID + "=?",
selectionArgs, null, null, null);
if (cursor.getCount() == 0) { if (cursor.getCount() == 0) {
return null; return null;
} }
@ -337,7 +280,8 @@ public class DatabaseBackend extends SQLiteOpenHelper {
public Account findAccountByUuid(String accountUuid) { public Account findAccountByUuid(String accountUuid) {
SQLiteDatabase db = this.getReadableDatabase(); SQLiteDatabase db = this.getReadableDatabase();
String[] selectionArgs = { accountUuid }; String[] selectionArgs = { accountUuid };
Cursor cursor = db.query(Account.TABLENAME, null, Account.UUID + "=?", selectionArgs, null, null, null); Cursor cursor = db.query(Account.TABLENAME, null, Account.UUID + "=?",
selectionArgs, null, null, null);
if (cursor.getCount() == 0) { if (cursor.getCount() == 0) {
return null; return null;
} }

View file

@ -27,10 +27,8 @@ import eu.siacs.conversations.entities.Presences;
import eu.siacs.conversations.parser.MessageParser; import eu.siacs.conversations.parser.MessageParser;
import eu.siacs.conversations.persistance.DatabaseBackend; import eu.siacs.conversations.persistance.DatabaseBackend;
import eu.siacs.conversations.persistance.FileBackend; import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.persistance.OnPhoneContactsMerged;
import eu.siacs.conversations.ui.OnAccountListChangedListener; import eu.siacs.conversations.ui.OnAccountListChangedListener;
import eu.siacs.conversations.ui.OnConversationListChangedListener; import eu.siacs.conversations.ui.OnConversationListChangedListener;
import eu.siacs.conversations.ui.OnRosterFetchedListener;
import eu.siacs.conversations.ui.UiCallback; import eu.siacs.conversations.ui.UiCallback;
import eu.siacs.conversations.utils.ExceptionHelper; import eu.siacs.conversations.utils.ExceptionHelper;
import eu.siacs.conversations.utils.OnPhoneContactsLoadedListener; import eu.siacs.conversations.utils.OnPhoneContactsLoadedListener;
@ -57,13 +55,13 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.database.DatabaseUtils;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.Uri; import android.net.Uri;
import android.os.Binder; import android.os.Binder;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.os.Looper;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.PowerManager.WakeLock; import android.os.PowerManager.WakeLock;
import android.os.SystemClock; import android.os.SystemClock;
@ -85,6 +83,8 @@ public class XmppConnectionService extends Service {
private static final int CONNECT_TIMEOUT = 60; private static final int CONNECT_TIMEOUT = 60;
private static final long CARBON_GRACE_PERIOD = 60000L; private static final long CARBON_GRACE_PERIOD = 60000L;
private static String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts";
private MessageParser mMessageParser = new MessageParser(this); private MessageParser mMessageParser = new MessageParser(this);
private List<Account> accounts; private List<Account> accounts;
@ -110,8 +110,9 @@ public class XmppConnectionService extends Service {
@Override @Override
public void onChange(boolean selfChange) { public void onChange(boolean selfChange) {
super.onChange(selfChange); super.onChange(selfChange);
Log.d(LOGTAG, "contact list has changed"); Intent intent = new Intent(getApplicationContext(), XmppConnectionService.class);
mergePhoneContactsWithRoster(null); intent.setAction(ACTION_MERGE_PHONE_CONTACTS);
startService(intent);
} }
}; };
@ -300,17 +301,14 @@ public class XmppConnectionService extends Service {
} }
} else { } else {
Contact contact = findContact(account, fromParts[0]); Contact contact = account.getRoster().getContact(
if (contact == null) { packet.getFrom());
if ("subscribe".equals(type)) { /*
account.getXmppConnection().addPendingSubscription( * if (contact == null) { if ("subscribe".equals(type)) {
fromParts[0]); * account.getXmppConnection().addPendingSubscription(
} else { * fromParts[0]); } else { // Log.d(LOGTAG,packet.getFrom()+
// Log.d(LOGTAG,packet.getFrom()+ * // " could not be found"); } return; }
// " could not be found"); */
}
return;
}
if (type == null) { if (type == null) {
if (fromParts.length == 2) { if (fromParts.length == 2) {
contact.updatePresence(fromParts[1], Presences contact.updatePresence(fromParts[1], Presences
@ -337,9 +335,6 @@ public class XmppConnectionService extends Service {
+ contact.getPgpKeyId()); + contact.getPgpKeyId());
} }
} }
replaceContactInConversation(account,
contact.getJid(), contact);
databaseBackend.updateContact(contact, true);
} else { } else {
// Log.d(LOGTAG,"presence without resource "+packet.toString()); // Log.d(LOGTAG,"presence without resource "+packet.toString());
} }
@ -349,25 +344,16 @@ public class XmppConnectionService extends Service {
} else { } else {
contact.removePresence(fromParts[1]); contact.removePresence(fromParts[1]);
} }
replaceContactInConversation(account, contact.getJid(),
contact);
databaseBackend.updateContact(contact, true);
} else if (type.equals("subscribe")) { } else if (type.equals("subscribe")) {
Log.d(LOGTAG, "received subscribe packet from " Log.d(LOGTAG, "received subscribe packet from "
+ packet.getFrom()); + packet.getFrom());
if (contact if (contact.getOption(Contact.Options.PREEMPTIVE_GRANT)) {
.getSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT)) {
Log.d(LOGTAG, "preemptive grant; granting"); Log.d(LOGTAG, "preemptive grant; granting");
sendPresenceUpdatesTo(contact); sendPresenceUpdatesTo(contact);
contact.setSubscriptionOption(Contact.Subscription.FROM); contact.setOption(Contact.Options.FROM);
contact.resetSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT); contact.resetOption(Contact.Options.PREEMPTIVE_GRANT);
replaceContactInConversation(account, if ((contact.getOption(Contact.Options.ASKING))
contact.getJid(), contact); && (!contact.getOption(Contact.Options.TO))) {
databaseBackend.updateContact(contact, false);
if ((contact
.getSubscriptionOption(Contact.Subscription.ASKING))
&& (!contact
.getSubscriptionOption(Contact.Subscription.TO))) {
requestPresenceUpdatesFrom(contact); requestPresenceUpdatesFrom(contact);
} }
} else { } else {
@ -391,7 +377,6 @@ public class XmppConnectionService extends Service {
if ((from == null) || (from.equals(account.getJid()))) { if ((from == null) || (from.equals(account.getJid()))) {
Element query = packet.findChild("query"); Element query = packet.findChild("query");
processRosterItems(account, query); processRosterItems(account, query);
mergePhoneContactsWithRoster(null);
} else { } else {
Log.d(LOGTAG, "unauthorized roster push from: " + from); Log.d(LOGTAG, "unauthorized roster push from: " + from);
} }
@ -508,50 +493,24 @@ public class XmppConnectionService extends Service {
private void processRosterItems(Account account, Element elements) { private void processRosterItems(Account account, Element elements) {
String version = elements.getAttribute("ver"); String version = elements.getAttribute("ver");
if (version != null) { if (version != null) {
account.setRosterVersion(version); account.getRoster().setVersion(version);
databaseBackend.updateAccount(account);
} }
for (Element item : elements.getChildren()) { for (Element item : elements.getChildren()) {
if (item.getName().equals("item")) { if (item.getName().equals("item")) {
String jid = item.getAttribute("jid"); String jid = item.getAttribute("jid");
String subscription = item.getAttribute("subscription");
Contact contact = databaseBackend.findContact(account, jid);
if (contact == null) {
if (!subscription.equals("remove")) {
String name = item.getAttribute("name"); String name = item.getAttribute("name");
if (name == null) { String subscription = item.getAttribute("subscription");
name = jid.split("@")[0]; Contact contact = account.getRoster().getContact(jid);
} contact.setServerName(name);
contact = new Contact(account, name, jid, null);
contact.parseSubscriptionFromElement(item);
databaseBackend.createContact(contact);
}
} else {
if (subscription.equals("remove")) { if (subscription.equals("remove")) {
databaseBackend.deleteContact(contact); contact.resetOption(Contact.Options.IN_ROSTER);
replaceContactInConversation(account, contact.getJid(),
null);
} else { } else {
contact.setOption(Contact.Options.IN_ROSTER);
contact.parseSubscriptionFromElement(item); contact.parseSubscriptionFromElement(item);
databaseBackend.updateContact(contact, false);
replaceContactInConversation(account, contact.getJid(),
contact);
} }
} }
} }
} }
}
private void replaceContactInConversation(Account account, String jid,
Contact contact) {
List<Conversation> conversations = getConversations();
for (Conversation c : conversations) {
if (c.getContactJid().equals(jid) && (c.getAccount() == account)) {
c.setContact(contact);
break;
}
}
}
public class XmppConnectionBinder extends Binder { public class XmppConnectionBinder extends Binder {
public XmppConnectionService getService() { public XmppConnectionService getService() {
@ -562,7 +521,9 @@ public class XmppConnectionService extends Service {
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
this.wakeLock.acquire(); this.wakeLock.acquire();
// Log.d(LOGTAG,"calling start service. caller was:"+intent.getAction()); if ((intent.getAction()!=null)&&(intent.getAction().equals(ACTION_MERGE_PHONE_CONTACTS))) {
mergePhoneContactsWithRoster();
}
ConnectivityManager cm = (ConnectivityManager) getApplicationContext() ConnectivityManager cm = (ConnectivityManager) getApplicationContext()
.getSystemService(Context.CONNECTIVITY_SERVICE); .getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
@ -636,6 +597,10 @@ public class XmppConnectionService extends Service {
this.fileBackend = new FileBackend(getApplicationContext()); this.fileBackend = new FileBackend(getApplicationContext());
this.accounts = databaseBackend.getAccounts(); this.accounts = databaseBackend.getAccounts();
for (Account account : this.accounts) {
this.databaseBackend.readRoster(account.getRoster());
}
this.mergePhoneContactsWithRoster();
this.getConversations(); this.getConversations();
getContentResolver().registerContentObserver( getContentResolver().registerContentObserver(
@ -654,6 +619,7 @@ public class XmppConnectionService extends Service {
Log.d(LOGTAG, "stopping service"); Log.d(LOGTAG, "stopping service");
super.onDestroy(); super.onDestroy();
for (Account account : accounts) { for (Account account : accounts) {
databaseBackend.writeRoster(account.getRoster());
if (account.getXmppConnection() != null) { if (account.getXmppConnection() != null) {
disconnect(account, true); disconnect(account, true);
} }
@ -725,10 +691,10 @@ public class XmppConnectionService extends Service {
connection.setOnBindListener(new OnBindListener() { connection.setOnBindListener(new OnBindListener() {
@Override @Override
public void onBind(Account account) { public void onBind(final Account account) {
databaseBackend.clearPresences(account); //contact presences account.getRoster().clearPresences();
account.clearPresences(); // self presences account.clearPresences(); // self presences
updateRoster(account, null); fetchRosterFromServer(account);
sendPresence(account); sendPresence(account);
connectMultiModeConversations(account); connectMultiModeConversations(account);
if (convChangedListener != null) { if (convChangedListener != null) {
@ -887,27 +853,7 @@ public class XmppConnectionService extends Service {
return packet; return packet;
} }
private void getRoster(Account account, public void fetchRosterFromServer(Account account) {
final OnRosterFetchedListener listener) {
List<Contact> contacts = databaseBackend.getContactsByAccount(account);
for (int i = 0; i < contacts.size(); ++i) {
contacts.get(i).setAccount(account);
}
if (listener != null) {
listener.onRosterFetched(contacts);
}
}
public List<Contact> getRoster(Account account) {
List<Contact> contacts = databaseBackend.getContactsByAccount(account);
for (int i = 0; i < contacts.size(); ++i) {
contacts.get(i).setAccount(account);
}
return contacts;
}
public void updateRoster(final Account account,
final OnRosterFetchedListener listener) {
IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET); IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET);
if (!"".equals(account.getRosterVersion())) { if (!"".equals(account.getRosterVersion())) {
Log.d(LOGTAG, account.getJid() + ": fetching roster version " Log.d(LOGTAG, account.getJid() + ": fetching roster version "
@ -925,62 +871,23 @@ public class XmppConnectionService extends Service {
IqPacket packet) { IqPacket packet) {
Element roster = packet.findChild("query"); Element roster = packet.findChild("query");
if (roster != null) { if (roster != null) {
Log.d(LOGTAG, account.getJid() account.getRoster().markAllAsNotInRoster();
+ ": processing roster");
processRosterItems(account, roster); processRosterItems(account, roster);
StringBuilder mWhere = new StringBuilder();
mWhere.append("jid NOT IN(");
List<Element> items = roster.getChildren();
for (int i = 0; i < items.size(); ++i) {
mWhere.append(DatabaseUtils
.sqlEscapeString(items.get(i)
.getAttribute("jid")));
if (i != items.size() - 1) {
mWhere.append(",");
}
}
mWhere.append(") and accountUuid = \"");
mWhere.append(account.getUuid());
mWhere.append("\"");
List<Contact> contactsToDelete = databaseBackend
.getContacts(mWhere.toString());
for (Contact contact : contactsToDelete) {
databaseBackend.deleteContact(contact);
replaceContactInConversation(account,
contact.getJid(), null);
}
} else {
Log.d(LOGTAG, account.getJid()
+ ": empty roster returend");
}
mergePhoneContactsWithRoster(new OnPhoneContactsMerged() {
@Override
public void phoneContactsMerged() {
if (listener != null) {
getRoster(account, listener);
} }
} }
}); });
} }
});
}
public void mergePhoneContactsWithRoster( private void mergePhoneContactsWithRoster() {
final OnPhoneContactsMerged listener) {
PhoneHelper.loadPhoneContacts(getApplicationContext(), PhoneHelper.loadPhoneContacts(getApplicationContext(),
new OnPhoneContactsLoadedListener() { new OnPhoneContactsLoadedListener() {
@Override @Override
public void onPhoneContactsLoaded( public void onPhoneContactsLoaded(List<Bundle> phoneContacts) {
Hashtable<String, Bundle> phoneContacts) { for (Bundle phoneContact : phoneContacts) {
List<Contact> contacts = databaseBackend for (Account account : accounts) {
.getContactsByAccount(null); String jid = phoneContact.getString("jid");
for (int i = 0; i < contacts.size(); ++i) { Contact contact = account.getRoster()
Contact contact = contacts.get(i); .getContact(jid);
if (phoneContacts.containsKey(contact.getJid())) {
Bundle phoneContact = phoneContacts.get(contact
.getJid());
String systemAccount = phoneContact String systemAccount = phoneContact
.getInt("phoneid") .getInt("phoneid")
+ "#" + "#"
@ -988,29 +895,11 @@ public class XmppConnectionService extends Service {
contact.setSystemAccount(systemAccount); contact.setSystemAccount(systemAccount);
contact.setPhotoUri(phoneContact contact.setPhotoUri(phoneContact
.getString("photouri")); .getString("photouri"));
contact.setDisplayName(phoneContact contact.setSystemName(phoneContact
.getString("displayname")); .getString("displayname"));
databaseBackend.updateContact(contact, false);
replaceContactInConversation(
contact.getAccount(), contact.getJid(),
contact);
} else {
if ((contact.getSystemAccount() != null)
|| (contact.getProfilePhoto() != null)) {
contact.setSystemAccount(null);
contact.setPhotoUri(null);
databaseBackend.updateContact(contact,
false);
replaceContactInConversation(
contact.getAccount(),
contact.getJid(), contact);
} }
} }
} }
if (listener != null) {
listener.phoneContactsMerged();
}
}
}); });
} }
@ -1025,7 +914,6 @@ public class XmppConnectionService extends Service {
for (Conversation conv : this.conversations) { for (Conversation conv : this.conversations) {
Account account = accountLookupTable.get(conv.getAccountUuid()); Account account = accountLookupTable.get(conv.getAccountUuid());
conv.setAccount(account); conv.setAccount(account);
conv.setContact(findContact(account, conv.getContactJid()));
conv.setMessages(databaseBackend.getMessages(conv, 50)); conv.setMessages(databaseBackend.getMessages(conv, 50));
} }
} }
@ -1043,14 +931,6 @@ public class XmppConnectionService extends Service {
return this.accounts; return this.accounts;
} }
public Contact findContact(Account account, String jid) {
Contact contact = databaseBackend.findContact(account, jid);
if (contact != null) {
contact.setAccount(account);
}
return contact;
}
public Conversation findOrCreateConversation(Account account, String jid, public Conversation findOrCreateConversation(Account account, String jid,
boolean muc) { boolean muc) {
for (Conversation conv : this.getConversations()) { for (Conversation conv : this.getConversations()) {
@ -1072,11 +952,9 @@ public class XmppConnectionService extends Service {
conversation.setMessages(databaseBackend.getMessages(conversation, conversation.setMessages(databaseBackend.getMessages(conversation,
50)); 50));
this.databaseBackend.updateConversation(conversation); this.databaseBackend.updateConversation(conversation);
conversation.setContact(findContact(account,
conversation.getContactJid()));
} else { } else {
String conversationName; String conversationName;
Contact contact = findContact(account, jid); Contact contact = account.getRoster().getContact(jid);
if (contact != null) { if (contact != null) {
conversationName = contact.getDisplayName(); conversationName = contact.getDisplayName();
} else { } else {
@ -1089,7 +967,6 @@ public class XmppConnectionService extends Service {
conversation = new Conversation(conversationName, account, jid, conversation = new Conversation(conversationName, account, jid,
Conversation.MODE_SINGLE); Conversation.MODE_SINGLE);
} }
conversation.setContact(contact);
this.databaseBackend.createConversation(conversation); this.databaseBackend.createConversation(conversation);
} }
this.conversations.add(conversation); this.conversations.add(conversation);
@ -1137,17 +1014,6 @@ public class XmppConnectionService extends Service {
accountChangedListener.onAccountListChangedListener(); accountChangedListener.onAccountListChangedListener();
} }
public void deleteContact(Contact contact) {
IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
Element query = iq.query("jabber:iq:roster");
query.addChild("item").setAttribute("jid", contact.getJid())
.setAttribute("subscription", "remove");
contact.getAccount().getXmppConnection().sendIqPacket(iq, null);
replaceContactInConversation(contact.getAccount(), contact.getJid(),
null);
databaseBackend.deleteContact(contact);
}
public void updateAccount(Account account) { public void updateAccount(Account account) {
this.statusListener.onStatusChanged(account); this.statusListener.onStatusChanged(account);
databaseBackend.updateAccount(account); databaseBackend.updateAccount(account);
@ -1308,12 +1174,6 @@ public class XmppConnectionService extends Service {
return mBinder; return mBinder;
} }
public void updateContact(Contact contact) {
databaseBackend.updateContact(contact, false);
replaceContactInConversation(contact.getAccount(), contact.getJid(),
contact);
}
public void updateMessage(Message message) { public void updateMessage(Message message) {
databaseBackend.updateMessage(message); databaseBackend.updateMessage(message);
} }
@ -1322,30 +1182,34 @@ public class XmppConnectionService extends Service {
SharedPreferences sharedPref = getPreferences(); SharedPreferences sharedPref = getPreferences();
boolean autoGrant = sharedPref.getBoolean("grant_new_contacts", true); boolean autoGrant = sharedPref.getBoolean("grant_new_contacts", true);
if (autoGrant) { if (autoGrant) {
contact.setSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT); contact.setOption(Contact.Options.PREEMPTIVE_GRANT);
contact.setSubscriptionOption(Contact.Subscription.ASKING); contact.setOption(Contact.Options.ASKING);
} }
databaseBackend.createContact(contact); pushContactToServer(contact);
IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
Element query = new Element("query");
query.setAttribute("xmlns", "jabber:iq:roster");
Element item = new Element("item");
item.setAttribute("jid", contact.getJid());
item.setAttribute("name", contact.getJid());
query.addChild(item);
iq.addChild(query);
Account account = contact.getAccount();
account.getXmppConnection().sendIqPacket(iq, null);
if (autoGrant) { if (autoGrant) {
requestPresenceUpdatesFrom(contact); requestPresenceUpdatesFrom(contact);
if (account.getXmppConnection().hasPendingSubscription( if (contact.getAccount().getXmppConnection().hasPendingSubscription(
contact.getJid())) { contact.getJid())) {
Log.d("xmppService", "contact had pending subscription"); Log.d("xmppService", "contact had pending subscription");
sendPresenceUpdatesTo(contact); sendPresenceUpdatesTo(contact);
} }
} }
replaceContactInConversation(contact.getAccount(), contact.getJid(), }
contact);
public void pushContactToServer(Contact contact) {
IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
iq.query("jabber:iq:roster").addChild(contact.asElement());
Account account = contact.getAccount();
account.getXmppConnection().sendIqPacket(iq, null);
}
public void deleteContactOnServer(Contact contact) {
IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
Element item = iq.query("jabber:iq:roster").addChild("item");
item.setAttribute("jid", contact.getJid());
item.setAttribute("subscription", "remove");
Account account = contact.getAccount();
account.getXmppConnection().sendIqPacket(iq, null);
} }
public void requestPresenceUpdatesFrom(Contact contact) { public void requestPresenceUpdatesFrom(Contact contact) {
@ -1392,11 +1256,10 @@ public class XmppConnectionService extends Service {
PresencePacket packet = new PresencePacket(); PresencePacket packet = new PresencePacket();
packet.setAttribute("from", account.getFullJid()); packet.setAttribute("from", account.getFullJid());
String sig = account.getPgpSignature(); String sig = account.getPgpSignature();
if (sig!=null) { if (sig != null) {
packet.addChild("status").setContent("online"); packet.addChild("status").setContent("online");
packet.addChild("x","jabber:x:signed").setContent(sig); packet.addChild("x", "jabber:x:signed").setContent(sig);
} }
Log.d(LOGTAG,packet.toString());
account.getXmppConnection().sendPresencePacket(packet); account.getXmppConnection().sendPresencePacket(packet);
} }
@ -1404,18 +1267,6 @@ public class XmppConnectionService extends Service {
this.databaseBackend.updateConversation(conversation); this.databaseBackend.updateConversation(conversation);
} }
public Contact findContact(String uuid) {
Contact contact = this.databaseBackend.getContact(uuid);
if (contact != null) {
for (Account account : getAccounts()) {
if (contact.getAccountUuid().equals(account.getUuid())) {
contact.setAccount(account);
}
}
}
return contact;
}
public void removeOnTLSExceptionReceivedListener() { public void removeOnTLSExceptionReceivedListener() {
this.tlsException = null; this.tlsException = null;
} }
@ -1517,4 +1368,13 @@ public class XmppConnectionService extends Service {
getConversations(), conversation, notify); getConversations(), conversation, notify);
} }
} }
public Account findAccountByJid(String accountJid) {
for (Account account : this.accounts) {
if (account.getJid().equals(accountJid)) {
return account;
}
}
return null;
}
} }

View file

@ -1,8 +1,6 @@
package eu.siacs.conversations.ui; package eu.siacs.conversations.ui;
import java.math.BigInteger;
import java.util.Iterator; import java.util.Iterator;
import java.util.Locale;
import org.openintents.openpgp.util.OpenPgpUtils; import org.openintents.openpgp.util.OpenPgpUtils;
@ -17,7 +15,6 @@ import android.os.Bundle;
import android.provider.ContactsContract.CommonDataKinds; import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Intents; import android.provider.ContactsContract.Intents;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
@ -31,6 +28,7 @@ import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import eu.siacs.conversations.R; import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.PgpEngine; import eu.siacs.conversations.crypto.PgpEngine;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Presences; import eu.siacs.conversations.entities.Presences;
import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.utils.UIHelper;
@ -40,12 +38,14 @@ public class ContactDetailsActivity extends XmppActivity {
protected ContactDetailsActivity activity = this; protected ContactDetailsActivity activity = this;
private String uuid;
private Contact contact; private Contact contact;
private String accountJid;
private String contactJid;
private EditText name; private EditText name;
private TextView contactJid; private TextView contactJidTv;
private TextView accountJid; private TextView accountJidTv;
private TextView status; private TextView status;
private TextView askAgain; private TextView askAgain;
private CheckBox send; private CheckBox send;
@ -56,7 +56,7 @@ public class ContactDetailsActivity extends XmppActivity {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
activity.xmppConnectionService.deleteContact(contact); activity.xmppConnectionService.deleteContactOnServer(contact);
activity.finish(); activity.finish();
} }
}; };
@ -65,8 +65,8 @@ public class ContactDetailsActivity extends XmppActivity {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
contact.setDisplayName(name.getText().toString()); contact.setServerName(name.getText().toString());
activity.xmppConnectionService.updateContact(contact); activity.xmppConnectionService.pushContactToServer(contact);
populateView(); populateView();
} }
}; };
@ -104,12 +104,13 @@ public class ContactDetailsActivity extends XmppActivity {
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (getIntent().getAction().equals(ACTION_VIEW_CONTACT)) { if (getIntent().getAction().equals(ACTION_VIEW_CONTACT)) {
this.uuid = getIntent().getExtras().getString("uuid"); this.accountJid = getIntent().getExtras().getString("account");
this.contactJid = getIntent().getExtras().getString("contact");
} }
setContentView(R.layout.activity_contact_details); setContentView(R.layout.activity_contact_details);
contactJid = (TextView) findViewById(R.id.details_contactjid); contactJidTv = (TextView) findViewById(R.id.details_contactjid);
accountJid = (TextView) findViewById(R.id.details_account); accountJidTv = (TextView) findViewById(R.id.details_account);
status = (TextView) findViewById(R.id.details_contactstatus); status = (TextView) findViewById(R.id.details_contactstatus);
send = (CheckBox) findViewById(R.id.details_send_presence); send = (CheckBox) findViewById(R.id.details_send_presence);
receive = (CheckBox) findViewById(R.id.details_receive_presence); receive = (CheckBox) findViewById(R.id.details_receive_presence);
@ -170,18 +171,18 @@ public class ContactDetailsActivity extends XmppActivity {
private void populateView() { private void populateView() {
setTitle(contact.getDisplayName()); setTitle(contact.getDisplayName());
if (contact.getSubscriptionOption(Contact.Subscription.FROM)) { if (contact.getOption(Contact.Options.FROM)) {
send.setChecked(true); send.setChecked(true);
} else { } else {
send.setText(R.string.preemptively_grant); send.setText(R.string.preemptively_grant);
if (contact if (contact
.getSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT)) { .getOption(Contact.Options.PREEMPTIVE_GRANT)) {
send.setChecked(true); send.setChecked(true);
} else { } else {
send.setChecked(false); send.setChecked(false);
} }
} }
if (contact.getSubscriptionOption(Contact.Subscription.TO)) { if (contact.getOption(Contact.Options.TO)) {
receive.setChecked(true); receive.setChecked(true);
} else { } else {
receive.setText(R.string.ask_for_presence_updates); receive.setText(R.string.ask_for_presence_updates);
@ -195,7 +196,7 @@ public class ContactDetailsActivity extends XmppActivity {
} }
}); });
if (contact.getSubscriptionOption(Contact.Subscription.ASKING)) { if (contact.getOption(Contact.Options.ASKING)) {
receive.setChecked(true); receive.setChecked(true);
} else { } else {
receive.setChecked(false); receive.setChecked(false);
@ -233,11 +234,11 @@ public class ContactDetailsActivity extends XmppActivity {
break; break;
} }
if (contact.getPresences().size() > 1) { if (contact.getPresences().size() > 1) {
contactJid.setText(contact.getJid()+" ("+contact.getPresences().size()+")"); contactJidTv.setText(contact.getJid()+" ("+contact.getPresences().size()+")");
} else { } else {
contactJid.setText(contact.getJid()); contactJidTv.setText(contact.getJid());
} }
accountJid.setText(contact.getAccount().getJid()); accountJidTv.setText(contact.getAccount().getJid());
UIHelper.prepareContactBadge(this, badge, contact, getApplicationContext()); UIHelper.prepareContactBadge(this, badge, contact, getApplicationContext());
@ -286,65 +287,66 @@ public class ContactDetailsActivity extends XmppActivity {
@Override @Override
public void onBackendConnected() { public void onBackendConnected() {
if (uuid != null) { if ((accountJid != null)&&(contactJid != null)) {
this.contact = xmppConnectionService.findContact(uuid); Account account = xmppConnectionService.findAccountByJid(accountJid);
if (this.contact != null) { if (account==null) {
populateView(); return;
} }
this.contact = account.getRoster().getContact(contactJid);
populateView();
} }
} }
@Override @Override
protected void onStop() { protected void onStop() {
super.onStop(); super.onStop();
boolean needsUpdating = false; boolean updated = false;
if (contact.getSubscriptionOption(Contact.Subscription.FROM)) { if (contact.getOption(Contact.Options.FROM)) {
if (!send.isChecked()) { if (!send.isChecked()) {
contact.resetSubscriptionOption(Contact.Subscription.FROM); contact.resetOption(Contact.Options.FROM);
contact.resetSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT); contact.resetOption(Contact.Options.PREEMPTIVE_GRANT);
activity.xmppConnectionService.stopPresenceUpdatesTo(contact); activity.xmppConnectionService.stopPresenceUpdatesTo(contact);
needsUpdating = true; updated = true;
} }
} else { } else {
if (contact if (contact
.getSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT)) { .getOption(Contact.Options.PREEMPTIVE_GRANT)) {
if (!send.isChecked()) { if (!send.isChecked()) {
contact.resetSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT); contact.resetOption(Contact.Options.PREEMPTIVE_GRANT);
needsUpdating = true; updated = true;
} }
} else { } else {
if (send.isChecked()) { if (send.isChecked()) {
contact.setSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT); contact.setOption(Contact.Options.PREEMPTIVE_GRANT);
needsUpdating = true; updated = true;
} }
} }
} }
if (contact.getSubscriptionOption(Contact.Subscription.TO)) { if (contact.getOption(Contact.Options.TO)) {
if (!receive.isChecked()) { if (!receive.isChecked()) {
contact.resetSubscriptionOption(Contact.Subscription.TO); contact.resetOption(Contact.Options.TO);
activity.xmppConnectionService.stopPresenceUpdatesFrom(contact); activity.xmppConnectionService.stopPresenceUpdatesFrom(contact);
needsUpdating = true; updated = true;
} }
} else { } else {
if (contact.getSubscriptionOption(Contact.Subscription.ASKING)) { if (contact.getOption(Contact.Options.ASKING)) {
if (!receive.isChecked()) { if (!receive.isChecked()) {
contact.resetSubscriptionOption(Contact.Subscription.ASKING); contact.resetOption(Contact.Options.ASKING);
activity.xmppConnectionService activity.xmppConnectionService
.stopPresenceUpdatesFrom(contact); .stopPresenceUpdatesFrom(contact);
needsUpdating = true; updated = true;
} }
} else { } else {
if (receive.isChecked()) { if (receive.isChecked()) {
contact.setSubscriptionOption(Contact.Subscription.ASKING); contact.setOption(Contact.Options.ASKING);
activity.xmppConnectionService activity.xmppConnectionService
.requestPresenceUpdatesFrom(contact); .requestPresenceUpdatesFrom(contact);
needsUpdating = true; updated = true;
} }
} }
} }
if (needsUpdating) { if (updated) {
Toast.makeText(getApplicationContext(), "Subscription updated", Toast.LENGTH_SHORT).show(); Toast.makeText(getApplicationContext(), "Subscription updated", Toast.LENGTH_SHORT).show();
activity.xmppConnectionService.updateContact(contact);
} }
} }

View file

@ -18,7 +18,6 @@ import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.util.Log;
import android.util.SparseBooleanArray; import android.util.SparseBooleanArray;
import android.view.ActionMode; import android.view.ActionMode;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -34,13 +33,11 @@ import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ListView; import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.Toast; import android.widget.Toast;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@ -130,8 +127,10 @@ public class ContactsActivity extends XmppActivity {
Intent intent = new Intent(getApplicationContext(), Intent intent = new Intent(getApplicationContext(),
ContactDetailsActivity.class); ContactDetailsActivity.class);
intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT); intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT);
intent.putExtra("uuid", selectedContacts.get(0).getUuid()); intent.putExtra("account", selectedContacts.get(0).getAccount().getJid());
intent.putExtra("contact",selectedContacts.get(0).getJid());
startActivity(intent); startActivity(intent);
finish();
break; break;
case R.id.action_invite: case R.id.action_invite:
invite(); invite();
@ -270,7 +269,7 @@ public class ContactsActivity extends XmppActivity {
aggregatedContacts.clear(); aggregatedContacts.clear();
for (Contact contact : rosterContacts) { for (Contact contact : rosterContacts) {
if (contact.match(searchString)) if (contact.match(searchString)&&(contact.getOption(Contact.Options.IN_ROSTER)))
aggregatedContacts.add(contact); aggregatedContacts.add(contact);
} }
@ -287,9 +286,8 @@ public class ContactsActivity extends XmppActivity {
if (aggregatedContacts.size() == 0) { if (aggregatedContacts.size() == 0) {
if (Validator.isValidJid(searchString)) { if (Validator.isValidJid(searchString)) {
String name = searchString.split("@")[0]; Contact newContact = new Contact(searchString);
Contact newContact = new Contact(null, name, searchString, null); newContact.resetOption(Contact.Options.IN_ROSTER);
newContact.flagAsNotInRoster();
aggregatedContacts.add(newContact); aggregatedContacts.add(newContact);
contactsHeader.setText("Create new contact"); contactsHeader.setText("Create new contact");
} else { } else {
@ -463,7 +461,7 @@ public class ContactsActivity extends XmppActivity {
} }
public void startConversation(Contact contact, Account account, boolean muc) { public void startConversation(Contact contact, Account account, boolean muc) {
if (!contact.isInRoster()&&(!muc)) { if (!contact.getOption(Contact.Options.IN_ROSTER)&&(!muc)) {
xmppConnectionService.createContact(contact); xmppConnectionService.createContact(contact);
} }
Conversation conversation = xmppConnectionService Conversation conversation = xmppConnectionService
@ -517,7 +515,7 @@ public class ContactsActivity extends XmppActivity {
this.rosterContacts.clear(); this.rosterContacts.clear();
for(Account account : accounts) { for(Account account : accounts) {
if (account.getStatus() != Account.STATUS_DISABLED) { if (account.getStatus() != Account.STATUS_DISABLED) {
rosterContacts.addAll(xmppConnectionService.getRoster(account)); rosterContacts.addAll(account.getRoster().getContacts());
} }
} }
updateAggregatedContacts(); updateAggregatedContacts();
@ -533,52 +531,12 @@ public class ContactsActivity extends XmppActivity {
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.action_refresh_contacts:
refreshContacts();
break;
default: default:
break; break;
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
private void refreshContacts() {
final ProgressBar progress = (ProgressBar) findViewById(R.id.progressBar1);
final EditText searchBar = (EditText) findViewById(R.id.new_conversation_search);
final TextView contactsHeader = (TextView) findViewById(R.id.contacts_header);
final ListView contactList = (ListView) findViewById(R.id.contactList);
searchBar.setVisibility(View.GONE);
contactsHeader.setVisibility(View.GONE);
contactList.setVisibility(View.GONE);
progress.setVisibility(View.VISIBLE);
this.accounts = xmppConnectionService.getAccounts();
this.rosterContacts.clear();
for (int i = 0; i < accounts.size(); ++i) {
if (accounts.get(i).getStatus() == Account.STATUS_ONLINE) {
xmppConnectionService.updateRoster(accounts.get(i),
new OnRosterFetchedListener() {
@Override
public void onRosterFetched(
final List<Contact> roster) {
runOnUiThread(new Runnable() {
@Override
public void run() {
rosterContacts.addAll(roster);
progress.setVisibility(View.GONE);
searchBar.setVisibility(View.VISIBLE);
contactList.setVisibility(View.VISIBLE);
contactList.setVisibility(View.VISIBLE);
updateAggregatedContacts();
}
});
}
});
}
}
}
@Override @Override
public void onActionModeStarted(ActionMode mode) { public void onActionModeStarted(ActionMode mode) {
super.onActionModeStarted(mode); super.onActionModeStarted(mode);

View file

@ -474,10 +474,11 @@ public class ConversationActivity extends XmppActivity {
break; break;
case R.id.action_contact_details: case R.id.action_contact_details:
Contact contact = this.getSelectedConversation().getContact(); Contact contact = this.getSelectedConversation().getContact();
if (contact != null) { if (contact.getOption(Contact.Options.IN_ROSTER)) {
Intent intent = new Intent(this, ContactDetailsActivity.class); Intent intent = new Intent(this, ContactDetailsActivity.class);
intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT); intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT);
intent.putExtra("uuid", contact.getUuid()); intent.putExtra("account", this.getSelectedConversation().getAccount().getJid());
intent.putExtra("contact",contact.getJid());
startActivity(intent); startActivity(intent);
} else { } else {
showAddToRosterDialog(getSelectedConversation()); showAddToRosterDialog(getSelectedConversation());
@ -874,8 +875,7 @@ public class ConversationActivity extends XmppActivity {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
String jid = conversation.getContactJid(); String jid = conversation.getContactJid();
Account account = getSelectedConversation().getAccount(); Account account = getSelectedConversation().getAccount();
String name = jid.split("@")[0]; Contact contact = account.getRoster().getContact(jid);
Contact contact = new Contact(account, name, jid, null);
xmppConnectionService.createContact(contact); xmppConnectionService.createContact(contact);
} }
}); });

View file

@ -102,7 +102,7 @@ public class ShareWithActivity extends XmppActivity {
contacts.removeAllViews(); contacts.removeAllViews();
final List<Contact> contactsList = new ArrayList<Contact>(); final List<Contact> contactsList = new ArrayList<Contact>();
for(Account account : xmppConnectionService.getAccounts()) { for(Account account : xmppConnectionService.getAccounts()) {
for(final Contact contact : xmppConnectionService.getRoster(account)) { for(final Contact contact : account.getRoster().getContacts()) {
if (!displayedContacts.contains(contact.getUuid())) { if (!displayedContacts.contains(contact.getUuid())) {
contactsList.add(contact); contactsList.add(contact);
} }

View file

@ -1,9 +1,9 @@
package eu.siacs.conversations.utils; package eu.siacs.conversations.utils;
import java.util.Hashtable; import java.util.List;
import android.os.Bundle; import android.os.Bundle;
public interface OnPhoneContactsLoadedListener { public interface OnPhoneContactsLoadedListener {
public void onPhoneContactsLoaded(Hashtable<String, Bundle> phoneContacts); public void onPhoneContactsLoaded(List<Bundle> phoneContacts);
} }

View file

@ -1,8 +1,8 @@
package eu.siacs.conversations.utils; package eu.siacs.conversations.utils;
import java.util.Hashtable; import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.CursorLoader; import android.content.CursorLoader;
import android.content.Loader; import android.content.Loader;
@ -10,20 +10,14 @@ import android.content.Loader.OnLoadCompleteListener;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Looper;
import android.provider.ContactsContract; import android.provider.ContactsContract;
import android.provider.ContactsContract.Profile; import android.provider.ContactsContract.Profile;
import android.provider.MediaStore;
public class PhoneHelper { public class PhoneHelper {
public static void loadPhoneContacts(Context context, public static void loadPhoneContacts(Context context,
final OnPhoneContactsLoadedListener listener) { final OnPhoneContactsLoadedListener listener) {
if (Looper.myLooper() == null) { final List<Bundle> phoneContacts = new ArrayList<Bundle>();
Looper.prepare();
}
final Looper mLooper = Looper.myLooper();
final Hashtable<String, Bundle> phoneContacts = new Hashtable<String, Bundle>();
final String[] PROJECTION = new String[] { ContactsContract.Data._ID, final String[] PROJECTION = new String[] { ContactsContract.Data._ID,
ContactsContract.Data.DISPLAY_NAME, ContactsContract.Data.DISPLAY_NAME,
@ -58,15 +52,14 @@ public class PhoneHelper {
.getColumnIndex(ContactsContract.Data.PHOTO_THUMBNAIL_URI))); .getColumnIndex(ContactsContract.Data.PHOTO_THUMBNAIL_URI)));
contact.putString("lookup", cursor.getString(cursor contact.putString("lookup", cursor.getString(cursor
.getColumnIndex(ContactsContract.Data.LOOKUP_KEY))); .getColumnIndex(ContactsContract.Data.LOOKUP_KEY)));
phoneContacts.put(
cursor.getString(cursor contact.putString("jid",cursor.getString(cursor
.getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA)), .getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA)));
contact); phoneContacts.add(contact);
} }
if (listener != null) { if (listener != null) {
listener.onPhoneContactsLoaded(phoneContacts); listener.onPhoneContactsLoaded(phoneContacts);
} }
mLooper.quit();
} }
}); });
mCursorLoader.startLoading(); mCursorLoader.startLoading();

View file

@ -506,7 +506,7 @@ public class UIHelper {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
contact.addOtrFingerprint(conversation.getOtrFingerprint()); contact.addOtrFingerprint(conversation.getOtrFingerprint());
msg.setVisibility(View.GONE); msg.setVisibility(View.GONE);
activity.xmppConnectionService.updateContact(contact); //activity.xmppConnectionService.updateContact(contact);
} }
}); });
builder.setView(view); builder.setView(view);