Procházet zdrojové kódy

Scan - Improvements (#2610)

* Update NCUploadScanDocument.swift
* Update NCScan.swift
* Update NCNetworking.swift
* Update NCManageDatabase+Metadata.swift
* Update CCAdvanced.m
* Update NCNetworkingCheckRemoteUser.swift
* fix quota, verify quota free before error 507

Signed-off-by: Marino Faggiana <marino@marinofaggiana.com>

---------

Signed-off-by: Marino Faggiana <marino@marinofaggiana.com>
Marino Faggiana před 1 rokem
rodič
revize
5b1c49a3e5

+ 3 - 6
iOSClient/AppDelegate.swift

@@ -257,9 +257,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
             NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Create share accounts \(error.localizedDescription)")
         }
 
-        NCOperationQueue.shared.cancelAllQueue()
-        NCNetworking.shared.cancelAllDownloadTransfer()
-        NextcloudKit.shared.sessionManager.cancelAllRequests()
+        NCNetworking.shared.cancelSessions(inBackground: false)
 
         presentPasscode { }
 
@@ -269,7 +267,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
     // L'applicazione terminerà
     func applicationWillTerminate(_ application: UIApplication) {
 
-        NCNetworking.shared.cancelAllDownloadTransfer()
+        NCNetworking.shared.cancelSessions(inBackground: false)
 
         if UIApplication.shared.backgroundRefreshStatus == .available {
 
@@ -560,8 +558,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
 
         guard let tableAccount = NCManageDatabase.shared.setAccountActive(account) else { return }
 
-        NCOperationQueue.shared.cancelAllQueue()
-        NCNetworking.shared.cancelAllTask()
+        NCNetworking.shared.cancelSessions(inBackground: false)
 
         self.account = tableAccount.account
         self.urlBase = tableAccount.urlBase

+ 1 - 1
iOSClient/Color/NCColorPicker.swift

@@ -199,7 +199,7 @@ class NCColorPicker: UIViewController {
             let serverUrl = metadata.serverUrl + "/" + metadata.fileName
             if NCManageDatabase.shared.setDirectory(serverUrl: serverUrl, colorFolder: hexColor, account: metadata.account) != nil {
                 self.dismiss(animated: true)
-                NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": metadata.serverUrl])
+                NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource)
             }
         }
         self.dismiss(animated: true)

+ 23 - 22
iOSClient/Data/NCManageDatabase+Metadata.swift

@@ -631,28 +631,29 @@ extension NCManageDatabase {
         do {
             let realm = try Realm()
             try realm.write {
-                let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first
-                if let newFileName = newFileName {
-                    result?.fileName = newFileName
-                    result?.fileNameView = newFileName
-                }
-                if let session = session {
-                    result?.session = session
-                }
-                if let sessionError = sessionError {
-                    result?.sessionError = sessionError
-                }
-                if let sessionSelector = sessionSelector {
-                    result?.sessionSelector = sessionSelector
-                }
-                if let sessionTaskIdentifier = sessionTaskIdentifier {
-                    result?.sessionTaskIdentifier = sessionTaskIdentifier
-                }
-                if let status = status {
-                    result?.status = status
-                }
-                if let etag = etag {
-                    result?.etag = etag
+                if let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first {
+                    if let newFileName = newFileName {
+                        result.fileName = newFileName
+                        result.fileNameView = newFileName
+                    }
+                    if let session = session {
+                        result.session = session
+                    }
+                    if let sessionError = sessionError {
+                        result.sessionError = sessionError
+                    }
+                    if let sessionSelector = sessionSelector {
+                        result.sessionSelector = sessionSelector
+                    }
+                    if let sessionTaskIdentifier = sessionTaskIdentifier {
+                        result.sessionTaskIdentifier = sessionTaskIdentifier
+                    }
+                    if let status = status {
+                        result.status = status
+                    }
+                    if let etag = etag {
+                        result.etag = etag
+                    }
                 }
             }
         } catch let error {

+ 6 - 2
iOSClient/Main/Collection Common/NCCollectionViewCommon.swift

@@ -801,7 +801,9 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
         if namedButtonMore == NCGlobal.shared.buttonMoreMore || namedButtonMore == NCGlobal.shared.buttonMoreLock {
             toggleMenu(metadata: metadata, indexPath: indexPath, imageIcon: image)
         } else if namedButtonMore == NCGlobal.shared.buttonMoreStop {
-            NCNetworking.shared.cancelTransferMetadata(metadata) { }
+            Task {
+                await NCNetworking.shared.cancel(metadata: metadata)
+            }
         }
     }
 
@@ -826,7 +828,9 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
     func tapButtonTransfer(_ sender: Any) {
         if let ocId = NCNetworking.shared.transferInForegorund?.ocId,
            let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
-            NCNetworking.shared.cancelTransferMetadata(metadata) { }
+            Task {
+                await NCNetworking.shared.cancel(metadata: metadata)
+            }
         }
     }
 

+ 1 - 1
iOSClient/Menu/NCSortMenu.swift

@@ -144,6 +144,6 @@ class NCSortMenu: NSObject {
 
         self.sortButton?.setTitle(NSLocalizedString(layoutForView.titleButtonHeader, comment: ""), for: .normal)
         NCManageDatabase.shared.setLayoutForView(layoutForView: layoutForView)
-        NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": self.serverUrl])
+        NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource)
     }
 }

