aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java/ml/docilealligator
diff options
context:
space:
mode:
authorscria1000 <91804886+scria1000@users.noreply.github.com>2021-12-09 11:54:25 +0000
committerscria1000 <91804886+scria1000@users.noreply.github.com>2021-12-09 11:54:25 +0000
commit87ab68217dcc5ca419b2a96a37bec27edbb8fdb8 (patch)
tree141217bc43289e4c4e7a9a9342d6c3a73ca4d5cb /app/src/main/java/ml/docilealligator
parentd101cddf0fb57f4c28e1adbdf481a8aa26acaf6d (diff)
downloadinfinity-for-reddit-87ab68217dcc5ca419b2a96a37bec27edbb8fdb8.tar
infinity-for-reddit-87ab68217dcc5ca419b2a96a37bec27edbb8fdb8.tar.gz
infinity-for-reddit-87ab68217dcc5ca419b2a96a37bec27edbb8fdb8.tar.bz2
infinity-for-reddit-87ab68217dcc5ca419b2a96a37bec27edbb8fdb8.tar.lz
infinity-for-reddit-87ab68217dcc5ca419b2a96a37bec27edbb8fdb8.tar.xz
infinity-for-reddit-87ab68217dcc5ca419b2a96a37bec27edbb8fdb8.tar.zst
infinity-for-reddit-87ab68217dcc5ca419b2a96a37bec27edbb8fdb8.zip
Some more spoiler parsing optimizations
Don't bother trying to parse a text if it doesn't have spoiler opening.
Diffstat (limited to 'app/src/main/java/ml/docilealligator')
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java8
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerOpening.java21
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerOpeningParser.java27
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerParserPlugin.java52
4 files changed, 93 insertions, 15 deletions
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java
index 4a06c3a7..a9275779 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java
@@ -70,6 +70,7 @@ import ml.docilealligator.infinityforreddit.comment.SendComment;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
+import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin;
import ml.docilealligator.infinityforreddit.markdown.SuperscriptPlugin;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
import ml.docilealligator.infinityforreddit.utils.Utils;
@@ -134,6 +135,8 @@ public class CommentActivity extends BaseActivity implements UploadImageEnabledA
private Uri capturedImageUri;
private ArrayList<UploadedImage> uploadedImages = new ArrayList<>();
private Menu mMenu;
+ private int commentColor;
+ private int commentSpoilerBackgroundColor;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -192,6 +195,7 @@ public class CommentActivity extends BaseActivity implements UploadImageEnabledA
builder.linkColor(linkColor);
}
})
+ .usePlugin(SpoilerParserPlugin.create(commentColor, commentSpoilerBackgroundColor))
.usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS))
.build();
if (parentTextMarkdown != null) {
@@ -337,7 +341,9 @@ public class CommentActivity extends BaseActivity implements UploadImageEnabledA
protected void applyCustomTheme() {
coordinatorLayout.setBackgroundColor(mCustomThemeWrapper.getBackgroundColor());
applyAppBarLayoutAndCollapsingToolbarLayoutAndToolbarTheme(appBarLayout, null, toolbar);
- commentParentMarkwonView.setTextColor(mCustomThemeWrapper.getCommentColor());
+ commentColor = mCustomThemeWrapper.getCommentColor();
+ commentSpoilerBackgroundColor = commentColor | 0xFF000000;
+ commentParentMarkwonView.setTextColor(commentColor);
divider.setBackgroundColor(mCustomThemeWrapper.getDividerColor());
commentEditText.setTextColor(mCustomThemeWrapper.getCommentColor());
int secondaryTextColor = mCustomThemeWrapper.getSecondaryTextColor();
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerOpening.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerOpening.java
new file mode 100644
index 00000000..279cba65
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerOpening.java
@@ -0,0 +1,21 @@
+package ml.docilealligator.infinityforreddit.markdown;
+
+import org.commonmark.node.CustomNode;
+import org.commonmark.node.Visitor;
+
+class SpoilerOpening extends CustomNode {
+ private String literal;
+
+ @Override
+ public void accept(Visitor visitor) {
+ visitor.visit(this);
+ }
+
+ public String getLiteral() {
+ return literal;
+ }
+
+ public void setLiteral(String literal) {
+ this.literal = literal;
+ }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerOpeningParser.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerOpeningParser.java
new file mode 100644
index 00000000..391e4a88
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerOpeningParser.java
@@ -0,0 +1,27 @@
+package ml.docilealligator.infinityforreddit.markdown;
+
+import androidx.annotation.Nullable;
+
+import org.commonmark.node.Node;
+
+import io.noties.markwon.inlineparser.InlineProcessor;
+
+public class SpoilerOpeningParser extends InlineProcessor {
+ @Override
+ public char specialCharacter() {
+ return '>';
+ }
+
+ @Nullable
+ @Override
+ protected Node parse() {
+ index++;
+ if (peek() == '!') {
+ index++;
+ SpoilerOpening node = new SpoilerOpening();
+ node.setLiteral(">!");
+ return node;
+ }
+ return null;
+ }
+}
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 3a05b71c..85dc2be5 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerParserPlugin.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerParserPlugin.java
@@ -11,7 +11,6 @@ import androidx.annotation.NonNull;
import org.commonmark.node.Block;
import org.commonmark.node.BlockQuote;
import org.commonmark.node.HtmlBlock;
-import org.commonmark.node.HtmlInline;
import org.commonmark.parser.Parser;
import java.util.ArrayList;
@@ -19,13 +18,17 @@ import java.util.Set;
import java.util.Stack;
import io.noties.markwon.AbstractMarkwonPlugin;
+import io.noties.markwon.MarkwonVisitor;
import io.noties.markwon.core.CorePlugin;
import io.noties.markwon.core.spans.CodeBlockSpan;
import io.noties.markwon.core.spans.CodeSpan;
+import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin;
public class SpoilerParserPlugin extends AbstractMarkwonPlugin {
private final int textColor;
private final int backgroundColor;
+ private boolean textHasSpoiler = false;
+ private int firstSpoilerStart = -1;
SpoilerParserPlugin(int textColor, int backgroundColor) {
this.textColor = textColor;
@@ -37,12 +40,29 @@ public class SpoilerParserPlugin extends AbstractMarkwonPlugin {
}
@Override
+ public void configureVisitor(@NonNull MarkwonVisitor.Builder builder) {
+ builder.on(SpoilerOpening.class, (visitor, opening) -> {
+ textHasSpoiler = true;
+ if (firstSpoilerStart == -1) {
+ firstSpoilerStart = visitor.length();
+ }
+ visitor.builder().append(opening.getLiteral());
+ });
+ }
+
+ @Override
+ public void configure(@NonNull Registry registry) {
+ registry.require(MarkwonInlineParserPlugin.class, plugin ->
+ plugin.factoryBuilder().addInlineProcessor(new SpoilerOpeningParser())
+ );
+ }
+
+ @Override
public void configureParser(@NonNull Parser.Builder builder) {
builder.customBlockParserFactory(new BlockQuoteWithExceptionParser.Factory());
Set<Class<? extends Block>> blocks = CorePlugin.enabledBlockTypes();
blocks.remove(HtmlBlock.class);
- blocks.remove(HtmlInline.class);
blocks.remove(BlockQuote.class);
builder.enabledBlockTypes(blocks);
@@ -50,16 +70,19 @@ public class SpoilerParserPlugin extends AbstractMarkwonPlugin {
@Override
public void afterSetText(@NonNull TextView textView) {
- textView.setHighlightColor(Color.TRANSPARENT);
-
- if (textView.getText().length() < 5) {
+ if (!textHasSpoiler || textView.getText().length() < 5) {
+ firstSpoilerStart = 0;
return;
}
+ textView.setHighlightColor(Color.TRANSPARENT);
+
SpannableStringBuilder markdownStringBuilder = new SpannableStringBuilder(textView.getText());
- ArrayList<Pair<Integer, Integer>> spoilers = parse(markdownStringBuilder);
+ ArrayList<Pair<Integer, Integer>> spoilers = parse(markdownStringBuilder, firstSpoilerStart);
+ firstSpoilerStart = 0;
if (spoilers.size() == 0) {
+ textHasSpoiler = false;
return;
}
@@ -118,31 +141,32 @@ 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 ArrayList<Pair<Integer, Integer>> parse(SpannableStringBuilder markdown) {
+ private ArrayList<Pair<Integer, Integer>> parse(SpannableStringBuilder markdown, int start) {
final int MAX_NEW_LINE = 1;
int length = markdown.length();
Stack<Integer> openSpoilerStack = new Stack<>();
ArrayList<Pair<Integer, Integer>> closedSpoilers = new ArrayList<>();
int new_lines = 0;
- for (int i = 0; i < length; i++) {
- if (markdown.charAt(i) == '\n') {
+ for (int i = start; i < length; i++) {
+ char currentChar = markdown.charAt(i);
+ if (currentChar == '\n') {
new_lines++;
if (new_lines > MAX_NEW_LINE) {
openSpoilerStack.clear();
new_lines = 0;
}
- } else if ((markdown.charAt(i) != '>')
- && (markdown.charAt(i) != '<')
- && (markdown.charAt(i) != '!')) {
+ } else if ((currentChar != '>')
+ && (currentChar != '<')
+ && (currentChar != '!')) {
new_lines = 0;
} else if ((i + 1 < length)
- && markdown.charAt(i) == '>'
+ && currentChar == '>'
&& 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) == '!'
+ && currentChar == '!'
&& markdown.charAt(i + 1) == '<') {
var pos = openSpoilerStack.pop();
if (!closedSpoilers.isEmpty()