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}