Merge 619baf3b2a62227c8595d9fe4ae36835e2851ebf into 18938a1aa2e178185de82a4f605d03a0ccb3084d
This commit is contained in:
commit
f337f7bb6e
@ -0,0 +1,13 @@
|
|||||||
|
package ru.noties.markwon;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author pa.gulko zTrap (25.10.2017)
|
||||||
|
* @since 1.0.1
|
||||||
|
*/
|
||||||
|
public interface ImageClickResolver {
|
||||||
|
|
||||||
|
void resolve(View view, @NonNull String link);
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package ru.noties.markwon;
|
||||||
|
|
||||||
|
import android.content.ActivityNotFoundException;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.provider.Browser;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author pa.gulko zTrap (25.10.2017)
|
||||||
|
* @since 1.0.1
|
||||||
|
*/
|
||||||
|
public class ImageClickResolverDef implements ImageClickResolver {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resolve(View view, @NonNull String link) {
|
||||||
|
final Uri uri = Uri.parse(link);
|
||||||
|
final Context context = view.getContext();
|
||||||
|
final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
||||||
|
intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
|
||||||
|
try {
|
||||||
|
context.startActivity(intent);
|
||||||
|
} catch (ActivityNotFoundException e) {
|
||||||
|
Log.w("LinkResolverDef", "Actvity was not found for intent, " + intent.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -26,6 +26,7 @@ public class SpannableConfiguration {
|
|||||||
private final LinkSpan.Resolver linkResolver;
|
private final LinkSpan.Resolver linkResolver;
|
||||||
private final UrlProcessor urlProcessor;
|
private final UrlProcessor urlProcessor;
|
||||||
private final SpannableHtmlParser htmlParser;
|
private final SpannableHtmlParser htmlParser;
|
||||||
|
private final ImageClickResolver imageClickResolver;
|
||||||
|
|
||||||
private SpannableConfiguration(Builder builder) {
|
private SpannableConfiguration(Builder builder) {
|
||||||
this.theme = builder.theme;
|
this.theme = builder.theme;
|
||||||
@ -34,6 +35,7 @@ public class SpannableConfiguration {
|
|||||||
this.linkResolver = builder.linkResolver;
|
this.linkResolver = builder.linkResolver;
|
||||||
this.urlProcessor = builder.urlProcessor;
|
this.urlProcessor = builder.urlProcessor;
|
||||||
this.htmlParser = builder.htmlParser;
|
this.htmlParser = builder.htmlParser;
|
||||||
|
this.imageClickResolver = builder.imageClickResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SpannableTheme theme() {
|
public SpannableTheme theme() {
|
||||||
@ -60,6 +62,10 @@ public class SpannableConfiguration {
|
|||||||
return htmlParser;
|
return htmlParser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ImageClickResolver imageClickResolver() {
|
||||||
|
return imageClickResolver;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
@ -69,6 +75,7 @@ public class SpannableConfiguration {
|
|||||||
private LinkSpan.Resolver linkResolver;
|
private LinkSpan.Resolver linkResolver;
|
||||||
private UrlProcessor urlProcessor;
|
private UrlProcessor urlProcessor;
|
||||||
private SpannableHtmlParser htmlParser;
|
private SpannableHtmlParser htmlParser;
|
||||||
|
private ImageClickResolver imageClickResolver;
|
||||||
|
|
||||||
Builder(Context context) {
|
Builder(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
@ -104,6 +111,11 @@ public class SpannableConfiguration {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder imageClickResolver(ImageClickResolver imageClickResolver) {
|
||||||
|
this.imageClickResolver = imageClickResolver;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public SpannableConfiguration build() {
|
public SpannableConfiguration build() {
|
||||||
if (theme == null) {
|
if (theme == null) {
|
||||||
theme = SpannableTheme.create(context);
|
theme = SpannableTheme.create(context);
|
||||||
@ -120,8 +132,12 @@ public class SpannableConfiguration {
|
|||||||
if (urlProcessor == null) {
|
if (urlProcessor == null) {
|
||||||
urlProcessor = new UrlProcessorNoOp();
|
urlProcessor = new UrlProcessorNoOp();
|
||||||
}
|
}
|
||||||
|
if (imageClickResolver == null) {
|
||||||
|
imageClickResolver = new ImageClickResolverDef();
|
||||||
|
}
|
||||||
if (htmlParser == null) {
|
if (htmlParser == null) {
|
||||||
htmlParser = SpannableHtmlParser.create(theme, asyncDrawableLoader, urlProcessor, linkResolver);
|
htmlParser = SpannableHtmlParser.create(theme, asyncDrawableLoader, urlProcessor,
|
||||||
|
linkResolver, imageClickResolver);
|
||||||
}
|
}
|
||||||
return new SpannableConfiguration(this);
|
return new SpannableConfiguration(this);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,9 @@ import android.support.annotation.NonNull;
|
|||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.text.style.ClickableSpan;
|
||||||
import android.text.style.StrikethroughSpan;
|
import android.text.style.StrikethroughSpan;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
import org.commonmark.ext.gfm.strikethrough.Strikethrough;
|
import org.commonmark.ext.gfm.strikethrough.Strikethrough;
|
||||||
import org.commonmark.ext.gfm.tables.TableBody;
|
import org.commonmark.ext.gfm.tables.TableBody;
|
||||||
@ -431,8 +433,12 @@ public class SpannableMarkdownVisitor extends AbstractVisitor {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// todo, maybe, if image is not inside a link, we should make it clickable, so
|
setSpan(length, new ClickableSpan() {
|
||||||
// user can open it in external viewer?
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
configuration.imageClickResolver().resolve(view, destination);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -4,9 +4,12 @@ import android.support.annotation.NonNull;
|
|||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.text.style.ClickableSpan;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import ru.noties.markwon.ImageClickResolver;
|
||||||
import ru.noties.markwon.UrlProcessor;
|
import ru.noties.markwon.UrlProcessor;
|
||||||
import ru.noties.markwon.spans.AsyncDrawable;
|
import ru.noties.markwon.spans.AsyncDrawable;
|
||||||
import ru.noties.markwon.spans.AsyncDrawableSpan;
|
import ru.noties.markwon.spans.AsyncDrawableSpan;
|
||||||
@ -17,14 +20,17 @@ class ImageProviderImpl implements SpannableHtmlParser.ImageProvider {
|
|||||||
private final SpannableTheme theme;
|
private final SpannableTheme theme;
|
||||||
private final AsyncDrawable.Loader loader;
|
private final AsyncDrawable.Loader loader;
|
||||||
private final UrlProcessor urlProcessor;
|
private final UrlProcessor urlProcessor;
|
||||||
|
private final ImageClickResolver imageClickResolver;
|
||||||
|
|
||||||
ImageProviderImpl(
|
ImageProviderImpl(
|
||||||
@NonNull SpannableTheme theme,
|
@NonNull SpannableTheme theme,
|
||||||
@NonNull AsyncDrawable.Loader loader,
|
@NonNull AsyncDrawable.Loader loader,
|
||||||
@NonNull UrlProcessor urlProcessor) {
|
@NonNull UrlProcessor urlProcessor,
|
||||||
|
@NonNull ImageClickResolver imageClickResolver) {
|
||||||
this.theme = theme;
|
this.theme = theme;
|
||||||
this.loader = loader;
|
this.loader = loader;
|
||||||
this.urlProcessor = urlProcessor;
|
this.urlProcessor = urlProcessor;
|
||||||
|
this.imageClickResolver = imageClickResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -53,6 +59,14 @@ class ImageProviderImpl implements SpannableHtmlParser.ImageProvider {
|
|||||||
final SpannableString string = new SpannableString(replacement);
|
final SpannableString string = new SpannableString(replacement);
|
||||||
string.setSpan(span, 0, string.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
string.setSpan(span, 0, string.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
|
||||||
|
final ClickableSpan clickableSpan = new ClickableSpan() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
imageClickResolver.resolve(view, destination);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
string.setSpan(clickableSpan, 0, string.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
|
||||||
spanned = string;
|
spanned = string;
|
||||||
} else {
|
} else {
|
||||||
spanned = null;
|
spanned = null;
|
||||||
|
@ -10,6 +10,8 @@ import android.text.Spanned;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import ru.noties.markwon.ImageClickResolver;
|
||||||
|
import ru.noties.markwon.ImageClickResolverDef;
|
||||||
import ru.noties.markwon.LinkResolverDef;
|
import ru.noties.markwon.LinkResolverDef;
|
||||||
import ru.noties.markwon.UrlProcessor;
|
import ru.noties.markwon.UrlProcessor;
|
||||||
import ru.noties.markwon.UrlProcessorNoOp;
|
import ru.noties.markwon.UrlProcessorNoOp;
|
||||||
@ -25,7 +27,8 @@ public class SpannableHtmlParser {
|
|||||||
@NonNull SpannableTheme theme,
|
@NonNull SpannableTheme theme,
|
||||||
@NonNull AsyncDrawable.Loader loader
|
@NonNull AsyncDrawable.Loader loader
|
||||||
) {
|
) {
|
||||||
return builderWithDefaults(theme, loader, null, null)
|
return builderWithDefaults(theme, loader, null, null,
|
||||||
|
null)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,9 +36,10 @@ public class SpannableHtmlParser {
|
|||||||
@NonNull SpannableTheme theme,
|
@NonNull SpannableTheme theme,
|
||||||
@NonNull AsyncDrawable.Loader loader,
|
@NonNull AsyncDrawable.Loader loader,
|
||||||
@NonNull UrlProcessor urlProcessor,
|
@NonNull UrlProcessor urlProcessor,
|
||||||
@NonNull LinkSpan.Resolver resolver
|
@NonNull LinkSpan.Resolver linkResolver,
|
||||||
|
@NonNull ImageClickResolver imageClickResolver
|
||||||
) {
|
) {
|
||||||
return builderWithDefaults(theme, loader, urlProcessor, resolver)
|
return builderWithDefaults(theme, loader, urlProcessor, linkResolver, imageClickResolver)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,22 +48,28 @@ public class SpannableHtmlParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Builder builderWithDefaults(@NonNull SpannableTheme theme) {
|
public static Builder builderWithDefaults(@NonNull SpannableTheme theme) {
|
||||||
return builderWithDefaults(theme, null, null, null);
|
return builderWithDefaults(theme, null, null, null,
|
||||||
|
null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Builder builderWithDefaults(
|
public static Builder builderWithDefaults(
|
||||||
@NonNull SpannableTheme theme,
|
@NonNull SpannableTheme theme,
|
||||||
@Nullable AsyncDrawable.Loader asyncDrawableLoader,
|
@Nullable AsyncDrawable.Loader asyncDrawableLoader,
|
||||||
@Nullable UrlProcessor urlProcessor,
|
@Nullable UrlProcessor urlProcessor,
|
||||||
@Nullable LinkSpan.Resolver resolver
|
@Nullable LinkSpan.Resolver linkResolver,
|
||||||
|
@Nullable ImageClickResolver imageClickResolver
|
||||||
) {
|
) {
|
||||||
|
|
||||||
if (urlProcessor == null) {
|
if (urlProcessor == null) {
|
||||||
urlProcessor = new UrlProcessorNoOp();
|
urlProcessor = new UrlProcessorNoOp();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resolver == null) {
|
if (linkResolver == null) {
|
||||||
resolver = new LinkResolverDef();
|
linkResolver = new LinkResolverDef();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imageClickResolver == null) {
|
||||||
|
imageClickResolver = new ImageClickResolverDef();
|
||||||
}
|
}
|
||||||
|
|
||||||
final BoldProvider boldProvider = new BoldProvider();
|
final BoldProvider boldProvider = new BoldProvider();
|
||||||
@ -68,7 +78,8 @@ public class SpannableHtmlParser {
|
|||||||
|
|
||||||
final ImageProvider imageProvider;
|
final ImageProvider imageProvider;
|
||||||
if (asyncDrawableLoader != null) {
|
if (asyncDrawableLoader != null) {
|
||||||
imageProvider = new ImageProviderImpl(theme, asyncDrawableLoader, urlProcessor);
|
imageProvider = new ImageProviderImpl(theme, asyncDrawableLoader, urlProcessor,
|
||||||
|
imageClickResolver);
|
||||||
} else {
|
} else {
|
||||||
imageProvider = null;
|
imageProvider = null;
|
||||||
}
|
}
|
||||||
@ -86,7 +97,7 @@ public class SpannableHtmlParser {
|
|||||||
.simpleTag("del", strikeProvider)
|
.simpleTag("del", strikeProvider)
|
||||||
.simpleTag("s", strikeProvider)
|
.simpleTag("s", strikeProvider)
|
||||||
.simpleTag("strike", strikeProvider)
|
.simpleTag("strike", strikeProvider)
|
||||||
.simpleTag("a", new LinkProvider(theme, urlProcessor, resolver))
|
.simpleTag("a", new LinkProvider(theme, urlProcessor, linkResolver))
|
||||||
.imageProvider(imageProvider);
|
.imageProvider(imageProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user