소스 검색

Fix Share extension duplicates

1. move all files into to the app
2. check if file with same path exists
finally, ask user to resolve conflicts.
Use DispatchQueue to keep track of all (un-)uploaded files. When done, dismiss.

Signed-off-by: Henrik Storch <henrik.storch@nextcloud.com>
Henrik Storch 3 년 전
부모
커밋
a6b2f2e3e7

+ 9 - 0
Nextcloud.xcodeproj/project.pbxproj

@@ -18,6 +18,11 @@
 		371B5A2E23D0B04500FAFAE9 /* NCMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371B5A2D23D0B04500FAFAE9 /* NCMenu.swift */; };
 		3781B9B023DB2B7E006B4B1D /* AppDelegate+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3781B9AF23DB2B7E006B4B1D /* AppDelegate+Menu.swift */; };
 		8491B1CD273BBA82001C8C5B /* UIViewController+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8491B1CC273BBA82001C8C5B /* UIViewController+Menu.swift */; };
+		AF22B206277B4E4C00DAB0CC /* NCCreateFormUploadConflict.swift in Sources */ = {isa = PBXBuildFile; fileRef = F704B5E42430AA8000632F5F /* NCCreateFormUploadConflict.swift */; };
+		AF22B207277B4E4C00DAB0CC /* NCCreateFormUploadConflict.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F704B5E22430AA6F00632F5F /* NCCreateFormUploadConflict.storyboard */; };
+		AF22B208277B4E4C00DAB0CC /* NCCreateFormUploadConflictCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F704B5E82430C0B800632F5F /* NCCreateFormUploadConflictCell.swift */; };
+		AF22B209277B4E4C00DAB0CC /* NCCreateFormUploadConflictCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F704B5E62430C06700632F5F /* NCCreateFormUploadConflictCell.xib */; };
+		AF2AC8CC27620F9300F249C7 /* XLForm in Frameworks */ = {isa = PBXBuildFile; productRef = AF2AC8CB27620F9300F249C7 /* XLForm */; };
 		AF2D7C7C2742556F00ADF566 /* NCShareLinkCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF2D7C7B2742556F00ADF566 /* NCShareLinkCell.swift */; };
 		AF2D7C7E2742559100ADF566 /* NCShareUserCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF2D7C7D2742559100ADF566 /* NCShareUserCell.swift */; };
 		AF4BF614275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF613275629E20081CEEF /* NCManageDatabase+Account.swift */; };
@@ -2061,7 +2066,9 @@
 				F7148054262ED51000693E51 /* NCListCell.xib in Resources */,
 				F7D57C8626317BDA00DE301D /* NCAccountRequest.storyboard in Resources */,
 				F7145A1A1D12E3B700CAFEEC /* Images.xcassets in Resources */,
+				AF22B209277B4E4C00DAB0CC /* NCCreateFormUploadConflictCell.xib in Resources */,
 				F7148063262ED66200693E51 /* NCEmptyView.xib in Resources */,
+				AF22B207277B4E4C00DAB0CC /* NCCreateFormUploadConflict.storyboard in Resources */,
 				F7145A231D12E3B700CAFEEC /* Localizable.strings in Resources */,
 				F746EC51273906C40052598D /* NCViewCertificateDetails.storyboard in Resources */,
 				F79EC784263161BA004E59D6 /* NCRenameFile.storyboard in Resources */,
@@ -2257,6 +2264,7 @@
 				AF817EF2274BC781009ED85B /* NCUserBaseUrl.swift in Sources */,
 				F78295311F962EFA00A572F5 /* NCEndToEndEncryption.m in Sources */,
 				F74AF3A5247FB6AE00AC767B /* NCUtilityFileSystem.swift in Sources */,
+				AF22B206277B4E4C00DAB0CC /* NCCreateFormUploadConflict.swift in Sources */,
 				F7BD71E62636EAFC00643C34 /* NCNetworkingE2EE.swift in Sources */,
 				F7F878AF1FB9E3B900599E4F /* NCEndToEndMetadata.swift in Sources */,
 				F702F2D025EE5B5C008F8E80 /* NCGlobal.swift in Sources */,
