diff --git a/app/src/main/java/eu/faircode/email/AdapterRule.java b/app/src/main/java/eu/faircode/email/AdapterRule.java index 5c4ff7c30d..9d644d79e8 100644 --- a/app/src/main/java/eu/faircode/email/AdapterRule.java +++ b/app/src/main/java/eu/faircode/email/AdapterRule.java @@ -53,10 +53,14 @@ import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; +import java.text.Collator; import java.text.DateFormat; import java.text.NumberFormat; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; +import java.util.Locale; import javax.mail.MessagingException; @@ -70,6 +74,7 @@ public class AdapterRule extends RecyclerView.Adapter { private NumberFormat NF = NumberFormat.getNumberInstance(); private int protocol = -1; + private String sort; private String search = null; private List all = new ArrayList<>(); private List selected = new ArrayList<>(); @@ -574,9 +579,37 @@ public class AdapterRule extends RecyclerView.Adapter { }); } - public void set(int protocol, @NonNull List rules) { + public void set(int protocol, String sort, @NonNull List rules) { this.protocol = protocol; - Log.i("Set protocol=" + protocol + " rules=" + rules.size() + " search=" + search); + this.sort = sort; + Log.i("Set protocol=" + protocol + " rules=" + rules.size() + " sort=" + sort + " search=" + search); + + final Collator collator = Collator.getInstance(Locale.getDefault()); + collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc + + Collections.sort(rules, new Comparator() { + @Override + public int compare(TupleRuleEx r1, TupleRuleEx r2) { + int order; + if ("last_applied".equals(sort)) + order = -Long.compare( + r1.last_applied == null ? 0 : r1.last_applied, + r2.last_applied == null ? 0 : r2.last_applied); + else if ("applied".equals(sort)) { + order = -Integer.compare( + r1.applied == null ? 0 : r1.applied, + r2.applied == null ? 0 : r2.applied); + } else + order = Integer.compare(r1.order, r2.order); + + if (order == 0) + return collator.compare( + r1.name == null ? "" : r1.name, + r2.name == null ? "" : r2.name); + else + return order; + } + }); all = rules; @@ -624,10 +657,16 @@ public class AdapterRule extends RecyclerView.Adapter { } } + public void setSort(String sort) { + this.sort = sort; + set(protocol, sort, all); + notifyDataSetChanged(); + } + public void search(String query) { Log.i("Rules query=" + query); search = query; - set(protocol, all); + set(protocol, sort, all); } private static class DiffCallback extends DiffUtil.Callback { diff --git a/app/src/main/java/eu/faircode/email/DaoRule.java b/app/src/main/java/eu/faircode/email/DaoRule.java index cc9fd7964b..b3859c2998 100644 --- a/app/src/main/java/eu/faircode/email/DaoRule.java +++ b/app/src/main/java/eu/faircode/email/DaoRule.java @@ -53,8 +53,7 @@ public interface DaoRule { @Query("SELECT rule.*, folder.account, folder.name AS folderName, account.name AS accountName FROM rule" + " JOIN folder ON folder.id = rule.folder" + " JOIN account ON account.id = folder.account" + - " WHERE rule.folder = :folder" + - " ORDER BY `order`, name COLLATE NOCASE") + " WHERE rule.folder = :folder") LiveData> liveRules(long folder); @Query("SELECT COUNT(*) FROM rule") diff --git a/app/src/main/java/eu/faircode/email/FragmentRules.java b/app/src/main/java/eu/faircode/email/FragmentRules.java index 10c12453e2..c77a95cf1c 100644 --- a/app/src/main/java/eu/faircode/email/FragmentRules.java +++ b/app/src/main/java/eu/faircode/email/FragmentRules.java @@ -173,14 +173,18 @@ public class FragmentRules extends FragmentBase { searching = savedInstanceState.getString("fair:searching"); adapter.search(searching); - DB db = DB.getInstance(getContext()); + final Context context = getContext(); + DB db = DB.getInstance(context); db.rule().liveRules(folder).observe(getViewLifecycleOwner(), new Observer>() { @Override public void onChanged(List rules) { if (rules == null) rules = new ArrayList<>(); - adapter.set(protocol, rules); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + String sort = prefs.getString("rule_sort", "order"); + + adapter.set(protocol, sort, rules); pbWait.setVisibility(View.GONE); grpReady.setVisibility(View.VISIBLE); @@ -270,13 +274,35 @@ public class FragmentRules extends FragmentBase { MenuCompat.setGroupDividerEnabled(menu, true); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); + String sort = prefs.getString("rule_sort", "order"); + + if ("last_applied".equals(sort)) + menu.findItem(R.id.menu_sort_on_last_applied).setChecked(true); + else if ("applied".equals(sort)) + menu.findItem(R.id.menu_sort_on_applied).setChecked(true); + else + menu.findItem(R.id.menu_sort_on_order).setChecked(true); + super.onCreateOptionsMenu(menu, inflater); } @Override public boolean onOptionsItemSelected(MenuItem item) { int itemId = item.getItemId(); - if (itemId == R.id.menu_export) { + if (itemId == R.id.menu_sort_on_order) { + item.setChecked(true); + onMenuSort("order"); + return true; + } else if (itemId == R.id.menu_sort_on_applied) { + item.setChecked(true); + onMenuSort("applied"); + return true; + } else if (itemId == R.id.menu_sort_on_last_applied) { + item.setChecked(true); + onMenuSort("last_applied"); + return true; + } else if (itemId == R.id.menu_export) { onMenuExport(); return true; } else if (itemId == R.id.menu_import) { @@ -289,6 +315,13 @@ public class FragmentRules extends FragmentBase { return super.onOptionsItemSelected(item); } + private void onMenuSort(String sort) { + final Context context = getContext(); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + prefs.edit().putString("rule_sort", sort).apply(); + adapter.setSort(sort); + } + private void onMenuExport() { final Context context = getContext(); if (!ActivityBilling.isPro(context)) { diff --git a/app/src/main/res/menu/menu_rules.xml b/app/src/main/res/menu/menu_rules.xml index dce5ab2ba2..44244d9503 100644 --- a/app/src/main/res/menu/menu_rules.xml +++ b/app/src/main/res/menu/menu_rules.xml @@ -8,6 +8,26 @@ app:actionViewClass="androidx.appcompat.widget.SearchView" app:showAsAction="collapseActionView|always" /> + + + + + + + + + + Hidden Oldest first + Order + Applied count + Last applied + Filter out Read Unstarred