filter contacts and starting confercenes

iNPUTmice created

Change summary

res/menu/start_conversation.xml                      |  12 
src/eu/siacs/conversations/entities/Contact.java     |  21 +
src/eu/siacs/conversations/entities/ListItem.java    |   7 
src/eu/siacs/conversations/ui/StartConversation.java | 171 ++++++++++++-
src/eu/siacs/conversations/utils/UIHelper.java       |   4 
5 files changed, 185 insertions(+), 30 deletions(-)

Detailed changes

res/menu/start_conversation.xml 🔗

@@ -1,12 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <menu xmlns:android="http://schemas.android.com/apk/res/android" >
 
-    <item
-        android:id="@+id/action_search"
-        android:actionViewClass="android.widget.SearchView"
-        android:icon="@drawable/ic_action_search"
-        android:showAsAction="collapseActionView|ifRoom"
-        android:title="@string/search"/>
     <item
         android:id="@+id/action_create_contact"
         android:icon="@drawable/ic_action_add_person"
@@ -17,6 +11,12 @@
         android:icon="@drawable/ic_action_add_group"
         android:showAsAction="ifRoom"
         android:title="@string/create_conference"/>
+    <item
+        android:id="@+id/action_search"
+        android:actionViewClass="android.widget.SearchView"
+        android:icon="@drawable/ic_action_search"
+        android:showAsAction="collapseActionView|ifRoom"
+        android:title="@string/search"/>
     <item
         android:id="@+id/action_accounts"
         android:orderInCategory="90"

src/eu/siacs/conversations/entities/Contact.java 🔗

@@ -12,7 +12,7 @@ import eu.siacs.conversations.xml.Element;
 import android.content.ContentValues;
 import android.database.Cursor;
 
-public class Contact {
+public class Contact implements ListItem {
 	public static final String TABLENAME = "contacts";
 
 	public static final String SYSTEMNAME = "systemname";
@@ -37,7 +37,7 @@ public class Contact {
 	protected Account account;
 
 	protected boolean inRoster = true;
-	
+
 	public Lastseen lastseen = new Lastseen();
 
 	public Contact(String account, String systemName, String serverName,
@@ -83,8 +83,10 @@ public class Contact {
 	}
 
 	public boolean match(String needle) {
-		return (jid.toLowerCase().contains(needle.toLowerCase()) || (getDisplayName()
-				.toLowerCase().contains(needle.toLowerCase())));
+		return needle == null
+				|| jid.contains(needle.toLowerCase())
+				|| getDisplayName().toLowerCase()
+						.contains(needle.toLowerCase());
 	}
 
 	public ContentValues getContentValues() {
@@ -142,8 +144,8 @@ public class Contact {
 						|| domainParts[0].equals("room")
 						|| domainParts[0].equals("muc")
 						|| domainParts[0].equals("chat")
-						|| domainParts[0].equals("sala")
-						|| domainParts[0].equals("salas"));
+						|| domainParts[0].equals("sala") || domainParts[0]
+							.equals("salas"));
 			}
 		}
 	}
@@ -308,9 +310,14 @@ public class Contact {
 		public static final int DIRTY_PUSH = 6;
 		public static final int DIRTY_DELETE = 7;
 	}
-	
+
 	public class Lastseen {
 		public long time = 0;
 		public String presence = null;
 	}
+
+	@Override
+	public int compareTo(ListItem another) {
+		return this.getDisplayName().compareToIgnoreCase(another.getDisplayName());
+	}
 }

src/eu/siacs/conversations/entities/ListItem.java 🔗

@@ -0,0 +1,7 @@
+package eu.siacs.conversations.entities;
+
+public interface ListItem extends Comparable<ListItem> {
+	public String getDisplayName();
+	public String getJid();
+	public String getProfilePhoto();
+}

src/eu/siacs/conversations/ui/StartConversation.java 🔗

@@ -1,44 +1,71 @@
 package eu.siacs.conversations.ui;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
 import android.app.ActionBar;
 import android.app.ActionBar.Tab;
 import android.app.ActionBar.TabListener;
 import android.app.Fragment;
 import android.app.FragmentTransaction;
 import android.app.ListFragment;
+import android.content.Context;
 import android.os.Bundle;
 import android.support.v13.app.FragmentPagerAdapter;
 import android.support.v4.view.ViewPager;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
