ConversationFragment.java

  1package eu.siacs.conversations.ui;
  2
  3import java.util.ArrayList;
  4import java.util.HashMap;
  5import java.util.List;
  6import java.util.Set;
  7
  8import org.openintents.openpgp.OpenPgpError;
  9
 10import net.java.otr4j.session.SessionStatus;
 11
 12import eu.siacs.conversations.R;
 13import eu.siacs.conversations.crypto.OnPgpEngineResult;
 14import eu.siacs.conversations.crypto.PgpEngine;
 15import eu.siacs.conversations.entities.Account;
 16import eu.siacs.conversations.entities.Contact;
 17import eu.siacs.conversations.entities.Conversation;
 18import eu.siacs.conversations.entities.Message;
 19import eu.siacs.conversations.entities.MucOptions;
 20import eu.siacs.conversations.entities.MucOptions.OnRenameListener;
 21import eu.siacs.conversations.services.XmppConnectionService;
 22import eu.siacs.conversations.utils.UIHelper;
 23import eu.siacs.conversations.xmpp.jingle.JingleConnection;
 24import android.app.AlertDialog;
 25import android.app.Fragment;
 26import android.app.PendingIntent;
 27import android.content.Context;
 28import android.content.DialogInterface;
 29import android.content.Intent;
 30import android.content.IntentSender;
 31import android.content.SharedPreferences;
 32import android.content.IntentSender.SendIntentException;
 33import android.graphics.Bitmap;
 34import android.graphics.Typeface;
 35import android.net.Uri;
 36import android.os.Bundle;
 37import android.preference.PreferenceManager;
 38import android.util.DisplayMetrics;
 39import android.util.Log;
 40import android.view.LayoutInflater;
 41import android.view.View;
 42import android.view.View.OnClickListener;
 43import android.view.ViewGroup;
 44import android.widget.ArrayAdapter;
 45import android.widget.Button;
 46import android.widget.EditText;
 47import android.widget.LinearLayout;
 48import android.widget.ListView;
 49import android.widget.ImageButton;
 50import android.widget.ImageView;
 51import android.widget.TextView;
 52import android.widget.Toast;
 53
 54public class ConversationFragment extends Fragment {
 55
 56	protected Conversation conversation;
 57	protected ListView messagesView;
 58	protected LayoutInflater inflater;
 59	protected List<Message> messageList = new ArrayList<Message>();
 60	protected ArrayAdapter<Message> messageListAdapter;
 61	protected Contact contact;
 62	protected BitmapCache mBitmapCache = new BitmapCache();
 63
 64	protected String queuedPqpMessage = null;
 65
 66	private EditText chatMsg;
 67	private String pastedText = null;
 68
 69	protected Bitmap selfBitmap;
 70	
 71	private boolean useSubject = true;
 72
 73	private IntentSender askForPassphraseIntent = null;
 74
 75	private OnClickListener sendMsgListener = new OnClickListener() {
 76
 77		@Override
 78		public void onClick(View v) {
 79			if (chatMsg.getText().length() < 1)
 80				return;
 81			Message message = new Message(conversation, chatMsg.getText()
 82					.toString(), conversation.getNextEncryption());
 83			if (conversation.getNextEncryption() == Message.ENCRYPTION_OTR) {
 84				sendOtrMessage(message);
 85			} else if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) {
 86				sendPgpMessage(message);
 87			} else {
 88				sendPlainTextMessage(message);
 89			}
 90		}
 91	};
 92	protected OnClickListener clickToDecryptListener = new OnClickListener() {
 93
 94		@Override
 95		public void onClick(View v) {
 96			if (askForPassphraseIntent != null) {
 97				try {
 98					getActivity().startIntentSenderForResult(
 99							askForPassphraseIntent,
100							ConversationActivity.REQUEST_DECRYPT_PGP, null, 0,
101							0, 0);
102				} catch (SendIntentException e) {
103					Log.d("xmppService", "couldnt fire intent");
104				}
105			}
106		}
107	};
108
109	private LinearLayout pgpInfo;
110	private LinearLayout mucError;
111	private TextView mucErrorText;
112	private OnClickListener clickToMuc = new OnClickListener() {
113
114		@Override
115		public void onClick(View v) {
116			Intent intent = new Intent(getActivity(), MucDetailsActivity.class);
117			intent.setAction(MucDetailsActivity.ACTION_VIEW_MUC);
118			intent.putExtra("uuid", conversation.getUuid());
119			startActivity(intent);
120		}
121	};
122	private ConversationActivity activity;
123
124	public void hidePgpPassphraseBox() {
125		pgpInfo.setVisibility(View.GONE);
126	}
127
128	public void updateChatMsgHint() {
129		if (conversation.getMode() == Conversation.MODE_MULTI) {
130			chatMsg.setHint(getString(R.string.send_message_to_conference));
131		} else {
132			switch (conversation.getNextEncryption()) {
133			case Message.ENCRYPTION_NONE:
134				chatMsg.setHint(getString(R.string.send_plain_text_message));
135				break;
136			case Message.ENCRYPTION_OTR:
137				chatMsg.setHint(getString(R.string.send_otr_message));
138				break;
139			case Message.ENCRYPTION_PGP:
140				chatMsg.setHint(getString(R.string.send_pgp_message));
141				break;
142			default:
143				break;
144			}
145		}
146	}
147
148	@Override
149	public View onCreateView(final LayoutInflater inflater,
150			ViewGroup container, Bundle savedInstanceState) {
151
152		final DisplayMetrics metrics = getResources().getDisplayMetrics();
153		
154		this.inflater = inflater;
155
156		final View view = inflater.inflate(R.layout.fragment_conversation,
157				container, false);
158		chatMsg = (EditText) view.findViewById(R.id.textinput);
159		
160		if (pastedText!=null) {
161			chatMsg.setText(pastedText);
162		}
163		
164		ImageButton sendButton = (ImageButton) view
165				.findViewById(R.id.textSendButton);
166		sendButton.setOnClickListener(this.sendMsgListener);
167
168		pgpInfo = (LinearLayout) view.findViewById(R.id.pgp_keyentry);
169		pgpInfo.setOnClickListener(clickToDecryptListener);
170		mucError = (LinearLayout) view.findViewById(R.id.muc_error);
171		mucError.setOnClickListener(clickToMuc);
172		mucErrorText = (TextView) view.findViewById(R.id.muc_error_msg);
173
174		messagesView = (ListView) view.findViewById(R.id.messages_view);
175
176		messageListAdapter = new ArrayAdapter<Message>(this.getActivity()
177				.getApplicationContext(), R.layout.message_sent,
178				this.messageList) {
179
180			private static final int SENT = 0;
181			private static final int RECIEVED = 1;
182
183			@Override
184			public int getViewTypeCount() {
185				return 2;
186			}
187
188			@Override
189			public int getItemViewType(int position) {
190				if (getItem(position).getStatus() <= Message.STATUS_RECIEVED) {
191					return RECIEVED;
192				} else {
193					return SENT;
194				}
195			}
196
197			@Override
198			public View getView(int position, View view, ViewGroup parent) {
199				final Message item = getItem(position);
200				int type = getItemViewType(position);
201				ViewHolder viewHolder;
202				if (view == null) {
203					viewHolder = new ViewHolder();
204					switch (type) {
205					case SENT:
206						view = (View) inflater.inflate(R.layout.message_sent,
207								null);
208						viewHolder.contact_picture = (ImageView) view
209								.findViewById(R.id.message_photo);
210						viewHolder.contact_picture.setImageBitmap(selfBitmap);
211						break;
212					case RECIEVED:
213						view = (View) inflater.inflate(
214								R.layout.message_recieved, null);
215						viewHolder.contact_picture = (ImageView) view
216								.findViewById(R.id.message_photo);
217						
218						viewHolder.download_button = (Button) view.findViewById(R.id.download_button);
219						
220						if (item.getConversation().getMode() == Conversation.MODE_SINGLE) {
221
222							viewHolder.contact_picture.setImageBitmap(mBitmapCache
223									.get(item.getConversation().getName(useSubject), item
224											.getConversation().getContact(),
225											getActivity()
226													.getApplicationContext()));
227
228						}
229						break;
230					default:
231						viewHolder = null;
232						break;
233					}
234					viewHolder.indicator = (ImageView) view.findViewById(R.id.security_indicator);
235					viewHolder.image = (ImageView) view.findViewById(R.id.message_image);
236					viewHolder.messageBody = (TextView) view
237							.findViewById(R.id.message_body);
238					viewHolder.time = (TextView) view
239							.findViewById(R.id.message_time);
240					view.setTag(viewHolder);
241				} else {
242					viewHolder = (ViewHolder) view.getTag();
243				}
244				
245				if (type == RECIEVED) {
246					if (item.getConversation().getMode() == Conversation.MODE_MULTI) {
247						if (item.getCounterpart() != null) {
248							viewHolder.contact_picture.setImageBitmap(mBitmapCache
249									.get(item.getCounterpart(), null,
250											getActivity()
251													.getApplicationContext()));
252						} else {
253							viewHolder.contact_picture.setImageBitmap(mBitmapCache
254									.get(item.getConversation().getName(useSubject),
255											null, getActivity()
256													.getApplicationContext()));
257						}
258					}
259				}
260				
261				if (item.getEncryption() == Message.ENCRYPTION_NONE) {
262					viewHolder.indicator.setVisibility(View.GONE);
263				} else {
264					viewHolder.indicator.setVisibility(View.VISIBLE);
265				}
266				
267				String filesize = "";
268				
269				if ((item.getType() == Message.TYPE_IMAGE)&&((item.getEncryption() == Message.ENCRYPTION_DECRYPTED)||(item.getEncryption() == Message.ENCRYPTION_NONE))) {
270					String[] fileParams = item.getBody().split(",");
271					if ((fileParams.length>=1)&&(item.getStatus() != Message.STATUS_PREPARING)) {
272						long size = Long.parseLong(fileParams[0]);
273						filesize = size/1024+" KB \u00B7 ";
274					}
275					if ((item.getStatus() == Message.STATUS_PREPARING)||(item.getStatus() == Message.STATUS_RECIEVING)) {
276						viewHolder.image.setVisibility(View.GONE);
277						viewHolder.messageBody.setVisibility(View.VISIBLE);
278						if (item.getStatus() == Message.STATUS_PREPARING) {
279							viewHolder.messageBody.setText(getString(R.string.preparing_image));
280						} else if (item.getStatus() == Message.STATUS_RECIEVING) {
281							viewHolder.download_button.setVisibility(View.GONE);
282							viewHolder.messageBody.setText(getString(R.string.receiving_image));
283						}
284						viewHolder.messageBody.setTextColor(0xff33B5E5);
285						viewHolder.messageBody.setTypeface(null,Typeface.ITALIC);
286					} else if (item.getStatus() == Message.STATUS_RECEIVED_OFFER) {
287						viewHolder.image.setVisibility(View.GONE);
288						viewHolder.messageBody.setVisibility(View.GONE);
289						viewHolder.download_button.setVisibility(View.VISIBLE);
290						viewHolder.download_button.setOnClickListener(new OnClickListener() {
291							
292							@Override
293							public void onClick(View v) {
294								JingleConnection connection = item.getJingleConnection();
295								if (connection!=null) {
296									connection.accept();
297								} else {
298									Log.d("xmppService","attached jingle connection was null");
299								}
300							}
301						});
302					} else {
303						viewHolder.messageBody.setVisibility(View.GONE);
304						viewHolder.image.setVisibility(View.VISIBLE);
305			        	if (fileParams.length==3) {
306			        		double target = metrics.density * 288;
307			        		int w = Integer.parseInt(fileParams[1]);
308			        		int h = Integer.parseInt(fileParams[2]);
309			        		int scalledW;
310			    			int scalledH;
311			    			if (w <= h) {
312			    				scalledW = (int) (w / ((double) h / target));
313			    				scalledH = (int) target;
314			    			} else {
315			    				scalledW = (int)  target;
316			    				scalledH = (int) (h / ((double) w / target));
317			    			}
318			        		viewHolder.image.setLayoutParams(new LinearLayout.LayoutParams(scalledW, scalledH));
319			        	} else {
320			        		Log.d("xmppService","message body has less than 3 params");
321			        	}
322						activity.loadBitmap(item, viewHolder.image);
323						viewHolder.image.setOnClickListener(new OnClickListener() {
324							
325							@Override
326							public void onClick(View v) {
327								Uri uri = Uri.parse("content://eu.siacs.conversations.images/"+item.getConversationUuid()+"/"+item.getUuid());
328								Log.d("xmppService","staring intent with uri:"+uri.toString());
329								Intent intent = new Intent(Intent.ACTION_VIEW);
330							    intent.setDataAndType(uri, "image/*");
331							    startActivity(intent);
332							}
333						});
334					}
335				} else {
336					viewHolder.image.setVisibility(View.GONE);
337					viewHolder.messageBody.setVisibility(View.VISIBLE);
338					String body = item.getBody();
339					if (body != null) {
340						if (item.getEncryption() == Message.ENCRYPTION_PGP) {
341							viewHolder.messageBody
342									.setText(getString(R.string.encrypted_message));
343							viewHolder.messageBody.setTextColor(0xff33B5E5);
344							viewHolder.messageBody.setTypeface(null,
345									Typeface.ITALIC);
346						} else if (item.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) {
347							viewHolder.messageBody.setText(getString(R.string.decryption_failed));
348							viewHolder.messageBody.setTextColor(0xFFe92727);
349							viewHolder.messageBody.setTypeface(null,Typeface.NORMAL);
350						} else {
351							viewHolder.messageBody.setText(body.trim());
352							viewHolder.messageBody.setTextColor(0xff333333);
353							viewHolder.messageBody.setTypeface(null,
354									Typeface.NORMAL);
355						}
356					}
357				}
358				switch (item.getStatus()) {
359				case Message.STATUS_UNSEND:
360					viewHolder.time.setTypeface(null, Typeface.ITALIC);
361					viewHolder.time.setTextColor(0xFF8e8e8e);
362					viewHolder.time.setText(filesize+"sending\u2026");
363					break;
364				case Message.STATUS_OFFERED:
365					viewHolder.time.setTypeface(null, Typeface.ITALIC);
366					viewHolder.time.setTextColor(0xFF8e8e8e);
367					viewHolder.time.setText(filesize+"offering\u2026");
368					break;
369				case Message.STATUS_SEND_FAILED:
370					viewHolder.time.setText(filesize+getString(R.string.send_failed) + " \u00B7 " + UIHelper.readableTimeDifference(item
371							.getTimeSent()));
372					viewHolder.time.setTextColor(0xFFe92727);
373					viewHolder.time.setTypeface(null,Typeface.NORMAL);
374					break;
375				case Message.STATUS_SEND_REJECTED:
376					viewHolder.time.setText(filesize+getString(R.string.send_rejected));
377					viewHolder.time.setTextColor(0xFFe92727);
378					viewHolder.time.setTypeface(null,Typeface.NORMAL);
379					break;
380				default:
381					viewHolder.time.setTypeface(null, Typeface.NORMAL);
382					viewHolder.time.setTextColor(0xFF8e8e8e);
383					if (item.getConversation().getMode() == Conversation.MODE_SINGLE) {
384						viewHolder.time.setText(filesize+UIHelper
385								.readableTimeDifference(item.getTimeSent()));
386					} else {
387						viewHolder.time.setText(item.getCounterpart()
388								+ " \u00B7 "
389								+ UIHelper.readableTimeDifference(item
390										.getTimeSent()));
391					}
392					break;
393				}
394				return view;
395			}
396		};
397		messagesView.setAdapter(messageListAdapter);
398
399		return view;
400	}
401
402	protected Bitmap findSelfPicture() {
403		SharedPreferences sharedPref = PreferenceManager
404				.getDefaultSharedPreferences(getActivity()
405						.getApplicationContext());
406		boolean showPhoneSelfContactPicture = sharedPref.getBoolean(
407				"show_phone_selfcontact_picture", true);
408
409		return UIHelper.getSelfContactPicture(conversation.getAccount(), 48,
410				showPhoneSelfContactPicture, getActivity());
411	}
412
413	@Override
414	public void onStart() {
415		super.onStart();
416		this.activity = (ConversationActivity) getActivity();
417		SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
418		this.useSubject = preferences.getBoolean("use_subject_in_muc", true);
419		if (activity.xmppConnectionServiceBound) {
420			this.onBackendConnected();
421		}
422	}
423
424	public void onBackendConnected() {
425		this.conversation = activity.getSelectedConversation();
426		if (this.conversation == null) {
427			return;
428		}
429		this.selfBitmap = findSelfPicture();
430		updateMessages();
431		// rendering complete. now go tell activity to close pane
432		if (activity.getSlidingPaneLayout().isSlideable()) {
433			if (!activity.shouldPaneBeOpen()) {
434				activity.getSlidingPaneLayout().closePane();
435				activity.getActionBar().setDisplayHomeAsUpEnabled(true);
436				activity.getActionBar().setTitle(conversation.getName(useSubject));
437				activity.invalidateOptionsMenu();
438
439			}
440		}
441		if (conversation.getMode() == Conversation.MODE_MULTI) {
442			activity.xmppConnectionService
443					.setOnRenameListener(new OnRenameListener() {
444
445						@Override
446						public void onRename(final boolean success) {
447							activity.xmppConnectionService.updateConversation(conversation);
448							getActivity().runOnUiThread(new Runnable() {
449
450								@Override
451								public void run() {
452									if (success) {
453										Toast.makeText(
454												getActivity(),
455												getString(R.string.your_nick_has_been_changed),
456												Toast.LENGTH_SHORT).show();
457									} else {
458										Toast.makeText(getActivity(),
459												getString(R.string.nick_in_use),
460												Toast.LENGTH_SHORT).show();
461									}
462								}
463							});
464						}
465					});
466		}
467	}
468	
469	private void decryptMessage(final Message message) {
470		Log.d("xmppService","called to decrypt");
471		PgpEngine engine = activity.xmppConnectionService.getPgpEngine();
472		if (engine!=null) {
473			engine.decrypt(message,new OnPgpEngineResult() {
474				
475				@Override
476				public void userInputRequried(PendingIntent pi) {
477					askForPassphraseIntent = pi.getIntentSender();
478					pgpInfo.setVisibility(View.VISIBLE);
479				}
480				
481				@Override
482				public void success() {
483					Log.d("xmppService","successfully decrypted");
484					activity.xmppConnectionService.databaseBackend.updateMessage(message);
485					updateMessages();
486				}
487				
488				@Override
489				public void error(OpenPgpError openPgpError) {
490					Log.d("xmppService","decryption error"+openPgpError.getMessage());
491					message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED);
492					//updateMessages();
493				}
494			});
495		} else {
496			Log.d("xmppService","engine was null");
497		}
498	}
499	
500	public void updateMessages() {
501		ConversationActivity activity = (ConversationActivity) getActivity();
502		if (this.conversation != null) {
503			for (Message message : this.conversation.getMessages()) {
504				if ((message.getEncryption() == Message.ENCRYPTION_PGP)&&(message.getStatus() == Message.STATUS_RECIEVED)) {
505					decryptMessage(message);
506					break;
507				}
508			}
509			this.messageList.clear();
510			this.messageList.addAll(this.conversation.getMessages());
511			this.messageListAdapter.notifyDataSetChanged();
512			if (conversation.getMode() == Conversation.MODE_SINGLE) {
513				if (messageList.size() >= 1) {
514					conversation.setNextEncryption(conversation.getLatestEncryption());
515					makeFingerprintWarning(conversation.getLatestEncryption());
516				}
517			} else {
518				if (conversation.getMucOptions().getError() != 0) {
519					mucError.setVisibility(View.VISIBLE);
520					if (conversation.getMucOptions().getError() == MucOptions.ERROR_NICK_IN_USE) {
521						mucErrorText.setText(getString(R.string.nick_in_use));
522					}
523				} else {
524					mucError.setVisibility(View.GONE);
525				}
526			}
527			getActivity().invalidateOptionsMenu();
528			updateChatMsgHint();
529			int size = this.messageList.size();
530			if (size >= 1)
531				messagesView.setSelection(size - 1);
532			if (!activity.shouldPaneBeOpen()) {
533				conversation.markRead();
534				// TODO update notifications
535				UIHelper.updateNotification(getActivity(),
536						activity.getConversationList(), null, false);
537				activity.updateConversationList();
538			}
539		}
540	}
541
542	protected void makeFingerprintWarning(int latestEncryption) {
543		final LinearLayout fingerprintWarning = (LinearLayout) getView()
544				.findViewById(R.id.new_fingerprint);
545		if (conversation.getContact() != null) {
546			Set<String> knownFingerprints = conversation.getContact()
547					.getOtrFingerprints();
548			if ((latestEncryption == Message.ENCRYPTION_OTR)
549					&& (conversation.hasValidOtrSession()
550							&& (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) && (!knownFingerprints
551								.contains(conversation.getOtrFingerprint())))) {
552				fingerprintWarning.setVisibility(View.VISIBLE);
553				TextView fingerprint = (TextView) getView().findViewById(
554						R.id.otr_fingerprint);
555				fingerprint.setText(conversation.getOtrFingerprint());
556				fingerprintWarning.setOnClickListener(new OnClickListener() {
557
558					@Override
559					public void onClick(View v) {
560						AlertDialog dialog = UIHelper
561								.getVerifyFingerprintDialog(
562										(ConversationActivity) getActivity(),
563										conversation, fingerprintWarning);
564						dialog.show();
565					}
566				});
567			} else {
568				fingerprintWarning.setVisibility(View.GONE);
569			}
570		} else {
571			fingerprintWarning.setVisibility(View.GONE);
572		}
573	}
574
575	protected void sendPlainTextMessage(Message message) {
576		ConversationActivity activity = (ConversationActivity) getActivity();
577		activity.xmppConnectionService.sendMessage(message, null);
578		chatMsg.setText("");
579	}
580
581	protected void sendPgpMessage(final Message message) {
582		final ConversationActivity activity = (ConversationActivity) getActivity();
583		final XmppConnectionService xmppService = activity.xmppConnectionService;
584		final Contact contact = message.getConversation().getContact();
585		final Account account = message.getConversation().getAccount();
586		if (activity.hasPgp()) {
587			if (contact.getPgpKeyId() != 0) {
588				xmppService.getPgpEngine().hasKey(contact, new OnPgpEngineResult() {
589					
590					@Override
591					public void userInputRequried(PendingIntent pi) {
592						activity.runIntent(pi, ConversationActivity.REQUEST_SEND_MESSAGE);
593					}
594					
595					@Override
596					public void success() {
597						xmppService.getPgpEngine().encrypt(account, message,new OnPgpEngineResult() {
598							
599							@Override
600							public void userInputRequried(PendingIntent pi) {
601								activity.runIntent(pi, ConversationActivity.REQUEST_SEND_MESSAGE);
602							}
603							
604							@Override
605							public void success() {
606								xmppService.sendMessage(message, null);
607								chatMsg.setText("");
608							}
609							
610							@Override
611							public void error(OpenPgpError openPgpError) {
612								// TODO Auto-generated method stub
613								
614							}
615						});
616					}
617					
618					@Override
619					public void error(OpenPgpError openPgpError) {
620						Log.d("xmppService","openpgp error"+openPgpError.getMessage());
621					}
622				});
623				
624				
625					
626					
627			} else {
628				AlertDialog.Builder builder = new AlertDialog.Builder(
629						getActivity());
630				builder.setTitle("No openPGP key found");
631				builder.setIconAttribute(android.R.attr.alertDialogIcon);
632				builder.setMessage("There is no openPGP key associated with this contact");
633				builder.setNegativeButton("Cancel", null);
634				builder.setPositiveButton("Send plain text",
635						new DialogInterface.OnClickListener() {
636
637							@Override
638							public void onClick(DialogInterface dialog,
639									int which) {
640								conversation.setNextEncryption(Message.ENCRYPTION_NONE);
641								message.setEncryption(Message.ENCRYPTION_NONE);
642								xmppService.sendMessage(message, null);
643								chatMsg.setText("");
644							}
645						});
646				builder.create().show();
647			}
648		}
649	}
650
651	protected void sendOtrMessage(final Message message) {
652		ConversationActivity activity = (ConversationActivity) getActivity();
653		final XmppConnectionService xmppService = activity.xmppConnectionService;
654		if (conversation.hasValidOtrSession()) {
655			activity.xmppConnectionService.sendMessage(message, null);
656			chatMsg.setText("");
657		} else {
658			activity.selectPresence(message.getConversation(), new OnPresenceSelected() {
659				
660				@Override
661				public void onPresenceSelected(boolean success, String presence) {
662					if (success) {
663						xmppService.sendMessage(message,presence);
664						chatMsg.setText("");
665					}
666				}
667
668				@Override
669				public void onSendPlainTextInstead() {
670					message.setEncryption(Message.ENCRYPTION_NONE);
671					xmppService.sendMessage(message,null);
672					chatMsg.setText("");
673				}
674			},"otr");
675		}
676	}
677
678	private static class ViewHolder {
679
680		protected Button download_button;
681		protected ImageView image;
682		protected ImageView indicator;
683		protected TextView time;
684		protected TextView messageBody;
685		protected ImageView contact_picture;
686
687	}
688
689	private class BitmapCache {
690		private HashMap<String, Bitmap> bitmaps = new HashMap<String, Bitmap>();
691		private Bitmap error = null;
692
693		public Bitmap get(String name, Contact contact, Context context) {
694			if (bitmaps.containsKey(name)) {
695				return bitmaps.get(name);
696			} else {
697				Bitmap bm;
698				if (contact != null){
699					bm = UIHelper.getContactPicture(contact, 48, context, false);
700				} else {
701					bm = UIHelper.getContactPicture(name, 48, context, false);
702				}
703				bitmaps.put(name, bm);
704				return bm;
705			}
706		}
707	}
708
709	/*class DecryptMessage extends AsyncTask<Message, Void, Boolean> {
710
711		@Override
712		protected Boolean doInBackground(Message... params) {
713			final ConversationActivity activity = (ConversationActivity) getActivity();
714			askForPassphraseIntent = null;
715			for (int i = 0; i < params.length; ++i) {
716				if (params[i].getEncryption() == Message.ENCRYPTION_PGP) {
717					String body = params[i].getBody();
718					String decrypted = null;
719					if (activity == null) {
720						return false;
721					} else if (!activity.xmppConnectionServiceBound) {
722						return false;
723					}
724					try {
725						decrypted = activity.xmppConnectionService
726								.getPgpEngine().decrypt(conversation.getAccount(),body);
727					} catch (UserInputRequiredException e) {
728						askForPassphraseIntent = e.getPendingIntent()
729								.getIntentSender();
730						activity.runOnUiThread(new Runnable() {
731
732							@Override
733							public void run() {
734								pgpInfo.setVisibility(View.VISIBLE);
735							}
736						});
737
738						return false;
739
740					} catch (OpenPgpException e) {
741						Log.d("gultsch", "error decrypting pgp");
742					}
743					if (decrypted != null) {
744						params[i].setBody(decrypted);
745						params[i].setEncryption(Message.ENCRYPTION_DECRYPTED);
746						activity.xmppConnectionService.updateMessage(params[i]);
747					}
748					if (activity != null) {
749						activity.runOnUiThread(new Runnable() {
750
751							@Override
752							public void run() {
753								messageListAdapter.notifyDataSetChanged();
754							}
755						});
756					}
757				}
758				if (activity != null) {
759					activity.runOnUiThread(new Runnable() {
760
761						@Override
762						public void run() {
763							activity.updateConversationList();
764						}
765					});
766				}
767			}
768			return true;
769		}
770
771	}*/
772
773	public void setText(String text) {
774		this.pastedText = text;
775	}
776}