Browse Source

Add cancleable HUD for copying files

+ use semaphore to make 5 parallel requests to optimise download and network traffic

Signed-off-by: Henrik Storch <henrik.storch@nextcloud.com>
Henrik Storch 3 years ago
parent
commit
ec09099f7d

+ 4 - 4
Share/NCShareExtension.swift

@@ -104,7 +104,7 @@ class NCShareExtension: UIViewController {
         createFolderView.addGestureRecognizer(createFolderGesture)
 
         uploadView.layer.cornerRadius = 10
-        
+
         // uploadImage.image = NCUtility.shared.loadImage(named: "square.and.arrow.up", color: NCBrandColor.shared.label)
         uploadLabel.text = NSLocalizedString("_upload_", comment: "")
         uploadLabel.textColor = .systemBlue
@@ -130,7 +130,7 @@ class NCShareExtension: UIViewController {
         if let indicatorView = hud.indicatorView as? JGProgressHUDRingIndicatorView {
             indicatorView.ringWidth = 1.5
         }
-        
+
         NotificationCenter.default.addObserver(self, selector: #selector(triggerProgressTask(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterProgressTask), object: nil)
     }
 
@@ -188,7 +188,7 @@ class NCShareExtension: UIViewController {
         guard let progress = notification.userInfo?["progress"] as? Float else { return }
         hud.progress = progress
     }
-    
+
     func setNavigationBar(navigationTitle: String) {
 
         navigationItem.title = navigationTitle
@@ -357,7 +357,7 @@ extension NCShareExtension {
         hud.textLabel.text = NSLocalizedString("_upload_file_", comment: "") + " \(counterUploaded + 1) " + NSLocalizedString("_of_", comment: "") + " \(filesName.count)"
         hud.progress = 0
         hud.show(in: self.view)
-        
+
         NCNetworking.shared.upload(metadata: metadata) { } completion: { errorCode, _ in
             if errorCode == 0 {
                 self.counterUploaded += 1

+ 52 - 19
iOSClient/Main/NCFunctionCenter.swift

@@ -39,7 +39,6 @@ import JGProgressHUD
     let appDelegate = UIApplication.shared.delegate as! AppDelegate
     var viewerQuickLook: NCViewerQuickLook?
     var documentController: UIDocumentInteractionController?
-    var copyDispatchGroup: DispatchGroup?
 
     // MARK: - Download
 
@@ -97,8 +96,8 @@ import JGProgressHUD
                             self.openDocumentController(metadata: metadata)
                         }
 
-                    case NCGlobal.shared.selectorLoadCopy:
-                        copyDispatchGroup?.leave()
+                    case NCGlobal.shared.selectorLoadCopy: break
+//                        copyDispatchGroup?.leave()
 
                     case NCGlobal.shared.selectorLoadOffline:
 
@@ -418,26 +417,60 @@ import JGProgressHUD
 
     // MARK: - Copy & Paste
 
-    func copyPasteboard(pasteboardOcIds: [String], completion: @escaping () -> Void) {
+    func copyPasteboard(pasteboardOcIds: [String], hudView: UIView, completion: @escaping () -> Void) {
         var metadatas: [tableMetadata] = pasteboardOcIds.compactMap(NCManageDatabase.shared.getMetadataFromOcId)
         var items = [[String: Any]]()
-        copyDispatchGroup = DispatchGroup()
+        var isCancelled = false
+        let hud = JGProgressHUD()
+        let copyDispatchGroup = DispatchGroup()
+        let seamphore = DispatchSemaphore(value: 5)
+        hud.textLabel.text = NSLocalizedString("_wait_", comment: "")
+        hud.show(in: hudView)
+
+        // getting file data can take some time and block the main queue
+        DispatchQueue.global(qos: .userInitiated).async {
+            metadatas = metadatas.compactMap({ metadata in
+                if let pasteboardItem = metadata.toPasteBoardItem() {
+                    items.append(pasteboardItem)
+                    return nil
+                }
+                return metadata
+            })
+
+            if !metadatas.isEmpty {
+                DispatchQueue.main.async {
+                    hud.textLabel.text = NSLocalizedString("_status_downloading_", comment: "")
+                    hud.detailTextLabel.text = NSLocalizedString("_tap_to_cancel_", comment: "")
+                    hud.tapOnHUDViewBlock = { hud in
+                        isCancelled = true
+                        hud.dismiss()
+                    }
+                    hud.show(in: hudView)
+                }
+            }
 
-        for metadata in metadatas {
-            if let pasteboardItem = metadata.toPasteBoardItem() {
-                metadatas.removeAll(where: { $0 == metadata })
-                items.append(pasteboardItem)
-            } else {
-                copyDispatchGroup?.enter()
-                NCNetworking.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorLoadCopy) { _ in }
+            // do 5 downloads in paralell to optimize efficiancy
+            for metadata in metadatas {
+                guard !isCancelled else { return }
+                copyDispatchGroup.enter()
+                NCNetworking.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorLoadCopy) { _ in
+                    copyDispatchGroup.leave()
+                    seamphore.signal()
+                }
+                seamphore.wait()
             }
-        }
 
-        copyDispatchGroup?.notify(queue: .main, execute: {
-            items.append(contentsOf: metadatas.compactMap({ $0.toPasteBoardItem() }))
-            UIPasteboard.general.setItems(items, options: [:])
-            completion()
-        })
+            copyDispatchGroup.notify(queue: .main, execute: {
+                guard !isCancelled else { return }
+                hud.indicatorView = JGProgressHUDSuccessIndicatorView()
+                hud.textLabel.text = NSLocalizedString("_success_", comment: "")
+                hud.detailTextLabel.text = ""
+                hud.dismiss(afterDelay: 1)
+                items.append(contentsOf: metadatas.compactMap({ $0.toPasteBoardItem() }))
+                UIPasteboard.general.setItems(items, options: [:])
+                completion()
+            })
+        }
     }
 
     func pastePasteboard(serverUrl: String) {
@@ -647,7 +680,7 @@ import JGProgressHUD
         let titleOffline = isOffline ? NSLocalizedString("_remove_available_offline_", comment: "") :  NSLocalizedString("_set_available_offline_", comment: "")
 
         let copy = UIAction(title: NSLocalizedString("_copy_file_", comment: ""), image: UIImage(systemName: "doc.on.doc")) { _ in
-            self.copyPasteboard(pasteboardOcIds: [metadata.ocId], completion: { })
+            self.copyPasteboard(pasteboardOcIds: [metadata.ocId], hudView: viewController.view, completion: { })
         }
 
         let copyPath = UIAction(title: NSLocalizedString("_copy_path_", comment: ""), image: UIImage(systemName: "doc.on.clipboard")) { _ in

+ 2 - 2
iOSClient/Menu/NCCollectionViewCommon+Menu.swift

@@ -320,7 +320,7 @@ extension NCCollectionViewCommon {
                     title: NSLocalizedString("_copy_file_", comment: ""),
                     icon: NCUtility.shared.loadImage(named: "doc.on.doc"),
                     action: { _ in
-                        NCFunctionCenter.shared.copyPasteboard(pasteboardOcIds: [metadata.ocId], completion: { })
+                        NCFunctionCenter.shared.copyPasteboard(pasteboardOcIds: [metadata.ocId], hudView: self.view, completion: { })
                     }
                 )
             )
@@ -535,7 +535,7 @@ extension NCCollectionViewCommon {
                 title: NSLocalizedString("_copy_file_", comment: ""),
                 icon: NCUtility.shared.loadImage(named: "doc.on.doc"),
                 action: { _ in
-                    NCFunctionCenter.shared.copyPasteboard(pasteboardOcIds: self.selectOcId, completion: { self.tapSelect(sender: self) })
+                    NCFunctionCenter.shared.copyPasteboard(pasteboardOcIds: self.selectOcId, hudView: self.view, completion: { self.tapSelect(sender: self) })
                 }
             )
         )

+ 1 - 1
iOSClient/Menu/NCMedia+Menu.swift

@@ -224,7 +224,7 @@ extension NCMedia {
                     icon: NCUtility.shared.loadImage(named: "doc.on.doc"),
                     action: { _ in
                         self.isEditMode = false
-                        NCFunctionCenter.shared.copyPasteboard(pasteboardOcIds: self.selectOcId) {
+                        NCFunctionCenter.shared.copyPasteboard(pasteboardOcIds: self.selectOcId, hudView: self.view) {
                             self.selectOcId.removeAll()
                             self.reloadDataThenPerform { }
                         }

+ 1 - 1
iOSClient/Menu/NCViewer+Menu.swift

@@ -257,7 +257,7 @@ extension NCViewer {
                 title: NSLocalizedString("_copy_file_", comment: ""),
                 icon: NCUtility.shared.loadImage(named: "doc.on.doc"),
                 action: { _ in
-                    NCFunctionCenter.shared.copyPasteboard(pasteboardOcIds: [metadata.ocId], completion: { })
+                    NCFunctionCenter.shared.copyPasteboard(pasteboardOcIds: [metadata.ocId], hudView: viewController.view, completion: { })
                 }
             )
         )

+ 1 - 0
iOSClient/Supporting Files/en.lproj/Localizable.strings

@@ -21,6 +21,7 @@
 //
 
 "_cancel_"                  = "Cancel";
+"_tap_to_cancel_"           = "Tap to cancel";
 "_upload_file_"             = "Upload file";
 "_accessibility_add_upload_" = "Add and upload";
 "_download_file_"           = "Download file";