From 78c3862978ef0d6e9bbfe8383618a28c4a4f529f Mon Sep 17 00:00:00 2001
From: Oliver Wiese <oliver.wiese@fu-berlin.de>
Date: Sat, 10 Apr 2021 11:48:17 +0200
Subject: [PATCH] fix bug: delete/read flag

---
 enzevalos_iphone/MailHandler.swift            | 90 ++-----------------
 enzevalos_iphone/OutgoingMail.swift           |  2 +-
 .../SwiftUI/Inbox/MailListView.swift          |  3 +-
 .../SwiftUI/Read/ReadMainView.swift           |  5 +-
 enzevalos_iphone/SwiftUI/Read/ReadModel.swift | 31 ++++---
 .../Read/Tabbed Views/MessageViewMain.swift   |  8 +-
 .../persistentData/MailRecord.swift           | 37 ++++++--
 .../PersistentDataProvider.swift              | 21 +----
 8 files changed, 67 insertions(+), 130 deletions(-)

diff --git a/enzevalos_iphone/MailHandler.swift b/enzevalos_iphone/MailHandler.swift
index 06e01d27..f7d8dfc2 100644
--- a/enzevalos_iphone/MailHandler.swift
+++ b/enzevalos_iphone/MailHandler.swift
@@ -519,105 +519,25 @@
     }
     
     func move(mails: [UInt64], fromPath: String, toPath: String)  {
-        // 1. Check IMAP session
-        guard let session = IMAPSession else {
-            return
-        }
-        // 2. Check if we have to create a folder.
+        // 1. Check if we have to create a folder.
         createFolders(of: [fromPath, toPath], completionHandler: {error in
             guard error == nil else {
                 return
             }
-            // 3. Move mail on server
+            // 2. Move mail on server
             guard let fromFolder = self.dataProvider.generateFetchedFolderResultsController(folderpath: fromPath, moc: nil).fetchedObjects?.first else {
                 return
             }
             if let uidValidity = fromFolder.uidValidity as? UInt32 {
                 self.moveOnServer(uidValidity: uidValidity, mails: mails, fromPath: fromPath, toPath: toPath, completionHandler: {error in
-                                    print("Move mails from \(fromFolder) to \(toPath) complete with error \(String(describing: error))")})
-                    // 4. Move mail in core data
+                    // 3. Move mail in core data
                     self.dataProvider.moveMails(with: mails, from: fromPath, to: toPath)
+                })
+                    
             }
         })
     }
     