+ 4 - 3
iOSClient/NCGlobal.swift

@@ -208,9 +208,10 @@ class NCGlobal: NSObject {
     @objc let errorUnauthorized401: Int             = 401
     @objc let errorForbidden: Int                   = 403
     @objc let errorResourceNotFound: Int            = 404
-    @objc let errordMethodNotSupported: Int         = 405
+    @objc let errorMethodNotSupported: Int          = 405
     @objc let errorConflict: Int                    = 409
     @objc let errorPreconditionFailed: Int          = 412
+    @objc let errorQuota: Int                       = 507
     @objc let errorUnauthorized997: Int             = 997
     @objc let errorConnectionLost: Int              = -1005
     @objc let errorNetworkNotAvailable: Int         = -1009
@@ -348,8 +349,8 @@ class NCGlobal: NSObject {
     let notificationCenterUpdateBadgeNumber                     = "updateBadgeNumber"               // userInfo: counter
     let notificationCenterReloadAvatar                          = "reloadAvatar"
 
-    @objc let notificationCenterReloadDataSource                = "reloadDataSource"                // userInfo: serverUrl?
-    let notificationCenterReloadDataSourceNetwork               = "reloadDataSourceNetwork"         // userInfo: serverUrl?
+    @objc let notificationCenterReloadDataSource                = "reloadDataSource"
+    let notificationCenterReloadDataSourceNetwork               = "reloadDataSourceNetwork"
     let notificationCenterReloadDataSourceNetworkForced         = "reloadDataSourceNetworkForced"
 
     let notificationCenterChangeStatusFolderE2EE                = "changeStatusFolderE2EE"          // userInfo: serverUrl

+ 86 - 128
iOSClient/Networking/NCNetworking.swift

@@ -284,56 +284,8 @@ class NCNetworking: NSObject, NKCommonDelegate {
         }
     }
 
-    // MARK: - Utility
-
-    func cancelTaskWithUrl(_ url: URL) {
-        NextcloudKit.shared.getSessionManager().getAllTasks { tasks in
-            tasks.filter { $0.state == .running }.filter { $0.originalRequest?.url == url }.first?.cancel()
-        }
-    }
-
-    func cancelAllTask() {
-        NextcloudKit.shared.getSessionManager().getAllTasks { tasks in
-            for task in tasks {
-                task.cancel()
-            }
-        }
-    }
-
-    func isInTaskUploadBackground(fileName: String, completion: @escaping (_ exists: Bool) -> Void) {
-
-        let sessions: [URLSession] = [NCNetworking.shared.sessionManagerBackground, NCNetworking.shared.sessionManagerBackgroundWWan]
-
-        for session in sessions {
-            session.getAllTasks(completionHandler: { tasks in
-                for task in tasks {
-                    let url = task.originalRequest?.url
-                    let urlFileName = url?.lastPathComponent
-                    if urlFileName == fileName {
-                        completion(true)
-                    }
-                }
-                if session == sessions.last {
-                    completion(false)
-                }
-            })
-        }
-    }
-
     // MARK: - Download
 
-    func cancelDownload(ocId: String, serverUrl: String, fileName: String) {
-
-        guard let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(ocId, fileNameView: fileName) else { return }
-
-        if let request = downloadRequest[fileNameLocalPath] {
-            request.cancel()
-        } else if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
-            NCManageDatabase.shared.setMetadataSession(ocId: ocId, session: "", sessionError: "", sessionSelector: "", sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusNormal)
-            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadCancelFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account])
-        }
-    }
-
     func download(metadata: tableMetadata, selector: String, notificationCenterProgressTask: Bool = true,
                   requestHandler: @escaping (_ request: DownloadRequest) -> Void = { _ in },
                   progressHandler: @escaping (_ progress: Progress) -> Void = { _ in },
@@ -768,113 +720,119 @@ class NCNetworking: NSObject, NKCommonDelegate {
         })
     }
 
