Merge branch 'feature-remove-spans' of https://github.com/Mishiranu/Conversations into Mishiranu-feature-remove-spans

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/ui/EditMessage.java            | 36 
src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java | 19 
src/main/java/eu/siacs/conversations/ui/widget/CopyTextView.java    | 66 
src/main/res/layout/message_received.xml                            |  2 
src/main/res/layout/message_sent.xml                                |  2 
5 files changed, 118 insertions(+), 7 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/ui/EditMessage.java 🔗

@@ -1,7 +1,11 @@
 package eu.siacs.conversations.ui;
 
 import android.content.Context;
+import android.os.Build;
 import android.os.Handler;
+import android.text.Editable;
+import android.text.InputFilter;
+import android.text.Spanned;
 import android.util.AttributeSet;
 import android.view.KeyEvent;
 import android.widget.EditText;
@@ -89,4 +93,36 @@ public class EditMessage extends EditText {
 		boolean onTabPressed(boolean repeated);
 	}
 
+	private static final InputFilter SPAN_FILTER = new InputFilter() {
+
+		@Override
+		public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
+			return source instanceof Spanned ? source.toString() : source;
+		}
+	};
+
+	@Override
+	public boolean onTextContextMenuItem(int id) {
+		if (id == android.R.id.paste) {
+			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+				return super.onTextContextMenuItem(android.R.id.pasteAsPlainText);
+			} else {
+				Editable editable = getEditableText();
+				InputFilter[] filters = editable.getFilters();
+				InputFilter[] tempFilters = new InputFilter[filters != null ? filters.length + 1 : 1];
+				if (filters != null) {
+					System.arraycopy(filters, 0, tempFilters, 1, filters.length);
+				}
+				tempFilters[0] = SPAN_FILTER;
+				editable.setFilters(tempFilters);
+				try {
+					return super.onTextContextMenuItem(id);
+				} finally {
+					editable.setFilters(filters);
+				}
+			}
+		} else {
+			return super.onTextContextMenuItem(id);
+		}
+	}
 }

src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java 🔗

@@ -54,12 +54,13 @@ import eu.siacs.conversations.entities.Transferable;
 import eu.siacs.conversations.persistance.FileBackend;
 import eu.siacs.conversations.ui.ConversationActivity;
 import eu.siacs.conversations.ui.widget.ClickableMovementMethod;
+import eu.siacs.conversations.ui.widget.CopyTextView;
 import eu.siacs.conversations.ui.widget.ListSelectionManager;
 import eu.siacs.conversations.utils.CryptoHelper;
 import eu.siacs.conversations.utils.GeoHelper;
 import eu.siacs.conversations.utils.UIHelper;
 
-public class MessageAdapter extends ArrayAdapter<Message> {
+public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextView.CopyHandler {
 
 	private static final int SENT = 0;
 	private static final int RECEIVED = 1;
@@ -487,7 +488,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 					viewHolder.edit_indicator = (ImageView) view.findViewById(R.id.edit_indicator);
 					viewHolder.image = (ImageView) view
 						.findViewById(R.id.message_image);
-					viewHolder.messageBody = (TextView) view
+					viewHolder.messageBody = (CopyTextView) view
 						.findViewById(R.id.message_body);
 					viewHolder.time = (TextView) view
 						.findViewById(R.id.message_time);
@@ -508,7 +509,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 					viewHolder.edit_indicator = (ImageView) view.findViewById(R.id.edit_indicator);
 					viewHolder.image = (ImageView) view
 						.findViewById(R.id.message_image);
-					viewHolder.messageBody = (TextView) view
+					viewHolder.messageBody = (CopyTextView) view
 						.findViewById(R.id.message_body);
 					viewHolder.time = (TextView) view
 						.findViewById(R.id.message_time);
@@ -526,7 +527,10 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 					viewHolder = null;
 					break;
 			}
-			if (viewHolder.messageBody != null) listSelectionManager.onCreate(viewHolder.messageBody);
+			if (viewHolder.messageBody != null) {
+				listSelectionManager.onCreate(viewHolder.messageBody);
+				viewHolder.messageBody.setCopyHandler(this);
+			}
 			view.setTag(viewHolder);
 		} else {
 			viewHolder = (ViewHolder) view.getTag();
@@ -684,6 +688,11 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 		listSelectionManager.onAfterNotifyDataSetChanged();
 	}
 
+	@Override
+	public String transformTextForCopy(CharSequence text, int start, int end) {
+		return text.toString().substring(start, end);
+	}
+
 	public void openDownloadable(Message message) {
 		DownloadableFile file = activity.xmppConnectionService.getFileBackend().getFile(message);
 		if (!file.exists()) {
@@ -761,7 +770,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 		protected ImageView indicator;
 		protected ImageView indicatorReceived;
 		protected TextView time;
-		protected TextView messageBody;
+		protected CopyTextView messageBody;
 		protected ImageView contact_picture;
 		protected TextView status_message;
 		protected TextView encryption;

src/main/java/eu/siacs/conversations/ui/widget/CopyTextView.java 🔗

@@ -0,0 +1,66 @@
+package eu.siacs.conversations.ui.widget;
+
+import android.annotation.TargetApi;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+public class CopyTextView extends TextView {
+
+	public CopyTextView(Context context) {
+		super(context);
+	}
+
+	public CopyTextView(Context context, AttributeSet attrs) {
+		super(context, attrs);
+	}
+
+	public CopyTextView(Context context, AttributeSet attrs, int defStyleAttr) {
+		super(context, attrs, defStyleAttr);
+	}
+
+	@SuppressWarnings("unused")
+	@TargetApi(Build.VERSION_CODES.LOLLIPOP)
+	public CopyTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+		super(context, attrs, defStyleAttr, defStyleRes);
+	}
+
+	public interface CopyHandler {
+		public String transformTextForCopy(CharSequence text, int start, int end);
+	}
+
+	private CopyHandler copyHandler;
+
+	public void setCopyHandler(CopyHandler copyHandler) {
+		this.copyHandler = copyHandler;
+	}
+
+	@Override
+	public boolean onTextContextMenuItem(int id) {
+		CharSequence text = getText();
+		int min = 0;
+		int max = text.length();
+		if (isFocused()) {
+			final int selStart = getSelectionStart();
+			final int selEnd = getSelectionEnd();
+			min = Math.max(0, Math.min(selStart, selEnd));
+			max = Math.max(0, Math.max(selStart, selEnd));
+		}
+		String textForCopy = null;
+		if (id == android.R.id.copy && copyHandler != null) {
+			textForCopy = copyHandler.transformTextForCopy(getText(), min, max);
+		}
+		try {
+			return super.onTextContextMenuItem(id);
+		} finally {
+			if (textForCopy != null) {
+				ClipboardManager clipboard = (ClipboardManager) getContext().
+						getSystemService(Context.CLIPBOARD_SERVICE);
+				clipboard.setPrimaryClip(ClipData.newPlainText(null, textForCopy));
+			}
+		}
+	}
+}

src/main/res/layout/message_received.xml 🔗

@@ -49,7 +49,7 @@
                 android:background="@color/black87"
                 android:scaleType="centerCrop" />
 
-            <TextView
+            <eu.siacs.conversations.ui.widget.CopyTextView
                 android:id="@+id/message_body"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"

src/main/res/layout/message_sent.xml 🔗

@@ -50,7 +50,7 @@
                 android:longClickable="true"
                 android:scaleType="centerCrop" />
 
-            <TextView
+            <eu.siacs.conversations.ui.widget.CopyTextView
                 android:id="@+id/message_body"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"