diff --git a/app/src/main/java/eu/faircode/email/ActivityCode.java b/app/src/main/java/eu/faircode/email/ActivityCode.java index 950b3a59ad..0ccfa94fa8 100644 --- a/app/src/main/java/eu/faircode/email/ActivityCode.java +++ b/app/src/main/java/eu/faircode/email/ActivityCode.java @@ -19,6 +19,7 @@ package eu.faircode.email; Copyright 2018-2023 by Marcel Bokhorst (M66B) */ +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; @@ -35,6 +36,7 @@ import android.view.View; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; +import android.widget.Toast; import androidx.activity.OnBackPressedCallback; import androidx.annotation.NonNull; @@ -46,6 +48,10 @@ import org.jsoup.nodes.Element; import org.w3c.dom.css.CSSStyleSheet; import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.util.List; @@ -54,9 +60,11 @@ public class ActivityCode extends ActivityBase { private ContentLoadingProgressBar pbWait; private Group grpReady; - private boolean lines = BuildConfig.DEBUG; + private boolean lines = false; private boolean links = false; - private boolean sanitize = BuildConfig.DEBUG; + private boolean sanitize = false; + + private static final int REQUEST_SAVE = 1; @Override protected void onCreate(Bundle savedInstanceState) { @@ -151,18 +159,6 @@ public class ActivityCode extends ActivityBase { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); boolean debug = prefs.getBoolean("debug", false); - menu.findItem(R.id.menu_lines) - .setChecked(lines) - .setIcon(lines - ? R.drawable.twotone_speaker_notes_off_24 - : R.drawable.twotone_speaker_notes_24); - - menu.findItem(R.id.menu_links) - .setChecked(links) - .setIcon(links - ? R.drawable.twotone_link_off_24 - : R.drawable.twotone_link_24); - menu.findItem(R.id.menu_sanitize) .setVisible(BuildConfig.DEBUG || debug) .setChecked(sanitize) @@ -173,6 +169,8 @@ public class ActivityCode extends ActivityBase { ? R.string.title_legend_show_full : R.string.title_legend_show_reformatted)); + menu.findItem(R.id.menu_lines).setChecked(lines); + menu.findItem(R.id.menu_links).setChecked(links); return super.onPrepareOptionsMenu(menu); } @@ -180,28 +178,47 @@ public class ActivityCode extends ActivityBase { @Override public boolean onOptionsItemSelected(MenuItem item) { int itemId = item.getItemId(); - if (itemId == android.R.id.home) { + if (itemId == R.id.menu_sanitize) { + sanitize = !sanitize; + invalidateOptionsMenu(); + load(); + return true; + } else if (itemId == android.R.id.home) { finishAndRemoveTask(); return true; } else if (itemId == R.id.menu_lines) { lines = !lines; - invalidateOptionsMenu(); + item.setChecked(lines); load(); return true; } else if (itemId == R.id.menu_links) { links = !links; - invalidateOptionsMenu(); + item.setChecked(links); load(); return true; - } else if (itemId == R.id.menu_sanitize) { - sanitize = !sanitize; - invalidateOptionsMenu(); - load(); + } else if (itemId == R.id.menu_save) { + selectFile(); return true; } return super.onOptionsItemSelected(item); } + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + try { + switch (requestCode) { + case REQUEST_SAVE: + if (resultCode == RESULT_OK) + save(data); + break; + } + } catch (Throwable ex) { + Log.e(ex); + } + } + private void load() { Intent intent = getIntent(); long id = intent.getLongExtra("id", -1L); @@ -304,6 +321,82 @@ public class ActivityCode extends ActivityBase { protected void onException(Bundle args, @NonNull Throwable ex) { Log.unexpectedError(getSupportFragmentManager(), ex, false); } - }.execute(this, args, "view:text"); + }.execute(this, args, "code:view"); + } + + private void selectFile() { + long id = getIntent().getLongExtra("id", -1L); + + Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + intent.setType("*/*"); + intent.putExtra(Intent.EXTRA_TITLE, Long.toString(id) + ".html"); + Helper.openAdvanced(this, intent); + startActivityForResult(intent, REQUEST_SAVE); + } + + private void save(Intent data) { + long id = getIntent().getLongExtra("id", -1L); + + Bundle args = new Bundle(); + args.putLong("id", id); + args.putParcelable("uri", data.getData()); + + new SimpleTask() { + private Toast toast = null; + + @Override + protected void onPreExecute(Bundle args) { + toast = ToastEx.makeText(ActivityCode.this, R.string.title_executing, Toast.LENGTH_LONG); + toast.show(); + } + + @Override + protected void onPostExecute(Bundle args) { + if (toast != null) + toast.cancel(); + } + + @Override + protected Void onExecute(Context context, Bundle args) throws Throwable { + long id = args.getLong("id"); + Uri uri = args.getParcelable("uri"); + + if (uri == null) + throw new FileNotFoundException(); + + if (!"content".equals(uri.getScheme())) { + Log.w("Export uri=" + uri); + throw new IllegalArgumentException(uri.getScheme()); + } + + DB db = DB.getInstance(context); + EntityMessage message = db.message().getMessage(id); + if (message == null) + return null; + + File file = message.getFile(context); + + ContentResolver resolver = context.getContentResolver(); + try (OutputStream os = resolver.openOutputStream(uri)) { + try (InputStream is = new FileInputStream(file)) { + Helper.copy(is, os); + } + } + + return null; + } + + @Override + protected void onExecuted(Bundle args, Void data) { + ToastEx.makeText(ActivityCode.this, R.string.title_completed, Toast.LENGTH_LONG).show(); + } + + @Override + protected void onException(Bundle args, @NonNull Throwable ex) { + Log.unexpectedError(getSupportFragmentManager(), ex, false); + } + }.execute(this, args, "code:save"); } } diff --git a/app/src/main/res/drawable/twotone_link_24.xml b/app/src/main/res/drawable/twotone_link_24.xml deleted file mode 100644 index 9affeb9f87..0000000000 --- a/app/src/main/res/drawable/twotone_link_24.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/twotone_link_off_24.xml b/app/src/main/res/drawable/twotone_link_off_24.xml deleted file mode 100644 index d9d49a7bab..0000000000 --- a/app/src/main/res/drawable/twotone_link_off_24.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/twotone_speaker_notes_24.xml b/app/src/main/res/drawable/twotone_speaker_notes_24.xml deleted file mode 100644 index e86b90fb2f..0000000000 --- a/app/src/main/res/drawable/twotone_speaker_notes_24.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - diff --git a/app/src/main/res/drawable/twotone_speaker_notes_off_24.xml b/app/src/main/res/drawable/twotone_speaker_notes_off_24.xml deleted file mode 100644 index a22022b1ae..0000000000 --- a/app/src/main/res/drawable/twotone_speaker_notes_off_24.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - diff --git a/app/src/main/res/menu/menu_code.xml b/app/src/main/res/menu/menu_code.xml index 95f705a37f..2525689432 100644 --- a/app/src/main/res/menu/menu_code.xml +++ b/app/src/main/res/menu/menu_code.xml @@ -1,24 +1,27 @@ + + + app:showAsAction="never" /> + app:showAsAction="never" /> + android:id="@+id/menu_save" + android:title="@string/title_save" + app:showAsAction="never" />