-    // MARK: - Transfer (Download Upload)
+    // MARK: - Cancel (Download Upload)
 
-    func cancelTransferMetadata(_ metadata: tableMetadata, completion: @escaping () -> Void) {
+    // sessionIdentifierDownload: String = "com.nextcloud.nextcloudkit.session.download"
+    // sessionIdentifierUpload: String = "com.nextcloud.nextcloudkit.session.upload"
 
-        let metadata = tableMetadata.init(value: metadata)
+    // sessionIdentifierBackground: String = "com.nextcloud.session.upload.background"
+    // sessionIdentifierBackgroundWWan: String = "com.nextcloud.session.upload.backgroundWWan"
+    // sessionIdentifierBackgroundExtension: String = "com.nextcloud.session.upload.extension"
 
-        if metadata.session.count == 0 {
-            NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
-            return completion()
+    func cancelSessions(inBackground: Bool) {
+        Task {
+            await cancel(inBackground: inBackground)
         }
+    }
 
-        if metadata.session == NextcloudKit.shared.nkCommonInstance.sessionIdentifierDownload {
+    func cancel(inBackground: Bool) async {
 
-            NCNetworking.shared.cancelDownload(ocId: metadata.ocId, serverUrl: metadata.serverUrl, fileName: metadata.fileName)
-            return completion()
-        }
+#if !EXTENSION
+        NCOperationQueue.shared.downloadCancelAll()
+#endif
 
-        if metadata.session == NextcloudKit.shared.nkCommonInstance.sessionIdentifierUpload || metadata.chunk > 0 {
+        NextcloudKit.shared.sessionManager.cancelAllRequests()
 
-            CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
-            if let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView),
-               let request = uploadRequest[fileNameLocalPath] {
-                request.cancel()
-            }
-            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])
+        downloadRequest.removeAll()
+        uploadRequest.removeAll()
 
-            return completion()
-        }
+        let metadatasDownload = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "status < 0"))
+        let metadatasUpload = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "status > 0 AND session == %@", NextcloudKit.shared.nkCommonInstance.sessionIdentifierUpload))
+        let metadatasUploadBackground = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "status > 0 AND (session == %@ || session == %@)", NCNetworking.shared.sessionIdentifierBackground, NCNetworking.shared.sessionIdentifierBackgroundWWan))
 
-        var session: URLSession?
-        if metadata.session == NCNetworking.shared.sessionIdentifierBackground {
-            session = NCNetworking.shared.sessionManagerBackground
-        } else if metadata.session == NCNetworking.shared.sessionIdentifierBackgroundWWan {
-            session = NCNetworking.shared.sessionManagerBackgroundWWan
+        // DOWNLOAD
+        for metadata in metadatasDownload {
+            CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
+            NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: "", sessionError: "", sessionSelector: "", sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusNormal)
         }
-        if session == nil {
+        // UPLOAD
+        for metadata in metadatasUpload {
+            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])
-            return completion()
         }
 
-        session?.getTasksWithCompletionHandler { _, uploadTasks, _ in
+        guard inBackground else { return }
 
-            var cancel = false
-            if metadata.session.count > 0 && metadata.session.contains("upload") {
-                for task in uploadTasks {
-                    if task.taskIdentifier == metadata.sessionTaskIdentifier {
-                        task.cancel()
-                        cancel = true
-                    }
-                }
-                if cancel == false {
-                    do {
-                        try FileManager.default.removeItem(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
-                    } catch { }
-                    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])
-                }
-            }
-            completion()
+        // BACKGROUND
+        for metadata in metadatasUploadBackground {
+            CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
+            NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
         }
+
+        let tasksBackground = await NCNetworking.shared.sessionManagerBackground.tasks
+        for task in tasksBackground.1 { // ([URLSessionDataTask], [URLSessionUploadTask], [URLSessionDownloadTask])
+            task.cancel()
+        }
+        let tasksBackgroundWWan = await NCNetworking.shared.sessionManagerBackgroundWWan.tasks
+        for task in tasksBackgroundWWan.1 { // ([URLSessionDataTask], [URLSessionUploadTask], [URLSessionDownloadTask])
+            task.cancel()
+        }
+
+        NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource)
     }
 
-    func cancelAllTransfer(account: String, completion: @escaping () -> Void) {
+    func cancel(metadata: tableMetadata) async {
 
-        NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "status == %d OR status == %d", account, NCGlobal.shared.metadataStatusWaitUpload, NCGlobal.shared.metadataStatusUploadError))
+        let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
+        CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
 