+import android.view.MenuItem.OnActionExpandListener;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.SearchView;
+import android.widget.SearchView.OnQueryTextListener;
+import android.widget.TextView;
 import eu.siacs.conversations.R;
+import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.entities.Contact;
+import eu.siacs.conversations.entities.Conversation;
+import eu.siacs.conversations.entities.ListItem;
+import eu.siacs.conversations.utils.UIHelper;
 
 public class StartConversation extends XmppActivity {
 
 	private Tab mContactsTab;
 	private Tab mConferencesTab;
 	private ViewPager mViewPager;
-	private ListFragment mContactsListFragment = new ListFragment();
-	private ListFragment mConferenceListFragment = new ListFragment();
+	private SearchView mSearchView;
+
+	private MyListFragment mContactsListFragment = new MyListFragment();
+	private List<ListItem> contacts = new ArrayList<ListItem>();
+	private ArrayAdapter<ListItem> mContactsAdapter;
+
+	private MyListFragment mConferenceListFragment = new MyListFragment();
+	private List<ListItem> conferences = new ArrayList<ListItem>();
+	private ArrayAdapter<ListItem> mConferenceAdapter;
 
 	private TabListener mTabListener = new TabListener() {
 
 		@Override
 		public void onTabUnselected(Tab tab, FragmentTransaction ft) {
-			// TODO Auto-generated method stub
-
+			return;
 		}
 
 		@Override
 		public void onTabSelected(Tab tab, FragmentTransaction ft) {
 			mViewPager.setCurrentItem(tab.getPosition());
-			invalidateOptionsMenu();
+			onTabChanged();
 		}
 
 		@Override
 		public void onTabReselected(Tab tab, FragmentTransaction ft) {
-			// TODO Auto-generated method stub
-
+			return;
 		}
 	};
 
@@ -46,7 +73,33 @@ public class StartConversation extends XmppActivity {
 		@Override
 		public void onPageSelected(int position) {
 			getActionBar().setSelectedNavigationItem(position);
+			onTabChanged();
+		}
+	};
+	private OnQueryTextListener mOnQueryTextListener = new OnQueryTextListener() {
+
+		@Override
+		public boolean onQueryTextSubmit(String query) {
+			return true;
+		}
+
+		@Override
+		public boolean onQueryTextChange(String newText) {
+			filterContacts(newText);
+			return true;
+		}
+	};
+	private OnActionExpandListener mOnSearchActionExpandListener = new OnActionExpandListener() {
+
+		@Override
+		public boolean onMenuItemActionExpand(MenuItem item) {
+			return true;
+		}
+
+		@Override
+		public boolean onMenuItemActionCollapse(MenuItem item) {
 			invalidateOptionsMenu();
+			return true;
 		}
 	};
 
@@ -65,18 +118,17 @@ public class StartConversation extends XmppActivity {
 		actionBar.addTab(mContactsTab);
 		actionBar.addTab(mConferencesTab);
 
-		
 		mViewPager.setOnPageChangeListener(mOnPageChangeListener);
 		mViewPager.setAdapter(new FragmentPagerAdapter(getFragmentManager()) {
-			
+
 			@Override
 			public int getCount() {
 				return 2;
 			}
-			
+
 			@Override
 			public Fragment getItem(int position) {
-				if (position==0) {
+				if (position == 0) {
 					return mContactsListFragment;
 				} else {
 					return mConferenceListFragment;
@@ -84,18 +136,44 @@ public class StartConversation extends XmppActivity {
 			}
 		});
 
+		mConferenceAdapter = new ListItemAdapter(conferences);
+		mConferenceListFragment.setListAdapter(mConferenceAdapter);
+
+		mContactsAdapter = new ListItemAdapter(contacts);
+		mContactsListFragment.setListAdapter(mContactsAdapter);
+		mContactsListFragment
+				.setOnListItemClickListener(new OnItemClickListener() {
+
+					@Override
+					public void onItemClick(AdapterView<?> arg0, View arg1,
+							int position, long arg3) {
+						Contact contact = (Contact) contacts.get(position);
+						Conversation conversation = xmppConnectionService
+								.findOrCreateConversation(contact.getAccount(),
+										contact.getJid(), false);
+						switchToConversation(conversation, null, false);
+					}
+				});
+
 	}
-	
+
 	@Override
 	public boolean onCreateOptionsMenu(Menu menu) {
 		getMenuInflater().inflate(R.menu.start_conversation, menu);
-		MenuItem menuCreateContact = (MenuItem) menu.findItem(R.id.action_create_contact);
-		MenuItem menuCreateConference = (MenuItem) menu.findItem(R.id.action_create_conference);
+		MenuItem menuCreateContact = (MenuItem) menu
+				.findItem(R.id.action_create_contact);
+		MenuItem menuCreateConference = (MenuItem) menu
+				.findItem(R.id.action_create_conference);
+		MenuItem menuSearch = (MenuItem) menu.findItem(R.id.action_search);
 		if (getActionBar().getSelectedNavigationIndex() == 0) {
 			menuCreateConference.setVisible(false);
 		} else {
 			menuCreateContact.setVisible(false);
 		}
+		mSearchView = (SearchView) menuSearch.getActionView();
+		mSearchView.setOnQueryTextListener(this.mOnQueryTextListener);
+		menuSearch
+				.setOnActionExpandListener(this.mOnSearchActionExpandListener);
 		return true;
 	}
 
@@ -110,8 +188,71 @@ public class StartConversation extends XmppActivity {
 
 	@Override
 	void onBackendConnected() {
-		// TODO Auto-generated method stub
+		filterContacts(null);
+	}
+
+	protected void filterContacts(String needle) {
+		this.contacts.clear();
+		for (Account account : xmppConnectionService.getAccounts()) {
+			if (account.getStatus() != Account.STATUS_DISABLED) {
+				for (Contact contact : account.getRoster().getContacts()) {
+					if (contact.showInRoster() && contact.match(needle)) {
+						this.contacts.add(contact);
+					}
+				}
+			}
+		}
+		Collections.sort(this.contacts);
+		mContactsAdapter.notifyDataSetChanged();
+	}
+
+	private void onTabChanged() {
+		if (mSearchView == null || mSearchView.isIconified()) {
+			invalidateOptionsMenu();
+		}
+	}
+
+	private class ListItemAdapter extends ArrayAdapter<ListItem> {
+
+		public ListItemAdapter(List<ListItem> objects) {
+			super(getApplicationContext(), 0, objects);
+		}
 
+		@Override
+		public View getView(int position, View view, ViewGroup parent) {
+			LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+			ListItem item = getItem(position);
+			if (view == null) {
+				view = (View) inflater.inflate(R.layout.contact, null);
+			}
+			TextView name = (TextView) view
+					.findViewById(R.id.contact_display_name);
+			TextView jid = (TextView) view.findViewById(R.id.contact_jid);
+			ImageView picture = (ImageView) view
+					.findViewById(R.id.contact_photo);
+
+			jid.setText(item.getJid());
+			name.setText(item.getDisplayName());
+			picture.setImageBitmap(UIHelper.getContactPicture(item, 48,
+					this.getContext(), false));
+			return view;
+		}
+
+	}
+
+	public static class MyListFragment extends ListFragment {
+		private AdapterView.OnItemClickListener mOnItemClickListener;
+
+		@Override
+		public void onListItemClick(ListView l, View v, int position, long id) {
+			if (mOnItemClickListener != null) {
+				mOnItemClickListener.onItemClick(l, v, position, id);
+			}
+		}
+
+		public void setOnListItemClickListener(AdapterView.OnItemClickListener l) {
+			this.mOnItemClickListener = l;
+		}
 	}
 
 }

src/eu/siacs/conversations/utils/UIHelper.java 🔗

@@ -13,11 +13,11 @@ import eu.siacs.conversations.R;
 import eu.siacs.conversations.entities.Account;
 import eu.siacs.conversations.entities.Contact;
 import eu.siacs.conversations.entities.Conversation;
+import eu.siacs.conversations.entities.ListItem;
 import eu.siacs.conversations.entities.Message;
 import eu.siacs.conversations.entities.MucOptions.User;
 import eu.siacs.conversations.ui.ConversationActivity;
 import eu.siacs.conversations.ui.ManageAccountActivity;
-
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Notification;
@@ -239,7 +239,7 @@ public class UIHelper {
 		}
 	}
 
-	public static Bitmap getContactPicture(Contact contact, int dpSize,
+	public static Bitmap getContactPicture(ListItem contact, int dpSize,
 			Context context, boolean notification) {
 		String uri = contact.getProfilePhoto();
 		if (uri == null) {