From bd603a14c16cb20ae959e948e521323e6c4c6403 Mon Sep 17 00:00:00 2001 From: Vincent TE Date: Tue, 17 Sep 2024 11:28:05 +0200 Subject: [PATCH 1/2] Add Dialog to confirm we want to block a user --- .../com/infomaniak/mail/ui/MainViewModel.kt | 9 ++- .../mail/ui/main/thread/ThreadFragment.kt | 23 ++++-- .../actions/ConfirmationToBlockUserDialog.kt | 70 +++++++++++++++++++ .../thread/actions/JunkBottomSheetDialog.kt | 27 +++++-- .../actions/UserToBlockBottomSheetDialog.kt | 14 +++- .../dialog_confirmation_to_block_user.xml | 41 +++++++++++ app/src/main/res/values-de/strings.xml | 2 + app/src/main/res/values-es/strings.xml | 2 + app/src/main/res/values-fr/strings.xml | 2 + app/src/main/res/values-it/strings.xml | 4 +- app/src/main/res/values/strings.xml | 2 + 11 files changed, 181 insertions(+), 15 deletions(-) create mode 100644 app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/ConfirmationToBlockUserDialog.kt create mode 100644 app/src/main/res/layout/dialog_confirmation_to_block_user.xml diff --git a/app/src/main/java/com/infomaniak/mail/ui/MainViewModel.kt b/app/src/main/java/com/infomaniak/mail/ui/MainViewModel.kt index 0cd349df30..72b204ae0b 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/MainViewModel.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/MainViewModel.kt @@ -119,6 +119,7 @@ class MainViewModel @Inject constructor( val reportPhishingTrigger = SingleLiveEvent() val reportDisplayProblemTrigger = SingleLiveEvent() val canInstallUpdate = MutableLiveData(false) + val messageOfUserToBlock = SingleLiveEvent() val autoAdvanceThreadsUids = MutableLiveData>() @@ -1062,8 +1063,14 @@ class MainViewModel @Inject constructor( emit(hasOtherExpeditors) } + fun hasMoreThanOneExpeditors(threadUid: String) = liveData(ioCoroutineContext) { + val hasMoreThanOneExpeditors = + (threadController.getThread(threadUid)?.messages?.flatMap { it.from }?.filter { it.isMe() }?.size ?: 0) > 1 + emit(hasMoreThanOneExpeditors) + } + fun getMessagesFromUniqueExpeditors(threadUid: String) = liveData(ioCoroutineContext) { - val messageToRecipient = threadController.getThread(threadUid)?.messages?.flatMap { message -> + val messageToRecipient = threadController.getThread(threadUid)?.messages?.distinctBy { it.from }?.flatMap { message -> message.from.filterNot { it.isMe() } .distinct() .map { from -> message to from } diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/ThreadFragment.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/ThreadFragment.kt index 8f1d754da1..90fd1f89f2 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/thread/ThreadFragment.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/ThreadFragment.kt @@ -46,6 +46,7 @@ import com.infomaniak.mail.MatomoMail.ACTION_REPLY_NAME import com.infomaniak.mail.MatomoMail.OPEN_ACTION_BOTTOM_SHEET import com.infomaniak.mail.MatomoMail.OPEN_FROM_DRAFT_NAME import com.infomaniak.mail.MatomoMail.trackAttachmentActionsEvent +import com.infomaniak.mail.MatomoMail.trackBottomSheetThreadActionsEvent import com.infomaniak.mail.MatomoMail.trackMessageActionsEvent import com.infomaniak.mail.MatomoMail.trackNewMessageEvent import com.infomaniak.mail.MatomoMail.trackThreadActionsEvent @@ -71,10 +72,7 @@ import com.infomaniak.mail.ui.main.folder.TwoPaneViewModel.NavData import com.infomaniak.mail.ui.main.thread.SubjectFormatter.SubjectData import com.infomaniak.mail.ui.main.thread.ThreadAdapter.ContextMenuType import com.infomaniak.mail.ui.main.thread.ThreadAdapter.ThreadAdapterCallbacks -import com.infomaniak.mail.ui.main.thread.actions.AttachmentActionsBottomSheetDialogArgs -import com.infomaniak.mail.ui.main.thread.actions.MessageActionsBottomSheetDialogArgs -import com.infomaniak.mail.ui.main.thread.actions.ReplyBottomSheetDialogArgs -import com.infomaniak.mail.ui.main.thread.actions.ThreadActionsBottomSheetDialogArgs +import com.infomaniak.mail.ui.main.thread.actions.* import com.infomaniak.mail.ui.main.thread.calendar.AttendeesBottomSheetDialogArgs import com.infomaniak.mail.utils.PermissionUtils import com.infomaniak.mail.utils.UiUtils @@ -111,6 +109,9 @@ class ThreadFragment : Fragment() { @Inject lateinit var phoneContextualMenuAlertDialog: PhoneContextualMenuAlertDialog + @Inject + lateinit var confirmationToBlockUserDialog: ConfirmationToBlockUserDialog + @Inject lateinit var permissionUtils: PermissionUtils @@ -155,12 +156,26 @@ class ThreadFragment : Fragment() { observeAutoAdvance() observeReportDisplayProblemResult() + + observeMessageOfUserToBlock() } private fun observeReportDisplayProblemResult() { mainViewModel.reportDisplayProblemTrigger.observe(viewLifecycleOwner) { descriptionDialog.resetLoadingAndDismiss() } } + private fun observeMessageOfUserToBlock() = with(confirmationToBlockUserDialog) { + mainViewModel.messageOfUserToBlock.observe(viewLifecycleOwner) { + setPositiveButtonCallback { messageOfUserToBlock -> + messageOfUserToBlock?.let { + trackBottomSheetThreadActionsEvent("blockUser") + mainViewModel.blockUser(messageOfUserToBlock) + } + } + show(it) + } + } + override fun onConfigurationChanged(newConfig: Configuration) { threadAdapter.reRenderMails() super.onConfigurationChanged(newConfig) diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/ConfirmationToBlockUserDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/ConfirmationToBlockUserDialog.kt new file mode 100644 index 0000000000..6caadf4eaa --- /dev/null +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/ConfirmationToBlockUserDialog.kt @@ -0,0 +1,70 @@ +/* + * Infomaniak Mail - Android + * Copyright (C) 2024 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.infomaniak.mail.ui.main.thread.actions + +import android.content.Context +import androidx.appcompat.app.AlertDialog +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import com.infomaniak.lib.core.utils.context +import com.infomaniak.mail.R +import com.infomaniak.mail.data.models.message.Message +import com.infomaniak.mail.databinding.DialogConfirmationToBlockUserBinding +import com.infomaniak.mail.ui.alertDialogs.BaseAlertDialog +import dagger.hilt.android.qualifiers.ActivityContext +import dagger.hilt.android.scopes.ActivityScoped +import javax.inject.Inject + +@ActivityScoped +class ConfirmationToBlockUserDialog @Inject constructor( + @ActivityContext private val activityContext: Context, +) : BaseAlertDialog(activityContext) { + + private val binding: DialogConfirmationToBlockUserBinding by lazy { + DialogConfirmationToBlockUserBinding.inflate(activity.layoutInflater) + } + + private var onPositiveButtonClick: ((Message?) -> Unit)? = null + private var messageOfUserToBlock: Message? = null + + override val alertDialog: AlertDialog = with(binding) { + MaterialAlertDialogBuilder(context) + .setView(root) + .setPositiveButton(R.string.buttonConfirm) { _, _ -> + onPositiveButtonClick?.invoke(messageOfUserToBlock) + } + .setNegativeButton(com.infomaniak.lib.core.R.string.buttonCancel, null) + .create() + } + + override fun resetCallbacks() { + onPositiveButtonClick = null + } + + fun show(message: Message) = with(binding) { + messageOfUserToBlock = message + val recipient = message.from[0] + val title = recipient.name.ifBlank { recipient.email } + blockExpeditorTitle.text = activityContext.getString(R.string.blockExpeditorTitle, title) + blockExpeditorDescription.text = activityContext.getString(R.string.confirmationToBlockAnExpeditorText, recipient.email) + alertDialog.show() + } + + fun setPositiveButtonCallback(onPositiveButtonClick: (Message?) -> Unit) { + this.onPositiveButtonClick = onPositiveButtonClick + } +} diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/JunkBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/JunkBottomSheetDialog.kt index 966ba14cee..ada128027b 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/JunkBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/JunkBottomSheetDialog.kt @@ -43,6 +43,9 @@ class JunkBottomSheetDialog : ActionsBottomSheetDialog() { private var binding: BottomSheetJunkBinding by safeBinding() private val navigationArgs: JunkBottomSheetDialogArgs by navArgs() + + private var messageOfUserToBlock: Message? = null + override val mainViewModel: MainViewModel by activityViewModels() @Inject @@ -56,6 +59,7 @@ class JunkBottomSheetDialog : ActionsBottomSheetDialog() { super.onViewCreated(view, savedInstanceState) mainViewModel.getMessage(messageUid).observe(viewLifecycleOwner) { message -> + this@JunkBottomSheetDialog.messageOfUserToBlock = message handleButtons(threadUid, message) } @@ -70,24 +74,35 @@ class JunkBottomSheetDialog : ActionsBottomSheetDialog() { } } - private fun observeExpeditorsResult(threadUid: String) = with(binding) { - mainViewModel.hasOtherExpeditors(threadUid).observe(viewLifecycleOwner) { hasOtherExpeditors -> - if (hasOtherExpeditors) { - blockSender.setClosingOnClickListener { + private fun observeHasMoreThanOneExpeditor(threadUid: String) { + mainViewModel.hasMoreThanOneExpeditors(threadUid).observe(viewLifecycleOwner) { hasMoreThanOneExpeditor -> + binding.blockSender.setClosingOnClickListener { + if (hasMoreThanOneExpeditor) { safeNavigate( resId = R.id.userToBlockBottomSheetDialog, args = UserToBlockBottomSheetDialogArgs(threadUid).toBundle(), currentClassName = JunkBottomSheetDialog::class.java.name, ) + } else { + messageOfUserToBlock?.let { + mainViewModel.messageOfUserToBlock.value = messageOfUserToBlock + } } + } + } + } + + private fun observeExpeditorsResult(threadUid: String) { + mainViewModel.hasOtherExpeditors(threadUid).observe(viewLifecycleOwner) { hasOtherExpeditors -> + if (hasOtherExpeditors) { + observeHasMoreThanOneExpeditor(threadUid) } else { - blockSender.isGone = true + binding.blockSender.isGone = true } } } private fun handleButtons(threadUid: String, message: Message) = with(binding) { - spam.setClosingOnClickListener { trackBottomSheetThreadActionsEvent(ACTION_SPAM_NAME, value = message.folder.role == FolderRole.SPAM) mainViewModel.toggleThreadSpamStatus(threadUid) diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/UserToBlockBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/UserToBlockBottomSheetDialog.kt index 7aab797b43..ec4c00ea70 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/UserToBlockBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/UserToBlockBottomSheetDialog.kt @@ -17,6 +17,7 @@ */ package com.infomaniak.mail.ui.main.thread.actions +import android.content.DialogInterface import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -24,7 +25,7 @@ import android.view.ViewGroup import androidx.fragment.app.activityViewModels import androidx.navigation.fragment.navArgs import com.infomaniak.lib.core.utils.safeBinding -import com.infomaniak.mail.MatomoMail.trackBottomSheetThreadActionsEvent +import com.infomaniak.mail.data.models.message.Message import com.infomaniak.mail.databinding.BottomSheetUserToBlockBinding import com.infomaniak.mail.ui.MainViewModel @@ -32,6 +33,9 @@ class UserToBlockBottomSheetDialog : ActionsBottomSheetDialog() { private var binding: BottomSheetUserToBlockBinding by safeBinding() private val navigationArgs: UserToBlockBottomSheetDialogArgs by navArgs() + + private var messageOfUserToBlock: Message? = null + override val mainViewModel: MainViewModel by activityViewModels() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { @@ -43,11 +47,15 @@ class UserToBlockBottomSheetDialog : ActionsBottomSheetDialog() { mainViewModel.getMessagesFromUniqueExpeditors(threadUid).observe(viewLifecycleOwner) { messages -> messages?.let { binding.recipients.adapter = UserToBlockAdapter(messages) { message -> - trackBottomSheetThreadActionsEvent("blockUser") - mainViewModel.blockUser(message) + messageOfUserToBlock = message dismiss() } } } } + + override fun onDismiss(dialog: DialogInterface) { + super.onDismiss(dialog) + messageOfUserToBlock?.let { mainViewModel.messageOfUserToBlock.value = it } + } } diff --git a/app/src/main/res/layout/dialog_confirmation_to_block_user.xml b/app/src/main/res/layout/dialog_confirmation_to_block_user.xml new file mode 100644 index 0000000000..d6b9ea2818 --- /dev/null +++ b/app/src/main/res/layout/dialog_confirmation_to_block_user.xml @@ -0,0 +1,41 @@ + + + + + + + + diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 49fb9f55ba..d5df6eeaaf 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -106,6 +106,7 @@ Liste der Teilnehmer (%d) Bcc: Einen Absender blockieren + Block %s Passwort blockiert Blockierte Passwörter @@ -176,6 +177,7 @@ Werbeaktionen Sind Sie sicher, dass Sie sich von %s abmelden möchten? Abmelden + Diese E-Mail und alle zukünftigen Nachrichten von %s werden in den Junk-Mail-Ordner verschoben. Zu Kontakten hinzufügen E-Mail Adresse kopieren Schreiben Sie eine E-Mail diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 9c5ad64f7d..8d0803d560 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -106,6 +106,7 @@ Lista de asistentes (%d) CCO: Bloquear un remitente + Bloquear %s Contraseña bloqueada Contraseñas bloqueadas @@ -176,6 +177,7 @@ Promociones ¿Seguro que quieres desconectarte de %s? Cerrar sesión + Este correo electrónico y todos los futuros mensajes de %s se moverán a la carpeta de correo no deseado. Añadir a contactos Copiar dirección de correo electrónico Escriba un correo electrónico diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 3e6ad6091e..6b85709c29 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -107,6 +107,7 @@ Liste des participants (%d) Cci : Bloquer un expéditeur + Bloquer %s Mot de passe bloqué Mots de passe bloqués @@ -178,6 +179,7 @@ Promotions Êtes-vous sûr de vouloir vous déconnecter du compte %s ? Me déconnecter + Cet e-mail et tous les futurs messages de %s seront déplacés dans le dossier Courrier indésirable. Ajouter aux contacts Copier l’adresse mail Écrire un e-mail diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 5f9172ffad..0a6aff2bf3 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -105,7 +105,8 @@ Elenco dei partecipanti (%d) Bcc: - Bloccare un mittente + Blocca un mittente + Blocca %s Password bloccata Password bloccate @@ -176,6 +177,7 @@ Promozioni Sei sicuro di volerti disconnettere da %s? Disconnettersi + Questa e-mail e tutti i futuri messaggi di %s saranno spostati nella cartella della posta indesiderata. Aggiungi ai contatti Copia l’indirizzo e-mail Scrivi un’e-mail diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c59d3faa89..f69fcd2867 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -112,6 +112,7 @@ List of attendees (%d) Bcc: Block a sender + Block %s Blocked password Blocked passwords @@ -182,6 +183,7 @@ Promotions Are you sure you want to log out from %s? Log out + This email and all future messages from %s will be moved to the Junk Mail folder. Add to contacts Copy email address Write an email From 9850cf325ab04ec1f3290000e9a74a183545b375 Mon Sep 17 00:00:00 2001 From: Vincent TE Date: Mon, 23 Sep 2024 13:58:12 +0200 Subject: [PATCH 2/2] Code review --- app/src/main/java/com/infomaniak/mail/ui/MainViewModel.kt | 6 +++--- .../ui/main/thread/actions/ConfirmationToBlockUserDialog.kt | 3 ++- .../mail/ui/main/thread/actions/JunkBottomSheetDialog.kt | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/ui/MainViewModel.kt b/app/src/main/java/com/infomaniak/mail/ui/MainViewModel.kt index 72b204ae0b..83ee47bafa 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/MainViewModel.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/MainViewModel.kt @@ -1063,10 +1063,10 @@ class MainViewModel @Inject constructor( emit(hasOtherExpeditors) } - fun hasMoreThanOneExpeditors(threadUid: String) = liveData(ioCoroutineContext) { - val hasMoreThanOneExpeditors = + fun hasMoreThanOneExpeditor(threadUid: String) = liveData(ioCoroutineContext) { + val hasMoreThanOneExpeditor = (threadController.getThread(threadUid)?.messages?.flatMap { it.from }?.filter { it.isMe() }?.size ?: 0) > 1 - emit(hasMoreThanOneExpeditors) + emit(hasMoreThanOneExpeditor) } fun getMessagesFromUniqueExpeditors(threadUid: String) = liveData(ioCoroutineContext) { diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/ConfirmationToBlockUserDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/ConfirmationToBlockUserDialog.kt index 6caadf4eaa..9618ce285d 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/ConfirmationToBlockUserDialog.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/ConfirmationToBlockUserDialog.kt @@ -28,6 +28,7 @@ import com.infomaniak.mail.ui.alertDialogs.BaseAlertDialog import dagger.hilt.android.qualifiers.ActivityContext import dagger.hilt.android.scopes.ActivityScoped import javax.inject.Inject +import com.infomaniak.lib.core.R as RCore @ActivityScoped class ConfirmationToBlockUserDialog @Inject constructor( @@ -47,7 +48,7 @@ class ConfirmationToBlockUserDialog @Inject constructor( .setPositiveButton(R.string.buttonConfirm) { _, _ -> onPositiveButtonClick?.invoke(messageOfUserToBlock) } - .setNegativeButton(com.infomaniak.lib.core.R.string.buttonCancel, null) + .setNegativeButton(RCore.string.buttonCancel, null) .create() } diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/JunkBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/JunkBottomSheetDialog.kt index ada128027b..db860bc8b8 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/JunkBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/JunkBottomSheetDialog.kt @@ -75,7 +75,7 @@ class JunkBottomSheetDialog : ActionsBottomSheetDialog() { } private fun observeHasMoreThanOneExpeditor(threadUid: String) { - mainViewModel.hasMoreThanOneExpeditors(threadUid).observe(viewLifecycleOwner) { hasMoreThanOneExpeditor -> + mainViewModel.hasMoreThanOneExpeditor(threadUid).observe(viewLifecycleOwner) { hasMoreThanOneExpeditor -> binding.blockSender.setClosingOnClickListener { if (hasMoreThanOneExpeditor) { safeNavigate(