-        let metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "status != %d", NCGlobal.shared.metadataStatusNormal))
+        // No session found
+        if metadata.session.isEmpty {
+            uploadRequest.removeValue(forKey: fileNameLocalPath)
+            downloadRequest.removeValue(forKey: fileNameLocalPath)
+            NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
+            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource)
+            return
+        }
 
-        var counter = 0
-        for metadata in metadatas {
-            counter += 1
-            if metadata.status == NCGlobal.shared.metadataStatusWaitDownload || metadata.status == NCGlobal.shared.metadataStatusDownloadError {
+        // DOWNLOAD
+        if metadata.session == NextcloudKit.shared.nkCommonInstance.sessionIdentifierDownload {
+            if let request = downloadRequest[fileNameLocalPath] {
+                request.cancel()
+            } else if let metadata = NCManageDatabase.shared.getMetadataFromOcId(metadata.ocId) {
                 NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: "", sessionError: "", sessionSelector: "", sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusNormal)
+                NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadCancelFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account])
             }
-            if metadata.status == NCGlobal.shared.metadataStatusDownloading || metadata.status == NCGlobal.shared.metadataStatusUploading {
-                self.cancelTransferMetadata(metadata) {
-                    if counter == metadatas.count {
-                        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
-                            completion()
-                        }
-                    }
-                }
-            }
+            return
         }
 
-#if !EXTENSION
-        NCOperationQueue.shared.downloadCancelAll()
-#endif
-    }
-
-    func cancelAllDownloadTransfer() {
-
-        let metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "status != %d", NCGlobal.shared.metadataStatusNormal))
-        for metadata in metadatas {
-            if metadata.status == NCGlobal.shared.metadataStatusWaitDownload || metadata.status == NCGlobal.shared.metadataStatusDownloadError {
-                NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: "", sessionError: "", sessionSelector: "", sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusNormal)
-            }
-            if metadata.status == NCGlobal.shared.metadataStatusDownloading && metadata.session == NextcloudKit.shared.nkCommonInstance.sessionIdentifierDownload {
-                cancelDownload(ocId: metadata.ocId, serverUrl: metadata.serverUrl, fileName: metadata.fileName)
+        // UPLOAD FOREGROUND
+        if metadata.session == NextcloudKit.shared.nkCommonInstance.sessionIdentifierUpload {
+            if let request = uploadRequest[fileNameLocalPath] {
+                request.cancel()
+                uploadRequest.removeValue(forKey: fileNameLocalPath)
             }
+            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])
+            return
         }
 
-#if !EXTENSION
-        NCOperationQueue.shared.downloadCancelAll()
-#endif
+        // UPLOAD BACKGROUND
+        var session: URLSession?
+        if metadata.session == NCNetworking.shared.sessionIdentifierBackground {
+            session = NCNetworking.shared.sessionManagerBackground
+        } else if metadata.session == NCNetworking.shared.sessionIdentifierBackgroundWWan {
+            session = NCNetworking.shared.sessionManagerBackgroundWWan
+        }
+        if let tasks = await session?.tasks {
+            for task in tasks.1 { // ([URLSessionDataTask], [URLSessionUploadTask], [URLSessionDownloadTask])
+                if task.taskIdentifier == metadata.sessionTaskIdentifier {
+                    task.cancel()
+                    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])
+                }
+            }
+        }
     }
 
     // MARK: - WebDav Read file, folder
