Pārlūkot izejas kodu

Merge pull request #2080 from nextcloud/441Fix

441 fix
Marino Faggiana 2 gadi atpakaļ
vecāks
revīzija
3582f4e513

+ 2 - 2
Nextcloud.xcodeproj/project.pbxproj

@@ -3277,8 +3277,8 @@
 			isa = XCRemoteSwiftPackageReference;
 			repositoryURL = "https://github.com/nextcloud/ios-communication-library/";
 			requirement = {
-				branch = develop;
-				kind = branch;
+				kind = exactVersion;
+				version = 0.99.7;
 			};
 		};
 		F788ECC5263AAAF900ADC67F /* XCRemoteSwiftPackageReference "MarkdownKit" */ = {

+ 2 - 2
Share/NCShareExtension+Files.swift

@@ -36,9 +36,9 @@ extension NCShareExtension {
             groupByField = "classFile"
         }
 
-        let metadatasSource = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND directory == true", activeAccount.account, serverUrl))
+        let metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND directory == true", activeAccount.account, serverUrl))
         self.dataSource = NCDataSource(
-            metadatasSource: metadatasSource,
+            metadatas: metadatas,
             account: activeAccount.account,
             sort: layoutForView?.sort,
             ascending: layoutForView?.ascending,

+ 0 - 1
iOSClient/AppDelegate.swift

@@ -55,7 +55,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
     var listFilesVC: [String: NCFiles] = [:]
     var listFavoriteVC: [String: NCFavorite] = [:]
     var listOfflineVC: [String: NCOffline] = [:]
-    var listProgress: [String: NCGlobal.progressType] = [:]
 
     var disableSharesView: Bool = false
     var documentPickerViewController: NCDocumentPickerViewController?

+ 33 - 22
iOSClient/Data/NCDataSource.swift

@@ -26,7 +26,7 @@ import NCCommunication
 
 class NCDataSource: NSObject {
 
-    public var metadatasSource: [tableMetadata] = []
+    public var metadatas: [tableMetadata] = []
     public var metadatasForSection: [NCMetadataForSection] = []
 
     public var directory: tableDirectory?
@@ -48,10 +48,10 @@ class NCDataSource: NSObject {
         super.init()
     }
 
-    init(metadatasSource: [tableMetadata], account: String, directory: tableDirectory? = nil, sort: String? = "none", ascending: Bool? = false, directoryOnTop: Bool? = true, favoriteOnTop: Bool? = true, filterLivePhoto: Bool? = true, groupByField: String = "name", providers: [NCCSearchProvider]? = nil, searchResults: [NCCSearchResult]? = nil) {
+    init(metadatas: [tableMetadata], account: String, directory: tableDirectory? = nil, sort: String? = "none", ascending: Bool? = false, directoryOnTop: Bool? = true, favoriteOnTop: Bool? = true, filterLivePhoto: Bool? = true, groupByField: String = "name", providers: [NCCSearchProvider]? = nil, searchResults: [NCCSearchResult]? = nil) {
         super.init()
 
-        self.metadatasSource = metadatasSource
+        self.metadatas = metadatas
         self.directory = directory
         self.shares = NCManageDatabase.shared.getTableShares(account: account)
         self.localFiles = NCManageDatabase.shared.getTableLocalFile(account: account)
@@ -72,7 +72,7 @@ class NCDataSource: NSObject {
 
     func clearDataSource() {
 
-        self.metadatasSource.removeAll()
+        self.metadatas.removeAll()
         self.metadatasForSection.removeAll()
         self.directory = nil
         self.sectionsValue.removeAll()
@@ -89,7 +89,7 @@ class NCDataSource: NSObject {
 
     func addSection(metadatas: [tableMetadata], searchResult: NCCSearchResult?) {
 
-        self.metadatasSource.append(contentsOf: metadatas)
+        self.metadatas.append(contentsOf: metadatas)
 
         if let searchResult = searchResult {
             self.searchResults?.append(searchResult)
@@ -101,7 +101,7 @@ class NCDataSource: NSObject {
     internal func createSections() {
 
         // get all Section
-        for metadata in metadatasSource {
+        for metadata in self.metadatas {
             // skipped livePhoto
             if filterLivePhoto && metadata.livePhoto && metadata.ext == "mov" {
                 continue
@@ -163,7 +163,7 @@ class NCDataSource: NSObject {
         if let providers = self.providers, !providers.isEmpty, let searchResults = self.searchResults {
             searchResult = searchResults.filter({ $0.name == sectionValue}).first
         }
-        let metadatas = metadatasSource.filter({ getSectionValue(metadata: $0) == sectionValue})
+        let metadatas = self.metadatas.filter({ getSectionValue(metadata: $0) == sectionValue})
         let metadataForSection = NCMetadataForSection.init(sectionValue: sectionValue,
                                                             metadatas: metadatas,
                                                             shares: self.shares,
@@ -177,6 +177,17 @@ class NCDataSource: NSObject {
         metadatasForSection.append(metadataForSection)
     }
 
+    func getMetadataSourceForAllSections() -> [tableMetadata] {
+
+        var metadatas: [tableMetadata] = []
+
+        for section in metadatasForSection {
+            metadatas.append(contentsOf: section.metadatas)
+        }
+
+        return metadatas
+    }
+
     // MARK: -
 
     func appendMetadatasToSection(_ metadatas: [tableMetadata], metadataForSection: NCMetadataForSection, lastSearchResult: NCCSearchResult) -> [IndexPath] {
@@ -184,7 +195,7 @@ class NCDataSource: NSObject {
         guard let sectionIndex =  getSectionIndex(metadataForSection.sectionValue) else { return [] }
         var indexPaths: [IndexPath] = []
 
-        self.metadatasSource.append(contentsOf: metadatas)
+        self.metadatas.append(contentsOf: metadatas)
         metadataForSection.metadatas.append(contentsOf: metadatas)
         metadataForSection.lastSearchResult = lastSearchResult
         metadataForSection.createMetadatas()
@@ -205,10 +216,10 @@ class NCDataSource: NSObject {
         let sectionValue = getSectionValue(metadata: metadata)
 
         // ADD metadatasSource
-        if let rowIndex = self.metadatasSource.firstIndex(where: {$0.fileNameView == metadata.fileNameView || $0.ocId == metadata.ocId}) {
-            self.metadatasSource[rowIndex] = metadata
+        if let rowIndex = self.metadatas.firstIndex(where: {$0.fileNameView == metadata.fileNameView || $0.ocId == metadata.ocId}) {
+            self.metadatas[rowIndex] = metadata
         } else {
-            self.metadatasSource.append(metadata)
+            self.metadatas.append(metadata)
         }
 
         // ADD metadataForSection
@@ -264,8 +275,8 @@ class NCDataSource: NSObject {
         } else { return (nil, false) }
 
         // DELETE metadatasSource (IMPORTANT LAST)
-        if let rowIndex = self.metadatasSource.firstIndex(where: {$0.ocId == ocId}) {
-            self.metadatasSource.remove(at: rowIndex)
+        if let rowIndex = self.metadatas.firstIndex(where: {$0.ocId == ocId}) {
+            self.metadatas.remove(at: rowIndex)
         }
 
         return (indexPathReturn, self.isSameNumbersOfSections(numberOfSections: numberOfSections))
@@ -291,8 +302,8 @@ class NCDataSource: NSObject {
         }
 
         // UPDATE metadatasSource (IMPORTANT LAST)
-        if let rowIndex = self.metadatasSource.firstIndex(where: {$0.ocId == ocIdSearch}) {
-            self.metadatasSource[rowIndex] = metadata
+        if let rowIndex = self.metadatas.firstIndex(where: {$0.ocId == ocIdSearch}) {
+            self.metadatas[rowIndex] = metadata
         }
 
         let result = self.getIndexPathMetadata(ocId: ocId)
@@ -302,7 +313,7 @@ class NCDataSource: NSObject {
     // MARK: -
 
     func getIndexPathMetadata(ocId: String) -> (indexPath: IndexPath?, metadataForSection: NCMetadataForSection?) {
-        guard let metadata = metadatasSource.filter({ $0.ocId == ocId}).first else { return (nil, nil) }
+        guard let metadata = self.metadatas.filter({ $0.ocId == ocId}).first else { return (nil, nil) }
         let sectionValue = getSectionValue(metadata: metadata)
         guard let sectionIndex = getSectionIndex(sectionValue), let metadataForSection = getMetadataForSection(sectionValue), let rowIndex = metadataForSection.metadatas.firstIndex(where: {$0.ocId == ocId}) else { return (nil, nil) }
         return (IndexPath(row: rowIndex, section: sectionIndex), metadataForSection)
@@ -319,7 +330,7 @@ class NCDataSource: NSObject {
     }
     
     func numberOfItemsInSection(_ section: Int) -> Int {
-        guard self.sectionsValue.count > 0 && self.metadatasSource.count > 0, let metadataForSection = getMetadataForSection(section) else { return 0}
+        guard self.sectionsValue.count > 0 && self.metadatas.count > 0, let metadataForSection = getMetadataForSection(section) else { return 0}
         return metadataForSection.metadatas.count
     }
 
@@ -402,7 +413,7 @@ class NCMetadataForSection: NSObject {
     private var favoriteOnTop: Bool
     private var filterLivePhoto: Bool
 
-    private var metadatasSourceSorted: [tableMetadata] = []
+    private var metadatasSorted: [tableMetadata] = []
     private var metadatasFavoriteDirectory: [tableMetadata] = []
     private var metadatasFavoriteFile: [tableMetadata] = []
     private var metadatasDirectory: [tableMetadata] = []
@@ -436,7 +447,7 @@ class NCMetadataForSection: NSObject {
 
         // Clear
         //
-        metadatasSourceSorted.removeAll()
+        metadatasSorted.removeAll()
         metadatasFavoriteDirectory.removeAll()
         metadatasFavoriteFile.removeAll()
         metadatasDirectory.removeAll()
@@ -451,7 +462,7 @@ class NCMetadataForSection: NSObject {
         // Metadata order
         //
         if sort != "none" && sort != "" {
-            metadatasSourceSorted = metadatas.sorted {
+            metadatasSorted = metadatas.sorted {
 
                 switch sort {
                 case "date":
@@ -475,12 +486,12 @@ class NCMetadataForSection: NSObject {
                 }
             }
         } else {
-            metadatasSourceSorted = metadatas
+            metadatasSorted = metadatas
         }
 
         // Initialize datasource
         //
-        for metadata in metadatasSourceSorted {
+        for metadata in metadatasSorted {
 
             // skipped the root file
             if metadata.fileName == "." || metadata.serverUrl == ".." {

+ 1 - 0
iOSClient/Data/NCDatabase.swift

@@ -386,6 +386,7 @@ class tableMetadata: Object, NCUserBaseUrl {
     @objc dynamic var iconName = ""
     @objc dynamic var iconUrl = ""
     @objc dynamic var isAutoupload: Bool = false
+    @objc dynamic var isExtractFile: Bool = false
     @objc dynamic var livePhoto: Bool = false
     @objc dynamic var mountType = ""
     @objc dynamic var name = ""

+ 20 - 18
iOSClient/Favorites/NCFavorite.swift

@@ -47,28 +47,30 @@ class NCFavorite: NCCollectionViewCommon {
     override func reloadDataSource(forced: Bool = true) {
         super.reloadDataSource()
 
-        if !self.isSearching {
+        DispatchQueue.global().async {
+            var metadatas: [tableMetadata] = []
+
             if self.serverUrl.isEmpty {
-                self.metadatasSource = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND favorite == true", self.appDelegate.account))
+                metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND favorite == true", self.appDelegate.account))
             } else {
-                self.metadatasSource = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
+                metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
             }
-        }
 
-        self.dataSource = NCDataSource(metadatasSource: self.metadatasSource,
-                                       account: self.appDelegate.account,
-                                       sort: self.layoutForView?.sort,
-                                       ascending: self.layoutForView?.ascending,
-                                       directoryOnTop: self.layoutForView?.directoryOnTop,
-                                       favoriteOnTop: true,
-                                       filterLivePhoto: true,
-                                       groupByField: self.groupByField,
-                                       providers: self.providers,
-                                       searchResults: self.searchResults)
-
-        DispatchQueue.main.async {
-            self.refreshControl.endRefreshing()
-            self.collectionView.reloadData()
+            self.dataSource = NCDataSource(metadatas: metadatas,
+                                           account: self.appDelegate.account,
+                                           sort: self.layoutForView?.sort,
+                                           ascending: self.layoutForView?.ascending,
+                                           directoryOnTop: self.layoutForView?.directoryOnTop,
+                                           favoriteOnTop: true,
+                                           filterLivePhoto: true,
+                                           groupByField: self.groupByField,
+                                           providers: self.providers,
+                                           searchResults: self.searchResults)
+
+            DispatchQueue.main.async {
+                self.refreshControl.endRefreshing()
+                self.collectionView.reloadData()
+            }
         }
     }
 

+ 4 - 9
iOSClient/FileViewInFolder/NCFileViewInFolder.swift

@@ -83,15 +83,12 @@ class NCFileViewInFolder: NCCollectionViewCommon {
         super.reloadDataSource()
 
         DispatchQueue.global().async {
-
-            if !self.isSearching {
-                self.metadatasSource = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
-                if self.metadataFolder == nil {
-                    self.metadataFolder = NCManageDatabase.shared.getMetadataFolder(account: self.appDelegate.account, urlBase: self.appDelegate.urlBase, serverUrl: self.serverUrl)
-                }
+            let metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
+            if self.metadataFolder == nil {
+                self.metadataFolder = NCManageDatabase.shared.getMetadataFolder(account: self.appDelegate.account, urlBase: self.appDelegate.urlBase, serverUrl: self.serverUrl)
             }
 
-            self.dataSource = NCDataSource(metadatasSource: self.metadatasSource,
+            self.dataSource = NCDataSource(metadatas: metadatas,
                                            account: self.appDelegate.account,
                                            sort: self.layoutForView?.sort,
                                            ascending: self.layoutForView?.ascending,
@@ -103,10 +100,8 @@ class NCFileViewInFolder: NCCollectionViewCommon {
                                            searchResults: self.searchResults)
 
             DispatchQueue.main.async {
-
                 self.refreshControl.endRefreshing()
                 self.collectionView.reloadData()
-
                 // Blink file
                 if self.fileName != nil {
                     if let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", self.appDelegate.account, self.serverUrl, self.fileName!)) {

+ 27 - 25
iOSClient/Files/NCFiles.swift

@@ -78,33 +78,35 @@ class NCFiles: NCCollectionViewCommon {
         super.reloadDataSource()
 
         DispatchQueue.main.async { self.refreshControl.endRefreshing() }
-        guard !isSearching, !appDelegate.account.isEmpty, !appDelegate.urlBase.isEmpty, !serverUrl.isEmpty else { return }
+        DispatchQueue.global().async {
+            guard !self.isSearching, !self.appDelegate.account.isEmpty, !self.appDelegate.urlBase.isEmpty, !self.serverUrl.isEmpty else { return }
 
-        self.metadatasSource = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", appDelegate.account, serverUrl))
-        if self.metadataFolder == nil {
-            self.metadataFolder = NCManageDatabase.shared.getMetadataFolder(account: self.appDelegate.account, urlBase: appDelegate.urlBase, serverUrl: serverUrl)
-        }
-        let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", appDelegate.account, serverUrl))
+            let metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
+            if self.metadataFolder == nil {
+                self.metadataFolder = NCManageDatabase.shared.getMetadataFolder(account: self.appDelegate.account, urlBase: self.appDelegate.urlBase, serverUrl: self.serverUrl)
+            }
+            let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
 
-        // FORCED false: test the directory.etag
-        if !forced, let directory = directory, directory.etag == dataSource.directory?.etag {
-            return
-        }
+            // FORCED false: test the directory.etag
+            if !forced, let directory = directory, directory.etag == self.dataSource.directory?.etag {
+                return
+            }
 
-        dataSource = NCDataSource(
-            metadatasSource: self.metadatasSource,
-            account: self.appDelegate.account,
-            directory: directory,
-            sort: self.layoutForView?.sort,
-            ascending: self.layoutForView?.ascending,
-            directoryOnTop: self.layoutForView?.directoryOnTop,
-            favoriteOnTop: true,
-            filterLivePhoto: true,
-            groupByField: self.groupByField,
-            providers: self.providers,
-            searchResults: self.searchResults)
-
-        DispatchQueue.main.async { self.collectionView.reloadData() }
+            self.dataSource = NCDataSource(
+                metadatas: metadatas,
+                account: self.appDelegate.account,
+                directory: directory,
+                sort: self.layoutForView?.sort,
+                ascending: self.layoutForView?.ascending,
+                directoryOnTop: self.layoutForView?.directoryOnTop,
+                favoriteOnTop: true,
+                filterLivePhoto: true,
+                groupByField: self.groupByField,
+                providers: self.providers,
+                searchResults: self.searchResults)
+
+            DispatchQueue.main.async { self.collectionView.reloadData() }
+        }
     }
 
     override func reloadDataSourceNetwork(forced: Bool = false) {
@@ -130,7 +132,7 @@ class NCFiles: NCCollectionViewCommon {
 
             if metadatasUpdate?.count ?? 0 > 0 || metadatasDelete?.count ?? 0 > 0 || forced {
                 self.reloadDataSource(forced: false)
-            } else if self.dataSource.metadatasSource.isEmpty {
+            } else if self.dataSource.getMetadataSourceForAllSections().isEmpty {
                 DispatchQueue.main.async { self.collectionView.reloadData() }
             }
         }

+ 49 - 71
iOSClient/Main/Collection Common/NCCollectionViewCommon.swift

@@ -39,14 +39,13 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
     internal var isEncryptedFolder = false
     internal var isEditMode = false
     internal var selectOcId: [String] = []
-    internal var metadatasSource: [tableMetadata] = []
     internal var metadataFolder: tableMetadata?
     internal var dataSource = NCDataSource()
     internal var richWorkspaceText: String?
     internal var headerMenu: NCSectionHeaderMenu?
 
     internal var layoutForView: NCGlobal.layoutForViewType?
-    internal var selectableDataSource: [RealmSwiftObject] { dataSource.metadatasSource }
+    internal var selectableDataSource: [RealmSwiftObject] { dataSource.getMetadataSourceForAllSections() }
 
     private var autoUploadFileName = ""
     private var autoUploadDirectory = ""
@@ -533,6 +532,9 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
         else {
             return
         }
+        if metadata.livePhoto && metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue {
+            return
+        }
         let (indexPath, sameSections) = dataSource.reloadMetadata(ocId: metadata.ocId, ocIdTemp: ocIdTemp)
         if let indexPath = indexPath {
             if sameSections && (indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section)) {
@@ -606,7 +608,11 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
                     if status == NCGlobal.shared.metadataStatusInDownload {
                         cell.fileInfoLabel?.text = CCUtility.transformedSize(totalBytesExpected) + " - ↓ " + CCUtility.transformedSize(totalBytes)
                     } else if status == NCGlobal.shared.metadataStatusInUpload {
-                        cell.fileInfoLabel?.text = CCUtility.transformedSize(totalBytesExpected) + " - ↑ " + CCUtility.transformedSize(totalBytes)
+                        if totalBytes > 0 {
+                            cell.fileInfoLabel?.text = CCUtility.transformedSize(totalBytesExpected) + " - ↑ " + CCUtility.transformedSize(totalBytes)
+                        } else {
+                            cell.fileInfoLabel?.text = CCUtility.transformedSize(totalBytesExpected) + " - ↑ …"
+                        }
                     }
                 }
             }
@@ -742,7 +748,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
         self.isSearching = true
 
         self.providers?.removeAll()
-        self.metadatasSource.removeAll()
         self.dataSource.clearDataSource()
 
         self.collectionView.reloadData()
@@ -1031,7 +1036,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
         }
 
         isReloadDataSourceNetworkInProgress = true
-        self.metadatasSource.removeAll()
         self.dataSource.clearDataSource()
         self.refreshControl.beginRefreshing()
         self.collectionView.reloadData()
@@ -1042,7 +1046,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
                 self.providers = allProviders
                 self.searchResults = []
                 self.dataSource = NCDataSource(
-                    metadatasSource: self.metadatasSource,
+                    metadatas: [] ,
                     account: self.appDelegate.account,
                     sort: self.layoutForView?.sort,
                     ascending: self.layoutForView?.ascending,
@@ -1053,7 +1057,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
                     searchResults: self.searchResults)
             } update: { id, searchResult, metadatas in
                 guard let metadatas = metadatas, metadatas.count > 0, self.isSearching , let searchResult = searchResult else { return }
-                NCOperationQueue.shared.dataSourceAddSection(collectionViewCommon: self, metadatas: metadatas, searchResult: searchResult)
+                NCOperationQueue.shared.unifiedSearchAddSection(collectionViewCommon: self, metadatas: metadatas, searchResult: searchResult)
             } completion: {errorCode, errorDescription in
                 self.refreshControl.endRefreshing()
                 self.isReloadDataSourceNetworkInProgress = false
@@ -1061,11 +1065,13 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
             }
         } else {
             NCNetworking.shared.searchFiles(urlBase: appDelegate, literal: literalSearch) { metadatas, errorCode, errorDescription in
-                if  self.isSearching, errorCode == 0, let metadatas = metadatas {
-                    self.metadatasSource = metadatas
+                DispatchQueue.main.async {
+                    self.refreshControl.endRefreshing()
+                    self.collectionView.reloadData()
                 }
+                guard let metadatas = metadatas, errorCode == 0, self.isSearching else { return }
                 self.dataSource = NCDataSource(
-                    metadatasSource: self.metadatasSource,
+                    metadatas: metadatas,
                     account: self.appDelegate.account,
                     sort: self.layoutForView?.sort,
                     ascending: self.layoutForView?.ascending,
@@ -1076,10 +1082,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
                     providers: self.providers,
                     searchResults: self.searchResults)
                 self.isReloadDataSourceNetworkInProgress = false
-                DispatchQueue.main.async {
-                    self.refreshControl.endRefreshing()
-                    self.collectionView.reloadData()
-                }
             }
         }
     }
@@ -1100,7 +1102,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
             metadataForSection.unifiedSearchInProgress = false
             guard let searchResult = searchResult, let metadatas = metadatas else { return }
 
-            self.metadatasSource.append(contentsOf: metadatas)
             let indexPaths = self.dataSource.appendMetadatasToSection(metadatas, metadataForSection: metadataForSection, lastSearchResult: searchResult)
 
             DispatchQueue.main.async {
@@ -1118,57 +1119,41 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
         var tableDirectory: tableDirectory?
 
         NCNetworking.shared.readFile(serverUrlFileName: serverUrl) { (account, metadataFolder, errorCode, errorDescription) in
+            guard errorCode == 0 else {
+                completion(nil, nil, nil, nil, errorCode, errorDescription)
+                return
+            }
 
-            if errorCode == 0 {
-
-                if let metadataFolder = metadataFolder {
-                    tableDirectory = NCManageDatabase.shared.setDirectory(richWorkspace: metadataFolder.richWorkspace, serverUrl: self.serverUrl, account: account)
-                }
-
-                if forced || tableDirectory?.etag != metadataFolder?.etag || metadataFolder?.e2eEncrypted ?? false {
-
-                    NCNetworking.shared.readFolder(serverUrl: self.serverUrl, account: self.appDelegate.account) { account, metadataFolder, metadatas, metadatasUpdate, _, metadatasDelete, errorCode, errorDescription in
-
-                        if errorCode == 0 {
-                            self.metadataFolder = metadataFolder
-
-                            // E2EE
-                            if let metadataFolder = metadataFolder {
-                                if metadataFolder.e2eEncrypted && CCUtility.isEnd(toEndEnabled: self.appDelegate.account) {
-
-                                    NCCommunication.shared.getE2EEMetadata(fileId: metadataFolder.ocId, e2eToken: nil) { account, e2eMetadata, errorCode, errorDescription in
-
-                                        if errorCode == 0 && e2eMetadata != nil {
-
-                                            if !NCEndToEndMetadata.shared.decoderMetadata(e2eMetadata!, privateKey: CCUtility.getEndToEndPrivateKey(account), serverUrl: self.serverUrl, account: account, urlBase: self.appDelegate.urlBase) {
-
-                                                NCContentPresenter.shared.messageNotification("_error_e2ee_", description: "_e2e_error_decode_metadata_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorDecodeMetadata)
-                                            } else {
-                                                self.reloadDataSource()
-                                            }
-
-                                        } else if errorCode != NCGlobal.shared.errorResourceNotFound {
-
-                                            NCContentPresenter.shared.messageNotification("_error_e2ee_", description: "_e2e_error_decode_metadata_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorDecodeMetadata)
-                                        }
-
-                                        completion(tableDirectory, metadatas, metadatasUpdate, metadatasDelete, errorCode, errorDescription)
-                                    }
+            if let metadataFolder = metadataFolder {
+                tableDirectory = NCManageDatabase.shared.setDirectory(richWorkspace: metadataFolder.richWorkspace, serverUrl: self.serverUrl, account: account)
+            }
+            if forced || tableDirectory?.etag != metadataFolder?.etag || metadataFolder?.e2eEncrypted ?? false {
+                NCNetworking.shared.readFolder(serverUrl: self.serverUrl, account: self.appDelegate.account) { account, metadataFolder, metadatas, metadatasUpdate, _, metadatasDelete, errorCode, errorDescription in
+                    guard errorCode == 0 else {
+                        completion(tableDirectory, nil, nil, nil, errorCode, errorDescription)
+                        return
+                    }
+                    self.metadataFolder = metadataFolder
+                    // E2EE
+                    if let metadataFolder = metadataFolder, metadataFolder.e2eEncrypted, CCUtility.isEnd(toEndEnabled: self.appDelegate.account) {
+                        NCCommunication.shared.getE2EEMetadata(fileId: metadataFolder.ocId, e2eToken: nil) { account, e2eMetadata, errorCode, errorDescription in
+                            if errorCode == 0, let e2eMetadata = e2eMetadata {
+                                if NCEndToEndMetadata.shared.decoderMetadata(e2eMetadata, privateKey: CCUtility.getEndToEndPrivateKey(account), serverUrl: self.serverUrl, account: account, urlBase: self.appDelegate.urlBase) {
+                                    self.reloadDataSource()
                                 } else {
-                                    completion(tableDirectory, metadatas, metadatasUpdate, metadatasDelete, errorCode, errorDescription)
+                                    NCContentPresenter.shared.messageNotification("_error_e2ee_", description: "_e2e_error_decode_metadata_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorDecodeMetadata)
                                 }
-                            } else {
-                                completion(tableDirectory, metadatas, metadatasUpdate, metadatasDelete, errorCode, errorDescription)
+                            } else if errorCode != NCGlobal.shared.errorResourceNotFound {
+                                NCContentPresenter.shared.messageNotification("_error_e2ee_", description: "_e2e_error_decode_metadata_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorDecodeMetadata)
                             }
-                        } else {
-                            completion(tableDirectory, nil, nil, nil, errorCode, errorDescription)
+                            completion(tableDirectory, metadatas, metadatasUpdate, metadatasDelete, errorCode, errorDescription)
                         }
+                    } else {
+                        completion(tableDirectory, metadatas, metadatasUpdate, metadatasDelete, errorCode, errorDescription)
                     }
-                } else {
-                    completion(tableDirectory, nil, nil, nil, 0, "")
                 }
             } else {
-               completion(nil, nil, nil, nil, errorCode, errorDescription)
+                completion(tableDirectory, nil, nil, nil, 0, "")
             }
         }
     }
@@ -1320,6 +1305,7 @@ extension NCCollectionViewCommon: UICollectionViewDelegate {
 
         guard let metadata = dataSource.cellForItemAt(indexPath: indexPath) else { return }
         appDelegate.activeMetadata = metadata
+        let metadataSourceForAllSections = dataSource.getMetadataSourceForAllSections()
 
         if isEditMode {
             if let index = selectOcId.firstIndex(of: metadata.ocId) {
@@ -1328,7 +1314,7 @@ extension NCCollectionViewCommon: UICollectionViewDelegate {
                 selectOcId.append(metadata.ocId)
             }
             collectionView.reloadItems(at: [indexPath])
-            self.navigationItem.title = NSLocalizedString("_selected_", comment: "") + " : \(selectOcId.count)" + " / \(dataSource.metadatasSource.count)"
+            self.navigationItem.title = NSLocalizedString("_selected_", comment: "") + " : \(selectOcId.count)" + " / \(metadataSourceForAllSections.count)"
             return
         }
 
@@ -1347,7 +1333,7 @@ extension NCCollectionViewCommon: UICollectionViewDelegate {
 
             if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
                 var metadatas: [tableMetadata] = []
-                for metadata in dataSource.metadatasSource {
+                for metadata in metadataSourceForAllSections {
                     if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
                         metadatas.append(metadata)
                     }
@@ -1588,16 +1574,8 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
             cell.writeInfoDateSize(date: metadata.date, size: metadata.size)
         }
 
-        // Progress
-        var progress: Float = 0.0
-        var totalBytes: Int64 = 0
-        if let progressType = appDelegate.listProgress[metadata.ocId] {
-            progress = progressType.progress
-            totalBytes = progressType.totalBytes
-        }
         if metadata.status == NCGlobal.shared.metadataStatusDownloading || metadata.status == NCGlobal.shared.metadataStatusUploading {
             cell.fileProgressView?.isHidden = false
-            cell.fileProgressView?.progress = progress
         }
 
         // Accessibility [shared]
@@ -1686,7 +1664,7 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
             cell.fileInfoLabel?.text = CCUtility.transformedSize(metadata.size) + " - " + NSLocalizedString("_status_in_download_", comment: "")
             break
         case NCGlobal.shared.metadataStatusDownloading:
-            cell.fileInfoLabel?.text = CCUtility.transformedSize(metadata.size) + " - ↓ " + CCUtility.transformedSize(totalBytes)
+            cell.fileInfoLabel?.text = CCUtility.transformedSize(metadata.size) + " - ↓ "
             break
         case NCGlobal.shared.metadataStatusWaitUpload:
             cell.fileInfoLabel?.text = CCUtility.transformedSize(metadata.size) + " - " + NSLocalizedString("_status_wait_upload_", comment: "")
@@ -1695,7 +1673,7 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
             cell.fileInfoLabel?.text = CCUtility.transformedSize(metadata.size) + " - " + NSLocalizedString("_status_in_upload_", comment: "")
             break
         case NCGlobal.shared.metadataStatusUploading:
-            cell.fileInfoLabel?.text = CCUtility.transformedSize(metadata.size) + " - ↑ " + CCUtility.transformedSize(totalBytes)
+            cell.fileInfoLabel?.text = CCUtility.transformedSize(metadata.size) + " - ↑ "
             break
         case NCGlobal.shared.metadataStatusUploadError:
             if metadata.sessionError != "" {
@@ -1786,7 +1764,7 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
                     header.setButtonsCommand(heigt: 0)
                 }
                 if headerMenuButtonsView {
-                    header.setStatusButtonsView(enable: !dataSource.metadatasSource.isEmpty)
+                    header.setStatusButtonsView(enable: !dataSource.getMetadataSourceForAllSections().isEmpty)
                     header.setButtonsView(heigt: NCGlobal.shared.heightButtonsView)
                     header.setSortedTitle(layoutForView?.titleButtonHeader ?? "")
                 } else {

+ 5 - 11
iOSClient/Main/Create cloud/NCCreateFormUploadConflict.swift

@@ -397,29 +397,23 @@ extension NCCreateFormUploadConflict: UITableViewDataSource {
                 } else {
 
                     // PREVIEW
-                    CCUtility.extractImageVideoFromAssetLocalIdentifier(forUpload: metadataNewFile, queue: .main) { metadataNew, fileNamePath in
-
-                        if metadataNew != nil {
+                    NCUtility.shared.extractImageVideoFromAssetLocalIdentifier(metadata: metadataNewFile, modifyMetadataForUpload: false) { metadata, fileNamePath, error in
+                        if !error {
                             self.fileNamesPath[metadataNewFile.fileNameView] = fileNamePath!
-
                             do {
-
                                 let fileDictionary = try FileManager.default.attributesOfItem(atPath: fileNamePath!)
                                 let fileSize = fileDictionary[FileAttributeKey.size] as! Int64
-
                                 if mediaType == PHAssetMediaType.image {
                                     let data = try Data(contentsOf: URL(fileURLWithPath: fileNamePath!))
                                     if let image = UIImage(data: data) {
-                                        cell.imageNewFile.image = image
+                                        DispatchQueue.main.async { cell.imageNewFile.image = image }
                                     }
                                 } else if mediaType == PHAssetMediaType.video {
                                     if let image = NCUtility.shared.imageFromVideo(url: URL(fileURLWithPath: fileNamePath!), at: 0) {
-                                        cell.imageNewFile.image = image
+                                        DispatchQueue.main.async { cell.imageNewFile.image = image }
                                     }
                                 }
-
-                                cell.labelDetailNewFile.text = CCUtility.dateDiff(date) + "\n" + CCUtility.transformedSize(fileSize)
-
+                                DispatchQueue.main.async { cell.labelDetailNewFile.text = CCUtility.dateDiff(date) + "\n" + CCUtility.transformedSize(fileSize) }
                             } catch { print("Error: \(error)") }
                         }
                     }

+ 1 - 1
iOSClient/Main/NCMainTabBar.swift

@@ -211,7 +211,7 @@ class NCMainTabBar: UITabBar {
     @objc func updateBadgeNumber() {
         guard !appDelegate.account.isEmpty else { return }
 
-        let counterDownload = NCOperationQueue.shared.downloadCount()
+        let counterDownload = NCOperationQueue.shared.downloadQueueCount()
         let counterUpload = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "status == %d OR status == %d OR status == %d", NCGlobal.shared.metadataStatusWaitUpload, NCGlobal.shared.metadataStatusInUpload, NCGlobal.shared.metadataStatusUploading)).count
         let total = counterDownload + counterUpload
 

+ 1 - 1
iOSClient/NCGlobal.swift

@@ -115,7 +115,7 @@ class NCGlobal: NSObject {
     // Database Realm
     //
     let databaseDefault                             = "nextcloud.realm"
-    let databaseSchemaVersion: UInt64               = 228
+    let databaseSchemaVersion: UInt64               = 229
 
     // Intro selector
     //

+ 0 - 3
iOSClient/Networking/NCAutoUpload.swift

@@ -51,9 +51,6 @@ class NCAutoUpload: NSObject {
             }
 
             self.uploadAssetsNewAndFull(viewController: viewController, selector: NCGlobal.shared.selectorUploadAutoUpload, log: "Init Auto Upload") { items in
-                if items > 0 {
-                    self.appDelegate.networkingProcessUpload?.startProcess()
-                }
                 completion(items)
             }
         }

+ 132 - 231
iOSClient/Networking/NCNetworking.swift

@@ -112,22 +112,18 @@ import Photos
 
     func networkReachabilityObserver(_ typeReachability: NCCommunicationCommon.typeReachability) {
 
-        #if !EXTENSION
+#if !EXTENSION
         if typeReachability == NCCommunicationCommon.typeReachability.reachableCellular || typeReachability == NCCommunicationCommon.typeReachability.reachableEthernetOrWiFi {
-
             if !lastReachability {
                 NCService.shared.startRequestServicesServer()
             }
             lastReachability = true
-
         } else {
-
             if lastReachability {
                 NCContentPresenter.shared.messageNotification("_network_not_available_", description: nil, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: -1009)
             }
             lastReachability = false
         }
-
         networkReachability = typeReachability
         #endif
     }
@@ -233,7 +229,6 @@ import Photos
         if x509cert == nil {
             print("[LOG] OpenSSL couldn't parse X509 Certificate")
         } else {
-
             // save details
             if FileManager.default.fileExists(atPath: certNamePathTXT) {
                 do {
@@ -247,7 +242,6 @@ import Photos
                 BIO_free(output)
             }
             fclose(fileCertInfo)
-
             X509_free(x509cert)
         }
 
@@ -255,29 +249,26 @@ import Photos
     }
 
     func checkPushNotificationServerProxyCertificateUntrusted(viewController: UIViewController?, completion: @escaping (_ errorCode: Int) -> Void) {
-
         guard let host = URL(string: NCBrandOptions.shared.pushNotificationServerProxy)?.host else { return }
 
         NCCommunication.shared.checkServer(serverUrl: NCBrandOptions.shared.pushNotificationServerProxy) { errorCode, _ in
+            guard errorCode == 0 else {
+                completion(0)
+                return
+            }
 
             if errorCode == 0 {
-
                 NCNetworking.shared.writeCertificate(host: host)
                 completion(errorCode)
-
             } else if errorCode == NSURLErrorServerCertificateUntrusted {
-
                 let alertController = UIAlertController(title: NSLocalizedString("_ssl_certificate_untrusted_", comment: ""), message: NSLocalizedString("_connect_server_anyway_", comment: ""), preferredStyle: .alert)
-
                 alertController.addAction(UIAlertAction(title: NSLocalizedString("_yes_", comment: ""), style: .default, handler: { _ in
                     NCNetworking.shared.writeCertificate(host: host)
                     completion(0)
                 }))
-
                 alertController.addAction(UIAlertAction(title: NSLocalizedString("_no_", comment: ""), style: .default, handler: { _ in
                     completion(errorCode)
                 }))
-
                 alertController.addAction(UIAlertAction(title: NSLocalizedString("_certificate_details_", comment: ""), style: .default, handler: { _ in
                     if let navigationController = UIStoryboard(name: "NCViewCertificateDetails", bundle: nil).instantiateInitialViewController() as? UINavigationController {
                         let vcCertificateDetails = navigationController.topViewController as! NCViewCertificateDetails
@@ -285,12 +276,7 @@ import Photos
                         viewController?.present(navigationController, animated: true)
                     }
                 }))
-
                 viewController?.present(alertController, animated: true)
-
-            } else {
-
-                completion(0)
             }
         }
     }
@@ -315,21 +301,13 @@ import Photos
 
     @objc func cancelDownload(ocId: String, serverUrl: String, fileNameView: String) {
 
-        #if !EXTENSION
-        // removed progress ocid
-        DispatchQueue.main.async { (UIApplication.shared.delegate as! AppDelegate).listProgress[ocId] = nil }
-        #endif
-
         guard let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(ocId, fileNameView: fileNameView) else { return }
 
         if let request = downloadRequest[fileNameLocalPath] {
             request.cancel()
-        } else {
-            if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
-
-                NCManageDatabase.shared.setMetadataSession(ocId: ocId, session: "", sessionError: "", sessionSelector: "", sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusNormal)
-                NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadCancelFile, userInfo: ["ocId": metadata.ocId])
-            }
+        } else if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
+            NCManageDatabase.shared.setMetadataSession(ocId: ocId, session: "", sessionError: "", sessionSelector: "", sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusNormal)
+            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadCancelFile, userInfo: ["ocId": metadata.ocId])
         }
     }
     
@@ -358,15 +336,8 @@ import Photos
         }, progressHandler: { (progress) in
             
             if notificationCenterProgressTask {
-                #if !EXTENSION
-                // add progress ocid
-                let progressType = NCGlobal.progressType(progress: Float(progress.fractionCompleted), totalBytes: progress.totalUnitCount, totalBytesExpected: progress.completedUnitCount)
-                DispatchQueue.main.async { (UIApplication.shared.delegate as! AppDelegate).listProgress[metadata.ocId] = progressType }
-                #endif
-                
                 NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterProgressTask, object: nil, userInfo: ["account":metadata.account, "ocId":metadata.ocId, "fileName":metadata.fileName, "serverUrl":metadata.serverUrl, "status":NSNumber(value: NCGlobal.shared.metadataStatusInDownload), "progress":NSNumber(value: progress.fractionCompleted), "totalBytes":NSNumber(value: progress.totalUnitCount), "totalBytesExpected":NSNumber(value: progress.completedUnitCount)])
             }
-            
             progressHandler(progress)
                                         
         }) { (account, etag, date, _, allHeaderFields, error, errorCode, errorDescription) in
@@ -379,7 +350,6 @@ import Photos
 
                 NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: "", sessionError: "", sessionSelector: selector, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusNormal, etag: etag)
                 NCManageDatabase.shared.addLocalFile(metadata: metadata)
-
                 #if !EXTENSION
                 if let result = NCManageDatabase.shared.getE2eEncryption(predicate: NSPredicate(format: "fileNameIdentifier == %@ AND serverUrl == %@", metadata.fileName, metadata.serverUrl)) {
 
@@ -391,7 +361,6 @@ import Photos
             } else {
 
                 NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: "", sessionError: errorDescription, sessionSelector: selector, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusDownloadError)
-
                 #if !EXTENSION
                 if errorCode == 401 || errorCode == 403 {
                     NCNetworkingCheckRemoteUser.shared.checkRemoteUser(account: metadata.account, errorCode: errorCode, errorDescription: errorDescription)
@@ -400,17 +369,12 @@ import Photos
             }
 
             self.downloadRequest[fileNameLocalPath] = nil
-
             if error?.isExplicitlyCancelledError ?? false {
                 NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadCancelFile, userInfo: ["ocId": metadata.ocId])
             } else {
                 NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadedFile, userInfo: ["ocId": metadata.ocId, "selector": selector, "errorCode": errorCode, "errorDescription": errorDescription])
             }
-
             DispatchQueue.main.async {
-                #if !EXTENSION
-                (UIApplication.shared.delegate as! AppDelegate).listProgress[metadata.ocId] = nil
-                #endif
                 completion(errorCode)
             }
         }
@@ -474,12 +438,6 @@ import Photos
 
         }, progressHandler: { progress in
 
-            #if !EXTENSION
-            // add progress ocid
-            let progressType = NCGlobal.progressType(progress: Float(progress.fractionCompleted), totalBytes: progress.totalUnitCount, totalBytesExpected: progress.completedUnitCount)
-            DispatchQueue.main.async { (UIApplication.shared.delegate as! AppDelegate).listProgress[metadata.ocId] = progressType }
-            #endif
-
             NotificationCenter.default.postOnMainThread(
                 name: NCGlobal.shared.notificationCenterProgressTask,
                 userInfo: [
@@ -521,7 +479,6 @@ import Photos
         if NCUtilityFileSystem.shared.getFileSize(filePath: fileNameLocalPath) == 0 && metadata.size != 0 {
 
             NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
-
             completion(NCGlobal.shared.errorResourceNotFound, NSLocalizedString("_error_not_found_", value: "The requested resource could not be found", comment: ""))
 
         } else {
@@ -529,9 +486,7 @@ import Photos
             if let task = NCCommunicationBackground.shared.upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, dateCreationFile: metadata.creationDate as Date, dateModificationFile: metadata.date as Date, description: metadata.ocId, session: session!) {
 
                 NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, sessionError: "", sessionTaskIdentifier: task.taskIdentifier, status: NCGlobal.shared.metadataStatusUploading)
-
                 NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadStartFile, userInfo: ["ocId": metadata.ocId])
-
                 completion(0, "")
 
             } else {
@@ -543,115 +498,98 @@ import Photos
     }
 
     func uploadComplete(fileName: String, serverUrl: String, ocId: String?, etag: String?, date: NSDate?, size: Int64, description: String?, task: URLSessionTask, errorCode: Int, errorDescription: String) {
-        guard delegate == nil else {
-            delegate?.uploadComplete?(fileName: fileName, serverUrl: serverUrl, ocId: ocId, etag: etag, date: date, size: size, description: description, task: task, errorCode: errorCode, errorDescription: errorDescription)
-            return
-        }
-
-        guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(description) else { return }
-        let ocIdTemp = metadata.ocId
-        var errorDescription = errorDescription
-
-        if errorCode == 0, let ocId = ocId, size == metadata.size {
-
-            let metadata = tableMetadata.init(value: metadata)
+        DispatchQueue.global().async {
+            guard self.delegate == nil, let metadata = NCManageDatabase.shared.getMetadataFromOcId(description) else {
+                self.delegate?.uploadComplete?(fileName: fileName, serverUrl: serverUrl, ocId: ocId, etag: etag, date: date, size: size, description: description, task: task, errorCode: errorCode, errorDescription: errorDescription)
+                return
+            }
+            let ocIdTemp = metadata.ocId
+            var errorDescription = errorDescription
 
-            NCUtilityFileSystem.shared.deleteFile(filePath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
+            if errorCode == 0, let ocId = ocId, size == metadata.size {
 
-            metadata.uploadDate = date ?? NSDate()
-            metadata.etag = etag ?? ""
-            metadata.ocId = ocId
+                let metadata = tableMetadata.init(value: metadata)
 
-            if let fileId = NCUtility.shared.ocIdToFileId(ocId: ocId) {
-                metadata.fileId = fileId
-            }
+                NCUtilityFileSystem.shared.deleteFile(filePath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
 
-            metadata.session = ""
-            metadata.sessionError = ""
-            metadata.sessionTaskIdentifier = 0
-            metadata.status = NCGlobal.shared.metadataStatusNormal
+                metadata.uploadDate = date ?? NSDate()
+                metadata.etag = etag ?? ""
+                metadata.ocId = ocId
 
-            // Delete Asset on Photos album
-            if CCUtility.getRemovePhotoCameraRoll() && !metadata.assetLocalIdentifier.isEmpty {
-                metadata.deleteAssetLocalIdentifier = true
-            }
+                if let fileId = NCUtility.shared.ocIdToFileId(ocId: ocId) {
+                    metadata.fileId = fileId
+                }
 
-            NCManageDatabase.shared.addMetadata(metadata)
-            NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp))
+                metadata.session = ""
+                metadata.sessionError = ""
+                metadata.sessionTaskIdentifier = 0
+                metadata.status = NCGlobal.shared.metadataStatusNormal
 
-            #if !EXTENSION
-            self.getOcIdInBackgroundSession { listOcId in
-                if listOcId.count == 0 && self.uploadRequest.count == 0 {
-                    let appDelegate = UIApplication.shared.delegate as! AppDelegate
-                    appDelegate.networkingProcessUpload?.startProcess()
+                // Delete Asset on Photos album
+                if CCUtility.getRemovePhotoCameraRoll() && !metadata.assetLocalIdentifier.isEmpty {
+                    metadata.deleteAssetLocalIdentifier = true
                 }
-            }
-            #endif
 
-            NCCommunicationCommon.shared.writeLog("Upload complete " + serverUrl + "/" + fileName + ", result: success(\(size) bytes)")
-            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
-        } else {
-            if errorCode == NSURLErrorCancelled || errorCode == NCGlobal.shared.errorRequestExplicityCancelled {
+                NCManageDatabase.shared.addMetadata(metadata)
+                NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp))
 
-                CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
-                NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
+                NCCommunicationCommon.shared.writeLog("Upload complete " + serverUrl + "/" + fileName + ", result: success(\(size) bytes)")
+                NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
+            } else {
+                if errorCode == NSURLErrorCancelled || errorCode == NCGlobal.shared.errorRequestExplicityCancelled {
 
-                NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadCancelFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account])
+                    CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
+                    NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
 
-            } else if errorCode == 401 || errorCode == 403 {
-                #if !EXTENSION
-                NCNetworkingCheckRemoteUser.shared.checkRemoteUser(account: metadata.account, errorCode: errorCode, errorDescription: errorDescription)
-                #endif
-                NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: errorDescription, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusUploadError)
-            } else {
-                if size == 0 {
-                    errorDescription = "File length 0"
-                    NCCommunicationCommon.shared.writeLog("Upload error 0 length " + serverUrl + "/" + fileName + ", result: success(\(size) bytes)")
+                    NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadCancelFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account])
+
+                } else if errorCode == 401 || errorCode == 403 {
+                    #if !EXTENSION
+                    NCNetworkingCheckRemoteUser.shared.checkRemoteUser(account: metadata.account, errorCode: errorCode, errorDescription: errorDescription)
+                    #endif
+                    NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: errorDescription, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusUploadError)
+                } else {
+                    if size == 0 {
+                        errorDescription = "File length 0"
+                        NCCommunicationCommon.shared.writeLog("Upload error 0 length " + serverUrl + "/" + fileName + ", result: success(\(size) bytes)")
+                    }
+                    NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: errorDescription, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusUploadError)
                 }
-                NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: errorDescription, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusUploadError)
+                NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
             }
-            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
-        }
 
-        #if !EXTENSION
-        DispatchQueue.main.async { (UIApplication.shared.delegate as! AppDelegate).listProgress[metadata.ocId] = nil }
-        #endif
-        // Delete
-        self.uploadMetadataInBackground[fileName + serverUrl] = nil
+            self.uploadMetadataInBackground[fileName + serverUrl] = nil
+            self.delegate?.uploadComplete?(fileName: fileName, serverUrl: serverUrl, ocId: ocId, etag: etag, date: date, size: size, description: description, task: task, errorCode: errorCode, errorDescription: errorDescription)
+        }
     }
 
     func uploadProgress(_ progress: Float, totalBytes: Int64, totalBytesExpected: Int64, fileName: String, serverUrl: String, session: URLSession, task: URLSessionTask) {
-        delegate?.uploadProgress?(progress, totalBytes: totalBytes, totalBytesExpected: totalBytesExpected, fileName: fileName, serverUrl: serverUrl, session: session, task: task)
+        DispatchQueue.global().async {
+            self.delegate?.uploadProgress?(progress, totalBytes: totalBytes, totalBytesExpected: totalBytesExpected, fileName: fileName, serverUrl: serverUrl, session: session, task: task)
 
-        var metadata: tableMetadata?
-        let description: String = task.taskDescription ?? ""
+            var metadata: tableMetadata?
+            let description: String = task.taskDescription ?? ""
 
-        if let metadataTmp = self.uploadMetadataInBackground[fileName+serverUrl] {
-            metadata = metadataTmp
-        } else if let metadataTmp = NCManageDatabase.shared.getMetadataFromOcId(description) {
-            self.uploadMetadataInBackground[fileName+serverUrl] = metadataTmp
-            metadata = metadataTmp
-        }
-
-        if let metadata = metadata {
-
-            #if !EXTENSION
-            // add progress ocid
-            let progressType = NCGlobal.progressType(progress: progress, totalBytes: totalBytes, totalBytesExpected: totalBytesExpected)
-            DispatchQueue.main.async { (UIApplication.shared.delegate as! AppDelegate).listProgress[metadata.ocId] = progressType }
-            #endif
+            if let metadataTmp = self.uploadMetadataInBackground[fileName+serverUrl] {
+                metadata = metadataTmp
+            } else if let metadataTmp = NCManageDatabase.shared.getMetadataFromOcId(description) {
+                self.uploadMetadataInBackground[fileName+serverUrl] = metadataTmp
+                metadata = metadataTmp
+            }
 
-            NotificationCenter.default.postOnMainThread(
-                name: NCGlobal.shared.notificationCenterProgressTask,
-                userInfo: [
-                    "account": metadata.account,
-                    "ocId": metadata.ocId,
-                    "fileName": metadata.fileName,
-                    "serverUrl": serverUrl,
-                    "status": NSNumber(value: NCGlobal.shared.metadataStatusInUpload),
-                    "progress": NSNumber(value: progress),
-                    "totalBytes": NSNumber(value: totalBytes),
-                    "totalBytesExpected": NSNumber(value: totalBytesExpected)])
+            if let metadata = metadata {
+                NotificationCenter.default.postOnMainThread(
+                    name: NCGlobal.shared.notificationCenterProgressTask,
+                    userInfo: [
+                        "account": metadata.account,
+                        "ocId": metadata.ocId,
+                        "fileName": metadata.fileName,
+                        "serverUrl": serverUrl,
+                        "status": NSNumber(value: NCGlobal.shared.metadataStatusInUpload),
+                        "progress": NSNumber(value: progress),
+                        "totalBytes": NSNumber(value: totalBytes),
+                        "totalBytesExpected": NSNumber(value: totalBytesExpected)])
+            }
         }
     }
 
@@ -677,12 +615,7 @@ import Photos
     @objc func cancelTransferMetadata(_ metadata: tableMetadata, completion: @escaping () -> Void) {
 
         let metadata = tableMetadata.init(value: metadata)
-
-        #if !EXTENSION
-        // removed progress ocid
-        DispatchQueue.main.async { (UIApplication.shared.delegate as! AppDelegate).listProgress[metadata.ocId] = nil }
-        #endif
-
+        
         if metadata.session.count == 0 {
             NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
             return completion()
@@ -752,14 +685,10 @@ import Photos
         var counter = 0
         for metadata in metadatas {
             counter += 1
-
             if metadata.status == NCGlobal.shared.metadataStatusWaitDownload || metadata.status == NCGlobal.shared.metadataStatusDownloadError {
-
                 NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: "", sessionError: "", sessionSelector: "", sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusNormal)
             }
-
             if metadata.status == NCGlobal.shared.metadataStatusDownloading || metadata.status == NCGlobal.shared.metadataStatusUploading {
-
                 self.cancelTransferMetadata(metadata) {
                     if counter == metadatas.count {
                         DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
@@ -778,14 +707,10 @@ import Photos
     func cancelAllDownloadTransfer() {
 
         let metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "status != %d", NCGlobal.shared.metadataStatusNormal))
-
         for metadata in metadatas {
-
             if metadata.status == NCGlobal.shared.metadataStatusWaitDownload || metadata.status == NCGlobal.shared.metadataStatusDownloadError {
-
                 NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: "", sessionError: "", sessionSelector: "", sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusNormal)
             }
-
             if metadata.status == NCGlobal.shared.metadataStatusDownloading && metadata.session == NCCommunicationCommon.shared.sessionIdentifierDownload {
                 cancelDownload(ocId: metadata.ocId, serverUrl: metadata.serverUrl, fileNameView: metadata.fileNameView)
             }
@@ -801,33 +726,30 @@ import Photos
     @objc func readFolder(serverUrl: String, account: String, completion: @escaping (_ account: String, _ metadataFolder: tableMetadata?, _ metadatas: [tableMetadata]?, _ metadatasUpdate: [tableMetadata]?, _ metadatasLocalUpdate: [tableMetadata]?, _ metadatasDelete: [tableMetadata]?, _ errorCode: Int, _ errorDescription: String) -> Void) {
 
         NCCommunication.shared.readFileOrFolder(serverUrlFileName: serverUrl, depth: "1", showHiddenFiles: CCUtility.getShowHiddenFiles(), queue: NCCommunicationCommon.shared.backgroundQueue) { account, files, _, errorCode, errorDescription in
+            guard errorCode == 0 else {
+                completion(account, nil, nil, nil, nil, nil, errorCode, errorDescription)
+                return
+            }
 
-            if errorCode == 0 {
-
-                NCManageDatabase.shared.convertNCCommunicationFilesToMetadatas(files, useMetadataFolder: true, account: account) { metadataFolder, metadatasFolder, metadatas in
-
-                    // Add metadata folder
-                    NCManageDatabase.shared.addMetadata(tableMetadata.init(value: metadataFolder))
-
-                    // Update directory
-                    NCManageDatabase.shared.addDirectory(encrypted: metadataFolder.e2eEncrypted, favorite: metadataFolder.favorite, ocId: metadataFolder.ocId, fileId: metadataFolder.fileId, etag: metadataFolder.etag, permissions: metadataFolder.permissions, serverUrl: serverUrl, account: metadataFolder.account)
-                    NCManageDatabase.shared.setDirectory(richWorkspace: metadataFolder.richWorkspace, serverUrl: serverUrl, account: metadataFolder.account)
+            NCManageDatabase.shared.convertNCCommunicationFilesToMetadatas(files, useMetadataFolder: true, account: account) { metadataFolder, metadatasFolder, metadatas in
 
-                    // Update sub directories NO Update richWorkspace
-                    for metadata in metadatasFolder {
-                        let serverUrl = metadata.serverUrl + "/" + metadata.fileName
-                        NCManageDatabase.shared.addDirectory(encrypted: metadata.e2eEncrypted, favorite: metadata.favorite, ocId: metadata.ocId, fileId: metadata.fileId, etag: nil, permissions: metadata.permissions, serverUrl: serverUrl, account: account)
-                    }
+                // Add metadata folder
+                NCManageDatabase.shared.addMetadata(tableMetadata.init(value: metadataFolder))
 
-                    let metadatasResult = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND status == %d", account, serverUrl, NCGlobal.shared.metadataStatusNormal))
-                    let metadatasChanged = NCManageDatabase.shared.updateMetadatas(metadatas, metadatasResult: metadatasResult, addCompareEtagLocal: true)
+                // Update directory
+                NCManageDatabase.shared.addDirectory(encrypted: metadataFolder.e2eEncrypted, favorite: metadataFolder.favorite, ocId: metadataFolder.ocId, fileId: metadataFolder.fileId, etag: metadataFolder.etag, permissions: metadataFolder.permissions, serverUrl: serverUrl, account: metadataFolder.account)
+                NCManageDatabase.shared.setDirectory(richWorkspace: metadataFolder.richWorkspace, serverUrl: serverUrl, account: metadataFolder.account)
 
-                    completion(account, metadataFolder, metadatas, metadatasChanged.metadatasUpdate, metadatasChanged.metadatasLocalUpdate, metadatasChanged.metadatasDelete, errorCode, "")
+                // Update sub directories NO Update richWorkspace
+                for metadata in metadatasFolder {
+                    let serverUrl = metadata.serverUrl + "/" + metadata.fileName
+                    NCManageDatabase.shared.addDirectory(encrypted: metadata.e2eEncrypted, favorite: metadata.favorite, ocId: metadata.ocId, fileId: metadata.fileId, etag: nil, permissions: metadata.permissions, serverUrl: serverUrl, account: account)
                 }
 
-            } else {
+                let metadatasResult = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND status == %d", account, serverUrl, NCGlobal.shared.metadataStatusNormal))
+                let metadatasChanged = NCManageDatabase.shared.updateMetadatas(metadatas, metadatasResult: metadatasResult, addCompareEtagLocal: true)
 
-                completion(account, nil, nil, nil, nil, nil, errorCode, errorDescription)
+                completion(account, metadataFolder, metadatas, metadatasChanged.metadatasUpdate, metadatasChanged.metadatasLocalUpdate, metadatasChanged.metadatasDelete, errorCode, "")
             }
         }
     }
@@ -835,19 +757,15 @@ import Photos
     @objc func readFile(serverUrlFileName: String, showHiddenFiles: Bool = CCUtility.getShowHiddenFiles(), queue: DispatchQueue = NCCommunicationCommon.shared.backgroundQueue, completion: @escaping (_ account: String, _ metadata: tableMetadata?, _ errorCode: Int, _ errorDescription: String) -> Void) {
 
         NCCommunication.shared.readFileOrFolder(serverUrlFileName: serverUrlFileName, depth: "0", showHiddenFiles: showHiddenFiles, queue: queue) { account, files, _, errorCode, errorDescription in
-
-            if errorCode == 0 && files.count == 1 {
-
-                let file = files[0]
-                let isEncrypted = CCUtility.isFolderEncrypted(file.serverUrl, e2eEncrypted: file.e2eEncrypted, account: account, urlBase: file.urlBase)
-                let metadata = NCManageDatabase.shared.convertNCFileToMetadata(file, isEncrypted: isEncrypted, account: account)
-
-                completion(account, metadata, errorCode, errorDescription)
-
-            } else {
-
+            guard errorCode == 0, files.count == 1, let file = files.first else {
                 completion(account, nil, errorCode, errorDescription)
+                return
             }
+
+            let isEncrypted = CCUtility.isFolderEncrypted(file.serverUrl, e2eEncrypted: file.e2eEncrypted, account: account, urlBase: file.urlBase)
+            let metadata = NCManageDatabase.shared.convertNCFileToMetadata(file, isEncrypted: isEncrypted, account: account)
+
+            completion(account, metadata, errorCode, errorDescription)
         }
     }
     
@@ -1034,7 +952,6 @@ import Photos
     @objc func createFolder(fileName: String, serverUrl: String, account: String, urlBase: String, overwrite: Bool = false, completion: @escaping (_ errorCode: Int, _ errorDescription: String) -> Void) {
 
         let isDirectoryEncrypted = CCUtility.isFolderEncrypted(serverUrl, e2eEncrypted: false, account: account, urlBase: urlBase)
-        
         let fileName = fileName.trimmingCharacters(in: .whitespacesAndNewlines)
         
         if isDirectoryEncrypted {
@@ -1059,33 +976,26 @@ import Photos
         let fileNameFolderUrl = serverUrl + "/" + fileNameFolder
 
         NCCommunication.shared.createFolder(fileNameFolderUrl) { account, ocId, _, errorCode, errorDescription in
-
-            if errorCode == 0 {
-
-                self.readFile(serverUrlFileName: fileNameFolderUrl) { (account, metadataFolder, errorCode, errorDescription) in
-
-                    if errorCode == 0 {
-
-                        if let metadata = metadataFolder {
-
-                            NCManageDatabase.shared.addMetadata(metadata)
-                            NCManageDatabase.shared.addDirectory(encrypted: metadata.e2eEncrypted, favorite: metadata.favorite, ocId: metadata.ocId, fileId: metadata.fileId, etag: nil, permissions: metadata.permissions, serverUrl: fileNameFolderUrl, account: account)
-                        }
-
-                        if let metadata = NCManageDatabase.shared.getMetadataFromOcId(metadataFolder?.ocId) {
-                            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterCreateFolder, userInfo: ["ocId": metadata.ocId])
-                        }
-                    }
-
+            guard errorCode == 0 else {
+                if errorCode == 405 && overwrite {
+                    completion(0, "")
+                } else {
                     completion(errorCode, errorDescription)
                 }
+                return
+            }
 
-            } else if errorCode == 405 && overwrite {
-
-                completion(0, "")
-
-            } else {
+            self.readFile(serverUrlFileName: fileNameFolderUrl) { (account, metadataFolder, errorCode, errorDescription) in
 
+                if errorCode == 0 {
+                    if let metadata = metadataFolder {
+                        NCManageDatabase.shared.addMetadata(metadata)
+                        NCManageDatabase.shared.addDirectory(encrypted: metadata.e2eEncrypted, favorite: metadata.favorite, ocId: metadata.ocId, fileId: metadata.fileId, etag: nil, permissions: metadata.permissions, serverUrl: fileNameFolderUrl, account: account)
+                    }
+                    if let metadata = NCManageDatabase.shared.getMetadataFromOcId(metadataFolder?.ocId) {
+                        NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterCreateFolder, userInfo: ["ocId": metadata.ocId])
+                    }
+                }
                 completion(errorCode, errorDescription)
             }
         }
@@ -1263,21 +1173,21 @@ import Photos
 
     @objc func listingFavoritescompletion(selector: String, completion: @escaping (_ account: String, _ metadatas: [tableMetadata]?, _ errorCode: Int, _ errorDescription: String) -> Void) {
         NCCommunication.shared.listingFavorites(showHiddenFiles: CCUtility.getShowHiddenFiles(), queue: NCCommunicationCommon.shared.backgroundQueue) { account, files, errorCode, errorDescription in
+            guard errorCode == 0 else {
+                completion(account, nil, errorCode, errorDescription)
+                return
+            }
 
-            if errorCode == 0 {
-                NCManageDatabase.shared.convertNCCommunicationFilesToMetadatas(files, useMetadataFolder: false, account: account) { _, _, metadatas in
-                    NCManageDatabase.shared.updateMetadatasFavorite(account: account, metadatas: metadatas)
-                    if selector != NCGlobal.shared.selectorListingFavorite {
-                        #if !EXTENSION
-                        for metadata in metadatas {
-                            NCOperationQueue.shared.synchronizationMetadata(metadata, selector: selector)
-                        }
-                        #endif
+            NCManageDatabase.shared.convertNCCommunicationFilesToMetadatas(files, useMetadataFolder: false, account: account) { _, _, metadatas in
+                NCManageDatabase.shared.updateMetadatasFavorite(account: account, metadatas: metadatas)
+                if selector != NCGlobal.shared.selectorListingFavorite {
+                    #if !EXTENSION
+                    for metadata in metadatas {
+                        NCOperationQueue.shared.synchronizationMetadata(metadata, selector: selector)
                     }
-                    completion(account, metadatas, errorCode, errorDescription)
+                    #endif
                 }
-            } else {
-                completion(account, nil, errorCode, errorDescription)
+                completion(account, metadatas, errorCode, errorDescription)
             }
         }
     }
@@ -1433,13 +1343,10 @@ import Photos
         NCCommunication.shared.moveFileOrFolder(serverUrlFileNameSource: serverUrlFileNameSource, serverUrlFileNameDestination: serverUrlFileNameDestination, overwrite: overwrite) { account, errorCode, errorDescription in
 
             if errorCode == 0 {
-
                 if metadata.directory {
                     NCManageDatabase.shared.deleteDirectoryAndSubDirectory(serverUrl: CCUtility.stringAppendServerUrl(metadata.serverUrl, addFileName: metadata.fileName), account: account)
                 }
-
                 NCManageDatabase.shared.moveMetadata(ocId: metadata.ocId, serverUrlTo: serverUrlTo)
-
                 NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterMoveFile, userInfo: ["ocId": metadata.ocId, "serverUrlFrom": serverUrlFrom])
             }
 
@@ -1477,10 +1384,8 @@ import Photos
         NCCommunication.shared.copyFileOrFolder(serverUrlFileNameSource: serverUrlFileNameSource, serverUrlFileNameDestination: serverUrlFileNameDestination, overwrite: overwrite) { _, errorCode, errorDescription in
 
             if errorCode == 0 {
-
                 NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterCopyFile, userInfo: ["ocId": metadata.ocId, "serverUrlTo": serverUrlTo])
             }
-
             completion(errorCode, errorDescription)
         }
     }
@@ -1490,13 +1395,9 @@ import Photos
     func getVideoUrl(metadata: tableMetadata, completition: @escaping (_ url: URL?) -> Void) {
 
         if CCUtility.fileProviderStorageExists(metadata) {
-
             completition(URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)))
-
         } else {
-
             NCCommunication.shared.getDirectDownload(fileId: metadata.fileId) { _, url, errorCode, _ in
-
                 if errorCode == 0 && url != nil {
                     if let url = URL(string: url!) {
                         completition(url)

+ 9 - 8
iOSClient/Networking/NCNetworkingChunkedUpload.swift

@@ -84,18 +84,14 @@ extension NCNetworking {
                 }, taskHandler: { task in
 
                     NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, sessionError: "", sessionTaskIdentifier: task.taskIdentifier, status: NCGlobal.shared.metadataStatusUploading)
-
-                    NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadStartFile, userInfo: ["ocId": metadata.ocId])
-
                     NCCommunicationCommon.shared.writeLog("Upload chunk: " + fileName)
 
                 }, progressHandler: { progress in
 
                     if let size = size {
-
-                        let totalBytesExpected = size + progress.completedUnitCount
-                        let totalBytes = metadata.size
-                        let fractionCompleted = Float(totalBytesExpected) / Float(totalBytes)
+                        let totalBytesExpected = metadata.size
+                        let totalBytes = size + progress.completedUnitCount
+                        let fractionCompleted = Float(totalBytes) / Float(totalBytesExpected)
 
                         NotificationCenter.default.postOnMainThread(
                             name: NCGlobal.shared.notificationCenterProgressTask,
@@ -146,7 +142,7 @@ extension NCNetworking {
             addCustomHeaders["X-OC-CTime"] = creationDate
             addCustomHeaders["X-OC-MTime"] = modificationDate
 
-            NCCommunication.shared.moveFileOrFolder(serverUrlFileNameSource: serverUrlFileNameSource, serverUrlFileNameDestination: serverUrlFileNameDestination, overwrite: true, addCustomHeaders: addCustomHeaders) { _, errorCode, errorDescription in
+            NCCommunication.shared.moveFileOrFolder(serverUrlFileNameSource: serverUrlFileNameSource, serverUrlFileNameDestination: serverUrlFileNameDestination, overwrite: true, addCustomHeaders: addCustomHeaders, queue: DispatchQueue.global(qos: .background)) { _, errorCode, errorDescription in
 
                 NCCommunicationCommon.shared.writeLog("Assembling chunk with error code: \(errorCode)")
 
@@ -158,6 +154,8 @@ extension NCNetworking {
 
                 let serverUrl = metadata.serverUrl
                 let assetLocalIdentifier = metadata.assetLocalIdentifier
+                let isLivePhoto = metadata.livePhoto
+                let isE2eEncrypted = metadata.e2eEncrypted
 
                 NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
                 NCManageDatabase.shared.deleteChunks(account: metadata.account, ocId: metadata.ocId)
@@ -168,6 +166,9 @@ extension NCNetworking {
                     if errorCode == 0, let metadata = metadata {
 
                         metadata.assetLocalIdentifier = assetLocalIdentifier
+                        metadata.e2eEncrypted = isE2eEncrypted
+                        metadata.livePhoto = isLivePhoto
+
                         // Delete Asset on Photos album
                         if CCUtility.getRemovePhotoCameraRoll() && !metadata.assetLocalIdentifier.isEmpty {
                             metadata.deleteAssetLocalIdentifier = true

+ 0 - 12
iOSClient/Networking/NCNetworkingE2EE.swift

@@ -202,7 +202,6 @@ import Alamofire
         // Verify max size
         if metadata.size > NCGlobal.shared.e2eeMaxFileSize {
             NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp))
-
             NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "ocIdTemp": ocIdTemp, "errorCode": NCGlobal.shared.errorInternalError, "errorDescription": "E2E Error file too big"])
             start()
             return completion(NCGlobal.shared.errorInternalError, "E2E Error file too big")
@@ -221,7 +220,6 @@ import Alamofire
         let serverUrlFileName = serverUrl + "/" + metadata.fileName
 
         if NCEndToEndEncryption.sharedManager()?.encryptFileName(metadata.fileNameView, fileNameIdentifier: metadata.fileName, directory: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId), key: &key, initializationVector: &initializationVector, authenticationTag: &authenticationTag) == false {
-
             NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp))
             NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "ocIdTemp": ocIdTemp, "errorCode": NCGlobal.shared.errorInternalError, "errorDescription": "_e2e_error_create_encrypted_"])
             start()
@@ -258,9 +256,7 @@ import Alamofire
         }
 
         NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl])
-
         NCContentPresenter.shared.noteTop(text: NSLocalizedString("_upload_e2ee_", comment: ""), image: nil, type: NCContentPresenter.messageType.info, delay: NCGlobal.shared.dismissAfterSecond, priority: .max)
-
         NCNetworkingE2EE.shared.sendE2EMetadata(account: metadata.account, serverUrl: serverUrl, fileNameRename: nil, fileNameNewRename: nil, deleteE2eEncryption: nil, urlBase: metadata.urlBase, upload: true) { e2eToken, errorCode, errorDescription in
 
             start()
@@ -271,7 +267,6 @@ import Alamofire
 
                     NCNetworking.shared.uploadRequest[fileNameLocalPathRequest] = request
                     NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: nil, sessionSelector: nil, sessionTaskIdentifier: nil, status: NCGlobal.shared.metadataStatusUploading)
-
                     NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadStartFile, userInfo: ["ocId": metadata.ocId])
 
                 }, taskHandler: { _ in
@@ -293,11 +288,7 @@ import Alamofire
                 }) { account, ocId, etag, date, _, _, error, errorCode, errorDescription in
 
                     NCNetworking.shared.uploadRequest[fileNameLocalPath] = nil
-
                     if let metadata = NCManageDatabase.shared.getMetadataFromOcId(metadata.ocId) {
-
-                        let metadata = tableMetadata.init(value: metadata)
-
                         if error?.isExplicitlyCancelledError ?? false {
 
                             CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
@@ -323,7 +314,6 @@ import Alamofire
                             NCManageDatabase.shared.addLocalFile(metadata: metadata)
 
                             NCUtility.shared.createImageFrom(fileNameView: metadata.fileNameView, ocId: metadata.ocId, etag: metadata.etag, classFile: metadata.classFile)
-
                             NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
 
                         } else {
@@ -343,7 +333,6 @@ import Alamofire
                             NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
                         }
                     }
-
                     NCNetworkingE2EE.shared.unlock(account: metadata.account, serverUrl: serverUrl) { _, _, _, _ in
                         completion(errorCode, errorDescription)
                     }
@@ -353,7 +342,6 @@ import Alamofire
 
                 if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocIdTemp) {
                     NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: errorDescription, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusUploadError)
-
                     NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": errorDescription])
                 }
                 completion(errorCode, errorDescription)

+ 56 - 101
iOSClient/Networking/NCNetworkingProcessUpload.swift

@@ -38,7 +38,7 @@ class NCNetworkingProcessUpload: NSObject {
         startTimer()
     }
 
-    @objc func startProcess() {
+    private func startProcess() {
         if timerProcess?.isValid ?? false {
             DispatchQueue.main.async { self.process() }
         }
@@ -56,18 +56,17 @@ class NCNetworkingProcessUpload: NSObject {
     @objc private func process() {
         guard !appDelegate.account.isEmpty else { return }
 
-        let queue = DispatchQueue.global(qos: .background)
+        stopTimer()
+
         let applicationState = UIApplication.shared.applicationState
         var counterUpload: Int = 0
         let sessionSelectors = [NCGlobal.shared.selectorUploadFile, NCGlobal.shared.selectorUploadAutoUpload, NCGlobal.shared.selectorUploadAutoUploadAll]
         let metadatasUpload = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "status == %d OR status == %d", NCGlobal.shared.metadataStatusInUpload, NCGlobal.shared.metadataStatusUploading))
         counterUpload = metadatasUpload.count
 
-        stopTimer()
-
         print("[LOG] PROCESS-UPLOAD \(counterUpload)")
 
-        NCNetworking.shared.getOcIdInBackgroundSession(queue: queue, completion: { listOcId in
+        NCNetworking.shared.getOcIdInBackgroundSession(queue: DispatchQueue.global(qos: .background), completion: { listOcId in
 
             for sessionSelector in sessionSelectors {
                 if counterUpload < self.maxConcurrentOperationUpload {
@@ -105,33 +104,27 @@ class NCNetworkingProcessUpload: NSObject {
                             }
                         }
 
-                        let (metadataForUpload, metadataLivePhotoForUpload) = self.extractFiles(from: metadata, queue: queue)
-
-                        // Upload
-                        if let metadata = metadataForUpload {
-                            if (metadata.e2eEncrypted || metadata.chunk) && applicationState != .active { continue }
-                            if let metadata = NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusInUpload) {
-                                NCNetworking.shared.upload(metadata: metadata)
-                            }
-                            if metadata.e2eEncrypted || metadata.chunk {
-                                counterUpload = self.maxConcurrentOperationUpload
-                            } else {
-                                counterUpload += 1
-                            }
-                        }
-
-                        // Upload Live photo
-                        if let metadata = metadataLivePhotoForUpload {
-                            if (metadata.e2eEncrypted || metadata.chunk) && applicationState != .active { continue }
-                            if let metadata = NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusInUpload) {
-                                NCNetworking.shared.upload(metadata: metadata)
+                        let semaphore = Semaphore()
+                        self.extractFiles(from: metadata) { metadatas in
+                            if metadatas.isEmpty {
+                                NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
                             }
-                            if metadata.e2eEncrypted || metadata.chunk {
-                                counterUpload = self.maxConcurrentOperationUpload
-                            } else {
-                                counterUpload += 1
+                            for metadata in metadatas {
+                                if (metadata.e2eEncrypted || metadata.chunk) && applicationState != .active {  continue }
+                                let isWiFi = NCNetworking.shared.networkReachability == NCCommunicationCommon.typeReachability.reachableEthernetOrWiFi
+                                if metadata.session == NCNetworking.shared.sessionIdentifierBackgroundWWan && !isWiFi { continue }
+                                if let metadata = NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusInUpload) {
+                                    NCNetworking.shared.upload(metadata: metadata)
+                                }
+                                if metadata.e2eEncrypted || metadata.chunk {
+                                    counterUpload = self.maxConcurrentOperationUpload
+                                } else {
+                                    counterUpload += 1
+                                }
                             }
+                            semaphore.continue()
                         }
+                        semaphore.wait()
                     }
                 }
             }
@@ -187,89 +180,51 @@ class NCNetworkingProcessUpload: NSObject {
 
     // MARK: -
 
-    func extractFiles(from metadata: tableMetadata, queue: DispatchQueue) -> (metadataForUpload: tableMetadata?, metadataLivePhotoForUpload: tableMetadata?) {
+    func extractFiles(from metadata: tableMetadata, completition: @escaping (_ metadatas: [tableMetadata]) -> Void) {
 
-        var metadataForUpload: tableMetadata?
-        var metadataLivePhotoForUpload: tableMetadata?
         let chunckSize = CCUtility.getChunkSize() * 1000000
-        let semaphore = Semaphore()
-
-        guard queue != .main else { return(nil, nil) }
-        guard !metadata.assetLocalIdentifier.isEmpty else {
-            let filePath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileName)!
-            metadata.size = NCUtilityFileSystem.shared.getFileSize(filePath: filePath)
-            let results = NCCommunicationCommon.shared.getInternalType(fileName: metadata.fileNameView, mimeType: metadata.contentType, directory: false)
-            metadata.contentType = results.mimeType
-            metadata.iconName = results.iconName
-            metadata.classFile = results.classFile
-            if let date = NCUtilityFileSystem.shared.getFileCreationDate(filePath: filePath) { metadata.creationDate = date }
-            if let date =  NCUtilityFileSystem.shared.getFileModificationDate(filePath: filePath) { metadata.date = date }
-            // DETECT IF CHUNCK
-            if chunckSize > 0 && metadata.size > chunckSize {
-                metadata.chunk = true
-                metadata.session = NCCommunicationCommon.shared.sessionIdentifierUpload
-            }
-            // DETECT IF E2EE
-            if CCUtility.isFolderEncrypted(metadata.serverUrl, e2eEncrypted: metadata.e2eEncrypted, account: metadata.account, urlBase: metadata.urlBase) {
-                metadata.e2eEncrypted = true
+        var metadatas: [tableMetadata] = []
+        let metadataSource = tableMetadata.init(value: metadata)
+
+        guard !metadata.isExtractFile else { return  completition([metadataSource]) }
+        guard !metadataSource.assetLocalIdentifier.isEmpty else {
+            let filePath = CCUtility.getDirectoryProviderStorageOcId(metadataSource.ocId, fileNameView: metadataSource.fileName)!
+            metadataSource.size = NCUtilityFileSystem.shared.getFileSize(filePath: filePath)
+            let results = NCCommunicationCommon.shared.getInternalType(fileName: metadataSource.fileNameView, mimeType: metadataSource.contentType, directory: false)
+            metadataSource.contentType = results.mimeType
+            metadataSource.iconName = results.iconName
+            metadataSource.classFile = results.classFile
+            if let date = NCUtilityFileSystem.shared.getFileCreationDate(filePath: filePath) { metadataSource.creationDate = date }
+            if let date =  NCUtilityFileSystem.shared.getFileModificationDate(filePath: filePath) { metadataSource.date = date }
+            metadata.chunk = chunckSize != 0 && metadata.size > chunckSize
+            metadata.e2eEncrypted = CCUtility.isFolderEncrypted(metadata.serverUrl, e2eEncrypted: metadata.e2eEncrypted, account: metadata.account, urlBase: metadata.urlBase)
+            metadataSource.isExtractFile = true
+            if let metadata = NCManageDatabase.shared.addMetadata(metadataSource) {
+                metadatas.append(metadata)
             }
-            let metadata = NCManageDatabase.shared.addMetadata(metadata)
-            return (metadata, nil)
+            return completition(metadatas)
         }
 
-        CCUtility.extractImageVideoFromAssetLocalIdentifier(forUpload: metadata, queue: queue) { extractMetadata, fileNamePath in
-            if let metadata = extractMetadata {
+        NCUtility.shared.extractImageVideoFromAssetLocalIdentifier(metadata: metadataSource, modifyMetadataForUpload: true) { metadata, fileNamePath, returnError in
+            if let metadata = metadata, let fileNamePath = fileNamePath, !returnError {
+                metadatas.append(metadata)
                 let toPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
-                NCUtilityFileSystem.shared.moveFile(atPath: fileNamePath!, toPath: toPath)
-                metadata.size = NCUtilityFileSystem.shared.getFileSize(filePath: toPath)
-                // DETECT IF CHUNCK
-                if chunckSize > 0 && metadata.size > chunckSize {
-                    metadata.chunk = true
-                    metadata.session = NCCommunicationCommon.shared.sessionIdentifierUpload
-                }
-                // DETECT IF E2EE
-                if CCUtility.isFolderEncrypted(metadata.serverUrl, e2eEncrypted: metadata.e2eEncrypted, account: metadata.account, urlBase: metadata.urlBase) {
-                    metadata.e2eEncrypted = true
-                }
-                // update
-                metadataForUpload = NCManageDatabase.shared.addMetadata(metadata)
+                NCUtilityFileSystem.shared.moveFile(atPath: fileNamePath, toPath: toPath)
+            } else {
+                return completition(metadatas)
             }
-            semaphore.continue()
-        }
-        semaphore.wait()
-
-        if metadataForUpload == nil {
-            NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
-            return (nil, nil)
-        }
-
-        let fetchAssets = PHAsset.fetchAssets(withLocalIdentifiers: [metadata.assetLocalIdentifier], options: nil)
-        if metadata.livePhoto, fetchAssets.count > 0  {
-            let ocId = NSUUID().uuidString
-            let fileName = (metadata.fileName as NSString).deletingPathExtension + ".mov"
-            let filePath = CCUtility.getDirectoryProviderStorageOcId(ocId, fileNameView: fileName)!
-            CCUtility.extractLivePhotoAsset(fetchAssets.firstObject, filePath: filePath, queue: queue) { url in
-                if url != nil {
-                    let metadataLivePhoto = NCManageDatabase.shared.createMetadata(account: metadata.account, user: metadata.user, userId: metadata.userId, fileName: fileName, fileNameView: fileName, ocId: ocId, serverUrl: metadata.serverUrl, urlBase: metadata.urlBase, url: "", contentType: "", isLivePhoto: true)
-                    metadataLivePhoto.classFile = NCCommunicationCommon.typeClassFile.video.rawValue
-                    metadataLivePhoto.e2eEncrypted = metadata.e2eEncrypted
-                    metadataLivePhoto.isAutoupload = metadata.isAutoupload
-                    metadataLivePhoto.session = metadata.session
-                    metadataLivePhoto.sessionSelector = metadata.sessionSelector
-                    metadataLivePhoto.size = NCUtilityFileSystem.shared.getFileSize(filePath: filePath)
-                    metadataLivePhoto.status = metadata.status
-                    if chunckSize > 0 && metadataLivePhoto.size > chunckSize {
-                        metadataLivePhoto.chunk = true
-                        metadataLivePhoto.session = NCCommunicationCommon.shared.sessionIdentifierUpload
+            let fetchAssets = PHAsset.fetchAssets(withLocalIdentifiers: [metadataSource.assetLocalIdentifier], options: nil)
+            if metadataSource.livePhoto, fetchAssets.count > 0  {
+                NCUtility.shared.createMetadataLivePhotoFromMetadata(metadataSource, asset: fetchAssets.firstObject) { metadata in
+                    if let metadata = metadata, let metadata = NCManageDatabase.shared.addMetadata(metadata) {
+                        metadatas.append(metadata)
                     }
-                    metadataLivePhotoForUpload = NCManageDatabase.shared.addMetadata(metadataLivePhoto)
+                    completition(metadatas)
                 }
-                semaphore.continue()
+            } else {
+                completition(metadatas)
             }
-            semaphore.wait()
         }
-
-        return(metadataForUpload, metadataLivePhotoForUpload)
     }
 
     // MARK: -

+ 15 - 28
iOSClient/Networking/NCOperationQueue.swift

@@ -37,7 +37,7 @@ import NCCommunication
     private let synchronizationQueue = Queuer(name: "synchronizationQueue", maxConcurrentOperationCount: 1, qualityOfService: .default)
     private let downloadThumbnailQueue = Queuer(name: "downloadThumbnailQueue", maxConcurrentOperationCount: 10, qualityOfService: .default)
     private let downloadAvatarQueue = Queuer(name: "downloadAvatarQueue", maxConcurrentOperationCount: 10, qualityOfService: .default)
-    private let dataSourceQueue = Queuer(name: "dataSourceQueue", maxConcurrentOperationCount: 1, qualityOfService: .default)
+    private let unifiedSearchQueue = Queuer(name: "unifiedSearchQueue", maxConcurrentOperationCount: 1, qualityOfService: .default)
 
     private var timerReadFileForMediaQueue: Timer?
 
@@ -48,10 +48,10 @@ import NCCommunication
         synchronizationCancelAll()
         downloadThumbnailCancelAll()
         downloadAvatarCancelAll()
-        dataSourceAddSectionCancelAll()
+        unifiedSearchCancelAll()
     }
 
-    // Download file
+    // MARK: - Download file
 
     func download(metadata: tableMetadata, selector: String) {
         for operation in downloadQueue.operations as! [NCOperationDownload] {
@@ -64,7 +64,7 @@ import NCCommunication
     @objc func downloadCancelAll() {
         downloadQueue.cancelAll()
     }
-    @objc func downloadCount() -> Int {
+    @objc func downloadQueueCount() -> Int {
         return downloadQueue.operationCount
     }
     @objc func downloadExists(metadata: tableMetadata) -> Bool {
@@ -76,7 +76,7 @@ import NCCommunication
         return false
     }
 
-    // Delete file
+    // MARK: - Delete file
 
     @objc func delete(metadata: tableMetadata, onlyLocalCache: Bool) {
         for operation in deleteQueue.operations as! [NCOperationDelete] {
@@ -89,11 +89,8 @@ import NCCommunication
     @objc func deleteCancelAll() {
         deleteQueue.cancelAll()
     }
-    @objc func deleteCount() -> Int {
-        return deleteQueue.operationCount
-    }
 
-    // Copy Move file
+    // MARK: - Copy Move file
 
     @objc func copyMove(metadata: tableMetadata, serverUrl: String, overwrite: Bool, move: Bool) {
         for operation in copyMoveQueue.operations as! [NCOperationCopyMove] {
@@ -106,11 +103,8 @@ import NCCommunication
     @objc func copyMoveCancelAll() {
         copyMoveQueue.cancelAll()
     }
-    @objc func copyMoveCount() -> Int {
-        return copyMoveQueue.operationCount
-    }
 
-    // Synchronization
+    // MARK: - Synchronization
 
     @objc func synchronizationMetadata(_ metadata: tableMetadata, selector: String) {
         for operation in synchronizationQueue.operations as! [NCOperationSynchronization] {
@@ -124,7 +118,7 @@ import NCCommunication
         synchronizationQueue.cancelAll()
     }
 
-    // Download Thumbnail
+    // MARK: - Download Thumbnail
 
     @objc func downloadThumbnail(metadata: tableMetadata, placeholder: Bool, cell: UIView?, view: UIView?) {
 
@@ -160,7 +154,7 @@ import NCCommunication
         downloadThumbnailQueue.cancelAll()
     }
 
-    // Download Avatar
+    // MARK: - Download Avatar
 
     func downloadAvatar(user: String, dispalyName: String?, fileName: String, cell: NCCellProtocol, view: UIView?, cellImageView: UIImageView?) {
 
@@ -199,18 +193,14 @@ import NCCommunication
         downloadAvatarQueue.cancelAll()
     }
 
-    // Datasource
+    // MARK: - Unified Search
 
-    func dataSourceAddSection(collectionViewCommon: NCCollectionViewCommon, metadatas: [tableMetadata], searchResult: NCCSearchResult) {
-        dataSourceQueue.addOperation(NCOperationDataSource.init(collectionViewCommon: collectionViewCommon, metadatas: metadatas, searchResult: searchResult))
+    func unifiedSearchAddSection(collectionViewCommon: NCCollectionViewCommon, metadatas: [tableMetadata], searchResult: NCCSearchResult) {
+        unifiedSearchQueue.addOperation(NCOperationUnifiedSearch.init(collectionViewCommon: collectionViewCommon, metadatas: metadatas, searchResult: searchResult))
     }
 
-    @objc func dataSourceAddSectionCancelAll() {
-        dataSourceQueue.cancelAll()
-    }
-
-    func dataSourceAddSectionCount() -> Int {
-        return dataSourceQueue.operationCount
+    @objc func unifiedSearchCancelAll() {
+        unifiedSearchQueue.cancelAll()
     }
 }
 
@@ -542,7 +532,7 @@ class NCOperationDownloadAvatar: ConcurrentOperation {
 
 // MARK: -
 
-class NCOperationDataSource: ConcurrentOperation {
+class NCOperationUnifiedSearch: ConcurrentOperation {
 
     var collectionViewCommon: NCCollectionViewCommon
     var metadatas: [tableMetadata]
@@ -569,9 +559,6 @@ class NCOperationDataSource: ConcurrentOperation {
             self.finish()
         } else {
             self.collectionViewCommon.dataSource.addSection(metadatas: metadatas, searchResult: searchResult)
-            for metadata in self.metadatas {
-                self.collectionViewCommon.metadatasSource.append(metadata)
-            }
             self.collectionViewCommon.searchResults?.append(self.searchResult)
             reloadDataThenPerform {
                 self.finish()

+ 21 - 22
iOSClient/Offline/NCOffline.swift

@@ -47,42 +47,41 @@ class NCOffline: NCCollectionViewCommon {
     override func reloadDataSource(forced: Bool = true) {
         super.reloadDataSource()
 
-        var ocIds: [String] = []
+        DispatchQueue.global().async {
+            var ocIds: [String] = []
+            var metadatas: [tableMetadata] = []
 
-        if !self.isSearching {
             if self.serverUrl.isEmpty {
                 if let directories = NCManageDatabase.shared.getTablesDirectory(predicate: NSPredicate(format: "account == %@ AND offline == true", self.appDelegate.account), sorted: "serverUrl", ascending: true) {
                     for directory: tableDirectory in directories {
                         ocIds.append(directory.ocId)
                     }
                 }
-
                 let files = NCManageDatabase.shared.getTableLocalFiles(predicate: NSPredicate(format: "account == %@ AND offline == true", self.appDelegate.account), sorted: "fileName", ascending: true)
                 for file in files {
                     ocIds.append(file.ocId)
                 }
-
-                self.metadatasSource = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND ocId IN %@", self.appDelegate.account, ocIds))
+                metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND ocId IN %@", self.appDelegate.account, ocIds))
             } else {
-                self.metadatasSource = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
+                metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
             }
-        }
 
-        self.dataSource = NCDataSource(
-            metadatasSource: self.metadatasSource,
-            account: self.appDelegate.account,
-            sort: self.layoutForView?.sort,
-            ascending: self.layoutForView?.ascending,
-            directoryOnTop: self.layoutForView?.directoryOnTop,
-            favoriteOnTop: true,
-            filterLivePhoto: true,
-            groupByField: self.groupByField,
-            providers: self.providers,
-            searchResults: self.searchResults)
-
-        DispatchQueue.main.async {
-            self.refreshControl.endRefreshing()
-            self.collectionView.reloadData()
+            self.dataSource = NCDataSource(
+                metadatas: metadatas,
+                account: self.appDelegate.account,
+                sort: self.layoutForView?.sort,
+                ascending: self.layoutForView?.ascending,
+                directoryOnTop: self.layoutForView?.directoryOnTop,
+                favoriteOnTop: true,
+                filterLivePhoto: true,
+                groupByField: self.groupByField,
+                providers: self.providers,
+                searchResults: self.searchResults)
+
+            DispatchQueue.main.async {
+                self.refreshControl.endRefreshing()
+                self.collectionView.reloadData()
+            }
         }
     }
 

+ 2 - 3
iOSClient/Recent/NCRecent.swift

@@ -48,9 +48,8 @@ class NCRecent: NCCollectionViewCommon {
         super.reloadDataSource()
 
         DispatchQueue.global().async {
-
-            self.metadatasSource = NCManageDatabase.shared.getAdvancedMetadatas(predicate: NSPredicate(format: "account == %@", self.appDelegate.account), page: 1, limit: 100, sorted: "date", ascending: false)
-            self.dataSource = NCDataSource(metadatasSource: self.metadatasSource,
+            let metadatas = NCManageDatabase.shared.getAdvancedMetadatas(predicate: NSPredicate(format: "account == %@", self.appDelegate.account), page: 1, limit: 100, sorted: "date", ascending: false)
+            self.dataSource = NCDataSource(metadatas: metadatas,
                                            account: self.appDelegate.account,
                                            directoryOnTop: false,
                                            favoriteOnTop: false,

+ 3 - 4
iOSClient/Select/NCSelect.swift

@@ -625,7 +625,7 @@ extension NCSelect: UICollectionViewDataSource {
 
                 header.setButtonsCommand(heigt: 0)
                 header.setButtonsView(heigt: NCGlobal.shared.heightButtonsView)
-                header.setStatusButtonsView(enable: !dataSource.metadatasSource.isEmpty)
+                header.setStatusButtonsView(enable: !dataSource.getMetadataSourceForAllSections().isEmpty)
                 header.setSortedTitle(layoutForView?.titleButtonHeader ?? "")
 
                 header.setRichWorkspaceHeight(heightHeaderRichWorkspace)
@@ -749,9 +749,8 @@ extension NCSelect {
             }
         }
 
-
-        let metadatasSource = NCManageDatabase.shared.getMetadatas(predicate: predicate!)
-        self.dataSource = NCDataSource(metadatasSource: metadatasSource,
+        let metadatas = NCManageDatabase.shared.getMetadatas(predicate: predicate!)
+        self.dataSource = NCDataSource(metadatas: metadatas,
                                        account: activeAccount.account,
                                        sort: layoutForView?.sort,
                                        ascending: layoutForView?.ascending,

+ 4 - 4
iOSClient/Shares/NCShares.swift

@@ -48,17 +48,17 @@ class NCShares: NCCollectionViewCommon {
         super.reloadDataSource()
 
         DispatchQueue.global().async {
-            self.metadatasSource.removeAll()
             let sharess = NCManageDatabase.shared.getTableShares(account: self.appDelegate.account)
+            var metadatas: [tableMetadata] = []
             for share in sharess {
                 if let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", self.appDelegate.account, share.serverUrl, share.fileName)) {
-                    if !(self.metadatasSource.contains { $0.ocId == metadata.ocId }) {
-                        self.metadatasSource.append(metadata)
+                    if !(metadatas.contains { $0.ocId == metadata.ocId }) {
+                        metadatas.append(metadata)
                     }
                 }
             }
 
-            self.dataSource = NCDataSource(metadatasSource: self.metadatasSource,
+            self.dataSource = NCDataSource(metadatas: metadatas,
                                            account: self.appDelegate.account,
                                            sort: self.layoutForView?.sort,
                                            ascending: self.layoutForView?.ascending,

+ 21 - 29
iOSClient/Transfers/NCTransfers.swift

@@ -130,16 +130,12 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
         guard appDelegate.account == metadata.account else { return }
         guard let networkingProcessUpload = appDelegate.networkingProcessUpload else { return }
 
-        let (metadataForUpload, metadataLivePhotoForUpload) = networkingProcessUpload.extractFiles(from: metadata, queue: DispatchQueue.global(qos: .background))
-
-        // Upload
-        if let metadata = metadataForUpload, let metadata = NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusInUpload) {
-            NCNetworking.shared.upload(metadata: metadata)
-        }
-
-        // Upload Live photo
-        if let metadata = metadataLivePhotoForUpload, let metadata = NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusInUpload) {
-            NCNetworking.shared.upload(metadata: metadata)
+        networkingProcessUpload.extractFiles(from: metadata) { metadatas in
+            for metadata in metadatas {
+                if let metadata = NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusInUpload) {
+                    NCNetworking.shared.upload(metadata: metadata)
+                }
+            }
         }
     }
 
@@ -220,17 +216,8 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
 
         cell.labelInfo.text = CCUtility.dateDiff(metadata.date as Date) + " · " + CCUtility.transformedSize(metadata.size)
 
-        // Transfer
-        var progress: Float = 0.0
-        var totalBytes: Int64 = 0
-        if let progressType = appDelegate.listProgress[metadata.ocId] {
-            progress = progressType.progress
-            totalBytes = progressType.totalBytes
-        }
-
         if metadata.status == NCGlobal.shared.metadataStatusDownloading || metadata.status == NCGlobal.shared.metadataStatusUploading {
             cell.progressView.isHidden = false
-            cell.progressView.progress = progress
         } else {
             cell.progressView.isHidden = true
         }
@@ -247,11 +234,11 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
             break
         case NCGlobal.shared.metadataStatusDownloading:
             cell.labelStatus.text = NSLocalizedString("_status_downloading_", comment: "")
-            cell.labelInfo.text = CCUtility.transformedSize(metadata.size) + " - ↓ " + CCUtility.transformedSize(totalBytes)
+            cell.labelInfo.text = CCUtility.transformedSize(metadata.size) + " - ↓ "
             break
         case NCGlobal.shared.metadataStatusWaitUpload:
             cell.labelStatus.text = NSLocalizedString("_status_wait_upload_", comment: "")
-            cell.labelInfo.text = CCUtility.transformedSize(metadata.size)
+            cell.labelInfo.text = ""
             break
         case NCGlobal.shared.metadataStatusInUpload:
             cell.labelStatus.text = NSLocalizedString("_status_in_upload_", comment: "")
@@ -259,11 +246,11 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
             break
         case NCGlobal.shared.metadataStatusUploading:
             cell.labelStatus.text = NSLocalizedString("_status_uploading_", comment: "")
-            cell.labelInfo.text = CCUtility.transformedSize(metadata.size) + " - ↑ " + CCUtility.transformedSize(totalBytes)
+            cell.labelInfo.text = CCUtility.transformedSize(metadata.size) + " - ↑ "
             break
         case NCGlobal.shared.metadataStatusUploadError:
             cell.labelStatus.text = NSLocalizedString("_status_upload_error_", comment: "")
-            cell.labelInfo.text = CCUtility.transformedSize(metadata.size)
+            cell.labelInfo.text = metadata.sessionError
             break
         default:
             cell.labelStatus.text = ""
@@ -271,9 +258,10 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
             break
         }
         if self.appDelegate.account != metadata.account {
-            cell.labelInfo.text = NSLocalizedString("_waiting_for_", comment: "") + " " + NSLocalizedString("_user_", comment: "") + ": \(metadata.userId) " + NSLocalizedString("_in_", comment: "") + " \(metadata.urlBase)"
+            cell.labelInfo.text = NSLocalizedString("_waiting_for_", comment: "") + " " + NSLocalizedString("_user_", comment: "").lowercased() + " \(metadata.userId) " + NSLocalizedString("_in_", comment: "") + " \(metadata.urlBase)"
         }
-        if metadata.session == NCNetworking.shared.sessionIdentifierBackgroundWWan && NCNetworking.shared.networkReachability != NCCommunicationCommon.typeReachability.reachableEthernetOrWiFi {
+        let isWiFi = NCNetworking.shared.networkReachability == NCCommunicationCommon.typeReachability.reachableEthernetOrWiFi
+        if metadata.session == NCNetworking.shared.sessionIdentifierBackgroundWWan && !isWiFi {
             cell.labelInfo.text = NSLocalizedString("_waiting_for_", comment: "") + " " + NSLocalizedString("_reachable_wifi_", comment: "")
         }
         
@@ -294,11 +282,15 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
     override func reloadDataSource(forced: Bool = true) {
         super.reloadDataSource()
 
-        metadatasSource = NCManageDatabase.shared.getAdvancedMetadatas(predicate: NSPredicate(format: "status != %i", NCGlobal.shared.metadataStatusNormal), page: 1, limit: 100, sorted: "sessionTaskIdentifier", ascending: false)
-        self.dataSource = NCDataSource(metadatasSource: metadatasSource, account: self.appDelegate.account)
+        DispatchQueue.global().async {
+            let metadatas = NCManageDatabase.shared.getAdvancedMetadatas(predicate: NSPredicate(format: "status != %i", NCGlobal.shared.metadataStatusNormal), page: 1, limit: 100, sorted: "sessionTaskIdentifier", ascending: false)
+            self.dataSource = NCDataSource(metadatas: metadatas, account: self.appDelegate.account)
 
-        refreshControl.endRefreshing()
-        collectionView.reloadData()
+            DispatchQueue.main.async {
+                self.refreshControl.endRefreshing()
+                self.collectionView.reloadData()
+            }
+        }
     }
 
     override func reloadDataSourceNetwork(forced: Bool = false) {

+ 6 - 6
iOSClient/UserStatus/NCUserStatus.storyboard

@@ -333,9 +333,9 @@
                                         <nil key="highlightedColor"/>
                                     </label>
                                     <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="3CT-dJ-sEj">
-                                        <rect key="frame" x="10" y="67" width="192.66666666666666" height="30"/>
+                                        <rect key="frame" x="10" y="57" width="192.66666666666666" height="40"/>
                                         <constraints>
-                                            <constraint firstAttribute="height" constant="30" id="1F4-Cv-RzK"/>
+                                            <constraint firstAttribute="height" constant="40" id="1F4-Cv-RzK"/>
                                         </constraints>
                                         <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                         <state key="normal" title="clear status message"/>
@@ -344,9 +344,9 @@
                                         </connections>
                                     </button>
                                     <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="3xN-e7-N0L">
-                                        <rect key="frame" x="225.33333333333337" y="67" width="192.66666666666663" height="30"/>
+                                        <rect key="frame" x="225.33333333333337" y="57" width="192.66666666666663" height="40"/>
                                         <constraints>
-                                            <constraint firstAttribute="height" constant="30" id="66i-0j-Qrn"/>
+                                            <constraint firstAttribute="height" constant="40" id="66i-0j-Qrn"/>
                                         </constraints>
                                         <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                         <state key="normal" title="set status message"/>
@@ -359,9 +359,9 @@
                                 <constraints>
                                     <constraint firstAttribute="trailing" secondItem="isA-Km-19L" secondAttribute="trailing" constant="10" id="6Tt-c6-ue6"/>
                                     <constraint firstItem="isA-Km-19L" firstAttribute="leading" secondItem="rha-b0-jMR" secondAttribute="trailing" constant="10" id="GfS-dA-0gf"/>
-                                    <constraint firstItem="3xN-e7-N0L" firstAttribute="top" secondItem="rha-b0-jMR" secondAttribute="bottom" constant="40" id="KVL-2d-xDr"/>
+                                    <constraint firstItem="3xN-e7-N0L" firstAttribute="top" secondItem="rha-b0-jMR" secondAttribute="bottom" constant="30" id="KVL-2d-xDr"/>
                                     <constraint firstItem="rha-b0-jMR" firstAttribute="leading" secondItem="LVo-6E-efl" secondAttribute="leading" constant="10" id="L1H-XE-sur"/>
-                                    <constraint firstItem="3CT-dJ-sEj" firstAttribute="top" secondItem="rha-b0-jMR" secondAttribute="bottom" constant="40" id="P6x-uB-lne"/>
+                                    <constraint firstItem="3CT-dJ-sEj" firstAttribute="top" secondItem="rha-b0-jMR" secondAttribute="bottom" constant="30" id="P6x-uB-lne"/>
                                     <constraint firstItem="3CT-dJ-sEj" firstAttribute="leading" secondItem="LVo-6E-efl" secondAttribute="leading" constant="10" id="ceW-Ca-9iB"/>
                                     <constraint firstAttribute="trailing" secondItem="3xN-e7-N0L" secondAttribute="trailing" constant="10" id="egg-HN-e1j"/>
                                     <constraint firstItem="rha-b0-jMR" firstAttribute="top" secondItem="LVo-6E-efl" secondAttribute="top" constant="10" id="mZV-JR-YrU"/>

+ 2 - 2
iOSClient/UserStatus/NCUserStatus.swift

@@ -148,7 +148,7 @@ class NCUserStatus: UIViewController {
         clearStatusMessageAfterText.addGestureRecognizer(tap)
         clearStatusMessageAfterText.text = "  " + NSLocalizedString("_dont_clear_", comment: "")
 
-        clearStatusMessageButton.layer.cornerRadius = 15
+        clearStatusMessageButton.layer.cornerRadius = 20
         clearStatusMessageButton.layer.masksToBounds = true
         clearStatusMessageButton.layer.borderWidth = 0.5
         clearStatusMessageButton.layer.borderColor = UIColor.darkGray.cgColor
@@ -156,7 +156,7 @@ class NCUserStatus: UIViewController {
         clearStatusMessageButton.setTitle(NSLocalizedString("_clear_status_message_", comment: ""), for: .normal)
         clearStatusMessageButton.setTitleColor(NCBrandColor.shared.label, for: .normal)
 
-        setStatusMessageButton.layer.cornerRadius = 15
+        setStatusMessageButton.layer.cornerRadius = 20
         setStatusMessageButton.layer.masksToBounds = true
         setStatusMessageButton.backgroundColor = NCBrandColor.shared.brand
         setStatusMessageButton.setTitle(NSLocalizedString("_set_status_message_", comment: ""), for: .normal)

+ 0 - 3
iOSClient/Utility/CCUtility.h

@@ -243,9 +243,6 @@
 
 + (NSString *)getMimeType:(NSString *)fileNameView;
 
-+ (void)extractImageVideoFromAssetLocalIdentifierForUpload:(tableMetadata *)metadataForUpload queue:(dispatch_queue_t)queue completion:(void(^)(tableMetadata *newMetadata, NSString* fileNamePath))completion;
-+ (void)extractLivePhotoAsset:(PHAsset*)asset filePath:(NSString *)filePath queue:(dispatch_queue_t)queue withCompletion:(void (^)(NSURL* url))completion;
-
 // ===== E2E Encrypted =====
 
 + (NSString *)generateRandomIdentifier;

+ 0 - 176
iOSClient/Utility/CCUtility.m

@@ -1352,182 +1352,6 @@
     return path;
 }
 
-+ (void)extractImageVideoFromAssetLocalIdentifierForUpload:(tableMetadata *)metadataForUpload queue:(dispatch_queue_t)queue completion:(void(^)(tableMetadata *metadata, NSString* fileNamePath))completion
-{
-    if (metadataForUpload == nil) {
-        dispatch_async(queue, ^{
-            completion(nil, nil);
-        });
-        return;
-    }
-    
-    tableMetadata *metadata = [[NCManageDatabase shared] copyObjectWithMetadata:metadataForUpload];
-    
-    PHFetchResult *result = [PHAsset fetchAssetsWithLocalIdentifiers:@[metadata.assetLocalIdentifier] options:nil];
-    if (!result.count) {
-        dispatch_async(queue, ^{
-            completion(nil, nil);
-        });
-        return;
-    }
-    
-    PHAsset *asset = result[0];
-    NSDate *creationDate = asset.creationDate;
-    NSDate *modificationDate = asset.modificationDate;
-
-    // IMAGE
-    if (asset.mediaType == PHAssetMediaTypeImage) {
-
-        PHImageRequestOptions *options = [PHImageRequestOptions new];
-        options.networkAccessAllowed = YES;
-        options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
-        options.synchronous = YES;
-        options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
-
-            NSLog(@"cacheAsset: %f", progress);
-
-            if (error) {
-                [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:NCGlobal.shared.notificationCenterUploadedFile object:nil userInfo:@{@"ocId": metadata.ocId, @"errorCode": @(error.code), @"errorDescription": [NSString stringWithFormat:@"Image request iCloud failed [%@]", error.description]}];
-                dispatch_async(queue, ^{
-                    completion(nil, nil);
-                });
-                return;
-            }
-        };
-
-        NSString *extensionAsset = [[[asset valueForKey:@"filename"] pathExtension] uppercaseString];
-
-        //raw image will always ignore any edits made to the photo if compatibility is false
-        if ([extensionAsset isEqualToString:@"DNG"]) {
-            options.version = PHImageRequestOptionsVersionOriginal;
-        }
-
-        [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
-
-            NSError *error = nil;
-            NSString *fileName = metadata.fileNameView;
-
-            if (([extensionAsset isEqualToString:@"HEIC"] || [extensionAsset isEqualToString:@"DNG"]) && [CCUtility getFormatCompatibility]) {
-
-                CIImage *ciImage = [CIImage imageWithData:imageData];
-                CIContext *context = [CIContext context];
-                imageData = [context JPEGRepresentationOfImage:ciImage colorSpace:ciImage.colorSpace options:@{}];
-
-                NSString *fileNameJPEG = [[metadata.fileName lastPathComponent] stringByDeletingPathExtension];
-                fileName = [fileNameJPEG stringByAppendingString:@".jpg"];
-                metadata.contentType = @"image/jpeg";
-                metadata.ext = @"jpg";
-            }
-
-            NSString *fileNamePath = [NSTemporaryDirectory() stringByAppendingString:fileName];
-
-            [[NSFileManager defaultManager]removeItemAtPath:fileNamePath error:nil];
-            [imageData writeToFile:fileNamePath options:NSDataWritingAtomic error:&error];
-
-            if (metadata.e2eEncrypted) {
-                metadata.fileNameView = fileName;
-            } else {
-                metadata.fileNameView = fileName;
-                metadata.fileName = fileName;
-            }
-
-            metadata.creationDate = creationDate;
-            metadata.date = modificationDate;
-            metadata.size = [[NCUtilityFileSystem shared] getFileSizeWithFilePath:fileNamePath];
-
-            dispatch_async(queue, ^{
-                completion(metadata, fileNamePath);
-            });
-        }];
-    }
-
-    // VIDEO
-    if (asset.mediaType == PHAssetMediaTypeVideo) {
-
-        PHVideoRequestOptions *options = [PHVideoRequestOptions new];
-        options.networkAccessAllowed = YES;
-        options.version = PHVideoRequestOptionsVersionOriginal;
-        options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
-
-            NSLog(@"cacheAsset: %f", progress);
-
-            if (error) {
-                [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:NCGlobal.shared.notificationCenterUploadedFile object:nil userInfo:@{@"ocId": metadata.ocId, @"errorCode": @(error.code), @"errorDescription": [NSString stringWithFormat:@"Video request iCloud failed [%@]", error.description]}];
-                dispatch_async(queue, ^{
-                    completion(nil, nil);
-                });
-                return;
-            }
-        };
-
-        [[PHImageManager defaultManager] requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) {
-
-            if ([asset isKindOfClass:[AVURLAsset class]]) {
-
-                NSString *fileNamePath = [NSTemporaryDirectory() stringByAppendingString:metadata.fileNameView];
-                NSURL *fileNamePathURL = [[NSURL alloc] initFileURLWithPath:fileNamePath];
-                NSError *error = nil;
-
-                [[NSFileManager defaultManager] removeItemAtURL:fileNamePathURL error:nil];
-                [[NSFileManager defaultManager] copyItemAtURL:[(AVURLAsset *)asset URL] toURL:fileNamePathURL error:&error];
-
-                dispatch_async(queue, ^{
-                    if (error) {
-                        [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:NCGlobal.shared.notificationCenterUploadedFile object:nil userInfo:@{@"ocId": metadata.ocId, @"errorCode": @(error.code), @"errorDescription": [NSString stringWithFormat:@"Video request iCloud failed [%@]", error.description]}];
-                        completion(nil, nil);
-                    } else {
-                        metadata.creationDate = creationDate;
-                        metadata.date = modificationDate;
-                        metadata.size = [[NCUtilityFileSystem shared] getFileSizeWithFilePath:fileNamePath];
-                        completion(metadata, fileNamePath);
-                    }
-                });
-            }
-        }];
-    }
-}
-
-+ (void)extractLivePhotoAsset:(PHAsset*)asset filePath:(NSString *)filePath queue:(dispatch_queue_t)queue withCompletion:(void (^)(NSURL* url))completion
-{    
-    [CCUtility removeFileAtPath:filePath];
-    NSURL *fileUrl = [NSURL fileURLWithPath:filePath];
-    PHLivePhotoRequestOptions *options = [PHLivePhotoRequestOptions new];
-    options.deliveryMode = PHImageRequestOptionsDeliveryModeFastFormat;
-    options.networkAccessAllowed = YES;
-    
-    [[PHImageManager defaultManager] requestLivePhotoForAsset:asset targetSize:[UIScreen mainScreen].bounds.size contentMode:PHImageContentModeDefault options:options resultHandler:^(PHLivePhoto * _Nullable livePhoto, NSDictionary * _Nullable info) {
-        if (livePhoto) {
-            NSArray *assetResources = [PHAssetResource assetResourcesForLivePhoto:livePhoto];
-            PHAssetResource *videoResource = nil;
-            for(PHAssetResource *resource in assetResources){
-                if (resource.type == PHAssetResourceTypePairedVideo) {
-                    videoResource = resource;
-                    break;
-                }
-            }
-            if(videoResource){
-                [[PHAssetResourceManager defaultManager] writeDataForAssetResource:videoResource toFile:fileUrl options:nil completionHandler:^(NSError * _Nullable error) {
-                    dispatch_async(queue, ^{
-                        if (!error) {
-                            completion(fileUrl);
-                        } else {
-                            completion(nil);
-                        }
-                    });
-                }];
-            } else {
-                dispatch_async(queue, ^{
-                    completion(nil);
-                });
-            }
-        } else {
-            dispatch_async(queue, ^{
-                completion(nil);
-            });
-        }
-    }];
-}
-
 #pragma --------------------------------------------------------------------------------------------
 #pragma mark ===== E2E Encrypted =====
 #pragma --------------------------------------------------------------------------------------------

+ 147 - 2
iOSClient/Utility/NCUtility.swift

@@ -28,8 +28,8 @@ import NCCommunication
 import PDFKit
 import Accelerate
 import CoreMedia
-
-// MARK: - NCUtility
+import Queuer
+import Photos
 
 class NCUtility: NSObject {
     @objc static let shared: NCUtility = {
@@ -400,6 +400,151 @@ class NCUtility: NSObject {
 
     // MARK: -
 
+    func extractImageVideoFromAssetLocalIdentifier(metadata: tableMetadata, modifyMetadataForUpload: Bool, completion: @escaping (_ metadata: tableMetadata?, _ fileNamePath: String?, _ error: Bool) -> ()) {
+
+        var fileNamePath: String?
+        let metadata = tableMetadata.init(value: metadata)
+        let chunckSize = CCUtility.getChunkSize() * 1000000
+        var compatibilityFormat: Bool = false
+
+        func callCompletion(error: Bool) {
+            if error {
+                completion(nil, nil, true)
+            } else {
+                var metadataReturn = metadata
+                if modifyMetadataForUpload {
+                    metadata.chunk = chunckSize != 0 && metadata.size > chunckSize
+                    metadata.e2eEncrypted = CCUtility.isFolderEncrypted(metadata.serverUrl, e2eEncrypted: metadata.e2eEncrypted, account: metadata.account, urlBase: metadata.urlBase)
+                    metadata.isExtractFile = true
+                    if let metadata = NCManageDatabase.shared.addMetadata(metadata) {
+                        metadataReturn = metadata
+                    }
+                }
+                completion(metadataReturn, fileNamePath, error)
+            }
+        }
+
+        let fetchAssets = PHAsset.fetchAssets(withLocalIdentifiers: [metadata.assetLocalIdentifier], options: nil)
+        guard fetchAssets.count > 0, let asset = fetchAssets.firstObject, let extensionAsset = (asset.value(forKey: "filename") as? NSString)?.pathExtension.uppercased() else {
+            return callCompletion(error: true)
+        }
+
+        if asset.mediaType == PHAssetMediaType.image && (extensionAsset == "HEIC" || extensionAsset == "DNG") && CCUtility.getFormatCompatibility() {
+            let fileName = (metadata.fileNameView as NSString).deletingPathExtension + ".jpg"
+            metadata.contentType = "image/jpeg"
+            metadata.ext = "jpg"
+            fileNamePath = NSTemporaryDirectory() + fileName
+            metadata.fileNameView = fileName
+            if !metadata.e2eEncrypted {
+                metadata.fileName = fileName
+            }
+            compatibilityFormat = true
+        } else {
+            fileNamePath = NSTemporaryDirectory() + metadata.fileNameView
+        }
+        guard let fileNamePath = fileNamePath, let creationDate = asset.creationDate, let modificationDate = asset.modificationDate else {
+            return callCompletion(error: true)
+        }
+
+        if asset.mediaType == PHAssetMediaType.image {
+
+            let options = PHImageRequestOptions()
+            options.isNetworkAccessAllowed = true
+            options.deliveryMode = PHImageRequestOptionsDeliveryMode.highQualityFormat
+            options.isSynchronous = true
+            if extensionAsset == "DNG" {
+                options.version = PHImageRequestOptionsVersion.original
+            }
+            options.progressHandler = { (progress, error, stop, info) in
+                print(progress)
+                if error != nil { return callCompletion(error: true) }
+            }
+
+            PHImageManager.default().requestImageData(for: asset, options: options) { data, dataUI, orientation, info in
+                guard var data = data else { return callCompletion(error: true) }
+                if compatibilityFormat {
+                    guard let ciImage = CIImage.init(data: data), let colorSpace = ciImage.colorSpace, let dataJPEG = CIContext().jpegRepresentation(of: ciImage, colorSpace: colorSpace) else { return callCompletion(error: true) }
+                    data = dataJPEG
+                }
+                NCUtilityFileSystem.shared.deleteFile(filePath: fileNamePath)
+                do {
+                    try data.write(to: URL(fileURLWithPath: fileNamePath), options: .atomic)
+                } catch {
+                    return callCompletion(error: true)
+                }
+                metadata.creationDate = creationDate as NSDate
+                metadata.date = modificationDate as NSDate
+                metadata.size = NCUtilityFileSystem.shared.getFileSize(filePath: fileNamePath)
+                return callCompletion(error: false)
+            }
+
+        } else if asset.mediaType == PHAssetMediaType.video {
+            
+            let options = PHVideoRequestOptions()
+            options.isNetworkAccessAllowed = true
+            options.version = PHVideoRequestOptionsVersion.original
+            options.progressHandler = { (progress, error, stop, info) in
+                print(progress)
+                if error != nil { return callCompletion(error: true) }
+            }
+
+            PHImageManager.default().requestAVAsset(forVideo: asset, options: options) { asset, audioMix, info in
+                guard let asset = asset as? AVURLAsset else { return callCompletion(error: true) }
+                NCUtilityFileSystem.shared.deleteFile(filePath: fileNamePath)
+                do {
+                    try FileManager.default.copyItem(at: asset.url, to: URL(fileURLWithPath: fileNamePath))
+                } catch {
+                    return callCompletion(error: true)
+                }
+                metadata.creationDate = creationDate as NSDate
+                metadata.date = modificationDate as NSDate
+                metadata.size = NCUtilityFileSystem.shared.getFileSize(filePath: fileNamePath)
+                return callCompletion(error: false)
+            }
+        } else {
+            return callCompletion(error: true)
+        }
+    }
+
+    func createMetadataLivePhotoFromMetadata(_ metadata: tableMetadata, asset: PHAsset?, completion: @escaping (_ metadata: tableMetadata?) -> ()) {
+
+        guard let asset = asset else { return completion(nil) }
+        let options = PHLivePhotoRequestOptions()
+        options.deliveryMode = PHImageRequestOptionsDeliveryMode.fastFormat
+        options.isNetworkAccessAllowed = true
+        let chunckSize = CCUtility.getChunkSize() * 1000000
+        let ocId = NSUUID().uuidString
+        let fileName = (metadata.fileName as NSString).deletingPathExtension + ".mov"
+        let fileNamePath = CCUtility.getDirectoryProviderStorageOcId(ocId, fileNameView: fileName)!
+
+        PHImageManager.default().requestLivePhoto(for: asset, targetSize: UIScreen.main.bounds.size, contentMode: PHImageContentMode.default, options: options) { livePhoto, info in
+            guard let livePhoto = livePhoto else { return completion(nil) }
+            var videoResource: PHAssetResource?
+            for resource in PHAssetResource.assetResources(for: livePhoto) {
+                if resource.type == PHAssetResourceType.pairedVideo {
+                    videoResource = resource
+                    break
+                }
+            }
+            guard let videoResource = videoResource else { return completion(nil) }
+            NCUtilityFileSystem.shared.deleteFile(filePath: fileNamePath)
+            PHAssetResourceManager.default().writeData(for: videoResource, toFile: URL(fileURLWithPath: fileNamePath), options: nil) { error in
+                if error != nil { return completion(nil) }
+                let metadataLivePhoto = NCManageDatabase.shared.createMetadata(account: metadata.account, user: metadata.user, userId: metadata.userId, fileName: fileName, fileNameView: fileName, ocId: ocId, serverUrl: metadata.serverUrl, urlBase: metadata.urlBase, url: "", contentType: "", isLivePhoto: true)
+                metadataLivePhoto.classFile = NCCommunicationCommon.typeClassFile.video.rawValue
+                metadataLivePhoto.e2eEncrypted = metadata.e2eEncrypted
+                metadataLivePhoto.isAutoupload = metadata.isAutoupload
+                metadataLivePhoto.isExtractFile = true
+                metadataLivePhoto.session = metadata.session
+                metadataLivePhoto.sessionSelector = metadata.sessionSelector
+                metadataLivePhoto.size = NCUtilityFileSystem.shared.getFileSize(filePath: fileNamePath)
+                metadataLivePhoto.status = metadata.status
+                metadataLivePhoto.chunk = chunckSize != 0 && metadata.size > chunckSize
+                return completion(NCManageDatabase.shared.addMetadata(metadataLivePhoto))
+            }
+        }
+    }
+
     func imageFromVideo(url: URL, at time: TimeInterval) -> UIImage? {
 
         let asset = AVURLAsset(url: url)

+ 6 - 1
iOSClient/Viewer/NCViewerMedia/NCViewerMediaDetailView.swift

@@ -79,7 +79,12 @@ class NCViewerMediaDetailView: UIView {
         self.mapView = nil
     }
 
-    func show(metadata: tableMetadata, image: UIImage?, textColor: UIColor?, mediaMetadata: NCImageMetadata, ncplayer: NCPlayer?, delegate: NCViewerMediaDetailViewDelegate?) {
+    func show(metadata: tableMetadata,
+              image: UIImage?,
+              textColor: UIColor?,
+              mediaMetadata: NCImageMetadata,
+              ncplayer: NCPlayer?,
+              delegate: NCViewerMediaDetailViewDelegate?) {
 
         self.metadata = metadata
         self.latitude = mediaMetadata.latitude