Skip to content

Commit 4f88064

Browse files
Merge pull request #3728 from nextcloud/createFolderAU
Create folder auto upload
2 parents 6009c98 + db19c35 commit 4f88064

File tree

6 files changed

+99
-81
lines changed

6 files changed

+99
-81
lines changed

iOSClient/AppDelegate.swift

Lines changed: 6 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -291,50 +291,23 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
291291
return numTransfers
292292
}
293293

294-
// AUTO UPLOAD for get new photo
294+
// AUTO UPLOAD for get new photo
295295
let num = await NCAutoUpload.shared.initAutoUpload(tblAccount: tblAccount)
296296
nkLog(tag: self.global.logTagBgSync, emoji: .start, message: "Auto upload with \(num) new photo for \(tblAccount.account)")
297297

298298
// CREATION FOLDERS
299299
let predicateCreateFolder = NSPredicate(format: "status == %d AND sessionSelector == %@", self.global.metadataStatusWaitCreateFolder, self.global.selectorUploadAutoUpload)
300300
let metadatasWaitCreateFolder = await NCManageDatabase.shared.getMetadatasAsync(predicate: predicateCreateFolder,
301-
withLimit: NCBrandOptions.shared.httpMaximumConnectionsPerHost)
302-
303-
if let metadatasWaitCreateFolder,
304-
!metadatasWaitCreateFolder.isEmpty {
305-
var successCountCreateFolder: Int = 0
306-
for metadata in metadatasWaitCreateFolder {
307-
let serverUrl = NCUtilityFileSystem().createServerUrl(serverUrl: metadata.serverUrl, fileName: metadata.fileName)
308-
let resultsCreateFolder = await NCNetworking.shared.createFolder(fileName: metadata.fileName,
309-
serverUrl: metadata.serverUrl,
310-
overwrite: true,
311-
session: NCSession.shared.getSession(account: metadata.account),
312-
selector: metadata.sessionSelector)
313-
314-
guard resultsCreateFolder.error == .success else {
315-
nkLog(tag: self.global.logTagBgSync, emoji: .error, message: "Auto upload create folder \(serverUrl) with error: \(resultsCreateFolder.error.errorCode)")
316-
317-
return numTransfers
318-
}
319-
320-
nkLog(tag: self.global.logTagBgSync, message: "Auto upload create folder \(serverUrl)")
321-
322-
if resultsCreateFolder.serverExists == false {
323-
numTransfers += 1
324-
successCountCreateFolder += 1
325-
}
326-
}
301+
withLimit: NCBrandOptions.shared.httpMaximumConnectionsPerHost) ?? []
327302

