diff --git a/app/src/main/java/com/infomaniak/mail/data/models/MailTemplate.kt b/app/src/main/java/com/infomaniak/mail/data/models/MailTemplate.kt new file mode 100644 index 00000000000..d2edf76b19c --- /dev/null +++ b/app/src/main/java/com/infomaniak/mail/data/models/MailTemplate.kt @@ -0,0 +1,191 @@ +/* + * 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.data.models + +data class MailTemplate( + val id: Int, + val title: String, + val body: String, +) { + companion object { + val mocks: List = listOf( + MailTemplate( + id = 1, + title = "Bienvenue chez Infomaniak", + body = """ +

Bienvenue ! 👋

+

Nous sommes ravis de vous compter parmi nous. Votre compte est désormais actif et vous pouvez accéder à tous nos services.

+

Prochaines étapes :

+ +

Notre équipe support est disponible 24/7 pour vous accompagner.

+

Cordialement, L'équipe Infomaniak

+ """.trimIndent(), + ), + MailTemplate( + id = 2, + title = "Confirmation de commande", + body = """ +

Merci pour votre commande

+

Nous avons bien reçu votre commande #CMD-2026-8472.

+ + + +
kDrive Pro 1 ToCHF 10.50/mois
Nom de domaine .chCHF 15.00/an
+

Vous recevrez un e-mail séparé lorsque vos services seront activés.

+ """.trimIndent(), + ), + MailTemplate( + id = 3, + title = "Relance facture impayée", + body = """ +

Objet : Facture #FAC-2026-00342 en attente de paiement

+

Bonjour,

+

Sauf erreur de notre part, nous n'avons pas encore reçu le règlement de votre facture d'un montant de CHF 47.90, arrivée à échéance le 15 juillet 2026.

+
+ ⚠️ Rappel : Vos services pourraient être suspendus sous 7 jours sans régularisation. +
+

Vous pouvez régler en ligne depuis votre espace client.

+

En cas de paiement récent, merci de ne pas tenir compte de ce message.

+ """.trimIndent(), + ), + MailTemplate( + id = 4, + title = "Invitation réunion projet", + body = """ +

Réunion de lancement — Projet Migration Cloud

+

Bonjour à toutes et à tous,

+

Vous êtes convié(e) à la réunion de lancement qui se tiendra le :

+
+ 📅 Date : Mardi 18 août 2026
+ 🕐 Heure : 14h00 - 15h30
+ 📍 Lieu : kMeet (lien envoyé séparément) +
+

Ordre du jour :

+
    +
  1. Présentation des objectifs et périmètre
  2. +
  3. Architecture technique proposée
  4. +
  5. Planning et jalons clés
  6. +
  7. Questions diverses
  8. +
+

Merci de confirmer votre présence avant le 14 août.

+ """.trimIndent(), + ), + MailTemplate( + id = 5, + title = "Réinitialisation du mot de passe", + body = """ +

Vous avez demandé à réinitialiser votre mot de passe.

+

Cliquez sur le bouton ci-dessous pour définir un nouveau mot de passe :

+
+ Réinitialiser mon mot de passe +
+

Ce lien expire dans 1 heure. Si vous n'avez pas demandé cette réinitialisation, ignorez cet e-mail.

+ """.trimIndent(), + ), + MailTemplate( + id = 6, + title = "", + body = """ +

Cher client,

+

Nous vous informons d'une maintenance planifiée de nos serveurs le dimanche 23 août 2026 de 2h00 à 4h00.

+

Pendant cette fenêtre, les services suivants pourraient être temporairement indisponibles :

+ +

Nous nous excusons pour la gêne occasionnée.

+ """.trimIndent(), + ), + MailTemplate( + id = 7, + title = "Rapport mensuel d'utilisation", + body = """ +

📊 Votre consommation de juillet 2026

+

Voici le récapitulatif de votre utilisation :

+ + + + + + + + + + + + + + + + +
ServiceUtiliséLimite
kDrive Stockage742 Go1 To
kMail Envoi1 247 emailsIllimité
+

Accéder à mon espace client →

+ """.trimIndent(), + ), + MailTemplate( + id = 8, + title = "Pas de body", + body = "", + ), + MailTemplate( + id = 9, + title = "Vrai mail complet", + body = """ +
+
+
+
+ C'est un test : gras +
+
+
+
+
+ Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. +
+
+  Italic.  Gras italique  +
+
+ Surligneur  +
+
+ + Barre  + +
+
+
    +
  • Liste
  • +
  • Liste2
  • +
+
+ Lien +
+
+
+ """.trimIndent(), + ), + ) + } +} diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/settings/ItemSettingView.kt b/app/src/main/java/com/infomaniak/mail/ui/main/settings/ItemSettingView.kt index f8586300ea4..14a51b30b55 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/settings/ItemSettingView.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/settings/ItemSettingView.kt @@ -87,6 +87,11 @@ class ItemSettingView @JvmOverloads constructor( binding.title.text = title } + fun showChevron() = with(binding) { + action = Action.CHEVRON + chevron.isVisible = true + } + fun setSubtitle(@StringRes subtitle: Int) { binding.subtitle.apply { setText(subtitle) 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 60ff0c67cac..de411564470 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 @@ -1257,6 +1257,13 @@ class ThreadFragment : Fragment(), PickerEmojiObserver { ) } + private fun navigateToMoreOptionsBottomSheet() { + safeNavigate( + resId = R.id.moreOptionsBottomSheetDialog, + args = Bundle(), + ) + } + private fun navigateToSnoozeBottomSheet(snoozeScheduleType: SnoozeScheduleType?) { twoPaneFragment.navigateToSnoozeBottomSheet(snoozeScheduleType, threadViewModel.threadLive.value?.snoozeEndDate) } @@ -1391,6 +1398,7 @@ class ThreadFragment : Fragment(), PickerEmojiObserver { const val OPEN_AI_ACTIONS_BOTTOM_SHEET = "openAiActionsBottomSheet" const val OPEN_AI_SUMMARY_BOTTOM_SHEET = "openAiSummaryBottomSheet" const val OPEN_AI_TRANSLATE_BOTTOM_SHEET = "openAiTranslateBottomSheet" + const val OPEN_EMAIL_TEMPLATES_BOTTOM_SHEET = "openEmailTemplatesBottomSheet" private fun allAttachmentsFileName(subject: String) = "infomaniak-mail-attachments-$subject.zip" private fun allSwissTransferFilesName(subject: String) = "infomaniak-mail-swisstransfer-$subject.zip" diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/BodyContentPayload.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/BodyContentPayload.kt index 1440718db39..b9805304ab4 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/newMessage/BodyContentPayload.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/BodyContentPayload.kt @@ -17,6 +17,8 @@ */ package com.infomaniak.mail.ui.newMessage +import com.infomaniak.mail.ui.newMessage.EditorContentManager.Companion.toSanitizedHtml + /** * @param content The string representation of the body in either html or plain text format. * @param type The type of representation of [content]. Each type will lead to different processing of the content. @@ -26,6 +28,11 @@ data class BodyContentPayload(val content: String, val type: BodyContentType) { companion object { // Add some empty lines in the body, so the body focuses on these lines and not in the signature fun emptyBody() = BodyContentPayload(content = "


", type = BodyContentType.HTML_SANITIZED) + + fun bodyOf(body: BodyContentPayload) = BodyContentPayload( + content = "
${body.toSanitizedHtml()}

", + type = BodyContentType.HTML_SANITIZED + ) } } diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/EmailTemplateViewerFragment.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/EmailTemplateViewerFragment.kt new file mode 100644 index 00000000000..11c4c3b4eca --- /dev/null +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/EmailTemplateViewerFragment.kt @@ -0,0 +1,84 @@ +/* + * 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.newMessage + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.navigation.fragment.findNavController +import androidx.navigation.fragment.navArgs +import com.infomaniak.core.common.extensions.isNightModeEnabled +import com.infomaniak.core.legacy.utils.safeBinding +import com.infomaniak.mail.R +import com.infomaniak.mail.data.models.MailTemplate +import com.infomaniak.mail.databinding.FragmentEmailTemplateViewerBinding +import com.infomaniak.mail.ui.newMessage.EditorContentManager.Companion.toSanitizedHtml +import com.infomaniak.mail.utils.WebViewUtils +import com.infomaniak.mail.utils.WebViewUtils.Companion.setupThreadWebViewSettings +import com.infomaniak.mail.utils.extensions.enableAlgorithmicDarkening +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class EmailTemplateViewerFragment : Fragment() { + + private var binding: FragmentEmailTemplateViewerBinding by safeBinding() + private val newMessageViewModel: NewMessageViewModel by activityViewModels() + private val navigationArgs: EmailTemplateViewerFragmentArgs by navArgs() + + private val webViewUtils by lazy { WebViewUtils(requireContext()) } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + return FragmentEmailTemplateViewerBinding.inflate(inflater, container, false).also { binding = it }.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?): Unit = with(binding) { + val template = MailTemplate.mocks.firstOrNull { it.id == navigationArgs.templateId } ?: run { + findNavController().popBackStack() + return + } + + root.setTitle(template.title.ifBlank { getString(R.string.emailTemplateNoTitle) }) + + setupWebView(template) + insertButton.setOnClickListener { onInsertClicked(template) } + } + + private fun setupWebView(template: MailTemplate) = with(binding) { + val isDarkMode = requireContext().isNightModeEnabled() + val sanitizedHtml = BodyContentPayload(template.body, BodyContentType.HTML_UNSANITIZED).toSanitizedHtml() + val styledHtml = webViewUtils.processHtmlForDisplay(sanitizedHtml, isDarkMode, aliases = emptyList()) + + templateWebView.apply { + enableAlgorithmicDarkening(isDarkMode) + settings.setupThreadWebViewSettings() + loadDataWithBaseURL("", styledHtml, "text/html", "UTF-8", "") + } + } + + private fun onInsertClicked(template: MailTemplate) { + newMessageViewModel.setPlaceholderVisibility(false) + newMessageViewModel.editorBodyInitializer.postValue( + BodyContentPayload(template.body, BodyContentType.HTML_UNSANITIZED) + ) + findNavController().popBackStack(R.id.newMessageFragment, false) + } +} diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/EmailTemplatesFragment.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/EmailTemplatesFragment.kt new file mode 100644 index 00000000000..b6262fb32a6 --- /dev/null +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/EmailTemplatesFragment.kt @@ -0,0 +1,79 @@ +/* + * 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.newMessage + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.navigation.fragment.findNavController +import com.infomaniak.core.legacy.utils.safeBinding +import com.infomaniak.mail.R +import com.infomaniak.mail.data.models.MailTemplate +import com.infomaniak.mail.databinding.FragmentEmailTemplatesBinding +import com.infomaniak.mail.ui.main.settings.ItemSettingView +import com.infomaniak.mail.ui.newMessage.EditorContentManager.Companion.toSanitizedHtml +import com.infomaniak.mail.utils.JsoupParserUtil.jsoupParseWithLog +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class EmailTemplatesFragment : Fragment() { + + private var binding: FragmentEmailTemplatesBinding by safeBinding() + private val newMessageViewModel: NewMessageViewModel by activityViewModels() + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + return FragmentEmailTemplatesBinding.inflate(inflater, container, false).also { binding = it }.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) = with(binding) { + populateTemplates(MailTemplate.mocks) + } + + private fun populateTemplates(templates: List) = with(binding) { + templates.forEach { template -> + optionsContainer.addView(createTemplateItem(template)) + } + } + + private fun createTemplateItem(template: MailTemplate): ItemSettingView { + return ItemSettingView(requireContext()).apply { + setTitle(template.title) + val preview = template.body.toPlainTextPreview() + if (preview.isNotEmpty()) setSubtitle(preview) + showChevron() + setOnClickListener { onTemplateClicked(template) } + } + } + + private fun onTemplateClicked(template: MailTemplate) { + findNavController().navigate( + EmailTemplatesFragmentDirections.actionEmailTemplatesFragmentToEmailTemplateViewerFragment( + template.id + ) + ) + } + + private fun String.toPlainTextPreview(): String { + val sanitized = BodyContentPayload(this, BodyContentType.HTML_UNSANITIZED).toSanitizedHtml() + return jsoupParseWithLog(sanitized).text().trim() + } +} diff --git a/app/src/main/java/com/infomaniak/mail/ui/newMessage/MoreOptionsBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/newMessage/MoreOptionsBottomSheetDialog.kt new file mode 100644 index 00000000000..291eb53d9b5 --- /dev/null +++ b/app/src/main/java/com/infomaniak/mail/ui/newMessage/MoreOptionsBottomSheetDialog.kt @@ -0,0 +1,72 @@ +/* + * 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.newMessage + +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.core.view.isVisible +import androidx.fragment.app.activityViewModels +import androidx.lifecycle.distinctUntilChanged +import androidx.lifecycle.map +import com.infomaniak.core.legacy.utils.safeBinding +import com.infomaniak.core.legacy.utils.setBackNavigationResult +import com.infomaniak.mail.data.models.FeatureFlag +import com.infomaniak.mail.databinding.BottomSheetMoreOptionsBinding +import com.infomaniak.mail.ui.main.thread.ThreadFragment.Companion.OPEN_EMAIL_TEMPLATES_BOTTOM_SHEET +import com.infomaniak.mail.ui.main.thread.actions.ActionsBottomSheetDialog +import com.infomaniak.mail.ui.main.thread.actions.multiselection.MultiselectionViewModel + +class MoreOptionsBottomSheetDialog : ActionsBottomSheetDialog() { + + private var binding: BottomSheetMoreOptionsBinding by safeBinding() + override val multiselectionViewModel: MultiselectionViewModel by activityViewModels() + private val newMessageViewModel: NewMessageViewModel by activityViewModels() + + private val isScheduledDraftsEnabledLive by lazy { + newMessageViewModel.featureFlagsLive.map { it.contains(FeatureFlag.SCHEDULE_DRAFTS) }.distinctUntilChanged() + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + return BottomSheetMoreOptionsBinding.inflate(inflater, container, false).also { binding = it }.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + observeFeatureFlagUpdates() + + binding.scheduleSend.isEnabled = newMessageViewModel.isSendingAllowed.value == true + + // TODO: Open sendOptionsFragment instead of ScheduleSendBottomSheet when the new send options are implemented + binding.scheduleSend.setOnClickListener { setBackNavigationResult(OPEN_SCHEDULE_SEND_BOTTOM_SHEET, true) } + binding.emailTemplates.setOnClickListener { setBackNavigationResult(OPEN_EMAIL_TEMPLATES_BOTTOM_SHEET, true) } + } + + private fun observeFeatureFlagUpdates() { + isScheduledDraftsEnabledLive.observe(viewLifecycleOwner) { isScheduledDraftsEnabled -> + binding.scheduleSend.isVisible = isScheduledDraftsEnabled + } + } + + companion object { + const val OPEN_SCHEDULE_SEND_BOTTOM_SHEET = "openScheduleSendBottomSheet" + } +} 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 d323e0e530c..3d538556bb0 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 @@ -90,6 +90,8 @@ import com.infomaniak.mail.ui.bottomSheetDialogs.ScheduleSendBottomSheetDialog.C import com.infomaniak.mail.ui.bottomSheetDialogs.ScheduleSendBottomSheetDialogArgs import com.infomaniak.mail.ui.main.SnackbarManager import com.infomaniak.mail.ui.main.thread.AttachmentAdapter +import com.infomaniak.mail.ui.main.thread.ThreadFragment.Companion.OPEN_EMAIL_TEMPLATES_BOTTOM_SHEET +import com.infomaniak.mail.ui.newMessage.MoreOptionsBottomSheetDialog.Companion.OPEN_SCHEDULE_SEND_BOTTOM_SHEET import com.infomaniak.mail.ui.newMessage.NewMessageRecipientFieldsManager.FieldType import com.infomaniak.mail.ui.newMessage.NewMessageViewModel.ImportationResult import com.infomaniak.mail.ui.newMessage.NewMessageViewModel.UiFrom @@ -177,9 +179,6 @@ class NewMessageFragment : Fragment() { private val newMessageViewModel: NewMessageViewModel by activityViewModels() private val aiViewModel: AiViewModel by activityViewModels() private val encryptionViewModel: EncryptionViewModel by activityViewModels() - private val isScheduledDraftsEnabledLive by lazy { - newMessageViewModel.featureFlagsLive.map { it.contains(FeatureFlag.SCHEDULE_DRAFTS) }.distinctUntilChanged() - } private val areMentionsAvailableLive by lazy { newMessageViewModel.featureFlagsLive.map { it.contains(FeatureFlag.MENTIONS) }.distinctUntilChanged() } @@ -347,6 +346,23 @@ class NewMessageFragment : Fragment() { getBackNavigationResult(SCHEDULE_DRAFT_RESULT, ::scheduleDraft) getBackNavigationResult(AttachmentExt.DOWNLOAD_ATTACHMENT_RESULT, ::startActivity) + + getBackNavigationResult(OPEN_SCHEDULE_SEND_BOTTOM_SHEET) { openScheduleSendBottomSheet() } + + getBackNavigationResult(OPEN_EMAIL_TEMPLATES_BOTTOM_SHEET) { navigateToEmailTemplates() } + } + + private fun openScheduleSendBottomSheet() { + lifecycleScope.launch { + val mailbox = newMessageViewModel.currentMailbox() + if (checkMailboxStorage(mailbox)) { + if (newMessageViewModel.isEncryptionActivated.value == true) { + snackbarManager.postValue(getString(R.string.encryptedMessageSnackbarScheduledUnavailable)) + } else { + navigateToScheduleSendBottomSheet() + } + } + } } private fun setShimmerVisibility(isShimmering: Boolean) = with(binding) { @@ -845,9 +861,7 @@ class NewMessageFragment : Fragment() { } private fun observeFeatureFlagUpdates() { - isScheduledDraftsEnabledLive.observe(viewLifecycleOwner) { isScheduledDraftsEnabled -> - binding.scheduleButton.isVisible = isScheduledDraftsEnabled - } + binding.moreOptionsButton.isVisible = true areMentionsAvailableLive.observe(viewLifecycleOwner) { areMentionsAvailable -> binding.editorWebView.apply { @@ -932,23 +946,18 @@ class NewMessageFragment : Fragment() { private fun setupSendButtons(mailbox: Mailbox) = with(binding) { newMessageViewModel.isSendingAllowed.observe(viewLifecycleOwner) { - scheduleButton.isEnabled = it sendButton.isEnabled = it } - scheduleButton.setOnClickListener { - if (checkMailboxStorage(mailbox)) { - if (newMessageViewModel.isEncryptionActivated.value == true) { - snackbarManager.postValue(getString(R.string.encryptedMessageSnackbarScheduledUnavailable)) - } else { - navigateToScheduleSendBottomSheet() - } - } - } + moreOptionsButton.setOnClickListener { navigateToMoreOptionsBottomSheet() } sendButton.setOnClickListener { if (checkMailboxStorage(mailbox)) tryToSendEmail() } } + private fun navigateToMoreOptionsBottomSheet() = safelyNavigate(resId = R.id.moreOptionsBottomSheetDialog, args = Bundle()) + + private fun navigateToEmailTemplates() = safelyNavigate(resId = R.id.emailTemplatesFragment) + private fun navigateToScheduleSendBottomSheet(): Job = viewLifecycleOwner.lifecycleScope.launch { val mailbox = newMessageViewModel.currentMailbox() safelyNavigate( diff --git a/app/src/main/res/drawable/divider_with_padding.xml b/app/src/main/res/drawable/divider_with_padding.xml new file mode 100644 index 00000000000..dd6ce5e8ae9 --- /dev/null +++ b/app/src/main/res/drawable/divider_with_padding.xml @@ -0,0 +1,21 @@ + + diff --git a/app/src/main/res/drawable/ic_envelope_gear.xml b/app/src/main/res/drawable/ic_envelope_gear.xml new file mode 100644 index 00000000000..3bdbf67e95e --- /dev/null +++ b/app/src/main/res/drawable/ic_envelope_gear.xml @@ -0,0 +1,35 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/ic_file_pen.xml b/app/src/main/res/drawable/ic_file_pen.xml new file mode 100644 index 00000000000..26863a7bbd7 --- /dev/null +++ b/app/src/main/res/drawable/ic_file_pen.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/layout/bottom_sheet_more_options.xml b/app/src/main/res/layout/bottom_sheet_more_options.xml new file mode 100644 index 00000000000..16726770246 --- /dev/null +++ b/app/src/main/res/layout/bottom_sheet_more_options.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_email_template_viewer.xml b/app/src/main/res/layout/fragment_email_template_viewer.xml new file mode 100644 index 00000000000..48d9160a2ec --- /dev/null +++ b/app/src/main/res/layout/fragment_email_template_viewer.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_email_templates.xml b/app/src/main/res/layout/fragment_email_templates.xml new file mode 100644 index 00000000000..9bda7dfd942 --- /dev/null +++ b/app/src/main/res/layout/fragment_email_templates.xml @@ -0,0 +1,41 @@ + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_new_message.xml b/app/src/main/res/layout/fragment_new_message.xml index 23dc6ffa98e..9b8a353891c 100644 --- a/app/src/main/res/layout/fragment_new_message.xml +++ b/app/src/main/res/layout/fragment_new_message.xml @@ -643,13 +643,14 @@ tools:visibility="visible" /> diff --git a/app/src/main/res/navigation/new_message_navigation.xml b/app/src/main/res/navigation/new_message_navigation.xml index 6fad73b8875..674f4213395 100644 --- a/app/src/main/res/navigation/new_message_navigation.xml +++ b/app/src/main/res/navigation/new_message_navigation.xml @@ -47,6 +47,12 @@ + + + + + + + + + + + + (Kladde) Denne besked vil blive flyttet til dine kladder for at blive sendt, når du vil. Rediger afsendelse + E-mailskabeloner Du er ved at sende en besked uden emne. Vil du fortsætte? Tomt emne Der er intet at se her. @@ -411,6 +412,7 @@ Oversat i %s Mandag eftermiddag Mandag morgen + Flere valgmuligheder Flyt til Spam Søg efter en mappe @@ -509,6 +511,7 @@ Vælg tidspunkt Send Send bekræftelsen + Sendevalg Sendte beskeder Servere utilgængelige Accentfarve diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 828edb87785..cf6e62bae56 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -252,6 +252,7 @@ (Entwurf) Diese Nachricht wird in Ihre Entwürfe verschoben, damit Sie sie senden können, wann immer Sie möchten. Senden bearbeiten + E-Mail-Vorlagen Sie sind dabei, eine Nachricht ohne Betreff zu senden. Möchten Sie fortfahren? Leeres Thema Hier gibt es nichts zu sehen. @@ -411,6 +412,7 @@ Übersetzt in %s Montagnachmittag Montagmorgen + Weitere Optionen Einzug von Spam Einen Ordner suchen @@ -509,6 +511,7 @@ Zeit auswählen Senden Sie Senden Sie die Bestätigung + Sendeoptionen Gesendete Nachrichten Server nicht verfügbar Akzentfarbe diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 939b0f33efc..dc8914f910f 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -252,6 +252,7 @@ (Πρόχειρο) Αυτό το μήνυμα θα μετακινηθεί στα πρόχειρα ώστε να σταλεί όποτε θέλετε. Επεξεργασία αποστολής + Πρότυπα email Πρόκειται να στείλετε μήνυμα χωρίς θέμα. Θέλετε να συνεχίσετε; Κενό θέμα Δεν υπάρχει τίποτα εδώ. @@ -411,6 +412,7 @@ Μεταφράστηκε σε %s Δευτέρα απόγευμα Δευτέρα πρωί + Περισσότερες επιλογές Μετακίνηση στα Spam Αναζήτηση φακέλου @@ -509,6 +511,7 @@ Επιλέξτε ώρα Αποστολή Αποστολή επιβεβαίωσης + Επιλογές αποστολής Απεσταλμένα μηνύματα Οι διακομιστές δεν είναι διαθέσιμοι Χρώμα έμφασης diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 819d28e9b37..13b9fd6377d 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -252,6 +252,7 @@ (Borrador) Este mensaje se moverá a tus borradores para que puedas enviarlo cuando lo desees. Editar envío + Plantillas de correo electrónico Está a punto de enviar un mensaje sin asunto. ¿Desea continuar? Asunto vacío Aquí no hay nada que ver. @@ -411,6 +412,7 @@ Traducido en %s Lunes por la tarde Lunes mañana + Más opciones Mover en Spam Buscar un fichero @@ -509,6 +511,7 @@ Seleccionar la hora Enviar Enviar la confirmación + Opciones de envío Mensajes enviados Servidores no disponibles Color de acento diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 5ee1d68ad9f..d8405ef8fe1 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -252,6 +252,7 @@ (Luonnos) Tämä viesti siirretään luonnoksiisi lähetettäväksi milloin haluat. Muokkaa lähetystä + Sähköpostimallit Olet lähettämässä viestiä ilman aihetta. Haluatko jatkaa? Tyhjä aihe Täällä ei ole mitään nähtävää. @@ -411,6 +412,7 @@ Käännetty %s Maanantai-iltapäivä Maanantaiaamu + Lisää vaihtoehtoja Siirrä roskapostiin Hae kansiota @@ -509,6 +511,7 @@ Valitse aika Lähetä Lähetä vahvistus + Lähetysvalinnat Lähetetyt viestit Palvelimet eivät ole käytettävissä Korostusväri diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 2fc302578bc..21a3ce5a7d6 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -252,6 +252,7 @@ (Brouillon) Ce message sera déplacé dans vos brouillons pour être envoyé quand vous le souhaitez. Modifier l’envoi + Modèles d’e-mail Vous êtes sur le point d’envoyer un message sans objet. Voulez-vous continuer ? Objet vide Il n’y a rien à voir par ici. @@ -411,6 +412,7 @@ Traduit en %s Lundi après-midi Lundi matin + Plus d’options Déplacer dans Spam Rechercher un dossier @@ -509,6 +511,7 @@ Sélectionner l’heure Envoyer Envoyer la confirmation + Options d’envoi Messages envoyés Serveurs indisponibles Couleur d’accentuation diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index da2cccff1a0..a07afd19562 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -252,6 +252,7 @@ (Bozza) Questo messaggio verrà spostato nelle tue bozze per essere inviato quando vuoi. Modifica invio + Modelli di e-mail Stai per inviare un messaggio senza oggetto. Vuoi continuare? Oggetto vuoto Non c’è nulla da vedere qui. @@ -411,6 +412,7 @@ Tradotto in %s Lunedì pomeriggio Lunedì mattina + Altre opzioni Spostarsi in Spam Ricerca di un file @@ -509,6 +511,7 @@ Selezionare l’ora Invia Inviare la conferma + Opzioni di invio Messaggi inviati Server non disponibili Colore d’accento diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index d0dc46c4dd6..aa1fea869c2 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -252,6 +252,7 @@ (Utkast) Denne meldingen vil bli flyttet til utkastene dine for å bli sendt når du vil. Rediger sending + E-postmaler Du er i ferd med å sende en melding uten emne. Vil du fortsette? Tomt emne Det er ingenting å se her. @@ -411,6 +412,7 @@ Oversatt i %s Mandag ettermiddag Mandag morgen + Flere alternativer Flytt til Spam Søk etter mappe @@ -509,6 +511,7 @@ Velg tid Send Send bekreftelsen + Sendevalg Sendte meldinger Servere utilgjengelige Aksentfarge diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 686171535ce..9edb80bd1ae 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -252,6 +252,7 @@ (Concept) Dit bericht wordt naar uw concepten verplaatst om te worden verzonden wanneer u maar wilt. Verzenden bewerken + E-mailsjablonen U staat op het punt een bericht zonder onderwerp te verzenden. Wilt u doorgaan? Leeg onderwerp Er is hier niets te zien. @@ -411,6 +412,7 @@ Vertaald in %s Maandagmiddag Maandagochtend + Meer opties Naar Spam verplaatsen Een map zoeken @@ -509,6 +511,7 @@ Tijd selecteren Verzenden De bevestiging verzenden + Verzendopties Verzonden berichten Servers niet beschikbaar Accentkleur diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 6ed805948c2..71898624700 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -258,6 +258,7 @@ (Wersja robocza) Ta wiadomość zostanie przeniesiona do wersji roboczych, aby zostać wysłana kiedy chcesz. Edytuj wysyłkę + Szablony e-mail Zamierzasz wysłać wiadomość bez tematu. Czy chcesz kontynuować? Pusty temat Nie ma tu nic do wyświetlenia. @@ -427,6 +428,7 @@ Przetłumaczone w %s Poniedziałek po południu Poniedziałek rano + Więcej opcji Przenieś do Spam Wyszukaj folder @@ -535,6 +537,7 @@ Wybierz godzinę Wyślij Wyślij potwierdzenie + Opcje wysyłania Wysłane wiadomości Serwery niedostępne Kolor akcentu diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 94a66ef647e..b31a3a2613c 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -252,6 +252,7 @@ (Rascunho) Esta mensagem será movida para os seus rascunhos para ser enviada quando quiser. Editar envio + Modelos de e-mail Está prestes a enviar uma mensagem sem assunto. Deseja continuar? Assunto vazio Não há nada para ver aqui. @@ -411,6 +412,7 @@ Traduzido em %s Segunda-feira à tarde Segunda-feira de manhã + Mais opções Mover para Spam Procurar uma pasta @@ -509,6 +511,7 @@ Selecionar hora Enviar Enviar a confirmação + Opções de envio Mensagens enviadas Servidores indisponíveis Cor de destaque diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index c15eb0952e2..39966bbf15a 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -252,6 +252,7 @@ (Utkast) Detta meddelande kommer att flyttas till dina utkast för att skickas när du vill. Redigera sändning + E-postmallar Du är på väg att skicka ett meddelande utan ämne. Vill du fortsätta? Tomt ämne Det finns inget att se här. @@ -411,6 +412,7 @@ Översatt i %s Måndag eftermiddag Måndag morgon + Fler alternativ Flytta till Spam Sök efter en mapp @@ -509,6 +511,7 @@ Välj tid Skicka Skicka bekräftelsen + Skicka-alternativ Skickade meddelanden Servrar otillgängliga Accentfärg diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ad4b8709415..5a4d0fc6799 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -256,6 +256,7 @@ (Draft) This message will be moved to your drafts to be sent whenever you want. Edit Send + Email templates You are about to send a message without a subject. Do you want to continue? Empty subject There is nothing to see here. @@ -415,6 +416,7 @@ Translated in %s Monday afternoon Monday morning + More options Move in Spam Search a folder @@ -513,9 +515,10 @@ Select time Send Send the confirmation + Send options Sent messages - Accent colour Servers unavailable + Accent colour Choose the accent colour for the application Account management App lock