add contact to roster if a new conversation is created

Daniel Gultsch created

Change summary

res/xml/preferences.xml                                 |  23 +
src/de/gultsch/chat/entities/Contact.java               |  11 
src/de/gultsch/chat/services/XmppConnectionService.java | 145 ++++++----
src/de/gultsch/chat/ui/NewConversationActivity.java     |   5 
4 files changed, 109 insertions(+), 75 deletions(-)

Detailed changes

res/xml/preferences.xml 🔗

@@ -1,22 +1,23 @@
 <?xml version="1.0" encoding="utf-8"?>
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
     <PreferenceCategory 
-        android:title="Security">
-        <CheckBoxPreference
-            android:key="trust_unknown_tls_certificates"
-            android:title="Trust TLS certificates"
-            android:summary="Accounts with untrusted certificates simply will not connect to server"
-            />
+        android:title="Security and Privacy Options">
         <ListPreference
             android:key="default_conversation_encryption_type"
             android:title="Default conversation encryption"
             android:dialogTitle="Default conversation encryption"
             android:entries="@array/conversation_encryption_type_entries"
             android:entryValues="@array/conversation_encryption_type_values"
-            android:defaultValue="pgp"/>
+            android:defaultValue="none"/>
+        <CheckBoxPreference 
+            android:key="grant_new_contacts"
+            android:title="Grant presence updates"
+            android:summary="Preemptivly grant and ask for presence subscription for contacts you created"
+            android:defaultValue="true"
+            />
     </PreferenceCategory>
     <PreferenceCategory 
-        android:title="Notification settings">
+        android:title="Notification Settings">
         <CheckBoxPreference 
             android:key="show_notification"
             android:title="Notification"
@@ -33,9 +34,13 @@
             android:ringtoneType="notification"
             android:dependency="show_notification"
             android:summary="Play ringtone with notification"/>
+        <CheckBoxPreference 
+            android:key="notify_in_conversation_when_highlighted"
+            android:title="Conference notification"
+            android:summary="Always notify when a new conference message arrives instead of only when highlighted"/>
     </PreferenceCategory>
     <PreferenceCategory 
-        android:title="Advanced settings">
+        android:title="UI Options">
         <CheckBoxPreference 
             android:key="show_phone_selfcontact_picture"
             android:title="Use Phones self contact picture"

src/de/gultsch/chat/entities/Contact.java 🔗

@@ -38,6 +38,8 @@ public class Contact extends AbstractEntity implements Serializable {
 	protected Presences presences = new Presences();
 
 	protected Account account;
+	
+	protected boolean inRoster = true;
 
 	public Contact(Account account, String displayName, String jid,
 			String photoUri) {
@@ -262,4 +264,13 @@ public class Contact extends AbstractEntity implements Serializable {
 		public static final int ASKING = 2;
 		public static final int PREEMPTIVE_GRANT = 4;
 	}
+
+
+	public void flagAsNotInRoster() {
+		this.inRoster = false;
+	}
+	
+	public boolean isInRoster() {
+		return this.inRoster;
+	}
 }

src/de/gultsch/chat/services/XmppConnectionService.java 🔗

@@ -40,12 +40,14 @@ import android.app.NotificationManager;
 import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
+import android.content.SharedPreferences;
 import android.database.ContentObserver;
 import android.database.DatabaseUtils;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.PowerManager;
+import android.preference.PreferenceManager;
 import android.provider.ContactsContract;
 import android.util.Log;
 
@@ -104,7 +106,7 @@ public class XmppConnectionService extends Service {
 					notify = (message.getStatus() == Message.STATUS_RECIEVED);
 				}
 			} else if (packet.getType() == MessagePacket.TYPE_ERROR) {
-				message = MessageParser.parseError(packet,account,service);
+				message = MessageParser.parseError(packet, account, service);
 			} else {
 				Log.d(LOGTAG, "unparsed message " + packet.toString());
 			}
@@ -175,7 +177,8 @@ public class XmppConnectionService extends Service {
 			Contact contact = findContact(account, fromParts[0]);
 			if (contact == null) {
 				// most likely muc, self or roster not synced
-				Log.d(LOGTAG,"got presence for non contact "+packet.toString());
+				Log.d(LOGTAG,
+						"got presence for non contact " + packet.toString());
 				return;
 			}
 			String type = packet.getAttribute("type");
@@ -201,21 +204,26 @@ public class XmppConnectionService extends Service {
 					databaseBackend.updateContact(contact);
 				}
 			} else if (type.equals("subscribe")) {
-				Log.d(LOGTAG,account.getJid()+": "+contact.getJid()+" asked to subscribe");
-				if (contact.getSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT)) {
-					Log.d(LOGTAG,"preemptive grant existed. granting");
+				if (contact
+						.getSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT)) {
 					sendPresenceUpdatesTo(contact);
 					contact.setSubscriptionOption(Contact.Subscription.FROM);
 					contact.resetSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT);
 					replaceContactInConversation(contact.getJid(), contact);
 					databaseBackend.updateContact(contact);
