diff --git a/app/build.gradle b/app/build.gradle index faa99c29..7face7c9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -23,8 +23,8 @@ android { } dependencies { - def lifecycle_version = "2.2.0-alpha04" - final def markwon_version = "3.0.0" + def lifecycle_version = "2.2.0-alpha05" + final def markwon_version = "4.1.1" implementation fileTree(include: ['*.jar'], dir: 'libs') implementation 'androidx.appcompat:appcompat:1.1.0' @@ -47,17 +47,21 @@ dependencies { implementation "com.vdurmont:emoji-java:4.0.0" implementation "com.pes.materialcolorpicker:library:1.2.5" - implementation "ru.noties.markwon:core:$markwon_version" - implementation "ru.noties.markwon:ext-strikethrough:$markwon_version" - implementation "ru.noties.markwon:ext-tables:$markwon_version" - implementation "ru.noties.markwon:ext-tasklist:$markwon_version" - implementation "ru.noties.markwon:syntax-highlight:$markwon_version" - implementation "ru.noties.markwon:image-okhttp:$markwon_version" - implementation "ru.noties.markwon:html:$markwon_version" - implementation "ru.noties.markwon:recycler:$markwon_version" - implementation "ru.noties.markwon:recycler-table:$markwon_version" - implementation "ru.noties.markwon:image-gif:$markwon_version" - implementation "ru.noties.markwon:image-svg:$markwon_version" + implementation "io.noties.markwon:core:$markwon_version" + implementation "io.noties.markwon:ext-latex:$markwon_version" + implementation "io.noties.markwon:ext-strikethrough:$markwon_version" + implementation "io.noties.markwon:ext-tables:$markwon_version" + implementation "io.noties.markwon:ext-tasklist:$markwon_version" + implementation "io.noties.markwon:html:$markwon_version" + implementation "io.noties.markwon:image:$markwon_version" + implementation "io.noties.markwon:image-picasso:$markwon_version" + implementation "io.noties.markwon:linkify:$markwon_version" + implementation "io.noties.markwon:recycler:$markwon_version" + implementation "io.noties.markwon:recycler-table:$markwon_version" + implementation "io.noties.markwon:simple-ext:$markwon_version" + implementation "io.noties.markwon:syntax-highlight:$markwon_version" + implementation "com.caverock:androidsvg:1.4" + implementation "pl.droidsonroids.gif:android-gif-drawable:1.2.14" implementation "com.hendraanggrian.appcompat:socialview:0.2" implementation "com.hendraanggrian.appcompat:socialview-commons:0.2" diff --git a/app/src/main/java/org/mian/gitnex/activities/IssueDetailActivity.java b/app/src/main/java/org/mian/gitnex/activities/IssueDetailActivity.java index d24294f4..c57f1e82 100644 --- a/app/src/main/java/org/mian/gitnex/activities/IssueDetailActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/IssueDetailActivity.java @@ -10,26 +10,33 @@ import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; -import okhttp3.OkHttpClient; +import io.noties.markwon.AbstractMarkwonPlugin; +import io.noties.markwon.Markwon; +import io.noties.markwon.core.CorePlugin; +import io.noties.markwon.core.MarkwonTheme; +import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; +import io.noties.markwon.ext.tables.TablePlugin; +import io.noties.markwon.ext.tasklist.TaskListPlugin; +import io.noties.markwon.html.HtmlPlugin; +import io.noties.markwon.image.AsyncDrawable; +import io.noties.markwon.image.DefaultMediaDecoder; +import io.noties.markwon.image.ImageItem; +import io.noties.markwon.image.ImagesPlugin; +import io.noties.markwon.image.SchemeHandler; +import io.noties.markwon.image.gif.GifMediaDecoder; +import io.noties.markwon.image.svg.SvgMediaDecoder; +import io.noties.markwon.linkify.LinkifyPlugin; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; -import ru.noties.markwon.AbstractMarkwonPlugin; -import ru.noties.markwon.Markwon; -import ru.noties.markwon.core.CorePlugin; -import ru.noties.markwon.core.MarkwonTheme; -import ru.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import ru.noties.markwon.ext.tables.TablePlugin; -import ru.noties.markwon.ext.tasklist.TaskListPlugin; -import ru.noties.markwon.html.HtmlPlugin; -import ru.noties.markwon.image.ImagesPlugin; -import ru.noties.markwon.image.gif.GifPlugin; -import ru.noties.markwon.image.okhttp.OkHttpImagesPlugin; import android.content.Context; import android.graphics.Color; import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.Bundle; import android.os.Handler; +import android.text.Spanned; import android.util.Log; import android.view.Gravity; import android.view.Menu; @@ -63,6 +70,8 @@ import org.mian.gitnex.viewmodels.IssueCommentsViewModel; import org.ocpsoft.prettytime.PrettyTime; import java.text.DateFormat; import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Objects; @@ -286,22 +295,64 @@ public class IssueDetailActivity extends AppCompatActivity { final Markwon markwon = Markwon.builder(Objects.requireNonNull(getApplicationContext())) .usePlugin(CorePlugin.create()) - .usePlugin(OkHttpImagesPlugin.create(new OkHttpClient())) - .usePlugin(ImagesPlugin.createWithAssets(getApplicationContext())) + .usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() { + @Override + public void configureImages(@NonNull ImagesPlugin plugin) { + plugin.addSchemeHandler(new SchemeHandler() { + @NonNull + @Override + public ImageItem handle(@NonNull String raw, @NonNull Uri uri) { + + final int resourceId = getApplicationContext().getResources().getIdentifier( + raw.substring("drawable://".length()), + "drawable", + getApplicationContext().getPackageName()); + + final Drawable drawable = getApplicationContext().getDrawable(resourceId); + + assert drawable != null; + return ImageItem.withResult(drawable); + } + + @NonNull + @Override + public Collection supportedSchemes() { + return Collections.singleton("drawable"); + } + }); + plugin.addMediaDecoder(GifMediaDecoder.create(false)); + plugin.addMediaDecoder(SvgMediaDecoder.create(getApplicationContext().getResources())); + plugin.addMediaDecoder(SvgMediaDecoder.create()); + plugin.defaultMediaDecoder(DefaultMediaDecoder.create(getApplicationContext().getResources())); + plugin.defaultMediaDecoder(DefaultMediaDecoder.create()); + } + })) .usePlugin(new AbstractMarkwonPlugin() { @Override public void configureTheme(@NonNull MarkwonTheme.Builder builder) { builder .codeTextColor(tinyDb.getInt("codeBlockColor")) .codeBackgroundColor(tinyDb.getInt("codeBlockBackground")) - .linkColor(getApplicationContext().getResources().getColor(R.color.lightBlue)); + .linkColor(getResources().getColor(R.color.lightBlue)); } }) + .usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() { + @Override + public void configureImages(@NonNull ImagesPlugin plugin) { + plugin.placeholderProvider(new ImagesPlugin.PlaceholderProvider() { + @Nullable + @Override + public Drawable providePlaceholder(@NonNull AsyncDrawable drawable) { + return null; + } + }); + } + })) .usePlugin(TablePlugin.create(getApplicationContext())) .usePlugin(TaskListPlugin.create(getApplicationContext())) .usePlugin(HtmlPlugin.create()) - .usePlugin(GifPlugin.create()) .usePlugin(StrikethroughPlugin.create()) + .usePlugin(LinkifyPlugin.create()) .build(); TinyDB tinyDb = new TinyDB(getApplicationContext()); @@ -313,8 +364,8 @@ public class IssueDetailActivity extends AppCompatActivity { Picasso.get().load(singleIssue.getUser().getAvatar_url()).transform(new RoundedTransformation(100, 0)).resize(200, 200).centerCrop().into(assigneeAvatar); issueTitle.setText(getString(R.string.issueTitleWithId, singleIssue.getNumber(), singleIssue.getTitle())); String cleanIssueDescription = singleIssue.getBody().trim(); - final CharSequence bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(cleanIssueDescription)); - issueDescription.setText(UserMentions.UserMentionsFunc(getApplicationContext(), bodyWithMD, cleanIssueDescription)); + Spanned bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(cleanIssueDescription)); + markwon.setParsedMarkdown(issueDescription, UserMentions.UserMentionsFunc(getApplicationContext(), bodyWithMD, cleanIssueDescription)); RelativeLayout.LayoutParams paramsDesc = (RelativeLayout.LayoutParams)issueDescription.getLayoutParams(); diff --git a/app/src/main/java/org/mian/gitnex/adapters/ClosedIssuesAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/ClosedIssuesAdapter.java index e9c94182..8d9cf3fe 100644 --- a/app/src/main/java/org/mian/gitnex/adapters/ClosedIssuesAdapter.java +++ b/app/src/main/java/org/mian/gitnex/adapters/ClosedIssuesAdapter.java @@ -3,7 +3,9 @@ package org.mian.gitnex.adapters; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; -import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.text.Spanned; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -25,24 +27,30 @@ import org.ocpsoft.prettytime.PrettyTime; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Objects; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.recyclerview.widget.RecyclerView; -import okhttp3.OkHttpClient; -import ru.noties.markwon.AbstractMarkwonPlugin; -import ru.noties.markwon.Markwon; -import ru.noties.markwon.core.CorePlugin; -import ru.noties.markwon.core.MarkwonTheme; -import ru.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import ru.noties.markwon.ext.tables.TablePlugin; -import ru.noties.markwon.ext.tables.TableTheme; -import ru.noties.markwon.ext.tasklist.TaskListPlugin; -import ru.noties.markwon.html.HtmlPlugin; -import ru.noties.markwon.image.ImagesPlugin; -import ru.noties.markwon.image.gif.GifPlugin; -import ru.noties.markwon.image.okhttp.OkHttpImagesPlugin; +import io.noties.markwon.AbstractMarkwonPlugin; +import io.noties.markwon.Markwon; +import io.noties.markwon.core.CorePlugin; +import io.noties.markwon.core.MarkwonTheme; +import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; +import io.noties.markwon.ext.tables.TablePlugin; +import io.noties.markwon.ext.tasklist.TaskListPlugin; +import io.noties.markwon.html.HtmlPlugin; +import io.noties.markwon.image.AsyncDrawable; +import io.noties.markwon.image.DefaultMediaDecoder; +import io.noties.markwon.image.ImageItem; +import io.noties.markwon.image.ImagesPlugin; +import io.noties.markwon.image.SchemeHandler; +import io.noties.markwon.image.gif.GifMediaDecoder; +import io.noties.markwon.image.svg.SvgMediaDecoder; +import io.noties.markwon.linkify.LinkifyPlugin; /** * Author M M Arif @@ -185,8 +193,38 @@ public class ClosedIssuesAdapter extends RecyclerView.Adapter supportedSchemes() { + return Collections.singleton("drawable"); + } + }); + plugin.addMediaDecoder(GifMediaDecoder.create(false)); + plugin.addMediaDecoder(SvgMediaDecoder.create(context.getResources())); + plugin.addMediaDecoder(SvgMediaDecoder.create()); + plugin.defaultMediaDecoder(DefaultMediaDecoder.create(context.getResources())); + plugin.defaultMediaDecoder(DefaultMediaDecoder.create()); + } + })) .usePlugin(new AbstractMarkwonPlugin() { @Override public void configureTheme(@NonNull MarkwonTheme.Builder builder) { @@ -196,11 +234,23 @@ public class ClosedIssuesAdapter extends RecyclerView.Adapter supportedSchemes() { + return Collections.singleton("drawable"); + } + }); + plugin.addMediaDecoder(GifMediaDecoder.create(false)); + plugin.addMediaDecoder(SvgMediaDecoder.create(mCtx.getResources())); + plugin.addMediaDecoder(SvgMediaDecoder.create()); + plugin.defaultMediaDecoder(DefaultMediaDecoder.create(mCtx.getResources())); + plugin.defaultMediaDecoder(DefaultMediaDecoder.create()); + } + })) .usePlugin(new AbstractMarkwonPlugin() { @Override public void configureTheme(@NonNull MarkwonTheme.Builder builder) { builder .codeTextColor(tinyDb.getInt("codeBlockColor")) - .codeBackgroundColor(tinyDb.getInt("codeBlockBackground")); + .codeBackgroundColor(tinyDb.getInt("codeBlockBackground")) + .linkColor(mCtx.getResources().getColor(R.color.lightBlue)); } }) + .usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() { + @Override + public void configureImages(@NonNull ImagesPlugin plugin) { + plugin.placeholderProvider(new ImagesPlugin.PlaceholderProvider() { + @Nullable + @Override + public Drawable providePlaceholder(@NonNull AsyncDrawable drawable) { + return null; + } + }); + } + })) .usePlugin(TablePlugin.create(mCtx)) .usePlugin(TaskListPlugin.create(mCtx)) .usePlugin(HtmlPlugin.create()) - .usePlugin(GifPlugin.create()) .usePlugin(StrikethroughPlugin.create()) + .usePlugin(LinkifyPlugin.create()) .build(); - final CharSequence bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(cleanIssueComments)); - holder.issueComment.setText(UserMentions.UserMentionsFunc(mCtx, bodyWithMD, cleanIssueComments)); + Spanned bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(cleanIssueComments)); + markwon.setParsedMarkdown(holder.issueComment, bodyWithMD); String edited; diff --git a/app/src/main/java/org/mian/gitnex/adapters/IssuesAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/IssuesAdapter.java index 645b80f4..5a872ef8 100644 --- a/app/src/main/java/org/mian/gitnex/adapters/IssuesAdapter.java +++ b/app/src/main/java/org/mian/gitnex/adapters/IssuesAdapter.java @@ -3,7 +3,9 @@ package org.mian.gitnex.adapters; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; -import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.text.Spanned; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -25,24 +27,30 @@ import org.ocpsoft.prettytime.PrettyTime; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Objects; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.recyclerview.widget.RecyclerView; -import okhttp3.OkHttpClient; -import ru.noties.markwon.AbstractMarkwonPlugin; -import ru.noties.markwon.Markwon; -import ru.noties.markwon.core.CorePlugin; -import ru.noties.markwon.core.MarkwonTheme; -import ru.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import ru.noties.markwon.ext.tables.TablePlugin; -import ru.noties.markwon.ext.tables.TableTheme; -import ru.noties.markwon.ext.tasklist.TaskListPlugin; -import ru.noties.markwon.html.HtmlPlugin; -import ru.noties.markwon.image.ImagesPlugin; -import ru.noties.markwon.image.gif.GifPlugin; -import ru.noties.markwon.image.okhttp.OkHttpImagesPlugin; +import io.noties.markwon.AbstractMarkwonPlugin; +import io.noties.markwon.Markwon; +import io.noties.markwon.core.CorePlugin; +import io.noties.markwon.core.MarkwonTheme; +import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; +import io.noties.markwon.ext.tables.TablePlugin; +import io.noties.markwon.ext.tasklist.TaskListPlugin; +import io.noties.markwon.html.HtmlPlugin; +import io.noties.markwon.image.AsyncDrawable; +import io.noties.markwon.image.DefaultMediaDecoder; +import io.noties.markwon.image.ImageItem; +import io.noties.markwon.image.ImagesPlugin; +import io.noties.markwon.image.SchemeHandler; +import io.noties.markwon.image.gif.GifMediaDecoder; +import io.noties.markwon.image.svg.SvgMediaDecoder; +import io.noties.markwon.linkify.LinkifyPlugin; /** * Author M M Arif @@ -185,8 +193,38 @@ public class IssuesAdapter extends RecyclerView.Adapter final Markwon markwon = Markwon.builder(Objects.requireNonNull(context)) .usePlugin(CorePlugin.create()) - .usePlugin(OkHttpImagesPlugin.create(new OkHttpClient())) - .usePlugin(ImagesPlugin.createWithAssets(context)) + .usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() { + @Override + public void configureImages(@NonNull ImagesPlugin plugin) { + plugin.addSchemeHandler(new SchemeHandler() { + @NonNull + @Override + public ImageItem handle(@NonNull String raw, @NonNull Uri uri) { + + final int resourceId = context.getResources().getIdentifier( + raw.substring("drawable://".length()), + "drawable", + context.getPackageName()); + + final Drawable drawable = context.getDrawable(resourceId); + + assert drawable != null; + return ImageItem.withResult(drawable); + } + + @NonNull + @Override + public Collection supportedSchemes() { + return Collections.singleton("drawable"); + } + }); + plugin.addMediaDecoder(GifMediaDecoder.create(false)); + plugin.addMediaDecoder(SvgMediaDecoder.create(context.getResources())); + plugin.addMediaDecoder(SvgMediaDecoder.create()); + plugin.defaultMediaDecoder(DefaultMediaDecoder.create(context.getResources())); + plugin.defaultMediaDecoder(DefaultMediaDecoder.create()); + } + })) .usePlugin(new AbstractMarkwonPlugin() { @Override public void configureTheme(@NonNull MarkwonTheme.Builder builder) { @@ -196,11 +234,23 @@ public class IssuesAdapter extends RecyclerView.Adapter .linkColor(context.getResources().getColor(R.color.lightBlue)); } }) + .usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() { + @Override + public void configureImages(@NonNull ImagesPlugin plugin) { + plugin.placeholderProvider(new ImagesPlugin.PlaceholderProvider() { + @Nullable + @Override + public Drawable providePlaceholder(@NonNull AsyncDrawable drawable) { + return null; + } + }); + } + })) .usePlugin(TablePlugin.create(context)) .usePlugin(TaskListPlugin.create(context)) .usePlugin(HtmlPlugin.create()) - .usePlugin(GifPlugin.create()) .usePlugin(StrikethroughPlugin.create()) + .usePlugin(LinkifyPlugin.create()) .build(); if (!issuesModel.getUser().getFull_name().equals("")) { @@ -230,8 +280,8 @@ public class IssuesAdapter extends RecyclerView.Adapter if (!issuesModel.getBody().equals("")) { String cleanIssueDescription = issuesModel.getBody().trim(); issueDescription.setVisibility(View.VISIBLE); - final CharSequence bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(cleanIssueDescription)); - issueDescription.setText(UserMentions.UserMentionsFunc(context, bodyWithMD, cleanIssueDescription)); + Spanned bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(cleanIssueDescription)); + markwon.setParsedMarkdown(issueDescription, UserMentions.UserMentionsFunc(context, bodyWithMD, cleanIssueDescription)); } else { issueDescription.setText(""); diff --git a/app/src/main/java/org/mian/gitnex/adapters/MilestonesAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/MilestonesAdapter.java index 5690094f..20e71616 100644 --- a/app/src/main/java/org/mian/gitnex/adapters/MilestonesAdapter.java +++ b/app/src/main/java/org/mian/gitnex/adapters/MilestonesAdapter.java @@ -3,6 +3,9 @@ package org.mian.gitnex.adapters; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.text.Spanned; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -22,25 +25,31 @@ import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Objects; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.recyclerview.widget.RecyclerView; -import okhttp3.OkHttpClient; -import ru.noties.markwon.AbstractMarkwonPlugin; -import ru.noties.markwon.Markwon; -import ru.noties.markwon.core.CorePlugin; -import ru.noties.markwon.core.MarkwonTheme; -import ru.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import ru.noties.markwon.ext.tables.TablePlugin; -import ru.noties.markwon.ext.tables.TableTheme; -import ru.noties.markwon.ext.tasklist.TaskListPlugin; -import ru.noties.markwon.html.HtmlPlugin; -import ru.noties.markwon.image.ImagesPlugin; -import ru.noties.markwon.image.gif.GifPlugin; -import ru.noties.markwon.image.okhttp.OkHttpImagesPlugin; +import io.noties.markwon.AbstractMarkwonPlugin; +import io.noties.markwon.Markwon; +import io.noties.markwon.core.CorePlugin; +import io.noties.markwon.core.MarkwonTheme; +import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; +import io.noties.markwon.ext.tables.TablePlugin; +import io.noties.markwon.ext.tasklist.TaskListPlugin; +import io.noties.markwon.html.HtmlPlugin; +import io.noties.markwon.image.AsyncDrawable; +import io.noties.markwon.image.DefaultMediaDecoder; +import io.noties.markwon.image.ImageItem; +import io.noties.markwon.image.ImagesPlugin; +import io.noties.markwon.image.SchemeHandler; +import io.noties.markwon.image.gif.GifMediaDecoder; +import io.noties.markwon.image.svg.SvgMediaDecoder; +import io.noties.markwon.linkify.LinkifyPlugin; /** * Author M M Arif @@ -116,8 +125,38 @@ public class MilestonesAdapter extends RecyclerView.Adapter supportedSchemes() { + return Collections.singleton("drawable"); + } + }); + plugin.addMediaDecoder(GifMediaDecoder.create(false)); + plugin.addMediaDecoder(SvgMediaDecoder.create(mCtx.getResources())); + plugin.addMediaDecoder(SvgMediaDecoder.create()); + plugin.defaultMediaDecoder(DefaultMediaDecoder.create(mCtx.getResources())); + plugin.defaultMediaDecoder(DefaultMediaDecoder.create()); + } + })) .usePlugin(new AbstractMarkwonPlugin() { @Override public void configureTheme(@NonNull MarkwonTheme.Builder builder) { @@ -127,14 +166,27 @@ public class MilestonesAdapter extends RecyclerView.Adapter supportedSchemes() { + return Collections.singleton("drawable"); + } + }); + plugin.addMediaDecoder(GifMediaDecoder.create(false)); + plugin.addMediaDecoder(SvgMediaDecoder.create(mCtx.getResources())); + plugin.addMediaDecoder(SvgMediaDecoder.create()); + plugin.defaultMediaDecoder(DefaultMediaDecoder.create(mCtx.getResources())); + plugin.defaultMediaDecoder(DefaultMediaDecoder.create()); + } + })) .usePlugin(new AbstractMarkwonPlugin() { @Override public void configureTheme(@NonNull MarkwonTheme.Builder builder) { builder - .codeTextColor(Color.GREEN) - .codeBackgroundColor(Color.BLACK) + .codeTextColor(tinyDb.getInt("codeBlockColor")) + .codeBackgroundColor(tinyDb.getInt("codeBlockBackground")) .linkColor(mCtx.getResources().getColor(R.color.lightBlue)); } }) + .usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() { + @Override + public void configureImages(@NonNull ImagesPlugin plugin) { + plugin.placeholderProvider(new ImagesPlugin.PlaceholderProvider() { + @Nullable + @Override + public Drawable providePlaceholder(@NonNull AsyncDrawable drawable) { + return null; + } + }); + } + })) .usePlugin(TablePlugin.create(mCtx)) .usePlugin(TaskListPlugin.create(mCtx)) .usePlugin(HtmlPlugin.create()) - .usePlugin(GifPlugin.create()) .usePlugin(StrikethroughPlugin.create()) + .usePlugin(LinkifyPlugin.create()) .build(); - final CharSequence bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(currentItem.getBody())); + Spanned bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(currentItem.getBody())); if(!currentItem.getBody().equals("")) { - holder.releaseDescription.setText(bodyWithMD); + markwon.setParsedMarkdown(holder.releaseDescription, bodyWithMD); } else { holder.releaseDescription.setVisibility(View.GONE); diff --git a/app/src/main/java/org/mian/gitnex/fragments/RepoInfoFragment.java b/app/src/main/java/org/mian/gitnex/fragments/RepoInfoFragment.java index 7bbac01e..00d6b2d2 100644 --- a/app/src/main/java/org/mian/gitnex/fragments/RepoInfoFragment.java +++ b/app/src/main/java/org/mian/gitnex/fragments/RepoInfoFragment.java @@ -1,24 +1,31 @@ package org.mian.gitnex.fragments; import android.content.Context; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; -import okhttp3.OkHttpClient; +import io.noties.markwon.AbstractMarkwonPlugin; +import io.noties.markwon.Markwon; +import io.noties.markwon.core.CorePlugin; +import io.noties.markwon.core.MarkwonTheme; +import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; +import io.noties.markwon.ext.tables.TablePlugin; +import io.noties.markwon.ext.tasklist.TaskListPlugin; +import io.noties.markwon.html.HtmlPlugin; +import io.noties.markwon.image.AsyncDrawable; +import io.noties.markwon.image.DefaultMediaDecoder; +import io.noties.markwon.image.ImageItem; +import io.noties.markwon.image.ImagesPlugin; +import io.noties.markwon.image.SchemeHandler; +import io.noties.markwon.image.gif.GifMediaDecoder; +import io.noties.markwon.image.svg.SvgMediaDecoder; +import io.noties.markwon.linkify.LinkifyPlugin; import retrofit2.Call; import retrofit2.Callback; -import ru.noties.markwon.AbstractMarkwonPlugin; -import ru.noties.markwon.Markwon; -import ru.noties.markwon.core.CorePlugin; -import ru.noties.markwon.core.MarkwonTheme; -import ru.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import ru.noties.markwon.ext.tables.TablePlugin; -import ru.noties.markwon.ext.tasklist.TaskListPlugin; -import ru.noties.markwon.html.HtmlPlugin; -import ru.noties.markwon.image.ImagesPlugin; -import ru.noties.markwon.image.gif.GifPlugin; -import ru.noties.markwon.image.okhttp.OkHttpImagesPlugin; +import android.text.Spanned; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -40,6 +47,8 @@ import org.mian.gitnex.util.TinyDB; import org.ocpsoft.prettytime.PrettyTime; import java.text.DateFormat; import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Collections; import java.util.Locale; import java.util.Objects; @@ -299,30 +308,73 @@ public class RepoInfoFragment extends Fragment { if (response.code() == 200) { final Markwon markwon = Markwon.builder(Objects.requireNonNull(getContext())) - .usePlugin(CorePlugin.create()) - .usePlugin(OkHttpImagesPlugin.create(new OkHttpClient())) - .usePlugin(ImagesPlugin.createWithAssets(getContext())) - .usePlugin(new AbstractMarkwonPlugin() { - @Override - public void configureTheme(@NonNull MarkwonTheme.Builder builder) { - builder - .codeTextColor(tinyDb.getInt("codeBlockColor")) - .codeBackgroundColor(tinyDb.getInt("codeBlockBackground")) - .linkColor(getResources().getColor(R.color.lightBlue)); - } - }) - .usePlugin(TablePlugin.create(getContext())) - .usePlugin(TaskListPlugin.create(getContext())) - .usePlugin(HtmlPlugin.create()) - .usePlugin(GifPlugin.create()) - .usePlugin(StrikethroughPlugin.create()) - .build(); + .usePlugin(CorePlugin.create()) + .usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() { + @Override + public void configureImages(@NonNull ImagesPlugin plugin) { + plugin.addSchemeHandler(new SchemeHandler() { + @NonNull + @Override + public ImageItem handle(@NonNull String raw, @NonNull Uri uri) { - CharSequence bodyWithMD = null; + final int resourceId = getContext().getResources().getIdentifier( + raw.substring("drawable://".length()), + "drawable", + getContext().getPackageName()); + + final Drawable drawable = getContext().getDrawable(resourceId); + + assert drawable != null; + return ImageItem.withResult(drawable); + } + + @NonNull + @Override + public Collection supportedSchemes() { + return Collections.singleton("drawable"); + } + }); + plugin.addMediaDecoder(GifMediaDecoder.create(false)); + plugin.addMediaDecoder(SvgMediaDecoder.create(getContext().getResources())); + plugin.addMediaDecoder(SvgMediaDecoder.create()); + plugin.defaultMediaDecoder(DefaultMediaDecoder.create(getContext().getResources())); + plugin.defaultMediaDecoder(DefaultMediaDecoder.create()); + } + })) + .usePlugin(new AbstractMarkwonPlugin() { + @Override + public void configureTheme(@NonNull MarkwonTheme.Builder builder) { + builder + .codeTextColor(tinyDb.getInt("codeBlockColor")) + .codeBackgroundColor(tinyDb.getInt("codeBlockBackground")) + .linkColor(getResources().getColor(R.color.lightBlue)); + } + }) + .usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() { + @Override + public void configureImages(@NonNull ImagesPlugin plugin) { + plugin.placeholderProvider(new ImagesPlugin.PlaceholderProvider() { + @Nullable + @Override + public Drawable providePlaceholder(@NonNull AsyncDrawable drawable) { + return null; + } + }); + } + })) + .usePlugin(TablePlugin.create(getContext())) + .usePlugin(TaskListPlugin.create(getContext())) + .usePlugin(HtmlPlugin.create()) + .usePlugin(StrikethroughPlugin.create()) + .usePlugin(LinkifyPlugin.create()) + .build(); + + Spanned bodyWithMD = null; if (response.body() != null) { bodyWithMD = markwon.toMarkdown(response.body()); } - repoFileContents.setText(bodyWithMD); + assert bodyWithMD != null; + markwon.setParsedMarkdown(repoFileContents, bodyWithMD); } else if (response.code() == 401) {