From 592f844beb97e57336751afafbc2358b4e655648 Mon Sep 17 00:00:00 2001 From: M66B Date: Sun, 2 Oct 2022 10:56:43 +0200 Subject: [PATCH] Added long press date header to select messages --- CHANGELOG.md | 1 + app/build.gradle | 2 +- app/src/main/assets/CHANGELOG.md | 1 + .../eu/faircode/email/FragmentMessages.java | 85 +++++++++++++++++-- .../eu/faircode/email/ViewModelMessages.java | 7 +- metadata/en-US/changelogs/1973.txt | 1 + 6 files changed, 88 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e1a4b57f6..ca5b37d7ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ ### Next version +* Added long press date header to select messages * Added option to check paragraph with LanguageTool after a newline ### 1.1973 - 2022-10-01 diff --git a/app/build.gradle b/app/build.gradle index 431ad5f73f..440a665059 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,7 +4,7 @@ apply plugin: 'kotlin-android' apply plugin: 'de.undercouch.download' def getVersionCode = { -> return 1973 } -def getRevision = { -> return "b" } +def getRevision = { -> return "c" } def getReleaseName = { -> return "Mei long" } // https://en.wikipedia.org/wiki/List_of_dinosaur_genera diff --git a/app/src/main/assets/CHANGELOG.md b/app/src/main/assets/CHANGELOG.md index 9e1a4b57f6..ca5b37d7ae 100644 --- a/app/src/main/assets/CHANGELOG.md +++ b/app/src/main/assets/CHANGELOG.md @@ -6,6 +6,7 @@ ### Next version +* Added long press date header to select messages * Added option to check paragraph with LanguageTool after a newline ### 1.1973 - 2022-10-01 diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java index db4ca98c9f..832a40fd5c 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessages.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java @@ -98,6 +98,7 @@ import android.util.Base64; import android.util.LongSparseArray; import android.util.Pair; import android.util.TypedValue; +import android.view.GestureDetector; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; @@ -1034,6 +1035,73 @@ public class FragmentMessages extends FragmentBase }; rvMessage.addItemDecoration(dateDecorator); + rvMessage.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() { + private final GestureDetector gestureDetector = + new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() { + @Override + public void onLongPress(@NonNull MotionEvent e) { + if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) + return; + + int x = Math.round(e.getX()); + int y = Math.round(e.getY()); + + Rect rect = new Rect(); + for (int i = 0; i < rvMessage.getChildCount(); i++) { + View child = rvMessage.getChildAt(i); + if (child == null) + continue; + + dateDecorator.getItemOffsets(rect, child, rvMessage, null); + if (rect.height() == 0) + continue; + + rect.set(child.getLeft(), child.getTop() - rect.top, child.getRight(), child.getTop()); + if (!rect.contains(x, y)) + continue; + + int pos = rvMessage.getChildAdapterPosition(child); + if (pos == NO_POSITION) + continue; + + TupleMessageEx message = adapter.getItemAtPosition(pos); + if (message == null) + continue; + + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(message.received); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + + cal.add(Calendar.DATE, 1); + long to = cal.getTimeInMillis(); + + cal.add(Calendar.DATE, date_week ? -7 : -1); + long from = cal.getTimeInMillis(); + + onMenuSelect(from, to, true); + return; + } + } + }); + + @Override + public boolean onInterceptTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) { + gestureDetector.onTouchEvent(e); + return false; + } + + @Override + public void onTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) { + } + + @Override + public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { + } + }); + rvMessage.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView rv, int dx, int dy) { @@ -5426,7 +5494,7 @@ public class FragmentMessages extends FragmentBase onMenuConfirmLinks(); return true; } else if (itemId == R.id.menu_select_all || itemId == R.id.menu_select_found) { - onMenuSelectAll(); + onMenuSelect(0, Long.MAX_VALUE, false); return true; } else if (itemId == R.id.menu_mark_all_read) { onMenuMarkAllRead(); @@ -5758,9 +5826,9 @@ public class FragmentMessages extends FragmentBase positions.clear(); } - private void onMenuSelectAll() { + private void onMenuSelect(long from, long to, boolean extend) { ViewModelMessages model = new ViewModelProvider(getActivity()).get(ViewModelMessages.class); - model.getIds(getContext(), getViewLifecycleOwner(), new Observer>() { + model.getIds(getContext(), getViewLifecycleOwner(), from, to, new Observer>() { @Override public void onChanged(List ids) { view.post(new Runnable() { @@ -5769,9 +5837,16 @@ public class FragmentMessages extends FragmentBase try { if (selectionTracker == null) return; - selectionTracker.clearSelection(); + if (!extend) + selectionTracker.clearSelection(); for (long id : ids) - selectionTracker.select(id); + if (extend) { + if (selectionTracker.isSelected(id)) + selectionTracker.deselect(id); + else + selectionTracker.select(id); + } else + selectionTracker.select(id); } catch (Throwable ex) { Log.e(ex); } diff --git a/app/src/main/java/eu/faircode/email/ViewModelMessages.java b/app/src/main/java/eu/faircode/email/ViewModelMessages.java index 7a8549f0bd..a71a5beff4 100644 --- a/app/src/main/java/eu/faircode/email/ViewModelMessages.java +++ b/app/src/main/java/eu/faircode/email/ViewModelMessages.java @@ -441,7 +441,7 @@ public class ViewModelMessages extends ViewModel { }); } - void getIds(Context context, LifecycleOwner owner, final Observer> observer) { + void getIds(Context context, LifecycleOwner owner, long from, long to, final Observer> observer) { final Model model = models.get(last); if (model == null) { Log.w("Get IDs without model"); @@ -465,8 +465,9 @@ public class ViewModelMessages extends ViewModel { int count = ds.countItems(); for (int i = 0; i < count && isAlive(); i += 100) for (TupleMessageEx message : ds.loadRange(i, Math.min(100, count - i))) - if ((message.uid != null && !message.folderReadOnly) || - message.accountProtocol != EntityAccount.TYPE_IMAP) + if ((message.received >= from && message.received < to) && + ((message.uid != null && !message.folderReadOnly) || + message.accountProtocol != EntityAccount.TYPE_IMAP)) ids.add(message.id); Log.i("Loaded messages #" + ids.size()); diff --git a/metadata/en-US/changelogs/1973.txt b/metadata/en-US/changelogs/1973.txt index 5b119ffe19..013c8520fa 100644 --- a/metadata/en-US/changelogs/1973.txt +++ b/metadata/en-US/changelogs/1973.txt @@ -6,6 +6,7 @@ Mei long Next version +* Added long press date header to select messages * Added option to check paragraph with LanguageTool after a newline 1.1973 - 2022-10-01