diff --git a/app/src/main/java/com/infomaniak/mail/MatomoMail.kt b/app/src/main/java/com/infomaniak/mail/MatomoMail.kt index 82ae828b300..8a6c5111437 100644 --- a/app/src/main/java/com/infomaniak/mail/MatomoMail.kt +++ b/app/src/main/java/com/infomaniak/mail/MatomoMail.kt @@ -140,6 +140,7 @@ object MatomoMail : Matomo { CustomFolder("customFolder"), CustomFolders("customFolders"), CustomSchedule("customSchedule"), + CustomReminder("customReminder"), CustomScheduleConfirm("customScheduleConfirm"), DailyLimitReachedUpgrade("dailyLimitReachedUpgrade"), Delete("delete"), diff --git a/app/src/main/java/com/infomaniak/mail/ui/alertDialogs/CustomReminderPickerDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/alertDialogs/CustomReminderPickerDialog.kt new file mode 100644 index 00000000000..f5cabd366c0 --- /dev/null +++ b/app/src/main/java/com/infomaniak/mail/ui/alertDialogs/CustomReminderPickerDialog.kt @@ -0,0 +1,124 @@ +/* + * 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.DialogCustomReminderPickerBinding +import com.infomaniak.mail.utils.date.DateFormatUtils.MINUTES_IN_AN_HOUR +import com.infomaniak.mail.utils.date.DateFormatUtils.MINUTES_IN_A_DAY +import dagger.hilt.android.qualifiers.ActivityContext +import dagger.hilt.android.scopes.ActivityScoped +import javax.inject.Inject + +@ActivityScoped +class CustomReminderPickerDialog @Inject constructor( + @ActivityContext private val activityContext: Context, +) : BaseAlertDialog(activityContext) { + + private val binding: DialogCustomReminderPickerBinding by lazy { + DialogCustomReminderPickerBinding.inflate(activity.layoutInflater) + } + + override val alertDialog = initDialog() + + private var onDelaySelected: ((Int) -> Unit)? = null + + private val timeUnits = TimeUnit.entries.toTypedArray() + + private fun initDialog() = with(binding) { + MaterialAlertDialogBuilder(activityContext) + .setTitle(R.string.buttonCustomReminder) + .setView(root) + .setPositiveButton(R.string.buttonConfirm, null) + .setNegativeButton(com.infomaniak.core.legacy.R.string.buttonCancel, null) + .create() + } + + fun show(onDelaySelected: (Int) -> Unit) { + this.onDelaySelected = onDelaySelected + alertDialog.show() + setupPickers() + setupListeners() + } + + override fun resetCallbacks() { + onDelaySelected = null + } + + private fun setupPickers() = with(binding) { + numberPicker.minValue = 1 + numberPicker.maxValue = timeUnits[unitPicker.value].maxValue + numberPicker.wrapSelectorWheel = true + + unitPicker.minValue = 0 + unitPicker.maxValue = timeUnits.size - 1 + unitPicker.wrapSelectorWheel = false + + updateUnitLabels(numberPicker.value) + } + + private fun setupListeners() = with(binding) { + numberPicker.setOnValueChangedListener { _, oldVal, newVal -> + if ((oldVal == 1 && newVal > 1) || (oldVal > 1 && newVal == 1)) { + updateUnitLabels(newVal) + } + } + + unitPicker.setOnValueChangedListener { _, _, newUnitIndex -> numberPicker.maxValue = timeUnits[newUnitIndex].maxValue } + + positiveButton.setOnClickListener { + numberPicker.clearFocus() + unitPicker.clearFocus() + onDelaySelected?.invoke(getDelayMinutes()) + alertDialog.dismiss() + } + + negativeButton.setOnClickListener { alertDialog.cancel() } + } + + private fun updateUnitLabels(currentNumber: Int) { + val displayedUnits = timeUnits.map { + activityContext.resources.getQuantityString(it.titleRes, currentNumber) + }.toTypedArray() + + binding.unitPicker.displayedValues = displayedUnits + } + + private fun getDelayMinutes(): Int { + val number = binding.numberPicker.value + val selectedUnit = timeUnits[binding.unitPicker.value] + + return number * selectedUnit.multiplierInMinutes + } + + companion object { + private const val MAX_HOURS = 23 + private const val MAX_DAYS = 30 + + enum class TimeUnit( + val titleRes: Int, + val maxValue: Int, + val multiplierInMinutes: Int + ) { + Hours(R.plurals.unitHours, MAX_HOURS, MINUTES_IN_AN_HOUR), + Days(R.plurals.unitDays, MAX_DAYS, MINUTES_IN_A_DAY), + } + } +} 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 cc97a1dbe53..f983c019073 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 @@ -37,6 +37,7 @@ import com.infomaniak.mail.R import com.infomaniak.mail.data.LocalSettings 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.bottomSheetDialogs.ScheduleOption import com.infomaniak.mail.ui.bottomSheetDialogs.ScheduleOptionUtils @@ -66,6 +67,9 @@ class DraftSendOptionsFragment : Fragment() { @Inject lateinit var dateAndTimeScheduleDialog: SelectDateAndTimeForScheduledDraftDialog + @Inject + lateinit var customReminderPickerDialog: CustomReminderPickerDialog + @Inject lateinit var localSettings: LocalSettings @@ -81,6 +85,7 @@ class DraftSendOptionsFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) = with(binding) { dateAndTimeScheduleDialog.bindAlertToLifecycle(viewLifecycleOwner) + customReminderPickerDialog.bindAlertToLifecycle(viewLifecycleOwner) setupScheduleOptions() lastScheduleOption.associatedValue = lastSelectedEpoch?.toString() @@ -372,7 +377,17 @@ class DraftSendOptionsFragment : Fragment() { } private fun showCustomDelayReminderDatePicker() { - // TODO + customReminderPickerDialog.show( + onDelaySelected = { delayMinutes -> + trackScheduleSendEvent(MatomoName.CustomReminder) + newMessageViewModel.setReminderConfig(ReminderConfig.Delayed(delayMinutes, isCustom = true)) + binding.customDelayReminder.apply { + setSubtitle(requireContext().formatDelayText(delayMinutes)) + setCheckMark(displayCheckMark = true) + } + binding.optionsDelays.clearCheck() + }, + ) } } diff --git a/app/src/main/res/layout/dialog_custom_reminder_picker.xml b/app/src/main/res/layout/dialog_custom_reminder_picker.xml new file mode 100644 index 00000000000..aa823ea1f0f --- /dev/null +++ b/app/src/main/res/layout/dialog_custom_reminder_picker.xml @@ -0,0 +1,37 @@ + + + + + + + + diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 60a3115074c..731bdfdb9d0 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -729,6 +729,14 @@ Papirkurv Prøv venligst igen. Fjern blokering + + Dag + Dage + + + Time + Timer + Ukendt afsender Ukendt modtager (ukendt) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index c409fc02c2a..67a0771f300 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -729,6 +729,14 @@ Papierkorb Bitte versuchen Sie es erneut. Entsperren + + Tag + Tage + + + Stunde + Stunden + Unbekannter Spediteur Unbekannter Empfänger (unbekannt) diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 125a3139aeb..214c8304b31 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -729,6 +729,14 @@ Κάδος απορριμμάτων Παρακαλώ, δοκιμάστε ξανά. Ξεμπλοκάρισμα + + Ημέρα + Ημέρες + + + Ώρα + Ώρες + Άγνωστος αποστολέας Άγνωστος παραλήπτης (άγνωστο) diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 0dace42acdf..df4a38b65b8 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -729,6 +729,14 @@ Papelera Por favor, inténtelo de nuevo. Desbloquear + + Día + Días + + + Hora + Horas + Expedidor desconocido Destinatario desconocido (desconocido) diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 37245da2bef..efe815aa824 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -729,6 +729,14 @@ Roskakori Yritä uudelleen. Poista esto + + Päivä + Päivää + + + Tunti + Tuntia + Tuntematon lähettäjä Tuntematon vastaanottaja (tuntematon) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index e85db38a77d..aba89e0c3f4 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -729,6 +729,14 @@ Corbeille Veuillez réessayer. Débloquer + + Jour + Jours + + + Heure + Heures + Expéditeur inconnu Destinataire inconnu (inconnu) diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 5b83a645176..4c59c927a1e 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -729,6 +729,14 @@ Cestino Per favore, riprova. Sbloccare + + Giorno + Giorni + + + Ora + Ore + Spedizioniere sconosciuto Destinatario sconosciuto (sconosciuto) diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index 5a528b9a686..c36ea625582 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -729,6 +729,14 @@ Papirkurv Vennligst prøv igjen. Opphev blokkering + + Dag + Dager + + + Time + Timer + Ukjent avsender Ukjent mottaker (ukjent) diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 270043cdcf8..752b76350e2 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -729,6 +729,14 @@ Prullenbak Probeer het opnieuw. Deblokkeren + + Dag + Dagen + + + Uur + Uur + Onbekende afzender Onbekende ontvanger (onbekend) diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 1ad70767f18..ab3b9449709 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -787,6 +787,18 @@ Kosz Spróbuj ponownie. Odblokuj + + Dzień + Dni + Dni + Dni + + + Godzina + Godziny + Godzin + Godzin + Nieznany nadawca Nieznany odbiorca (nieznany) diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 9a15d48785b..c5ebcab3003 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -729,6 +729,14 @@ Lixo Por favor, tente novamente. Desbloquear + + Dia + Dias + + + Hora + Horas + Remetente desconhecido Destinatário desconhecido (desconhecido) diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index fd038232252..1f2c14f8d51 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -729,6 +729,14 @@ Papperskorg Försök igen. Avblockera + + Dag + Dagar + + + Timme + Timmar + Okänd avsändare Okänd mottagare (okänd) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e5ed9286206..4df26952dfa 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -733,6 +733,14 @@ Trash Please try again. Unblock + + Day + Days + + + Hour + Hours + Unknown expeditor Unknown recipient (unknown)