mirror of
https://codeberg.org/Bazsalanszky/Infinity-For-Lemmy.git
synced 2025-01-30 19:34:45 +01:00
Some more spoiler parsing optimizations
Don't bother trying to parse a text if it doesn't have spoiler opening.
This commit is contained in:
parent
d101cddf0f
commit
87ab68217d
@ -70,6 +70,7 @@ import ml.docilealligator.infinityforreddit.comment.SendComment;
|
|||||||
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
|
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
|
||||||
import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed;
|
import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed;
|
||||||
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
|
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
|
||||||
|
import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin;
|
||||||
import ml.docilealligator.infinityforreddit.markdown.SuperscriptPlugin;
|
import ml.docilealligator.infinityforreddit.markdown.SuperscriptPlugin;
|
||||||
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
|
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
|
||||||
import ml.docilealligator.infinityforreddit.utils.Utils;
|
import ml.docilealligator.infinityforreddit.utils.Utils;
|
||||||
@ -134,6 +135,8 @@ public class CommentActivity extends BaseActivity implements UploadImageEnabledA
|
|||||||
private Uri capturedImageUri;
|
private Uri capturedImageUri;
|
||||||
private ArrayList<UploadedImage> uploadedImages = new ArrayList<>();
|
private ArrayList<UploadedImage> uploadedImages = new ArrayList<>();
|
||||||
private Menu mMenu;
|
private Menu mMenu;
|
||||||
|
private int commentColor;
|
||||||
|
private int commentSpoilerBackgroundColor;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@ -192,6 +195,7 @@ public class CommentActivity extends BaseActivity implements UploadImageEnabledA
|
|||||||
builder.linkColor(linkColor);
|
builder.linkColor(linkColor);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.usePlugin(SpoilerParserPlugin.create(commentColor, commentSpoilerBackgroundColor))
|
||||||
.usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS))
|
.usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS))
|
||||||
.build();
|
.build();
|
||||||
if (parentTextMarkdown != null) {
|
if (parentTextMarkdown != null) {
|
||||||
@ -337,7 +341,9 @@ public class CommentActivity extends BaseActivity implements UploadImageEnabledA
|
|||||||
protected void applyCustomTheme() {
|
protected void applyCustomTheme() {
|
||||||
coordinatorLayout.setBackgroundColor(mCustomThemeWrapper.getBackgroundColor());
|
coordinatorLayout.setBackgroundColor(mCustomThemeWrapper.getBackgroundColor());
|
||||||
applyAppBarLayoutAndCollapsingToolbarLayoutAndToolbarTheme(appBarLayout, null, toolbar);
|
applyAppBarLayoutAndCollapsingToolbarLayoutAndToolbarTheme(appBarLayout, null, toolbar);
|
||||||
commentParentMarkwonView.setTextColor(mCustomThemeWrapper.getCommentColor());
|
commentColor = mCustomThemeWrapper.getCommentColor();
|
||||||
|
commentSpoilerBackgroundColor = commentColor | 0xFF000000;
|
||||||
|
commentParentMarkwonView.setTextColor(commentColor);
|
||||||
divider.setBackgroundColor(mCustomThemeWrapper.getDividerColor());
|
divider.setBackgroundColor(mCustomThemeWrapper.getDividerColor());
|
||||||
commentEditText.setTextColor(mCustomThemeWrapper.getCommentColor());
|
commentEditText.setTextColor(mCustomThemeWrapper.getCommentColor());
|
||||||
int secondaryTextColor = mCustomThemeWrapper.getSecondaryTextColor();
|
int secondaryTextColor = mCustomThemeWrapper.getSecondaryTextColor();
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,6 @@ import androidx.annotation.NonNull;
|
|||||||
import org.commonmark.node.Block;
|
import org.commonmark.node.Block;
|
||||||
import org.commonmark.node.BlockQuote;
|
import org.commonmark.node.BlockQuote;
|
||||||
import org.commonmark.node.HtmlBlock;
|
import org.commonmark.node.HtmlBlock;
|
||||||
import org.commonmark.node.HtmlInline;
|
|
||||||
import org.commonmark.parser.Parser;
|
import org.commonmark.parser.Parser;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -19,13 +18,17 @@ import java.util.Set;
|
|||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
import io.noties.markwon.AbstractMarkwonPlugin;
|
import io.noties.markwon.AbstractMarkwonPlugin;
|
||||||
|
import io.noties.markwon.MarkwonVisitor;
|
||||||
import io.noties.markwon.core.CorePlugin;
|
import io.noties.markwon.core.CorePlugin;
|
||||||
import io.noties.markwon.core.spans.CodeBlockSpan;
|
import io.noties.markwon.core.spans.CodeBlockSpan;
|
||||||
import io.noties.markwon.core.spans.CodeSpan;
|
import io.noties.markwon.core.spans.CodeSpan;
|
||||||
|
import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin;
|
||||||
|
|
||||||
public class SpoilerParserPlugin extends AbstractMarkwonPlugin {
|
public class SpoilerParserPlugin extends AbstractMarkwonPlugin {
|
||||||
private final int textColor;
|
private final int textColor;
|
||||||
private final int backgroundColor;
|
private final int backgroundColor;
|
||||||
|
private boolean textHasSpoiler = false;
|
||||||
|
private int firstSpoilerStart = -1;
|
||||||
|
|
||||||
SpoilerParserPlugin(int textColor, int backgroundColor) {
|
SpoilerParserPlugin(int textColor, int backgroundColor) {
|
||||||
this.textColor = textColor;
|
this.textColor = textColor;
|
||||||
@ -36,13 +39,30 @@ public class SpoilerParserPlugin extends AbstractMarkwonPlugin {
|
|||||||
return new SpoilerParserPlugin(textColor, backgroundColor);
|
return new SpoilerParserPlugin(textColor, backgroundColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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
|
@Override
|
||||||
public void configureParser(@NonNull Parser.Builder builder) {
|
public void configureParser(@NonNull Parser.Builder builder) {
|
||||||
builder.customBlockParserFactory(new BlockQuoteWithExceptionParser.Factory());
|
builder.customBlockParserFactory(new BlockQuoteWithExceptionParser.Factory());
|
||||||
|
|
||||||
Set<Class<? extends Block>> blocks = CorePlugin.enabledBlockTypes();
|
Set<Class<? extends Block>> blocks = CorePlugin.enabledBlockTypes();
|
||||||
blocks.remove(HtmlBlock.class);
|
blocks.remove(HtmlBlock.class);
|
||||||
blocks.remove(HtmlInline.class);
|
|
||||||
blocks.remove(BlockQuote.class);
|
blocks.remove(BlockQuote.class);
|
||||||
|
|
||||||
builder.enabledBlockTypes(blocks);
|
builder.enabledBlockTypes(blocks);
|
||||||
@ -50,16 +70,19 @@ public class SpoilerParserPlugin extends AbstractMarkwonPlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterSetText(@NonNull TextView textView) {
|
public void afterSetText(@NonNull TextView textView) {
|
||||||
textView.setHighlightColor(Color.TRANSPARENT);
|
if (!textHasSpoiler || textView.getText().length() < 5) {
|
||||||
|
firstSpoilerStart = 0;
|
||||||
if (textView.getText().length() < 5) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textView.setHighlightColor(Color.TRANSPARENT);
|
||||||
|
|
||||||
SpannableStringBuilder markdownStringBuilder = new SpannableStringBuilder(textView.getText());
|
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) {
|
if (spoilers.size() == 0) {
|
||||||
|
textHasSpoiler = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,31 +141,32 @@ public class SpoilerParserPlugin extends AbstractMarkwonPlugin {
|
|||||||
// Don't allow more than one new line after every non-blank line
|
// 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
|
// Try not to care about recursing spoilers, we just want the outermost spoiler because
|
||||||
// spoiler revealing-hiding breaks with recursing spoilers
|
// 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;
|
final int MAX_NEW_LINE = 1;
|
||||||
int length = markdown.length();
|
int length = markdown.length();
|
||||||
Stack<Integer> openSpoilerStack = new Stack<>();
|
Stack<Integer> openSpoilerStack = new Stack<>();
|
||||||
ArrayList<Pair<Integer, Integer>> closedSpoilers = new ArrayList<>();
|
ArrayList<Pair<Integer, Integer>> closedSpoilers = new ArrayList<>();
|
||||||
int new_lines = 0;
|
int new_lines = 0;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = start; i < length; i++) {
|
||||||
if (markdown.charAt(i) == '\n') {
|
char currentChar = markdown.charAt(i);
|
||||||
|
if (currentChar == '\n') {
|
||||||
new_lines++;
|
new_lines++;
|
||||||
if (new_lines > MAX_NEW_LINE) {
|
if (new_lines > MAX_NEW_LINE) {
|
||||||
openSpoilerStack.clear();
|
openSpoilerStack.clear();
|
||||||
new_lines = 0;
|
new_lines = 0;
|
||||||
}
|
}
|
||||||
} else if ((markdown.charAt(i) != '>')
|
} else if ((currentChar != '>')
|
||||||
&& (markdown.charAt(i) != '<')
|
&& (currentChar != '<')
|
||||||
&& (markdown.charAt(i) != '!')) {
|
&& (currentChar != '!')) {
|
||||||
new_lines = 0;
|
new_lines = 0;
|
||||||
} else if ((i + 1 < length)
|
} else if ((i + 1 < length)
|
||||||
&& markdown.charAt(i) == '>'
|
&& currentChar == '>'
|
||||||
&& markdown.charAt(i + 1) == '!') {
|
&& markdown.charAt(i + 1) == '!') {
|
||||||
openSpoilerStack.push(i + 2);
|
openSpoilerStack.push(i + 2);
|
||||||
} else if ((i + 1 < length) && (i - 1 >= 0)
|
} else if ((i + 1 < length) && (i - 1 >= 0)
|
||||||
&& openSpoilerStack.size() > 0
|
&& openSpoilerStack.size() > 0
|
||||||
&& markdown.charAt(i - 1) != '>'
|
&& markdown.charAt(i - 1) != '>'
|
||||||
&& markdown.charAt(i) == '!'
|
&& currentChar == '!'
|
||||||
&& markdown.charAt(i + 1) == '<') {
|
&& markdown.charAt(i + 1) == '<') {
|
||||||
var pos = openSpoilerStack.pop();
|
var pos = openSpoilerStack.pop();
|
||||||
if (!closedSpoilers.isEmpty()
|
if (!closedSpoilers.isEmpty()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user