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