From 90ac11426a9334080f453d1dd6560cf34c3db040 Mon Sep 17 00:00:00 2001 From: Markus Date: Sun, 1 Aug 2021 22:28:07 +0200 Subject: [PATCH 1/4] Removed markdown meta data from notification --- .../com/github/gotify/MarkwonFactory.java | 23 +++++++++++++++++++ .../com/github/gotify/messages/Extras.java | 8 +++++-- .../gotify/messages/ListMessageAdapter.java | 15 +++--------- .../gotify/service/WebSocketService.java | 9 ++++++++ 4 files changed, 41 insertions(+), 14 deletions(-) create mode 100644 app/src/main/java/com/github/gotify/MarkwonFactory.java diff --git a/app/src/main/java/com/github/gotify/MarkwonFactory.java b/app/src/main/java/com/github/gotify/MarkwonFactory.java new file mode 100644 index 00000000..a3ea0db5 --- /dev/null +++ b/app/src/main/java/com/github/gotify/MarkwonFactory.java @@ -0,0 +1,23 @@ +package com.github.gotify; + +import android.content.Context; + +import com.squareup.picasso.Picasso; + +import io.noties.markwon.Markwon; +import io.noties.markwon.core.CorePlugin; +import io.noties.markwon.ext.tables.TableAwareMovementMethod; +import io.noties.markwon.ext.tables.TablePlugin; +import io.noties.markwon.image.picasso.PicassoImagesPlugin; +import io.noties.markwon.movement.MovementMethodPlugin; + +public class MarkwonFactory { + public static Markwon create(Context context, Picasso picasso) { + return Markwon.builder(context) + .usePlugin(CorePlugin.create()) + .usePlugin(MovementMethodPlugin.create(TableAwareMovementMethod.create())) + .usePlugin(PicassoImagesPlugin.create(picasso)) + .usePlugin(TablePlugin.create(context)) + .build(); + } +} diff --git a/app/src/main/java/com/github/gotify/messages/Extras.java b/app/src/main/java/com/github/gotify/messages/Extras.java index 3e9b8cf2..1bc26128 100644 --- a/app/src/main/java/com/github/gotify/messages/Extras.java +++ b/app/src/main/java/com/github/gotify/messages/Extras.java @@ -7,11 +7,15 @@ public final class Extras { private Extras() {} public static boolean useMarkdown(Message message) { - if (message.getExtras() == null) { + return useMarkdown(message.getExtras()); + } + + public static boolean useMarkdown(Map extras) { + if (extras == null) { return false; } - Object display = message.getExtras().get("client::display"); + Object display = extras.get("client::display"); if (!(display instanceof Map)) { return false; } diff --git a/app/src/main/java/com/github/gotify/messages/ListMessageAdapter.java b/app/src/main/java/com/github/gotify/messages/ListMessageAdapter.java index c99b613a..169fc785 100644 --- a/app/src/main/java/com/github/gotify/messages/ListMessageAdapter.java +++ b/app/src/main/java/com/github/gotify/messages/ListMessageAdapter.java @@ -18,6 +18,8 @@ import androidx.recyclerview.widget.RecyclerView; import butterknife.BindView; import butterknife.ButterKnife; + +import com.github.gotify.MarkwonFactory; import com.github.gotify.R; import com.github.gotify.Settings; import com.github.gotify.Utils; @@ -25,11 +27,6 @@ import com.github.gotify.messages.provider.MessageWithImage; import com.squareup.picasso.Picasso; import io.noties.markwon.Markwon; -import io.noties.markwon.core.CorePlugin; -import io.noties.markwon.ext.tables.TableAwareMovementMethod; -import io.noties.markwon.ext.tables.TablePlugin; -import io.noties.markwon.image.picasso.PicassoImagesPlugin; -import io.noties.markwon.movement.MovementMethodPlugin; import java.text.DateFormat; import java.util.Date; import java.util.List; @@ -60,13 +57,7 @@ public class ListMessageAdapter extends RecyclerView.Adapter Date: Wed, 4 Aug 2021 21:53:44 +0200 Subject: [PATCH 2/4] Added (limited) support for rendering markdown in notification --- .../com/github/gotify/MarkwonFactory.java | 82 ++++++++++++++++++- .../gotify/messages/ListMessageAdapter.java | 1 - .../gotify/service/WebSocketService.java | 19 +++-- 3 files changed, 88 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/github/gotify/MarkwonFactory.java b/app/src/main/java/com/github/gotify/MarkwonFactory.java index a3ea0db5..e915ae70 100644 --- a/app/src/main/java/com/github/gotify/MarkwonFactory.java +++ b/app/src/main/java/com/github/gotify/MarkwonFactory.java @@ -1,23 +1,97 @@ package com.github.gotify; import android.content.Context; - +import android.graphics.Color; +import android.graphics.Typeface; +import android.text.style.BackgroundColorSpan; +import android.text.style.BulletSpan; +import android.text.style.QuoteSpan; +import android.text.style.RelativeSizeSpan; +import android.text.style.StyleSpan; +import android.text.style.TypefaceSpan; +import androidx.annotation.NonNull; import com.squareup.picasso.Picasso; - +import io.noties.markwon.AbstractMarkwonPlugin; import io.noties.markwon.Markwon; +import io.noties.markwon.MarkwonSpansFactory; import io.noties.markwon.core.CorePlugin; +import io.noties.markwon.core.CoreProps; +import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; import io.noties.markwon.ext.tables.TableAwareMovementMethod; import io.noties.markwon.ext.tables.TablePlugin; import io.noties.markwon.image.picasso.PicassoImagesPlugin; import io.noties.markwon.movement.MovementMethodPlugin; +import org.commonmark.node.BlockQuote; +import org.commonmark.node.Code; +import org.commonmark.node.Emphasis; +import org.commonmark.node.Heading; +import org.commonmark.node.ListItem; +import org.commonmark.node.StrongEmphasis; public class MarkwonFactory { public static Markwon create(Context context, Picasso picasso) { + return createBuilderBase(context, picasso).build(); + } + + public static Markwon createForNotification(Context context, Picasso picasso) { + final float[] headingSizes = { + 2.F, 1.5F, 1.17F, 1.F, .83F, .67F, + }; + + final int bulletGapWidth = + (int) (8 * context.getResources().getDisplayMetrics().density + 0.5F); + + return createBuilderBase(context, picasso) + .usePlugin( + new AbstractMarkwonPlugin() { + @Override + public void configureSpansFactory( + @NonNull MarkwonSpansFactory.Builder builder) { + builder.setFactory( + Heading.class, + (configuration, props) -> + new Object[] { + new RelativeSizeSpan( + headingSizes[ + CoreProps.HEADING_LEVEL + .require( + props) + - 1]), + new StyleSpan(Typeface.BOLD) + }) + .setFactory( + Emphasis.class, + (configuration, props) -> + new StyleSpan(Typeface.ITALIC)) + .setFactory( + StrongEmphasis.class, + (configuration, props) -> + new StyleSpan(Typeface.BOLD)) + .setFactory( + BlockQuote.class, + (configuration, props) -> new QuoteSpan()) + .setFactory( + Code.class, + (configuration, props) -> + new Object[] { + new BackgroundColorSpan(Color.LTGRAY), + new TypefaceSpan("monospace") + }) + .setFactory( + ListItem.class, + (configuration, props) -> + new BulletSpan(bulletGapWidth)); + } + }) + .build(); + } + + private static Markwon.Builder createBuilderBase(Context context, Picasso picasso) { return Markwon.builder(context) .usePlugin(CorePlugin.create()) .usePlugin(MovementMethodPlugin.create(TableAwareMovementMethod.create())) .usePlugin(PicassoImagesPlugin.create(picasso)) - .usePlugin(TablePlugin.create(context)) - .build(); + .usePlugin(StrikethroughPlugin.create()) + .usePlugin(TablePlugin.create(context)); } } diff --git a/app/src/main/java/com/github/gotify/messages/ListMessageAdapter.java b/app/src/main/java/com/github/gotify/messages/ListMessageAdapter.java index 169fc785..da500a1e 100644 --- a/app/src/main/java/com/github/gotify/messages/ListMessageAdapter.java +++ b/app/src/main/java/com/github/gotify/messages/ListMessageAdapter.java @@ -18,7 +18,6 @@ import androidx.recyclerview.widget.RecyclerView; import butterknife.BindView; import butterknife.ButterKnife; - import com.github.gotify.MarkwonFactory; import com.github.gotify.R; import com.github.gotify.Settings; diff --git a/app/src/main/java/com/github/gotify/service/WebSocketService.java b/app/src/main/java/com/github/gotify/service/WebSocketService.java index 73c82366..1b388319 100644 --- a/app/src/main/java/com/github/gotify/service/WebSocketService.java +++ b/app/src/main/java/com/github/gotify/service/WebSocketService.java @@ -13,12 +13,10 @@ import android.net.Uri; import android.os.Build; import android.os.IBinder; - import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.core.app.NotificationCompat; import androidx.core.content.ContextCompat; - import com.github.gotify.MarkwonFactory; import com.github.gotify.MissedMessageUtil; import com.github.gotify.NotificationSupport; @@ -34,12 +32,11 @@ import com.github.gotify.messages.Extras; import com.github.gotify.messages.MessagesActivity; import com.github.gotify.picasso.PicassoHandler; +import io.noties.markwon.Markwon; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicLong; -import io.noties.markwon.Markwon; - import static com.github.gotify.api.Callback.call; public class WebSocketService extends Service { @@ -67,7 +64,7 @@ public void onCreate() { missingMessageUtil = new MissedMessageUtil(client.createService(MessageApi.class)); Log.i("Create " + getClass().getSimpleName()); picassoHandler = new PicassoHandler(this, settings); - markwon = MarkwonFactory.create(this, picassoHandler.get()); + markwon = MarkwonFactory.createForNotification(this, picassoHandler.get()); } @Override @@ -296,8 +293,6 @@ private void showNotification( showNotificationGroup(priority); } - if (Extras.useMarkdown(extras)) message = markwon.toMarkdown(message).toString(); - b.setAutoCancel(true) .setDefaults(Notification.DEFAULT_ALL) .setWhen(System.currentTimeMillis()) @@ -306,13 +301,19 @@ private void showNotification( .setTicker(getString(R.string.app_name) + " - " + title) .setGroup(NotificationSupport.Group.MESSAGES) .setContentTitle(title) - .setContentText(message) - .setStyle(new NotificationCompat.BigTextStyle().bigText(message)) .setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND) .setLights(Color.CYAN, 1000, 5000) .setColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary)) .setContentIntent(contentIntent); + CharSequence formattedMessage = message; + if (Extras.useMarkdown(extras)) { + formattedMessage = markwon.toMarkdown(message); + message = formattedMessage.toString(); + } + b.setContentText(message); + b.setStyle(new NotificationCompat.BigTextStyle().bigText(formattedMessage)); + NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(Utils.longToInt(id), b.build()); From cc616a9a7d64d3bc39faccb53de97e9aa49cdb20 Mon Sep 17 00:00:00 2001 From: Markus Date: Wed, 4 Aug 2021 22:36:46 +0200 Subject: [PATCH 3/4] Ignore links in notification rendering They are not clickable so they should look like not clickable --- app/src/main/java/com/github/gotify/MarkwonFactory.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/github/gotify/MarkwonFactory.java b/app/src/main/java/com/github/gotify/MarkwonFactory.java index e915ae70..2eb735c5 100644 --- a/app/src/main/java/com/github/gotify/MarkwonFactory.java +++ b/app/src/main/java/com/github/gotify/MarkwonFactory.java @@ -25,6 +25,7 @@ import org.commonmark.node.Code; import org.commonmark.node.Emphasis; import org.commonmark.node.Heading; +import org.commonmark.node.Link; import org.commonmark.node.ListItem; import org.commonmark.node.StrongEmphasis; @@ -80,7 +81,8 @@ public void configureSpansFactory( .setFactory( ListItem.class, (configuration, props) -> - new BulletSpan(bulletGapWidth)); + new BulletSpan(bulletGapWidth)) + .setFactory(Link.class, ((configuration, props) -> null)); } }) .build(); From e25bf4cc12427c7de64022ea71703b5a2a6f41fa Mon Sep 17 00:00:00 2001 From: Markus Date: Wed, 18 Aug 2021 21:25:06 +0200 Subject: [PATCH 4/4] Fixed missing tables in notification Implementation as raw text. --- .../com/github/gotify/MarkwonFactory.java | 44 ++++++++++++++----- .../gotify/messages/ListMessageAdapter.java | 2 +- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/github/gotify/MarkwonFactory.java b/app/src/main/java/com/github/gotify/MarkwonFactory.java index 2eb735c5..e9784cb6 100644 --- a/app/src/main/java/com/github/gotify/MarkwonFactory.java +++ b/app/src/main/java/com/github/gotify/MarkwonFactory.java @@ -14,6 +14,7 @@ import io.noties.markwon.AbstractMarkwonPlugin; import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonSpansFactory; +import io.noties.markwon.MarkwonVisitor; import io.noties.markwon.core.CorePlugin; import io.noties.markwon.core.CoreProps; import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; @@ -21,6 +22,9 @@ import io.noties.markwon.ext.tables.TablePlugin; import io.noties.markwon.image.picasso.PicassoImagesPlugin; import io.noties.markwon.movement.MovementMethodPlugin; +import java.util.Collections; +import org.commonmark.ext.gfm.tables.TableCell; +import org.commonmark.ext.gfm.tables.TablesExtension; import org.commonmark.node.BlockQuote; import org.commonmark.node.Code; import org.commonmark.node.Emphasis; @@ -28,10 +32,17 @@ import org.commonmark.node.Link; import org.commonmark.node.ListItem; import org.commonmark.node.StrongEmphasis; +import org.commonmark.parser.Parser; public class MarkwonFactory { - public static Markwon create(Context context, Picasso picasso) { - return createBuilderBase(context, picasso).build(); + public static Markwon createForMessage(Context context, Picasso picasso) { + return Markwon.builder(context) + .usePlugin(CorePlugin.create()) + .usePlugin(MovementMethodPlugin.create(TableAwareMovementMethod.create())) + .usePlugin(PicassoImagesPlugin.create(picasso)) + .usePlugin(StrikethroughPlugin.create()) + .usePlugin(TablePlugin.create(context)) + .build(); } public static Markwon createForNotification(Context context, Picasso picasso) { @@ -42,7 +53,10 @@ public static Markwon createForNotification(Context context, Picasso picasso) { final int bulletGapWidth = (int) (8 * context.getResources().getDisplayMetrics().density + 0.5F); - return createBuilderBase(context, picasso) + return Markwon.builder(context) + .usePlugin(CorePlugin.create()) + .usePlugin(PicassoImagesPlugin.create(picasso)) + .usePlugin(StrikethroughPlugin.create()) .usePlugin( new AbstractMarkwonPlugin() { @Override @@ -84,16 +98,22 @@ public void configureSpansFactory( new BulletSpan(bulletGapWidth)) .setFactory(Link.class, ((configuration, props) -> null)); } + + @Override + public void configureParser(@NonNull Parser.Builder builder) { + builder.extensions(Collections.singleton(TablesExtension.create())); + } + + @Override + public void configureVisitor(@NonNull MarkwonVisitor.Builder builder) { + builder.on( + TableCell.class, + (visitor, node) -> { + visitor.visitChildren(node); + visitor.builder().append(' '); + }); + } }) .build(); } - - private static Markwon.Builder createBuilderBase(Context context, Picasso picasso) { - return Markwon.builder(context) - .usePlugin(CorePlugin.create()) - .usePlugin(MovementMethodPlugin.create(TableAwareMovementMethod.create())) - .usePlugin(PicassoImagesPlugin.create(picasso)) - .usePlugin(StrikethroughPlugin.create()) - .usePlugin(TablePlugin.create(context)); - } } diff --git a/app/src/main/java/com/github/gotify/messages/ListMessageAdapter.java b/app/src/main/java/com/github/gotify/messages/ListMessageAdapter.java index da500a1e..f8eaf173 100644 --- a/app/src/main/java/com/github/gotify/messages/ListMessageAdapter.java +++ b/app/src/main/java/com/github/gotify/messages/ListMessageAdapter.java @@ -56,7 +56,7 @@ public class ListMessageAdapter extends RecyclerView.Adapter