328-
// Exit until there are no more folders to create
329-
if successCountCreateFolder == metadatasWaitCreateFolder.count {
303+
for metadata in metadatasWaitCreateFolder {
304+
let error = await NCNetworking.shared.createFolderForAutoUpload(serverUrlFileName: metadata.serverUrlFileName, account: metadata.account)
305+
guard error == .success else {
306+
nkLog(tag: self.global.logTagBgSync, emoji: .error, message: "Auto upload create folder \(metadata.serverUrlFileName) with error: \(error.errorCode)")
330307
return numTransfers
331308
}
332309
}
333310

334-
if numTransfers >= NCBrandOptions.shared.httpMaximumConnectionsPerHostInUpload {
335-
return numTransfers
336-
}
337-
338311
// UPLOAD
339312
let predicateUpload = NSPredicate(format: "status == %d AND sessionSelector == %@ AND chunk == 0", self.global.metadataStatusWaitUpload, self.global.selectorUploadAutoUpload)
340313
let metadatasWaitUpload = await NCManageDatabase.shared.getMetadatasAsync(predicate: predicateUpload,

iOSClient/Data/NCManageDatabase+Metadata+Session.swift

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ extension NCManageDatabase {
2525
/// - errorCode: Optional error code to persist.
2626
/// - Returns: A detached copy of the updated `tableMetadata` object, or `nil` if not found.
2727
@discardableResult
28-
func setMetadataSessionAsync(ocId: String,
28+
func setMetadataSessionAsync(account: String? = nil,
29+
ocId: String? = nil,
30+
serverUrlFileName: String? = nil,
2931
newFileName: String? = nil,
3032
session: String? = nil,
3133
sessionTaskIdentifier: Int? = nil,
@@ -35,9 +37,18 @@ extension NCManageDatabase {
3537
etag: String? = nil,
3638
errorCode: Int? = nil,
3739
progress: Double? = nil) async -> tableMetadata? {
40+
var query: NSPredicate = NSPredicate()
41+
if let ocId {
42+
query = NSPredicate(format: "ocId == %@", ocId)
43+
} else if let account, let serverUrlFileName {
44+
query = NSPredicate(format: "account == %@ AND serverUrlFileName == %@", account, serverUrlFileName)
45+
} else {
46+
return nil
47+
}
48+
3849
await performRealmWriteAsync { realm in
3950
guard let metadata = realm.objects(tableMetadata.self)
40-
.filter("ocId == %@", ocId)
51+
.filter(query)
4152
.first else {
4253
return
4354
}
@@ -93,7 +104,7 @@ extension NCManageDatabase {
93104

94105
return await performRealmReadAsync { realm in
95106
realm.objects(tableMetadata.self)
96-
.filter("ocId == %@", ocId)
107+
.filter(query)
97108
.first?
98109
.detachedCopy()
99110
}

iOSClient/Extensions/UIAlertController+Extension.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ extension UIAlertController {
7777
} else {
7878
#if EXTENSION
7979
Task {
80-
let results = await NCNetworking.shared.createFolder(fileName: fileNameFolder, serverUrl: serverUrl, overwrite: false, session: session)
81-
completion?(results.error)
80+
let error = await NCNetworking.shared.createFolder(fileName: fileNameFolder, serverUrl: serverUrl, overwrite: false, session: session)
81+
completion?(error)
8282
}
8383
#else
8484
var metadata = tableMetadata()

iOSClient/Networking/NCNetworking+WebDAV.swift

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -107,40 +107,22 @@ extension NCNetworking {
107107
return(account, metadata, results.error)
108108
}
109109

110-
func fileExists(serverUrlFileName: String,
111-
account: String,
112-
completion: @escaping (_ account: String, _ exists: Bool, _ file: NKFile?, _ error: NKError) -> Void) {
113-
let options = NKRequestOptions(timeout: 10, queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)
110+
func fileExists(serverUrlFileName: String, account: String) async -> NKError? {
114111
let requestBody = NKDataFileXML(nkCommonInstance: NextcloudKit.shared.nkCommonInstance).getRequestBodyFileExists().data(using: .utf8)
115112

116-
NextcloudKit.shared.readFileOrFolder(serverUrlFileName: serverUrlFileName,
117-
depth: "0",
118-
requestBody: requestBody,
119-
account: account,
120-
options: options) { task in
113+
let results = await NextcloudKit.shared.readFileOrFolderAsync(serverUrlFileName: serverUrlFileName,
114+
depth: "0",
115+
requestBody: requestBody,
116+
account: account) { task in
121117
Task {
122118
let identifier = await NCNetworking.shared.networkingTasks.createIdentifier(account: account,
123119
path: serverUrlFileName,
124120
name: "readFileOrFolder")
125121
await NCNetworking.shared.networkingTasks.track(identifier: identifier, task: task)
126122
}
127-
} completion: { account, files, _, error in
128-
if error == .success, let file = files?.first {
129-
completion(account, true, file, error)
130-
} else if error.errorCode == self.global.errorResourceNotFound {
131-
completion(account, false, nil, error)
132-
} else {
133-
completion(account, false, nil, error)
134-
}
135123
}
136-
}
137124

138-
func fileExists(serverUrlFileName: String, account: String) async -> (account: String, exists: Bool, file: NKFile?, error: NKError) {
139-
await withUnsafeContinuation({ continuation in
140-
fileExists(serverUrlFileName: serverUrlFileName, account: account) { account, exists, file, error in
141-
continuation.resume(returning: (account, exists, file, error))
142-
}
143-
})
125+
return results.error
144126
}
145127

146128
// MARK: - Create Filename
@@ -187,8 +169,8 @@ extension NCNetworking {
187169
continue
188170
}
189171
let serverUrlFileName = utilityFileSystem.createServerUrl(serverUrl: serverUrl, fileName: resultFileName)
190-
let results = await fileExists(serverUrlFileName: serverUrlFileName, account: account)
191-
if results.exists {
172+
let error = await fileExists(serverUrlFileName: serverUrlFileName, account: account)
173+
if error == .success {
192174
newFileName()
193175
} else {
194176
exitLoop = true
@@ -204,15 +186,14 @@ extension NCNetworking {
204186
overwrite: Bool,
205187
session: NCSession.Session,
206188
selector: String? = nil,
207-
options: NKRequestOptions = NKRequestOptions()) async -> (serverExists: Bool, error: NKError) {
208-
189+
options: NKRequestOptions = NKRequestOptions()) async -> NKError {
209190
let capabilities = await NKCapabilities.shared.getCapabilities(for: session.account)
210191
var fileNameFolder = FileAutoRenamer.rename(fileName, isFolderPath: true, capabilities: capabilities)
211192
if !overwrite {
212193
fileNameFolder = utilityFileSystem.createFileName(fileNameFolder, serverUrl: serverUrl, account: session.account)
213194
}
214195
if fileNameFolder.isEmpty {
215-
return (false, NKError(errorCode: global.errorIncorrectFileName, errorDescription: ""))
196+
return NKError(errorCode: global.errorIncorrectFileName, errorDescription: "")
216197
}
217198
let serverUrlFileName = utilityFileSystem.createServerUrl(serverUrl: serverUrl, fileName: fileNameFolder)
218199

@@ -221,7 +202,7 @@ extension NCNetworking {
221202
if resultReadFile.error == .success,
222203
let metadata = resultReadFile.metadata {
223204
await NCManageDatabase.shared.createDirectory(metadata: metadata)
224-
return (true, .success)
205+
return .success
225206
}
226207

227208
/* create folder */
@@ -239,9 +220,47 @@ extension NCNetworking {
239220
let metadata = resultReadFile.metadata {
240221
await NCManageDatabase.shared.createDirectory(metadata: metadata)
241222
}
223+
} else {
224+
await NCManageDatabase.shared.setMetadataSessionAsync(account: session.account,
225+
serverUrlFileName: serverUrlFileName,
226+
sessionError: resultCreateFolder.error.errorDescription,
227+
errorCode: resultCreateFolder.error.errorCode)
228+
}
229+
230+
return resultCreateFolder.error
231+
}
232+
233+
func createFolderForAutoUpload(serverUrlFileName: String,
234+
account: String) async -> NKError {
235+
// Fast path: directory already exists → cleanup + success
236+
let error = await fileExists(serverUrlFileName: serverUrlFileName, account: account)
237+
if error == .success {
238+
await NCManageDatabase.shared.deleteMetadataAsync(predicate: NSPredicate(format: "account == %@ AND serverUrlFileName == %@", account, serverUrlFileName))
239+
return (.success)
240+
}
241+
242+
// Try to create the directory
243+
let results = await NextcloudKit.shared.createFolderAsync(serverUrlFileName: serverUrlFileName, account: account) { task in
244+
Task {
245+
let identifier = await NCNetworking.shared.networkingTasks.createIdentifier(account: account,
246+
path: serverUrlFileName,
247+
name: "createFolder")
248+
await NCNetworking.shared.networkingTasks.track(identifier: identifier, task: task)
249+
}
250+
}
251+
252+
// If creation reported success → cleanup
253+
if results.error == .success {
254+
await NCManageDatabase.shared.deleteMetadataAsync(predicate: NSPredicate(format: "account == %@ AND serverUrlFileName == %@", account, serverUrlFileName))
255+
} else {
256+
// set error
257+
await NCManageDatabase.shared.setMetadataSessionAsync(account: account,
258+
serverUrlFileName: serverUrlFileName,
259+
sessionError: results.error.errorDescription,
260+
errorCode: results.error.errorCode)
242261
}
243262

244-
return (false, resultCreateFolder.error)
263+
return results.error
245264
}
246265

247266
// MARK: - Delete

iOSClient/Networking/NCNetworkingProcess.swift

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,8 @@ actor NCNetworkingProcess {
170170
/// ------------------------ WEBDAV
171171
let waitWebDav = metadatas.filter { self.global.metadataStatusWaitWebDav.contains($0.status) }
172172
if !waitWebDav.isEmpty {
173-
let (status, error) = await metadataStatusWaitWebDav(metadatas: Array(waitWebDav))
174-
if (error == .cancelled) || (status == global.metadataStatusWaitDelete && error != .success) {
173+
let (_, error) = await metadataStatusWaitWebDav(metadatas: Array(waitWebDav))
174+
if error != .success {
175175
return
176176
}
177177
}
@@ -336,30 +336,39 @@ actor NCNetworkingProcess {
336336
guard timer != nil else {
337337
return (global.metadataStatusWaitCreateFolder, .cancelled)
338338
}
339+
var error: NKError = .success
340+
341+
if metadata.sessionSelector == self.global.selectorUploadAutoUpload {
342+
error = await networking.createFolderForAutoUpload(serverUrlFileName: metadata.serverUrlFileName, account: metadata.account)
343+
if error != .success {
344+
return (global.metadataStatusWaitCreateFolder, error)
345+
}
346+
} else {
347+
error = await networking.createFolder(fileName: metadata.fileName,
348+
serverUrl: metadata.serverUrl,
349+
overwrite: true,
350+
session: NCSession.shared.getSession(account: metadata.account),
351+
selector: metadata.sessionSelector)
352+
}
339353

340-
let resultsCreateFolder = await networking.createFolder(fileName: metadata.fileName,
341-
serverUrl: metadata.serverUrl,
342-
overwrite: true,
343-
session: NCSession.shared.getSession(account: metadata.account),
344-
selector: metadata.sessionSelector)
345354
if let sceneIdentifier = metadata.sceneIdentifier {
346355
await networking.transferDispatcher.notifyDelegates(forScene: sceneIdentifier) { delegate in
347356
delegate.transferChange(status: self.global.networkingStatusCreateFolder,
348357
metadata: metadata,
349-
error: resultsCreateFolder.error)
358+
error: error)
350359
} others: { delegate in
351360
delegate.transferReloadData(serverUrl: metadata.serverUrl, status: nil)
352361
}
353362
} else {
354363
await networking.transferDispatcher.notifyAllDelegates { delegate in
355364
delegate.transferChange(status: self.global.networkingStatusCreateFolder,
356365
metadata: metadata,
357-
error: resultsCreateFolder.error)
366+
error: error)
358367
}
359368
}
360369

361-
if resultsCreateFolder.error != .success {
362-
return (global.metadataStatusWaitCreateFolder, resultsCreateFolder.error)
370+
if error != .success {
371+
return (global.metadataStatusWaitCreateFolder, error)
363372
}
364373
}
365374

iOSClient/Transfers/NCTransfers.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
218218
cell.labelStatus.text = NSLocalizedString("_status_uploading_", comment: "") + user
219219
cell.labelInfo.text = utilityFileSystem.transformedSize(metadata.size)
220220
case NCGlobal.shared.metadataStatusDownloadError, NCGlobal.shared.metadataStatusUploadError:
221-
cell.imageStatus?.image = utility.loadImage(named: "exclamationmark.circle", colors: NCBrandColor.shared.iconImageMultiColors)
221+
cell.imageStatus?.image = utility.loadImage(named: "exclamationmark.circle", colors: [.red, .label])
222222
cell.labelStatus.text = NSLocalizedString("_status_upload_error_", comment: "") + user
223223
cell.labelInfo.text = metadata.sessionError
224224
default:
@@ -232,6 +232,12 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
232232
}
233233
cell.accessibilityLabel = metadata.fileNameView + ", " + (cell.labelInfo.text ?? "")
234234

235+
// Error
236+
if (metadata.errorCode != 0 || !metadata.sessionError.isEmpty) && cell.labelInfo.text?.isEmpty == true {
237+
cell.imageStatus?.image = utility.loadImage(named: "exclamationmark.circle", colors: [.red, .label])
238+
cell.labelInfo.text = metadata.sessionError + " cod. \(metadata.errorCode)"
239+
}
240+
235241
// Remove last separator
236242
if collectionView.numberOfItems(inSection: indexPath.section) == indexPath.row + 1 {
237243
cell.separator.isHidden = true

0 commit comments

Comments
 (0)