@@ -2271,6 +2279,7 @@
 				F7D57C8B26317BDE00DE301D /* NCAccountRequest.swift in Sources */,
 				F780710A1EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m in Sources */,
 				F79EC77F26316193004E59D6 /* NCRenameFile.swift in Sources */,
+				AF22B208277B4E4C00DAB0CC /* NCCreateFormUploadConflictCell.swift in Sources */,
 				F7148041262EBE4000693E51 /* NCShareExtension.swift in Sources */,
 				F76B3CCF1EAE01BD00921AC9 /* NCBrand.swift in Sources */,
 				F7BAADCC1ED5A87C00B7EAD4 /* NCManageDatabase.swift in Sources */,

+ 82 - 51
Share/NCShareExtension.swift

@@ -4,8 +4,10 @@
 //
 //  Created by Marino Faggiana on 20/04/2021.
 //  Copyright © 2021 Marino Faggiana. All rights reserved.
+//  Copyright © 2021 Henrik Storch. All rights reserved.
 //
 //  Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//  Author Henrik Storch <henrik.storch@nextcloud.com>
 //
 //  This program is free software: you can redistribute it and/or modify
 //  it under the terms of the GNU General Public License as published by
@@ -68,6 +70,7 @@ class NCShareExtension: UIViewController, NCListCellDelegate, NCEmptyDataSetDele
 
     private var numberFilesName: Int = 0
     private var counterUpload: Int = 0
+    private var uploadDispatchGroup: DispatchGroup?
 
     // MARK: - View Life Cycle
 
