diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 792f52f64e..ce4269d453 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -54,5 +54,6 @@ Where: * **[Ayowel](https://github.com/ayowel)**
~° Mermaid update * **[Matthew White](https://github.com/mehw)**
~° Zim-Wiki link/attachment conformance * **[Markus Paintner](https://github.com/goli4thus)**
~° Added duplicate lines action +* **[Sebastian Safari](https://ssebs.com/)**
~° Add text styling to the todo widget when using Markdown * **[Janez Pavel Žebovec](https://janezpavelzebovec.net/)**
~° Slovenian translation * **[Stephen Karl Larroque](https://github.com/lrq3000/)**
~° Bugfixes diff --git a/app/src/main/java/net/gsantner/markor/widget/MarkdownWidgetUtils.java b/app/src/main/java/net/gsantner/markor/widget/MarkdownWidgetUtils.java new file mode 100644 index 0000000000..3f6755214c --- /dev/null +++ b/app/src/main/java/net/gsantner/markor/widget/MarkdownWidgetUtils.java @@ -0,0 +1,65 @@ +package net.gsantner.markor.widget; + +import android.os.Build; +import android.text.Html; +import android.text.SpannableStringBuilder; +import android.text.Spanned; + +import com.vladsch.flexmark.ext.gfm.tasklist.TaskListExtension; +import com.vladsch.flexmark.html.HtmlRenderer; +import com.vladsch.flexmark.parser.Parser; + +import java.util.Collections; + +/** + * A utility class for converting Markdown to a {@link android.text.Spannable} for use in Android widgets. + *

+ * This class provides methods to render a limited subset of Markdown, making it suitable for display + * within {@link android.widget.RemoteViews}. + */ +public final class MarkdownWidgetUtils { + + /** + * Converts markdown → HTML using flexmark → Spanned → SpannableStringBuilder. + * Safe for RemoteViews (bold, italic, lists, headings, etc.). + */ + public static SpannableStringBuilder fromFlexmark(String markdown) { + if (markdown == null || markdown.isEmpty()) { + return new SpannableStringBuilder(""); + } + + Parser parser = Parser.builder() + .extensions(Collections.singletonList(TaskListExtension.create())) + .build(); + HtmlRenderer renderer = HtmlRenderer.builder() + .extensions(Collections.singletonList(TaskListExtension.create())) + .build(); + + String html = renderer.render(parser.parse(markdown)); + + Spanned spanned; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + spanned = Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY); + } else { + spanned = Html.fromHtml(html); + } + + // Flexmark produces

blocks, so Html.fromHtml adds newlines. + // Trim trailing newlines to match old behavior. + SpannableStringBuilder out = new SpannableStringBuilder(spanned); + trimTrailingNewlines(out); + + return out; + } + + + /** + * Helper to remove excessive newlines from Html.fromHtml output + */ + private static void trimTrailingNewlines(SpannableStringBuilder sb) { + while (sb.length() > 0 && sb.charAt(sb.length() - 1) == '\n') { + sb.delete(sb.length() - 1, sb.length()); + } + } + +} diff --git a/app/src/main/java/net/gsantner/markor/widget/TodoWidgetRemoteViewsFactory.java b/app/src/main/java/net/gsantner/markor/widget/TodoWidgetRemoteViewsFactory.java index a7b35da6d1..4d2a20eaad 100644 --- a/app/src/main/java/net/gsantner/markor/widget/TodoWidgetRemoteViewsFactory.java +++ b/app/src/main/java/net/gsantner/markor/widget/TodoWidgetRemoteViewsFactory.java @@ -1,5 +1,7 @@ package net.gsantner.markor.widget; +import static net.gsantner.markor.format.FormatRegistry.CONVERTER_MARKDOWN; + import android.content.Context; import android.content.Intent; import android.widget.RemoteViews; @@ -56,7 +58,19 @@ public int getCount() { @Override public RemoteViews getViewAt(int position) { RemoteViews views = new RemoteViews(_context.getPackageName(), R.layout.todo_widget_list_item); - views.setTextViewText(R.id.todo_widget_item_text, _tasks.get(position).getDescription()); + + String itemText = _tasks.get(position).getDescription(); + + boolean isMarkdown = CONVERTER_MARKDOWN.isFileOutOfThisFormat(_document.file); + + if (isMarkdown) { + CharSequence styled = MarkdownWidgetUtils.fromFlexmark(itemText); + views.setTextViewText(R.id.todo_widget_item_text, styled); + } else { + views.setTextViewText(R.id.todo_widget_item_text, itemText); + } + + views.setInt(R.id.todo_widget_item_text, "setTextColor", _appSettings.getEditorForegroundColor()); final Intent fillInIntent = new Intent() diff --git a/app/src/main/res/layout/todo_widget_layout.xml b/app/src/main/res/layout/todo_widget_layout.xml index 8b44245d6a..f6ce2641a7 100644 --- a/app/src/main/res/layout/todo_widget_layout.xml +++ b/app/src/main/res/layout/todo_widget_layout.xml @@ -1,23 +1,24 @@ + android:background="@color/background" + android:orientation="vertical" + android:padding="8dp"> + android:divider="@color/background" + android:dividerHeight="0dp" /> diff --git a/app/src/main/res/layout/todo_widget_list_item.xml b/app/src/main/res/layout/todo_widget_list_item.xml index f846da9354..b2327c77c8 100644 --- a/app/src/main/res/layout/todo_widget_list_item.xml +++ b/app/src/main/res/layout/todo_widget_list_item.xml @@ -3,6 +3,6 @@ android:id="@+id/todo_widget_item_text" android:layout_width="match_parent" android:layout_height="wrap_content" - android:padding="3dp" + android:padding="2dp" android:textSize="15sp" android:textColor="@color/primary_text" />