From d8c859c841dee7462ce71e002e8f728078c9d091 Mon Sep 17 00:00:00 2001 From: ykyivskyi-gd Date: Wed, 16 Jun 2021 20:15:42 +0300 Subject: [PATCH 1/8] Added files manager to save downloaded files to user's phone; --- FlowCrypt.xcodeproj/project.pbxproj | 12 +++++ .../FilesManager/FilesManager.swift | 47 +++++++++++++++++++ .../Message Provider/MessageService.swift | 4 +- 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 FlowCrypt/Functionality/FilesManager/FilesManager.swift diff --git a/FlowCrypt.xcodeproj/project.pbxproj b/FlowCrypt.xcodeproj/project.pbxproj index 40c124992..815c1f9a6 100644 --- a/FlowCrypt.xcodeproj/project.pbxproj +++ b/FlowCrypt.xcodeproj/project.pbxproj @@ -11,6 +11,7 @@ 04B472951ECE29F600B8266F /* MyMenuViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B472921ECE29F600B8266F /* MyMenuViewController.swift */; }; 04B472961ECE29F600B8266F /* SideMenuNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B472931ECE29F600B8266F /* SideMenuNavigationController.swift */; }; 211392A5266511E6009202EC /* PubLookup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211392A4266511E6009202EC /* PubLookup.swift */; }; + 215897E8267A553300423694 /* FilesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 215897E7267A553200423694 /* FilesManager.swift */; }; 21C7DEFC26669A3700C44800 /* CalendarExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21C7DEFB26669A3700C44800 /* CalendarExtension.swift */; }; 21C7DEFE26669CE100C44800 /* DateFormattingExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F56BD3723438C7000A7371A /* DateFormattingExtensions.swift */; }; 21C7DF0526697DA500C44800 /* PromiseKitExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21C7DF0426697DA500C44800 /* PromiseKitExtension.swift */; }; @@ -362,6 +363,7 @@ 113F04B20ECC35FC59A81A6C /* Pods-FlowCryptTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlowCryptTests.release.xcconfig"; path = "Target Support Files/Pods-FlowCryptTests/Pods-FlowCryptTests.release.xcconfig"; sourceTree = ""; }; 11C1375F41411882DC4C9431 /* Pods-FlowCryptUIApplication.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlowCryptUIApplication.release.xcconfig"; path = "Target Support Files/Pods-FlowCryptUIApplication/Pods-FlowCryptUIApplication.release.xcconfig"; sourceTree = ""; }; 211392A4266511E6009202EC /* PubLookup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PubLookup.swift; sourceTree = ""; }; + 215897E7267A553200423694 /* FilesManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilesManager.swift; sourceTree = ""; }; 21C7DEFB26669A3700C44800 /* CalendarExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarExtension.swift; sourceTree = ""; }; 21C7DF0426697DA500C44800 /* PromiseKitExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromiseKitExtension.swift; sourceTree = ""; }; 21C7DF08266C0D8F00C44800 /* EnterpriseServerApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnterpriseServerApi.swift; sourceTree = ""; }; @@ -743,6 +745,14 @@ path = SideMenu; sourceTree = ""; }; + 215897E6267A551300423694 /* FilesManager */ = { + isa = PBXGroup; + children = ( + 215897E7267A553200423694 /* FilesManager.swift */, + ); + path = FilesManager; + sourceTree = ""; + }; 21CE25D32650034500ADFF4B /* WKDURLs */ = { isa = PBXGroup; children = ( @@ -1379,6 +1389,7 @@ C132B9C61EC2DCC000763715 /* Functionality */ = { isa = PBXGroup; children = ( + 215897E6267A551300423694 /* FilesManager */, 21CE25D32650034500ADFF4B /* WKDURLs */, A370EAB6238697E000685215 /* Pgp */, D29AFFEE24092F4900C1387D /* DataManager */, @@ -2406,6 +2417,7 @@ 9F0C3C1A231819C500299985 /* MessageKindProviderType.swift in Sources */, 21C7DF09266C0D8F00C44800 /* EnterpriseServerApi.swift in Sources */, 9FF0670825520CF800FCC9E6 /* GmailService.swift in Sources */, + 215897E8267A553300423694 /* FilesManager.swift in Sources */, 9F5C2A77257D705100DE9B4B /* MessageLabel.swift in Sources */, 9F93623F2573D16F0009912F /* Gmail+Message.swift in Sources */, 9FC4112E2595EA8B001180A8 /* Gmail+Search.swift in Sources */, diff --git a/FlowCrypt/Functionality/FilesManager/FilesManager.swift b/FlowCrypt/Functionality/FilesManager/FilesManager.swift new file mode 100644 index 000000000..06a4ec1b4 --- /dev/null +++ b/FlowCrypt/Functionality/FilesManager/FilesManager.swift @@ -0,0 +1,47 @@ +// +// FilesManager.swift +// FlowCrypt +// +// Created by Yevhen Kyivskyi on 16.06.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import Promises + +protocol FileType { + var name: String { get } + var size: Int { get } + var data: Data { get } +} + +protocol FilesManagerType { + func download(file: FileType) -> Promise +} + +class FilesManager: FilesManagerType { + + private let documentsDirectoryURL: URL = { + FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! + }() + + private let queue: DispatchQueue = DispatchQueue.global(qos: .background) + + func download(file: FileType) -> Promise { + Promise { [weak self] resolve, reject in + guard let self = self else { + throw AppErr.nilSelf + } + + let url = self.documentsDirectoryURL.appendingPathComponent(file.name) + self.queue.async { + + do { + try file.data.write(to: url) + resolve(()) + } catch { + reject(error) + } + } + } + } +} diff --git a/FlowCrypt/Functionality/Mail Provider/Message Provider/MessageService.swift b/FlowCrypt/Functionality/Mail Provider/Message Provider/MessageService.swift index 4c86e8983..d66310bd3 100644 --- a/FlowCrypt/Functionality/Mail Provider/Message Provider/MessageService.swift +++ b/FlowCrypt/Functionality/Mail Provider/Message Provider/MessageService.swift @@ -10,9 +10,10 @@ import Foundation import Promises // MARK: - MessageAttachment -struct MessageAttachment { +struct MessageAttachment: FileType { let name: String let size: Int + let data: Data } // MARK: - FetchedMessage @@ -109,6 +110,7 @@ private extension MessageAttachment { init(block: MsgBlock) { self.name = block.attMeta?.name ?? "Attachment" self.size = block.attMeta?.length ?? 0 + self.data = block.attMeta?.data ?? Data() } } From 59c2a321c0abcb2e17e7acc5a68fc3b7c01b3b9a Mon Sep 17 00:00:00 2001 From: ykyivskyi-gd Date: Thu, 17 Jun 2021 16:04:57 +0300 Subject: [PATCH 2/8] Added action to attachment node to save file; Added tests for files manager; --- FlowCrypt.xcodeproj/project.pbxproj | 18 +++++++ .../Msg/MessageViewController.swift | 16 ++++++- .../FilesManager/FilesManager.swift | 4 +- .../Resources/en.lproj/Localizable.strings | 2 + .../FilesManager/FileMock.swift | 23 +++++++++ .../FilesManager/FilesManagerTests.swift | 47 +++++++++++++++++++ FlowCryptUI/Nodes/AttachmentNode.swift | 24 +++++++++- 7 files changed, 129 insertions(+), 5 deletions(-) create mode 100644 FlowCryptTests/Functionallity/FilesManager/FileMock.swift create mode 100644 FlowCryptTests/Functionallity/FilesManager/FilesManagerTests.swift diff --git a/FlowCrypt.xcodeproj/project.pbxproj b/FlowCrypt.xcodeproj/project.pbxproj index 815c1f9a6..fa7fbffc5 100644 --- a/FlowCrypt.xcodeproj/project.pbxproj +++ b/FlowCrypt.xcodeproj/project.pbxproj @@ -11,6 +11,9 @@ 04B472951ECE29F600B8266F /* MyMenuViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B472921ECE29F600B8266F /* MyMenuViewController.swift */; }; 04B472961ECE29F600B8266F /* SideMenuNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B472931ECE29F600B8266F /* SideMenuNavigationController.swift */; }; 211392A5266511E6009202EC /* PubLookup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211392A4266511E6009202EC /* PubLookup.swift */; }; + 21489B6B267B7BD800BDE4AC /* FilesManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B6A267B7BD800BDE4AC /* FilesManagerTests.swift */; }; + 21489B6C267B7C6A00BDE4AC /* FilesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 215897E7267A553200423694 /* FilesManager.swift */; }; + 21489B6E267B7D5000BDE4AC /* FileMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B6D267B7D5000BDE4AC /* FileMock.swift */; }; 215897E8267A553300423694 /* FilesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 215897E7267A553200423694 /* FilesManager.swift */; }; 21C7DEFC26669A3700C44800 /* CalendarExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21C7DEFB26669A3700C44800 /* CalendarExtension.swift */; }; 21C7DEFE26669CE100C44800 /* DateFormattingExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F56BD3723438C7000A7371A /* DateFormattingExtensions.swift */; }; @@ -363,6 +366,8 @@ 113F04B20ECC35FC59A81A6C /* Pods-FlowCryptTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlowCryptTests.release.xcconfig"; path = "Target Support Files/Pods-FlowCryptTests/Pods-FlowCryptTests.release.xcconfig"; sourceTree = ""; }; 11C1375F41411882DC4C9431 /* Pods-FlowCryptUIApplication.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlowCryptUIApplication.release.xcconfig"; path = "Target Support Files/Pods-FlowCryptUIApplication/Pods-FlowCryptUIApplication.release.xcconfig"; sourceTree = ""; }; 211392A4266511E6009202EC /* PubLookup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PubLookup.swift; sourceTree = ""; }; + 21489B6A267B7BD800BDE4AC /* FilesManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilesManagerTests.swift; sourceTree = ""; }; + 21489B6D267B7D5000BDE4AC /* FileMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileMock.swift; sourceTree = ""; }; 215897E7267A553200423694 /* FilesManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilesManager.swift; sourceTree = ""; }; 21C7DEFB26669A3700C44800 /* CalendarExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarExtension.swift; sourceTree = ""; }; 21C7DF0426697DA500C44800 /* PromiseKitExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromiseKitExtension.swift; sourceTree = ""; }; @@ -745,6 +750,15 @@ path = SideMenu; sourceTree = ""; }; + 21489B69267B7BC300BDE4AC /* FilesManager */ = { + isa = PBXGroup; + children = ( + 21489B6A267B7BD800BDE4AC /* FilesManagerTests.swift */, + 21489B6D267B7D5000BDE4AC /* FileMock.swift */, + ); + path = FilesManager; + sourceTree = ""; + }; 215897E6267A551300423694 /* FilesManager */ = { isa = PBXGroup; children = ( @@ -776,6 +790,7 @@ 21F836A62652A1B700B2448C /* Functionallity */ = { isa = PBXGroup; children = ( + 21489B69267B7BC300BDE4AC /* FilesManager */, 21F836A72652A1CD00B2448C /* WKDURLs */, ); path = Functionallity; @@ -2301,9 +2316,11 @@ D212D35E24C1AACF00035991 /* PrvKeyInfo.swift in Sources */, 9F1D5769263B540100477938 /* Logger.swift in Sources */, A3DAD5FE22E4574B00F2C4CD /* FlowCryptCoreTests.swift in Sources */, + 21489B6B267B7BD800BDE4AC /* FilesManagerTests.swift in Sources */, 21EA3B2326565B5D00691848 /* DomainRulesTests.swift in Sources */, 21F836CC2652A38700B2448C /* ZBase32EncodingTests.swift in Sources */, D2A9CA45242622F800E1D898 /* GeneralConstantsTest.swift in Sources */, + 21489B6C267B7C6A00BDE4AC /* FilesManager.swift in Sources */, A3DAD60B22E458C300F2C4CD /* DataExtensions.swift in Sources */, 21EA3B532656611C00691848 /* OrganisationalRule.swift in Sources */, A3DAD60822E4588800F2C4CD /* TestData.swift in Sources */, @@ -2315,6 +2332,7 @@ 9F7DE8C6232029D000F10B3E /* CoreTypes.swift in Sources */, 9F3EF32A23B15C9600FA0CEF /* ImapHelperTest.swift in Sources */, 5A39F439239ECDD0001F4607 /* ExtensionTests.swift in Sources */, + 21489B6E267B7D5000BDE4AC /* FileMock.swift in Sources */, D212D36524C1AC4800035991 /* KeyId.swift in Sources */, 9F003DBC25EA92D000EB38C0 /* LogOutHandler.swift in Sources */, 21F836A02652A19A00B2448C /* WKDURLsConstructor.swift in Sources */, diff --git a/FlowCrypt/Controllers/Msg/MessageViewController.swift b/FlowCrypt/Controllers/Msg/MessageViewController.swift index e23f09675..f1043f33e 100644 --- a/FlowCrypt/Controllers/Msg/MessageViewController.swift +++ b/FlowCrypt/Controllers/Msg/MessageViewController.swift @@ -55,6 +55,7 @@ final class MessageViewController: TableNodeViewController { private let messageService: MessageService private let messageOperationsProvider: MessageOperationsProvider private let trashFolderProvider: TrashFolderProviderType + private let filesManager: FilesManagerType private var fetchedMessage: FetchedMessage = .empty init( @@ -63,6 +64,7 @@ final class MessageViewController: TableNodeViewController { decorator: MessageViewDecorator = MessageViewDecorator(dateFormatter: DateFormatter()), storage: DataServiceType & KeyDataServiceType = DataService.shared, trashFolderProvider: TrashFolderProviderType = TrashFolderProvider(), + filesManager: FilesManagerType = FilesManager(), input: MessageViewController.Input, completion: MsgViewControllerCompletion? ) { @@ -72,6 +74,7 @@ final class MessageViewController: TableNodeViewController { self.decorator = decorator self.trashFolderProvider = trashFolderProvider self.onCompletion = completion + self.filesManager = filesManager super.init(node: TableNode()) } @@ -378,7 +381,18 @@ extension MessageViewController: ASTableDelegate, ASTableDataSource { AttachmentNode( input: .init( msgAttachment: fetchedMessage.attachments[index] - ) + ), + onDownloadTap: { [weak self] in + guard let self = self else { return } + self.filesManager.save(file: self.fetchedMessage.attachments[index]) + .then { _ in + self.showToast("message_attachment_saved_successfully".localized) + }.catch { error in + self.showToast( + "\("message_attachment_saved_with_error".localized) \(error.localizedDescription)" + ) + } + } ) } } diff --git a/FlowCrypt/Functionality/FilesManager/FilesManager.swift b/FlowCrypt/Functionality/FilesManager/FilesManager.swift index 06a4ec1b4..de7b84fbe 100644 --- a/FlowCrypt/Functionality/FilesManager/FilesManager.swift +++ b/FlowCrypt/Functionality/FilesManager/FilesManager.swift @@ -15,7 +15,7 @@ protocol FileType { } protocol FilesManagerType { - func download(file: FileType) -> Promise + func save(file: FileType) -> Promise } class FilesManager: FilesManagerType { @@ -26,7 +26,7 @@ class FilesManager: FilesManagerType { private let queue: DispatchQueue = DispatchQueue.global(qos: .background) - func download(file: FileType) -> Promise { + func save(file: FileType) -> Promise { Promise { [weak self] resolve, reject in guard let self = self else { throw AppErr.nilSelf diff --git a/FlowCrypt/Resources/en.lproj/Localizable.strings b/FlowCrypt/Resources/en.lproj/Localizable.strings index 2b8723717..5f356e5b9 100644 --- a/FlowCrypt/Resources/en.lproj/Localizable.strings +++ b/FlowCrypt/Resources/en.lproj/Localizable.strings @@ -16,6 +16,8 @@ "message_compose_secure" = "Compose Secure Message"; "message_unknown_sender" = "(unknown sender)"; "message_missed_subject" = "No subject"; +"message_attachment_saved_successfully" = "Attachemt was saved"; +"message_attachment_saved_with_error" = "Attachment could not saved."; // REPLY "reply_title" = "Your reply"; // not used diff --git a/FlowCryptTests/Functionallity/FilesManager/FileMock.swift b/FlowCryptTests/Functionallity/FilesManager/FileMock.swift new file mode 100644 index 000000000..37abe8d3f --- /dev/null +++ b/FlowCryptTests/Functionallity/FilesManager/FileMock.swift @@ -0,0 +1,23 @@ +// +// FileMock.swift +// FlowCryptTests +// +// Created by Yevhen Kyivskyi on 17.06.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import Foundation + +struct FileMock: FileType { + let name: String + let size: Int + let data: Data +} + +extension FileMock { + static let stringedFile = FileMock( + name: "mock_file.pdf", + size: 125, + data: "mocktext".data(using: .utf8)! + ) +} diff --git a/FlowCryptTests/Functionallity/FilesManager/FilesManagerTests.swift b/FlowCryptTests/Functionallity/FilesManager/FilesManagerTests.swift new file mode 100644 index 000000000..a9b2e058f --- /dev/null +++ b/FlowCryptTests/Functionallity/FilesManager/FilesManagerTests.swift @@ -0,0 +1,47 @@ +// +// FilesManagerTests.swift +// FlowCryptTests +// +// Created by Yevhen Kyivskyi on 17.06.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import XCTest + +class FilesManagerTests: XCTestCase { + + var filesManager: FilesManagerType! + + override func setUp() { + filesManager = FilesManager() + } + + override func tearDown() { + filesManager = nil + } + + func test_save_file() { + var isFileSaved = false + let file = FileMock.stringedFile + let expectation = XCTestExpectation() + + filesManager.save(file: file) + .then { _ in + isFileSaved = true + expectation.fulfill() + } + + let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! + let pathComponent = url.appendingPathComponent(file.name) + let filePath = pathComponent.path + + wait(for: [expectation], timeout: 0.5) + + XCTAssertTrue( + isFileSaved, "filesManager.save should call then block if file succesfully saved" + ) + XCTAssertTrue( + FileManager.default.fileExists(atPath: filePath), "file should exist in documents directory" + ) + } +} diff --git a/FlowCryptUI/Nodes/AttachmentNode.swift b/FlowCryptUI/Nodes/AttachmentNode.swift index d80e529e0..7c2b00f4c 100644 --- a/FlowCryptUI/Nodes/AttachmentNode.swift +++ b/FlowCryptUI/Nodes/AttachmentNode.swift @@ -22,9 +22,15 @@ public final class AttachmentNode: CellNode { private let buttonNode = ASButtonNode() private let borderNode = ASDisplayNode() - public init(input: Input) { + private var onDownloadTap: (() -> Void)? + + public init( + input: Input, + onDownloadTap: (() -> Void)? + ) { + self.onDownloadTap = onDownloadTap super.init() - + automaticallyManagesSubnodes = true borderNode.borderWidth = 1.0 borderNode.cornerRadius = 8.0 borderNode.borderColor = UIColor.lightGray.cgColor @@ -36,6 +42,20 @@ public final class AttachmentNode: CellNode { buttonNode.setImage(UIImage(named: "download")?.tinted(.gray), for: .normal) titleNode.attributedText = input.name subtitleNode.attributedText = input.size + + buttonNode.addTarget(self, action: #selector(onDownloadButtonTap), forControlEvents: .touchUpInside) + + } + + public override func layoutDidFinish() { + super.layoutDidFinish() + DispatchQueue.main.async { + self.view.bringSubviewToFront(self.buttonNode.view) + } + } + + @objc private func onDownloadButtonTap() { + onDownloadTap?() } public override func layoutSpecThatFits(_: ASSizeRange) -> ASLayoutSpec { From d5c38e9d644cb3fd31907d360bbe271306d82505 Mon Sep 17 00:00:00 2001 From: Anton Kharchevskyi Date: Thu, 17 Jun 2021 17:52:35 +0300 Subject: [PATCH 3/8] Fix for download attachment tap --- FlowCrypt/Models/OrganisationalRule.swift | 4 ++-- FlowCryptUI/Nodes/AttachmentNode.swift | 8 +------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/FlowCrypt/Models/OrganisationalRule.swift b/FlowCrypt/Models/OrganisationalRule.swift index 7321bd8ea..7c009be16 100644 --- a/FlowCrypt/Models/OrganisationalRule.swift +++ b/FlowCrypt/Models/OrganisationalRule.swift @@ -43,12 +43,12 @@ class OrganisationalRules { self.domainRules = domainRules self.domain = domain } - + init?(domainRules: DomainRules, email: String) { guard let recipientDomain = email.recipientDomain else { return nil } - + self.domain = recipientDomain self.domainRules = domainRules } diff --git a/FlowCryptUI/Nodes/AttachmentNode.swift b/FlowCryptUI/Nodes/AttachmentNode.swift index 7c2b00f4c..2b99d4cc8 100644 --- a/FlowCryptUI/Nodes/AttachmentNode.swift +++ b/FlowCryptUI/Nodes/AttachmentNode.swift @@ -34,6 +34,7 @@ public final class AttachmentNode: CellNode { borderNode.borderWidth = 1.0 borderNode.cornerRadius = 8.0 borderNode.borderColor = UIColor.lightGray.cgColor + borderNode.isUserInteractionEnabled = false imageNode.tintColor = .gray buttonNode.tintColor = .gray @@ -47,13 +48,6 @@ public final class AttachmentNode: CellNode { } - public override func layoutDidFinish() { - super.layoutDidFinish() - DispatchQueue.main.async { - self.view.bringSubviewToFront(self.buttonNode.view) - } - } - @objc private func onDownloadButtonTap() { onDownloadTap?() } From 0267bab5afec9f119369e989b23cf302b00574ad Mon Sep 17 00:00:00 2001 From: ykyivskyi-gd Date: Thu, 17 Jun 2021 23:40:01 +0300 Subject: [PATCH 4/8] Increased expectation timeout to FilesManager tests --- .../Functionallity/FilesManager/FilesManagerTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FlowCryptTests/Functionallity/FilesManager/FilesManagerTests.swift b/FlowCryptTests/Functionallity/FilesManager/FilesManagerTests.swift index a9b2e058f..543308ee9 100644 --- a/FlowCryptTests/Functionallity/FilesManager/FilesManagerTests.swift +++ b/FlowCryptTests/Functionallity/FilesManager/FilesManagerTests.swift @@ -35,7 +35,7 @@ class FilesManagerTests: XCTestCase { let pathComponent = url.appendingPathComponent(file.name) let filePath = pathComponent.path - wait(for: [expectation], timeout: 0.5) + wait(for: [expectation], timeout: 2) XCTAssertTrue( isFileSaved, "filesManager.save should call then block if file succesfully saved" From 757a80dfadf68f707c82bc2c3845a39b7574179f Mon Sep 17 00:00:00 2001 From: Tom J <6306961+tomholub@users.noreply.github.com> Date: Sat, 19 Jun 2021 13:42:24 +0000 Subject: [PATCH 5/8] Update Localizable.strings --- FlowCrypt/Resources/en.lproj/Localizable.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FlowCrypt/Resources/en.lproj/Localizable.strings b/FlowCrypt/Resources/en.lproj/Localizable.strings index 5f356e5b9..b228c0bc8 100644 --- a/FlowCrypt/Resources/en.lproj/Localizable.strings +++ b/FlowCrypt/Resources/en.lproj/Localizable.strings @@ -17,7 +17,7 @@ "message_unknown_sender" = "(unknown sender)"; "message_missed_subject" = "No subject"; "message_attachment_saved_successfully" = "Attachemt was saved"; -"message_attachment_saved_with_error" = "Attachment could not saved."; +"message_attachment_saved_with_error" = "Attachment could not be saved."; // REPLY "reply_title" = "Your reply"; // not used From 655f0d523f204c6de0007948a95e67ad335b2167 Mon Sep 17 00:00:00 2001 From: ykyivskyi-gd Date: Thu, 24 Jun 2021 16:22:22 +0300 Subject: [PATCH 6/8] Saving files using Files app; Opened saved files using Files app; --- FlowCrypt.xcodeproj/project.pbxproj | 63 ++----------------- .../Msg/MessageViewController.swift | 38 +++++++++-- .../FilesManager/FilesManager.swift | 28 +++++++-- .../Resources/en.lproj/Localizable.strings | 4 +- FlowCryptCommon/Extensions/URLExtension.swift | 23 +++++++ 5 files changed, 88 insertions(+), 68 deletions(-) create mode 100644 FlowCryptCommon/Extensions/URLExtension.swift diff --git a/FlowCrypt.xcodeproj/project.pbxproj b/FlowCrypt.xcodeproj/project.pbxproj index b222f5c95..145d001dd 100644 --- a/FlowCrypt.xcodeproj/project.pbxproj +++ b/FlowCrypt.xcodeproj/project.pbxproj @@ -11,10 +11,8 @@ 04B472951ECE29F600B8266F /* MyMenuViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B472921ECE29F600B8266F /* MyMenuViewController.swift */; }; 04B472961ECE29F600B8266F /* SideMenuNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B472931ECE29F600B8266F /* SideMenuNavigationController.swift */; }; 211392A5266511E6009202EC /* PubLookup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211392A4266511E6009202EC /* PubLookup.swift */; }; - 21489B6B267B7BD800BDE4AC /* FilesManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B6A267B7BD800BDE4AC /* FilesManagerTests.swift */; }; - 21489B6C267B7C6A00BDE4AC /* FilesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 215897E7267A553200423694 /* FilesManager.swift */; }; - 21489B6E267B7D5000BDE4AC /* FileMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B6D267B7D5000BDE4AC /* FileMock.swift */; }; 215897E8267A553300423694 /* FilesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 215897E7267A553200423694 /* FilesManager.swift */; }; + 2196A2202684B9BE001B9E00 /* URLExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2196A21F2684B9BE001B9E00 /* URLExtension.swift */; }; 21C7DEFC26669A3700C44800 /* CalendarExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21C7DEFB26669A3700C44800 /* CalendarExtension.swift */; }; 21C7DEFE26669CE100C44800 /* DateFormattingExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F56BD3723438C7000A7371A /* DateFormattingExtensions.swift */; }; 21C7DF0526697DA500C44800 /* PromiseKitExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21C7DF0426697DA500C44800 /* PromiseKitExtension.swift */; }; @@ -361,6 +359,7 @@ 21489B6A267B7BD800BDE4AC /* FilesManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilesManagerTests.swift; sourceTree = ""; }; 21489B6D267B7D5000BDE4AC /* FileMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileMock.swift; sourceTree = ""; }; 215897E7267A553200423694 /* FilesManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilesManager.swift; sourceTree = ""; }; + 2196A21F2684B9BE001B9E00 /* URLExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLExtension.swift; sourceTree = ""; }; 21C7DEFB26669A3700C44800 /* CalendarExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarExtension.swift; sourceTree = ""; }; 21C7DF0426697DA500C44800 /* PromiseKitExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromiseKitExtension.swift; sourceTree = ""; }; 21C7DF08266C0D8F00C44800 /* EnterpriseServerApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnterpriseServerApi.swift; sourceTree = ""; }; @@ -1571,6 +1570,7 @@ 9F56BD3723438C7000A7371A /* DateFormattingExtensions.swift */, 21C7DEFB26669A3700C44800 /* CalendarExtension.swift */, 9F716304234FC7200031645E /* LocalizationExtensions.swift */, + 2196A21F2684B9BE001B9E00 /* URLExtension.swift */, 9F56BD3923438D3700A7371A /* StyleExtension.swift */, 9F0C3C2723194E8500299985 /* CommonExtensions.swift */, 32DCA63656CB3323C26BC084 /* UIVIewExtensions.swift */, @@ -2365,62 +2365,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - A3DAD5F722E4574A00F2C4CD /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D2D27B7A248A874C007346FA /* BigIntExtension.swift in Sources */, - 9FC7EB7C266EB67D00F3BF5D /* EncryptedStorageProtocols.swift in Sources */, - 9F3EF32B23B16ADE00FA0CEF /* CommonExtensions.swift in Sources */, - 9FC7EBC2266EBE0100F3BF5D /* EmailProviderMock.swift in Sources */, - 9FC7EBD0266EBE1D00F3BF5D /* EncryptedPassPhraseStorageMock.swift in Sources */, - 9FA0157A26565B7800CBBA05 /* KeyMethodsTest.swift in Sources */, - A357699622EA2BC8009242C4 /* KeyInfo.swift in Sources */, - 9FC411902596229D001180A8 /* AppErr.swift in Sources */, - 9FC7EB69266EB64F00F3BF5D /* PassPhraseStorage.swift in Sources */, - D212D35E24C1AACF00035991 /* PrvKeyInfo.swift in Sources */, - 9F1D5769263B540100477938 /* Logger.swift in Sources */, - 9FC7EBC9266EBE0F00F3BF5D /* LocalPassPhraseStorageMock.swift in Sources */, - A3DAD5FE22E4574B00F2C4CD /* FlowCryptCoreTests.swift in Sources */, - 21489B6B267B7BD800BDE4AC /* FilesManagerTests.swift in Sources */, - 9FC7EBB0266EBD4600F3BF5D /* InMemoryPassPhraseStorage.swift in Sources */, - 21EA3B2326565B5D00691848 /* DomainRulesTests.swift in Sources */, - 9F4164102665754A00106194 /* PromiseExtensions.swift in Sources */, - 21F836CC2652A38700B2448C /* ZBase32EncodingTests.swift in Sources */, - 9FC7EBA3266EB95300F3BF5D /* PassPhraseStorageTests.swift in Sources */, - 9F7920EE2666D32500DA3D80 /* BackupServiceType.swift in Sources */, - 9FC7EB6F266EB66200F3BF5D /* PassPhrase.swift in Sources */, - D2A9CA45242622F800E1D898 /* GeneralConstantsTest.swift in Sources */, - 21489B6C267B7C6A00BDE4AC /* FilesManager.swift in Sources */, - A3DAD60B22E458C300F2C4CD /* DataExtensions.swift in Sources */, - 21EA3B532656611C00691848 /* OrganisationalRule.swift in Sources */, - A3DAD60822E4588800F2C4CD /* TestData.swift in Sources */, - D212D36124C1AC0D00035991 /* KeyDetails.swift in Sources */, - 9F6EE18C25A8AF970059BA51 /* GeneralConstants.swift in Sources */, - A3DAD60A22E458C100F2C4CD /* CodableExntensions.swift in Sources */, - D254733424C597CD00DEE698 /* CoreTypesTest.swift in Sources */, - 9F003DA425EA928200EB38C0 /* LocalStorage.swift in Sources */, - 9F7DE8C6232029D000F10B3E /* CoreTypes.swift in Sources */, - 9F3EF32A23B15C9600FA0CEF /* ImapHelperTest.swift in Sources */, - 5A39F439239ECDD0001F4607 /* ExtensionTests.swift in Sources */, - 21489B6E267B7D5000BDE4AC /* FileMock.swift in Sources */, - D212D36524C1AC4800035991 /* KeyId.swift in Sources */, - 9F003DBC25EA92D000EB38C0 /* LogOutHandler.swift in Sources */, - 21F836A02652A19A00B2448C /* WKDURLsConstructor.swift in Sources */, - 9F7920E32666D28400DA3D80 /* BackupServiceMock.swift in Sources */, - 9F7DE8C5232029BD00F10B3E /* Core.swift in Sources */, - 32DCAD6360C9EFF4FDD8EF6F /* DispatchTimeExtension.swift in Sources */, - 9F7DE8C723202A0200F10B3E /* CoreHost.swift in Sources */, - 9F3EF32823B15C8400FA0CEF /* ImapHelper.swift in Sources */, - 9F003D9E25EA910B00EB38C0 /* LocalStorageTests.swift in Sources */, - 9FA0158026565B9D00CBBA05 /* KeyMethods.swift in Sources */, - 32DCAF683D87EA6221F71335 /* SequenceExtensions.swift in Sources */, - 9F589F11238C7DDC007FD759 /* User.swift in Sources */, - 21F836D32652A46E00B2448C /* WKDURLsConstructorTests.swift in Sources */, - D2E26F6D24F263B600612AF1 /* KeyAlgo.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; C132B9AC1EC2DBD800763715 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -2660,6 +2604,7 @@ D29AFFF6240939AE00C1387D /* Then.swift in Sources */, 21C7DEFC26669A3700C44800 /* CalendarExtension.swift in Sources */, D2531F3423FEEF5F007E5198 /* StyleExtension.swift in Sources */, + 2196A2202684B9BE001B9E00 /* URLExtension.swift in Sources */, D254AA6024092AB80041CAE0 /* TapTicFeedback.swift in Sources */, D2531F472402C9DE007E5198 /* IntExtensions.swift in Sources */, D2FD0F692453245E00259FF0 /* Either.swift in Sources */, diff --git a/FlowCrypt/Controllers/Msg/MessageViewController.swift b/FlowCrypt/Controllers/Msg/MessageViewController.swift index 38102651b..d09328065 100644 --- a/FlowCrypt/Controllers/Msg/MessageViewController.swift +++ b/FlowCrypt/Controllers/Msg/MessageViewController.swift @@ -3,6 +3,7 @@ // import AsyncDisplayKit +import FlowCryptCommon import FlowCryptUI import Promises @@ -433,10 +434,8 @@ extension MessageViewController: ASTableDelegate, ASTableDataSource { ), onDownloadTap: { [weak self] in guard let self = self else { return } - self.filesManager.save(file: self.processedMessage.attachments[index]) - .then { _ in - self.showToast("message_attachment_saved_successfully".localized) - }.catch { error in + self.filesManager.saveToFilesApp(file: self.processedMessage.attachments[index], from: self) + .catch { error in self.showToast( "\("message_attachment_saved_with_error".localized) \(error.localizedDescription)" ) @@ -445,3 +444,34 @@ extension MessageViewController: ASTableDelegate, ASTableDataSource { ) } } + +// MARK: - UIDocumentPickerDelegate + +extension MessageViewController: UIDocumentPickerDelegate { + public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { + + guard let savedUrl = urls.first, + let sharedDocumentUrl = savedUrl.sharedDocumentURL else { + return + } + showFileSharedAlert(with: sharedDocumentUrl) + } + + private func showFileSharedAlert(with url: URL) { + let alert = UIAlertController( + title: "message_attachment_saved_successfully_title".localized, + message: "message_attachment_saved_successfully_message".localized, + preferredStyle: .alert + ) + + let cancel = UIAlertAction(title: "cancel".localized, style: .cancel) { _ in } + let open = UIAlertAction(title: "open".localized, style: .default) { _ in + UIApplication.shared.open(url) + } + + alert.addAction(cancel) + alert.addAction(open) + + present(alert, animated: true) + } +} diff --git a/FlowCrypt/Functionality/FilesManager/FilesManager.swift b/FlowCrypt/Functionality/FilesManager/FilesManager.swift index de7b84fbe..7e70fcafb 100644 --- a/FlowCrypt/Functionality/FilesManager/FilesManager.swift +++ b/FlowCrypt/Functionality/FilesManager/FilesManager.swift @@ -7,6 +7,7 @@ // import Promises +import UIKit protocol FileType { var name: String { get } @@ -15,7 +16,8 @@ protocol FileType { } protocol FilesManagerType { - func save(file: FileType) -> Promise + func save(file: FileType) -> Promise + func saveToFilesApp(file: FileType, from viewController: UIViewController & UIDocumentPickerDelegate) -> Promise } class FilesManager: FilesManagerType { @@ -26,8 +28,8 @@ class FilesManager: FilesManagerType { private let queue: DispatchQueue = DispatchQueue.global(qos: .background) - func save(file: FileType) -> Promise { - Promise { [weak self] resolve, reject in + func save(file: FileType) -> Promise { + Promise { [weak self] resolve, reject in guard let self = self else { throw AppErr.nilSelf } @@ -37,11 +39,29 @@ class FilesManager: FilesManagerType { do { try file.data.write(to: url) - resolve(()) + resolve(url) } catch { reject(error) } } } } + + func saveToFilesApp( + file: FileType, + from viewController: UIViewController & UIDocumentPickerDelegate + ) -> Promise { + Promise { [weak self] resolve, _ in + guard let self = self else { + throw AppErr.nilSelf + } + let url = try? awaitPromise(self.save(file: file)) + DispatchQueue.main.async { + let documentController = UIDocumentPickerViewController(url: url!, in: .exportToService) + documentController.delegate = viewController + viewController.present(documentController, animated: true) + resolve(()) + } + } + } } diff --git a/FlowCrypt/Resources/en.lproj/Localizable.strings b/FlowCrypt/Resources/en.lproj/Localizable.strings index 1f6959d35..b08ba6f09 100644 --- a/FlowCrypt/Resources/en.lproj/Localizable.strings +++ b/FlowCrypt/Resources/en.lproj/Localizable.strings @@ -5,6 +5,7 @@ "retry_title" = "retry"; "ok" = "Ok"; "cancel" = "Cancel"; +"open" = "Open"; // EMAIL "email_removed" = "Email moved to Trash"; @@ -18,7 +19,8 @@ "message_compose_secure" = "Compose Secure Message"; "message_unknown_sender" = "(unknown sender)"; "message_missed_subject" = "No subject"; -"message_attachment_saved_successfully" = "Attachemt was saved"; +"message_attachment_saved_successfully_title" = "Attachment Saved"; +"message_attachment_saved_successfully_message" = "Your attachment was saved in Files. Would you like to open it?"; "message_attachment_saved_with_error" = "Attachment could not be saved."; // REPLY diff --git a/FlowCryptCommon/Extensions/URLExtension.swift b/FlowCryptCommon/Extensions/URLExtension.swift new file mode 100644 index 000000000..7accb961a --- /dev/null +++ b/FlowCryptCommon/Extensions/URLExtension.swift @@ -0,0 +1,23 @@ +// +// URLExtension.swift +// FlowCryptCommon +// +// Created by Yevhen Kyivskyi on 24.06.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import Foundation + +public extension URL { + var sharedDocumentURL: URL? { + guard let scheme = self.scheme else { return nil } + + let urlString = self.absoluteString + let sharedDocumentUrlString = urlString.replacingOccurrences( + of: scheme, + with: "shareddocuments://" + ) + + return URL(string: sharedDocumentUrlString) + } +} From 85f7f311694844de2067bb2b69ac022f7b494cd2 Mon Sep 17 00:00:00 2001 From: ykyivskyi-gd Date: Thu, 24 Jun 2021 16:53:49 +0300 Subject: [PATCH 7/8] Fixed pbxproj file; --- FlowCrypt.xcodeproj/project.pbxproj | 63 ++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/FlowCrypt.xcodeproj/project.pbxproj b/FlowCrypt.xcodeproj/project.pbxproj index 0168e28a3..ce1b5d70d 100644 --- a/FlowCrypt.xcodeproj/project.pbxproj +++ b/FlowCrypt.xcodeproj/project.pbxproj @@ -11,7 +11,10 @@ 04B472951ECE29F600B8266F /* MyMenuViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B472921ECE29F600B8266F /* MyMenuViewController.swift */; }; 04B472961ECE29F600B8266F /* SideMenuNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B472931ECE29F600B8266F /* SideMenuNavigationController.swift */; }; 211392A5266511E6009202EC /* PubLookup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211392A4266511E6009202EC /* PubLookup.swift */; }; - 215897E8267A553300423694 /* FilesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 215897E7267A553200423694 /* FilesManager.swift */; }; + 21489B6B267B7BD800BDE4AC /* FilesManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B6A267B7BD800BDE4AC /* FilesManagerTests.swift */; }; + 21489B6C267B7C6A00BDE4AC /* FilesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 215897E7267A553200423694 /* FilesManager.swift */; }; + 21489B6E267B7D5000BDE4AC /* FileMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B6D267B7D5000BDE4AC /* FileMock.swift */; }; + 215897E8267A553300423694 /* FilesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 215897E7267A553200423694 /* FilesManager.swift */; }; 2196A2202684B9BE001B9E00 /* URLExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2196A21F2684B9BE001B9E00 /* URLExtension.swift */; }; 21489B78267CB42400BDE4AC /* ClientConfigurationProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B77267CB42400BDE4AC /* ClientConfigurationProvider.swift */; }; 21489B7A267CB4DF00BDE4AC /* ClientConfigurationObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B79267CB4DF00BDE4AC /* ClientConfigurationObject.swift */; }; @@ -786,6 +789,8 @@ 215897E7267A553200423694 /* FilesManager.swift */, ); path = FilesManager; + sourceTree = ""; + }; 21489B81267CC3BC00BDE4AC /* Organisational Rules Service */ = { isa = PBXGroup; children = ( @@ -2386,6 +2391,62 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + A3DAD5F722E4574A00F2C4CD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D2D27B7A248A874C007346FA /* BigIntExtension.swift in Sources */, + 9FC7EB7C266EB67D00F3BF5D /* EncryptedStorageProtocols.swift in Sources */, + 9F3EF32B23B16ADE00FA0CEF /* CommonExtensions.swift in Sources */, + 9FC7EBC2266EBE0100F3BF5D /* EmailProviderMock.swift in Sources */, + 9FC7EBD0266EBE1D00F3BF5D /* EncryptedPassPhraseStorageMock.swift in Sources */, + 9FA0157A26565B7800CBBA05 /* KeyMethodsTest.swift in Sources */, + A357699622EA2BC8009242C4 /* KeyInfo.swift in Sources */, + 9FC411902596229D001180A8 /* AppErr.swift in Sources */, + 9FC7EB69266EB64F00F3BF5D /* PassPhraseStorage.swift in Sources */, + D212D35E24C1AACF00035991 /* PrvKeyInfo.swift in Sources */, + 9F1D5769263B540100477938 /* Logger.swift in Sources */, + 9FC7EBC9266EBE0F00F3BF5D /* LocalPassPhraseStorageMock.swift in Sources */, + A3DAD5FE22E4574B00F2C4CD /* FlowCryptCoreTests.swift in Sources */, + 21489B6B267B7BD800BDE4AC /* FilesManagerTests.swift in Sources */, + 9FC7EBB0266EBD4600F3BF5D /* InMemoryPassPhraseStorage.swift in Sources */, + 21EA3B2326565B5D00691848 /* DomainRulesTests.swift in Sources */, + 9F4164102665754A00106194 /* PromiseExtensions.swift in Sources */, + 21F836CC2652A38700B2448C /* ZBase32EncodingTests.swift in Sources */, + 9FC7EBA3266EB95300F3BF5D /* PassPhraseStorageTests.swift in Sources */, + 9F7920EE2666D32500DA3D80 /* BackupServiceType.swift in Sources */, + 9FC7EB6F266EB66200F3BF5D /* PassPhrase.swift in Sources */, + D2A9CA45242622F800E1D898 /* GeneralConstantsTest.swift in Sources */, + 21489B6C267B7C6A00BDE4AC /* FilesManager.swift in Sources */, + A3DAD60B22E458C300F2C4CD /* DataExtensions.swift in Sources */, + 21EA3B532656611C00691848 /* OrganisationalRule.swift in Sources */, + A3DAD60822E4588800F2C4CD /* TestData.swift in Sources */, + D212D36124C1AC0D00035991 /* KeyDetails.swift in Sources */, + 9F6EE18C25A8AF970059BA51 /* GeneralConstants.swift in Sources */, + A3DAD60A22E458C100F2C4CD /* CodableExntensions.swift in Sources */, + D254733424C597CD00DEE698 /* CoreTypesTest.swift in Sources */, + 9F003DA425EA928200EB38C0 /* LocalStorage.swift in Sources */, + 9F7DE8C6232029D000F10B3E /* CoreTypes.swift in Sources */, + 9F3EF32A23B15C9600FA0CEF /* ImapHelperTest.swift in Sources */, + 5A39F439239ECDD0001F4607 /* ExtensionTests.swift in Sources */, + 21489B6E267B7D5000BDE4AC /* FileMock.swift in Sources */, + D212D36524C1AC4800035991 /* KeyId.swift in Sources */, + 9F003DBC25EA92D000EB38C0 /* LogOutHandler.swift in Sources */, + 21F836A02652A19A00B2448C /* WKDURLsConstructor.swift in Sources */, + 9F7920E32666D28400DA3D80 /* BackupServiceMock.swift in Sources */, + 9F7DE8C5232029BD00F10B3E /* Core.swift in Sources */, + 32DCAD6360C9EFF4FDD8EF6F /* DispatchTimeExtension.swift in Sources */, + 9F7DE8C723202A0200F10B3E /* CoreHost.swift in Sources */, + 9F3EF32823B15C8400FA0CEF /* ImapHelper.swift in Sources */, + 9F003D9E25EA910B00EB38C0 /* LocalStorageTests.swift in Sources */, + 9FA0158026565B9D00CBBA05 /* KeyMethods.swift in Sources */, + 32DCAF683D87EA6221F71335 /* SequenceExtensions.swift in Sources */, + 9F589F11238C7DDC007FD759 /* User.swift in Sources */, + 21F836D32652A46E00B2448C /* WKDURLsConstructorTests.swift in Sources */, + D2E26F6D24F263B600612AF1 /* KeyAlgo.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; C132B9AC1EC2DBD800763715 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; From a997a7e45aad381261ce5ece2bc2c9e5f24c8234 Mon Sep 17 00:00:00 2001 From: ykyivskyi-gd Date: Thu, 24 Jun 2021 16:55:22 +0300 Subject: [PATCH 8/8] Fixed merging effects --- FlowCrypt.xcodeproj/project.pbxproj | 56 ----------------------------- 1 file changed, 56 deletions(-) diff --git a/FlowCrypt.xcodeproj/project.pbxproj b/FlowCrypt.xcodeproj/project.pbxproj index ce1b5d70d..aea895c05 100644 --- a/FlowCrypt.xcodeproj/project.pbxproj +++ b/FlowCrypt.xcodeproj/project.pbxproj @@ -2391,62 +2391,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - A3DAD5F722E4574A00F2C4CD /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D2D27B7A248A874C007346FA /* BigIntExtension.swift in Sources */, - 9FC7EB7C266EB67D00F3BF5D /* EncryptedStorageProtocols.swift in Sources */, - 9F3EF32B23B16ADE00FA0CEF /* CommonExtensions.swift in Sources */, - 9FC7EBC2266EBE0100F3BF5D /* EmailProviderMock.swift in Sources */, - 9FC7EBD0266EBE1D00F3BF5D /* EncryptedPassPhraseStorageMock.swift in Sources */, - 9FA0157A26565B7800CBBA05 /* KeyMethodsTest.swift in Sources */, - A357699622EA2BC8009242C4 /* KeyInfo.swift in Sources */, - 9FC411902596229D001180A8 /* AppErr.swift in Sources */, - 9FC7EB69266EB64F00F3BF5D /* PassPhraseStorage.swift in Sources */, - D212D35E24C1AACF00035991 /* PrvKeyInfo.swift in Sources */, - 9F1D5769263B540100477938 /* Logger.swift in Sources */, - 9FC7EBC9266EBE0F00F3BF5D /* LocalPassPhraseStorageMock.swift in Sources */, - A3DAD5FE22E4574B00F2C4CD /* FlowCryptCoreTests.swift in Sources */, - 21489B6B267B7BD800BDE4AC /* FilesManagerTests.swift in Sources */, - 9FC7EBB0266EBD4600F3BF5D /* InMemoryPassPhraseStorage.swift in Sources */, - 21EA3B2326565B5D00691848 /* DomainRulesTests.swift in Sources */, - 9F4164102665754A00106194 /* PromiseExtensions.swift in Sources */, - 21F836CC2652A38700B2448C /* ZBase32EncodingTests.swift in Sources */, - 9FC7EBA3266EB95300F3BF5D /* PassPhraseStorageTests.swift in Sources */, - 9F7920EE2666D32500DA3D80 /* BackupServiceType.swift in Sources */, - 9FC7EB6F266EB66200F3BF5D /* PassPhrase.swift in Sources */, - D2A9CA45242622F800E1D898 /* GeneralConstantsTest.swift in Sources */, - 21489B6C267B7C6A00BDE4AC /* FilesManager.swift in Sources */, - A3DAD60B22E458C300F2C4CD /* DataExtensions.swift in Sources */, - 21EA3B532656611C00691848 /* OrganisationalRule.swift in Sources */, - A3DAD60822E4588800F2C4CD /* TestData.swift in Sources */, - D212D36124C1AC0D00035991 /* KeyDetails.swift in Sources */, - 9F6EE18C25A8AF970059BA51 /* GeneralConstants.swift in Sources */, - A3DAD60A22E458C100F2C4CD /* CodableExntensions.swift in Sources */, - D254733424C597CD00DEE698 /* CoreTypesTest.swift in Sources */, - 9F003DA425EA928200EB38C0 /* LocalStorage.swift in Sources */, - 9F7DE8C6232029D000F10B3E /* CoreTypes.swift in Sources */, - 9F3EF32A23B15C9600FA0CEF /* ImapHelperTest.swift in Sources */, - 5A39F439239ECDD0001F4607 /* ExtensionTests.swift in Sources */, - 21489B6E267B7D5000BDE4AC /* FileMock.swift in Sources */, - D212D36524C1AC4800035991 /* KeyId.swift in Sources */, - 9F003DBC25EA92D000EB38C0 /* LogOutHandler.swift in Sources */, - 21F836A02652A19A00B2448C /* WKDURLsConstructor.swift in Sources */, - 9F7920E32666D28400DA3D80 /* BackupServiceMock.swift in Sources */, - 9F7DE8C5232029BD00F10B3E /* Core.swift in Sources */, - 32DCAD6360C9EFF4FDD8EF6F /* DispatchTimeExtension.swift in Sources */, - 9F7DE8C723202A0200F10B3E /* CoreHost.swift in Sources */, - 9F3EF32823B15C8400FA0CEF /* ImapHelper.swift in Sources */, - 9F003D9E25EA910B00EB38C0 /* LocalStorageTests.swift in Sources */, - 9FA0158026565B9D00CBBA05 /* KeyMethods.swift in Sources */, - 32DCAF683D87EA6221F71335 /* SequenceExtensions.swift in Sources */, - 9F589F11238C7DDC007FD759 /* User.swift in Sources */, - 21F836D32652A46E00B2448C /* WKDURLsConstructorTests.swift in Sources */, - D2E26F6D24F263B600612AF1 /* KeyAlgo.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; C132B9AC1EC2DBD800763715 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647;