Enable gif playback in EmotePlugin.AsyncDrawableTarget. Fix bugs related to MediaMetadata map in ImageAndGifBlockParser.

This commit is contained in:
Docile-Alligator
2023-11-24 13:23:45 -05:00
parent 5fbc3a7224
commit a22600ceef
3 changed files with 51 additions and 41 deletions

View File

@ -2,6 +2,8 @@ package ml.docilealligator.infinityforreddit.markdown;
import static io.noties.markwon.inlineparser.InlineParserUtils.mergeChildTextNodes;
import androidx.annotation.Nullable;
import org.commonmark.internal.Bracket;
import org.commonmark.internal.util.Escaping;
import org.commonmark.node.Link;
@ -17,6 +19,7 @@ import ml.docilealligator.infinityforreddit.MediaMetadata;
public class EmoteCloseBracketInlineProcessor extends InlineProcessor {
private static final Pattern WHITESPACE = Pattern.compile("\\s+");
@Nullable
private Map<String, MediaMetadata> mediaMetadataMap;
@Override
@ -150,7 +153,7 @@ public class EmoteCloseBracketInlineProcessor extends InlineProcessor {
}
}
public void setMediaMetadataMap(Map<String, MediaMetadata> mediaMetadataMap) {
public void setMediaMetadataMap(@Nullable Map<String, MediaMetadata> mediaMetadataMap) {
this.mediaMetadataMap = mediaMetadataMap;
}
}

View File

@ -1,6 +1,7 @@
package ml.docilealligator.infinityforreddit.markdown;
import android.content.Context;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.text.Spanned;
import android.widget.TextView;
@ -32,7 +33,6 @@ import io.noties.markwon.image.AsyncDrawableLoader;
import io.noties.markwon.image.AsyncDrawableScheduler;
import io.noties.markwon.image.DrawableUtils;
import io.noties.markwon.image.ImageProps;
import io.noties.markwon.image.ImageSpanFactory;
import ml.docilealligator.infinityforreddit.MediaMetadata;
public class EmotePlugin extends AbstractMarkwonPlugin {
@ -82,7 +82,7 @@ public class EmotePlugin extends AbstractMarkwonPlugin {
@Override
public void configureSpansFactory(@NonNull MarkwonSpansFactory.Builder builder) {
builder.setFactory(Emote.class, new ImageSpanFactory());
builder.setFactory(Emote.class, new EmoteSpanFactory());
}
@Override
@ -92,45 +92,42 @@ public class EmotePlugin extends AbstractMarkwonPlugin {
@Override
public void configureVisitor(@NonNull MarkwonVisitor.Builder builder) {
builder.on(Emote.class, new MarkwonVisitor.NodeVisitor<Emote>() {
@Override
public void visit(@NonNull MarkwonVisitor visitor, @NonNull Emote emote) {
// if there is no image spanFactory, ignore
final SpanFactory spanFactory = visitor.configuration().spansFactory().get(Emote.class);
if (spanFactory == null) {
visitor.visitChildren(emote);
return;
}
final int length = visitor.length();
builder.on(Emote.class, (visitor, emote) -> {
// if there is no image spanFactory, ignore
final SpanFactory spanFactory = visitor.configuration().spansFactory().get(Emote.class);
if (spanFactory == null) {
visitor.visitChildren(emote);
// we must check if anything _was_ added, as we need at least one char to render
if (length == visitor.length()) {
visitor.builder().append('\uFFFC');
}
final MarkwonConfiguration configuration = visitor.configuration();
final Node parent = emote.getParent();
final boolean link = parent instanceof Link;
final String destination = configuration
.imageDestinationProcessor()
.process(emote.getMediaMetadata().original.url);
final RenderProps props = visitor.renderProps();
// apply image properties
// Please note that we explicitly set IMAGE_SIZE to null as we do not clear
// properties after we applied span (we could though)
ImageProps.DESTINATION.set(props, destination);
ImageProps.REPLACEMENT_TEXT_IS_LINK.set(props, link);
ImageProps.IMAGE_SIZE.set(props, null);
visitor.setSpans(length, spanFactory.getSpans(configuration, props));
return;
}
final int length = visitor.length();
visitor.visitChildren(emote);
// we must check if anything _was_ added, as we need at least one char to render
if (length == visitor.length()) {
visitor.builder().append('\uFFFC');
}
final MarkwonConfiguration configuration = visitor.configuration();
final Node parent = emote.getParent();
final boolean link = parent instanceof Link;
final String destination = configuration
.imageDestinationProcessor()
.process(emote.getMediaMetadata().original.url);
final RenderProps props = visitor.renderProps();
// apply image properties
// Please note that we explicitly set IMAGE_SIZE to null as we do not clear
// properties after we applied span (we could though)
ImageProps.DESTINATION.set(props, destination);
ImageProps.REPLACEMENT_TEXT_IS_LINK.set(props, link);
ImageProps.IMAGE_SIZE.set(props, null);
visitor.setSpans(length, spanFactory.getSpans(configuration, props));
});
}
@ -193,6 +190,9 @@ public class EmotePlugin extends AbstractMarkwonPlugin {
if (drawable.isAttached()) {
DrawableUtils.applyIntrinsicBoundsIfEmpty(resource);
drawable.setResult(resource);
if (resource instanceof Animatable) {
((Animatable) resource).start();
}
}
}
}

View File

@ -1,5 +1,7 @@
package ml.docilealligator.infinityforreddit.markdown;
import androidx.annotation.Nullable;
import org.commonmark.node.Block;
import org.commonmark.parser.block.AbstractBlockParser;
import org.commonmark.parser.block.AbstractBlockParserFactory;
@ -35,11 +37,16 @@ public class ImageAndGifBlockParser extends AbstractBlockParser {
public static class Factory extends AbstractBlockParserFactory {
private final Pattern redditPreviewPattern = Pattern.compile("!\\[img]\\(https://preview.redd.it/\\w+.(jpg|png|jpeg)((\\?+[-a-zA-Z0-9()@:%_+.~#?&/=]*)|)\\)");
private final Pattern gifPattern = Pattern.compile("!\\[gif]\\(giphy\\|\\w+(\\|downsized)?\\)");
@Nullable
private Map<String, MediaMetadata> mediaMetadataMap;
private final int fromIndex = "![img](https://preview.redd.it/".length();
@Override
public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockParser) {
if (mediaMetadataMap == null) {
return BlockStart.none();
}
String line = state.getLine().toString();
Matcher matcher = redditPreviewPattern.matcher(line);
if (matcher.find()) {
@ -62,7 +69,7 @@ public class ImageAndGifBlockParser extends AbstractBlockParser {
return BlockStart.none();
}
public void setMediaMetadataMap(Map<String, MediaMetadata> mediaMetadataMap) {
public void setMediaMetadataMap(@Nullable Map<String, MediaMetadata> mediaMetadataMap) {
this.mediaMetadataMap = mediaMetadataMap;
}
}