From e4d6244e0d21faa302675d5e8deca54ea6f20e20 Mon Sep 17 00:00:00 2001 From: M66B Date: Sat, 4 Jan 2025 19:43:23 +0100 Subject: [PATCH] Added sort on sender name Requires SDK 34 = Android 14 --- app/src/main/java/eu/faircode/email/DB.java | 2 ++ .../java/eu/faircode/email/DaoMessage.java | 34 +++++++------------ .../eu/faircode/email/FragmentMessages.java | 10 ++++++ .../faircode/email/FragmentOptionsMisc.java | 13 ------- .../eu/faircode/email/ViewModelMessages.java | 22 +++++++----- .../main/res/layout/fragment_options_misc.xml | 13 +------ app/src/main/res/menu/menu_messages.xml | 3 ++ app/src/main/res/values/strings.xml | 1 + 8 files changed, 42 insertions(+), 56 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/DB.java b/app/src/main/java/eu/faircode/email/DB.java index de5aa3e2a6..acf1831c87 100644 --- a/app/src/main/java/eu/faircode/email/DB.java +++ b/app/src/main/java/eu/faircode/email/DB.java @@ -168,6 +168,8 @@ public abstract class DB extends RoomDatabase { try { // https://www.sqlite.org/json1.html // The JSON functions and operators are built into SQLite by default, as of SQLite version 3.38.0 (2022-02-22) + // SDK 14 / Android 14 has 3.39.2 + // https://stackoverflow.com/questions/2421189/version-of-sqlite-used-in-android String version = getSqliteVersion(); if (version == null) return false; diff --git a/app/src/main/java/eu/faircode/email/DaoMessage.java b/app/src/main/java/eu/faircode/email/DaoMessage.java index 66f9d352b3..c505974d4c 100644 --- a/app/src/main/java/eu/faircode/email/DaoMessage.java +++ b/app/src/main/java/eu/faircode/email/DaoMessage.java @@ -1119,15 +1119,7 @@ public interface DaoMessage { " OR (NOT :found AND :type IS NULL AND folder.unified)" + " OR (NOT :found AND folder.type = :type)" + " THEN message.received ELSE 0 END) AS dummy" + - " FROM (SELECT * FROM message" + - " WHERE message.thread IN" + - " (SELECT DISTINCT mm.thread FROM folder ff" + - " JOIN message mm ON mm.folder = ff.id" + - " WHERE ((:found AND mm.ui_found)" + - " OR (NOT :found AND :type IS NULL AND ff.unified)" + - " OR (NOT :found AND :type IS NOT NULL AND ff.type = :type))" + - " AND (NOT mm.ui_hide OR :debug))" + - " ORDER BY received DESC) AS message" + // group_concat + " FROM message" + " JOIN account_view AS account ON account.id = message.account" + " LEFT JOIN identity_view AS identity ON identity.id = message.identity" + " JOIN folder_view AS folder ON folder.id = message.folder" + @@ -1141,8 +1133,9 @@ public interface DaoMessage { " OR (NOT :found AND :type IS NULL AND folder.unified)" + " OR (NOT :found AND :type IS NOT NULL AND folder.type = :type)) > 0)" + // thread can be the same in different accounts " AND SUM(NOT message.ui_hide OR :debug) > 0" + - " AND (NOT :filter_seen OR SUM(1 - message.ui_seen) > 0)" + - " AND (NOT :filter_unflagged OR COUNT(message.id) - SUM(1 - message.ui_flagged) > 0)" + + " AND (NOT (:filter_seen AND NOT :filter_unflagged) OR SUM(1 - message.ui_seen) > 0)" + + " AND (NOT (:filter_unflagged AND NOT :filter_seen) OR COUNT(message.id) - SUM(1 - message.ui_flagged) > 0)" + + " AND (NOT (:filter_seen AND :filter_unflagged) OR SUM(1 - message.ui_seen) > 0 OR COUNT(message.id) - SUM(1 - message.ui_flagged) > 0)" + " AND (NOT :filter_unknown OR SUM(message.avatar IS NOT NULL AND message.sender <> identity.email) > 0)" + " AND (NOT :filter_snoozed OR message.ui_snoozed IS NULL OR " + is_drafts + ")" + " AND (NOT :filter_deleted OR NOT message.ui_deleted)" + @@ -1154,6 +1147,7 @@ public interface DaoMessage { " WHEN 'starred' = :sort1 THEN COUNT(message.id) - SUM(1 - message.ui_flagged) = 0" + " WHEN 'priority' = :sort1 THEN -IFNULL(message.priority, 1)" + " WHEN 'sender' = :sort1 THEN LOWER(message.sender)" + + " WHEN 'sender_name' = :sort1 THEN LOWER(COALESCE(json_extract(message.`from`, '$[0].personal'), json_extract(message.`from`, '$[0].address')))" + " WHEN 'subject' = :sort1 THEN LOWER(message.subject)" + " WHEN 'size' = :sort1 THEN -SUM(message.total)" + " WHEN 'attachments' = :sort1 THEN -SUM(message.attachments)" + @@ -1167,7 +1161,7 @@ public interface DaoMessage { " ELSE 0" + " END" + ", CASE WHEN :ascending THEN message.received ELSE -message.received END") - DataSource.Factory pagedUnifiedLegacy( + DataSource.Factory pagedUnifiedJson( String type, String category, boolean threading, boolean group_category, String sort1, String sort2, boolean ascending, @@ -1205,13 +1199,7 @@ public interface DaoMessage { " (:found AND folder.type <> '" + EntityFolder.ARCHIVE + "')" + " OR (NOT :found AND folder.id = :folder)" + " THEN message.received ELSE 0 END) AS dummy" + - " FROM (SELECT * FROM message" + - " WHERE message.thread IN" + - " (SELECT DISTINCT mm.thread FROM message mm" + - " WHERE mm.folder = :folder" + - " AND (NOT mm.ui_hide OR :debug)" + - " AND (NOT :found OR mm.ui_found))" + - " ORDER BY received DESC) AS message" + // group_concat + " FROM message" + " JOIN account_view AS account ON account.id = message.account" + " LEFT JOIN identity_view AS identity ON identity.id = message.identity" + " JOIN folder_view AS folder ON folder.id = message.folder" + @@ -1224,8 +1212,9 @@ public interface DaoMessage { " HAVING (SUM((:found AND message.ui_found)" + " OR (NOT :found AND message.folder = :folder)) > 0)" + " AND SUM(NOT message.ui_hide OR :debug) > 0" + - " AND (NOT :filter_seen OR SUM(1 - message.ui_seen) > 0 OR " + is_outbox + ")" + - " AND (NOT :filter_unflagged OR COUNT(message.id) - SUM(1 - message.ui_flagged) > 0 OR " + is_outbox + ")" + + " AND (NOT (:filter_seen AND NOT :filter_unflagged) OR SUM(1 - message.ui_seen) > 0 OR " + is_outbox + ")" + + " AND (NOT (:filter_unflagged AND NOT :filter_seen) OR COUNT(message.id) - SUM(1 - message.ui_flagged) > 0 OR " + is_outbox + ")" + + " AND (NOT (:filter_seen AND :filter_unflagged) OR SUM(1 - message.ui_seen) > 0 OR COUNT(message.id) - SUM(1 - message.ui_flagged) > 0 OR " + is_outbox + ")" + " AND (NOT :filter_unknown OR SUM(message.avatar IS NOT NULL AND message.sender <> identity.email) > 0" + " OR " + is_outbox + " OR " + is_drafts + " OR " + is_sent + ")" + " AND (NOT :filter_snoozed OR message.ui_snoozed IS NULL OR " + is_outbox + " OR " + is_drafts + ")" + @@ -1237,6 +1226,7 @@ public interface DaoMessage { " WHEN 'starred' = :sort1 THEN COUNT(message.id) - SUM(1 - message.ui_flagged) = 0" + " WHEN 'priority' = :sort1 THEN -IFNULL(message.priority, 1)" + " WHEN 'sender' = :sort1 THEN LOWER(message.sender)" + + " WHEN 'sender_name' = :sort1 THEN LOWER(COALESCE(json_extract(message.`from`, '$[0].personal'), json_extract(message.`from`, '$[0].address')))" + " WHEN 'subject' = :sort1 THEN LOWER(message.subject)" + " WHEN 'size' = :sort1 THEN -SUM(message.total)" + " WHEN 'attachments' = :sort1 THEN -SUM(message.attachments)" + @@ -1250,7 +1240,7 @@ public interface DaoMessage { " ELSE 0" + " END" + ", CASE WHEN :ascending THEN message.received ELSE -message.received END") - DataSource.Factory pagedFolderLegacy( + DataSource.Factory pagedFolderJson( long folder, boolean threading, String sort1, String sort2, boolean ascending, boolean filter_seen, boolean filter_unflagged, boolean filter_unknown, boolean filter_snoozed, boolean filter_deleted, String filter_language, diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java index 937d72c2e7..1bc635280d 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessages.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java @@ -6429,10 +6429,14 @@ public class FragmentMessages extends FragmentBase menu.findItem(R.id.menu_sort_on_unread_starred).setVisible(false); menu.findItem(R.id.menu_sort_on_starred_unread).setVisible(false); menu.findItem(R.id.menu_sort_on_sender).setVisible(false); + menu.findItem(R.id.menu_sort_on_sender_name).setVisible(false); menu.findItem(R.id.menu_sort_on_subject).setVisible(false); menu.findItem(R.id.menu_sort_on_size).setVisible(false); menu.findItem(R.id.menu_sort_on_attachments).setVisible(false); menu.findItem(R.id.menu_sort_on_snoozed).setVisible(false); + } else { + if (!DB.hasJson()) + menu.findItem(R.id.menu_sort_on_sender_name).setVisible(false); } boolean unselected = (selectionTracker == null || !selectionTracker.hasSelection()); @@ -6453,6 +6457,8 @@ public class FragmentMessages extends FragmentBase menu.findItem(R.id.menu_sort_on_priority).setChecked(true); else if ("sender".equals(sort)) menu.findItem(R.id.menu_sort_on_sender).setChecked(true); + else if ("sender_name".equals(sort)) + menu.findItem(R.id.menu_sort_on_sender_name).setChecked(true); else if ("subject".equals(sort)) menu.findItem(R.id.menu_sort_on_subject).setChecked(true); else if ("size".equals(sort)) @@ -6609,6 +6615,10 @@ public class FragmentMessages extends FragmentBase item.setChecked(true); onMenuSort("sender"); return true; + } else if (itemId == R.id.menu_sort_on_sender_name) { + item.setChecked(true); + onMenuSort("sender_name"); + return true; } else if (itemId == R.id.menu_sort_on_subject) { item.setChecked(true); onMenuSort("subject"); diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java b/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java index c7a05c9719..b1791789db 100644 --- a/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java +++ b/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java @@ -183,7 +183,6 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc private TextView tvSqliteCache; private SeekBar sbSqliteCache; private ImageButton ibSqliteCache; - private SwitchCompat swLegacyQueries; private SwitchCompat swCacheLists; private SwitchCompat swOauthTabs; private TextView tvStartDelay; @@ -299,7 +298,6 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc "test1", "test2", "test3", "test4", "test5", "emergency_file", "work_manager", "task_description", // "external_storage", "sqlite_integrity_check", "wal", "sqlite_checkpoints", "sqlite_analyze", "sqlite_auto_vacuum", "sqlite_sync_extra", "sqlite_cache", - "legacy_queries", "cache_lists", "oauth_tabs", "start_delay", "range_size", "chunk_size", "thread_range", "restart_interval", "autoscroll_editor", "undo_manager", @@ -453,7 +451,6 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc tvSqliteCache = view.findViewById(R.id.tvSqliteCache); sbSqliteCache = view.findViewById(R.id.sbSqliteCache); ibSqliteCache = view.findViewById(R.id.ibSqliteCache); - swLegacyQueries = view.findViewById(R.id.swLegacyQueries); swCacheLists = view.findViewById(R.id.swCacheLists); swOauthTabs = view.findViewById(R.id.swOauthTabs); tvStartDelay = view.findViewById(R.id.tvStartDelay); @@ -1301,15 +1298,6 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc } }); - swLegacyQueries.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton v, boolean checked) { - prefs.edit().putBoolean("legacy_queries", checked).apply(); - ViewModelMessages model = new ViewModelProvider(getActivity()).get(ViewModelMessages.class); - model.clear(); - } - }); - swCacheLists.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton v, boolean checked) { @@ -2549,7 +2537,6 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc Helper.humanReadableByteCount(cache_size * 1024L))); sbSqliteCache.setProgress(sqlite_cache); - swLegacyQueries.setChecked(prefs.getBoolean("legacy_queries", false)); swCacheLists.setChecked(prefs.getBoolean("cache_lists", true)); swOauthTabs.setChecked(prefs.getBoolean("oauth_tabs", true)); diff --git a/app/src/main/java/eu/faircode/email/ViewModelMessages.java b/app/src/main/java/eu/faircode/email/ViewModelMessages.java index be29fc4d2b..d09c3e04da 100644 --- a/app/src/main/java/eu/faircode/email/ViewModelMessages.java +++ b/app/src/main/java/eu/faircode/email/ViewModelMessages.java @@ -89,7 +89,6 @@ public class ViewModelMessages extends ViewModel { BoundaryCallbackMessages.SearchCriteria criteria, boolean server) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - boolean legacy = prefs.getBoolean("legacy_queries", false); boolean cache_lists = prefs.getBoolean("cache_lists", true); Args args = new Args(context, @@ -125,8 +124,8 @@ public class ViewModelMessages extends ViewModel { .setPageSize(LOCAL_PAGE_SIZE) .setMaxSize(MAX_CACHED_ITEMS) .build(); - if (legacy) - pager = db.message().pagedUnifiedLegacy( + if ("sender_name".equals(args.sort1)) + pager = db.message().pagedUnifiedJson( args.type, args.category, args.threading, @@ -165,8 +164,8 @@ public class ViewModelMessages extends ViewModel { .setPrefetchDistance(REMOTE_PAGE_SIZE) .setMaxSize(MAX_CACHED_ITEMS) .build(); - if (legacy) - pager = db.message().pagedFolderLegacy( + if ("sender_name".equals(args.sort1)) + pager = db.message().pagedFolderJson( args.folder, args.threading, args.sort1, args.sort2, args.ascending, args.filter_seen, @@ -214,8 +213,8 @@ public class ViewModelMessages extends ViewModel { .setMaxSize(MAX_CACHED_ITEMS) .build(); if (args.folder < 0) { - if (legacy) - pager = db.message().pagedUnifiedLegacy( + if ("sender_name".equals(args.sort1)) + pager = db.message().pagedUnifiedJson( null, null, args.threading, false, criteria == null || criteria.touched == null ? "time" : "touched", "", false, @@ -234,8 +233,8 @@ public class ViewModelMessages extends ViewModel { args.debug); builder = new LivePagedListBuilder<>(pager, configSearch); } else { - if (legacy) - pager = db.message().pagedFolderLegacy( + if ("sender_name".equals(args.sort1)) + pager = db.message().pagedFolderJson( args.folder, args.threading, criteria == null || criteria.touched == null ? "time" : "touched", "", false, false, false, false, false, false, @@ -607,11 +606,16 @@ public class ViewModelMessages extends ViewModel { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); this.group_category = prefs.getBoolean("group_category", false); + String sort = prefs.getString(FragmentMessages.getSort(context, viewType, type), "time"); String[] sorts = sort.split("\\+"); this.sort1 = sorts[0]; this.sort2 = (sorts.length > 1 ? sorts[1] : ""); this.ascending = prefs.getBoolean(FragmentMessages.getSortOrder(context, viewType, type), outbox); + + if ("sender_name".equals(this.sort1) && !DB.hasJson()) + this.sort1 = "sender"; + this.filter_seen = prefs.getBoolean(FragmentMessages.getFilter(context, "seen", viewType, type), false); this.filter_unflagged = prefs.getBoolean(FragmentMessages.getFilter(context, "unflagged", viewType, type), false); this.filter_unknown = prefs.getBoolean(FragmentMessages.getFilter(context, "unknown", viewType, type), false); diff --git a/app/src/main/res/layout/fragment_options_misc.xml b/app/src/main/res/layout/fragment_options_misc.xml index 4a265cfde1..de49fb15d9 100644 --- a/app/src/main/res/layout/fragment_options_misc.xml +++ b/app/src/main/res/layout/fragment_options_misc.xml @@ -1178,17 +1178,6 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/ibSqliteCache" /> - - + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7a2070bd22..df374b52e8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2008,6 +2008,7 @@ Starred, unread Priority Sender + Sender name Subject Size Attachments