diff --git a/app/src/androidTest/java/fr/free/nrw/commons/ui/PasteSensitiveTextInputEditTextTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/ui/PasteSensitiveTextInputEditTextTest.kt new file mode 100644 index 000000000..49d26af97 --- /dev/null +++ b/app/src/androidTest/java/fr/free/nrw/commons/ui/PasteSensitiveTextInputEditTextTest.kt @@ -0,0 +1,79 @@ +package fr.free.nrw.commons.ui + +import android.R +import android.content.Context +import android.os.Build +import android.util.AttributeSet +import androidx.test.core.app.ApplicationProvider +import androidx.test.runner.AndroidJUnit4 +import fr.free.nrw.commons.ui.PasteSensitiveTextInputEditText +import org.junit.Assert +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import java.lang.Exception +import kotlin.Throws + +@RunWith(AndroidJUnit4::class) +class PasteSensitiveTextInputEditTextTest { + + private var context: Context? = null + private var textView: PasteSensitiveTextInputEditText? = null + + @Before + fun setup() { + context = ApplicationProvider.getApplicationContext() + textView = PasteSensitiveTextInputEditText(context) + } + + @Test + fun onTextContextMenuItemPasteFormattingDisabled() { + textView!!.setFormattingAllowed(false); + textView!!.setText("Text") + textView!!.onTextContextMenuItem(R.id.paste) + Assert.assertEquals("Text", textView!!.text.toString()) + } + + @Test + fun onTextContextMenuItemPasteFormattingAllowed() { + textView!!.setFormattingAllowed(true); + textView!!.setText("Text") + textView!!.onTextContextMenuItem(R.id.paste) + Assert.assertEquals("Text", textView!!.text.toString()) + } + + @Test + fun onTextContextMenuItemPaste() { + textView!!.setText("Text") + textView!!.onTextContextMenuItem(R.id.paste) + Assert.assertEquals("Text", textView!!.text.toString()) + } + + + @Test + fun onTextContextMenuItemNotPaste() { + textView!!.setText("Text") + textView!!.onTextContextMenuItem(R.id.copy) + Assert.assertEquals("Text", textView!!.text.toString()) + } + + // this test has no real value, just % for test code coverage + @Test + fun extractFormattingAttributeSet(){ + val methodExtractFormattingAttribute = textView!!.javaClass.getDeclaredMethod( + "extractFormattingAttribute", Context::class.java, AttributeSet::class.java) + methodExtractFormattingAttribute.isAccessible = true + methodExtractFormattingAttribute.invoke(textView, context, null) + } + + @Test + @Throws(Exception::class) + fun setFormattingAllowed() { + val fieldFormattingAllowed = textView!!.javaClass.getDeclaredField("formattingAllowed") + fieldFormattingAllowed.isAccessible = true + textView!!.setFormattingAllowed(true) + Assert.assertTrue(fieldFormattingAllowed.getBoolean(textView)) + textView!!.setFormattingAllowed(false) + Assert.assertFalse(fieldFormattingAllowed.getBoolean(textView)) + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/ui/PasteSensitiveTextInputEditText.java b/app/src/main/java/fr/free/nrw/commons/ui/PasteSensitiveTextInputEditText.java new file mode 100644 index 000000000..bde665632 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/ui/PasteSensitiveTextInputEditText.java @@ -0,0 +1,67 @@ +package fr.free.nrw.commons.ui; + +import android.content.Context; +import android.content.res.TypedArray; +import android.os.Build; +import android.os.Build.VERSION; +import android.util.AttributeSet; +import android.util.Log; +import com.google.android.material.textfield.TextInputEditText; +import fr.free.nrw.commons.R; + +public class PasteSensitiveTextInputEditText extends TextInputEditText { + + private boolean formattingAllowed = true; + + public PasteSensitiveTextInputEditText(final Context context) { + super(context); + } + + public PasteSensitiveTextInputEditText(final Context context, final AttributeSet attrs) { + super(context, attrs); + formattingAllowed = extractFormattingAttribute(context, attrs); + } + + @Override + public boolean onTextContextMenuItem(int id) { + + // if not paste command, or formatting is allowed, return default + if(id != android.R.id.paste || formattingAllowed){ + return super.onTextContextMenuItem(id); + } + + // if its paste and formatting not allowed + boolean proceeded; + if(VERSION.SDK_INT >= 23) { + proceeded = super.onTextContextMenuItem(android.R.id.pasteAsPlainText); + }else { + proceeded = super.onTextContextMenuItem(id); + if (proceeded && getText() != null) { + // rewrite with plain text so formatting is lost + setText(getText().toString()); + setSelection(getText().length()); + } + } + return proceeded; + } + + private boolean extractFormattingAttribute(Context context, AttributeSet attrs){ + + boolean formatAllowed = true; + + TypedArray a = context.getTheme().obtainStyledAttributes( + attrs, R.styleable.PasteSensitiveTextInputEditText, 0, 0); + + try { + formatAllowed = a.getBoolean( + R.styleable.PasteSensitiveTextInputEditText_allowFormatting, true); + } finally { + a.recycle(); + } + return formatAllowed; + } + + public void setFormattingAllowed(boolean formattingAllowed){ + this.formattingAllowed = formattingAllowed; + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetailAdapter.java b/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetailAdapter.java index cb51ac4ff..0eff105e8 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetailAdapter.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetailAdapter.java @@ -10,14 +10,12 @@ import android.widget.ImageView; import android.widget.Spinner; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.appcompat.widget.AppCompatEditText; -import androidx.appcompat.widget.AppCompatSpinner; import androidx.recyclerview.widget.RecyclerView; import butterknife.BindView; import butterknife.ButterKnife; -import com.google.android.material.textfield.TextInputEditText; import com.google.android.material.textfield.TextInputLayout; import fr.free.nrw.commons.R; +import fr.free.nrw.commons.ui.PasteSensitiveTextInputEditText; import fr.free.nrw.commons.utils.AbstractTextWatcher; import java.util.ArrayList; import java.util.HashMap; @@ -93,13 +91,13 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter - + android:inputType="textMultiLine" + app:allowFormatting="false" /> - + android:inputType="textMultiLine" + app:allowFormatting="false" /> diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index f43772fb5..ea801637b 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -57,4 +57,8 @@ + + + +