From 8c94bc51bddc12b38d5a68b2ba838d3b09f81693 Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Tue, 26 May 2026 11:14:46 +0200 Subject: [PATCH 01/11] fix: Remove archive button from bottom sheet --- .../thread/actions/MailActionsBottomSheetDialog.kt | 14 ++++++++++---- .../actions/MessageActionsBottomSheetDialog.kt | 6 +++++- .../actions/ThreadActionsBottomSheetDialog.kt | 4 +++- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MailActionsBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MailActionsBottomSheetDialog.kt index 0dd491d81a..b9fec9e6ff 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MailActionsBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MailActionsBottomSheetDialog.kt @@ -172,10 +172,16 @@ abstract class MailActionsBottomSheetDialog : ActionsBottomSheetDialog() { setTitle(favoriteText) } - fun setArchiveUi(isFromArchive: Boolean) = with(binding.archive) { - if (isFromArchive) { - setIconResource(R.drawable.ic_drawer_inbox) - setTitle(R.string.actionMoveToInbox) + fun setArchiveUi(isFromArchive: Boolean, isFromDraft: Boolean, isDraft: Boolean = false) = with(binding.archive) { + when { + isFromDraft || isDraft -> { + isVisible = false + return + } + isFromArchive -> { + setIconResource(R.drawable.ic_drawer_inbox) + setTitle(R.string.actionMoveToInbox) + } } } diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MessageActionsBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MessageActionsBottomSheetDialog.kt index 3546d9e357..bd6844724c 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MessageActionsBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MessageActionsBottomSheetDialog.kt @@ -70,6 +70,8 @@ class MessageActionsBottomSheetDialog : MailActionsBottomSheetDialog() { override val shouldCloseMultiSelection: Boolean = false private var isFromSpam: Boolean = false + private var isFromArchive: Boolean = false + private var isFromDraft: Boolean = false @Inject lateinit var descriptionDialog: DescriptionAlertDialog @@ -94,9 +96,11 @@ class MessageActionsBottomSheetDialog : MailActionsBottomSheetDialog() { junkMessagesViewModel.threadsUids = listOf(threadUid) val folderRole = folderRoleUtils.getActionFolderRole(message) isFromSpam = folderRole == FolderRole.SPAM + isFromDraft = folderRole == FolderRole.DRAFT + isFromArchive = folderRole == FolderRole.ARCHIVE setMarkAsReadUi(message.isSeen) - setArchiveUi(isFromArchive = folderRole == FolderRole.ARCHIVE) + setArchiveUi(isFromArchive, isFromDraft, message.isDraft) setFavoriteUi(message.isFavorite) setReactionUi(message.isValidReactionTarget) setSpamUi(binding.spam, isFromSpam) diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/ThreadActionsBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/ThreadActionsBottomSheetDialog.kt index bcb78fac25..f4e4fd0a79 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/ThreadActionsBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/ThreadActionsBottomSheetDialog.kt @@ -78,6 +78,7 @@ class ThreadActionsBottomSheetDialog : MailActionsBottomSheetDialog() { private var folderRole: FolderRole? = null private var isFromArchive: Boolean = false private var isFromSpam: Boolean = false + private var isFromDraft: Boolean = false @Inject lateinit var descriptionDialog: DescriptionAlertDialog @@ -105,9 +106,10 @@ class ThreadActionsBottomSheetDialog : MailActionsBottomSheetDialog() { folderRole = folderRoleUtils.getActionFolderRole(thread) isFromArchive = folderRole == FolderRole.ARCHIVE isFromSpam = folderRole == FolderRole.SPAM + isFromDraft = folderRole == FolderRole.DRAFT setMarkAsReadUi(thread.isSeen) - setArchiveUi(isFromArchive) + setArchiveUi(isFromArchive, isFromDraft) setFavoriteUi(thread.isFavorite) setSnoozeUi(thread.isSnoozed()) setReactionUi(canBeReactedTo = messageUidToReactTo != null) From df6da1d9a5e622a37620ed106329f22f7877e319 Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Tue, 26 May 2026 13:04:28 +0200 Subject: [PATCH 02/11] fix: Manage swipe actions in draft --- .../mail/ui/main/folder/ThreadListAdapter.kt | 26 +++++++--- .../mail/ui/main/folder/ThreadListFragment.kt | 51 ++++++++++++------- 2 files changed, 51 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListAdapter.kt b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListAdapter.kt index 441434df1d..f2ec1ea963 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListAdapter.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListAdapter.kt @@ -615,19 +615,31 @@ class ThreadListAdapter @Inject constructor( val featureFlags = callbacks?.getFeatureFlags?.invoke() (recyclerView as DragDropSwipeRecyclerView).apply { - if (localSettings.swipeLeft.canDisplay(folderRole, featureFlags, localSettings)) { - getSwipeActionUiData(localSettings.swipeLeft)?.let { (colorRes, iconRes) -> + if (folderRole == FolderRole.DRAFT) { + getSwipeActionUiData(SwipeAction.DELETE)?.let { (colorRes, iconRes) -> behindSwipedItemBackgroundColor = context.getColor(colorRes) behindSwipedItemIconDrawableId = iconRes } - } + getSwipeActionUiData(SwipeAction.QUICKACTIONS_MENU)?.let { (colorRes, iconRes) -> + behindSwipedItemBackgroundColor = context.getColor(colorRes) + behindSwipedItemIconDrawableId = iconRes + } + }else{ + if (localSettings.swipeLeft.canDisplay(folderRole, featureFlags, localSettings)) { + getSwipeActionUiData(localSettings.swipeLeft)?.let { (colorRes, iconRes) -> + behindSwipedItemBackgroundColor = context.getColor(colorRes) + behindSwipedItemIconDrawableId = iconRes + } + } - if (localSettings.swipeRight.canDisplay(folderRole, featureFlags, localSettings)) { - getSwipeActionUiData(localSettings.swipeRight)?.let { (colorRes, iconRes) -> - behindSwipedItemBackgroundSecondaryColor = context.getColor(colorRes) - behindSwipedItemIconSecondaryDrawableId = iconRes + if (localSettings.swipeRight.canDisplay(folderRole, featureFlags, localSettings)) { + getSwipeActionUiData(localSettings.swipeRight)?.let { (colorRes, iconRes) -> + behindSwipedItemBackgroundSecondaryColor = context.getColor(colorRes) + behindSwipedItemIconSecondaryDrawableId = iconRes + } } } + } } diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListFragment.kt b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListFragment.kt index 3b6c2b1cef..38f6b3a101 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListFragment.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListFragment.kt @@ -328,12 +328,13 @@ class ThreadListFragment : TwoPaneFragment(), PickerEmojiObserver { private fun unlockSwipeActionsIfSet() = with(binding.threadsList) { val isMultiSelectClosed = mainViewModel.isMultiSelectOn.not() + val isDraft = mainViewModel.currentFolderLive.value?.role == FolderRole.DRAFT - val isLeftSet = localSettings.swipeLeft != SwipeAction.NONE + val isLeftSet = localSettings.swipeLeft != SwipeAction.NONE || isDraft val isLeftEnabled = isLeftSet && isMultiSelectClosed if (isLeftEnabled) enableSwipeDirection(DirectionFlag.LEFT) else disableSwipeDirection(DirectionFlag.LEFT) - val isRightSet = localSettings.swipeRight != SwipeAction.NONE + val isRightSet = localSettings.swipeRight != SwipeAction.NONE || isDraft val isRightEnabled = isRightSet && isMultiSelectClosed if (isRightEnabled) enableSwipeDirection(DirectionFlag.RIGHT) else disableSwipeDirection(DirectionFlag.RIGHT) } @@ -414,27 +415,37 @@ class ThreadListFragment : TwoPaneFragment(), PickerEmojiObserver { } private fun updateDisabledSwipeActionsUi(featureFlags: FeatureFlagSet?, folderRole: FolderRole?) { + val isDraft = folderRole == FolderRole.DRAFT val isLeftEnabled = localSettings.swipeLeft.canDisplay(folderRole, featureFlags, localSettings) val isRightEnabled = localSettings.swipeRight.canDisplay(folderRole, featureFlags, localSettings) - setSwipeActionEnabledUi(DirectionFlag.LEFT, isLeftEnabled) - setSwipeActionEnabledUi(DirectionFlag.RIGHT, isRightEnabled) + setSwipeActionEnabledUi(DirectionFlag.LEFT, isLeftEnabled, isDraft) + setSwipeActionEnabledUi(DirectionFlag.RIGHT, isRightEnabled, isDraft) + } - private fun setSwipeActionEnabledUi(swipeDirection: DirectionFlag, isEnabled: Boolean) = with(binding.threadsList) { - fun SwipeAction.getIconRes(): Int? = if (isEnabled) iconRes else R.drawable.ic_close_small - fun SwipeAction.getBackgroundColor(): Int { - return if (isEnabled) getBackgroundColor(context) else SwipeAction.NONE.getBackgroundColor(context) - } + private fun setSwipeActionEnabledUi(swipeDirection: DirectionFlag, isEnabled: Boolean, isDraft: Boolean) = + with(binding.threadsList) { + fun SwipeAction.getIconRes(): Int? = if (isEnabled || isDraft) iconRes else R.drawable.ic_close_small + fun SwipeAction.getBackgroundColor(): Int { + return if (isEnabled || isDraft) getBackgroundColor(context) else SwipeAction.NONE.getBackgroundColor(context) + } - if (swipeDirection == DirectionFlag.LEFT) { - behindSwipedItemIconDrawableId = localSettings.swipeLeft.getIconRes() - behindSwipedItemBackgroundColor = localSettings.swipeLeft.getBackgroundColor() - } else { - behindSwipedItemIconSecondaryDrawableId = localSettings.swipeRight.getIconRes() - behindSwipedItemBackgroundSecondaryColor = localSettings.swipeRight.getBackgroundColor() + val targetAction = when { + isDraft && swipeDirection == DirectionFlag.LEFT -> SwipeAction.DELETE + isDraft && swipeDirection == DirectionFlag.RIGHT -> SwipeAction.QUICKACTIONS_MENU + swipeDirection == DirectionFlag.LEFT -> localSettings.swipeLeft + else -> localSettings.swipeRight + } + + if (swipeDirection == DirectionFlag.LEFT) { + behindSwipedItemIconDrawableId = targetAction.getIconRes() + behindSwipedItemBackgroundColor = targetAction.getBackgroundColor() + } else { + behindSwipedItemIconSecondaryDrawableId = targetAction.getIconRes() + behindSwipedItemBackgroundSecondaryColor = targetAction.getBackgroundColor() + } } - } private fun setupListeners() = with(binding) { @@ -494,9 +505,11 @@ class ThreadListFragment : TwoPaneFragment(), PickerEmojiObserver { threadsList.swipeListener = object : OnItemSwipeListener { override fun onItemSwiped(position: Int, direction: SwipeDirection, item: ThreadListItem.Content): Boolean { - val swipeAction = when (direction) { - SwipeDirection.LEFT_TO_RIGHT -> localSettings.swipeRight - SwipeDirection.RIGHT_TO_LEFT -> localSettings.swipeLeft + val swipeAction = when { + item.thread.folder.role == FolderRole.DRAFT && direction == SwipeDirection.RIGHT_TO_LEFT -> SwipeAction.DELETE + item.thread.folder.role == FolderRole.DRAFT && direction == SwipeDirection.LEFT_TO_RIGHT -> SwipeAction.QUICKACTIONS_MENU + direction == SwipeDirection.LEFT_TO_RIGHT -> localSettings.swipeRight + direction == SwipeDirection.RIGHT_TO_LEFT -> localSettings.swipeLeft else -> error("Only SwipeDirection.LEFT_TO_RIGHT and SwipeDirection.RIGHT_TO_LEFT can be triggered") } From d50be93d3f408ccf35664f8109551318899407dc Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Wed, 27 May 2026 16:44:41 +0200 Subject: [PATCH 03/11] fix: Manage multiselect in draft --- .../main/folder/ThreadListMultiSelection.kt | 3 +- .../actions/MultiSelectBottomSheetDialog.kt | 29 +++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListMultiSelection.kt b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListMultiSelection.kt index 357e30fc50..af74dd5c98 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListMultiSelection.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListMultiSelection.kt @@ -202,8 +202,9 @@ class ThreadListMultiSelection { val isSelectionEmpty = selectedThreads.isEmpty() threadListFragment.viewLifecycleOwner.lifecycleScope.launch { val isFromArchive = threadListFragment.folderRoleUtils.getActionFolderRole(selectedThreads) == FolderRole.ARCHIVE + val isFromDraft = threadListFragment.folderRoleUtils.getActionFolderRole(selectedThreads) == FolderRole.DRAFT for (index in 0 until getButtonCount()) { - val shouldDisable = isSelectionEmpty || (isFromArchive && index == ARCHIVE_INDEX) + val shouldDisable = isSelectionEmpty || ((isFromArchive || isFromDraft) && index == ARCHIVE_INDEX) if (shouldDisable) disable(index) else enable(index) } } diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MultiSelectBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MultiSelectBottomSheetDialog.kt index 83674d7f64..39d698b90e 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MultiSelectBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MultiSelectBottomSheetDialog.kt @@ -266,26 +266,37 @@ class MultiSelectBottomSheetDialog : ActionsBottomSheetDialog() { junkMessagesViewModel.potentialBlockedUsers.observe(viewLifecycleOwner) { potentialUsersToBlock -> val isFromSpam = mainViewModel.currentFolder.value?.role == FolderRole.SPAM setBlockUserUi(binding.blockSender, potentialUsersToBlock, isFromSpam) + hideFirstActionItemDivider() } } private fun setStateDependentUi(shouldRead: Boolean, shouldFavorite: Boolean, isFromArchive: Boolean, threads: Set) { - val (readIcon, readText) = getReadIconAndShortText(shouldRead) - binding.mainActions.setAction(R.id.actionReadUnread, readIcon, readText) + val isFromDraft = mainViewModel.currentFolder.value?.role == FolderRole.DRAFT + if (isFromDraft) { + with(binding) { + mainActions.isVisible = false + phishing.isVisible = false + favorite.isVisible = false + } + } else { + val (readIcon, readText) = getReadIconAndShortText(shouldRead) + binding.mainActions.setAction(R.id.actionReadUnread, readIcon, readText) - val (archiveIcon, archiveText) = getArchiveIconAndShortText(isFromArchive) - binding.mainActions.setAction(R.id.actionArchive, archiveIcon, archiveText) + val (archiveIcon, archiveText) = getArchiveIconAndShortText(isFromArchive) + binding.mainActions.setAction(R.id.actionArchive, archiveIcon, archiveText) - val (favoriteIcon, favoriteText) = getFavoriteIconAndShortText(shouldFavorite) - binding.favorite.apply { - setIconResource(favoriteIcon) - setTitle(favoriteText) + val (favoriteIcon, favoriteText) = getFavoriteIconAndShortText(shouldFavorite) + binding.favorite.apply { + setIconResource(favoriteIcon) + setTitle(favoriteText) + } } setSnoozeUi(threads) ThreadActionsBottomSheetDialog.setSpamUi( spam = binding.spam, - isFromSpam = mainViewModel.currentFolder.value?.role == FolderRole.SPAM + isFromSpam = mainViewModel.currentFolder.value?.role == FolderRole.SPAM, + isFromDraft = isFromDraft, ) hideFirstActionItemDivider() } From 509410ede137e3fe0a0115d78809f78ea99b1a35 Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Wed, 27 May 2026 16:45:26 +0200 Subject: [PATCH 04/11] fix: Remove action from BottomSheetDialog --- .../actions/MailActionsBottomSheetDialog.kt | 36 ++++++++++++++----- .../MessageActionsBottomSheetDialog.kt | 10 ++++-- .../actions/ThreadActionsBottomSheetDialog.kt | 15 ++++++-- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MailActionsBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MailActionsBottomSheetDialog.kt index b9fec9e6ff..06891890ff 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MailActionsBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MailActionsBottomSheetDialog.kt @@ -166,18 +166,36 @@ abstract class MailActionsBottomSheetDialog : ActionsBottomSheetDialog() { setTitle(readTextRes) } - fun setFavoriteUi(isFavorite: Boolean) = with(binding.favorite) { - val (favoriteIconRes, favoriteText) = computeFavoriteStyle(isFavorite) - setIconResource(favoriteIconRes) - setTitle(favoriteText) + fun setFavoriteUi(isFavorite: Boolean, isFromDraft: Boolean) = with(binding.favorite) { + when { + isFromDraft -> isVisible = false + else -> { + val (favoriteIconRes, favoriteText) = computeFavoriteStyle(isFavorite) + setIconResource(favoriteIconRes) + setTitle(favoriteText) + } + } + } + + fun setMainActionUi(isFromDraft: Boolean) { + if (isFromDraft) binding.mainActions.isVisible = false + } + + fun setMoveUi(isFromDraft: Boolean) { + if (isFromDraft) binding.move.isVisible = false + } + + fun setMarkUnreadUi(isFromDraft: Boolean) { + if (isFromDraft) binding.markAsReadUnread.isVisible = false } - fun setArchiveUi(isFromArchive: Boolean, isFromDraft: Boolean, isDraft: Boolean = false) = with(binding.archive) { + fun setReportPhishingUi(isFromDraft: Boolean) { + if (isFromDraft) binding.phishing.isVisible = false + } + + fun setArchiveUi(isFromArchive: Boolean, isFromDraft: Boolean) = with(binding.archive) { when { - isFromDraft || isDraft -> { - isVisible = false - return - } + isFromDraft -> isVisible = false isFromArchive -> { setIconResource(R.drawable.ic_drawer_inbox) setTitle(R.string.actionMoveToInbox) diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MessageActionsBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MessageActionsBottomSheetDialog.kt index bd6844724c..c3384d709d 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MessageActionsBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MessageActionsBottomSheetDialog.kt @@ -100,10 +100,14 @@ class MessageActionsBottomSheetDialog : MailActionsBottomSheetDialog() { isFromArchive = folderRole == FolderRole.ARCHIVE setMarkAsReadUi(message.isSeen) - setArchiveUi(isFromArchive, isFromDraft, message.isDraft) - setFavoriteUi(message.isFavorite) + setArchiveUi(isFromArchive, isFromDraft) + setFavoriteUi(message.isFavorite, isFromDraft) setReactionUi(message.isValidReactionTarget) - setSpamUi(binding.spam, isFromSpam) + setSpamUi(binding.spam, isFromSpam, isFromDraft) + setMainActionUi(isFromDraft) + setMoveUi(isFromDraft) + setMarkUnreadUi(isFromDraft) + setReportPhishingUi(isFromDraft) observeReportPhishingResult() observePotentialBlockedSenders() diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/ThreadActionsBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/ThreadActionsBottomSheetDialog.kt index f4e4fd0a79..6c48a1efad 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/ThreadActionsBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/ThreadActionsBottomSheetDialog.kt @@ -110,10 +110,14 @@ class ThreadActionsBottomSheetDialog : MailActionsBottomSheetDialog() { setMarkAsReadUi(thread.isSeen) setArchiveUi(isFromArchive, isFromDraft) - setFavoriteUi(thread.isFavorite) + setFavoriteUi(thread.isFavorite, isFromDraft) setSnoozeUi(thread.isSnoozed()) setReactionUi(canBeReactedTo = messageUidToReactTo != null) - setSpamUi(binding.spam, isFromSpam) + setSpamUi(binding.spam, isFromSpam, isFromDraft) + setMainActionUi(isFromDraft) + setMoveUi(isFromDraft) + setMarkUnreadUi(isFromDraft) + setReportPhishingUi(isFromDraft) initOnClickListener(onActionClick(thread, messageUidToExecuteAction, messageUidToReactTo)) } @@ -335,7 +339,12 @@ class ThreadActionsBottomSheetDialog : MailActionsBottomSheetDialog() { const val TAG = "ThreadActionsBottomSheetDialog" const val OPEN_SNOOZE_BOTTOM_SHEET = "openSnoozeBottomSheet" - fun setSpamUi(spam: ActionItemView, isFromSpam: Boolean) { + fun setSpamUi(spam: ActionItemView, isFromSpam: Boolean, isFromDraft: Boolean) { + if (isFromDraft) { + spam.isVisible = false + return + } + spam.apply { val (text, icon) = if (isFromSpam) { R.string.actionNonSpam to R.drawable.ic_non_spam From bc0a5a980e79fecd2274524e4385246bf38ea64b Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Thu, 28 May 2026 09:21:08 +0200 Subject: [PATCH 05/11] fix: Do not use updateDynamicIcons if it is a draft --- .../mail/ui/main/folder/ThreadListAdapter.kt | 27 ++++++------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListAdapter.kt b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListAdapter.kt index f2ec1ea963..7153b40aba 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListAdapter.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListAdapter.kt @@ -612,34 +612,23 @@ class ThreadListAdapter @Inject constructor( } private fun Thread.updateDynamicIcons() { + if (folderRole == FolderRole.DRAFT) return val featureFlags = callbacks?.getFeatureFlags?.invoke() (recyclerView as DragDropSwipeRecyclerView).apply { - if (folderRole == FolderRole.DRAFT) { - getSwipeActionUiData(SwipeAction.DELETE)?.let { (colorRes, iconRes) -> + if (localSettings.swipeLeft.canDisplay(folderRole, featureFlags, localSettings)) { + getSwipeActionUiData(localSettings.swipeLeft)?.let { (colorRes, iconRes) -> behindSwipedItemBackgroundColor = context.getColor(colorRes) behindSwipedItemIconDrawableId = iconRes } - getSwipeActionUiData(SwipeAction.QUICKACTIONS_MENU)?.let { (colorRes, iconRes) -> - behindSwipedItemBackgroundColor = context.getColor(colorRes) - behindSwipedItemIconDrawableId = iconRes - } - }else{ - if (localSettings.swipeLeft.canDisplay(folderRole, featureFlags, localSettings)) { - getSwipeActionUiData(localSettings.swipeLeft)?.let { (colorRes, iconRes) -> - behindSwipedItemBackgroundColor = context.getColor(colorRes) - behindSwipedItemIconDrawableId = iconRes - } - } + } - if (localSettings.swipeRight.canDisplay(folderRole, featureFlags, localSettings)) { - getSwipeActionUiData(localSettings.swipeRight)?.let { (colorRes, iconRes) -> - behindSwipedItemBackgroundSecondaryColor = context.getColor(colorRes) - behindSwipedItemIconSecondaryDrawableId = iconRes - } + if (localSettings.swipeRight.canDisplay(folderRole, featureFlags, localSettings)) { + getSwipeActionUiData(localSettings.swipeRight)?.let { (colorRes, iconRes) -> + behindSwipedItemBackgroundSecondaryColor = context.getColor(colorRes) + behindSwipedItemIconSecondaryDrawableId = iconRes } } - } } From c2890fc199be94a99dd88f94c08d6d5dfb8c0a1f Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Thu, 28 May 2026 09:22:17 +0200 Subject: [PATCH 06/11] refactor: Clean code --- .../mail/ui/main/folder/ThreadListMultiSelection.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListMultiSelection.kt b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListMultiSelection.kt index af74dd5c98..48a0fb6d85 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListMultiSelection.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListMultiSelection.kt @@ -201,8 +201,10 @@ class ThreadListMultiSelection { val isSelectionEmpty = selectedThreads.isEmpty() threadListFragment.viewLifecycleOwner.lifecycleScope.launch { - val isFromArchive = threadListFragment.folderRoleUtils.getActionFolderRole(selectedThreads) == FolderRole.ARCHIVE - val isFromDraft = threadListFragment.folderRoleUtils.getActionFolderRole(selectedThreads) == FolderRole.DRAFT + val actionFolderRole = threadListFragment.folderRoleUtils.getActionFolderRole(selectedThreads) + val isFromArchive = actionFolderRole == FolderRole.ARCHIVE + val isFromDraft = actionFolderRole == FolderRole.DRAFT + for (index in 0 until getButtonCount()) { val shouldDisable = isSelectionEmpty || ((isFromArchive || isFromDraft) && index == ARCHIVE_INDEX) if (shouldDisable) disable(index) else enable(index) From 6cd4be0ecb29cd6ceed52af2984ab48290ecf821 Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Tue, 2 Jun 2026 12:35:08 +0200 Subject: [PATCH 07/11] refactor: Clean code --- .../actions/MailActionsBottomSheetDialog.kt | 32 +++++++------ .../actions/MultiSelectBottomSheetDialog.kt | 48 +++++++++---------- 2 files changed, 42 insertions(+), 38 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MailActionsBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MailActionsBottomSheetDialog.kt index 06891890ff..3de0e1bc7a 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MailActionsBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MailActionsBottomSheetDialog.kt @@ -167,38 +167,42 @@ abstract class MailActionsBottomSheetDialog : ActionsBottomSheetDialog() { } fun setFavoriteUi(isFavorite: Boolean, isFromDraft: Boolean) = with(binding.favorite) { - when { - isFromDraft -> isVisible = false - else -> { - val (favoriteIconRes, favoriteText) = computeFavoriteStyle(isFavorite) - setIconResource(favoriteIconRes) - setTitle(favoriteText) - } + if (isFromDraft) { + isVisible = false + } else { + isVisible = true + val (favoriteIconRes, favoriteText) = computeFavoriteStyle(isFavorite) + setIconResource(favoriteIconRes) + setTitle(favoriteText) } } + fun setMainActionUi(isFromDraft: Boolean) { - if (isFromDraft) binding.mainActions.isVisible = false + binding.mainActions.isVisible = !isFromDraft } fun setMoveUi(isFromDraft: Boolean) { - if (isFromDraft) binding.move.isVisible = false + binding.move.isVisible = !isFromDraft } fun setMarkUnreadUi(isFromDraft: Boolean) { - if (isFromDraft) binding.markAsReadUnread.isVisible = false + binding.markAsReadUnread.isVisible = !isFromDraft } fun setReportPhishingUi(isFromDraft: Boolean) { - if (isFromDraft) binding.phishing.isVisible = false + binding.phishing.isVisible = !isFromDraft } fun setArchiveUi(isFromArchive: Boolean, isFromDraft: Boolean) = with(binding.archive) { - when { - isFromDraft -> isVisible = false - isFromArchive -> { + isVisible = !isFromDraft + if (isVisible) { + if (isFromArchive) { setIconResource(R.drawable.ic_drawer_inbox) setTitle(R.string.actionMoveToInbox) + } else { + setIconResource(R.drawable.ic_archive_folder) + setTitle(R.string.actionArchive) } } } diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MultiSelectBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MultiSelectBottomSheetDialog.kt index 39d698b90e..68f24fb8f3 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MultiSelectBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MultiSelectBottomSheetDialog.kt @@ -271,34 +271,34 @@ class MultiSelectBottomSheetDialog : ActionsBottomSheetDialog() { } private fun setStateDependentUi(shouldRead: Boolean, shouldFavorite: Boolean, isFromArchive: Boolean, threads: Set) { - val isFromDraft = mainViewModel.currentFolder.value?.role == FolderRole.DRAFT - if (isFromDraft) { - with(binding) { - mainActions.isVisible = false - phishing.isVisible = false - favorite.isVisible = false - } - } else { - val (readIcon, readText) = getReadIconAndShortText(shouldRead) - binding.mainActions.setAction(R.id.actionReadUnread, readIcon, readText) + with(binding) { + val isFromDraft = mainViewModel.currentFolder.value?.role == FolderRole.DRAFT + if (isFromDraft) { + mainActions.isVisible = false + phishing.isVisible = false + favorite.isVisible = false + } else { + val (readIcon, readText) = getReadIconAndShortText(shouldRead) + mainActions.setAction(R.id.actionReadUnread, readIcon, readText) - val (archiveIcon, archiveText) = getArchiveIconAndShortText(isFromArchive) - binding.mainActions.setAction(R.id.actionArchive, archiveIcon, archiveText) + val (archiveIcon, archiveText) = getArchiveIconAndShortText(isFromArchive) + mainActions.setAction(R.id.actionArchive, archiveIcon, archiveText) - val (favoriteIcon, favoriteText) = getFavoriteIconAndShortText(shouldFavorite) - binding.favorite.apply { - setIconResource(favoriteIcon) - setTitle(favoriteText) + val (favoriteIcon, favoriteText) = getFavoriteIconAndShortText(shouldFavorite) + favorite.apply { + setIconResource(favoriteIcon) + setTitle(favoriteText) + } } - } - setSnoozeUi(threads) - ThreadActionsBottomSheetDialog.setSpamUi( - spam = binding.spam, - isFromSpam = mainViewModel.currentFolder.value?.role == FolderRole.SPAM, - isFromDraft = isFromDraft, - ) - hideFirstActionItemDivider() + setSnoozeUi(threads) + ThreadActionsBottomSheetDialog.setSpamUi( + spam = spam, + isFromSpam = mainViewModel.currentFolder.value?.role == FolderRole.SPAM, + isFromDraft = isFromDraft, + ) + hideFirstActionItemDivider() + } } private fun setSnoozeUi(threads: Set) = with(binding) { From 2f5008cd41d73c1e742341d0c2385fd381a75648 Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Tue, 2 Jun 2026 13:10:22 +0200 Subject: [PATCH 08/11] feat: Remove swipe action if the user-defined swipe action is not allowed in the draft --- .../mail/ui/main/folder/ThreadListAdapter.kt | 1 - .../mail/ui/main/folder/ThreadListFragment.kt | 79 +++++++++++++------ .../actions/MailActionsBottomSheetDialog.kt | 21 ++--- 3 files changed, 61 insertions(+), 40 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListAdapter.kt b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListAdapter.kt index 7153b40aba..441434df1d 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListAdapter.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListAdapter.kt @@ -612,7 +612,6 @@ class ThreadListAdapter @Inject constructor( } private fun Thread.updateDynamicIcons() { - if (folderRole == FolderRole.DRAFT) return val featureFlags = callbacks?.getFeatureFlags?.invoke() (recyclerView as DragDropSwipeRecyclerView).apply { diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListFragment.kt b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListFragment.kt index 38f6b3a101..beb20111e7 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListFragment.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListFragment.kt @@ -326,17 +326,38 @@ class ThreadListFragment : TwoPaneFragment(), PickerEmojiObserver { _binding = null } - private fun unlockSwipeActionsIfSet() = with(binding.threadsList) { - val isMultiSelectClosed = mainViewModel.isMultiSelectOn.not() + private fun isAllowedToSwipeInDraft(swipeDirection: DirectionFlag): Boolean { + val allowedSwipeActionsForDraft = listOf( + SwipeAction.DELETE, + SwipeAction.QUICKACTIONS_MENU, + SwipeAction.READ_UNREAD, + SwipeAction.FAVORITE + ) val isDraft = mainViewModel.currentFolderLive.value?.role == FolderRole.DRAFT + return if (swipeDirection == DirectionFlag.LEFT) { + isDraft && localSettings.swipeLeft in allowedSwipeActionsForDraft + } else { + isDraft && localSettings.swipeRight in allowedSwipeActionsForDraft + } + } - val isLeftSet = localSettings.swipeLeft != SwipeAction.NONE || isDraft - val isLeftEnabled = isLeftSet && isMultiSelectClosed - if (isLeftEnabled) enableSwipeDirection(DirectionFlag.LEFT) else disableSwipeDirection(DirectionFlag.LEFT) + private fun unlockSwipeActionsIfSet() = with(binding.threadsList) { + val isMultiSelectClosed = !mainViewModel.isMultiSelectOn + val isInDraft = mainViewModel.currentFolderLive.value?.role == FolderRole.DRAFT + + fun updateSwipeDirection(direction: DirectionFlag, action: SwipeAction) { + val isActionSet = action != SwipeAction.NONE + val isAllowedByCurrentFolder = !isInDraft || isAllowedToSwipeInDraft(direction) - val isRightSet = localSettings.swipeRight != SwipeAction.NONE || isDraft - val isRightEnabled = isRightSet && isMultiSelectClosed - if (isRightEnabled) enableSwipeDirection(DirectionFlag.RIGHT) else disableSwipeDirection(DirectionFlag.RIGHT) + if (isMultiSelectClosed && isActionSet && isAllowedByCurrentFolder) { + enableSwipeDirection(direction) + } else { + disableSwipeDirection(direction) + } + } + + updateSwipeDirection(DirectionFlag.LEFT, localSettings.swipeLeft) + updateSwipeDirection(DirectionFlag.RIGHT, localSettings.swipeRight) } private fun setupDensityDependentUi() = with(binding) { @@ -426,24 +447,32 @@ class ThreadListFragment : TwoPaneFragment(), PickerEmojiObserver { private fun setSwipeActionEnabledUi(swipeDirection: DirectionFlag, isEnabled: Boolean, isDraft: Boolean) = with(binding.threadsList) { - fun SwipeAction.getIconRes(): Int? = if (isEnabled || isDraft) iconRes else R.drawable.ic_close_small - fun SwipeAction.getBackgroundColor(): Int { - return if (isEnabled || isDraft) getBackgroundColor(context) else SwipeAction.NONE.getBackgroundColor(context) - } + val isEnabledOrDraft = isEnabled || isDraft + fun SwipeAction.resolveIconRes(): Int? = if (isEnabledOrDraft) iconRes else R.drawable.ic_close_small - val targetAction = when { - isDraft && swipeDirection == DirectionFlag.LEFT -> SwipeAction.DELETE - isDraft && swipeDirection == DirectionFlag.RIGHT -> SwipeAction.QUICKACTIONS_MENU - swipeDirection == DirectionFlag.LEFT -> localSettings.swipeLeft - else -> localSettings.swipeRight + fun SwipeAction.resolveBackgroundColor(): Int { + return if (isEnabledOrDraft) { + getBackgroundColor(context) + } else { + SwipeAction.NONE.getBackgroundColor(context) + } } + val action = if (swipeDirection == DirectionFlag.LEFT) localSettings.swipeLeft else localSettings.swipeRight + + val isActionSet = action != SwipeAction.NONE + val isMultiSelectClosed = !mainViewModel.isMultiSelectOn + val isAllowedByCurrentFolder = !isDraft || isAllowedToSwipeInDraft(swipeDirection) + + val shouldEnableSwipe = isActionSet && isMultiSelectClosed && isAllowedByCurrentFolder + if (shouldEnableSwipe) enableSwipeDirection(swipeDirection) else disableSwipeDirection(swipeDirection) + if (swipeDirection == DirectionFlag.LEFT) { - behindSwipedItemIconDrawableId = targetAction.getIconRes() - behindSwipedItemBackgroundColor = targetAction.getBackgroundColor() + behindSwipedItemIconDrawableId = action.resolveIconRes() + behindSwipedItemBackgroundColor = action.resolveBackgroundColor() } else { - behindSwipedItemIconSecondaryDrawableId = targetAction.getIconRes() - behindSwipedItemBackgroundSecondaryColor = targetAction.getBackgroundColor() + behindSwipedItemIconSecondaryDrawableId = action.resolveIconRes() + behindSwipedItemBackgroundSecondaryColor = action.resolveBackgroundColor() } } @@ -505,11 +534,9 @@ class ThreadListFragment : TwoPaneFragment(), PickerEmojiObserver { threadsList.swipeListener = object : OnItemSwipeListener { override fun onItemSwiped(position: Int, direction: SwipeDirection, item: ThreadListItem.Content): Boolean { - val swipeAction = when { - item.thread.folder.role == FolderRole.DRAFT && direction == SwipeDirection.RIGHT_TO_LEFT -> SwipeAction.DELETE - item.thread.folder.role == FolderRole.DRAFT && direction == SwipeDirection.LEFT_TO_RIGHT -> SwipeAction.QUICKACTIONS_MENU - direction == SwipeDirection.LEFT_TO_RIGHT -> localSettings.swipeRight - direction == SwipeDirection.RIGHT_TO_LEFT -> localSettings.swipeLeft + val swipeAction = when (direction) { + SwipeDirection.LEFT_TO_RIGHT -> localSettings.swipeRight + SwipeDirection.RIGHT_TO_LEFT -> localSettings.swipeLeft else -> error("Only SwipeDirection.LEFT_TO_RIGHT and SwipeDirection.RIGHT_TO_LEFT can be triggered") } diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MailActionsBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MailActionsBottomSheetDialog.kt index 3de0e1bc7a..bf80ae1dba 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MailActionsBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/MailActionsBottomSheetDialog.kt @@ -167,17 +167,14 @@ abstract class MailActionsBottomSheetDialog : ActionsBottomSheetDialog() { } fun setFavoriteUi(isFavorite: Boolean, isFromDraft: Boolean) = with(binding.favorite) { - if (isFromDraft) { - isVisible = false - } else { - isVisible = true + isVisible = !isFromDraft + if (!isFromDraft) { val (favoriteIconRes, favoriteText) = computeFavoriteStyle(isFavorite) setIconResource(favoriteIconRes) setTitle(favoriteText) } } - fun setMainActionUi(isFromDraft: Boolean) { binding.mainActions.isVisible = !isFromDraft } @@ -196,14 +193,12 @@ abstract class MailActionsBottomSheetDialog : ActionsBottomSheetDialog() { fun setArchiveUi(isFromArchive: Boolean, isFromDraft: Boolean) = with(binding.archive) { isVisible = !isFromDraft - if (isVisible) { - if (isFromArchive) { - setIconResource(R.drawable.ic_drawer_inbox) - setTitle(R.string.actionMoveToInbox) - } else { - setIconResource(R.drawable.ic_archive_folder) - setTitle(R.string.actionArchive) - } + if (isFromArchive) { + setIconResource(R.drawable.ic_drawer_inbox) + setTitle(R.string.actionMoveToInbox) + } else { + setIconResource(R.drawable.ic_archive_folder) + setTitle(R.string.actionArchive) } } From 4d754e8efcd9be8916fe504e888d7e849b426901 Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Wed, 3 Jun 2026 09:34:10 +0200 Subject: [PATCH 09/11] refactor: Create isAllowedToSwipe and remove isAllowedToSwipeInDraft --- .../mail/ui/main/folder/ThreadListFragment.kt | 23 +++++++++++-------- .../mail/ui/main/thread/ThreadViewModel.kt | 1 - 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListFragment.kt b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListFragment.kt index beb20111e7..1a0a2597b6 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListFragment.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListFragment.kt @@ -326,30 +326,33 @@ class ThreadListFragment : TwoPaneFragment(), PickerEmojiObserver { _binding = null } - private fun isAllowedToSwipeInDraft(swipeDirection: DirectionFlag): Boolean { + private fun isAllowedToSwipe(swipeDirection: DirectionFlag, folderRole: FolderRole?): Boolean { + if (folderRole != FolderRole.DRAFT) return true + + val action = if (swipeDirection == DirectionFlag.LEFT) { + localSettings.swipeLeft + } else { + localSettings.swipeRight + } + val allowedSwipeActionsForDraft = listOf( SwipeAction.DELETE, SwipeAction.QUICKACTIONS_MENU, SwipeAction.READ_UNREAD, SwipeAction.FAVORITE ) - val isDraft = mainViewModel.currentFolderLive.value?.role == FolderRole.DRAFT - return if (swipeDirection == DirectionFlag.LEFT) { - isDraft && localSettings.swipeLeft in allowedSwipeActionsForDraft - } else { - isDraft && localSettings.swipeRight in allowedSwipeActionsForDraft - } + + return action in allowedSwipeActionsForDraft } private fun unlockSwipeActionsIfSet() = with(binding.threadsList) { val isMultiSelectClosed = !mainViewModel.isMultiSelectOn - val isInDraft = mainViewModel.currentFolderLive.value?.role == FolderRole.DRAFT fun updateSwipeDirection(direction: DirectionFlag, action: SwipeAction) { val isActionSet = action != SwipeAction.NONE - val isAllowedByCurrentFolder = !isInDraft || isAllowedToSwipeInDraft(direction) + val folderRole = mainViewModel.currentFolderLive.value?.role - if (isMultiSelectClosed && isActionSet && isAllowedByCurrentFolder) { + if (isMultiSelectClosed && isActionSet && isAllowedToSwipe(direction, folderRole)) { enableSwipeDirection(direction) } else { disableSwipeDirection(direction) diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/ThreadViewModel.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/ThreadViewModel.kt index 636eb071a7..478ca23d90 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/thread/ThreadViewModel.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/ThreadViewModel.kt @@ -94,7 +94,6 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChangedBy import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapLatest From 5f08c6aec3fb3ac0ab79597a9d1354c666137df2 Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Wed, 3 Jun 2026 09:58:18 +0200 Subject: [PATCH 10/11] refactor: Reduce cognitive complexity --- .../mail/ui/main/folder/ThreadListFragment.kt | 56 +++++++++++-------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListFragment.kt b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListFragment.kt index 1a0a2597b6..debba2b383 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListFragment.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListFragment.kt @@ -439,45 +439,53 @@ class ThreadListFragment : TwoPaneFragment(), PickerEmojiObserver { } private fun updateDisabledSwipeActionsUi(featureFlags: FeatureFlagSet?, folderRole: FolderRole?) { - val isDraft = folderRole == FolderRole.DRAFT val isLeftEnabled = localSettings.swipeLeft.canDisplay(folderRole, featureFlags, localSettings) val isRightEnabled = localSettings.swipeRight.canDisplay(folderRole, featureFlags, localSettings) - setSwipeActionEnabledUi(DirectionFlag.LEFT, isLeftEnabled, isDraft) - setSwipeActionEnabledUi(DirectionFlag.RIGHT, isRightEnabled, isDraft) + setSwipeActionEnabledUi(DirectionFlag.LEFT, isLeftEnabled, folderRole) + setSwipeActionEnabledUi(DirectionFlag.RIGHT, isRightEnabled, folderRole) } - private fun setSwipeActionEnabledUi(swipeDirection: DirectionFlag, isEnabled: Boolean, isDraft: Boolean) = - with(binding.threadsList) { - val isEnabledOrDraft = isEnabled || isDraft - fun SwipeAction.resolveIconRes(): Int? = if (isEnabledOrDraft) iconRes else R.drawable.ic_close_small + private fun setSwipeActionEnabledUi(swipeDirection: DirectionFlag, isEnabled: Boolean, folderRole: FolderRole?) { + val action = if (swipeDirection == DirectionFlag.LEFT) localSettings.swipeLeft else localSettings.swipeRight + updateSwipeEnableState(swipeDirection, folderRole, action) + updateSwipeVisuals(swipeDirection, isEnabled, folderRole, action) + } - fun SwipeAction.resolveBackgroundColor(): Int { - return if (isEnabledOrDraft) { - getBackgroundColor(context) - } else { - SwipeAction.NONE.getBackgroundColor(context) - } - } + private fun updateSwipeEnableState(swipeDirection: DirectionFlag, folderRole: FolderRole?, action: SwipeAction) { + val isActionSet = action != SwipeAction.NONE + val isMultiSelectClosed = !mainViewModel.isMultiSelectOn - val action = if (swipeDirection == DirectionFlag.LEFT) localSettings.swipeLeft else localSettings.swipeRight + val shouldEnableSwipe = isActionSet && isMultiSelectClosed && isAllowedToSwipe(swipeDirection, folderRole) - val isActionSet = action != SwipeAction.NONE - val isMultiSelectClosed = !mainViewModel.isMultiSelectOn - val isAllowedByCurrentFolder = !isDraft || isAllowedToSwipeInDraft(swipeDirection) + with(binding.threadsList) { + if (shouldEnableSwipe) { + enableSwipeDirection(swipeDirection) + } else { + disableSwipeDirection(swipeDirection) + } + } + } - val shouldEnableSwipe = isActionSet && isMultiSelectClosed && isAllowedByCurrentFolder - if (shouldEnableSwipe) enableSwipeDirection(swipeDirection) else disableSwipeDirection(swipeDirection) + private fun updateSwipeVisuals(swipeDirection: DirectionFlag, isEnabled: Boolean, folderRole: FolderRole?, action: SwipeAction) { + with(binding.threadsList) { + val resolvedIconRes = if (isEnabled) action.iconRes else R.drawable.ic_close_small + val resolvedBackgroundColor = if (isEnabled) { + action.getBackgroundColor(context) + } else { + SwipeAction.NONE.getBackgroundColor(context) + } if (swipeDirection == DirectionFlag.LEFT) { - behindSwipedItemIconDrawableId = action.resolveIconRes() - behindSwipedItemBackgroundColor = action.resolveBackgroundColor() + behindSwipedItemIconDrawableId = resolvedIconRes + behindSwipedItemBackgroundColor = resolvedBackgroundColor } else { - behindSwipedItemIconSecondaryDrawableId = action.resolveIconRes() - behindSwipedItemBackgroundSecondaryColor = action.resolveBackgroundColor() + behindSwipedItemIconSecondaryDrawableId = resolvedIconRes + behindSwipedItemBackgroundSecondaryColor = resolvedBackgroundColor } } + } private fun setupListeners() = with(binding) { From e087d5e38fdfc1aca2c591515aefe4c9181b15ab Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Wed, 3 Jun 2026 10:15:13 +0200 Subject: [PATCH 11/11] refactor: Clean code --- .../mail/ui/main/folder/ThreadListFragment.kt | 23 +++++++++---------- .../main/folder/ThreadListMultiSelection.kt | 5 ++-- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListFragment.kt b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListFragment.kt index debba2b383..8a6e6e24c0 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListFragment.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListFragment.kt @@ -326,8 +326,8 @@ class ThreadListFragment : TwoPaneFragment(), PickerEmojiObserver { _binding = null } - private fun isAllowedToSwipe(swipeDirection: DirectionFlag, folderRole: FolderRole?): Boolean { - if (folderRole != FolderRole.DRAFT) return true + private fun isAllowedToSwipe(swipeDirection: DirectionFlag): Boolean { + if (mainViewModel.currentFolderLive.value?.role != FolderRole.DRAFT) return true val action = if (swipeDirection == DirectionFlag.LEFT) { localSettings.swipeLeft @@ -350,9 +350,8 @@ class ThreadListFragment : TwoPaneFragment(), PickerEmojiObserver { fun updateSwipeDirection(direction: DirectionFlag, action: SwipeAction) { val isActionSet = action != SwipeAction.NONE - val folderRole = mainViewModel.currentFolderLive.value?.role - if (isMultiSelectClosed && isActionSet && isAllowedToSwipe(direction, folderRole)) { + if (isMultiSelectClosed && isActionSet && isAllowedToSwipe(direction)) { enableSwipeDirection(direction) } else { disableSwipeDirection(direction) @@ -442,22 +441,22 @@ class ThreadListFragment : TwoPaneFragment(), PickerEmojiObserver { val isLeftEnabled = localSettings.swipeLeft.canDisplay(folderRole, featureFlags, localSettings) val isRightEnabled = localSettings.swipeRight.canDisplay(folderRole, featureFlags, localSettings) - setSwipeActionEnabledUi(DirectionFlag.LEFT, isLeftEnabled, folderRole) - setSwipeActionEnabledUi(DirectionFlag.RIGHT, isRightEnabled, folderRole) + setSwipeActionEnabledUi(DirectionFlag.LEFT, isLeftEnabled) + setSwipeActionEnabledUi(DirectionFlag.RIGHT, isRightEnabled) } - private fun setSwipeActionEnabledUi(swipeDirection: DirectionFlag, isEnabled: Boolean, folderRole: FolderRole?) { + private fun setSwipeActionEnabledUi(swipeDirection: DirectionFlag, isEnabled: Boolean) { val action = if (swipeDirection == DirectionFlag.LEFT) localSettings.swipeLeft else localSettings.swipeRight - updateSwipeEnableState(swipeDirection, folderRole, action) - updateSwipeVisuals(swipeDirection, isEnabled, folderRole, action) + updateSwipeEnableState(swipeDirection, action) + updateSwipeVisuals(swipeDirection, isEnabled, action) } - private fun updateSwipeEnableState(swipeDirection: DirectionFlag, folderRole: FolderRole?, action: SwipeAction) { + private fun updateSwipeEnableState(swipeDirection: DirectionFlag, action: SwipeAction) { val isActionSet = action != SwipeAction.NONE val isMultiSelectClosed = !mainViewModel.isMultiSelectOn - val shouldEnableSwipe = isActionSet && isMultiSelectClosed && isAllowedToSwipe(swipeDirection, folderRole) + val shouldEnableSwipe = isActionSet && isMultiSelectClosed && isAllowedToSwipe(swipeDirection) with(binding.threadsList) { if (shouldEnableSwipe) { @@ -468,7 +467,7 @@ class ThreadListFragment : TwoPaneFragment(), PickerEmojiObserver { } } - private fun updateSwipeVisuals(swipeDirection: DirectionFlag, isEnabled: Boolean, folderRole: FolderRole?, action: SwipeAction) { + private fun updateSwipeVisuals(swipeDirection: DirectionFlag, isEnabled: Boolean, action: SwipeAction) { with(binding.threadsList) { val resolvedIconRes = if (isEnabled) action.iconRes else R.drawable.ic_close_small val resolvedBackgroundColor = if (isEnabled) { diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListMultiSelection.kt b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListMultiSelection.kt index 48a0fb6d85..58f5a16d4d 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListMultiSelection.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListMultiSelection.kt @@ -202,11 +202,10 @@ class ThreadListMultiSelection { val isSelectionEmpty = selectedThreads.isEmpty() threadListFragment.viewLifecycleOwner.lifecycleScope.launch { val actionFolderRole = threadListFragment.folderRoleUtils.getActionFolderRole(selectedThreads) - val isFromArchive = actionFolderRole == FolderRole.ARCHIVE - val isFromDraft = actionFolderRole == FolderRole.DRAFT + val isArchiveOrDraft = actionFolderRole == FolderRole.ARCHIVE || actionFolderRole == FolderRole.DRAFT for (index in 0 until getButtonCount()) { - val shouldDisable = isSelectionEmpty || ((isFromArchive || isFromDraft) && index == ARCHIVE_INDEX) + val shouldDisable = isSelectionEmpty || (isArchiveOrDraft && index == ARCHIVE_INDEX) if (shouldDisable) disable(index) else enable(index) } }