diff --git a/Mail/Views/Alerts/ConfirmationBlockRecipientView.swift b/Mail/Views/Alerts/ConfirmationBlockRecipientView.swift new file mode 100644 index 000000000..af9fe0992 --- /dev/null +++ b/Mail/Views/Alerts/ConfirmationBlockRecipientView.swift @@ -0,0 +1,76 @@ +/* + Infomaniak Mail - iOS App + 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 . + */ + +import Foundation +import InfomaniakCoreUI +import InfomaniakDI +import MailCore +import MailCoreUI +import MailResources +import SwiftUI + +struct ConfirmationBlockRecipientView: View { + @LazyInjectService private var matomo: MatomoUtils + + @EnvironmentObject private var mailboxManager: MailboxManager + @EnvironmentObject private var actionsManager: ActionsManager + + let recipient: Recipient + let reportedMessage: Message + let origin: ActionOrigin + var onDismiss: (() -> Void)? + + private var contact: CommonContact { + return CommonContactCache.getOrCreateContact(contactConfiguration: .correspondent( + correspondent: recipient, + contextMailboxManager: mailboxManager + )) + } + + var body: some View { + VStack(alignment: .leading, spacing: 0) { + Text(MailResourcesStrings.Localizable.blockExpeditorTitle(contact.fullName)) + .textStyle(.bodyMedium) + .padding(.bottom, IKPadding.alertTitleBottom) + + Text(MailResourcesStrings.Localizable.confirmationToBlockAnExpeditorText(recipient.email)) + .textStyle(.body) + .padding(.bottom, IKPadding.alertDescriptionBottom) + + ModalButtonsView(primaryButtonTitle: MailResourcesStrings.Localizable.buttonBlockAnExpeditor) { + Task { + matomo.track(eventWithCategory: .blockUserAction, name: "confirmSelectedUser") + try await actionsManager.performAction( + target: [reportedMessage], + action: .block, + origin: origin + ) + onDismiss?() + } + } + } + } +} + +#Preview { + ConfirmationBlockRecipientView( + recipient: PreviewHelper.sampleRecipient1, + reportedMessage: PreviewHelper.sampleMessage, + origin: .floatingPanel(source: .threadList) + ) +} diff --git a/Mail/Views/Bottom sheets/Actions/ActionsPanelViewModifier.swift b/Mail/Views/Bottom sheets/Actions/ActionsPanelViewModifier.swift index a714c6a57..b546db3e2 100644 --- a/Mail/Views/Bottom sheets/Actions/ActionsPanelViewModifier.swift +++ b/Mail/Views/Bottom sheets/Actions/ActionsPanelViewModifier.swift @@ -18,6 +18,7 @@ import Foundation import MailCore +import MailResources import SwiftModalPresentation import SwiftUI @@ -40,9 +41,11 @@ extension View { struct ActionsPanelViewModifier: ViewModifier { @EnvironmentObject private var mailboxManager: MailboxManager - @ModalState private var reportForJunkMessage: Message? + @ModalState private var reportForJunkMessages: [Message]? @ModalState private var reportedForDisplayProblemMessage: Message? @ModalState private var reportedForPhishingMessage: Message? + @ModalState private var blockSenderAlert: BlockRecipientAlertState? + @ModalState private var blockSendersList: BlockRecipientState? @ModalState private var messagesToMove: [Message]? @ModalState private var flushAlert: FlushAlertState? @ModalState private var shareMailLink: ShareMailLinkResult? @@ -59,7 +62,9 @@ struct ActionsPanelViewModifier: ViewModifier { originFolder: originFolder?.freezeIfNeeded(), nearestFlushAlert: $flushAlert, nearestMessagesToMoveSheet: $messagesToMove, - nearestReportJunkMessageActionsPanel: $reportForJunkMessage, + nearestBlockSenderAlert: $blockSenderAlert, + nearestBlockSendersList: $blockSendersList, + nearestReportJunkMessageActionsPanel: $reportForJunkMessages, nearestReportedForPhishingMessageAlert: $reportedForPhishingMessage, nearestReportedForDisplayProblemMessageAlert: $reportedForDisplayProblemMessage, nearestShareMailLinkPanel: $shareMailLink @@ -79,8 +84,19 @@ struct ActionsPanelViewModifier: ViewModifier { ) .sheetViewStyle() } - .floatingPanel(item: $reportForJunkMessage) { reportForJunkMessage in - ReportJunkView(reportedMessage: reportForJunkMessage, origin: origin) + .floatingPanel(item: $reportForJunkMessages) { reportForJunkMessages in + ReportJunkView(reportedMessages: reportForJunkMessages, origin: origin) + } + .floatingPanel(item: $blockSendersList, + title: MailResourcesStrings.Localizable.blockAnExpeditorTitle) { blockSenderState in + BlockSenderView(recipientsToMessage: blockSenderState.recipientsToMessage, origin: origin) + } + .customAlert(item: $blockSenderAlert) { blockSenderState in + ConfirmationBlockRecipientView( + recipient: blockSenderState.recipient, + reportedMessage: blockSenderState.message, + origin: origin + ) } .customAlert(item: $reportedForDisplayProblemMessage) { message in ReportDisplayProblemView(message: message) diff --git a/Mail/Views/Bottom sheets/Actions/BlockSenderView.swift b/Mail/Views/Bottom sheets/Actions/BlockSenderView.swift new file mode 100644 index 000000000..345b4dfe0 --- /dev/null +++ b/Mail/Views/Bottom sheets/Actions/BlockSenderView.swift @@ -0,0 +1,81 @@ +/* + Infomaniak Mail - iOS App + 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 . + */ + +import InfomaniakCore +import InfomaniakCoreUI +import InfomaniakDI +import MailCore +import MailCoreUI +import MailResources +import SwiftModalPresentation +import SwiftUI + +struct BlockSenderView: View { + @LazyInjectService private var matomo: MatomoUtils + + @Environment(\.dismiss) private var dismiss + + @State private var selectedRecipient: Recipient? + @State private var recipients = [Recipient]() + + let recipientsToMessage: [Recipient: Message] + let origin: ActionOrigin + + var body: some View { + VStack(spacing: 0) { + ForEach(recipients) { recipient in + Button { + selectedRecipient = recipient + matomo.track(eventWithCategory: .blockUserAction, name: "selectUser") + } label: { + RecipientCell(recipient: recipient) + .padding(.horizontal, value: .medium) + .padding(.vertical, value: .small) + } + if recipient != recipients.last { + IKDivider() + } + } + } + .customAlert(item: $selectedRecipient) { recipient in + ConfirmationBlockRecipientView( + recipient: recipient, + reportedMessage: recipientsToMessage[recipient]!, + origin: origin + ) { + dismiss() + } + } + .onAppear { + recipients = recipientsToMessage.keys + .sorted { + let name1 = ($0.name.isEmpty ? $0.email : $0.name) + let name2 = ($1.name.isEmpty ? $1.email : $1.name) + return name1.caseInsensitiveCompare(name2) == .orderedAscending + } + } + } +} + +#Preview { + BlockSenderView( + recipientsToMessage: PreviewHelper.sampleRecipientWithMessage, + origin: .floatingPanel(source: .threadList) + ) + .accentColor(AccentColor.pink.primary.swiftUIColor) +} diff --git a/Mail/Views/Bottom sheets/Actions/ReportJunkView.swift b/Mail/Views/Bottom sheets/Actions/ReportJunkView.swift index d74dab5df..d5686da51 100644 --- a/Mail/Views/Bottom sheets/Actions/ReportJunkView.swift +++ b/Mail/Views/Bottom sheets/Actions/ReportJunkView.swift @@ -27,12 +27,23 @@ import SwiftUI struct ReportJunkView: View { @LazyInjectService private var platformDetector: PlatformDetectable + @EnvironmentObject private var mailboxManager: MailboxManager @Environment(\.dismiss) private var dismiss - let reportedMessage: Message - let actions: [Action] = [.spam, .phishing, .block] + let reportedMessages: [Message] let origin: ActionOrigin + private var filteredActions: [Action] { + let currentUserEmail = mailboxManager.mailbox.email + let uniqueSenders = Set(reportedMessages.compactMap { $0.from.first?.email }) + + if uniqueSenders == [currentUserEmail] { + return [.spam, .phishing] + } else { + return [.spam, .phishing, .blockList] + } + } + var body: some View { VStack(alignment: .leading, spacing: 0) { if platformDetector.isMac { @@ -42,12 +53,11 @@ struct ReportJunkView: View { .padding(.horizontal, value: .medium) } - ForEach(actions) { action in - if action != actions.first { + ForEach(filteredActions) { action in + if action != filteredActions.first { IKDivider() } - - MessageActionView(targetMessages: [reportedMessage], action: action, origin: origin) + MessageActionView(targetMessages: reportedMessages, action: action, origin: origin) } } .matomoView(view: [MatomoUtils.View.bottomSheet.displayName, "ReportJunkView"]) @@ -55,6 +65,6 @@ struct ReportJunkView: View { } #Preview { - ReportJunkView(reportedMessage: PreviewHelper.sampleMessage, origin: .floatingPanel(source: .threadList)) + ReportJunkView(reportedMessages: PreviewHelper.sampleMessages, origin: .floatingPanel(source: .threadList)) .accentColor(AccentColor.pink.primary.swiftUIColor) } diff --git a/MailCore/Cache/Actions/Action+List.swift b/MailCore/Cache/Actions/Action+List.swift index c7c9c57d1..7061aadcf 100644 --- a/MailCore/Cache/Actions/Action+List.swift +++ b/MailCore/Cache/Actions/Action+List.swift @@ -111,7 +111,7 @@ extension Action: CaseIterable { let star = messages.allSatisfy(\.flagged) let listActions: [Action] = [ - spam ? .nonSpam : .spam, + spam ? .nonSpam : .reportJunk, star ? .unstar : .star ] @@ -125,7 +125,7 @@ extension Action: CaseIterable { let showUnstar = messages.contains { $0.flagged } let spam = originFolder?.role == .spam - let spamAction: Action? = spam ? .nonSpam : .spam + let spamAction: Action? = spam ? .nonSpam : .reportJunk let tempListActions: [Action?] = [ .openMovePanel, @@ -278,6 +278,12 @@ public extension Action { iconResource: MailResourcesAsset.blockUser, matomoName: "blockUser" ) + static let blockList = Action( + id: "blockList", + title: MailResourcesStrings.Localizable.actionBlockSender, + iconResource: MailResourcesAsset.blockUser, + matomoName: "blockUser" + ) static let phishing = Action( id: "phishing", title: MailResourcesStrings.Localizable.actionPhishing, diff --git a/MailCore/Cache/Actions/ActionOrigin.swift b/MailCore/Cache/Actions/ActionOrigin.swift index 029b1d74d..8ba9bc9ea 100644 --- a/MailCore/Cache/Actions/ActionOrigin.swift +++ b/MailCore/Cache/Actions/ActionOrigin.swift @@ -39,7 +39,9 @@ public struct ActionOrigin { private(set) var nearestMessagesActionsPanel: Binding<[Message]?>? private(set) var nearestFlushAlert: Binding? private(set) var nearestMessagesToMoveSheet: Binding<[Message]?>? - private(set) var nearestReportJunkMessageActionsPanel: Binding? + private(set) var nearestBlockSenderAlert: Binding? + private(set) var nearestBlockSendersList: Binding? + private(set) var nearestReportJunkMessageActionsPanel: Binding<[Message]?>? private(set) var nearestReportedForPhishingMessageAlert: Binding? private(set) var nearestReportedForDisplayProblemMessageAlert: Binding? private(set) var nearestShareMailLinkPanel: Binding? @@ -50,7 +52,9 @@ public struct ActionOrigin { nearestMessagesActionsPanel: Binding<[Message]?>? = nil, nearestFlushAlert: Binding? = nil, nearestMessagesToMoveSheet: Binding<[Message]?>? = nil, - nearestReportJunkMessageActionsPanel: Binding? = nil, + nearestBlockSenderAlert: Binding? = nil, + nearestBlockSendersList: Binding? = nil, + nearestReportJunkMessageActionsPanel: Binding<[Message]?>? = nil, nearestReportedForPhishingMessageAlert: Binding? = nil, nearestReportedForDisplayProblemMessageAlert: Binding? = nil, nearestShareMailLinkPanel: Binding? = nil @@ -60,6 +64,8 @@ public struct ActionOrigin { self.nearestMessagesActionsPanel = nearestMessagesActionsPanel self.nearestFlushAlert = nearestFlushAlert self.nearestMessagesToMoveSheet = nearestMessagesToMoveSheet + self.nearestBlockSenderAlert = nearestBlockSenderAlert + self.nearestBlockSendersList = nearestBlockSendersList self.nearestReportJunkMessageActionsPanel = nearestReportJunkMessageActionsPanel self.nearestReportedForPhishingMessageAlert = nearestReportedForPhishingMessageAlert self.nearestReportedForDisplayProblemMessageAlert = nearestReportedForDisplayProblemMessageAlert @@ -75,7 +81,9 @@ public struct ActionOrigin { originFolder: Folder? = nil, nearestFlushAlert: Binding? = nil, nearestMessagesToMoveSheet: Binding<[Message]?>? = nil, - nearestReportJunkMessageActionsPanel: Binding? = nil, + nearestBlockSenderAlert: Binding? = nil, + nearestBlockSendersList: Binding? = nil, + nearestReportJunkMessageActionsPanel: Binding<[Message]?>? = nil, nearestReportedForPhishingMessageAlert: Binding? = nil, nearestReportedForDisplayProblemMessageAlert: Binding? = nil, nearestShareMailLinkPanel: Binding? = nil) -> ActionOrigin { @@ -84,6 +92,8 @@ public struct ActionOrigin { folder: originFolder, nearestFlushAlert: nearestFlushAlert, nearestMessagesToMoveSheet: nearestMessagesToMoveSheet, + nearestBlockSenderAlert: nearestBlockSenderAlert, + nearestBlockSendersList: nearestBlockSendersList, nearestReportJunkMessageActionsPanel: nearestReportJunkMessageActionsPanel, nearestReportedForPhishingMessageAlert: nearestReportedForPhishingMessageAlert, nearestReportedForDisplayProblemMessageAlert: nearestReportedForDisplayProblemMessageAlert, diff --git a/MailCore/Cache/Actions/ActionsManager.swift b/MailCore/Cache/Actions/ActionsManager.swift index e70d568a6..b38cd2612 100644 --- a/MailCore/Cache/Actions/ActionsManager.swift +++ b/MailCore/Cache/Actions/ActionsManager.swift @@ -167,8 +167,7 @@ public class ActionsManager: ObservableObject { } case .reportJunk: Task { @MainActor in - assert(messagesWithDuplicates.count <= 1, "More than one message was passed for junk report") - origin.nearestReportJunkMessageActionsPanel?.wrappedValue = messagesWithDuplicates.first + origin.nearestReportJunkMessageActionsPanel?.wrappedValue = messagesWithDuplicates } case .spam: let messagesFromFolder = messagesWithDuplicates.fromFolderOrSearch(originFolder: origin.frozenFolder) @@ -185,6 +184,19 @@ public class ActionsManager: ObservableObject { guard let message = messagesWithDuplicates.first else { return } try await mailboxManager.apiFetcher.blockSender(message: message) snackbarPresenter.show(message: MailResourcesStrings.Localizable.snackbarSenderBlacklisted(1)) + case .blockList: + Task { @MainActor in + + let uniqueRecipient = self.getUniqueRecipients(reportedMessages: messages) + if uniqueRecipient.count > 1 { + origin.nearestBlockSendersList?.wrappedValue = BlockRecipientState(recipientsToMessage: uniqueRecipient) + } else if let recipient = uniqueRecipient.first { + origin.nearestBlockSenderAlert?.wrappedValue = BlockRecipientAlertState( + recipient: recipient.key, + message: messages.first! + ) + } + } case .shareMailLink: guard let message = messagesWithDuplicates.first else { return } let result = try await mailboxManager.apiFetcher.shareMailLink(message: message) @@ -303,4 +315,30 @@ public class ActionsManager: ObservableObject { .snackbarThreadDeletedPermanently(messages.uniqueThreadsInFolder(originFolder).count) } } + + private func getUniqueRecipients(reportedMessages messages: [Message]) -> [Recipient: Message] { + var uniqueRecipients = [String: Recipient]() + var recipientToMessage = [Recipient: Message]() + + for reportedMessage in messages { + guard let recipient = reportedMessage.from.first, + !recipient.isMe(currentMailboxEmail: mailboxManager.mailbox.email) + else { + continue + } + + if let existingRecipient = uniqueRecipients[recipient.email] { + if (existingRecipient.name.isEmpty) && !(recipient.name.isEmpty) { + let message = recipientToMessage[existingRecipient] + uniqueRecipients[recipient.email] = recipient + recipientToMessage[recipient] = message + recipientToMessage[existingRecipient] = nil + } + } else { + uniqueRecipients[recipient.email] = recipient + recipientToMessage[recipient] = reportedMessage + } + } + return recipientToMessage + } } diff --git a/MailCore/Utils/BlockRecipientState.swift b/MailCore/Utils/BlockRecipientState.swift new file mode 100644 index 000000000..50d1af76f --- /dev/null +++ b/MailCore/Utils/BlockRecipientState.swift @@ -0,0 +1,38 @@ +/* + Infomaniak Mail - iOS App + 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 . + */ + +import Foundation + +public struct BlockRecipientState: Identifiable { + public var id = UUID() + public let recipientsToMessage: [Recipient: Message] + public init(recipientsToMessage: [Recipient: Message]) { + self.recipientsToMessage = recipientsToMessage + } +} + +public struct BlockRecipientAlertState: Identifiable { + public var id = UUID() + public let recipient: Recipient + public let message: Message + + public init(recipient: Recipient, message: Message) { + self.recipient = recipient + self.message = message + } +} diff --git a/MailCore/Utils/Matomo+Extension.swift b/MailCore/Utils/Matomo+Extension.swift index d260233cd..6a2e7b002 100644 --- a/MailCore/Utils/Matomo+Extension.swift +++ b/MailCore/Utils/Matomo+Extension.swift @@ -65,6 +65,7 @@ public extension MatomoUtils.EventCategory { // Actions static let attachmentActions = MatomoUtils.EventCategory(displayName: "attachmentActions") + static let blockUserAction = MatomoUtils.EventCategory(displayName: "blockUserAction") static let bottomSheetMessageActions = MatomoUtils.EventCategory(displayName: "bottomSheetMessageActions") static let bottomSheetThreadActions = MatomoUtils.EventCategory(displayName: "bottomSheetThreadActions") static let contactActions = MatomoUtils.EventCategory(displayName: "contactActions") diff --git a/MailCoreUI/Helpers/PreviewHelper.swift b/MailCoreUI/Helpers/PreviewHelper.swift index 31dc51df8..c61c8e445 100644 --- a/MailCoreUI/Helpers/PreviewHelper.swift +++ b/MailCoreUI/Helpers/PreviewHelper.swift @@ -129,6 +129,13 @@ public enum PreviewHelper { flagged: false, hasUnsubscribeLink: true) + public static let sampleMessages = Array( + repeating: PreviewHelper.sampleMessage, + count: 6 + ) + + public static let sampleRecipientWithMessage = [PreviewHelper.sampleRecipient1: sampleMessage] + public static let samplePresentableBody = PresentableBody(message: sampleMessage) public static let sampleRecipient1 = Recipient(email: "from@example.com", name: "John Doe") diff --git a/MailResources/Localizable/de.lproj/Localizable.strings b/MailResources/Localizable/de.lproj/Localizable.strings index 9ff33cfc5..2f770baf0 100644 --- a/MailResources/Localizable/de.lproj/Localizable.strings +++ b/MailResources/Localizable/de.lproj/Localizable.strings @@ -3,8 +3,8 @@ * Project: kMail * Locale: de, German * Tagged: ios - * Exported by: elena willen - * Exported at: Wed, 04 Sep 2024 11:22:24 +0200 + * Exported by: Matthieu Déglon + * Exported at: Wed, 11 Sep 2024 15:20:23 +0200 */ /* loco:62bb154d7513e127cb2e9c94 */ @@ -283,6 +283,12 @@ /* loco:6266649755d41301973d0c43 */ "bccTitle" = "Bcc:"; +/* loco:669a5cc96c0dbf9fe909b662 */ +"blockAnExpeditorTitle" = "Einen Absender blockieren"; + +/* loco:66dee0ef5c6d656046044445 */ +"blockExpeditorTitle" = "Block %s"; + /* loco:649ea00ef9c6ecfe620a0b62 */ "blockedPasswordTitle" = "Passwort blockiert"; @@ -334,6 +340,9 @@ /* loco:651ebd40ccc14ebdca0313a5 */ "buttonBackToApp" = "Zurück zur Anwendung Mail"; +/* loco:66db0113e0da22884c09f724 */ +"buttonBlockAnExpeditor" = "Block"; + /* loco:62b2d43771635f1d1f0da462 */ "buttonBold" = "Kühn"; @@ -347,7 +356,7 @@ "buttonCancel" = "Abbrechen"; /* loco:62befe9ca822415272753592 */ -"buttonClose" = "Schliessen Sie"; +"buttonClose" = "Schliessen"; /* loco:63e391b028b5fa7bab41e292 */ "buttonConfirm" = "Bestätigen"; @@ -409,9 +418,6 @@ /* loco:6425777e2343387912223aa2 */ "buttonLater" = "Später"; -/* loco:665868ebce4392ec5d0e94f2 */ -"buttonLink" = "Einen Hyperlink hinzufügen"; - /* loco:645b485e158c37a429012092 */ "buttonLoadMore" = "Mehr Unterhaltungen laden"; @@ -538,6 +544,9 @@ /* loco:63a473bcf3bb7f422358cfd2 */ "confirmLogoutTitle" = "Abmelden"; +/* loco:66db00746332bbedae01f2f2 */ +"confirmationToBlockAnExpeditorText" = "Diese E-Mail und alle zukünftigen Nachrichten von %s werden in den Junk-Mail-Ordner verschoben."; + /* loco:62737dea7bd28e302301e5c2 */ "contactActionAddToContacts" = "Zu Kontakten hinzufügen"; diff --git a/MailResources/Localizable/en.lproj/Localizable.strings b/MailResources/Localizable/en.lproj/Localizable.strings index 99f7f887a..62a7d2017 100644 --- a/MailResources/Localizable/en.lproj/Localizable.strings +++ b/MailResources/Localizable/en.lproj/Localizable.strings @@ -3,8 +3,8 @@ * Project: kMail * Locale: en, English * Tagged: ios - * Exported by: elena willen - * Exported at: Wed, 04 Sep 2024 11:22:24 +0200 + * Exported by: Matthieu Déglon + * Exported at: Wed, 11 Sep 2024 15:20:23 +0200 */ /* loco:62bb154d7513e127cb2e9c94 */ @@ -283,6 +283,12 @@ /* loco:6266649755d41301973d0c43 */ "bccTitle" = "Bcc:"; +/* loco:669a5cc96c0dbf9fe909b662 */ +"blockAnExpeditorTitle" = "Block a sender"; + +/* loco:66dee0ef5c6d656046044445 */ +"blockExpeditorTitle" = "Block %s"; + /* loco:649ea00ef9c6ecfe620a0b62 */ "blockedPasswordTitle" = "Blocked password"; @@ -334,6 +340,9 @@ /* loco:651ebd40ccc14ebdca0313a5 */ "buttonBackToApp" = "Back to the Mail application"; +/* loco:66db0113e0da22884c09f724 */ +"buttonBlockAnExpeditor" = "Block"; + /* loco:62b2d43771635f1d1f0da462 */ "buttonBold" = "Bold"; @@ -409,9 +418,6 @@ /* loco:6425777e2343387912223aa2 */ "buttonLater" = "Later"; -/* loco:665868ebce4392ec5d0e94f2 */ -"buttonLink" = "Add a hyperlink"; - /* loco:645b485e158c37a429012092 */ "buttonLoadMore" = "Load more conversations"; @@ -538,6 +544,9 @@ /* loco:63a473bcf3bb7f422358cfd2 */ "confirmLogoutTitle" = "Log out"; +/* loco:66db00746332bbedae01f2f2 */ +"confirmationToBlockAnExpeditorText" = "This email and all future messages from %s will be moved to the Junk Mail folder."; + /* loco:62737dea7bd28e302301e5c2 */ "contactActionAddToContacts" = "Add to contacts"; diff --git a/MailResources/Localizable/es.lproj/Localizable.strings b/MailResources/Localizable/es.lproj/Localizable.strings index 4fdd1f5f6..16128607f 100644 --- a/MailResources/Localizable/es.lproj/Localizable.strings +++ b/MailResources/Localizable/es.lproj/Localizable.strings @@ -3,8 +3,8 @@ * Project: kMail * Locale: es, Spanish * Tagged: ios - * Exported by: elena willen - * Exported at: Wed, 04 Sep 2024 11:22:24 +0200 + * Exported by: Matthieu Déglon + * Exported at: Wed, 11 Sep 2024 15:20:23 +0200 */ /* loco:62bb154d7513e127cb2e9c94 */ @@ -283,6 +283,12 @@ /* loco:6266649755d41301973d0c43 */ "bccTitle" = "CCO:"; +/* loco:669a5cc96c0dbf9fe909b662 */ +"blockAnExpeditorTitle" = "Bloquear un remitente"; + +/* loco:66dee0ef5c6d656046044445 */ +"blockExpeditorTitle" = "Bloquear %s"; + /* loco:649ea00ef9c6ecfe620a0b62 */ "blockedPasswordTitle" = "Contraseña bloqueada"; @@ -334,6 +340,9 @@ /* loco:651ebd40ccc14ebdca0313a5 */ "buttonBackToApp" = "Volver a la aplicación Mail"; +/* loco:66db0113e0da22884c09f724 */ +"buttonBlockAnExpeditor" = "Bloque"; + /* loco:62b2d43771635f1d1f0da462 */ "buttonBold" = "Negrita"; @@ -409,9 +418,6 @@ /* loco:6425777e2343387912223aa2 */ "buttonLater" = "Más tarde"; -/* loco:665868ebce4392ec5d0e94f2 */ -"buttonLink" = "Añadir un hipervínculo"; - /* loco:645b485e158c37a429012092 */ "buttonLoadMore" = "Cargar más conversaciones"; @@ -538,6 +544,9 @@ /* loco:63a473bcf3bb7f422358cfd2 */ "confirmLogoutTitle" = "Cerrar sesión"; +/* loco:66db00746332bbedae01f2f2 */ +"confirmationToBlockAnExpeditorText" = "Este correo electrónico y todos los futuros mensajes de %s se moverán a la carpeta de correo no deseado."; + /* loco:62737dea7bd28e302301e5c2 */ "contactActionAddToContacts" = "Añadir a contactos"; diff --git a/MailResources/Localizable/fr.lproj/Localizable.strings b/MailResources/Localizable/fr.lproj/Localizable.strings index 52b640e14..865ffc5fc 100644 --- a/MailResources/Localizable/fr.lproj/Localizable.strings +++ b/MailResources/Localizable/fr.lproj/Localizable.strings @@ -3,8 +3,8 @@ * Project: kMail * Locale: fr, French * Tagged: ios - * Exported by: elena willen - * Exported at: Wed, 04 Sep 2024 11:22:24 +0200 + * Exported by: Matthieu Déglon + * Exported at: Wed, 11 Sep 2024 15:20:23 +0200 */ /* loco:62bb154d7513e127cb2e9c94 */ @@ -283,6 +283,12 @@ /* loco:6266649755d41301973d0c43 */ "bccTitle" = "Cci :"; +/* loco:669a5cc96c0dbf9fe909b662 */ +"blockAnExpeditorTitle" = "Bloquer un expéditeur"; + +/* loco:66dee0ef5c6d656046044445 */ +"blockExpeditorTitle" = "Bloquer %s"; + /* loco:649ea00ef9c6ecfe620a0b62 */ "blockedPasswordTitle" = "Mot de passe bloqué"; @@ -334,6 +340,9 @@ /* loco:651ebd40ccc14ebdca0313a5 */ "buttonBackToApp" = "Retour à l’application Mail"; +/* loco:66db0113e0da22884c09f724 */ +"buttonBlockAnExpeditor" = "Bloquer"; + /* loco:62b2d43771635f1d1f0da462 */ "buttonBold" = "Gras"; @@ -409,9 +418,6 @@ /* loco:6425777e2343387912223aa2 */ "buttonLater" = "Plus tard"; -/* loco:665868ebce4392ec5d0e94f2 */ -"buttonLink" = "Ajouter un lien hypertexte"; - /* loco:645b485e158c37a429012092 */ "buttonLoadMore" = "Charger plus de conversations"; @@ -538,6 +544,9 @@ /* loco:63a473bcf3bb7f422358cfd2 */ "confirmLogoutTitle" = "Me déconnecter"; +/* loco:66db00746332bbedae01f2f2 */ +"confirmationToBlockAnExpeditorText" = "Cet e-mail et tous les futurs messages de %s seront déplacés dans le dossier Courrier indésirable."; + /* loco:62737dea7bd28e302301e5c2 */ "contactActionAddToContacts" = "Ajouter aux contacts"; diff --git a/MailResources/Localizable/it.lproj/Localizable.strings b/MailResources/Localizable/it.lproj/Localizable.strings index 06ee2ac91..711474f1a 100644 --- a/MailResources/Localizable/it.lproj/Localizable.strings +++ b/MailResources/Localizable/it.lproj/Localizable.strings @@ -3,8 +3,8 @@ * Project: kMail * Locale: it, Italian * Tagged: ios - * Exported by: elena willen - * Exported at: Wed, 04 Sep 2024 11:22:24 +0200 + * Exported by: Matthieu Déglon + * Exported at: Wed, 11 Sep 2024 15:20:23 +0200 */ /* loco:62bb154d7513e127cb2e9c94 */ @@ -283,6 +283,12 @@ /* loco:6266649755d41301973d0c43 */ "bccTitle" = "Bcc:"; +/* loco:669a5cc96c0dbf9fe909b662 */ +"blockAnExpeditorTitle" = "Blocca un mittente"; + +/* loco:66dee0ef5c6d656046044445 */ +"blockExpeditorTitle" = "Blocca %s"; + /* loco:649ea00ef9c6ecfe620a0b62 */ "blockedPasswordTitle" = "Password bloccata"; @@ -334,6 +340,9 @@ /* loco:651ebd40ccc14ebdca0313a5 */ "buttonBackToApp" = "Torna all’applicazione Mail"; +/* loco:66db0113e0da22884c09f724 */ +"buttonBlockAnExpeditor" = "Blocca"; + /* loco:62b2d43771635f1d1f0da462 */ "buttonBold" = "In grassetto"; @@ -409,9 +418,6 @@ /* loco:6425777e2343387912223aa2 */ "buttonLater" = "Più tardi"; -/* loco:665868ebce4392ec5d0e94f2 */ -"buttonLink" = "Aggiungere un collegamento ipertestuale"; - /* loco:645b485e158c37a429012092 */ "buttonLoadMore" = "Carica altre conversazioni"; @@ -538,6 +544,9 @@ /* loco:63a473bcf3bb7f422358cfd2 */ "confirmLogoutTitle" = "Disconnettersi"; +/* loco:66db00746332bbedae01f2f2 */ +"confirmationToBlockAnExpeditorText" = "Questa e-mail e tutti i futuri messaggi di %s saranno spostati nella cartella della posta indesiderata."; + /* loco:62737dea7bd28e302301e5c2 */ "contactActionAddToContacts" = "Aggiungi ai contatti";