Skip to content

Commit

Permalink
feat: Save all attachments
Browse files Browse the repository at this point in the history
  • Loading branch information
valentinperignon committed Jun 9, 2023
1 parent 1e9995c commit 493d1bc
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 19 deletions.
8 changes: 4 additions & 4 deletions .package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -157,17 +157,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/realm/realm-core.git",
"state" : {
"revision" : "72226e2fd84f3a3a8ab3cffc2890c7951f1351d5",
"version" : "13.10.1"
"revision" : "36b2df44453ba5e830369c76ab0683799a287605",
"version" : "13.13.0"
}
},
{
"identity" : "realm-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/realm/realm-swift",
"state" : {
"revision" : "08ee98e7f52a5fb11b10b7430e6f84adbb7433a4",
"version" : "10.39.1"
"revision" : "45ea4a0ec4bb3161c807be0a9a4921161dbe60a2",
"version" : "10.40.1"
}
},
{
Expand Down
25 changes: 19 additions & 6 deletions Mail/Helpers/DocumentPicker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,29 @@ import UIKit
import UniformTypeIdentifiers

struct DocumentPicker: UIViewControllerRepresentable {
var completion: ([URL]) -> Void
enum PickerType {
case selectContent([UTType], ([URL]) -> Void)
case exportContent([URL])
}

@Environment(\.dismiss) private var dismiss

let pickerType: PickerType

func makeCoordinator() -> DocumentPicker.Coordinator {
return DocumentPicker.Coordinator(parent: self)
}

func makeUIViewController(context: UIViewControllerRepresentableContext<DocumentPicker>) -> UIDocumentPickerViewController {
let supportedTypes: [UTType] = [UTType.item]
let picker = UIDocumentPickerViewController(forOpeningContentTypes: supportedTypes, asCopy: true)
picker.allowsMultipleSelection = true
func makeUIViewController(context: Context) -> UIDocumentPickerViewController {
let picker: UIDocumentPickerViewController
switch pickerType {
case let .selectContent(types, _):
picker = UIDocumentPickerViewController(forOpeningContentTypes: types, asCopy: true)
picker.allowsMultipleSelection = true
case let .exportContent(urls):
picker = UIDocumentPickerViewController(forExporting: urls, asCopy: true)
}

picker.delegate = context.coordinator
return picker
}
Expand All @@ -51,7 +63,8 @@ struct DocumentPicker: UIViewControllerRepresentable {
}

func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
parent.completion(urls)
// TODO: Get completion
//parent.completion(urls)
parent.dismiss()
}
}
Expand Down
4 changes: 2 additions & 2 deletions Mail/Views/New Message/ComposeMessageView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,9 @@ struct ComposeMessageView: View {
.ignoresSafeArea()
}
.sheet(isPresented: $isShowingFileSelection) {
DocumentPicker { urls in
DocumentPicker(pickerType: .selectContent([.item]){ urls in
attachmentsManager.importAttachments(attachments: urls)
}
})
}
.sheet(isPresented: $isShowingPhotoLibrary) {
ImagePicker { results in
Expand Down
27 changes: 24 additions & 3 deletions Mail/Views/Thread/AttachmentsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,18 @@ import MailResources
import RealmSwift
import SwiftUI

struct AllAttachmentsURL: Identifiable {
let id = UUID()
let url: URL
}

struct AttachmentsView: View {
@State private var showDocumentPicker = false

@State private var previewedAttachment: Attachment?
@State private var downloadInProgress = false
@State private var allAttachmentsURL: AllAttachmentsURL?

@EnvironmentObject var mailboxManager: MailboxManager
@ObservedRealmObject var message: Message

Expand Down Expand Up @@ -71,11 +81,18 @@ struct AttachmentsView: View {
.textStyle(.bodySmallSecondary)

MailButton(label: MailResourcesStrings.Localizable.buttonDownloadAll) {
// TODO: Download all attachments
matomo.track(eventWithCategory: .message, name: "downloadAll")
showWorkInProgressSnackBar()
Task {
await tryOrDisplayError {
matomo.track(eventWithCategory: .message, name: "downloadAll")
downloadInProgress = true
let attachmentURL = try await mailboxManager.apiFetcher.downloadAttachments(message: message)
allAttachmentsURL = AllAttachmentsURL(url: attachmentURL)
downloadInProgress = false
}
}
}
.mailButtonStyle(.smallLink)
.mailButtonLoading(downloadInProgress)

Spacer()
}
Expand All @@ -84,6 +101,10 @@ struct AttachmentsView: View {
.sheet(item: $previewedAttachment) { previewedAttachment in
AttachmentPreview(attachment: previewedAttachment)
}
.sheet(item: $allAttachmentsURL) { allAttachmentsURL in
DocumentPicker(pickerType: .exportContent([allAttachmentsURL.url]))
.ignoresSafeArea()
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions MailCore/API/Endpoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,10 @@ public extension Endpoint {
return .mailbox(uuid: uuid).appending(path: "/message/unstar")
}

static func downloadAttachments(messageResource: String) -> Endpoint {
return .resource(messageResource).appending(path: "/attachmentsArchive")
}

static func blockSender(messageResource: String) -> Endpoint {
return .resource(messageResource).appending(path: "/blacklist")
}
Expand Down
20 changes: 16 additions & 4 deletions MailCore/API/MailApiFetcher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ public class MailApiFetcher: ApiFetcher {
) async throws -> (data: T, responseAt: Int?) {
do {
return try await super.perform(request: request)
} catch InfomaniakError.apiError(let apiError) {
} catch let InfomaniakError.apiError(apiError) {
throw MailApiError.mailApiErrorWithFallback(apiErrorCode: apiError.code)
} catch InfomaniakError.serverError(statusCode: let statusCode) {
} catch let InfomaniakError.serverError(statusCode: statusCode) {
throw MailServerError(httpStatus: statusCode)
} catch {
if let afError = error.asAFError {
if case .responseSerializationFailed(let reason) = afError,
case .decodingFailed(let error) = reason {
if case let .responseSerializationFailed(reason) = afError,
case let .decodingFailed(error) = reason {
var rawJson = "No data"
if let data = request.data,
let stringData = String(data: data, encoding: .utf8) {
Expand Down Expand Up @@ -293,6 +293,18 @@ public class MailApiFetcher: ApiFetcher {
parameters: ["uids": messages.map(\.uid)])).data
}

public func downloadAttachments(message: Message) async throws -> URL {
let destination = DownloadRequest.suggestedDownloadDestination(options: [
.createIntermediateDirectories,
.removePreviousFile
])
let download = authenticatedSession.download(
Endpoint.downloadAttachments(messageResource: message.resource).url,
to: destination
)
return try await download.serializingDownloadedFileURL().value
}

public func blockSender(message: Message) async throws -> Bool {
try await perform(request: authenticatedRequest(.blockSender(messageResource: message.resource), method: .post)).data
}
Expand Down

0 comments on commit 493d1bc

Please sign in to comment.