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