+					if ((contact
+							.getSubscriptionOption(Contact.Subscription.ASKING))
+							&& (!contact
+									.getSubscriptionOption(Contact.Subscription.TO))) {
+						requestPresenceUpdatesFrom(contact);
+					}
 				} else {
-					//TODO: ask user to handle it maybe
+					// TODO: ask user to handle it maybe
 				}
 			} else {
-				Log.d(LOGTAG,packet.toString());
+				Log.d(LOGTAG, packet.toString());
 			}
-			replaceContactInConversation(contact.getJid(),contact);
+			replaceContactInConversation(contact.getJid(), contact);
 		}
 	};
 
@@ -257,7 +265,7 @@ public class XmppConnectionService extends Service {
 					} else {
 						contact.parseSubscriptionFromElement(item);
 						databaseBackend.updateContact(contact);
-						replaceContactInConversation(contact.getJid(),contact);
+						replaceContactInConversation(contact.getJid(), contact);
 					}
 				}
 			}
@@ -456,48 +464,44 @@ public class XmppConnectionService extends Service {
 						if (roster != null) {
 							String version = roster.getAttribute("ver");
 							processRosterItems(account, roster);
-							if (version!=null) {
-								account.setRosterVersion(version);
-								databaseBackend.updateAccount(account);
-							} else {
-								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("\"");
-								Log.d(LOGTAG,mWhere.toString());
-								List<Contact> contactsToDelete = databaseBackend.getContats(mWhere.toString());
-								for(Contact contact : contactsToDelete) {
-									databaseBackend.deleteContact(contact);
-									replaceContactInConversation(contact.getJid(), null);
+							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(",");
 								}
 							}
-							mergePhoneContactsWithRoster(new OnPhoneContactsMerged() {
-								
-								@Override
-								public void phoneContactsMerged() {
-									if (listener != null) {
-										getRoster(account, listener);
-									}
-								}
-							});
-						} else {
-							if (listener != null) {
-								getRoster(account, listener);
+							mWhere.append(") and accountUuid = \"");
+							mWhere.append(account.getUuid());
+							mWhere.append("\"");
+							List<Contact> contactsToDelete = databaseBackend
+									.getContats(mWhere.toString());
+							for (Contact contact : contactsToDelete) {
+								databaseBackend.deleteContact(contact);
+								replaceContactInConversation(contact.getJid(),
+										null);
 							}
+
 						}
+						mergePhoneContactsWithRoster(new OnPhoneContactsMerged() {
+
+							@Override
+							public void phoneContactsMerged() {
+								if (listener != null) {
+									getRoster(account, listener);
+								}
+							}
+						});
 					}
 				});
 	}
 
