diff --git a/app/src/main/java/eu/faircode/email/DaoContact.java b/app/src/main/java/eu/faircode/email/DaoContact.java
index 404ddd3814..a5a8e3265e 100644
--- a/app/src/main/java/eu/faircode/email/DaoContact.java
+++ b/app/src/main/java/eu/faircode/email/DaoContact.java
@@ -135,11 +135,12 @@ public interface DaoContact {
@Query("DELETE FROM contact" +
" WHERE last_contacted IS NOT NULL" +
- " AND last_contacted < :before" +
+ " AND last_contacted < :last" +
+ " AND times_contacted < :times" +
" AND state <> " + EntityContact.STATE_FAVORITE +
" AND (type = " + EntityContact.TYPE_TO +
" OR type = " + EntityContact.TYPE_FROM + ")")
- int deleteContacts(long before);
+ int deleteContacts(long last, int times);
@Query("DELETE FROM contact" +
" WHERE (:account IS NULL OR account = :account)" +
diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsSend.java b/app/src/main/java/eu/faircode/email/FragmentOptionsSend.java
index 3f9d75d679..8caaf9b116 100644
--- a/app/src/main/java/eu/faircode/email/FragmentOptionsSend.java
+++ b/app/src/main/java/eu/faircode/email/FragmentOptionsSend.java
@@ -29,8 +29,10 @@ import android.graphics.Color;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
+import android.text.Editable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
+import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -41,6 +43,7 @@ import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
+import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.RadioButton;
import android.widget.RadioGroup;
@@ -73,6 +76,8 @@ public class FragmentOptionsSend extends FragmentBase implements SharedPreferenc
private SwitchCompat swSuggestFrequently;
private SwitchCompat swSuggestAccount;
private SwitchCompat swAutoIdentity;
+ private EditText etAutoDeleteAge;
+ private EditText etAutoDeleteFreq;
private Button btnLocalContacts;
private SwitchCompat swSendChips;
private SwitchCompat swNavColor;
@@ -126,6 +131,7 @@ public class FragmentOptionsSend extends FragmentBase implements SharedPreferenc
private final static List RESET_OPTIONS = Collections.unmodifiableList(Arrays.asList(
"keyboard", "keyboard_no_fullscreen",
"suggest_names", "suggest_sent", "suggested_received", "suggest_frequently", "suggest_account", "auto_identity",
+ "purge_contact_age", "purge_contact_freq",
"send_reminders", "send_chips", "send_nav_color", "send_pending",
"save_revisions", "auto_save_paragraph", "auto_save_dot", "discard_delete",
"send_delayed",
@@ -162,6 +168,8 @@ public class FragmentOptionsSend extends FragmentBase implements SharedPreferenc
swSuggestFrequently = view.findViewById(R.id.swSuggestFrequently);
swSuggestAccount = view.findViewById(R.id.swSuggestAccount);
swAutoIdentity = view.findViewById(R.id.swAutoIdentity);
+ etAutoDeleteAge = view.findViewById(R.id.etAutoDeleteAge);
+ etAutoDeleteFreq = view.findViewById(R.id.etAutoDeleteFreq);
btnLocalContacts = view.findViewById(R.id.btnLocalContacts);
swSendChips = view.findViewById(R.id.swSendChips);
swNavColor = view.findViewById(R.id.swNavColor);
@@ -304,6 +312,48 @@ public class FragmentOptionsSend extends FragmentBase implements SharedPreferenc
}
});
+ etAutoDeleteAge.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ // Do nothing
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ // Do nothing
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ Integer months = Helper.parseInt(s.toString());
+ if (months == null)
+ prefs.edit().remove("purge_contact_age").apply();
+ else
+ prefs.edit().putInt("purge_contact_age", months).apply();
+ }
+ });
+
+ etAutoDeleteFreq.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ // Do nothing
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ // Do nothing
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ Integer months = Helper.parseInt(s.toString());
+ if (months == null)
+ prefs.edit().remove("purge_contact_freq").apply();
+ else
+ prefs.edit().putInt("purge_contact_freq", months).apply();
+ }
+ });
+
btnLocalContacts.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -746,6 +796,8 @@ public class FragmentOptionsSend extends FragmentBase implements SharedPreferenc
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (!RESET_OPTIONS.contains(key))
return;
+ if ("purge_contact_age".equals(key) || "purge_contact_freq".equals(key))
+ return;
getMainHandler().removeCallbacks(update);
getMainHandler().postDelayed(update, FragmentOptions.DELAY_SETOPTIONS);
@@ -780,6 +832,9 @@ public class FragmentOptionsSend extends FragmentBase implements SharedPreferenc
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
+ int purge_contact_age = prefs.getInt("purge_contact_age", 0);
+ int purge_contact_freq = prefs.getInt("purge_contact_freq", 0);
+
swKeyboard.setChecked(prefs.getBoolean("keyboard", true));
swKeyboardNoFullscreen.setChecked(prefs.getBoolean("keyboard_no_fullscreen", false));
swSuggestNames.setChecked(prefs.getBoolean("suggest_names", true));
@@ -791,6 +846,8 @@ public class FragmentOptionsSend extends FragmentBase implements SharedPreferenc
swSuggestAccount.setEnabled(swSuggestSent.isChecked() || swSuggestReceived.isChecked());
swAutoIdentity.setChecked(prefs.getBoolean("auto_identity", false));
swAutoIdentity.setEnabled(swSuggestSent.isChecked() || swSuggestReceived.isChecked());
+ etAutoDeleteAge.setText(purge_contact_age > 0 ? Integer.toString(purge_contact_age) : null);
+ etAutoDeleteFreq.setText(purge_contact_freq > 0 ? Integer.toString(purge_contact_freq) : null);
swSendChips.setChecked(prefs.getBoolean("send_chips", true));
swNavColor.setChecked(prefs.getBoolean("send_nav_color", false));
swSendReminders.setChecked(prefs.getBoolean("send_reminders", true));
diff --git a/app/src/main/java/eu/faircode/email/WorkerCleanup.java b/app/src/main/java/eu/faircode/email/WorkerCleanup.java
index 4a55685274..088cc04197 100644
--- a/app/src/main/java/eu/faircode/email/WorkerCleanup.java
+++ b/app/src/main/java/eu/faircode/email/WorkerCleanup.java
@@ -47,8 +47,6 @@ public class WorkerCleanup extends Worker {
private static final int CLEANUP_INTERVAL = 4; // hours
private static final long KEEP_FILES_DURATION = 3600 * 1000L; // milliseconds
private static final long KEEP_IMAGES_DURATION = 3 * 24 * 3600 * 1000L; // milliseconds
- private static final long KEEP_CONTACTS_DURATION = 365 * 24 * 3600 * 1000L; // milliseconds
- private static final int KEEP_CONTACTS_COUNT = 10000;
private static final Semaphore semaphore = new Semaphore(1);
@@ -336,17 +334,24 @@ public class WorkerCleanup extends Worker {
Fts4DbHelper.optimize(sdb);
}
- Log.breadcrumb("worker", "cleanup", "contacts");
- try {
- db.beginTransaction();
- int contacts = db.contact().countContacts();
- int deleted = (contacts < KEEP_CONTACTS_COUNT ? 0 :
- db.contact().deleteContacts(now - KEEP_CONTACTS_DURATION));
- db.setTransactionSuccessful();
- Log.i("Contacts=" + contacts + " deleted=" + deleted);
- } finally {
- db.endTransaction();
- }
+ int purge_contact_age = prefs.getInt("purge_contact_age", 0);
+ int purge_contact_freq = prefs.getInt("purge_contact_freq", 0);
+
+ Log.breadcrumb("worker", "cleanup", "contacts" +
+ " age=" + purge_contact_age +
+ " freq=" + purge_contact_freq);
+ if (purge_contact_age > 0 && purge_contact_freq > 0)
+ try {
+ db.beginTransaction();
+ int contacts = db.contact().countContacts();
+ int deleted = db.contact().deleteContacts(
+ now - purge_contact_age * 30 * 24 * 3600 * 1000L,
+ purge_contact_freq);
+ db.setTransactionSuccessful();
+ Log.i("Contacts=" + contacts + " deleted=" + deleted);
+ } finally {
+ db.endTransaction();
+ }
if (sqlite_analyze) {
// https://sqlite.org/lang_analyze.html
diff --git a/app/src/main/res/layout/fragment_options_send.xml b/app/src/main/res/layout/fragment_options_send.xml
index 6b4d91e484..c3b799dca7 100644
--- a/app/src/main/res/layout/fragment_options_send.xml
+++ b/app/src/main/res/layout/fragment_options_send.xml
@@ -232,6 +232,67 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swAutoIdentity" />
+
+
+
+
+
+
+
+
+
+
+ app:layout_constraintTop_toBottomOf="@id/etAutoDeleteFreq" />
Suggest addresses found in received messages
Sort suggested addresses on frequency of use
Limit suggestions to current account
+ Automatically delete local contacts older than and less used than:
Alternative reply/forward prefix
Show address bubbles
Use the identity color for the bottom action bar