Selaa lähdekoodia

Conflicts resolved

Marino Faggiana 7 vuotta sitten
vanhempi
commit
47274239a9
100 muutettua tiedostoa jossa 49758 lisäystä ja 465 poistoa
  1. 12798 0
      Libraries external/Realm/Realm.framework/05603C2F-C898-38D9-9FBA-9734EA4CF1F2.bcsymbolmap
  2. 11692 0
      Libraries external/Realm/Realm.framework/C74843BA-D836-3500-BC79-EACEC3C25778.bcsymbolmap
  3. 30 1
      Libraries external/Realm/Realm.framework/CHANGELOG.md
  4. BIN
      Libraries external/Realm/Realm.framework/Info.plist
  5. BIN
      Libraries external/Realm/Realm.framework/Realm
  6. 12798 0
      Libraries external/Realm/RealmSwift.framework/05603C2F-C898-38D9-9FBA-9734EA4CF1F2.bcsymbolmap
  7. 11692 0
      Libraries external/Realm/RealmSwift.framework/C74843BA-D836-3500-BC79-EACEC3C25778.bcsymbolmap
  8. BIN
      Libraries external/Realm/RealmSwift.framework/Info.plist
  9. BIN
      Libraries external/Realm/RealmSwift.framework/RealmSwift
  10. 1 1
      Picker/DocumentPickerViewController.swift
  11. 108 11
      PickerFileProvider/FileProviderData.swift
  12. 156 105
      PickerFileProvider/FileProviderEnumerator.swift
  13. 129 107
      PickerFileProvider/FileProviderExtension+Actions.swift
  14. 217 67
      PickerFileProvider/FileProviderExtension+Network.swift
  15. 49 132
      PickerFileProvider/FileProviderExtension.swift
  16. 16 4
      PickerFileProvider/FileProviderItem.swift
  17. 1 1
      Share/ShareViewController.m
  18. 3 3
      iOSClient/AppDelegate.m
  19. 2 2
      iOSClient/Brand/Picker.plist
  20. 2 2
      iOSClient/Brand/PickerFileProvider.plist
  21. 2 2
      iOSClient/Brand/Share.plist
  22. 2 2
      iOSClient/Brand/iOSClient.plist
  23. 1 0
      iOSClient/CCGlobal.h
  24. 1 1
      iOSClient/Create/CCCreateCloud.swift
  25. 6 5
      iOSClient/Database/NCManageDatabase.swift
  26. 2 2
      iOSClient/Main/CCMain.m
  27. 7 5
      iOSClient/Networking/CCNetworking.h
  28. 25 12
      iOSClient/Networking/CCNetworking.m
  29. 18 0
      iOSClient/Settings/CCAdvanced.m
  30. BIN
      iOSClient/Supporting Files/cs-CZ.lproj/BKPasscodeView.strings
  31. BIN
      iOSClient/Supporting Files/cs-CZ.lproj/CTAssetsPicker.strings
  32. BIN
      iOSClient/Supporting Files/cs-CZ.lproj/Error.strings
  33. BIN
      iOSClient/Supporting Files/cs-CZ.lproj/InfoPlist.strings
  34. BIN
      iOSClient/Supporting Files/cs-CZ.lproj/Intro.strings
  35. BIN
      iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings
  36. BIN
      iOSClient/Supporting Files/cs-CZ.lproj/SwiftWebVC.strings
  37. BIN
      iOSClient/Supporting Files/de.lproj/BKPasscodeView.strings
  38. BIN
      iOSClient/Supporting Files/de.lproj/CTAssetsPicker.strings
  39. BIN
      iOSClient/Supporting Files/de.lproj/Error.strings
  40. BIN
      iOSClient/Supporting Files/de.lproj/InfoPlist.strings
  41. BIN
      iOSClient/Supporting Files/de.lproj/Intro.strings
  42. BIN
      iOSClient/Supporting Files/de.lproj/Localizable.strings
  43. BIN
      iOSClient/Supporting Files/de.lproj/SwiftWebVC.strings
  44. BIN
      iOSClient/Supporting Files/en-GB.lproj/BKPasscodeView.strings
  45. BIN
      iOSClient/Supporting Files/en-GB.lproj/CTAssetsPicker.strings
  46. BIN
      iOSClient/Supporting Files/en-GB.lproj/Error.strings
  47. BIN
      iOSClient/Supporting Files/en-GB.lproj/InfoPlist.strings
  48. BIN
      iOSClient/Supporting Files/en-GB.lproj/Intro.strings
  49. BIN
      iOSClient/Supporting Files/en-GB.lproj/Localizable.strings
  50. BIN
      iOSClient/Supporting Files/en-GB.lproj/SwiftWebVC.strings
  51. BIN
      iOSClient/Supporting Files/en.lproj/Error.strings
  52. BIN
      iOSClient/Supporting Files/es-419.lproj/CTAssetsPicker.strings
  53. BIN
      iOSClient/Supporting Files/es-419.lproj/Error.strings
  54. BIN
      iOSClient/Supporting Files/es-419.lproj/InfoPlist.strings
  55. BIN
      iOSClient/Supporting Files/es-419.lproj/Intro.strings
  56. BIN
      iOSClient/Supporting Files/es-419.lproj/Localizable.strings
  57. BIN
      iOSClient/Supporting Files/es-419.lproj/SwiftWebVC.strings
  58. BIN
      iOSClient/Supporting Files/es-CL.lproj/BKPasscodeView.strings
  59. BIN
      iOSClient/Supporting Files/es-CL.lproj/CTAssetsPicker.strings
  60. BIN
      iOSClient/Supporting Files/es-CL.lproj/Error.strings
  61. BIN
      iOSClient/Supporting Files/es-CL.lproj/InfoPlist.strings
  62. BIN
      iOSClient/Supporting Files/es-CL.lproj/Intro.strings
  63. BIN
      iOSClient/Supporting Files/es-CL.lproj/Localizable.strings
  64. BIN
      iOSClient/Supporting Files/es-CL.lproj/SwiftWebVC.strings
  65. BIN
      iOSClient/Supporting Files/es-CO.lproj/BKPasscodeView.strings
  66. BIN
      iOSClient/Supporting Files/es-CO.lproj/CTAssetsPicker.strings
  67. BIN
      iOSClient/Supporting Files/es-CO.lproj/Error.strings
  68. BIN
      iOSClient/Supporting Files/es-CO.lproj/InfoPlist.strings
  69. BIN
      iOSClient/Supporting Files/es-CO.lproj/Intro.strings
  70. BIN
      iOSClient/Supporting Files/es-CO.lproj/Localizable.strings
  71. BIN
      iOSClient/Supporting Files/es-CO.lproj/SwiftWebVC.strings
  72. BIN
      iOSClient/Supporting Files/es-CR.lproj/BKPasscodeView.strings
  73. BIN
      iOSClient/Supporting Files/es-CR.lproj/CTAssetsPicker.strings
  74. BIN
      iOSClient/Supporting Files/es-CR.lproj/Error.strings
  75. BIN
      iOSClient/Supporting Files/es-CR.lproj/InfoPlist.strings
  76. BIN
      iOSClient/Supporting Files/es-CR.lproj/Intro.strings
  77. BIN
      iOSClient/Supporting Files/es-CR.lproj/Localizable.strings
  78. BIN
      iOSClient/Supporting Files/es-CR.lproj/SwiftWebVC.strings
  79. BIN
      iOSClient/Supporting Files/es-DO.lproj/BKPasscodeView.strings
  80. BIN
      iOSClient/Supporting Files/es-DO.lproj/CTAssetsPicker.strings
  81. BIN
      iOSClient/Supporting Files/es-DO.lproj/Error.strings
  82. BIN
      iOSClient/Supporting Files/es-DO.lproj/InfoPlist.strings
  83. BIN
      iOSClient/Supporting Files/es-DO.lproj/Intro.strings
  84. BIN
      iOSClient/Supporting Files/es-DO.lproj/Localizable.strings
  85. BIN
      iOSClient/Supporting Files/es-DO.lproj/SwiftWebVC.strings
  86. BIN
      iOSClient/Supporting Files/es-EC.lproj/BKPasscodeView.strings
  87. BIN
      iOSClient/Supporting Files/es-EC.lproj/CTAssetsPicker.strings
  88. BIN
      iOSClient/Supporting Files/es-EC.lproj/Error.strings
  89. BIN
      iOSClient/Supporting Files/es-EC.lproj/InfoPlist.strings
  90. BIN
      iOSClient/Supporting Files/es-EC.lproj/Intro.strings
  91. BIN
      iOSClient/Supporting Files/es-EC.lproj/Localizable.strings
  92. BIN
      iOSClient/Supporting Files/es-EC.lproj/SwiftWebVC.strings
  93. BIN
      iOSClient/Supporting Files/es-GT.lproj/BKPasscodeView.strings
  94. BIN
      iOSClient/Supporting Files/es-GT.lproj/CTAssetsPicker.strings
  95. BIN
      iOSClient/Supporting Files/es-GT.lproj/Error.strings
  96. BIN
      iOSClient/Supporting Files/es-GT.lproj/InfoPlist.strings
  97. BIN
      iOSClient/Supporting Files/es-GT.lproj/Intro.strings
  98. BIN
      iOSClient/Supporting Files/es-GT.lproj/Localizable.strings
  99. BIN
      iOSClient/Supporting Files/es-GT.lproj/SwiftWebVC.strings
  100. BIN
      iOSClient/Supporting Files/es-HN.lproj/BKPasscodeView.strings

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 12798 - 0
Libraries external/Realm/Realm.framework/05603C2F-C898-38D9-9FBA-9734EA4CF1F2.bcsymbolmap


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 11692 - 0
Libraries external/Realm/Realm.framework/C74843BA-D836-3500-BC79-EACEC3C25778.bcsymbolmap


+ 30 - 1
Libraries external/Realm/Realm.framework/CHANGELOG.md

