diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java b/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java index b33f451ab3..bf84f5a164 100644 --- a/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java +++ b/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java @@ -30,6 +30,7 @@ import android.content.pm.PackageManager; import android.database.sqlite.SQLiteDatabaseCorruptException; import android.graphics.Paint; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.Debug; import android.provider.Settings; @@ -57,10 +58,13 @@ import androidx.lifecycle.Observer; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.preference.PreferenceManager; +import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.Locale; import java.util.SortedMap; @@ -105,9 +109,12 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc private TextView tvFingerprint; private Button btnCharsets; private Button btnCiphers; + private Button btnFiles; private Group grpDebug; + private final static long MIN_FILE_SIZE = 1024 * 1024L; + private final static String[] RESET_OPTIONS = new String[]{ "shortcuts", "fts", "language", "watchdog", "updates", "experiments", "query_threads", "crash_reports", "cleanup_attachments", @@ -166,6 +173,7 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc tvFingerprint = view.findViewById(R.id.tvFingerprint); btnCharsets = view.findViewById(R.id.btnCharsets); btnCiphers = view.findViewById(R.id.btnCiphers); + btnFiles = view.findViewById(R.id.btnFiles); grpDebug = view.findViewById(R.id.grpDebug); @@ -387,6 +395,16 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc @Override public void onClick(View v) { new SimpleTask>() { + @Override + protected void onPreExecute(Bundle args) { + btnCharsets.setEnabled(false); + } + + @Override + protected void onPostExecute(Bundle args) { + btnCharsets.setEnabled(true); + } + @Override protected SortedMap onExecute(Context context, Bundle args) { return Charset.availableCharsets(); @@ -468,6 +486,87 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc } }); + final String title = getString(R.string.title_advanced_files, Helper.humanReadableByteCount(MIN_FILE_SIZE)); + btnFiles.setText(title); + + btnFiles.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + new SimpleTask>() { + @Override + protected void onPreExecute(Bundle args) { + btnFiles.setEnabled(false); + } + + @Override + protected void onPostExecute(Bundle args) { + btnFiles.setEnabled(true); + } + + @Override + protected List onExecute(Context context, Bundle args) { + List files = new ArrayList<>(); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + files.addAll(getFiles(context.getFilesDir(), MIN_FILE_SIZE)); + files.addAll(getFiles(context.getCacheDir(), MIN_FILE_SIZE)); + } else + files.addAll(getFiles(context.getDataDir(), MIN_FILE_SIZE)); + Collections.sort(files, new Comparator() { + @Override + public int compare(File f1, File f2) { + return -Long.compare(f1.length(), f2.length()); + } + }); + return files; + } + + private List getFiles(File dir, long minSize) { + List files = new ArrayList(); + File[] listed = dir.listFiles(); + if (listed != null) + for (File file : listed) + if (file.isDirectory()) + files.addAll(getFiles(file, minSize)); + else if (file.length() > minSize) + files.add(file); + return files; + } + + @Override + protected void onExecuted(Bundle args, List files) { + StringBuilder sb = new StringBuilder(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) + sb.append("Data: ").append(getContext().getDataDir()).append("\r\n"); + sb.append("Files: ").append(getContext().getFilesDir()).append("\r\n"); + sb.append("Cache: ").append(getContext().getCacheDir()).append("\r\n"); + + for (File file : files) + sb.append(file.getAbsolutePath()) + .append(' ') + .append(Helper.humanReadableByteCount(file.length())) + .append("\r\n"); + + new AlertDialog.Builder(getContext()) + .setTitle(title) + .setMessage(sb.toString()) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // Do nothing + } + }) + .show(); + } + + @Override + protected void onException(Bundle args, Throwable ex) { + Log.unexpectedError(getParentFragmentManager(), ex); + } + }.execute(FragmentOptionsMisc.this, new Bundle(), "setup:files"); + } + }); + tvFtsIndexed.setText(null); DB db = DB.getInstance(getContext()); diff --git a/app/src/main/res/layout/fragment_options_misc.xml b/app/src/main/res/layout/fragment_options_misc.xml index 878f2069f8..83265c711e 100644 --- a/app/src/main/res/layout/fragment_options_misc.xml +++ b/app/src/main/res/layout/fragment_options_misc.xml @@ -495,10 +495,20 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/btnCharsets" /> +