Преглед изворни кода

Init START new Files Provider for iOS 13

marinofaggiana пре 5 година
родитељ
комит
bb7922be2b

+ 69 - 157
File Provider Extension/FileProviderData.swift

@@ -21,12 +21,12 @@
 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
 
-import FileProvider
-
-class FileProviderData: NSObject {
-    
-    var fileManager = FileManager()
-    
+class fileProviderData: NSObject {
+    @objc static let sharedInstance: fileProviderData = {
+        let instance = fileProviderData()
+        return instance
+    }()
+        
     var account = ""
     var accountUser = ""
     var accountUserID = ""
@@ -46,9 +46,6 @@ class FileProviderData: NSObject {
     // 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]()
@@ -60,100 +57,86 @@ class FileProviderData: NSObject {
     
     // MARK: - 
     
-    func setupActiveAccount() -> Bool {
+    func setupActiveAccount(domain: String?) -> Bool {
+        
+        var foundAccount: Bool = false
         
         if CCUtility.getDisableFilesApp() || NCBrandOptions.sharedInstance.disable_openin_file {
             return false
         }
         
-        guard let activeAccount = NCManageDatabase.sharedInstance.getAccountActive() else {
+        // NO DOMAIN -> Set default account
+        if domain == nil {
+            
+            guard let tableAccounts = NCManageDatabase.sharedInstance.getAccountActive() else {
+                return false
+            }
+            
+            account = tableAccounts.account
+            accountUser = tableAccounts.user
+            accountUserID = tableAccounts.userID
+            accountPassword = CCUtility.getPassword(tableAccounts.account)
+            accountUrl = tableAccounts.url
+            homeServerUrl = CCUtility.getHomeServerUrlActiveUrl(tableAccounts.url)
+    
+            return true
+        }
+        
+        let tableAccounts = NCManageDatabase.sharedInstance.getAllAccount()
+        if tableAccounts.count == 0 {
             return false
         }
         
-        if account == "" {
-            queueTradeSafe.sync(flags: .barrier) {
-                account = activeAccount.account
-                accountUser = activeAccount.user
-                accountUserID = activeAccount.userID
-                accountPassword = CCUtility.getPassword(activeAccount.account)
-                accountUrl = activeAccount.url
-                homeServerUrl = CCUtility.getHomeServerUrlActiveUrl(activeAccount.url)
+        for tableAccount in tableAccounts {
+            guard let url = NSURL(string: tableAccount.url) else {
+                continue
             }
-        } else if account != activeAccount.account {
-            assert(false, "change user")
-        }
+            guard let host = url.host else {
+                continue
+            }
+            let accountDomain = tableAccount.userID + " (" + host + ")"
+            if accountDomain == domain {
+                account = tableAccount.account
+                accountUser = tableAccount.user
+                accountUserID = tableAccount.userID
+                accountPassword = CCUtility.getPassword(tableAccount.account)
+                accountUrl = tableAccount.url
+                homeServerUrl = CCUtility.getHomeServerUrlActiveUrl(tableAccount.url)
                 
-        return true
-    }
-    
-    // MARK: -
-    
-    func getAccountFromItemIdentifier(_ itemIdentifier: NSFileProviderItemIdentifier) -> String? {
+                foundAccount = true
+            }
+        }
         
-        let fileID = itemIdentifier.rawValue
-        return NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "fileID == %@", fileID))?.account
+        return foundAccount
     }
     
-    func getTableMetadataFromItemIdentifier(_ itemIdentifier: NSFileProviderItemIdentifier) -> tableMetadata? {
+    func setupActiveAccount(itemIdentifier: NSFileProviderItemIdentifier) -> Bool {
         
-        let fileID = itemIdentifier.rawValue
-        return NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "fileID == %@", fileID))
-    }
+        var foundAccount: Bool = false
 
-    func getItemIdentifier(metadata: tableMetadata) -> NSFileProviderItemIdentifier {
-        
-        return NSFileProviderItemIdentifier(metadata.fileID)
-    }
-    
-    func createFileIdentifierOnFileSystem(metadata: tableMetadata) {
-        
-        let itemIdentifier = getItemIdentifier(metadata: metadata)
-        
-        if metadata.directory {
-            CCUtility.getDirectoryProviderStorageFileID(itemIdentifier.rawValue)
-        } else {
-            CCUtility.getDirectoryProviderStorageFileID(itemIdentifier.rawValue, fileNameView: metadata.fileNameView)
+        guard let accountFromItemIdentifier = fileProviderUtility.sharedInstance.getAccountFromItemIdentifier(itemIdentifier) else {
+            return false
         }
-    }
-    
-    func getParentItemIdentifier(metadata: tableMetadata) -> NSFileProviderItemIdentifier? {
         
-        if let directory = NCManageDatabase.sharedInstance.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, metadata.serverUrl))  {
-            if directory.serverUrl == homeServerUrl {
-                return NSFileProviderItemIdentifier(NSFileProviderItemIdentifier.rootContainer.rawValue)
-            } else {
-                // get the metadata.FileID of parent Directory
-                if let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "fileID == %@", directory.fileID))  {
-                    let identifier = getItemIdentifier(metadata: metadata)
-                    return identifier
-                }
-            }
+        let tableAccounts = NCManageDatabase.sharedInstance.getAllAccount()
+        if tableAccounts.count == 0 {
+            return false
         }
         
-        return nil
-    }
-    
-    func getTableDirectoryFromParentItemIdentifier(_ parentItemIdentifier: NSFileProviderItemIdentifier) -> tableDirectory? {
-        
-        var predicate: NSPredicate
-        
-        if parentItemIdentifier == .rootContainer {
-            
-            predicate = NSPredicate(format: "account == %@ AND serverUrl == %@", account, homeServerUrl)
-            
-        } else {
-            
-            guard let metadata = getTableMetadataFromItemIdentifier(parentItemIdentifier) else {
-                return nil
+        for tableAccount in tableAccounts {
+            if accountFromItemIdentifier == tableAccount.account {
+                account = tableAccount.account
+                accountUser = tableAccount.user
+                accountUserID = tableAccount.userID
+                accountPassword = CCUtility.getPassword(tableAccount.account)
+                accountUrl = tableAccount.url
+                homeServerUrl = CCUtility.getHomeServerUrlActiveUrl(tableAccount.url)
+                
+                foundAccount = true
             }
-            predicate = NSPredicate(format: "fileID == %@", metadata.fileID)
-        }
-        
-        guard let directory = NCManageDatabase.sharedInstance.getTableDirectory(predicate: predicate) else {
-            return nil
         }
         
-        return directory
+        return foundAccount
     }
     
     // MARK: -
@@ -172,14 +155,12 @@ class FileProviderData: NSObject {
                 guard let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "fileID == %@", identifier)) else {
                     continue
                 }
-                guard let parentItemIdentifier = getParentItemIdentifier(metadata: metadata) else {
+                guard let parentItemIdentifier = fileProviderUtility.sharedInstance.getParentItemIdentifier(metadata: metadata, homeServerUrl: homeServerUrl) else {
                     continue
                 }
                 
-                let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, providerData: self)
-                queueTradeSafe.sync(flags: .barrier) {
-                    fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
-                }
+                let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier)
+                fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
                 updateWorkingSet = true
             }
         }
@@ -193,10 +174,8 @@ class FileProviderData: NSObject {
                     continue
                 }
                 
-                let itemIdentifier = getItemIdentifier(metadata: metadata)
-                queueTradeSafe.sync(flags: .barrier) {
-                    fileProviderSignalDeleteWorkingSetItemIdentifier[itemIdentifier] = itemIdentifier
-                }
+                let itemIdentifier = fileProviderUtility.sharedInstance.getItemIdentifier(metadata: metadata)
+                fileProviderSignalDeleteWorkingSetItemIdentifier[itemIdentifier] = itemIdentifier
                 updateWorkingSet = true
             }
         }
@@ -223,71 +202,4 @@ class FileProviderData: NSObject {
             }
         }
     }
-    
-    // MARK: -
-    
-    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 atPath == toPath {
-            return nil
-        }
-                
-        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
-    }
-    
-    func fileExists(atPath: String) -> Bool {
-        return fileManager.fileExists(atPath: atPath)
-    }
 }

+ 65 - 83
File Provider Extension/FileProviderEnumerator.swift

@@ -27,19 +27,17 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
     
     var enumeratedItemIdentifier: NSFileProviderItemIdentifier
     var serverUrl: String?
-    var providerData: FileProviderData
     
