diff options
Diffstat (limited to 'src/main/java/eu/siacs/conversations/ui/ConversationFragment.java')
-rw-r--r-- | src/main/java/eu/siacs/conversations/ui/ConversationFragment.java | 336 |
1 files changed, 205 insertions, 131 deletions
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 0edc6b6f..93a4cc7e 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -103,7 +103,9 @@ public class ConversationFragment extends Fragment { private RelativeLayout snackbar; private TextView snackbarMessage; private TextView snackbarAction; - private boolean messagesLoaded = false; + private boolean messagesLoaded = true; + private Toast messageLoaderToast; + private OnScrollListener mOnScrollListener = new OnScrollListener() { @Override @@ -114,20 +116,69 @@ public class ConversationFragment extends Fragment { @Override public void onScroll(AbsListView view, int firstVisibleItem, - int visibleItemCount, int totalItemCount) { + int visibleItemCount, int totalItemCount) { synchronized (ConversationFragment.this.messageList) { - if (firstVisibleItem == 0 && messagesLoaded) { + if (firstVisibleItem < 5 && messagesLoaded && messageList.size() > 0) { long timestamp = ConversationFragment.this.messageList.get(0).getTimeSent(); messagesLoaded = false; - int size = activity.xmppConnectionService.loadMoreMessages(conversation, timestamp); - ConversationFragment.this.messageList.clear(); - ConversationFragment.this.messageList.addAll(conversation.getMessages()); - updateStatusMessages(); - messageListAdapter.notifyDataSetChanged(); - if (size != 0) { - messagesLoaded = true; - } - messagesView.setSelectionFromTop(size + 1, 0); + activity.xmppConnectionService.loadMoreMessages(conversation, timestamp, new XmppConnectionService.OnMoreMessagesLoaded() { + @Override + public void onMoreMessagesLoaded(final int count, Conversation conversation) { + if (ConversationFragment.this.conversation != conversation) { + return; + } + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + final int oldPosition = messagesView.getFirstVisiblePosition(); + View v = messagesView.getChildAt(0); + final int pxOffset = (v == null) ? 0 : v.getTop(); + ConversationFragment.this.conversation.populateWithMessages(ConversationFragment.this.messageList); + updateStatusMessages(); + messageListAdapter.notifyDataSetChanged(); + if (count != 0) { + final int newPosition = oldPosition + count; + int offset = 0; + try { + Message tmpMessage = messageList.get(newPosition); + + while(tmpMessage.wasMergedIntoPrevious()) { + offset++; + tmpMessage = tmpMessage.prev(); + } + } catch (final IndexOutOfBoundsException ignored) { + + } + messagesView.setSelectionFromTop(newPosition - offset, pxOffset); + messagesLoaded = true; + if (messageLoaderToast != null) { + messageLoaderToast.cancel(); + } + } + } + }); + } + + @Override + public void informUser(final int resId) { + + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + if (messageLoaderToast != null) { + messageLoaderToast.cancel(); + } + if (ConversationFragment.this.conversation != conversation) { + return; + } + messageLoaderToast = Toast.makeText(activity,resId,Toast.LENGTH_LONG); + messageLoaderToast.show(); + } + }); + + } + }); + } } } @@ -153,13 +204,7 @@ public class ConversationFragment extends Fragment { @Override public void onClick(View v) { - if (conversation.getOtrFingerprint() != null) { - Intent intent = new Intent(getActivity(), VerifyOTRActivity.class); - intent.setAction(VerifyOTRActivity.ACTION_VERIFY_CONTACT); - intent.putExtra("contact", conversation.getContact().getJid().toBareJid().toString()); - intent.putExtra("account", conversation.getAccount().getJid().toBareJid().toString()); - startActivity(intent); - } + activity.verifyOtrSessionDialog(conversation,v); } }; private ConcurrentLinkedQueue<Message> mEncryptedMessages = new ConcurrentLinkedQueue<>(); @@ -170,7 +215,7 @@ public class ConversationFragment extends Fragment { public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_SEND) { InputMethodManager imm = (InputMethodManager) v.getContext() - .getSystemService(Context.INPUT_METHOD_SERVICE); + .getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(v.getWindowToken(), 0); sendMessage(); return true; @@ -213,7 +258,7 @@ public class ConversationFragment extends Fragment { } Message message = new Message(conversation, mEditMessage.getText() .toString(), conversation.getNextEncryption(activity - .forceEncryption())); + .forceEncryption())); if (conversation.getMode() == Conversation.MODE_MULTI) { if (conversation.getNextCounterpart() != null) { message.setCounterpart(conversation.getNextCounterpart()); @@ -234,13 +279,13 @@ public class ConversationFragment extends Fragment { if (conversation.getMode() == Conversation.MODE_MULTI && conversation.getNextCounterpart() != null) { this.mEditMessage.setHint(getString( - R.string.send_private_message_to, - conversation.getNextCounterpart().getResourcepart())); + R.string.send_private_message_to, + conversation.getNextCounterpart().getResourcepart())); } else { switch (conversation.getNextEncryption(activity.forceEncryption())) { case Message.ENCRYPTION_NONE: mEditMessage - .setHint(getString(R.string.send_plain_text_message)); + .setHint(getString(R.string.send_plain_text_message)); break; case Message.ENCRYPTION_OTR: mEditMessage.setHint(getString(R.string.send_otr_message)); @@ -256,7 +301,7 @@ public class ConversationFragment extends Fragment { @Override public View onCreateView(final LayoutInflater inflater, - ViewGroup container, Bundle savedInstanceState) { + ViewGroup container, Bundle savedInstanceState) { final View view = inflater.inflate(R.layout.fragment_conversation, container, false); mEditMessage = (EditMessage) view.findViewById(R.id.textinput); @@ -289,49 +334,51 @@ public class ConversationFragment extends Fragment { messageListAdapter = new MessageAdapter((ConversationActivity) getActivity(), this.messageList); messageListAdapter.setOnContactPictureClicked(new OnContactPictureClicked() { - @Override - public void onContactPictureClicked(Message message) { - if (message.getStatus() <= Message.STATUS_RECEIVED) { - if (message.getConversation().getMode() == Conversation.MODE_MULTI) { - if (message.getCounterpart() != null) { - if (!message.getCounterpart().isBareJid()) { - highlightInConference(message.getCounterpart().getResourcepart()); - } else { - highlightInConference(message.getCounterpart().toString()); - } - } + @Override + public void onContactPictureClicked(Message message) { + if (message.getStatus() <= Message.STATUS_RECEIVED) { + if (message.getConversation().getMode() == Conversation.MODE_MULTI) { + if (message.getCounterpart() != null) { + if (!message.getCounterpart().isBareJid()) { + highlightInConference(message.getCounterpart().getResourcepart()); } else { - Contact contact = message.getConversation() - .getContact(); - if (contact.showInRoster()) { - activity.switchToContactDetails(contact); - } else { - activity.showAddToRosterDialog(message - .getConversation()); - } + highlightInConference(message.getCounterpart().toString()); } + } + } else { + Contact contact = message.getConversation() + .getContact(); + if (contact.showInRoster()) { + activity.switchToContactDetails(contact); } else { - Account account = message.getConversation().getAccount(); - Intent intent = new Intent(activity, EditAccountActivity.class); - intent.putExtra("jid", account.getJid().toBareJid().toString()); - startActivity(intent); + activity.showAddToRosterDialog(message + .getConversation()); } } - }); + } else { + Account account = message.getConversation().getAccount(); + Intent intent = new Intent(activity, EditAccountActivity.class); + intent.putExtra("jid", account.getJid().toBareJid().toString()); + startActivity(intent); + } + } + }); messageListAdapter - .setOnContactPictureLongClicked(new OnContactPictureLongClicked() { + .setOnContactPictureLongClicked(new OnContactPictureLongClicked() { - @Override - public void onContactPictureLongClicked(Message message) { - if (message.getStatus() <= Message.STATUS_RECEIVED) { - if (message.getConversation().getMode() == Conversation.MODE_MULTI) { - if (message.getCounterpart() != null) { - privateMessageWith(message.getCounterpart()); - } + @Override + public void onContactPictureLongClicked(Message message) { + if (message.getStatus() <= Message.STATUS_RECEIVED) { + if (message.getConversation().getMode() == Conversation.MODE_MULTI) { + if (message.getCounterpart() != null) { + privateMessageWith(message.getCounterpart()); } } + } else { + activity.showQrCode(); } - }); + } + }); messagesView.setAdapter(messageListAdapter); registerForContextMenu(messagesView); @@ -341,7 +388,7 @@ public class ConversationFragment extends Fragment { @Override public void onCreateContextMenu(ContextMenu menu, View v, - ContextMenuInfo menuInfo) { + ContextMenuInfo menuInfo) { synchronized (this.messageList) { super.onCreateContextMenu(menu, v, menuInfo); AdapterView.AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) menuInfo; @@ -351,7 +398,8 @@ public class ConversationFragment extends Fragment { } private void populateContextMenu(ContextMenu menu) { - if (this.selectedMessage.getType() != Message.TYPE_STATUS) { + final Message m = this.selectedMessage; + if (m.getType() != Message.TYPE_STATUS) { activity.getMenuInflater().inflate(R.menu.message_context, menu); menu.setHeaderTitle(R.string.message_options); MenuItem copyText = menu.findItem(R.id.copy_text); @@ -360,29 +408,26 @@ public class ConversationFragment extends Fragment { MenuItem copyUrl = menu.findItem(R.id.copy_url); MenuItem downloadImage = menu.findItem(R.id.download_image); MenuItem cancelTransmission = menu.findItem(R.id.cancel_transmission); - if (this.selectedMessage.getType() != Message.TYPE_TEXT - || this.selectedMessage.getDownloadable() != null) { + if (m.getType() != Message.TYPE_TEXT || m.getDownloadable() != null) { copyText.setVisible(false); } - if (this.selectedMessage.getType() != Message.TYPE_IMAGE - || this.selectedMessage.getDownloadable() != null) { + if (m.getType() != Message.TYPE_IMAGE || m.getDownloadable() != null) { shareImage.setVisible(false); } - if (this.selectedMessage.getStatus() != Message.STATUS_SEND_FAILED) { + if (m.getStatus() != Message.STATUS_SEND_FAILED) { sendAgain.setVisible(false); } - if ((this.selectedMessage.getType() != Message.TYPE_IMAGE && this.selectedMessage - .getDownloadable() == null) - || this.selectedMessage.getImageParams().url == null) { + if ((m.getType() != Message.TYPE_IMAGE && m.getDownloadable() == null) + || m.getImageParams().url == null) { copyUrl.setVisible(false); } - if (this.selectedMessage.getType() != Message.TYPE_TEXT - || this.selectedMessage.getDownloadable() != null - || !this.selectedMessage.bodyContainsDownloadable()) { + if (m.getType() != Message.TYPE_TEXT + || m.getDownloadable() != null + || !m.bodyContainsDownloadable()) { downloadImage.setVisible(false); } - if (this.selectedMessage.getDownloadable() == null - || this.selectedMessage.getDownloadable() instanceof DownloadablePlaceholder) { + if (!((m.getDownloadable() != null && !(m.getDownloadable() instanceof DownloadablePlaceholder)) + || (m.isFileOrImage() && m.getStatus() == Message.STATUS_WAITING))) { cancelTransmission.setVisible(false); } } @@ -419,16 +464,16 @@ public class ConversationFragment extends Fragment { shareIntent.setAction(Intent.ACTION_SEND); shareIntent.putExtra(Intent.EXTRA_STREAM, activity.xmppConnectionService.getFileBackend() - .getJingleFileUri(message)); + .getJingleFileUri(message)); shareIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); shareIntent.setType("image/webp"); activity.startActivity(Intent.createChooser(shareIntent, - getText(R.string.share_with))); + getText(R.string.share_with))); } private void copyText(Message message) { if (activity.copyTextToClipboard(message.getMergedBody(), - R.string.message_text)) { + R.string.message_text)) { Toast.makeText(activity, R.string.message_copied_to_clipboard, Toast.LENGTH_SHORT).show(); } @@ -448,21 +493,23 @@ public class ConversationFragment extends Fragment { private void copyUrl(Message message) { if (activity.copyTextToClipboard( - message.getImageParams().url.toString(), R.string.image_url)) { + message.getImageParams().url.toString(), R.string.image_url)) { Toast.makeText(activity, R.string.url_copied_to_clipboard, Toast.LENGTH_SHORT).show(); - } + } } private void downloadImage(Message message) { activity.xmppConnectionService.getHttpConnectionManager() - .createNewConnection(message); + .createNewConnection(message); } private void cancelTransmission(Message message) { Downloadable downloadable = message.getDownloadable(); if (downloadable!=null) { downloadable.cancel(); + } else { + activity.xmppConnectionService.markMessage(message,Message.STATUS_SEND_FAILED); } } @@ -478,9 +525,9 @@ public class ConversationFragment extends Fragment { mEditMessage.getText().insert(0, nick + ": "); } else { if (mEditMessage.getText().charAt( - mEditMessage.getSelectionStart() - 1) != ' ') { + mEditMessage.getSelectionStart() - 1) != ' ') { nick = " " + nick; - } + } mEditMessage.getText().insert(mEditMessage.getSelectionStart(), nick + " "); } @@ -501,6 +548,7 @@ public class ConversationFragment extends Fragment { } if (this.conversation != null) { this.conversation.setNextMessage(mEditMessage.getText().toString()); + this.conversation.trim(); } this.activity = (ConversationActivity) getActivity(); this.conversation = conversation; @@ -511,8 +559,13 @@ public class ConversationFragment extends Fragment { } this.mEditMessage.setText(""); this.mEditMessage.append(this.conversation.getNextMessage()); - this.messagesView.invalidate(); + this.messagesView.invalidateViews(); updateMessages(); + this.messagesLoaded = true; + int size = this.messageList.size(); + if (size > 0) { + messagesView.setSelection(size - 1); + } } public void updateMessages() { @@ -524,12 +577,30 @@ public class ConversationFragment extends Fragment { final ConversationActivity activity = (ConversationActivity) getActivity(); if (this.conversation != null) { final Contact contact = this.conversation.getContact(); - if (this.conversation.isMuted()) { + if (this.conversation.isBlocked()) { + showSnackbar(R.string.contact_blocked, R.string.unblock, + new OnClickListener() { + @Override + public void onClick(final View v) { + v.post(new Runnable() { + @Override + public void run() { + v.setVisibility(View.INVISIBLE); + } + }); + if (conversation.isDomainBlocked()) { + BlockContactDialog.show(getActivity(), ((ConversationActivity) getActivity()).xmppConnectionService, conversation); + } else { + ((ConversationActivity) getActivity()).unblockConversation(conversation); + } + } + }); + } else if (this.conversation.isMuted()) { showSnackbar(R.string.notifications_disabled, R.string.enable, new OnClickListener() { @Override - public void onClick(View v) { + public void onClick(final View v) { activity.unmuteConversation(conversation); } }); @@ -542,7 +613,7 @@ public class ConversationFragment extends Fragment { @Override public void onClick(View v) { activity.xmppConnectionService - .createContact(contact); + .createContact(contact); activity.switchToContactDetails(contact); } }); @@ -579,31 +650,24 @@ public class ConversationFragment extends Fragment { default: break; } - } - this.messageList.clear(); - if (this.conversation.getMessages().size() == 0) { - messagesLoaded = false; - } else { - this.messageList.addAll(this.conversation.getMessages()); - messagesLoaded = true; - for (Message message : this.messageList) { - if (message.getEncryption() == Message.ENCRYPTION_PGP - && (message.getStatus() == Message.STATUS_RECEIVED || message + } + conversation.populateWithMessages(ConversationFragment.this.messageList); + for (Message message : this.messageList) { + if (message.getEncryption() == Message.ENCRYPTION_PGP + && (message.getStatus() == Message.STATUS_RECEIVED || message .getStatus() >= Message.STATUS_SEND) - && message.getDownloadable() == null) { - if (!mEncryptedMessages.contains(message)) { - mEncryptedMessages.add(message); - } + && message.getDownloadable() == null) { + if (!mEncryptedMessages.contains(message)) { + mEncryptedMessages.add(message); } - } - decryptNext(); - updateStatusMessages(); + } } + decryptNext(); + updateStatusMessages(); this.messageListAdapter.notifyDataSetChanged(); updateChatMsgHint(); if (!activity.isConversationsOverviewVisable() || !activity.isConversationsOverviewHideable()) { - activity.xmppConnectionService.markRead(conversation, true); - activity.updateConversationList(); + activity.sendReadMarkerIfNecessary(conversation); } this.updateSendButton(); } @@ -667,44 +731,44 @@ public class ConversationFragment extends Fragment { switch (c.getContact().getMostAvailableStatus()) { case Presences.CHAT: this.mSendButton - .setImageResource(R.drawable.ic_action_send_now_online); + .setImageResource(R.drawable.ic_action_send_now_online); break; case Presences.ONLINE: this.mSendButton - .setImageResource(R.drawable.ic_action_send_now_online); + .setImageResource(R.drawable.ic_action_send_now_online); break; case Presences.AWAY: this.mSendButton - .setImageResource(R.drawable.ic_action_send_now_away); + .setImageResource(R.drawable.ic_action_send_now_away); break; case Presences.XA: this.mSendButton - .setImageResource(R.drawable.ic_action_send_now_away); + .setImageResource(R.drawable.ic_action_send_now_away); break; case Presences.DND: this.mSendButton - .setImageResource(R.drawable.ic_action_send_now_dnd); + .setImageResource(R.drawable.ic_action_send_now_dnd); break; default: this.mSendButton - .setImageResource(R.drawable.ic_action_send_now_offline); + .setImageResource(R.drawable.ic_action_send_now_offline); break; } } else if (c.getMode() == Conversation.MODE_MULTI) { if (c.getMucOptions().online()) { this.mSendButton - .setImageResource(R.drawable.ic_action_send_now_online); + .setImageResource(R.drawable.ic_action_send_now_online); } else { this.mSendButton - .setImageResource(R.drawable.ic_action_send_now_offline); + .setImageResource(R.drawable.ic_action_send_now_offline); } } else { this.mSendButton - .setImageResource(R.drawable.ic_action_send_now_offline); + .setImageResource(R.drawable.ic_action_send_now_offline); } } else { this.mSendButton - .setImageResource(R.drawable.ic_action_send_now_offline); + .setImageResource(R.drawable.ic_action_send_now_offline); } } @@ -716,8 +780,7 @@ public class ConversationFragment extends Fragment { return; } else { if (this.messageList.get(i).getStatus() == Message.STATUS_SEND_DISPLAYED) { - this.messageList.add(i + 1, - Message.createStatusMessage(conversation)); + this.messageList.add(i + 1,Message.createStatusMessage(conversation)); return; } } @@ -728,19 +791,30 @@ public class ConversationFragment extends Fragment { protected void makeFingerprintWarning() { if (conversation.smpRequested()) { - showSnackbar(R.string.smp_requested, R.string.verify, clickToVerify); + showSnackbar(R.string.smp_requested, R.string.verify, new OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(activity, VerifyOTRActivity.class); + intent.setAction(VerifyOTRActivity.ACTION_VERIFY_CONTACT); + intent.putExtra("contact", conversation.getContact().getJid().toBareJid().toString()); + intent.putExtra("account", conversation.getAccount().getJid().toBareJid().toString()); + intent.putExtra("mode",VerifyOTRActivity.MODE_ANSWER_QUESTION); + startActivity(intent); + } + }); } else if (conversation.hasValidOtrSession() && (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) && (!conversation.isOtrFingerprintVerified())) { showSnackbar(R.string.unknown_otr_fingerprint, R.string.verify, clickToVerify); - } + } } - protected void showSnackbar(int message, int action, - OnClickListener clickListener) { + protected void showSnackbar(final int message, final int action, + final OnClickListener clickListener) { snackbar.setVisibility(View.VISIBLE); snackbar.setOnClickListener(null); snackbarMessage.setText(message); snackbarMessage.setOnClickListener(null); + snackbarAction.setVisibility(View.VISIBLE); snackbarAction.setText(action); snackbarAction.setOnClickListener(clickListener); } @@ -767,7 +841,7 @@ public class ConversationFragment extends Fragment { @Override public void userInputRequried(PendingIntent pi, - Contact contact) { + Contact contact) { activity.runIntent( pi, ConversationActivity.REQUEST_ENCRYPT_MESSAGE); @@ -791,11 +865,11 @@ public class ConversationFragment extends Fragment { @Override public void onClick(DialogInterface dialog, - int which) { + int which) { conversation - .setNextEncryption(Message.ENCRYPTION_NONE); + .setNextEncryption(Message.ENCRYPTION_NONE); xmppService.databaseBackend - .updateConversation(conversation); + .updateConversation(conversation); message.setEncryption(Message.ENCRYPTION_NONE); xmppService.sendMessage(message); messageSent(); @@ -806,9 +880,9 @@ public class ConversationFragment extends Fragment { if (conversation.getMucOptions().pgpKeysInUse()) { if (!conversation.getMucOptions().everybodyHasKeys()) { Toast warning = Toast - .makeText(getActivity(), - R.string.missing_public_keys, - Toast.LENGTH_LONG); + .makeText(getActivity(), + R.string.missing_public_keys, + Toast.LENGTH_LONG); warning.setGravity(Gravity.CENTER_VERTICAL, 0, 0); warning.show(); } @@ -820,12 +894,12 @@ public class ConversationFragment extends Fragment { @Override public void onClick(DialogInterface dialog, - int which) { + int which) { conversation - .setNextEncryption(Message.ENCRYPTION_NONE); + .setNextEncryption(Message.ENCRYPTION_NONE); message.setEncryption(Message.ENCRYPTION_NONE); xmppService.databaseBackend - .updateConversation(conversation); + .updateConversation(conversation); xmppService.sendMessage(message); messageSent(); } @@ -838,7 +912,7 @@ public class ConversationFragment extends Fragment { } public void showNoPGPKeyDialog(boolean plural, - DialogInterface.OnClickListener listener) { + DialogInterface.OnClickListener listener) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setIconAttribute(android.R.attr.alertDialogIcon); if (plural) { |