From 9aaf8d5e807ffb3ce2a63b8526814abd1b9bd099 Mon Sep 17 00:00:00 2001 From: Ambroise Decouttere Date: Mon, 15 Jan 2024 15:21:18 +0100 Subject: [PATCH 1/6] fix: Show attachment when opening draft --- .../AttachmentsManagerWorker/AttachmentsManagerWorker.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/MailCore/Cache/AttachmentsManagerWorker/AttachmentsManagerWorker.swift b/MailCore/Cache/AttachmentsManagerWorker/AttachmentsManagerWorker.swift index 6f4f71450..6c8f50509 100644 --- a/MailCore/Cache/AttachmentsManagerWorker/AttachmentsManagerWorker.swift +++ b/MailCore/Cache/AttachmentsManagerWorker/AttachmentsManagerWorker.swift @@ -308,7 +308,11 @@ extension AttachmentsManagerWorker: AttachmentsManagerWorkable { guard let liveDraft else { return [] } - return liveDraft.attachments.filter { $0.contentId == nil && !$0.isInvalidated }.toArray() + return liveDraft.attachments.filter { attachment in + guard !attachment.isInvalidated else { return false } + guard let contentId = attachment.contentId else { return true } + return contentId.isEmpty + }.toArray() } public var allAttachmentsUploaded: Bool { From 2301d48737559a0c09ffe2a1812af31789fd1f35 Mon Sep 17 00:00:00 2001 From: Ambroise Decouttere Date: Thu, 18 Jan 2024 11:38:08 +0100 Subject: [PATCH 2/6] fix(ComposeMessage): Preview attachment on click --- Mail/Views/Attachment/AttachmentPreview.swift | 7 +++-- .../Attachments/AttachmentUploadCell.swift | 26 +++++++++++++++---- .../Message/Attachment/AttachmentsView.swift | 2 +- .../MailboxManager+Message.swift | 11 ++++---- MailCore/Models/Attachment.swift | 5 ++-- 5 files changed, 32 insertions(+), 19 deletions(-) diff --git a/Mail/Views/Attachment/AttachmentPreview.swift b/Mail/Views/Attachment/AttachmentPreview.swift index 68d39d17e..534472ccb 100644 --- a/Mail/Views/Attachment/AttachmentPreview.swift +++ b/Mail/Views/Attachment/AttachmentPreview.swift @@ -37,8 +37,8 @@ struct AttachmentPreview: View { var body: some View { NavigationView { Group { - if let url = attachment.localUrl, FileManager.default.fileExists(atPath: url.path) { - PreviewController(url: url) + if FileManager.default.fileExists(atPath: attachment.localUrl.path) { + PreviewController(url: attachment.localUrl) } else { ProgressView() } @@ -51,9 +51,8 @@ struct AttachmentPreview: View { ToolbarItemGroup(placement: .bottomBar) { Button { - guard let attachmentURL = attachment.localUrl else { return } matomo.track(eventWithCategory: .message, name: "download") - downloadedAttachmentURL = IdentifiableURL(url: attachmentURL) + downloadedAttachmentURL = IdentifiableURL(url: attachment.localUrl) } label: { Label { Text(MailResourcesStrings.Localizable.buttonDownload) diff --git a/Mail/Views/New Message/Attachments/AttachmentUploadCell.swift b/Mail/Views/New Message/Attachments/AttachmentUploadCell.swift index 7ee0004e1..74dab9ca8 100644 --- a/Mail/Views/New Message/Attachments/AttachmentUploadCell.swift +++ b/Mail/Views/New Message/Attachments/AttachmentUploadCell.swift @@ -23,28 +23,32 @@ import MailResources import SwiftUI struct AttachmentUploadCell: View { - private let detachedAttachment: Attachment + @EnvironmentObject private var mailboxManager: MailboxManager + + private let attachment: Attachment private let attachmentRemoved: ((Attachment) -> Void)? @ObservedObject var uploadTask: AttachmentUploadTask + @State private var previewedAttachment: Attachment? + init(uploadTask: AttachmentUploadTask, attachment: Attachment, attachmentRemoved: ((Attachment) -> Void)?) { self.uploadTask = uploadTask - detachedAttachment = attachment.detached() + self.attachment = attachment self.attachmentRemoved = attachmentRemoved } var body: some View { AttachmentView( - attachment: detachedAttachment, - subtitle: uploadTask.error != nil ? (uploadTask.error!.errorDescription ?? "") : detachedAttachment.size + attachment: attachment.detached(), + subtitle: uploadTask.error != nil ? (uploadTask.error!.errorDescription ?? "") : attachment.size .formatted(.defaultByteCount) ) { Button { if let attachmentRemoved { @InjectService var matomo: MatomoUtils matomo.track(eventWithCategory: .attachmentActions, name: "delete") - attachmentRemoved(detachedAttachment) + attachmentRemoved(attachment) } } label: { IKIcon(MailResourcesAsset.close, size: .small) @@ -56,6 +60,18 @@ struct AttachmentUploadCell: View { IndeterminateProgressView(indeterminate: uploadTask.progress == 0, progress: uploadTask.progress) .opacity(uploadTask.progress == 1 ? 0 : 1) } + .onTapGesture { + guard let attachment = attachment.thaw()?.freezeIfNeeded() else { return } + previewedAttachment = attachment + if !FileManager.default.fileExists(atPath: attachment.localUrl.path) { + Task { + await mailboxManager.saveAttachmentLocally(attachment: attachment) + } + } + } + .sheet(item: $previewedAttachment) { previewedAttachment in + AttachmentPreview(attachment: previewedAttachment) + } } } diff --git a/Mail/Views/Thread/Message/Attachment/AttachmentsView.swift b/Mail/Views/Thread/Message/Attachment/AttachmentsView.swift index b912a5009..79ce5e5ce 100644 --- a/Mail/Views/Thread/Message/Attachment/AttachmentsView.swift +++ b/Mail/Views/Thread/Message/Attachment/AttachmentsView.swift @@ -48,7 +48,7 @@ struct AttachmentsView: View { Button { matomo.track(eventWithCategory: .attachmentActions, name: "open") previewedAttachment = attachment - if !FileManager.default.fileExists(atPath: attachment.localUrl?.path ?? "") { + if !FileManager.default.fileExists(atPath: attachment.localUrl.path) { Task { await mailboxManager.saveAttachmentLocally(attachment: attachment) } diff --git a/MailCore/Cache/MailboxManager/MailboxManager+Message.swift b/MailCore/Cache/MailboxManager/MailboxManager+Message.swift index 6af8e3fdf..58c63bf1b 100644 --- a/MailCore/Cache/MailboxManager/MailboxManager+Message.swift +++ b/MailCore/Cache/MailboxManager/MailboxManager+Message.swift @@ -314,13 +314,12 @@ public extension MailboxManager { func saveAttachmentLocally(attachment: Attachment) async { do { let data = try await attachmentData(attachment) - if let url = attachment.localUrl { - let parentFolder = url.deletingLastPathComponent() - if !FileManager.default.fileExists(atPath: parentFolder.path) { - try FileManager.default.createDirectory(at: parentFolder, withIntermediateDirectories: true) - } - try data.write(to: url) + let url = attachment.localUrl + let parentFolder = url.deletingLastPathComponent() + if !FileManager.default.fileExists(atPath: parentFolder.path) { + try FileManager.default.createDirectory(at: parentFolder, withIntermediateDirectories: true) } + try data.write(to: url) } catch { // Handle error print("Failed to save attachment: \(error)") diff --git a/MailCore/Models/Attachment.swift b/MailCore/Models/Attachment.swift index 7a60d67b1..795bd1431 100644 --- a/MailCore/Models/Attachment.swift +++ b/MailCore/Models/Attachment.swift @@ -42,9 +42,8 @@ public class Attachment: /* Hashable, */ EmbeddedObject, Codable, Identifiable { return parentLink.first } - public var localUrl: URL? { - guard let message = parent else { return nil } - return FileManager.default.temporaryDirectory.appendingPathComponent("\(message.uid)_\(partId)/\(name)") + public var localUrl: URL { + return FileManager.default.temporaryDirectory.appendingPathComponent("\(uuid)_\(partId)/\(name)") } public var uti: UTType? { From ffe74d227ab8fda683e13b5f64025cbd7a62643b Mon Sep 17 00:00:00 2001 From: Ambroise Decouttere Date: Thu, 18 Jan 2024 14:04:31 +0100 Subject: [PATCH 3/6] fix: Add temporaryLocalUrl to preview attachment not fully uploaded --- Mail/Views/Attachment/AttachmentPreview.swift | 2 ++ .../AttachmentsManagerWorker/AttachmentsManagerWorker.swift | 1 + MailCore/Models/Attachment.swift | 2 ++ 3 files changed, 5 insertions(+) diff --git a/Mail/Views/Attachment/AttachmentPreview.swift b/Mail/Views/Attachment/AttachmentPreview.swift index 534472ccb..85b3da6ce 100644 --- a/Mail/Views/Attachment/AttachmentPreview.swift +++ b/Mail/Views/Attachment/AttachmentPreview.swift @@ -39,6 +39,8 @@ struct AttachmentPreview: View { Group { if FileManager.default.fileExists(atPath: attachment.localUrl.path) { PreviewController(url: attachment.localUrl) + } else if FileManager.default.fileExists(atPath: attachment.temporaryLocalUrl) { + PreviewController(url: URL(fileURLWithPath: attachment.temporaryLocalUrl)) } else { ProgressView() } diff --git a/MailCore/Cache/AttachmentsManagerWorker/AttachmentsManagerWorker.swift b/MailCore/Cache/AttachmentsManagerWorker/AttachmentsManagerWorker.swift index 6c8f50509..317ee2e92 100644 --- a/MailCore/Cache/AttachmentsManagerWorker/AttachmentsManagerWorker.swift +++ b/MailCore/Cache/AttachmentsManagerWorker/AttachmentsManagerWorker.swift @@ -253,6 +253,7 @@ public final class AttachmentsManagerWorker { self.updateAttachmentUploadTaskProgress(attachment, progress: progress) } } + remoteAttachment.temporaryLocalUrl = url.path await updateAttachment(oldAttachment: localAttachment, newAttachment: remoteAttachment) return remoteAttachment } diff --git a/MailCore/Models/Attachment.swift b/MailCore/Models/Attachment.swift index 795bd1431..4304c5c2c 100644 --- a/MailCore/Models/Attachment.swift +++ b/MailCore/Models/Attachment.swift @@ -37,6 +37,7 @@ public class Attachment: /* Hashable, */ EmbeddedObject, Codable, Identifiable { @Persisted public var driveUrl: String? @Persisted(originProperty: "attachments") var parentLink: LinkingObjects @Persisted public var saved = false + @Persisted public var temporaryLocalUrl: String public var parent: Message? { return parentLink.first @@ -158,6 +159,7 @@ public class Attachment: /* Hashable, */ EmbeddedObject, Codable, Identifiable { contentId = remoteAttachment.contentId resource = remoteAttachment.resource driveUrl = remoteAttachment.driveUrl + temporaryLocalUrl = remoteAttachment.temporaryLocalUrl } } From 005cc5d5d7c5a1b3e516d0c6c437d115c9fbd9d6 Mon Sep 17 00:00:00 2001 From: Ambroise Decouttere Date: Thu, 18 Jan 2024 14:37:07 +0100 Subject: [PATCH 4/6] chore: Update realm version --- MailCore/Cache/MailboxManager/MailboxManager.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MailCore/Cache/MailboxManager/MailboxManager.swift b/MailCore/Cache/MailboxManager/MailboxManager.swift index b78af00a7..11f3c1a22 100644 --- a/MailCore/Cache/MailboxManager/MailboxManager.swift +++ b/MailCore/Cache/MailboxManager/MailboxManager.swift @@ -73,7 +73,7 @@ public final class MailboxManager: ObservableObject, MailboxManageable, RealmAcc let realmName = "\(mailbox.userId)-\(mailbox.mailboxId).realm" realmConfiguration = Realm.Configuration( fileURL: MailboxManager.constants.rootDocumentsURL.appendingPathComponent(realmName), - schemaVersion: 23, + schemaVersion: 24, migrationBlock: { migration, oldSchemaVersion in // No migration needed from 0 to 16 if oldSchemaVersion < 17 { From d35c424ded44c879edb338673fecaba9d33f373b Mon Sep 17 00:00:00 2001 From: Ambroise Decouttere Date: Thu, 18 Jan 2024 14:44:08 +0100 Subject: [PATCH 5/6] fix: Optional temporaryLocalUrl --- Mail/Views/Attachment/AttachmentPreview.swift | 5 +++-- MailCore/Models/Attachment.swift | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Mail/Views/Attachment/AttachmentPreview.swift b/Mail/Views/Attachment/AttachmentPreview.swift index 85b3da6ce..6ee1c3a67 100644 --- a/Mail/Views/Attachment/AttachmentPreview.swift +++ b/Mail/Views/Attachment/AttachmentPreview.swift @@ -39,8 +39,9 @@ struct AttachmentPreview: View { Group { if FileManager.default.fileExists(atPath: attachment.localUrl.path) { PreviewController(url: attachment.localUrl) - } else if FileManager.default.fileExists(atPath: attachment.temporaryLocalUrl) { - PreviewController(url: URL(fileURLWithPath: attachment.temporaryLocalUrl)) + } else if let temporaryLocalUrl = attachment.temporaryLocalUrl, + FileManager.default.fileExists(atPath: temporaryLocalUrl) { + PreviewController(url: URL(fileURLWithPath: temporaryLocalUrl)) } else { ProgressView() } diff --git a/MailCore/Models/Attachment.swift b/MailCore/Models/Attachment.swift index 4304c5c2c..4528a53ef 100644 --- a/MailCore/Models/Attachment.swift +++ b/MailCore/Models/Attachment.swift @@ -37,7 +37,7 @@ public class Attachment: /* Hashable, */ EmbeddedObject, Codable, Identifiable { @Persisted public var driveUrl: String? @Persisted(originProperty: "attachments") var parentLink: LinkingObjects @Persisted public var saved = false - @Persisted public var temporaryLocalUrl: String + @Persisted public var temporaryLocalUrl: String? public var parent: Message? { return parentLink.first From 6f125d945fd67238bce214058e3077c8626022b8 Mon Sep 17 00:00:00 2001 From: Ambroise Decouttere Date: Thu, 18 Jan 2024 15:26:12 +0100 Subject: [PATCH 6/6] fix: PR feedback --- .../Attachments/AttachmentUploadCell.swift | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/Mail/Views/New Message/Attachments/AttachmentUploadCell.swift b/Mail/Views/New Message/Attachments/AttachmentUploadCell.swift index 74dab9ca8..b55d37b38 100644 --- a/Mail/Views/New Message/Attachments/AttachmentUploadCell.swift +++ b/Mail/Views/New Message/Attachments/AttachmentUploadCell.swift @@ -61,18 +61,22 @@ struct AttachmentUploadCell: View { .opacity(uploadTask.progress == 1 ? 0 : 1) } .onTapGesture { - guard let attachment = attachment.thaw()?.freezeIfNeeded() else { return } - previewedAttachment = attachment - if !FileManager.default.fileExists(atPath: attachment.localUrl.path) { - Task { - await mailboxManager.saveAttachmentLocally(attachment: attachment) - } - } + showAttachmentPreview() } .sheet(item: $previewedAttachment) { previewedAttachment in AttachmentPreview(attachment: previewedAttachment) } } + + private func showAttachmentPreview() { + guard let attachment = attachment.thaw()?.freezeIfNeeded() else { return } + previewedAttachment = attachment + if !FileManager.default.fileExists(atPath: attachment.localUrl.path) { + Task { + await mailboxManager.saveAttachmentLocally(attachment: attachment) + } + } + } } #Preview {