-    init(enumeratedItemIdentifier: NSFileProviderItemIdentifier, providerData: FileProviderData) {
+    init(enumeratedItemIdentifier: NSFileProviderItemIdentifier) {
         
         self.enumeratedItemIdentifier = enumeratedItemIdentifier
-        self.providerData = providerData
         
         // Select ServerUrl
         if (enumeratedItemIdentifier == .rootContainer) {
-            serverUrl = providerData.homeServerUrl
+            serverUrl = fileProviderData.sharedInstance.homeServerUrl
         } else {
-                
-            let metadata = providerData.getTableMetadataFromItemIdentifier(enumeratedItemIdentifier)
+            
+            let metadata = fileProviderUtility.sharedInstance.getTableMetadataFromItemIdentifier(enumeratedItemIdentifier)
             if metadata != nil  {
                 if let directorySource = NCManageDatabase.sharedInstance.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata!.account, metadata!.serverUrl))  {
                     serverUrl = directorySource.serverUrl + "/" + metadata!.fileName
@@ -65,34 +63,34 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
             var itemIdentifierMetadata = [NSFileProviderItemIdentifier:tableMetadata]()
             
             // ***** Tags *****
-            let tags = NCManageDatabase.sharedInstance.getTags(predicate: NSPredicate(format: "account == %@", providerData.account))
+            let tags = NCManageDatabase.sharedInstance.getTags(predicate: NSPredicate(format: "account == %@", fileProviderData.sharedInstance.account))
             for tag in tags {
                 
                 guard let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "fileID == %@", tag.fileID))  else {
                     continue
                 }
                 
-                providerData.createFileIdentifierOnFileSystem(metadata: metadata)
-                    
-                itemIdentifierMetadata[providerData.getItemIdentifier(metadata: metadata)] = metadata
+                fileProviderUtility.sharedInstance.createFileIdentifierOnFileSystem(metadata: metadata)
+                
+                itemIdentifierMetadata[fileProviderUtility.sharedInstance.getItemIdentifier(metadata: metadata)] = metadata
             }
             
             // ***** Favorite *****
-            providerData.listFavoriteIdentifierRank = NCManageDatabase.sharedInstance.getTableMetadatasDirectoryFavoriteIdentifierRank(account: providerData.account)
-            for (identifier, _) in providerData.listFavoriteIdentifierRank {
-             
+            fileProviderData.sharedInstance.listFavoriteIdentifierRank = NCManageDatabase.sharedInstance.getTableMetadatasDirectoryFavoriteIdentifierRank(account: fileProviderData.sharedInstance.account)
+            for (identifier, _) in fileProviderData.sharedInstance.listFavoriteIdentifierRank {
+                
                 guard let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "fileID == %@", identifier)) else {
                     continue
                 }
-               
-                itemIdentifierMetadata[ providerData.getItemIdentifier(metadata: metadata)] = metadata
+                
+                itemIdentifierMetadata[fileProviderUtility.sharedInstance.getItemIdentifier(metadata: metadata)] = metadata
             }
             
             // create items
             for (_, metadata) in itemIdentifierMetadata {
-                let parentItemIdentifier = providerData.getParentItemIdentifier(metadata: metadata)
+                let parentItemIdentifier = fileProviderUtility.sharedInstance.getParentItemIdentifier(metadata: metadata, homeServerUrl: fileProviderData.sharedInstance.homeServerUrl)
                 if parentItemIdentifier != nil {
-                    let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier!, providerData: providerData)
+                    let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier!)
                     items.append(item)
                 }
             }
@@ -110,7 +108,7 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
             }
             
             // Select items from database
