Browse Source

Merge pull request #2558 from nextcloud/chunk

Chunk new
Marino Faggiana 1 year ago
parent
commit
cf7063bf56

+ 1 - 1
Brand/Database.swift

@@ -26,4 +26,4 @@ import Foundation
 // Database Realm
 //
 let databaseName                    = "nextcloud.realm"
-let databaseSchemaVersion: UInt64   = 301
+let databaseSchemaVersion: UInt64   = 304

+ 16 - 10
Nextcloud.xcodeproj/project.pbxproj

@@ -300,6 +300,13 @@
 		F74AF3A4247FB6AE00AC767B /* NCUtilityFileSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74AF3A3247FB6AE00AC767B /* NCUtilityFileSystem.swift */; };
 		F74AF3A5247FB6AE00AC767B /* NCUtilityFileSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74AF3A3247FB6AE00AC767B /* NCUtilityFileSystem.swift */; };
 		F74AF3A6247FB6AE00AC767B /* NCUtilityFileSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74AF3A3247FB6AE00AC767B /* NCUtilityFileSystem.swift */; };
+		F74B6D952A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74B6D942A7E239A00F03C5F /* NCManageDatabase+Chunk.swift */; };
+		F74B6D962A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74B6D942A7E239A00F03C5F /* NCManageDatabase+Chunk.swift */; };
+		F74B6D972A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74B6D942A7E239A00F03C5F /* NCManageDatabase+Chunk.swift */; };
+		F74B6D982A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74B6D942A7E239A00F03C5F /* NCManageDatabase+Chunk.swift */; };
+		F74B6D992A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74B6D942A7E239A00F03C5F /* NCManageDatabase+Chunk.swift */; };
+		F74B6D9A2A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74B6D942A7E239A00F03C5F /* NCManageDatabase+Chunk.swift */; };
+		F74B6D9B2A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74B6D942A7E239A00F03C5F /* NCManageDatabase+Chunk.swift */; };
 		F74C0436253F1CDC009762AB /* NCShares.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74C0434253F1CDC009762AB /* NCShares.swift */; };
 		F74C0437253F1CDC009762AB /* NCShares.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F74C0435253F1CDC009762AB /* NCShares.storyboard */; };
 		F74DE14325135B6800917068 /* NCTransfers.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74DE14125135B6800917068 /* NCTransfers.swift */; };
@@ -505,7 +512,6 @@
 		F793E59E28B763C2005E4B02 /* NCAskAuthorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = F733598025C1C188002ABA72 /* NCAskAuthorization.swift */; };
 		F793E59F28B764F6005E4B02 /* NCContentPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F765608E23BF813500765969 /* NCContentPresenter.swift */; };
 		F793E5A128B76541005E4B02 /* NotificationCenter+MainThread.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70460512499061800BB98A7 /* NotificationCenter+MainThread.swift */; };
-		F793E5A228B76580005E4B02 /* NCNetworkingChunkedUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B8CD90261AF3F7007C1359 /* NCNetworkingChunkedUpload.swift */; };
 		F798F0E225880608000DAFFD /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extension.swift */; };
 		F798F0E725880609000DAFFD /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extension.swift */; };
 		F798F0EC2588060A000DAFFD /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extension.swift */; };
@@ -563,9 +569,6 @@
 		F7B6B70427C4E7FA00A7F6EB /* NCScan+CollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B6B70327C4E7FA00A7F6EB /* NCScan+CollectionView.swift */; };
 		F7B7504B2397D38F004E13EC /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extension.swift */; };
 		F7B8B83025681C3400967775 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = F7B8B82F25681C3400967775 /* GoogleService-Info.plist */; };
-		F7B8CD91261AF3F7007C1359 /* NCNetworkingChunkedUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B8CD90261AF3F7007C1359 /* NCNetworkingChunkedUpload.swift */; };
-		F7B8CD96261AF401007C1359 /* NCNetworkingChunkedUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B8CD90261AF3F7007C1359 /* NCNetworkingChunkedUpload.swift */; };
-		F7B8CD9B261AF401007C1359 /* NCNetworkingChunkedUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B8CD90261AF3F7007C1359 /* NCNetworkingChunkedUpload.swift */; };
 		F7BAADC81ED5A87C00B7EAD4 /* NCDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB41ED5A87C00B7EAD4 /* NCDatabase.swift */; };
 		F7BAADC91ED5A87C00B7EAD4 /* NCDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB41ED5A87C00B7EAD4 /* NCDatabase.swift */; };
 		F7BAADCB1ED5A87C00B7EAD4 /* NCManageDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB51ED5A87C00B7EAD4 /* NCManageDatabase.swift */; };
@@ -990,6 +993,7 @@
 		F749B650297B0F2400087535 /* NCManageDatabase+Avatar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+Avatar.swift"; sourceTree = "<group>"; };
 		F74AF3A3247FB6AE00AC767B /* NCUtilityFileSystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCUtilityFileSystem.swift; sourceTree = "<group>"; };
 		F74AFCE822E8B024003DE61F /* FSCalendar.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FSCalendar.framework; path = Carthage/Build/iOS/FSCalendar.framework; sourceTree = "<group>"; };
+		F74B6D942A7E239A00F03C5F /* NCManageDatabase+Chunk.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+Chunk.swift"; sourceTree = "<group>"; };
 		F74C0434253F1CDC009762AB /* NCShares.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCShares.swift; sourceTree = "<group>"; };
 		F74C0435253F1CDC009762AB /* NCShares.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCShares.storyboard; sourceTree = "<group>"; };
 		F74C4FBA2328C3C100A23E25 /* OpenSSL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenSSL.framework; path = Carthage/Build/iOS/OpenSSL.framework; sourceTree = "<group>"; };
@@ -1213,7 +1217,6 @@
 		F7B6B70327C4E7FA00A7F6EB /* NCScan+CollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCScan+CollectionView.swift"; sourceTree = "<group>"; };
 		F7B7504A2397D38E004E13EC /* UIImage+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Extension.swift"; sourceTree = "<group>"; };
 		F7B8B82F25681C3400967775 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "GoogleService-Info.plist"; sourceTree = SOURCE_ROOT; };
-		F7B8CD90261AF3F7007C1359 /* NCNetworkingChunkedUpload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCNetworkingChunkedUpload.swift; sourceTree = "<group>"; };
 		F7BAADB41ED5A87C00B7EAD4 /* NCDatabase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCDatabase.swift; sourceTree = "<group>"; };
 		F7BAADB51ED5A87C00B7EAD4 /* NCManageDatabase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCManageDatabase.swift; sourceTree = "<group>"; };
 		F7BB04851FD58ACB00BBFD2A /* cs-CZ */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "cs-CZ"; path = "cs-CZ.lproj/Localizable.strings"; sourceTree = "<group>"; };
@@ -1853,7 +1856,6 @@
 				F72CD63925C19EBF00F46F9A /* NCAutoUpload.swift */,
 				F75A9EE523796C6F0044CFCE /* NCNetworking.swift */,
 				F7D96FCB246ED7E100536D73 /* NCNetworkingCheckRemoteUser.swift */,
-				F7B8CD90261AF3F7007C1359 /* NCNetworkingChunkedUpload.swift */,
 				F70D8D8024A4A9BF000A5756 /* NCNetworkingProcessUpload.swift */,
 				F72A47EB2487B06B005AD489 /* NCOperationQueue.swift */,
 				F755BD9A20594AC7008C5FBB /* NCService.swift */,
@@ -2172,6 +2174,7 @@
 				F7C1EEA425053A9C00866ACC /* NCDataSource.swift */,
 				F7BAADB51ED5A87C00B7EAD4 /* NCManageDatabase.swift */,
 				AF4BF613275629E20081CEEF /* NCManageDatabase+Account.swift */,
+				F74B6D942A7E239A00F03C5F /* NCManageDatabase+Chunk.swift */,
 				AF4BF61D27562B3F0081CEEF /* NCManageDatabase+Activity.swift */,
 				F749B650297B0F2400087535 /* NCManageDatabase+Avatar.swift */,
 				F763D29C2A249C4500A3C901 /* NCManageDatabase+Capabilities.swift */,
@@ -3321,6 +3324,7 @@
 				F763D2A32A249C4500A3C901 /* NCManageDatabase+Capabilities.swift in Sources */,
 				F749B656297B0F2400087535 /* NCManageDatabase+Avatar.swift in Sources */,
 				F782FDC424E6933900666099 /* NCUtility.swift in Sources */,
+				F74B6D9B2A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -3366,6 +3370,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				F74B6D9A2A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */,
 				F7490E8329882C84009DCE94 /* NCManageDatabase+LayoutForView.swift in Sources */,
 				F7490E7629882BF3009DCE94 /* NCUserBaseUrl.swift in Sources */,
 				F7490E8029882C76009DCE94 /* NCManageDatabase+Avatar.swift in Sources */,
@@ -3412,6 +3417,7 @@
 				AF4BF61F27562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */,
 				F7A0D1362591FBC5008F8A13 /* String+Extension.swift in Sources */,
 				F7EDE4D6262D7B9600414FE6 /* NCListCell.swift in Sources */,
+				F74B6D982A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */,
 				F7707687263A853700A1BA94 /* NCContentPresenter.swift in Sources */,
 				F343A4B62A1E084200DDA874 /* PHAsset+Extension.swift in Sources */,
 				F70460532499095400BB98A7 /* NotificationCenter+MainThread.swift in Sources */,
