Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/stefan-niedermann/nextcloud-deck.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Niedermann <info@niedermann.it>2020-12-17 14:48:22 +0300
committerNiedermann IT-Dienstleistungen <stefan-niedermann@users.noreply.github.com>2020-12-17 18:14:29 +0300
commit268c106ce811f38f7281ac760d686d8fb1c31a77 (patch)
treeabd3ed4c39c2f77b2f2b3d8d5c78d7de7dfe01cf
parentc6aff34f2e84c6c49f4b4d5dd2cb24950342deef (diff)
Only provide option to insert link when no link is selected
Signed-off-by: Stefan Niedermann <info@niedermann.it>
-rw-r--r--markdown/src/androidTest/java/it/niedermann/android/markdown/MarkwonMarkdownUtilTest.java77
-rw-r--r--markdown/src/main/java/it/niedermann/android/markdown/markwon/MarkwonMarkdownUtil.java24
-rw-r--r--markdown/src/main/java/it/niedermann/android/markdown/markwon/format/ContextBasedRangeFormattingCallback.java15
3 files changed, 90 insertions, 26 deletions
diff --git a/markdown/src/androidTest/java/it/niedermann/android/markdown/MarkwonMarkdownUtilTest.java b/markdown/src/androidTest/java/it/niedermann/android/markdown/MarkwonMarkdownUtilTest.java
index f09c14134..c0e32ea34 100644
--- a/markdown/src/androidTest/java/it/niedermann/android/markdown/MarkwonMarkdownUtilTest.java
+++ b/markdown/src/androidTest/java/it/niedermann/android/markdown/MarkwonMarkdownUtilTest.java
@@ -194,6 +194,38 @@ public class MarkwonMarkdownUtilTest extends TestCase {
// builder = new StringBuilder("Lorem *ipsum* dolor sit amet.");
// assertEquals(17, MarkwonMarkdownUtil.togglePunctuation(builder, 7, 12, "**"));
// assertEquals("Lorem ***ipsum*** dolor sit amet.", builder.toString());
+
+ // Text is not directly surrounded by punctuation but contains it
+
+ // TODO Remove containing punctuation
+// builder = new StringBuilder("Lorem *ipsum* dolor sit amet.");
+// assertEquals(11, MarkwonMarkdownUtil.togglePunctuation(builder, 6, 13, "*"));
+// assertEquals("Lorem ipsum dolor sit amet.", builder.toString());
+
+ // TODO Remove containing punctuation
+// builder = new StringBuilder("Lorem *ipsum* dolor sit amet.");
+// assertEquals(27, MarkwonMarkdownUtil.togglePunctuation(builder, 0, 29, "*"));
+// assertEquals("Lorem ipsum dolor sit amet.", builder.toString());
+
+ // TODO Remove multiple containing punctuations
+// builder = new StringBuilder("Lorem *ipsum* dolor *sit* amet.");
+// assertEquals(27, MarkwonMarkdownUtil.togglePunctuation(builder, 0, 31, "*"));
+// assertEquals("Lorem ipsum dolor sit amet.", builder.toString());
+
+ // TODO Toggle bold to italic
+// builder = new StringBuilder("Lorem **ipsum** dolor sit amet.");
+// assertEquals(29, MarkwonMarkdownUtil.togglePunctuation(builder, 0, 31, "*"));
+// assertEquals("Lorem *ipsum* dolor sit amet.", builder.toString());
+
+ // TODO Toggle multiple bold parts to italic
+// builder = new StringBuilder("Lorem **ipsum** dolor **sit** amet.");
+// assertEquals(31, MarkwonMarkdownUtil.togglePunctuation(builder, 0, 35, "*"));
+// assertEquals("Lorem *ipsum* dolor *sit* amet.", builder.toString());
+
+ // TODO Do nothing
+// builder = new StringBuilder("Lorem *ipsum dolor sit amet.");
+// assertEquals(28, MarkwonMarkdownUtil.togglePunctuation(builder, 0, 28, "*"));
+// assertEquals("Lorem *ipsum dolor sit amet.", builder.toString());
}
@Test
@@ -240,23 +272,40 @@ public class MarkwonMarkdownUtilTest extends TestCase {
}
@Test
- public void testRemoveSurroundingPunctuation() {
+ @SuppressWarnings("ConstantConditions")
+ public void testSelectionIsInLink() {
try {
- final Method m = MarkwonMarkdownUtil.class.getDeclaredMethod("removeSurroundingPunctuation", StringBuilder.class, int.class, int.class, String.class);
+ final Method m = MarkwonMarkdownUtil.class.getDeclaredMethod("selectionIsInLink", CharSequence.class, int.class, int.class);
m.setAccessible(true);
- StringBuilder builder;
-
- builder = new StringBuilder("*Lorem Ipsum*");
- m.invoke(null, builder, 1, 12, "*");
- assertEquals("Lorem Ipsum", builder.toString());
-
- builder = new StringBuilder("**Lorem Ipsum**");
- m.invoke(null, builder, 2, 13, "**");
- assertEquals("Lorem Ipsum", builder.toString());
- builder = new StringBuilder("**Lorem Ipsum**");
- m.invoke(null, builder, 2, 13, "*");
- assertEquals("*Lorem Ipsum*", builder.toString());
+ assertTrue((Boolean) m.invoke(null, "Lorem [ipsum](https://example.com) dolor sit amet.", 7, 12));
+ assertTrue((Boolean) m.invoke(null, "Lorem [ipsum](https://example.com) dolor sit amet.", 6, 34));
+ assertTrue((Boolean) m.invoke(null, "Lorem [ipsum](https://example.com) dolor sit amet.", 14, 33));
+ assertTrue((Boolean) m.invoke(null, "Lorem [ipsum](https://example.com) dolor sit amet.", 12, 14));
+ assertTrue((Boolean) m.invoke(null, "Lorem [ipsum](https://example.com) dolor sit amet.", 0, 7));
+ assertTrue((Boolean) m.invoke(null, "Lorem [ipsum](https://example.com) dolor sit amet.", 33, 34));
+
+ assertTrue((Boolean) m.invoke(null, "Lorem [](https://example.com) dolor sit amet.", 6, 28));
+ assertTrue((Boolean) m.invoke(null, "Lorem [](https://example.com) dolor sit amet.", 7, 28));
+ assertTrue((Boolean) m.invoke(null, "Lorem [](https://example.com) dolor sit amet.", 8, 28));
+ assertTrue((Boolean) m.invoke(null, "Lorem [](https://example.com) dolor sit amet.", 9, 28));
+ assertTrue((Boolean) m.invoke(null, "Lorem [](https://example.com) dolor sit amet.", 6, 29));
+ assertTrue((Boolean) m.invoke(null, "Lorem [](https://example.com) dolor sit amet.", 7, 29));
+ assertTrue((Boolean) m.invoke(null, "Lorem [](https://example.com) dolor sit amet.", 8, 29));
+ assertTrue((Boolean) m.invoke(null, "Lorem [](https://example.com) dolor sit amet.", 9, 29));
+
+ assertTrue((Boolean) m.invoke(null, "Lorem [ipsum]() dolor sit amet.", 6, 12));
+ assertTrue((Boolean) m.invoke(null, "Lorem [ipsum]() dolor sit amet.", 6, 13));
+ assertTrue((Boolean) m.invoke(null, "Lorem [ipsum]() dolor sit amet.", 6, 14));
+ assertTrue((Boolean) m.invoke(null, "Lorem [ipsum]() dolor sit amet.", 6, 15));
+ assertTrue((Boolean) m.invoke(null, "Lorem [ipsum]() dolor sit amet.", 7, 12));
+ assertTrue((Boolean) m.invoke(null, "Lorem [ipsum]() dolor sit amet.", 7, 13));
+ assertTrue((Boolean) m.invoke(null, "Lorem [ipsum]() dolor sit amet.", 7, 14));
+ assertTrue((Boolean) m.invoke(null, "Lorem [ipsum]() dolor sit amet.", 7, 15));
+
+ assertFalse((Boolean) m.invoke(null, "Lorem [ipsum](https://example.com) dolor sit amet.", 0, 6));
+ assertFalse((Boolean) m.invoke(null, "Lorem [ipsum](https://example.com) dolor sit amet.", 34, 50));
+ assertFalse((Boolean) m.invoke(null, "Lorem [ipsum](https://example.com) dolor sit amet.", 41, 44));
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
diff --git a/markdown/src/main/java/it/niedermann/android/markdown/markwon/MarkwonMarkdownUtil.java b/markdown/src/main/java/it/niedermann/android/markdown/markwon/MarkwonMarkdownUtil.java
index d4e388187..fe28ac0b5 100644
--- a/markdown/src/main/java/it/niedermann/android/markdown/markwon/MarkwonMarkdownUtil.java
+++ b/markdown/src/main/java/it/niedermann/android/markdown/markwon/MarkwonMarkdownUtil.java
@@ -8,6 +8,8 @@ import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import io.noties.markwon.Markwon;
import io.noties.markwon.ext.strikethrough.StrikethroughPlugin;
@@ -126,7 +128,8 @@ public class MarkwonMarkdownUtil {
case "~~": {
final boolean selectionIsSurroundedByPunctuation = selectionIsSurroundedByPunctuation(builder.toString(), selectionStart, selectionEnd, punctuation);
if (selectionIsSurroundedByPunctuation) {
- removeSurroundingPunctuation(builder, selectionStart, selectionEnd, punctuation);
+ builder.delete(selectionEnd, selectionEnd + punctuation.length());
+ builder.delete(selectionStart - punctuation.length(), selectionStart);
} else {
builder.insert(selectionEnd, punctuation);
builder.insert(selectionStart, punctuation);
@@ -184,15 +187,14 @@ public class MarkwonMarkdownUtil {
&& punctuation.contentEquals(text.subSequence(end, end + punctuation.length()));
}
- /**
- * Mutates the given {@param builder} and removes the text range from {@param start} to
- * {@param end} and its surrounding {@param punctuation}.
- * Doesn't make any assumptions about the text lengths and will throw a
- * {@link StringIndexOutOfBoundsException} if {@param start}, {@param end} or the
- * {@param punctuation} is out of range of the given {@param builder}.
- */
- private static void removeSurroundingPunctuation(@NonNull StringBuilder builder, int start, int end, @NonNull String punctuation) throws StringIndexOutOfBoundsException {
- builder.delete(end, end + punctuation.length());
- builder.delete(start - punctuation.length(), start);
+ public static boolean selectionIsInLink(@NonNull CharSequence text, int start, int end) {
+ final Pattern pattern = Pattern.compile("\\[(.+)?]\\(([^ ]+?)?( \"(.+)\")?\\)");
+ final Matcher matcher = pattern.matcher(text);
+ while (matcher.find()) {
+ if ((start >= matcher.start() && start < matcher.end()) || (end > matcher.start() && end <= matcher.end())) {
+ return true;
+ }
+ }
+ return false;
}
}
diff --git a/markdown/src/main/java/it/niedermann/android/markdown/markwon/format/ContextBasedRangeFormattingCallback.java b/markdown/src/main/java/it/niedermann/android/markdown/markwon/format/ContextBasedRangeFormattingCallback.java
index 1519341d8..6cca65e43 100644
--- a/markdown/src/main/java/it/niedermann/android/markdown/markwon/format/ContextBasedRangeFormattingCallback.java
+++ b/markdown/src/main/java/it/niedermann/android/markdown/markwon/format/ContextBasedRangeFormattingCallback.java
@@ -4,6 +4,7 @@ import android.graphics.Typeface;
import android.text.Editable;
import android.text.SpannableStringBuilder;
import android.text.style.StyleSpan;
+import android.util.Log;
import android.util.SparseIntArray;
import android.view.ActionMode;
import android.view.Menu;
@@ -49,7 +50,19 @@ public class ContextBasedRangeFormattingCallback implements ActionMode.Callback
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
- // TODO hide actions if not available?
+ final CharSequence text = editText.getText();
+ if (text != null) {
+ final int selectionStart = editText.getSelectionStart();
+ final int selectionEnd = editText.getSelectionEnd();
+ if (selectionStart >= 0 && selectionStart <= text.length()) {
+ if (MarkwonMarkdownUtil.selectionIsInLink(text, selectionStart, selectionEnd)) {
+ menu.findItem(R.id.link).setVisible(false);
+ Log.i(TAG, "Hide link menu item because the selection is already within a link.");
+ }
+ } else {
+ Log.e(TAG, "SelectionStart is " + selectionStart + ". Expected to be between 0 and " + text.length());
+ }
+ }
return false;
}