@@ -408,77 +411,98 @@ class NCShareExtension: UIViewController, NCListCellDelegate, NCEmptyDataSetDele
     }
 
     @objc func actionUpload() {
+        guard !filesName.isEmpty else { fatalError("No files") }
+        uploadDispatchGroup = DispatchGroup()
+        uploadDispatchGroup?.enter()
+        uploadDispatchGroup?.notify(queue: .main, execute: finishedUploading)
 
-        if let fileName = filesName.first {
-
-            counterUpload += 1
-            filesName.removeFirst()
+        var conflicts: [tableMetadata] = []
+        for fileName in filesName {
             let ocId = NSUUID().uuidString
-            let filePath = CCUtility.getDirectoryProviderStorageOcId(ocId, fileNameView: fileName)!
-
-            if NCUtilityFileSystem.shared.moveFile(atPath: (NSTemporaryDirectory() + fileName), toPath: filePath) {
-
-                let metadata = NCManageDatabase.shared.createMetadata(account: activeAccount.account, user: activeAccount.user, userId: activeAccount.userId, fileName: fileName, fileNameView: fileName, ocId: ocId, serverUrl: serverUrl, urlBase: activeAccount.urlBase, url: "", contentType: "", livePhoto: false)
-
-                metadata.session = NCCommunicationCommon.shared.sessionIdentifierUpload
-                metadata.sessionSelector = NCGlobal.shared.selectorUploadFile
-                metadata.size = NCUtilityFileSystem.shared.getFileSize(filePath: filePath)
-                metadata.status = NCGlobal.shared.metadataStatusWaitUpload
+            let atPath = (NSTemporaryDirectory() + fileName)
+            let toPath = CCUtility.getDirectoryProviderStorageOcId(ocId, fileNameView: fileName)!
+            guard NCUtilityFileSystem.shared.copyFile(atPath: atPath, toPath: toPath) else { continue }
+            let metadata = NCManageDatabase.shared.createMetadata(account: activeAccount.account, user: activeAccount.user, userId: activeAccount.userId, fileName: fileName, fileNameView: fileName, ocId: ocId, serverUrl: serverUrl, urlBase: activeAccount.urlBase, url: "", contentType: "", livePhoto: false)
+            metadata.session = NCCommunicationCommon.shared.sessionIdentifierUpload
+            metadata.sessionSelector = NCGlobal.shared.selectorUploadFile
+            metadata.size = NCUtilityFileSystem.shared.getFileSize(filePath: toPath)
+            metadata.status = NCGlobal.shared.metadataStatusWaitUpload
+            if NCManageDatabase.shared.getMetadataConflict(account: activeAccount.account, serverUrl: serverUrl, fileName: fileName) != nil {
+                conflicts.append(metadata)
+            } else {
+                upload(metadata)
+            }
+        }
+        
+        if !conflicts.isEmpty {
+            uploadDispatchGroup?.enter()
+            DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
+                if let conflict = UIStoryboard(name: "NCCreateFormUploadConflict", bundle: nil).instantiateInitialViewController() as? NCCreateFormUploadConflict {
 
-                // E2EE
-                if CCUtility.isFolderEncrypted(metadata.serverUrl, e2eEncrypted: metadata.e2eEncrypted, account: metadata.account, urlBase: metadata.urlBase) {
-                    metadata.e2eEncrypted = true
-                }
+                    conflict.serverUrl = self.serverUrl
+                    conflict.metadatasUploadInConflict = conflicts
+                    conflict.delegate = self
 
-                // CHUNCK
-                if chunckSize != 0 && metadata.size > chunckSize {
-                    metadata.chunk = true
+                    self.present(conflict, animated: true, completion: nil)
                 }
+            }
+        }
+        uploadDispatchGroup?.leave()
+    }
 
-                NCNetworking.shared.upload(metadata: metadata) {
-
-                } completion: { errorCode, errorDescription in
+    func upload(_ metadata: tableMetadata) {
+        uploadDispatchGroup?.enter()
+        // E2EE
+        if CCUtility.isFolderEncrypted(metadata.serverUrl, e2eEncrypted: metadata.e2eEncrypted, account: metadata.account, urlBase: metadata.urlBase) {
+            metadata.e2eEncrypted = true
+        }
 
-                    if errorCode == 0 {
+        // CHUNCK
+        if chunckSize != 0 && metadata.size > chunckSize {
+            metadata.chunk = true
+        }
 
-                        self.actionUpload()
+        NCNetworking.shared.upload(metadata: metadata) {
 
-                    } else {
+        } completion: { errorCode, errorDescription in
+            if errorCode == 0 {
+                self.counterUpload += 1
+                self.uploadDispatchGroup?.leave()
+            } else {
 
-                        IHProgressHUD.dismiss()
+                IHProgressHUD.dismiss()
 
-                        NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocId))
-                        NCManageDatabase.shared.deleteChunks(account: self.activeAccount.account, ocId: ocId)
+                NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
+                NCManageDatabase.shared.deleteChunks(account: self.activeAccount.account, ocId: metadata.ocId)
 
-                        let alertController = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: errorDescription, preferredStyle: .alert)
-                        alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in
-                            self.extensionContext?.completeRequest(returningItems: self.extensionContext?.inputItems, completionHandler: nil)
-                        }))
-                        self.present(alertController, animated: true)
-                    }
-                }
+                let alertController = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: errorDescription, preferredStyle: .alert)
+                alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in
+                    // what does this do?
+//                    self.extensionContext?.completeRequest(returningItems: self.extensionContext?.inputItems, completionHandler: nil)
+                    self.uploadDispatchGroup?.leave()
+                }))
+                self.present(alertController, animated: true)
             }
-        } else {
-
-            IHProgressHUD.showSuccesswithStatus(NSLocalizedString("_success_", comment: ""))
+        }
+    }
 
-            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
-                self.extensionContext?.completeRequest(returningItems: self.extensionContext?.inputItems, completionHandler: nil)
-            }
+    func finishedUploading() {
+        IHProgressHUD.showSuccesswithStatus(NSLocalizedString("_success_", comment: ""))
+        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
+            self.extensionContext?.completeRequest(returningItems: self.extensionContext?.inputItems, completionHandler: nil)
         }
     }
 
     func rename(fileName: String, fileNameNew: String) {
+        guard let fileIx = self.filesName.firstIndex(where: { $0 == fileName }),
+              !self.filesName.contains(fileNameNew),
+              NCUtilityFileSystem.shared.moveFile(atPath: (NSTemporaryDirectory() + fileName), toPath: (NSTemporaryDirectory() + fileNameNew))
+        else { return }
 
-        if let row = self.filesName.firstIndex(where: {$0 == fileName}) {
-
-            if NCUtilityFileSystem.shared.moveFile(atPath: (NSTemporaryDirectory() + fileName), toPath: (NSTemporaryDirectory() + fileNameNew)) {
-                filesName[row] = fileNameNew
-                tableView.reloadData()
-            }
-        }
+        filesName[fileIx] = fileNameNew
+        tableView.reloadData()
     }
