StartConversation.java

  1package eu.siacs.conversations.ui;
  2
  3import java.util.ArrayList;
  4import java.util.Collections;
  5import java.util.List;
  6
  7import android.app.ActionBar;
  8import android.app.ActionBar.Tab;
  9import android.app.ActionBar.TabListener;
 10import android.app.AlertDialog;
 11import android.app.Fragment;
 12import android.app.FragmentTransaction;
 13import android.app.ListFragment;
 14import android.content.Context;
 15import android.graphics.Color;
 16import android.os.Bundle;
 17import android.support.v13.app.FragmentPagerAdapter;
 18import android.support.v4.view.ViewPager;
 19import android.view.ContextMenu;
 20import android.view.ContextMenu.ContextMenuInfo;
 21import android.view.LayoutInflater;
 22import android.view.Menu;
 23import android.view.MenuItem;
 24import android.view.View;
 25import android.view.ViewGroup;
 26import android.widget.AdapterView;
 27import android.widget.AdapterView.AdapterContextMenuInfo;
 28import android.widget.AdapterView.OnItemClickListener;
 29import android.widget.ArrayAdapter;
 30import android.widget.AutoCompleteTextView;
 31import android.widget.ImageView;
 32import android.widget.ListView;
 33import android.widget.SearchView;
 34import android.widget.SearchView.OnQueryTextListener;
 35import android.widget.Spinner;
 36import android.widget.TextView;
 37import eu.siacs.conversations.R;
 38import eu.siacs.conversations.entities.Account;
 39import eu.siacs.conversations.entities.Contact;
 40import eu.siacs.conversations.entities.Conversation;
 41import eu.siacs.conversations.entities.ListItem;
 42import eu.siacs.conversations.utils.KnownHostsAdapter;
 43import eu.siacs.conversations.utils.UIHelper;
 44import eu.siacs.conversations.utils.Validator;
 45
 46public class StartConversation extends XmppActivity {
 47
 48	private Tab mContactsTab;
 49	private Tab mConferencesTab;
 50	private ViewPager mViewPager;
 51	private SearchView mSearchView;
 52
 53	private MyListFragment mContactsListFragment = new MyListFragment();
 54	private List<ListItem> contacts = new ArrayList<ListItem>();
 55	private ArrayAdapter<ListItem> mContactsAdapter;
 56
 57	private MyListFragment mConferenceListFragment = new MyListFragment();
 58	private List<ListItem> conferences = new ArrayList<ListItem>();
 59	private ArrayAdapter<ListItem> mConferenceAdapter;
 60	
 61	private List<String> mActivatedAccounts = new ArrayList<String>();
 62	private List<String> mKnownHosts;
 63	private List<String> mKnownConferenceHosts;
 64
 65	private TabListener mTabListener = new TabListener() {
 66
 67		@Override
 68		public void onTabUnselected(Tab tab, FragmentTransaction ft) {
 69			return;
 70		}
 71
 72		@Override
 73		public void onTabSelected(Tab tab, FragmentTransaction ft) {
 74			mViewPager.setCurrentItem(tab.getPosition());
 75			onTabChanged();
 76		}
 77
 78		@Override
 79		public void onTabReselected(Tab tab, FragmentTransaction ft) {
 80			return;
 81		}
 82	};
 83
 84	private ViewPager.SimpleOnPageChangeListener mOnPageChangeListener = new ViewPager.SimpleOnPageChangeListener() {
 85		@Override
 86		public void onPageSelected(int position) {
 87			getActionBar().setSelectedNavigationItem(position);
 88			onTabChanged();
 89		}
 90	};
 91	private OnQueryTextListener mOnQueryTextListener = new OnQueryTextListener() {
 92
 93		@Override
 94		public boolean onQueryTextSubmit(String query) {
 95			return true;
 96		}
 97
 98		@Override
 99		public boolean onQueryTextChange(String newText) {
100			filterContacts(newText);
101			return true;
102		}
103	};
104
105	@Override
106	public void onCreate(Bundle savedInstanceState) {
107		super.onCreate(savedInstanceState);
108		setContentView(R.layout.activity_start_conversation);
109		mViewPager = (ViewPager) findViewById(R.id.start_conversation_view_pager);
110		ActionBar actionBar = getActionBar();
111		actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
112
113		mContactsTab = actionBar.newTab().setText(R.string.contacts)
114				.setTabListener(mTabListener);
115		mConferencesTab = actionBar.newTab().setText(R.string.conferences)
116				.setTabListener(mTabListener);
117		actionBar.addTab(mContactsTab);
118		actionBar.addTab(mConferencesTab);
119
120		mViewPager.setOnPageChangeListener(mOnPageChangeListener);
121		mViewPager.setAdapter(new FragmentPagerAdapter(getFragmentManager()) {
122
123			@Override
124			public int getCount() {
125				return 2;
126			}
127
128			@Override
129			public Fragment getItem(int position) {
130				if (position == 0) {
131					return mContactsListFragment;
132				} else {
133					return mConferenceListFragment;
134				}
135			}
136		});
137
138		mConferenceAdapter = new ListItemAdapter(conferences);
139		mConferenceListFragment.setListAdapter(mConferenceAdapter);
140
141		mContactsAdapter = new ListItemAdapter(contacts);
142		mContactsListFragment.setListAdapter(mContactsAdapter);
143		mContactsListFragment
144				.setOnListItemClickListener(new OnItemClickListener() {
145
146					@Override
147					public void onItemClick(AdapterView<?> arg0, View arg1,
148							int position, long arg3) {
149						openConversationForContact(position);
150					}
151				});
152
153	}
154
155	protected void openConversationForContact(int position) {
156		Contact contact = (Contact) contacts.get(position);
157		Conversation conversation = xmppConnectionService
158				.findOrCreateConversation(contact.getAccount(),
159						contact.getJid(), false);
160		switchToConversation(conversation, null, false);
161	}
162	
163	protected void openDetailsForContact(int position) {
164		Contact contact = (Contact) contacts.get(position);
165		switchToContactDetails(contact);
166	}
167	
168	protected void deleteContact(int position) {
169		Contact contact = (Contact) contacts.get(position);
170		xmppConnectionService.deleteContactOnServer(contact);
171		filterContacts(null);
172	}
173	
174	protected void showCreateContactDialog() {
175		AlertDialog.Builder builder = new AlertDialog.Builder(this);
176		builder.setTitle(R.string.create_contact);
177		View dialogView = getLayoutInflater().inflate(R.layout.create_contact_dialog, null);
178		final Spinner spinner = (Spinner) dialogView.findViewById(R.id.account);
179		final AutoCompleteTextView jid = (AutoCompleteTextView) dialogView.findViewById(R.id.jid);
180		jid.setAdapter(new KnownHostsAdapter(this, android.R.layout.simple_list_item_1, mKnownHosts));
181		populateAccountSpinner(spinner);
182		builder.setView(dialogView);
183		builder.setNegativeButton(R.string.cancel, null);
184		builder.setPositiveButton(R.string.create, null);
185		final AlertDialog dialog = builder.create();
186		dialog.show();
187		dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
188			
189			@Override
190			public void onClick(View v) {
191				if (Validator.isValidJid(jid.getText().toString())) {
192					String accountJid = (String) spinner.getSelectedItem();
193					String contactJid = jid.getText().toString();
194					Account account = xmppConnectionService.findAccountByJid(accountJid);
195					Contact contact = account.getRoster().getContact(contactJid);
196					if (contact.showInRoster()) {
197						jid.setError(getString(R.string.contact_already_exists));
198					} else {
199						xmppConnectionService.createContact(contact);
200						switchToConversation(contact);
201						dialog.dismiss();
202					}
203				} else {
204					jid.setError(getString(R.string.invalid_jid));
205				}
206			}
207		});
208		
209	}
210	
211	protected void showJoinConferenceDialog() {
212		AlertDialog.Builder builder = new AlertDialog.Builder(this);
213		builder.setTitle(R.string.join_conference);
214		View dialogView = getLayoutInflater().inflate(R.layout.join_conference_dialog, null);
215		final Spinner spinner = (Spinner) dialogView.findViewById(R.id.account);
216		final AutoCompleteTextView jid = (AutoCompleteTextView) dialogView.findViewById(R.id.jid);
217		jid.setAdapter(new KnownHostsAdapter(this, android.R.layout.simple_list_item_1, mKnownConferenceHosts));
218		populateAccountSpinner(spinner);
219		builder.setView(dialogView);
220		builder.setNegativeButton(R.string.cancel, null);
221		builder.setPositiveButton(R.string.join, null);
222		final AlertDialog dialog = builder.create();
223		dialog.show();
224		dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
225			
226			@Override
227			public void onClick(View v) {
228				if (Validator.isValidJid(jid.getText().toString())) {
229					String accountJid = (String) spinner.getSelectedItem();
230					String conferenceJid = jid.getText().toString();
231					Account account = xmppConnectionService.findAccountByJid(accountJid);
232					Conversation conversation = xmppConnectionService.findOrCreateConversation(account, conferenceJid, true);
233					switchToConversation(conversation);
234				} else {
235					jid.setError(getString(R.string.invalid_jid));
236				}
237			}
238		});
239	}
240	
241	protected void switchToConversation(Contact contact) {
242		Conversation conversation = xmppConnectionService.findOrCreateConversation(contact.getAccount(), contact.getJid(), false);
243		switchToConversation(conversation);
244	}
245	
246	private void populateAccountSpinner(Spinner spinner) {
247		ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, mActivatedAccounts);
248		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
249		spinner.setAdapter(adapter);
250	}
251
252	@Override
253	public boolean onCreateOptionsMenu(Menu menu) {
254		getMenuInflater().inflate(R.menu.start_conversation, menu);
255		MenuItem menuCreateContact = (MenuItem) menu
256				.findItem(R.id.action_create_contact);
257		MenuItem menuCreateConference = (MenuItem) menu
258				.findItem(R.id.action_join_conference);
259		MenuItem menuSearch = (MenuItem) menu.findItem(R.id.action_search);
260		if (getActionBar().getSelectedNavigationIndex() == 0) {
261			menuCreateConference.setVisible(false);
262		} else {
263			menuCreateContact.setVisible(false);
264		}
265		mSearchView = (SearchView) menuSearch.getActionView();
266		int id = mSearchView.getContext().getResources()
267				.getIdentifier("android:id/search_src_text", null, null);
268		TextView textView = (TextView) mSearchView.findViewById(id);
269		textView.setTextColor(Color.WHITE);
270		mSearchView.setOnQueryTextListener(this.mOnQueryTextListener);
271		return true;
272	}
273
274	@Override
275	public boolean onOptionsItemSelected(MenuItem item) {
276		switch (item.getItemId()) {
277		case R.id.action_create_contact:
278			showCreateContactDialog();
279			break;
280		case R.id.action_join_conference:
281			showJoinConferenceDialog();
282			break;
283		}
284		return super.onOptionsItemSelected(item);
285	}
286
287	@Override
288	void onBackendConnected() {
289		filterContacts(null);
290		this.mActivatedAccounts.clear();
291		for (Account account : xmppConnectionService.getAccounts()) {
292			if (account.getStatus() != Account.STATUS_DISABLED) {
293				this.mActivatedAccounts.add(account.getJid());
294			}
295		}
296		this.mKnownHosts = xmppConnectionService.getKnownHosts();
297		this.mKnownConferenceHosts = xmppConnectionService.getKnownConferenceHosts();
298	}
299
300	protected void filterContacts(String needle) {
301		this.contacts.clear();
302		for (Account account : xmppConnectionService.getAccounts()) {
303			if (account.getStatus() != Account.STATUS_DISABLED) {
304				for (Contact contact : account.getRoster().getContacts()) {
305					if (contact.showInRoster() && contact.match(needle)) {
306						this.contacts.add(contact);
307					}
308				}
309			}
310		}
311		Collections.sort(this.contacts);
312		mContactsAdapter.notifyDataSetChanged();
313	}
314
315	private void onTabChanged() {
316		invalidateOptionsMenu();
317	}
318
319	private class ListItemAdapter extends ArrayAdapter<ListItem> {
320
321		public ListItemAdapter(List<ListItem> objects) {
322			super(getApplicationContext(), 0, objects);
323		}
324
325		@Override
326		public View getView(int position, View view, ViewGroup parent) {
327			LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
328			ListItem item = getItem(position);
329			if (view == null) {
330				view = (View) inflater.inflate(R.layout.contact, null);
331			}
332			TextView name = (TextView) view
333					.findViewById(R.id.contact_display_name);
334			TextView jid = (TextView) view.findViewById(R.id.contact_jid);
335			ImageView picture = (ImageView) view
336					.findViewById(R.id.contact_photo);
337
338			jid.setText(item.getJid());
339			name.setText(item.getDisplayName());
340			picture.setImageBitmap(UIHelper.getContactPicture(item, 48,
341					this.getContext(), false));
342			return view;
343		}
344
345	}
346
347	public static class MyListFragment extends ListFragment {
348		private AdapterView.OnItemClickListener mOnItemClickListener;
349		private int mContextPosition = -1;
350
351		@Override
352		public void onListItemClick(ListView l, View v, int position, long id) {
353			if (mOnItemClickListener != null) {
354				mOnItemClickListener.onItemClick(l, v, position, id);
355			}
356		}
357
358		public void setOnListItemClickListener(AdapterView.OnItemClickListener l) {
359			this.mOnItemClickListener = l;
360		}
361
362		@Override
363		public void onViewCreated(View view, Bundle savedInstanceState) {
364			super.onViewCreated(view, savedInstanceState);
365			registerForContextMenu(getListView());
366		}
367
368		@Override
369		public void onCreateContextMenu(ContextMenu menu, View v,
370				ContextMenuInfo menuInfo) {
371			super.onCreateContextMenu(menu, v, menuInfo);
372			getActivity().getMenuInflater().inflate(R.menu.contact_context,
373					menu);
374			AdapterView.AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) menuInfo;
375			this.mContextPosition = acmi.position;
376		}
377
378		@Override
379		public boolean onContextItemSelected(MenuItem item) {
380			StartConversation activity = (StartConversation) getActivity();
381			switch(item.getItemId()) {
382			case R.id.context_start_conversation:
383				activity.openConversationForContact(mContextPosition);
384				break;
385			case R.id.context_contact_details:
386				activity.openDetailsForContact(mContextPosition);
387				break;
388			case R.id.context_delete_contact:
389				activity.deleteContact(mContextPosition);
390				break;
391			}
392			return true;
393		}
394	}
395}