From c0b3a3ff0c32c8025174ebb92fbcf4a7fc67f497 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 15 Feb 2016 23:15:04 +0100 Subject: basic support for XEP-0308: Last Message Correction. fixes #864 --- .../conversations/ui/ConversationFragment.java | 72 +++++++++++++++++----- .../eu/siacs/conversations/ui/EditMessage.java | 2 + .../conversations/ui/adapter/MessageAdapter.java | 15 ++++- 3 files changed, 74 insertions(+), 15 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/ui') diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index c555ead03..6ead99625 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -8,7 +8,6 @@ import android.content.ActivityNotFoundException; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.content.IntentSender; import android.content.IntentSender.SendIntentException; import android.os.Bundle; import android.support.annotation.Nullable; @@ -40,6 +39,7 @@ import net.java.otr4j.session.SessionStatus; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.UUID; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; @@ -51,7 +51,6 @@ import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.MucOptions; import eu.siacs.conversations.entities.Presence; -import eu.siacs.conversations.entities.Presences; import eu.siacs.conversations.entities.Transferable; import eu.siacs.conversations.entities.TransferablePlaceholder; import eu.siacs.conversations.services.XmppConnectionService; @@ -294,8 +293,14 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa activity.attachFile(ConversationActivity.ATTACHMENT_CHOICE_CHOOSE_IMAGE); break; case CANCEL: - if (conversation != null && conversation.getMode() == Conversation.MODE_MULTI) { - conversation.setNextCounterpart(null); + if (conversation != null) { + if (conversation.getCorrectingMessage() != null) { + conversation.setCorrectingMessage(null); + mEditMessage.getEditableText().clear(); + } + if (conversation.getMode() == Conversation.MODE_MULTI) { + conversation.setNextCounterpart(null); + } updateChatMsgHint(); updateSendButton(); } @@ -330,12 +335,21 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa if (body.length() == 0 || this.conversation == null) { return; } - Message message = new Message(conversation, body, conversation.getNextEncryption()); - if (conversation.getMode() == Conversation.MODE_MULTI) { - if (conversation.getNextCounterpart() != null) { - message.setCounterpart(conversation.getNextCounterpart()); - message.setType(Message.TYPE_PRIVATE); + final Message message; + if (conversation.getCorrectingMessage() == null) { + message = new Message(conversation, body, conversation.getNextEncryption()); + if (conversation.getMode() == Conversation.MODE_MULTI) { + if (conversation.getNextCounterpart() != null) { + message.setCounterpart(conversation.getNextCounterpart()); + message.setType(Message.TYPE_PRIVATE); + } } + } else { + message = conversation.getCorrectingMessage(); + message.setBody(body); + message.setEdited(message.getUuid()); + message.setUuid(UUID.randomUUID().toString()); + conversation.setCorrectingMessage(null); } switch (conversation.getNextEncryption()) { case Message.ENCRYPTION_OTR: @@ -356,7 +370,9 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa public void updateChatMsgHint() { final boolean multi = conversation.getMode() == Conversation.MODE_MULTI; - if (multi && conversation.getNextCounterpart() != null) { + if (conversation.getCorrectingMessage() != null) { + this.mEditMessage.setHint(R.string.send_corrected_message); + } else if (multi && conversation.getNextCounterpart() != null) { this.mEditMessage.setHint(getString( R.string.send_private_message_to, conversation.getNextCounterpart().getResourcepart())); @@ -487,8 +503,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa } @Override - public void onCreateContextMenu(ContextMenu menu, View v, - ContextMenuInfo menuInfo) { + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { synchronized (this.messageList) { super.onCreateContextMenu(menu, v, menuInfo); AdapterView.AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) menuInfo; @@ -503,6 +518,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa activity.getMenuInflater().inflate(R.menu.message_context, menu); menu.setHeaderTitle(R.string.message_options); MenuItem copyText = menu.findItem(R.id.copy_text); + MenuItem correctMessage = menu.findItem(R.id.correct_message); MenuItem shareWith = menu.findItem(R.id.share_with); MenuItem sendAgain = menu.findItem(R.id.send_again); MenuItem copyUrl = menu.findItem(R.id.copy_url); @@ -514,6 +530,11 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa && m.treatAsDownloadable() != Message.Decision.MUST) { copyText.setVisible(true); } + if (m.getType() == Message.TYPE_TEXT + && m.getStatus() != Message.STATUS_RECEIVED + && !m.isCarbon()) { + correctMessage.setVisible(true); + } if ((m.getType() != Message.TYPE_TEXT && m.getType() != Message.TYPE_PRIVATE && m.getTransferable() == null) @@ -550,6 +571,9 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa case R.id.copy_text: copyText(selectedMessage); return true; + case R.id.correct_message: + correctMessage(selectedMessage); + return true; case R.id.send_again: resendMessage(selectedMessage); return true; @@ -652,6 +676,16 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa updateSendButton(); } + private void correctMessage(Message message) { + while(message.mergeable(message.next())) { + message = message.next(); + } + this.conversation.setCorrectingMessage(message); + this.mEditMessage.getEditableText().clear(); + this.mEditMessage.getEditableText().append(message.getBody()); + + } + protected void highlightInConference(String nick) { String oldString = mEditMessage.getText().toString().trim(); if (oldString.isEmpty() || mEditMessage.getSelectionStart() == 0) { @@ -958,9 +992,12 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa final Conversation c = this.conversation; final SendButtonAction action; final Presence.Status status; - final boolean empty = this.mEditMessage == null || this.mEditMessage.getText().length() == 0; + final String text = this.mEditMessage == null ? "" : this.mEditMessage.getText().toString(); + final boolean empty = text.length() == 0; final boolean conference = c.getMode() == Conversation.MODE_MULTI; - if (conference && !c.getAccount().httpUploadAvailable()) { + if (c.getCorrectingMessage() != null && (empty || text.equals(c.getCorrectingMessage().getBody()))) { + action = SendButtonAction.CANCEL; + } else if (conference && !c.getAccount().httpUploadAvailable()) { if (empty && c.getNextCounterpart() != null) { action = SendButtonAction.CANCEL; } else { @@ -1238,6 +1275,13 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa updateSendButton(); } + @Override + public void onTextChanged() { + if (conversation != null && conversation.getCorrectingMessage() != null) { + updateSendButton(); + } + } + private int completionIndex = 0; private int lastCompletionLength = 0; private String incomplete; diff --git a/src/main/java/eu/siacs/conversations/ui/EditMessage.java b/src/main/java/eu/siacs/conversations/ui/EditMessage.java index fc655b0ce..e3841d1d5 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditMessage.java +++ b/src/main/java/eu/siacs/conversations/ui/EditMessage.java @@ -69,6 +69,7 @@ public class EditMessage extends EditText { this.isUserTyping = false; this.keyboardListener.onTextDeleted(); } + this.keyboardListener.onTextChanged(); } } @@ -84,6 +85,7 @@ public class EditMessage extends EditText { void onTypingStarted(); void onTypingStopped(); void onTextDeleted(); + void onTextChanged(); boolean onTabPressed(boolean repeated); } diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java index fc2bd2abc..f6496b21c 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -123,6 +123,16 @@ public class MessageAdapter extends ArrayAdapter { if (viewHolder.indicatorReceived != null) { viewHolder.indicatorReceived.setVisibility(View.GONE); } + + if (viewHolder.edit_indicator != null) { + if (message.edited()) { + viewHolder.edit_indicator.setVisibility(View.VISIBLE); + viewHolder.edit_indicator.setImageResource(darkBackground ? R.drawable.ic_mode_edit_white_18dp : R.drawable.ic_mode_edit_black_18dp); + viewHolder.edit_indicator.setAlpha(darkBackground ? 0.7f : 0.57f); + } else { + viewHolder.edit_indicator.setVisibility(View.GONE); + } + } boolean multiReceived = message.getConversation().getMode() == Conversation.MODE_MULTI && message.getMergedStatus() <= Message.STATUS_RECEIVED; if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE || message.getTransferable() != null) { @@ -179,7 +189,7 @@ public class MessageAdapter extends ArrayAdapter { if (message.getEncryption() == Message.ENCRYPTION_NONE) { viewHolder.indicator.setVisibility(View.GONE); } else { - viewHolder.indicator.setImageResource(darkBackground ? R.drawable.ic_secure_indicator_white : R.drawable.ic_secure_indicator); + viewHolder.indicator.setImageResource(darkBackground ? R.drawable.ic_lock_white_18dp : R.drawable.ic_lock_black_18dp); viewHolder.indicator.setVisibility(View.VISIBLE); if (message.getEncryption() == Message.ENCRYPTION_AXOLOTL) { XmppAxolotlSession.Trust trust = message.getConversation() @@ -463,6 +473,7 @@ public class MessageAdapter extends ArrayAdapter { .findViewById(R.id.download_button); viewHolder.indicator = (ImageView) view .findViewById(R.id.security_indicator); + viewHolder.edit_indicator = (ImageView) view.findViewById(R.id.edit_indicator); viewHolder.image = (ImageView) view .findViewById(R.id.message_image); viewHolder.messageBody = (TextView) view @@ -483,6 +494,7 @@ public class MessageAdapter extends ArrayAdapter { .findViewById(R.id.download_button); viewHolder.indicator = (ImageView) view .findViewById(R.id.security_indicator); + viewHolder.edit_indicator = (ImageView) view.findViewById(R.id.edit_indicator); viewHolder.image = (ImageView) view .findViewById(R.id.message_image); viewHolder.messageBody = (TextView) view @@ -701,6 +713,7 @@ public class MessageAdapter extends ArrayAdapter { protected TextView status_message; protected TextView encryption; public Button load_more_messages; + public ImageView edit_indicator; } class BitmapWorkerTask extends AsyncTask { -- cgit v1.2.3