mirror of https://github.com/M66B/FairEmail.git
Improved formatting
This commit is contained in:
parent
cba389c103
commit
07a0bd7bde
|
@ -22,7 +22,6 @@ package eu.faircode.email;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.Html;
|
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
@ -131,8 +130,7 @@ public class ActivityCompose extends ActivityBilling implements FragmentManager.
|
||||||
CharSequence body = intent.getCharSequenceExtra(Intent.EXTRA_TEXT);
|
CharSequence body = intent.getCharSequenceExtra(Intent.EXTRA_TEXT);
|
||||||
if (body != null)
|
if (body != null)
|
||||||
if (body instanceof Spanned)
|
if (body instanceof Spanned)
|
||||||
args.putString("body",
|
args.putString("body", Jsoup.clean(HtmlHelper.toHtml((Spanned) body), Whitelist.relaxed()));
|
||||||
Jsoup.clean(Html.toHtml((Spanned) body), Whitelist.relaxed()));
|
|
||||||
else
|
else
|
||||||
args.putString("body", body.toString()); // TODO: clean?
|
args.putString("body", body.toString()); // TODO: clean?
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import android.content.Context;
|
||||||
import android.content.res.AssetFileDescriptor;
|
import android.content.res.AssetFileDescriptor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.Html;
|
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
@ -101,10 +100,10 @@ public class ActivityEml extends ActivityBase {
|
||||||
.append(apart.disposition).append(' ')
|
.append(apart.disposition).append(' ')
|
||||||
.append(apart.filename);
|
.append(apart.filename);
|
||||||
}
|
}
|
||||||
result.parts = Html.fromHtml(sb.toString());
|
result.parts = HtmlHelper.fromHtml(sb.toString());
|
||||||
|
|
||||||
String html = HtmlHelper.sanitize(parts.getHtml(context), true);
|
String html = HtmlHelper.sanitize(parts.getHtml(context), true);
|
||||||
result.body = Html.fromHtml(html);
|
result.body = HtmlHelper.fromHtml(html);
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
mmessage.writeTo(bos);
|
mmessage.writeTo(bos);
|
||||||
|
|
|
@ -1547,7 +1547,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
||||||
final boolean show_quotes = properties.getValue("quotes", message.id);
|
final boolean show_quotes = properties.getValue("quotes", message.id);
|
||||||
final boolean show_images = properties.getValue("images", message.id);
|
final boolean show_images = properties.getValue("images", message.id);
|
||||||
|
|
||||||
return Html.fromHtml(HtmlHelper.sanitize(body, show_quotes), new Html.ImageGetter() {
|
return HtmlHelper.fromHtml(HtmlHelper.sanitize(body, show_quotes), new Html.ImageGetter() {
|
||||||
@Override
|
@Override
|
||||||
public Drawable getDrawable(String source) {
|
public Drawable getDrawable(String source) {
|
||||||
Drawable image = HtmlHelper.decodeImage(source, context, message.id, show_images);
|
Drawable image = HtmlHelper.decodeImage(source, context, message.id, show_images);
|
||||||
|
|
|
@ -22,7 +22,6 @@ package eu.faircode.email;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.Html;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -107,7 +106,7 @@ public class FragmentAnswer extends FragmentBase {
|
||||||
@Override
|
@Override
|
||||||
protected void onExecuted(Bundle args, EntityAnswer answer) {
|
protected void onExecuted(Bundle args, EntityAnswer answer) {
|
||||||
etName.setText(answer == null ? null : answer.name);
|
etName.setText(answer == null ? null : answer.name);
|
||||||
etText.setText(answer == null ? null : Html.fromHtml(answer.text));
|
etText.setText(answer == null ? null : HtmlHelper.fromHtml(answer.text));
|
||||||
bottom_navigation.findViewById(R.id.action_delete).setVisibility(answer == null ? View.GONE : View.VISIBLE);
|
bottom_navigation.findViewById(R.id.action_delete).setVisibility(answer == null ? View.GONE : View.VISIBLE);
|
||||||
|
|
||||||
pbWait.setVisibility(View.GONE);
|
pbWait.setVisibility(View.GONE);
|
||||||
|
@ -168,7 +167,7 @@ public class FragmentAnswer extends FragmentBase {
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putLong("id", id);
|
args.putLong("id", id);
|
||||||
args.putString("name", etName.getText().toString());
|
args.putString("name", etName.getText().toString());
|
||||||
args.putString("text", Html.toHtml(etText.getText()));
|
args.putString("text", HtmlHelper.toHtml(etText.getText()));
|
||||||
|
|
||||||
new SimpleTask<Void>() {
|
new SimpleTask<Void>() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -94,13 +94,11 @@ import org.openintents.openpgp.util.OpenPgpServiceConnection;
|
||||||
import org.xml.sax.XMLReader;
|
import org.xml.sax.XMLReader;
|
||||||
|
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
@ -235,7 +233,7 @@ public class FragmentCompose extends FragmentBase {
|
||||||
Spanned signature = null;
|
Spanned signature = null;
|
||||||
if (pro) {
|
if (pro) {
|
||||||
if (identity != null && !TextUtils.isEmpty(identity.signature))
|
if (identity != null && !TextUtils.isEmpty(identity.signature))
|
||||||
signature = Html.fromHtml(identity.signature, new Html.ImageGetter() {
|
signature = HtmlHelper.fromHtml(identity.signature, new Html.ImageGetter() {
|
||||||
@Override
|
@Override
|
||||||
public Drawable getDrawable(String source) {
|
public Drawable getDrawable(String source) {
|
||||||
int px = Helper.dp2pixels(getContext(), 24);
|
int px = Helper.dp2pixels(getContext(), 24);
|
||||||
|
@ -503,7 +501,7 @@ public class FragmentCompose extends FragmentBase {
|
||||||
private void onReferenceEditConfirmed() {
|
private void onReferenceEditConfirmed() {
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putLong("id", working);
|
args.putLong("id", working);
|
||||||
args.putString("body", Html.toHtml(etBody.getText()));
|
args.putString("body", HtmlHelper.toHtml(etBody.getText()));
|
||||||
|
|
||||||
new SimpleTask<Void>() {
|
new SimpleTask<Void>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -522,26 +520,23 @@ public class FragmentCompose extends FragmentBase {
|
||||||
String body = args.getString("body");
|
String body = args.getString("body");
|
||||||
|
|
||||||
File file = EntityMessage.getFile(context, id);
|
File file = EntityMessage.getFile(context, id);
|
||||||
File ref = EntityMessage.getRefFile(context, id);
|
File refFile = EntityMessage.getRefFile(context, id);
|
||||||
|
|
||||||
|
String ref = Helper.readText(refFile);
|
||||||
|
String plain = HtmlHelper.getText(ref);
|
||||||
|
String html = "<p>" + plain.replaceAll("\\r?\\n", "<br />" + "</p>");
|
||||||
|
|
||||||
BufferedReader in = null;
|
|
||||||
BufferedWriter out = null;
|
BufferedWriter out = null;
|
||||||
try {
|
try {
|
||||||
out = new BufferedWriter(new FileWriter(file));
|
out = new BufferedWriter(new FileWriter(file));
|
||||||
out.write(body);
|
out.write(body);
|
||||||
|
out.write(html);
|
||||||
in = new BufferedReader(new FileReader(ref));
|
|
||||||
String str;
|
|
||||||
while ((str = in.readLine()) != null)
|
|
||||||
out.write(str);
|
|
||||||
} finally {
|
} finally {
|
||||||
if (out != null)
|
if (out != null)
|
||||||
out.close();
|
out.close();
|
||||||
if (in != null)
|
|
||||||
in.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ref.delete();
|
refFile.delete();
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1237,8 +1232,8 @@ public class FragmentCompose extends FragmentBase {
|
||||||
SpannableString s = new SpannableString(etBody.getText());
|
SpannableString s = new SpannableString(etBody.getText());
|
||||||
ImageSpan is = new ImageSpan(getContext(), Uri.parse("cid:" + BuildConfig.APPLICATION_ID + "." + attachment.id), ImageSpan.ALIGN_BASELINE);
|
ImageSpan is = new ImageSpan(getContext(), Uri.parse("cid:" + BuildConfig.APPLICATION_ID + "." + attachment.id), ImageSpan.ALIGN_BASELINE);
|
||||||
s.setSpan(is, start, start + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
s.setSpan(is, start, start + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
String html = Html.toHtml(s);
|
String html = HtmlHelper.toHtml(s);
|
||||||
etBody.setText(Html.fromHtml(html, cidGetter, null));
|
etBody.setText(HtmlHelper.fromHtml(html, cidGetter, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
onAction(R.id.action_save);
|
onAction(R.id.action_save);
|
||||||
|
@ -1295,7 +1290,7 @@ public class FragmentCompose extends FragmentBase {
|
||||||
return false;
|
return false;
|
||||||
if (!etSubject.getText().toString().trim().equals(etSubject.getTag()))
|
if (!etSubject.getText().toString().trim().equals(etSubject.getTag()))
|
||||||
return false;
|
return false;
|
||||||
if (!TextUtils.isEmpty(Jsoup.parse(Html.toHtml(etBody.getText())).text().trim()))
|
if (!TextUtils.isEmpty(Jsoup.parse(HtmlHelper.toHtml(etBody.getText())).text().trim()))
|
||||||
return false;
|
return false;
|
||||||
if (rvAttachment.getAdapter().getItemCount() > 0)
|
if (rvAttachment.getAdapter().getItemCount() > 0)
|
||||||
return false;
|
return false;
|
||||||
|
@ -1321,7 +1316,7 @@ public class FragmentCompose extends FragmentBase {
|
||||||
args.putString("cc", etCc.getText().toString().trim());
|
args.putString("cc", etCc.getText().toString().trim());
|
||||||
args.putString("bcc", etBcc.getText().toString().trim());
|
args.putString("bcc", etBcc.getText().toString().trim());
|
||||||
args.putString("subject", etSubject.getText().toString().trim());
|
args.putString("subject", etSubject.getText().toString().trim());
|
||||||
args.putString("body", Html.toHtml(spannable));
|
args.putString("body", HtmlHelper.toHtml(spannable));
|
||||||
args.putBoolean("empty", isEmpty());
|
args.putBoolean("empty", isEmpty());
|
||||||
|
|
||||||
Log.i("Run execute id=" + working);
|
Log.i("Run execute id=" + working);
|
||||||
|
@ -2253,13 +2248,13 @@ public class FragmentCompose extends FragmentBase {
|
||||||
final boolean show_images = args.getBoolean("show_images", false);
|
final boolean show_images = args.getBoolean("show_images", false);
|
||||||
|
|
||||||
String body = Helper.readText(EntityMessage.getFile(context, id));
|
String body = Helper.readText(EntityMessage.getFile(context, id));
|
||||||
Spanned spannedBody = Html.fromHtml(body, cidGetter, null);
|
Spanned spannedBody = HtmlHelper.fromHtml(body, cidGetter, null);
|
||||||
|
|
||||||
Spanned spannedReference = null;
|
Spanned spannedReference = null;
|
||||||
File refFile = EntityMessage.getRefFile(context, id);
|
File refFile = EntityMessage.getRefFile(context, id);
|
||||||
if (refFile.exists()) {
|
if (refFile.exists()) {
|
||||||
String quote = HtmlHelper.sanitize(Helper.readText(refFile), true);
|
String quote = HtmlHelper.sanitize(Helper.readText(refFile), true);
|
||||||
Spanned spannedQuote = Html.fromHtml(quote,
|
Spanned spannedQuote = HtmlHelper.fromHtml(quote,
|
||||||
new Html.ImageGetter() {
|
new Html.ImageGetter() {
|
||||||
@Override
|
@Override
|
||||||
public Drawable getDrawable(String source) {
|
public Drawable getDrawable(String source) {
|
||||||
|
|
|
@ -26,7 +26,6 @@ import android.graphics.drawable.GradientDrawable;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.Html;
|
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
|
@ -296,14 +295,14 @@ public class FragmentIdentity extends FragmentBase {
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
View dview = LayoutInflater.from(getContext()).inflate(R.layout.dialog_html, null);
|
View dview = LayoutInflater.from(getContext()).inflate(R.layout.dialog_html, null);
|
||||||
final EditText etHtml = dview.findViewById(R.id.etHtml);
|
final EditText etHtml = dview.findViewById(R.id.etHtml);
|
||||||
etHtml.setText(Html.toHtml(etSignature.getText()));
|
etHtml.setText(HtmlHelper.toHtml(etSignature.getText()));
|
||||||
|
|
||||||
new DialogBuilderLifecycle(getContext(), getViewLifecycleOwner())
|
new DialogBuilderLifecycle(getContext(), getViewLifecycleOwner())
|
||||||
.setView(dview)
|
.setView(dview)
|
||||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
Spanned html = Html.fromHtml(etHtml.getText().toString());
|
Spanned html = HtmlHelper.fromHtml(etHtml.getText().toString());
|
||||||
etSignature.setText(html);
|
etSignature.setText(html);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -480,7 +479,7 @@ public class FragmentIdentity extends FragmentBase {
|
||||||
args.putString("password", tilPassword.getEditText().getText().toString());
|
args.putString("password", tilPassword.getEditText().getText().toString());
|
||||||
args.putString("realm", etRealm.getText().toString());
|
args.putString("realm", etRealm.getText().toString());
|
||||||
args.putInt("color", color);
|
args.putInt("color", color);
|
||||||
args.putString("signature", Html.toHtml(etSignature.getText()));
|
args.putString("signature", HtmlHelper.toHtml(etSignature.getText()));
|
||||||
args.putBoolean("synchronize", cbSynchronize.isChecked());
|
args.putBoolean("synchronize", cbSynchronize.isChecked());
|
||||||
args.putBoolean("primary", cbPrimary.isChecked());
|
args.putBoolean("primary", cbPrimary.isChecked());
|
||||||
|
|
||||||
|
@ -718,7 +717,7 @@ public class FragmentIdentity extends FragmentBase {
|
||||||
|
|
||||||
etDisplay.setText(identity == null ? null : identity.display);
|
etDisplay.setText(identity == null ? null : identity.display);
|
||||||
etSignature.setText(identity == null ||
|
etSignature.setText(identity == null ||
|
||||||
TextUtils.isEmpty(identity.signature) ? null : Html.fromHtml(identity.signature));
|
TextUtils.isEmpty(identity.signature) ? null : HtmlHelper.fromHtml(identity.signature));
|
||||||
|
|
||||||
etHost.setText(identity == null ? null : identity.host);
|
etHost.setText(identity == null ? null : identity.host);
|
||||||
cbStartTls.setChecked(identity == null ? false : identity.starttls);
|
cbStartTls.setChecked(identity == null ? false : identity.starttls);
|
||||||
|
|
|
@ -53,7 +53,8 @@ public class FragmentPro extends FragmentBase implements SharedPreferences.OnSha
|
||||||
btnPurchase = view.findViewById(R.id.btnPurchase);
|
btnPurchase = view.findViewById(R.id.btnPurchase);
|
||||||
tvPrice = view.findViewById(R.id.tvPrice);
|
tvPrice = view.findViewById(R.id.tvPrice);
|
||||||
|
|
||||||
tvList.setText(Html.fromHtml("<a href=\"" + BuildConfig.PRO_FEATURES_URI + "\">" + Html.escapeHtml(getString(R.string.title_pro_list)) + "</a>"));
|
tvList.setText(HtmlHelper.fromHtml(
|
||||||
|
"<a href=\"" + BuildConfig.PRO_FEATURES_URI + "\">" + Html.escapeHtml(getString(R.string.title_pro_list)) + "</a>"));
|
||||||
tvList.setMovementMethod(LinkMovementMethod.getInstance());
|
tvList.setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
|
|
||||||
btnPurchase.setOnClickListener(new View.OnClickListener() {
|
btnPurchase.setOnClickListener(new View.OnClickListener() {
|
||||||
|
|
|
@ -34,7 +34,6 @@ import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.Html;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.text.method.LinkMovementMethod;
|
import android.text.method.LinkMovementMethod;
|
||||||
|
@ -378,7 +377,7 @@ public class FragmentQuickSetup extends FragmentBase {
|
||||||
@Override
|
@Override
|
||||||
protected void onException(Bundle args, Throwable ex) {
|
protected void onException(Bundle args, Throwable ex) {
|
||||||
if (args.containsKey("documentation")) {
|
if (args.containsKey("documentation")) {
|
||||||
tvInstructions.setText(Html.fromHtml(args.getString("documentation")));
|
tvInstructions.setText(HtmlHelper.fromHtml(args.getString("documentation")));
|
||||||
tvInstructions.setVisibility(View.VISIBLE);
|
tvInstructions.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,8 @@ import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.text.Html;
|
||||||
|
import android.text.Spanned;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
|
|
||||||
|
@ -49,20 +51,35 @@ import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.core.text.HtmlCompat;
|
||||||
|
|
||||||
|
import static androidx.core.text.HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_LIST_ITEM;
|
||||||
|
import static androidx.core.text.HtmlCompat.TO_HTML_PARAGRAPH_LINES_CONSECUTIVE;
|
||||||
|
|
||||||
public class HtmlHelper {
|
public class HtmlHelper {
|
||||||
private static final int PREVIEW_SIZE = 250;
|
private static final int PREVIEW_SIZE = 250;
|
||||||
private static Pattern pattern = Pattern.compile("([http|https]+://[\\w\\S(\\.|:|/)]+)");
|
private static Pattern pattern = Pattern.compile("([http|https]+://[\\w\\S(\\.|:|/)]+)");
|
||||||
private static final List<String> heads = Arrays.asList("p", "h1", "h2", "h3", "h4", "h5", "tr");
|
private static final List<String> heads = Arrays.asList("h1", "h2", "h3", "h4", "h5", "h6", "p", "table", "ol", "ul", "br", "hr");
|
||||||
private static final List<String> tails = Arrays.asList("br", "dd", "dt", "p", "h1", "h2", "h3", "h4", "h5");
|
private static final List<String> tails = Arrays.asList("h1", "h2", "h3", "h4", "h5", "h6", "p", "ol", "ul", "li");
|
||||||
|
|
||||||
static String sanitize(String html, boolean quotes) {
|
static String sanitize(String html, boolean showQuotes) {
|
||||||
Document document = Jsoup.parse(Jsoup.clean(html, Whitelist
|
Document document = Jsoup.parse(Jsoup.clean(html, Whitelist
|
||||||
.relaxed()
|
.relaxed()
|
||||||
.addProtocols("img", "src", "cid")
|
.addProtocols("img", "src", "cid")
|
||||||
.addProtocols("img", "src", "data")));
|
.addProtocols("img", "src", "data")));
|
||||||
|
|
||||||
for (Element tr : document.select("tr"))
|
for (Element td : document.select("th,td")) {
|
||||||
tr.after("<br>");
|
Element next = td.nextElementSibling();
|
||||||
|
if (next != null && ("th".equals(next.tagName()) || "td".equals(next.tagName())))
|
||||||
|
td.append("<span> </span>");
|
||||||
|
else
|
||||||
|
td.append("<br>");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Element ol : document.select("ol,ul"))
|
||||||
|
ol.append("<br>");
|
||||||
|
|
||||||
for (Element img : document.select("img")) {
|
for (Element img : document.select("img")) {
|
||||||
boolean linked = false;
|
boolean linked = false;
|
||||||
|
@ -88,15 +105,16 @@ public class HtmlHelper {
|
||||||
p.appendChild(img);
|
p.appendChild(img);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!quotes)
|
if (!showQuotes)
|
||||||
for (Element quote : document.select("blockquote"))
|
for (Element quote : document.select("blockquote"))
|
||||||
quote.text("…");
|
quote.html("…");
|
||||||
|
|
||||||
|
// Autolink
|
||||||
NodeTraversor.traverse(new NodeVisitor() {
|
NodeTraversor.traverse(new NodeVisitor() {
|
||||||
@Override
|
@Override
|
||||||
public void head(Node node, int depth) {
|
public void head(Node node, int depth) {
|
||||||
if (node instanceof TextNode) {
|
if (node instanceof TextNode) {
|
||||||
String text = ((TextNode) node).text();
|
String text = Html.escapeHtml(((TextNode) node).text());
|
||||||
Matcher matcher = pattern.matcher(text);
|
Matcher matcher = pattern.matcher(text);
|
||||||
while (matcher.find()) {
|
while (matcher.find()) {
|
||||||
String ref = matcher.group();
|
String ref = matcher.group();
|
||||||
|
@ -281,29 +299,72 @@ public class HtmlHelper {
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
NodeTraversor.traverse(new NodeVisitor() {
|
NodeTraversor.traverse(new NodeVisitor() {
|
||||||
|
private int qlevel = 0;
|
||||||
|
|
||||||
public void head(Node node, int depth) {
|
public void head(Node node, int depth) {
|
||||||
if (node instanceof TextNode)
|
if (node instanceof TextNode)
|
||||||
sb.append(((TextNode) node).text());
|
sb.append(((TextNode) node).text()).append(' ');
|
||||||
else {
|
else {
|
||||||
String name = node.nodeName();
|
String name = node.nodeName();
|
||||||
if (name.equals("li"))
|
if ("li".equals(name))
|
||||||
sb.append("\n * ");
|
sb.append("* ");
|
||||||
else if (name.equals("dt"))
|
else if ("blockquote".equals(name))
|
||||||
sb.append(" ");
|
qlevel++;
|
||||||
else if (heads.contains(name))
|
|
||||||
sb.append("\n");
|
if (heads.contains(name))
|
||||||
|
newline();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tail(Node node, int depth) {
|
public void tail(Node node, int depth) {
|
||||||
String name = node.nodeName();
|
String name = node.nodeName();
|
||||||
|
if ("a".equals(name))
|
||||||
|
sb.append("[").append(node.absUrl("href")).append("] ");
|
||||||
|
if ("img".equals(name))
|
||||||
|
sb.append("[").append(node.absUrl("src")).append("] ");
|
||||||
|
else if ("th".equals(name) || "td".equals(name)) {
|
||||||
|
Node next = node.nextSibling();
|
||||||
|
if (next == null || !("th".equals(next.nodeName()) || "td".equals(next.nodeName())))
|
||||||
|
newline();
|
||||||
|
} else if ("blockquote".equals(name))
|
||||||
|
qlevel--;
|
||||||
|
|
||||||
if (tails.contains(name))
|
if (tails.contains(name))
|
||||||
|
newline();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void newline() {
|
||||||
|
trimEnd(sb);
|
||||||
sb.append("\n");
|
sb.append("\n");
|
||||||
else if (name.equals("a"))
|
for (int i = 0; i < qlevel; i++)
|
||||||
sb.append(" <").append(node.absUrl("href")).append(">");
|
sb.append('>');
|
||||||
|
if (qlevel > 0)
|
||||||
|
sb.append(' ');
|
||||||
}
|
}
|
||||||
}, Jsoup.parse(html));
|
}, Jsoup.parse(html));
|
||||||
|
|
||||||
|
trimEnd(sb);
|
||||||
|
sb.append("\n");
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void trimEnd(StringBuilder sb) {
|
||||||
|
int length = sb.length();
|
||||||
|
while (length > 0 && sb.charAt(length - 1) == ' ')
|
||||||
|
length--;
|
||||||
|
sb.setLength(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Spanned fromHtml(@NonNull String html) {
|
||||||
|
return fromHtml(html, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Spanned fromHtml(@NonNull String html, @Nullable Html.ImageGetter imageGetter, @Nullable Html.TagHandler tagHandler) {
|
||||||
|
return HtmlCompat.fromHtml(html, FROM_HTML_SEPARATOR_LINE_BREAK_LIST_ITEM, imageGetter, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String toHtml(Spanned spanned) {
|
||||||
|
return HtmlCompat.toHtml(spanned, TO_HTML_PARAGRAPH_LINES_CONSECUTIVE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,6 @@ import android.os.Handler;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.text.Html;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.LongSparseArray;
|
import android.util.LongSparseArray;
|
||||||
|
|
||||||
|
@ -583,7 +582,7 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.setStyle(new Notification.BigTextStyle()
|
builder.setStyle(new Notification.BigTextStyle()
|
||||||
.bigText(Html.fromHtml(sb.toString()))
|
.bigText(HtmlHelper.fromHtml(sb.toString()))
|
||||||
.setSummaryText(title));
|
.setSummaryText(title));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,7 +677,7 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
if (!TextUtils.isEmpty(message.subject))
|
if (!TextUtils.isEmpty(message.subject))
|
||||||
sb.append(message.subject).append("<br>");
|
sb.append(message.subject).append("<br>");
|
||||||
sb.append(HtmlHelper.getPreview(body));
|
sb.append(HtmlHelper.getPreview(body));
|
||||||
mbuilder.setStyle(new Notification.BigTextStyle().bigText(Html.fromHtml(sb.toString())));
|
mbuilder.setStyle(new Notification.BigTextStyle().bigText(HtmlHelper.fromHtml(sb.toString())));
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
Log.e(ex);
|
Log.e(ex);
|
||||||
mbuilder.setStyle(new Notification.BigTextStyle().bigText(ex.toString()));
|
mbuilder.setStyle(new Notification.BigTextStyle().bigText(ex.toString()));
|
||||||
|
|
Loading…
Reference in New Issue