ConversationActivity.java

  1package eu.siacs.conversations.ui;
  2
  3import android.annotation.SuppressLint;
  4import android.app.ActionBar;
  5import android.app.AlertDialog;
  6import android.app.FragmentTransaction;
  7import android.app.PendingIntent;
  8import android.content.DialogInterface;
  9import android.content.DialogInterface.OnClickListener;
 10import android.content.Intent;
 11import android.content.IntentSender.SendIntentException;
 12import android.net.Uri;
 13import android.os.Bundle;
 14import android.os.SystemClock;
 15import android.provider.MediaStore;
 16import android.support.v4.widget.SlidingPaneLayout;
 17import android.support.v4.widget.SlidingPaneLayout.PanelSlideListener;
 18import android.view.KeyEvent;
 19import android.view.Menu;
 20import android.view.MenuItem;
 21import android.view.View;
 22import android.widget.AdapterView;
 23import android.widget.AdapterView.OnItemClickListener;
 24import android.widget.ArrayAdapter;
 25import android.widget.CheckBox;
 26import android.widget.ListView;
 27import android.widget.PopupMenu;
 28import android.widget.PopupMenu.OnMenuItemClickListener;
 29import android.widget.Toast;
 30
 31import java.util.ArrayList;
 32import java.util.List;
 33
 34import eu.siacs.conversations.R;
 35import eu.siacs.conversations.entities.Contact;
 36import eu.siacs.conversations.entities.Conversation;
 37import eu.siacs.conversations.entities.Message;
 38import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
 39import eu.siacs.conversations.services.XmppConnectionService.OnConversationUpdate;
 40import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate;
 41import eu.siacs.conversations.ui.adapter.ConversationAdapter;
 42import eu.siacs.conversations.utils.ExceptionHelper;
 43
 44public class ConversationActivity extends XmppActivity implements
 45		OnAccountUpdate, OnConversationUpdate, OnRosterUpdate {
 46
 47	public static final String VIEW_CONVERSATION = "viewConversation";
 48	public static final String CONVERSATION = "conversationUuid";
 49	public static final String TEXT = "text";
 50	public static final String PRESENCE = "eu.siacs.conversations.presence";
 51
 52	public static final int REQUEST_SEND_MESSAGE = 0x0201;
 53	public static final int REQUEST_DECRYPT_PGP = 0x0202;
 54	public static final int REQUEST_ENCRYPT_MESSAGE = 0x0207;
 55	private static final int REQUEST_ATTACH_FILE_DIALOG = 0x0203;
 56	private static final int REQUEST_IMAGE_CAPTURE = 0x0204;
 57	private static final int REQUEST_RECORD_AUDIO = 0x0205;
 58	private static final int REQUEST_SEND_PGP_IMAGE = 0x0206;
 59	private static final int ATTACHMENT_CHOICE_CHOOSE_IMAGE = 0x0301;
 60	private static final int ATTACHMENT_CHOICE_TAKE_PHOTO = 0x0302;
 61	private static final int ATTACHMENT_CHOICE_RECORD_VOICE = 0x0303;
 62	private static final String STATE_OPEN_CONVERSATION = "state_open_conversation";
 63	private static final String STATE_PANEL_OPEN = "state_panel_open";
 64	private static final String STATE_PENDING_URI = "state_pending_uri";
 65
 66	private String mOpenConverstaion = null;
 67	private boolean mPanelOpen = true;
 68	private Uri mPendingImageUri = null;
 69
 70	private View mContentView;
 71
 72	private List<Conversation> conversationList = new ArrayList<Conversation>();
 73	private Conversation selectedConversation = null;
 74	private ListView listView;
 75	private ConversationFragment mConversationFragment;
 76
 77	private ArrayAdapter<Conversation> listAdapter;
 78
 79	private Toast prepareImageToast;
 80
 81
 82	public List<Conversation> getConversationList() {
 83		return this.conversationList;
 84	}
 85
 86	public Conversation getSelectedConversation() {
 87		return this.selectedConversation;
 88	}
 89
 90	public void setSelectedConversation(Conversation conversation) {
 91		this.selectedConversation = conversation;
 92	}
 93
 94	public ListView getConversationListView() {
 95		return this.listView;
 96	}
 97
 98	public void showConversationsOverview() {
 99		if (mContentView instanceof SlidingPaneLayout) {
100			SlidingPaneLayout mSlidingPaneLayout = (SlidingPaneLayout) mContentView;
101			mSlidingPaneLayout.openPane();
102		}
103	}
104
105	@Override
106	protected String getShareableUri() {
107		Conversation conversation = getSelectedConversation();
108		if (conversation != null) {
109			return "xmpp:" + conversation.getAccount().getJid();
110		} else {
111			return "";
112		}
113	}
114
115	public void hideConversationsOverview() {
116		if (mContentView instanceof SlidingPaneLayout) {
117			SlidingPaneLayout mSlidingPaneLayout = (SlidingPaneLayout) mContentView;
118			mSlidingPaneLayout.closePane();
119		}
120	}
121
122	public boolean isConversationsOverviewHideable() {
123		if (mContentView instanceof SlidingPaneLayout) {
124			SlidingPaneLayout mSlidingPaneLayout = (SlidingPaneLayout) mContentView;
125			return mSlidingPaneLayout.isSlideable();
126		} else {
127			return false;
128		}
129	}
130
131	public boolean isConversationsOverviewVisable() {
132		if (mContentView instanceof SlidingPaneLayout) {
133			SlidingPaneLayout mSlidingPaneLayout = (SlidingPaneLayout) mContentView;
134			return mSlidingPaneLayout.isOpen();
135		} else {
136			return true;
137		}
138	}
139
140	@Override
141	protected void onCreate(Bundle savedInstanceState) {
142		super.onCreate(savedInstanceState);
143		if (savedInstanceState != null) {mOpenConverstaion = savedInstanceState.getString(
144					STATE_OPEN_CONVERSATION, null);
145			mPanelOpen = savedInstanceState.getBoolean(STATE_PANEL_OPEN, true);
146			String pending = savedInstanceState.getString(STATE_PENDING_URI, null);
147			if (pending != null) {
148				mPendingImageUri = Uri.parse(pending);
149			}
150		}
151
152		setContentView(R.layout.fragment_conversations_overview);
153
154		this.mConversationFragment = new ConversationFragment();
155		FragmentTransaction transaction = getFragmentManager().beginTransaction();
156		transaction.replace(R.id.selected_conversation, this.mConversationFragment, "conversation");
157		transaction.commit();
158
159		listView = (ListView) findViewById(R.id.list);
160		this.listAdapter = new ConversationAdapter(this, conversationList);
161		listView.setAdapter(this.listAdapter);
162
163		getActionBar().setDisplayHomeAsUpEnabled(false);
164		getActionBar().setHomeButtonEnabled(false);
165
166		listView.setOnItemClickListener(new OnItemClickListener() {
167
168			@Override
169			public void onItemClick(AdapterView<?> arg0, View clickedView,
170									int position, long arg3) {
171				if (getSelectedConversation() != conversationList.get(position)) {
172					setSelectedConversation(conversationList.get(position));
173					ConversationActivity.this.mConversationFragment.reInit(getSelectedConversation());
174				}
175				hideConversationsOverview();
176			}
177		});
178		mContentView = findViewById(R.id.content_view_spl);
179		if (mContentView == null) {
180			mContentView = findViewById(R.id.content_view_ll);
181		}
182		if (mContentView instanceof SlidingPaneLayout) {
183			SlidingPaneLayout mSlidingPaneLayout = (SlidingPaneLayout) mContentView;
184			mSlidingPaneLayout.setParallaxDistance(150);
185			mSlidingPaneLayout
186					.setShadowResource(R.drawable.es_slidingpane_shadow);
187			mSlidingPaneLayout.setSliderFadeColor(0);
188			mSlidingPaneLayout.setPanelSlideListener(new PanelSlideListener() {
189
190				@Override
191				public void onPanelOpened(View arg0) {
192					ActionBar ab = getActionBar();
193					if (ab != null) {
194						ab.setDisplayHomeAsUpEnabled(false);
195						ab.setHomeButtonEnabled(false);
196						ab.setTitle(R.string.app_name);
197					}
198					invalidateOptionsMenu();
199					hideKeyboard();
200					if (xmppConnectionServiceBound) {
201						xmppConnectionService.getNotificationService()
202								.setOpenConversation(null);
203					}
204					closeContextMenu();
205				}
206
207				@Override
208				public void onPanelClosed(View arg0) {
209					openConversation();
210				}
211
212				@Override
213				public void onPanelSlide(View arg0, float arg1) {
214					// TODO Auto-generated method stub
215
216				}
217			});
218		}
219	}
220
221	public void openConversation() {
222		ActionBar ab = getActionBar();
223		if (ab != null) {
224			ab.setDisplayHomeAsUpEnabled(true);
225			ab.setHomeButtonEnabled(true);
226			if (getSelectedConversation().getMode() == Conversation.MODE_SINGLE
227					|| ConversationActivity.this
228					.useSubjectToIdentifyConference()) {
229				ab.setTitle(getSelectedConversation().getName());
230			} else {
231				ab.setTitle(getSelectedConversation().getContactJid()
232						.split("/")[0]);
233			}
234		}
235		invalidateOptionsMenu();
236		if (xmppConnectionServiceBound) {
237			xmppConnectionService.getNotificationService().setOpenConversation(getSelectedConversation());
238			if (!getSelectedConversation().isRead()) {
239				xmppConnectionService.markRead(getSelectedConversation(), true);
240				listView.invalidateViews();
241			}
242		}
243	}
244
245	@Override
246	public boolean onCreateOptionsMenu(Menu menu) {
247		getMenuInflater().inflate(R.menu.conversations, menu);
248		MenuItem menuSecure = menu.findItem(R.id.action_security);
249		MenuItem menuArchive = menu.findItem(R.id.action_archive);
250		MenuItem menuMucDetails = menu.findItem(R.id.action_muc_details);
251		MenuItem menuContactDetails = menu
252				.findItem(R.id.action_contact_details);
253		MenuItem menuAttach = menu.findItem(R.id.action_attach_file);
254		MenuItem menuClearHistory = menu.findItem(R.id.action_clear_history);
255		MenuItem menuAdd = menu.findItem(R.id.action_add);
256		MenuItem menuInviteContact = menu.findItem(R.id.action_invite);
257		MenuItem menuMute = menu.findItem(R.id.action_mute);
258
259		if (isConversationsOverviewVisable()
260				&& isConversationsOverviewHideable()) {
261			menuArchive.setVisible(false);
262			menuMucDetails.setVisible(false);
263			menuContactDetails.setVisible(false);
264			menuSecure.setVisible(false);
265			menuInviteContact.setVisible(false);
266			menuAttach.setVisible(false);
267			menuClearHistory.setVisible(false);
268			menuMute.setVisible(false);
269		} else {
270			menuAdd.setVisible(!isConversationsOverviewHideable());
271			if (this.getSelectedConversation() != null) {
272				if (this.getSelectedConversation().getLatestMessage()
273						.getEncryption() != Message.ENCRYPTION_NONE) {
274					menuSecure.setIcon(R.drawable.ic_action_secure);
275				}
276				if (this.getSelectedConversation().getMode() == Conversation.MODE_MULTI) {
277					menuContactDetails.setVisible(false);
278					menuAttach.setVisible(false);
279				} else {
280					menuMucDetails.setVisible(false);
281					menuInviteContact.setVisible(false);
282				}
283			}
284		}
285		return true;
286	}
287
288	private void selectPresenceToAttachFile(final int attachmentChoice) {
289		selectPresence(getSelectedConversation(), new OnPresenceSelected() {
290
291			@Override
292			public void onPresenceSelected() {
293				if (attachmentChoice == ATTACHMENT_CHOICE_TAKE_PHOTO) {
294					mPendingImageUri = xmppConnectionService.getFileBackend()
295							.getTakePhotoUri();
296					Intent takePictureIntent = new Intent(
297							MediaStore.ACTION_IMAGE_CAPTURE);
298					takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
299							mPendingImageUri);
300					if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
301						startActivityForResult(takePictureIntent,
302								REQUEST_IMAGE_CAPTURE);
303					}
304				} else if (attachmentChoice == ATTACHMENT_CHOICE_CHOOSE_IMAGE) {
305					Intent attachFileIntent = new Intent();
306					attachFileIntent.setType("image/*");
307					attachFileIntent.setAction(Intent.ACTION_GET_CONTENT);
308					Intent chooser = Intent.createChooser(attachFileIntent,
309							getString(R.string.attach_file));
310					startActivityForResult(chooser, REQUEST_ATTACH_FILE_DIALOG);
311				} else if (attachmentChoice == ATTACHMENT_CHOICE_RECORD_VOICE) {
312					Intent intent = new Intent(
313							MediaStore.Audio.Media.RECORD_SOUND_ACTION);
314					startActivityForResult(intent, REQUEST_RECORD_AUDIO);
315				}
316			}
317		});
318	}
319
320	private void attachFile(final int attachmentChoice) {
321		final Conversation conversation = getSelectedConversation();
322		if (conversation.getNextEncryption(forceEncryption()) == Message.ENCRYPTION_PGP) {
323			if (hasPgp()) {
324				if (conversation.getContact().getPgpKeyId() != 0) {
325					xmppConnectionService.getPgpEngine().hasKey(
326							conversation.getContact(),
327							new UiCallback<Contact>() {
328
329								@Override
330								public void userInputRequried(PendingIntent pi,
331															  Contact contact) {
332									ConversationActivity.this.runIntent(pi,
333											attachmentChoice);
334								}
335
336								@Override
337								public void success(Contact contact) {
338									selectPresenceToAttachFile(attachmentChoice);
339								}
340
341								@Override
342								public void error(int error, Contact contact) {
343									displayErrorDialog(error);
344								}
345							});
346				} else {
347					final ConversationFragment fragment = (ConversationFragment) getFragmentManager()
348							.findFragmentByTag("conversation");
349					if (fragment != null) {
350						fragment.showNoPGPKeyDialog(false,
351								new OnClickListener() {
352
353									@Override
354									public void onClick(DialogInterface dialog,
355														int which) {
356										conversation
357												.setNextEncryption(Message.ENCRYPTION_NONE);
358										xmppConnectionService.databaseBackend
359												.updateConversation(conversation);
360										selectPresenceToAttachFile(attachmentChoice);
361									}
362								});
363					}
364				}
365			} else {
366				showInstallPgpDialog();
367			}
368		} else if (getSelectedConversation().getNextEncryption(
369				forceEncryption()) == Message.ENCRYPTION_NONE) {
370			selectPresenceToAttachFile(attachmentChoice);
371		} else {
372			selectPresenceToAttachFile(attachmentChoice);
373		}
374	}
375
376	@Override
377	public boolean onOptionsItemSelected(MenuItem item) {
378		if (item.getItemId() == android.R.id.home) {
379			showConversationsOverview();
380			return true;
381		} else if (item.getItemId() == R.id.action_add) {
382			startActivity(new Intent(this, StartConversationActivity.class));
383			return true;
384		} else if (getSelectedConversation() != null) {
385			switch (item.getItemId()) {
386				case R.id.action_attach_file:
387					attachFileDialog();
388					break;
389				case R.id.action_archive:
390					this.endConversation(getSelectedConversation());
391					break;
392				case R.id.action_contact_details:
393					Contact contact = this.getSelectedConversation().getContact();
394					if (contact.showInRoster()) {
395						switchToContactDetails(contact);
396					} else {
397						showAddToRosterDialog(getSelectedConversation());
398					}
399					break;
400				case R.id.action_muc_details:
401					Intent intent = new Intent(this,
402							ConferenceDetailsActivity.class);
403					intent.setAction(ConferenceDetailsActivity.ACTION_VIEW_MUC);
404					intent.putExtra("uuid", getSelectedConversation().getUuid());
405					startActivity(intent);
406					break;
407				case R.id.action_invite:
408					inviteToConversation(getSelectedConversation());
409					break;
410				case R.id.action_security:
411					selectEncryptionDialog(getSelectedConversation());
412					break;
413				case R.id.action_clear_history:
414					clearHistoryDialog(getSelectedConversation());
415					break;
416				case R.id.action_mute:
417					muteConversationDialog(getSelectedConversation());
418					break;
419				default:
420					break;
421			}
422			return super.onOptionsItemSelected(item);
423		} else {
424			return super.onOptionsItemSelected(item);
425		}
426	}
427
428	public void endConversation(Conversation conversation) {
429		conversation.setStatus(Conversation.STATUS_ARCHIVED);
430		showConversationsOverview();
431		xmppConnectionService.archiveConversation(conversation);
432		if (conversationList.size() > 0) {
433			setSelectedConversation(conversationList.get(0));
434			this.mConversationFragment.reInit(getSelectedConversation());
435		} else {
436			setSelectedConversation(null);
437		}
438	}
439
440	@SuppressLint("InflateParams")
441	protected void clearHistoryDialog(final Conversation conversation) {
442		AlertDialog.Builder builder = new AlertDialog.Builder(this);
443		builder.setTitle(getString(R.string.clear_conversation_history));
444		View dialogView = getLayoutInflater().inflate(
445				R.layout.dialog_clear_history, null);
446		final CheckBox endConversationCheckBox = (CheckBox) dialogView
447				.findViewById(R.id.end_conversation_checkbox);
448		builder.setView(dialogView);
449		builder.setNegativeButton(getString(R.string.cancel), null);
450		builder.setPositiveButton(getString(R.string.delete_messages),
451				new OnClickListener() {
452
453					@Override
454					public void onClick(DialogInterface dialog, int which) {
455						ConversationActivity.this.xmppConnectionService
456								.clearConversationHistory(conversation);
457						if (endConversationCheckBox.isChecked()) {
458							endConversation(conversation);
459						}
460					}
461				});
462		builder.create().show();
463	}
464
465	protected void attachFileDialog() {
466		View menuAttachFile = findViewById(R.id.action_attach_file);
467		if (menuAttachFile == null) {
468			return;
469		}
470		PopupMenu attachFilePopup = new PopupMenu(this, menuAttachFile);
471		attachFilePopup.inflate(R.menu.attachment_choices);
472		attachFilePopup
473				.setOnMenuItemClickListener(new OnMenuItemClickListener() {
474
475					@Override
476					public boolean onMenuItemClick(MenuItem item) {
477						switch (item.getItemId()) {
478							case R.id.attach_choose_picture:
479								attachFile(ATTACHMENT_CHOICE_CHOOSE_IMAGE);
480								break;
481							case R.id.attach_take_picture:
482								attachFile(ATTACHMENT_CHOICE_TAKE_PHOTO);
483								break;
484							case R.id.attach_record_voice:
485								attachFile(ATTACHMENT_CHOICE_RECORD_VOICE);
486								break;
487						}
488						return false;
489					}
490				});
491		attachFilePopup.show();
492	}
493
494	protected void selectEncryptionDialog(final Conversation conversation) {
495		View menuItemView = findViewById(R.id.action_security);
496		if (menuItemView == null) {
497			return;
498		}
499		PopupMenu popup = new PopupMenu(this, menuItemView);
500		final ConversationFragment fragment = (ConversationFragment) getFragmentManager()
501				.findFragmentByTag("conversation");
502		if (fragment != null) {
503			popup.setOnMenuItemClickListener(new OnMenuItemClickListener() {
504
505				@Override
506				public boolean onMenuItemClick(MenuItem item) {
507					switch (item.getItemId()) {
508						case R.id.encryption_choice_none:
509							conversation.setNextEncryption(Message.ENCRYPTION_NONE);
510							item.setChecked(true);
511							break;
512						case R.id.encryption_choice_otr:
513							conversation.setNextEncryption(Message.ENCRYPTION_OTR);
514							item.setChecked(true);
515							break;
516						case R.id.encryption_choice_pgp:
517							if (hasPgp()) {
518								if (conversation.getAccount().getKeys()
519										.has("pgp_signature")) {
520									conversation
521											.setNextEncryption(Message.ENCRYPTION_PGP);
522									item.setChecked(true);
523								} else {
524									announcePgp(conversation.getAccount(),
525											conversation);
526								}
527							} else {
528								showInstallPgpDialog();
529							}
530							break;
531						default:
532							conversation.setNextEncryption(Message.ENCRYPTION_NONE);
533							break;
534					}
535					xmppConnectionService.databaseBackend
536							.updateConversation(conversation);
537					fragment.updateChatMsgHint();
538					return true;
539				}
540			});
541			popup.inflate(R.menu.encryption_choices);
542			MenuItem otr = popup.getMenu().findItem(R.id.encryption_choice_otr);
543			MenuItem none = popup.getMenu().findItem(
544					R.id.encryption_choice_none);
545			if (conversation.getMode() == Conversation.MODE_MULTI) {
546				otr.setEnabled(false);
547			} else {
548				if (forceEncryption()) {
549					none.setVisible(false);
550				}
551			}
552			switch (conversation.getNextEncryption(forceEncryption())) {
553				case Message.ENCRYPTION_NONE:
554					none.setChecked(true);
555					break;
556				case Message.ENCRYPTION_OTR:
557					otr.setChecked(true);
558					break;
559				case Message.ENCRYPTION_PGP:
560					popup.getMenu().findItem(R.id.encryption_choice_pgp)
561							.setChecked(true);
562					break;
563				default:
564					popup.getMenu().findItem(R.id.encryption_choice_none)
565							.setChecked(true);
566					break;
567			}
568			popup.show();
569		}
570	}
571
572	protected void muteConversationDialog(final Conversation conversation) {
573		AlertDialog.Builder builder = new AlertDialog.Builder(this);
574		builder.setTitle(R.string.disable_notifications_for_this_conversation);
575		final int[] durations = getResources().getIntArray(
576				R.array.mute_options_durations);
577		builder.setItems(R.array.mute_options_descriptions,
578				new OnClickListener() {
579
580					@Override
581					public void onClick(DialogInterface dialog, int which) {
582						long till;
583						if (durations[which] == -1) {
584							till = Long.MAX_VALUE;
585						} else {
586							till = SystemClock.elapsedRealtime()
587									+ (durations[which] * 1000);
588						}
589						conversation.setMutedTill(till);
590						ConversationActivity.this.xmppConnectionService.databaseBackend
591								.updateConversation(conversation);
592						ConversationFragment selectedFragment = (ConversationFragment) getFragmentManager()
593								.findFragmentByTag("conversation");
594						if (selectedFragment != null) {
595							selectedFragment.updateMessages();
596						}
597					}
598				});
599		builder.create().show();
600	}
601
602	@Override
603	public boolean onKeyDown(int keyCode, KeyEvent event) {
604		if (keyCode == KeyEvent.KEYCODE_BACK) {
605			if (!isConversationsOverviewVisable()) {
606				showConversationsOverview();
607				return false;
608			}
609		}
610		return super.onKeyDown(keyCode, event);
611	}
612
613	@Override
614	protected void onNewIntent(Intent intent) {
615		if (xmppConnectionServiceBound) {
616			if (intent != null && VIEW_CONVERSATION.equals(intent.getType())) {
617				handleViewConversationIntent(intent);
618			}
619		} else {
620			setIntent(intent);
621		}
622	}
623
624	@Override
625	public void onStart() {
626		super.onStart();
627		if (this.xmppConnectionServiceBound) {
628			this.onBackendConnected();
629		}
630		if (conversationList.size() >= 1) {
631			this.onConversationUpdate();
632		}
633	}
634
635	@Override
636	protected void onStop() {
637		if (xmppConnectionServiceBound) {
638			xmppConnectionService.removeOnConversationListChangedListener();
639			xmppConnectionService.removeOnAccountListChangedListener();
640			xmppConnectionService.removeOnRosterUpdateListener();
641			xmppConnectionService.getNotificationService().setOpenConversation(
642					null);
643		}
644		super.onStop();
645	}
646
647	@Override
648	public void onSaveInstanceState(Bundle savedInstanceState) {
649		Conversation conversation = getSelectedConversation();
650		if (conversation != null) {
651			savedInstanceState.putString(STATE_OPEN_CONVERSATION,
652					conversation.getUuid());
653		}
654		savedInstanceState.putBoolean(STATE_PANEL_OPEN,
655				isConversationsOverviewVisable());
656		if (this.mPendingImageUri != null) {
657			savedInstanceState.putString(STATE_PENDING_URI, this.mPendingImageUri.toString());
658		}
659		super.onSaveInstanceState(savedInstanceState);
660	}
661
662	@Override
663	void onBackendConnected() {
664		this.registerListener();
665		updateConversationList();
666
667		if (xmppConnectionService.getAccounts().size() == 0) {
668			startActivity(new Intent(this, EditAccountActivity.class));
669		} else if (conversationList.size() <= 0) {
670			startActivity(new Intent(this, StartConversationActivity.class));
671			finish();
672		} else if (getIntent() != null
673				&& VIEW_CONVERSATION.equals(getIntent().getType())) {
674			handleViewConversationIntent(getIntent());
675		} else if (mOpenConverstaion != null) {
676			selectConversationByUuid(mOpenConverstaion);
677			if (mPanelOpen) {
678				showConversationsOverview();
679			} else {
680				if (isConversationsOverviewHideable()) {
681					openConversation();
682				}
683			}
684			this.mConversationFragment.reInit(getSelectedConversation());
685			mOpenConverstaion = null;
686		} else if (getSelectedConversation() != null) {
687			this.mConversationFragment.updateMessages();
688		} else {
689			showConversationsOverview();
690			mPendingImageUri = null;
691			setSelectedConversation(conversationList.get(0));
692			this.mConversationFragment.reInit(getSelectedConversation());
693		}
694
695		if (mPendingImageUri != null) {
696			attachImageToConversation(getSelectedConversation(),
697					mPendingImageUri);
698			mPendingImageUri = null;
699		}
700		ExceptionHelper.checkForCrash(this, this.xmppConnectionService);
701		setIntent(new Intent());
702	}
703
704	private void handleViewConversationIntent(Intent intent) {
705		String uuid = (String) intent.getExtras().get(CONVERSATION);
706		String text = intent.getExtras().getString(TEXT, "");
707		selectConversationByUuid(uuid);
708		this.mConversationFragment.reInit(getSelectedConversation());
709		this.mConversationFragment.appendText(text);
710		hideConversationsOverview();
711		if (mContentView instanceof SlidingPaneLayout) {
712			openConversation();
713		}
714	}
715
716	private void selectConversationByUuid(String uuid) {
717		for (int i = 0; i < conversationList.size(); ++i) {
718			if (conversationList.get(i).getUuid().equals(uuid)) {
719				setSelectedConversation(conversationList.get(i));
720			}
721		}
722	}
723
724	public void registerListener() {
725		xmppConnectionService.setOnConversationListChangedListener(this);
726		xmppConnectionService.setOnAccountListChangedListener(this);
727		xmppConnectionService.setOnRosterUpdateListener(this);
728	}
729
730	@Override
731	protected void onActivityResult(int requestCode, int resultCode,
732									final Intent data) {
733		super.onActivityResult(requestCode, resultCode, data);
734		if (resultCode == RESULT_OK) {
735			if (requestCode == REQUEST_DECRYPT_PGP) {
736				ConversationFragment selectedFragment = (ConversationFragment) getFragmentManager()
737						.findFragmentByTag("conversation");
738				if (selectedFragment != null) {
739					selectedFragment.hideSnackbar();
740					selectedFragment.updateMessages();
741				}
742			} else if (requestCode == REQUEST_ATTACH_FILE_DIALOG) {
743				mPendingImageUri = data.getData();
744				if (xmppConnectionServiceBound) {
745					attachImageToConversation(getSelectedConversation(),
746							mPendingImageUri);
747					mPendingImageUri = null;
748				}
749			} else if (requestCode == REQUEST_SEND_PGP_IMAGE) {
750
751			} else if (requestCode == ATTACHMENT_CHOICE_CHOOSE_IMAGE) {
752				attachFile(ATTACHMENT_CHOICE_CHOOSE_IMAGE);
753			} else if (requestCode == ATTACHMENT_CHOICE_TAKE_PHOTO) {
754				attachFile(ATTACHMENT_CHOICE_TAKE_PHOTO);
755			} else if (requestCode == REQUEST_ANNOUNCE_PGP) {
756				announcePgp(getSelectedConversation().getAccount(),
757						getSelectedConversation());
758			} else if (requestCode == REQUEST_ENCRYPT_MESSAGE) {
759				// encryptTextMessage();
760			} else if (requestCode == REQUEST_IMAGE_CAPTURE && mPendingImageUri != null) {
761				if (xmppConnectionServiceBound) {
762					attachImageToConversation(getSelectedConversation(),
763							mPendingImageUri);
764					mPendingImageUri = null;
765				}
766				Intent intent = new Intent(
767						Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
768				intent.setData(mPendingImageUri);
769				sendBroadcast(intent);
770			} else if (requestCode == REQUEST_RECORD_AUDIO) {
771				attachAudioToConversation(getSelectedConversation(),
772						data.getData());
773			}
774		} else {
775			if (requestCode == REQUEST_IMAGE_CAPTURE) {
776				mPendingImageUri = null;
777			}
778		}
779	}
780
781	private void attachAudioToConversation(Conversation conversation, Uri uri) {
782
783	}
784
785	private void attachImageToConversation(Conversation conversation, Uri uri) {
786		prepareImageToast = Toast.makeText(getApplicationContext(),
787				getText(R.string.preparing_image), Toast.LENGTH_LONG);
788		prepareImageToast.show();
789		xmppConnectionService.attachImageToConversation(conversation, uri,
790				new UiCallback<Message>() {
791
792					@Override
793					public void userInputRequried(PendingIntent pi,
794												  Message object) {
795						hidePrepareImageToast();
796						ConversationActivity.this.runIntent(pi,
797								ConversationActivity.REQUEST_SEND_PGP_IMAGE);
798					}
799
800					@Override
801					public void success(Message message) {
802						xmppConnectionService.sendMessage(message);
803					}
804
805					@Override
806					public void error(int error, Message message) {
807						hidePrepareImageToast();
808						displayErrorDialog(error);
809					}
810				});
811	}
812
813	private void hidePrepareImageToast() {
814		if (prepareImageToast != null) {
815			runOnUiThread(new Runnable() {
816
817				@Override
818				public void run() {
819					prepareImageToast.cancel();
820				}
821			});
822		}
823	}
824
825	public void updateConversationList() {
826		xmppConnectionService
827				.populateWithOrderedConversations(conversationList);
828		listAdapter.notifyDataSetChanged();
829	}
830
831	public void runIntent(PendingIntent pi, int requestCode) {
832		try {
833			this.startIntentSenderForResult(pi.getIntentSender(), requestCode,
834					null, 0, 0, 0);
835		} catch (SendIntentException e1) {
836		}
837	}
838
839	public void encryptTextMessage(Message message) {
840		xmppConnectionService.getPgpEngine().encrypt(message,
841				new UiCallback<Message>() {
842
843					@Override
844					public void userInputRequried(PendingIntent pi,
845												  Message message) {
846						ConversationActivity.this.runIntent(pi,
847								ConversationActivity.REQUEST_SEND_MESSAGE);
848					}
849
850					@Override
851					public void success(Message message) {
852						message.setEncryption(Message.ENCRYPTION_DECRYPTED);
853						xmppConnectionService.sendMessage(message);
854					}
855
856					@Override
857					public void error(int error, Message message) {
858
859					}
860				});
861	}
862
863	public boolean forceEncryption() {
864		return getPreferences().getBoolean("force_encryption", false);
865	}
866
867	public boolean useSendButtonToIndicateStatus() {
868		return getPreferences().getBoolean("send_button_status", false);
869	}
870
871	public boolean indicateReceived() {
872		return getPreferences().getBoolean("indicate_received", false);
873	}
874
875	@Override
876	public void onAccountUpdate() {
877		final ConversationFragment fragment = (ConversationFragment) getFragmentManager()
878				.findFragmentByTag("conversation");
879		if (fragment != null) {
880			runOnUiThread(new Runnable() {
881
882				@Override
883				public void run() {
884					fragment.updateMessages();
885				}
886			});
887		}
888	}
889
890	@Override
891	public void onConversationUpdate() {
892		runOnUiThread(new Runnable() {
893
894			@Override
895			public void run() {
896				updateConversationList();
897				if (conversationList.size() == 0) {
898						startActivity(new Intent(getApplicationContext(),
899								StartConversationActivity.class));
900						finish();
901				} else {
902					ConversationActivity.this.mConversationFragment.updateMessages();
903				}
904			}
905		});
906	}
907
908	@Override
909	public void onRosterUpdate() {
910		runOnUiThread(new Runnable() {
911
912				@Override
913				public void run() {
914					ConversationActivity.this.mConversationFragment.updateMessages();
915				}
916			});
917	}
918}