@@ -1176,7 +1134,7 @@ class NCNetworking: NSObject, NKCommonDelegate {
 
         NextcloudKit.shared.createFolder(serverUrlFileName: fileNameFolderUrl) { account, _, _, error in
             guard error == .success else {
-                if error.errorCode == NCGlobal.shared.errordMethodNotSupported && overwrite {
+                if error.errorCode == NCGlobal.shared.errorMethodNotSupported && overwrite {
                     completion(NKError())
                 } else {
                     completion(error)

+ 6 - 18
iOSClient/Networking/NCNetworkingCheckRemoteUser.swift

@@ -27,28 +27,16 @@ class NCNetworkingCheckRemoteUser {
 
     func checkRemoteUser(account: String, error: NKError) {
 
-        guard let tableAccount = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", account)) else {
-            return
-        }
-
-        // remove all process ----
-
-        NCNetworking.shared.cancelAllTransfer(account: account) { }
-        NCOperationQueue.shared.cancelAllQueue()
-        NCNetworking.shared.cancelAllTask()
+        guard let tableAccount = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", account)),  
+            let token = CCUtility.getPassword(account), !token.isEmpty,
+            let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
 
-        // -----------------------
+        NCNetworking.shared.cancelSessions(inBackground: true)
 
         if NCGlobal.shared.capabilityServerVersionMajor >= NCGlobal.shared.nextcloudVersion17 {
 
-            let token = CCUtility.getPassword(account)!
-            if token.isEmpty {
-                return
-            }
-
             NextcloudKit.shared.getRemoteWipeStatus(serverUrl: tableAccount.urlBase, token: token) { account, wipe, _, error in
 
-                let appDelegate = UIApplication.shared.delegate as! AppDelegate
                 if wipe {
 
                     appDelegate.deleteAccount(account, wipe: true)
@@ -58,7 +46,7 @@ class NCNetworkingCheckRemoteUser {
 
                 } else {
 
-                    if UIApplication.shared.applicationState == .active && NextcloudKit.shared.isNetworkReachable() && !CCUtility.getPassword(account).isEmpty {
+                    if UIApplication.shared.applicationState == .active && NextcloudKit.shared.isNetworkReachable() {
                         let description = String.localizedStringWithFormat(NSLocalizedString("_error_check_remote_user_", comment: ""), tableAccount.user, tableAccount.urlBase)
                         let error = NKError(errorCode: error.errorCode, errorDescription: description)
                         NCContentPresenter.shared.showError(error: error, priority: .max)
@@ -68,7 +56,7 @@ class NCNetworkingCheckRemoteUser {
                 }
             }
 
-        } else if CCUtility.getPassword(account) != "" {
+        } else {
 
             if UIApplication.shared.applicationState == .active && NextcloudKit.shared.isNetworkReachable() {
                 let description = String.localizedStringWithFormat(NSLocalizedString("_error_check_remote_user_", comment: ""), tableAccount.user, tableAccount.urlBase)

+ 10 - 1
iOSClient/Networking/NCNetworkingProcessUpload.swift

@@ -190,7 +190,16 @@ class NCNetworkingProcessUpload: NSObject {
                 if counterUpload == 0 {
                     let metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND status == %d", self.appDelegate.account, NCGlobal.shared.metadataStatusUploadError))
                     for metadata in metadatas {
-                        NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: NCNetworking.shared.sessionIdentifierBackground, sessionError: "", sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusWaitUpload)
+                        // Verify QUOTA
+                        if metadata.sessionError.contains("\(NCGlobal.shared.errorQuota)") {
+                            NextcloudKit.shared.getUserProfile { account, userProfile, _, error in
+                                if error == .success, let userProfile, userProfile.quotaFree > 0, userProfile.quotaFree > metadata.size {
+                                    NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: NCNetworking.shared.sessionIdentifierBackground, sessionError: "", sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusWaitUpload)
+                                }
+                            }
+                        } else {
+                            NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: NCNetworking.shared.sessionIdentifierBackground, sessionError: "", sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusWaitUpload)
+                        }
                     }
 
                     // verify delete Asset Local Identifiers in auto upload (DELETE Photos album)

+ 8 - 9
iOSClient/Scan document/NCScan.storyboard

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="bdK-eL-mz4">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="bdK-eL-mz4">
     <device id="retina4_7" orientation="portrait" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21678"/>
         <capability name="Safe area layout guides" minToolsVersion="9.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
@@ -17,7 +17,7 @@
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                         <subviews>
                             <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="jwq-kF-6Nq" userLabel="collectionViewSource">
-                                <rect key="frame" x="57" y="44" width="318" height="160"/>
+                                <rect key="frame" x="57" y="64" width="318" height="160"/>
                                 <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                 <constraints>
                                     <constraint firstAttribute="height" constant="160" id="0Wb-eO-Qiu"/>
@@ -69,7 +69,7 @@
                                 </connections>
                             </collectionView>
                             <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="fGo-qU-AYi" userLabel="collectionViewDestination">
-                                <rect key="frame" x="0.0" y="239" width="375" height="378"/>
+                                <rect key="frame" x="0.0" y="259" width="375" height="358"/>
                                 <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                 <collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="0.0" minimumInteritemSpacing="0.0" id="9Sn-Y3-S86">
                                     <size key="itemSize" width="120" height="120"/>
@@ -149,7 +149,7 @@
                                 </connections>
                             </collectionView>
                             <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="PDF" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YHy-9G-ngy">
-                                <rect key="frame" x="0.0" y="204" width="375" height="30"/>
+                                <rect key="frame" x="0.0" y="224" width="375" height="30"/>
                                 <color key="backgroundColor" white="1" alpha="0.5" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                 <constraints>
                                     <constraint firstAttribute="height" constant="30" id="vrg-ki-2Lk"/>
@@ -159,7 +159,7 @@
                                 <nil key="highlightedColor"/>
                             </label>
                             <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0Gy-eG-A0f">
-                                <rect key="frame" x="20" y="74" width="30" height="30"/>
+                                <rect key="frame" x="20" y="94" width="30" height="30"/>
                                 <constraints>
                                     <constraint firstAttribute="height" constant="30" id="A6e-zC-q5t"/>
                                     <constraint firstAttribute="width" constant="30" id="U2p-ow-Iad"/>
@@ -177,14 +177,13 @@
                                 <segments>
                                     <segment title="First"/>
                                     <segment title="Second"/>
-                                    <segment title="Third"/>
                                 </segments>
                                 <connections>
                                     <action selector="indexChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="yeI-C2-uGJ"/>
                                 </connections>
                             </segmentedControl>
                             <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Fqr-e6-s3n" userLabel="transferDown">
-                                <rect key="frame" x="20" y="144" width="30" height="30"/>
+                                <rect key="frame" x="20" y="164" width="30" height="30"/>
                                 <constraints>
                                     <constraint firstAttribute="height" constant="30" id="YPl-DJ-aNS"/>
                                     <constraint firstAttribute="width" constant="30" id="yGb-Y2-8Oj"/>
@@ -251,7 +250,7 @@
                 <navigationController automaticallyAdjustsScrollViewInsets="NO" modalPresentationStyle="fullScreen" id="bdK-eL-mz4" sceneMemberID="viewController">
                     <toolbarItems/>
                     <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="xl6-fB-rBw">
-                        <rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
+                        <rect key="frame" x="0.0" y="20" width="375" height="44"/>
                         <autoresizingMask key="autoresizingMask"/>
                     </navigationBar>
                     <nil name="viewControllers"/>

+ 25 - 26
iOSClient/Scan document/NCScan.swift

@@ -48,11 +48,10 @@ class NCScan: UIViewController, NCScanCellCellDelegate {
     private var tipView: EasyTipView?
 
     enum TypeFilter {
+        case document
         case original
-        case grayScale
-        case bn
     }
-    internal var filter: TypeFilter = TypeFilter.original
+    internal var filter: TypeFilter = TypeFilter.document
 
     // MARK: - View Life Cycle
 
@@ -80,9 +79,8 @@ class NCScan: UIViewController, NCScanCellCellDelegate {
         labelTitlePDFzone.backgroundColor = .systemGray6
         labelTitlePDFzone.textColor = .label
 
-        segmentControlFilter.setTitle(NSLocalizedString("_filter_original_", comment: ""), forSegmentAt: 0)
-        segmentControlFilter.setTitle(NSLocalizedString("_filter_grayscale_", comment: ""), forSegmentAt: 1)
-        segmentControlFilter.setTitle(NSLocalizedString("_filter_bn_", comment: ""), forSegmentAt: 2)
+        segmentControlFilter.setTitle(NSLocalizedString("_filter_document_", comment: ""), forSegmentAt: 0)
+        segmentControlFilter.setTitle(NSLocalizedString("_filter_original_", comment: ""), forSegmentAt: 1)
 
         add.setImage(UIImage(systemName: "plus")?.image(color: .label, size: 25), for: .normal)
         transferDown.setImage(UIImage(systemName: "arrow.down")?.image(color: .label, size: 25), for: .normal)
@@ -215,11 +213,9 @@ class NCScan: UIViewController, NCScanCellCellDelegate {
 
         switch segmentControlFilter.selectedSegmentIndex {
         case 0:
-            filter = .original
+            filter = .document
         case 1:
-            filter = .grayScale
-        case 2:
-            filter = .bn
+            filter = .original
         default:
             break
         }
@@ -253,28 +249,31 @@ class NCScan: UIViewController, NCScanCellCellDelegate {
         }
     }
 
+    /*
+     func applyGrayScaleFilter(image: UIImage?) -> UIImage? {
+             guard let ciImage = image?.ciImage else { return nil }
+             let filter = CIFilter(name: "CIColorControls",
+                                   parameters: ["inputImage" : ciImage,
+                                                "inputContrast": NSNumber(1.0),
+                                                "inputSaturation": NSNumber(0.0),
+                                                "inputBrightness": NSNumber(0.0)])
+             guard let out = filter?.outputImage else { return nil }
+             return UIImage(ciImage: out)
+         }
+     */
+
     func filter(image: UIImage) -> UIImage? {
 
-        var inputContrast: Double = 0
+        guard let ciImage = CIImage(image: image) else { return image }
 
-        if filter == .original {
+        if filter == .document {
+            let imageFilter = ciImage.applyingFilter("CIColorControls", parameters: ["inputSaturation": 0, "inputContrast": 1.1]).applyingFilter("CIDocumentEnhancer", parameters: ["inputAmount": 5])
+            let context: CIContext = CIContext(options: nil)
+            let cgImage: CGImage = context.createCGImage(imageFilter, from: imageFilter.extent)!
+            let image: UIImage = UIImage(cgImage: cgImage)
             return image
         }
 
-        if filter == .grayScale {
-            inputContrast = 1
-        }
-
-        if filter == .bn {
-            inputContrast = 4
-        }
-
-        let ciImage = CIImage(image: image)!
-        let imageFilter = ciImage.applyingFilter("CIColorControls", parameters: ["inputSaturation": 0, "inputContrast": inputContrast])
-
-        let context: CIContext = CIContext(options: nil)
-        let cgImage: CGImage = context.createCGImage(imageFilter, from: imageFilter.extent)!
-        let image: UIImage = UIImage(cgImage: cgImage)
         return image
     }
 

+ 9 - 19
iOSClient/Scan document/NCUploadScanDocument.swift

@@ -182,30 +182,20 @@ class NCUploadScanDocument: ObservableObject {
     private func changeCompressionImage(_ image: UIImage, quality: Double) -> UIImage {
 
         var compressionQuality: CGFloat = 0.0
-        var baseHeight: Float = 595.2    // A4
-        var baseWidth: Float = 841.8     // A4
+        let baseHeight: Float = 595.2    // A4
+        let baseWidth: Float = 841.8     // A4
 
         switch quality {
         case 0:
-            baseHeight *= 2
-            baseWidth *= 2
-            compressionQuality = 0.3
+            compressionQuality = 0.1
         case 1:
-            baseHeight *= 3
-            baseWidth *= 3
-            compressionQuality = 0.4
+            compressionQuality = 0.3
         case 2:
-            baseHeight *= 4
-            baseWidth *= 4
             compressionQuality = 0.5
         case 3:
-            baseHeight *= 5
-            baseWidth *= 5
-            compressionQuality = 0.6
+            compressionQuality = 0.7
         case 4:
-            baseHeight = Float(image.size.height)
-            baseWidth = Float(image.size.width)
-            compressionQuality = 0.6
+            compressionQuality = 0.9
         default:
             break
         }
@@ -231,7 +221,7 @@ class NCUploadScanDocument: ObservableObject {
         }
 
         let rect = CGRect(x: 0.0, y: 0.0, width: CGFloat(newWidth), height: CGFloat(newHeight))
-        UIGraphicsBeginImageContext(rect.size)
+        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
         image.draw(in: rect)
         let img = UIGraphicsGetImageFromCurrentImageContext()
         let imageData = img?.jpegData(compressionQuality: CGFloat(compressionQuality))
@@ -502,7 +492,7 @@ struct UploadScanDocumentView: View {
                 }
                 HUDView(showHUD: $uploadScanDocument.showHUD, textLabel: NSLocalizedString("_wait_", comment: ""), image: "doc.badge.arrow.up")
                     .offset(y: uploadScanDocument.showHUD ? 5 : -200)
-                    .animation(.easeOut)
+                    .animation(.easeOut, value: UUID())
             }
         }
         .background(Color(UIColor.systemGroupedBackground))
@@ -512,7 +502,7 @@ struct UploadScanDocumentView: View {
         .sheet(isPresented: $isPresentedUploadConflict) {
             UploadConflictView(delegate: uploadScanDocument, serverUrl: uploadScanDocument.serverUrl, metadatasUploadInConflict: [uploadScanDocument.metadata], metadatasNOConflict: [])
         }.onTapGesture {
-            UIApplication.shared.windows.filter { $0.isKeyWindow }.first?.endEditing(true)
+            UIApplication.shared.connectedScenes.flatMap { ($0 as? UIWindowScene)?.windows ?? [] }.filter { $0.isKeyWindow }.first?.endEditing(true)
         }
     }
 }

+ 39 - 31
iOSClient/Settings/CCAdvanced.m

@@ -367,26 +367,25 @@
 
 - (void)clearCache:(NSString *)account
 {
-    [[NCNetworking shared] cancelAllTransferWithAccount:account completion:^{ }];
-    [[NCOperationQueue shared] cancelAllQueue];
-    [[NCNetworking shared] cancelAllTask];
-    
-    [[NSURLCache sharedURLCache] setMemoryCapacity:0];
-    [[NSURLCache sharedURLCache] setDiskCapacity:0];
-    
-    [[NCManageDatabase shared] clearDatabaseWithAccount:account removeAccount:false];
-    
-    [CCUtility removeGroupDirectoryProviderStorage];
-    [CCUtility removeGroupLibraryDirectory];
+    [[NCNetworking shared] cancelSessionsInBackground:true];
 
-    [CCUtility removeDocumentsDirectory];
-    [CCUtility removeTemporaryDirectory];
-    
-    [CCUtility createDirectoryStandard];
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void) {
 
-    [[NCAutoUpload shared] alignPhotoLibraryWithViewController:self];
+        [[NSURLCache sharedURLCache] setMemoryCapacity:0];
+        [[NSURLCache sharedURLCache] setDiskCapacity:0];
+
+        [[NCManageDatabase shared] clearDatabaseWithAccount:account removeAccount:false];
+
+        [CCUtility removeGroupDirectoryProviderStorage];
+        [CCUtility removeGroupLibraryDirectory];
+
+        [CCUtility removeDocumentsDirectory];
+        [CCUtility removeTemporaryDirectory];
+
+        [CCUtility createDirectoryStandard];
+
+        [[NCAutoUpload shared] alignPhotoLibraryWithViewController:self];
 
-    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void) {
         [[NCActivityIndicator shared] stop];
         [self calculateSize];
     });
@@ -419,7 +418,11 @@
 - (void)clearAllCacheRequest:(XLFormRowDescriptor *)sender
 {
     [self deselectFormRow:sender];
-    [self clearCache:nil];
+
+    [[NCActivityIndicator shared] startActivityWithBackgroundView:nil style: UIActivityIndicatorViewStyleLarge blurEffect:true];
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void) {
+        [self clearCache:nil];
+    });
 }
 
 - (void)calculateSize
@@ -445,20 +448,25 @@
     
     [alertController addAction: [UIAlertAction actionWithTitle:NSLocalizedString(@"_ok_", nil) style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {
                 
-        [[NSURLCache sharedURLCache] setMemoryCapacity:0];
-        [[NSURLCache sharedURLCache] setDiskCapacity:0];
+        [[NCNetworking shared] cancelSessionsInBackground:true];
 
-        [CCUtility removeGroupDirectoryProviderStorage];
-        [CCUtility removeGroupApplicationSupport];
-        
-        [CCUtility removeDocumentsDirectory];
-        [CCUtility removeTemporaryDirectory];
-        
-        [CCUtility deleteAllChainStore];
-        
-        [[NCManageDatabase shared] removeDB];
-        
-        exit(0);
+        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void) {
+
+            [[NCManageDatabase shared] removeDB];
+
+            [[NSURLCache sharedURLCache] setMemoryCapacity:0];
+            [[NSURLCache sharedURLCache] setDiskCapacity:0];
+
+            [CCUtility removeGroupDirectoryProviderStorage];
+            [CCUtility removeGroupApplicationSupport];
+
+            [CCUtility removeDocumentsDirectory];
+            [CCUtility removeTemporaryDirectory];
+
+            [CCUtility deleteAllChainStore];
+
+            exit(0);
+        });
     }]];
     
     [alertController addAction: [UIAlertAction actionWithTitle:NSLocalizedString(@"_cancel_", nil) style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {

+ 1 - 1
iOSClient/Share/NCSharePaging.swift

@@ -118,7 +118,7 @@ class NCSharePaging: UIViewController {
 
     override func viewWillDisappear(_ animated: Bool) {
         super.viewWillDisappear(animated)
-        NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": metadata.serverUrl])
+        NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource)
     }
 
     deinit {

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

@@ -715,6 +715,7 @@
 "_scanned_images_"                  = "Scanned images";
 "_scan_document_pdf_page_"          = "Page";
 "_scan_label_document_zone_"        = "Drag images down for document creation";
+"_filter_document_"                 = "Document";
 "_filter_original_"                 = "Original";
 "_filter_bn_"                       = "Black & White";
 "_filter_grayscale_"                = "Grayscale";

+ 6 - 4
iOSClient/Transfers/NCTransfers.swift

@@ -106,8 +106,8 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
 
         alertController.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel, handler: nil))
         alertController.addAction(UIAlertAction(title: NSLocalizedString("_cancel_all_task_", comment: ""), style: .default, handler: { _ in
-            NCNetworking.shared.cancelAllTransfer(account: self.appDelegate.account) {
-                self.reloadDataSource()
+            Task {
+                await NCNetworking.shared.cancel(inBackground: true)
             }
         }))
 
@@ -269,8 +269,10 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
         super.reloadDataSource()
 
         self.queryDB(isForced: isForced)
-        self.refreshControl.endRefreshing()
-        self.collectionView.reloadData()
+        DispatchQueue.main.async {
+            self.refreshControl.endRefreshing()
+            self.collectionView.reloadData()
+        }
     }
 
     override func reloadDataSourceNetwork(isForced: Bool = false) {