From b5b0e56feaea9a620fb24d45e78985480c0dd7c3 Mon Sep 17 00:00:00 2001 From: M66B Date: Thu, 29 Nov 2018 09:51:22 +0100 Subject: [PATCH] Added setting to enable/disable conversation threading --- FAQ.md | 1 - .../main/java/eu/faircode/email/ActivityBase.java | 3 ++- .../main/java/eu/faircode/email/ActivityView.java | 1 + .../java/eu/faircode/email/AdapterMessage.java | 7 +++++-- .../main/java/eu/faircode/email/DaoMessage.java | 11 ++++++----- .../java/eu/faircode/email/FragmentMessages.java | 14 ++++++++++---- .../java/eu/faircode/email/FragmentOptions.java | 12 +++++++++++- .../java/eu/faircode/email/ViewModelMessages.java | 8 +++++--- app/src/main/res/layout/fragment_options.xml | 11 ++++++++++- app/src/main/res/values/strings.xml | 1 + 10 files changed, 51 insertions(+), 18 deletions(-) diff --git a/FAQ.md b/FAQ.md index ac08e9e9c9..007655d667 100644 --- a/FAQ.md +++ b/FAQ.md @@ -52,7 +52,6 @@ Anything on this list is in random order and *might* be added in the near future * Better design: please let me know what you have in mind [in this forum](https://forum.xda-developers.com/android/apps-games/source-email-t3824168). * Hide archived messages: hiding archived messages which exists in other folders too would have a performance impact. * Save all attachments: there is no [Storage Access Framework](https://developer.android.com/guide/topics/providers/document-provider) API to selected multiple files to save. -* Show single messages: listing single messages just clutters the list without much benefit, so this will not be added. * S/MIME encryption: only PGP encryption will be supported, see [this FAQ](#user-content-faq12) for more information. Since FairEmail is meant to be privacy friendly, the following will not be added: diff --git a/app/src/main/java/eu/faircode/email/ActivityBase.java b/app/src/main/java/eu/faircode/email/ActivityBase.java index 08e009c8de..9939018480 100644 --- a/app/src/main/java/eu/faircode/email/ActivityBase.java +++ b/app/src/main/java/eu/faircode/email/ActivityBase.java @@ -92,7 +92,8 @@ abstract class ActivityBase extends AppCompatActivity implements SharedPreferenc if (this.getClass().equals(ActivitySetup.class)) startActivity(getIntent()); } else if (!this.getClass().equals(ActivitySetup.class) && - ("compact".equals(key) || + ("threading".equals(key) || + "compact".equals(key) || "avatars".equals(key) || "identicons".equals(key) || "preview".equals(key) || diff --git a/app/src/main/java/eu/faircode/email/ActivityView.java b/app/src/main/java/eu/faircode/email/ActivityView.java index bc4ca589ca..bfd2d2effc 100644 --- a/app/src/main/java/eu/faircode/email/ActivityView.java +++ b/app/src/main/java/eu/faircode/email/ActivityView.java @@ -1077,6 +1077,7 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB Bundle args = new Bundle(); args.putLong("account", intent.getLongExtra("account", -1)); args.putString("thread", intent.getStringExtra("thread")); + args.putLong("id", intent.getLongExtra("id", -1)); args.putBoolean("found", intent.getBooleanExtra("found", false)); FragmentMessages fragment = new FragmentMessages(); diff --git a/app/src/main/java/eu/faircode/email/AdapterMessage.java b/app/src/main/java/eu/faircode/email/AdapterMessage.java index 7a63cebc05..e508850dba 100644 --- a/app/src/main/java/eu/faircode/email/AdapterMessage.java +++ b/app/src/main/java/eu/faircode/email/AdapterMessage.java @@ -113,6 +113,7 @@ public class AdapterMessage extends PagedListAdapter 0" + " ORDER BY CASE" + " WHEN 'unread' = :sort THEN NOT message.ui_seen" + @@ -66,7 +66,7 @@ public interface DaoMessage { " ELSE 0" + " END DESC, message.received DESC") @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH) - DataSource.Factory pagedUnifiedInbox(String sort, boolean debug); + DataSource.Factory pagedUnifiedInbox(boolean threading, String sort, boolean debug); @Query("SELECT message.*" + ", account.name AS accountName, identity.color AS accountColor, account.notify AS accountNotify" + @@ -91,7 +91,7 @@ public interface DaoMessage { " WHERE (message.account = f.account OR folder.type = '" + EntityFolder.OUTBOX + "')" + " AND (NOT message.ui_hide OR :debug)" + " AND ui_found = :found" + - " GROUP BY CASE WHEN message.thread IS NULL THEN message.id ELSE message.thread END" + + " GROUP BY CASE WHEN message.thread IS NULL OR NOT :threading THEN message.id ELSE message.thread END" + " HAVING SUM(CASE WHEN folder.id = :folder THEN 1 ELSE 0 END) > 0" + " ORDER BY CASE" + " WHEN 'unread' = :sort THEN NOT message.ui_seen" + @@ -99,7 +99,7 @@ public interface DaoMessage { " ELSE 0" + " END DESC, message.received DESC") @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH) - DataSource.Factory pagedFolder(long folder, String sort, boolean found, boolean debug); + DataSource.Factory pagedFolder(long folder, boolean threading, String sort, boolean found, boolean debug); @Query("SELECT message.*" + ", account.name AS accountName, identity.color AS accountColor, account.notify AS accountNotify" + @@ -125,6 +125,7 @@ public interface DaoMessage { " JOIN folder ON folder.id = message.folder" + " WHERE message.account = :account" + " AND message.thread = :thread" + + " AND (:id IS NULL OR message.id = :id)" + " AND ui_found = :found" + " AND (NOT message.ui_hide OR :debug)" + " ORDER BY CASE" + @@ -132,7 +133,7 @@ public interface DaoMessage { " WHEN 'starred' = :sort THEN message.ui_flagged" + " ELSE 0" + " END DESC, message.received DESC") - DataSource.Factory pagedThread(long account, String thread, boolean found, String sort, boolean debug); + DataSource.Factory pagedThread(long account, String thread, Long id, boolean found, String sort, boolean debug); @Query("SELECT COUNT(id)" + " FROM message" + diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java index 78790a7c64..a519f146e3 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessages.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java @@ -93,9 +93,11 @@ public class FragmentMessages extends FragmentEx { private long folder = -1; private boolean outgoing = false; private String thread = null; + private long id = -1; private boolean found = false; private String search = null; + private boolean threading = true; private boolean actionbar = false; private boolean autoclose = false; @@ -136,10 +138,12 @@ public class FragmentMessages extends FragmentEx { folder = args.getLong("folder", -1); outgoing = args.getBoolean("outgoing", false); thread = args.getString("thread"); + id = args.getLong("id", -1); found = args.getBoolean("found", false); search = args.getString("search"); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); + threading = prefs.getBoolean("threading", true); actionbar = prefs.getBoolean("actionbar", true); autoclose = prefs.getBoolean("autoclose", false); @@ -1222,7 +1226,7 @@ public class FragmentMessages extends FragmentEx { switch (viewType) { case UNIFIED: - messages = new LivePagedListBuilder<>(db.message().pagedUnifiedInbox(sort, debug), LOCAL_PAGE_SIZE).build(); + messages = new LivePagedListBuilder<>(db.message().pagedUnifiedInbox(threading, sort, debug), LOCAL_PAGE_SIZE).build(); break; case FOLDER: if (searchCallback == null) @@ -1255,14 +1259,15 @@ public class FragmentMessages extends FragmentEx { .setPrefetchDistance(REMOTE_PAGE_SIZE) .build(); LivePagedListBuilder builder = new LivePagedListBuilder<>( - db.message().pagedFolder(folder, sort, false, debug), config); + db.message().pagedFolder(folder, threading, sort, false, debug), config); if (browse) builder.setBoundaryCallback(searchCallback); messages = builder.build(); break; case THREAD: - messages = new LivePagedListBuilder<>(db.message().pagedThread(account, thread, found, sort, debug), LOCAL_PAGE_SIZE).build(); + messages = new LivePagedListBuilder<>( + db.message().pagedThread(account, thread, threading ? null : id, found, sort, debug), LOCAL_PAGE_SIZE).build(); break; } } else { @@ -1299,7 +1304,7 @@ public class FragmentMessages extends FragmentEx { .setPrefetchDistance(REMOTE_PAGE_SIZE) .build(); LivePagedListBuilder builder = new LivePagedListBuilder<>( - db.message().pagedFolder(folder, "time", true, false), config); + db.message().pagedFolder(folder, threading, "time", true, false), config); builder.setBoundaryCallback(searchCallback); messages = builder.build(); } @@ -1497,6 +1502,7 @@ public class FragmentMessages extends FragmentEx { new Intent(ActivityView.ACTION_VIEW_THREAD) .putExtra("account", target.account) .putExtra("thread", target.thread) + .putExtra("id", target.id) .putExtra("found", target.found)); } diff --git a/app/src/main/java/eu/faircode/email/FragmentOptions.java b/app/src/main/java/eu/faircode/email/FragmentOptions.java index d02f6c6e1a..4e085ece33 100644 --- a/app/src/main/java/eu/faircode/email/FragmentOptions.java +++ b/app/src/main/java/eu/faircode/email/FragmentOptions.java @@ -43,9 +43,10 @@ import androidx.appcompat.widget.SwitchCompat; public class FragmentOptions extends FragmentEx implements SharedPreferences.OnSharedPreferenceChangeListener { private SwitchCompat swEnabled; private SwitchCompat swMetered; + private SwitchCompat swThreading; + private SwitchCompat swCompact; private SwitchCompat swAvatars; private SwitchCompat swIdenticons; - private SwitchCompat swCompact; private SwitchCompat swPreview; private SwitchCompat swLight; private SwitchCompat swBrowse; @@ -69,6 +70,7 @@ public class FragmentOptions extends FragmentEx implements SharedPreferences.OnS // Get controls swEnabled = view.findViewById(R.id.swEnabled); swMetered = view.findViewById(R.id.swMetered); + swThreading = view.findViewById(R.id.swThreading); swCompact = view.findViewById(R.id.swCompact); swAvatars = view.findViewById(R.id.swAvatars); swIdenticons = view.findViewById(R.id.swIdenticons); @@ -107,6 +109,14 @@ public class FragmentOptions extends FragmentEx implements SharedPreferences.OnS } }); + swThreading.setChecked(prefs.getBoolean("threading", true)); + swThreading.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { + prefs.edit().putBoolean("threading", checked).apply(); + } + }); + swCompact.setChecked(prefs.getBoolean("compact", false)); swCompact.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override diff --git a/app/src/main/java/eu/faircode/email/ViewModelMessages.java b/app/src/main/java/eu/faircode/email/ViewModelMessages.java index b5199740b3..15a7892777 100644 --- a/app/src/main/java/eu/faircode/email/ViewModelMessages.java +++ b/app/src/main/java/eu/faircode/email/ViewModelMessages.java @@ -56,18 +56,20 @@ public class ViewModelMessages extends ViewModel { next = item; } return new Target[]{ - prev == null ? null : new Target(prev.account, prev.thread, prev.ui_found), - next == null ? null : new Target(next.account, next.thread, next.ui_found)}; + prev == null ? null : new Target(prev.account, prev.thread, prev.id, prev.ui_found), + next == null ? null : new Target(next.account, next.thread, next.id, next.ui_found)}; } class Target { long account; String thread; + long id; boolean found; - Target(long account, String thread, boolean found) { + Target(long account, String thread, long id, boolean found) { this.account = account; this.thread = thread; + this.id = id; this.found = found; } } diff --git a/app/src/main/res/layout/fragment_options.xml b/app/src/main/res/layout/fragment_options.xml index 1cb5d9e3df..7f7ab42924 100644 --- a/app/src/main/res/layout/fragment_options.xml +++ b/app/src/main/res/layout/fragment_options.xml @@ -29,6 +29,15 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/swEnabled" /> + + + app:layout_constraintTop_toBottomOf="@id/swThreading" /> Advanced options Synchronize Use metered connections + Conversation threading Compact message view Show contact photos Show identicons