Inline full message display

pull/162/head
M66B 5 years ago
parent f590613292
commit c4c0d2a80b

@ -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);

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M5,16h3v3h2v-5L5,14v2zM8,8L5,8v2h5L10,5L8,5v3zM14,19h2v-3h3v-2h-5v5zM16,8L16,5h-2v5h5L19,8h-3z"/>
</vector>

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="24dp"
android:scrollbarStyle="outsideOverlay">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tvMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_ask_show_html"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="?android:attr/textColorPrimary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<CheckBox
android:id="@+id/cbNotAgain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_no_ask_again"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvMessage" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

@ -427,17 +427,6 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swImagesInline" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/swRemoteContent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_advanced_remote_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvImagesInlineHint"
app:switchPadding="12dp" />
<TextView
android:id="@+id/tvRemoteContentHint"
android:layout_width="0dp"
@ -448,7 +437,7 @@
android:textStyle="italic"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swRemoteContent" />
app:layout_constraintTop_toBottomOf="@id/tvImagesInlineHint" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/swSeekbar"

@ -78,6 +78,17 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvNoInternetBody" />
<View
android:id="@+id/wvBody"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:paddingBottom="6dp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvBody" />
<include
android:id="@+id/InCalendar"
layout="@layout/include_message_calendar"
@ -85,7 +96,7 @@
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvBody" />
app:layout_constraintTop_toBottomOf="@id/wvBody" />
<include
android:id="@+id/inAttachmentsAlt"

@ -264,7 +264,6 @@
<string name="title_advanced_text_color">Show text colors</string>
<string name="title_advanced_collapse_quotes">Collapse quoted text</string>
<string name="title_advanced_images_inline">Automatically show inline images</string>
<string name="title_advanced_remote_content">Automatically show remote content when viewing original messages</string>
<string name="title_advanced_seekbar">Show relative conversation position with a dot</string>
<string name="title_advanced_actionbar">Show conversation action bar</string>

Loading…
Cancel
Save