From c72eb4c5dc65b5583cbbc4f2e6c8619fb463643b Mon Sep 17 00:00:00 2001 From: Elena Willen Date: Wed, 16 Aug 2023 10:14:52 +0200 Subject: [PATCH 01/20] feat(ThreaView): Add external tag --- Mail/Views/Thread/ThreadView.swift | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/Mail/Views/Thread/ThreadView.swift b/Mail/Views/Thread/ThreadView.swift index 540683f01..a5bcd0c0d 100644 --- a/Mail/Views/Thread/ThreadView.swift +++ b/Mail/Views/Thread/ThreadView.swift @@ -60,14 +60,26 @@ struct ThreadView: View { } .frame(width: 0, height: 0) - Text(thread.formattedSubject) - .textStyle(.header2) - .frame(maxWidth: .infinity, alignment: .leading) - .multilineTextAlignment(.leading) - .lineSpacing(8) - .padding(.top, 8) - .padding(.bottom, 16) - .padding(.horizontal, 16) + HStack(alignment: .bottom, spacing: 0) { + Text(thread.formattedSubject) + .textStyle(.header2) + .frame(maxWidth: .infinity, alignment: .leading) + .multilineTextAlignment(.leading) + .lineSpacing(8) + + Button { + //TODO: add action + } label: { + Text(MailResourcesStrings.Localizable.externalTag) + .textStyle(.labelMedium) + .padding(4) + .background(MailResourcesAsset.yellowColor.swiftUIColor) + .cornerRadius(2) + } + } + .padding(.top, 8) + .padding(.bottom, 16) + .padding(.horizontal, 16) MessageListView(messages: thread.messages) } From b03a25e2c060d7e0566dc7f0388d8a5673f5b0ad Mon Sep 17 00:00:00 2001 From: Elena Willen Date: Wed, 16 Aug 2023 16:54:18 +0200 Subject: [PATCH 02/20] feat: Create alert ExternalExpeditorView --- Mail/Views/Alerts/ExternalExpeditorView.swift | 43 +++++++++++++++++++ .../New Message/ComposeMessageView.swift | 3 ++ .../General/SettingsNotificationsView.swift | 2 +- Mail/Views/Thread/ThreadView.swift | 12 +++++- 4 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 Mail/Views/Alerts/ExternalExpeditorView.swift diff --git a/Mail/Views/Alerts/ExternalExpeditorView.swift b/Mail/Views/Alerts/ExternalExpeditorView.swift new file mode 100644 index 000000000..915e89de8 --- /dev/null +++ b/Mail/Views/Alerts/ExternalExpeditorView.swift @@ -0,0 +1,43 @@ +/* + Infomaniak Mail - iOS App + Copyright (C) 2022 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 MailResources +import RealmSwift +import SwiftUI + +struct ExternalExpeditorView: View { + @Environment(\.dismiss) private var dismiss + + var body: some View { + VStack(alignment: .leading, spacing: 24) { + Text(MailResourcesStrings.Localizable.externalDialogTitleExpeditor) + .textStyle(.bodyMedium) + Text(MailResourcesStrings.Localizable.externalDialogDescriptionPlural) + .textStyle(.bodySecondary) + ModalButtonsView(primaryButtonTitle: MailResourcesStrings.Localizable.externalDialogConfirmButton, secondaryButtonTitle: nil) { + dismiss() + } + } + } +} + +struct ExternalExpeditorView_Previews: PreviewProvider { + static var previews: some View { + ExternalExpeditorView() + } +} diff --git a/Mail/Views/New Message/ComposeMessageView.swift b/Mail/Views/New Message/ComposeMessageView.swift index da5d65852..e91d2966f 100644 --- a/Mail/Views/New Message/ComposeMessageView.swift +++ b/Mail/Views/New Message/ComposeMessageView.swift @@ -55,6 +55,7 @@ final class NewMessageAlert: SheetState { enum State { case link(handler: (String) -> Void) case emptySubject(handler: () -> Void) + case externalExpeditor } } @@ -159,6 +160,8 @@ struct ComposeMessageView: View { AddLinkView(actionHandler: handler) case .emptySubject(let handler): EmptySubjectView(actionHandler: handler) + case .externalExpeditor : + ExternalExpeditorView() case .none: EmptyView() } diff --git a/Mail/Views/Settings/General/SettingsNotificationsView.swift b/Mail/Views/Settings/General/SettingsNotificationsView.swift index a406a86f6..bcd754e2c 100644 --- a/Mail/Views/Settings/General/SettingsNotificationsView.swift +++ b/Mail/Views/Settings/General/SettingsNotificationsView.swift @@ -144,7 +144,7 @@ struct SettingsNotificationsView: View { func updateTopicsForCurrentUserIfNeeded() { Task { guard let subscribedTopics else { return } - + await notificationService.updateTopicsIfNeeded(subscribedTopics, userApiFetcher: mailboxManager.apiFetcher) } } diff --git a/Mail/Views/Thread/ThreadView.swift b/Mail/Views/Thread/ThreadView.swift index a5bcd0c0d..3cda85a45 100644 --- a/Mail/Views/Thread/ThreadView.swift +++ b/Mail/Views/Thread/ThreadView.swift @@ -45,6 +45,8 @@ struct ThreadView: View { @State private var displayNavigationTitle = false @State private var replyOrReplyAllMessage: Message? + @StateObject private var alert = NewMessageAlert() + @ObservedRealmObject var thread: Thread private let toolbarActions: [Action] = [.reply, .forward, .archive, .delete] @@ -68,7 +70,7 @@ struct ThreadView: View { .lineSpacing(8) Button { - //TODO: add action + alert.state = .externalExpeditor } label: { Text(MailResourcesStrings.Localizable.externalTag) .textStyle(.labelMedium) @@ -159,6 +161,14 @@ struct ThreadView: View { // Dismiss on iPhone only dismiss() } + .customAlert(isPresented: $alert.isShowing) { + switch alert.state { + case .externalExpeditor: + ExternalExpeditorView() + default: + EmptyView() + } + } .matomoView(view: [MatomoUtils.View.threadView.displayName, "Main"]) } From ab84e30ea6373a4cd7a25c58b0923e43173eb868 Mon Sep 17 00:00:00 2001 From: Elena Willen Date: Mon, 21 Aug 2023 13:23:22 +0200 Subject: [PATCH 03/20] feat: Add onTagColor --- Mail/Views/Thread/ThreadView.swift | 1 + .../Colors/onTagColor.colorset/Contents.json | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 MailResources/Assets.xcassets/Colors/onTagColor.colorset/Contents.json diff --git a/Mail/Views/Thread/ThreadView.swift b/Mail/Views/Thread/ThreadView.swift index 3cda85a45..fcde6129e 100644 --- a/Mail/Views/Thread/ThreadView.swift +++ b/Mail/Views/Thread/ThreadView.swift @@ -73,6 +73,7 @@ struct ThreadView: View { alert.state = .externalExpeditor } label: { Text(MailResourcesStrings.Localizable.externalTag) + .foregroundColor(MailResourcesAsset.onTagColor.swiftUIColor) .textStyle(.labelMedium) .padding(4) .background(MailResourcesAsset.yellowColor.swiftUIColor) diff --git a/MailResources/Assets.xcassets/Colors/onTagColor.colorset/Contents.json b/MailResources/Assets.xcassets/Colors/onTagColor.colorset/Contents.json new file mode 100644 index 000000000..be3a0c974 --- /dev/null +++ b/MailResources/Assets.xcassets/Colors/onTagColor.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x33", + "green" : "0x33", + "red" : "0x33" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} From 9715cccdac4622efd175ad71e5e590f312d91ae8 Mon Sep 17 00:00:00 2001 From: Elena Willen Date: Mon, 21 Aug 2023 13:25:32 +0200 Subject: [PATCH 04/20] feat: Create bottom banner --- .../New Message/ComposeMessageView.swift | 33 +++++++++++++++++++ .../info.imageset/Contents.json | 15 +++++++++ .../Assets.xcassets/info.imageset/info.svg | 6 ++++ 3 files changed, 54 insertions(+) create mode 100644 MailResources/Assets.xcassets/info.imageset/Contents.json create mode 100644 MailResources/Assets.xcassets/info.imageset/info.svg diff --git a/Mail/Views/New Message/ComposeMessageView.swift b/Mail/Views/New Message/ComposeMessageView.swift index e91d2966f..40f14392a 100644 --- a/Mail/Views/New Message/ComposeMessageView.swift +++ b/Mail/Views/New Message/ComposeMessageView.swift @@ -73,6 +73,7 @@ struct ComposeMessageView: View { @State private var editorFocus = false @State private var currentSignature: Signature? @State private var initialAttachments = [Attachable]() + @State private var showExternalTag = true @State private var editorModel = RichTextEditorModel() @State private var scrollView: UIScrollView? @@ -243,6 +244,38 @@ struct ComposeMessageView: View { .disabled(isSendButtonDisabled) } } + .safeAreaInset(edge: .bottom) { + if showExternalTag { + HStack(spacing: 24) { + Text(MailResourcesStrings.Localizable.externalDialogTitleRecipient) + .foregroundColor(MailResourcesAsset.onTagColor.swiftUIColor) + .textStyle(.bodySmall) + + Spacer() + + Button { + alert.state = .externalExpeditor + } label: { + MailResourcesAsset.info.swiftUIImage + .resizable() + .foregroundColor(MailResourcesAsset.onTagColor) + .frame(width: 16, height: 16) + } + + Button { + showExternalTag = false + } label: { + MailResourcesAsset.closeSmall.swiftUIImage + .resizable() + .foregroundColor(MailResourcesAsset.onTagColor) + .frame(width: 16, height: 16) + } + } + .frame(maxWidth: .infinity) + .padding() + .background(MailResourcesAsset.yellowColor.swiftUIColor) + } + } } /// Progress view diff --git a/MailResources/Assets.xcassets/info.imageset/Contents.json b/MailResources/Assets.xcassets/info.imageset/Contents.json new file mode 100644 index 000000000..329199522 --- /dev/null +++ b/MailResources/Assets.xcassets/info.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "info.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/MailResources/Assets.xcassets/info.imageset/info.svg b/MailResources/Assets.xcassets/info.imageset/info.svg new file mode 100644 index 000000000..b50a065b0 --- /dev/null +++ b/MailResources/Assets.xcassets/info.imageset/info.svg @@ -0,0 +1,6 @@ + + + + + + From 24f866b8708c64559d5cf4b458255f52700493e2 Mon Sep 17 00:00:00 2001 From: Elena Willen Date: Thu, 24 Aug 2023 16:30:12 +0200 Subject: [PATCH 05/20] feat: Update Endpoint --- MailCore/API/Endpoint.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MailCore/API/Endpoint.swift b/MailCore/API/Endpoint.swift index 0f52708bd..d1afb1f8b 100644 --- a/MailCore/API/Endpoint.swift +++ b/MailCore/API/Endpoint.swift @@ -52,7 +52,7 @@ public extension Endpoint { static var mailboxes: Endpoint { return .base.appending( path: "/mailbox", - queryItems: [URLQueryItem(name: "with", value: "unseen")] + queryItems: [URLQueryItem(name: "with", value: "unseen,aliases,external_mail_flag_enabled")] ) } From 4ea8282e8ef8f8120d1a7deff64a9174b8289de9 Mon Sep 17 00:00:00 2001 From: Elena Willen Date: Thu, 24 Aug 2023 16:32:15 +0200 Subject: [PATCH 06/20] feat: Update Mailbox model with new properties --- Mail/Helpers/PreviewHelper.swift | 4 +++- MailCore/Models/Mailbox.swift | 10 +++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Mail/Helpers/PreviewHelper.swift b/Mail/Helpers/PreviewHelper.swift index 9e63238d8..f7d784e9a 100644 --- a/Mail/Helpers/PreviewHelper.swift +++ b/Mail/Helpers/PreviewHelper.swift @@ -52,7 +52,9 @@ enum PreviewHelper { mdaVersion: "", isLimited: false, isFree: false, - dailyLimit: 999) + dailyLimit: 999, + aliases: ["test@example.com", "test@example.ch"].toRealmList(), + externalMailFlagEnabled: true) static let sampleFolder = Folder(id: "", path: "Folder", diff --git a/MailCore/Models/Mailbox.swift b/MailCore/Models/Mailbox.swift index cd60d5d51..d9e63f283 100644 --- a/MailCore/Models/Mailbox.swift +++ b/MailCore/Models/Mailbox.swift @@ -46,6 +46,8 @@ public class Mailbox: Object, Codable, Identifiable { @Persisted public var dailyLimit: Int @Persisted public var unseenMessages = 0 @Persisted public var remoteUnseenMessages: Int + @Persisted public var aliases: List + @Persisted public var externalMailFlagEnabled: Bool @Persisted public var userId = 0 { didSet { objectId = MailboxInfosManager.getObjectId(mailboxId: mailboxId, userId: userId) @@ -88,6 +90,8 @@ public class Mailbox: Object, Codable, Identifiable { case isFree case dailyLimit case remoteUnseenMessages = "unseenMessages" + case aliases + case externalMailFlagEnabled } public convenience init( @@ -109,7 +113,9 @@ public class Mailbox: Object, Codable, Identifiable { mdaVersion: String, isLimited: Bool, isFree: Bool, - dailyLimit: Int + dailyLimit: Int, + aliases: List, + externalMailFlagEnabled: Bool ) { self.init() @@ -132,6 +138,8 @@ public class Mailbox: Object, Codable, Identifiable { self.isLimited = isLimited self.isFree = isFree self.dailyLimit = dailyLimit + self.aliases = aliases + self.externalMailFlagEnabled = externalMailFlagEnabled } } From 8e26ac24f7e48c8ff77f7dafac98370655eeb94b Mon Sep 17 00:00:00 2001 From: Elena Willen Date: Thu, 24 Aug 2023 16:32:55 +0200 Subject: [PATCH 07/20] feat: Create isExternal function --- MailCore/Models/Recipient.swift | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/MailCore/Models/Recipient.swift b/MailCore/Models/Recipient.swift index 3b5c5cd9d..6567e0606 100644 --- a/MailCore/Models/Recipient.swift +++ b/MailCore/Models/Recipient.swift @@ -85,6 +85,21 @@ public final class Recipient: EmbeddedObject, Codable { return email == recipient.email && name == recipient.name } + public func isExternal(mailboxManager: MailboxManager) -> Bool { + let trustedDomains = ["@infomaniak.com", "@infomaniak.event", "@swisstransfer.com"] + let isKnownDomain = trustedDomains.contains { domain in + return email.hasSuffix(domain) + } + + let isMailerDeamon = Regex(pattern: "mailer-daemon@(?:.+.)?infomaniak.ch")?.firstMatch(in: email).isEmpty ?? false ? false : true + + let isAnAlias = mailboxManager.mailbox.aliases.contains(email) + + let isContact = (mailboxManager.contactManager.contacts(matching: email)).isEmpty ? false : true + + return !isKnownDomain && !isMailerDeamon && !isAnAlias //&& !isContact + } + public var htmlDescription: String { let emailString = "<\(email)>" if name.isEmpty { From d38e521df35d3a0ac5b58e0844df725e0ef23c1f Mon Sep 17 00:00:00 2001 From: Elena Willen Date: Thu, 24 Aug 2023 16:34:02 +0200 Subject: [PATCH 08/20] feat: Rename and update ExternalRecipientView --- Mail/Views/Alerts/ExternalExpeditorView.swift | 43 ------------- Mail/Views/Alerts/ExternalRecipientView.swift | 62 +++++++++++++++++++ 2 files changed, 62 insertions(+), 43 deletions(-) delete mode 100644 Mail/Views/Alerts/ExternalExpeditorView.swift create mode 100644 Mail/Views/Alerts/ExternalRecipientView.swift diff --git a/Mail/Views/Alerts/ExternalExpeditorView.swift b/Mail/Views/Alerts/ExternalExpeditorView.swift deleted file mode 100644 index 915e89de8..000000000 --- a/Mail/Views/Alerts/ExternalExpeditorView.swift +++ /dev/null @@ -1,43 +0,0 @@ -/* - Infomaniak Mail - iOS App - Copyright (C) 2022 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 MailResources -import RealmSwift -import SwiftUI - -struct ExternalExpeditorView: View { - @Environment(\.dismiss) private var dismiss - - var body: some View { - VStack(alignment: .leading, spacing: 24) { - Text(MailResourcesStrings.Localizable.externalDialogTitleExpeditor) - .textStyle(.bodyMedium) - Text(MailResourcesStrings.Localizable.externalDialogDescriptionPlural) - .textStyle(.bodySecondary) - ModalButtonsView(primaryButtonTitle: MailResourcesStrings.Localizable.externalDialogConfirmButton, secondaryButtonTitle: nil) { - dismiss() - } - } - } -} - -struct ExternalExpeditorView_Previews: PreviewProvider { - static var previews: some View { - ExternalExpeditorView() - } -} diff --git a/Mail/Views/Alerts/ExternalRecipientView.swift b/Mail/Views/Alerts/ExternalRecipientView.swift new file mode 100644 index 000000000..e67b72082 --- /dev/null +++ b/Mail/Views/Alerts/ExternalRecipientView.swift @@ -0,0 +1,62 @@ +/* + Infomaniak Mail - iOS App + Copyright (C) 2022 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 MailCore +import MailResources +import RealmSwift +import SwiftUI + +struct ExternalRecipientView: View { + @Environment(\.dismiss) private var dismiss + + @State public var externalTagSate: DisplayExternalRecipientStatus.State + + public var isDraft: Bool + + var body: some View { + VStack(alignment: .leading, spacing: 24) { + + isDraft ? Text(MailResourcesStrings.Localizable.externalDialogTitleRecipient) + .textStyle(.bodyMedium) : Text(MailResourcesStrings.Localizable.externalDialogTitleExpeditor) + .textStyle(.bodyMedium) + + switch externalTagSate { + case .none: + EmptyView() + case .one(let recipient): + isDraft ? Text(MailResourcesStrings.Localizable.externalDialogDescriptionRecipient(recipient.email)) + .textStyle(.bodySecondary) : Text(MailResourcesStrings.Localizable.externalDialogDescriptionExpeditor(recipient.email)) + .textStyle(.bodySecondary) + case .many: + isDraft ? Text(MailResourcesStrings.Localizable.externalDialogDescriptionRecipientPlural) + .textStyle(.bodySecondary) : Text(MailResourcesStrings.Localizable.externalDialogDescriptionExpeditorPlural) + .textStyle(.bodySecondary) + } + + ModalButtonsView(primaryButtonTitle: MailResourcesStrings.Localizable.externalDialogConfirmButton, secondaryButtonTitle: nil) { + dismiss() + } + } + } +} + +struct ExternalRecipientView_Previews: PreviewProvider { + static var previews: some View { + ExternalRecipientView(externalTagSate: .many, isDraft: false) + } +} From 20d9cd23991973153c16236230601911f0177446 Mon Sep 17 00:00:00 2001 From: Elena Willen Date: Thu, 24 Aug 2023 16:41:00 +0200 Subject: [PATCH 09/20] feat: Create DisplayExternalRecipientStatus --- .../New Message/ComposeMessageView.swift | 64 ++++++++++--------- Mail/Views/Thread/ThreadView.swift | 28 ++++---- MailCore/Models/Draft.swift | 16 +++++ MailCore/Models/Thread.swift | 8 +++ .../DisplayExternalRecipientStatus.swift | 60 +++++++++++++++++ 5 files changed, 136 insertions(+), 40 deletions(-) create mode 100644 MailCore/Utils/Model/DisplayExternalRecipientStatus.swift diff --git a/Mail/Views/New Message/ComposeMessageView.swift b/Mail/Views/New Message/ComposeMessageView.swift index 40f14392a..089bf8bb7 100644 --- a/Mail/Views/New Message/ComposeMessageView.swift +++ b/Mail/Views/New Message/ComposeMessageView.swift @@ -55,7 +55,7 @@ final class NewMessageAlert: SheetState { enum State { case link(handler: (String) -> Void) case emptySubject(handler: () -> Void) - case externalExpeditor + case externalRecipient(state: DisplayExternalRecipientStatus.State) } } @@ -161,8 +161,8 @@ struct ComposeMessageView: View { AddLinkView(actionHandler: handler) case .emptySubject(let handler): EmptySubjectView(actionHandler: handler) - case .externalExpeditor : - ExternalExpeditorView() + case .externalRecipient(let state): + ExternalRecipientView(externalTagSate: state, isDraft: true) case .none: EmptyView() } @@ -246,34 +246,40 @@ struct ComposeMessageView: View { } .safeAreaInset(edge: .bottom) { if showExternalTag { - HStack(spacing: 24) { - Text(MailResourcesStrings.Localizable.externalDialogTitleRecipient) - .foregroundColor(MailResourcesAsset.onTagColor.swiftUIColor) - .textStyle(.bodySmall) - - Spacer() - - Button { - alert.state = .externalExpeditor - } label: { - MailResourcesAsset.info.swiftUIImage - .resizable() - .foregroundColor(MailResourcesAsset.onTagColor) - .frame(width: 16, height: 16) - } - - Button { - showExternalTag = false - } label: { - MailResourcesAsset.closeSmall.swiftUIImage - .resizable() - .foregroundColor(MailResourcesAsset.onTagColor) - .frame(width: 16, height: 16) + let externalTag = draft.displayExternalTag(mailboxManager: mailboxManager) + switch externalTag { + case .many, .one: + HStack(spacing: 24) { + Text(MailResourcesStrings.Localizable.externalDialogTitleRecipient) + .foregroundColor(MailResourcesAsset.onTagColor.swiftUIColor) + .textStyle(.bodySmall) + + Spacer() + + Button { + alert.state = .externalRecipient(state: externalTag) + } label: { + MailResourcesAsset.info.swiftUIImage + .resizable() + .foregroundColor(MailResourcesAsset.onTagColor) + .frame(width: 16, height: 16) + } + + Button { + showExternalTag = false + } label: { + MailResourcesAsset.closeSmall.swiftUIImage + .resizable() + .foregroundColor(MailResourcesAsset.onTagColor) + .frame(width: 16, height: 16) + } } + .frame(maxWidth: .infinity) + .padding() + .background(MailResourcesAsset.yellowColor.swiftUIColor) + case .none: + EmptyView() } - .frame(maxWidth: .infinity) - .padding() - .background(MailResourcesAsset.yellowColor.swiftUIColor) } } } diff --git a/Mail/Views/Thread/ThreadView.swift b/Mail/Views/Thread/ThreadView.swift index fcde6129e..5bf24bb41 100644 --- a/Mail/Views/Thread/ThreadView.swift +++ b/Mail/Views/Thread/ThreadView.swift @@ -69,15 +69,21 @@ struct ThreadView: View { .multilineTextAlignment(.leading) .lineSpacing(8) - Button { - alert.state = .externalExpeditor - } label: { - Text(MailResourcesStrings.Localizable.externalTag) - .foregroundColor(MailResourcesAsset.onTagColor.swiftUIColor) - .textStyle(.labelMedium) - .padding(4) - .background(MailResourcesAsset.yellowColor.swiftUIColor) - .cornerRadius(2) + let externalTag = thread.displayExternalRecipientState(mailboxManager: mailboxManager, recipientsList: thread.from) + switch externalTag { + case .many, .one: + Button { + alert.state = .externalRecipient(state: externalTag) + } label: { + Text(MailResourcesStrings.Localizable.externalTag) + .foregroundColor(MailResourcesAsset.onTagColor.swiftUIColor) + .textStyle(.labelMedium) + .padding(4) + .background(MailResourcesAsset.yellowColor.swiftUIColor) + .cornerRadius(2) + } + case .none: + EmptyView() } } .padding(.top, 8) @@ -164,8 +170,8 @@ struct ThreadView: View { } .customAlert(isPresented: $alert.isShowing) { switch alert.state { - case .externalExpeditor: - ExternalExpeditorView() + case .externalRecipient(let state): + ExternalRecipientView(externalTagSate: state, isDraft: false) default: EmptyView() } diff --git a/MailCore/Models/Draft.swift b/MailCore/Models/Draft.swift index 28d031754..225915a63 100644 --- a/MailCore/Models/Draft.swift +++ b/MailCore/Models/Draft.swift @@ -298,3 +298,19 @@ public extension Draft { return available } } + +public extension Draft { + /// Compute if the draft has external recipients + func displayExternalTag(mailboxManager: MailboxManager) -> DisplayExternalRecipientStatus.State { + var recipientsList = List() + recipientsList.append(objectsIn: cc) + recipientsList.append(objectsIn: bcc) + recipientsList.append(objectsIn: to) + return displayExternalRecipientState(mailboxManager: mailboxManager, recipientsList: recipientsList) + } + + func displayExternalRecipientState(mailboxManager: MailboxManager, recipientsList: List) -> DisplayExternalRecipientStatus.State { + let externalDisplayStatus = DisplayExternalRecipientStatus(mailboxManager: mailboxManager, recipientsList: recipientsList) + return externalDisplayStatus.state + } +} diff --git a/MailCore/Models/Thread.swift b/MailCore/Models/Thread.swift index 2ef811a48..b68e4f2bb 100644 --- a/MailCore/Models/Thread.swift +++ b/MailCore/Models/Thread.swift @@ -212,6 +212,14 @@ public class Thread: Object, Decodable, Identifiable { } } +public extension Thread { + /// Compute if the thread has external recipients + func displayExternalRecipientState(mailboxManager: MailboxManager, recipientsList: List) -> DisplayExternalRecipientStatus.State { + let externalDisplayStatus = DisplayExternalRecipientStatus(mailboxManager: mailboxManager, recipientsList: recipientsList) + return externalDisplayStatus.state + } +} + public enum Filter: String { case all, seen, unseen, starred, unstarred diff --git a/MailCore/Utils/Model/DisplayExternalRecipientStatus.swift b/MailCore/Utils/Model/DisplayExternalRecipientStatus.swift new file mode 100644 index 000000000..792198080 --- /dev/null +++ b/MailCore/Utils/Model/DisplayExternalRecipientStatus.swift @@ -0,0 +1,60 @@ +/* + Infomaniak Mail - iOS App + Copyright (C) 2022 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 RealmSwift + +public struct DisplayExternalRecipientStatus { + public enum State { + case none + case one(recipient: Recipient) + case many + } + + let mailboxManager: MailboxManager + let recipientsList: List + + public init(mailboxManager: MailboxManager, recipientsList: List) { + self.mailboxManager = mailboxManager + self.recipientsList = recipientsList + } + + public var state: State { + var externalList = [Recipient]() + let recipients = recipientsList + for recipient in recipients { + guard externalList.count < 2 else { + break + } + + guard recipient.isExternal(mailboxManager: mailboxManager) else { + continue + } + + externalList.append(recipient) + } + + if externalList.isEmpty { + return .none + } else if let recipient = externalList.first, externalList.count == 1 { + return .one(recipient: recipient) + } else { + return .many + } + } +} From c0ec2511b1534e620f71e6c8eccde5874c2d1206 Mon Sep 17 00:00:00 2001 From: Elena Willen Date: Thu, 24 Aug 2023 16:44:22 +0200 Subject: [PATCH 10/20] fix: Remove comment for test purposes --- MailCore/Models/Recipient.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MailCore/Models/Recipient.swift b/MailCore/Models/Recipient.swift index 6567e0606..73bee2b2d 100644 --- a/MailCore/Models/Recipient.swift +++ b/MailCore/Models/Recipient.swift @@ -97,7 +97,7 @@ public final class Recipient: EmbeddedObject, Codable { let isContact = (mailboxManager.contactManager.contacts(matching: email)).isEmpty ? false : true - return !isKnownDomain && !isMailerDeamon && !isAnAlias //&& !isContact + return !isKnownDomain && !isMailerDeamon && !isAnAlias && !isContact } public var htmlDescription: String { From 1dac3154c445300525a85888ed202afca733f372 Mon Sep 17 00:00:00 2001 From: Elena Willen Date: Fri, 25 Aug 2023 10:48:27 +0200 Subject: [PATCH 11/20] feat: Update RecipientChipLabel colors --- Mail/Components/RecipientChipLabel.swift | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/Mail/Components/RecipientChipLabel.swift b/Mail/Components/RecipientChipLabel.swift index e36752e7a..a26d403da 100644 --- a/Mail/Components/RecipientChipLabel.swift +++ b/Mail/Components/RecipientChipLabel.swift @@ -18,18 +18,20 @@ import Foundation import MailCore +import MailResources import SwiftUI import UIKit struct RecipientChipLabelView: UIViewRepresentable { @Environment(\.isEnabled) private var isEnabled: Bool + @EnvironmentObject private var mailboxManager: MailboxManager let recipient: Recipient var removeHandler: (() -> Void)? var switchFocusHandler: (() -> Void)? func makeUIView(context: Context) -> RecipientChipLabel { - let label = RecipientChipLabel(recipient: recipient) + let label = RecipientChipLabel(recipient: recipient, external: recipient.isExternal(mailboxManager: mailboxManager)) label.removeHandler = removeHandler label.switchFocusHandler = switchFocusHandler label.setContentHuggingPriority(.defaultHigh, for: .horizontal) @@ -58,8 +60,9 @@ class RecipientChipLabel: UILabel, UIKeyInput { override var canBecomeFirstResponder: Bool { return isUserInteractionEnabled } var hasText = false + var isExternal = false - init(recipient: Recipient) { + init(recipient: Recipient, external: Bool) { super.init(frame: .zero) text = recipient.name.isEmpty ? recipient.email : recipient.name @@ -67,10 +70,13 @@ class RecipientChipLabel: UILabel, UIKeyInput { numberOfLines = 1 font = .systemFont(ofSize: 16) - updateColors(isFirstResponder: false) layer.cornerRadius = intrinsicContentSize.height / 2 + layer.borderWidth = 1 layer.masksToBounds = true + + isExternal = external + updateColors(isFirstResponder: false) } @available(*, unavailable) @@ -103,7 +109,14 @@ class RecipientChipLabel: UILabel, UIKeyInput { } private func updateColors(isFirstResponder: Bool) { - textColor = isFirstResponder ? UserDefaults.shared.accentColor.secondary.color : .tintColor - backgroundColor = isFirstResponder ? .tintColor : UserDefaults.shared.accentColor.secondary.color + if isExternal { + textColor = isFirstResponder ? MailResourcesAsset.onTagColor.color : MailResourcesAsset.textPrimaryColor.color + borderColor = MailResourcesAsset.yellowColor.color + backgroundColor = isFirstResponder ? MailResourcesAsset.yellowColor.color : MailResourcesAsset.textFieldColor.color + } else { + textColor = isFirstResponder ? UserDefaults.shared.accentColor.secondary.color : .tintColor + borderColor = isFirstResponder ? .tintColor : UserDefaults.shared.accentColor.secondary.color + backgroundColor = isFirstResponder ? .tintColor : UserDefaults.shared.accentColor.secondary.color + } } } From 790deb6128a00b63ef6f3a0e2aa7cd0f2e8d562e Mon Sep 17 00:00:00 2001 From: Elena Willen Date: Fri, 25 Aug 2023 14:21:50 +0200 Subject: [PATCH 12/20] feat: Update UI --- Mail/Views/Thread/ThreadView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mail/Views/Thread/ThreadView.swift b/Mail/Views/Thread/ThreadView.swift index 5bf24bb41..9fe6f2a76 100644 --- a/Mail/Views/Thread/ThreadView.swift +++ b/Mail/Views/Thread/ThreadView.swift @@ -62,7 +62,7 @@ struct ThreadView: View { } .frame(width: 0, height: 0) - HStack(alignment: .bottom, spacing: 0) { + VStack(alignment: .leading, spacing: 8) { Text(thread.formattedSubject) .textStyle(.header2) .frame(maxWidth: .infinity, alignment: .leading) From 07643bdad8f5a65410600e2825132d6acd890cd7 Mon Sep 17 00:00:00 2001 From: Elena Willen Date: Fri, 25 Aug 2023 14:42:27 +0200 Subject: [PATCH 13/20] feat: email added manually is considered as not external --- .../Header Cells/ComposeMessageCellRecipients.swift | 1 + MailCore/Cache/MailboxManager/MailboxManager.swift | 2 +- MailCore/Models/Recipient.swift | 9 +++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Mail/Views/New Message/Header Cells/ComposeMessageCellRecipients.swift b/Mail/Views/New Message/Header Cells/ComposeMessageCellRecipients.swift index 41d1b1129..927c01a57 100644 --- a/Mail/Views/New Message/Header Cells/ComposeMessageCellRecipients.swift +++ b/Mail/Views/New Message/Header Cells/ComposeMessageCellRecipients.swift @@ -127,6 +127,7 @@ struct ComposeMessageCellRecipients: View { } withAnimation { + recipient.isAddedByMe = true $recipients.append(recipient) } textDebounce.text = "" diff --git a/MailCore/Cache/MailboxManager/MailboxManager.swift b/MailCore/Cache/MailboxManager/MailboxManager.swift index e8814c2e2..f47ab69cd 100644 --- a/MailCore/Cache/MailboxManager/MailboxManager.swift +++ b/MailCore/Cache/MailboxManager/MailboxManager.swift @@ -66,7 +66,7 @@ public final class MailboxManager: ObservableObject, MailboxManageable { let realmName = "\(mailbox.userId)-\(mailbox.mailboxId).realm" realmConfiguration = Realm.Configuration( fileURL: MailboxManager.constants.rootDocumentsURL.appendingPathComponent(realmName), - schemaVersion: 18, + schemaVersion: 19, migrationBlock: { migration, oldSchemaVersion in // No migration needed from 0 to 16 if oldSchemaVersion < 17 { diff --git a/MailCore/Models/Recipient.swift b/MailCore/Models/Recipient.swift index 73bee2b2d..6c1e3727c 100644 --- a/MailCore/Models/Recipient.swift +++ b/MailCore/Models/Recipient.swift @@ -40,6 +40,12 @@ public struct RecipientHolder { public final class Recipient: EmbeddedObject, Codable { @Persisted public var email: String @Persisted public var name: String + @Persisted public var isAddedByMe = false + + enum CodingKeys: String, CodingKey { + case email + case name + } public convenience init(email: String, name: String) { self.init() @@ -86,6 +92,9 @@ public final class Recipient: EmbeddedObject, Codable { } public func isExternal(mailboxManager: MailboxManager) -> Bool { + ///if the email adress is added manually by me, it's not considered as an external + guard !isAddedByMe else { return false } + let trustedDomains = ["@infomaniak.com", "@infomaniak.event", "@swisstransfer.com"] let isKnownDomain = trustedDomains.contains { domain in return email.hasSuffix(domain) From b0fb18e247bcdc288afdf2a82f094c72c7935c07 Mon Sep 17 00:00:00 2001 From: Elena Willen Date: Fri, 25 Aug 2023 14:59:27 +0200 Subject: [PATCH 14/20] fix: border color --- Mail/Components/RecipientChipLabel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mail/Components/RecipientChipLabel.swift b/Mail/Components/RecipientChipLabel.swift index a26d403da..7e6107a91 100644 --- a/Mail/Components/RecipientChipLabel.swift +++ b/Mail/Components/RecipientChipLabel.swift @@ -115,7 +115,7 @@ class RecipientChipLabel: UILabel, UIKeyInput { backgroundColor = isFirstResponder ? MailResourcesAsset.yellowColor.color : MailResourcesAsset.textFieldColor.color } else { textColor = isFirstResponder ? UserDefaults.shared.accentColor.secondary.color : .tintColor - borderColor = isFirstResponder ? .tintColor : UserDefaults.shared.accentColor.secondary.color + borderColor = isFirstResponder ? UserDefaults.shared.accentColor.primary.color : UserDefaults.shared.accentColor.secondary.color backgroundColor = isFirstResponder ? .tintColor : UserDefaults.shared.accentColor.secondary.color } } From aad4894b7c61bc2b658b09a8a9ac7f87dbfb6c44 Mon Sep 17 00:00:00 2001 From: Elena Willen Date: Fri, 25 Aug 2023 16:03:20 +0200 Subject: [PATCH 15/20] feat: Matomo --- .../Views/New Message/ComposeMessageView.swift | 18 ++++++++++++++---- .../Recipients/FullRecipientsList.swift | 3 +++ Mail/Views/Thread/ThreadView.swift | 1 + MailCore/Utils/Matomo+Extension.swift | 11 +++++++---- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/Mail/Views/New Message/ComposeMessageView.swift b/Mail/Views/New Message/ComposeMessageView.swift index 089bf8bb7..1f8910c80 100644 --- a/Mail/Views/New Message/ComposeMessageView.swift +++ b/Mail/Views/New Message/ComposeMessageView.swift @@ -253,10 +253,11 @@ struct ComposeMessageView: View { Text(MailResourcesStrings.Localizable.externalDialogTitleRecipient) .foregroundColor(MailResourcesAsset.onTagColor.swiftUIColor) .textStyle(.bodySmall) - + Spacer() - + Button { + matomo.track(eventWithCategory: .externals, name: "bannerInfo") alert.state = .externalRecipient(state: externalTag) } label: { MailResourcesAsset.info.swiftUIImage @@ -264,8 +265,9 @@ struct ComposeMessageView: View { .foregroundColor(MailResourcesAsset.onTagColor) .frame(width: 16, height: 16) } - + Button { + matomo.track(eventWithCategory: .externals, name: "bannerManuallyClosed") showExternalTag = false } label: { MailResourcesAsset.closeSmall.swiftUIImage @@ -317,7 +319,15 @@ struct ComposeMessageView: View { } private func sendDraft() { - matomo.trackSendMessage(numberOfTo: draft.to.count, numberOfCc: draft.cc.count, numberOfBcc: draft.bcc.count) + var sentWithExternals = false + switch draft.displayExternalTag(mailboxManager: mailboxManager) { + case .one, .many: + sentWithExternals = true + case .none: + sentWithExternals = false + } + + matomo.trackSendMessage(draft: draft, sentWithExternals: sentWithExternals) if let liveDraft = draft.thaw() { try? liveDraft.realm?.write { liveDraft.action = .send diff --git a/Mail/Views/New Message/Recipients/FullRecipientsList.swift b/Mail/Views/New Message/Recipients/FullRecipientsList.swift index 5ece0bed4..c5210ba48 100644 --- a/Mail/Views/New Message/Recipients/FullRecipientsList.swift +++ b/Mail/Views/New Message/Recipients/FullRecipientsList.swift @@ -46,6 +46,9 @@ struct FullRecipientsList: View { @MainActor private func remove(recipientAt: Int) { @InjectService var matomo: MatomoUtils matomo.track(eventWithCategory: .newMessage, name: "deleteRecipient") + if recipients[recipientAt].isExternal(mailboxManager: mailboxManager) { + matomo.track(eventWithCategory: .externals, name: "deleteRecipient") + } withAnimation { $recipients.remove(at: recipientAt) diff --git a/Mail/Views/Thread/ThreadView.swift b/Mail/Views/Thread/ThreadView.swift index 9fe6f2a76..b569cdcc9 100644 --- a/Mail/Views/Thread/ThreadView.swift +++ b/Mail/Views/Thread/ThreadView.swift @@ -73,6 +73,7 @@ struct ThreadView: View { switch externalTag { case .many, .one: Button { + matomo.track(eventWithCategory: .externals, name: "threadTag") alert.state = .externalRecipient(state: externalTag) } label: { Text(MailResourcesStrings.Localizable.externalTag) diff --git a/MailCore/Utils/Matomo+Extension.swift b/MailCore/Utils/Matomo+Extension.swift index 52904eb5f..d091632fc 100644 --- a/MailCore/Utils/Matomo+Extension.swift +++ b/MailCore/Utils/Matomo+Extension.swift @@ -33,6 +33,7 @@ public extension MatomoUtils.View { public extension MatomoUtils.EventCategory { static let createFolder = MatomoUtils.EventCategory(displayName: "createFolder") + static let externals = MatomoUtils.EventCategory(displayName: "externals") static let invalidPasswordMailbox = MatomoUtils.EventCategory(displayName: "invalidPasswordMailbox") static let menuDrawer = MatomoUtils.EventCategory(displayName: "menuDrawer") static let message = MatomoUtils.EventCategory(displayName: "message") @@ -72,12 +73,14 @@ public extension MatomoUtils.EventCategory { // MARK: - Helpers public extension MatomoUtils { - func trackSendMessage(numberOfTo: Int, numberOfCc: Int, numberOfBcc: Int) { + func trackSendMessage(draft: Draft, sentWithExternals: Bool) { track(eventWithCategory: .newMessage, name: "sendMail") - track(eventWithCategory: .newMessage, action: .data, name: "numberOfTo", value: Float(numberOfTo)) - track(eventWithCategory: .newMessage, action: .data, name: "numberOfCC", value: Float(numberOfCc)) - track(eventWithCategory: .newMessage, action: .data, name: "numberOfBCC", value: Float(numberOfBcc)) + track(eventWithCategory: .newMessage, action: .data, name: "numberOfTo", value: Float(draft.to.count)) + track(eventWithCategory: .newMessage, action: .data, name: "numberOfCC", value: Float(draft.cc.count)) + track(eventWithCategory: .newMessage, action: .data, name: "numberOfBCC", value: Float(draft.bcc.count)) + + track(eventWithCategory: .externals, action: .data, name: "emailSentWithExternals", value: sentWithExternals) } } From 5b456ec6e53ebae5aca2ccbe6f60bde2dc3b991a Mon Sep 17 00:00:00 2001 From: Elena Willen Date: Fri, 25 Aug 2023 16:33:06 +0200 Subject: [PATCH 16/20] fix: Code smells --- Mail/Views/New Message/ComposeMessageView.swift | 2 +- MailCore/Models/Recipient.swift | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Mail/Views/New Message/ComposeMessageView.swift b/Mail/Views/New Message/ComposeMessageView.swift index 1f8910c80..12814e14d 100644 --- a/Mail/Views/New Message/ComposeMessageView.swift +++ b/Mail/Views/New Message/ComposeMessageView.swift @@ -319,7 +319,7 @@ struct ComposeMessageView: View { } private func sendDraft() { - var sentWithExternals = false + let sentWithExternals: Bool switch draft.displayExternalTag(mailboxManager: mailboxManager) { case .one, .many: sentWithExternals = true diff --git a/MailCore/Models/Recipient.swift b/MailCore/Models/Recipient.swift index 6c1e3727c..0c6dd3524 100644 --- a/MailCore/Models/Recipient.swift +++ b/MailCore/Models/Recipient.swift @@ -100,11 +100,12 @@ public final class Recipient: EmbeddedObject, Codable { return email.hasSuffix(domain) } - let isMailerDeamon = Regex(pattern: "mailer-daemon@(?:.+.)?infomaniak.ch")?.firstMatch(in: email).isEmpty ?? false ? false : true + guard let regex = Regex(pattern: "mailer-daemon@(?:.+.)?infomaniak.ch") else { return false } + let isMailerDeamon = !regex.firstMatch(in: email).isEmpty let isAnAlias = mailboxManager.mailbox.aliases.contains(email) - let isContact = (mailboxManager.contactManager.contacts(matching: email)).isEmpty ? false : true + let isContact = !(mailboxManager.contactManager.contacts(matching: email)).isEmpty return !isKnownDomain && !isMailerDeamon && !isAnAlias && !isContact } From 5812f6f1a807b928029303a1a2afb02b0073fd2b Mon Sep 17 00:00:00 2001 From: Elena Date: Mon, 28 Aug 2023 11:50:37 +0200 Subject: [PATCH 17/20] Update Mail/Views/Thread/ThreadView.swift Co-authored-by: Valentin Perignon --- Mail/Views/Thread/ThreadView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mail/Views/Thread/ThreadView.swift b/Mail/Views/Thread/ThreadView.swift index b569cdcc9..16e4e9839 100644 --- a/Mail/Views/Thread/ThreadView.swift +++ b/Mail/Views/Thread/ThreadView.swift @@ -77,7 +77,7 @@ struct ThreadView: View { alert.state = .externalRecipient(state: externalTag) } label: { Text(MailResourcesStrings.Localizable.externalTag) - .foregroundColor(MailResourcesAsset.onTagColor.swiftUIColor) + .foregroundColor(MailResourcesAsset.onTagColor) .textStyle(.labelMedium) .padding(4) .background(MailResourcesAsset.yellowColor.swiftUIColor) From 69230c08d701809b2624e64402f1400677f4ad3f Mon Sep 17 00:00:00 2001 From: Elena Date: Mon, 28 Aug 2023 11:50:51 +0200 Subject: [PATCH 18/20] Update Mail/Views/New Message/ComposeMessageView.swift Co-authored-by: Valentin Perignon --- Mail/Views/New Message/ComposeMessageView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mail/Views/New Message/ComposeMessageView.swift b/Mail/Views/New Message/ComposeMessageView.swift index 12814e14d..ddfd15f99 100644 --- a/Mail/Views/New Message/ComposeMessageView.swift +++ b/Mail/Views/New Message/ComposeMessageView.swift @@ -251,7 +251,7 @@ struct ComposeMessageView: View { case .many, .one: HStack(spacing: 24) { Text(MailResourcesStrings.Localizable.externalDialogTitleRecipient) - .foregroundColor(MailResourcesAsset.onTagColor.swiftUIColor) + .foregroundColor(MailResourcesAsset.onTagColor) .textStyle(.bodySmall) Spacer() From 63075b76259c5558d5f474a4753027ae3190ad31 Mon Sep 17 00:00:00 2001 From: Elena Willen Date: Mon, 28 Aug 2023 14:03:27 +0200 Subject: [PATCH 19/20] fix: feedbacks --- Mail/Views/Alerts/ExternalRecipientView.swift | 4 +--- Mail/Views/New Message/ComposeMessageView.swift | 8 ++++---- MailCore/Models/Recipient.swift | 10 ++++++++-- .../Utils/Model/DisplayExternalRecipientStatus.swift | 5 ----- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/Mail/Views/Alerts/ExternalRecipientView.swift b/Mail/Views/Alerts/ExternalRecipientView.swift index e67b72082..22543af98 100644 --- a/Mail/Views/Alerts/ExternalRecipientView.swift +++ b/Mail/Views/Alerts/ExternalRecipientView.swift @@ -24,13 +24,11 @@ import SwiftUI struct ExternalRecipientView: View { @Environment(\.dismiss) private var dismiss - @State public var externalTagSate: DisplayExternalRecipientStatus.State - + public var externalTagSate: DisplayExternalRecipientStatus.State public var isDraft: Bool var body: some View { VStack(alignment: .leading, spacing: 24) { - isDraft ? Text(MailResourcesStrings.Localizable.externalDialogTitleRecipient) .textStyle(.bodyMedium) : Text(MailResourcesStrings.Localizable.externalDialogTitleExpeditor) .textStyle(.bodyMedium) diff --git a/Mail/Views/New Message/ComposeMessageView.swift b/Mail/Views/New Message/ComposeMessageView.swift index ddfd15f99..50344804a 100644 --- a/Mail/Views/New Message/ComposeMessageView.swift +++ b/Mail/Views/New Message/ComposeMessageView.swift @@ -73,7 +73,7 @@ struct ComposeMessageView: View { @State private var editorFocus = false @State private var currentSignature: Signature? @State private var initialAttachments = [Attachable]() - @State private var showExternalTag = true + @State private var isShowingExternalTag = true @State private var editorModel = RichTextEditorModel() @State private var scrollView: UIScrollView? @@ -245,7 +245,7 @@ struct ComposeMessageView: View { } } .safeAreaInset(edge: .bottom) { - if showExternalTag { + if isShowingExternalTag { let externalTag = draft.displayExternalTag(mailboxManager: mailboxManager) switch externalTag { case .many, .one: @@ -268,7 +268,7 @@ struct ComposeMessageView: View { Button { matomo.track(eventWithCategory: .externals, name: "bannerManuallyClosed") - showExternalTag = false + isShowingExternalTag = false } label: { MailResourcesAsset.closeSmall.swiftUIImage .resizable() @@ -277,7 +277,7 @@ struct ComposeMessageView: View { } } .frame(maxWidth: .infinity) - .padding() + .padding(16) .background(MailResourcesAsset.yellowColor.swiftUIColor) case .none: EmptyView() diff --git a/MailCore/Models/Recipient.swift b/MailCore/Models/Recipient.swift index 0c6dd3524..d9b066d8c 100644 --- a/MailCore/Models/Recipient.swift +++ b/MailCore/Models/Recipient.swift @@ -91,6 +91,8 @@ public final class Recipient: EmbeddedObject, Codable { return email == recipient.email && name == recipient.name } + private static let mailerDeamonRegex = Regex(pattern: "mailer-daemon@(?:.+.)?infomaniak.ch") + public func isExternal(mailboxManager: MailboxManager) -> Bool { ///if the email adress is added manually by me, it's not considered as an external guard !isAddedByMe else { return false } @@ -100,8 +102,12 @@ public final class Recipient: EmbeddedObject, Codable { return email.hasSuffix(domain) } - guard let regex = Regex(pattern: "mailer-daemon@(?:.+.)?infomaniak.ch") else { return false } - let isMailerDeamon = !regex.firstMatch(in: email).isEmpty + let isMailerDeamon: Bool + if let regex = Self.mailerDeamonRegex { + isMailerDeamon = !regex.firstMatch(in: email).isEmpty + } else { + isMailerDeamon = false + } let isAnAlias = mailboxManager.mailbox.aliases.contains(email) diff --git a/MailCore/Utils/Model/DisplayExternalRecipientStatus.swift b/MailCore/Utils/Model/DisplayExternalRecipientStatus.swift index 792198080..3ec9b836c 100644 --- a/MailCore/Utils/Model/DisplayExternalRecipientStatus.swift +++ b/MailCore/Utils/Model/DisplayExternalRecipientStatus.swift @@ -29,11 +29,6 @@ public struct DisplayExternalRecipientStatus { let mailboxManager: MailboxManager let recipientsList: List - public init(mailboxManager: MailboxManager, recipientsList: List) { - self.mailboxManager = mailboxManager - self.recipientsList = recipientsList - } - public var state: State { var externalList = [Recipient]() let recipients = recipientsList From 3e43f3423b94571c56df177e740fd38e150d110d Mon Sep 17 00:00:00 2001 From: Elena Willen Date: Tue, 29 Aug 2023 11:23:24 +0200 Subject: [PATCH 20/20] fix: Chip color not updated on delete --- Mail/Components/RecipientChipLabel.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Mail/Components/RecipientChipLabel.swift b/Mail/Components/RecipientChipLabel.swift index 7e6107a91..a5415c0a5 100644 --- a/Mail/Components/RecipientChipLabel.swift +++ b/Mail/Components/RecipientChipLabel.swift @@ -42,7 +42,9 @@ struct RecipientChipLabelView: UIViewRepresentable { func updateUIView(_ uiLabel: RecipientChipLabel, context: Context) { uiLabel.text = recipient.name.isEmpty ? recipient.email : recipient.name + uiLabel.isExternal = recipient.isExternal(mailboxManager: mailboxManager) uiLabel.isUserInteractionEnabled = isEnabled + uiLabel.updateColors(isFirstResponder: uiLabel.isFirstResponder) } } @@ -108,7 +110,7 @@ class RecipientChipLabel: UILabel, UIKeyInput { removeHandler?() } - private func updateColors(isFirstResponder: Bool) { + public func updateColors(isFirstResponder: Bool) { if isExternal { textColor = isFirstResponder ? MailResourcesAsset.onTagColor.color : MailResourcesAsset.textPrimaryColor.color borderColor = MailResourcesAsset.yellowColor.color