@@ -3448,7 +3454,6 @@
 				F72FD3B8297ED49A00075D28 /* NCManageDatabase+E2EE.swift in Sources */,
 				F7EDE4E0262D7BAF00414FE6 /* NCGridCell.swift in Sources */,
 				F7A76DC8256A71CD00119AB3 /* UIImage+Extension.swift in Sources */,
-				F7B8CD96261AF401007C1359 /* NCNetworkingChunkedUpload.swift in Sources */,
 				F763D2A02A249C4500A3C901 /* NCManageDatabase+Capabilities.swift in Sources */,
 				F757CC8529E7F88B00F31428 /* NCManageDatabase+Groupfolders.swift in Sources */,
 				F7BAADC91ED5A87C00B7EAD4 /* NCDatabase.swift in Sources */,
@@ -3503,6 +3508,7 @@
 				F793E59D28B761E7005E4B02 /* NCNetworking.swift in Sources */,
 				F7BF9D832934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */,
 				F757CC8329E7F88B00F31428 /* NCManageDatabase+Groupfolders.swift in Sources */,
+				F74B6D962A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */,
 				F749B652297B0F2400087535 /* NCManageDatabase+Avatar.swift in Sources */,
 				F783030628B4C51E00B84583 /* String+Extension.swift in Sources */,
 				F763D29E2A249C4500A3C901 /* NCManageDatabase+Capabilities.swift in Sources */,
@@ -3512,7 +3518,6 @@
 				F78302FB28B4C3EE00B84583 /* NCManageDatabase+Video.swift in Sources */,
 				F72EA95228B7BA2A00C88F0C /* DashboardWidgetProvider.swift in Sources */,
 				F343A4BC2A1E734600DDA874 /* Optional+Extension.swift in Sources */,
-				F793E5A228B76580005E4B02 /* NCNetworkingChunkedUpload.swift in Sources */,
 				F783031228B4C8EC00B84583 /* CCUtility.m in Sources */,
 				F72EA95828B7BC4F00C88F0C /* FilesData.swift in Sources */,
 				F793E59E28B763C2005E4B02 /* NCAskAuthorization.swift in Sources */,
@@ -3548,6 +3553,7 @@
 				F343A4B72A1E084300DDA874 /* PHAsset+Extension.swift in Sources */,
 				F7434B3620E23FE000417916 /* NCManageDatabase.swift in Sources */,
 				F798F0E725880609000DAFFD /* UIColor+Extension.swift in Sources */,
+				F74B6D992A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */,
 				F7D68FCF28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */,
 				F7864AD02A78FE73004870E0 /* NCManageDatabase+LocalFile.swift in Sources */,
 				AF4BF61B27562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */,
@@ -3561,7 +3567,6 @@
 				F749B64E297B0CBB00087535 /* NCManageDatabase+Share.swift in Sources */,
 				AF817EF3274BC781009ED85B /* NCUserBaseUrl.swift in Sources */,
 				F771E3F320E239A600AFB62D /* FileProviderData.swift in Sources */,
-				F7B8CD9B261AF401007C1359 /* NCNetworkingChunkedUpload.swift in Sources */,
 				F7A0D1372591FBC5008F8A13 /* String+Extension.swift in Sources */,
 				F771E3D720E2392D00AFB62D /* FileProviderEnumerator.swift in Sources */,
 				F74AF3A6247FB6AE00AC767B /* NCUtilityFileSystem.swift in Sources */,
@@ -3646,7 +3651,6 @@
 				F7BAADC81ED5A87C00B7EAD4 /* NCDatabase.swift in Sources */,
 				F75C0C4823D1FAE300163CC8 /* NCRichWorkspaceCommon.swift in Sources */,
 				F78ACD4A21903F850088454D /* NCTrashListCell+NCTrashCellProtocol.swift in Sources */,
-				F7B8CD91261AF3F7007C1359 /* NCNetworkingChunkedUpload.swift in Sources */,
 				F757CC8D29E82D0500F31428 /* NCGroupfolders.swift in Sources */,
 				F760329F252F0F8E0015A421 /* NCTransferCell.swift in Sources */,
 				F3BB46542A3A1E9D00461F6E /* CCCellMore.swift in Sources */,
@@ -3671,6 +3675,7 @@
 				8491B1CD273BBA82001C8C5B /* UIViewController+Menu.swift in Sources */,
 				F761856C29E98543006EB3B0 /* NCIntroCollectionViewCell.swift in Sources */,
 				F75DD765290ABB25002EB562 /* Intent.intentdefinition in Sources */,
+				F74B6D952A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */,
 				F702F2F725EE5CED008F8E80 /* NCLogin.swift in Sources */,
 				F7E98C1627E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */,
 				F7F4F11227ECDC52008676F9 /* UIFont+Extension.swift in Sources */,
@@ -3792,6 +3797,7 @@
 				F75DD767290ABB25002EB562 /* Intent.intentdefinition in Sources */,
 				F749B64C297B0CBB00087535 /* NCManageDatabase+Share.swift in Sources */,
 				F7A8D73F28F181EF008BBE1C /* NCGlobal.swift in Sources */,
+				F74B6D972A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */,
 				F749B653297B0F2400087535 /* NCManageDatabase+Avatar.swift in Sources */,
 				F763D29F2A249C4500A3C901 /* NCManageDatabase+Capabilities.swift in Sources */,
 				F7A8D74328F1826F008BBE1C /* String+Extension.swift in Sources */,

+ 10 - 4
Share/NCShareExtension.swift

