From 294d109ab1c830455f89e30018f92c774e2b7cc3 Mon Sep 17 00:00:00 2001 From: M66B Date: Sat, 8 Aug 2020 14:01:56 +0200 Subject: [PATCH] Added swipe up to move thread --- .../eu/faircode/email/FragmentMessages.java | 138 ++++++++++++++++-- .../eu/faircode/email/FragmentOptions.java | 2 +- .../email/FragmentOptionsBehavior.java | 12 +- .../res/layout/fragment_options_behavior.xml | 13 +- app/src/main/res/values/strings.xml | 1 + 5 files changed, 151 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java index f3f60e8ad4..006bfd96dd 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessages.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java @@ -335,12 +335,13 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. private static final int REQUEST_MESSAGES_SNOOZE = 14; static final int REQUEST_MESSAGE_MOVE = 15; private static final int REQUEST_MESSAGES_MOVE = 16; - static final int REQUEST_PRINT = 17; - private static final int REQUEST_SEARCH = 18; - private static final int REQUEST_ACCOUNT = 19; - private static final int REQUEST_EMPTY_FOLDER = 20; - private static final int REQUEST_BOUNDARY_RETRY = 21; - static final int REQUEST_PICK_CONTACT = 22; + private static final int REQUEST_THREAD_MOVE = 17; + static final int REQUEST_PRINT = 18; + private static final int REQUEST_SEARCH = 19; + private static final int REQUEST_ACCOUNT = 20; + private static final int REQUEST_EMPTY_FOLDER = 21; + private static final int REQUEST_BOUNDARY_RETRY = 22; + static final int REQUEST_PICK_CONTACT = 23; static final String ACTION_STORE_RAW = BuildConfig.APPLICATION_ID + ".STORE_RAW"; static final String ACTION_DECRYPT = BuildConfig.APPLICATION_ID + ".DECRYPT"; @@ -1307,13 +1308,42 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. } }); - boolean swipe_close = prefs.getBoolean("swipe_close", false); - if (swipe_close && viewType == AdapterMessage.ViewType.THREAD) { + if (viewType == AdapterMessage.ViewType.THREAD) { + boolean swipe_close = prefs.getBoolean("swipe_close", false); + boolean swipe_move = prefs.getBoolean("swipe_move", false); IOverScrollDecor decor = new VerticalOverScrollBounceEffectDecorator( new RecyclerViewOverScrollDecorAdapter(rvMessage, touchHelper) { + @Override + public boolean isInAbsoluteStart() { + if (!swipe_close) + return false; + return super.isInAbsoluteStart(); + } + @Override public boolean isInAbsoluteEnd() { - return false; + PagedList list = ((AdapterMessage) rvMessage.getAdapter()).getCurrentList(); + if (list == null) + return false; + + boolean moveable = false; + for (TupleMessageEx message : list) { + if (message == null) + return false; + + if (!EntityFolder.isOutgoing(message.folderType) && + (!filter_archive || !EntityFolder.ARCHIVE.equals(message.folderType))) { + moveable = true; + break; + } + } + + if (!moveable) + return false; + + if (!swipe_move) + return false; + return super.isInAbsoluteEnd(); } }, DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD, @@ -1321,12 +1351,37 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. DEFAULT_DECELERATE_FACTOR ); decor.setOverScrollUpdateListener(new IOverScrollUpdateListener() { + private boolean triggered = false; + @Override public void onOverScrollUpdate(IOverScrollDecor decor, int state, float offset) { float height = decor.getView().getHeight(); - if (height != 0 && - offset * DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD > height / 4) - handleAutoClose(); + if (height == 0) + return; + + if (offset == 0) + triggered = false; + else if (!triggered && + Math.abs(offset * DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD) > height / 4) { + triggered = true; + + if (offset > 0) + handleAutoClose(); + else { + Bundle args = new Bundle(); + args.putString("title", getString(R.string.title_move_to_folder)); + args.putLong("account", account); + args.putString("thread", thread); + args.putLong("id", id); + args.putBoolean("filter_archive", filter_archive); + args.putLongArray("disabled", new long[]{folder}); + + FragmentDialogFolder fragment = new FragmentDialogFolder(); + fragment.setArguments(args); + fragment.setTargetFragment(FragmentMessages.this, REQUEST_THREAD_MOVE); + fragment.show(getParentFragmentManager(), "overscroll:move"); + } + } } }); } @@ -3158,6 +3213,61 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. }.execute(this, args, "messages:move"); } + private void onActionMoveThread(Bundle args) { + new SimpleTask>() { + @Override + protected ArrayList onExecute(Context context, Bundle args) { + long aid = args.getLong("account"); + String thread = args.getString("thread"); + long id = args.getLong("id"); + boolean filter_archive = args.getBoolean("filter_archive"); + long tid = args.getLong("folder"); + + ArrayList result = new ArrayList<>(); + + DB db = DB.getInstance(context); + try { + db.beginTransaction(); + + EntityAccount account = db.account().getAccount(aid); + if (account == null) + return result; + + EntityFolder targetFolder = db.folder().getFolder(tid); + if (targetFolder == null) + return result; + + List messages = db.message().getMessagesByThread( + aid, thread, threading ? null : id, null); + for (EntityMessage threaded : messages) { + EntityFolder sourceFolder = db.folder().getFolder(threaded.folder); + if (sourceFolder != null && !sourceFolder.read_only && + !targetFolder.id.equals(threaded.folder) && + !EntityFolder.isOutgoing(sourceFolder.type) && + (!filter_archive || !EntityFolder.ARCHIVE.equals(sourceFolder.type))) + result.add(new MessageTarget(context, threaded, account, sourceFolder, account, targetFolder)); + } + + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + + return result; + } + + @Override + protected void onExecuted(Bundle args, ArrayList result) { + moveAskConfirmed(result); + } + + @Override + protected void onException(Bundle args, Throwable ex) { + Log.unexpectedError(getParentFragmentManager(), ex); + } + }.execute(FragmentMessages.this, args, "messages:move"); + } + static void onActionUndo(TupleMessageEx message, final Context context, final LifecycleOwner owner, final FragmentManager manager) { Bundle args = new Bundle(); args.putLong("id", message.id); @@ -5385,6 +5495,10 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. if (resultCode == RESULT_OK && data != null) onActionMoveSelection(data.getBundleExtra("args")); break; + case REQUEST_THREAD_MOVE: + if (resultCode == RESULT_OK && data != null) + onActionMoveThread(data.getBundleExtra("args")); + break; case REQUEST_PRINT: if (resultCode == RESULT_OK && data != null) onPrint(data.getBundleExtra("args")); diff --git a/app/src/main/java/eu/faircode/email/FragmentOptions.java b/app/src/main/java/eu/faircode/email/FragmentOptions.java index b5bba92317..163ea5d602 100644 --- a/app/src/main/java/eu/faircode/email/FragmentOptions.java +++ b/app/src/main/java/eu/faircode/email/FragmentOptions.java @@ -87,7 +87,7 @@ public class FragmentOptions extends FragmentBase { "message_zoom", "addresses", "attachments_alt", "thumbnails", "contrast", "monospaced", "text_color", "text_size", "text_font", "text_align", "inline_images", "collapse_quotes", "seekbar", "actionbar", "actionbar_color", "navbar_colorize", - "autoscroll", "swipenav", "swipe_close", "autoexpand", "autoclose", "onclose", + "autoscroll", "swipenav", "swipe_close", "swipe_move", "autoexpand", "autoclose", "onclose", "language_detection", "quick_filter", "quick_scroll", "experiments", "debug", diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsBehavior.java b/app/src/main/java/eu/faircode/email/FragmentOptionsBehavior.java index 0841533642..eb71067cfa 100644 --- a/app/src/main/java/eu/faircode/email/FragmentOptionsBehavior.java +++ b/app/src/main/java/eu/faircode/email/FragmentOptionsBehavior.java @@ -69,6 +69,7 @@ public class FragmentOptionsBehavior extends FragmentBase implements SharedPrefe private SwitchCompat swVolumeNav; private SwitchCompat swReversed; private SwitchCompat swSwipeClose; + private SwitchCompat swSwipeMove; private SwitchCompat swAutoExpand; private SwitchCompat swExpandAll; private SwitchCompat swExpandOne; @@ -87,7 +88,7 @@ public class FragmentOptionsBehavior extends FragmentBase implements SharedPrefe "double_back", "conversation_actions", "conversation_actions_replies", "language_detection", "default_snooze", "pull", "autoscroll", "quick_filter", "quick_scroll", - "doubletap", "swipenav", "volumenav", "reversed", "swipe_close", + "doubletap", "swipenav", "volumenav", "reversed", "swipe_close", "swipe_move", "autoexpand", "expand_all", "expand_one", "collapse_multiple", "autoclose", "onclose", "undo_timeout", "autoread", "flag_snoozed", "autounflag", "auto_important", "reset_importance" @@ -118,6 +119,7 @@ public class FragmentOptionsBehavior extends FragmentBase implements SharedPrefe swVolumeNav = view.findViewById(R.id.swVolumeNav); swReversed = view.findViewById(R.id.swReversed); swSwipeClose = view.findViewById(R.id.swSwipeClose); + swSwipeMove = view.findViewById(R.id.swSwipeMove); swAutoExpand = view.findViewById(R.id.swAutoExpand); swExpandAll = view.findViewById(R.id.swExpandAll); swExpandOne = view.findViewById(R.id.swExpandOne); @@ -262,6 +264,13 @@ public class FragmentOptionsBehavior extends FragmentBase implements SharedPrefe } }); + swSwipeMove.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { + prefs.edit().putBoolean("swipe_move", checked).apply(); + } + }); + swAutoExpand.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { @@ -436,6 +445,7 @@ public class FragmentOptionsBehavior extends FragmentBase implements SharedPrefe swVolumeNav.setChecked(prefs.getBoolean("volumenav", false)); swReversed.setChecked(prefs.getBoolean("reversed", false)); swSwipeClose.setChecked(prefs.getBoolean("swipe_close", false)); + swSwipeMove.setChecked(prefs.getBoolean("swipe_move", false)); swAutoExpand.setChecked(prefs.getBoolean("autoexpand", true)); swExpandAll.setChecked(prefs.getBoolean("expand_all", false)); diff --git a/app/src/main/res/layout/fragment_options_behavior.xml b/app/src/main/res/layout/fragment_options_behavior.xml index 8391e2c064..336313716b 100644 --- a/app/src/main/res/layout/fragment_options_behavior.xml +++ b/app/src/main/res/layout/fragment_options_behavior.xml @@ -262,6 +262,17 @@ app:layout_constraintTop_toBottomOf="@id/swReversed" app:switchPadding="12dp" /> + + Volume up/down to go to next/previous conversation Reverse navigation direction Swipe down to close conversation + Swipe up to move conversation Automatically expand messages Automatically expand all read messages Expand only one message at a time