IOS-273 integrate trashing mails into NetworkService, UI
authorDirk Zimmermann <dirk@pep-project.org>
Wed, 08 Feb 2017 08:31:46 +0100
changeset 165033eba5b4f5f5
parent 1649 e10ecf2d2ecb
child 1651 b13d3139ad92
IOS-273 integrate trashing mails into NetworkService, UI
pEpForiOS/Models/CdMessage+Pantomime.swift
pEpForiOS/Network/Service/NetworkService.swift
pEpForiOS/UI/EmailDisplay/EmailListViewController.swift
pEpForiOSTests/NetworkServiceTests.swift
     1.1 --- a/pEpForiOS/Models/CdMessage+Pantomime.swift	Tue Feb 07 17:40:35 2017 +0100
     1.2 +++ b/pEpForiOS/Models/CdMessage+Pantomime.swift	Wed Feb 08 08:31:46 2017 +0100
     1.3 @@ -355,6 +355,9 @@
     1.4          Record.saveAndWait()
     1.5          if mail.pEpRating != PEPUtil.pEpRatingNone,
     1.6              let msg = mail.message() {
     1.7 +            if msg.isGhost {
     1.8 +                Log.info(component: #function, content: "Message ghost from full insert?")
     1.9 +            }
    1.10              MessageModelConfig.messageFolderDelegate?.didChange(messageFolder: msg)
    1.11          }
    1.12  
     2.1 --- a/pEpForiOS/Network/Service/NetworkService.swift	Tue Feb 07 17:40:35 2017 +0100
     2.2 +++ b/pEpForiOS/Network/Service/NetworkService.swift	Wed Feb 08 08:31:46 2017 +0100
     2.3 @@ -67,6 +67,8 @@
     2.4      let backgrounder: BackgroundTaskProtocol?
     2.5      let mySelfer: KickOffMySelfProtocol?
     2.6  
     2.7 +    let context = Record.Context.background
     2.8 +
     2.9      public init(sleepTimeInSeconds: Double = 10.0, parentName: String? = nil,
    2.10                  backgrounder: BackgroundTaskProtocol? = nil,
    2.11                  mySelfer: KickOffMySelfProtocol? = nil) {
    2.12 @@ -153,8 +155,7 @@
    2.13          }
    2.14      }
    2.15  
    2.16 -    func fetchAccounts(
    2.17 -        context: NSManagedObjectContext, needsVerificationOnly: Bool = false) -> [CdAccount] {
    2.18 +    func fetchAccounts(needsVerificationOnly: Bool = false) -> [CdAccount] {
    2.19          let p = NSPredicate(format: "needsVerification = %@",
    2.20                              NSNumber(booleanLiteral: needsVerificationOnly))
    2.21          return CdAccount.all(predicate: p, in: context) as? [CdAccount] ?? []
    2.22 @@ -162,10 +163,8 @@
    2.23  
    2.24      func gatherConnectInfos(needsVerificationOnly: Bool = false) -> [AccountConnectInfo] {
    2.25          var connectInfos = [AccountConnectInfo]()
    2.26 -        let context = Record.Context.background
    2.27          context.performAndWait {
    2.28 -            let accounts = self.fetchAccounts(
    2.29 -                context: context, needsVerificationOnly: needsVerificationOnly)
    2.30 +            let accounts = self.fetchAccounts(needsVerificationOnly: needsVerificationOnly)
    2.31              for acc in accounts {
    2.32                  let smtpCI = acc.smtpConnectInfo
    2.33                  let imapCI = acc.imapConnectInfo
    2.34 @@ -181,9 +180,8 @@
    2.35      func checkVerified(accountInfo: AccountConnectInfo,
    2.36                         operations: [BaseOperation], needsVerificationOnly: Bool) {
    2.37          if needsVerificationOnly {
    2.38 -            let context = Record.Context.background
    2.39              context.performAndWait {
    2.40 -                guard let account = context.object(with: accountInfo.accountID) as? CdAccount else {
    2.41 +                guard let account = self.context.object(with: accountInfo.accountID) as? CdAccount else {
    2.42                      return
    2.43                  }
    2.44                  var accountVerified = true
    2.45 @@ -196,7 +194,7 @@
    2.46                  }
    2.47                  if accountVerified {
    2.48                      account.needsVerification = false
    2.49 -                    Record.saveAndWait(context: context)
    2.50 +                    Record.saveAndWait(context: self.context)
    2.51                      self.sendLayerDelegate?.didVerify(cdAccount: account, error: nil)
    2.52                      self.mySelfer?.startMySelf()
    2.53                  } else {
    2.54 @@ -269,6 +267,21 @@
    2.55          return (opDrafts, [opAppend, opDrafts])
    2.56      }
    2.57  
    2.58 +    func buildTrashOperations(
    2.59 +        imapSyncData: ImapSyncData, errorContainer: ServiceErrorProtocol,
    2.60 +        opImapFinished: Operation, previousOp: BaseOperation) -> (BaseOperation?, [Operation]) {
    2.61 +        var lastOp = previousOp
    2.62 +        var trashOps = [TrashMailsOperation]()
    2.63 +        let folders = TrashMailsOperation.foldersWithTrashedMessages(context: context)
    2.64 +        for cdF in folders {
    2.65 +            let op = TrashMailsOperation(imapSyncData: imapSyncData, folder: cdF)
    2.66 +            op.addDependency(lastOp)
    2.67 +            opImapFinished.addDependency(op)
    2.68 +            lastOp = op
    2.69 +            trashOps.append(op)
    2.70 +        }
    2.71 +        return (lastOp, trashOps)
    2.72 +    }
    2.73  
    2.74      /**
    2.75       Determine "interesting" folder names that should be synced, and for each:
    2.76 @@ -449,12 +462,17 @@
    2.77                  opImapFinished: opImapFinished, previousOp: opFetchFolders)
    2.78              operations.append(contentsOf: sendOperations)
    2.79  
    2.80 +            let (lastTrashOp, trashOperations) = buildTrashOperations(
    2.81 +                imapSyncData: imapSyncData, errorContainer: errorContainer,
    2.82 +                opImapFinished: opImapFinished, previousOp: lastSendOp ?? opFetchFolders)
    2.83 +            operations.append(contentsOf: trashOperations)
    2.84 +
    2.85              // 3.d Server-to-client synchronization (IMAP)
    2.86  
    2.87              let folderInfos = determineInterestingFolders(accountInfo: accountInfo)
    2.88  
    2.89              // sync new messages
    2.90 -            var lastImapOp: Operation = lastSendOp ?? opFetchFolders
    2.91 +            var lastImapOp: Operation = lastTrashOp ?? opFetchFolders
    2.92              for fi in folderInfos {
    2.93                  let fetchMessagesOp = FetchMessagesOperation(
    2.94                      parentName: parentName, errorContainer: errorContainer,
     3.1 --- a/pEpForiOS/UI/EmailDisplay/EmailListViewController.swift	Tue Feb 07 17:40:35 2017 +0100
     3.2 +++ b/pEpForiOS/UI/EmailDisplay/EmailListViewController.swift	Wed Feb 08 08:31:46 2017 +0100
     3.3 @@ -190,7 +190,7 @@
     3.4                  return
     3.5              }
     3.6  
     3.7 -            message.imapFlags?.deleted = true
     3.8 +            message.delete() // mark for deletion/trash
     3.9              message.save()
    3.10              self.tableView.reloadData()
    3.11          }
     4.1 --- a/pEpForiOSTests/NetworkServiceTests.swift	Tue Feb 07 17:40:35 2017 +0100
     4.2 +++ b/pEpForiOSTests/NetworkServiceTests.swift	Wed Feb 08 08:31:46 2017 +0100
     4.3 @@ -168,9 +168,11 @@
     4.4          to.userName = "Unit 001"
     4.5          to.address = "unittest.ios.1@peptest.ch"
     4.6  
     4.7 -        let folder = CdFolder.by(folderType: .sent, account: cdAccount)
     4.8 -        XCTAssertNotNil(folder)
     4.9 -        XCTAssertEqual((folder?.messages ?? NSSet()).count, 0)
    4.10 +        guard let sentFolder = CdFolder.by(folderType: .sent, account: cdAccount) else {
    4.11 +            XCTFail()
    4.12 +            return
    4.13 +        }
    4.14 +        XCTAssertEqual((sentFolder.messages ?? NSSet()).count, 0)
    4.15  
    4.16          // Build outgoing emails
    4.17          var outgoingMails = [CdMessage]()
    4.18 @@ -179,7 +181,7 @@
    4.19          for i in 1...numMails {
    4.20              let message = CdMessage.create()
    4.21              message.from = from
    4.22 -            message.parent = folder
    4.23 +            message.parent = sentFolder
    4.24              message.shortMessage = "Some subject \(i)"
    4.25              message.longMessage = "Long message \(i)"
    4.26              message.longMessageFormatted = "<h1>Long HTML \(i)</h1>"
    4.27 @@ -213,12 +215,6 @@
    4.28              XCTAssertTrue(m.isDeleted)
    4.29          }
    4.30  
    4.31 -        guard let sentFolder = CdFolder.by(folderType: .sent, account: cdAccount) else {
    4.32 -            XCTFail()
    4.33 -            cancelNetworkService(networkService: networkService)
    4.34 -            return
    4.35 -        }
    4.36 -
    4.37          // Make sure the sent folder will still *not* be synced in the next step
    4.38          sentFolder.lastLookedAt = Date(
    4.39              timeIntervalSinceNow: -(networkService.timeIntervalForInterestingFolders + 1))