@@ -65,7 +65,6 @@ class NCShareExtension: UIViewController {
     var autoUploadDirectory = ""
     let refreshControl = UIRefreshControl()
     var activeAccount: tableAccount!
-    let chunckSize = CCUtility.getChunkSize() * 1000000
     var progress: CGFloat = 0
     var counterUploaded: Int = 0
     var uploadErrors: [tableMetadata] = []
@@ -337,8 +336,16 @@ extension NCShareExtension {
         metadata.contentType = results.mimeType
         metadata.iconName = results.iconName
         metadata.classFile = results.classFile
-        // CHUNCK
-        metadata.chunk = chunckSize != 0 && metadata.size > chunckSize
+        // CHUNK
+        var chunkSize = NCGlobal.shared.chunkSizeMBCellular
+        if NCNetworking.shared.networkReachability == NKCommon.TypeReachability.reachableEthernetOrWiFi {
+            chunkSize = NCGlobal.shared.chunkSizeMBEthernetOrWiFi
+        }
+        if metadata.size > chunkSize {
+            metadata.chunk = chunkSize
+        } else {
+            metadata.chunk = 0
+        }
         // E2EE
         metadata.e2eEncrypted = metadata.isDirectoryE2EE
 
@@ -353,7 +360,6 @@ extension NCShareExtension {
             if error != .success {
                 let path = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId)!
                 NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
-                NCManageDatabase.shared.deleteChunks(account: metadata.account, ocId: metadata.ocId)
                 NCUtilityFileSystem.shared.deleteFile(filePath: path)
                 self.uploadErrors.append(metadata)
             }

+ 0 - 14
iOSClient/Data/NCDatabase.swift

@@ -30,20 +30,6 @@ protocol DateCompareable {
     var dateKey: Date { get }
 }
 
-class tableChunk: Object {
-
-    @objc dynamic var account = ""
-    @objc dynamic var chunkFolder = ""
-    @objc dynamic var fileName = ""
-    @objc dynamic var index = ""
-    @objc dynamic var ocId = ""
-    @objc dynamic var size: Int64 = 0
-
-    override static func primaryKey() -> String {
-        return "index"
-    }
-}
-
 class tableComments: Object, DateCompareable {
     var dateKey: Date { creationDateTime as Date }
 

+ 127 - 0
iOSClient/Data/NCManageDatabase+Chunk.swift

@@ -0,0 +1,127 @@
+//
+//  NCManageDatabase+Chunk.swift
+//  Nextcloud
+//
+//  Created by Marino Faggiana on 05/08/23.
+//  Copyright © 2023 Marino Faggiana. All rights reserved.
+//
+//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+import Foundation
+import RealmSwift
+import NextcloudKit
+
+class tableChunk: Object {
+
+    @Persisted var account = ""
+    @Persisted var chunkFolder = ""
+    @Persisted(primaryKey: true) var index = ""
+    @Persisted var fileName: Int = 0
+    @Persisted var ocId = ""
+    @Persisted var size: Int64 = 0
+}
+
+extension NCManageDatabase {
+
+    func getChunkFolder(account: String, ocId: String) -> String {
+
+        do {
+            let realm = try Realm()
+            realm.refresh()
+            guard let result = realm.objects(tableChunk.self).filter("account == %@ AND ocId == %@", account, ocId).first else { return NSUUID().uuidString }
+            return result.chunkFolder
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
+
+        return NSUUID().uuidString
+    }
+
+    func getChunks(account: String, ocId: String) -> [(fileName: String, size: Int64)] {
+
+        var filesChunk: [(fileName: String, size: Int64)] = []
+
+        do {
+            let realm = try Realm()
+            realm.refresh()
+            let results = realm.objects(tableChunk.self).filter("account == %@ AND ocId == %@", account, ocId).sorted(byKeyPath: "fileName", ascending: true)
+            for result in results {
+                filesChunk.append((fileName: "\(result.fileName)", size: result.size))
+            }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
+
+        return filesChunk
+    }
+
+    func addChunks(account: String, ocId: String, chunkFolder: String, filesChunk: [(fileName: String, size: Int64)]) {
+
+        do {
+            let realm = try Realm()
+            try realm.write {
+                let results = realm.objects(tableChunk.self).filter(NSPredicate(format: "account == %@ AND ocId == %@", account, ocId))
+                realm.delete(results)
+                for fileChunk in filesChunk {
+                    let object = tableChunk()
+                    object.account = account
+                    object.chunkFolder = chunkFolder
+                    object.fileName = Int(fileChunk.fileName) ?? 0
+                    object.index = ocId + fileChunk.fileName
+                    object.ocId = ocId
+                    object.size = fileChunk.size
+                    realm.add(object, update: .all)
+                }
+            }
+        } catch let error {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
+    }
+
+    func deleteChunk(account: String, ocId: String, fileChunk: (fileName: String, size: Int64), directory: String) {
+
+        do {
+            let realm = try Realm()
+            try realm.write {
+                let result = realm.objects(tableChunk.self).filter(NSPredicate(format: "account == %@ AND ocId == %@ AND fileName == %d", account, ocId, Int(fileChunk.fileName) ?? 0))
+                realm.delete(result)
+                let filePath = directory + "/\(fileChunk.fileName)"
+                NCUtilityFileSystem.shared.deleteFile(filePath: filePath)
+            }
+        } catch let error {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
+    }
+
+    func deleteChunks(account: String, ocId: String, directory: String) {
+
+        do {
+            let realm = try Realm()
+            try realm.write {
+                let results = realm.objects(tableChunk.self).filter(NSPredicate(format: "account == %@ AND ocId == %@", account, ocId))
+                for result in results {
+                    let filePath = directory + "/\(result.fileName)"
+                    NCUtilityFileSystem.shared.deleteFile(filePath: filePath)
+                }
+                realm.delete(results)
+            }
+        } catch let error {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
+    }
+
+}

+ 2 - 2
iOSClient/Data/NCManageDatabase+Metadata.swift

@@ -38,7 +38,7 @@ class tableMetadata: Object, NCUserBaseUrl {
     @objc dynamic var account = ""
     @objc dynamic var assetLocalIdentifier = ""
     @objc dynamic var checksums = ""
-    @objc dynamic var chunk: Bool = false
+    @objc dynamic var chunk: Int = 0
     @objc dynamic var classFile = ""
     @objc dynamic var commentsUnread: Bool = false
     @objc dynamic var contentType = ""
@@ -220,7 +220,7 @@ extension tableMetadata {
     }
 
     var isTransferInForeground: Bool {
-        (status > 0 && (chunk || e2eEncrypted))
+        (status > 0 && (chunk > 0 || e2eEncrypted))
     }
 
     var isDownload: Bool {

+ 5 - 104
iOSClient/Data/NCManageDatabase.swift

@@ -98,6 +98,11 @@ class NCManageDatabase: NSObject {
                         migration.deleteData(forType: tableVideo.className())
                     }
 
+                    if oldSchemaVersion < 304 {
+                        migration.deleteData(forType: tableChunk.className())
+                        migration.deleteData(forType: tableMetadata.className())
+                    }
+
                 }, shouldCompactOnLaunch: { totalBytes, usedBytes in
 
                     // totalBytes refers to the size of the file on disk in bytes (data + free space)
@@ -257,110 +262,6 @@ class NCManageDatabase: NSObject {
         return object.isInvalidated
     }
 
-    // MARK: -
-    // MARK: Table Chunk
-
-    func getChunkFolder(account: String, ocId: String) -> String {
-
-        do {
-            let realm = try Realm()
-            realm.refresh()
-            guard let result = realm.objects(tableChunk.self).filter("account == %@ AND ocId == %@", account, ocId).first else { return NSUUID().uuidString }
-            return result.chunkFolder
-        } catch let error as NSError {
-            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
-        }
-
-        return NSUUID().uuidString
-    }
-
-    func getChunks(account: String, ocId: String) -> [String] {
-
-        var filesNames: [String] = []
-
-        do {
-            let realm = try Realm()
-            realm.refresh()
-            let results = realm.objects(tableChunk.self).filter("account == %@ AND ocId == %@", account, ocId).sorted(byKeyPath: "fileName", ascending: true)
-            for result in results {
-                filesNames.append(result.fileName)
-            }
-            return filesNames
-        } catch let error as NSError {
-            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
-        }
-
-        return filesNames
-    }
-
-    func addChunks(account: String, ocId: String, chunkFolder: String, fileNames: [String]) {
-
-        var size: Int64 = 0
-
-        do {
-            let realm = try Realm()
-            try realm.write {
-
-                for fileName in fileNames {
-
-                    let object = tableChunk()
-                    size += NCUtilityFileSystem.shared.getFileSize(filePath: CCUtility.getDirectoryProviderStorageOcId(ocId, fileNameView: fileName)!)
-
-                    object.account = account
-                    object.chunkFolder = chunkFolder
-                    object.fileName = fileName
-                    object.index = ocId + fileName
-                    object.ocId = ocId
-                    object.size = size
-
-                    realm.add(object, update: .all)
-                }
-            }
-        } catch let error {
-            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
-        }
-    }
-
-    func getChunk(account: String, fileName: String) -> tableChunk? {
-
-        do {
-            let realm = try Realm()
-            realm.refresh()
-            guard let result = realm.objects(tableChunk.self).filter("account == %@ AND fileName == %@", account, fileName).first else { return nil }
-            return tableChunk.init(value: result)
-        } catch let error as NSError {
-            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
-        }
-
-        return nil
-    }
-
-    func deleteChunk(account: String, ocId: String, fileName: String) {
-
-        do {
-            let realm = try Realm()
-            try realm.write {
-                let result = realm.objects(tableChunk.self).filter(NSPredicate(format: "account == %@ AND ocId == %@ AND fileName == %@", account, ocId, fileName))
-                realm.delete(result)
-            }
-        } catch let error {
-            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
-        }
-    }
-
-    func deleteChunks(account: String, ocId: String) {
-
-        do {
-            let realm = try Realm()
-            try realm.write {
-                let result = realm.objects(tableChunk.self).filter(NSPredicate(format: "account == %@ AND ocId == %@", account, ocId))
-                realm.delete(result)
-            }
-        } catch let error {
-            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
-        }
-    }
-
     // MARK: -
     // MARK: Table Direct Editing
 

+ 13 - 7
iOSClient/Main/Collection Common/NCCollectionViewCommon.swift

@@ -517,17 +517,22 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
 
         guard let userInfo = notification.userInfo as NSDictionary?,
               let ocId = userInfo["ocId"] as? String,
+              let ocIdTemp = userInfo["ocIdTemp"] as? String,
               let serverUrl = userInfo["serverUrl"] as? String,
               let account = userInfo["account"] as? String
         else { return }
 
-        if ocId == NCNetworking.shared.transferInForegorund?.ocId {
+        if ocIdTemp == NCNetworking.shared.transferInForegorund?.ocId {
             NCNetworking.shared.transferInForegorund = nil
             self.collectionView?.reloadData()
         }
 
-        if account == appDelegate.account, serverUrl == self.serverUrl {
-            reloadDataSource()
+        if account == appDelegate.account, serverUrl == self.serverUrl, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
+            if metadata.e2eEncrypted {
+                reloadDataSourceNetwork(isForced: true)
+            } else {
+                reloadDataSource()
+            }
         }
     }
 
@@ -555,13 +560,14 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
               let progressNumber = userInfo["progress"] as? NSNumber,
               let totalBytes = userInfo["totalBytes"] as? Int64,
               let totalBytesExpected = userInfo["totalBytesExpected"] as? Int64,
-              let ocId = userInfo["ocId"] as? String,
-              let chunk = userInfo["chunk"] as? Bool,
-              let e2eEncrypted = userInfo["e2eEncrypted"] as? Bool
+              let ocId = userInfo["ocId"] as? String
         else { return }
 
+        let chunk: Int = userInfo["chunk"] as? Int ?? 0
+        let e2eEncrypted: Bool = userInfo["e2eEncrypted"] as? Bool ?? false
+
         // Header Transfer
-        if headerMenuTransferView && (chunk || e2eEncrypted) {
+        if headerMenuTransferView && (chunk > 0 || e2eEncrypted) {
             if NCNetworking.shared.transferInForegorund?.ocId == ocId {
                 NCNetworking.shared.transferInForegorund?.progress = progressNumber.floatValue
             } else {

+ 5 - 2
iOSClient/Main/NCActionCenter.swift

@@ -339,10 +339,13 @@ class NCActionCenter: NSObject, UIDocumentInteractionControllerDelegate, NCSelec
         let processor = ParallelWorker(n: 5, titleKey: "_downloading_", totalTasks: downloadMetadata.count, hudView: appDelegate.window?.rootViewController?.view)
         for (metadata, url) in downloadMetadata {
             processor.execute { completion in
-                NCNetworking.shared.download(metadata: metadata, selector: "", completion: { _, _ in
+                NCNetworking.shared.download(metadata: metadata, selector: "", notificationCenterProgressTask: false) { _ in
+                } progressHandler: { progress in
+                    processor.hud?.progress = Float(progress.fractionCompleted)
+                } completion: { _, _ in
                     if CCUtility.fileProviderStorageExists(metadata) { items.append(url) }
                     completion()
-                })
+                }
             }
         }
 

+ 1 - 0
iOSClient/Menu/NCContextMenu.swift

@@ -41,6 +41,7 @@ class NCContextMenu: NSObject {
 
         let hud = JGProgressHUD()
         hud.indicatorView = JGProgressHUDRingIndicatorView()
+        hud.textLabel.text = NSLocalizedString("_downloading_", comment: "")
         hud.detailTextLabel.text = NSLocalizedString("_tap_to_cancel_", comment: "")
         if let indicatorView = hud.indicatorView as? JGProgressHUDRingIndicatorView { indicatorView.ringWidth = 1.5 }
         hud.tapOnHUDViewBlock = { _ in

+ 4 - 0
iOSClient/NCGlobal.swift

@@ -131,6 +131,10 @@ class NCGlobal: NSObject {
     let e2eePassphraseTest                          = "more over television factory tendency independence international intellectual impress interest sentence pony"
     @objc let e2eeReadVersions                      = ["1.1", "1.2"]
 
+    // CHUNK
+    let chunkSizeMBCellular                         = 10000000
+    let chunkSizeMBEthernetOrWiFi                   = 100000000
+
     // Video
     //
     let maxHTTPCache: Int64                         = 10000000000   // 10 GB

+ 26 - 11
iOSClient/Networking/E2EE/NCNetworkingE2EEUpload.swift

@@ -91,7 +91,7 @@ class NCNetworkingE2EEUpload: NSObject {
         // ** Unlock **
         await NCNetworkingE2EE.shared.unlock(account: metadata.account, serverUrl: metadata.serverUrl)
 
-        if sendFileResults.afError?.isExplicitlyCancelledError ?? false {
+        if let afError = sendFileResults.afError, afError.isExplicitlyCancelledError {
 
             CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
             NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
@@ -105,6 +105,7 @@ class NCNetworkingE2EEUpload: NSObject {
             metadata.date = sendFileResults.date ?? NSDate()
             metadata.etag = sendFileResults.etag ?? ""
             metadata.ocId = ocId
+            metadata.chunk = 0
 
             metadata.session = ""
             metadata.sessionError = ""
@@ -181,16 +182,30 @@ class NCNetworkingE2EEUpload: NSObject {
 
     private func sendFile(metadata: tableMetadata, e2eToken: String, uploadE2EEDelegate: uploadE2EEDelegate? = nil) async -> (ocId: String?, etag: String?, date: NSDate? ,afError: AFError?, error: NKError) {
 
-        let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileName)!
+        if metadata.chunk > 0 {
+
+            return await withCheckedContinuation({ continuation in
+                NCNetworking.shared.uploadChunkFile(metadata: metadata, withUploadComplete: false, addCustomHeaders: ["e2e-token": e2eToken]) {
+                    uploadE2EEDelegate?.start()
+                } progressHandler: { totalBytesExpected, totalBytes, fractionCompleted in
+                    uploadE2EEDelegate?.uploadE2EEProgress(totalBytesExpected, totalBytes, fractionCompleted)
+                } completion: { account, file, afError, error in
+                    continuation.resume(returning: (ocId: file?.ocId, etag: file?.etag, date: file?.date ,afError: afError, error: error))
+                }
+            })
 
-        return await withCheckedContinuation({ continuation in
-            NCNetworking.shared.uploadFile(metadata: metadata, fileNameLocalPath: fileNameLocalPath, withUploadComplete: false, addCustomHeaders: ["e2e-token": e2eToken]) {
-                uploadE2EEDelegate?.start()
-            } progressHandler: { totalBytesExpected, totalBytes, fractionCompleted in
-                uploadE2EEDelegate?.uploadE2EEProgress(totalBytesExpected, totalBytes, fractionCompleted)
-            } completion: { account, ocId, etag, date, size, allHeaderFields, afError, error in
-                continuation.resume(returning: (ocId: ocId, etag: etag, date: date ,afError: afError, error: error))
-            }
-        })
+        } else {
+
+            let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileName)!
+            return await withCheckedContinuation({ continuation in
+                NCNetworking.shared.uploadFile(metadata: metadata, fileNameLocalPath: fileNameLocalPath, withUploadComplete: false, addCustomHeaders: ["e2e-token": e2eToken]) {
+                    uploadE2EEDelegate?.start()
+                } progressHandler: { totalBytesExpected, totalBytes, fractionCompleted in
+                    uploadE2EEDelegate?.uploadE2EEProgress(totalBytesExpected, totalBytes, fractionCompleted)
+                } completion: { account, ocId, etag, date, size, allHeaderFields, afError, error in
+                    continuation.resume(returning: (ocId: ocId, etag: etag, date: date ,afError: afError, error: error))
+                }
+            })
+        }
     }
 }

+ 183 - 75
iOSClient/Networking/NCNetworking.swift

@@ -364,7 +364,7 @@ class NCNetworking: NSObject, NKCommonDelegate {
         }, progressHandler: { (progress) in
             
             if notificationCenterProgressTask {
-                NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterProgressTask, object: nil, userInfo: ["account": metadata.account, "ocId": metadata.ocId, "fileName": metadata.fileName, "serverUrl": metadata.serverUrl, "chunk": metadata.chunk, "e2eEncrypted": metadata.e2eEncrypted, "status": NSNumber(value: NCGlobal.shared.metadataStatusInDownload), "progress": NSNumber(value: progress.fractionCompleted), "totalBytes": NSNumber(value: progress.totalUnitCount), "totalBytesExpected": NSNumber(value: progress.completedUnitCount)])
+                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)
                                         
@@ -408,7 +408,7 @@ class NCNetworking: NSObject, NKCommonDelegate {
                 completion: @escaping (_ error: NKError) -> () = { error in }) {
 
         let metadata = tableMetadata.init(value: metadata)
-        NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Upload file \(metadata.fileNameView) with Identifier \(metadata.assetLocalIdentifier) with size \(metadata.size) [CHUNCK \(metadata.chunk), E2EE \(metadata.isDirectoryE2EE)]")
+        NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Upload file \(metadata.fileNameView) with Identifier \(metadata.assetLocalIdentifier) with size \(metadata.size) [CHUNK \(metadata.chunk), E2EE \(metadata.isDirectoryE2EE)]")
 
         if metadata.isDirectoryE2EE {
 #if !EXTENSION_FILE_PROVIDER_EXTENSION && !EXTENSION_WIDGET
@@ -417,13 +417,13 @@ class NCNetworking: NSObject, NKCommonDelegate {
                 completion(error)
             }
 #endif
-        } else if metadata.chunk {
-            uploadChunkedFile(metadata: metadata, start: start, progressHandler: progressHandler) { error in
+        } else if metadata.chunk > 0 {
+            uploadChunkFile(metadata: metadata, start: start, progressHandler: progressHandler) { _, _, _, error in
                 completion(error)
             }
         } else if metadata.session == NextcloudKit.shared.nkCommonInstance.sessionIdentifierUpload {
             let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
-            uploadFile(metadata: metadata, fileNameLocalPath:fileNameLocalPath, start: start, progressHandler: progressHandler) { account, ocId, etag, date, size, allHeaderFields, afError, error in
+            uploadFile(metadata: metadata, fileNameLocalPath:fileNameLocalPath, start: start, progressHandler: progressHandler) { _, _, _, _, _, _, _, error in
                 completion(error)
             }
         } else {
@@ -433,7 +433,10 @@ class NCNetworking: NSObject, NKCommonDelegate {
         }
     }
 
-    func uploadFile(metadata: tableMetadata, fileNameLocalPath: String, withUploadComplete: Bool = true ,addCustomHeaders: [String: String]? = nil,
+    func uploadFile(metadata: tableMetadata,
+                    fileNameLocalPath: String,
+                    withUploadComplete: Bool = true,
+                    addCustomHeaders: [String: String]? = nil,
                     start: @escaping () -> () = { },
                     progressHandler: @escaping (_ totalBytesExpected: Int64, _ totalBytes: Int64, _ fractionCompleted: Double) -> () = { _, _, _ in },
                     completion: @escaping (_ account: String, _ ocId: String?, _ etag: String?, _ date: NSDate?, _ size: Int64, _ allHeaderFields: [AnyHashable : Any]?, _ afError: AFError?, _ error: NKError) -> Void) {
@@ -479,6 +482,110 @@ class NCNetworking: NSObject, NKCommonDelegate {
         }
     }
 
+    func uploadChunkFile(metadata: tableMetadata,
+                         withUploadComplete: Bool = true,
+                         addCustomHeaders: [String: String] = [:],
+                         start: @escaping () -> () = { },
+                         progressHandler: @escaping (_ totalBytesExpected: Int64, _ totalBytes: Int64, _ fractionCompleted: Double) -> () = { _, _, _ in },
+                         completion: @escaping (_ account: String, _ file: NKFile?, _ afError: AFError?, _ error: NKError) -> Void) {
+
+        let directory = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId)!
+        let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
+        let chunkFolder = NCManageDatabase.shared.getChunkFolder(account: metadata.account, ocId: metadata.ocId)
+        let filesChunk = NCManageDatabase.shared.getChunks(account: metadata.account, ocId: metadata.ocId)
+        var uploadTask: URLSessionTask?
+
+        var chunkSize = NCGlobal.shared.chunkSizeMBCellular
+        if NCNetworking.shared.networkReachability == NKCommon.TypeReachability.reachableEthernetOrWiFi {
+            chunkSize = NCGlobal.shared.chunkSizeMBEthernetOrWiFi
+        }
+
+        NextcloudKit.shared.uploadChunk(directory: directory,
+                                        fileName: metadata.fileName,
+                                        date: metadata.date as Date,
+                                        creationDate: metadata.creationDate as Date,
+                                        serverUrl: metadata.serverUrl,
+                                        chunkFolder: chunkFolder,
+                                        filesChunk: filesChunk,
+                                        chunkSize: chunkSize,
+                                        addCustomHeaders: addCustomHeaders) { filesChunk in
+
+            start()
+            NCManageDatabase.shared.addChunks(account: metadata.account, ocId: metadata.ocId, chunkFolder: chunkFolder, filesChunk: filesChunk)
+            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadStartFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "sessionSelector": metadata.sessionSelector])
+
+        } requestHandler: { request in
+
+            self.uploadRequest[fileNameLocalPath] = request
+
+        } taskHandler: { task in
+
+            uploadTask = task
+            NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, sessionError: "", sessionTaskIdentifier: task.taskIdentifier, status: NCGlobal.shared.metadataStatusUploading)
+
+        } progressHandler: { totalBytesExpected, totalBytes, fractionCompleted in
+
+            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.metadataStatusInUpload),
+                    "chunk": metadata.chunk,
+                    "e2eEncrypted": metadata.e2eEncrypted,
+                    "progress": NSNumber(value: fractionCompleted),
+                    "totalBytes": NSNumber(value: totalBytes),
+                    "totalBytesExpected": NSNumber(value: totalBytesExpected)])
+
+            progressHandler(totalBytesExpected, totalBytes, fractionCompleted)
+
+        } uploaded: { fileChunk in
+
+            NCManageDatabase.shared.deleteChunk(account: metadata.account, ocId: metadata.ocId, fileChunk: fileChunk, directory: directory)
+
+        } completion: { account, filesChunk, file, afError, error in
+
+            self.uploadRequest.removeValue(forKey: fileNameLocalPath)
+
+            if error == .success {
+                NCManageDatabase.shared.deleteChunks(account: account, ocId: metadata.ocId, directory: directory)
+            }
+
+            switch error.errorCode {
+            case NKError.chunkResourceNotFound:
+                NCManageDatabase.shared.deleteChunks(account: account, ocId: metadata.ocId, directory: directory)
+            case NKError.chunkNoEnoughMemory:
+                NCManageDatabase.shared.deleteChunks(account: account, ocId: metadata.ocId, directory: directory)
+                NCContentPresenter.shared.messageNotification("_chunk_enough_memory_", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: .error)
+            case NKError.chunkCreateFolder:
+                NCContentPresenter.shared.messageNotification("_chunk_create_folder_", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: .error)
+            case NKError.chunkFilesNull:
+                NCManageDatabase.shared.deleteChunks(account: account, ocId: metadata.ocId, directory: directory)
+                NCContentPresenter.shared.messageNotification("_chunk_files_null_", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: .error)
+            case NKError.chunkFileNull: // (cancel)
+                NCManageDatabase.shared.deleteChunks(account: account, ocId: metadata.ocId, directory: directory)
+            case NKError.chunkFileUpload:
+                if let afError, !afError.isExplicitlyCancelledError {
+                    NCContentPresenter.shared.messageNotification("_error_", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: .error)
+                }
+                break
+            case NKError.chunkMoveFile:
+                NCManageDatabase.shared.deleteChunks(account: account, ocId: metadata.ocId, directory: directory)
+                NCContentPresenter.shared.messageNotification("_chunk_move_", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: .error)
+            default: break
+            }
+
+            if withUploadComplete, let uploadTask {
+                self.uploadComplete(fileName: metadata.fileName, serverUrl: metadata.serverUrl, ocId: file?.ocId, etag: file?.etag, date: file?.date, size: file?.size ?? 0, description: metadata.ocId, task: uploadTask, error: error)
+            }
+
+            completion(account, file, afError, error)
+        }
+    }
+
     private func uploadFileInBackground(metadata: tableMetadata,
                                         start: @escaping () -> () = { },
                                         completion: @escaping (_ error: NKError) -> Void) {
@@ -521,97 +628,96 @@ class NCNetworking: NSObject, NKCommonDelegate {
     }
 
     func uploadComplete(fileName: String, serverUrl: String, ocId: String?, etag: String?, date: NSDate?, size: Int64, description: String?, task: URLSessionTask, error: NKError) {
+
+        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, error: error)
+            return
+        }
+        let ocIdTemp = metadata.ocId
+        let selector = metadata.sessionSelector
         var isApplicationStateActive = false
 #if !EXTENSION
         isApplicationStateActive = UIApplication.shared.applicationState == .active
 #endif
-        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, error: error)
-                return
-            }
-            let ocIdTemp = metadata.ocId
-            let selector = metadata.sessionSelector
 
-            if error == .success, let ocId = ocId, size == metadata.size {
+        if error == .success, let ocId = ocId, size == metadata.size {
 
-                let metadata = tableMetadata.init(value: metadata)
+            let metadata = tableMetadata.init(value: metadata)
 
-                metadata.uploadDate = date ?? NSDate()
-                metadata.etag = etag ?? ""
-                metadata.ocId = ocId
+            metadata.uploadDate = date ?? NSDate()
+            metadata.etag = etag ?? ""
+            metadata.ocId = ocId
+            metadata.chunk = 0
 
-                if let fileId = NCUtility.shared.ocIdToFileId(ocId: ocId) {
-                    metadata.fileId = fileId
-                }
+            if let fileId = NCUtility.shared.ocIdToFileId(ocId: ocId) {
+                metadata.fileId = fileId
+            }
 
-                metadata.session = ""
-                metadata.sessionError = ""
-                metadata.sessionTaskIdentifier = 0
-                metadata.status = NCGlobal.shared.metadataStatusNormal
+            metadata.session = ""
+            metadata.sessionError = ""
+            metadata.sessionTaskIdentifier = 0
+            metadata.status = NCGlobal.shared.metadataStatusNormal
 
-                // Delete Asset on Photos album
-                if CCUtility.getRemovePhotoCameraRoll() && !metadata.assetLocalIdentifier.isEmpty {
-                    metadata.deleteAssetLocalIdentifier = true
-                }
+            // Delete Asset on Photos album
+            if CCUtility.getRemovePhotoCameraRoll() && !metadata.assetLocalIdentifier.isEmpty {
+                metadata.deleteAssetLocalIdentifier = true
+            }
 
-                NCManageDatabase.shared.addMetadata(metadata)
-                NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp))
+            NCManageDatabase.shared.addMetadata(metadata)
+            NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp))
 
-                if selector == NCGlobal.shared.selectorUploadFileNODelete {
-                    NCUtilityFileSystem.shared.moveFile(atPath: CCUtility.getDirectoryProviderStorageOcId(ocIdTemp), toPath: CCUtility.getDirectoryProviderStorageOcId(ocId))
-                    NCManageDatabase.shared.addLocalFile(metadata: metadata)
-                } else {
-                    NCUtilityFileSystem.shared.deleteFile(filePath: CCUtility.getDirectoryProviderStorageOcId(ocIdTemp))
-                }
+            if selector == NCGlobal.shared.selectorUploadFileNODelete {
+                NCUtilityFileSystem.shared.moveFile(atPath: CCUtility.getDirectoryProviderStorageOcId(ocIdTemp), toPath: CCUtility.getDirectoryProviderStorageOcId(ocId))
+                NCManageDatabase.shared.addLocalFile(metadata: metadata)
+            } else {
+                NCUtilityFileSystem.shared.deleteFile(filePath: CCUtility.getDirectoryProviderStorageOcId(ocIdTemp))
+            }
 
-                NextcloudKit.shared.nkCommonInstance.writeLog("[SUCCESS] Upload complete " + serverUrl + "/" + fileName + ", result: success(\(size) bytes)")
-                NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "error": error])
+            NextcloudKit.shared.nkCommonInstance.writeLog("[SUCCESS] Upload complete " + serverUrl + "/" + fileName + ", result: success(\(size) bytes)")
+            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "error": error])
 
-            } else {
+        } else {
 
-                if error.errorCode == NSURLErrorCancelled || error.errorCode == NCGlobal.shared.errorRequestExplicityCancelled {
+            if error.errorCode == NSURLErrorCancelled || error.errorCode == NCGlobal.shared.errorRequestExplicityCancelled {
 
-                    CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
-                    NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
-                    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))
+                NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadCancelFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account])
 
-                } else if error.errorCode == NCGlobal.shared.errorForbidden && isApplicationStateActive {
-
-                    DispatchQueue.main.async {
-                        let newFileName = NCUtilityFileSystem.shared.createFileName(metadata.fileName, serverUrl: metadata.serverUrl, account: metadata.account)
-                        let alertController = UIAlertController(title: error.errorDescription, message: NSLocalizedString("_change_upload_filename_", comment: ""), preferredStyle: .alert)
-                        alertController.addAction(UIAlertAction(title: String(format: NSLocalizedString("_save_file_as_", comment: ""), newFileName), style: .default, handler: { action in
-                            let atpath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId) + "/" + metadata.fileName
-                            let toPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId) + "/" + newFileName
-                            NCUtilityFileSystem.shared.moveFile(atPath: atpath, toPath: toPath)
-                            NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, newFileName: newFileName, session: nil, sessionError: "", sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusWaitUpload)
-                        }))
-                        alertController.addAction(UIAlertAction(title: NSLocalizedString("_discard_changes_", comment: ""), style: .destructive, handler: { action in
-                            CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
-                            NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
-                            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadCancelFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account])
-                        }))
+            } else if error.errorCode == NCGlobal.shared.errorForbidden && isApplicationStateActive {
 #if !EXTENSION
-                        let appDelegate = UIApplication.shared.delegate as! AppDelegate
-                        appDelegate.window?.rootViewController?.present(alertController, animated: true)
+                DispatchQueue.main.async {
+                    let newFileName = NCUtilityFileSystem.shared.createFileName(metadata.fileName, serverUrl: metadata.serverUrl, account: metadata.account)
+                    let alertController = UIAlertController(title: error.errorDescription, message: NSLocalizedString("_change_upload_filename_", comment: ""), preferredStyle: .alert)
+                    alertController.addAction(UIAlertAction(title: String(format: NSLocalizedString("_save_file_as_", comment: ""), newFileName), style: .default, handler: { action in
+                        let atpath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId) + "/" + metadata.fileName
+                        let toPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId) + "/" + newFileName
+                        NCUtilityFileSystem.shared.moveFile(atPath: atpath, toPath: toPath)
+                        NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, newFileName: newFileName, session: nil, sessionError: "", sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusWaitUpload)
+                    }))
+                    alertController.addAction(UIAlertAction(title: NSLocalizedString("_discard_changes_", comment: ""), style: .destructive, handler: { action in
+                        CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
+                        NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
+                        NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadCancelFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account])
+                    }))
+
+                    let appDelegate = UIApplication.shared.delegate as! AppDelegate
+                    appDelegate.window?.rootViewController?.present(alertController, animated: true)
+                }
 #endif