-            metadatasFromDB = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", providerData.account, serverUrl), sorted: "fileName", ascending: true)
+            metadatasFromDB = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", fileProviderData.sharedInstance.account, serverUrl), sorted: "fileName", ascending: true)
             
             // Calculate current page
             if (page != NSFileProviderPage.initialPageSortedByDate as NSFileProviderPage && page != NSFileProviderPage.initialPageSortedByName as NSFileProviderPage) {
@@ -118,10 +116,10 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
                 var numPage = Int(String(data: page.rawValue, encoding: .utf8)!)!
                 
                 if (metadatasFromDB != nil) {
-                    items = self.selectItems(numPage: numPage, account: providerData.account, metadatas: metadatasFromDB!)
+                    items = self.selectItems(numPage: numPage, account: fileProviderData.sharedInstance.account, metadatas: metadatasFromDB!)
                     observer.didEnumerate(items)
                 }
-                if (items.count == providerData.itemForPage) {
+                if (items.count == fileProviderData.sharedInstance.itemForPage) {
                     numPage += 1
                     let providerPage = NSFileProviderPage("\(numPage)".data(using: .utf8)!)
                     observer.finishEnumerating(upTo: providerPage)
@@ -132,41 +130,41 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
             }
             
             // Update the WorkingSet -> Favorite
-            providerData.updateFavoriteForWorkingSet()
+            fileProviderData.sharedInstance.updateFavoriteForWorkingSet()
             
-            // Read 
+            // Read
             var fileName: String?
-            var serverUrlForFileName = self.providerData.homeServerUrl
+            var serverUrlForFileName = fileProviderData.sharedInstance.homeServerUrl
             
-            if serverUrl != self.providerData.homeServerUrl {
+            if serverUrl != fileProviderData.sharedInstance.homeServerUrl {
                 fileName = (serverUrl as NSString).lastPathComponent
                 serverUrlForFileName = (serverUrl as NSString).deletingLastPathComponent
             }
             
-            OCNetworking.sharedManager().readFile(withAccount: providerData.account, serverUrl: serverUrlForFileName, fileName: fileName, completion: { (account, metadata, message, errorCode) in
-                
-                if errorCode == 0 && account == self.providerData.account {
+            OCNetworking.sharedManager().readFile(withAccount: fileProviderData.sharedInstance.account, serverUrl: serverUrlForFileName, fileName: fileName, completion: { (account, metadata, message, errorCode) in
+
+                if errorCode == 0 && account == fileProviderData.sharedInstance.account {
                     
-                    if self.providerData.listServerUrlEtag[serverUrl] == nil || self.providerData.listServerUrlEtag[serverUrl] != metadata!.etag || metadatasFromDB == nil {
+                    if fileProviderData.sharedInstance.listServerUrlEtag[serverUrl] == nil || fileProviderData.sharedInstance.listServerUrlEtag[serverUrl] != metadata!.etag || metadatasFromDB == nil {
                         
-                        OCNetworking.sharedManager().readFolder(withAccount: self.providerData.account, serverUrl: serverUrl, depth: "1", completion: { (account, metadatas, metadataFolder, message, errorCode) in
+                        OCNetworking.sharedManager().readFolder(withAccount: fileProviderData.sharedInstance.account, serverUrl: serverUrl, depth: "1", completion: { (account, metadatas, metadataFolder, message, errorCode) in
                             
-                            if errorCode == 0 && account == self.providerData.account {
+                            if errorCode == 0 && account == fileProviderData.sharedInstance.account {
                                 
                                 if metadataFolder != nil {
                                     // Update directory etag
-                                    NCManageDatabase.sharedInstance.setDirectory(serverUrl: serverUrl, serverUrlTo: nil, etag: metadataFolder!.etag, fileID: metadataFolder!.fileID, encrypted: metadataFolder!.e2eEncrypted, account: self.providerData.account)
+                                    NCManageDatabase.sharedInstance.setDirectory(serverUrl: serverUrl, serverUrlTo: nil, etag: metadataFolder!.etag, fileID: metadataFolder!.fileID, encrypted: metadataFolder!.e2eEncrypted, account: fileProviderData.sharedInstance.account)
                                     // Save etag for this serverUrl
-                                    self.providerData.listServerUrlEtag[serverUrl] = metadataFolder!.etag
+                                    fileProviderData.sharedInstance.listServerUrlEtag[serverUrl] = metadataFolder!.etag
                                 }
                                 
                                 if metadatas != nil {
                                     
-                                    NCManageDatabase.sharedInstance.deleteMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND (status == %d OR status == %d)", self.providerData.account, serverUrl, k_metadataStatusNormal, k_metadataStatusHide))
+                                    NCManageDatabase.sharedInstance.deleteMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND (status == %d OR status == %d)", fileProviderData.sharedInstance.account, serverUrl, k_metadataStatusNormal, k_metadataStatusHide))
                                     
-                                    NCManageDatabase.sharedInstance.setDateReadDirectory(serverUrl: serverUrl, account: self.providerData.account)
+                                    NCManageDatabase.sharedInstance.setDateReadDirectory(serverUrl: serverUrl, account: fileProviderData.sharedInstance.account)
                                     
-                                    let metadatasInDownload = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND (status == %d OR status == %d OR status == %d OR status == %d)", self.providerData.account, serverUrl, k_metadataStatusWaitDownload, k_metadataStatusInDownload, k_metadataStatusDownloading, k_metadataStatusDownloadError), sorted: nil, ascending: false)
+                                    let metadatasInDownload = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND (status == %d OR status == %d OR status == %d OR status == %d)", fileProviderData.sharedInstance.account, serverUrl, k_metadataStatusWaitDownload, k_metadataStatusInDownload, k_metadataStatusDownloading, k_metadataStatusDownloadError), sorted: nil, ascending: false)
                                     
                                     _ = NCManageDatabase.sharedInstance.addMetadatas(metadatas as! [tableMetadata])
                                     if metadatasInDownload != nil {
@@ -174,7 +172,7 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
                                     }
                                 }
                                 
-                                metadatasFromDB = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.providerData.account, serverUrl), sorted: "fileName", ascending: true)
+                                metadatasFromDB = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", fileProviderData.sharedInstance.account, serverUrl), sorted: "fileName", ascending: true)
                                 
                                 self.selectFirstPageItems(metadatasFromDB, observer: observer)
                                 
@@ -204,66 +202,50 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
         // Report the deleted items
         //
         if enumeratedItemIdentifier == .workingSet {
-            providerData.queueTradeSafe.sync() {
-                for (itemIdentifier, _) in providerData.fileProviderSignalDeleteWorkingSetItemIdentifier {
-                    itemsDelete.append(itemIdentifier)
-                }
-            }
-            providerData.queueTradeSafe.sync(flags: .barrier) {
-                providerData.fileProviderSignalDeleteWorkingSetItemIdentifier.removeAll()
+            for (itemIdentifier, _) in fileProviderData.sharedInstance.fileProviderSignalDeleteWorkingSetItemIdentifier {
+                itemsDelete.append(itemIdentifier)
             }
+            fileProviderData.sharedInstance.fileProviderSignalDeleteWorkingSetItemIdentifier.removeAll()
         } else {
-            providerData.queueTradeSafe.sync() {
-                for (itemIdentifier, _) in providerData.fileProviderSignalDeleteContainerItemIdentifier {
-                    itemsDelete.append(itemIdentifier)
-                }
-            }
-            providerData.queueTradeSafe.sync(flags: .barrier) {
-                providerData.fileProviderSignalDeleteContainerItemIdentifier.removeAll()
+            for (itemIdentifier, _) in fileProviderData.sharedInstance.fileProviderSignalDeleteContainerItemIdentifier {
+                itemsDelete.append(itemIdentifier)
             }
+            fileProviderData.sharedInstance.fileProviderSignalDeleteContainerItemIdentifier.removeAll()
         }
             
         // Report the updated items
         //
         if enumeratedItemIdentifier == .workingSet {
-            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)
-                    }
+            for (itemIdentifier, item) in fileProviderData.sharedInstance.fileProviderSignalUpdateWorkingSetItem {
+                let account = fileProviderUtility.sharedInstance.getAccountFromItemIdentifier(itemIdentifier)
+                if account != nil && account == fileProviderData.sharedInstance.account {
+                    itemsUpdate.append(item)
+                } else {
+                    itemsDelete.append(itemIdentifier)
                 }
             }
-            providerData.queueTradeSafe.sync(flags: .barrier) {
-                providerData.fileProviderSignalUpdateWorkingSetItem.removeAll()
-            }
+            fileProviderData.sharedInstance.fileProviderSignalUpdateWorkingSetItem.removeAll()
         } else {
-            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)
-                    }
+            for (itemIdentifier, item) in fileProviderData.sharedInstance.fileProviderSignalUpdateContainerItem {
+                let account = fileProviderUtility.sharedInstance.getAccountFromItemIdentifier(itemIdentifier)
+                if account != nil && account == fileProviderData.sharedInstance.account {
+                    itemsUpdate.append(item)
+                } else {
+                    itemsDelete.append(itemIdentifier)
                 }
             }
-            providerData.queueTradeSafe.sync(flags: .barrier) {
-                providerData.fileProviderSignalUpdateContainerItem.removeAll()
-            }
+            fileProviderData.sharedInstance.fileProviderSignalUpdateContainerItem.removeAll()
         }
-            
+        
         observer.didDeleteItems(withIdentifiers: itemsDelete)
         observer.didUpdate(itemsUpdate)
-            
-        let data = "\(providerData.currentAnchor)".data(using: .utf8)
+        
+        let data = "\(fileProviderData.sharedInstance.currentAnchor)".data(using: .utf8)
         observer.finishEnumeratingChanges(upTo: NSFileProviderSyncAnchor(data!), moreComing: false)
     }
     
     func currentSyncAnchor(completionHandler: @escaping (NSFileProviderSyncAnchor?) -> Void) {
-        let data = "\(providerData.currentAnchor)".data(using: .utf8)
+        let data = "\(fileProviderData.sharedInstance.currentAnchor)".data(using: .utf8)
         completionHandler(NSFileProviderSyncAnchor(data!))
     }
     
@@ -276,10 +258,10 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
         var items: [NSFileProviderItemProtocol] = []
         
         if (metadatas != nil) {
-            items = self.selectItems(numPage: 0, account: self.providerData.account, metadatas: metadatas!)
+            items = self.selectItems(numPage: 0, account: fileProviderData.sharedInstance.account, metadatas: metadatas!)
             observer.didEnumerate(items)
         }
-        if (items.count == self.providerData.itemForPage) {
+        if (items.count == fileProviderData.sharedInstance.itemForPage) {
             let providerPage = NSFileProviderPage("1".data(using: .utf8)!)
             observer.finishEnumerating(upTo: providerPage)
         } else {
@@ -290,8 +272,8 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
     func selectItems(numPage: Int, account: String, metadatas: [tableMetadata]) -> [NSFileProviderItemProtocol] {
         
         var items: [NSFileProviderItemProtocol] = []
-        let start = numPage * providerData.itemForPage + 1
-        let stop = start + (providerData.itemForPage - 1)
+        let start = numPage * fileProviderData.sharedInstance.itemForPage + 1
+        let stop = start + (fileProviderData.sharedInstance.itemForPage - 1)
         var counter = 0
         
         autoreleasepool {
@@ -306,11 +288,11 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
                 counter += 1
                 if (counter >= start && counter <= stop) {
                     
-                    providerData.createFileIdentifierOnFileSystem(metadata: metadata)
+                    fileProviderUtility.sharedInstance.createFileIdentifierOnFileSystem(metadata: metadata)
                     
-                    let parentItemIdentifier = providerData.getParentItemIdentifier(metadata: metadata)
+                    let parentItemIdentifier = fileProviderUtility.sharedInstance.getParentItemIdentifier(metadata: metadata, homeServerUrl: fileProviderData.sharedInstance.homeServerUrl)
                     if parentItemIdentifier != nil {
-                        let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier!, providerData: providerData)
+                        let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier!)
                         items.append(item)
                     }
                 }

+ 59 - 112
File Provider Extension/FileProviderExtension+Actions.swift

@@ -27,22 +27,16 @@ extension FileProviderExtension {
 
     override func createDirectory(withName directoryName: String, inParentItemIdentifier parentItemIdentifier: NSFileProviderItemIdentifier, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) {
         
-        // Check account
-        if providerData.setupActiveAccount() == false {
-            completionHandler(nil, NSFileProviderError(.notAuthenticated))
-            return
-        }
-        
-        guard let tableDirectory = providerData.getTableDirectoryFromParentItemIdentifier(parentItemIdentifier) else {
+        guard let tableDirectory = fileProviderUtility.sharedInstance.getTableDirectoryFromParentItemIdentifier(parentItemIdentifier, account: fileProviderData.sharedInstance.account, homeServerUrl: fileProviderData.sharedInstance.homeServerUrl) else {
             completionHandler(nil, NSFileProviderError(.noSuchItem))
             return
         }
         
         let serverUrl = tableDirectory.serverUrl
         
-        OCNetworking.sharedManager().createFolder(withAccount: providerData.account, serverUrl: serverUrl, fileName: directoryName, completion: { (account, fileID, date, message, errorCode) in
+        OCNetworking.sharedManager().createFolder(withAccount: fileProviderData.sharedInstance.account, serverUrl: serverUrl, fileName: directoryName, completion: { (account, fileID, date, message, errorCode) in
             
-            if errorCode == 0 && account == self.providerData.account {
+            if errorCode == 0 && account == fileProviderData.sharedInstance.account {
                 
                 let metadata = tableMetadata()
                 
@@ -66,17 +60,13 @@ extension FileProviderExtension {
                     return
                 }
                 
-                let parentItemIdentifier = self.providerData.getParentItemIdentifier(metadata: metadataDB)
+                let parentItemIdentifier = fileProviderUtility.sharedInstance.getParentItemIdentifier(metadata: metadataDB, homeServerUrl: fileProviderData.sharedInstance.homeServerUrl)
                 if parentItemIdentifier != nil {
                     
-                    let item = FileProviderItem(metadata: metadataDB, parentItemIdentifier: parentItemIdentifier!, providerData: self.providerData)
-                    
-                    self.providerData.queueTradeSafe.sync(flags: .barrier) {
-                        self.providerData.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
-                        self.providerData.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
-                    }
-                    
-                    self.providerData.signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
+                    let item = FileProviderItem(metadata: metadataDB, parentItemIdentifier: parentItemIdentifier!)
+                    fileProviderData.sharedInstance.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
+                    fileProviderData.sharedInstance.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
+                    fileProviderData.sharedInstance.signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
                     
                     completionHandler(item, nil)
                     
@@ -91,18 +81,12 @@ extension FileProviderExtension {
     
     override func deleteItem(withIdentifier itemIdentifier: NSFileProviderItemIdentifier, completionHandler: @escaping (Error?) -> Void) {
         
-        // Check account
-        if providerData.setupActiveAccount() == false {
-            completionHandler(NSFileProviderError(.notAuthenticated))
-            return
-        }
-        
-        guard let metadata = self.providerData.getTableMetadataFromItemIdentifier(itemIdentifier) else {
+        guard let metadata = fileProviderUtility.sharedInstance.getTableMetadataFromItemIdentifier(itemIdentifier) else {
             completionHandler(NSFileProviderError(.noSuchItem))
             return
         }
             
-        guard let parentItemIdentifier = self.providerData.getParentItemIdentifier(metadata: metadata) else {
+        guard let parentItemIdentifier = fileProviderUtility.sharedInstance.getParentItemIdentifier(metadata: metadata, homeServerUrl: fileProviderData.sharedInstance.homeServerUrl) else {
             completionHandler( NSFileProviderError(.noSuchItem))
             return
         }
@@ -110,30 +94,21 @@ extension FileProviderExtension {
         deleteFile(withIdentifier: itemIdentifier, parentItemIdentifier: parentItemIdentifier, metadata: metadata)
        
         // return immediately
-        providerData.queueTradeSafe.sync(flags: .barrier) {
-            providerData.fileProviderSignalDeleteContainerItemIdentifier[itemIdentifier] = itemIdentifier
-            providerData.fileProviderSignalDeleteWorkingSetItemIdentifier[itemIdentifier] = itemIdentifier
-        }
-
-        self.providerData.signalEnumerator(for: [parentItemIdentifier, .workingSet])
+        fileProviderData.sharedInstance.fileProviderSignalDeleteContainerItemIdentifier[itemIdentifier] = itemIdentifier
+        fileProviderData.sharedInstance.fileProviderSignalDeleteWorkingSetItemIdentifier[itemIdentifier] = itemIdentifier
+        fileProviderData.sharedInstance.signalEnumerator(for: [parentItemIdentifier, .workingSet])
 
         completionHandler(nil)
     }
     
     override func reparentItem(withIdentifier itemIdentifier: NSFileProviderItemIdentifier, toParentItemWithIdentifier parentItemIdentifier: NSFileProviderItemIdentifier, newName: String?, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) {
         
-        // Check account
-        if providerData.setupActiveAccount() == false {
-            completionHandler(nil, NSFileProviderError(.notAuthenticated))
-            return
-        }
-        
         guard let itemFrom = try? item(for: itemIdentifier) else {
             completionHandler(nil, NSFileProviderError(.noSuchItem))
             return
         }
         
-        guard let metadataFrom = providerData.getTableMetadataFromItemIdentifier(itemIdentifier) else {
+        guard let metadataFrom = fileProviderUtility.sharedInstance.getTableMetadataFromItemIdentifier(itemIdentifier) else {
             completionHandler(nil, NSFileProviderError(.noSuchItem))
             return
         }
@@ -142,16 +117,16 @@ extension FileProviderExtension {
         let serverUrlFrom = metadataFrom.serverUrl
         let fileNameFrom = serverUrlFrom + "/" + itemFrom.filename
         
-        guard let tableDirectoryTo = providerData.getTableDirectoryFromParentItemIdentifier(parentItemIdentifier) else {
+        guard let tableDirectoryTo = fileProviderUtility.sharedInstance.getTableDirectoryFromParentItemIdentifier(parentItemIdentifier, account: fileProviderData.sharedInstance.account, homeServerUrl: fileProviderData.sharedInstance.homeServerUrl) else {
             completionHandler(nil, NSFileProviderError(.noSuchItem))
             return
         }
         let serverUrlTo = tableDirectoryTo.serverUrl
         let fileNameTo = serverUrlTo + "/" + itemFrom.filename
         
-        OCNetworking.sharedManager().moveFileOrFolder(withAccount:  providerData.account, fileName: fileNameFrom, fileNameTo: fileNameTo, completion: { (account, message, errorCode) in
+        OCNetworking.sharedManager().moveFileOrFolder(withAccount:  metadataFrom.account, fileName: fileNameFrom, fileNameTo: fileNameTo, completion: { (account, message, errorCode) in
             
-            if errorCode == 0 && account == self.providerData.account {
+            if errorCode == 0 && account == metadataFrom.account {
                 
                 if metadataFrom.directory {
                     NCManageDatabase.sharedInstance.deleteDirectoryAndSubDirectory(serverUrl: serverUrlFrom, account: account!)
@@ -165,14 +140,10 @@ extension FileProviderExtension {
                     return
                 }
                 
-                let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, providerData: self.providerData)
-                
-                self.providerData.queueTradeSafe.sync(flags: .barrier) {
-                    self.providerData.fileProviderSignalUpdateContainerItem[itemIdentifier] = item
-                    self.providerData.fileProviderSignalUpdateWorkingSetItem[itemIdentifier] = item
-                }
-                
-                self.providerData.signalEnumerator(for: [parentItemIdentifier, .workingSet])
+                let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier)
+                fileProviderData.sharedInstance.fileProviderSignalUpdateContainerItem[itemIdentifier] = item
+                fileProviderData.sharedInstance.fileProviderSignalUpdateWorkingSetItem[itemIdentifier] = item
+                fileProviderData.sharedInstance.signalEnumerator(for: [parentItemIdentifier, .workingSet])
                 
                 completionHandler(item, nil)
                 
@@ -184,18 +155,12 @@ extension FileProviderExtension {
     
     override func renameItem(withIdentifier itemIdentifier: NSFileProviderItemIdentifier, toName itemName: String, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) {
         
-        // Check account
-        if providerData.setupActiveAccount() == false {
-            completionHandler(nil, NSFileProviderError(.notAuthenticated))
-            return
-        }
-        
-        guard let metadata = providerData.getTableMetadataFromItemIdentifier(itemIdentifier) else {
+        guard let metadata = fileProviderUtility.sharedInstance.getTableMetadataFromItemIdentifier(itemIdentifier) else {
             completionHandler(nil, NSFileProviderError(.noSuchItem))
             return
         }
         
-        guard let directoryTable = NCManageDatabase.sharedInstance.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", providerData.account, metadata.serverUrl)) else {
+        guard let directoryTable = NCManageDatabase.sharedInstance.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, metadata.serverUrl)) else {
             completionHandler(nil, NSFileProviderError(.noSuchItem))
             return
         }
@@ -204,9 +169,9 @@ extension FileProviderExtension {
         let fileNamePathFrom = metadata.serverUrl + "/" + fileNameFrom
         let fileNamePathTo = metadata.serverUrl + "/" + itemName
         
-        OCNetworking.sharedManager().moveFileOrFolder(withAccount: providerData.account, fileName: fileNamePathFrom, fileNameTo: fileNamePathTo, completion: { (account, message, errorCode) in
+        OCNetworking.sharedManager().moveFileOrFolder(withAccount: metadata.account, fileName: fileNamePathFrom, fileNameTo: fileNamePathTo, completion: { (account, message, errorCode) in
             
-            if errorCode == 0 && account == self.providerData.account {
+            if errorCode == 0 && account == metadata.account {
                 
                 // Rename metadata
                 guard let metadata = NCManageDatabase.sharedInstance.renameMetadata(fileNameTo: itemName, fileID: metadata.fileID) else {
@@ -220,28 +185,24 @@ extension FileProviderExtension {
                     
                 } else {
                     
-                    let itemIdentifier = self.providerData.getItemIdentifier(metadata: metadata)
+                    let itemIdentifier = fileProviderUtility.sharedInstance.getItemIdentifier(metadata: metadata)
                     
                     // rename file
-                    _ = self.providerData.moveFile(CCUtility.getDirectoryProviderStorageFileID(itemIdentifier.rawValue, fileNameView: fileNameFrom), toPath: CCUtility.getDirectoryProviderStorageFileID(itemIdentifier.rawValue, fileNameView: itemName))
-                    _ = self.providerData.moveFile(CCUtility.getDirectoryProviderStorageIconFileID(itemIdentifier.rawValue, fileNameView: fileNameFrom), toPath: CCUtility.getDirectoryProviderStorageIconFileID(itemIdentifier.rawValue, fileNameView: itemName))
+                    _ = fileProviderUtility.sharedInstance.moveFile(CCUtility.getDirectoryProviderStorageFileID(itemIdentifier.rawValue, fileNameView: fileNameFrom), toPath: CCUtility.getDirectoryProviderStorageFileID(itemIdentifier.rawValue, fileNameView: itemName))
+                    _ = fileProviderUtility.sharedInstance.moveFile(CCUtility.getDirectoryProviderStorageIconFileID(itemIdentifier.rawValue, fileNameView: fileNameFrom), toPath: CCUtility.getDirectoryProviderStorageIconFileID(itemIdentifier.rawValue, fileNameView: itemName))
                     
                     NCManageDatabase.sharedInstance.setLocalFile(fileID: metadata.fileID, date: nil, exifDate: nil, exifLatitude: nil, exifLongitude: nil, fileName: itemName, etag: nil)
                 }
                 
-                guard let parentItemIdentifier = self.providerData.getParentItemIdentifier(metadata: metadata) else {
+                guard let parentItemIdentifier = fileProviderUtility.sharedInstance.getParentItemIdentifier(metadata: metadata, homeServerUrl: fileProviderData.sharedInstance.homeServerUrl) else {
                     completionHandler(nil, NSFileProviderError(.noSuchItem))
                     return
                 }
                 
-                let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, providerData: self.providerData)
-                
-                self.providerData.queueTradeSafe.sync(flags: .barrier) {
-                    self.providerData.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
-                    self.providerData.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
-                }
-                
-                self.providerData.signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
+                let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier)
+                fileProviderData.sharedInstance.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
+                fileProviderData.sharedInstance.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
+                fileProviderData.sharedInstance.signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
                 
                 completionHandler(item, nil)
             } else {
@@ -252,41 +213,31 @@ extension FileProviderExtension {
     
     override func setFavoriteRank(_ favoriteRank: NSNumber?, forItemIdentifier itemIdentifier: NSFileProviderItemIdentifier, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) {
         
-        // Check account
-        if providerData.setupActiveAccount() == false {
-            completionHandler(nil, NSFileProviderError(.notAuthenticated))
-            return
-        }
-        
-        guard let metadata = providerData.getTableMetadataFromItemIdentifier(itemIdentifier) else {
+        guard let metadata = fileProviderUtility.sharedInstance.getTableMetadataFromItemIdentifier(itemIdentifier) else {
             completionHandler(nil, NSFileProviderError(.noSuchItem))
             return
         }
         
-        guard let parentItemIdentifier = providerData.getParentItemIdentifier(metadata: metadata) else {
+        guard let parentItemIdentifier = fileProviderUtility.sharedInstance.getParentItemIdentifier(metadata: metadata, homeServerUrl: fileProviderData.sharedInstance.homeServerUrl) else {
             completionHandler(nil, NSFileProviderError(.noSuchItem))
             return
         }
         
         var favorite = false
         if favoriteRank == nil {
-            providerData.listFavoriteIdentifierRank.removeValue(forKey: itemIdentifier.rawValue)
+            fileProviderData.sharedInstance.listFavoriteIdentifierRank.removeValue(forKey: itemIdentifier.rawValue)
         } else {
-            let rank = providerData.listFavoriteIdentifierRank[itemIdentifier.rawValue]
+            let rank = fileProviderData.sharedInstance.listFavoriteIdentifierRank[itemIdentifier.rawValue]
             if rank == nil {
-                providerData.listFavoriteIdentifierRank[itemIdentifier.rawValue] = favoriteRank
+                fileProviderData.sharedInstance.listFavoriteIdentifierRank[itemIdentifier.rawValue] = favoriteRank
             }
             favorite = true
         }
         
-        let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, providerData: providerData)
-        
-        providerData.queueTradeSafe.sync(flags: .barrier) {
-            providerData.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
-            providerData.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
-        }
-
-        providerData.signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
+        let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier)
+        fileProviderData.sharedInstance.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
+        fileProviderData.sharedInstance.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
+        fileProviderData.sharedInstance.signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
 
         completionHandler(item, nil)
         
@@ -297,44 +248,40 @@ extension FileProviderExtension {
     
     override func setTagData(_ tagData: Data?, forItemIdentifier itemIdentifier: NSFileProviderItemIdentifier, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) {
         
-        guard let metadata = providerData.getTableMetadataFromItemIdentifier(itemIdentifier) else {
+        guard let metadata = fileProviderUtility.sharedInstance.getTableMetadataFromItemIdentifier(itemIdentifier) else {
             completionHandler(nil, NSFileProviderError(.noSuchItem))
             return
         }
         
         // Add, Remove (nil)
-        NCManageDatabase.sharedInstance.addTag(metadata.fileID, tagIOS: tagData, account: providerData.account)
+        NCManageDatabase.sharedInstance.addTag(metadata.fileID, tagIOS: tagData, account: metadata.account)
         
-        guard let parentItemIdentifier = providerData.getParentItemIdentifier(metadata: metadata) else {
+        guard let parentItemIdentifier = fileProviderUtility.sharedInstance.getParentItemIdentifier(metadata: metadata, homeServerUrl: fileProviderData.sharedInstance.homeServerUrl) else {
             completionHandler(nil, NSFileProviderError(.noSuchItem))
             return
         }
         
-        let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, providerData: providerData)
-        
-        providerData.queueTradeSafe.sync(flags: .barrier) {
-            providerData.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
-            providerData.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
-        }
-        
-        providerData.signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
+        let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier)
+        fileProviderData.sharedInstance.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
+        fileProviderData.sharedInstance.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
+        fileProviderData.sharedInstance.signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
         
         completionHandler(item, nil)
     }
     
     override func setLastUsedDate(_ lastUsedDate: Date?, forItemIdentifier itemIdentifier: NSFileProviderItemIdentifier, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) {
         
-        guard let metadata = providerData.getTableMetadataFromItemIdentifier(itemIdentifier) else {
+        guard let metadata = fileProviderUtility.sharedInstance.getTableMetadataFromItemIdentifier(itemIdentifier) else {
             completionHandler(nil, NSFileProviderError(.noSuchItem))
             return
         }
         
-        guard let parentItemIdentifier = providerData.getParentItemIdentifier(metadata: metadata) else {
+        guard let parentItemIdentifier = fileProviderUtility.sharedInstance.getParentItemIdentifier(metadata: metadata, homeServerUrl: fileProviderData.sharedInstance.homeServerUrl) else {
             completionHandler(nil, NSFileProviderError(.noSuchItem))
             return
         }
         
-        let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, providerData: providerData)
+        let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier)
         item.lastUsedDate = lastUsedDate
 
         completionHandler(item, nil)
@@ -350,7 +297,7 @@ extension FileProviderExtension {
                 let metadata = tableMetadata()
                 var error: NSError?
             
-                guard let tableDirectory = self.providerData.getTableDirectoryFromParentItemIdentifier(parentItemIdentifier) else {
+                guard let tableDirectory = fileProviderUtility.sharedInstance.getTableDirectoryFromParentItemIdentifier(parentItemIdentifier, account: fileProviderData.sharedInstance.account, homeServerUrl: fileProviderData.sharedInstance.homeServerUrl) else {
                     completionHandler(nil, NSFileProviderError(.noSuchItem))
                     return
                 }
@@ -364,7 +311,7 @@ extension FileProviderExtension {
             
                 // typefile directory ? (NOT PERMITTED)
                 do {
-                    let attributes = try self.providerData.fileManager.attributesOfItem(atPath: fileURL.path)
+                    let attributes = try fileProviderUtility.sharedInstance.fileManager.attributesOfItem(atPath: fileURL.path)
                     size = attributes[FileAttributeKey.size] as! Double
                     let typeFile = attributes[FileAttributeKey.type] as! FileAttributeType
                     if typeFile == FileAttributeType.typeDirectory {
@@ -376,11 +323,11 @@ extension FileProviderExtension {
                     return
                 }
             
-                let fileName = NCUtility.sharedInstance.createFileName(fileURL.lastPathComponent, serverUrl: tableDirectory.serverUrl, account: self.providerData.account)
-                let fileID = CCUtility.createMetadataID(fromAccount: self.providerData.account, serverUrl: tableDirectory.serverUrl, fileNameView: fileName, directory: false)!
+                let fileName = NCUtility.sharedInstance.createFileName(fileURL.lastPathComponent, serverUrl: tableDirectory.serverUrl, account: fileProviderData.sharedInstance.account)
+                let fileID = CCUtility.createMetadataID(fromAccount: fileProviderData.sharedInstance.account, serverUrl: tableDirectory.serverUrl, fileNameView: fileName, directory: false)!
             
                 self.fileCoordinator.coordinate(readingItemAt: fileURL, options: .withoutChanges, error: &error) { (url) in
-                    _ = self.providerData.moveFile(url.path, toPath: CCUtility.getDirectoryProviderStorageFileID(fileID, fileNameView: fileName))
+                    _ = fileProviderUtility.sharedInstance.moveFile(url.path, toPath: CCUtility.getDirectoryProviderStorageFileID(fileID, fileNameView: fileName))
                 }
             
                 fileURL.stopAccessingSecurityScopedResource()
@@ -388,7 +335,7 @@ extension FileProviderExtension {
                 // ---------------------------------------------------------------------------------
             
                 // Metadata TEMP
-                metadata.account = self.providerData.account
+                metadata.account = fileProviderData.sharedInstance.account
                 metadata.date = NSDate()
                 metadata.directory = false
                 metadata.etag = ""
@@ -413,7 +360,7 @@ extension FileProviderExtension {
                     return
                 }
                             
-                let item = FileProviderItem(metadata: metadataDB, parentItemIdentifier: parentItemIdentifier, providerData: self.providerData)
+                let item = FileProviderItem(metadata: metadataDB, parentItemIdentifier: parentItemIdentifier)
             
                 completionHandler(item, nil)
 

+ 34 - 49
File Provider Extension/FileProviderExtension+Network.swift

@@ -33,7 +33,7 @@ extension FileProviderExtension {
         
         let path = metadata.serverUrl + "/" + metadata.fileName
 
-        OCNetworking.sharedManager().deleteFileOrFolder(withAccount: providerData.account, path: path, completion: { (account, message, errorCode) in
+        OCNetworking.sharedManager().deleteFileOrFolder(withAccount: fileProviderData.sharedInstance.account, path: path, completion: { (account, message, errorCode) in
             if errorCode == 0 || errorCode == kOCErrorServerPathNotFound {
                 self.deleteFileSystem(for: metadata, serverUrl: metadata.serverUrl, itemIdentifier: itemIdentifier)
             }
@@ -44,14 +44,14 @@ extension FileProviderExtension {
         
         let fileNamePath = CCUtility.getDirectoryProviderStorageFileID(itemIdentifier.rawValue)!
         do {
-            try self.providerData.fileManager.removeItem(atPath: fileNamePath)
+            try fileProviderUtility.sharedInstance.fileManager.removeItem(atPath: fileNamePath)
         } catch let error {
             print("error: \(error)")
         }
         
         if metadata.directory {
             let dirForDelete = CCUtility.stringAppendServerUrl(serverUrl, addFileName: metadata.fileName)
-            NCManageDatabase.sharedInstance.deleteDirectoryAndSubDirectory(serverUrl: dirForDelete!, account: providerData.account)
+            NCManageDatabase.sharedInstance.deleteDirectoryAndSubDirectory(serverUrl: dirForDelete!, account: fileProviderData.sharedInstance.account)
         }
         
         NCManageDatabase.sharedInstance.deleteMetadata(predicate: NSPredicate(format: "fileID == %@", metadata.fileID))
@@ -64,25 +64,21 @@ extension FileProviderExtension {
     
     func settingFavorite(_ favorite: Bool, withIdentifier itemIdentifier: NSFileProviderItemIdentifier, parentItemIdentifier: NSFileProviderItemIdentifier, metadata: tableMetadata) {
         
-        let fileNamePath = CCUtility.returnFileNamePath(fromFileName: metadata.fileName, serverUrl: metadata.serverUrl, activeUrl: self.providerData.accountUrl)
+        let fileNamePath = CCUtility.returnFileNamePath(fromFileName: metadata.fileName, serverUrl: metadata.serverUrl, activeUrl: fileProviderData.sharedInstance.accountUrl)
 
-        OCNetworking.sharedManager().settingFavorite(withAccount: providerData.account, fileName: fileNamePath, favorite: favorite, completion: { (account, message, errorCode) in
-            if errorCode == 0 && account == self.providerData.account {
+        OCNetworking.sharedManager().settingFavorite(withAccount: metadata.account, fileName: fileNamePath, favorite: favorite, completion: { (account, message, errorCode) in
+            if errorCode == 0 && account == metadata.account {
                 // Change DB
                 metadata.favorite = favorite
                 _ = NCManageDatabase.sharedInstance.addMetadata(metadata)
             } else {
                 // Errore, remove from listFavoriteIdentifierRank
-                self.providerData.listFavoriteIdentifierRank.removeValue(forKey: itemIdentifier.rawValue)
+                fileProviderData.sharedInstance.listFavoriteIdentifierRank.removeValue(forKey: itemIdentifier.rawValue)
                 
-                let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, providerData: self.providerData)
-                
-                self.providerData.queueTradeSafe.sync(flags: .barrier) {
-                    self.providerData.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
-                    self.providerData.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
-                }
-                
-                self.providerData.signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
+                let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier)
+                fileProviderData.sharedInstance.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
+                fileProviderData.sharedInstance.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
+                fileProviderData.sharedInstance.signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
             }
         })
     }
@@ -102,21 +98,18 @@ extension FileProviderExtension {
             return
         }
         
-        guard let parentItemIdentifier = providerData.getParentItemIdentifier(metadata: metadata) else {
+        guard let parentItemIdentifier = fileProviderUtility.sharedInstance.getParentItemIdentifier(metadata: metadata, homeServerUrl: fileProviderData.sharedInstance.homeServerUrl) else {
             return
         }
         
-        let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, providerData: providerData)
+        let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier)
 
         // Register for bytesSent
         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.providerData.signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
+        fileProviderData.sharedInstance.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
+        fileProviderData.sharedInstance.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
+        fileProviderData.sharedInstance.signalEnumerator(for: [item.parentItemIdentifier, .workingSet])
     }
     
     func uploadFileSuccessFailure(_ fileName: String!, fileID: String!, assetLocalIdentifier: String!, serverUrl: String!, selector: String!, errorMessage: String!, errorCode: Int) {
@@ -125,7 +118,7 @@ extension FileProviderExtension {
             return
         }
         
-        guard let parentItemIdentifier = providerData.getParentItemIdentifier(metadata: metadata) else {
+        guard let parentItemIdentifier = fileProviderUtility.sharedInstance.getParentItemIdentifier(metadata: metadata, homeServerUrl: fileProviderData.sharedInstance.homeServerUrl) else {
             return
         }
         
@@ -133,11 +126,9 @@ extension FileProviderExtension {
         if errorCode == 0 {
             
             // Remove temp fileID
-            providerData.queueTradeSafe.sync(flags: .barrier) {
-                let itemIdentifier = NSFileProviderItemIdentifier(CCUtility.createMetadataID(fromAccount: metadata.account, serverUrl: metadata.serverUrl, fileNameView: metadata.fileNameView, directory: false))
-                self.providerData.fileProviderSignalDeleteContainerItemIdentifier[itemIdentifier] = itemIdentifier
-                self.providerData.fileProviderSignalDeleteWorkingSetItemIdentifier[itemIdentifier] = itemIdentifier
-            }
+            let itemIdentifier = NSFileProviderItemIdentifier(CCUtility.createMetadataID(fromAccount: metadata.account, serverUrl: metadata.serverUrl, fileNameView: metadata.fileNameView, directory: false))
+            fileProviderData.sharedInstance.fileProviderSignalDeleteContainerItemIdentifier[itemIdentifier] = itemIdentifier
+            fileProviderData.sharedInstance.fileProviderSignalDeleteWorkingSetItemIdentifier[itemIdentifier] = itemIdentifier
             
             // Recreate ico
             CCGraphics.createNewImage(from: fileName, fileID: fileID, extension: NSString(string: fileName).pathExtension, filterGrayScale: false, typeFile: metadata.typeFile, writeImage: true)
@@ -147,12 +138,9 @@ extension FileProviderExtension {
             metadata.sessionSelector = ""
             let metadata = NCManageDatabase.sharedInstance.addMetadata(metadata)
             
-            let item = FileProviderItem(metadata: metadata!, parentItemIdentifier: parentItemIdentifier, providerData: providerData)
-
-            providerData.queueTradeSafe.sync(flags: .barrier) {
-                self.providerData.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
-                self.providerData.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
-            }
+            let item = FileProviderItem(metadata: metadata!, parentItemIdentifier: parentItemIdentifier)
+            fileProviderData.sharedInstance.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
+            fileProviderData.sharedInstance.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
             
             uploadFileImportDocument()
             
@@ -163,24 +151,21 @@ extension FileProviderExtension {
             metadata.status = Int(k_metadataStatusUploadError)
             let metadata = NCManageDatabase.sharedInstance.addMetadata(metadata)
             
-            let item = FileProviderItem(metadata: metadata!, parentItemIdentifier: parentItemIdentifier, providerData: providerData)
-            
-            providerData.queueTradeSafe.sync(flags: .barrier) {
-                providerData.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
-                providerData.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
-            }
+            let item = FileProviderItem(metadata: metadata!, parentItemIdentifier: parentItemIdentifier)
+            fileProviderData.sharedInstance.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item
+            fileProviderData.sharedInstance.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item
         }
         
-        self.providerData.signalEnumerator(for: [parentItemIdentifier, .workingSet])
+        fileProviderData.sharedInstance.signalEnumerator(for: [parentItemIdentifier, .workingSet])
     }
     
     func uploadFileImportDocument() {
         
-        let tableMetadatas = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND session == %@ AND (status == %d OR status == %d)", providerData.account, k_upload_session_extension, k_metadataStatusInUpload, k_metadataStatusUploading), sorted: "fileName", ascending: true)
+        let tableMetadatas = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND session == %@ AND (status == %d OR status == %d)", fileProviderData.sharedInstance.account, k_upload_session_extension, k_metadataStatusInUpload, k_metadataStatusUploading), sorted: "fileName", ascending: true)
         
         if (tableMetadatas == nil || (tableMetadatas!.count < Int(k_maxConcurrentOperation))) {
             
-            guard let metadataForUpload = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "account == %@ AND session == %@ AND status == %d", providerData.account, k_upload_session_extension, k_metadataStatusWaitUpload)) else {
+            guard let metadataForUpload = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "account == %@ AND session == %@ AND status == %d", fileProviderData.sharedInstance.account, k_upload_session_extension, k_metadataStatusWaitUpload)) else {
                 return
             }
             
@@ -194,15 +179,15 @@ extension FileProviderExtension {
         var itemIdentifierForUpload = itemIdentifier
         
         // Is itemIdentifier = fileName [Apple Works and ... ?]
-        if itemIdentifier.rawValue.contains(fileName) && providerData.fileExists(atPath: CCUtility.getDirectoryProviderStorage()+"/"+itemIdentifier.rawValue) {
-            guard let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "account == %@ AND fileID == %@ AND fileName == %@", providerData.account, itemIdentifier.rawValue, fileName)) else {
+        if itemIdentifier.rawValue.contains(fileName) && fileProviderUtility.sharedInstance.fileExists(atPath: CCUtility.getDirectoryProviderStorage()+"/"+itemIdentifier.rawValue) {
+            guard let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "account == %@ AND fileID == %@ AND fileName == %@", fileProviderData.sharedInstance.account, itemIdentifier.rawValue, fileName)) else {
                 return
             }
-            itemIdentifierForUpload = providerData.getItemIdentifier(metadata: metadata)
-            _ = providerData.moveFile(CCUtility.getDirectoryProviderStorage()+"/"+itemIdentifier.rawValue, toPath: CCUtility.getDirectoryProviderStorage()+"/"+itemIdentifierForUpload.rawValue)
+            itemIdentifierForUpload = fileProviderUtility.sharedInstance.getItemIdentifier(metadata: metadata)
+            _ = fileProviderUtility.sharedInstance.moveFile(CCUtility.getDirectoryProviderStorage()+"/"+itemIdentifier.rawValue, toPath: CCUtility.getDirectoryProviderStorage()+"/"+itemIdentifierForUpload.rawValue)
         }
         
-        guard let metadata = providerData.getTableMetadataFromItemIdentifier(itemIdentifierForUpload) else {
+        guard let metadata = fileProviderUtility.sharedInstance.getTableMetadataFromItemIdentifier(itemIdentifierForUpload) else {
             return
         }
         

+ 3 - 9
File Provider Extension/FileProviderExtension+Thumbnail.swift

@@ -30,15 +30,9 @@ extension FileProviderExtension {
         let progress = Progress(totalUnitCount: Int64(itemIdentifiers.count))
         var counterProgress: Int64 = 0
         
-        // Check account
-        if providerData.setupActiveAccount() == false {
-            completionHandler(NSFileProviderError(.notAuthenticated))
-            return Progress(totalUnitCount:0)
-        }
-        
         for itemIdentifier in itemIdentifiers {
             
-            guard let metadata = providerData.getTableMetadataFromItemIdentifier(itemIdentifier) else {
+            guard let metadata = fileProviderUtility.sharedInstance.getTableMetadataFromItemIdentifier(itemIdentifier) else {
                 
                 counterProgress += 1
                 if (counterProgress == progress.totalUnitCount) {
@@ -53,9 +47,9 @@ extension FileProviderExtension {
                 let width = NCUtility.sharedInstance.getScreenWidthForPreview()
                 let height = NCUtility.sharedInstance.getScreenHeightForPreview()
                 
-                OCNetworking.sharedManager().downloadPreview(withAccount: providerData.account, metadata: metadata, withWidth: width, andHeight: height, completion: { (account, preview, message, errorCode) in
+                OCNetworking.sharedManager().downloadPreview(withAccount: metadata.account, metadata: metadata, withWidth: width, andHeight: height, completion: { (account, preview, message, errorCode) in
                    
-                    if errorCode == 0 && account == self.providerData.account {
+                    if errorCode == 0 && account == metadata.account {
                         do {
                             let url = URL.init(fileURLWithPath: CCUtility.getDirectoryProviderStorageIconFileID(metadata.fileID, fileNameView: metadata.fileNameView))
                             let data = try Data.init(contentsOf: url)

+ 48 - 38
File Provider Extension/FileProviderExtension.swift

@@ -50,8 +50,6 @@ import FileProvider
 
 class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
     
-    var providerData = FileProviderData()
-
     var outstandingDownloadTasks = [URL: URLSessionTask]()
     
     lazy var fileCoordinator: NSFileCoordinator = {
@@ -68,9 +66,6 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
         // Create directory File Provider Storage
         CCUtility.getDirectoryProviderStorage()
         
-        // Setup account
-        _ = providerData.setupActiveAccount()
-        
         // Upload Imnport Document
         self.uploadFileImportDocument()
     }
@@ -83,15 +78,37 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
         
         // Check account
         if (containerItemIdentifier != NSFileProviderItemIdentifier.workingSet) {
-            if providerData.setupActiveAccount() == false {
+            
+#if targetEnvironment(simulator)
+            
+            if #available(iOS 13, *) {
+                if containerItemIdentifier == NSFileProviderItemIdentifier.rootContainer && self.domain?.identifier.rawValue == nil {
+                    throw NSError(domain: NSFileProviderErrorDomain, code: NSFileProviderError.notAuthenticated.rawValue, userInfo:[:])
+                } else if self.domain?.identifier.rawValue != nil {
+                    if fileProviderData.sharedInstance.setupActiveAccount(domain: self.domain?.identifier.rawValue) == false {
+                        throw NSError(domain: NSFileProviderErrorDomain, code: NSFileProviderError.notAuthenticated.rawValue, userInfo:[:])
+                    }
+                } else {
+                    if fileProviderData.sharedInstance.setupActiveAccount(itemIdentifier: containerItemIdentifier) == false {
+                        throw NSError(domain: NSFileProviderErrorDomain, code: NSFileProviderError.notAuthenticated.rawValue, userInfo:[:])
+                    }
+                }
+            } else {
+                if fileProviderData.sharedInstance.setupActiveAccount(domain: nil) == false {
+                    throw NSError(domain: NSFileProviderErrorDomain, code: NSFileProviderError.notAuthenticated.rawValue, userInfo:[:])
+                }
+            }
+#else
+            if fileProviderData.sharedInstance.setupActiveAccount(domain: nil) == false {
                 throw NSError(domain: NSFileProviderErrorDomain, code: NSFileProviderError.notAuthenticated.rawValue, userInfo:[:])
             }
+#endif            
         }
 
         if (containerItemIdentifier == NSFileProviderItemIdentifier.rootContainer) {
-            maybeEnumerator = FileProviderEnumerator(enumeratedItemIdentifier: containerItemIdentifier, providerData: providerData)
+            maybeEnumerator = FileProviderEnumerator(enumeratedItemIdentifier: containerItemIdentifier)
         } else if (containerItemIdentifier == NSFileProviderItemIdentifier.workingSet) {
-            maybeEnumerator = FileProviderEnumerator(enumeratedItemIdentifier: containerItemIdentifier, providerData: providerData)
+            maybeEnumerator = FileProviderEnumerator(enumeratedItemIdentifier: containerItemIdentifier)
         } else {
             // determine if the item is a directory or a file
             // - for a directory, instantiate an enumerator of its subitems
@@ -99,16 +116,16 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
             let item = try self.item(for: containerItemIdentifier)
             
             if item.typeIdentifier == kUTTypeFolder as String {
-                maybeEnumerator = FileProviderEnumerator(enumeratedItemIdentifier: containerItemIdentifier, providerData: providerData)
+                maybeEnumerator = FileProviderEnumerator(enumeratedItemIdentifier: containerItemIdentifier)
             } else {
-                maybeEnumerator = FileProviderEnumerator(enumeratedItemIdentifier: containerItemIdentifier, providerData: providerData)
+                maybeEnumerator = FileProviderEnumerator(enumeratedItemIdentifier: containerItemIdentifier)
             }
         }
         
         guard let enumerator = maybeEnumerator else {
             throw NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError, userInfo:[:])
         }
-       
+        
         return enumerator
     }
     
@@ -119,30 +136,30 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
         if identifier == .rootContainer {
             
             let metadata = tableMetadata()
-                    
-            metadata.account = providerData.account
+            
+            metadata.account = fileProviderData.sharedInstance.account
             metadata.directory = true
             metadata.fileID = NSFileProviderItemIdentifier.rootContainer.rawValue
             metadata.fileName = ""
             metadata.fileNameView = ""
-            metadata.serverUrl = providerData.homeServerUrl
+            metadata.serverUrl = fileProviderData.sharedInstance.homeServerUrl
             metadata.typeFile = k_metadataTypeFile_directory
             
-            return FileProviderItem(metadata: metadata, parentItemIdentifier: NSFileProviderItemIdentifier(NSFileProviderItemIdentifier.rootContainer.rawValue), providerData: providerData)
+            return FileProviderItem(metadata: metadata, parentItemIdentifier: NSFileProviderItemIdentifier(NSFileProviderItemIdentifier.rootContainer.rawValue))
             
         } else {
             
-            guard let metadata = providerData.getTableMetadataFromItemIdentifier(identifier) else {
+            guard let metadata = fileProviderUtility.sharedInstance.getTableMetadataFromItemIdentifier(identifier) else {
                 throw NSFileProviderError(.noSuchItem)
             }
             
-            guard let parentItemIdentifier = providerData.getParentItemIdentifier(metadata: metadata) else {
+            guard let parentItemIdentifier = fileProviderUtility.sharedInstance.getParentItemIdentifier(metadata: metadata, homeServerUrl: fileProviderData.sharedInstance.homeServerUrl) else {
                 throw NSFileProviderError(.noSuchItem)
             }
             
-            let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, providerData: providerData)
+            let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier)
             return item
-        }        
+        }
     }
     
     override func urlForItem(withPersistentIdentifier identifier: NSFileProviderItemIdentifier) -> URL? {
@@ -151,18 +168,18 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
         guard let item = try? item(for: identifier) else {
             return nil
         }
-            
+        
         // in this implementation, all paths are structured as <base storage directory>/<item identifier>/<item file name>
-            
+        
         let manager = NSFileProviderManager.default
         var url = manager.documentStorageURL.appendingPathComponent(identifier.rawValue, isDirectory: true)
-            
+        
         if item.typeIdentifier == (kUTTypeFolder as String) {
             url = url.appendingPathComponent(item.filename, isDirectory:true)
         } else {
             url = url.appendingPathComponent(item.filename, isDirectory:false)
         }
-            
+        
         return url
     }
     
@@ -182,12 +199,12 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
     // MARK: -
     
     override func providePlaceholder(at url: URL, completionHandler: @escaping (Error?) -> Void) {
-
+        
         guard let identifier = persistentIdentifierForItem(at: url) else {
             completionHandler(NSFileProviderError(.noSuchItem))
             return
         }
-
+        
         do {
             let fileProviderItem = try item(for: identifier)
             let placeholderURL = NSFileProviderManager.placeholderURL(for: url)
@@ -204,13 +221,7 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
         let pathComponents = url.pathComponents
         let identifier = NSFileProviderItemIdentifier(pathComponents[pathComponents.count - 2])
             
-        // Check account
-        if providerData.setupActiveAccount() == false {
-            completionHandler(NSFileProviderError(.notAuthenticated))
-            return
-        }
-            
-        guard let metadata = providerData.getTableMetadataFromItemIdentifier(identifier) else {
+        guard let metadata = fileProviderUtility.sharedInstance.getTableMetadataFromItemIdentifier(identifier) else {
             completionHandler(NSFileProviderError(.noSuchItem))
             return
         }
@@ -221,7 +232,7 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
             if metadata.session == k_upload_session_extension {
                 self.reUpload(metadata)
             }
-                
+            
             completionHandler(nil)
             return
         }
@@ -238,10 +249,10 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
             return
         }
         
-        let task = OCNetworking.sharedManager().download(withAccount: providerData.account, fileNameServerUrl: metadata.serverUrl + "/" + metadata.fileName, fileNameLocalPath: url.path, encode:true, communication: OCNetworking.sharedManager()?.sharedOCCommunicationExtensionDownload(), completion: { (account, lenght, etag, date, message, errorCode) in
+        let task = OCNetworking.sharedManager().download(withAccount: metadata.account, fileNameServerUrl: metadata.serverUrl + "/" + metadata.fileName, fileNameLocalPath: url.path, encode: true, communication: OCNetworking.sharedManager()?.sharedOCCommunicationExtensionDownload(), completion: { (account, lenght, etag, date, message, errorCode) in
             
-            if errorCode == 0 && account == self.providerData.account {
-                
+            if errorCode == 0 && account == metadata.account {
+
                 // remove Task
                 self.outstandingDownloadTasks.removeValue(forKey: url)
                 
@@ -255,7 +266,6 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
                 _ = NCManageDatabase.sharedInstance.addMetadata(metadata)
                 
                 completionHandler(nil)
-                return
                 
             } else {
                 
@@ -303,7 +313,7 @@ class FileProviderExtension: NSFileProviderExtension, CCNetworkingDelegate {
         if !fileHasLocalChanges {
             // remove the existing file to free up space
             do {
-                _ = try providerData.fileManager.removeItem(at: url)
+                _ = try fileProviderUtility.sharedInstance.fileManager.removeItem(at: url)
             } catch let error {
                 print("error: \(error)")
             }

+ 13 - 17
File Provider Extension/FileProviderItem.swift

@@ -75,10 +75,10 @@ class FileProviderItem: NSObject, NSFileProviderItem {
     var isDownload = false
     var isUpload = false
 
-    init(metadata: tableMetadata, parentItemIdentifier: NSFileProviderItemIdentifier, providerData: FileProviderData) {
+    init(metadata: tableMetadata, parentItemIdentifier: NSFileProviderItemIdentifier) {
         
         self.parentItemIdentifier = parentItemIdentifier
-        self.itemIdentifier = providerData.getItemIdentifier(metadata: metadata)
+        self.itemIdentifier = fileProviderUtility.sharedInstance.getItemIdentifier(metadata: metadata)
                 
         self.contentModificationDate = metadata.date as Date
         self.creationDate = metadata.date as Date
@@ -91,26 +91,22 @@ class FileProviderItem: NSObject, NSFileProviderItem {
         // This is a file
         if (!metadata.directory) {
             
-            let fileIdentifier =  CCUtility.getDirectoryProviderStorageFileID(self.itemIdentifier.rawValue, fileNameView: metadata.fileNameView)!
-            var fileSize = 0 as Double
-         
-            do {
-                let attributes = try FileManager.default.attributesOfItem(atPath: fileIdentifier)
-                fileSize = attributes[FileAttributeKey.size] as! Double
-            } catch let error {
-                print("error: \(error)")
-            }
-            
-            // Download
-            if fileSize == 0 {
+            self.documentSize = NSNumber(value: metadata.size)
+           
+            let tableLocalFile = NCManageDatabase.sharedInstance.getTableLocalFile(predicate: NSPredicate(format: "fileID == %@", metadata.fileID))
+            if tableLocalFile == nil {
                 self.isDownloaded = false
                 self.isMostRecentVersionDownloaded = false
             } else {
-                self.documentSize = NSNumber(value:fileSize)
                 self.isDownloaded = true
                 self.isMostRecentVersionDownloaded = true
             }
             
+            // Download
+            if (metadata.session == k_download_session_extension && metadata.status != k_metadataStatusDownloadError) {
+                self.isDownloading = true
+            }
+            
             // Upload
             if (metadata.session == k_upload_session_extension && metadata.status != k_metadataStatusUploadError) {
                 isUpload = true
@@ -128,11 +124,11 @@ class FileProviderItem: NSObject, NSFileProviderItem {
         } else {
             
             // Favorite directory
-            let rank = providerData.listFavoriteIdentifierRank[metadata.fileID]
+            let rank = fileProviderData.sharedInstance.listFavoriteIdentifierRank[metadata.fileID]
             if (rank == nil) {
                 favoriteRank = nil
             } else {
-                favoriteRank = providerData.listFavoriteIdentifierRank[metadata.fileID]
+                favoriteRank = fileProviderData.sharedInstance.listFavoriteIdentifierRank[metadata.fileID]
             }
         }
         

+ 166 - 0
File Provider Extension/FileProviderUtility.swift

@@ -0,0 +1,166 @@
+//
+//  FileProviderData.swift
+//  Files
+//
+//  Created by Marino Faggiana on 27/05/18.
+//  Copyright © 2018 Marino Faggiana. All rights reserved.
+//
+//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+class fileProviderUtility: NSObject {
+    @objc static let sharedInstance: fileProviderUtility = {
+        let instance = fileProviderUtility()
+        return instance
+    }()
+    
+    var fileManager = FileManager()
+    
+    func getAccountFromItemIdentifier(_ itemIdentifier: NSFileProviderItemIdentifier) -> String? {
+        
+        let fileID = itemIdentifier.rawValue
+        return NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "fileID == %@", fileID))?.account
+    }
+    
+    func getTableMetadataFromItemIdentifier(_ itemIdentifier: NSFileProviderItemIdentifier) -> tableMetadata? {
+        
+        let fileID = itemIdentifier.rawValue
+        return NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "fileID == %@", fileID))
+    }
+
+    func getItemIdentifier(metadata: tableMetadata) -> NSFileProviderItemIdentifier {
+        
+        return NSFileProviderItemIdentifier(metadata.fileID)
+    }
+    
+    func createFileIdentifierOnFileSystem(metadata: tableMetadata) {
+        
+        let itemIdentifier = getItemIdentifier(metadata: metadata)
+        
+        if metadata.directory {
+            CCUtility.getDirectoryProviderStorageFileID(itemIdentifier.rawValue)
+        } else {
+            CCUtility.getDirectoryProviderStorageFileID(itemIdentifier.rawValue, fileNameView: metadata.fileNameView)
+        }
+    }
+    
+    func getParentItemIdentifier(metadata: tableMetadata, homeServerUrl: String) -> NSFileProviderItemIdentifier? {
+        
+        if let directory = NCManageDatabase.sharedInstance.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, metadata.serverUrl))  {
+            if directory.serverUrl == homeServerUrl {
+                return NSFileProviderItemIdentifier(NSFileProviderItemIdentifier.rootContainer.rawValue)
+            } else {
+                // get the metadata.FileID of parent Directory
+                if let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "fileID == %@", directory.fileID))  {
+                    let identifier = getItemIdentifier(metadata: metadata)
+                    return identifier
+                }
+            }
+        }
+        
+        return nil
+    }
+    
+    func getTableDirectoryFromParentItemIdentifier(_ parentItemIdentifier: NSFileProviderItemIdentifier, account: String, homeServerUrl: String) -> tableDirectory? {
+        
+        var predicate: NSPredicate
+        
+        if parentItemIdentifier == .rootContainer {
+            
+            predicate = NSPredicate(format: "account == %@ AND serverUrl == %@", account, homeServerUrl)
+            
+        } else {
+            
+            guard let metadata = getTableMetadataFromItemIdentifier(parentItemIdentifier) else {
+                return nil
+            }
+            predicate = NSPredicate(format: "fileID == %@", metadata.fileID)
+        }
+        
+        guard let directory = NCManageDatabase.sharedInstance.getTableDirectory(predicate: predicate) else {
+            return nil
+        }
+        
+        return directory
+    }
+    
+    // MARK: -
+    
+    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 atPath == toPath {
+            return nil
+        }
+                
+        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
+    }
+    
+    func fileExists(atPath: String) -> Bool {
+        return fileManager.fileExists(atPath: atPath)
+    }
+}

+ 4 - 0
Nextcloud.xcodeproj/project.pbxproj

@@ -321,6 +321,7 @@
 		F7632FC1218353AA00721B71 /* NCTrashSectionFooter.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7632FC0218353AA00721B71 /* NCTrashSectionFooter.xib */; };
 		F76673ED22C901F6007ED366 /* FileProviderDomain.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76673EC22C901F5007ED366 /* FileProviderDomain.swift */; };
 		F76673EE22C901F6007ED366 /* FileProviderDomain.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76673EC22C901F5007ED366 /* FileProviderDomain.swift */; };
+		F76673F022C90434007ED366 /* FileProviderUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76673EF22C90433007ED366 /* FileProviderUtility.swift */; };
 		F76B3CCE1EAE01BD00921AC9 /* NCBrand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76B3CCD1EAE01BD00921AC9 /* NCBrand.swift */; };
 		F76B3CCF1EAE01BD00921AC9 /* NCBrand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76B3CCD1EAE01BD00921AC9 /* NCBrand.swift */; };
 		F76C6F8E21943C8C0063591B /* NCActionSheetHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76C6F8D21943C8C0063591B /* NCActionSheetHeader.swift */; };
@@ -1099,6 +1100,7 @@
 		F76344751BF259A800188725 /* synchronized.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = synchronized.gif; sourceTree = "<group>"; };
 		F76344761BF259A800188725 /* synchronizedcrypto.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = synchronizedcrypto.gif; sourceTree = "<group>"; };
 		F76673EC22C901F5007ED366 /* FileProviderDomain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileProviderDomain.swift; sourceTree = "<group>"; };
+		F76673EF22C90433007ED366 /* FileProviderUtility.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileProviderUtility.swift; sourceTree = "<group>"; };
 		F768EAFB1BFB7CD800B6E341 /* CCShareOC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCShareOC.h; sourceTree = "<group>"; };
 		F768EAFC1BFB7CD800B6E341 /* CCShareOC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCShareOC.m; sourceTree = "<group>"; };
 		F768EB021BFB7EA900B6E341 /* CCShare.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = CCShare.storyboard; sourceTree = "<group>"; };
@@ -2279,6 +2281,7 @@
 				F771E3F620E239B400AFB62D /* FileProviderExtension+Network.swift */,
 				F771E3F520E239B400AFB62D /* FileProviderExtension+Thumbnail.swift */,
 				F771E3D420E2392D00AFB62D /* FileProviderItem.swift */,
+				F76673EF22C90433007ED366 /* FileProviderUtility.swift */,
 				F7434B5F20E2440600417916 /* FileProviderExtension-Bridging-Header.h */,
 			);
 			path = "File Provider Extension";
@@ -3527,6 +3530,7 @@
 				F7434B5920E241B600417916 /* OCNetworking.m in Sources */,
 				F7434B5520E240A900417916 /* UtilsFramework.m in Sources */,
 				F7434B4120E2405200417916 /* OCRichObjectStrings.m in Sources */,
+				F76673F022C90434007ED366 /* FileProviderUtility.swift in Sources */,
 				F7434B3420E23FD700417916 /* NCDatabase.swift in Sources */,
 				F7434B4020E2404E00417916 /* OCNotificationsAction.m in Sources */,
 				F7434B5320E2409E00417916 /* OCXMLSharedParser.m in Sources */,