From 9c7eda3c9310d1febece539f5babd7182f0c29b3 Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Wed, 15 Apr 2026 08:46:46 +0200 Subject: [PATCH 1/9] feat: Add logic for multiple recipients UI needs improvement (currently displays email instead of name and requires pressing Enter to confirm) --- .../cache/userInfo/MergedContactController.kt | 4 + .../mail/ui/newMessage/ContactChipAdapter.kt | 17 +++ .../NewMessageRecipientFieldsManager.kt | 4 + .../mail/ui/newMessage/NewMessageViewModel.kt | 22 ++++ .../mail/ui/newMessage/RecipientFieldView.kt | 119 +++++++++++++++--- 5 files changed, 147 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/data/cache/userInfo/MergedContactController.kt b/app/src/main/java/com/infomaniak/mail/data/cache/userInfo/MergedContactController.kt index a48addddd87..61982a2f158 100644 --- a/app/src/main/java/com/infomaniak/mail/data/cache/userInfo/MergedContactController.kt +++ b/app/src/main/java/com/infomaniak/mail/data/cache/userInfo/MergedContactController.kt @@ -69,6 +69,10 @@ class MergedContactController @Inject constructor(@UserInfoRealm private val use return getMergedContactFromAddressBookQuery(contact).find().map { it } } + fun getMergedContactFromEmail(email: String): MergedContact? { + return null //TODO + } + fun getMergedContactsAsync(): Flow> { return getMergedContactsQuery().asFlow() } diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/ContactChipAdapter.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/ContactChipAdapter.kt index 086a0153348..7152b6bde1e 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/ContactChipAdapter.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/ContactChipAdapter.kt @@ -74,6 +74,23 @@ class ContactChipAdapter( } } + fun addChips(newRecipients: List): Pair { + var added = 0 + var duplicates = 0 + newRecipients.forEach { recipient -> + if (recipients.add(recipient)) { + added++ + } else { + duplicates++ + } + } + if (added > 0){ + notifyItemRangeInserted(itemCount - added, added) + } + + return Pair(added, duplicates) + } + fun removeChip(recipient: Recipient) { val index = recipients.indexOf(recipient) recipients.remove(recipient) diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageRecipientFieldsManager.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageRecipientFieldsManager.kt index 65d6cd6c209..90599ed78f5 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageRecipientFieldsManager.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageRecipientFieldsManager.kt @@ -74,6 +74,7 @@ class NewMessageRecipientFieldsManager @Inject constructor(private val snackbarM getAddressBookWithGroupCallback = newMessageViewModel::getAddressBookWithName, getMergedContactFromContactGroupCallback = newMessageViewModel::getMergedContactFromContactGroup, getMergedContactFromAddressBookCallback = newMessageViewModel::getMergedContactFromAddressBook, + getMergedContactFromEmailCallback = newMessageViewModel::getMergedContactFromEmail ), ) @@ -88,6 +89,7 @@ class NewMessageRecipientFieldsManager @Inject constructor(private val snackbarM getAddressBookWithGroupCallback = newMessageViewModel::getAddressBookWithName, getMergedContactFromContactGroupCallback = newMessageViewModel::getMergedContactFromContactGroup, getMergedContactFromAddressBookCallback = newMessageViewModel::getMergedContactFromAddressBook, + getMergedContactFromEmailCallback = newMessageViewModel::getMergedContactFromEmail ) ) @@ -102,6 +104,8 @@ class NewMessageRecipientFieldsManager @Inject constructor(private val snackbarM getAddressBookWithGroupCallback = newMessageViewModel::getAddressBookWithName, getMergedContactFromContactGroupCallback = newMessageViewModel::getMergedContactFromContactGroup, getMergedContactFromAddressBookCallback = newMessageViewModel::getMergedContactFromAddressBook, + getMergedContactFromEmailCallback = newMessageViewModel::getMergedContactFromEmail + ) ) } diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageViewModel.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageViewModel.kt index 93a7fccd522..3c960f78de7 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageViewModel.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageViewModel.kt @@ -416,6 +416,10 @@ class NewMessageViewModel @Inject constructor( return mergedContactController.getMergedContactFromAddressBook(addressBook) } + fun getMergedContactFromEmail(email: String) : MergedContact?{ + return mergedContactController.getMergedContactFromEmail(email) + } + private fun saveNavArgsToSavedState(localUuid: String) { savedStateHandle[NewMessageActivityArgs::draftLocalUuid.name] = localUuid @@ -760,6 +764,21 @@ class NewMessageViewModel @Inject constructor( } } + fun addRecipientsToField(recipients: List, type: FieldType){ + if (recipients.isEmpty()) return + + if (type == FieldType.CC || type == FieldType.BCC) otherRecipientsFieldsAreEmpty.value = false + + val recipientsLiveData = when (type) { + FieldType.TO -> toLiveData + FieldType.CC -> ccLiveData + FieldType.BCC -> bccLiveData + } + + recipientsLiveData.addRecipientsThenSetValue(recipients) + + } + fun addRecipientToField(recipient: Recipient, type: FieldType) { if (type == FieldType.CC || type == FieldType.BCC) otherRecipientsFieldsAreEmpty.value = false @@ -1072,6 +1091,9 @@ class NewMessageViewModel @Inject constructor( if (isTaskRoot) appContext.showToast(R.string.snackbarScheduling) } + private fun MutableLiveData.addRecipientsThenSetValue(recipients: List) { + updateRecipientsThenSetValue { it.addAll(recipients) } + } private fun MutableLiveData.addRecipientThenSetValue(recipient: Recipient) { updateRecipientsThenSetValue { it.add(recipient) } } diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt index 21a30f87b1a..02818e72165 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt @@ -60,7 +60,7 @@ import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject import kotlin.math.min import com.infomaniak.core.legacy.R as RCore - +import com.infomaniak.mail.data.cache.userInfo.MergedContactController @AndroidEntryPoint class RecipientFieldView @JvmOverloads constructor( context: Context, @@ -121,6 +121,7 @@ class RecipientFieldView @JvmOverloads constructor( private var getAddressBookWithGroup: ((ContactGroup) -> AddressBook?)? = null private var getMergedContactFromContactGroup: ((ContactGroup) -> List)? = null private var getMergedContactFromAddressBook: ((AddressBook) -> List)? = null + private var getMergedContactFromEmail: ((String) -> MergedContact?)? = null @Inject lateinit var snackbarManager: SnackbarManager @@ -163,7 +164,7 @@ class RecipientFieldView @JvmOverloads constructor( onContactClicked = ::contactClicked, onAddUnrecognizedContact = { val input = textInput.text.toString() - addRecipient(email = input, name = input) + addRecipientsFromInput(input = input) }, snackbarManager = snackbarManager, getAddressBookWithGroup = { getAddressBookWithGroup?.invoke(it) }, @@ -260,7 +261,11 @@ class RecipientFieldView @JvmOverloads constructor( setOnEditorActionListener { _, actionId, _ -> if (actionId == EditorInfo.IME_ACTION_DONE && text?.isNotBlank() == true) { - contactAdapter.addFirstAvailableItem() + if (isAutoCompletionOpened && contactAdapter.itemCount > 0) { + contactAdapter.addFirstAvailableItem() + } else { + addRecipientsFromInput(text.toString()) + } } true // Keep keyboard open } @@ -373,35 +378,108 @@ class RecipientFieldView @JvmOverloads constructor( else -> emptyList() } - for (mergedContact in listOfContact) { - addRecipient(mergedContact.email, mergedContact.name) - } + val contactsToAdd = listOfContact.map { Pair(it.name, it.email) } + addMultipleRecipients(contactsToAdd) } - private fun addRecipient(email: String, name: String) { + private fun addMultipleRecipients(recipients: List>) { + if (recipients.isEmpty()) return - if (!email.isEmail()) { - snackbarManager.setValue(context.getString(R.string.addUnknownRecipientInvalidEmail)) + if (contactChipAdapter.itemCount + recipients.size > MAX_ALLOWED_RECIPIENT) { + snackbarManager.setValue(context.getString(R.string.tooManyRecipients)) return } - if (contactChipAdapter.itemCount > MAX_ALLOWED_RECIPIENT) { - snackbarManager.setValue(context.getString(R.string.tooManyRecipients)) - return + val newRecipients = recipients.mapNotNull { (name, email) -> + if (contactAdapter.addUsedContact(email)) { + Recipient().initLocalValues(email, name) + } else { + null + } } + if (newRecipients.isEmpty()) return + if (contactChipAdapter.isEmpty()) { expand() binding.chipsRecyclerView.isVisible = true } - val recipientIsNew = contactAdapter.addUsedContact(email) - if (recipientIsNew) { - val recipient = Recipient().initLocalValues(email, name) - contactChipAdapter.addChip(recipient) - onContactAdded?.invoke(recipient) - clearField() + val (added, skipped) = contactChipAdapter.addChips(newRecipients) + + newRecipients.forEach { onContactAdded?.invoke(it) } + + clearField() + + if (skipped > 0) { + snackbarManager.setValue( + // context.getString(R.string.duplicateRecipientsSkipped, skipped)) + "X emails sont dupliqué") + } + } + + + fun getContactName(email: String): String { + return getMergedContactFromEmail?.invoke(email)?.name ?: email + } + private fun addRecipientsFromInput(input: String) { + val potentialEmails = input.split(EMAIL_SEPARATORS_REGEX).filter { it.isNotBlank() }.map { it.trim() } + + val emailToAdd = mutableListOf() + val invalidEmails = mutableListOf() + + potentialEmails.forEach { email -> + + if (email.isEmail()) { + emailToAdd.add(email) + } else { + invalidEmails.add(email) + } + } + + val recipientsToAdd = emailToAdd.map { email -> + getContactName(email) to email + } + + + + val totalAfterAdd = contactChipAdapter.itemCount + recipientsToAdd.size + + + if (totalAfterAdd > MAX_ALLOWED_RECIPIENT) { + snackbarManager.setValue(context.getString(R.string.tooManyRecipients)) + return + } + + if (recipientsToAdd.isNotEmpty()) { + addMultipleRecipients(recipientsToAdd) + } + + + // if (contactChipAdapter.isEmpty()) { + // expand() + // binding.chipsRecyclerView.isVisible = true + // } + + // val recipientIsNew = contactAdapter.addUsedContact(email) + // if (recipientIsNew) { + // val recipient = Recipient().initLocalValues(email, name) + // contactChipAdapter.addChip(recipient) + // onContactAdded?.invoke(recipient) + // clearField() + // } + + if (invalidEmails.isNotEmpty()){ + snackbarManager.setValue( + // context.getString("Des emails sont invalides") + "X emails sont invalides" + ) } + // before + // if (!email.isEmail()) { + // snackbarManager.setValue(context.getString(R.string.addUnknownRecipientInvalidEmail)) + // return + // } } private fun showContactContextMenu(recipient: Recipient, anchor: BackspaceAwareChip, isForSingleChip: Boolean = false) { @@ -443,6 +521,7 @@ class RecipientFieldView @JvmOverloads constructor( getAddressBookWithGroup = getAddressBookWithGroupCallback getMergedContactFromContactGroup = getMergedContactFromContactGroupCallback getMergedContactFromAddressBook = getMergedContactFromAddressBookCallback + getMergedContactFromEmail = getMergedContactFromEmailCallback gotFocus = gotFocusCallback } } @@ -512,7 +591,8 @@ class RecipientFieldView @JvmOverloads constructor( val onToggleEverythingCallback: ((isCollapsed: Boolean) -> Unit)? = null, val getAddressBookWithGroupCallback: (ContactGroup) -> AddressBook?, val getMergedContactFromContactGroupCallback: (ContactGroup) -> List, - val getMergedContactFromAddressBookCallback: (AddressBook) -> List + val getMergedContactFromAddressBookCallback: (AddressBook) -> List, + val getMergedContactFromEmailCallback: ((String) -> MergedContact?)? ) companion object { @@ -520,6 +600,7 @@ class RecipientFieldView @JvmOverloads constructor( private const val MAX_ALLOWED_RECIPIENT = 99 private const val EXTERNAL_CHIP_STROKE_WIDTH = 1 private const val NO_STROKE = 0.0f + private val EMAIL_SEPARATORS_REGEX = Regex("""[,;\s\r\n]+""") fun Chip.setChipStyle(displayAsExternal: Boolean, encryptionStatus: EncryptionStatus) = when { encryptionStatus == EncryptionStatus.Encrypted -> { From cad419518e0ff5f31e56d91eb82ecd2c185a5082 Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Wed, 15 Apr 2026 10:18:05 +0200 Subject: [PATCH 2/9] feat: Display first name in chips instead of email for merged contacts and enable automatic chip creation without pressing Enter --- .../mail/data/cache/userInfo/MergedContactController.kt | 6 +++++- .../infomaniak/mail/ui/newMessage/RecipientFieldView.kt | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/data/cache/userInfo/MergedContactController.kt b/app/src/main/java/com/infomaniak/mail/data/cache/userInfo/MergedContactController.kt index 61982a2f158..b9c29063f2e 100644 --- a/app/src/main/java/com/infomaniak/mail/data/cache/userInfo/MergedContactController.kt +++ b/app/src/main/java/com/infomaniak/mail/data/cache/userInfo/MergedContactController.kt @@ -54,6 +54,10 @@ class MergedContactController @Inject constructor(@UserInfoRealm private val use .sort(MergedContact::name.name) .sort(MergedContact::comesFromApi.name, Sort.DESCENDING) } + + private fun getMergedContactFromEmailQuery(email: String): RealmQuery { + return userInfoRealm.query("${MergedContact::email.name} == $0", email) + } //endregion //region Get data @@ -70,7 +74,7 @@ class MergedContactController @Inject constructor(@UserInfoRealm private val use } fun getMergedContactFromEmail(email: String): MergedContact? { - return null //TODO + return getMergedContactFromEmailQuery(email).find().firstOrNull() } fun getMergedContactsAsync(): Flow> { diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt index 02818e72165..dddd496e712 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt @@ -252,8 +252,12 @@ class RecipientFieldView @JvmOverloads constructor( doOnTextChanged { text, _, _, _ -> if (text?.isNotEmpty() == true) { - performContactSearch(text) - if (!isAutoCompletionOpened) openAutoCompletion() + if (text.contains(EMAIL_SEPARATORS_REGEX)) { + addRecipientsFromInput(text.toString()) + } else { + performContactSearch(text) + if (!isAutoCompletionOpened) openAutoCompletion() + } } else if (isAutoCompletionOpened) { closeAutoCompletion() } From bd9a13fc7e86126e7f47e25706f82b154e2989ae Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Wed, 15 Apr 2026 14:09:27 +0200 Subject: [PATCH 3/9] feat: Separate logic for pasting multiple emails and write an email --- .../ui/newMessage/BackspaceAwareTextInput.kt | 21 +++ .../mail/ui/newMessage/RecipientFieldView.kt | 129 ++++++++++-------- 2 files changed, 91 insertions(+), 59 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/BackspaceAwareTextInput.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/BackspaceAwareTextInput.kt index fcbb19894cd..276bdbc64a8 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/BackspaceAwareTextInput.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/BackspaceAwareTextInput.kt @@ -17,6 +17,7 @@ */ package com.infomaniak.mail.ui.newMessage +import android.content.ClipboardManager import android.content.Context import android.util.AttributeSet import android.view.KeyEvent @@ -28,13 +29,33 @@ class BackspaceAwareTextInput @JvmOverloads constructor( ) : TextInputEditText(context, attrs) { private var backspaceOnEmptyField: () -> Unit = {} + private var onPasteIntercept: ((String) -> Boolean)? = null override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { if (keyCode == KeyEvent.KEYCODE_DEL && text.isNullOrEmpty()) backspaceOnEmptyField() return super.onKeyDown(keyCode, event) } + override fun onTextContextMenuItem(id: Int): Boolean { + if (id == android.R.id.paste) { + val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + val clip = clipboard.primaryClip + + if (clip != null && clip.itemCount > 0) { + val pastedText = clip.getItemAt(0).text?.toString() ?: "" + if (onPasteIntercept?.invoke(pastedText) == true) { + return true + } + } + } + return super.onTextContextMenuItem(id) + } + fun setBackspaceOnEmptyFieldListener(listener: () -> Unit) { backspaceOnEmptyField = listener } + + fun setOnPasteInterceptListener(listener: (String) -> Boolean) { + onPasteIntercept = listener + } } diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt index dddd496e712..953b7f4c5c7 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt @@ -21,6 +21,7 @@ import android.content.Context import android.content.res.ColorStateList import android.graphics.drawable.InsetDrawable import android.util.AttributeSet +import android.util.Log import android.view.LayoutInflater import android.view.inputmethod.EditorInfo import android.widget.FrameLayout @@ -60,7 +61,7 @@ import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject import kotlin.math.min import com.infomaniak.core.legacy.R as RCore -import com.infomaniak.mail.data.cache.userInfo.MergedContactController + @AndroidEntryPoint class RecipientFieldView @JvmOverloads constructor( context: Context, @@ -170,13 +171,13 @@ class RecipientFieldView @JvmOverloads constructor( getAddressBookWithGroup = { getAddressBookWithGroup?.invoke(it) }, ) + + contactChipAdapter = ContactChipAdapter( - openContextMenu = ::showContactContextMenu, - onBackspace = { recipient -> + openContextMenu = ::showContactContextMenu, onBackspace = { recipient -> removeRecipient(recipient) focusTextField() - } - ) + }) isSelfCollapsed = true @@ -185,6 +186,7 @@ class RecipientFieldView @JvmOverloads constructor( setToggleRelatedListeners() setTextInputListeners() setPopupMenuListeners() + setPasteListeners(textInput) if (isInEditMode) { singleChip.root.isVisible = canCollapseEverything @@ -252,12 +254,8 @@ class RecipientFieldView @JvmOverloads constructor( doOnTextChanged { text, _, _, _ -> if (text?.isNotEmpty() == true) { - if (text.contains(EMAIL_SEPARATORS_REGEX)) { - addRecipientsFromInput(text.toString()) - } else { - performContactSearch(text) - if (!isAutoCompletionOpened) openAutoCompletion() - } + performContactSearch(text) + if (!isAutoCompletionOpened) openAutoCompletion() } else if (isAutoCompletionOpened) { closeAutoCompletion() } @@ -295,6 +293,17 @@ class RecipientFieldView @JvmOverloads constructor( } } + private fun setPasteListeners(textInput: BackspaceAwareTextInput) { + textInput.setOnPasteInterceptListener { pastedText -> + if (pastedText.contains(EMAIL_SEPARATORS_REGEX)) { + addRecipientsFromInput(pastedText) + true + } else { + false + } + } + } + private fun focusLastChip() { val count = contactChipAdapter.itemCount // chipsRecyclerView.children.last() won't work because they are not always ordered correctly @@ -382,15 +391,41 @@ class RecipientFieldView @JvmOverloads constructor( else -> emptyList() } - val contactsToAdd = listOfContact.map { Pair(it.name, it.email) } - addMultipleRecipients(contactsToAdd) + for (mergedContact in listOfContact) { + addRecipient(mergedContact.email, mergedContact.name) + } + } + + private fun addRecipient(email: String, name: String) { + if (!email.isEmail()) { + snackbarManager.setValue(context.getString(R.string.addUnknownRecipientInvalidEmail)) + return + } + + if (contactChipAdapter.itemCount > MAX_ALLOWED_RECIPIENT) { + snackbarManager.setValue(context.getString(R.string.tooManyRecipients)) + return + } + + if (contactChipAdapter.isEmpty()) { + expand() + binding.chipsRecyclerView.isVisible = true + } + + val recipientIsNew = contactAdapter.addUsedContact(email) + if (recipientIsNew) { + val recipient = Recipient().initLocalValues(email, name) + contactChipAdapter.addChip(recipient) + onContactAdded?.invoke(recipient) + clearField() + } } private fun addMultipleRecipients(recipients: List>) { if (recipients.isEmpty()) return if (contactChipAdapter.itemCount + recipients.size > MAX_ALLOWED_RECIPIENT) { - snackbarManager.setValue(context.getString(R.string.tooManyRecipients)) + snackbarManager.setValue(context.getString(R.string.tooManyRecipients)) // TODO: change string to add plurals return } @@ -402,88 +437,66 @@ class RecipientFieldView @JvmOverloads constructor( } } - if (newRecipients.isEmpty()) return + val skipped1 = recipients.size - newRecipients.size + if (skipped1 > 0) { + snackbarManager.setValue( + // context.getString(R.string.duplicateRecipientsSkipped, skipped)) + "${skipped1} emails are duplicated" //TODO: manage string + plurals + ) + if (skipped1 == recipients.size){ + return + } + } if (contactChipAdapter.isEmpty()) { expand() binding.chipsRecyclerView.isVisible = true } - val (added, skipped) = contactChipAdapter.addChips(newRecipients) - + contactChipAdapter.addChips(newRecipients) newRecipients.forEach { onContactAdded?.invoke(it) } clearField() - - if (skipped > 0) { - snackbarManager.setValue( - // context.getString(R.string.duplicateRecipientsSkipped, skipped)) - "X emails sont dupliqué") - } } fun getContactName(email: String): String { return getMergedContactFromEmail?.invoke(email)?.name ?: email } + private fun addRecipientsFromInput(input: String) { val potentialEmails = input.split(EMAIL_SEPARATORS_REGEX).filter { it.isNotBlank() }.map { it.trim() } - val emailToAdd = mutableListOf() + val emailsToAdd = mutableListOf() val invalidEmails = mutableListOf() potentialEmails.forEach { email -> - if (email.isEmail()) { - emailToAdd.add(email) + emailsToAdd.add(email) } else { invalidEmails.add(email) } } - val recipientsToAdd = emailToAdd.map { email -> + val recipientsToAdd = emailsToAdd.map { email -> getContactName(email) to email } - - val totalAfterAdd = contactChipAdapter.itemCount + recipientsToAdd.size if (totalAfterAdd > MAX_ALLOWED_RECIPIENT) { - snackbarManager.setValue(context.getString(R.string.tooManyRecipients)) + snackbarManager.setValue(context.getString(R.string.tooManyRecipients)) // TODO: check plurals return } - if (recipientsToAdd.isNotEmpty()) { - addMultipleRecipients(recipientsToAdd) - } - - - // if (contactChipAdapter.isEmpty()) { - // expand() - // binding.chipsRecyclerView.isVisible = true - // } - - // val recipientIsNew = contactAdapter.addUsedContact(email) - // if (recipientIsNew) { - // val recipient = Recipient().initLocalValues(email, name) - // contactChipAdapter.addChip(recipient) - // onContactAdded?.invoke(recipient) - // clearField() - // } + addMultipleRecipients(recipientsToAdd) - if (invalidEmails.isNotEmpty()){ + if (invalidEmails.isNotEmpty()) { snackbarManager.setValue( - // context.getString("Des emails sont invalides") - "X emails sont invalides" + "${invalidEmails.size} email addresses are invalid" // TODO: manage string ) } - // before - // if (!email.isEmail()) { - // snackbarManager.setValue(context.getString(R.string.addUnknownRecipientInvalidEmail)) - // return - // } } private fun showContactContextMenu(recipient: Recipient, anchor: BackspaceAwareChip, isForSingleChip: Boolean = false) { @@ -505,8 +518,7 @@ class RecipientFieldView @JvmOverloads constructor( } fun initRecipientField( - autoComplete: RecyclerView, - callBackRecipientField: CallBackRecipientField + autoComplete: RecyclerView, callBackRecipientField: CallBackRecipientField ) { val margin = context.resources.getDimensionPixelSize(R.dimen.dividerHorizontalPadding) @@ -615,8 +627,7 @@ class RecipientFieldView @JvmOverloads constructor( iconTint = R.color.encryptionIconColor, ) } - encryptionStatus == EncryptionStatus.PartiallyEncrypted || - encryptionStatus == EncryptionStatus.Loading -> ChipStyle( + encryptionStatus == EncryptionStatus.PartiallyEncrypted || encryptionStatus == EncryptionStatus.Loading -> ChipStyle( backgroundColor = R.color.encryptionBackgroundColor, textColor = R.color.encryptionTextColor, icon = R.drawable.ic_lock_open_filled_pastille, From 204494ebda70179f97721f60a4e1041f5134790b Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Thu, 16 Apr 2026 10:50:48 +0200 Subject: [PATCH 4/9] feat: Add error messages in all languages with plural handling --- .../mail/ui/newMessage/RecipientFieldView.kt | 22 +++++++++++-------- app/src/main/res/values-da/strings.xml | 13 ++++++++++- app/src/main/res/values-de/strings.xml | 13 ++++++++++- app/src/main/res/values-el/strings.xml | 13 ++++++++++- app/src/main/res/values-es/strings.xml | 13 ++++++++++- app/src/main/res/values-fi/strings.xml | 13 ++++++++++- app/src/main/res/values-fr/strings.xml | 13 ++++++++++- app/src/main/res/values-it/strings.xml | 13 ++++++++++- app/src/main/res/values-nb/strings.xml | 13 ++++++++++- app/src/main/res/values-nl/strings.xml | 13 ++++++++++- app/src/main/res/values-pl/strings.xml | 19 +++++++++++++++- app/src/main/res/values-pt/strings.xml | 13 ++++++++++- app/src/main/res/values-sv/strings.xml | 13 ++++++++++- app/src/main/res/values/strings.xml | 14 ++++++++++-- 14 files changed, 175 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt index 953b7f4c5c7..7a3c5237fa0 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt @@ -403,7 +403,7 @@ class RecipientFieldView @JvmOverloads constructor( } if (contactChipAdapter.itemCount > MAX_ALLOWED_RECIPIENT) { - snackbarManager.setValue(context.getString(R.string.tooManyRecipients)) + snackbarManager.setValue(context.resources.getQuantityString(R.plurals.tooManyRecipients, 1)) return } @@ -425,7 +425,7 @@ class RecipientFieldView @JvmOverloads constructor( if (recipients.isEmpty()) return if (contactChipAdapter.itemCount + recipients.size > MAX_ALLOWED_RECIPIENT) { - snackbarManager.setValue(context.getString(R.string.tooManyRecipients)) // TODO: change string to add plurals + snackbarManager.setValue(context.resources.getQuantityString(R.plurals.tooManyRecipients, recipients.size)) return } @@ -437,13 +437,17 @@ class RecipientFieldView @JvmOverloads constructor( } } - val skipped1 = recipients.size - newRecipients.size - if (skipped1 > 0) { + val nbDuplicateRecipient = recipients.size - newRecipients.size + if (nbDuplicateRecipient > 0) { snackbarManager.setValue( - // context.getString(R.string.duplicateRecipientsSkipped, skipped)) - "${skipped1} emails are duplicated" //TODO: manage string + plurals + context.resources.getQuantityString( + R.plurals.addMultipleDuplicateEmails, + nbDuplicateRecipient, + nbDuplicateRecipient + ) ) - if (skipped1 == recipients.size){ + + if (nbDuplicateRecipient == recipients.size) { return } } @@ -486,7 +490,7 @@ class RecipientFieldView @JvmOverloads constructor( if (totalAfterAdd > MAX_ALLOWED_RECIPIENT) { - snackbarManager.setValue(context.getString(R.string.tooManyRecipients)) // TODO: check plurals + snackbarManager.setValue(context.resources.getQuantityString(R.plurals.tooManyRecipients, totalAfterAdd)) return } @@ -494,7 +498,7 @@ class RecipientFieldView @JvmOverloads constructor( if (invalidEmails.isNotEmpty()) { snackbarManager.setValue( - "${invalidEmails.size} email addresses are invalid" // TODO: manage string + context.resources.getQuantityString(R.plurals.addMultipleInvalidEmails, invalidEmails.size, invalidEmails.size) ) } } diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index c38fa7696ec..67290e8dceb 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -48,6 +48,14 @@ Vis i mørk tema Vis i lyst tema Tekst til visning + + %d email er allerede blevet tilføjet + %d emails er allerede blevet tilføjet + + + %d email er ugyldig + %d emails er ugyldige + E-mailadressen er allerede i brug E-mailadressen er ugyldig Tilføj en modtager @@ -660,7 +668,10 @@ Til: I morgen tidlig - Du kan ikke tilføje denne adresse, fordi du har nået grænsen for modtagere + + Du kan ikke tilføje denne adresse, fordi du har nået grænsen for modtagere + Du kan ikke tilføje disse adresser, fordi du har nået grænsen for modtagere + Papirkurv Fjern blokering Ukendt afsender diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 38d0c348c62..651bf027c35 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -48,6 +48,14 @@ Ansicht im dunklen Thema Ansicht im hellen Thema Anzuzeigender Text + + %d E-Mail wurde bereits hinzugefügt + %d E-Mails wurden bereits hinzugefügt + + + %d E-Mails sind ungültig + %d E-Mail ist ungültig + Die E-Mail wird bereits verwendet Die E-Mail ist ungültig Einen Empfänger hinzufügen @@ -660,7 +668,10 @@ An: Morgen früh - Sie können diese Adresse nicht hinzufügen, da Sie die Höchstzahl an Empfängern erreicht haben + + Sie können diese Adresse nicht hinzufügen, da Sie die Höchstzahl an Empfängern erreicht haben + Sie können diese Adressen nicht hinzufügen, da Sie die Höchstzahl an Empfängern erreicht haben + Papierkorb Entsperren Unbekannter Spediteur diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index a3ec193a193..fc13747ddd9 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -48,6 +48,14 @@ Προβολή σε σκούρο θέμα Προβολή σε φωτεινό θέμα Κείμενο για εμφάνιση + + %d email έχει ήδη προστεθεί + %d emails έχουν ήδη προστεθεί + + + %d email είναι μη έγκυρο + %d emails είναι μη έγκυρα + Το e-mail χρησιμοποιείται ήδη Το e-mail δεν είναι έγκυρο Προσθήκη παραλήπτη @@ -660,7 +668,10 @@ Προς: Αύριο το πρωί - Δεν μπορείτε να προσθέσετε αυτή τη διεύθυνση γιατί έχετε φτάσει το όριο παραληπτών + + Δεν μπορείτε να προσθέσετε αυτή τη διεύθυνση γιατί έχετε φτάσει το όριο παραληπτών + Δεν μπορείτε να προσθέσετε αυτές τις διευθύνσεις γιατί έχετε φτάσει το όριο παραληπτών + Κάδος απορριμμάτων Ξεμπλοκάρισμα Άγνωστος αποστολέας diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 8111d7cbdeb..35fb4b6e42e 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -48,6 +48,14 @@ Ver en tema oscuro Ver en tema claro Texto a mostrar + + %d email ya se ha añadido + %d emails ya se han añadido + + + %d email no es válido + %d emails no son válidos + El correo electrónico ya está utilizado El correo electrónico no es válido Añadir un destinatario @@ -660,7 +668,10 @@ Para: Mañana por la mañana - No puede añadir esta dirección porque ha alcanzado el límite de destinatarios + + No puede añadir esta dirección porque ha alcanzado el límite de destinatarios + No puede añadir estas direcciones porque ha alcanzado el límite de destinatarios + Papelera Desbloquear Expedidor desconocido diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index bd29e2881cf..af4f3d460b2 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -48,6 +48,14 @@ Näytä tummassa teemassa Näytä vaaleassa teemassa Näytettävä teksti + + %d email on jo lisätty + %d emailia on jo lisätty + + + %d email on virheellinen + %d emailia ovat virheellisiä + Sähköpostiosoite on jo käytössä Sähköpostiosoite on virheellinen Lisää vastaanottaja @@ -660,7 +668,10 @@ Vastaanottaja: Huomenna aamulla - Et voi lisätä tätä osoitetta, koska olet saavuttanut vastaanottajien rajan + + Et voi lisätä tätä osoitetta, koska olet saavuttanut vastaanottajien rajan + Et voi lisätä näitä osoitteita, koska olet saavuttanut vastaanottajien rajan + Roskakori Poista esto Tuntematon lähettäjä diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 237020638a0..9ee9fab6023 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -48,6 +48,14 @@ Voir en thème sombre Voir en thème clair Texte à afficher + + %d e-mail a déjà été ajouté + %d e-mails ont déjà été ajoutés + + + %d e-mail est invalide + %d e-mails sont invalides + L’adresse mail est déjà utilisée L’adresse mail n’est pas valide Ajouter un destinataire @@ -660,7 +668,10 @@ À : Demain matin - Vous ne pouvez pas ajouter cette adresse car vous avez atteint la limite de destinataires + + Vous ne pouvez pas ajouter cette adresse car vous avez atteint la limite de destinataires + Vous ne pouvez pas ajouter ces adresses car vous avez atteint la limite de destinataires + Corbeille Débloquer Expéditeur inconnu diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index a85a370073d..8e4055f7fd7 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -48,6 +48,14 @@ Visualizzazione in tema scuro Vista in tema chiaro Testo da visualizzare + + %d email è già stato aggiunto + %d email sono già stati aggiunti + + + %d email non è valido + %d email non sono validi + L’e-mail è già utilizzata L’e-mail non è valida Aggiungi un destinatario @@ -660,7 +668,10 @@ A: Domani mattina - Non è possibile aggiungere questo indirizzo perché è stato raggiunto il limite di destinatari + + Non è possibile aggiungere questo indirizzo perché è stato raggiunto il limite di destinatari + Non è possibile aggiungere questi indirizzi perché è stato raggiunto il limite di destinatari + Cestino Sbloccare Spedizioniere sconosciuto diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index c695dc6806a..c539f106ca9 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -48,6 +48,14 @@ Vis i mørkt tema Vis i lyst tema Tekst å vise + + %d email er allerede lagt til + %d emails er allerede lagt til + + + %d email er ugyldig + %d emails er ugyldige + E-postadressen er allerede i bruk E-postadressen er ugyldig Legg til mottaker @@ -660,7 +668,10 @@ Til: I morgen tidlig - Du kan ikke legge til denne adressen fordi du har nådd grensen for mottakere + + Du kan ikke legge til denne adressen fordi du har nådd grensen for mottakere + Du kan ikke legge til disse adressene fordi du har nådd grensen for mottakere + Papirkurv Opphev blokkering Ukjent avsender diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index b678be346c2..599eba7bde9 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -48,6 +48,14 @@ Weergeven in donker thema Weergeven in licht thema Weer te geven tekst + + %d email is al toegevoegd + %d emails zijn al toegevoegd + + + %d email is ongeldig + %d emails zijn ongeldig + Het e-mailadres wordt al gebruikt Het e-mailadres is ongeldig Een ontvanger toevoegen @@ -660,7 +668,10 @@ Aan: Morgenochtend - U kunt dit adres niet toevoegen omdat u de limiet van ontvangers heeft bereikt + + U kunt dit adres niet toevoegen omdat u de limiet van ontvangers heeft bereikt + U kunt deze adressen niet toevoegen omdat u de limiet van ontvangers heeft bereikt + Prullenbak Deblokkeren Onbekende afzender diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index af9d595dde4..78889cbfdba 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -48,6 +48,18 @@ Zobacz w ciemnym motywie Zobacz w jasnym motywie Tekst do wyświetlenia + + %d email został już dodany + %d emaile zostały już dodane + %d emaili zostało już dodanych + %d emaili zostało już dodanych + + + %d email jest nieprawidłowy + %d emaile są nieprawidłowe + %d emaili jest nieprawidłowych + %d emaili jest nieprawidłowych + Ten adres e-mail jest już używany Adres e-mail jest nieprawidłowy Dodaj odbiorcę @@ -704,7 +716,12 @@ Do: Jutro rano - Nie możesz dodać tego adresu, ponieważ osiągnąłeś/aś limit odbiorców + + Nie możesz dodać tego adresu, ponieważ osiągnąłeś/aś limit odbiorców + Nie możesz dodać tych adresów, ponieważ osiągnąłeś limit odbiorców + Nie możesz dodać tych adresów, ponieważ osiągnąłeś limit odbiorców + Nie możesz dodać tych adresów, ponieważ osiągnąłeś limit odbiorców + Kosz Odblokuj Nieznany nadawca diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 30bfc92e3bf..1ae8e640c97 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -48,6 +48,14 @@ Ver no tema escuro Ver no tema claro Texto a exibir + + %d email já foi adicionado + %d emails já foram adicionados + + + %d email é inválido + %d emails são inválidos + O e-mail já está sendo usado O e-mail é inválido Adicionar destinatário @@ -660,7 +668,10 @@ Para: Amanhã de manhã - Não pode adicionar este endereço pois atingiu o limite de destinatários + + Não pode adicionar este endereço pois atingiu o limite de destinatários + Não pode adicionar estes endereços pois atingiu o limite de destinatários + Lixo Desbloquear Remetente desconhecido diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index fea697360a6..80898114661 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -48,6 +48,14 @@ Visa i mörkt tema Visa i ljust tema Text att visa + + %d email har redan lagts till + %d emails har redan lagts till + + + %d email är ogiltig + %d emails är ogiltiga + E-postadressen används redan E-postadressen är ogiltig Lägg till mottagare @@ -660,7 +668,10 @@ Till: I morgon bitti - Du kan inte lägga till denna adress eftersom du har nått gränsen för mottagare + + Du kan inte lägga till denna adress eftersom du har nått gränsen för mottagare + Du kan inte lägga till dessa adresser eftersom du har nått gränsen för mottagare + Papperskorg Avblockera Okänd avsändare diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d035ece8e30..36b70f7919d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -17,7 +17,6 @@ --> Infomaniak Mail - draft_service_channel_id general_channel_id sync_messages_service_channel_id @@ -53,6 +52,14 @@ View in dark theme View in light theme Text to display + + %d email has already been added + %d emails have already been added + + + %d email is invalid + %d emails are invalid + The email is already used The email is invalid Add a recipient @@ -665,7 +672,10 @@ To: Tomorrow morning - You can’t add this address because you have reached the limit of recipients + + You can’t add this address because you have reached the limit of recipients + You can’t add these addresses because you have reached the limit of recipients + Trash Unblock Unknown expeditor From 36c53d96b3da9671973a569df7a8e79d8e13c2bb Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Thu, 16 Apr 2026 11:12:31 +0200 Subject: [PATCH 5/9] refactor: Clean code --- .../mail/ui/newMessage/ContactChipAdapter.kt | 9 +++------ .../mail/ui/newMessage/NewMessageViewModel.kt | 20 +------------------ .../mail/ui/newMessage/RecipientFieldView.kt | 7 ++++--- 3 files changed, 8 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/ContactChipAdapter.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/ContactChipAdapter.kt index 7152b6bde1e..ad7baf72228 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/ContactChipAdapter.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/ContactChipAdapter.kt @@ -74,21 +74,18 @@ class ContactChipAdapter( } } - fun addChips(newRecipients: List): Pair { + fun addChips(newRecipients: List): Int { var added = 0 - var duplicates = 0 newRecipients.forEach { recipient -> if (recipients.add(recipient)) { added++ - } else { - duplicates++ } } - if (added > 0){ + if (added > 0) { notifyItemRangeInserted(itemCount - added, added) } - return Pair(added, duplicates) + return added } fun removeChip(recipient: Recipient) { diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageViewModel.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageViewModel.kt index 3c960f78de7..4c809f69bc2 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageViewModel.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageViewModel.kt @@ -416,7 +416,7 @@ class NewMessageViewModel @Inject constructor( return mergedContactController.getMergedContactFromAddressBook(addressBook) } - fun getMergedContactFromEmail(email: String) : MergedContact?{ + fun getMergedContactFromEmail(email: String): MergedContact? { return mergedContactController.getMergedContactFromEmail(email) } @@ -764,21 +764,6 @@ class NewMessageViewModel @Inject constructor( } } - fun addRecipientsToField(recipients: List, type: FieldType){ - if (recipients.isEmpty()) return - - if (type == FieldType.CC || type == FieldType.BCC) otherRecipientsFieldsAreEmpty.value = false - - val recipientsLiveData = when (type) { - FieldType.TO -> toLiveData - FieldType.CC -> ccLiveData - FieldType.BCC -> bccLiveData - } - - recipientsLiveData.addRecipientsThenSetValue(recipients) - - } - fun addRecipientToField(recipient: Recipient, type: FieldType) { if (type == FieldType.CC || type == FieldType.BCC) otherRecipientsFieldsAreEmpty.value = false @@ -1091,9 +1076,6 @@ class NewMessageViewModel @Inject constructor( if (isTaskRoot) appContext.showToast(R.string.snackbarScheduling) } - private fun MutableLiveData.addRecipientsThenSetValue(recipients: List) { - updateRecipientsThenSetValue { it.addAll(recipients) } - } private fun MutableLiveData.addRecipientThenSetValue(recipient: Recipient) { updateRecipientsThenSetValue { it.add(recipient) } } diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt index 7a3c5237fa0..7d6f5fb641f 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt @@ -21,7 +21,6 @@ import android.content.Context import android.content.res.ColorStateList import android.graphics.drawable.InsetDrawable import android.util.AttributeSet -import android.util.Log import android.view.LayoutInflater import android.view.inputmethod.EditorInfo import android.widget.FrameLayout @@ -522,7 +521,8 @@ class RecipientFieldView @JvmOverloads constructor( } fun initRecipientField( - autoComplete: RecyclerView, callBackRecipientField: CallBackRecipientField + autoComplete: RecyclerView, + callBackRecipientField: CallBackRecipientField ) { val margin = context.resources.getDimensionPixelSize(R.dimen.dividerHorizontalPadding) @@ -631,7 +631,8 @@ class RecipientFieldView @JvmOverloads constructor( iconTint = R.color.encryptionIconColor, ) } - encryptionStatus == EncryptionStatus.PartiallyEncrypted || encryptionStatus == EncryptionStatus.Loading -> ChipStyle( + encryptionStatus == EncryptionStatus.PartiallyEncrypted || + encryptionStatus == EncryptionStatus.Loading -> ChipStyle( backgroundColor = R.color.encryptionBackgroundColor, textColor = R.color.encryptionTextColor, icon = R.drawable.ic_lock_open_filled_pastille, From 3fa0dfae8fedb8f7e4c92bc6e9f22a8b8c0d52db Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Thu, 16 Apr 2026 12:43:32 +0200 Subject: [PATCH 6/9] fix: Resolve bug during email address duplication or when exceeding maximum limit --- .../mail/ui/newMessage/ContactChipAdapter.kt | 10 +- .../NewMessageRecipientFieldsManager.kt | 2 +- .../mail/ui/newMessage/RecipientFieldView.kt | 126 ++++++++++++------ app/src/main/res/values-da/strings.xml | 7 +- app/src/main/res/values-de/strings.xml | 7 +- app/src/main/res/values-el/strings.xml | 7 +- app/src/main/res/values-es/strings.xml | 7 +- app/src/main/res/values-fi/strings.xml | 7 +- app/src/main/res/values-fr/strings.xml | 7 +- app/src/main/res/values-it/strings.xml | 7 +- app/src/main/res/values-nb/strings.xml | 7 +- app/src/main/res/values-nl/strings.xml | 7 +- app/src/main/res/values-pl/strings.xml | 11 +- app/src/main/res/values-pt/strings.xml | 7 +- app/src/main/res/values-sv/strings.xml | 7 +- app/src/main/res/values/strings.xml | 7 +- 16 files changed, 145 insertions(+), 88 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/ContactChipAdapter.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/ContactChipAdapter.kt index ad7baf72228..e56ef96b5d6 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/ContactChipAdapter.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/ContactChipAdapter.kt @@ -76,14 +76,8 @@ class ContactChipAdapter( fun addChips(newRecipients: List): Int { var added = 0 - newRecipients.forEach { recipient -> - if (recipients.add(recipient)) { - added++ - } - } - if (added > 0) { - notifyItemRangeInserted(itemCount - added, added) - } + newRecipients.forEach { recipient -> if (recipients.add(recipient)) added++ } + if (added > 0) notifyItemRangeInserted(itemCount - added, added) return added } diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageRecipientFieldsManager.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageRecipientFieldsManager.kt index 90599ed78f5..724822e0596 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageRecipientFieldsManager.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageRecipientFieldsManager.kt @@ -1,3 +1,4 @@ + /* * Infomaniak Mail - Android * Copyright (C) 2023-2025 Infomaniak Network SA @@ -105,7 +106,6 @@ class NewMessageRecipientFieldsManager @Inject constructor(private val snackbarM getMergedContactFromContactGroupCallback = newMessageViewModel::getMergedContactFromContactGroup, getMergedContactFromAddressBookCallback = newMessageViewModel::getMergedContactFromAddressBook, getMergedContactFromEmailCallback = newMessageViewModel::getMergedContactFromEmail - ) ) } diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt index 7d6f5fb641f..c03bccbd104 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt @@ -170,8 +170,6 @@ class RecipientFieldView @JvmOverloads constructor( getAddressBookWithGroup = { getAddressBookWithGroup?.invoke(it) }, ) - - contactChipAdapter = ContactChipAdapter( openContextMenu = ::showContactContextMenu, onBackspace = { recipient -> removeRecipient(recipient) @@ -402,14 +400,11 @@ class RecipientFieldView @JvmOverloads constructor( } if (contactChipAdapter.itemCount > MAX_ALLOWED_RECIPIENT) { - snackbarManager.setValue(context.resources.getQuantityString(R.plurals.tooManyRecipients, 1)) + snackbarManager.setValue(context.getString(R.string.tooManyRecipients)) return } - if (contactChipAdapter.isEmpty()) { - expand() - binding.chipsRecyclerView.isVisible = true - } + updateChipsVisibility() val recipientIsNew = contactAdapter.addUsedContact(email) if (recipientIsNew) { @@ -423,46 +418,99 @@ class RecipientFieldView @JvmOverloads constructor( private fun addMultipleRecipients(recipients: List>) { if (recipients.isEmpty()) return - if (contactChipAdapter.itemCount + recipients.size > MAX_ALLOWED_RECIPIENT) { - snackbarManager.setValue(context.resources.getQuantityString(R.plurals.tooManyRecipients, recipients.size)) + val availableSlots = MAX_ALLOWED_RECIPIENT - contactChipAdapter.itemCount + val result = processRecipients(recipients, availableSlots) + + showWarningSnackbars( + initialRecipientsSize = recipients.size, + initialAvailableSlots = availableSlots, + duplicateCount = result.duplicateCount, + outOfSpaceCount = result.outOfSpaceCount + ) + + updateChipsVisibility() + + contactChipAdapter.addChips(result.acceptedRecipients) + result.acceptedRecipients.forEach { onContactAdded?.invoke(it) } + + clearField() + } + + private fun processRecipients( + recipients: List>, + initialAvailableSlots: Int + ): ProcessedRecipientsResult { + var availableSlots = initialAvailableSlots + var duplicateCount = 0 + var outOfSpaceCount = 0 + + val acceptedRecipients = buildList { + for ((name, email) in recipients) { + if (availableSlots <= 0) { + outOfSpaceCount++ + continue + } + + if (!contactAdapter.addUsedContact(email)) { + duplicateCount++ + continue + } + + availableSlots-- + add(Recipient().initLocalValues(email, name)) + } + } + + return ProcessedRecipientsResult(acceptedRecipients, duplicateCount, outOfSpaceCount) + } + + private fun showWarningSnackbars( + initialRecipientsSize: Int, + initialAvailableSlots: Int, + duplicateCount: Int, + outOfSpaceCount: Int + ) { + if (initialAvailableSlots == 0) { + snackbarManager.setValue( + context.resources.getQuantityString( + R.plurals.tooManyRecipientsPaste, + initialRecipientsSize, + initialRecipientsSize + ) + ) return } - val newRecipients = recipients.mapNotNull { (name, email) -> - if (contactAdapter.addUsedContact(email)) { - Recipient().initLocalValues(email, name) - } else { - null - } + if (outOfSpaceCount > 0) { + snackbarManager.setValue( + context.resources.getQuantityString( + R.plurals.tooManyRecipientsPaste, + outOfSpaceCount, + outOfSpaceCount + ) + ) + return } - val nbDuplicateRecipient = recipients.size - newRecipients.size - if (nbDuplicateRecipient > 0) { + if (duplicateCount > 0) { snackbarManager.setValue( context.resources.getQuantityString( R.plurals.addMultipleDuplicateEmails, - nbDuplicateRecipient, - nbDuplicateRecipient + duplicateCount, + duplicateCount ) ) - - if (nbDuplicateRecipient == recipients.size) { - return - } + return } + } + private fun updateChipsVisibility() { if (contactChipAdapter.isEmpty()) { expand() binding.chipsRecyclerView.isVisible = true } - - contactChipAdapter.addChips(newRecipients) - newRecipients.forEach { onContactAdded?.invoke(it) } - - clearField() } - fun getContactName(email: String): String { return getMergedContactFromEmail?.invoke(email)?.name ?: email } @@ -485,19 +533,15 @@ class RecipientFieldView @JvmOverloads constructor( getContactName(email) to email } - val totalAfterAdd = contactChipAdapter.itemCount + recipientsToAdd.size - - - if (totalAfterAdd > MAX_ALLOWED_RECIPIENT) { - snackbarManager.setValue(context.resources.getQuantityString(R.plurals.tooManyRecipients, totalAfterAdd)) - return - } - addMultipleRecipients(recipientsToAdd) if (invalidEmails.isNotEmpty()) { snackbarManager.setValue( - context.resources.getQuantityString(R.plurals.addMultipleInvalidEmails, invalidEmails.size, invalidEmails.size) + context.resources.getQuantityString( + R.plurals.addMultipleInvalidEmails, + invalidEmails.size, + invalidEmails.size + ) ) } } @@ -649,6 +693,12 @@ class RecipientFieldView @JvmOverloads constructor( }.applyTo(this) } + private data class ProcessedRecipientsResult( + val acceptedRecipients: List, + val duplicateCount: Int, + val outOfSpaceCount: Int + ) + private data class ChipStyle( val backgroundColor: Int, val textColor: Int, diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 67290e8dceb..945560473c2 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -668,9 +668,10 @@ Til: I morgen tidlig - - Du kan ikke tilføje denne adresse, fordi du har nået grænsen for modtagere - Du kan ikke tilføje disse adresser, fordi du har nået grænsen for modtagere + Du kan ikke tilføje denne adresse, fordi du har nået grænsen for modtagere + + %d adresse kunne ikke tilføjes, fordi du har nået grænsen for modtagere + %d adresser kunne ikke tilføjes, fordi du har nået grænsen for modtagere Papirkurv Fjern blokering diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 651bf027c35..29d34f4a9e2 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -668,9 +668,10 @@ An: Morgen früh - - Sie können diese Adresse nicht hinzufügen, da Sie die Höchstzahl an Empfängern erreicht haben - Sie können diese Adressen nicht hinzufügen, da Sie die Höchstzahl an Empfängern erreicht haben + Sie können diese Adresse nicht hinzufügen, da Sie die Höchstzahl an Empfängern erreicht haben + + %d Adresse konnte nicht hinzugefügt werden, da Sie das Empfängerlimit erreicht haben + %d Adressen konnten nicht hinzugefügt werden, da Sie das Empfängerlimit erreicht haben Papierkorb Entsperren diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index fc13747ddd9..10f19596fe6 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -668,9 +668,10 @@ Προς: Αύριο το πρωί - - Δεν μπορείτε να προσθέσετε αυτή τη διεύθυνση γιατί έχετε φτάσει το όριο παραληπτών - Δεν μπορείτε να προσθέσετε αυτές τις διευθύνσεις γιατί έχετε φτάσει το όριο παραληπτών + Δεν μπορείτε να προσθέσετε αυτή τη διεύθυνση γιατί έχετε φτάσει το όριο παραληπτών + + %d διεύθυνση δεν μπόρεσε να προστεθεί επειδή έχετε φτάσει στο όριο των παραληπτών + %d διευθύνσεις δεν μπόρεσαν να προστεθούν επειδή έχετε φτάσει στο όριο των παραληπτών Κάδος απορριμμάτων Ξεμπλοκάρισμα diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 35fb4b6e42e..4aebd348f4e 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -668,9 +668,10 @@ Para: Mañana por la mañana - - No puede añadir esta dirección porque ha alcanzado el límite de destinatarios - No puede añadir estas direcciones porque ha alcanzado el límite de destinatarios + No puede añadir esta dirección porque ha alcanzado el límite de destinatarios + + %d dirección no se ha podido añadir porque has alcanzado el límite de destinatarios + %d direcciones no se han podido añadir porque has alcanzado el límite de destinatarios Papelera Desbloquear diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index af4f3d460b2..d6253b35e30 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -668,9 +668,10 @@ Vastaanottaja: Huomenna aamulla - - Et voi lisätä tätä osoitetta, koska olet saavuttanut vastaanottajien rajan - Et voi lisätä näitä osoitteita, koska olet saavuttanut vastaanottajien rajan + Et voi lisätä tätä osoitetta, koska olet saavuttanut vastaanottajien rajan + + %d osoite ei voitu lisätä, koska olet saavuttanut vastaanottajien enimmäismäärän + %d osoitetta ei voitu lisätä, koska olet saavuttanut vastaanottajien enimmäismäärän Roskakori Poista esto diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 9ee9fab6023..0ecd30ffa5e 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -668,9 +668,10 @@ À : Demain matin - - Vous ne pouvez pas ajouter cette adresse car vous avez atteint la limite de destinataires - Vous ne pouvez pas ajouter ces adresses car vous avez atteint la limite de destinataires + Vous ne pouvez pas ajouter cette adresse car vous avez atteint la limite de destinataires + + %d adresse n’a pas pu être ajoutée car vous avez atteint la limite de destinataires + %d adresses n’ont pas pu être ajoutées car vous avez atteint la limite de destinataires. Corbeille Débloquer diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 8e4055f7fd7..79bb851c340 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -668,9 +668,10 @@ A: Domani mattina - - Non è possibile aggiungere questo indirizzo perché è stato raggiunto il limite di destinatari - Non è possibile aggiungere questi indirizzi perché è stato raggiunto il limite di destinatari + Non è possibile aggiungere questo indirizzo perché è stato raggiunto il limite di destinatari + + %d indirizzo non ha potuto essere aggiunto perché hai raggiunto il limite dei destinatari + %d indirizzi non hanno potuto essere aggiunti perché hai raggiunto il limite dei destinatari Cestino Sbloccare diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index c539f106ca9..5d8dd58e63b 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -668,9 +668,10 @@ Til: I morgen tidlig - - Du kan ikke legge til denne adressen fordi du har nådd grensen for mottakere - Du kan ikke legge til disse adressene fordi du har nådd grensen for mottakere + Du kan ikke legge til denne adressen fordi du har nådd grensen for mottakere + + %d adresse kunne ikke legges til fordi du har nått grensen for mottakere + %d adresser kunne ikke legges til fordi du har nått grensen for mottakere Papirkurv Opphev blokkering diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 599eba7bde9..334bd7f9abd 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -668,9 +668,10 @@ Aan: Morgenochtend - - U kunt dit adres niet toevoegen omdat u de limiet van ontvangers heeft bereikt - U kunt deze adressen niet toevoegen omdat u de limiet van ontvangers heeft bereikt + U kunt dit adres niet toevoegen omdat u de limiet van ontvangers heeft bereikt + + %d adres kon niet worden toegevoegd omdat u de limiet voor ontvangers heeft bereikt + %d adressen konden niet worden toegevoegd omdat u de limiet voor ontvangers heeft bereikt Prullenbak Deblokkeren diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 78889cbfdba..ca2c9269248 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -716,11 +716,12 @@ Do: Jutro rano - - Nie możesz dodać tego adresu, ponieważ osiągnąłeś/aś limit odbiorców - Nie możesz dodać tych adresów, ponieważ osiągnąłeś limit odbiorców - Nie możesz dodać tych adresów, ponieważ osiągnąłeś limit odbiorców - Nie możesz dodać tych adresów, ponieważ osiągnąłeś limit odbiorców + Nie możesz dodać tego adresu, ponieważ osiągnąłeś/aś limit odbiorców + + %d adres nie mógł zostać dodany, ponieważ osiągnięto limit odbiorców + %d adresy nie mogły zostać dodane, ponieważ osiągnięto limit odbiorców + %d adresów nie mogło zostać dodanych, ponieważ osiągnięto limit odbiorców + %d adresów nie mogło zostać dodanych, ponieważ osiągnięto limit odbiorców Kosz Odblokuj diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 1ae8e640c97..311227a0208 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -668,9 +668,10 @@ Para: Amanhã de manhã - - Não pode adicionar este endereço pois atingiu o limite de destinatários - Não pode adicionar estes endereços pois atingiu o limite de destinatários + Não pode adicionar este endereço pois atingiu o limite de destinatários + + %d endereço não pôde ser adicionado porque atingiu o limite de destinatários + %d endereços não puderam ser adicionados porque atingiu o limite de destinatários Lixo Desbloquear diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 80898114661..b6338ee6f20 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -668,9 +668,10 @@ Till: I morgon bitti - - Du kan inte lägga till denna adress eftersom du har nått gränsen för mottagare - Du kan inte lägga till dessa adresser eftersom du har nått gränsen för mottagare + Du kan inte lägga till denna adress eftersom du har nått gränsen för mottagare + + %d adress kunde inte läggas till eftersom du har nått gränsen för mottagare + %d adresser kunde inte läggas till eftersom du har nått gränsen för mottagare Papperskorg Avblockera diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 36b70f7919d..8547d3ca530 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -672,9 +672,10 @@ To: Tomorrow morning - - You can’t add this address because you have reached the limit of recipients - You can’t add these addresses because you have reached the limit of recipients + You can’t add this address because you have reached the limit of recipients + + %d address could not be added because you have reached the recipient limit + %d addresses could not be added because you have reached the recipient limit Trash Unblock From 505850bd16da634d90c981cf8e1cabd1a6b4d5ee Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Tue, 21 Apr 2026 08:49:15 +0200 Subject: [PATCH 7/9] fix: Correct strings --- app/src/main/res/values-de/strings.xml | 4 ++-- app/src/main/res/values-fr/strings.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 29d34f4a9e2..d76eb506909 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -53,8 +53,8 @@ %d E-Mails wurden bereits hinzugefügt - %d E-Mails sind ungültig - %d E-Mail ist ungültig + %d E-Mail ist ungültig + %d E-Mails sind ungültig Die E-Mail wird bereits verwendet Die E-Mail ist ungültig diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 0ecd30ffa5e..9ae0577728e 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -671,7 +671,7 @@ Vous ne pouvez pas ajouter cette adresse car vous avez atteint la limite de destinataires %d adresse n’a pas pu être ajoutée car vous avez atteint la limite de destinataires - %d adresses n’ont pas pu être ajoutées car vous avez atteint la limite de destinataires. + %d adresses n’ont pas pu être ajoutées car vous avez atteint la limite de destinataires Corbeille Débloquer From 22bb36e114c228c6b7ab7da47708d1653c2b7882 Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Tue, 21 Apr 2026 08:59:31 +0200 Subject: [PATCH 8/9] fix: Resolve critical edge cases for maximum recipient limit --- .../mail/ui/newMessage/NewMessageRecipientFieldsManager.kt | 1 - .../com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageRecipientFieldsManager.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageRecipientFieldsManager.kt index 724822e0596..95f298f04c0 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageRecipientFieldsManager.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageRecipientFieldsManager.kt @@ -1,4 +1,3 @@ - /* * Infomaniak Mail - Android * Copyright (C) 2023-2025 Infomaniak Network SA diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt index c03bccbd104..9656b675b5a 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt @@ -399,7 +399,7 @@ class RecipientFieldView @JvmOverloads constructor( return } - if (contactChipAdapter.itemCount > MAX_ALLOWED_RECIPIENT) { + if (contactChipAdapter.itemCount >= MAX_ALLOWED_RECIPIENT) { snackbarManager.setValue(context.getString(R.string.tooManyRecipients)) return } @@ -418,7 +418,7 @@ class RecipientFieldView @JvmOverloads constructor( private fun addMultipleRecipients(recipients: List>) { if (recipients.isEmpty()) return - val availableSlots = MAX_ALLOWED_RECIPIENT - contactChipAdapter.itemCount + val availableSlots = (MAX_ALLOWED_RECIPIENT - contactChipAdapter.itemCount).coerceAtLeast(0) val result = processRecipients(recipients, availableSlots) showWarningSnackbars( From 9bfa10d5297d0fff50f359554e7fc235706be35d Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Fri, 24 Apr 2026 15:35:30 +0200 Subject: [PATCH 9/9] refactor: Clean code --- .../mail/ui/newMessage/BackspaceAwareTextInput.kt | 8 ++++---- .../infomaniak/mail/ui/newMessage/RecipientFieldView.kt | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/BackspaceAwareTextInput.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/BackspaceAwareTextInput.kt index 276bdbc64a8..09ff472159c 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/BackspaceAwareTextInput.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/BackspaceAwareTextInput.kt @@ -21,6 +21,7 @@ import android.content.ClipboardManager import android.content.Context import android.util.AttributeSet import android.view.KeyEvent +import android.R as Randroid import com.google.android.material.textfield.TextInputEditText class BackspaceAwareTextInput @JvmOverloads constructor( @@ -37,17 +38,16 @@ class BackspaceAwareTextInput @JvmOverloads constructor( } override fun onTextContextMenuItem(id: Int): Boolean { - if (id == android.R.id.paste) { + if (id == Randroid.id.paste) { val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager val clip = clipboard.primaryClip if (clip != null && clip.itemCount > 0) { val pastedText = clip.getItemAt(0).text?.toString() ?: "" - if (onPasteIntercept?.invoke(pastedText) == true) { - return true - } + if (onPasteIntercept?.invoke(pastedText) == true) return true } } + return super.onTextContextMenuItem(id) } diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt index 9656b675b5a..c1be9775912 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt @@ -171,7 +171,8 @@ class RecipientFieldView @JvmOverloads constructor( ) contactChipAdapter = ContactChipAdapter( - openContextMenu = ::showContactContextMenu, onBackspace = { recipient -> + openContextMenu = ::showContactContextMenu, + onBackspace = { recipient -> removeRecipient(recipient) focusTextField() })