diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java b/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java index 5cee090cb7..5739988ef1 100644 --- a/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java +++ b/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java @@ -46,10 +46,11 @@ import androidx.lifecycle.Lifecycle; import androidx.lifecycle.Observer; import androidx.preference.PreferenceManager; +import io.requery.android.database.sqlite.SQLiteDatabase; + public class FragmentOptionsMisc extends FragmentBase implements SharedPreferences.OnSharedPreferenceChangeListener { private SwitchCompat swExternalSearch; private SwitchCompat swFts; - private Button btnFtsReset; private TextView tvFtsIndexed; private SwitchCompat swEnglish; private SwitchCompat swWatchdog; @@ -93,7 +94,6 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc swExternalSearch = view.findViewById(R.id.swExternalSearch); swFts = view.findViewById(R.id.swFts); - btnFtsReset = view.findViewById(R.id.btnFtsReset); tvFtsIndexed = view.findViewById(R.id.tvFtsIndexed); swEnglish = view.findViewById(R.id.swEnglish); swWatchdog = view.findViewById(R.id.swWatchdog); @@ -137,33 +137,31 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc @Override public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { prefs.edit().putBoolean("fts", checked).apply(); + WorkerFts.init(getContext(), true); - } - }); - btnFtsReset.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Bundle args = new Bundle(); - - new SimpleTask() { - @Override - protected Void onExecute(Context context, Bundle args) throws Throwable { - DB db = DB.getInstance(context); - db.message().resetFts(); - return null; - } - - @Override - protected void onExecuted(Bundle args, Void data) { - WorkerFts.init(getContext(), true); - } - - @Override - protected void onException(Bundle args, Throwable ex) { - Log.unexpectedError(getParentFragmentManager(), ex); - } - }.execute(FragmentOptionsMisc.this, args, "fts:reset"); + if (!checked) { + Bundle args = new Bundle(); + + new SimpleTask() { + @Override + protected Void onExecute(Context context, Bundle args) { + SQLiteDatabase sdb = FtsDbHelper.getInstance(context); + FtsDbHelper.delete(sdb); + FtsDbHelper.optimize(sdb); + + DB db = DB.getInstance(context); + db.message().resetFts(); + + return null; + } + + @Override + protected void onException(Bundle args, Throwable ex) { + Log.unexpectedError(getParentFragmentManager(), ex); + } + }.execute(FragmentOptionsMisc.this, args, "fts:reset"); + } } }); @@ -246,12 +244,18 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc DB db = DB.getInstance(getContext()); db.message().liveFts().observe(getViewLifecycleOwner(), new Observer() { + private TupleFtsStats last = null; + @Override public void onChanged(TupleFtsStats stats) { if (stats == null) tvFtsIndexed.setText(null); - else - tvFtsIndexed.setText(getString(R.string.title_advanced_fts_indexed, stats.fts, stats.total)); + else if (last == null || !last.equals(stats)) + tvFtsIndexed.setText(getString(R.string.title_advanced_fts_indexed, + stats.fts, + stats.total, + Helper.humanReadableByteCount(FtsDbHelper.size(getContext()), true))); + last = stats; } }); diff --git a/app/src/main/java/eu/faircode/email/FtsDbHelper.java b/app/src/main/java/eu/faircode/email/FtsDbHelper.java index b45411fd2d..7e159ba677 100644 --- a/app/src/main/java/eu/faircode/email/FtsDbHelper.java +++ b/app/src/main/java/eu/faircode/email/FtsDbHelper.java @@ -85,6 +85,10 @@ public class FtsDbHelper extends SQLiteOpenHelper { db.insert("message", SQLiteDatabase.CONFLICT_FAIL, cv); } + static void delete(SQLiteDatabase db) { + db.delete("message", null, null); + } + static void delete(SQLiteDatabase db, long id) { db.delete("message", "rowid = ?", new Object[]{id}); } @@ -120,4 +124,13 @@ public class FtsDbHelper extends SQLiteOpenHelper { null, null, null, null, "time"); } + + static long size(Context context) { + return context.getDatabasePath(DATABASE_NAME).length(); + } + + static void optimize(SQLiteDatabase db) { + Log.i("FTS optimize"); + db.execSQL("INSERT INTO message (message) VALUES ('optimize')"); + } } diff --git a/app/src/main/java/eu/faircode/email/TupleFtsStats.java b/app/src/main/java/eu/faircode/email/TupleFtsStats.java index ac2cc3759c..f075b7cbcc 100644 --- a/app/src/main/java/eu/faircode/email/TupleFtsStats.java +++ b/app/src/main/java/eu/faircode/email/TupleFtsStats.java @@ -19,7 +19,18 @@ package eu.faircode.email; Copyright 2018-2020 by Marcel Bokhorst (M66B) */ +import androidx.annotation.Nullable; + public class TupleFtsStats { public long fts; public long total; + + @Override + public boolean equals(@Nullable Object obj) { + if (obj instanceof TupleFtsStats) { + TupleFtsStats other = (TupleFtsStats) obj; + return (this.fts == other.fts && this.total == other.total); + } else + return false; + } } diff --git a/app/src/main/java/eu/faircode/email/WorkerCleanup.java b/app/src/main/java/eu/faircode/email/WorkerCleanup.java index 8e53c6a2b2..605f90cbad 100644 --- a/app/src/main/java/eu/faircode/email/WorkerCleanup.java +++ b/app/src/main/java/eu/faircode/email/WorkerCleanup.java @@ -68,6 +68,7 @@ public class WorkerCleanup extends Worker { static void cleanup(Context context, boolean manual) { DB db = DB.getInstance(context); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); try { Log.i("Start cleanup manual=" + manual); @@ -111,7 +112,6 @@ public class WorkerCleanup extends Worker { ServiceSynchronize.reschedule(context); // Clear last search - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); prefs.edit().remove("last_search").apply(); } @@ -193,21 +193,26 @@ public class WorkerCleanup extends Worker { } } - Log.i("Cleanup FTS"); - int fts = 0; - SQLiteDatabase sdb = FtsDbHelper.getInstance(context); - try (Cursor cursor = FtsDbHelper.getIds(sdb)) { - while (cursor.moveToNext()) { - long rowid = cursor.getLong(0); - EntityMessage message = db.message().getMessage(rowid); - if (message == null) { - Log.i("Deleting rowid" + rowid); - FtsDbHelper.delete(sdb, rowid); - fts++; + boolean fts = prefs.getBoolean("fts", true); + Log.i("Cleanup FTS=" + fts); + if (fts) { + int deleted = 0; + SQLiteDatabase sdb = FtsDbHelper.getInstance(context); + try (Cursor cursor = FtsDbHelper.getIds(sdb)) { + while (cursor.moveToNext()) { + long rowid = cursor.getLong(0); + EntityMessage message = db.message().getMessage(rowid); + if (message == null || !message.fts) { + Log.i("Deleting FTS rowid=" + rowid); + FtsDbHelper.delete(sdb, rowid); + deleted++; + } } } + Log.i("Cleanup FTS=" + deleted); + if (manual) + FtsDbHelper.optimize(sdb); } - Log.i("Cleanup FTS=" + fts); Log.i("Cleanup contacts"); int contacts = db.contact().deleteContacts(now - KEEP_CONTACTS_DURATION); @@ -221,7 +226,6 @@ public class WorkerCleanup extends Worker { } finally { Log.i("End cleanup"); - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); prefs.edit() .remove("crash_report_count") .putLong("last_cleanup", new Date().getTime()) diff --git a/app/src/main/res/layout/fragment_options_misc.xml b/app/src/main/res/layout/fragment_options_misc.xml index 6f293a07d3..c25a1936a7 100644 --- a/app/src/main/res/layout/fragment_options_misc.xml +++ b/app/src/main/res/layout/fragment_options_misc.xml @@ -47,29 +47,18 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/swFts" /> -