-                    }
+            } else {
 
-                } else {
-                    
-                    NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: error.errorDescription, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusUploadError)
-                    NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "error": error])
-                }
+                NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: error.errorDescription, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusUploadError)
+                NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "error": error])
             }
+        }
 
-            // Update Badge
-            let counterBadge = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "status == %d OR status == %d OR status == %d", NCGlobal.shared.metadataStatusWaitUpload, NCGlobal.shared.metadataStatusInUpload, NCGlobal.shared.metadataStatusUploading))
-            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUpdateBadgeNumber, userInfo: ["counter":counterBadge.count])
+        // Update Badge
+        let counterBadge = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "status == %d OR status == %d OR status == %d", NCGlobal.shared.metadataStatusWaitUpload, NCGlobal.shared.metadataStatusInUpload, NCGlobal.shared.metadataStatusUploading))
+        NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUpdateBadgeNumber, userInfo: ["counter":counterBadge.count])
 
-            self.uploadMetadataInBackground.removeValue(forKey: fileName + serverUrl)
-            self.delegate?.uploadComplete?(fileName: fileName, serverUrl: serverUrl, ocId: ocId, etag: etag, date: date, size: size, description: description, task: task, error: error)
-        }
+        self.uploadMetadataInBackground.removeValue(forKey: fileName + serverUrl)
+        self.delegate?.uploadComplete?(fileName: fileName, serverUrl: serverUrl, ocId: ocId, etag: etag, date: date, size: size, description: description, task: task, error: error)
     }
 
     func uploadProgress(_ progress: Float, totalBytes: Int64, totalBytesExpected: Int64, fileName: String, serverUrl: String, session: URLSession, task: URLSessionTask) {
@@ -663,6 +769,8 @@ class NCNetworking: NSObject, NKCommonDelegate {
         })
     }
 
