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