-
+    
     func accountRequestChangeAccount(account: String) {
         setAccount(account: account)
     }
@@ -997,3 +1021,10 @@ class NCShareExtensionButtonWithIndexPath: UIButton {
     var fileName: String?
     var image: UIImage?
 }
+
+extension NCShareExtension: NCCreateFormUploadConflictDelegate {
+    func dismissCreateFormUploadConflict(metadatas: [tableMetadata]?) {
+        metadatas?.forEach { self.upload($0) }
+        uploadDispatchGroup?.leave()
+    }
+}

+ 7 - 0
iOSClient/AppDelegate.swift

@@ -890,3 +890,10 @@ extension AppDelegate: NCAudioRecorderViewControllerDelegate {
     func didFinishWithoutRecording(_ viewController: NCAudioRecorderViewController, fileName: String) {
     }
 }
+
+extension AppDelegate: NCCreateFormUploadConflictDelegate {
+    func dismissCreateFormUploadConflict(metadatas: [tableMetadata]?) {
+        guard let metadatas = metadatas, !metadatas.isEmpty else { return }
+        networkingProcessUpload?.createProcessUploads(metadatas: metadatas)
+    }
+}

+ 1 - 0
iOSClient/Main/Create cloud/NCCreateFormUploadAssets.swift

@@ -463,6 +463,7 @@ class NCCreateFormUploadAssets: XLFormViewController, NCSelectDelegate {
                         conflict.metadatasNOConflict = metadatasNOConflict
                         conflict.metadatasMOV = metadatasMOV
                         conflict.metadatasUploadInConflict = metadatasUploadInConflict
+                        conflict.delegate = self.appDelegate
 
                         self.appDelegate.window?.rootViewController?.present(conflict, animated: true, completion: nil)
                     }

+ 1 - 7
iOSClient/Main/Create cloud/NCCreateFormUploadConflict.swift

@@ -58,7 +58,6 @@ extension NCCreateFormUploadConflictDelegate {
     @objc var alwaysNewFileNameNumber: Bool = false
     @objc var textLabelDetailNewFile: String?
 
-    let appDelegate = UIApplication.shared.delegate as! AppDelegate
     var metadatasConflictNewFiles: [String] = []
     var metadatasConflictAlreadyExistingFiles: [String] = []
     var fileNamesPath: [String: String] = [:]
@@ -310,12 +309,7 @@ extension NCCreateFormUploadConflictDelegate {
         }
 
         metadatasNOConflict.append(contentsOf: metadatasMOV)
-
-        if delegate != nil {
-            delegate?.dismissCreateFormUploadConflict(metadatas: metadatasNOConflict)
-        } else {
-            appDelegate.networkingProcessUpload?.createProcessUploads(metadatas: metadatasNOConflict)
-        }
+        delegate?.dismissCreateFormUploadConflict(metadatas: metadatasNOConflict)
 
         dismiss(animated: true)
     }

+ 1 - 1
iOSClient/Main/NCPickerViewController.swift

@@ -160,7 +160,7 @@ class NCDocumentPickerViewController: NSObject, UIDocumentPickerDelegate {
                 if NCManageDatabase.shared.getMetadataConflict(account: appDelegate.account, serverUrl: serverUrl, fileName: fileName) != nil {
 
                     if let conflict = UIStoryboard(name: "NCCreateFormUploadConflict", bundle: nil).instantiateInitialViewController() as? NCCreateFormUploadConflict {
-
+                        conflict.delegate = appDelegate
                         conflict.serverUrl = serverUrl
                         conflict.metadatasUploadInConflict = [metadataForUpload]