+
+
     // MARK: - Transfer (Download Upload)
 
     @objc func cancelTransferMetadata(_ metadata: tableMetadata, completion: @escaping () -> Void) {
@@ -680,7 +788,7 @@ class NCNetworking: NSObject, NKCommonDelegate {
             return completion()
         }
 
-        if metadata.session == NextcloudKit.shared.nkCommonInstance.sessionIdentifierUpload || metadata.chunk {
+        if metadata.session == NextcloudKit.shared.nkCommonInstance.sessionIdentifierUpload || metadata.chunk > 0 {
 
             CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
             if let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView),

+ 0 - 287
iOSClient/Networking/NCNetworkingChunkedUpload.swift

@@ -1,287 +0,0 @@
-//
-//  NCNetworkingUploadChunk.swift
-//  Nextcloud
-//
-//  Created by Marino Faggiana on 05/04/21.
-//  Copyright © 2021 Marino Faggiana. All rights reserved.
-//
-//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
-//
-//  This program is free software: you can redistribute it and/or modify
-//  it under the terms of the GNU General Public License as published by
-//  the Free Software Foundation, either version 3 of the License, or
-//  (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//  GNU General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-//
-
-import UIKit
-import NextcloudKit
-
-extension NCNetworking {
-
-    internal func uploadChunkedFile(metadata: tableMetadata,
-                                    start: @escaping () -> () = { },
-                                    progressHandler: @escaping (_ totalBytesExpected: Int64, _ totalBytes: Int64, _ fractionCompleted: Double) -> () = { _, _, _ in },
-                                    completion: @escaping (_ error: NKError) -> Void) {
-
-        let directoryProviderStorageOcId = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId)!
-        let chunkFolder = NCManageDatabase.shared.getChunkFolder(account: metadata.account, ocId: metadata.ocId)
-        let chunkFolderPath = metadata.urlBase + "/" + NextcloudKit.shared.nkCommonInstance.dav + "/uploads/" + metadata.userId + "/" + chunkFolder
-        let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
-        let chunkSize = CCUtility.getChunkSize()
-        let fileSizeInGB = Double(metadata.size) / 1e9
-        let ocIdTemp = metadata.ocId
-        let selector = metadata.sessionSelector
-        var uploadError = NKError()
-
-        var filesNames = NCManageDatabase.shared.getChunks(account: metadata.account, ocId: metadata.ocId)
-
-        if filesNames.count == 0 {
-            filesNames = NextcloudKit.shared.nkCommonInstance.chunkedFile(inputDirectory: directoryProviderStorageOcId, outputDirectory: directoryProviderStorageOcId, fileName: metadata.fileName, chunkSizeMB: chunkSize)
-            if filesNames.count > 0 {
-                NCManageDatabase.shared.addChunks(account: metadata.account, ocId: metadata.ocId, chunkFolder: chunkFolder, fileNames: filesNames)
-            } else {
-                NCContentPresenter.shared.dismiss()
-                let error = NKError(errorCode: NCGlobal.shared.errorReadFile, errorDescription: "_err_file_not_found_")
-                NCContentPresenter.shared.showError(error: error)
-                NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
-                return completion(uploadError)
-            }
-        } else {
-            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": metadata.serverUrl])
-        }
-
-        let pathServerUrl = CCUtility.returnPathfromServerUrl(metadata.serverUrl, urlBase: metadata.urlBase, userId: metadata.userId, account: metadata.account)!
-        let serverUrlFileNameDestination = metadata.urlBase + "/" + NextcloudKit.shared.nkCommonInstance.dav + "/files/" + metadata.userId + pathServerUrl + "/" + metadata.fileName
-
-        let destinationHeader: [String: String] = ["Destination" : serverUrlFileNameDestination]
-
-        // Create folder for chunks
-        createChunkedFolder(customHeaders: destinationHeader, chunkFolderPath: chunkFolderPath, account: metadata.account) { error in
-
-            NCContentPresenter.shared.dismiss(after: NCGlobal.shared.dismissAfterSecond)
-
-            guard error == .success else {
-                self.uploadChunkFileError(metadata: metadata, chunkFolderPath: chunkFolderPath, directoryProviderStorageOcId: directoryProviderStorageOcId, error: error)
-                completion(error)
-                return
-            }
-
-            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadStartFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "sessionSelector": metadata.sessionSelector])
-
-            start()
-
-            // Upload the chunks
-            for fileName in filesNames {
-
-                let serverUrlFileName = chunkFolderPath + "/" + fileName
-                let fileSize = CCUtility.fileProviderStorageSize(metadata.ocId, fileNameView: fileName)
-                // ops! the upload has probably been cancelled
-                if fileSize == 0 {
-                    CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
-                    NCManageDatabase.shared.deleteChunks(account: metadata.account, ocId: metadata.ocId)
-                    NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
-                    return completion(NKError())
-                }
-                let fileNameChunkLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: fileName)!
-
-                var size: Int64?
-                if let tableChunk = NCManageDatabase.shared.getChunk(account: metadata.account, fileName: fileName) {
-                    size = tableChunk.size - NCUtilityFileSystem.shared.getFileSize(filePath: fileNameChunkLocalPath)
-                }
-
-                let semaphore = DispatchSemaphore(value: 0)
-
-                NextcloudKit.shared.upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameChunkLocalPath, addCustomHeaders: destinationHeader, requestHandler: { request in
-
-                    self.uploadRequest[fileNameLocalPath] = request
-
-                }, taskHandler: { task in
-
-                    NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, sessionError: "", sessionTaskIdentifier: task.taskIdentifier, status: NCGlobal.shared.metadataStatusUploading)
-                    NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Upload chunk: " + fileName)
-
-                }, progressHandler: { progress in
-
-                    if let size = size {
-                        let totalBytesExpected = metadata.size
-                        let totalBytes = size
-                        let fractionCompleted = Double(totalBytes) / Double(totalBytesExpected)
-
-                        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.metadataStatusInUpload),
-                                "chunk": metadata.chunk,
-                                "e2eEncrypted": metadata.e2eEncrypted,
-                                "progress": NSNumber(value: fractionCompleted),
-                                "totalBytes": NSNumber(value: totalBytes),
-                                "totalBytesExpected": NSNumber(value: totalBytesExpected)])
-
-                        progressHandler(totalBytesExpected, totalBytes, fractionCompleted)
-                    }
-
-                }) { _, _, _, _, _, _, _, error in
-
-                    self.uploadRequest.removeValue(forKey: fileNameLocalPath)
-                    uploadError = error
-                    semaphore.signal()
-                }
-
-                semaphore.wait()
-
-                if uploadError == .success {
-                    NCManageDatabase.shared.deleteChunk(account: metadata.account, ocId: metadata.ocId, fileName: fileName)
-                } else {
-                    break
-                }
-            }
-
-            guard uploadError == .success else {
-                self.uploadChunkFileError(metadata: metadata, chunkFolderPath: chunkFolderPath, directoryProviderStorageOcId: directoryProviderStorageOcId, error: uploadError)
-                completion(error)
-                return
-            }
-
-            // Assemble the chunks
-            let serverUrlFileNameSource = chunkFolderPath + "/.file"
-
-            var customHeaders: [String: String] = [:]
-
-            if metadata.creationDate.timeIntervalSince1970 > 0 {
-                customHeaders["X-OC-CTime"] = "\(metadata.creationDate.timeIntervalSince1970)"
-            }
-
-            if metadata.date.timeIntervalSince1970 > 0 {
-                customHeaders["X-OC-MTime"] = "\(metadata.date.timeIntervalSince1970)"
-            }
-
-            destinationHeader.forEach { customHeaders[$0] = $1 }
-
-            // Calculate Assemble Timeout
-            let ASSEMBLE_TIME_PER_GB: Double    = 3 * 60            // 3  min
-            let ASSEMBLE_TIME_MIN: Double       = 60                // 60 sec
-            let ASSEMBLE_TIME_MAX: Double       = 30 * 60           // 30 min
-            let timeout = max(ASSEMBLE_TIME_MIN, min(ASSEMBLE_TIME_PER_GB * fileSizeInGB, ASSEMBLE_TIME_MAX))
-
-            let options = NKRequestOptions(customHeader: customHeaders, timeout: timeout, queue: DispatchQueue.global())
-            
-            NextcloudKit.shared.moveFileOrFolder(serverUrlFileNameSource: serverUrlFileNameSource, serverUrlFileNameDestination: serverUrlFileNameDestination, overwrite: true, options: options) { _, error in
-
-                NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Assembling chunk with error code: \(error.errorCode)")
-
-                guard error == .success else {
-                    self.uploadChunkFileError(metadata: metadata, chunkFolderPath: chunkFolderPath, directoryProviderStorageOcId: directoryProviderStorageOcId, error: error)
-                    completion(error)
-                    return
-                }
-
-                let serverUrl = metadata.serverUrl
-                let assetLocalIdentifier = metadata.assetLocalIdentifier
-                let isLivePhoto = metadata.livePhoto
-                let account = metadata.account
-                let fileName = metadata.fileName
-
-                NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp))
-                NCManageDatabase.shared.deleteChunks(account: metadata.account, ocId: ocIdTemp)
-
-                self.readFile(serverUrlFileName: serverUrlFileNameDestination) { (_, metadata, _) in
-
-                    if error == .success, let metadata = metadata {
-
-                        metadata.assetLocalIdentifier = assetLocalIdentifier
-                        metadata.livePhoto = isLivePhoto
-
-                        // Delete Asset on Photos album
-                        if CCUtility.getRemovePhotoCameraRoll() && !metadata.assetLocalIdentifier.isEmpty {
-                            metadata.deleteAssetLocalIdentifier = true
-                        }
-                        NCManageDatabase.shared.addMetadata(metadata)
-
-                        if selector == NCGlobal.shared.selectorUploadFileNODelete {
-                            NCUtilityFileSystem.shared.moveFile(atPath: CCUtility.getDirectoryProviderStorageOcId(ocIdTemp, fileNameView: fileName), toPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: fileName))
-                            NCManageDatabase.shared.addLocalFile(metadata: metadata)
-                        }
-                        NCUtilityFileSystem.shared.deleteFile(filePath: directoryProviderStorageOcId)
-
-                        NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": serverUrl])
-                        NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": serverUrl, "account": account, "fileName": fileName, "ocIdTemp": ocIdTemp, "error": error])
-
-                    } else {
-
-                        NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSourceNetworkForced)
-                        NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": ocIdTemp, "serverUrl": serverUrl, "account": account, "fileName": fileName, "ocIdTemp": ocIdTemp, "error": error])
-                    }
-
-                    completion(error)
-                }
-            }
-        }
-    }
-
-    private func createChunkedFolder(customHeaders: [String : String], chunkFolderPath: String, account: String, completion: @escaping (_ errorCode: NKError) -> Void) {
-
-        let options = NKRequestOptions(customHeader: customHeaders, queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)
-
-        NextcloudKit.shared.readFileOrFolder(serverUrlFileName: chunkFolderPath, depth: "0", showHiddenFiles: CCUtility.getShowHiddenFiles(), options: options) { _, _, _, error in
-
-            if error == .success {
-                completion(NKError())
-            } else if error.errorCode == NCGlobal.shared.errorResourceNotFound {
-                NextcloudKit.shared.createFolder(serverUrlFileName: chunkFolderPath, options: options) { _, _, _, error in
-                    completion(error)
-                }
-            } else {
-                completion(error)
-            }
-        }
-    }
-
-    private func uploadChunkFileError(metadata: tableMetadata, chunkFolderPath: String, directoryProviderStorageOcId: String, error: NKError) {
-
-        var errorDescription = error.errorDescription
-
-        NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Upload chunk error code: \(error.errorCode)")
-
-        if error.errorCode == NSURLErrorCancelled || error.errorCode == NCGlobal.shared.errorRequestExplicityCancelled {
-
-            // Delete chunk folder
-            NextcloudKit.shared.deleteFileOrFolder(serverUrlFileName: chunkFolderPath) { _, _ in }
-
-            NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
-            NCManageDatabase.shared.deleteChunks(account: metadata.account, ocId: metadata.ocId)
-            NCUtilityFileSystem.shared.deleteFile(filePath: directoryProviderStorageOcId)
-
-            NextcloudKit.shared.deleteFileOrFolder(serverUrlFileName: chunkFolderPath) { _, _ in }
-
-            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadCancelFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account])
-
-        } else {
-
-            // NO report for the connection lost
-            if error.errorCode == NCGlobal.shared.errorConnectionLost {
-                errorDescription = ""
-            } else {
-                let description = errorDescription + " code: \(error.errorCode)"
-                let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: description)
-                NCContentPresenter.shared.showError(error: error)
-            }
-
-            NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: errorDescription, sessionTaskIdentifier: NCGlobal.shared.metadataStatusNormal, status: NCGlobal.shared.metadataStatusUploadError)
-        }
-
-        NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": metadata.ocId, "error": error])
-    }
-}

