From 6790158ed960ad25a55135870aac08bb1da4571a Mon Sep 17 00:00:00 2001 From: Thomas Date: Sun, 6 Aug 2023 18:13:08 +0200 Subject: [PATCH] Support Markdown --- app/build.gradle | 2 + .../entities/app/MarkdownConverter.java | 41 +++++++++++++++++++ .../mastodon/helper/SpannableHelper.java | 40 +++++++++++++++++- 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/app/fedilab/android/mastodon/client/entities/app/MarkdownConverter.java diff --git a/app/build.gradle b/app/build.gradle index cab8fabe1..beb7c2618 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -185,6 +185,8 @@ dependencies { implementation 'com.github.vkay94:DoubleTapPlayerView:1.0.0' + implementation 'io.noties.markwon:core:4.6.2' + //************ CAST **************/// //---> Google libs (google_full) diff --git a/app/src/main/java/app/fedilab/android/mastodon/client/entities/app/MarkdownConverter.java b/app/src/main/java/app/fedilab/android/mastodon/client/entities/app/MarkdownConverter.java new file mode 100644 index 000000000..54dd38d58 --- /dev/null +++ b/app/src/main/java/app/fedilab/android/mastodon/client/entities/app/MarkdownConverter.java @@ -0,0 +1,41 @@ +package app.fedilab.android.mastodon.client.entities.app; +/* Copyright 2023 Thomas Schneider + * + * This file is a part of Fedilab + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Fedilab; if not, + * see . */ + +import android.text.style.URLSpan; + +import java.util.List; + +public class MarkdownConverter { + + public List markdownItems; + + public MarkdownItem getByPosition(int position) { + if (markdownItems != null && markdownItems.size() > 0 && position < markdownItems.size()) { + for (MarkdownItem markdownItem : markdownItems) { + if (markdownItem.position == position) { + return markdownItem; + } + } + } + return null; + } + + public static class MarkdownItem { + public String code; + public int position; + public URLSpan urlSpan; + } +} diff --git a/app/src/main/java/app/fedilab/android/mastodon/helper/SpannableHelper.java b/app/src/main/java/app/fedilab/android/mastodon/helper/SpannableHelper.java index 00549a0dc..50c4d847c 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/helper/SpannableHelper.java +++ b/app/src/main/java/app/fedilab/android/mastodon/helper/SpannableHelper.java @@ -84,9 +84,11 @@ import app.fedilab.android.mastodon.client.entities.api.Emoji; import app.fedilab.android.mastodon.client.entities.api.Filter; import app.fedilab.android.mastodon.client.entities.api.Mention; import app.fedilab.android.mastodon.client.entities.api.Status; +import app.fedilab.android.mastodon.client.entities.app.MarkdownConverter; import app.fedilab.android.mastodon.ui.drawer.StatusAdapter; import app.fedilab.android.mastodon.viewmodel.mastodon.FiltersVM; import es.dmoral.toasty.Toasty; +import io.noties.markwon.Markwon; public class SpannableHelper { @@ -149,7 +151,43 @@ public class SpannableHelper { } //Get all links - SpannableStringBuilder content = new SpannableStringBuilder(initialContent); + MarkdownConverter markdownConverter = new MarkdownConverter(); + markdownConverter.markdownItems = new ArrayList<>(); + int next; + int position = 0; + for (int i = 0; i < initialContent.length(); i = next) { + // find the next span transition + next = initialContent.nextSpanTransition(i, initialContent.length(), URLSpan.class); + MarkdownConverter.MarkdownItem markdownItem = new MarkdownConverter.MarkdownItem(); + markdownItem.code = initialContent.subSequence(i, next).toString(); + + markdownItem.position = position; + // get all spans in this range + URLSpan[] spans = initialContent.getSpans(i, next, URLSpan.class); + if (spans != null && spans.length > 0) { + markdownItem.urlSpan = spans[0]; + } + + if (markdownItem.code.trim().length() > 0) { + markdownConverter.markdownItems.add(markdownItem); + position++; + } + } + final Markwon markwon = Markwon.create(context); + + final Spanned markdown = markwon.toMarkdown(initialContent.toString()); + SpannableStringBuilder content = new SpannableStringBuilder(markdown); + position = 0; + for (MarkdownConverter.MarkdownItem markdownItem : markdownConverter.markdownItems) { + Pattern p = Pattern.compile("(" + Pattern.quote(markdownItem.code) + ")", Pattern.CASE_INSENSITIVE); + Matcher m = p.matcher(content); + while (m.find()) { + content.setSpan(markdownItem.urlSpan, m.start(), m.end(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + } + position++; + } + + URLSpan[] urls = content.getSpans(0, (content.length() - 1), URLSpan.class); //Loop through links for (URLSpan span : urls) {