diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsDisplay.java b/app/src/main/java/eu/faircode/email/FragmentOptionsDisplay.java
index 40493e0d29..c392a85745 100644
--- a/app/src/main/java/eu/faircode/email/FragmentOptionsDisplay.java
+++ b/app/src/main/java/eu/faircode/email/FragmentOptionsDisplay.java
@@ -107,6 +107,7 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer
private SwitchCompat swMonospaced;
private SwitchCompat swTextColor;
private SwitchCompat swTextSize;
+ private SwitchCompat swTextAlign;
private SwitchCompat swCollapseQuotes;
private SwitchCompat swImagesInline;
private SwitchCompat swAttachmentsAlt;
@@ -124,7 +125,7 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer
"keywords_header", "flags", "flags_background",
"preview", "preview_italic", "preview_lines",
"addresses", "button_archive_trash", "button_move",
- "contrast", "monospaced", "text_color", "text_size",
+ "contrast", "monospaced", "text_color", "text_size", "text_align",
"inline_images", "collapse_quotes", "attachments_alt",
"parse_classes", "authentication"
};
@@ -189,6 +190,7 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer
swMonospaced = view.findViewById(R.id.swMonospaced);
swTextColor = view.findViewById(R.id.swTextColor);
swTextSize = view.findViewById(R.id.swTextSize);
+ swTextAlign = view.findViewById(R.id.swTextAlign);
swCollapseQuotes = view.findViewById(R.id.swCollapseQuotes);
swImagesInline = view.findViewById(R.id.swImagesInline);
swAttachmentsAlt = view.findViewById(R.id.swAttachmentsAlt);
@@ -602,6 +604,13 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer
}
});
+ swTextAlign.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
+ prefs.edit().putBoolean("text_align", checked).apply();
+ }
+ });
+
swCollapseQuotes.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
@@ -776,6 +785,7 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer
swMonospaced.setChecked(prefs.getBoolean("monospaced", false));
swTextColor.setChecked(prefs.getBoolean("text_color", true));
swTextSize.setChecked(prefs.getBoolean("text_size", true));
+ swTextAlign.setChecked(prefs.getBoolean("text_align", true));
swCollapseQuotes.setChecked(prefs.getBoolean("collapse_quotes", false));
swImagesInline.setChecked(prefs.getBoolean("inline_images", false));
swAttachmentsAlt.setChecked(prefs.getBoolean("attachments_alt", false));
diff --git a/app/src/main/java/eu/faircode/email/HtmlHelper.java b/app/src/main/java/eu/faircode/email/HtmlHelper.java
index adcd0237c8..6706f0ebb3 100644
--- a/app/src/main/java/eu/faircode/email/HtmlHelper.java
+++ b/app/src/main/java/eu/faircode/email/HtmlHelper.java
@@ -36,6 +36,7 @@ import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.TextUtils;
+import android.text.style.AlignmentSpan;
import android.text.style.BulletSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.ImageSpan;
@@ -50,6 +51,7 @@ import android.text.style.TypefaceSpan;
import android.text.style.URLSpan;
import android.text.style.UnderlineSpan;
import android.util.Base64;
+import android.view.View;
import android.view.textclassifier.TextClassificationManager;
import android.view.textclassifier.TextLanguage;
@@ -313,6 +315,7 @@ public class HtmlHelper {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean text_color = prefs.getBoolean("text_color", true);
boolean text_size = prefs.getBoolean("text_size", true);
+ boolean text_align = prefs.getBoolean("text_align", true);
boolean display_hidden = prefs.getBoolean("display_hidden", false);
boolean disable_tracking = prefs.getBoolean("disable_tracking", true);
boolean parse_classes = prefs.getBoolean("parse_classes", false);
@@ -449,6 +452,8 @@ public class HtmlHelper {
.addProtocols("a", "href", "full");
if (text_color)
whitelist.addAttributes("font", "color");
+ if (text_align)
+ whitelist.addTags("center").addAttributes(":all", "align");
if (!view)
whitelist.addProtocols("img", "src", "content");
@@ -506,6 +511,19 @@ public class HtmlHelper {
// Element style
style = mergeStyles(style, element.attr("style"));
+ if (text_align) {
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/center
+ if ("center".equals(element.tagName())) {
+ style = mergeStyles(style, "text-align:center");
+ element.tagName("div");
+ }
+
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes
+ String align = element.attr("align");
+ if (!TextUtils.isEmpty(align))
+ style = mergeStyles(style, "text-align:" + align);
+ }
+
// Process style
if (!TextUtils.isEmpty(style)) {
StringBuilder sb = new StringBuilder();
@@ -637,6 +655,12 @@ public class HtmlHelper {
element.attr("line-after", "true");
}
break;
+
+ case "text-align":
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/text-align
+ if (text_align)
+ sb.append(key).append(':').append(value).append(';');
+ break;
}
}
}
@@ -1721,6 +1745,7 @@ public class HtmlHelper {
final int dp3 = Helper.dp2pixels(context, 3);
final int dp6 = Helper.dp2pixels(context, 6);
final int dp24 = Helper.dp2pixels(context, 24);
+ final boolean ltr = (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_LTR);
// https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements
NodeTraversor.traverse(new NodeVisitor() {
@@ -1871,6 +1896,22 @@ public class HtmlHelper {
if ("line-through".equals(value))
ssb.setSpan(new StrikethroughSpan(), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
+ case "text-align":
+ Layout.Alignment alignment = null;
+ switch (value) {
+ case "left":
+ alignment = (ltr ? Layout.Alignment.ALIGN_NORMAL : Layout.Alignment.ALIGN_OPPOSITE);
+ break;
+ case "center":
+ alignment = Layout.Alignment.ALIGN_CENTER;
+ break;
+ case "right":
+ alignment = (ltr ? Layout.Alignment.ALIGN_OPPOSITE : Layout.Alignment.ALIGN_NORMAL);
+ break;
+ }
+ if (alignment != null)
+ ssb.setSpan(new AlignmentSpan.Standard(alignment), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ break;
}
}
}
diff --git a/app/src/main/res/layout/fragment_options_display.xml b/app/src/main/res/layout/fragment_options_display.xml
index 4f72728925..5785776f48 100644
--- a/app/src/main/res/layout/fragment_options_display.xml
+++ b/app/src/main/res/layout/fragment_options_display.xml
@@ -826,6 +826,18 @@
app:layout_constraintTop_toBottomOf="@id/swTextColor"
app:switchPadding="12dp" />
+
+
Use monospaced font for message text
Show text colors
Show small and large texts
+ Show left/center/right aligned texts
Collapse quoted text
Automatically show inline images
Show relative conversation position with a dot