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