ConversationActivity.java

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