+ 3 - 4
iOSClient/Networking/NCNetworkingProcessUpload.swift

@@ -124,7 +124,7 @@ class NCNetworkingProcessUpload: NSObject {
                 }
             }
             // CHUNK
-            if metadatasUpload.filter({ $0.chunk }).count > 0 {
+            if metadatasUpload.filter({ $0.chunk > 0 }).count > 0 {
                 self.pauseProcess = false
                 return completition(counterUpload)
             }
@@ -168,13 +168,13 @@ class NCNetworkingProcessUpload: NSObject {
                                     continue
                                 }
 
-                                if applicationState != .active && (isInDirectoryE2EE || metadata.chunk) {
+                                if applicationState != .active && (isInDirectoryE2EE || metadata.chunk > 0) {
                                     continue
                                 }
 
                                 if let metadata = NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusInUpload) {
                                     NCNetworking.shared.upload(metadata: metadata)
-                                    if isInDirectoryE2EE || metadata.chunk {
+                                    if isInDirectoryE2EE || metadata.chunk > 0 {
                                         maxConcurrentOperationUpload = 1
                                     }
                                     counterUpload += 1
@@ -263,7 +263,6 @@ class NCNetworkingProcessUpload: NSObject {
         for metadata in metadatasUploadShareExtension {
             let path = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId)!
             NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
-            NCManageDatabase.shared.deleteChunks(account: metadata.account, ocId: metadata.ocId)
             NCUtilityFileSystem.shared.deleteFile(filePath: path)
         }
 

+ 2 - 25
iOSClient/Settings/CCAdvanced.m

@@ -101,24 +101,6 @@
         [row.cellConfig setObject:UIColor.labelColor forKey:@"textLabel.textColor"];
         [section addFormRow:row];
     }
-    
-    // Section : Chunk --------------------------------------------------------------
-
-    section = [XLFormSectionDescriptor formSection];
-    [form addFormSection:section];
-    section.footerTitle = NSLocalizedString(@"_chunk_footer_title_", nil);
-    
-    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"chunk" rowType:XLFormRowDescriptorTypeStepCounter title:NSLocalizedString(@"_chunk_size_mb_", nil)];
-    row.cellConfigAtConfigure[@"backgroundColor"] = UIColor.secondarySystemGroupedBackgroundColor;
-    row.value = [NSString stringWithFormat:@"%ld", CCUtility.getChunkSize];
-    [row.cellConfig setObject:[UIFont systemFontOfSize:15.0] forKey:@"textLabel.font"];
-    [row.cellConfig setObject:UIColor.labelColor forKey:@"textLabel.textColor"];
-    [row.cellConfigAtConfigure setObject:@YES forKey:@"stepControl.wraps"];
-
-    [row.cellConfigAtConfigure setObject:@10 forKey:@"stepControl.stepValue"];
-    [row.cellConfigAtConfigure setObject:@0 forKey:@"stepControl.minimumValue"];
-    [row.cellConfigAtConfigure setObject:@100 forKey:@"stepControl.maximumValue"];
-    [section addFormRow:row];
 
     // Section : Privacy --------------------------------------------------------------
 
@@ -373,12 +355,7 @@
         [CCUtility setLogLevel:levelLog];
         [[[NextcloudKit shared] nkCommonInstance] setLevelLog:levelLog];
     }
