StartConversationActivity.java

  1package eu.siacs.conversations.ui;
  2
  3import android.annotation.SuppressLint;
  4import android.annotation.TargetApi;
  5import android.app.ActionBar;
  6import android.app.ActionBar.Tab;
  7import android.app.ActionBar.TabListener;
  8import android.app.AlertDialog;
  9import android.app.Fragment;
 10import android.app.FragmentTransaction;
 11import android.app.ListFragment;
 12import android.content.Context;
 13import android.content.DialogInterface;
 14import android.content.DialogInterface.OnClickListener;
 15import android.content.Intent;
 16import android.net.Uri;
 17import android.nfc.NdefMessage;
 18import android.nfc.NdefRecord;
 19import android.nfc.NfcAdapter;
 20import android.os.Build;
 21import android.os.Bundle;
 22import android.os.Parcelable;
 23import android.support.v13.app.FragmentPagerAdapter;
 24import android.support.v4.view.ViewPager;
 25import android.text.Editable;
 26import android.text.TextWatcher;
 27import android.util.Log;
 28import android.view.ContextMenu;
 29import android.view.ContextMenu.ContextMenuInfo;
 30import android.view.KeyEvent;
 31import android.view.Menu;
 32import android.view.MenuItem;
 33import android.view.View;
 34import android.view.inputmethod.InputMethodManager;
 35import android.widget.AdapterView;
 36import android.widget.AdapterView.AdapterContextMenuInfo;
 37import android.widget.AdapterView.OnItemClickListener;
 38import android.widget.ArrayAdapter;
 39import android.widget.AutoCompleteTextView;
 40import android.widget.CheckBox;
 41import android.widget.EditText;
 42import android.widget.ListView;
 43import android.widget.Spinner;
 44
 45import com.google.zxing.integration.android.IntentIntegrator;
 46import com.google.zxing.integration.android.IntentResult;
 47
 48import java.util.ArrayList;
 49import java.util.Arrays;
 50import java.util.Collections;
 51import java.util.List;
 52
 53import eu.siacs.conversations.Config;
 54import eu.siacs.conversations.R;
 55import eu.siacs.conversations.entities.Account;
 56import eu.siacs.conversations.entities.Blockable;
 57import eu.siacs.conversations.entities.Bookmark;
 58import eu.siacs.conversations.entities.Contact;
 59import eu.siacs.conversations.entities.Conversation;
 60import eu.siacs.conversations.entities.ListItem;
 61import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate;
 62import eu.siacs.conversations.ui.adapter.KnownHostsAdapter;
 63import eu.siacs.conversations.ui.adapter.ListItemAdapter;
 64import eu.siacs.conversations.utils.Validator;
 65import eu.siacs.conversations.utils.XmppUri;
 66import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
 67import eu.siacs.conversations.xmpp.jid.InvalidJidException;
 68import eu.siacs.conversations.xmpp.jid.Jid;
 69
 70public class StartConversationActivity extends XmppActivity implements OnRosterUpdate, OnUpdateBlocklist {
 71
 72	public int conference_context_id;
 73	public int contact_context_id;
 74	private Tab mContactsTab;
 75	private Tab mConferencesTab;
 76	private ViewPager mViewPager;
 77	private MyListFragment mContactsListFragment = new MyListFragment();
 78	private List<ListItem> contacts = new ArrayList<>();
 79	private ArrayAdapter<ListItem> mContactsAdapter;
 80	private MyListFragment mConferenceListFragment = new MyListFragment();
 81	private List<ListItem> conferences = new ArrayList<ListItem>();
 82	private ArrayAdapter<ListItem> mConferenceAdapter;
 83	private List<String> mActivatedAccounts = new ArrayList<String>();
 84	private List<String> mKnownHosts;
 85	private List<String> mKnownConferenceHosts;
 86	private Invite mPendingInvite = null;
 87	private Menu mOptionsMenu;
 88	private EditText mSearchEditText;
 89	private MenuItem.OnActionExpandListener mOnActionExpandListener = new MenuItem.OnActionExpandListener() {
 90
 91		@Override
 92		public boolean onMenuItemActionExpand(MenuItem item) {
 93			mSearchEditText.post(new Runnable() {
 94
 95				@Override
 96				public void run() {
 97					mSearchEditText.requestFocus();
 98					InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
 99					imm.showSoftInput(mSearchEditText,
100							InputMethodManager.SHOW_IMPLICIT);
101				}
102			});
103
104			return true;
105		}
106
107		@Override
108		public boolean onMenuItemActionCollapse(MenuItem item) {
109			InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
110			imm.hideSoftInputFromWindow(mSearchEditText.getWindowToken(),
111					InputMethodManager.HIDE_IMPLICIT_ONLY);
112			mSearchEditText.setText("");
113			filter(null);
114			return true;
115		}
116	};
117	private TabListener mTabListener = new TabListener() {
118
119		@Override
120		public void onTabUnselected(Tab tab, FragmentTransaction ft) {
121			return;
122		}
123
124		@Override
125		public void onTabSelected(Tab tab, FragmentTransaction ft) {
126			mViewPager.setCurrentItem(tab.getPosition());
127			onTabChanged();
128		}
129
130		@Override
131		public void onTabReselected(Tab tab, FragmentTransaction ft) {
132			return;
133		}
134	};
135	private ViewPager.SimpleOnPageChangeListener mOnPageChangeListener = new ViewPager.SimpleOnPageChangeListener() {
136		@Override
137		public void onPageSelected(int position) {
138			if (getActionBar() != null) {
139				getActionBar().setSelectedNavigationItem(position);
140			}
141			onTabChanged();
142		}
143	};
144	private TextWatcher mSearchTextWatcher = new TextWatcher() {
145
146		@Override
147		public void afterTextChanged(Editable editable) {
148			filter(editable.toString());
149		}
150
151		@Override
152		public void beforeTextChanged(CharSequence s, int start, int count,
153				int after) {
154		}
155
156		@Override
157		public void onTextChanged(CharSequence s, int start, int before,
158				int count) {
159		}
160	};
161	private MenuItem mMenuSearchView;
162	private String mInitialJid;
163
164	@Override
165	public void onRosterUpdate() {
166		runOnUiThread(new Runnable() {
167
168			@Override
169			public void run() {
170				if (mSearchEditText != null) {
171					filter(mSearchEditText.getText().toString());
172				}
173			}
174		});
175	}
176
177	@Override
178	public void onCreate(Bundle savedInstanceState) {
179		super.onCreate(savedInstanceState);
180		setContentView(R.layout.activity_start_conversation);
181		mViewPager = (ViewPager) findViewById(R.id.start_conversation_view_pager);
182		ActionBar actionBar = getActionBar();
183		actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
184
185		mContactsTab = actionBar.newTab().setText(R.string.contacts)
186			.setTabListener(mTabListener);
187		mConferencesTab = actionBar.newTab().setText(R.string.conferences)
188			.setTabListener(mTabListener);
189		actionBar.addTab(mContactsTab);
190		actionBar.addTab(mConferencesTab);
191
192		mViewPager.setOnPageChangeListener(mOnPageChangeListener);
193		mViewPager.setAdapter(new FragmentPagerAdapter(getFragmentManager()) {
194
195			@Override
196			public int getCount() {
197				return 2;
198			}
199
200			@Override
201			public Fragment getItem(int position) {
202				if (position == 0) {
203					return mContactsListFragment;
204				} else {
205					return mConferenceListFragment;
206				}
207			}
208		});
209
210		mConferenceAdapter = new ListItemAdapter(this, conferences);
211		mConferenceListFragment.setListAdapter(mConferenceAdapter);
212		mConferenceListFragment.setContextMenu(R.menu.conference_context);
213		mConferenceListFragment
214			.setOnListItemClickListener(new OnItemClickListener() {
215
216				@Override
217				public void onItemClick(AdapterView<?> arg0, View arg1,
218						int position, long arg3) {
219					openConversationForBookmark(position);
220				}
221			});
222
223		mContactsAdapter = new ListItemAdapter(this, contacts);
224		mContactsListFragment.setListAdapter(mContactsAdapter);
225		mContactsListFragment.setContextMenu(R.menu.contact_context);
226		mContactsListFragment
227			.setOnListItemClickListener(new OnItemClickListener() {
228
229				@Override
230				public void onItemClick(AdapterView<?> arg0, View arg1,
231						int position, long arg3) {
232					openConversationForContact(position);
233				}
234			});
235
236	}
237
238	protected void openConversationForContact(int position) {
239		Contact contact = (Contact) contacts.get(position);
240		Conversation conversation = xmppConnectionService
241			.findOrCreateConversation(contact.getAccount(),
242					contact.getJid(), false);
243		switchToConversation(conversation);
244	}
245
246	protected void openConversationForContact() {
247		int position = contact_context_id;
248		openConversationForContact(position);
249	}
250
251	protected void openConversationForBookmark() {
252		openConversationForBookmark(conference_context_id);
253	}
254
255	protected void openConversationForBookmark(int position) {
256		Bookmark bookmark = (Bookmark) conferences.get(position);
257		Conversation conversation = xmppConnectionService
258			.findOrCreateConversation(bookmark.getAccount(),
259					bookmark.getJid(), true);
260		conversation.setBookmark(bookmark);
261		if (!conversation.getMucOptions().online()) {
262			xmppConnectionService.joinMuc(conversation);
263		}
264		if (!bookmark.autojoin()) {
265			bookmark.setAutojoin(true);
266			xmppConnectionService.pushBookmarks(bookmark.getAccount());
267		}
268		switchToConversation(conversation);
269	}
270
271	protected void openDetailsForContact() {
272		int position = contact_context_id;
273		Contact contact = (Contact) contacts.get(position);
274		switchToContactDetails(contact);
275	}
276
277	protected void toggleContactBlock() {
278		final int position = contact_context_id;
279		BlockContactDialog.show(this, xmppConnectionService, (Contact)contacts.get(position));
280	}
281
282	protected void deleteContact() {
283		final int position = contact_context_id;
284		final Contact contact = (Contact) contacts.get(position);
285		final AlertDialog.Builder builder = new AlertDialog.Builder(this);
286		builder.setNegativeButton(R.string.cancel, null);
287		builder.setTitle(R.string.action_delete_contact);
288		builder.setMessage(getString(R.string.remove_contact_text,
289					contact.getJid()));
290		builder.setPositiveButton(R.string.delete, new OnClickListener() {
291
292			@Override
293			public void onClick(DialogInterface dialog, int which) {
294				xmppConnectionService.deleteContactOnServer(contact);
295				filter(mSearchEditText.getText().toString());
296			}
297		});
298		builder.create().show();
299	}
300
301	protected void deleteConference() {
302		int position = conference_context_id;
303		final Bookmark bookmark = (Bookmark) conferences.get(position);
304
305		AlertDialog.Builder builder = new AlertDialog.Builder(this);
306		builder.setNegativeButton(R.string.cancel, null);
307		builder.setTitle(R.string.delete_bookmark);
308		builder.setMessage(getString(R.string.remove_bookmark_text,
309					bookmark.getJid()));
310		builder.setPositiveButton(R.string.delete, new OnClickListener() {
311
312			@Override
313			public void onClick(DialogInterface dialog, int which) {
314				bookmark.unregisterConversation();
315				Account account = bookmark.getAccount();
316				account.getBookmarks().remove(bookmark);
317				xmppConnectionService.pushBookmarks(account);
318				filter(mSearchEditText.getText().toString());
319			}
320		});
321		builder.create().show();
322
323	}
324
325	@SuppressLint("InflateParams")
326	protected void showCreateContactDialog(final String prefilledJid, final String fingerprint) {
327		AlertDialog.Builder builder = new AlertDialog.Builder(this);
328		builder.setTitle(R.string.create_contact);
329		View dialogView = getLayoutInflater().inflate(R.layout.create_contact_dialog, null);
330		final Spinner spinner = (Spinner) dialogView.findViewById(R.id.account);
331		final AutoCompleteTextView jid = (AutoCompleteTextView) dialogView.findViewById(R.id.jid);
332		jid.setAdapter(new KnownHostsAdapter(this,android.R.layout.simple_list_item_1, mKnownHosts));
333		if (prefilledJid != null) {
334			jid.append(prefilledJid);
335			if (fingerprint!=null) {
336				jid.setFocusable(false);
337				jid.setFocusableInTouchMode(false);
338				jid.setClickable(false);
339				jid.setCursorVisible(false);
340			}
341		}
342		populateAccountSpinner(spinner);
343		builder.setView(dialogView);
344		builder.setNegativeButton(R.string.cancel, null);
345		builder.setPositiveButton(R.string.create, null);
346		final AlertDialog dialog = builder.create();
347		dialog.show();
348		dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(
349				new View.OnClickListener() {
350
351					@Override
352					public void onClick(View v) {
353						if (!xmppConnectionServiceBound) {
354							return;
355						}
356						if (Validator.isValidJid(jid.getText().toString())) {
357							final Jid accountJid;
358							try {
359								accountJid = Jid.fromString((String) spinner.getSelectedItem());
360							} catch (final InvalidJidException e) {
361								return;
362							}
363							final Jid contactJid;
364							try {
365								contactJid = Jid.fromString(jid.getText().toString());
366							} catch (final InvalidJidException e) {
367								jid.setError(getString(R.string.invalid_jid));
368								return;
369							}
370							Account account = xmppConnectionService
371								.findAccountByJid(accountJid);
372							if (account == null) {
373								dialog.dismiss();
374								return;
375							}
376							Contact contact = account.getRoster().getContact(contactJid);
377							if (contact.showInRoster()) {
378								jid.setError(getString(R.string.contact_already_exists));
379							} else {
380								contact.addOtrFingerprint(fingerprint);
381								xmppConnectionService.createContact(contact);
382								dialog.dismiss();
383								switchToConversation(contact);
384							}
385						} else {
386							jid.setError(getString(R.string.invalid_jid));
387						}
388					}
389				});
390
391	}
392
393	@SuppressLint("InflateParams")
394	protected void showJoinConferenceDialog(String prefilledJid) {
395		AlertDialog.Builder builder = new AlertDialog.Builder(this);
396		builder.setTitle(R.string.join_conference);
397		View dialogView = getLayoutInflater().inflate(R.layout.join_conference_dialog, null);
398		final Spinner spinner = (Spinner) dialogView.findViewById(R.id.account);
399		final AutoCompleteTextView jid = (AutoCompleteTextView) dialogView.findViewById(R.id.jid);
400		jid.setAdapter(new KnownHostsAdapter(this,android.R.layout.simple_list_item_1, mKnownConferenceHosts));
401		if (prefilledJid != null) {
402			jid.append(prefilledJid);
403		}
404		populateAccountSpinner(spinner);
405		final CheckBox bookmarkCheckBox = (CheckBox) dialogView
406			.findViewById(R.id.bookmark);
407		builder.setView(dialogView);
408		builder.setNegativeButton(R.string.cancel, null);
409		builder.setPositiveButton(R.string.join, null);
410		final AlertDialog dialog = builder.create();
411		dialog.show();
412		dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(
413				new View.OnClickListener() {
414
415					@Override
416					public void onClick(View v) {
417						if (!xmppConnectionServiceBound) {
418							return;
419						}
420						if (Validator.isValidJid(jid.getText().toString())) {
421							final Jid accountJid;
422							try {
423								accountJid = Jid.fromString((String) spinner.getSelectedItem());
424							} catch (final InvalidJidException e) {
425								return;
426							}
427							final Jid conferenceJid;
428							try {
429								conferenceJid = Jid.fromString(jid.getText().toString());
430							} catch (final InvalidJidException e) {
431								jid.setError(getString(R.string.invalid_jid));
432								return;
433							}
434							Account account = xmppConnectionService
435								.findAccountByJid(accountJid);
436							if (account == null) {
437								dialog.dismiss();
438								return;
439							}
440							if (bookmarkCheckBox.isChecked()) {
441								if (account.hasBookmarkFor(conferenceJid)) {
442									jid.setError(getString(R.string.bookmark_already_exists));
443								} else {
444									Bookmark bookmark = new Bookmark(account,
445											conferenceJid);
446									bookmark.setAutojoin(true);
447									account.getBookmarks().add(bookmark);
448									xmppConnectionService
449										.pushBookmarks(account);
450									Conversation conversation = xmppConnectionService
451										.findOrCreateConversation(account,
452												conferenceJid, true);
453									conversation.setBookmark(bookmark);
454									if (!conversation.getMucOptions().online()) {
455										xmppConnectionService
456											.joinMuc(conversation);
457									}
458									dialog.dismiss();
459									switchToConversation(conversation);
460								}
461							} else {
462								Conversation conversation = xmppConnectionService
463									.findOrCreateConversation(account,
464											conferenceJid, true);
465								if (!conversation.getMucOptions().online()) {
466									xmppConnectionService.joinMuc(conversation);
467								}
468								dialog.dismiss();
469								switchToConversation(conversation);
470							}
471						} else {
472							jid.setError(getString(R.string.invalid_jid));
473						}
474					}
475				});
476	}
477
478	protected void switchToConversation(Contact contact) {
479		Conversation conversation = xmppConnectionService
480			.findOrCreateConversation(contact.getAccount(),
481					contact.getJid(), false);
482		switchToConversation(conversation);
483	}
484
485	private void populateAccountSpinner(Spinner spinner) {
486		ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
487				android.R.layout.simple_spinner_item, mActivatedAccounts);
488		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
489		spinner.setAdapter(adapter);
490	}
491
492	@Override
493	public boolean onCreateOptionsMenu(Menu menu) {
494		this.mOptionsMenu = menu;
495		getMenuInflater().inflate(R.menu.start_conversation, menu);
496		MenuItem menuCreateContact = menu
497			.findItem(R.id.action_create_contact);
498		MenuItem menuCreateConference = menu
499			.findItem(R.id.action_join_conference);
500		mMenuSearchView = menu.findItem(R.id.action_search);
501		mMenuSearchView.setOnActionExpandListener(mOnActionExpandListener);
502		View mSearchView = mMenuSearchView.getActionView();
503		mSearchEditText = (EditText) mSearchView
504			.findViewById(R.id.search_field);
505		mSearchEditText.addTextChangedListener(mSearchTextWatcher);
506		if (getActionBar().getSelectedNavigationIndex() == 0) {
507			menuCreateConference.setVisible(false);
508		} else {
509			menuCreateContact.setVisible(false);
510		}
511		if (mInitialJid != null) {
512			mMenuSearchView.expandActionView();
513			mSearchEditText.append(mInitialJid);
514			filter(mInitialJid);
515		}
516		return true;
517	}
518
519	@Override
520	public boolean onOptionsItemSelected(MenuItem item) {
521		switch (item.getItemId()) {
522			case R.id.action_create_contact:
523				showCreateContactDialog(null,null);
524				return true;
525			case R.id.action_join_conference:
526				showJoinConferenceDialog(null);
527				return true;
528			case R.id.action_scan_qr_code:
529				new IntentIntegrator(this).initiateScan();
530				return true;
531		}
532		return super.onOptionsItemSelected(item);
533	}
534
535	@Override
536	public boolean onKeyUp(int keyCode, KeyEvent event) {
537		if (keyCode == KeyEvent.KEYCODE_SEARCH && !event.isLongPress()) {
538			mOptionsMenu.findItem(R.id.action_search).expandActionView();
539			return true;
540		}
541		return super.onKeyUp(keyCode, event);
542	}
543
544	@Override
545	public void onActivityResult(int requestCode, int resultCode, Intent intent) {
546		if ((requestCode & 0xFFFF) == IntentIntegrator.REQUEST_CODE) {
547			IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
548			if (scanResult != null && scanResult.getFormatName() != null) {
549				String data = scanResult.getContents();
550				Invite invite = new Invite(data);
551				if (xmppConnectionServiceBound) {
552					invite.invite();
553				} else if (invite.getJid() != null) {
554					this.mPendingInvite = invite;
555				} else {
556					this.mPendingInvite = null;
557				}
558			}
559		}
560		super.onActivityResult(requestCode, requestCode, intent);
561	}
562
563	@Override
564	protected void onBackendConnected() {
565		this.mActivatedAccounts.clear();
566		for (Account account : xmppConnectionService.getAccounts()) {
567			if (account.getStatus() != Account.State.DISABLED) {
568				this.mActivatedAccounts.add(account.getJid().toBareJid().toString());
569			}
570		}
571		this.mKnownHosts = xmppConnectionService.getKnownHosts();
572		this.mKnownConferenceHosts = xmppConnectionService
573			.getKnownConferenceHosts();
574		if (this.mPendingInvite != null) {
575			mPendingInvite.invite();
576			this.mPendingInvite = null;
577		} else if (!handleIntent(getIntent())) {
578			if (mSearchEditText != null) {
579				filter(mSearchEditText.getText().toString());
580			} else {
581				filter(null);
582			}
583		}
584		setIntent(null);
585	}
586
587	@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
588	Invite getInviteJellyBean(NdefRecord record) {
589		return new Invite(record.toUri());
590	}
591
592	protected boolean handleIntent(Intent intent) {
593		if (intent == null || intent.getAction() == null) {
594			return false;
595		}
596		switch (intent.getAction()) {
597			case Intent.ACTION_SENDTO:
598			case Intent.ACTION_VIEW:
599				Log.d(Config.LOGTAG, "received uri=" + intent.getData());
600				return new Invite(intent.getData()).invite();
601			case NfcAdapter.ACTION_NDEF_DISCOVERED:
602				for (Parcelable message : getIntent().getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)) {
603					if (message instanceof NdefMessage) {
604						Log.d(Config.LOGTAG, "received message=" + message);
605						for (NdefRecord record : ((NdefMessage) message).getRecords()) {
606							switch (record.getTnf()) {
607								case NdefRecord.TNF_WELL_KNOWN:
608									if (Arrays.equals(record.getType(), NdefRecord.RTD_URI)) {
609										if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
610											return getInviteJellyBean(record).invite();
611										} else {
612											byte[] payload = record.getPayload();
613											if (payload[0] == 0) {
614												return new Invite(Uri.parse(new String(Arrays.copyOfRange(
615																	payload, 1, payload.length)))).invite();
616											}
617										}
618									}
619							}
620						}
621					}
622				}
623		}
624		return false;
625	}
626
627	private boolean handleJid(Invite invite) {
628		List<Contact> contacts = xmppConnectionService.findContacts(invite.getJid());
629		if (contacts.size() == 0) {
630			showCreateContactDialog(invite.getJid().toString(),invite.getFingerprint());
631			return false;
632		} else if (contacts.size() == 1) {
633			Contact contact = contacts.get(0);
634			if (invite.getFingerprint() != null) {
635				if (contact.addOtrFingerprint(invite.getFingerprint())) {
636					Log.d(Config.LOGTAG,"added new fingerprint");
637					xmppConnectionService.syncRosterToDisk(contact.getAccount());
638				}
639			}
640			switchToConversation(contact);
641			return true;
642		} else {
643			if (mMenuSearchView != null) {
644				mMenuSearchView.expandActionView();
645				mSearchEditText.setText("");
646				mSearchEditText.append(invite.getJid().toString());
647				filter(invite.getJid().toString());
648			} else {
649				mInitialJid = invite.getJid().toString();
650			}
651			return true;
652		}
653	}
654
655	protected void filter(String needle) {
656		if (xmppConnectionServiceBound) {
657			this.filterContacts(needle);
658			this.filterConferences(needle);
659		}
660	}
661
662	protected void filterContacts(String needle) {
663		this.contacts.clear();
664		for (Account account : xmppConnectionService.getAccounts()) {
665			if (account.getStatus() != Account.State.DISABLED) {
666				for (Contact contact : account.getRoster().getContacts()) {
667					if (contact.showInRoster() && contact.match(needle)) {
668						this.contacts.add(contact);
669					}
670				}
671			}
672		}
673		Collections.sort(this.contacts);
674		mContactsAdapter.notifyDataSetChanged();
675	}
676
677	protected void filterConferences(String needle) {
678		this.conferences.clear();
679		for (Account account : xmppConnectionService.getAccounts()) {
680			if (account.getStatus() != Account.State.DISABLED) {
681				for (Bookmark bookmark : account.getBookmarks()) {
682					if (bookmark.match(needle)) {
683						this.conferences.add(bookmark);
684					}
685				}
686			}
687		}
688		Collections.sort(this.conferences);
689		mConferenceAdapter.notifyDataSetChanged();
690	}
691
692	private void onTabChanged() {
693		invalidateOptionsMenu();
694	}
695
696	@Override
697	public void OnUpdateBlocklist(final Status status) {
698		runOnUiThread(new Runnable() {
699
700			@Override
701			public void run() {
702				if (mSearchEditText != null) {
703					filter(mSearchEditText.getText().toString());
704				}
705			}
706		});
707	}
708
709	public static class MyListFragment extends ListFragment {
710		private AdapterView.OnItemClickListener mOnItemClickListener;
711		private int mResContextMenu;
712
713		public void setContextMenu(final int res) {
714			this.mResContextMenu = res;
715		}
716
717		@Override
718		public void onListItemClick(final ListView l, final View v, final int position, final long id) {
719			if (mOnItemClickListener != null) {
720				mOnItemClickListener.onItemClick(l, v, position, id);
721			}
722		}
723
724		public void setOnListItemClickListener(AdapterView.OnItemClickListener l) {
725			this.mOnItemClickListener = l;
726		}
727
728		@Override
729		public void onViewCreated(final View view, final Bundle savedInstanceState) {
730			super.onViewCreated(view, savedInstanceState);
731			registerForContextMenu(getListView());
732			getListView().setFastScrollEnabled(true);
733		}
734
735		@Override
736		public void onCreateContextMenu(final ContextMenu menu, final View v,
737				final ContextMenuInfo menuInfo) {
738			super.onCreateContextMenu(menu, v, menuInfo);
739			final StartConversationActivity activity = (StartConversationActivity) getActivity();
740			activity.getMenuInflater().inflate(mResContextMenu, menu);
741			final AdapterView.AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) menuInfo;
742			if (mResContextMenu == R.menu.conference_context) {
743				activity.conference_context_id = acmi.position;
744			} else {
745				activity.contact_context_id = acmi.position;
746				final Blockable contact = (Contact) activity.contacts.get(acmi.position);
747
748				final MenuItem blockUnblockItem = menu.findItem(R.id.context_contact_block_unblock);
749				if (blockUnblockItem != null) {
750					if (contact.isBlocked()) {
751						blockUnblockItem.setTitle(R.string.unblock_contact);
752					} else {
753						blockUnblockItem.setTitle(R.string.block_contact);
754					}
755				}
756			}
757		}
758
759		@Override
760		public boolean onContextItemSelected(final MenuItem item) {
761			StartConversationActivity activity = (StartConversationActivity) getActivity();
762			switch (item.getItemId()) {
763				case R.id.context_start_conversation:
764					activity.openConversationForContact();
765					break;
766				case R.id.context_contact_details:
767					activity.openDetailsForContact();
768					break;
769				case R.id.context_contact_block_unblock:
770					activity.toggleContactBlock();
771					break;
772				case R.id.context_delete_contact:
773					activity.deleteContact();
774					break;
775				case R.id.context_join_conference:
776					activity.openConversationForBookmark();
777					break;
778				case R.id.context_delete_conference:
779					activity.deleteConference();
780			}
781			return true;
782		}
783	}
784
785	private class Invite extends XmppUri {
786
787		public Invite(final Uri uri) {
788			super(uri);
789		}
790
791		public Invite(final String uri) {
792			super(uri);
793		}
794
795		boolean invite() {
796			if (jid != null) {
797				if (muc) {
798					showJoinConferenceDialog(jid);
799				} else {
800					return handleJid(this);
801				}
802			}
803			return false;
804		}
805	}
806}