merge IOS-1336
authorXavier Algarra <xavier@pep-project.org>
Mon, 29 Oct 2018 12:47:12 +0100
branchIOS-1336
changeset 6940b4ba8d4a1351
parent 6939 c60309f5e255
parent 6936 b884a23e02bd
child 6941 870b42369359
merge
pEpForiOS/UI/EmailDisplayList/MessageViewModel+Operations.swift
     1.1 --- a/pEpForiOS.xcodeproj/project.pbxproj	Mon Oct 29 12:46:22 2018 +0100
     1.2 +++ b/pEpForiOS.xcodeproj/project.pbxproj	Mon Oct 29 12:47:12 2018 +0100
     1.3 @@ -31,7 +31,6 @@
     1.4  		004422CA2179ECD600BDF6DF /* PassiveModeViewModelTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004422C92179ECD600BDF6DF /* PassiveModeViewModelTest.swift */; };
     1.5  		004422D9217A25AD00BDF6DF /* UnecryptedSubjectViewModelTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004422D8217A25AD00BDF6DF /* UnecryptedSubjectViewModelTest.swift */; };
     1.6  		004A8C552112FDD500203143 /* EmailListView+UITableViewDataSourcePrefetching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004A8C542112FDD500203143 /* EmailListView+UITableViewDataSourcePrefetching.swift */; };
     1.7 -		004A8C592113056900203143 /* MessageViewModel+Operations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004A8C582113056900203143 /* MessageViewModel+Operations.swift */; };
     1.8  		004A8C5B211316E100203143 /* SelfReferencingOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004A8C5A211316E100203143 /* SelfReferencingOperation.swift */; };
     1.9  		005A21FB20CAA5F50082D19F /* ThreadedEmailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 005A21FA20CAA5F50082D19F /* ThreadedEmailViewModel.swift */; };
    1.10  		0069DCFB2110679200846EB1 /* EmailViewController+UIPopoverPresentationControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0069DCFA2110679200846EB1 /* EmailViewController+UIPopoverPresentationControllerDelegate.swift */; };
    1.11 @@ -603,7 +602,6 @@
    1.12  		004422C92179ECD600BDF6DF /* PassiveModeViewModelTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassiveModeViewModelTest.swift; sourceTree = "<group>"; };
    1.13  		004422D8217A25AD00BDF6DF /* UnecryptedSubjectViewModelTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnecryptedSubjectViewModelTest.swift; sourceTree = "<group>"; };
    1.14  		004A8C542112FDD500203143 /* EmailListView+UITableViewDataSourcePrefetching.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EmailListView+UITableViewDataSourcePrefetching.swift"; sourceTree = "<group>"; };
    1.15 -		004A8C582113056900203143 /* MessageViewModel+Operations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MessageViewModel+Operations.swift"; sourceTree = "<group>"; };
    1.16  		004A8C5A211316E100203143 /* SelfReferencingOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelfReferencingOperation.swift; sourceTree = "<group>"; };
    1.17  		005A21FA20CAA5F50082D19F /* ThreadedEmailViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreadedEmailViewModel.swift; sourceTree = "<group>"; };
    1.18  		0069DCFA2110679200846EB1 /* EmailViewController+UIPopoverPresentationControllerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EmailViewController+UIPopoverPresentationControllerDelegate.swift"; sourceTree = "<group>"; };
    1.19 @@ -1221,7 +1219,6 @@
    1.20  			isa = PBXGroup;
    1.21  			children = (
    1.22  				000D3C2E20D12BFD006B11B2 /* MessageViewModel.swift */,
    1.23 -				004A8C582113056900203143 /* MessageViewModel+Operations.swift */,
    1.24  				0038494920D25576008000EA /* ProfilePictureComposer.swift */,
    1.25  				0038494B20D2587F008000EA /* PepPictureComposer.swift */,
    1.26  			);
    1.27 @@ -3123,7 +3120,6 @@
    1.28  				436C232F1E02A52D00071430 /* LimitedOperationQueue.swift in Sources */,
    1.29  				434F40941EB0B173002FBF0D /* ObservableValue.swift in Sources */,
    1.30  				15F0F7AD213594FC002BE853 /* Folder+Imap.swift in Sources */,
    1.31 -				004A8C592113056900203143 /* MessageViewModel+Operations.swift in Sources */,
    1.32  				430D73651E9CBD4E00EA6FA9 /* AttachmentsViewOperation.swift in Sources */,
    1.33  				495F607C20B564CD00F47BD6 /* EmailViewController+SizeClasses.swift in Sources */,
    1.34  				43313DFC1DEC7F6000C111C8 /* DeleteFoldersOperation.swift in Sources */,
     2.1 --- a/pEpForiOS/UI/EmailDisplayList/EmailListViewModel+MessageFolderDelegate.swift	Mon Oct 29 12:46:22 2018 +0100
     2.2 +++ b/pEpForiOS/UI/EmailDisplayList/EmailListViewModel+MessageFolderDelegate.swift	Mon Oct 29 12:47:12 2018 +0100
     2.3 @@ -352,7 +352,7 @@
     2.4      private func update(topMessage: Message,
     2.5                          previewMessage: MessageViewModel,
     2.6                          atIndex indexExisting: Int) {
     2.7 -        DispatchQueue.main.async { [weak self] in
     2.8 +        DispatchQueue.main.sync { [weak self] in
     2.9              guard let me = self else {
    2.10                  // Assumtion taken over from original implementaion: It's ok here.
    2.11                  return
     3.1 --- a/pEpForiOS/UI/EmailDisplayList/MessageViewModel+Operations.swift	Mon Oct 29 12:46:22 2018 +0100
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,106 +0,0 @@
     3.4 -//
     3.5 -//  MessageViewModel+PrefetchableViewModel.swift
     3.6 -//  pEp
     3.7 -//
     3.8 -//  Created by Borja González de Pablo on 02/08/2018.
     3.9 -//  Copyright © 2018 p≡p Security S.A. All rights reserved.
    3.10 -//
    3.11 -
    3.12 -import Foundation
    3.13 -import MessageModel
    3.14 -
    3.15 -extension MessageViewModel {
    3.16 -
    3.17 -    func getMessageCountOperation(completion: @escaping (Int)->()) -> SelfReferencingOperation {
    3.18 -       
    3.19 -        let getMessageCountOperation = SelfReferencingOperation {  [weak self] operation in
    3.20 -            guard let me = self else {
    3.21 -                return
    3.22 -            }
    3.23 -            MessageModel.performAndWait {
    3.24 -                guard
    3.25 -                    let operation = operation,
    3.26 -                    !operation.isCancelled,
    3.27 -                let message = me.message() else {
    3.28 -                    return
    3.29 -                }
    3.30 -                let messageCount = message.numberOfMessagesInThread()
    3.31 -                me.internalMessageCount = messageCount
    3.32 -                if (!operation.isCancelled){
    3.33 -                    DispatchQueue.main.async {
    3.34 -                        completion(messageCount)
    3.35 -                    }
    3.36 -                }
    3.37 -            }
    3.38 -        }
    3.39 -        return getMessageCountOperation
    3.40 -    }
    3.41 -
    3.42 -    func getBodyPeekOperation(for message: Message, completion: @escaping (String)->()) -> SelfReferencingOperation {
    3.43 -
    3.44 -        let getBodyPeekOperation = SelfReferencingOperation {operation in
    3.45 -            guard
    3.46 -                let operation = operation,
    3.47 -                !operation.isCancelled else {
    3.48 -                return
    3.49 -            }
    3.50 -            MessageModel.performAndWait {
    3.51 -                guard !operation.isCancelled else {
    3.52 -                    return
    3.53 -                }
    3.54 -                let summary = MessageViewModel.getSummary(fromMessage: message)
    3.55 -                guard !operation.isCancelled else {
    3.56 -                    return
    3.57 -                }
    3.58 -                self.internalBoddyPeek = summary
    3.59 -                if(!operation.isCancelled){
    3.60 -                    DispatchQueue.main.async {
    3.61 -                        completion(summary)
    3.62 -                    }
    3.63 -                }
    3.64 -            }
    3.65 -        }
    3.66 -        return getBodyPeekOperation
    3.67 -    }
    3.68 -
    3.69 -    func getSecurityBadgeOperation(
    3.70 -        completion: @escaping (UIImage?) -> ()) -> SelfReferencingOperation {
    3.71 -        let getSecurityBadgeOperation = SelfReferencingOperation { [weak self] operation in
    3.72 -            guard let me = self else {
    3.73 -                return
    3.74 -            }
    3.75 -            MessageModel.performAndWait {
    3.76 -                guard
    3.77 -                    let operation = operation,
    3.78 -                    !operation.isCancelled,
    3.79 -                    let message = me.message() else {
    3.80 -                        return
    3.81 -                }
    3.82 -
    3.83 -                if (!operation.isCancelled) {
    3.84 -                    me.profilePictureComposer.securityBadge(for: message, completion: completion)
    3.85 -                }
    3.86 -            }
    3.87 -        }
    3.88 -        return getSecurityBadgeOperation
    3.89 -    }
    3.90 -
    3.91 -    func getProfilePictureOperation(
    3.92 -        completion: @escaping (UIImage?) -> ()) -> SelfReferencingOperation {
    3.93 -        let getSecurityBadgeOperation = SelfReferencingOperation { [weak self] operation in
    3.94 -            guard let me = self else {
    3.95 -                return
    3.96 -            }
    3.97 -            MessageModel.performAndWait {
    3.98 -                guard
    3.99 -                    let operation = operation,
   3.100 -                    !operation.isCancelled else {
   3.101 -                        return
   3.102 -                }
   3.103 -                me.profilePictureComposer.profilePicture(for: me.displayedImageIdentity, completion: completion)
   3.104 -            }
   3.105 -        }
   3.106 -        return getSecurityBadgeOperation
   3.107 -    }
   3.108 -
   3.109 -}
     4.1 --- a/pEpForiOS/UI/EmailDisplayList/MessageViewModel.swift	Mon Oct 29 12:46:22 2018 +0100
     4.2 +++ b/pEpForiOS/UI/EmailDisplayList/MessageViewModel.swift	Mon Oct 29 12:47:12 2018 +0100
     4.3 @@ -18,8 +18,8 @@
     4.4      private let uuid: MessageID
     4.5      private let parentFolderName: String
     4.6      private let accountAddress: String
     4.7 +    private let displayedImageIdentity: Identity
     4.8  
     4.9 -    let displayedImageIdentity: Identity
    4.10      let identity:Identity
    4.11      let dateSent: Date
    4.12      let longMessageFormatted: String?
    4.13 @@ -310,3 +310,101 @@
    4.14          return uuid
    4.15      }
    4.16  }
    4.17 +
    4.18 +//PRAGMA MARK: Message View Model + Operations
    4.19 +
    4.20 +extension MessageViewModel {
    4.21 +
    4.22 +    private func getMessageCountOperation(completion: @escaping (Int)->()) -> SelfReferencingOperation {
    4.23 +
    4.24 +        let getMessageCountOperation = SelfReferencingOperation {  [weak self] operation in
    4.25 +            guard let me = self else {
    4.26 +                return
    4.27 +            }
    4.28 +            MessageModel.performAndWait {
    4.29 +                guard
    4.30 +                    let operation = operation,
    4.31 +                    !operation.isCancelled,
    4.32 +                    let message = me.message() else {
    4.33 +                        return
    4.34 +                }
    4.35 +                let messageCount = message.numberOfMessagesInThread()
    4.36 +                me.internalMessageCount = messageCount
    4.37 +                if (!operation.isCancelled){
    4.38 +                    DispatchQueue.main.async {
    4.39 +                        completion(messageCount)
    4.40 +                    }
    4.41 +                }
    4.42 +            }
    4.43 +        }
    4.44 +        return getMessageCountOperation
    4.45 +    }
    4.46 +
    4.47 +    private func getBodyPeekOperation(for message: Message, completion: @escaping (String)->()) -> SelfReferencingOperation {
    4.48 +
    4.49 +        let getBodyPeekOperation = SelfReferencingOperation {operation in
    4.50 +            guard
    4.51 +                let operation = operation,
    4.52 +                !operation.isCancelled else {
    4.53 +                    return
    4.54 +            }
    4.55 +            MessageModel.performAndWait {
    4.56 +                guard !operation.isCancelled else {
    4.57 +                    return
    4.58 +                }
    4.59 +                let summary = MessageViewModel.getSummary(fromMessage: message)
    4.60 +                guard !operation.isCancelled else {
    4.61 +                    return
    4.62 +                }
    4.63 +                self.internalBoddyPeek = summary
    4.64 +                if(!operation.isCancelled){
    4.65 +                    DispatchQueue.main.async {
    4.66 +                        completion(summary)
    4.67 +                    }
    4.68 +                }
    4.69 +            }
    4.70 +        }
    4.71 +        return getBodyPeekOperation
    4.72 +    }
    4.73 +
    4.74 +    private func getSecurityBadgeOperation(
    4.75 +        completion: @escaping (UIImage?) -> ()) -> SelfReferencingOperation {
    4.76 +        let getSecurityBadgeOperation = SelfReferencingOperation { [weak self] operation in
    4.77 +            guard let me = self else {
    4.78 +                return
    4.79 +            }
    4.80 +            MessageModel.performAndWait {
    4.81 +                guard
    4.82 +                    let operation = operation,
    4.83 +                    !operation.isCancelled,
    4.84 +                    let message = me.message() else {
    4.85 +                        return
    4.86 +                }
    4.87 +
    4.88 +                if (!operation.isCancelled) {
    4.89 +                    me.profilePictureComposer.securityBadge(for: message, completion: completion)
    4.90 +                }
    4.91 +            }
    4.92 +        }
    4.93 +        return getSecurityBadgeOperation
    4.94 +    }
    4.95 +
    4.96 +    private func getProfilePictureOperation(
    4.97 +        completion: @escaping (UIImage?) -> ()) -> SelfReferencingOperation {
    4.98 +        let getSecurityBadgeOperation = SelfReferencingOperation { [weak self] operation in
    4.99 +            guard let me = self else {
   4.100 +                return
   4.101 +            }
   4.102 +            MessageModel.performAndWait {
   4.103 +                guard
   4.104 +                    let operation = operation,
   4.105 +                    !operation.isCancelled else {
   4.106 +                        return
   4.107 +                }
   4.108 +                me.profilePictureComposer.profilePicture(for: me.displayedImageIdentity, completion: completion)
   4.109 +            }
   4.110 +        }
   4.111 +        return getSecurityBadgeOperation
   4.112 +    }
   4.113 +
   4.114 +}
     5.1 --- a/pEpForiOSTests/Models/Folder/FolderCellViewModelTests.swift	Mon Oct 29 12:46:22 2018 +0100
     5.2 +++ b/pEpForiOSTests/Models/Folder/FolderCellViewModelTests.swift	Mon Oct 29 12:47:12 2018 +0100
     5.3 @@ -45,15 +45,47 @@
     5.4          XCTAssertEqual(icon, inputIcon)
     5.5      }
     5.6      
     5.7 -    func testIsSelectable() {
     5.8 +    func testIsNotSelectable() {
     5.9          givenAViewModelWithFolderAndLevel()
    5.10          let isSelectable = viewModel.isSelectable
    5.11 -        let inputSelectable = folder.isLocalFolder || folder.selectable
    5.12 -        XCTAssertEqual(isSelectable, inputSelectable)
    5.13 +        XCTAssertFalse(isSelectable)
    5.14 +    }
    5.15 +
    5.16 +    func testIsSelectableFolderIfIsUnified(){
    5.17 +        givenAviewModelWithUnifiedFolder()
    5.18 +        let isSelectable = viewModel.isSelectable
    5.19 +        XCTAssertTrue(isSelectable)
    5.20 +    }
    5.21 +
    5.22 +    func testIsSelectableFolderIfIsLocal() {
    5.23 +        givenAViewModelWithLocalFolder()
    5.24 +        let isSelectable = viewModel.isSelectable
    5.25 +        XCTAssertTrue(isSelectable)
    5.26 +    }
    5.27 +
    5.28 +    func testSelectableFolderIsSelectable() {
    5.29 +        givenAViewModelWithSelectableFolder()
    5.30 +        let isSelectable = viewModel.isSelectable
    5.31 +        XCTAssertTrue(isSelectable)
    5.32 +    }
    5.33 +
    5.34 +    func givenAViewModelWithSelectableFolder() {
    5.35 +        folder = Folder(name: Input.folderName, parent: nil, account: account, folderType:.outbox, selectable: false)
    5.36 +        viewModel = FolderCellViewModel(folder: folder, level: 0)
    5.37      }
    5.38      
    5.39 +    func givenAviewModelWithUnifiedFolder() {
    5.40 +        viewModel = FolderCellViewModel(folder: UnifiedInbox(), level: 0)
    5.41 +    }
    5.42 +
    5.43 +    func givenAViewModelWithLocalFolder() {
    5.44 +        folder = Folder(name: Input.folderName, parent: nil, account: account, folderType: .outbox)
    5.45 +        viewModel = FolderCellViewModel(folder: folder, level: 0)
    5.46 +
    5.47 +    }
    5.48 +
    5.49      func givenAViewModelWithFolderAndLevel() {
    5.50 -        
    5.51 +
    5.52          let level = Input.level
    5.53          viewModel = FolderCellViewModel(folder: folder, level: level)
    5.54      }
     6.1 --- a/pEpForiOSTests/Models/MessageViewModelTests.swift	Mon Oct 29 12:46:22 2018 +0100
     6.2 +++ b/pEpForiOSTests/Models/MessageViewModelTests.swift	Mon Oct 29 12:47:12 2018 +0100
     6.3 @@ -46,6 +46,7 @@
     6.4              static let longLongMessage = "Hey Borja, How is it going? Are you okay? I was wondering"
     6.5                  + " if we could meet sometime this afternoon. I would like to disc"
     6.6              static let expectedDateText = "Jan 2, 1991"
     6.7 +            static let expectedNumberOfMessages = 0
     6.8          }
     6.9      }
    6.10  
    6.11 @@ -141,6 +142,17 @@
    6.12          wait(for: [expectation], timeout: specificWaitTime)
    6.13      }
    6.14  
    6.15 +    func testMessageCountIsReceived() {
    6.16 +        givenViewModelRepresentsASubjectAndBodyMessage()
    6.17 +        let specificWaitTime = UnitTestUtils.waitTime * 5000
    6.18 +        let expectation = XCTestExpectation(description: "Message count is received")
    6.19 +        viewModel.messageCount { (numberOfMessages) in
    6.20 +            XCTAssertEqual(numberOfMessages, Defaults.Outputs.expectedNumberOfMessages)
    6.21 +            expectation.fulfill()
    6.22 +        }
    6.23 +        wait(for: [expectation], timeout: specificWaitTime)
    6.24 +    }
    6.25 +
    6.26      func testFormattedBody() {
    6.27          givenViewModelRepresentsMessageWithFormattedBody()
    6.28          let formattedMessage = viewModel.longMessageFormatted
    6.29 @@ -195,6 +207,14 @@
    6.30          waitForExpectations(timeout: UnitTestUtils.waitTime)
    6.31      }
    6.32  
    6.33 +    func testMessageCountIsAddedToQueue() {
    6.34 +        givenViewModelHasAnAddingExpectationOperationQueue()
    6.35 +        viewModel.messageCount { _ in
    6.36 +            //do nothing
    6.37 +        }
    6.38 +        waitForExpectations(timeout: UnitTestUtils.waitTime)
    6.39 +    }
    6.40 +
    6.41      func testQueueCancelledWhenStoppingUpdates() {
    6.42          givenViewModelHasACancellingExpectationOperationQueue()
    6.43          viewModel.unsubscribeForUpdates()
    6.44 @@ -243,6 +263,17 @@
    6.45          XCTAssertEqual(message, retrievedMessage)
    6.46      }
    6.47  
    6.48 +    func testFromIdentity() {
    6.49 +        let message = givenThereIsAOneRecipientMessage()
    6.50 +        viewModel = MessageViewModel(with: message)
    6.51 +        guard let identity = message.from else {
    6.52 +            XCTFail("No identity")
    6.53 +            return
    6.54 +        }
    6.55 +        let retrievedIdentity = viewModel.identity
    6.56 +        XCTAssertEqual(identity, retrievedIdentity)
    6.57 +    }
    6.58 +
    6.59      //PRAGMA - MARK: GIVEN
    6.60  
    6.61      //PRAGMA MARK: ViewModels