From 530d64beca87181e9bea8034353353cd8a7083a4 Mon Sep 17 00:00:00 2001 From: steckbrief Date: Sun, 12 Jun 2016 11:44:23 +0200 Subject: Implements FS#217: Rework display of /me messages --- .../ui/adapter/MessageAdapter.java | 1016 ++++++++++---------- src/main/res/drawable/mecmd_message_border.xml | 15 + .../res/layout/fragment_conversations_overview.xml | 2 +- src/main/res/layout/message_mecmd.xml | 112 +++ src/main/res/layout/message_received.xml | 10 +- src/main/res/layout/message_sent.xml | 75 +- src/main/res/layout/message_status.xml | 4 +- src/main/res/values/dimens.xml | 7 +- 8 files changed, 744 insertions(+), 497 deletions(-) create mode 100644 src/main/res/drawable/mecmd_message_border.xml create mode 100644 src/main/res/layout/message_mecmd.xml (limited to 'src') diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/adapter/MessageAdapter.java b/src/main/java/de/thedevstack/conversationsplus/ui/adapter/MessageAdapter.java index 9a501b89..a4711aa0 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/adapter/MessageAdapter.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/adapter/MessageAdapter.java @@ -13,9 +13,13 @@ import android.net.Uri; import android.os.AsyncTask; import android.text.Spannable; import android.text.SpannableString; + import android.text.style.ForegroundColorSpan; + import android.text.style.StyleSpan; import android.text.util.Linkify; + +import android.util.DisplayMetrics; import android.util.Patterns; import android.view.View; import android.view.View.OnClickListener; @@ -29,11 +33,13 @@ import android.widget.TextView; import android.widget.Toast; import java.lang.ref.WeakReference; + import java.util.List; import java.util.concurrent.RejectedExecutionException; import java.util.regex.Matcher; import java.util.regex.Pattern; + import de.thedevstack.conversationsplus.ConversationsPlusApplication; import de.thedevstack.conversationsplus.ConversationsPlusColors; import de.thedevstack.conversationsplus.ConversationsPlusPreferences; @@ -44,6 +50,7 @@ import de.thedevstack.conversationsplus.entities.Conversation; import de.thedevstack.conversationsplus.entities.DownloadableFile; import de.thedevstack.conversationsplus.entities.FileParams; import de.thedevstack.conversationsplus.entities.Message; + import de.thedevstack.conversationsplus.entities.Transferable; import de.thedevstack.conversationsplus.enums.FileStatus; import de.thedevstack.conversationsplus.persistance.FileBackend; @@ -61,177 +68,192 @@ import de.thedevstack.conversationsplus.utils.ui.ViewUtil; public class MessageAdapter extends ArrayAdapter { - private static final int SENT = 0; - private static final int RECEIVED = 1; - private static final int STATUS = 2; - private static final int NULL = 3; - private static final Pattern XMPP_PATTERN = Pattern - .compile("xmpp\\:(?:(?:[" - + Patterns.GOOD_IRI_CHAR - + "\\;\\/\\?\\@\\&\\=\\#\\~\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])" - + "|(?:\\%[a-fA-F0-9]{2}))+"); - - private ConversationActivity activity; - - private OnContactPictureClicked mOnContactPictureClickedListener; - private OnContactPictureLongClicked mOnContactPictureLongClickedListener; - - public MessageAdapter(ConversationActivity activity, List messages) { - super(activity, 0, messages); - this.activity = activity; - } - - public void setOnContactPictureClicked(OnContactPictureClicked listener) { - this.mOnContactPictureClickedListener = listener; - } - - public void setOnContactPictureLongClicked( - OnContactPictureLongClicked listener) { - this.mOnContactPictureLongClickedListener = listener; - } - - @Override - public int getViewTypeCount() { - return 3; - } - - public int getItemViewType(Message message) { - if (message.getType() == Message.TYPE_STATUS) { - return STATUS; - } else if (message.getStatus() <= Message.STATUS_RECEIVED) { - return RECEIVED; - } - - return SENT; - } - - @Override - public int getItemViewType(int position) { - return this.getItemViewType(getItem(position)); - } - - private int getMessageTextColor(boolean onDark, boolean primary) { - if (onDark) { - return primary ? ConversationsPlusColors.primaryTextOnDark() : ConversationsPlusColors.secondaryTextOnDark(); - } else { - return primary ? ConversationsPlusColors.primaryText() : ConversationsPlusColors.secondaryText(); - } - } - - private void displayStatus(ViewHolder viewHolder, Message message, int type) { - String filesize = null; - String info = null; - boolean error = false; - if (viewHolder.indicatorReceived != null) { - viewHolder.indicatorReceived.setVisibility(View.GONE); - } - - boolean multiReceived = message.getConversation().getMode() == Conversation.MODE_MULTI - && message.getStatus() <= Message.STATUS_RECEIVED; - if (message.hasFileAttached() || message.getTransferable() != null) { + private static final int SENT = 0; + private static final int RECEIVED = 1; + private static final int STATUS = 2; + private static final int ME_COMMAND = 3; + private static final Pattern XMPP_PATTERN = Pattern + .compile("xmpp\\:(?:(?:[" + + Patterns.GOOD_IRI_CHAR + + "\\;\\/\\?\\@\\&\\=\\#\\~\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])" + + "|(?:\\%[a-fA-F0-9]{2}))+"); + + private ConversationActivity activity; + + private DisplayMetrics metrics; + + private OnContactPictureClicked mOnContactPictureClickedListener; + private OnContactPictureLongClicked mOnContactPictureLongClickedListener; + + private OnLongClickListener openContextMenu = new OnLongClickListener() { + + @Override + public boolean onLongClick(View v) { + v.showContextMenu(); + return true; + } + }; + + + public MessageAdapter(ConversationActivity activity, List messages) { + super(activity, 0, messages); + this.activity = activity; + metrics = getContext().getResources().getDisplayMetrics(); + } + + public void setOnContactPictureClicked(OnContactPictureClicked listener) { + this.mOnContactPictureClickedListener = listener; + } + + public void setOnContactPictureLongClicked( + OnContactPictureLongClicked listener) { + this.mOnContactPictureLongClickedListener = listener; + } + + @Override + public int getViewTypeCount() { + return 4; + } + + public int getItemViewType(Message message) { + if (message.hasMeCommand()) { + return ME_COMMAND; + } else if (message.getType() == Message.TYPE_STATUS) { + return STATUS; + } else if (message.getStatus() <= Message.STATUS_RECEIVED) { + return RECEIVED; + } + + return SENT; + } + + @Override + public int getItemViewType(int position) { + return this.getItemViewType(getItem(position)); + } + + private int getMessageTextColor(boolean onDark, boolean primary) { + if (onDark) { + return primary ? ConversationsPlusColors.primaryTextOnDark() : ConversationsPlusColors.secondaryTextOnDark(); + } else { + return primary ? ConversationsPlusColors.primaryText() : ConversationsPlusColors.secondaryText(); + } + } + + private void displayStatus(ViewHolder viewHolder, Message message, int type) { + String filesize = null; + String info = null; + boolean error = false; + if (viewHolder.indicatorReceived != null) { + viewHolder.indicatorReceived.setVisibility(View.GONE); + } + + boolean multiReceived = message.getConversation().getMode() == Conversation.MODE_MULTI + && message.getStatus() <= Message.STATUS_RECEIVED; + if (message.hasFileAttached() || message.getTransferable() != null) { FileParams params = message.getFileParams(); if (null != params) { filesize = UIHelper.getHumanReadableFileSize(params.getSize()); } - if (message.getTransferable() != null && message.getTransferable().getStatus() == Transferable.STATUS_FAILED) { - error = true; - } - } - switch (message.getStatus()) { - case Message.STATUS_WAITING: - info = getContext().getString(R.string.waiting); - break; - case Message.STATUS_UNSEND: - Transferable d = message.getTransferable(); - if (d!=null) { - info = getContext().getString(R.string.sending_file,d.getProgress()); - } else { - info = getContext().getString(R.string.sending); - } - break; - case Message.STATUS_OFFERED: - info = getContext().getString(R.string.offering); - break; - case Message.STATUS_SEND_RECEIVED: - if (ConversationsPlusPreferences.indicateReceived()) { - viewHolder.indicatorReceived.setVisibility(View.VISIBLE); - } - break; - case Message.STATUS_SEND_DISPLAYED: - if (ConversationsPlusPreferences.indicateReceived()) { - viewHolder.indicatorReceived.setVisibility(View.VISIBLE); - } - break; - case Message.STATUS_SEND_FAILED: - info = getContext().getString(R.string.send_failed); - error = true; - break; - default: - if (multiReceived) { - info = UIHelper.getMessageDisplayName(message); - } - break; - } - if (error && type == SENT) { - viewHolder.time.setTextColor(ConversationsPlusColors.warning()); - } else { - viewHolder.time.setTextColor(this.getMessageTextColor(viewHolder.darkBackground,false)); - } - if (message.getEncryption() == Message.ENCRYPTION_NONE) { - viewHolder.indicator.setVisibility(View.GONE); - } else { - viewHolder.indicator.setImageResource(viewHolder.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() - .getAccount().getAxolotlService().getFingerprintTrust( - message.getFingerprint()); - - if(trust == null || (!trust.trusted() && !trust.trustedInactive())) { - viewHolder.indicator.setColorFilter(ConversationsPlusColors.warning()); - viewHolder.indicator.setAlpha(1.0f); - } else { - viewHolder.indicator.clearColorFilter(); - if (viewHolder.darkBackground) { - viewHolder.indicator.setAlpha(0.7f); - } else { - viewHolder.indicator.setAlpha(0.57f); - } - } - } else { - viewHolder.indicator.clearColorFilter(); - if (viewHolder.darkBackground) { - viewHolder.indicator.setAlpha(0.7f); - } else { - viewHolder.indicator.setAlpha(0.57f); - } - } - } - - String formatedTime = UIHelper.readableTimeDifferenceFull(getContext(), - message.getTimeSent()); - if (message.getStatus() <= Message.STATUS_RECEIVED) { + if (message.getTransferable() != null && message.getTransferable().getStatus() == Transferable.STATUS_FAILED) { + error = true; + } + } + switch (message.getStatus()) { + case Message.STATUS_WAITING: + info = getContext().getString(R.string.waiting); + break; + case Message.STATUS_UNSEND: + Transferable d = message.getTransferable(); + if (d != null) { + info = getContext().getString(R.string.sending_file, d.getProgress()); + } else { + info = getContext().getString(R.string.sending); + } + break; + case Message.STATUS_OFFERED: + info = getContext().getString(R.string.offering); + break; + case Message.STATUS_SEND_RECEIVED: + if (ConversationsPlusPreferences.indicateReceived()) { + viewHolder.indicatorReceived.setVisibility(View.VISIBLE); + } + break; + case Message.STATUS_SEND_DISPLAYED: + if (ConversationsPlusPreferences.indicateReceived()) { + viewHolder.indicatorReceived.setVisibility(View.VISIBLE); + } + break; + case Message.STATUS_SEND_FAILED: + info = getContext().getString(R.string.send_failed); + error = true; + break; + default: + if (multiReceived) { + info = UIHelper.getMessageDisplayName(message); + } + break; + } + if (error && type == SENT) { + viewHolder.time.setTextColor(ConversationsPlusColors.warning()); + } else { + viewHolder.time.setTextColor(this.getMessageTextColor(viewHolder.darkBackground, false)); + } + if (message.getEncryption() == Message.ENCRYPTION_NONE) { + viewHolder.indicator.setVisibility(View.GONE); + } else { + viewHolder.indicator.setImageResource(viewHolder.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() + .getAccount().getAxolotlService().getFingerprintTrust( + message.getFingerprint()); + + if (trust == null || (!trust.trusted() && !trust.trustedInactive())) { + viewHolder.indicator.setColorFilter(ConversationsPlusColors.warning()); + viewHolder.indicator.setAlpha(1.0f); + } else { + viewHolder.indicator.clearColorFilter(); + if (viewHolder.darkBackground) { + viewHolder.indicator.setAlpha(0.7f); + } else { + viewHolder.indicator.setAlpha(0.57f); + } + } + } else { + viewHolder.indicator.clearColorFilter(); + if (viewHolder.darkBackground) { + viewHolder.indicator.setAlpha(0.7f); + } else { + viewHolder.indicator.setAlpha(0.57f); + } + } + } + + String formatedTime = UIHelper.readableTimeDifferenceFull(getContext(), message.getTimeSent()); + if (message.getStatus() <= Message.STATUS_RECEIVED) { StringBuilder timeText = new StringBuilder(); timeText.append((null != formatedTime) ? formatedTime + ((null != info || null != filesize) ? " \u00B7 " : "") : ""); timeText.append((null != filesize) ? filesize + ((null != info) ? " \u00B7 " : "") : ""); timeText.append((null != info) ? info : ""); + viewHolder.time.setText(timeText); - } else { - if ((filesize != null) && (info != null)) { - viewHolder.time.setText(filesize + " \u00B7 " + info); - } else if ((filesize == null) && (info != null)) { - if (error) { - viewHolder.time.setText(info + " \u00B7 " + formatedTime); - } else { - viewHolder.time.setText(info); - } - } else if ((filesize != null) && (info == null)) { - viewHolder.time.setText(filesize + " \u00B7 " + formatedTime); - } else { - viewHolder.time.setText(formatedTime); - } - } + } else { + if ((filesize != null) && (info != null)) { + viewHolder.time.setText(filesize + " \u00B7 " + info); + } else if ((filesize == null) && (info != null)) { + if (error) { + viewHolder.time.setText(info + " \u00B7 " + formatedTime); + } else { + viewHolder.time.setText(info); + } + } else if ((filesize != null) && (info == null)) { + viewHolder.time.setText(filesize + " \u00B7 " + formatedTime); + } else { + viewHolder.time.setText(formatedTime); + } + } if (message.hasFileAttached() && null != message.getFileParams() && null != viewHolder.remoteFileStatus) { FileStatus fileStatus = message.getFileParams().getFileStatus(); @@ -255,122 +277,132 @@ public class MessageAdapter extends ArrayAdapter { } } } - } - - private void displayInfoMessage(ViewHolder viewHolder, String text) { - if (viewHolder.download_button != null) { - viewHolder.download_button.setVisibility(View.GONE); - } - viewHolder.image.setVisibility(View.GONE); - viewHolder.messageBody.setVisibility(View.VISIBLE); - viewHolder.messageBody.setText(text); - viewHolder.messageBody.setTextColor(getMessageTextColor(viewHolder.darkBackground, false)); - viewHolder.messageBody.setTypeface(null, Typeface.ITALIC); - viewHolder.messageBody.setTextIsSelectable(false); - } - - private void displayDecryptionFailed(ViewHolder viewHolder) { - if (viewHolder.download_button != null) { - viewHolder.download_button.setVisibility(View.GONE); - } - viewHolder.image.setVisibility(View.GONE); - viewHolder.messageBody.setVisibility(View.VISIBLE); - viewHolder.messageBody.setText(getContext().getString( - R.string.decryption_failed)); - viewHolder.messageBody.setTextColor(getMessageTextColor(viewHolder.darkBackground, false)); - viewHolder.messageBody.setTypeface(null, Typeface.NORMAL); - viewHolder.messageBody.setTextIsSelectable(false); - } - - private void displayTextMessage(final ViewHolder viewHolder, final Message message) { - if (viewHolder.download_button != null) { - viewHolder.download_button.setVisibility(View.GONE); - } - viewHolder.image.setVisibility(View.GONE); - viewHolder.messageBody.setVisibility(View.VISIBLE); - viewHolder.messageBody.setIncludeFontPadding(true); - if (message.getBody() != null) { - final String nick = UIHelper.getMessageDisplayName(message); - String body; - if (message.hasMeCommand()) { - body = message.getBodyReplacedMeCommand(nick); - } else { - body = message.getBody(); - } - final SpannableString formattedBody = new SpannableString(body); - if (message.getType() != Message.TYPE_PRIVATE) { - if (message.hasMeCommand()) { - final Spannable span = new SpannableString(formattedBody); - span.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 0, nick.length(), - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - viewHolder.messageBody.setText(span); - } else { - viewHolder.messageBody.setText(formattedBody); - } - } else { - String privateMarker; - if (message.getStatus() <= Message.STATUS_RECEIVED) { - privateMarker = activity - .getString(R.string.private_message); - } else { - final String to; - if (message.getCounterpart() != null) { - to = message.getCounterpart().getResourcepart(); - } else { - to = ""; - } - privateMarker = activity.getString(R.string.private_message_to, to); - } - final Spannable span = new SpannableString(privateMarker + " " - + formattedBody); - span.setSpan(new ForegroundColorSpan(getMessageTextColor(viewHolder.darkBackground,false)), 0, privateMarker - .length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - span.setSpan(new StyleSpan(Typeface.BOLD), 0, - privateMarker.length(), - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - if (message.hasMeCommand()) { - span.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), privateMarker.length() + 1, - privateMarker.length() + 1 + nick.length(), - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } - viewHolder.messageBody.setText(span); - } - int patternMatchCount = 0; - int oldAutoLinkMask = viewHolder.messageBody.getAutoLinkMask(); - - // first check if we have a match on XMPP_PATTERN so we do not have to check for EMAIL_ADDRESSES - patternMatchCount += countMatches(XMPP_PATTERN, body); - if ((Linkify.EMAIL_ADDRESSES & oldAutoLinkMask) != 0 && patternMatchCount > 0) { - oldAutoLinkMask -= Linkify.EMAIL_ADDRESSES; - } - - // count matches for all patterns - if ((Linkify.WEB_URLS & oldAutoLinkMask) != 0) { - patternMatchCount += countMatches(Patterns.WEB_URL, body); - } - if ((Linkify.EMAIL_ADDRESSES & oldAutoLinkMask) != 0) { - patternMatchCount += countMatches(Patterns.EMAIL_ADDRESS, body); - } - if ((Linkify.PHONE_NUMBERS & oldAutoLinkMask) != 0) { - patternMatchCount += countMatches(Patterns.PHONE, body); - } - - viewHolder.messageBody.setTextIsSelectable(patternMatchCount <= 1); - viewHolder.messageBody.setAutoLinkMask(0); - Linkify.addLinks(viewHolder.messageBody, XMPP_PATTERN, "xmpp"); - viewHolder.messageBody.setAutoLinkMask(oldAutoLinkMask); - } else { - viewHolder.messageBody.setText(""); - viewHolder.messageBody.setTextIsSelectable(false); - } - viewHolder.messageBody.setTextColor(this.getMessageTextColor(viewHolder.darkBackground, true)); - viewHolder.messageBody.setTypeface(null, Typeface.NORMAL); - } + } + + private void displayInfoMessage(ViewHolder viewHolder, String text) { + if (viewHolder.download_button != null) { + viewHolder.download_button.setVisibility(View.GONE); + } + if (null != viewHolder.image) { + viewHolder.image.setVisibility(View.GONE); + } + + viewHolder.messageBody.setVisibility(View.VISIBLE); + viewHolder.messageBody.setText(text); + viewHolder.messageBody.setTextColor(getMessageTextColor(viewHolder.darkBackground, false)); + viewHolder.messageBody.setTypeface(null, Typeface.ITALIC); + viewHolder.messageBody.setTextIsSelectable(false); + } + + private void displayDecryptionFailed(ViewHolder viewHolder) { + if (viewHolder.download_button != null) { + viewHolder.download_button.setVisibility(View.GONE); + } + + viewHolder.image.setVisibility(View.GONE); + + viewHolder.messageBody.setVisibility(View.VISIBLE); + viewHolder.messageBody.setText(getContext().getString( + R.string.decryption_failed)); + viewHolder.messageBody.setTextColor(getMessageTextColor(viewHolder.darkBackground, false)); + viewHolder.messageBody.setTypeface(null, Typeface.NORMAL); + viewHolder.messageBody.setTextIsSelectable(false); + } + + private void displayTextMessage(final ViewHolder viewHolder, final Message message) { + if (viewHolder.download_button != null) { + viewHolder.download_button.setVisibility(View.GONE); + } + if (null != viewHolder.image) { + viewHolder.image.setVisibility(View.GONE); + } + + viewHolder.messageBody.setVisibility(View.VISIBLE); + viewHolder.messageBody.setIncludeFontPadding(true); + if (message.getBody() != null) { + final String nick = UIHelper.getMessageDisplayName(message); + String body; + if (message.hasMeCommand()) { + body = message.getBodyReplacedMeCommand(nick); + } else { + body = message.getBody(); + } + final SpannableString formattedBody = new SpannableString(body); + + if (message.getType() != Message.TYPE_PRIVATE) { + if (message.hasMeCommand()) { + final Spannable span = new SpannableString(formattedBody); + span.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 0, nick.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + viewHolder.messageBody.setText(span); + } else { + viewHolder.messageBody.setText(formattedBody); + } + } else { + String privateMarker; + if (message.getStatus() <= Message.STATUS_RECEIVED) { + privateMarker = activity.getString(R.string.private_message); + } else { + final String to; + if (message.getCounterpart() != null) { + to = message.getCounterpart().getResourcepart(); + } else { + to = ""; + } + privateMarker = activity.getString(R.string.private_message_to, to); + } + final Spannable span = new SpannableString(privateMarker + " " + + formattedBody); + span.setSpan(new ForegroundColorSpan(getMessageTextColor(viewHolder.darkBackground, false)), 0, privateMarker + .length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + span.setSpan(new StyleSpan(Typeface.BOLD), 0, + privateMarker.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + if (message.hasMeCommand()) { + span.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), privateMarker.length() + 1, + privateMarker.length() + 1 + nick.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } + viewHolder.messageBody.setText(span); + } + int patternMatchCount = 0; + int oldAutoLinkMask = viewHolder.messageBody.getAutoLinkMask(); + + // first check if we have a match on XMPP_PATTERN so we do not have to check for EMAIL_ADDRESSES + patternMatchCount += countMatches(XMPP_PATTERN, body); + if ((Linkify.EMAIL_ADDRESSES & oldAutoLinkMask) != 0 && patternMatchCount > 0) { + oldAutoLinkMask -= Linkify.EMAIL_ADDRESSES; + } + + // count matches for all patterns + if ((Linkify.WEB_URLS & oldAutoLinkMask) != 0) { + patternMatchCount += countMatches(Patterns.WEB_URL, body); + } + if ((Linkify.EMAIL_ADDRESSES & oldAutoLinkMask) != 0) { + patternMatchCount += countMatches(Patterns.EMAIL_ADDRESS, body); + } + if ((Linkify.PHONE_NUMBERS & oldAutoLinkMask) != 0) { + patternMatchCount += countMatches(Patterns.PHONE, body); + } + + viewHolder.messageBody.setTextIsSelectable(patternMatchCount <= 1); + viewHolder.messageBody.setAutoLinkMask(0); + Linkify.addLinks(viewHolder.messageBody, XMPP_PATTERN, "xmpp"); + viewHolder.messageBody.setAutoLinkMask(oldAutoLinkMask); + } else { + viewHolder.messageBody.setText(""); + viewHolder.messageBody.setTextIsSelectable(false); + } + viewHolder.messageBody.setTextColor(this.getMessageTextColor(viewHolder.darkBackground, true)); + viewHolder.messageBody.setTypeface(null, Typeface.NORMAL); + viewHolder.messageBody.setOnLongClickListener(openContextMenu); + } /** * Counts the number of occurrences of the pattern in body. + * * @param pattern the pattern to match - * @param body the body to find the pattern + * @param body the body to find the pattern * @return the number of occurrences */ private int countMatches(Pattern pattern, String body) { @@ -386,6 +418,7 @@ public class MessageAdapter extends ArrayAdapter { viewHolder.download_button.setVisibility(View.VISIBLE); viewHolder.download_button.setText(btnText); viewHolder.download_button.setOnClickListener(onClickListener); + viewHolder.download_button.setOnLongClickListener(openContextMenu); } private void displayFileInfoForFileMessage(final Message message, ViewHolder viewHolder) { @@ -400,8 +433,8 @@ public class MessageAdapter extends ArrayAdapter { viewHolder.messageBody.setAutoLinkMask(oldAutoLinkMask); } - private void displayDownloadableMessage(ViewHolder viewHolder, final Message message) { - viewHolder.image.setVisibility(View.GONE); + private void displayDownloadableMessage(ViewHolder viewHolder, final Message message) { + viewHolder.image.setVisibility(View.GONE); FileParams fileParams = message.getFileParams(); String btnText; int resId = R.string.download_x_file; @@ -417,17 +450,16 @@ public class MessageAdapter extends ArrayAdapter { btnText = activity.getString(resId, UIHelper.getFileDescriptionString(activity, message)); } - this.displayDownloadButton(viewHolder, btnText, new OnClickListener() { - - @Override - public void onClick(View v) { - activity.startDownloadable(message); - } - }); - } + this.displayDownloadButton(viewHolder, btnText, new OnClickListener() { + @Override + public void onClick(View v) { + activity.startDownloadable(message); + } + }); + } - private void displayOpenableMessage(ViewHolder viewHolder,final Message message) { - viewHolder.image.setVisibility(View.GONE); + private void displayOpenableMessage(ViewHolder viewHolder, final Message message) { + viewHolder.image.setVisibility(View.GONE); FileParams fileParams = message.getFileParams(); String btnText; @@ -440,43 +472,45 @@ public class MessageAdapter extends ArrayAdapter { } this.displayDownloadButton(viewHolder, btnText, new OnClickListener() { + @Override + public void onClick(View v) { + openDownloadable(message); + } + }); + + } + + private void displayLocationMessage(ViewHolder viewHolder, final Message message) { + viewHolder.image.setVisibility(View.GONE); + viewHolder.messageBody.setVisibility(View.GONE); + viewHolder.download_button.setVisibility(View.VISIBLE); + viewHolder.download_button.setText(R.string.show_location); + viewHolder.download_button.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + showLocation(message); + } + }); + + viewHolder.download_button.setOnLongClickListener(openContextMenu); + } + + private void displayImageMessage(ViewHolder viewHolder, final Message message) { + if (viewHolder.download_button != null) { + viewHolder.download_button.setVisibility(View.GONE); + } - @Override - public void onClick(View v) { - openDownloadable(message); - } - }); - } - - private void displayLocationMessage(ViewHolder viewHolder, final Message message) { - viewHolder.image.setVisibility(View.GONE); - viewHolder.messageBody.setVisibility(View.GONE); - viewHolder.download_button.setVisibility(View.VISIBLE); - viewHolder.download_button.setText(R.string.show_location); - viewHolder.download_button.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - showLocation(message); - } - }); - } - - private void displayImageMessage(ViewHolder viewHolder, - final Message message) { - if (viewHolder.download_button != null) { - viewHolder.download_button.setVisibility(View.GONE); - } - - ImageUtil.loadBitmap(message, viewHolder.image, viewHolder.messageBody, true); - viewHolder.image.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - openDownloadable(message); - } - }); - } + ImageUtil.loadBitmap(message, viewHolder.image, viewHolder.messageBody, true); + + viewHolder.image.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + openDownloadable(message); + } + }); + + viewHolder.image.setOnLongClickListener(openContextMenu); + } private View displayStatusMessage(final Message message, ViewHolder viewHolder) { if (null != viewHolder) { @@ -491,6 +525,7 @@ public class MessageAdapter extends ArrayAdapter { } viewHolder.status_message.setText(message.getBody()); } + return viewHolder.view; } @@ -500,13 +535,13 @@ public class MessageAdapter extends ArrayAdapter { displayInfoMessage(viewHolder, activity.getString(R.string.checking_remote_filesize)); } else if (MessageUtil.isAttachedFileAnImage(message) && (FileStatus.DOWNLOADED == message.getFileParams().getFileStatus()) - || FileStatus.DELETED == message.getFileParams().getFileStatus() - || FileStatus.DELETING == message.getFileParams().getFileStatus() - || FileStatus.DELETE_FAILED == message.getFileParams().getFileStatus() - || FileStatus.UPLOADED == message.getFileParams().getFileStatus()) { + || FileStatus.DELETED == message.getFileParams().getFileStatus() + || FileStatus.DELETING == message.getFileParams().getFileStatus() + || FileStatus.DELETE_FAILED == message.getFileParams().getFileStatus() + || FileStatus.UPLOADED == message.getFileParams().getFileStatus()) { displayImageMessage(viewHolder, message); } else if ((MessageUtil.isTypeFileAndDecrypted(message) || FileStatus.DOWNLOADED == message.getFileParams().getFileStatus()) - && !MessageUtil.needsDownload(message)) { + && !MessageUtil.needsDownload(message)) { displayOpenableMessage(viewHolder, message); } else if (Message.Decision.NEVER == message.treatAsDownloadable() || !MessageUtil.mayFileRemoteAvailable(message)) { displayTextMessage(viewHolder, message); @@ -558,10 +593,11 @@ public class MessageAdapter extends ArrayAdapter { } private void displayAvatar(final Message message, int type, ViewHolder viewHolder) { - if (type == RECEIVED) { + if (type == ME_COMMAND || (type == RECEIVED)) { // && message.getConversation().getMode() == Conversation.MODE_MULTI ImageView imageView = viewHolder.contact_picture; if (null != imageView) { this.loadAvatar(message, imageView); + imageView.setOnClickListener(new OnClickListener() { @Override @@ -605,6 +641,9 @@ public class MessageAdapter extends ArrayAdapter { case STATUS: viewResId = R.layout.message_status; break; + case ME_COMMAND: + viewResId = R.layout.message_mecmd; + break; } return activity.getLayoutInflater().inflate(viewResId, parent, false); @@ -614,7 +653,8 @@ public class MessageAdapter extends ArrayAdapter { View view = initializeView(type, parent); ViewHolder viewHolder = new ViewHolder(view); if (SENT == type - || RECEIVED == type) { + || RECEIVED == type + || ME_COMMAND == type) { viewHolder.message_box = ViewUtil.visible(view, R.id.message_box); viewHolder.indicator = (ImageView) view.findViewById(R.id.security_indicator); viewHolder.messageBody = (TextView) view.findViewById(R.id.message_body); @@ -626,7 +666,8 @@ public class MessageAdapter extends ArrayAdapter { viewHolder.download_button = (Button) view.findViewById(R.id.download_button); viewHolder.image = (ImageView) view.findViewById(R.id.message_image); } - if (RECEIVED == type) { // Extra block as preparation for new /me representation + if (ME_COMMAND == type + || (RECEIVED == type)) { // && message.getConversation().getMode() == Conversation.MODE_MULTI --> only muc received msgs viewHolder.contact_picture = ViewUtil.visible(view, R.id.message_photo); } if (RECEIVED == type) { @@ -644,13 +685,13 @@ public class MessageAdapter extends ArrayAdapter { return viewHolder; } - @Override - public View getView(int position, View view, ViewGroup parent) { - final Message message = getItem(position); - final boolean isInValidSession = message.isValidInSession(); - final Conversation conversation = message.getConversation(); - final Account account = conversation.getAccount(); - final int type = getItemViewType(position); + @Override + public View getView(int position, View view, ViewGroup parent) { + final Message message = getItem(position); + final boolean isInValidSession = message.isValidInSession(); + final Conversation conversation = message.getConversation(); + final Account account = conversation.getAccount(); + final int type = getItemViewType(position); ViewHolder viewHolder; if (null == view) { viewHolder = initializeViewHolderAndView(message, type, parent); @@ -668,7 +709,7 @@ public class MessageAdapter extends ArrayAdapter { this.displayAvatar(message, type, viewHolder); - viewHolder.darkBackground = (type == RECEIVED && !isInValidSession); + viewHolder.darkBackground = (type == RECEIVED && !isInValidSession); this.displayStatus(viewHolder, message, type); if (null != message.getTransferable() || message.hasFileAttached()) { @@ -691,9 +732,7 @@ public class MessageAdapter extends ArrayAdapter { } else { displayInfoMessage(viewHolder, activity.getString(R.string.install_openkeychain)); if (viewHolder != null) { - viewHolder.message_box - .setOnClickListener(new OnClickListener() { - + viewHolder.message_box.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { activity.showInstallPgpDialog(); @@ -707,163 +746,164 @@ public class MessageAdapter extends ArrayAdapter { displayTextMessage(viewHolder, message); } - if (type == RECEIVED) { - if(isInValidSession) { - viewHolder.encryption.setVisibility(View.GONE); - } else { - viewHolder.message_box.setBackgroundResource(R.drawable.message_bubble_received_warning); - viewHolder.encryption.setVisibility(View.VISIBLE); - viewHolder.encryption.setText(CryptoHelper.encryptionTypeToText(message.getEncryption())); - } - } - - return view; - } - - public void openDownloadable(Message message) { - DownloadableFile file = FileBackend.getFile(message); - if (!file.exists()) { - Toast.makeText(activity,R.string.file_deleted,Toast.LENGTH_SHORT).show(); - return; - } - boolean bInPrivateStorage = false; - if (file.getAbsolutePath().startsWith(FileBackend.getPrivateFileDirectoryPath())) { - bInPrivateStorage = true; - } - Intent openIntent = new Intent(Intent.ACTION_VIEW); - String mime = file.getMimeType(); - if (mime == null) { - mime = "*/*"; - } - Uri uri; - if (bInPrivateStorage) { - uri = ConversationsPlusFileProvider.createUriForPrivateFile(file); - } else { - uri = Uri.fromFile(file); - } - openIntent.setDataAndType(uri, mime); - PackageManager manager = activity.getPackageManager(); - List infos = manager.queryIntentActivities(openIntent, 0); - if (bInPrivateStorage) { - for (ResolveInfo info : infos) { - ConversationsPlusApplication.getAppContext().grantUriPermission(info.activityInfo.packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); - } - } - if (infos.size() == 0) { - openIntent.setDataAndType(uri,"*/*"); - } - if (bInPrivateStorage) { - openIntent.putExtra(Intent.EXTRA_STREAM, uri); - openIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - } - try { - getContext().startActivity(openIntent); - return; - } catch (ActivityNotFoundException e) { - //ignored - } - Toast.makeText(activity,R.string.no_application_found_to_open_file,Toast.LENGTH_SHORT).show(); - } - - public void showLocation(Message message) { - for(Intent intent : GeoHelper.createGeoIntentsFromMessage(message)) { - if (intent.resolveActivity(getContext().getPackageManager()) != null) { - getContext().startActivity(intent); - return; - } - } - Toast.makeText(activity,R.string.no_application_found_to_display_location,Toast.LENGTH_SHORT).show(); - } - - public interface OnContactPictureClicked { - void onContactPictureClicked(Message message); - } - - public interface OnContactPictureLongClicked { - void onContactPictureLongClicked(Message message); - } - - private static class ViewHolder { + if (type == RECEIVED) { + if (isInValidSession) { + viewHolder.encryption.setVisibility(View.GONE); + } else { + viewHolder.message_box.setBackgroundResource(R.drawable.message_bubble_received_warning); + viewHolder.encryption.setVisibility(View.VISIBLE); + viewHolder.encryption.setText(CryptoHelper.encryptionTypeToText(message.getEncryption())); + } + } + + return view; + } + + public void openDownloadable(Message message) { + DownloadableFile file = FileBackend.getFile(message); + if (!file.exists()) { + Toast.makeText(activity, R.string.file_deleted, Toast.LENGTH_SHORT).show(); + return; + } + boolean bInPrivateStorage = false; + if (file.getAbsolutePath().startsWith(FileBackend.getPrivateFileDirectoryPath())) { + bInPrivateStorage = true; + } + Intent openIntent = new Intent(Intent.ACTION_VIEW); + String mime = file.getMimeType(); + if (mime == null) { + mime = "*/*"; + } + Uri uri; + if (bInPrivateStorage) { + uri = ConversationsPlusFileProvider.createUriForPrivateFile(file); + } else { + uri = Uri.fromFile(file); + } + openIntent.setDataAndType(uri, mime); + PackageManager manager = activity.getPackageManager(); + List infos = manager.queryIntentActivities(openIntent, 0); + if (bInPrivateStorage) { + for (ResolveInfo info : infos) { + ConversationsPlusApplication.getAppContext().grantUriPermission(info.activityInfo.packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); + } + } + if (infos.size() == 0) { + openIntent.setDataAndType(uri, "*/*"); + } + if (bInPrivateStorage) { + openIntent.putExtra(Intent.EXTRA_STREAM, uri); + openIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + } + try { + getContext().startActivity(openIntent); + return; + } catch (ActivityNotFoundException e) { + //ignored + } + Toast.makeText(activity, R.string.no_application_found_to_open_file, Toast.LENGTH_SHORT).show(); + } + + public void showLocation(Message message) { + for (Intent intent : GeoHelper.createGeoIntentsFromMessage(message)) { + if (intent.resolveActivity(getContext().getPackageManager()) != null) { + getContext().startActivity(intent); + return; + } + } + Toast.makeText(activity, R.string.no_application_found_to_display_location, Toast.LENGTH_SHORT).show(); + } + + public interface OnContactPictureClicked { + void onContactPictureClicked(Message message); + } + + public interface OnContactPictureLongClicked { + void onContactPictureLongClicked(Message message); + } + + private static class ViewHolder { protected ViewHolder(View view) { this.view = view; } + protected View view; - protected LinearLayout message_box; - protected Button download_button; - protected ImageView image; - protected ImageView indicator; - protected ImageView indicatorReceived; - protected TextView time; - protected TextView messageBody; - protected ImageView contact_picture; - protected TextView status_message; - protected TextView encryption; + protected LinearLayout message_box; + protected Button download_button; + protected ImageView image; + protected ImageView indicator; + protected ImageView indicatorReceived; + protected TextView time; + protected TextView messageBody; + protected ImageView contact_picture; + protected TextView status_message; + protected TextView encryption; public TextView remoteFileStatus; protected boolean darkBackground; } - class BitmapWorkerTask extends AsyncTask { - private final WeakReference imageViewReference; - private Message message = null; + class BitmapWorkerTask extends AsyncTask { + private final WeakReference imageViewReference; + private Message message = null; - public BitmapWorkerTask(ImageView imageView) { - imageViewReference = new WeakReference<>(imageView); - } + public BitmapWorkerTask(ImageView imageView) { + imageViewReference = new WeakReference<>(imageView); + } - @Override - protected Bitmap doInBackground(Message... params) { + @Override + protected Bitmap doInBackground(Message... params) { int avatarPixel = activity.getResources().getDimensionPixelOffset(R.dimen.msg_avatar_size); - return AvatarService.getInstance().get(params[0], avatarPixel, isCancelled()); - } - - @Override - protected void onPostExecute(Bitmap bitmap) { - if (bitmap != null) { - final ImageView imageView = imageViewReference.get(); - if (imageView != null) { - imageView.setImageBitmap(bitmap); - imageView.setBackgroundColor(0x00000000); - } - } - } - } - - public static boolean cancelPotentialWork(Message message, ImageView imageView) { - final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); - - if (bitmapWorkerTask != null) { - final Message oldMessage = bitmapWorkerTask.message; - if (oldMessage == null || message != oldMessage) { - bitmapWorkerTask.cancel(true); - } else { - return false; - } - } - return true; - } - - private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) { - if (imageView != null) { - final Drawable drawable = imageView.getDrawable(); - if (drawable instanceof AsyncDrawable) { - final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; - return asyncDrawable.getBitmapWorkerTask(); - } - } - return null; - } - - static class AsyncDrawable extends BitmapDrawable { - private final WeakReference bitmapWorkerTaskReference; - - public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) { - super(res, bitmap); - bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask); - } - - public BitmapWorkerTask getBitmapWorkerTask() { - return bitmapWorkerTaskReference.get(); - } - } -} + return AvatarService.getInstance().get(params[0], avatarPixel, isCancelled()); + } + + @Override + protected void onPostExecute(Bitmap bitmap) { + if (bitmap != null) { + final ImageView imageView = imageViewReference.get(); + if (imageView != null) { + imageView.setImageBitmap(bitmap); + imageView.setBackgroundColor(0x00000000); + } + } + } + } + + public static boolean cancelPotentialWork(Message message, ImageView imageView) { + final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); + + if (bitmapWorkerTask != null) { + final Message oldMessage = bitmapWorkerTask.message; + if (oldMessage == null || message != oldMessage) { + bitmapWorkerTask.cancel(true); + } else { + return false; + } + } + return true; + } + + private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) { + if (imageView != null) { + final Drawable drawable = imageView.getDrawable(); + if (drawable instanceof AsyncDrawable) { + final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; + return asyncDrawable.getBitmapWorkerTask(); + } + } + return null; + } + + static class AsyncDrawable extends BitmapDrawable { + private final WeakReference bitmapWorkerTaskReference; + + public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) { + super(res, bitmap); + bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask); + } + + public BitmapWorkerTask getBitmapWorkerTask() { + return bitmapWorkerTaskReference.get(); + } + } +} \ No newline at end of file diff --git a/src/main/res/drawable/mecmd_message_border.xml b/src/main/res/drawable/mecmd_message_border.xml new file mode 100644 index 00000000..990d0288 --- /dev/null +++ b/src/main/res/drawable/mecmd_message_border.xml @@ -0,0 +1,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/main/res/layout/fragment_conversations_overview.xml b/src/main/res/layout/fragment_conversations_overview.xml index 2223219a..3f50a692 100644 --- a/src/main/res/layout/fragment_conversations_overview.xml +++ b/src/main/res/layout/fragment_conversations_overview.xml @@ -27,4 +27,4 @@ android:orientation="vertical" > - \ No newline at end of file + diff --git a/src/main/res/layout/message_mecmd.xml b/src/main/res/layout/message_mecmd.xml new file mode 100644 index 00000000..4074c5ba --- /dev/null +++ b/src/main/res/layout/message_mecmd.xml @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/res/layout/message_received.xml b/src/main/res/layout/message_received.xml index 029b0d74..906e90bf 100644 --- a/src/main/res/layout/message_received.xml +++ b/src/main/res/layout/message_received.xml @@ -11,13 +11,14 @@ + app:riv_corner_radius="2dp" + android:visibility="gone" /> + android:longClickable="true" + android:visibility="gone"> + android:longClickable="true" + android:visibility="gone"> + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/res/layout/message_status.xml b/src/main/res/layout/message_status.xml index aa02e154..4c1dbbc3 100644 --- a/src/main/res/layout/message_status.xml +++ b/src/main/res/layout/message_status.xml @@ -11,8 +11,8 @@ 240dp 30dp 8dp - 48dp + 18dp + 56dp + @dimen/avatar_size + 24dp + 48dp + 32dp -- cgit v1.2.3