diff --git a/app/src/amazon/AndroidManifest.xml b/app/src/amazon/AndroidManifest.xml index ed0c10c11b..bd58679360 100644 --- a/app/src/amazon/AndroidManifest.xml +++ b/app/src/amazon/AndroidManifest.xml @@ -474,6 +474,15 @@ + + + + + + + + + + . + + Copyright 2018-2023 by Marcel Bokhorst (M66B) +*/ + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.constraintlayout.widget.Group; +import androidx.preference.PreferenceManager; + +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.w3c.dom.css.CSSStyleSheet; + +import java.io.File; +import java.util.List; + +public class ActivityHTML extends ActivityBase { + private TextView tvText; + private ContentLoadingProgressBar pbWait; + private Group grpReady; + + private boolean sanitize = BuildConfig.DEBUG; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + if (savedInstanceState != null) + sanitize = savedInstanceState.getBoolean("fair:sanitize"); + + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + View view = LayoutInflater.from(this).inflate(R.layout.activity_text, null); + setContentView(view); + + tvText = findViewById(R.id.tvText); + pbWait = findViewById(R.id.pbWait); + grpReady = findViewById(R.id.grpReady); + + // Initialize + grpReady.setVisibility(View.GONE); + + load(); + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + setIntent(intent); + load(); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + outState.putBoolean("fair:sanitize", sanitize); + super.onSaveInstanceState(outState); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.menu_html, menu); + return true; + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + boolean debug = prefs.getBoolean("debug", false); + + menu.findItem(R.id.menu_sanitize) + .setVisible(BuildConfig.DEBUG || debug) + .setChecked(sanitize); + return super.onPrepareOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int itemId = item.getItemId(); + if (itemId == android.R.id.home) { + finish(); + return true; + } else if (itemId == R.id.menu_sanitize) { + sanitize = !sanitize; + item.setChecked(sanitize); + load(); + return true; + } + return super.onOptionsItemSelected(item); + } + + private void load() { + Intent intent = getIntent(); + long id = intent.getLongExtra("id", -1L); + Log.i("Text id=" + id + " sanitize=" + sanitize); + + Bundle args = new Bundle(); + args.putLong("id", id); + args.putBoolean("sanitize", sanitize); + + new SimpleTask() { + @Override + protected void onPreExecute(Bundle args) { + pbWait.setVisibility(View.VISIBLE); + } + + @Override + protected void onPostExecute(Bundle args) { + pbWait.setVisibility(View.GONE); + } + + @Override + protected String onExecute(Context context, Bundle args) throws Throwable { + long id = args.getLong("id"); + boolean sanitize = args.getBoolean("sanitize"); + + DB db = DB.getInstance(context); + EntityMessage message = db.message().getMessage(id); + if (message == null) + return null; + + args.putString("subject", message.subject); + + File file = message.getFile(context); + if (sanitize) { + Document d = JsoupEx.parse(file); + + List sheets = + HtmlHelper.parseStyles(d.head().select("style")); + for (Element element : d.select("*")) { + String computed = HtmlHelper.processStyles(context, + element.tagName(), + element.className(), + element.attr("style"), + sheets); + if (!TextUtils.isEmpty(computed)) + element.attr("x-computed", computed); + } + + d = HtmlHelper.sanitizeView(context, d, false); + d.outputSettings().prettyPrint(true).outline(true).indentAmount(1); + + return d.html(); + } else + return Helper.readText(file); + } + + @Override + protected void onExecuted(Bundle args, String text) { + getSupportActionBar().setSubtitle(args.getString("subject")); + + tvText.setText(text); + grpReady.setVisibility(View.VISIBLE); + } + + @Override + protected void onException(Bundle args, @NonNull Throwable ex) { + Log.unexpectedError(getSupportFragmentManager(), ex, false); + } + }.execute(this, args, "view:text"); + } +} diff --git a/app/src/main/java/eu/faircode/email/AdapterMessage.java b/app/src/main/java/eu/faircode/email/AdapterMessage.java index e84fa8df79..14b6064883 100644 --- a/app/src/main/java/eu/faircode/email/AdapterMessage.java +++ b/app/src/main/java/eu/faircode/email/AdapterMessage.java @@ -149,7 +149,6 @@ import com.google.android.material.snackbar.Snackbar; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; -import org.w3c.dom.css.CSSStyleSheet; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; @@ -6108,7 +6107,7 @@ public class AdapterMessage extends RecyclerView.Adapter() { - @Override - protected File onExecute(Context context, Bundle args) throws IOException { - Long id = args.getLong("id"); - - DB db = DB.getInstance(context); - EntityMessage message = db.message().getMessage(id); - if (message == null || !message.content) - return null; - - File file = message.getFile(context); - Document d = JsoupEx.parse(file); - - if (BuildConfig.DEBUG) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - boolean overview_mode = prefs.getBoolean("overview_mode", false); - HtmlHelper.setViewport(d, overview_mode); - } - - d.head().prependElement("meta").attr("charset", "utf-8"); - - if (message.language != null) - d.body().attr("lang", message.language); - - List sheets = - HtmlHelper.parseStyles(d.head().select("style")); - for (Element element : d.select("*")) { - String computed = HtmlHelper.processStyles(context, - element.tagName(), - element.className(), - element.attr("style"), - sheets); - if (!TextUtils.isEmpty(computed)) - element.attr("x-computed", computed); - } - - if (BuildConfig.DEBUG) { - d = HtmlHelper.sanitizeView(context, d, false); - d.outputSettings().prettyPrint(true).outline(true).indentAmount(1); - } - - File dir = Helper.ensureExists(new File(context.getFilesDir(), "shared")); - File share = new File(dir, message.id + ".txt"); - Helper.writeText(share, d.html()); - - return share; - } - - @Override - protected void onExecuted(Bundle args, File share) { - Helper.share(context, share, "text/plain", share.getName()); - } - - @Override - protected void onException(Bundle args, Throwable ex) { - Log.unexpectedError(parentFragment.getParentFragmentManager(), ex); - } - }.execute(context, owner, args, "message:headers"); + context.startActivity(new Intent(context, ActivityHTML.class) + .putExtra("id", message.id)); } private void onMenuRawSave(TupleMessageEx message) { diff --git a/app/src/main/res/layout/activity_text.xml b/app/src/main/res/layout/activity_text.xml new file mode 100644 index 0000000000..1b59c5deca --- /dev/null +++ b/app/src/main/res/layout/activity_text.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + diff --git a/app/src/main/res/menu/menu_html.xml b/app/src/main/res/menu/menu_html.xml new file mode 100644 index 0000000000..04d5268559 --- /dev/null +++ b/app/src/main/res/menu/menu_html.xml @@ -0,0 +1,9 @@ + + + + diff --git a/app/src/main/res/menu/popup_message_more.xml b/app/src/main/res/menu/popup_message_more.xml index 0c83cc45ec..9976b0089e 100644 --- a/app/src/main/res/menu/popup_message_more.xml +++ b/app/src/main/res/menu/popup_message_more.xml @@ -138,9 +138,9 @@ android:title="@string/title_show_headers" /> + android:title="@string/title_show_html" /> Downloading images might take some time Print block quotes lines Show headers - Share as HTML + Show HTML Save raw message Send as attachment Message @@ -2344,6 +2344,7 @@ Follow dark system theme Google removed dark mode for Android versions before version 10 + Sanitize Important diff --git a/app/src/play/AndroidManifest.xml b/app/src/play/AndroidManifest.xml index 7da46ef521..c26a247b80 100644 --- a/app/src/play/AndroidManifest.xml +++ b/app/src/play/AndroidManifest.xml @@ -474,6 +474,15 @@ + +