-    /* TODO
-     func move(mails: [MailRecord], from: String, to: String, folderCreated: Bool = false) {
-        guard IMAPSession != nil else {
-            return
-        }
-        let uids = MCOIndexSet()
-        let provider = PersistentDataProvider.dataProvider
-        guard let toFolders = provider.generateFetchedFolderResultsController(folderpath: to).fetchedObjects else {
-            return
-        }
-        guard let fromFolder = provider.generateFetchedFolderResultsController(folderpath: from).fetchedObjects?.first else {
-            return
-        }
-        // Create a folder -> Do we have to check if the folder exists on the server?
-        guard toFolders.isEmpty && !folderCreated else {
-            let op = IMAPSession?.createFolderOperation(to)
-            op?.start({[unowned self] error in
-                guard error == nil else {
-                    let conError = MailServerConnectionError.findErrorCode(error: error!)
-                    self.errorhandling(error: conError, originalCall: {self.move(mails: mails, from: from, to: to)}, completionCallback: nil)
-                    return
-                }
-                self.move(mails: mails, from: from, to: to, folderCreated: true)
-            })
-            return
-        }
-        let folderstatusFrom = IMAPSession?.folderStatusOperation(from)
-        folderstatusFrom?.start {[unowned self] (error, status) -> Void in
-            guard error == nil else {
-                let conerror = MailServerConnectionError.findErrorCode(error: error!)
-                self.errorhandling(error: conerror, originalCall: {self.move(mails: mails, from: from, to: to)}, completionCallback: nil)
-                return
-            }
-            if let statusFrom = status, let currentUidValidity = fromFolder.uidValidity as? UInt32 {
-                let uidValidity = statusFrom.uidValidity
-                var uids = MCOIndexSet()
-                if uidValidity == currentUidValidity {
-                    for mail in mails {
-                        uids.add(mail.uID)
-                        mail.folder.removeFromMails(mail)
-                        if let record = mail.record {
-                            record.removeFromPersistentMails(mail)
-                            if record.mailsInFolder(folder: f).count == 0 {
-                                f.removeFromKeyRecords(record)
-                            }
-                        }
-                        DataHandler.handler.delete(mail: mail)
-                }
-                let op = self.IMAPSession?.moveMessagesOperation(withFolder: from, uids: uids, destFolder: to)
-                op?.start {[unowned self]
-                    (err, vanished) -> Void in
-                    guard err == nil else {
-                        let conerror = MailServerConnectionError.findErrorCode(error: err!)
-                        self.errorhandling(error: conerror, originalCall: {self.move(mails: mails, from: from, to: to)}, completionCallback: { err in
-                            guard err != nil else {
-                                return
-                            }
-                            let op = self.IMAPSession?.copyMessagesOperation(withFolder: from, uids: uids, destFolder: to)
-                            op?.start({[unowned self] error, _ in
-                                guard error == nil else {
-                                    return
-                                }
-                                uids.enumerate({uid in
-                                    self.setFlag(uid, flags: MCOMessageFlag.deleted, folder: from)
-                                })
-                            })
-                        })
-                        return
-                    }
-                }
-            } else {
-                f.uidvalidity = uidValidity
-            }
-        }
-        }
-        }
-         */
     
     func allFolders(_ completion: @escaping (Error?) -> Void) {
         guard IMAPSession != nil else {
diff --git a/enzevalos_iphone/OutgoingMail.swift b/enzevalos_iphone/OutgoingMail.swift
index 2e375ff1..56dc93e3 100644
--- a/enzevalos_iphone/OutgoingMail.swift
+++ b/enzevalos_iphone/OutgoingMail.swift
@@ -190,7 +190,7 @@ class OutgoingMail {
     func send(informUser: Bool = false) {
         self.informUser = informUser
         if let mail = mail {
-            LetterboxModel.instance.dataProvider.deleteMail(mail: mail)
+            mail.delete()
         }
         LetterboxModel.instance.mailHandler.sendSMTP(mail: self, callback: { error in
             if error != nil {
diff --git a/enzevalos_iphone/SwiftUI/Inbox/MailListView.swift b/enzevalos_iphone/SwiftUI/Inbox/MailListView.swift
index 577caca4..18c7d5cd 100644
--- a/enzevalos_iphone/SwiftUI/Inbox/MailListView.swift
+++ b/enzevalos_iphone/SwiftUI/Inbox/MailListView.swift
@@ -54,11 +54,10 @@ struct MailListView: View {
     private func deleteMails(at offsets: IndexSet) {
         var ids = [UInt64]()
         for index in offsets {
-            //PersistentDataProvider.dataProvider.delete(object: mails[index])
             let mail = mails[index]
             ids.append(UInt64(mail.uID))
         }
-        MailHandler.init().move(mails: ids, fromPath: folderPath, toPath: UserManager.backendTrashFolderPath)
+        MailRecord.delete(with: ids, folderPath: folderPath)
     }
     
     func filterKeyRecord(keyRecord: MailRecord) -> Bool {
diff --git a/enzevalos_iphone/SwiftUI/Read/ReadMainView.swift b/enzevalos_iphone/SwiftUI/Read/ReadMainView.swift
index 27d7620e..24d47ee2 100644
--- a/enzevalos_iphone/SwiftUI/Read/ReadMainView.swift
+++ b/enzevalos_iphone/SwiftUI/Read/ReadMainView.swift
@@ -18,7 +18,7 @@
 import SwiftUI
 
 struct ReadMainView <M: DisplayMail>: View {
-    @ObservedObject var model: ReadModel<M>
+    @StateObject var model: ReadModel<M>
     
     var body: some View {
         TabView(selection: $model.currentTab) {
@@ -32,6 +32,9 @@ struct ReadMainView <M: DisplayMail>: View {
             }
         }
         .navigationBarTitle(subject)
+        .onDisappear(perform: {
+            model.onDisappear()
+        })
     }
     
     var subject: Text {
diff --git a/enzevalos_iphone/SwiftUI/Read/ReadModel.swift b/enzevalos_iphone/SwiftUI/Read/ReadModel.swift
index 8b78a307..41724da7 100644
--- a/enzevalos_iphone/SwiftUI/Read/ReadModel.swift
+++ b/enzevalos_iphone/SwiftUI/Read/ReadModel.swift
@@ -35,17 +35,35 @@ enum ReadPart {
 
 
 class ReadModel <M: DisplayMail>: ObservableObject {
-    
     @Published var dismissView = false
     @Published var currentTab = ReadPart.Security.value
-
     
     private var userAction:  UserAction?
     var mail: M
     
     init(mail: M) {
         self.mail = mail
-        mail.markAsRead(isRead: true)
+    }
+    
+    func onDisappear() {
+        if let action = userAction {
+            switch action {
+            case .Delete:
+                if let mail = mail as? MailRecord {
+                    mail.delete()
+                }
+            case .Archive:
+                if let mail = mail as? MailRecord {
+                    mail.archive()
+                }
+            case .Unread:
+                mail.markAsRead(isRead: false)
+            default:
+                mail.markAsRead(isRead: true)
+            }
+        } else {
+            mail.markAsRead(isRead: true)
+        }
     }
     
     func newUserAction(action: UserAction) -> PreMailData? {
@@ -55,9 +73,6 @@ class ReadModel <M: DisplayMail>: ObservableObject {
             // TODO
             return nil
         case .Delete:
-            if let mail = mail as? MailRecord {
-                PersistentDataProvider.dataProvider.deleteMail(mail: mail)
-            }
             dismissView = true
             return nil
         case .Move:
@@ -70,13 +85,9 @@ class ReadModel <M: DisplayMail>: ObservableObject {
         case .Forward:
             return PreMailData(body: mail.preparePreviousMailBody(), subject: ResponseType.Reply.addPrefix(subject: mail.subject), to: [], cc: [], bcc: [])
         case .Archive:
-            if let mail = mail as? MailRecord {
-                PersistentDataProvider.dataProvider.archiveMail(mail: mail)
-            }
             dismissView = true
             return nil
         case .Unread:
-            mail.markAsRead(isRead: !mail.isRead)
             dismissView = true
             return nil
         }
diff --git a/enzevalos_iphone/SwiftUI/Read/Tabbed Views/MessageViewMain.swift b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/MessageViewMain.swift
index ba80bae9..b0d34670 100644
--- a/enzevalos_iphone/SwiftUI/Read/Tabbed Views/MessageViewMain.swift	
+++ b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/MessageViewMain.swift	
@@ -26,9 +26,13 @@ struct MessageViewMain <M: DisplayMail>: View {
                     self.showExtraButtons = false
                 }
             FloatingReplyButtons
-        }.onAppear(perform: {self.model.mail.markAsRead(isRead: true)})
+        }
         .sheet(item: $newMail, content: {mail in ComposeView(preData: mail)})
-        
+        .onChange(of: model.dismissView, perform: { value in
+            if value {
+                presentationMode.wrappedValue.dismiss()
+            }
+        })
     }
     
     var Subjectbar: some View{
diff --git a/enzevalos_iphone/persistentData/MailRecord.swift b/enzevalos_iphone/persistentData/MailRecord.swift
index 7abc53e8..fcca5026 100644
--- a/enzevalos_iphone/persistentData/MailRecord.swift
+++ b/enzevalos_iphone/persistentData/MailRecord.swift
@@ -140,7 +140,12 @@ extension MailRecord: DisplayMail {
         
         set {
             var mcoflag = MCOMessageFlag.init(rawValue: Int(flag))
-            mcoflag = mcoflag.update(with: .seen) ?? mcoflag
+            if newValue {
+                mcoflag = mcoflag.update(with: .seen) ?? mcoflag
+            } else {
+                mcoflag.subtract(.seen)
+            }
+            
             self.flag = Int16(mcoflag.rawValue)
             
             if let moc = self.managedObjectContext {
@@ -210,14 +215,7 @@ extension MailRecord: DisplayMail {
     }
     
     func markAsRead(isRead: Bool) {
-        
-        // TODO: FIX! Faults the current objects...
-//        if let context = self.managedObjectContext {
-//            var newFlag = self.messageFlag
-//            newFlag.insert(.seen)
-//            flag = Int16(newFlag.rawValue)
-//            try? PersistentDataProvider.dataProvider.save(taskContext: context) // <- later?
-//        }
+        self.isRead = isRead
         return
     }
     
@@ -256,4 +254,25 @@ extension MailRecord {
         return request
     }
 }
+/// Functions to manipulate mails
+extension MailRecord {
+    
+    static func delete(with ids: [UInt64], folderPath: String) {
+        MailHandler.init().move(mails: ids, fromPath: folderPath, toPath: UserManager.backendTrashFolderPath)
+    }
+    
+    func archive() {
+        guard let folder = self.inFolder?.path else {
+            return
+        }
+        MailHandler.init().move(mails: [UInt64(self.uID)], fromPath: folder, toPath: UserManager.backendArchiveFolderPath)
+    }
+    
+    func delete() {
+        guard let folder = self.inFolder?.path else {
+            return
+        }
+        MailHandler.init().move(mails: [UInt64(self.uID)], fromPath: folder, toPath: UserManager.backendTrashFolderPath)
+    }
+}
 
diff --git a/enzevalos_iphone/persistentData/PersistentDataProvider.swift b/enzevalos_iphone/persistentData/PersistentDataProvider.swift
index 9cfdc3ce..ca757f27 100644
--- a/enzevalos_iphone/persistentData/PersistentDataProvider.swift
+++ b/enzevalos_iphone/persistentData/PersistentDataProvider.swift
@@ -475,26 +475,7 @@ class PersistentDataProvider {
             completionHandler(nil)
         }
     }
-    
-    func deleteMail(mail: MailRecord) {
-        guard let folder = mail.inFolder?.path else {
-            let taskContext = newTaskContext()
-            taskContext.perform {
-                taskContext.delete(mail)
-                try? self.save(taskContext: taskContext)
-            }
-            return
-        }
-        moveMails(with: [UInt64(mail.uID)], from: folder, to: UserManager.backendTrashFolderPath)
-    }
-    
-    func archiveMail(mail: MailRecord) {
-        guard let folder = mail.inFolder?.path else {
-            return
-        }
-        moveMails(with: [UInt64(mail.uID)], from: folder, to: UserManager.backendArchiveFolderPath)
-    }
-    
+
     func moveMails(with uids: [UInt64], from: String, to: String) {
         guard let rfc = try? lookUp(entityName: MailRecord.entityName, sorting: ["uID": true], equalPredicates: ["inFolder.path": from], differentPredicates: nil, inPredicates: ["uID": uids.map({"\($0)"})]) else {
             return
-- 
GitLab