From 97e701386ec04d39ed37c166982c75abce993249 Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Wed, 22 Jul 2026 15:40:04 +0200 Subject: [PATCH 1/4] feat: Add string --- app/src/main/res/values-da/strings.xml | 1 + app/src/main/res/values-de/strings.xml | 1 + app/src/main/res/values-el/strings.xml | 1 + app/src/main/res/values-es/strings.xml | 1 + app/src/main/res/values-fi/strings.xml | 1 + app/src/main/res/values-fr/strings.xml | 1 + app/src/main/res/values-it/strings.xml | 1 + app/src/main/res/values-nb/strings.xml | 1 + app/src/main/res/values-nl/strings.xml | 1 + app/src/main/res/values-pl/strings.xml | 1 + app/src/main/res/values-pt/strings.xml | 1 + app/src/main/res/values-sv/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 13 files changed, 13 insertions(+) diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 731bdfdb9d..3b3c10e1b8 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -521,6 +521,7 @@ Vælg dato Ingen signatur Vælg tidspunkt + Kun mig Modtagere og mig Send Send bekræftelsen diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 67a0771f30..f45b4c4c8f 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -521,6 +521,7 @@ Datum auswählen Keine Unterschrift Zeit auswählen + Nur ich Empfänger und mich Senden Sie Senden Sie die Bestätigung diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 214c8304b3..e53dcfe5a5 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -521,6 +521,7 @@ Επιλέξτε ημερομηνία Χωρίς υπογραφή Επιλέξτε ώρα + Μόνο εγώ Οι παραλήπτες και εγώ Αποστολή Αποστολή επιβεβαίωσης diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index df4a38b65b..3fdf684ba1 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -521,6 +521,7 @@ Seleccione la fecha Sin firma Seleccionar la hora + Solo yo Los destinatarios y yo Enviar Enviar la confirmación diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index efe815aa82..df0b058f28 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -521,6 +521,7 @@ Valitse päivämäärä Ei allekirjoitusta Valitse aika + Vain minä Vastaanottajat ja minä Lähetä Lähetä vahvistus diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index aba89e0c3f..4351327ff3 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -521,6 +521,7 @@ Sélectionner la date Aucune signature Sélectionner l’heure + Moi uniquement Les destinataires et moi Envoyer Envoyer la confirmation diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 4c59c927a1..aeadc32925 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -521,6 +521,7 @@ Selezionare la data Nessuna firma Selezionare l’ora + Solo io I destinatari e io Invia Inviare la conferma diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index c36ea62558..368a6f2562 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -521,6 +521,7 @@ Velg dato Ingen signatur Velg tid + Bare jeg Mottakere og meg Send Send bekreftelsen diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 752b76350e..aadb4d4368 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -521,6 +521,7 @@ Datum selecteren Geen handtekening Tijd selecteren + Alleen ik Ontvangers en mij Verzenden De bevestiging verzenden diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index ab3b944970..c3dfe7a86b 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -551,6 +551,7 @@ Wybierz datę Brak podpisu Wybierz godzinę + Tylko ja Odbiorcy i ja Wyślij Wyślij potwierdzenie diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index c5ebcab300..a65442e675 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -521,6 +521,7 @@ Selecionar data Sem assinatura Selecionar hora + Só eu Os destinatários e eu Enviar Enviar a confirmação diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 1f2c14f8d5..11c6f3d4c8 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -521,6 +521,7 @@ Välj datum Ingen signatur Välj tid + Bara jag Mottagare och mig Skicka Skicka bekräftelsen diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4df26952df..90d40294e0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -525,6 +525,7 @@ Select date No signature Select time + Me only Recipients and I Send Send the confirmation From 7c24bc3b2dae2239b1d37d5a219de988c50ed9b2 Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Wed, 22 Jul 2026 15:48:53 +0200 Subject: [PATCH 2/4] feat: Add visibility reminder dialog --- .../SelectVisibilityReminderDialog.kt | 87 +++++++++++++++++++ .../mail/ui/newMessage/NewMessageFragment.kt | 5 +- .../mail/ui/newMessage/NewMessageViewModel.kt | 6 ++ .../sendOptions/DraftSendOptionsFragment.kt | 35 ++++++++ .../dialog_select_visibility_reminder.xml | 44 ++++++++++ 5 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/com/infomaniak/mail/ui/alertDialogs/SelectVisibilityReminderDialog.kt create mode 100644 app/src/main/res/layout/dialog_select_visibility_reminder.xml diff --git a/app/src/main/java/com/infomaniak/mail/ui/alertDialogs/SelectVisibilityReminderDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/alertDialogs/SelectVisibilityReminderDialog.kt new file mode 100644 index 0000000000..d3b285f410 --- /dev/null +++ b/app/src/main/java/com/infomaniak/mail/ui/alertDialogs/SelectVisibilityReminderDialog.kt @@ -0,0 +1,87 @@ +/* + * Infomaniak Mail - Android + * Copyright (C) 2026 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.alertDialogs + +import android.content.Context +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import com.infomaniak.mail.R +import com.infomaniak.mail.databinding.DialogSelectVisibilityReminderBinding +import dagger.hilt.android.qualifiers.ActivityContext +import dagger.hilt.android.scopes.ActivityScoped +import javax.inject.Inject + +@ActivityScoped +class SelectVisibilityReminderDialog @Inject constructor( + @ActivityContext private val activityContext: Context, +) : BaseAlertDialog(activityContext) { + private val binding: DialogSelectVisibilityReminderBinding by lazy { + DialogSelectVisibilityReminderBinding.inflate(activity.layoutInflater) + } + + override val alertDialog = initDialog() + + private var isRecipientsAndMeSelected: Boolean = true + + private var onVisibilitySelected: ((Boolean) -> Unit)? = null + + private fun initDialog() = with(binding) { + MaterialAlertDialogBuilder(activityContext) + .setTitle(R.string.reminderVisibilityTitle) + .setView(root) + .setPositiveButton(R.string.buttonConfirm, null) + .setNegativeButton(com.infomaniak.core.legacy.R.string.buttonCancel, null) + .create() + } + + fun show( + selectRecipientsAndMe: Boolean = true, + onVisibilitySelected: (Boolean) -> Unit, + ) { + this.onVisibilitySelected = onVisibilitySelected + alertDialog.show() + isRecipientsAndMeSelected = selectRecipientsAndMe + setupRadioGroup(selectRecipientsAndMe) + setupListeners() + } + + override fun resetCallbacks() { + onVisibilitySelected = null + } + + private fun setupRadioGroup(selectRecipientsAndMe: Boolean) = with(binding) { + val defaultSelection = if (selectRecipientsAndMe) { + R.id.selectionReminderRecipientsAndMe + } else { + R.id.selectionReminderMeOnly + } + reminderVisibilityGroup.check(defaultSelection) + } + + private fun setupListeners() = with(binding) { + reminderVisibilityGroup.onItemCheckedListener { id, _, _ -> + this@SelectVisibilityReminderDialog.isRecipientsAndMeSelected = (id == R.id.selectionReminderRecipientsAndMe) + } + + positiveButton.setOnClickListener { + onVisibilitySelected?.invoke(this@SelectVisibilityReminderDialog.isRecipientsAndMeSelected) + alertDialog.dismiss() + } + + negativeButton.setOnClickListener { alertDialog.cancel() } + } +} diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageFragment.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageFragment.kt index 15bd2b6e54..2554e2a486 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageFragment.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageFragment.kt @@ -481,7 +481,10 @@ class NewMessageFragment : Fragment() { reminderAlert.apply { onAction1 { navigateToScheduleSendBottomSheet() } - onAction2 { newMessageViewModel.setReminderConfig(ReminderConfig.None) } + onAction2 { + newMessageViewModel.setReminderConfig(ReminderConfig.None) + newMessageViewModel.setShouldRemindRecipient(true) + } } recipientFieldsManager.setupAutoCompletionFields() 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 b8468d74d0..c1edcdb303 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 @@ -262,6 +262,9 @@ class NewMessageViewModel @Inject constructor( private val _reminderConfig = MutableStateFlow(ReminderConfig.None) val reminderConfig: StateFlow = _reminderConfig.asStateFlow() + private val _shouldRemindRecipient = MutableStateFlow(true) + val shouldRemindRecipient: StateFlow = _shouldRemindRecipient.asStateFlow() + //region Check mailbox existence private val exitSignal: CompletableJob = Job() @@ -1236,7 +1239,10 @@ class NewMessageViewModel @Inject constructor( updatedMentions } + } + fun setShouldRemindRecipient(value: Boolean) { + _shouldRemindRecipient.value = value } fun setScheduleConfig(config: ScheduleConfig) { diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/sendOptions/DraftSendOptionsFragment.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/sendOptions/DraftSendOptionsFragment.kt index f983c01907..f7eed1e268 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/sendOptions/DraftSendOptionsFragment.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/sendOptions/DraftSendOptionsFragment.kt @@ -39,6 +39,7 @@ import com.infomaniak.mail.data.models.FeatureFlag import com.infomaniak.mail.databinding.FragmentSendOptionsBinding import com.infomaniak.mail.ui.alertDialogs.CustomReminderPickerDialog import com.infomaniak.mail.ui.alertDialogs.SelectDateAndTimeForScheduledDraftDialog +import com.infomaniak.mail.ui.alertDialogs.SelectVisibilityReminderDialog import com.infomaniak.mail.ui.bottomSheetDialogs.ScheduleOption import com.infomaniak.mail.ui.bottomSheetDialogs.ScheduleOptionUtils import com.infomaniak.mail.ui.main.settings.SettingRadioButtonView @@ -70,6 +71,9 @@ class DraftSendOptionsFragment : Fragment() { @Inject lateinit var customReminderPickerDialog: CustomReminderPickerDialog + @Inject + lateinit var selectVisibilityDialog: SelectVisibilityReminderDialog + @Inject lateinit var localSettings: LocalSettings @@ -79,6 +83,12 @@ class DraftSendOptionsFragment : Fragment() { navigationArgs.currentlyScheduledEpochMillis.takeIf { it != 0L } } + private var shouldRemindRecipient: Boolean + get() = newMessageViewModel.shouldRemindRecipient.value + set(value) { + newMessageViewModel.setShouldRemindRecipient(value) + } + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { return FragmentSendOptionsBinding.inflate(inflater, container, false).also { binding = it }.root } @@ -86,10 +96,12 @@ class DraftSendOptionsFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) = with(binding) { dateAndTimeScheduleDialog.bindAlertToLifecycle(viewLifecycleOwner) customReminderPickerDialog.bindAlertToLifecycle(viewLifecycleOwner) + selectVisibilityDialog.bindAlertToLifecycle(viewLifecycleOwner) setupScheduleOptions() lastScheduleOption.associatedValue = lastSelectedEpoch?.toString() + updateReminderVisibilitySubtitle() setReminderOptionsVisible(isVisible = false) setScheduleOptionsVisible(isVisible = false) @@ -205,6 +217,7 @@ class DraftSendOptionsFragment : Fragment() { } customDelayReminder.setOnClickListener { onCustomDelayReminderClicked() } + reminderVisibility.setOnClickListener { showVisibilityReminderPicker() } } private fun setReminderOptionsVisible(isVisible: Boolean) { @@ -215,11 +228,15 @@ class DraftSendOptionsFragment : Fragment() { private fun removeReminderOptionsSelection() { binding.optionsDelays.clearCheck() newMessageViewModel.setReminderConfig(ReminderConfig.None) + shouldRemindRecipient = true + updateReminderVisibilitySubtitle() } private fun defaultReminderSelection() = with(binding) { optionsDelays.check(R.id.hours24) newMessageViewModel.setReminderConfig(ReminderConfig.Delayed(ReminderPreset.HOURS_24.delayMinutes, isCustom = false)) + shouldRemindRecipient = true + updateReminderVisibilitySubtitle() } private fun defaultScheduleSelection() = with(binding) { @@ -390,4 +407,22 @@ class DraftSendOptionsFragment : Fragment() { ) } + private fun showVisibilityReminderPicker() { + selectVisibilityDialog.show( + selectRecipientsAndMe = shouldRemindRecipient, + onVisibilitySelected = { isRecipientsAndMe -> + shouldRemindRecipient = isRecipientsAndMe + updateReminderVisibilitySubtitle() + }, + ) + } + + private fun updateReminderVisibilitySubtitle() = with(binding) { + val subtitleRes = if (shouldRemindRecipient) { + R.string.selectionReminderRecipientsAndMe + } else { + R.string.selectionReminderMeOnly + } + reminderVisibility.setSubtitle(subtitleRes) + } } diff --git a/app/src/main/res/layout/dialog_select_visibility_reminder.xml b/app/src/main/res/layout/dialog_select_visibility_reminder.xml new file mode 100644 index 0000000000..a57564225f --- /dev/null +++ b/app/src/main/res/layout/dialog_select_visibility_reminder.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + From d565a5543eba812ed400950b478f5a7720bb8206 Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Thu, 30 Jul 2026 09:19:36 +0200 Subject: [PATCH 3/4] refactor: Clean code --- .../SelectVisibilityReminderDialog.kt | 15 +++++---- .../dialog_select_visibility_reminder.xml | 32 ++++++++----------- 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/ui/alertDialogs/SelectVisibilityReminderDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/alertDialogs/SelectVisibilityReminderDialog.kt index d3b285f410..5b2d90b491 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/alertDialogs/SelectVisibilityReminderDialog.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/alertDialogs/SelectVisibilityReminderDialog.kt @@ -18,6 +18,7 @@ package com.infomaniak.mail.ui.alertDialogs import android.content.Context +import androidx.appcompat.app.AlertDialog import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.infomaniak.mail.R import com.infomaniak.mail.databinding.DialogSelectVisibilityReminderBinding @@ -39,10 +40,10 @@ class SelectVisibilityReminderDialog @Inject constructor( private var onVisibilitySelected: ((Boolean) -> Unit)? = null - private fun initDialog() = with(binding) { - MaterialAlertDialogBuilder(activityContext) + private fun initDialog(): AlertDialog { + return MaterialAlertDialogBuilder(activityContext) .setTitle(R.string.reminderVisibilityTitle) - .setView(root) + .setView(binding.root) .setPositiveButton(R.string.buttonConfirm, null) .setNegativeButton(com.infomaniak.core.legacy.R.string.buttonCancel, null) .create() @@ -72,13 +73,13 @@ class SelectVisibilityReminderDialog @Inject constructor( reminderVisibilityGroup.check(defaultSelection) } - private fun setupListeners() = with(binding) { - reminderVisibilityGroup.onItemCheckedListener { id, _, _ -> - this@SelectVisibilityReminderDialog.isRecipientsAndMeSelected = (id == R.id.selectionReminderRecipientsAndMe) + private fun setupListeners() { + binding.reminderVisibilityGroup.onItemCheckedListener { id, _, _ -> + isRecipientsAndMeSelected = (id == R.id.selectionReminderRecipientsAndMe) } positiveButton.setOnClickListener { - onVisibilitySelected?.invoke(this@SelectVisibilityReminderDialog.isRecipientsAndMeSelected) + onVisibilitySelected?.invoke(isRecipientsAndMeSelected) alertDialog.dismiss() } diff --git a/app/src/main/res/layout/dialog_select_visibility_reminder.xml b/app/src/main/res/layout/dialog_select_visibility_reminder.xml index a57564225f..1aa145775f 100644 --- a/app/src/main/res/layout/dialog_select_visibility_reminder.xml +++ b/app/src/main/res/layout/dialog_select_visibility_reminder.xml @@ -15,30 +15,24 @@ ~ You should have received a copy of the GNU General Public License ~ along with this program. If not, see . --> - - - - - + - + - + From c166a2cbb80f8e39913c4277848543ebf76c0ad8 Mon Sep 17 00:00:00 2001 From: Elouan BOITEUX Date: Thu, 30 Jul 2026 09:45:02 +0200 Subject: [PATCH 4/4] refactor: Observe shouldReminderRecipient --- .../newMessage/sendOptions/DraftSendOptionsFragment.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/sendOptions/DraftSendOptionsFragment.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/sendOptions/DraftSendOptionsFragment.kt index f7eed1e268..caeae2a2c1 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/sendOptions/DraftSendOptionsFragment.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/sendOptions/DraftSendOptionsFragment.kt @@ -101,7 +101,6 @@ class DraftSendOptionsFragment : Fragment() { setupScheduleOptions() lastScheduleOption.associatedValue = lastSelectedEpoch?.toString() - updateReminderVisibilitySubtitle() setReminderOptionsVisible(isVisible = false) setScheduleOptionsVisible(isVisible = false) @@ -112,6 +111,11 @@ class DraftSendOptionsFragment : Fragment() { observeFeatureFlagUpdates() observeScheduleConfig() observeReminderConfig() + observeShouldRemindRecipient() + } + + private fun observeShouldRemindRecipient() { + newMessageViewModel.shouldRemindRecipient.observe(viewLifecycleOwner) { updateReminderVisibilitySubtitle() } } private fun observeFeatureFlagUpdates() = with(binding) { @@ -229,14 +233,12 @@ class DraftSendOptionsFragment : Fragment() { binding.optionsDelays.clearCheck() newMessageViewModel.setReminderConfig(ReminderConfig.None) shouldRemindRecipient = true - updateReminderVisibilitySubtitle() } private fun defaultReminderSelection() = with(binding) { optionsDelays.check(R.id.hours24) newMessageViewModel.setReminderConfig(ReminderConfig.Delayed(ReminderPreset.HOURS_24.delayMinutes, isCustom = false)) shouldRemindRecipient = true - updateReminderVisibilitySubtitle() } private fun defaultScheduleSelection() = with(binding) { @@ -412,7 +414,6 @@ class DraftSendOptionsFragment : Fragment() { selectRecipientsAndMe = shouldRemindRecipient, onVisibilitySelected = { isRecipientsAndMe -> shouldRemindRecipient = isRecipientsAndMe - updateReminderVisibilitySubtitle() }, ) }