Skip to content

Commit

Permalink
Merge pull request #1252 from Infomaniak/compose-view-init-refactor
Browse files Browse the repository at this point in the history
refactor: Compose view init
  • Loading branch information
valentinperignon committed Jan 31, 2024
2 parents 6d8d9f4 + c141657 commit 2ae150a
Show file tree
Hide file tree
Showing 27 changed files with 370 additions and 206 deletions.
39 changes: 33 additions & 6 deletions Mail/Utils/DraftUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,55 @@
*/

import Foundation
import InfomaniakCoreUI
import InfomaniakDI
import MailCore
import SwiftUI

@MainActor
enum DraftUtils {
public static func editDraft(from thread: Thread, mailboxManager: MailboxManageable, editedDraft: Binding<EditedDraft?>) {
public static func editDraft(
from thread: Thread,
mailboxManager: MailboxManageable,
composeMessageIntent: Binding<ComposeMessageIntent?>
) {
guard let message = thread.messages.first else { return }
// If we already have the draft locally, present it directly
if let draft = mailboxManager.draft(messageUid: message.uid, using: nil)?.detached() {
editedDraft.wrappedValue = EditedDraft.existing(draft: draft)
matomoOpenDraft(isLoadedRemotely: false)
composeMessageIntent.wrappedValue = ComposeMessageIntent.existing(draft: draft, originMailboxManager: mailboxManager)
} else {
DraftUtils.editDraft(from: message, mailboxManager: mailboxManager, editedDraft: editedDraft)
DraftUtils.editDraft(from: message, mailboxManager: mailboxManager, composeMessageIntent: composeMessageIntent)
}
}

public static func editDraft(from message: Message, mailboxManager: MailboxManageable, editedDraft: Binding<EditedDraft?>) {
public static func editDraft(
from message: Message,
mailboxManager: MailboxManageable,
composeMessageIntent: Binding<ComposeMessageIntent?>
) {
// If we already have the draft locally, present it directly
if let draft = mailboxManager.draft(messageUid: message.uid, using: nil)?.detached() {
editedDraft.wrappedValue = EditedDraft.existing(draft: draft)
matomoOpenDraft(isLoadedRemotely: false)
composeMessageIntent.wrappedValue = ComposeMessageIntent.existing(draft: draft, originMailboxManager: mailboxManager)
// Draft comes from API, we will update it after showing the ComposeMessageView
} else {
editedDraft.wrappedValue = EditedDraft.existing(draft: Draft(messageUid: message.uid))
matomoOpenDraft(isLoadedRemotely: true)
composeMessageIntent.wrappedValue = ComposeMessageIntent.existingRemote(
messageUid: message.uid,
originMailboxManager: mailboxManager
)
}
}

private static func matomoOpenDraft(isLoadedRemotely: Bool) {
@InjectService var matomo: MatomoUtils
matomo.track(eventWithCategory: .newMessage, name: "openFromDraft")
matomo.track(
eventWithCategory: .newMessage,
action: .data,
name: "openLocalDraft",
value: !isLoadedRemotely
)
}
}
2 changes: 1 addition & 1 deletion Mail/Utils/ShortcutModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ struct ShortcutModifier: ViewModifier {
private func shortcutNewMessage() {
matomo.track(eventWithCategory: .keyboardShortcutActions, action: .input, name: "newMessage")

mainViewState.editedDraft = EditedDraft.new()
mainViewState.composeMessageIntent = .new(originMailboxManager: viewModel.mailboxManager)
}

private func shortcutRefresh() {
Expand Down
13 changes: 5 additions & 8 deletions Mail/Views/AI Writer/AIModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ final class AIModel: ObservableObject {
private let mailboxManager: MailboxManager
private let draftContentManager: DraftContentManager
private let draft: Draft
private var messageReply: MessageReply?

private var contextId: String?
private var recipientsList: String?
Expand All @@ -72,15 +71,13 @@ final class AIModel: ObservableObject {
}
}

var isReplying: Bool {
messageReply?.isReplying == true
}
var isReplying: Bool

init(mailboxManager: MailboxManager, draftContentManager: DraftContentManager, editedDraft: EditedDraft) {
init(mailboxManager: MailboxManager, draftContentManager: DraftContentManager, draft: Draft, isReplying: Bool) {
self.mailboxManager = mailboxManager
self.draftContentManager = draftContentManager
draft = editedDraft.detachedDraft
messageReply = editedDraft.messageReply
self.draft = draft
self.isReplying = isReplying
}
}

Expand Down Expand Up @@ -194,7 +191,7 @@ extension AIModel {
// If the context is too long, we must remove it so that the user can use
// the AI assistant without context for future trials
if self.error == .contextMaxSyntaxTokensReached {
messageReply = nil
isReplying = false
}
}

Expand Down
3 changes: 2 additions & 1 deletion Mail/Views/AI Writer/Prompt/AIPromptView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ struct AIPromptView: View {
AIPromptView(aiModel: AIModel(
mailboxManager: PreviewHelper.sampleMailboxManager,
draftContentManager: PreviewHelper.sampleDraftContentManager,
editedDraft: EditedDraft.new()
draft: Draft(),
isReplying: false
))
}
3 changes: 2 additions & 1 deletion Mail/Views/AI Writer/Proposition/AIPropositionMenu.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ struct FixedMenuOrderModifier: ViewModifier {
AIPropositionMenu(aiModel: AIModel(
mailboxManager: PreviewHelper.sampleMailboxManager,
draftContentManager: PreviewHelper.sampleDraftContentManager,
editedDraft: .new()
draft: Draft(),
isReplying: false
))
}
3 changes: 2 additions & 1 deletion Mail/Views/AI Writer/Proposition/AIPropositionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ struct AIPropositionView: View {
AIPropositionView(aiModel: AIModel(
mailboxManager: PreviewHelper.sampleMailboxManager,
draftContentManager: PreviewHelper.sampleDraftContentManager,
editedDraft: .new()
draft: Draft(),
isReplying: false
))
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ struct ContactActionView: View {

private func writeEmail() {
dismiss()
mainViewState.editedDraft = EditedDraft.writing(to: recipient)
mainViewState.composeMessageIntent = .writeTo(recipient: recipient, originMailboxManager: mailboxManager)
}

private func addToContacts() {
Expand Down
2 changes: 1 addition & 1 deletion Mail/Views/New Message/ComposeMessageBodyView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ struct ComposeMessageBodyView: View {
let messageReply: MessageReply?

private var isRemoteContentBlocked: Bool {
return UserDefaults.shared.displayExternalContent == .askMe && messageReply?.message.localSafeDisplay == false
return UserDefaults.shared.displayExternalContent == .askMe && messageReply?.frozenMessage.localSafeDisplay == false
}

var body: some View {
Expand Down
114 changes: 114 additions & 0 deletions Mail/Views/New Message/ComposeMessageIntentView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
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 <http://www.gnu.org/licenses/>.
*/

import InfomaniakDI
import MailCore
import NavigationBackport
import RealmSwift
import SwiftUI

struct ComposeMessageIntentView: View {
@LazyInjectService private var accountManager: AccountManager
@LazyInjectService private var snackbarPresenter: SnackBarPresentable

@Environment(\.dismiss) private var dismiss

@State private var draft: Draft?
@State private var mailboxManager: MailboxManager?
@State private var messageReply: MessageReply?

let composeMessageIntent: ComposeMessageIntent

var body: some View {
NBNavigationStack {
if let draft,
let mailboxManager {
ComposeMessageView(draft: draft, mailboxManager: mailboxManager, messageReply: messageReply)
} else {
ProgressView()
.progressViewStyle(.circular)
}
}
.interactiveDismissDisabled()
.task(id: composeMessageIntent) {
await initFromIntent()
}
}

func initFromIntent() async {
guard let mailboxManager = accountManager.getMailboxManager(
for: composeMessageIntent.mailboxId,
userId: composeMessageIntent.userId
) else {
dismiss()
snackbarPresenter.show(message: MailError.unknownError.errorDescription ?? "")
return
}

var draftToWrite: Draft?
switch composeMessageIntent.type {
case .new:
draftToWrite = Draft(localUUID: UUID().uuidString)
case .existing(let existingDraftLocalUUID):
draftToWrite = mailboxManager.draft(localUuid: existingDraftLocalUUID)
case .existingRemote(let messageUid):
draftToWrite = Draft(messageUid: messageUid)
case .mailTo(let mailToURLComponents):
draftToWrite = Draft.mailTo(urlComponents: mailToURLComponents)
case .writeTo(let recipient):
draftToWrite = Draft.writing(to: recipient)
case .reply(let messageUid, let replyMode):
if let frozenMessage = mailboxManager.getRealm().object(ofType: Message.self, forPrimaryKey: messageUid)?.freeze() {
let messageReply = MessageReply(frozenMessage: frozenMessage, replyMode: replyMode)
self.messageReply = messageReply
draftToWrite = Draft.replying(
reply: messageReply,
currentMailboxEmail: mailboxManager.mailbox.email
)
}
}

if let draftToWrite {
let draftLocalUUID = draftToWrite.localUUID
writeDraftToRealm(mailboxManager.getRealm(), draft: draftToWrite)

Task { @MainActor in
draft = mailboxManager.draft(localUuid: draftLocalUUID)
self.mailboxManager = mailboxManager
}
} else {
dismiss()
snackbarPresenter.show(message: MailError.localMessageNotFound.errorDescription ?? "")
}
}

func writeDraftToRealm(_ realm: Realm, draft: Draft) {
try? realm.write {
draft.action = draft.action == nil && draft.remoteUUID.isEmpty ? .initialSave : .save
draft.delay = UserDefaults.shared.cancelSendDelay.rawValue

realm.add(draft, update: .modified)
}
}
}

#Preview {
ComposeMessageIntentView(
composeMessageIntent: .new(originMailboxManager: PreviewHelper.sampleMailboxManager)
)
}
Loading

0 comments on commit 2ae150a

Please sign in to comment.