From ffc2d669e5fbefbb73c6987dbe4ccf9406ce5777 Mon Sep 17 00:00:00 2001 From: Balazs Toldi Date: Thu, 3 Aug 2023 13:50:51 +0200 Subject: [PATCH] Show images in comments and post Replace image links in posts and comments with actual images. --- app/build.gradle | 5 +- .../activities/CommentActivity.java | 4 +- .../activities/EditCommentActivity.java | 4 +- .../activities/EditPostActivity.java | 4 +- .../activities/PostImageActivity.java | 4 +- .../activities/PostLinkActivity.java | 4 +- .../activities/PostTextActivity.java | 4 +- .../adapters/MessageRecyclerViewAdapter.java | 4 +- .../comment/ParseComment.java | 3 +- .../markdown/ClickableGlideImagesPlugin.java | 59 +++++++++++++++++++ .../markdown/MarkdownUtils.java | 47 ++++----------- .../infinityforlemmy/post/ParsePost.java | 7 ++- .../toldi/infinityforlemmy/utils/Utils.java | 4 +- 13 files changed, 96 insertions(+), 57 deletions(-) create mode 100644 app/src/main/java/eu/toldi/infinityforlemmy/markdown/ClickableGlideImagesPlugin.java diff --git a/app/build.gradle b/app/build.gradle index 25ecfd4c..250794d5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId "eu.toldi.infinityforlemmy" minSdk 21 targetSdk 33 - versionCode 126 - versionName "0.0.6" + versionCode 128 + versionName "0.0.8" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" javaCompileOptions { annotationProcessorOptions { @@ -169,6 +169,7 @@ dependencies { implementation "io.noties.markwon:recycler-table:$markwonVersion" implementation "io.noties.markwon:simple-ext:$markwonVersion" implementation "io.noties.markwon:inline-parser:$markwonVersion" + implementation "io.noties.markwon:image-glide:$markwonVersion" implementation 'com.atlassian.commonmark:commonmark-ext-gfm-tables:0.14.0' implementation 'me.saket:better-link-movement-method:2.2.0' diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/activities/CommentActivity.java b/app/src/main/java/eu/toldi/infinityforlemmy/activities/CommentActivity.java index 00874037..b6e3f770 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/activities/CommentActivity.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/activities/CommentActivity.java @@ -513,8 +513,8 @@ public class CommentActivity extends BaseActivity implements UploadImageEnabledA int start = Math.max(binding.commentCommentEditText.getSelectionStart(), 0); int end = Math.max(binding.commentCommentEditText.getSelectionEnd(), 0); binding.commentCommentEditText.getText().replace(Math.min(start, end), Math.max(start, end), - "[" + uploadedImage.imageName + "](" + uploadedImage.imageUrl + ")", - 0, "[]()".length() + uploadedImage.imageName.length() + uploadedImage.imageUrl.length()); + "![" + uploadedImage.imageName + "](" + uploadedImage.imageUrl + ")", + 0, "![]()".length() + uploadedImage.imageName.length() + uploadedImage.imageUrl.length()); } @Override diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/activities/EditCommentActivity.java b/app/src/main/java/eu/toldi/infinityforlemmy/activities/EditCommentActivity.java index f6ce56bc..32fbf00d 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/activities/EditCommentActivity.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/activities/EditCommentActivity.java @@ -345,7 +345,7 @@ public class EditCommentActivity extends BaseActivity implements UploadImageEnab int start = Math.max(contentEditText.getSelectionStart(), 0); int end = Math.max(contentEditText.getSelectionEnd(), 0); contentEditText.getText().replace(Math.min(start, end), Math.max(start, end), - "[" + uploadedImage.imageName + "](" + uploadedImage.imageUrl + ")", - 0, "[]()".length() + uploadedImage.imageName.length() + uploadedImage.imageUrl.length()); + "![" + uploadedImage.imageName + "](" + uploadedImage.imageUrl + ")", + 0, "![]()".length() + uploadedImage.imageName.length() + uploadedImage.imageUrl.length()); } } diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/activities/EditPostActivity.java b/app/src/main/java/eu/toldi/infinityforlemmy/activities/EditPostActivity.java index 198026c5..150c80fb 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/activities/EditPostActivity.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/activities/EditPostActivity.java @@ -456,7 +456,7 @@ public class EditPostActivity extends BaseActivity implements UploadImageEnabled int start = Math.max(contentEditText.getSelectionStart(), 0); int end = Math.max(contentEditText.getSelectionEnd(), 0); contentEditText.getText().replace(Math.min(start, end), Math.max(start, end), - "[" + uploadedImage.imageName + "](" + uploadedImage.imageUrl + ")", - 0, "[]()".length() + uploadedImage.imageName.length() + uploadedImage.imageUrl.length()); + "![" + uploadedImage.imageName + "](" + uploadedImage.imageUrl + ")", + 0, "![]()".length() + uploadedImage.imageName.length() + uploadedImage.imageUrl.length()); } } diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/activities/PostImageActivity.java b/app/src/main/java/eu/toldi/infinityforlemmy/activities/PostImageActivity.java index ae151664..1a6e0aad 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/activities/PostImageActivity.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/activities/PostImageActivity.java @@ -792,7 +792,7 @@ public class PostImageActivity extends BaseActivity implements FlairBottomSheetF int start = Math.max(contentEditText.getSelectionStart(), 0); int end = Math.max(contentEditText.getSelectionEnd(), 0); contentEditText.getText().replace(Math.min(start, end), Math.max(start, end), - "[" + uploadedImage.imageName + "](" + uploadedImage.imageUrl + ")", - 0, "[]()".length() + uploadedImage.imageName.length() + uploadedImage.imageUrl.length()); + "![" + uploadedImage.imageName + "](" + uploadedImage.imageUrl + ")", + 0, "![]()".length() + uploadedImage.imageName.length() + uploadedImage.imageUrl.length()); } } diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/activities/PostLinkActivity.java b/app/src/main/java/eu/toldi/infinityforlemmy/activities/PostLinkActivity.java index 14c4d99a..48335d42 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/activities/PostLinkActivity.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/activities/PostLinkActivity.java @@ -722,7 +722,7 @@ public class PostLinkActivity extends BaseActivity implements FlairBottomSheetFr int start = Math.max(contentEditText.getSelectionStart(), 0); int end = Math.max(contentEditText.getSelectionEnd(), 0); contentEditText.getText().replace(Math.min(start, end), Math.max(start, end), - "[" + uploadedImage.imageName + "](" + uploadedImage.imageUrl + ")", - 0, "[]()".length() + uploadedImage.imageName.length() + uploadedImage.imageUrl.length()); + "![" + uploadedImage.imageName + "](" + uploadedImage.imageUrl + ")", + 0, "![]()".length() + uploadedImage.imageName.length() + uploadedImage.imageUrl.length()); } } diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/activities/PostTextActivity.java b/app/src/main/java/eu/toldi/infinityforlemmy/activities/PostTextActivity.java index 49b6bd62..c49413eb 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/activities/PostTextActivity.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/activities/PostTextActivity.java @@ -673,8 +673,8 @@ public class PostTextActivity extends BaseActivity implements FlairBottomSheetFr int start = Math.max(contentEditText.getSelectionStart(), 0); int end = Math.max(contentEditText.getSelectionEnd(), 0); contentEditText.getText().replace(Math.min(start, end), Math.max(start, end), - "[" + uploadedImage.imageName + "](" + uploadedImage.imageUrl + ")", - 0, "[]()".length() + uploadedImage.imageName.length() + uploadedImage.imageUrl.length()); + "![" + uploadedImage.imageName + "](" + uploadedImage.imageUrl + ")", + 0, "![]()".length() + uploadedImage.imageName.length() + uploadedImage.imageUrl.length()); } @Override diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/adapters/MessageRecyclerViewAdapter.java b/app/src/main/java/eu/toldi/infinityforlemmy/adapters/MessageRecyclerViewAdapter.java index e8164232..8096414c 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/adapters/MessageRecyclerViewAdapter.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/adapters/MessageRecyclerViewAdapter.java @@ -42,7 +42,7 @@ import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import io.noties.markwon.inlineparser.BangInlineProcessor; +import io.noties.markwon.image.glide.GlideImagesPlugin; import io.noties.markwon.inlineparser.HtmlInlineProcessor; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; import io.noties.markwon.linkify.LinkifyPlugin; @@ -105,7 +105,6 @@ public class MessageRecyclerViewAdapter extends PagedListAdapter { plugin.excludeInlineProcessor(HtmlInlineProcessor.class); - plugin.excludeInlineProcessor(BangInlineProcessor.class); })) .usePlugin(new AbstractMarkwonPlugin() { @Override @@ -129,6 +128,7 @@ public class MessageRecyclerViewAdapter extends PagedListAdapter { plugin.excludeInlineProcessor(HtmlInlineProcessor.class); - plugin.excludeInlineProcessor(BangInlineProcessor.class); })) .usePlugin(miscPlugin) .usePlugin(SuperscriptPlugin.create()) @@ -51,6 +51,7 @@ public class MarkdownUtils { .setOnLinkLongClickListener(onLinkLongClickListener))) .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) .usePlugin(TableEntryPlugin.create(context)) + .usePlugin(ClickableGlideImagesPlugin.create(context)) .build(); } @@ -60,7 +61,6 @@ public class MarkdownUtils { return Markwon.builder(context) .usePlugin(MarkwonInlineParserPlugin.create(plugin -> { plugin.excludeInlineProcessor(HtmlInlineProcessor.class); - plugin.excludeInlineProcessor(BangInlineProcessor.class); })) .usePlugin(miscPlugin) .usePlugin(SuperscriptPlugin.create()) @@ -70,6 +70,7 @@ public class MarkdownUtils { .setOnLinkLongClickListener(onLinkLongClickListener))) .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) .usePlugin(TableEntryPlugin.create(context)) + .usePlugin(GlideImagesPlugin.create(context)) .build(); } @@ -104,6 +105,15 @@ public class MarkdownUtils { .build(); } + @NonNull + public static MarkwonAdapter createTablesAndImagesAdapter(@NonNull Context context) { + return MarkwonAdapter.builder(R.layout.adapter_default_entry, R.id.text) + .include(TableBlock.class, TableEntry.create(builder -> builder + .tableLayout(R.layout.adapter_table_block, R.id.table_layout) + .textLayoutIsRoot(R.layout.view_table_entry_cell))) + .build(); + } + /** * Creates a CustomMarkwonAdapter configured with support for tables. */ @@ -119,35 +129,4 @@ public class MarkdownUtils { private static final Pattern emptyPattern = Pattern.compile("!\\[\\]\\((.*?)\\)"); private static final Pattern nonEmptyPattern = Pattern.compile("!\\[(.*?)\\]\\((.*?)\\)"); - public static String processImageCaptions(String markdown, String replacementCaption) { - // Pattern for Markdown images with empty captions - - // Pattern for Markdown images with non-empty captions - - - Matcher emptyMatcher = emptyPattern.matcher(markdown); - StringBuffer sb = new StringBuffer(); - - while (emptyMatcher.find()) { - // Replace the matched pattern with the same URL, but with a caption - emptyMatcher.appendReplacement(sb, "[" + replacementCaption + "](" + emptyMatcher.group(1) + ")"); - } - - // Append the rest of the content - emptyMatcher.appendTail(sb); - - // Now process non-empty captions - Matcher nonEmptyMatcher = nonEmptyPattern.matcher(sb.toString()); - StringBuffer finalSb = new StringBuffer(); - - while (nonEmptyMatcher.find()) { - // Replace the matched pattern with the same URL and caption, but without the "!" - nonEmptyMatcher.appendReplacement(finalSb, "[" + nonEmptyMatcher.group(1) + "](" + nonEmptyMatcher.group(2) + ")"); - } - - // Append the rest of the content - nonEmptyMatcher.appendTail(finalSb); - - return finalSb.toString(); - } } diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/post/ParsePost.java b/app/src/main/java/eu/toldi/infinityforlemmy/post/ParsePost.java index 92b5222a..ed7354d6 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/post/ParsePost.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/post/ParsePost.java @@ -214,6 +214,7 @@ public class ParsePost { String url = (!data.getJSONObject("post").isNull("url")) ? data.getJSONObject("post").getString("url") : ""; String communityURL = (!data.getJSONObject("community").isNull("icon")) ? data.getJSONObject("community").getString("icon") : ""; + String authorAvatar = (!data.getJSONObject("creator").isNull("avatar")) ? data.getJSONObject("creator").getString("avatar") : null; Uri uri = Uri.parse(url); String path = uri.getPath(); @@ -654,14 +655,14 @@ public class ParsePost { post.setVoteType(data.getInt("my_vote")); post.setScore(post.getScore() - 1); } - - if (!data.getJSONObject("post").isNull("body")) { - String body = MarkdownUtils.processImageCaptions(data.getJSONObject("post").getString("body"), "Image"); + String body = data.getJSONObject("post").getString("body"); post.setSelfText(body); post.setSelfTextPlain(body); post.setSelfTextPlainTrimmed(body.trim()); } + + post.setAuthorIconUrl(authorAvatar); post.setSubredditIconUrl(communityURL); return post; } diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/utils/Utils.java b/app/src/main/java/eu/toldi/infinityforlemmy/utils/Utils.java index d20a7ae6..8fb71951 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/utils/Utils.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/utils/Utils.java @@ -382,8 +382,8 @@ public final class Utils { int start = Math.max(editText.getSelectionStart(), 0); int end = Math.max(editText.getSelectionEnd(), 0); editText.getText().replace(Math.min(start, end), Math.max(start, end), - "[" + fileName + "](" + imageUrlOrError + ")", - 0, "[]()".length() + fileName.length() + imageUrlOrError.length()); + "![" + fileName + "](" + imageUrlOrError + ")", + 0, "![]()".length() + fileName.length() + imageUrlOrError.length()); Snackbar.make(coordinatorLayout, R.string.upload_image_success, Snackbar.LENGTH_LONG).show(); } else { Toast.makeText(context, R.string.upload_image_failed, Toast.LENGTH_LONG).show();