Add Gmail-style vertical swipe-to-select for thread multi-selection - #2928
Draft
JorisBodin with Copilot wants to merge 2 commits into
Draft
Add Gmail-style vertical swipe-to-select for thread multi-selection#2928JorisBodin with Copilot wants to merge 2 commits into
JorisBodin with Copilot wants to merge 2 commits into
Conversation
Copilot
AI
changed the title
[WIP] Add swipe-to-select gesture for email thread list
Add Gmail-style vertical swipe-to-select for thread multi-selection
Jun 2, 2026
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



This change adds drag-to-select behavior to the thread list while multi-selection mode is already active. Users can now vertically swipe across items to select or deselect multiple threads in one gesture, without interfering with horizontal swipe actions.
New touch listener for drag selection
SwipeToSelectTouchListener(RecyclerView.OnItemTouchListener) inui/main/folder.dy > touchSlop && dy > dx).SELECTED_STATEpayload updates, and triggers haptic feedback when crossing item boundaries.UP,CANCEL, or disallow-intercept.Adapter API for position-to-thread lookup
ThreadListAdapter.getThreadAt(position: Int): Thread?to expose content-thread access safely from adapter positions.Fragment wiring
SwipeToSelectTouchListenerinThreadListFragment.setupAdapter().MainViewModelmulti-selection state via aMultiSelectionListener<Thread>adapter.Original prompt
Goal
Add a "swipe-to-select" gesture to the email thread list so that, when multi-selection mode is already active, the user can drag their finger vertically across list items to select (or deselect) multiple threads in one motion — similar to Gmail on Android.
Context
Relevant files (all in
app/src/main/java/com/infomaniak/mail/ui/main/folder/):ThreadListAdapter.kt— extendsDragDropSwipeAdapter. Multi-select is toggled viatoggleMultiSelectedThread(). ExposesmultiSelection: MultiSelectionListener<Thread>(private).dataSetcomes from the parentDragDropSwipeAdapter.ThreadListFragment.kt— sets up the RecyclerView insetupAdapter(). Attaches theswipeListener(horizontal actions). CallsunlockSwipeActionsIfSet()which disables horizontal swipe directions whenisMultiSelectOn == true.MultiSelectionListener.kt— interface withisEnabled,selectedItems: MutableSet<Thread>,publishSelectedItems: () -> Unit.ThreadListMultiSelection.kt— handles multi-select actions (archive, delete, etc.).ThreadListItem.kt— sealed class;ThreadListItem.Content(val thread: Thread)is the item type for emails.What to implement
1. New file:
SwipeToSelectTouchListener.ktCreate
app/src/main/java/com/infomaniak/mail/ui/main/folder/SwipeToSelectTouchListener.kt.This class implements
RecyclerView.OnItemTouchListenerand provides Gmail-style drag-to-select behaviour:onInterceptTouchEvent:ACTION_DOWN: record the start coordinates and the item position under the finger. Do NOT intercept yet.ACTION_MOVE: ifmultiSelection.isEnabledis true AND the vertical displacement exceedsscaledTouchSlopAND the vertical displacement is greater than the horizontal displacement (so it's clearly a vertical drag, not a horizontal swipe), setisActive = trueand returntrueto steal the event stream. When activating, record the selection state of the item at the start position (was it already selected?) — this determines the intent for the whole gesture: if the first item was unselected → the gesture selects all touched items; if it was selected → the gesture deselects all touched items.isActive.onTouchEvent:ACTION_MOVE: userv.findChildViewUnder(e.x, e.y)to find the item currently under the finger. If it is a new position (not the last one processed), and it is aThreadListItem.Content, apply the intent (add or remove fromselectedItems), callpublishSelectedItems(), and callrv.adapter?.notifyItemChanged(pos, ThreadListAdapter.NotificationType.SELECTED_STATE). Also perform haptic feedback (HapticFeedbackConstants.VIRTUAL_KEY) when the finger crosses from one item to the next.ACTION_UP/ACTION_CANCEL: resetisActive,lastSelectedPosition,startY,startX,selectionIntent.onRequestDisallowInterceptTouchEvent: ifdisallowInterceptis true, resetisActive.