@@ -1,4 +1,33 @@
-3.4.0 Release notes (2018-04-25)
+3.6.0 Release notes (2018-05-29)
+=============================================================
+
+### Breaking Changes
+
+* None.
+
+### Enhancements
+
+* Improve performance of sync metadata operations and resolving thread-safe
+  references.
+* `shouldCompactOnLaunch` is now supported for compacting the local data of
+  synchronized Realms.
+
+### Bugfixes
+
+* Fix a potential deadlock when a sync session progress callback held the last
+  strong reference to the sync session.
+* Fix some cases where comparisons to `nil` in queries were not properly
+  serialized when subscribing to a query.
+* Don't delete objects added during a migration after a call to `-[RLMMigration
+  deleteDataForClassName:]`.
+* Fix incorrect results and/or crashes when multiple `-[RLMMigration
+  enumerateObjects:block:]` blocks deleted objects of the same type.
+* Fix some edge-cases where `-[RLMMigration enumerateObjects:block:]`
+  enumerated the incorrect objects following deletions.
+* Restore the pre-3.5.0 behavior for Swift optional properties missing an ivar
+  rather than crashing.
+
+3.5.0 Release notes (2018-04-25)
 =============================================================
 
 ### Enhancements

BIN
Libraries external/Realm/Realm.framework/Info.plist


BIN
Libraries external/Realm/Realm.framework/Realm


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 12798 - 0
Libraries external/Realm/RealmSwift.framework/05603C2F-C898-38D9-9FBA-9734EA4CF1F2.bcsymbolmap


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 11692 - 0
Libraries external/Realm/RealmSwift.framework/C74843BA-D836-3500-BC79-EACEC3C25778.bcsymbolmap


BIN
Libraries external/Realm/RealmSwift.framework/Info.plist


BIN
Libraries external/Realm/RealmSwift.framework/RealmSwift


+ 1 - 1
Picker/DocumentPickerViewController.swift

@@ -480,7 +480,7 @@ extension DocumentPickerViewController {
                     
                         // Upload fileName to Cloud
                     
-                        CCNetworking.shared().uploadFile(fileName, serverUrl: self!.serverUrl, assetLocalIdentifier: nil, session: k_upload_session_foreground, taskStatus: Int(k_taskStatusResume), selector: "", selectorPost: "", errorCode: 0, delegate: self)
+                        CCNetworking.shared().uploadFile(fileName, serverUrl: self!.serverUrl, fileID: nil, assetLocalIdentifier: nil, session: k_upload_session_foreground, taskStatus: Int(k_taskStatusResume), selector: "", selectorPost: "", errorCode: 0, delegate: self)
                         
                         self!.hud.visibleHudTitle(NSLocalizedString("_uploading_", comment: ""), mode: MBProgressHUDMode.determinate, color: NCBrandColor.sharedInstance.brandElement)
                     }

+ 108 - 11
PickerFileProvider/FileProviderData.swift

@@ -25,6 +25,8 @@ import FileProvider
 
 class FileProviderData: NSObject {
     
+    var fileManager = FileManager()
+    
     var account = ""
     var accountUser = ""
     var accountUserID = ""
@@ -36,11 +38,43 @@ class FileProviderData: NSObject {
     // Directory
     var groupURL: URL?
     var fileProviderStorageURL: URL?
-        
+    
+    // metadata Selector
+    let selectorPostImportDocument = "importDocument"
+    let selectorPostItemChanged = "itemChanged"
+    
+    // Metadata Temp for Import
+    let FILEID_IMPORT_METADATA_TEMP = k_uploadSessionID + "FILE_PROVIDER_EXTENSION"
+    
+    // Max item for page
+    let itemForPage = 20
+
+    // List of etag for serverUrl
+    var listServerUrlEtag = [String:String]()
+    
+    // Anchor
+    var currentAnchor: UInt64 = 0
+
+    // Rank favorite
+    var listFavoriteIdentifierRank = [String:NSNumber]()
+    
+    // Queue for trade-safe
+    let queueTradeSafe = DispatchQueue(label: "com.nextcloud.fileproviderextension.tradesafe", attributes: .concurrent)
+
+    // Item for signalEnumerator
+    var fileProviderSignalDeleteContainerItemIdentifier = [NSFileProviderItemIdentifier:NSFileProviderItemIdentifier]()
+    var fileProviderSignalUpdateContainerItem = [NSFileProviderItemIdentifier:FileProviderItem]()
+    var fileProviderSignalDeleteWorkingSetItemIdentifier = [NSFileProviderItemIdentifier:NSFileProviderItemIdentifier]()
+    var fileProviderSignalUpdateWorkingSetItem = [NSFileProviderItemIdentifier:FileProviderItem]()
+
+    // MARK: - 
+    
     func setupActiveAccount() -> Bool {
         
-        groupURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: NCBrandOptions.sharedInstance.capabilitiesGroups)
-        fileProviderStorageURL = groupURL!.appendingPathComponent(k_assetLocalIdentifierFileProviderStorage)
+        queueTradeSafe.sync(flags: .barrier) {
+            groupURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: NCBrandOptions.sharedInstance.capabilitiesGroups)
+            fileProviderStorageURL = groupURL!.appendingPathComponent(k_assetLocalIdentifierFileProviderStorage)
+        }
         
         // Create dir File Provider Storage
         do {
@@ -49,6 +83,10 @@ class FileProviderData: NSObject {
             NSLog("Unable to create directory \(error.debugDescription)")
         }
         
+        if CCUtility.getDisableFilesApp() {
+            return false
+        }
+        
         guard let activeAccount = NCManageDatabase.sharedInstance.getAccountActive() else {
             return false
         }
@@ -57,14 +95,16 @@ class FileProviderData: NSObject {
             assert(false, "change user")
         }
         
-        account = activeAccount.account
-        accountUser = activeAccount.user
-        accountUserID = activeAccount.userID
-        accountPassword = activeAccount.password
-        accountUrl = activeAccount.url
-        homeServerUrl = CCUtility.getHomeServerUrlActiveUrl(activeAccount.url)
-        directoryUser = CCUtility.getDirectoryActiveUser(activeAccount.user, activeUrl: activeAccount.url)
-                
+        queueTradeSafe.sync(flags: .barrier) {
+            account = activeAccount.account
+            accountUser = activeAccount.user
+            accountUserID = activeAccount.userID
+            accountPassword = activeAccount.password
+            accountUrl = activeAccount.url
+            homeServerUrl = CCUtility.getHomeServerUrlActiveUrl(activeAccount.url)
+            directoryUser = CCUtility.getDirectoryActiveUser(activeAccount.user, activeUrl: activeAccount.url)
+        }
+        
         return true
     }
     
@@ -148,4 +188,61 @@ class FileProviderData: NSObject {
         
         return directory
     }
+    
+    func copyFile(_ atPath: String, toPath: String) -> Error? {
+        
+        var errorResult: Error?
+        
+        if !fileManager.fileExists(atPath: atPath) {
+            return NSError(domain: NSCocoaErrorDomain, code: NSFileNoSuchFileError, userInfo:[:])
+        }
+        
+        do {
+            try fileManager.removeItem(atPath: toPath)
+        } catch let error {
+            print("error: \(error)")
+        }
+        do {
+            try fileManager.copyItem(atPath: atPath, toPath: toPath)
+        } catch let error {
+            errorResult = error
+        }
+        
+        return errorResult
+    }
+    
+    func moveFile(_ atPath: String, toPath: String) -> Error? {
+        
+        var errorResult: Error?
+        
+        if !fileManager.fileExists(atPath: atPath) {
+            return NSError(domain: NSCocoaErrorDomain, code: NSFileNoSuchFileError, userInfo:[:])
+        }
+        
+        do {
+            try fileManager.removeItem(atPath: toPath)
+        } catch let error {
+            print("error: \(error)")
+        }
+        do {
+            try fileManager.moveItem(atPath: atPath, toPath: toPath)
+        } catch let error {
+            errorResult = error
+        }
+        
+        return errorResult
+    }
+    
+    func deleteFile(_ atPath: String) -> Error? {
+        
+        var errorResult: Error?
+        
+        do {
+            try fileManager.removeItem(atPath: atPath)
+        } catch let error {
+            errorResult = error
+        }
+        
+        return errorResult
+    }
 }

+ 156 - 105
PickerFileProvider/FileProviderEnumerator.swift

@@ -26,7 +26,6 @@ import FileProvider
 class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
     
     var enumeratedItemIdentifier: NSFileProviderItemIdentifier
-    let recordForPage = 20
     var serverUrl: String?
     var providerData: FileProviderData
     
@@ -61,7 +60,7 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
     func enumerateItems(for observer: NSFileProviderEnumerationObserver, startingAt page: NSFileProviderPage) {
         
         var items: [NSFileProviderItemProtocol] = []
-        var metadatas: [tableMetadata]?
+        var metadatasFromDB: [tableMetadata]?
 
         /* ONLY iOS 11*/
         guard #available(iOS 11, *) else {
@@ -69,6 +68,7 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
             return
         }
         
+        /*** WorkingSet ***/
         if enumeratedItemIdentifier == .workingSet {
             
             var itemIdentifierMetadata = [NSFileProviderItemIdentifier:tableMetadata]()
@@ -87,8 +87,8 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
             }
             
             // ***** Favorite *****
-            listFavoriteIdentifierRank = NCManageDatabase.sharedInstance.getTableMetadatasDirectoryFavoriteIdentifierRank()
-            for (identifier, _) in listFavoriteIdentifierRank {
+            providerData.listFavoriteIdentifierRank = NCManageDatabase.sharedInstance.getTableMetadatasDirectoryFavoriteIdentifierRank()
+            for (identifier, _) in providerData.listFavoriteIdentifierRank {
              
                 guard let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "account = %@ AND fileID = %@", providerData.account, identifier)) else {
                     continue
@@ -108,129 +108,162 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
             
             observer.didEnumerate(items)
             observer.finishEnumerating(upTo: nil)
-            return
-        }
+            
+        } else {
         
-        guard let serverUrl = serverUrl else {
-            observer.finishEnumerating(upTo: nil)
-            return
-        }
+        /*** ServerUrl ***/
             
-        // Select items from database
-        if let directory = NCManageDatabase.sharedInstance.getTableDirectory(predicate: NSPredicate(format: "account = %@ AND serverUrl = %@", providerData.account, serverUrl))  {
-            metadatas = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account = %@ AND directoryID = %@", providerData.account, directory.directoryID), sorted: "fileName", ascending: true)
-        }
+            guard let serverUrl = serverUrl else {
+                observer.finishEnumerating(upTo: nil)
+                return
+            }
+            
+            // Select items from database
+            if let directory = NCManageDatabase.sharedInstance.getTableDirectory(predicate: NSPredicate(format: "account = %@ AND serverUrl = %@", providerData.account, serverUrl))  {
+                metadatasFromDB = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account = %@ AND directoryID = %@", providerData.account, directory.directoryID), sorted: "fileName", ascending: true)
+            }
             
-        // Calculate current page
-        if (page != NSFileProviderPage.initialPageSortedByDate as NSFileProviderPage && page != NSFileProviderPage.initialPageSortedByName as NSFileProviderPage) {
+            // Calculate current page
+            if (page != NSFileProviderPage.initialPageSortedByDate as NSFileProviderPage && page != NSFileProviderPage.initialPageSortedByName as NSFileProviderPage) {
                 
-            var numPage = Int(String(data: page.rawValue, encoding: .utf8)!)!
+                var numPage = Int(String(data: page.rawValue, encoding: .utf8)!)!
                 
-            if (metadatas != nil) {
-                items = self.selectItems(numPage: numPage, account: providerData.account, metadatas: metadatas!)
-                observer.didEnumerate(items)
+                if (metadatasFromDB != nil) {
+                    items = self.selectItems(numPage: numPage, account: providerData.account, metadatas: metadatasFromDB!)
+                    observer.didEnumerate(items)
+                }
+                if (items.count == providerData.itemForPage) {
+                    numPage += 1
+                    let providerPage = NSFileProviderPage("\(numPage)".data(using: .utf8)!)
+                    observer.finishEnumerating(upTo: providerPage)
+                } else {
+                    observer.finishEnumerating(upTo: nil)
+                }
+                return
             }
-            if (items.count == self.recordForPage) {
-                numPage += 1
-                let providerPage = NSFileProviderPage("\(numPage)".data(using: .utf8)!)
-                observer.finishEnumerating(upTo: providerPage)
-            } else {
-                observer.finishEnumerating(upTo: nil)
+            
+            // Read 
+            var fileName: String?
+            var serverUrlForFileName = self.providerData.homeServerUrl
+            
+            if serverUrl != self.providerData.homeServerUrl {
+                fileName = (serverUrl as NSString).lastPathComponent
+                serverUrlForFileName = (serverUrl as NSString).deletingLastPathComponent
             }
-            return
-        }
             
-        let ocNetworking = OCnetworking.init(delegate: nil, metadataNet: nil, withUser: providerData.accountUser, withUserID: providerData.accountUserID, withPassword: providerData.accountPassword, withUrl: providerData.accountUrl)
-        ocNetworking?.readFolder(serverUrl, depth: "1", account: providerData.account, success: { (metadatas, metadataFolder, directoryID) in
+            let ocNetworking = OCnetworking.init(delegate: nil, metadataNet: nil, withUser: providerData.accountUser, withUserID: providerData.accountUserID, withPassword: providerData.accountPassword, withUrl: providerData.accountUrl)
+            ocNetworking?.readFile(fileName, serverUrl: serverUrlForFileName, account: providerData.account, success: { (metadata) in
                 
-            if (metadatas != nil) {
-                NCManageDatabase.sharedInstance.deleteMetadata(predicate: NSPredicate(format: "account = %@ AND directoryID = %@ AND session = ''", self.providerData.account, directoryID!), clearDateReadDirectoryID: directoryID!)
-                if let metadataDB = NCManageDatabase.sharedInstance.addMetadatas(metadatas as! [tableMetadata], serverUrl: serverUrl) {
-                    items = self.selectItems(numPage: 0, account: self.providerData.account, metadatas: metadataDB)
-                    if (items.count > 0) {
-                        observer.didEnumerate(items)
-                    }
+                if self.providerData.listServerUrlEtag[serverUrl] == nil || self.providerData.listServerUrlEtag[serverUrl] != metadata!.etag {
+                    
+                    ocNetworking?.readFolder(serverUrl, depth: "1", account: self.providerData.account, success: { (metadatas, metadataFolder, directoryID) in
+                        
+                        // Save etag for this serverUrl
+                        if metadataFolder != nil {
+                            self.providerData.listServerUrlEtag[serverUrl] = metadataFolder!.etag
+                        }
+                        
+                        if metadatas != nil {
+                            
+                            // Insert metadata on DB
+                            NCManageDatabase.sharedInstance.deleteMetadata(predicate: NSPredicate(format: "account = %@ AND directoryID = %@ AND session = ''", self.providerData.account, directoryID!), clearDateReadDirectoryID: directoryID!)
+                            _ = NCManageDatabase.sharedInstance.addMetadatas(metadatas as! [tableMetadata], serverUrl: serverUrl)
+                            
+                            metadatasFromDB = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account = %@ AND directoryID = %@", self.providerData.account, directoryID!), sorted: "fileName", ascending: true)
+                            self.selectFirstPageItems(metadatasFromDB, observer: observer)
+                            
+                        } else {
+                            
+                            self.selectFirstPageItems(metadatasFromDB, observer: observer)
+                        }
+                        
+                    }, failure: { (errorMessage, errorCode) in
+                        
+                        self.selectFirstPageItems(metadatasFromDB, observer: observer)
+                    })
+                    
+                } else {
+                    
+                    self.selectFirstPageItems(metadatasFromDB, observer: observer)
                 }
-            }
                 
-            if (items.count == self.recordForPage) {
-                let providerPage = NSFileProviderPage("1".data(using: .utf8)!)
-                observer.finishEnumerating(upTo: providerPage)
-            } else {
-                observer.finishEnumerating(upTo: nil)
-            }
-                
-        }, failure: { (errorMessage, errorCode) in
+            }, failure: { (message, errorCode) in
                 
-            // select item from database
-            if (metadatas != nil) {
-                items = self.selectItems(numPage: 0, account: self.providerData.account, metadatas: metadatas!)
-                observer.didEnumerate(items)
-            }
-            if (items.count == self.recordForPage) {
-                let providerPage = NSFileProviderPage("1".data(using: .utf8)!)
-                observer.finishEnumerating(upTo: providerPage)
-            } else {
-                observer.finishEnumerating(upTo: nil)
-            }
-        })
+                 self.selectFirstPageItems(metadatasFromDB, observer: observer)
+            })
+        }
     }
     
     func enumerateChanges(for observer: NSFileProviderChangeObserver, from anchor: NSFileProviderSyncAnchor) {
         
         guard #available(iOS 11, *) else { return }
     
-        // Report the deleted items
-        //
         var itemsDelete = [NSFileProviderItemIdentifier]()
+        var itemsUpdate = [FileProviderItem]()
         
+        // Report the deleted items
+        //
         if enumeratedItemIdentifier == .workingSet {
-            for (itemIdentifier, _) in fileProviderSignalDeleteWorkingSetItemIdentifier {
-                itemsDelete.append(itemIdentifier)
+            providerData.queueTradeSafe.sync() {
+                for (itemIdentifier, _) in providerData.fileProviderSignalDeleteWorkingSetItemIdentifier {
+                    itemsDelete.append(itemIdentifier)
+                }
+            }
+            providerData.queueTradeSafe.sync(flags: .barrier) {
+                providerData.fileProviderSignalDeleteWorkingSetItemIdentifier.removeAll()
             }
-            fileProviderSignalDeleteWorkingSetItemIdentifier.removeAll()
         } else {
-            for (itemIdentifier, _) in fileProviderSignalDeleteContainerItemIdentifier {
-                itemsDelete.append(itemIdentifier)
+            providerData.queueTradeSafe.sync() {
+                for (itemIdentifier, _) in providerData.fileProviderSignalDeleteContainerItemIdentifier {
+                    itemsDelete.append(itemIdentifier)
+                }
+            }
+            providerData.queueTradeSafe.sync(flags: .barrier) {
+                providerData.fileProviderSignalDeleteContainerItemIdentifier.removeAll()
             }
-            fileProviderSignalDeleteContainerItemIdentifier.removeAll()
         }
-        
+            
         // Report the updated items
         //
-        var itemsUpdate = [FileProviderItem]()
-        
         if enumeratedItemIdentifier == .workingSet {
-            for (itemIdentifier, item) in fileProviderSignalUpdateWorkingSetItem {
-                let account = providerData.getAccountFromItemIdentifier(itemIdentifier)
-                if account != nil && account == providerData.account {
-                    itemsUpdate.append(item)
-                } else {
-                    itemsDelete.append(itemIdentifier)
+            providerData.queueTradeSafe.sync() {
+                for (itemIdentifier, item) in providerData.fileProviderSignalUpdateWorkingSetItem {
+                    let account = providerData.getAccountFromItemIdentifier(itemIdentifier)
+                    if account != nil && account == providerData.account {
+                        itemsUpdate.append(item)
+                    } else {
+                        itemsDelete.append(itemIdentifier)
+                    }
                 }
             }
-            fileProviderSignalUpdateWorkingSetItem.removeAll()
+            providerData.queueTradeSafe.sync(flags: .barrier) {
+                providerData.fileProviderSignalUpdateWorkingSetItem.removeAll()
+            }
         } else {
-            for (itemIdentifier, item) in fileProviderSignalUpdateContainerItem {
-                let account = providerData.getAccountFromItemIdentifier(itemIdentifier)
-                if account != nil && account == providerData.account {
-                    itemsUpdate.append(item)
-                } else {
-                    itemsDelete.append(itemIdentifier)
+            providerData.queueTradeSafe.sync(flags: .barrier) {
+                for (itemIdentifier, item) in providerData.fileProviderSignalUpdateContainerItem {
+                    let account = providerData.getAccountFromItemIdentifier(itemIdentifier)
+                    if account != nil && account == providerData.account {
+                        itemsUpdate.append(item)
+                    } else {
+                        itemsDelete.append(itemIdentifier)
+                    }
                 }
             }
-            fileProviderSignalUpdateContainerItem.removeAll()
+            providerData.queueTradeSafe.sync(flags: .barrier) {
+                providerData.fileProviderSignalUpdateContainerItem.removeAll()
+            }
         }
-        
+            
         observer.didDeleteItems(withIdentifiers: itemsDelete)
         observer.didUpdate(itemsUpdate)
-        
-        let data = "\(currentAnchor)".data(using: .utf8)
-        observer.finishEnumeratingChanges(upTo: NSFileProviderSyncAnchor(data!), moreComing: false)        
+            
+        let data = "\(providerData.currentAnchor)".data(using: .utf8)
+        observer.finishEnumeratingChanges(upTo: NSFileProviderSyncAnchor(data!), moreComing: false)
     }
     
     func currentSyncAnchor(completionHandler: @escaping (NSFileProviderSyncAnchor?) -> Void) {
-        let data = "\(currentAnchor)".data(using: .utf8)
+        let data = "\(providerData.currentAnchor)".data(using: .utf8)
         completionHandler(NSFileProviderSyncAnchor(data!))
     }
     
@@ -238,33 +271,51 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
     //  MARK: - User Function
     // --------------------------------------------------------------------------------------------
 
+    func selectFirstPageItems(_ metadatas: [tableMetadata]?, observer: NSFileProviderEnumerationObserver) {
+        
+        var items: [NSFileProviderItemProtocol] = []
+        
+        if (metadatas != nil) {
+            items = self.selectItems(numPage: 0, account: self.providerData.account, metadatas: metadatas!)
+            observer.didEnumerate(items)
+        }
+        if (items.count == self.providerData.itemForPage) {
+            let providerPage = NSFileProviderPage("1".data(using: .utf8)!)
+            observer.finishEnumerating(upTo: providerPage)
+        } else {
+            observer.finishEnumerating(upTo: nil)
+        }
+    }
+    
     func selectItems(numPage: Int, account: String, metadatas: [tableMetadata]) -> [NSFileProviderItemProtocol] {
         
         var items: [NSFileProviderItemProtocol] = []
-        let start = numPage * self.recordForPage + 1
-        let stop = start + (self.recordForPage - 1)
+        let start = numPage * providerData.itemForPage + 1
+        let stop = start + (providerData.itemForPage - 1)
         var counter = 0
         
-        for metadata in metadatas {
-            
-            // E2EE Remove
-            if metadata.e2eEncrypted || metadata.status == Double(k_metadataStatusHide) || metadata.session != "" {
-                continue
-            }
+        autoreleasepool {
             
-            counter += 1
-            if (counter >= start && counter <= stop) {
+            for metadata in metadatas {
                 
-                providerData.createFileIdentifierOnFileSystem(metadata: metadata)
-
-                let parentItemIdentifier = providerData.getParentItemIdentifier(metadata: metadata)
-                if parentItemIdentifier != nil {
-                    let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier!, providerData: providerData)
-                    items.append(item)
+                // E2EE Remove
+                if metadata.e2eEncrypted || metadata.status == Double(k_metadataStatusHide) || (metadata.session != "" && metadata.session != k_download_session_extension && metadata.session != k_upload_session_extension) {
+                    continue
+                }
+                
+                counter += 1
+                if (counter >= start && counter <= stop) {
+                    
+                    providerData.createFileIdentifierOnFileSystem(metadata: metadata)
+                    
+                    let parentItemIdentifier = providerData.getParentItemIdentifier(metadata: metadata)
+                    if parentItemIdentifier != nil {
+                        let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier!, providerData: providerData)
+                        items.append(item)
+                    }
                 }
             }
         }
-        
         return items
     }
 

+ 129 - 107
PickerFileProvider/FileProviderExtension+Actions.swift

@@ -73,11 +73,13 @@ extension FileProviderExtension {
                 
                 let item = FileProviderItem(metadata: metadataDB, parentItemIdentifier: parentItemIdentifier!, providerData: self.providerData)
                 
-                fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
-                fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
+                self.providerData.queueTradeSafe.sync(flags: .barrier) {
+                    self.providerData.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
+                    self.providerData.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
+                }
 
                 self.signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
-                
+
                 completionHandler(item, nil)
                 
             } else {
@@ -110,14 +112,24 @@ extension FileProviderExtension {
             return
         }
         
-        deleteFile(withIdentifier: itemIdentifier, parentItemIdentifier: parentItemIdentifier, metadata: metadata)
-
+        guard let serverUrl = NCManageDatabase.sharedInstance.getServerUrl(metadata.directoryID) else {
+            return
+        }
+        
+        // Delete queue upload for ImportDocument (if exists)
+        NCManageDatabase.sharedInstance.deleteQueueUpload(assetLocalIdentifier: metadata.assetLocalIdentifier, selector: metadata.sessionSelector)
+        
+        //
+        deleteFile(withIdentifier: itemIdentifier, parentItemIdentifier: parentItemIdentifier, metadata: metadata, serverUrl: serverUrl)
+       
         // return immediately
-        fileProviderSignalDeleteContainerItemIdentifier[itemIdentifier] = itemIdentifier
-        fileProviderSignalDeleteWorkingSetItemIdentifier[itemIdentifier] = itemIdentifier
+        providerData.queueTradeSafe.sync(flags: .barrier) {
+            providerData.fileProviderSignalDeleteContainerItemIdentifier[itemIdentifier] = itemIdentifier
+            providerData.fileProviderSignalDeleteWorkingSetItemIdentifier[itemIdentifier] = itemIdentifier
+        }
 
         self.signalEnumerator(for: [parentItemIdentifier, .workingSet])
-        
+
         completionHandler(nil)
     }
     
@@ -179,11 +191,13 @@ extension FileProviderExtension {
             
             let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, providerData: self.providerData)
             
-            fileProviderSignalUpdateContainerItem[itemIdentifier] = item
-            fileProviderSignalUpdateWorkingSetItem[itemIdentifier] = item
+            self.providerData.queueTradeSafe.sync(flags: .barrier) {
+                self.providerData.fileProviderSignalUpdateContainerItem[itemIdentifier] = item
+                self.providerData.fileProviderSignalUpdateWorkingSetItem[itemIdentifier] = item
+            }
 
             self.signalEnumerator(for: [parentItemIdentifier, .workingSet])
-                
+
             completionHandler(item, nil)
             
         }, failure: { (errorMessage, errorCode) in
@@ -238,7 +252,7 @@ extension FileProviderExtension {
                 
                 let itemIdentifier = self.providerData.getItemIdentifier(metadata: metadata)
                 
-                _ = self.moveFile(self.providerData.fileProviderStorageURL!.path + "/" + itemIdentifier.rawValue + "/" + fileNameFrom, toPath: self.providerData.fileProviderStorageURL!.path + "/" + itemIdentifier.rawValue + "/" + itemName)
+                _ = self.providerData.moveFile(self.providerData.fileProviderStorageURL!.path + "/" + itemIdentifier.rawValue + "/" + fileNameFrom, toPath: self.providerData.fileProviderStorageURL!.path + "/" + itemIdentifier.rawValue + "/" + itemName)
                 
                 NCManageDatabase.sharedInstance.setLocalFile(fileID: metadata.fileID, date: nil, exifDate: nil, exifLatitude: nil, exifLongitude: nil, fileName: itemName, etag: nil, etagFPE: nil)
             }
@@ -249,12 +263,14 @@ extension FileProviderExtension {
             }
             
             let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, providerData: self.providerData)
-                
-            fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
-            fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
+            
+            self.providerData.queueTradeSafe.sync(flags: .barrier) {
+                self.providerData.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
+                self.providerData.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
+            }
 
             self.signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
-                
+
             completionHandler(item, nil)
             
         }, failure: { (errorMessage, errorCode) in
@@ -285,19 +301,21 @@ extension FileProviderExtension {
         
         var favorite = false
         if favoriteRank == nil {
-            listFavoriteIdentifierRank.removeValue(forKey: itemIdentifier.rawValue)
+            providerData.listFavoriteIdentifierRank.removeValue(forKey: itemIdentifier.rawValue)
         } else {
-            let rank = listFavoriteIdentifierRank[itemIdentifier.rawValue]
+            let rank = providerData.listFavoriteIdentifierRank[itemIdentifier.rawValue]
             if rank == nil {
-                listFavoriteIdentifierRank[itemIdentifier.rawValue] = favoriteRank
+                providerData.listFavoriteIdentifierRank[itemIdentifier.rawValue] = favoriteRank
             }
             favorite = true
         }
         
         let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, providerData: providerData)
         
-        fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
-        fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
+        providerData.queueTradeSafe.sync(flags: .barrier) {
+            providerData.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
+            providerData.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
+        }
 
         signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
 
@@ -328,11 +346,13 @@ extension FileProviderExtension {
         
         let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, providerData: providerData)
         
-        fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
-        fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
-
+        providerData.queueTradeSafe.sync(flags: .barrier) {
+            providerData.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
+            providerData.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
+        }
+        
         signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
-
+        
         completionHandler(item, nil)
     }
     
@@ -362,106 +382,108 @@ extension FileProviderExtension {
         /* ONLY iOS 11*/
         guard #available(iOS 11, *) else { return }
         
-        var size = 0 as Double
-        let metadata = tableMetadata()
-        let fileCoordinator = NSFileCoordinator()
-        var error: NSError?
-        
-        guard let tableDirectory = self.providerData.getTableDirectoryFromParentItemIdentifier(parentItemIdentifier) else {
-            completionHandler(nil, NSFileProviderError(.noSuchItem))
-            return
-        }
-        let serverUrl = tableDirectory.serverUrl
+        DispatchQueue.main.async {
             
-        // --------------------------------------------- Copy file here with security access
+            autoreleasepool {
             
-        if fileURL.startAccessingSecurityScopedResource() == false {
-            completionHandler(nil, NSFileProviderError(.noSuchItem))
-            return
-        }
-        
-        // typefile directory ? (NOT PERMITTED)
-        do {
-            let attributes = try self.fileManager.attributesOfItem(atPath: fileURL.path)
-            size = attributes[FileAttributeKey.size] as! Double
-            let typeFile = attributes[FileAttributeKey.type] as! FileAttributeType
-            if typeFile == FileAttributeType.typeDirectory {
-                completionHandler(nil, NSFileProviderError(.noSuchItem))
-                return
-            }
-        } catch {
-            completionHandler(nil, NSFileProviderError(.noSuchItem))
-            return
-        }
-        
-        let fileName = self.createFileName(fileURL.lastPathComponent, directoryID: tableDirectory.directoryID, serverUrl: serverUrl)
-        let fileNamePathDirectory = self.providerData.fileProviderStorageURL!.path + "/" + self.FILEID_IMPORT_METADATA_TEMP + tableDirectory.directoryID + fileName
+                var size = 0 as Double
+                let metadata = tableMetadata()
+                var error: NSError?
             
-        do {
-            try FileManager.default.createDirectory(atPath: fileNamePathDirectory, withIntermediateDirectories: true, attributes: nil)
-        } catch  { }
+                guard let tableDirectory = self.providerData.getTableDirectoryFromParentItemIdentifier(parentItemIdentifier) else {
+                    completionHandler(nil, NSFileProviderError(.noSuchItem))
+                    return
+                }
+                let serverUrl = tableDirectory.serverUrl
             
-        fileCoordinator.coordinate(readingItemAt: fileURL, options: .withoutChanges, error: &error) { (url) in
-            _ = self.moveFile(url.path, toPath: fileNamePathDirectory + "/" + fileName)
-        }
+                // --------------------------------------------- Copy file here with security access
             
-        fileURL.stopAccessingSecurityScopedResource()
+                if fileURL.startAccessingSecurityScopedResource() == false {
+                    completionHandler(nil, NSFileProviderError(.noSuchItem))
+                    return
+                }
             
-        // ---------------------------------------------------------------------------------
+                // typefile directory ? (NOT PERMITTED)
+                do {
+                    let attributes = try self.providerData.fileManager.attributesOfItem(atPath: fileURL.path)
+                    size = attributes[FileAttributeKey.size] as! Double
+                    let typeFile = attributes[FileAttributeKey.type] as! FileAttributeType
+                    if typeFile == FileAttributeType.typeDirectory {
+                        completionHandler(nil, NSFileProviderError(.noSuchItem))
+                        return
+                    }
+                } catch {
+                    completionHandler(nil, NSFileProviderError(.noSuchItem))
+                    return
+                }
             
-        // Metadata TEMP
-        metadata.account = self.providerData.account
-        metadata.date = NSDate()
-        metadata.directory = false
-        metadata.directoryID = tableDirectory.directoryID
-        metadata.etag = ""
-        metadata.fileID = self.FILEID_IMPORT_METADATA_TEMP + tableDirectory.directoryID + fileName
-        metadata.size = size
-        metadata.status = Double(k_metadataStatusHide)
-        metadata.fileName = fileName
-        metadata.fileNameView = fileName
-        CCUtility.insertTypeFileIconName(fileName, metadata: metadata)
+                let fileName = self.createFileName(fileURL.lastPathComponent, directoryID: tableDirectory.directoryID, serverUrl: serverUrl)
+                let fileNamePathDirectory = self.providerData.fileProviderStorageURL!.path + "/" + self.providerData.FILEID_IMPORT_METADATA_TEMP + tableDirectory.directoryID + fileName
             
-        if (size > 0) {
-                
-            let metadataNet = CCMetadataNet()
-                
-            metadataNet.account = self.providerData.account
-            metadataNet.assetLocalIdentifier = self.FILEID_IMPORT_METADATA_TEMP + tableDirectory.directoryID + fileName
-            metadataNet.fileName = fileName
-            metadataNet.path = fileNamePathDirectory + "/" + fileName
-            metadataNet.selector = selectorUploadFile
-            metadataNet.selectorPost = ""
-            metadataNet.serverUrl = serverUrl
-            metadataNet.session = k_upload_session_extension
-            metadataNet.sessionError = ""
-            metadataNet.sessionID = ""
-            metadataNet.taskStatus = Int(k_taskStatusResume)
-                
-            _ = NCManageDatabase.sharedInstance.addQueueUpload(metadataNet: metadataNet)
-        }
+                do {
+                    try FileManager.default.createDirectory(atPath: fileNamePathDirectory, withIntermediateDirectories: true, attributes: nil)
+                } catch  { }
             
-        guard let metadataDB = NCManageDatabase.sharedInstance.addMetadata(metadata) else {
-            completionHandler(nil, NSFileProviderError(.noSuchItem))
-            return
-        }
+                self.fileCoordinator.coordinate(readingItemAt: fileURL, options: .withoutChanges, error: &error) { (url) in
+                    _ = self.providerData.moveFile(url.path, toPath: fileNamePathDirectory + "/" + fileName)
+                }
             
-        let item = FileProviderItem(metadata: metadataDB, parentItemIdentifier: parentItemIdentifier, providerData: self.providerData)
+                fileURL.stopAccessingSecurityScopedResource()
             
-        fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
-        fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
-
-        self.signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
+                // ---------------------------------------------------------------------------------
             
-        completionHandler(item, nil)
+                // Metadata TEMP
+                metadata.account = self.providerData.account
+                metadata.assetLocalIdentifier = self.providerData.FILEID_IMPORT_METADATA_TEMP + tableDirectory.directoryID + fileName
+                metadata.date = NSDate()
+                metadata.directory = false
+                metadata.directoryID = tableDirectory.directoryID
+                metadata.etag = ""
+                metadata.fileID = self.providerData.FILEID_IMPORT_METADATA_TEMP + tableDirectory.directoryID + fileName
+                metadata.size = size
+                metadata.status = Double(k_metadataStatusHide)
+                metadata.fileName = fileName
+                metadata.fileNameView = fileName
+                CCUtility.insertTypeFileIconName(fileName, metadata: metadata)
+            
+                if (size > 0) {
+                    
+                    let metadataNet = CCMetadataNet()
+                    
+                    metadataNet.account = self.providerData.account
+                    metadataNet.assetLocalIdentifier = self.providerData.FILEID_IMPORT_METADATA_TEMP + tableDirectory.directoryID + fileName
+                    metadataNet.fileName = fileName
+                    metadataNet.path = fileNamePathDirectory + "/" + fileName
+                    metadataNet.selector = selectorUploadFile
+                    metadataNet.selectorPost = self.providerData.selectorPostImportDocument
+                    metadataNet.serverUrl = serverUrl
+                    metadataNet.session = k_upload_session_extension
+                    metadataNet.sessionError = ""
+                    metadataNet.sessionID = ""
+                    metadataNet.taskStatus = Int(k_taskStatusResume)
+                    
+                    _ = NCManageDatabase.sharedInstance.addQueueUpload(metadataNet: metadataNet)
+                }
+            
+                guard let metadataDB = NCManageDatabase.sharedInstance.addMetadata(metadata) else {
+                    completionHandler(nil, NSFileProviderError(.noSuchItem))
+                    return
+                }
+            
+                let item = FileProviderItem(metadata: metadataDB, parentItemIdentifier: parentItemIdentifier, providerData: self.providerData)
+            
+                completionHandler(item, nil)
+
+                self.uploadFileImportDocument()            
+            }
+        }
     }
     
     func createFileName(_ fileName: String, directoryID: String, serverUrl: String) -> String {
         
-        let serialQueue = DispatchQueue(label: "queueCreateFileName")
         var resultFileName = fileName
         
-        serialQueue.sync {
+        providerData.queueTradeSafe.sync {
             
             var exitLoop = false
             

+ 217 - 67
PickerFileProvider/FileProviderExtension+Network.swift

@@ -26,56 +26,116 @@ import FileProvider
 extension FileProviderExtension {
 
     // --------------------------------------------------------------------------------------------
-    //  MARK: - Delete
+    //  MARK: - Read folder
     // --------------------------------------------------------------------------------------------
     
-    func deleteFile(withIdentifier itemIdentifier: NSFileProviderItemIdentifier, parentItemIdentifier: NSFileProviderItemIdentifier, metadata: tableMetadata) {
+    func readFolder(enumeratedItemIdentifier: NSFileProviderItemIdentifier) {
         
         /* ONLY iOS 11*/
         guard #available(iOS 11, *) else { return }
         
-        guard let serverUrl = NCManageDatabase.sharedInstance.getServerUrl(metadata.directoryID) else {
-            return
-        }
+        var serverUrl: String?
+        var counter = 0
         
-        let ocNetworking = OCnetworking.init(delegate: nil, metadataNet: nil, withUser: providerData.accountUser, withUserID: providerData.accountUserID, withPassword: providerData.accountPassword, withUrl: providerData.accountUrl)
-        ocNetworking?.deleteFileOrFolder(metadata.fileName, serverUrl: serverUrl, success: {
+        if (enumeratedItemIdentifier == .rootContainer) {
             
-            let fileNamePath = self.providerData.directoryUser + "/" + metadata.fileID
-            do {
-                try self.fileManager.removeItem(atPath: fileNamePath)
-            } catch let error {
-                print("error: \(error)")
-            }
-            do {
-                try self.fileManager.removeItem(atPath: fileNamePath + ".ico")
-            } catch let error {
-                print("error: \(error)")
+            serverUrl = providerData.homeServerUrl
+            
+        } else {
+            
+            guard let metadata = providerData.getTableMetadataFromItemIdentifier(enumeratedItemIdentifier) else {
+                return
             }
-            do {
-                try self.fileManager.removeItem(atPath: self.providerData.fileProviderStorageURL!.path + "/" + itemIdentifier.rawValue)
-            } catch let error {
-                print("error: \(error)")
+            guard let directorySource = NCManageDatabase.sharedInstance.getTableDirectory(predicate: NSPredicate(format: "account = %@ AND directoryID = %@", providerData.account, metadata.directoryID)) else {
+                return
             }
             
-            if metadata.directory {
-                let dirForDelete = CCUtility.stringAppendServerUrl(serverUrl, addFileName: metadata.fileName)
-                NCManageDatabase.sharedInstance.deleteDirectoryAndSubDirectory(serverUrl: dirForDelete!)
+            serverUrl = directorySource.serverUrl + "/" + metadata.fileName
+        }
+        
+        let ocNetworking = OCnetworking.init(delegate: nil, metadataNet: nil, withUser: providerData.accountUser, withUserID: providerData.accountUserID, withPassword: providerData.accountPassword, withUrl: providerData.accountUrl)
+        ocNetworking?.readFolder(serverUrl, depth: "1", account: providerData.account, success: { (metadatas, metadataFolder, directoryID) in
+            
+            NCManageDatabase.sharedInstance.deleteMetadata(predicate: NSPredicate(format: "account = %@ AND directoryID = %@ AND session = ''", self.providerData.account, directoryID!), clearDateReadDirectoryID: directoryID!)
+            guard let metadatasUpdate = NCManageDatabase.sharedInstance.addMetadatas(metadatas as! [tableMetadata], serverUrl: serverUrl) else {
+                return
             }
             
-            NCManageDatabase.sharedInstance.deleteLocalFile(predicate: NSPredicate(format: "fileID == %@", metadata.fileID))
-            NCManageDatabase.sharedInstance.deleteMetadata(predicate: NSPredicate(format: "fileID == %@", metadata.fileID), clearDateReadDirectoryID: nil)
+            for metadata in metadatasUpdate {
+             
+                let item = FileProviderItem(metadata: metadata, parentItemIdentifier: enumeratedItemIdentifier, providerData: self.providerData)
+             
+                self.providerData.queueTradeSafe.sync(flags: .barrier) {
+                    self.providerData.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
+                }
+             
+                counter += 1
+                if counter >= self.providerData.itemForPage {
+                    //self.signalEnumerator(for: [enumeratedItemIdentifier])
+                    counter = 0
+                }
+             }
+             
+            //self.signalEnumerator(for: [enumeratedItemIdentifier])
+            
+        }, failure: { (errorMessage, errorCode) in
+        })
+    }
+    
+    // --------------------------------------------------------------------------------------------
+    //  MARK: - Delete
+    // --------------------------------------------------------------------------------------------
+    
+    func deleteFile(withIdentifier itemIdentifier: NSFileProviderItemIdentifier, parentItemIdentifier: NSFileProviderItemIdentifier, metadata: tableMetadata, serverUrl: String) {
+        
+        /* ONLY iOS 11*/
+        guard #available(iOS 11, *) else { return }
+        
+        let ocNetworking = OCnetworking.init(delegate: nil, metadataNet: nil, withUser: providerData.accountUser, withUserID: providerData.accountUserID, withPassword: providerData.accountPassword, withUrl: providerData.accountUrl)
+        ocNetworking?.deleteFileOrFolder(metadata.fileName, serverUrl: serverUrl, success: {
+            
+            self.deleteFileSystem(for: metadata, serverUrl: serverUrl, itemIdentifier: itemIdentifier)
             
         }, failure: { (errorMessage, errorCode) in
             
             // remove itemIdentifier on fileProviderSignalDeleteItemIdentifier
-            fileProviderSignalDeleteContainerItemIdentifier.removeValue(forKey: itemIdentifier)
-            fileProviderSignalDeleteWorkingSetItemIdentifier.removeValue(forKey: itemIdentifier)
-
+            self.providerData.queueTradeSafe.sync(flags: .barrier) {
+                self.providerData.fileProviderSignalDeleteContainerItemIdentifier.removeValue(forKey: itemIdentifier)
+                self.providerData.fileProviderSignalDeleteWorkingSetItemIdentifier.removeValue(forKey: itemIdentifier)
+            }
+            
             self.signalEnumerator(for: [parentItemIdentifier, .workingSet])
         })
     }
     
+    func deleteFileSystem(for metadata: tableMetadata, serverUrl: String, itemIdentifier: NSFileProviderItemIdentifier) {
+        
+        let fileNamePath = self.providerData.directoryUser + "/" + metadata.fileID
+        do {
+            try self.providerData.fileManager.removeItem(atPath: fileNamePath)
+        } catch let error {
+            print("error: \(error)")
+        }
+        do {
+            try self.providerData.fileManager.removeItem(atPath: fileNamePath + ".ico")
+        } catch let error {
+            print("error: \(error)")
+        }
+        do {
+            try self.providerData.fileManager.removeItem(atPath: self.providerData.fileProviderStorageURL!.path + "/" + itemIdentifier.rawValue)
+        } catch let error {
+            print("error: \(error)")
+        }
+        
+        if metadata.directory {
+            let dirForDelete = CCUtility.stringAppendServerUrl(serverUrl, addFileName: metadata.fileName)
+            NCManageDatabase.sharedInstance.deleteDirectoryAndSubDirectory(serverUrl: dirForDelete!)
+        }
+        
+        NCManageDatabase.sharedInstance.deleteLocalFile(predicate: NSPredicate(format: "fileID == %@", metadata.fileID))
+        NCManageDatabase.sharedInstance.deleteMetadata(predicate: NSPredicate(format: "fileID == %@", metadata.fileID), clearDateReadDirectoryID: nil)
+    }
+    
     // --------------------------------------------------------------------------------------------
     //  MARK: - Favorite
     // --------------------------------------------------------------------------------------------
@@ -101,15 +161,16 @@ extension FileProviderExtension {
         }, failure: { (errorMessage, errorCode) in
             
             // Errore, remove from listFavoriteIdentifierRank
-            listFavoriteIdentifierRank.removeValue(forKey: itemIdentifier.rawValue)
+            self.providerData.listFavoriteIdentifierRank.removeValue(forKey: itemIdentifier.rawValue)
 
             let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, providerData: self.providerData)
             
-            fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
-            fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
-
-            self.signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
+            self.providerData.queueTradeSafe.sync(flags: .barrier) {
+                self.providerData.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
+                self.providerData.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
+            }
             
+            self.signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
         })
     }
     
@@ -117,64 +178,132 @@ extension FileProviderExtension {
     //  MARK: - Upload
     // --------------------------------------------------------------------------------------------
     
+    func uploadStart(_ fileID: String!, task: URLSessionUploadTask!, serverUrl: String!) {
+     
+        /* ONLY iOS 11*/
+        guard #available(iOS 11, *) else { return }
+
+        guard let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "fileID = %@", fileID)) else {
+            return
+        }
+        
+        guard let parentItemIdentifier = providerData.getParentItemIdentifier(metadata: metadata) else {
+            return
+        }
+        
+        let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, providerData: providerData)
+
+        NSFileProviderManager.default.register(task, forItemWithIdentifier: NSFileProviderItemIdentifier(item.itemIdentifier.rawValue)) { (error) in }
+        
+        providerData.queueTradeSafe.sync(flags: .barrier) {
+            self.providerData.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
+            self.providerData.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
+        }
+        
+        self.signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
+    }
+    
     func uploadFileSuccessFailure(_ fileName: String!, fileID: String!, assetLocalIdentifier: String!, serverUrl: String!, selector: String!, selectorPost: String!, errorMessage: String!, errorCode: Int) {
         
         /* ONLY iOS 11*/
         guard #available(iOS 11, *) else { return }
         
-        if let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "fileID = %@", assetLocalIdentifier)) {
-            
-            let parentItemIdentifier = providerData.getParentItemIdentifier(metadata: metadata)
-            if parentItemIdentifier != nil {
-                
-                let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier!, providerData: providerData)
-            
-                fileProviderSignalDeleteContainerItemIdentifier[item.itemIdentifier] = item.itemIdentifier
-                fileProviderSignalDeleteWorkingSetItemIdentifier[item.itemIdentifier] = item.itemIdentifier
-
-                signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
-            }
+        guard let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "account = %@ AND fileID = %@", providerData.account, fileID)) else {
+            return
         }
         
-        NCManageDatabase.sharedInstance.deleteMetadata(predicate: NSPredicate(format: "fileID = %@", assetLocalIdentifier), clearDateReadDirectoryID: nil)
+        guard let parentItemIdentifier = providerData.getParentItemIdentifier(metadata: metadata) else {
+            return
+        }
         
         if errorCode == 0 {
             
-            NCManageDatabase.sharedInstance.deleteQueueUpload(assetLocalIdentifier: assetLocalIdentifier, selector: selector)
-            
-            if let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "account = %@ AND fileID = %@", providerData.account, fileID)) {
+            // importDocument
+            if (selectorPost == providerData.selectorPostImportDocument) {
+                
+                NCManageDatabase.sharedInstance.deleteQueueUpload(assetLocalIdentifier: assetLocalIdentifier, selector: selector)
                 
                 // Rename directory file
-                if fileManager.fileExists(atPath: providerData.fileProviderStorageURL!.path + "/" + assetLocalIdentifier) {
+                if providerData.fileManager.fileExists(atPath: providerData.fileProviderStorageURL!.path + "/" + assetLocalIdentifier) {
                     let itemIdentifier = providerData.getItemIdentifier(metadata: metadata)
-                    _ = moveFile(providerData.fileProviderStorageURL!.path + "/" + assetLocalIdentifier, toPath: providerData.fileProviderStorageURL!.path + "/" + itemIdentifier.rawValue)
+                    _ = providerData.moveFile(providerData.fileProviderStorageURL!.path + "/" + assetLocalIdentifier, toPath: providerData.fileProviderStorageURL!.path + "/" + itemIdentifier.rawValue)
                 }
                 
-                NCManageDatabase.sharedInstance.setLocalFile(fileID: fileID, date: nil, exifDate: nil, exifLatitude: nil, exifLongitude: nil, fileName: nil, etag: metadata.etag, etagFPE: metadata.etag)
-                
-                guard let parentItemIdentifier = providerData.getParentItemIdentifier(metadata: metadata) else {
-                    return
+                providerData.queueTradeSafe.sync(flags: .barrier) {
+                    let itemIdentifier = NSFileProviderItemIdentifier(assetLocalIdentifier)
+                    self.providerData.fileProviderSignalDeleteContainerItemIdentifier[itemIdentifier] = itemIdentifier
+                    self.providerData.fileProviderSignalDeleteWorkingSetItemIdentifier[itemIdentifier] = itemIdentifier
                 }
                 
-                let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, providerData: providerData)
-                    
-                fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
-                fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
+            }
+            
+            // itemChanged
+            if (selectorPost == providerData.selectorPostItemChanged) {
+                
+                let filePathItemIdentifier = providerData.fileProviderStorageURL!.path + "/" + providerData.getItemIdentifier(metadata: metadata).rawValue + "/" + metadata.fileName
+                _ = self.providerData.copyFile(filePathItemIdentifier, toPath: providerData.directoryUser + "/" + metadata.fileID)
+            }
+            
+            NCManageDatabase.sharedInstance.setLocalFile(fileID: fileID, date: nil, exifDate: nil, exifLatitude: nil, exifLongitude: nil, fileName: nil, etag: metadata.etag, etagFPE: metadata.etag)
+            
+            // remove session data
+            metadata.assetLocalIdentifier = ""
+            metadata.session = ""
+            metadata.sessionID = ""
+            metadata.sessionSelector = ""
+            metadata.sessionSelectorPost = ""
+            let metadata = NCManageDatabase.sharedInstance.addMetadata(metadata)
+            
+            let item = FileProviderItem(metadata: metadata!, parentItemIdentifier: parentItemIdentifier, providerData: providerData)
 
-                signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
+            providerData.queueTradeSafe.sync(flags: .barrier) {
+                self.providerData.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
+                self.providerData.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
             }
             
-            uploadFile()
+            uploadFileImportDocument()
             
         } else {
             
-            //TODO: manage error
+            // importDocument
+            if (selectorPost == providerData.selectorPostImportDocument) {
+                
+                NCManageDatabase.sharedInstance.unlockQueueUpload(assetLocalIdentifier: assetLocalIdentifier)
+            }
+            
+            // itemChanged
+            if (selectorPost == providerData.selectorPostItemChanged) {
+                
+                let itemIdentifier = providerData.getItemIdentifier(metadata: metadata)
+                
+                let urlString = (providerData.fileProviderStorageURL!.path + "/"  + itemIdentifier.rawValue + "/" + fileName).addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)!
+                let url = URL(string: urlString)!
+                
+                DispatchQueue.main.asyncAfter(deadline: .now() + Double(k_timerProcessAutoUploadExtension)) {
+                    
+                    self.uploadFileItemChanged(for: itemIdentifier, url: url)
+                }
+            }
+            
+            // remove session data
+            metadata.session = ""
+            metadata.sessionID = ""
+            metadata.sessionSelector = ""
+            metadata.sessionSelectorPost = ""
+            let metadata = NCManageDatabase.sharedInstance.addMetadata(metadata)
+            
+            let item = FileProviderItem(metadata: metadata!, parentItemIdentifier: parentItemIdentifier, providerData: providerData)
             
-            NCManageDatabase.sharedInstance.unlockQueueUpload(assetLocalIdentifier: assetLocalIdentifier)
+            providerData.queueTradeSafe.sync(flags: .barrier) {
+                providerData.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
+                providerData.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
+            }
         }
+        
+        self.signalEnumerator(for: [parentItemIdentifier, .workingSet])
     }
     
-    func uploadFile() {
+    func uploadFileImportDocument() {
         
         let queueInLock = NCManageDatabase.sharedInstance.getQueueUploadInLock()
         if queueInLock != nil && queueInLock!.count == 0 {
@@ -182,9 +311,9 @@ extension FileProviderExtension {
             let metadataNetQueue = NCManageDatabase.sharedInstance.lockQueueUpload(selector: selectorUploadFile, withPath: true)
             if  metadataNetQueue != nil {
                 
-                if self.copyFile(metadataNetQueue!.path, toPath: providerData.directoryUser + "/" + metadataNetQueue!.fileName) == nil {
+                if self.providerData.copyFile(metadataNetQueue!.path, toPath: providerData.directoryUser + "/" + metadataNetQueue!.fileName) == nil {
                     
-                    CCNetworking.shared().uploadFile(metadataNetQueue!.fileName, serverUrl: metadataNetQueue!.serverUrl, assetLocalIdentifier: metadataNetQueue!.assetLocalIdentifier ,session: metadataNetQueue!.session, taskStatus: metadataNetQueue!.taskStatus, selector: metadataNetQueue!.selector, selectorPost: metadataNetQueue!.selectorPost, errorCode: 0, delegate: self)
+                    CCNetworking.shared().uploadFile(metadataNetQueue!.fileName, serverUrl: metadataNetQueue!.serverUrl, fileID: metadataNetQueue!.assetLocalIdentifier, assetLocalIdentifier: metadataNetQueue!.assetLocalIdentifier, session: metadataNetQueue!.session, taskStatus: metadataNetQueue!.taskStatus, selector: metadataNetQueue!.selector, selectorPost: metadataNetQueue!.selectorPost, errorCode: 0, delegate: self)
                     
                 } else {
                     // file not present, delete record Upload Queue
@@ -194,6 +323,27 @@ extension FileProviderExtension {
         }
     }
     
+    func uploadFileItemChanged(for itemIdentifier: NSFileProviderItemIdentifier, url: URL) {
+        
+        guard let metadata = providerData.getTableMetadataFromItemIdentifier(itemIdentifier) else {
+            return
+        }
+        
+        metadata.assetLocalIdentifier = ""
+        metadata.session = k_upload_session_extension
+        metadata.sessionID = metadata.fileID
+        metadata.sessionSelector = selectorUploadFile
+        metadata.sessionSelectorPost = providerData.selectorPostItemChanged
+        
+        guard let metadataForUpload = NCManageDatabase.sharedInstance.addMetadata(metadata) else {
+            return
+        }
+        
+        _ = self.providerData.copyFile(url.path, toPath: providerData.directoryUser + "/" + metadata.fileID)
+        
+        CCNetworking.shared().uploadFileMetadata(metadataForUpload, taskStatus: Int(k_taskStatusResume), delegate: self)
+    }
+    
     func verifyUploadQueueInLock() {
         
         let tasks = CCNetworking.shared().getUploadTasksExtensionSession()

+ 49 - 132
PickerFileProvider/FileProviderExtension.swift

@@ -26,17 +26,6 @@ import FileProvider
 // Timer for Upload (queue)
 var timerUpload: Timer?
 
-// Item for signalEnumerator
-var fileProviderSignalDeleteContainerItemIdentifier = [NSFileProviderItemIdentifier:NSFileProviderItemIdentifier]()
-var fileProviderSignalUpdateContainerItem = [NSFileProviderItemIdentifier:FileProviderItem]()
-var fileProviderSignalDeleteWorkingSetItemIdentifier = [NSFileProviderItemIdentifier:NSFileProviderItemIdentifier]()
-var fileProviderSignalUpdateWorkingSetItem = [NSFileProviderItemIdentifier:FileProviderItem]()
-
-// Rank favorite
-var listFavoriteIdentifierRank = [String:NSNumber]()
-
-var currentAnchor: UInt64 = 0
-
 /* -----------------------------------------------------------------------------------------------------------------------------------------------
                                                             STRUCT item
    -----------------------------------------------------------------------------------------------------------------------------------------------
@@ -64,13 +53,20 @@ var currentAnchor: UInt64 = 0
 
 class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
     
-    var fileManager = FileManager()
     var providerData = FileProviderData()
 
     var outstandingDownloadTasks = [URL: URLSessionTask]()
-
-    // Metadata Temp for Import
-    let FILEID_IMPORT_METADATA_TEMP = k_uploadSessionID + "FILE_PROVIDER_EXTENSION"
+    
+    lazy var fileCoordinator: NSFileCoordinator = {
+        
+        if #available(iOSApplicationExtension 11.0, *) {
+            let fileCoordinator = NSFileCoordinator()
+            fileCoordinator.purposeIdentifier = NSFileProviderManager.default.providerIdentifier
+            return fileCoordinator
+        } else {
+            return NSFileCoordinator()
+        }
+    }()
     
     override init() {
         
@@ -85,10 +81,10 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
             // Timer for upload
             if timerUpload == nil {
                 
-                timerUpload = Timer.init(timeInterval: TimeInterval(k_timerProcessAutoDownloadUpload), repeats: true, block: { (Timer) in
+                timerUpload = Timer.init(timeInterval: TimeInterval(k_timerProcessAutoUploadExtension), repeats: true, block: { (Timer) in
                     
                     // new upload
-                    self.uploadFile()
+                    self.uploadFileImportDocument()
                 })
                 
                 RunLoop.main.add(timerUpload!, forMode: .defaultRunLoopMode)
@@ -98,7 +94,7 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
             
             NSFileCoordinator().coordinate(writingItemAt: self.documentStorageURL, options: [], error: nil, byAccessor: { newURL in
                 do {
-                    try fileManager.createDirectory(at: newURL, withIntermediateDirectories: true, attributes: nil)
+                    try providerData.fileManager.createDirectory(at: newURL, withIntermediateDirectories: true, attributes: nil)
                 } catch let error {
                     print("error: \(error)")
                 }
@@ -114,11 +110,6 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
         guard #available(iOS 11, *) else { throw NSError(domain: NSCocoaErrorDomain, code: NSFileNoSuchFileError, userInfo:[:]) }
         
         var maybeEnumerator: NSFileProviderEnumerator? = nil
-        
-        // update workingset
-        if (containerItemIdentifier != NSFileProviderItemIdentifier.workingSet) {
-            self.updateWorkingSet()
-        }
 
         if (containerItemIdentifier == NSFileProviderItemIdentifier.rootContainer) {
             
@@ -127,6 +118,9 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
                 throw NSError(domain: NSFileProviderErrorDomain, code: NSFileProviderError.notAuthenticated.rawValue, userInfo:[:])
             }
             
+            // Update WorkingSet
+            self.updateWorkingSet()
+            
             maybeEnumerator = FileProviderEnumerator(enumeratedItemIdentifier: containerItemIdentifier, providerData: providerData)
         } else if (containerItemIdentifier == NSFileProviderItemIdentifier.workingSet) {
             maybeEnumerator = FileProviderEnumerator(enumeratedItemIdentifier: containerItemIdentifier, providerData: providerData)
@@ -157,7 +151,7 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
         /* ONLY iOS 11*/
         guard #available(iOS 11, *) else { return }
         
-        currentAnchor += 1
+        providerData.currentAnchor += 1
 
         for containerItemIdentifier in containerItemIdentifiers {
             
@@ -176,14 +170,12 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
         /* ONLY iOS 11*/
         guard #available(iOS 11, *) else { return }
         
-        var updateItemsWorkingSet = [NSFileProviderItemIdentifier:FileProviderItem]()
-        
         // ***** Favorite Files <-> Favorite Nextcloud *****
         
-        listFavoriteIdentifierRank = NCManageDatabase.sharedInstance.getTableMetadatasDirectoryFavoriteIdentifierRank()
-
+        providerData.listFavoriteIdentifierRank = NCManageDatabase.sharedInstance.getTableMetadatasDirectoryFavoriteIdentifierRank()
+        
         // (ADD)
-        for (identifier, _) in listFavoriteIdentifierRank {
+        for (identifier, _) in providerData.listFavoriteIdentifierRank {
             
             guard let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "account = %@ AND fileID = %@", providerData.account, identifier)) else {
                 continue
@@ -194,8 +186,10 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
             }
             
             let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, providerData: providerData)
-        
-            updateItemsWorkingSet[item.itemIdentifier] = item
+            
+            providerData.queueTradeSafe.sync(flags: .barrier) {
+                providerData.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
+            }
         }
         
         // (REMOVE)
@@ -207,18 +201,17 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
                 }
                 
                 let itemIdentifier = providerData.getItemIdentifier(metadata: metadata)
-                listFavoriteIdentifierRank.removeValue(forKey: itemIdentifier.rawValue)
+                providerData.listFavoriteIdentifierRank.removeValue(forKey: itemIdentifier.rawValue)
                 let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, providerData: providerData)
                 
-                updateItemsWorkingSet[item.itemIdentifier] = item
+                providerData.queueTradeSafe.sync(flags: .barrier) {
+                    providerData.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
+                }
             }
         }
         
         // Update workingSet
-        for (itemIdentifier, item) in updateItemsWorkingSet {
-            fileProviderSignalUpdateWorkingSetItem[itemIdentifier] = item
-            self.signalEnumerator(for: [.workingSet])
-        }
+        self.signalEnumerator(for: [.workingSet])
     }
     
     // MARK: - Item
@@ -238,8 +231,8 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
                 metadata.directory = true
                 metadata.directoryID = directory.directoryID
                 metadata.fileID = NSFileProviderItemIdentifier.rootContainer.rawValue
-                metadata.fileName = NCBrandOptions.sharedInstance.brand
-                metadata.fileNameView = NCBrandOptions.sharedInstance.brand
+                metadata.fileName = ""
+                metadata.fileNameView = ""
                 metadata.typeFile = k_metadataTypeFile_directory
                     
                 return FileProviderItem(metadata: metadata, parentItemIdentifier: NSFileProviderItemIdentifier(NSFileProviderItemIdentifier.rootContainer.rawValue), providerData: providerData)
@@ -257,7 +250,6 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
             
             let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, providerData: providerData)
             return item
-
         }
         
         throw NSFileProviderError(.noSuchItem)
@@ -357,8 +349,8 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
                 return
             }
             
-            // Upload ?
-            if metadata.fileID.contains(k_uploadSessionID) {
+            // is Upload [Office 365 !!!]
+            if metadata.sessionTaskIdentifier > 0 || metadata.fileID.contains(k_uploadSessionID) {
                 completionHandler(nil)
                 return
             }
@@ -373,13 +365,13 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
                 
                 // Verify last version on "Local Table"
                 if localEtag != localEtagFPE {
-                    if self.copyFile(providerData.directoryUser+"/"+metadata.fileID, toPath: url.path) == nil {
+                    if providerData.copyFile(providerData.directoryUser+"/"+metadata.fileID, toPath: url.path) == nil {
                         NCManageDatabase.sharedInstance.setLocalFile(fileID: metadata.fileID, date: nil, exifDate: nil, exifLatitude: nil, exifLongitude: nil, fileName: nil, etag: nil, etagFPE: localEtag)
                     }
                 }
                 
                 do {
-                    let attributes = try fileManager.attributesOfItem(atPath: url.path)
+                    let attributes = try providerData.fileManager.attributesOfItem(atPath: url.path)
                     fileSize = attributes[FileAttributeKey.size] as! Double
                 } catch let error {
                     print("error: \(error)")
@@ -397,17 +389,17 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
             }
             
             // delete prev file + ico on Directory User
-            _ = self.deleteFile("\(providerData.directoryUser)/\(metadata.fileID)")
-            _ = self.deleteFile("\(providerData.directoryUser)/\(metadata.fileID).ico")
+            _ = providerData.deleteFile("\(providerData.directoryUser)/\(metadata.fileID)")
+            _ = providerData.deleteFile("\(providerData.directoryUser)/\(metadata.fileID).ico")
 
             let ocNetworking = OCnetworking.init(delegate: nil, metadataNet: nil, withUser: providerData.accountUser, withUserID: providerData.accountUserID, withPassword: providerData.accountPassword, withUrl: providerData.accountUrl)
-            let task = ocNetworking?.downloadFileNameServerUrl("\(serverUrl)/\(metadata.fileName)", fileNameLocalPath: "\(providerData.directoryUser)/\(metadata.fileID)", communication: CCNetworking.shared().sharedOCCommunicationExtensionDownload(metadata.fileName), success: { (lenght, etag, date) in
+            let task = ocNetworking?.downloadFileNameServerUrl("\(serverUrl)/\(metadata.fileName)", fileNameLocalPath: "\(providerData.directoryUser)/\(metadata.fileID)", communication: CCNetworking.shared().sharedOCCommunicationExtensionDownload(), success: { (lenght, etag, date) in
                 
                 // remove Task
                 self.outstandingDownloadTasks.removeValue(forKey: url)
 
                 // copy download file to url
-                _ = self.copyFile("\(self.providerData.directoryUser)/\(metadata.fileID)", toPath: url.path)
+                _ = self.providerData.copyFile("\(self.providerData.directoryUser)/\(metadata.fileID)", toPath: url.path)
             
                 // update DB Local
                 metadata.date = date! as NSDate
@@ -460,40 +452,17 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
         
         if #available(iOSApplicationExtension 11.0, *) {
             
-            let fileName = url.lastPathComponent
             let pathComponents = url.pathComponents
-            let metadataNet = CCMetadataNet()
 
             assert(pathComponents.count > 2)
-            let identifier = NSFileProviderItemIdentifier(pathComponents[pathComponents.count - 2])
-            
-            guard let metadata = providerData.getTableMetadataFromItemIdentifier(identifier) else {
-                return
-            }
-            
-            guard let serverUrl = NCManageDatabase.sharedInstance.getServerUrl(metadata.directoryID) else {
-                return
-            }
-            
-            metadataNet.account = providerData.account
-            metadataNet.assetLocalIdentifier = FILEID_IMPORT_METADATA_TEMP + metadata.directoryID + fileName
-            metadataNet.fileName = fileName
-            metadataNet.path = url.path
-            metadataNet.selector = selectorUploadFile
-            metadataNet.selectorPost = ""
-            metadataNet.serverUrl = serverUrl
-            metadataNet.session = k_upload_session_extension
-            metadataNet.sessionError = ""
-            metadataNet.sessionID = ""
-            metadataNet.taskStatus = Int(k_taskStatusResume)
-                
-            _ = NCManageDatabase.sharedInstance.addQueueUpload(metadataNet: metadataNet)
+
+            let itemIdentifier = NSFileProviderItemIdentifier(pathComponents[pathComponents.count - 2])
             
-            self.uploadFile()
+            uploadFileItemChanged(for: itemIdentifier, url: url)
             
         } else {
             
-            let fileSize = (try! fileManager.attributesOfItem(atPath: url.path)[FileAttributeKey.size] as! NSNumber).uint64Value
+            let fileSize = (try! providerData.fileManager.attributesOfItem(atPath: url.path)[FileAttributeKey.size] as! NSNumber).uint64Value
             NSLog("[LOG] Item changed at URL %@ %lu", url as NSURL, fileSize)
             
             guard let account = NCManageDatabase.sharedInstance.getAccountActive() else {
@@ -529,7 +498,7 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
                 let destinationDirectoryUser = "\(directoryUser!)/\(uploadID)"
                 
                 // copy sourceURL on directoryUser
-                _ = self.copyFile(url.path, toPath: destinationDirectoryUser)
+                _ = providerData.copyFile(url.path, toPath: destinationDirectoryUser)
                 
                 // Prepare for send Metadata
                 metadata!.sessionID = uploadID
@@ -543,9 +512,9 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
                 let directoryUser = CCUtility.getDirectoryActiveUser(account.user, activeUrl: account.url)
                 let destinationDirectoryUser = "\(directoryUser!)/\(fileName)"
                 
-                _ = self.copyFile(url.path, toPath: destinationDirectoryUser)
+                _ = providerData.copyFile(url.path, toPath: destinationDirectoryUser)
 
-                CCNetworking.shared().uploadFile(fileName, serverUrl: serverUrl, assetLocalIdentifier: nil, session: k_upload_session, taskStatus: Int(k_taskStatusResume), selector: nil, selectorPost: nil, errorCode: 0, delegate: self)
+                CCNetworking.shared().uploadFile(fileName, serverUrl: serverUrl, fileID: nil, assetLocalIdentifier: nil, session: k_upload_session, taskStatus: Int(k_taskStatusResume), selector: nil, selectorPost: nil, errorCode: 0, delegate: self)
             }
 
             self.stopProvidingItem(at: url)
@@ -564,7 +533,7 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
         if !fileHasLocalChanges {
             // remove the existing file to free up space
             do {
-                _ = try fileManager.removeItem(at: url)
+                _ = try providerData.fileManager.removeItem(at: url)
             } catch let error {
                 print("error: \(error)")
             }
@@ -581,57 +550,5 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
             outstandingDownloadTasks.removeValue(forKey: url)
         }
     }
-    
-    // --------------------------------------------------------------------------------------------
-    //  MARK: - User Function
-    // --------------------------------------------------------------------------------------------
-    
-    func copyFile(_ atPath: String, toPath: String) -> Error? {
-        
-        var errorResult: Error?
-        
-        do {
-            try fileManager.removeItem(atPath: toPath)
-        } catch let error {
-            print("error: \(error)")
-        }
-        do {
-            try fileManager.copyItem(atPath: atPath, toPath: toPath)
-        } catch let error {
-            errorResult = error
-        }
-        
-        return errorResult
-    }
-    
-    func moveFile(_ atPath: String, toPath: String) -> Error? {
-        
-        var errorResult: Error?
-        
-        do {
-            try fileManager.removeItem(atPath: toPath)
-        } catch let error {
-            print("error: \(error)")
-        }
-        do {
-            try fileManager.moveItem(atPath: atPath, toPath: toPath)
-        } catch let error {
-            errorResult = error
-        }
-        
-        return errorResult
-    }
-    
-    func deleteFile(_ atPath: String) -> Error? {
-        
-        var errorResult: Error?
-        
-        do {
-            try fileManager.removeItem(atPath: atPath)
-        } catch let error {
-            errorResult = error
-        }
-        
-        return errorResult
-    }
+
 }

+ 16 - 4
PickerFileProvider/FileProviderItem.swift

@@ -34,7 +34,11 @@ class FileProviderItem: NSObject, NSFileProviderItem {
         if (self.isDirectory) {
             return [ .allowsAddingSubItems, .allowsContentEnumerating, .allowsReading, .allowsDeleting, .allowsRenaming ]
         } else {
-            return [ .allowsWriting, .allowsReading, .allowsDeleting, .allowsRenaming, .allowsReparenting ]
+            if isUpload {
+                return [ ]
+            } else {
+                return [ .allowsWriting, .allowsReading, .allowsDeleting, .allowsRenaming, .allowsReparenting ]
+            }
         }
     }
     
@@ -68,6 +72,8 @@ class FileProviderItem: NSObject, NSFileProviderItem {
     var favoriteRank: NSNumber?                                     // Favorite
     
     var isDirectory = false
+    var isDownload = false
+    var isUpload = false
 
     init(metadata: tableMetadata, parentItemIdentifier: NSFileProviderItemIdentifier, providerData: FileProviderData) {
         
@@ -106,22 +112,28 @@ class FileProviderItem: NSObject, NSFileProviderItem {
             }
             
             // Upload
-            if metadata.fileID.contains(k_uploadSessionID) {
+            if metadata.sessionSelectorPost == providerData.selectorPostImportDocument || metadata.sessionSelectorPost == providerData.selectorPostItemChanged {
+                isUpload = true
                 self.isDownloaded = true
                 self.isMostRecentVersionDownloaded = true
                 self.isUploading = true
                 self.isUploaded = false
             }
             
+            // Error ?
+            if metadata.sessionError != "" {
+                uploadingError = NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError, userInfo:[:])
+            }
+            
         } else {
             
             // Favorite directory
             if #available(iOSApplicationExtension 11.0, *) {
-                let rank = listFavoriteIdentifierRank[metadata.fileID]
+                let rank = providerData.listFavoriteIdentifierRank[metadata.fileID]
                 if (rank == nil) {
                     favoriteRank = nil
                 } else {
-                    favoriteRank = listFavoriteIdentifierRank[metadata.fileID]
+                    favoriteRank = providerData.listFavoriteIdentifierRank[metadata.fileID]
                 }
             }
         }

+ 1 - 1
Share/ShareViewController.m

@@ -216,7 +216,7 @@
     
         NSString *fileName = [self.filesName objectAtIndex:0];
         
-        [[CCNetworking sharedNetworking] uploadFile:fileName serverUrl:_serverUrl assetLocalIdentifier:nil session:k_upload_session_foreground taskStatus:k_taskStatusResume selector:@"" selectorPost:@"" errorCode:0 delegate:self];
+        [[CCNetworking sharedNetworking] uploadFile:fileName serverUrl:_serverUrl fileID:nil assetLocalIdentifier:nil session:k_upload_session_foreground taskStatus:k_taskStatusResume selector:@"" selectorPost:@"" errorCode:0 delegate:self];
         
         [self.hud visibleHudTitle:NSLocalizedString(@"_uploading_", nil) mode:MBProgressHUDModeDeterminate color:[NCBrandColor sharedInstance].brandElement];
     }

+ 3 - 3
iOSClient/AppDelegate.m

@@ -1337,7 +1337,7 @@
         if ([metadata.session isEqualToString:k_upload_session_wwan])
             metadata.session = k_upload_session;
         
-        [[CCNetworking sharedNetworking] uploadFileMetadata:metadata taskStatus:k_taskStatusResume];
+        [[CCNetworking sharedNetworking] uploadFileMetadata:metadata taskStatus:k_taskStatusResume delegate:nil];
     }
     else if ([[_listChangeTask objectForKey:fileID] isEqualToString:@"reloadDownload"]) {
         
@@ -1515,7 +1515,7 @@
                 metadataNet.session = k_upload_session;
             }
             
-            [[CCNetworking sharedNetworking] uploadFile:metadataNet.fileName serverUrl:metadataNet.serverUrl assetLocalIdentifier:metadataNet.assetLocalIdentifier session:metadataNet.session taskStatus:k_taskStatusResume selector:metadataNet.selector selectorPost:metadataNet.selectorPost errorCode:0 delegate:nil];
+            [[CCNetworking sharedNetworking] uploadFile:metadataNet.fileName serverUrl:metadataNet.serverUrl fileID:nil assetLocalIdentifier:metadataNet.assetLocalIdentifier session:metadataNet.session taskStatus:k_taskStatusResume selector:metadataNet.selector selectorPost:metadataNet.selectorPost errorCode:0 delegate:nil];
             counterNewUpload++;
         }
         
@@ -1563,7 +1563,7 @@
     
     for (tableMetadata *metadata in metadatas) {
         
-        [[CCNetworking sharedNetworking] uploadFileMetadata:metadata taskStatus: k_taskStatusResume];
+        [[CCNetworking sharedNetworking] uploadFileMetadata:metadata taskStatus: k_taskStatusResume delegate:nil];
         
         [directoryIDs addObject:metadata.directoryID];
         

+ 2 - 2
iOSClient/Brand/Picker.plist

@@ -17,9 +17,9 @@
 	<key>CFBundlePackageType</key>
 	<string>XPC!</string>
 	<key>CFBundleShortVersionString</key>
-	<string>2.21.0</string>
+	<string>2.21.1</string>
 	<key>CFBundleVersion</key>
-	<string>00018</string>
+	<string>00005</string>
 	<key>NSAppTransportSecurity</key>
 	<dict>
 		<key>NSAllowsArbitraryLoads</key>

+ 2 - 2
iOSClient/Brand/PickerFileProvider.plist

@@ -17,9 +17,9 @@
 	<key>CFBundlePackageType</key>
 	<string>XPC!</string>
 	<key>CFBundleShortVersionString</key>
-	<string>2.21.0</string>
+	<string>2.21.1</string>
 	<key>CFBundleVersion</key>
-	<string>00018</string>
+	<string>00005</string>
 	<key>NSExtension</key>
 	<dict>
 		<key>NSExtensionFileProviderDocumentGroup</key>

+ 2 - 2
iOSClient/Brand/Share.plist

@@ -17,9 +17,9 @@
 	<key>CFBundlePackageType</key>
 	<string>XPC!</string>
 	<key>CFBundleShortVersionString</key>
-	<string>2.21.0</string>
+	<string>2.21.1</string>
 	<key>CFBundleVersion</key>
-	<string>00018</string>
+	<string>00005</string>
 	<key>NSAppTransportSecurity</key>
 	<dict>
 		<key>NSAllowsArbitraryLoads</key>

+ 2 - 2
iOSClient/Brand/iOSClient.plist

@@ -46,7 +46,7 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>2.21.0</string>
+	<string>2.21.1</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleURLTypes</key>
@@ -69,7 +69,7 @@
 		</dict>
 	</array>
 	<key>CFBundleVersion</key>
-	<string>00018</string>
+	<string>00005</string>
 	<key>FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED</key>
 	<true/>
 	<key>Fabric</key>

+ 1 - 0
iOSClient/CCGlobal.h

@@ -135,6 +135,7 @@ extern NSString *const flowEndpoint;
 
 #define k_timerVerifySession                            10
 #define k_timerProcessAutoDownloadUpload                5
+#define k_timerProcessAutoUploadExtension               10
 #define k_timerUpdateApplicationIconBadgeNumber         3
 
 #define k_maxConcurrentOperation                         10

+ 1 - 1
iOSClient/Create/CCCreateCloud.swift

@@ -633,7 +633,7 @@ class CreateFormUploadFile: XLFormViewController, CCMoveDelegate {
             let success = FileManager.default.createFile(atPath: "\(self.appDelegate.directoryUser!)/\(fileNameSave)", contents: data, attributes: nil)
             
             if success {
-                CCNetworking.shared().uploadFile(fileNameSave, serverUrl: self.serverUrl, assetLocalIdentifier: nil, session: k_upload_session, taskStatus: Int(k_taskStatusResume), selector: nil, selectorPost: nil, errorCode: 0, delegate: self.appDelegate.activeMain)
+                CCNetworking.shared().uploadFile(fileNameSave, serverUrl: self.serverUrl, fileID: nil, assetLocalIdentifier: nil, session: k_upload_session, taskStatus: Int(k_taskStatusResume), selector: nil, selectorPost: nil, errorCode: 0, delegate: self.appDelegate.activeMain)
             } else {
                 self.appDelegate.messageNotification("_error_", description: "_error_creation_file_", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.info, errorCode: 0)
             }

+ 6 - 5
iOSClient/Database/NCManageDatabase.swift

@@ -790,7 +790,7 @@ class NCManageDatabase: NSObject {
             return nil
         }
         
-        var result :tableDirectory?
+        var result: tableDirectory?
         let realm = try! Realm()
 
         do {
@@ -2438,8 +2438,6 @@ class NCManageDatabase: NSObject {
         
         let realm = try! Realm()
         
-        realm.beginWrite()
-        
         if withPath {
             result = realm.objects(tableQueueUpload.self).filter("account = %@ AND selector = %@ AND lock == false AND path != nil", tableAccount.account, selector).sorted(byKeyPath: "date", ascending: true).first
         } else {
@@ -2447,15 +2445,18 @@ class NCManageDatabase: NSObject {
         }
         
         if result == nil {
-            realm.cancelWrite()
             return nil
         }
         
+        let directoryID = self.getDirectoryID(result!.serverUrl)
+        
+        realm.beginWrite()
+        
         let metadataNet = CCMetadataNet()
         
         metadataNet.account = result!.account
         metadataNet.assetLocalIdentifier = result!.assetLocalIdentifier
-        metadataNet.directoryID = self.getDirectoryID(result!.serverUrl)
+        metadataNet.directoryID = directoryID
         metadataNet.errorCode = result!.errorCode
         metadataNet.fileName = result!.fileName
         metadataNet.fileNameView = result!.fileNameView

+ 2 - 2
iOSClient/Main/CCMain.m

@@ -721,7 +721,7 @@
                 if ([data writeToFile:fileNamePath options:NSDataWritingAtomic error:&error]) {
                     
                     // Upload File
-                    [[CCNetworking sharedNetworking] uploadFile:fileName serverUrl:serverUrl assetLocalIdentifier: nil session:k_upload_session taskStatus: k_taskStatusResume selector:@"" selectorPost:@"" errorCode:0 delegate:nil];
+                    [[CCNetworking sharedNetworking] uploadFile:fileName serverUrl:serverUrl fileID:nil assetLocalIdentifier: nil session:k_upload_session taskStatus: k_taskStatusResume selector:@"" selectorPost:@"" errorCode:0 delegate:nil];
                     
                 } else {
                     
@@ -3495,7 +3495,7 @@
                         [CCUtility copyFileAtPath:[NSString stringWithFormat:@"%@/%@", directoryUser, metadata.fileID] toPath:[NSString stringWithFormat:@"%@/%@", appDelegate.directoryUser, metadata.fileNameView]];
                         
                         dispatch_after(dispatch_time(DISPATCH_TIME_NOW, timer * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
-                            [[CCNetworking sharedNetworking] uploadFile:metadata.fileNameView serverUrl:_serverUrl assetLocalIdentifier:nil session:k_upload_session taskStatus:k_taskStatusResume selector:@"" selectorPost:@"" errorCode:0 delegate:nil];
+                            [[CCNetworking sharedNetworking] uploadFile:metadata.fileNameView serverUrl:_serverUrl fileID:nil assetLocalIdentifier:nil session:k_upload_session taskStatus:k_taskStatusResume selector:@"" selectorPost:@"" errorCode:0 delegate:nil];
                         });
                         
                         timer += 0.1;

+ 7 - 5
iOSClient/Networking/CCNetworking.h

@@ -49,7 +49,7 @@
 
 // Sessions
 - (OCCommunication *)sharedOCCommunication;
-- (OCCommunication *)sharedOCCommunicationExtensionDownload:(NSString *)identifier;
+- (OCCommunication *)sharedOCCommunicationExtensionDownload;
 
 - (NSURLSession *)getSessionfromSessionDescription:(NSString *)sessionDescription;
 - (NSArray *)getUploadTasksExtensionSession;
@@ -62,8 +62,8 @@
 
 // Upload
 - (void)uploadFileFromAssetLocalIdentifier:(CCMetadataNet *)metadataNet delegate:(id)delegate;
-- (void)uploadFile:(NSString *)fileName serverUrl:(NSString *)serverUrl assetLocalIdentifier:(NSString *)assetLocalIdentifier session:(NSString *)session taskStatus:(NSInteger)taskStatus selector:(NSString *)selector selectorPost:(NSString *)selectorPost errorCode:(NSInteger)errorCode delegate:(id)delegate;
-- (void)uploadFileMetadata:(tableMetadata *)metadata taskStatus:(NSInteger)taskStatus;
+- (void)uploadFile:(NSString *)fileName serverUrl:(NSString *)serverUrl fileID:(NSString *)fileID assetLocalIdentifier:(NSString *)assetLocalIdentifier session:(NSString *)session taskStatus:(NSInteger)taskStatus selector:(NSString *)selector selectorPost:(NSString *)selectorPost errorCode:(NSInteger)errorCode delegate:(id)delegate;
+- (void)uploadFileMetadata:(tableMetadata *)metadata taskStatus:(NSInteger)taskStatus delegate:(id)delegate;
 
 // Utility
 
@@ -76,8 +76,10 @@
 
 @optional - (void)reloadDatasource:(NSString *)serverUrl;
 
-- (void)downloadFileSuccessFailure:(NSString *)fileName fileID:(NSString *)fileID serverUrl:(NSString *)serverUrl selector:(NSString *)selector selectorPost:(NSString *)selectorPost errorMessage:(NSString *)errorMessage errorCode:(NSInteger)errorCode;
-- (void)uploadFileSuccessFailure:(NSString *)fileName fileID:(NSString *)fileID assetLocalIdentifier:(NSString *)assetLocalIdentifier serverUrl:(NSString *)serverUrl selector:(NSString *)selector selectorPost:(NSString *)selectorPost errorMessage:(NSString *)errorMessage errorCode:(NSInteger)errorCode;
+@optional  - (void)downloadFileSuccessFailure:(NSString *)fileName fileID:(NSString *)fileID serverUrl:(NSString *)serverUrl selector:(NSString *)selector selectorPost:(NSString *)selectorPost errorMessage:(NSString *)errorMessage errorCode:(NSInteger)errorCode;
+
+@optional - (void)uploadStart:(NSString *)fileID task:(NSURLSessionUploadTask *)task serverUrl:(NSString *)serverUrl;
+@optional - (void)uploadFileSuccessFailure:(NSString *)fileName fileID:(NSString *)fileID assetLocalIdentifier:(NSString *)assetLocalIdentifier serverUrl:(NSString *)serverUrl selector:(NSString *)selector selectorPost:(NSString *)selectorPost errorMessage:(NSString *)errorMessage errorCode:(NSInteger)errorCode;
 
 @end
 

+ 25 - 12
iOSClient/Networking/CCNetworking.m

@@ -288,14 +288,13 @@
     return sharedOCCommunication;
 }
 
-- (OCCommunication *)sharedOCCommunicationExtensionDownload:(NSString *)identifier
+- (OCCommunication *)sharedOCCommunicationExtensionDownload
 {
     static OCCommunication *sharedOCCommunicationExtensionDownload = nil;
-    static NSString *extensionDownloadIdentifier = k_download_session_extension;
     
-    if (sharedOCCommunicationExtensionDownload == nil || [extensionDownloadIdentifier isEqualToString:identifier] == false)
+    if (sharedOCCommunicationExtensionDownload == nil)
     {
-        NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier];
+        NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:k_download_session_extension];
         config.sharedContainerIdentifier = [NCBrandOptions sharedInstance].capabilitiesGroups;
         config.HTTPMaximumConnectionsPerHost = 1;
         config.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
@@ -309,7 +308,6 @@
             return NSURLSessionAuthChallengePerformDefaultHandling;
         }];
         
-        extensionDownloadIdentifier = identifier;
         sharedOCCommunicationExtensionDownload = [[OCCommunication alloc] initWithUploadSessionManager:nil andDownloadSessionManager:sessionManager andNetworkSessionManager:nil];
     }
     
@@ -865,7 +863,7 @@
                 [delegate uploadFileSuccessFailure:metadataNet.fileName fileID:metadataNet.fileID assetLocalIdentifier:metadataNet.assetLocalIdentifier serverUrl:metadataNet.serverUrl selector:metadataNet.selector selectorPost:metadataNet.selectorPost errorMessage:[NSString stringWithFormat:@"Image request failed [%@]", error.description] errorCode:error.code];
             } else {
                 // OOOOOK
-                [self upload:metadataNet.fileName serverUrl:metadataNet.serverUrl assetLocalIdentifier:metadataNet.assetLocalIdentifier session:metadataNet.session taskStatus:metadataNet.taskStatus selector:metadataNet.selector selectorPost:metadataNet.selectorPost errorCode:metadataNet.errorCode delegate:delegate];
+                [self upload:metadataNet.fileName serverUrl:metadataNet.serverUrl fileID:nil assetLocalIdentifier:metadataNet.assetLocalIdentifier session:metadataNet.session taskStatus:metadataNet.taskStatus selector:metadataNet.selector selectorPost:metadataNet.selectorPost errorCode:metadataNet.errorCode delegate:delegate];
             }
         }];
     }
@@ -901,7 +899,7 @@
                 } else {
                     dispatch_async(dispatch_get_main_queue(), ^{
                         // OOOOOK
-                        [self upload:metadataNet.fileName serverUrl:metadataNet.serverUrl assetLocalIdentifier:metadataNet.assetLocalIdentifier session:metadataNet.session taskStatus:metadataNet.taskStatus selector:metadataNet.selector selectorPost:metadataNet.selectorPost errorCode:metadataNet.errorCode delegate:delegate];
+                        [self upload:metadataNet.fileName serverUrl:metadataNet.serverUrl fileID:nil assetLocalIdentifier:metadataNet.assetLocalIdentifier session:metadataNet.session taskStatus:metadataNet.taskStatus selector:metadataNet.selector selectorPost:metadataNet.selectorPost errorCode:metadataNet.errorCode delegate:delegate];
                     });
                 }
             }
@@ -909,18 +907,23 @@
     }
 }
 
-- (void)uploadFile:(NSString *)fileName serverUrl:(NSString *)serverUrl assetLocalIdentifier:(NSString *)assetLocalIdentifier session:(NSString *)session taskStatus:(NSInteger)taskStatus selector:(NSString *)selector selectorPost:(NSString *)selectorPost errorCode:(NSInteger)errorCode delegate:(id)delegate
+- (void)uploadFile:(NSString *)fileName serverUrl:(NSString *)serverUrl fileID:(NSString *)fileID assetLocalIdentifier:(NSString *)assetLocalIdentifier session:(NSString *)session taskStatus:(NSInteger)taskStatus selector:(NSString *)selector selectorPost:(NSString *)selectorPost errorCode:(NSInteger)errorCode delegate:(id)delegate
 {
-    [self upload:fileName serverUrl:serverUrl assetLocalIdentifier:assetLocalIdentifier session:session taskStatus:taskStatus selector:selector selectorPost:selectorPost errorCode:errorCode delegate:delegate];
+    [self upload:fileName serverUrl:serverUrl fileID:fileID assetLocalIdentifier:assetLocalIdentifier session:session taskStatus:taskStatus selector:selector selectorPost:selectorPost errorCode:errorCode delegate:delegate];
 }
 
-- (void)upload:(NSString *)fileName serverUrl:(NSString *)serverUrl assetLocalIdentifier:(NSString *)assetLocalIdentifier session:(NSString *)session taskStatus:(NSInteger)taskStatus selector:(NSString *)selector selectorPost:(NSString *)selectorPost errorCode:(NSInteger)errorCode delegate:(id)delegate
+- (void)upload:(NSString *)fileName serverUrl:(NSString *)serverUrl fileID:(NSString *)fileID assetLocalIdentifier:(NSString *)assetLocalIdentifier session:(NSString *)session taskStatus:(NSInteger)taskStatus selector:(NSString *)selector selectorPost:(NSString *)selectorPost errorCode:(NSInteger)errorCode delegate:(id)delegate
 {
     NSString *directoryID = [[NCManageDatabase sharedInstance] getDirectoryID:serverUrl];
     if (!directoryID) return;
     
     //fileID
-    NSString *uploadID =  [k_uploadSessionID stringByAppendingString:[CCUtility createRandomString:16]];
+    NSString *uploadID;
+    if (fileID == nil) {
+        uploadID = [k_uploadSessionID stringByAppendingString:[CCUtility createRandomString:16]];
+    } else {
+        uploadID = fileID;
+    }
     
     //add delegate
     if (delegate)
@@ -978,12 +981,16 @@
     }
 }
 
-- (void)uploadFileMetadata:(tableMetadata *)metadata taskStatus:(NSInteger)taskStatus
+- (void)uploadFileMetadata:(tableMetadata *)metadata taskStatus:(NSInteger)taskStatus delegate:(id)delegate
 {
     BOOL reSend = NO;
     NSString *serverUrl = [[NCManageDatabase sharedInstance] getServerUrl:metadata.directoryID];
     if (!serverUrl) return;
     
+    //add delegate
+    if (delegate)
+        [_delegates setObject:delegate forKey:metadata.fileID];
+    
     if ([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:@"%@/%@", _directoryUser, metadata.sessionID]]) {
             
         reSend = YES;
@@ -1135,6 +1142,12 @@
          }
     }
 
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if ([[self getDelegate:sessionID] respondsToSelector:@selector(uploadStart:task:serverUrl:)]) {
+            [[self getDelegate:sessionID] uploadStart:metadata.fileID task:uploadTask serverUrl:serverUrl];
+        }
+    });
+    
 #ifndef EXTENSION
     [(AppDelegate *)[[UIApplication sharedApplication] delegate] updateApplicationIconBadgeNumber];
 #endif

+ 18 - 0
iOSClient/Settings/CCAdvanced.m

@@ -119,6 +119,19 @@
     [row.cellConfig setObject:[UIFont systemFontOfSize:15.0]forKey:@"textLabel.font"];
     [section addFormRow:row];
     
+    // Section : Files App --------------------------------------------------------------
+    
+    section = [XLFormSectionDescriptor formSection];
+    [form addFormSection:section];
+    section.footerTitle = NSLocalizedString(@"_disable_files_app_footer_", nil);
+
+    // Disable Files App
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"disablefilesapp" rowType:XLFormRowDescriptorTypeBooleanSwitch title:NSLocalizedString(@"_disable_files_app_", nil)];
+    if ([CCUtility getDisableFilesApp]) row.value = @"1";
+    else row.value = @"0";
+    [row.cellConfig setObject:[UIFont systemFontOfSize:15.0]forKey:@"textLabel.font"];
+    [section addFormRow:row];
+    
     // Section CLEAR CACHE -------------------------------------------------
     
     section = [XLFormSectionDescriptor formSection];
@@ -212,6 +225,11 @@
         
         [CCUtility setFormatCompatibility:[[rowDescriptor.value valueData] boolValue]];
     }
+    
+    if ([rowDescriptor.tag isEqualToString:@"disablefilesapp"]) {
+        
+        [CCUtility setDisableFilesApp:[[rowDescriptor.value valueData] boolValue]];
+    }
 }
 
 #pragma --------------------------------------------------------------------------------------------

BIN
iOSClient/Supporting Files/cs-CZ.lproj/BKPasscodeView.strings


BIN
iOSClient/Supporting Files/cs-CZ.lproj/CTAssetsPicker.strings


BIN
iOSClient/Supporting Files/cs-CZ.lproj/Error.strings


BIN
iOSClient/Supporting Files/cs-CZ.lproj/InfoPlist.strings


BIN
iOSClient/Supporting Files/cs-CZ.lproj/Intro.strings


BIN
iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/cs-CZ.lproj/SwiftWebVC.strings


BIN
iOSClient/Supporting Files/de.lproj/BKPasscodeView.strings


BIN
iOSClient/Supporting Files/de.lproj/CTAssetsPicker.strings


BIN
iOSClient/Supporting Files/de.lproj/Error.strings


BIN
iOSClient/Supporting Files/de.lproj/InfoPlist.strings


BIN
iOSClient/Supporting Files/de.lproj/Intro.strings


BIN
iOSClient/Supporting Files/de.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/de.lproj/SwiftWebVC.strings


BIN
iOSClient/Supporting Files/en-GB.lproj/BKPasscodeView.strings


BIN
iOSClient/Supporting Files/en-GB.lproj/CTAssetsPicker.strings


BIN
iOSClient/Supporting Files/en-GB.lproj/Error.strings


BIN
iOSClient/Supporting Files/en-GB.lproj/InfoPlist.strings


BIN
iOSClient/Supporting Files/en-GB.lproj/Intro.strings


BIN
iOSClient/Supporting Files/en-GB.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/en-GB.lproj/SwiftWebVC.strings


BIN
iOSClient/Supporting Files/en.lproj/Error.strings


BIN
iOSClient/Supporting Files/es-419.lproj/CTAssetsPicker.strings


BIN
iOSClient/Supporting Files/es-419.lproj/Error.strings


BIN
iOSClient/Supporting Files/es-419.lproj/InfoPlist.strings


BIN
iOSClient/Supporting Files/es-419.lproj/Intro.strings


BIN
iOSClient/Supporting Files/es-419.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-419.lproj/SwiftWebVC.strings


BIN
iOSClient/Supporting Files/es-CL.lproj/BKPasscodeView.strings


BIN
iOSClient/Supporting Files/es-CL.lproj/CTAssetsPicker.strings


BIN
iOSClient/Supporting Files/es-CL.lproj/Error.strings


BIN
iOSClient/Supporting Files/es-CL.lproj/InfoPlist.strings


BIN
iOSClient/Supporting Files/es-CL.lproj/Intro.strings


BIN
iOSClient/Supporting Files/es-CL.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-CL.lproj/SwiftWebVC.strings


BIN
iOSClient/Supporting Files/es-CO.lproj/BKPasscodeView.strings


BIN
iOSClient/Supporting Files/es-CO.lproj/CTAssetsPicker.strings


BIN
iOSClient/Supporting Files/es-CO.lproj/Error.strings


BIN
iOSClient/Supporting Files/es-CO.lproj/InfoPlist.strings


BIN
iOSClient/Supporting Files/es-CO.lproj/Intro.strings


BIN
iOSClient/Supporting Files/es-CO.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-CO.lproj/SwiftWebVC.strings


BIN
iOSClient/Supporting Files/es-CR.lproj/BKPasscodeView.strings


BIN
iOSClient/Supporting Files/es-CR.lproj/CTAssetsPicker.strings


BIN
iOSClient/Supporting Files/es-CR.lproj/Error.strings


BIN
iOSClient/Supporting Files/es-CR.lproj/InfoPlist.strings


BIN
iOSClient/Supporting Files/es-CR.lproj/Intro.strings


BIN
iOSClient/Supporting Files/es-CR.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-CR.lproj/SwiftWebVC.strings


BIN
iOSClient/Supporting Files/es-DO.lproj/BKPasscodeView.strings


BIN
iOSClient/Supporting Files/es-DO.lproj/CTAssetsPicker.strings


BIN
iOSClient/Supporting Files/es-DO.lproj/Error.strings


BIN
iOSClient/Supporting Files/es-DO.lproj/InfoPlist.strings


BIN
iOSClient/Supporting Files/es-DO.lproj/Intro.strings


BIN
iOSClient/Supporting Files/es-DO.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-DO.lproj/SwiftWebVC.strings


BIN
iOSClient/Supporting Files/es-EC.lproj/BKPasscodeView.strings


BIN
iOSClient/Supporting Files/es-EC.lproj/CTAssetsPicker.strings


BIN
iOSClient/Supporting Files/es-EC.lproj/Error.strings


BIN
iOSClient/Supporting Files/es-EC.lproj/InfoPlist.strings


BIN
iOSClient/Supporting Files/es-EC.lproj/Intro.strings


BIN
iOSClient/Supporting Files/es-EC.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-EC.lproj/SwiftWebVC.strings


BIN
iOSClient/Supporting Files/es-GT.lproj/BKPasscodeView.strings


BIN
iOSClient/Supporting Files/es-GT.lproj/CTAssetsPicker.strings


BIN
iOSClient/Supporting Files/es-GT.lproj/Error.strings


BIN
iOSClient/Supporting Files/es-GT.lproj/InfoPlist.strings


BIN
iOSClient/Supporting Files/es-GT.lproj/Intro.strings


BIN
iOSClient/Supporting Files/es-GT.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-GT.lproj/SwiftWebVC.strings


BIN
iOSClient/Supporting Files/es-HN.lproj/BKPasscodeView.strings


Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä