From 3e00a7a738e57ca058aa15f32bfe5b4909109da6 Mon Sep 17 00:00:00 2001 From: Docile-Alligator <25734209+Docile-Alligator@users.noreply.github.com> Date: Sun, 10 Mar 2024 15:12:49 -0400 Subject: Uploaded image richtext_json. Enable uploading images in markdown editor. --- .../infinityforreddit/UploadedImage.java | 21 +++++-- .../activities/CommentActivity.java | 4 +- .../activities/EditCommentActivity.java | 4 +- .../activities/EditPostActivity.java | 4 +- .../activities/PostGalleryActivity.java | 2 +- .../activities/PostTextActivity.java | 7 ++- .../MarkdownBottomBarRecyclerViewAdapter.java | 2 +- .../UploadedImagesRecyclerViewAdapter.java | 2 +- .../markdown/RichTextJSONConverter.java | 12 ++++ .../markdown/UploadedImageBlock.java | 13 ++++ .../markdown/UploadedImageBlockParser.java | 70 ++++++++++++++++++++++ .../markdown/UploadedImagePlugin.java | 33 ++++++++++ .../infinityforreddit/post/SubmitPost.java | 2 +- .../infinityforreddit/utils/UploadImageUtils.java | 28 ++++++--- .../infinityforreddit/utils/Utils.java | 12 ++-- 15 files changed, 186 insertions(+), 30 deletions(-) create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/markdown/UploadedImageBlock.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/markdown/UploadedImageBlockParser.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/markdown/UploadedImagePlugin.java (limited to 'app/src') diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/UploadedImage.java b/app/src/main/java/ml/docilealligator/infinityforreddit/UploadedImage.java index e3d28734..f966c934 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/UploadedImage.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/UploadedImage.java @@ -5,16 +5,26 @@ import android.os.Parcelable; public class UploadedImage implements Parcelable { public String imageName; - public String imageUrl; + public String imageUrlOrKey; + private String caption = ""; - public UploadedImage(String imageName, String imageUrl) { + public UploadedImage(String imageName, String imageUrlOrKey) { this.imageName = imageName; - this.imageUrl = imageUrl; + this.imageUrlOrKey = imageUrlOrKey; } protected UploadedImage(Parcel in) { imageName = in.readString(); - imageUrl = in.readString(); + imageUrlOrKey = in.readString(); + caption = in.readString(); + } + + public String getCaption() { + return caption == null ? "" : caption; + } + + public void setCaption(String caption) { + this.caption = caption == null ? "" : caption; } public static final Creator CREATOR = new Creator() { @@ -37,6 +47,7 @@ public class UploadedImage implements Parcelable { @Override public void writeToParcel(Parcel parcel, int i) { parcel.writeString(imageName); - parcel.writeString(imageUrl); + parcel.writeString(imageUrlOrKey); + parcel.writeString(caption); } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java index 55195475..806a3ec2 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java @@ -573,8 +573,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.imageUrlOrKey + ")", + 0, "[]()".length() + uploadedImage.imageName.length() + uploadedImage.imageUrlOrKey.length()); } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditCommentActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditCommentActivity.java index 3369da0a..9daff3ef 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditCommentActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditCommentActivity.java @@ -353,7 +353,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.imageUrlOrKey + ")", + 0, "[]()".length() + uploadedImage.imageName.length() + uploadedImage.imageUrlOrKey.length()); } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditPostActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditPostActivity.java index 9ef56da0..fb3e5261 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditPostActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditPostActivity.java @@ -357,7 +357,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.imageUrlOrKey + ")", + 0, "[]()".length() + uploadedImage.imageName.length() + uploadedImage.imageUrlOrKey.length()); } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/PostGalleryActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/PostGalleryActivity.java index e5497355..bf82df4a 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/PostGalleryActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/PostGalleryActivity.java @@ -489,7 +489,7 @@ public class PostGalleryActivity extends BaseActivity implements FlairBottomShee mExecutor.execute(() -> { try { Bitmap resource = Glide.with(PostGalleryActivity.this).asBitmap().load(imageUri).submit().get(); - String response = UploadImageUtils.uploadImage(mOauthRetrofit, mUploadMediaRetrofit, accessToken, resource, true); + String response = UploadImageUtils.uploadImage(mOauthRetrofit, mUploadMediaRetrofit, accessToken, resource, true, false); String mediaId = new JSONObject(response).getJSONObject(JSONUtils.ASSET_KEY).getString(JSONUtils.ASSET_ID_KEY); handler.post(() -> { adapter.setImageAsUploaded(mediaId); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/PostTextActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/PostTextActivity.java index c36b8ed9..2c968e68 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/PostTextActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/PostTextActivity.java @@ -532,6 +532,9 @@ public class PostTextActivity extends BaseActivity implements FlairBottomSheetFr Intent intent = new Intent(this, FullMarkdownActivity.class); intent.putExtra(FullMarkdownActivity.EXTRA_COMMENT_MARKDOWN, contentEditText.getText().toString()); intent.putExtra(FullMarkdownActivity.EXTRA_SUBMIT_POST, true); + if (!uploadedImages.isEmpty()) { + intent.putParcelableArrayListExtra("test", uploadedImages); + } startActivityForResult(intent, MARKDOWN_PREVIEW_REQUEST_CODE); } else if (itemId == R.id.action_send_post_text_activity) { submitPost(item); @@ -718,8 +721,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.getCaption() + "](" + uploadedImage.imageUrlOrKey + ")", + 0, "![]()".length() + uploadedImage.getCaption().length() + uploadedImage.imageUrlOrKey.length()); } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/MarkdownBottomBarRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/MarkdownBottomBarRecyclerViewAdapter.java index 7b74c87b..8faf9607 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/MarkdownBottomBarRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/MarkdownBottomBarRecyclerViewAdapter.java @@ -31,7 +31,7 @@ public class MarkdownBottomBarRecyclerViewAdapter extends RecyclerView.Adapter formatMap; @@ -545,6 +546,17 @@ public class RichTextJSONConverter implements Visitor { } catch (JSONException e) { throw new RuntimeException(e); } + } else if (customBlock instanceof UploadedImageBlock) { + try { + JSONObject nodeJSON = new JSONObject(); + nodeJSON.put(TYPE, IMAGE_E); + nodeJSON.put(IMAGE_ID, ((UploadedImageBlock) customBlock).uploadeImage.imageUrlOrKey); + nodeJSON.put(CONTENT, ((UploadedImageBlock) customBlock).uploadeImage.getCaption()); + + document.put(nodeJSON); + } catch (JSONException e) { + throw new RuntimeException(e); + } } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/UploadedImageBlock.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/UploadedImageBlock.java new file mode 100644 index 00000000..e6e3371c --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/UploadedImageBlock.java @@ -0,0 +1,13 @@ +package ml.docilealligator.infinityforreddit.markdown; + +import org.commonmark.node.CustomBlock; + +import ml.docilealligator.infinityforreddit.UploadedImage; + +public class UploadedImageBlock extends CustomBlock { + public UploadedImage uploadeImage; + + public UploadedImageBlock(UploadedImage uploadeImage) { + this.uploadeImage = uploadeImage; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/UploadedImageBlockParser.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/UploadedImageBlockParser.java new file mode 100644 index 00000000..26c50627 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/UploadedImageBlockParser.java @@ -0,0 +1,70 @@ +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; +import org.commonmark.parser.block.BlockContinue; +import org.commonmark.parser.block.BlockStart; +import org.commonmark.parser.block.MatchedBlockParser; +import org.commonmark.parser.block.ParserState; + +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import ml.docilealligator.infinityforreddit.UploadedImage; + +public class UploadedImageBlockParser extends AbstractBlockParser { + private final UploadedImageBlock uploadedImageBlock; + + UploadedImageBlockParser(UploadedImage uploadedImage) { + this.uploadedImageBlock = new UploadedImageBlock(uploadedImage); + } + + @Override + public Block getBlock() { + return uploadedImageBlock; + } + + @Override + public BlockContinue tryContinue(ParserState parserState) { + return null; + } + + public static class Factory extends AbstractBlockParserFactory { + private final Pattern pattern = Pattern.compile("!\\[.*]\\(\\w+\\)"); + @Nullable + private Map uploadedImageMap; + + @Override + public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockParser) { + if (uploadedImageMap == null || uploadedImageMap.isEmpty()) { + return BlockStart.none(); + } + + String line = state.getLine().toString(); + Matcher matcher = pattern.matcher(line); + if (matcher.find()) { + int startIndex = line.lastIndexOf('('); + if (startIndex > 0) { + int endIndex = line.indexOf(')', startIndex); + String id = line.substring(startIndex + 1, endIndex); + UploadedImage uploadedImage = uploadedImageMap.get(id); + if (uploadedImage != null) { + //![caption](id) + String caption = line.substring(matcher.start() + 2, startIndex - 1); + uploadedImage.setCaption(caption); + return BlockStart.of(new UploadedImageBlockParser(uploadedImage)); + } + } + } + return BlockStart.none(); + } + + public void setUploadedImageMap(@Nullable Map uploadedImageMap) { + this.uploadedImageMap = uploadedImageMap; + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/UploadedImagePlugin.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/UploadedImagePlugin.java new file mode 100644 index 00000000..bde869d1 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/UploadedImagePlugin.java @@ -0,0 +1,33 @@ +package ml.docilealligator.infinityforreddit.markdown; + +import androidx.annotation.NonNull; + +import org.commonmark.parser.Parser; + +import java.util.Map; + +import io.noties.markwon.AbstractMarkwonPlugin; +import ml.docilealligator.infinityforreddit.UploadedImage; + +public class UploadedImagePlugin extends AbstractMarkwonPlugin { + private final UploadedImageBlockParser.Factory factory; + + public UploadedImagePlugin() { + this.factory = new UploadedImageBlockParser.Factory(); + } + + @NonNull + @Override + public String processMarkdown(@NonNull String markdown) { + return super.processMarkdown(markdown); + } + + @Override + public void configureParser(@NonNull Parser.Builder builder) { + builder.customBlockParserFactory(factory); + } + + public void setUploadedImageMap(Map uploadedImageMap) { + factory.setUploadedImageMap(uploadedImageMap); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/post/SubmitPost.java b/app/src/main/java/ml/docilealligator/infinityforreddit/post/SubmitPost.java index bf6fdbda..f5bcb248 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/post/SubmitPost.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/post/SubmitPost.java @@ -88,7 +88,7 @@ public class SubmitPost { Call uploadMediaToAWS = uploadVideoToAWSApi.uploadMediaToAWS(nameValuePairsMap, fileToUpload); Response uploadMediaToAWSResponse = uploadMediaToAWS.execute(); if (uploadMediaToAWSResponse.isSuccessful()) { - String url = UploadImageUtils.parseXMLResponseFromAWS(uploadMediaToAWSResponse.body()); + String url = UploadImageUtils.parseImageFromXMLResponseFromAWS(uploadMediaToAWSResponse.body()); if (url == null) { submitPostListener.submitFailed(null); return; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/utils/UploadImageUtils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/utils/UploadImageUtils.java index e0bf7c25..848ad260 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/utils/UploadImageUtils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/utils/UploadImageUtils.java @@ -34,7 +34,15 @@ public class UploadImageUtils { @Nullable public static String uploadImage(Retrofit oauthRetrofit, Retrofit uploadMediaRetrofit, - String accessToken, Bitmap image, boolean returnResponseForGallerySubmission) throws IOException, JSONException, XmlPullParserException { + String accessToken, Bitmap image, boolean getImageKey) throws IOException, JSONException, XmlPullParserException { + return uploadImage(oauthRetrofit, uploadMediaRetrofit, accessToken, image, false, getImageKey); + } + + @Nullable + public static String uploadImage(Retrofit oauthRetrofit, Retrofit uploadMediaRetrofit, + String accessToken, Bitmap image, + boolean returnResponseForGallerySubmission, + boolean getImageKey) throws IOException, JSONException, XmlPullParserException { RedditAPI api = oauthRetrofit.create(RedditAPI.class); Map uploadImageParams = new HashMap<>(); @@ -60,7 +68,7 @@ public class UploadImageUtils { if (returnResponseForGallerySubmission) { return uploadImageResponse.body(); } - return parseXMLResponseFromAWS(uploadMediaToAWSResponse.body()); + return parseImageFromXMLResponseFromAWS(uploadMediaToAWSResponse.body(), getImageKey); } else { return "Error: " + uploadMediaToAWSResponse.code(); } @@ -70,19 +78,25 @@ public class UploadImageUtils { } @Nullable - public static String parseXMLResponseFromAWS(String response) throws XmlPullParserException, IOException { + public static String parseImageFromXMLResponseFromAWS(String response) throws XmlPullParserException, IOException { + //Get Image URL + return parseImageFromXMLResponseFromAWS(response, false); + } + + @Nullable + public static String parseImageFromXMLResponseFromAWS(String response, boolean getImageKey) throws XmlPullParserException, IOException { XmlPullParser xmlPullParser = XmlPullParserFactory.newInstance().newPullParser(); xmlPullParser.setInput(new StringReader(response)); - boolean isLocationTag = false; + boolean isKeyTag = false; int eventType = xmlPullParser.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { if (eventType == XmlPullParser.START_TAG) { - if (xmlPullParser.getName().equals("Location")) { - isLocationTag = true; + if ((xmlPullParser.getName().equals("Key") && getImageKey) || (xmlPullParser.getName().equals("Location") && !getImageKey)) { + isKeyTag = true; } } else if (eventType == XmlPullParser.TEXT) { - if (isLocationTag) { + if (isKeyTag) { return xmlPullParser.getText(); } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java index 48e8fedb..eca017a6 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java @@ -397,20 +397,20 @@ public final class Utils { executor.execute(() -> { try { Bitmap bitmap = Glide.with(context).asBitmap().load(imageUri).submit().get(); - String imageUrlOrError = UploadImageUtils.uploadImage(oauthRetrofit, uploadMediaRetrofit, accessToken, bitmap); + String imageKeyOrError = UploadImageUtils.uploadImage(oauthRetrofit, uploadMediaRetrofit, accessToken, bitmap, true); handler.post(() -> { - if (imageUrlOrError != null && !imageUrlOrError.startsWith("Error: ")) { + if (imageKeyOrError != null && !imageKeyOrError.startsWith("Error: ")) { String fileName = Utils.getFileName(context, imageUri); if (fileName == null) { - fileName = imageUrlOrError; + fileName = imageKeyOrError; } - uploadedImages.add(new UploadedImage(fileName, imageUrlOrError)); + uploadedImages.add(new UploadedImage(fileName, imageKeyOrError)); 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()); + "![](" + imageKeyOrError + ")", + 0, "![]()".length() + imageKeyOrError.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(); -- cgit v1.2.3