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().toBareJid().toString());
232			}
233		}
234		invalidateOptionsMenu();
235		if (xmppConnectionServiceBound) {
236			xmppConnectionService.getNotificationService().setOpenConversation(getSelectedConversation());
237			if (!getSelectedConversation().isRead()) {
238				xmppConnectionService.markRead(getSelectedConversation(), true);
239				listView.invalidateViews();
240			}
241		}
242	}
243
244	@Override
245	public boolean onCreateOptionsMenu(Menu menu) {
246		getMenuInflater().inflate(R.menu.conversations, menu);
247		MenuItem menuSecure = menu.findItem(R.id.action_security);
248		MenuItem menuArchive = menu.findItem(R.id.action_archive);
249		MenuItem menuMucDetails = menu.findItem(R.id.action_muc_details);
250		MenuItem menuContactDetails = menu
251				.findItem(R.id.action_contact_details);
252		MenuItem menuAttach = menu.findItem(R.id.action_attach_file);
253		MenuItem menuClearHistory = menu.findItem(R.id.action_clear_history);
254		MenuItem menuAdd = menu.findItem(R.id.action_add);
255		MenuItem menuInviteContact = menu.findItem(R.id.action_invite);
256		MenuItem menuMute = menu.findItem(R.id.action_mute);
257
258		if (isConversationsOverviewVisable()
259				&& isConversationsOverviewHideable()) {
260			menuArchive.setVisible(false);
261			menuMucDetails.setVisible(false);
262			menuContactDetails.setVisible(false);
263			menuSecure.setVisible(false);
264			menuInviteContact.setVisible(false);
265			menuAttach.setVisible(false);
266			menuClearHistory.setVisible(false);
267			menuMute.setVisible(false);
268		} else {
269			menuAdd.setVisible(!isConversationsOverviewHideable());
270			if (this.getSelectedConversation() != null) {
271				if (this.getSelectedConversation().getLatestMessage()
272						.getEncryption() != Message.ENCRYPTION_NONE) {
273					menuSecure.setIcon(R.drawable.ic_action_secure);
274				}
275				if (this.getSelectedConversation().getMode() == Conversation.MODE_MULTI) {
276					menuContactDetails.setVisible(false);
277					menuAttach.setVisible(false);
278				} else {
279					menuMucDetails.setVisible(false);
280					menuInviteContact.setVisible(false);
281				}
282			}
283		}
284		return true;
285	}
286
287	private void selectPresenceToAttachFile(final int attachmentChoice) {
288		selectPresence(getSelectedConversation(), new OnPresenceSelected() {
289
290			@Override
291			public void onPresenceSelected() {
292				if (attachmentChoice == ATTACHMENT_CHOICE_TAKE_PHOTO) {
293					mPendingImageUri = xmppConnectionService.getFileBackend()
294							.getTakePhotoUri();
295					Intent takePictureIntent = new Intent(
296							MediaStore.ACTION_IMAGE_CAPTURE);
297					takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
298							mPendingImageUri);
299					if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
300						startActivityForResult(takePictureIntent,
301								REQUEST_IMAGE_CAPTURE);
302					}
303				} else if (attachmentChoice == ATTACHMENT_CHOICE_CHOOSE_IMAGE) {
304					Intent attachFileIntent = new Intent();
305					attachFileIntent.setType("image/*");
306					attachFileIntent.setAction(Intent.ACTION_GET_CONTENT);
307					Intent chooser = Intent.createChooser(attachFileIntent,
308							getString(R.string.attach_file));
309					startActivityForResult(chooser, REQUEST_ATTACH_FILE_DIALOG);
310				} else if (attachmentChoice == ATTACHMENT_CHOICE_RECORD_VOICE) {
311					Intent intent = new Intent(
312							MediaStore.Audio.Media.RECORD_SOUND_ACTION);
313					startActivityForResult(intent, REQUEST_RECORD_AUDIO);
314				}
315			}
316		});
317	}
318
319	private void attachFile(final int attachmentChoice) {
320		final Conversation conversation = getSelectedConversation();
321		if (conversation.getNextEncryption(forceEncryption()) == Message.ENCRYPTION_PGP) {
322			if (hasPgp()) {
323				if (conversation.getContact().getPgpKeyId() != 0) {
324					xmppConnectionService.getPgpEngine().hasKey(
325							conversation.getContact(),
326							new UiCallback<Contact>() {
327
328								@Override
329								public void userInputRequried(PendingIntent pi,
330															  Contact contact) {
331									ConversationActivity.this.runIntent(pi,
332											attachmentChoice);
333								}
334
335								@Override
336								public void success(Contact contact) {
337									selectPresenceToAttachFile(attachmentChoice);
338								}
339
340								@Override
341								public void error(int error, Contact contact) {
342									displayErrorDialog(error);
343								}
344							});
345				} else {
346					final ConversationFragment fragment = (ConversationFragment) getFragmentManager()
347							.findFragmentByTag("conversation");
348					if (fragment != null) {
349						fragment.showNoPGPKeyDialog(false,
350								new OnClickListener() {
351
352									@Override
353									public void onClick(DialogInterface dialog,
354														int which) {
355										conversation
356												.setNextEncryption(Message.ENCRYPTION_NONE);
357										xmppConnectionService.databaseBackend
358												.updateConversation(conversation);
359										selectPresenceToAttachFile(attachmentChoice);
360									}
361								});
362					}
363				}
364			} else {
365				showInstallPgpDialog();
366			}
367		} else if (getSelectedConversation().getNextEncryption(
368				forceEncryption()) == Message.ENCRYPTION_NONE) {
369			selectPresenceToAttachFile(attachmentChoice);
370		} else {
371			selectPresenceToAttachFile(attachmentChoice);
372		}
373	}
374
375	@Override
376	public boolean onOptionsItemSelected(MenuItem item) {
377		if (item.getItemId() == android.R.id.home) {
378			showConversationsOverview();
379			return true;
380		} else if (item.getItemId() == R.id.action_add) {
381			startActivity(new Intent(this, StartConversationActivity.class));
382			return true;
383		} else if (getSelectedConversation() != null) {
384			switch (item.getItemId()) {
385				case R.id.action_attach_file:
386					attachFileDialog();
387					break;
388				case R.id.action_archive:
389					this.endConversation(getSelectedConversation());
390					break;
391				case R.id.action_contact_details:
392					Contact contact = this.getSelectedConversation().getContact();
393					if (contact.showInRoster()) {
394						switchToContactDetails(contact);
395					} else {
396						showAddToRosterDialog(getSelectedConversation());
397					}
398					break;
399				case R.id.action_muc_details:
400					Intent intent = new Intent(this,
401							ConferenceDetailsActivity.class);
402					intent.setAction(ConferenceDetailsActivity.ACTION_VIEW_MUC);
403					intent.putExtra("uuid", getSelectedConversation().getUuid());
404					startActivity(intent);
405					break;
406				case R.id.action_invite:
407					inviteToConversation(getSelectedConversation());
408					break;
409				case R.id.action_security:
410					selectEncryptionDialog(getSelectedConversation());
411					break;
412				case R.id.action_clear_history:
413					clearHistoryDialog(getSelectedConversation());
414					break;
415				case R.id.action_mute:
416					muteConversationDialog(getSelectedConversation());
417					break;
418				default:
419					break;
420			}
421			return super.onOptionsItemSelected(item);
422		} else {
423			return super.onOptionsItemSelected(item);
424		}
425	}
426
427	public void endConversation(Conversation conversation) {
428		conversation.setStatus(Conversation.STATUS_ARCHIVED);
429		showConversationsOverview();
430		xmppConnectionService.archiveConversation(conversation);
431		if (conversationList.size() > 0) {
432			setSelectedConversation(conversationList.get(0));
433			this.mConversationFragment.reInit(getSelectedConversation());
434		} else {
435			setSelectedConversation(null);
436		}
437	}
438
439	@SuppressLint("InflateParams")
440	protected void clearHistoryDialog(final Conversation conversation) {
441		AlertDialog.Builder builder = new AlertDialog.Builder(this);
442		builder.setTitle(getString(R.string.clear_conversation_history));
443		View dialogView = getLayoutInflater().inflate(
444				R.layout.dialog_clear_history, null);
445		final CheckBox endConversationCheckBox = (CheckBox) dialogView
446				.findViewById(R.id.end_conversation_checkbox);
447		builder.setView(dialogView);
448		builder.setNegativeButton(getString(R.string.cancel), null);
449		builder.setPositiveButton(getString(R.string.delete_messages),
450				new OnClickListener() {
451
452					@Override
453					public void onClick(DialogInterface dialog, int which) {
454						ConversationActivity.this.xmppConnectionService
455								.clearConversationHistory(conversation);
456						if (endConversationCheckBox.isChecked()) {
457							endConversation(conversation);
458						}
459					}
460				});
461		builder.create().show();
462	}
463
464	protected void attachFileDialog() {
465		View menuAttachFile = findViewById(R.id.action_attach_file);
466		if (menuAttachFile == null) {
467			return;
468		}
469		PopupMenu attachFilePopup = new PopupMenu(this, menuAttachFile);
470		attachFilePopup.inflate(R.menu.attachment_choices);
471		attachFilePopup
472				.setOnMenuItemClickListener(new OnMenuItemClickListener() {
473
474					@Override
475					public boolean onMenuItemClick(MenuItem item) {
476						switch (item.getItemId()) {
477							case R.id.attach_choose_picture:
478								attachFile(ATTACHMENT_CHOICE_CHOOSE_IMAGE);
479								break;
480							case R.id.attach_take_picture:
481								attachFile(ATTACHMENT_CHOICE_TAKE_PHOTO);
482								break;
483							case R.id.attach_record_voice:
484								attachFile(ATTACHMENT_CHOICE_RECORD_VOICE);
485								break;
486						}
487						return false;
488					}
489				});
490		attachFilePopup.show();
491	}
492
493	protected void selectEncryptionDialog(final Conversation conversation) {
494		View menuItemView = findViewById(R.id.action_security);
495		if (menuItemView == null) {
496			return;
497		}
498		PopupMenu popup = new PopupMenu(this, menuItemView);
499		final ConversationFragment fragment = (ConversationFragment) getFragmentManager()
500				.findFragmentByTag("conversation");
501		if (fragment != null) {
502			popup.setOnMenuItemClickListener(new OnMenuItemClickListener() {
503
504				@Override
505				public boolean onMenuItemClick(MenuItem item) {
506					switch (item.getItemId()) {
507						case R.id.encryption_choice_none:
508							conversation.setNextEncryption(Message.ENCRYPTION_NONE);
509							item.setChecked(true);
510							break;
511						case R.id.encryption_choice_otr:
512							conversation.setNextEncryption(Message.ENCRYPTION_OTR);
513							item.setChecked(true);
514							break;
515						case R.id.encryption_choice_pgp:
516							if (hasPgp()) {
517								if (conversation.getAccount().getKeys()
518										.has("pgp_signature")) {
519									conversation
520											.setNextEncryption(Message.ENCRYPTION_PGP);
521									item.setChecked(true);
522								} else {
523									announcePgp(conversation.getAccount(),
524											conversation);
525								}
526							} else {
527								showInstallPgpDialog();
528							}
529							break;
530						default:
531							conversation.setNextEncryption(Message.ENCRYPTION_NONE);
532							break;
533					}
534					xmppConnectionService.databaseBackend
535							.updateConversation(conversation);
536					fragment.updateChatMsgHint();
537					return true;
538				}
539			});
540			popup.inflate(R.menu.encryption_choices);
541			MenuItem otr = popup.getMenu().findItem(R.id.encryption_choice_otr);
542			MenuItem none = popup.getMenu().findItem(
543					R.id.encryption_choice_none);
544			if (conversation.getMode() == Conversation.MODE_MULTI) {
545				otr.setEnabled(false);
546			} else {
547				if (forceEncryption()) {
548					none.setVisible(false);
549				}
550			}
551			switch (conversation.getNextEncryption(forceEncryption())) {
552				case Message.ENCRYPTION_NONE:
553					none.setChecked(true);
554					break;
555				case Message.ENCRYPTION_OTR:
556					otr.setChecked(true);
557					break;
558				case Message.ENCRYPTION_PGP:
559					popup.getMenu().findItem(R.id.encryption_choice_pgp)
560							.setChecked(true);
561					break;
562				default:
563					popup.getMenu().findItem(R.id.encryption_choice_none)
564							.setChecked(true);
565					break;
566			}
567			popup.show();
568		}
569	}
570
571	protected void muteConversationDialog(final Conversation conversation) {
572		AlertDialog.Builder builder = new AlertDialog.Builder(this);
573		builder.setTitle(R.string.disable_notifications_for_this_conversation);
574		final int[] durations = getResources().getIntArray(
575				R.array.mute_options_durations);
576		builder.setItems(R.array.mute_options_descriptions,
577				new OnClickListener() {
578
579					@Override
580					public void onClick(DialogInterface dialog, int which) {
581						long till;
582						if (durations[which] == -1) {
583							till = Long.MAX_VALUE;
584						} else {
585							till = SystemClock.elapsedRealtime()
586									+ (durations[which] * 1000);
587						}
588						conversation.setMutedTill(till);
589						ConversationActivity.this.xmppConnectionService.databaseBackend
590								.updateConversation(conversation);
591						ConversationFragment selectedFragment = (ConversationFragment) getFragmentManager()
592								.findFragmentByTag("conversation");
593						if (selectedFragment != null) {
594							selectedFragment.updateMessages();
595						}
596					}
597				});
598		builder.create().show();
599	}
600
601	@Override
602	public boolean onKeyDown(int keyCode, KeyEvent event) {
603		if (keyCode == KeyEvent.KEYCODE_BACK) {
604			if (!isConversationsOverviewVisable()) {
605				showConversationsOverview();
606				return false;
607			}
608		}
609		return super.onKeyDown(keyCode, event);
610	}
611
612	@Override
613	protected void onNewIntent(Intent intent) {
614		if (xmppConnectionServiceBound) {
615			if (intent != null && VIEW_CONVERSATION.equals(intent.getType())) {
616				handleViewConversationIntent(intent);
617			}
618		} else {
619			setIntent(intent);
620		}
621	}
622
623	@Override
624	public void onStart() {
625		super.onStart();
626		if (this.xmppConnectionServiceBound) {
627			this.onBackendConnected();
628		}
629		if (conversationList.size() >= 1) {
630			this.onConversationUpdate();
631		}
632	}
633
634	@Override
635	protected void onStop() {
636		if (xmppConnectionServiceBound) {
637			xmppConnectionService.removeOnConversationListChangedListener();
638			xmppConnectionService.removeOnAccountListChangedListener();
639			xmppConnectionService.removeOnRosterUpdateListener();
640			xmppConnectionService.getNotificationService().setOpenConversation(
641					null);
642		}
643		super.onStop();
644	}
645
646	@Override
647	public void onSaveInstanceState(Bundle savedInstanceState) {
648		Conversation conversation = getSelectedConversation();
649		if (conversation != null) {
650			savedInstanceState.putString(STATE_OPEN_CONVERSATION,
651					conversation.getUuid());
652		}
653		savedInstanceState.putBoolean(STATE_PANEL_OPEN,
654				isConversationsOverviewVisable());
655		if (this.mPendingImageUri != null) {
656			savedInstanceState.putString(STATE_PENDING_URI, this.mPendingImageUri.toString());
657		}
658		super.onSaveInstanceState(savedInstanceState);
659	}
660
661	@Override
662	void onBackendConnected() {
663		this.registerListener();
664		updateConversationList();
665
666		if (xmppConnectionService.getAccounts().size() == 0) {
667			startActivity(new Intent(this, EditAccountActivity.class));
668		} else if (conversationList.size() <= 0) {
669			startActivity(new Intent(this, StartConversationActivity.class));
670			finish();
671		} else if (getIntent() != null
672				&& VIEW_CONVERSATION.equals(getIntent().getType())) {
673			handleViewConversationIntent(getIntent());
674		} else if (mOpenConverstaion != null) {
675			selectConversationByUuid(mOpenConverstaion);
676			if (mPanelOpen) {
677				showConversationsOverview();
678			} else {
679				if (isConversationsOverviewHideable()) {
680					openConversation();
681				}
682			}
683			this.mConversationFragment.reInit(getSelectedConversation());
684			mOpenConverstaion = null;
685		} else if (getSelectedConversation() != null) {
686			this.mConversationFragment.updateMessages();
687		} else {
688			showConversationsOverview();
689			mPendingImageUri = null;
690			setSelectedConversation(conversationList.get(0));
691			this.mConversationFragment.reInit(getSelectedConversation());
692		}
693
694		if (mPendingImageUri != null) {
695			attachImageToConversation(getSelectedConversation(),
696					mPendingImageUri);
697			mPendingImageUri = null;
698		}
699		ExceptionHelper.checkForCrash(this, this.xmppConnectionService);
700		setIntent(new Intent());
701	}
702
703	private void handleViewConversationIntent(Intent intent) {
704		String uuid = (String) intent.getExtras().get(CONVERSATION);
705		String text = intent.getExtras().getString(TEXT, "");
706		selectConversationByUuid(uuid);
707		this.mConversationFragment.reInit(getSelectedConversation());
708		this.mConversationFragment.appendText(text);
709		hideConversationsOverview();
710		if (mContentView instanceof SlidingPaneLayout) {
711			openConversation();
712		}
713	}
714
715	private void selectConversationByUuid(String uuid) {
716		for (int i = 0; i < conversationList.size(); ++i) {
717			if (conversationList.get(i).getUuid().equals(uuid)) {
718				setSelectedConversation(conversationList.get(i));
719			}
720		}
721	}
722
723	public void registerListener() {
724		xmppConnectionService.setOnConversationListChangedListener(this);
725		xmppConnectionService.setOnAccountListChangedListener(this);
726		xmppConnectionService.setOnRosterUpdateListener(this);
727	}
728
729	@Override
730	protected void onActivityResult(int requestCode, int resultCode,
731									final Intent data) {
732		super.onActivityResult(requestCode, resultCode, data);
733		if (resultCode == RESULT_OK) {
734			if (requestCode == REQUEST_DECRYPT_PGP) {
735				ConversationFragment selectedFragment = (ConversationFragment) getFragmentManager()
736						.findFragmentByTag("conversation");
737				if (selectedFragment != null) {
738					selectedFragment.hideSnackbar();
739					selectedFragment.updateMessages();
740				}
741			} else if (requestCode == REQUEST_ATTACH_FILE_DIALOG) {
742				mPendingImageUri = data.getData();
743				if (xmppConnectionServiceBound) {
744					attachImageToConversation(getSelectedConversation(),
745							mPendingImageUri);
746					mPendingImageUri = null;
747				}
748			} else if (requestCode == REQUEST_SEND_PGP_IMAGE) {
749
750			} else if (requestCode == ATTACHMENT_CHOICE_CHOOSE_IMAGE) {
751				attachFile(ATTACHMENT_CHOICE_CHOOSE_IMAGE);
752			} else if (requestCode == ATTACHMENT_CHOICE_TAKE_PHOTO) {
753				attachFile(ATTACHMENT_CHOICE_TAKE_PHOTO);
754			} else if (requestCode == REQUEST_ANNOUNCE_PGP) {
755				announcePgp(getSelectedConversation().getAccount(),
756						getSelectedConversation());
757			} else if (requestCode == REQUEST_ENCRYPT_MESSAGE) {
758				// encryptTextMessage();
759			} else if (requestCode == REQUEST_IMAGE_CAPTURE && mPendingImageUri != null) {
760				if (xmppConnectionServiceBound) {
761					attachImageToConversation(getSelectedConversation(),
762							mPendingImageUri);
763					mPendingImageUri = null;
764				}
765				Intent intent = new Intent(
766						Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
767				intent.setData(mPendingImageUri);
768				sendBroadcast(intent);
769			} else if (requestCode == REQUEST_RECORD_AUDIO) {
770				attachAudioToConversation(getSelectedConversation(),
771						data.getData());
772			}
773		} else {
774			if (requestCode == REQUEST_IMAGE_CAPTURE) {
775				mPendingImageUri = null;
776			}
777		}
778	}
779
780	private void attachAudioToConversation(Conversation conversation, Uri uri) {
781
782	}
783
784	private void attachImageToConversation(Conversation conversation, Uri uri) {
785		prepareImageToast = Toast.makeText(getApplicationContext(),
786				getText(R.string.preparing_image), Toast.LENGTH_LONG);
787		prepareImageToast.show();
788		xmppConnectionService.attachImageToConversation(conversation, uri,
789				new UiCallback<Message>() {
790
791					@Override
792					public void userInputRequried(PendingIntent pi,
793												  Message object) {
794						hidePrepareImageToast();
795						ConversationActivity.this.runIntent(pi,
796								ConversationActivity.REQUEST_SEND_PGP_IMAGE);
797					}
798
799					@Override
800					public void success(Message message) {
801						xmppConnectionService.sendMessage(message);
802					}
803
804					@Override
805					public void error(int error, Message message) {
806						hidePrepareImageToast();
807						displayErrorDialog(error);
808					}
809				});
810	}
811
812	private void hidePrepareImageToast() {
813		if (prepareImageToast != null) {
814			runOnUiThread(new Runnable() {
815
816				@Override
817				public void run() {
818					prepareImageToast.cancel();
819				}
820			});
821		}
822	}
823
824	public void updateConversationList() {
825		xmppConnectionService
826				.populateWithOrderedConversations(conversationList);
827		listAdapter.notifyDataSetChanged();
828	}
829
830	public void runIntent(PendingIntent pi, int requestCode) {
831		try {
832			this.startIntentSenderForResult(pi.getIntentSender(), requestCode,
833					null, 0, 0, 0);
834		} catch (SendIntentException e1) {
835		}
836	}
837
838	public void encryptTextMessage(Message message) {
839		xmppConnectionService.getPgpEngine().encrypt(message,
840				new UiCallback<Message>() {
841
842					@Override
843					public void userInputRequried(PendingIntent pi,
844												  Message message) {
845						ConversationActivity.this.runIntent(pi,
846								ConversationActivity.REQUEST_SEND_MESSAGE);
847					}
848
849					@Override
850					public void success(Message message) {
851						message.setEncryption(Message.ENCRYPTION_DECRYPTED);
852						xmppConnectionService.sendMessage(message);
853					}
854
855					@Override
856					public void error(int error, Message message) {
857
858					}
859				});
860	}
861
862	public boolean forceEncryption() {
863		return getPreferences().getBoolean("force_encryption", false);
864	}
865
866	public boolean useSendButtonToIndicateStatus() {
867		return getPreferences().getBoolean("send_button_status", false);
868	}
869
870	public boolean indicateReceived() {
871		return getPreferences().getBoolean("indicate_received", false);
872	}
873
874	@Override
875	public void onAccountUpdate() {
876		final ConversationFragment fragment = (ConversationFragment) getFragmentManager()
877				.findFragmentByTag("conversation");
878		if (fragment != null) {
879			runOnUiThread(new Runnable() {
880
881				@Override
882				public void run() {
883					fragment.updateMessages();
884				}
885			});
886		}
887	}
888
889	@Override
890	public void onConversationUpdate() {
891		runOnUiThread(new Runnable() {
892
893			@Override
894			public void run() {
895				updateConversationList();
896				if (conversationList.size() == 0) {
897						startActivity(new Intent(getApplicationContext(),
898								StartConversationActivity.class));
899						finish();
900				} else {
901					ConversationActivity.this.mConversationFragment.updateMessages();
902				}
903			}
904		});
905	}
906
907	@Override
908	public void onRosterUpdate() {
909		runOnUiThread(new Runnable() {
910
911				@Override
912				public void run() {
913					ConversationActivity.this.mConversationFragment.updateMessages();
914				}
915			});
916	}
917}