aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerParserPlugin.java118
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/post/ParsePost.java2
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java49
3 files changed, 72 insertions, 97 deletions
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerParserPlugin.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerParserPlugin.java
index 1cca0cfe..3a05b71c 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerParserPlugin.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerParserPlugin.java
@@ -3,6 +3,7 @@ package ml.docilealligator.infinityforreddit.markdown;
import android.graphics.Color;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
+import android.util.Pair;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -13,8 +14,7 @@ import org.commonmark.node.HtmlBlock;
import org.commonmark.node.HtmlInline;
import org.commonmark.parser.Parser;
-import java.util.LinkedHashMap;
-import java.util.Map;
+import java.util.ArrayList;
import java.util.Set;
import java.util.Stack;
@@ -52,21 +52,21 @@ public class SpoilerParserPlugin extends AbstractMarkwonPlugin {
public void afterSetText(@NonNull TextView textView) {
textView.setHighlightColor(Color.TRANSPARENT);
- if(textView.getText().length() < 5) {
+ if (textView.getText().length() < 5) {
return;
}
SpannableStringBuilder markdownStringBuilder = new SpannableStringBuilder(textView.getText());
- LinkedHashMap<Integer, Integer> spoilers = parse(markdownStringBuilder);
- if(spoilers.size() == 0) {
+ ArrayList<Pair<Integer, Integer>> spoilers = parse(markdownStringBuilder);
+ if (spoilers.size() == 0) {
return;
}
- int offset = 2;
- for (Map.Entry<Integer, Integer> entry : spoilers.entrySet()) {
- int spoilerStart = entry.getKey() - offset;
- int spoilerEnd = entry.getValue() - offset;
+ int offset = 2;
+ for (Pair<Integer, Integer> spoiler : spoilers) {
+ int spoilerStart = spoiler.first - offset;
+ int spoilerEnd = spoiler.second - offset;
// Try not to set a spoiler span if it's inside a CodeSpan
CodeSpan[] codeSpans = markdownStringBuilder.getSpans(spoilerStart, spoilerEnd, CodeSpan.class);
@@ -78,6 +78,7 @@ public class SpoilerParserPlugin extends AbstractMarkwonPlugin {
SpoilerSpan spoilerSpan = new SpoilerSpan(textColor, backgroundColor);
markdownStringBuilder.setSpan(spoilerSpan, spoilerStart, spoilerEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
offset += 4;
+ continue;
}
for (CodeSpan codeSpan : codeSpans) {
@@ -108,7 +109,7 @@ public class SpoilerParserPlugin extends AbstractMarkwonPlugin {
}
}
}
- if(offset > 2) {
+ if (offset > 2) {
textView.setText(markdownStringBuilder);
}
}
@@ -117,86 +118,45 @@ public class SpoilerParserPlugin extends AbstractMarkwonPlugin {
// Don't allow more than one new line after every non-blank line
// Try not to care about recursing spoilers, we just want the outermost spoiler because
// spoiler revealing-hiding breaks with recursing spoilers
- private LinkedHashMap<Integer, Integer> parse(SpannableStringBuilder markdown) {
+ private ArrayList<Pair<Integer, Integer>> parse(SpannableStringBuilder markdown) {
final int MAX_NEW_LINE = 1;
- var openSpoilerStack = new Stack<Integer>();
- var closedSpoilerMap = new LinkedHashMap<Integer, Integer>();
- int variable_max_depth = calculateBalance(0, markdown) + 1;
+ int length = markdown.length();
+ Stack<Integer> openSpoilerStack = new Stack<>();
+ ArrayList<Pair<Integer, Integer>> closedSpoilers = new ArrayList<>();
int new_lines = 0;
- int depth = 0;
- for (int i = 0; i < markdown.length(); i++) {
- if (markdown.charAt(i) == '\u2000' || markdown.charAt(i) == '\t') {
- continue;
- } else if (markdown.charAt(i) == '>' && (i + 1) < markdown.length() && markdown.charAt(i + 1) == '!') {
- openSpoilerStack.push(i + 1);
- depth++;
- } else if (openSpoilerStack.size() > 0
- && markdown.charAt(i) == '!' && (i + 1) < markdown.length()
- && markdown.charAt(i + 1) == '<') {
- var pos = i + 1;
- for (int j = 0; j < depth; j++) {
- if (!openSpoilerStack.isEmpty()) pos = openSpoilerStack.peek();
- if (pos + 1 <= i) {
- if (!openSpoilerStack.isEmpty()) pos = openSpoilerStack.peek();
- break;
- } else {
- if (!openSpoilerStack.isEmpty()) pos = openSpoilerStack.pop();
- }
- }
- if (depth <= variable_max_depth && pos + 1 <= i) //Spoiler content cannot be zero or less length
- {
- openSpoilerStack.clear();
- closedSpoilerMap.put(pos + 1, i);
- }
- depth--;
- } else if (markdown.charAt(i) == '\n') {
+ for (int i = 0; i < length; i++) {
+ if (markdown.charAt(i) == '\n') {
new_lines++;
- if (openSpoilerStack.size() >= 1 && new_lines > MAX_NEW_LINE) {
+ if (new_lines > MAX_NEW_LINE) {
openSpoilerStack.clear();
new_lines = 0;
- depth = 0;
- variable_max_depth = calculateBalance(i, markdown) + 1;
}
- } else {
+ } else if ((markdown.charAt(i) != '>')
+ && (markdown.charAt(i) != '<')
+ && (markdown.charAt(i) != '!')) {
new_lines = 0;
- }
-
- if (openSpoilerStack.size() >= 32) // No
- {
- openSpoilerStack.clear();
- closedSpoilerMap.clear();
- continue;
- }
- }
- return closedSpoilerMap;
- }
-
- private int calculateBalance(int index, SpannableStringBuilder line) {
- final int MAX_NEW_LINE = 1;
- int new_lines = 0;
- int opening = 0;
- int closing = 0;
- for (int i = index; i < line.length(); i++) {
- if (line.charAt(i) == '\u0020' || line.charAt(i) == '\t') {
- continue;
- } else if (line.charAt(i) == '>'
- && (i + 1) < line.length()
- && line.charAt(i + 1) == '!') {
- opening++;
- } else if (line.charAt(i) == '!' && (i + 1) < line.length()
- && line.charAt(i + 1) == '<') {
- closing++;
- } else if (line.charAt(i) == '\n') {
- new_lines++;
- if (new_lines > MAX_NEW_LINE) {
- break;
+ } else if ((i + 1 < length)
+ && markdown.charAt(i) == '>'
+ && markdown.charAt(i + 1) == '!') {
+ openSpoilerStack.push(i + 2);
+ } else if ((i + 1 < length) && (i - 1 >= 0)
+ && openSpoilerStack.size() > 0
+ && markdown.charAt(i - 1) != '>'
+ && markdown.charAt(i) == '!'
+ && markdown.charAt(i + 1) == '<') {
+ var pos = openSpoilerStack.pop();
+ if (!closedSpoilers.isEmpty()
+ && closedSpoilers.get(closedSpoilers.size() - 1).first > pos
+ && closedSpoilers.get(closedSpoilers.size() - 1).second < i) {
+ closedSpoilers.remove(closedSpoilers.size() - 1);
+ }
+ if (pos != i) {
+ closedSpoilers.add(Pair.create(pos, i));
}
} else {
new_lines = 0;
- continue;
}
}
- return Math.abs(opening - closing);
+ return closedSpoilers;
}
-
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/post/ParsePost.java b/app/src/main/java/ml/docilealligator/infinityforreddit/post/ParsePost.java
index 0685170a..834db92f 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/post/ParsePost.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/post/ParsePost.java
@@ -541,7 +541,7 @@ public class ParsePost {
}
} catch (IllegalArgumentException ignore) { }
} else if (post.getPostType() == Post.LINK_TYPE || post.getPostType() == Post.NO_PREVIEW_LINK_TYPE) {
- if (data.has(JSONUtils.GALLERY_DATA_KEY)) {
+ if (!data.isNull(JSONUtils.GALLERY_DATA_KEY)) {
JSONArray galleryIdsArray = data.getJSONObject(JSONUtils.GALLERY_DATA_KEY).getJSONArray(JSONUtils.ITEMS_KEY);
JSONObject galleryObject = data.getJSONObject(JSONUtils.MEDIA_METADATA_KEY);
ArrayList<Post.Gallery> gallery = new ArrayList<>();
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java
index e7ee8d6a..41bb5e98 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java
@@ -49,7 +49,7 @@ import ml.docilealligator.infinityforreddit.SortType;
import ml.docilealligator.infinityforreddit.UploadedImage;
import retrofit2.Retrofit;
-public class Utils {
+public final class Utils {
public static final int NETWORK_TYPE_OTHER = -1;
public static final int NETWORK_TYPE_WIFI = 0;
public static final int NETWORK_TYPE_CELLULAR = 1;
@@ -60,21 +60,36 @@ public class Utils {
private static final long MONTH_MILLIS = 30 * DAY_MILLIS;
private static final long YEAR_MILLIS = 12 * MONTH_MILLIS;
+ public static final Pattern[] REGEX_PATTERN = {
+ Pattern.compile("((?<=[\\s])|^)/[rRuU]/[\\w-]+/{0,1}"),
+ Pattern.compile("((?<=[\\s])|^)[rRuU]/[\\w-]+/{0,1}"),
+ Pattern.compile("\\^{2,}"),
+ Pattern.compile("(^|^ *|\\n *)#(?!($|\\s|#))"),
+ Pattern.compile("(^|^ *|\\n *)##(?!($|\\s|#))"),
+ Pattern.compile("(^|^ *|\\n *)###(?!($|\\s|#))"),
+ Pattern.compile("(^|^ *|\\n *)####(?!($|\\s|#))"),
+ Pattern.compile("(^|^ *|\\n *)#####(?!($|\\s|#))"),
+ Pattern.compile("(^|^ *|\\n *)######(?!($|\\s|#))"),
+ Pattern.compile("!\\[gif]\\(giphy\\|\\w+\\)"),
+ Pattern.compile("!\\[gif]\\(giphy\\|\\w+\\|downsized\\)"),
+ Pattern.compile("!\\[gif]\\(emote\\|\\w+\\|\\w+\\)"),
+ Pattern.compile("!\\[img]\\(emote\\|\\w+\\|\\w+\\)")
+ };
+
public static String modifyMarkdown(String markdown) {
- StringBuilder regexed = new StringBuilder(markdown
- .replaceAll("((?<=[\\s])|^)/[rRuU]/[\\w-]+/{0,1}", "[$0](https://www.reddit.com$0)")
- .replaceAll("((?<=[\\s])|^)[rRuU]/[\\w-]+/{0,1}", "[$0](https://www.reddit.com/$0)")
- .replaceAll("\\^{2,}", "^")
- .replaceAll("(^|^ *|\\n *)#(?!($|\\s|#))", "$0 ")
- .replaceAll("(^|^ *|\\n *)##(?!($|\\s|#))", "$0 ")
- .replaceAll("(^|^ *|\\n *)###(?!($|\\s|#))", "$0 ")
- .replaceAll("(^|^ *|\\n *)####(?!($|\\s|#))", "$0 ")
- .replaceAll("(^|^ *|\\n *)#####(?!($|\\s|#))", "$0 ")
- .replaceAll("(^|^ *|\\n *)######(?!($|\\s|#))", "$0 "));
+ String regexed = REGEX_PATTERN[0].matcher(markdown).replaceAll("[$0](https://www.reddit.com$0)");
+ regexed = REGEX_PATTERN[1].matcher(regexed).replaceAll("[$0](https://www.reddit.com/$0)");
+ regexed = REGEX_PATTERN[2].matcher(regexed).replaceAll("^");
+ regexed = REGEX_PATTERN[3].matcher(regexed).replaceAll("$0");
+ regexed = REGEX_PATTERN[4].matcher(regexed).replaceAll("$0");
+ regexed = REGEX_PATTERN[5].matcher(regexed).replaceAll("$0");
+ regexed = REGEX_PATTERN[6].matcher(regexed).replaceAll("$0");
+ regexed = REGEX_PATTERN[7].matcher(regexed).replaceAll("$0");
+ regexed = REGEX_PATTERN[8].matcher(regexed).replaceAll("$0");
//return fixSuperScript(regexed);
// We don't want to fix super scripts here because we need the original markdown later for editing posts
- return regexed.toString();
+ return regexed;
}
public static String fixSuperScript(String regexedMarkdown) {
@@ -121,21 +136,21 @@ public class Utils {
public static String parseInlineGifInComments(String markdown) {
StringBuilder markdownStringBuilder = new StringBuilder(markdown);
- Pattern inlineGifPattern = Pattern.compile("!\\[gif]\\(giphy\\|\\w+\\)");
+ Pattern inlineGifPattern = REGEX_PATTERN[9];
Matcher matcher = inlineGifPattern.matcher(markdownStringBuilder);
while (matcher.find()) {
- markdownStringBuilder.replace(matcher.start(), matcher.end(), "[gif](https://media3.giphy.com/media/" + markdownStringBuilder.substring(matcher.start() + "![gif](giphy|".length(), matcher.end() - 1) + "/giphy.mp4)");
+ markdownStringBuilder.replace(matcher.start(), matcher.end(), "[gif](https://i.giphy.com/media/" + markdownStringBuilder.substring(matcher.start() + "![gif](giphy|".length(), matcher.end() - 1) + "/giphy.mp4)");
matcher = inlineGifPattern.matcher(markdownStringBuilder);
}
- Pattern inlineGifPattern2 = Pattern.compile("!\\[gif]\\(giphy\\|\\w+\\|downsized\\)");
+ Pattern inlineGifPattern2 = REGEX_PATTERN[10];
Matcher matcher2 = inlineGifPattern2.matcher(markdownStringBuilder);
while (matcher2.find()) {
- markdownStringBuilder.replace(matcher2.start(), matcher2.end(), "[gif](https://media3.giphy.com/media/" + markdownStringBuilder.substring(matcher2.start() + "![gif](giphy|".length(), matcher2.end() - "|downsized\\)".length()) + "/giphy.mp4)");
+ markdownStringBuilder.replace(matcher2.start(), matcher2.end(), "[gif](https://i.giphy.com/media/" + markdownStringBuilder.substring(matcher2.start() + "![gif](giphy|".length(), matcher2.end() - "|downsized\\)".length() + 1) + "/giphy.mp4)");
matcher2 = inlineGifPattern2.matcher(markdownStringBuilder);
}
- Pattern inlineGifPattern3 = Pattern.compile("!\\[gif]\\(emote\\|\\w+\\|\\w+\\)");
+ Pattern inlineGifPattern3 = REGEX_PATTERN[11];
Matcher matcher3 = inlineGifPattern3.matcher(markdownStringBuilder);
while (matcher3.find()) {
markdownStringBuilder.replace(matcher3.start(), matcher3.end(),