-    
-    if ([rowDescriptor.tag isEqualToString:@"chunk"]) {
-        NSInteger chunkSize = [[rowDescriptor.value valueData] intValue];
-        [CCUtility setChunkSize:chunkSize];
-    }
-    
+
     if ([rowDescriptor.tag isEqualToString:@"deleteoldfiles"]) {
         
         NSInteger days = [[rowDescriptor.value valueData] intValue];
@@ -502,7 +479,7 @@
 
 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
     
-    if (indexPath.section == 5 && indexPath.row == 2) {
+    if (indexPath.section == 4 && indexPath.row == 2) {
         return 80;
     } else {
         return NCGlobal.shared.heightCellSettings;

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

@@ -948,6 +948,10 @@
 "_deletion_progess_"        = "Deletion in progress";
 "_copying_progess_"         = "Copying in progress";
 "_moving_progess_"          = "Moving in progress";
+"_chunk_enough_memory_"     = "It seems there is not enough space to send the file";
+"_chunk_create_folder_"     = "The file could not be sent, please check the server log";
+"_chunk_files_null_"        = "The file for sending could not be created";
+"_chunk_move_"              = "The sent file could not be reassembled, please check the server log";
 
 // Video
 "_select_trace_"            = "Select the trace";

+ 0 - 3
iOSClient/Utility/CCUtility.h

@@ -169,9 +169,6 @@
 + (BOOL)getAccountRequest;
 + (void)setAccountRequest:(BOOL)set;
 
-+ (NSInteger)getChunkSize;
-+ (void)setChunkSize:(NSInteger)size;
-
 + (NSInteger)getCleanUpDay;
 + (void)setCleanUpDay:(NSInteger)days;
 

+ 0 - 22
iOSClient/Utility/CCUtility.m

@@ -667,28 +667,6 @@
     [UICKeyChainStore setString:sSet forKey:@"accountRequest" service:NCGlobal.shared.serviceShareKeyChain];
 }
 
-/// In megabytes (MB)
-+ (NSInteger)getChunkSize
-{
-    NSString *size = [UICKeyChainStore stringForKey:@"chunkSize" service:NCGlobal.shared.serviceShareKeyChain];
-    NSInteger sizeInt = [size integerValue];
-
-    if (size == nil || sizeInt < 10) {
-        return 0;
-    } else {
-        return [size integerValue];
-    }
-}
-
-/// In megabytes (MB)
-+ (void)setChunkSize:(NSInteger)size
-{
-    if (size < 10) size = 0;
-
-    NSString *sizeString = [@(size) stringValue];
-    [UICKeyChainStore setString:sizeString forKey:@"chunkSize" service:NCGlobal.shared.serviceShareKeyChain];
-}
-
 + (NSInteger)getCleanUpDay
 {
     NSString *size = [UICKeyChainStore stringForKey:@"cleanUpDay" service:NCGlobal.shared.serviceShareKeyChain];

+ 30 - 9
iOSClient/Utility/NCCameraRoll.swift

@@ -29,7 +29,10 @@ class NCCameraRoll: NSObject {
 
     func extractCameraRoll(from metadata: tableMetadata, viewController: UIViewController?, hud: JGProgressHUD, completition: @escaping (_ metadatas: [tableMetadata]) -> Void) {
 
-        let chunckSize = CCUtility.getChunkSize() * 1000000
+        var chunkSize = NCGlobal.shared.chunkSizeMBCellular
+        if NCNetworking.shared.networkReachability == NKCommon.TypeReachability.reachableEthernetOrWiFi {
+            chunkSize = NCGlobal.shared.chunkSizeMBEthernetOrWiFi
+        }
         var metadatas: [tableMetadata] = []
         let metadataSource = tableMetadata.init(value: metadata)
 
@@ -47,9 +50,13 @@ class NCCameraRoll: NSObject {
             if let date = NCUtilityFileSystem.shared.getFileModificationDate(filePath: filePath) {
                 metadataSource.date = date
             }
-            metadataSource.chunk = chunckSize != 0 && metadata.size > chunckSize
+            if metadataSource.size > chunkSize {
+                metadataSource.chunk = chunkSize
+            } else {
+                metadataSource.chunk = 0
+            }
             metadataSource.e2eEncrypted = metadata.isDirectoryE2EE
-            if metadataSource.chunk || metadataSource.e2eEncrypted {
+            if metadataSource.chunk > 0 || metadataSource.e2eEncrypted {
                 metadataSource.session = NextcloudKit.shared.nkCommonInstance.sessionIdentifierUpload
             }
             metadataSource.isExtractFile = true
@@ -89,8 +96,11 @@ class NCCameraRoll: NSObject {
 
         var fileNamePath: String?
         let metadata = tableMetadata.init(value: metadata)
-        let chunckSize = CCUtility.getChunkSize() * 1000000
         var compatibilityFormat: Bool = false
+        var chunkSize = NCGlobal.shared.chunkSizeMBCellular
+        if NCNetworking.shared.networkReachability == NKCommon.TypeReachability.reachableEthernetOrWiFi {
+            chunkSize = NCGlobal.shared.chunkSizeMBEthernetOrWiFi
+        }
 
         func callCompletionWithError(_ error: Bool = true) {
             if error {
@@ -98,9 +108,13 @@ class NCCameraRoll: NSObject {
             } else {
                 var metadataReturn = metadata
                 if modifyMetadataForUpload {
-                    metadata.chunk = chunckSize != 0 && metadata.size > chunckSize
+                    if metadata.size > chunkSize {
+                        metadata.chunk = chunkSize
+                    } else {
+                        metadata.chunk = 0
+                    }
                     metadata.e2eEncrypted = metadata.isDirectoryE2EE
-                    if metadata.chunk || metadata.e2eEncrypted {
+                    if metadata.chunk > 0 || metadata.e2eEncrypted {
                         metadata.session = NextcloudKit.shared.nkCommonInstance.sessionIdentifierUpload
                     }
                     metadata.isExtractFile = true
@@ -234,10 +248,13 @@ class NCCameraRoll: NSObject {
         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)!
+        var chunkSize = NCGlobal.shared.chunkSizeMBCellular
+        if NCNetworking.shared.networkReachability == NKCommon.TypeReachability.reachableEthernetOrWiFi {
+            chunkSize = NCGlobal.shared.chunkSizeMBEthernetOrWiFi
+        }
 
         PHImageManager.default().requestLivePhoto(for: asset, targetSize: UIScreen.main.bounds.size, contentMode: PHImageContentMode.default, options: options) { livePhoto, _ in
             guard let livePhoto = livePhoto else { return completion(nil) }
@@ -267,9 +284,13 @@ class NCCameraRoll: NSObject {
                 metadataLivePhoto.sessionSelector = metadata.sessionSelector
                 metadataLivePhoto.size = NCUtilityFileSystem.shared.getFileSize(filePath: fileNamePath)
                 metadataLivePhoto.status = metadata.status
-                metadataLivePhoto.chunk = chunckSize != 0 && metadata.size > chunckSize
+                if metadataLivePhoto.size > chunkSize {
+                    metadataLivePhoto.chunk = chunkSize
+                } else {
+                    metadataLivePhoto.chunk = 0
+                }
                 metadataLivePhoto.e2eEncrypted = metadata.isDirectoryE2EE
-                if metadataLivePhoto.chunk || metadataLivePhoto.e2eEncrypted {
+                if metadataLivePhoto.chunk > 0 || metadataLivePhoto.e2eEncrypted {
                     metadataLivePhoto.session = NextcloudKit.shared.nkCommonInstance.sessionIdentifierUpload
                 }
                 metadataLivePhoto.creationDate = metadata.creationDate

+ 4 - 0
iOSClient/Utility/ParallelWorker.swift

@@ -51,6 +51,10 @@ class ParallelWorker {
 
         DispatchQueue.main.async {
             let hud = JGProgressHUD()
+            hud.indicatorView = JGProgressHUDRingIndicatorView()
+            if let indicatorView = hud.indicatorView as? JGProgressHUDRingIndicatorView {
+                indicatorView.ringWidth = 1.5
+            }
             hud.textLabel.text = NSLocalizedString(self.titleKey, comment: "")
             hud.detailTextLabel.text = NSLocalizedString("_tap_to_cancel_", comment: "")
             hud.show(in: hudView)

+ 1 - 0
iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift

@@ -464,6 +464,7 @@ extension NCPlayerToolBar: NCSelectDelegate {
             } else {
                 var downloadRequest: DownloadRequest?
                 hud.indicatorView = JGProgressHUDRingIndicatorView()
+                hud.textLabel.text = NSLocalizedString("_downloading_", comment: "")
                 hud.detailTextLabel.text = NSLocalizedString("_tap_to_cancel_", comment: "")
                 if let indicatorView = hud.indicatorView as? JGProgressHUDRingIndicatorView {
                     indicatorView.ringWidth = 1.5