mirror of
https://github.com/M66B/FairEmail.git
synced 2026-04-04 16:16:33 +02:00
Inline full message display
This commit is contained in:
@@ -139,7 +139,7 @@ public class ActivityEML extends ActivityBase {
|
||||
|
||||
result.html = parts.getHtml(context);
|
||||
if (result.html != null) {
|
||||
result.body = HtmlHelper.fromHtml(HtmlHelper.sanitize(context, result.html, false, false));
|
||||
result.body = HtmlHelper.fromHtml(HtmlHelper.sanitize(context, result.html, false));
|
||||
if (result.html.length() > 100 * 1024)
|
||||
result.html = null;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -68,7 +68,7 @@ public class EditTextCompose extends AppCompatEditText {
|
||||
ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);
|
||||
|
||||
String html = item.coerceToHtmlText(context);
|
||||
html = HtmlHelper.sanitize(context, html, true, false);
|
||||
html = HtmlHelper.sanitize(context, html, false);
|
||||
Spanned paste = HtmlHelper.fromHtml(html);
|
||||
|
||||
int start = getSelectionStart();
|
||||
|
||||
@@ -2026,7 +2026,6 @@ public class FragmentCompose extends FragmentBase {
|
||||
long answer = args.getLong("answer", -1);
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
boolean text_color = prefs.getBoolean("text_color", true);
|
||||
boolean plain_only = prefs.getBoolean("plain_only", false);
|
||||
boolean encrypt_default = prefs.getBoolean("encrypt_default", false);
|
||||
boolean receipt_default = prefs.getBoolean("receipt_default", false);
|
||||
@@ -2096,7 +2095,7 @@ public class FragmentCompose extends FragmentBase {
|
||||
data.draft.subject = args.getString("subject", "");
|
||||
body = args.getString("body", "");
|
||||
if (!TextUtils.isEmpty(body))
|
||||
body = HtmlHelper.sanitize(context, body, text_color, false);
|
||||
body = HtmlHelper.sanitize(context, body, false);
|
||||
|
||||
if (answer > 0) {
|
||||
EntityAnswer a = db.answer().getAnswer(answer);
|
||||
@@ -2164,7 +2163,7 @@ public class FragmentCompose extends FragmentBase {
|
||||
data.draft.subject = ref.subject;
|
||||
if (ref.content) {
|
||||
String html = Helper.readText(ref.getFile(context));
|
||||
body = HtmlHelper.sanitize(context, html, text_color, true);
|
||||
body = HtmlHelper.sanitize(context, html, true);
|
||||
}
|
||||
} else if ("list".equals(action)) {
|
||||
data.draft.subject = ref.subject;
|
||||
@@ -2411,7 +2410,7 @@ public class FragmentCompose extends FragmentBase {
|
||||
if (data.draft.content) {
|
||||
File file = data.draft.getFile(context);
|
||||
String html = Helper.readText(file);
|
||||
html = HtmlHelper.sanitize(context, html, true, true);
|
||||
html = HtmlHelper.sanitize(context, html, true);
|
||||
Helper.writeText(file, html);
|
||||
} else {
|
||||
if (data.draft.uid == null)
|
||||
@@ -3114,9 +3113,6 @@ public class FragmentCompose extends FragmentBase {
|
||||
final long id = args.getLong("id");
|
||||
final boolean show_images = args.getBoolean("show_images", false);
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
boolean text_color = prefs.getBoolean("text_color", true);
|
||||
|
||||
int colorPrimary = Helper.resolveColor(context, R.attr.colorPrimary);
|
||||
|
||||
DB db = DB.getInstance(context);
|
||||
@@ -3143,7 +3139,7 @@ public class FragmentCompose extends FragmentBase {
|
||||
Spanned spannedRef = null;
|
||||
File refFile = draft.getRefFile(context);
|
||||
if (refFile.exists()) {
|
||||
String quote = HtmlHelper.sanitize(context, Helper.readText(refFile), text_color, show_images);
|
||||
String quote = HtmlHelper.sanitize(context, Helper.readText(refFile), show_images);
|
||||
Spanned spannedQuote = HtmlHelper.fromHtml(quote,
|
||||
new Html.ImageGetter() {
|
||||
@Override
|
||||
|
||||
@@ -48,7 +48,6 @@ import android.os.Parcelable;
|
||||
import android.print.PrintAttributes;
|
||||
import android.print.PrintDocumentAdapter;
|
||||
import android.print.PrintManager;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.LongSparseArray;
|
||||
@@ -232,7 +231,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
|
||||
private boolean autoExpanded = true;
|
||||
private Map<String, List<Long>> values = new HashMap<>();
|
||||
private LongSparseArray<Float> sizes = new LongSparseArray<>();
|
||||
private LongSparseArray<Spanned> bodies = new LongSparseArray<>();
|
||||
private LongSparseArray<Integer> heights = new LongSparseArray<>();
|
||||
private LongSparseArray<List<EntityAttachment>> attachments = new LongSparseArray<>();
|
||||
private LongSparseArray<TupleAccountSwipes> accountSwipes = new LongSparseArray<>();
|
||||
|
||||
@@ -258,8 +257,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
|
||||
static final int REQUEST_PRINT = 17;
|
||||
private static final int REQUEST_SEARCH = 18;
|
||||
private static final int REQUEST_ACCOUNT = 19;
|
||||
static final int REQUEST_MESSAGE_PROPERTY = 20;
|
||||
private static final int REQUEST_EMPTY_FOLDER = 21;
|
||||
private static final int REQUEST_EMPTY_FOLDER = 20;
|
||||
|
||||
static final String ACTION_STORE_RAW = BuildConfig.APPLICATION_ID + ".STORE_RAW";
|
||||
static final String ACTION_DECRYPT = BuildConfig.APPLICATION_ID + ".DECRYPT";
|
||||
@@ -1253,16 +1251,13 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBody(long id, Spanned value) {
|
||||
if (value == null)
|
||||
bodies.remove(id);
|
||||
else
|
||||
bodies.put(id, value);
|
||||
public void setHeight(long id, int height) {
|
||||
heights.put(id, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spanned getBody(long id) {
|
||||
return bodies.get(id);
|
||||
public int getHeight(long id, int defaultHeight) {
|
||||
return heights.get(id, defaultHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1285,16 +1280,6 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scrollBy(final int dx, final int dy) {
|
||||
new Handler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
rvMessage.scrollBy(dx, dy);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move(long id, String type) {
|
||||
Bundle args = new Bundle();
|
||||
@@ -2187,6 +2172,15 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
|
||||
outState.putLongArray("fair:sizes:keys", skeys);
|
||||
outState.putFloatArray("fair:sizes:values", svalues);
|
||||
|
||||
long[] hkeys = new long[heights.size()];
|
||||
int[] hvalues = new int[heights.size()];
|
||||
for (int i = 0; i < heights.size(); i++) {
|
||||
hkeys[i] = heights.keyAt(i);
|
||||
hvalues[i] = heights.valueAt(i);
|
||||
}
|
||||
outState.putLongArray("fair:heights:keys", hkeys);
|
||||
outState.putIntArray("fair:heights:values", hvalues);
|
||||
|
||||
if (rvMessage != null) {
|
||||
Parcelable rv = rvMessage.getLayoutManager().onSaveInstanceState();
|
||||
outState.putParcelable("fair:rv", rv);
|
||||
@@ -2221,6 +2215,12 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
|
||||
for (int i = 0; i < skeys.length; i++)
|
||||
sizes.put(skeys[i], svalues[i]);
|
||||
|
||||
long[] hkeys = savedInstanceState.getLongArray("fair:heights:keys");
|
||||
int[] hvalues = savedInstanceState.getIntArray("fair:heights:values");
|
||||
|
||||
for (int i = 0; i < hkeys.length; i++)
|
||||
heights.put(hkeys[i], hvalues[i]);
|
||||
|
||||
if (rvMessage != null) {
|
||||
Parcelable rv = savedInstanceState.getBundle("fair:rv");
|
||||
rvMessage.getLayoutManager().onRestoreInstanceState(rv);
|
||||
@@ -2338,7 +2338,8 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
|
||||
Log.i("Hidden id=" + id);
|
||||
for (String key : values.keySet())
|
||||
values.get(key).remove(id);
|
||||
bodies.remove(id);
|
||||
sizes.remove(id);
|
||||
heights.remove(id);
|
||||
attachments.remove(id);
|
||||
}
|
||||
updateExpanded();
|
||||
@@ -3706,10 +3707,6 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
|
||||
onMenuFolders(args.getLong("account"));
|
||||
}
|
||||
break;
|
||||
case REQUEST_MESSAGE_PROPERTY:
|
||||
if (resultCode == RESULT_OK)
|
||||
onPropertySet(data.getBundleExtra("args"));
|
||||
break;
|
||||
case REQUEST_EMPTY_FOLDER:
|
||||
if (resultCode == RESULT_OK)
|
||||
onEmptyFolder(data.getBundleExtra("args"));
|
||||
@@ -4440,14 +4437,6 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
|
||||
}.execute(this, pargs, "message:print");
|
||||
}
|
||||
|
||||
private void onPropertySet(Bundle args) {
|
||||
long id = args.getLong("id");
|
||||
String name = args.getString("name");
|
||||
boolean value = args.getBoolean("value");
|
||||
Log.i("Set property " + name + "=" + value + " id=" + id);
|
||||
iProperties.setValue(name, id, value);
|
||||
}
|
||||
|
||||
private void onEmptyFolder(Bundle args) {
|
||||
new SimpleTask<Void>() {
|
||||
@Override
|
||||
|
||||
@@ -46,7 +46,7 @@ public class FragmentOptions extends FragmentBase {
|
||||
"flags", "flags_background", "preview", "preview_italic",
|
||||
"addresses", "attachments_alt",
|
||||
"contrast", "monospaced", "text_color",
|
||||
"inline_images", "collapse_quotes", "autocontent", "seekbar", "actionbar",
|
||||
"inline_images", "collapse_quotes", "seekbar", "actionbar",
|
||||
"autoscroll", "swipenav", "autoexpand", "autoclose", "onclose",
|
||||
"experiments", "debug",
|
||||
"biometrics"
|
||||
|
||||
@@ -71,7 +71,6 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer
|
||||
private SwitchCompat swTextColor;
|
||||
private SwitchCompat swCollapseQuotes;
|
||||
private SwitchCompat swImagesInline;
|
||||
private SwitchCompat swRemoteContent;
|
||||
private SwitchCompat swSeekbar;
|
||||
private SwitchCompat swActionbar;
|
||||
|
||||
@@ -81,7 +80,7 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer
|
||||
"subject_top", "subject_italic", "subject_ellipsize",
|
||||
"flags", "flags_background", "preview", "preview_italic", "addresses", "attachments_alt",
|
||||
"contrast", "monospaced", "text_color",
|
||||
"inline_images", "collapse_quotes", "autocontent", "seekbar", "actionbar",
|
||||
"inline_images", "collapse_quotes", "seekbar", "actionbar",
|
||||
};
|
||||
|
||||
@Override
|
||||
@@ -121,7 +120,6 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer
|
||||
swTextColor = view.findViewById(R.id.swTextColor);
|
||||
swCollapseQuotes = view.findViewById(R.id.swCollapseQuotes);
|
||||
swImagesInline = view.findViewById(R.id.swImagesInline);
|
||||
swRemoteContent = view.findViewById(R.id.swRemoteContent);
|
||||
swSeekbar = view.findViewById(R.id.swSeekbar);
|
||||
swActionbar = view.findViewById(R.id.swActionbar);
|
||||
|
||||
@@ -341,13 +339,6 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer
|
||||
}
|
||||
});
|
||||
|
||||
swRemoteContent.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
|
||||
prefs.edit().putBoolean("autocontent", checked).apply();
|
||||
}
|
||||
});
|
||||
|
||||
swSeekbar.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
|
||||
@@ -451,7 +442,6 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer
|
||||
swTextColor.setChecked(prefs.getBoolean("text_color", true));
|
||||
swCollapseQuotes.setChecked(prefs.getBoolean("collapse_quotes", false));
|
||||
swImagesInline.setChecked(prefs.getBoolean("inline_images", false));
|
||||
swRemoteContent.setChecked(prefs.getBoolean("autocontent", false));
|
||||
swSeekbar.setChecked(prefs.getBoolean("seekbar", false));
|
||||
swActionbar.setChecked(prefs.getBoolean("actionbar", true));
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
|
||||
for (String option : RESET_QUESTIONS)
|
||||
editor.remove(option);
|
||||
for (String key : prefs.getAll().keySet())
|
||||
if (key.endsWith(".show_images"))
|
||||
if (key.endsWith(".show_full") || key.endsWith(".show_images"))
|
||||
editor.remove(key);
|
||||
editor.apply();
|
||||
ToastEx.makeText(getContext(), R.string.title_setup_done, Toast.LENGTH_LONG).show();
|
||||
|
||||
@@ -96,7 +96,11 @@ public class HtmlHelper {
|
||||
private static final ExecutorService executor =
|
||||
Executors.newSingleThreadExecutor(Helper.backgroundThreadFactory);
|
||||
|
||||
static String sanitize(Context context, String html, boolean text_color, boolean show_images) {
|
||||
static String sanitize(Context context, String html, boolean show_images) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
boolean text_color = prefs.getBoolean("text_color", true);
|
||||
boolean disable_tracking = prefs.getBoolean("disable_tracking", true);
|
||||
|
||||
Document parsed = JsoupEx.parse(html);
|
||||
|
||||
// <html xmlns:v="urn:schemas-microsoft-com:vml"
|
||||
@@ -349,40 +353,12 @@ public class HtmlHelper {
|
||||
else
|
||||
table.tagName("div");
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
boolean disable_tracking = prefs.getBoolean("disable_tracking", true);
|
||||
|
||||
// Build list of allowed hosts
|
||||
List<String> hosts = new ArrayList<>();
|
||||
// Remove tracking pixels
|
||||
if (disable_tracking)
|
||||
for (Element img : document.select("img")) {
|
||||
String src = img.attr("src");
|
||||
if (!TextUtils.isEmpty(src) && !isTrackingPixel(img)) {
|
||||
Uri uri = Uri.parse(img.attr("src"));
|
||||
String host = uri.getHost();
|
||||
if (host != null && !hosts.contains(host))
|
||||
hosts.add(host);
|
||||
}
|
||||
}
|
||||
removeTrackingPixels(context, document);
|
||||
|
||||
// Images
|
||||
for (Element img : document.select("img")) {
|
||||
// Remove link tracking pixels
|
||||
if (disable_tracking) {
|
||||
String src = img.attr("src");
|
||||
if (!TextUtils.isEmpty(src) && isTrackingPixel(img)) {
|
||||
Uri uri = Uri.parse(img.attr("src"));
|
||||
String host = uri.getHost();
|
||||
if (host == null || !hosts.contains(host)) {
|
||||
img.removeAttr("src");
|
||||
img.tagName("a");
|
||||
img.attr("href", src);
|
||||
img.appendText(context.getString(R.string.title_hint_tracking_image,
|
||||
img.attr("width"), img.attr("height")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!show_images) {
|
||||
String alt = img.attr("alt");
|
||||
if (!TextUtils.isEmpty(alt)) {
|
||||
@@ -515,6 +491,36 @@ public class HtmlHelper {
|
||||
return false;
|
||||
}
|
||||
|
||||
static void removeTrackingPixels(Context context, Document document) {
|
||||
// Build list of allowed hosts
|
||||
List<String> hosts = new ArrayList<>();
|
||||
for (Element img : document.select("img")) {
|
||||
String src = img.attr("src");
|
||||
if (!TextUtils.isEmpty(src) && !isTrackingPixel(img)) {
|
||||
Uri uri = Uri.parse(img.attr("src"));
|
||||
String host = uri.getHost();
|
||||
if (host != null && !hosts.contains(host))
|
||||
hosts.add(host);
|
||||
}
|
||||
}
|
||||
|
||||
// Images
|
||||
for (Element img : document.select("img")) {
|
||||
String src = img.attr("src");
|
||||
if (!TextUtils.isEmpty(src) && isTrackingPixel(img)) {
|
||||
Uri uri = Uri.parse(img.attr("src"));
|
||||
String host = uri.getHost();
|
||||
if (host == null || !hosts.contains(host)) {
|
||||
img.removeAttr("src");
|
||||
img.tagName("a");
|
||||
img.attr("href", src);
|
||||
img.appendText(context.getString(R.string.title_hint_tracking_image,
|
||||
img.attr("width"), img.attr("height")));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Drawable decodeImage(final Context context, final long id, String source, boolean show, final TextView view) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
boolean compact = prefs.getBoolean("compact", false);
|
||||
|
||||
Reference in New Issue
Block a user