-	public void mergePhoneContactsWithRoster(final OnPhoneContactsMerged listener) {
+	public void mergePhoneContactsWithRoster(
+			final OnPhoneContactsMerged listener) {
 		PhoneHelper.loadPhoneContacts(getApplicationContext(),
 				new OnPhoneContactsLoadedListener() {
 					@Override
@@ -520,18 +524,20 @@ public class XmppConnectionService extends Service {
 								contact.setDisplayName(phoneContact
 										.getString("displayname"));
 								databaseBackend.updateContact(contact);
-								replaceContactInConversation(contact.getJid(), contact);
+								replaceContactInConversation(contact.getJid(),
+										contact);
 							} else {
 								if ((contact.getSystemAccount() != null)
 										|| (contact.getProfilePhoto() != null)) {
 									contact.setSystemAccount(null);
 									contact.setPhotoUri(null);
 									databaseBackend.updateContact(contact);
-									replaceContactInConversation(contact.getJid(), contact);
+									replaceContactInConversation(
+											contact.getJid(), contact);
 								}
 							}
 						}
-						if (listener!=null) {
+						if (listener != null) {
 							listener.phoneContactsMerged();
 						}
 					}
@@ -562,7 +568,7 @@ public class XmppConnectionService extends Service {
 
 	public Contact findContact(Account account, String jid) {
 		Contact contact = databaseBackend.findContact(account, jid);
-		if (contact!=null) {
+		if (contact != null) {
 			contact.setAccount(account);
 		}
 		return contact;
@@ -650,7 +656,7 @@ public class XmppConnectionService extends Service {
 		if (accountChangedListener != null)
 			accountChangedListener.onAccountListChangedListener();
 	}
-	
+
 	public void deleteContact(Contact contact) {
 		IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
 		Element query = new Element("query");
@@ -772,6 +778,14 @@ public class XmppConnectionService extends Service {
 	}
 
 	public void createContact(Contact contact) {
+		SharedPreferences sharedPref = PreferenceManager
+				.getDefaultSharedPreferences(getApplicationContext());
+		boolean autoGrant = sharedPref.getBoolean("grant_new_contacts", true);
+		if (autoGrant) {
+			contact.setSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT);
+			contact.setSubscriptionOption(Contact.Subscription.ASKING);
+		}
+		databaseBackend.createContact(contact);
 		IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
 		Element query = new Element("query");
 		query.setAttribute("xmlns", "jabber:iq:roster");
@@ -781,49 +795,50 @@ public class XmppConnectionService extends Service {
 		query.addChild(item);
 		iq.addChild(query);
 		Account account = contact.getAccount();
-		Log.d(LOGTAG,account.getJid()+": adding "+contact.getJid()+" to roster");
 		account.getXmppConnection().sendIqPacket(iq, null);
+		if (autoGrant) {
+			requestPresenceUpdatesFrom(contact);
+		}
 		replaceContactInConversation(contact.getJid(), contact);
-		databaseBackend.createContact(contact);
 	}
 
 	public void requestPresenceUpdatesFrom(Contact contact) {
-		//Requesting a Subscription type=subscribe
+		// Requesting a Subscription type=subscribe
 		PresencePacket packet = new PresencePacket();
 		packet.setAttribute("type", "subscribe");
 		packet.setAttribute("to", contact.getJid());
-		packet.setAttribute("from",contact.getAccount().getJid());
-		Log.d(LOGTAG,packet.toString());
+		packet.setAttribute("from", contact.getAccount().getJid());
+		Log.d(LOGTAG, packet.toString());
 		contact.getAccount().getXmppConnection().sendPresencePacket(packet);
 	}
-	
+
 	public void stopPresenceUpdatesFrom(Contact contact) {
-		//Unsubscribing  type='unsubscribe'
+		// Unsubscribing type='unsubscribe'
 		PresencePacket packet = new PresencePacket();
 		packet.setAttribute("type", "unsubscribe");
 		packet.setAttribute("to", contact.getJid());
-		packet.setAttribute("from",contact.getAccount().getJid());
-		Log.d(LOGTAG,packet.toString());
+		packet.setAttribute("from", contact.getAccount().getJid());
+		Log.d(LOGTAG, packet.toString());
 		contact.getAccount().getXmppConnection().sendPresencePacket(packet);
 	}
-	
+
 	public void stopPresenceUpdatesTo(Contact contact) {
-		//Canceling a Subscription type=unsubscribed
+		// Canceling a Subscription type=unsubscribed
 		PresencePacket packet = new PresencePacket();
 		packet.setAttribute("type", "unsubscribed");
 		packet.setAttribute("to", contact.getJid());
-		packet.setAttribute("from",contact.getAccount().getJid());
-		Log.d(LOGTAG,packet.toString());
+		packet.setAttribute("from", contact.getAccount().getJid());
+		Log.d(LOGTAG, packet.toString());
 		contact.getAccount().getXmppConnection().sendPresencePacket(packet);
 	}
-	
+
 	public void sendPresenceUpdatesTo(Contact contact) {
-		//type='subscribed'
+		// type='subscribed'
 		PresencePacket packet = new PresencePacket();
 		packet.setAttribute("type", "subscribed");
 		packet.setAttribute("to", contact.getJid());
-		packet.setAttribute("from",contact.getAccount().getJid());
-		Log.d(LOGTAG,packet.toString());
+		packet.setAttribute("from", contact.getAccount().getJid());
+		Log.d(LOGTAG, packet.toString());
 		contact.getAccount().getXmppConnection().sendPresencePacket(packet);
 	}
 }

src/de/gultsch/chat/ui/NewConversationActivity.java 🔗

@@ -79,6 +79,7 @@ public class NewConversationActivity extends XmppActivity {
 			if (Validator.isValidJid(searchString)) {
 				String name = searchString.split("@")[0];
 				Contact newContact = new Contact(null, name, searchString, null);
+				newContact.flagAsNotInRoster();
 				aggregatedContacts.add(newContact);
 				contactsHeader.setText("Create new contact");
 			} else {
@@ -228,7 +229,9 @@ public class NewConversationActivity extends XmppActivity {
 	}
 
 	public void startConversation(Contact contact, Account account, boolean muc) {
-		Log.d("xmppService","starting conversation for account:"+account.getJid()+" and contact:"+contact.getJid());
+		if (!contact.isInRoster()) {
+			xmppConnectionService.createContact(contact);
+		}
 		Conversation conversation = xmppConnectionService
 				.findOrCreateConversation(account, contact.getJid(), muc);