Browse Source

Merge pull request #2147 from nextcloud/feature/DashboardWidget

Feature/dashboard widget
Marino Faggiana 2 years ago
parent
commit
30e43a7898
100 changed files with 3274 additions and 1245 deletions
  1. 4 1
      .swiftlint.yml
  2. 6 8
      File Provider Extension/FileProviderData.swift
  3. 5 5
      File Provider Extension/FileProviderEnumerator.swift
  4. 13 13
      File Provider Extension/FileProviderExtension+Actions.swift
  5. 19 13
      File Provider Extension/FileProviderExtension+Thumbnail.swift
  6. 11 11
      File Provider Extension/FileProviderExtension.swift
  7. 2 2
      File Provider Extension/FileProviderItem.swift
  8. 398 34
      Nextcloud.xcodeproj/project.pbxproj
  9. 97 0
      Nextcloud.xcodeproj/xcshareddata/xcschemes/Notification Service Extension.xcscheme
  10. 124 0
      Nextcloud.xcodeproj/xcshareddata/xcschemes/Widget.xcscheme
  11. 5 5
      NextcloudTests/SharePermissionTest.swift
  12. 2 2
      Share/NCShareCell.swift
  13. 1 1
      Share/NCShareExtension+DataSource.swift
  14. 3 3
      Share/NCShareExtension+Files.swift
  15. 3 4
      Share/NCShareExtension+NCDelegate.swift
  16. 12 12
      Share/NCShareExtension.swift
  17. 11 0
      Widget/Assets.xcassets/AccentColor.colorset/Contents.json
  18. 11 0
      Widget/Assets.xcassets/AppIcon.imageset/Contents.json
  19. 6 0
      Widget/Assets.xcassets/Contents.json
  20. 11 0
      Widget/Assets.xcassets/WidgetBackground.colorset/Contents.json
  21. 12 0
      Widget/Assets.xcassets/nextcloud.imageset/Contents.json
  22. BIN
      Widget/Assets.xcassets/nextcloud.imageset/nextcloud-icon29@1x.png
  23. 137 0
      Widget/Dashboard/DashboardData.swift
  24. 48 0
      Widget/Dashboard/DashboardWidgetProvider.swift
  25. 75 0
      Widget/Dashboard/DashboardWidgetView.swift
  26. 230 0
      Widget/Nextcloud/NextcloudData.swift
  27. 49 0
      Widget/Nextcloud/NextcloudWidgetProvider.swift
  28. 182 0
      Widget/Nextcloud/NextcloudWidgetView.swift
  29. 44 0
      Widget/Toolbar/ToolbarData.swift
  30. 47 0
      Widget/Toolbar/ToolbarWidgetProvider.swift
  31. 118 0
      Widget/Toolbar/ToolbarWidgetView.swift
  32. 5 0
      Widget/Widget-Brinding-header.h
  33. 59 0
      Widget/Widget.intentdefinition
  34. 75 0
      Widget/Widget.swift
  35. 1 1
      iOSClient/Account Request/NCAccountRequest.swift
  36. 24 24
      iOSClient/Activity/NCActivity.swift
  37. 8 7
      iOSClient/Activity/NCActivityTableViewCell.swift
  38. 114 33
      iOSClient/AppDelegate.swift
  39. 3 3
      iOSClient/Brand/NCBrand.swift
  40. 4 10
      iOSClient/Brand/NCBridgeSwift.h
  41. 14 0
      iOSClient/Brand/Widget.entitlements
  42. 16 0
      iOSClient/Brand/Widget.plist
  43. 9 9
      iOSClient/Data/NCDataSource.swift
  44. 2 2
      iOSClient/Data/NCDatabase.swift
  45. 15 15
      iOSClient/Data/NCManageDatabase+Account.swift
  46. 6 6
      iOSClient/Data/NCManageDatabase+Activity.swift
  47. 47 38
      iOSClient/Data/NCManageDatabase+Metadata.swift
  48. 4 4
      iOSClient/Data/NCManageDatabase+Video.swift
  49. 57 55
      iOSClient/Data/NCManageDatabase.swift
  50. 7 6
      iOSClient/Diagnostics/NCCapabilitiesViewController.swift
  51. 7 0
      iOSClient/Extensions/String+Extensions.swift
  52. 6 5
      iOSClient/Extensions/UIAlertController+Extension.swift
  53. 2 2
      iOSClient/Extensions/UIControl+Extensions.swift
  54. 6 6
      iOSClient/Favorites/NCFavorite.swift
  55. 3 3
      iOSClient/Files/NCFiles.swift
  56. 12 8
      iOSClient/Login/NCAppConfigView.swift
  57. 13 13
      iOSClient/Login/NCLogin.swift
  58. 5 4
      iOSClient/Login/NCLoginWeb.swift
  59. 43 57
      iOSClient/Main/Collection Common/NCCollectionViewCommon.swift
  60. 2 2
      iOSClient/Main/Collection Common/NCSelectableNavigationView.swift
  61. 6 3
      iOSClient/Main/Create cloud/NCCreateFormUploadAssets.swift
  62. 4 3
      iOSClient/Main/Create cloud/NCCreateFormUploadConflict.swift
  63. 34 35
      iOSClient/Main/Create cloud/NCCreateFormUploadDocuments.swift
  64. 10 5
      iOSClient/Main/Create cloud/NCCreateFormUploadScanDocument.swift
  65. 1 1
      iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.swift
  66. 62 56
      iOSClient/Main/NCFunctionCenter.swift
  67. 3 1
      iOSClient/Main/NCMainTabBar.swift
  68. 9 4
      iOSClient/Main/NCPickerViewController.swift
  69. 22 17
      iOSClient/Media/NCMedia.swift
  70. 7 8
      iOSClient/Menu/AppDelegate+Menu.swift
  71. 14 14
      iOSClient/Menu/NCCollectionViewCommon+Menu.swift
  72. 1 1
      iOSClient/Menu/NCMedia+Menu.swift
  73. 1 1
      iOSClient/Menu/NCMenuAction.swift
  74. 53 0
      iOSClient/Menu/NCNotification+Menu.swift
  75. 1 1
      iOSClient/Menu/NCSortMenu.swift
  76. 1 1
      iOSClient/Menu/NCTrash+Menu.swift
  77. 11 11
      iOSClient/Menu/NCViewer+Menu.swift
  78. 12 8
      iOSClient/Menu/UIViewController+Menu.swift
  79. 19 19
      iOSClient/More/NCMore.swift
  80. 23 4
      iOSClient/NCGlobal.swift
  81. 109 21
      iOSClient/Networking/NCAutoUpload.swift
  82. 194 198
      iOSClient/Networking/NCNetworking.swift
  83. 32 48
      iOSClient/Networking/NCNetworkingCheckRemoteUser.swift
  84. 55 52
      iOSClient/Networking/NCNetworkingChunkedUpload.swift
  85. 83 90
      iOSClient/Networking/NCNetworkingE2EE.swift
  86. 24 65
      iOSClient/Networking/NCNetworkingProcessUpload.swift
  87. 37 29
      iOSClient/Networking/NCOperationQueue.swift
  88. 77 50
      iOSClient/Networking/NCService.swift
  89. 16 2
      iOSClient/Notification/NCNotification.storyboard
  90. 43 19
      iOSClient/Notification/NCNotification.swift
  91. 3 3
      iOSClient/Offline/NCOffline.swift
  92. 10 10
      iOSClient/PushNotification/NCPushNotification.m
  93. 6 4
      iOSClient/Recent/NCRecent.swift
  94. 4 4
      iOSClient/Rename file/NCRenameFile.swift
  95. 15 14
      iOSClient/RichWorkspace/NCRichWorkspaceCommon.swift
  96. 3 3
      iOSClient/RichWorkspace/NCViewerRichWorkspace.swift
  97. 2 2
      iOSClient/Security/NCEndToEndMetadata.swift
  98. 4 4
      iOSClient/Select/NCSelect.swift
  99. 6 6
      iOSClient/Settings/CCAdvanced.m
  100. 2 1
      iOSClient/Settings/CCManageAutoUpload.m

+ 4 - 1
.swiftlint.yml

@@ -41,6 +41,9 @@ excluded:
   - File Provider Extension/FileProviderExtension.swift
   - File Provider Extension/FileProviderUtility.swift
   - Notification Service Extension/NotificationService.swift
+  - Widget/Dashboard/DashboardData.swift
+  - Widget/Nextcloud/NextcloudData.swift
+  - Widget/Nextcloud/NextcloudWidgetView.swift
   - iOSClient/Activity/NCActivity.swift
   - iOSClient/Activity/NCActivityTableViewCell.swift
   - iOSClient/AppDelegate.swift
@@ -122,6 +125,7 @@ excluded:
   - iOSClient/Utility/NCStoreReview.swift
   - iOSClient/Utility/NCUtility.swift
   - iOSClient/Utility/NCUtilityFileSystem.swift
+  - iOSClient/Utility/NCUtilityGUI.swift
   - iOSClient/Viewer/NCViewer.swift
   - iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift
   - iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift
@@ -133,5 +137,4 @@ excluded:
   - iOSClient/Viewer/NCViewerProviderContextMenu.swift
   - iOSClient/Viewer/NCViewerRichdocument/NCViewerRichdocument.swift
 
-
 reporter: "xcode"

+ 6 - 8
File Provider Extension/FileProviderData.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 
 class fileProviderData: NSObject {
     static let shared: fileProviderData = {
@@ -77,11 +77,11 @@ class fileProviderData: NSObject {
 
         // LOG
         if let pathDirectoryGroup = CCUtility.getDirectoryGroup()?.path {
-            NCCommunicationCommon.shared.pathLog = pathDirectoryGroup
+            NKCommon.shared.pathLog = pathDirectoryGroup
             let levelLog = CCUtility.getLogLevel()
-            NCCommunicationCommon.shared.levelLog = levelLog
+            NKCommon.shared.levelLog = levelLog
             let version = NSString(format: NCBrandOptions.shared.textCopyrightNextcloudiOS as NSString, NCUtility.shared.getVersionApp()) as String
-            NCCommunicationCommon.shared.writeLog("Start File Provider session with level \(levelLog) " + version + " (File Provider Extension)")
+            NKCommon.shared.writeLog("Start File Provider session with level \(levelLog) " + version + " (File Provider Extension)")
         }
 
         // NO DOMAIN -> Set default account
@@ -89,7 +89,6 @@ class fileProviderData: NSObject {
 
             guard let activeAccount = NCManageDatabase.shared.getActiveAccount() else { return nil }
             let serverVersionMajor = NCManageDatabase.shared.getCapabilitiesServerInt(account: activeAccount.account, elements: NCElementsJSON.shared.capabilitiesVersionMajor)
-            let webDav = NCUtilityFileSystem.shared.getWebDAV(account: activeAccount.account)
 
             account = activeAccount.account
             user = activeAccount.user
@@ -97,7 +96,7 @@ class fileProviderData: NSObject {
             accountUrlBase = activeAccount.urlBase
             homeServerUrl = NCUtilityFileSystem.shared.getHomeServer(account: activeAccount.account)
 
-            NCCommunicationCommon.shared.setup(account: activeAccount.account, user: activeAccount.user, userId: activeAccount.userId, password: CCUtility.getPassword(activeAccount.account), urlBase: activeAccount.urlBase, userAgent: CCUtility.getUserAgent(), webDav: webDav, nextcloudVersion: serverVersionMajor, delegate: NCNetworking.shared)
+            NKCommon.shared.setup(account: activeAccount.account, user: activeAccount.user, userId: activeAccount.userId, password: CCUtility.getPassword(activeAccount.account), urlBase: activeAccount.urlBase, userAgent: CCUtility.getUserAgent(), nextcloudVersion: serverVersionMajor, delegate: NCNetworking.shared)
             NCNetworking.shared.delegate = providerExtension as? NCNetworkingDelegate
 
             return tableAccount.init(value: activeAccount)
@@ -114,7 +113,6 @@ class fileProviderData: NSObject {
             if accountDomain == domain!.identifier.rawValue {
 
                 let serverVersionMajor = NCManageDatabase.shared.getCapabilitiesServerInt(account: activeAccount.account, elements: NCElementsJSON.shared.capabilitiesVersionMajor)
-                let webDav = NCUtilityFileSystem.shared.getWebDAV(account: activeAccount.account)
 
                 account = activeAccount.account
                 user = activeAccount.user
@@ -122,7 +120,7 @@ class fileProviderData: NSObject {
                 accountUrlBase = activeAccount.urlBase
                 homeServerUrl = NCUtilityFileSystem.shared.getHomeServer(account: activeAccount.account)
 
-                NCCommunicationCommon.shared.setup(account: activeAccount.account, user: activeAccount.user, userId: activeAccount.userId, password: CCUtility.getPassword(activeAccount.account), urlBase: activeAccount.urlBase, userAgent: CCUtility.getUserAgent(), webDav: webDav, nextcloudVersion: serverVersionMajor, delegate: NCNetworking.shared)
+                NKCommon.shared.setup(account: activeAccount.account, user: activeAccount.user, userId: activeAccount.userId, password: CCUtility.getPassword(activeAccount.account), urlBase: activeAccount.urlBase, userAgent: CCUtility.getUserAgent(), nextcloudVersion: serverVersionMajor, delegate: NCNetworking.shared)
                 NCNetworking.shared.delegate = providerExtension as? NCNetworkingDelegate
 
                 return tableAccount.init(value: activeAccount)

+ 5 - 5
File Provider Extension/FileProviderEnumerator.swift

@@ -23,7 +23,7 @@
 
 import UIKit
 import FileProvider
-import NCCommunication
+import NextcloudKit
 
 class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
 
@@ -203,15 +203,15 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
             directoryEtag = tableDirectory.etag
         }
 
-        NCCommunication.shared.readFileOrFolder(serverUrlFileName: serverUrl, depth: "0", showHiddenFiles: CCUtility.getShowHiddenFiles()) { account, files, _, errorCode, _ in
+        NextcloudKit.shared.readFileOrFolder(serverUrlFileName: serverUrl, depth: "0", showHiddenFiles: CCUtility.getShowHiddenFiles()) { account, files, _, error in
 
             if directoryEtag != files.first?.etag {
 
-                NCCommunication.shared.readFileOrFolder(serverUrlFileName: serverUrl, depth: "1", showHiddenFiles: CCUtility.getShowHiddenFiles()) { account, files, _, errorCode, _ in
+                NextcloudKit.shared.readFileOrFolder(serverUrlFileName: serverUrl, depth: "1", showHiddenFiles: CCUtility.getShowHiddenFiles()) { account, files, _, error in
 
-                    if errorCode == 0 {
+                    if error == .success {
                         DispatchQueue.global().async {
-                            NCManageDatabase.shared.convertNCCommunicationFilesToMetadatas(files, useMetadataFolder: true, account: account) { _, metadatasFolder, metadatas in
+                            NCManageDatabase.shared.convertNKFilesToMetadatas(files, useMetadataFolder: true, account: account) { _, metadatasFolder, metadatas in
                                 let metadatasResult = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND status == %d", account, serverUrl, NCGlobal.shared.metadataStatusNormal))
                                 NCManageDatabase.shared.updateMetadatas(metadatas, metadatasResult: metadatasResult)
                                 for metadata in metadatasFolder {

+ 13 - 13
File Provider Extension/FileProviderExtension+Actions.swift

@@ -23,7 +23,7 @@
 
 import UIKit
 import FileProvider
-import NCCommunication
+import NextcloudKit
 
 extension FileProviderExtension {
 
@@ -37,13 +37,13 @@ extension FileProviderExtension {
         let directoryName = NCUtilityFileSystem.shared.createFileName(directoryName, serverUrl: tableDirectory.serverUrl, account: fileProviderData.shared.account)
         let serverUrlFileName = tableDirectory.serverUrl + "/" + directoryName
 
-        NCCommunication.shared.createFolder(serverUrlFileName) { account, ocId, _, errorCode, _ in
+        NextcloudKit.shared.createFolder(serverUrlFileName) { account, ocId, _, error in
 
-            if errorCode == 0 {
+            if error == .success {
 
-                NCCommunication.shared.readFileOrFolder(serverUrlFileName: serverUrlFileName, depth: "0", showHiddenFiles: CCUtility.getShowHiddenFiles()) { account, files, _, errorCode, _ in
+                NextcloudKit.shared.readFileOrFolder(serverUrlFileName: serverUrlFileName, depth: "0", showHiddenFiles: CCUtility.getShowHiddenFiles()) { account, files, _, error in
 
-                    if errorCode == 0 && files.count > 0 {
+                    if error == .success && files.count > 0 {
 
                         let file = files.first!
                         let metadata = NCManageDatabase.shared.convertNCFileToMetadata(file, isEncrypted: false, account: fileProviderData.shared.account)
@@ -88,9 +88,9 @@ extension FileProviderExtension {
         let serverUrl = metadata.serverUrl
         let fileName = metadata.fileName
 
-        NCCommunication.shared.deleteFileOrFolder(serverUrlFileName) { account, errorCode, _ in
+        NextcloudKit.shared.deleteFileOrFolder(serverUrlFileName) { account, error in
 
-            if errorCode == 0 { // || error == kOCErrorServerPathNotFound {
+            if error == .success { // || error == kOCErrorServerPathNotFound {
 
                 let fileNamePath = CCUtility.getDirectoryProviderStorageOcId(itemIdentifier.rawValue)!
                 do {
@@ -138,9 +138,9 @@ extension FileProviderExtension {
         let serverUrlTo = tableDirectoryTo.serverUrl
         let fileNameTo = serverUrlTo + "/" + itemFrom.filename
 
-        NCCommunication.shared.moveFileOrFolder(serverUrlFileNameSource: fileNameFrom, serverUrlFileNameDestination: fileNameTo, overwrite: false) { account, errorCode, _ in
+        NextcloudKit.shared.moveFileOrFolder(serverUrlFileNameSource: fileNameFrom, serverUrlFileNameDestination: fileNameTo, overwrite: false) { account, error in
 
-            if errorCode == 0 {
+            if error == .success {
 
                 if metadataFrom.directory {
                     NCManageDatabase.shared.deleteDirectoryAndSubDirectory(serverUrl: serverUrlFrom, account: account)
@@ -180,9 +180,9 @@ extension FileProviderExtension {
         let fileNamePathTo = metadata.serverUrl + "/" + itemName
         let ocId = metadata.ocId
 
-        NCCommunication.shared.moveFileOrFolder(serverUrlFileNameSource: fileNamePathFrom, serverUrlFileNameDestination: fileNamePathTo, overwrite: false) { account, errorCode, _ in
+        NextcloudKit.shared.moveFileOrFolder(serverUrlFileNameSource: fileNamePathFrom, serverUrlFileNameDestination: fileNamePathTo, overwrite: false) { account, error in
 
-            if errorCode == 0 {
+            if error == .success {
 
                 // Rename metadata
                 NCManageDatabase.shared.renameMetadata(fileNameTo: itemName, ocId: ocId)
@@ -247,9 +247,9 @@ extension FileProviderExtension {
         if (favorite == true && metadata.favorite == false) || (favorite == false && metadata.favorite == true) {
             let fileNamePath = CCUtility.returnFileNamePath(fromFileName: metadata.fileName, serverUrl: metadata.serverUrl, urlBase: metadata.urlBase, account: metadata.account)!
 
-            NCCommunication.shared.setFavorite(fileName: fileNamePath, favorite: favorite) { _, errorCode, _ in
+            NextcloudKit.shared.setFavorite(fileName: fileNamePath, favorite: favorite) { _, error in
 
-                if errorCode == 0 {
+                if error == .success {
 
                     guard let metadataTemp = NCManageDatabase.shared.getMetadataFromOcId(ocId) else {
                         completionHandler(nil, NSFileProviderError(.noSuchItem))

+ 19 - 13
File Provider Extension/FileProviderExtension+Thumbnail.swift

@@ -23,7 +23,7 @@
 
 import UIKit
 import FileProvider
-import NCCommunication
+import NextcloudKit
 
 extension FileProviderExtension {
 
@@ -45,20 +45,26 @@ extension FileProviderExtension {
                 let fileNamePath = CCUtility.returnFileNamePath(fromFileName: metadata.fileName, serverUrl: metadata.serverUrl, urlBase: metadata.urlBase, account: metadata.account)!
                 let fileNameIconLocalPath = CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)!
 
-                NCCommunication.shared.getPreview(fileNamePath: fileNamePath, widthPreview: NCGlobal.shared.sizeIcon, heightPreview: NCGlobal.shared.sizeIcon) { _, data, errorCode, _ in
-                    if errorCode == 0 && data != nil {
-                        do {
-                            try data!.write(to: URL(fileURLWithPath: fileNameIconLocalPath), options: .atomic)
-                        } catch { }
-                        perThumbnailCompletionHandler(itemIdentifier, data, nil)
-                    } else {
-                        perThumbnailCompletionHandler(itemIdentifier, nil, NSFileProviderError(.serverUnreachable))
-                    }
-                    counterProgress += 1
-                    if counterProgress == progress.totalUnitCount {
-                        completionHandler(nil)
+                if let urlBase = metadata.urlBase.urlEncoded,
+                   let fileNamePath = fileNamePath.urlEncoded,
+                   let url = URL(string: "\(urlBase)/index.php/core/preview.png?file=\(fileNamePath)&x=\(size)&y=\(size)&a=1&mode=cover") {
+
+                    NextcloudKit.shared.getPreview(url: url) { _, data, error in
+                        if error == .success && data != nil {
+                            do {
+                                try data!.write(to: URL(fileURLWithPath: fileNameIconLocalPath), options: .atomic)
+                            } catch { }
+                            perThumbnailCompletionHandler(itemIdentifier, data, nil)
+                        } else {
+                            perThumbnailCompletionHandler(itemIdentifier, nil, NSFileProviderError(.serverUnreachable))
+                        }
+                        counterProgress += 1
+                        if counterProgress == progress.totalUnitCount {
+                            completionHandler(nil)
+                        }
                     }
                 }
+
             } else {
                 counterProgress += 1
                 if counterProgress == progress.totalUnitCount {

+ 11 - 11
File Provider Extension/FileProviderExtension.swift

@@ -23,7 +23,7 @@
 
 import UIKit
 import FileProvider
-import NCCommunication
+import NextcloudKit
 import Alamofire
 
 /* -----------------------------------------------------------------------------------------------------------------------------------------------
@@ -119,7 +119,7 @@ class FileProviderExtension: NSFileProviderExtension, NCNetworkingDelegate {
             metadata.fileName = "root"
             metadata.fileNameView = "root"
             metadata.serverUrl = fileProviderData.shared.homeServerUrl
-            metadata.classFile = NCCommunicationCommon.typeClassFile.directory.rawValue
+            metadata.classFile = NKCommon.typeClassFile.directory.rawValue
 
             return FileProviderItem(metadata: metadata, parentItemIdentifier: NSFileProviderItemIdentifier(NSFileProviderItemIdentifier.rootContainer.rawValue))
 
@@ -209,7 +209,7 @@ class FileProviderExtension: NSFileProviderExtension, NCNetworkingDelegate {
         NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusDownloading)
         fileProviderData.shared.signalEnumerator(ocId: metadata.ocId, update: true)
 
-        NCCommunication.shared.download(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, requestHandler: { _ in
+        NextcloudKit.shared.download(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, requestHandler: { _ in
 
         }, taskHandler: { task in
 
@@ -218,7 +218,7 @@ class FileProviderExtension: NSFileProviderExtension, NCNetworkingDelegate {
 
         }, progressHandler: { _ in
 
-        }) { _, etag, date, _, _, _, errorCode, errorDescription in
+        }) { _, etag, date, _, _, _, error in
 
             self.outstandingSessionTasks.removeValue(forKey: url)
             guard var metadata = fileProviderUtility.shared.getTableMetadataFromItemIdentifier(identifier) else {
@@ -227,7 +227,7 @@ class FileProviderExtension: NSFileProviderExtension, NCNetworkingDelegate {
             }
             metadata = tableMetadata.init(value: metadata)
 
-            if errorCode == 0 {
+            if error == .success {
 
                 metadata.status = NCGlobal.shared.metadataStatusNormal
                 metadata.date = date ?? NSDate()
@@ -238,7 +238,7 @@ class FileProviderExtension: NSFileProviderExtension, NCNetworkingDelegate {
 
                 completionHandler(nil)
 
-            } else if errorCode == 200 {
+            } else if error.errorCode == 200 {
 
                 NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusNormal)
 
@@ -247,7 +247,7 @@ class FileProviderExtension: NSFileProviderExtension, NCNetworkingDelegate {
             } else {
 
                 metadata.status = NCGlobal.shared.metadataStatusDownloadError
-                metadata.sessionError = errorDescription
+                metadata.sessionError = error.errorDescription
                 NCManageDatabase.shared.addMetadata(metadata)
 
                 completionHandler(NSFileProviderError(.noSuchItem))
@@ -277,7 +277,7 @@ class FileProviderExtension: NSFileProviderExtension, NCNetworkingDelegate {
         let serverUrlFileName = metadata.serverUrl + "/" + fileName
         let fileNameLocalPath = url.path
 
-        if let task = NCCommunicationBackground.shared.upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, dateCreationFile: nil, dateModificationFile: nil, description: metadata.ocId, session: NCNetworking.shared.sessionManagerBackgroundExtension) {
+        if let task = NKBackground.shared.upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, dateCreationFile: nil, dateModificationFile: nil, description: metadata.ocId, session: NCNetworking.shared.sessionManagerBackgroundExtension) {
 
             fileProviderData.shared.fileProviderManager.register(task, forItemWithIdentifier: NSFileProviderItemIdentifier(metadata.fileId)) { _ in }
         }
@@ -357,7 +357,7 @@ class FileProviderExtension: NSFileProviderExtension, NCNetworkingDelegate {
                 let serverUrlFileName = tableDirectory.serverUrl + "/" + fileName
                 let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(ocIdTemp, fileNameView: fileName)!
 
-                if let task = NCCommunicationBackground.shared.upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, dateCreationFile: nil, dateModificationFile: nil, description: ocIdTemp, session: NCNetworking.shared.sessionManagerBackgroundExtension) {
+                if let task = NKBackground.shared.upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, dateCreationFile: nil, dateModificationFile: nil, description: ocIdTemp, session: NCNetworking.shared.sessionManagerBackgroundExtension) {
 
                     self.outstandingSessionTasks[URL(fileURLWithPath: fileNameLocalPath)] = task as URLSessionTask
 
@@ -371,7 +371,7 @@ class FileProviderExtension: NSFileProviderExtension, NCNetworkingDelegate {
         }
     }
 
-    func uploadComplete(fileName: String, serverUrl: String, ocId: String?, etag: String?, date: NSDate?, size: Int64, description: String?, task: URLSessionTask, errorCode: Int, errorDescription: String) {
+    func uploadComplete(fileName: String, serverUrl: String, ocId: String?, etag: String?, date: NSDate?, size: Int64, description: String?, task: URLSessionTask, error: NKError) {
 
         guard let ocIdTemp = description else { return }
         guard let metadataTemp = NCManageDatabase.shared.getMetadataFromOcId(ocIdTemp) else { return }
@@ -383,7 +383,7 @@ class FileProviderExtension: NSFileProviderExtension, NCNetworkingDelegate {
         }
         outstandingOcIdTemp[ocIdTemp] = ocId
 
-        if errorCode == 0 {
+        if error == .success {
 
             // New file
             if ocId != ocIdTemp {

+ 2 - 2
File Provider Extension/FileProviderItem.swift

@@ -23,7 +23,7 @@
 
 import UIKit
 import FileProvider
-import NCCommunication
+import NextcloudKit
 
 class FileProviderItem: NSObject, NSFileProviderItem {
 
@@ -43,7 +43,7 @@ class FileProviderItem: NSObject, NSFileProviderItem {
     }
 
     var typeIdentifier: String {
-        let results = NCCommunicationCommon.shared.getInternalType(fileName: metadata.fileNameView, mimeType: "", directory: metadata.directory)
+        let results = NKCommon.shared.getInternalType(fileName: metadata.fileNameView, mimeType: "", directory: metadata.directory)
         return results.typeIdentifier
     }
 

+ 398 - 34
Nextcloud.xcodeproj/project.pbxproj

@@ -144,6 +144,7 @@
 		F718C24E254D507B00C5C256 /* NCViewerMediaDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F718C24D254D507B00C5C256 /* NCViewerMediaDetailView.swift */; };
 		F719D9E0288D37A300762E33 /* NCColorPicker.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F719D9DF288D37A300762E33 /* NCColorPicker.storyboard */; };
 		F719D9E2288D396100762E33 /* NCColorPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = F719D9E1288D396100762E33 /* NCColorPicker.swift */; };
+		F71EB73728CA81D1007FAB9D /* Widget.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = F71EB73628CA81D1007FAB9D /* Widget.intentdefinition */; };
 		F7226EDC1EE4089300EBECB1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7226EDB1EE4089300EBECB1 /* Main.storyboard */; };
 		F723985C253C95CE00257F49 /* NCViewerRichdocument.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F723985B253C95CE00257F49 /* NCViewerRichdocument.storyboard */; };
 		F7239871253D86B600257F49 /* NCEmptyDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7239870253D86B600257F49 /* NCEmptyDataSet.swift */; };
@@ -156,15 +157,32 @@
 		F72685E727C78E490019EF5E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F72685E927C78E490019EF5E /* InfoPlist.strings */; };
 		F726EEEC1FED1C820030B9C8 /* NCEndToEndInitialize.swift in Sources */ = {isa = PBXBuildFile; fileRef = F726EEEB1FED1C820030B9C8 /* NCEndToEndInitialize.swift */; };
 		F72928A0253B0937009CA4FD /* NCMainNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F729289F253B0937009CA4FD /* NCMainNavigationController.swift */; };
+		F72A17D828B221E300F3F159 /* DashboardWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72A17D728B221E300F3F159 /* DashboardWidgetView.swift */; };
 		F72A47EC2487B06B005AD489 /* NCOperationQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72A47EB2487B06B005AD489 /* NCOperationQueue.swift */; };
+		F72AD70D28C24B93006CB92D /* NextcloudKit in Frameworks */ = {isa = PBXBuildFile; productRef = F72AD70C28C24B93006CB92D /* NextcloudKit */; };
+		F72AD70F28C24BA1006CB92D /* NextcloudKit in Frameworks */ = {isa = PBXBuildFile; productRef = F72AD70E28C24BA1006CB92D /* NextcloudKit */; };
+		F72AD71128C24BBB006CB92D /* NextcloudKit in Frameworks */ = {isa = PBXBuildFile; productRef = F72AD71028C24BBB006CB92D /* NextcloudKit */; };
+		F72AD71328C24BCC006CB92D /* NextcloudKit in Frameworks */ = {isa = PBXBuildFile; productRef = F72AD71228C24BCC006CB92D /* NextcloudKit */; };
 		F72CD01227A7E92400E59476 /* JGProgressHUD in Frameworks */ = {isa = PBXBuildFile; productRef = F72CD01127A7E92400E59476 /* JGProgressHUD */; };
 		F72CD63A25C19EBF00F46F9A /* NCAutoUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72CD63925C19EBF00F46F9A /* NCAutoUpload.swift */; };
 		F72D1007210B6882009C96B7 /* NCPushNotificationEncryption.m in Sources */ = {isa = PBXBuildFile; fileRef = F72D1005210B6882009C96B7 /* NCPushNotificationEncryption.m */; };
 		F72D404923D2082500A97FD0 /* NCViewerNextcloudText.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72D404823D2082500A97FD0 /* NCViewerNextcloudText.swift */; };
 		F72D7EB7263B1207000B3DFC /* MarkdownKit in Frameworks */ = {isa = PBXBuildFile; productRef = F72D7EB6263B1207000B3DFC /* MarkdownKit */; };
 		F72DA9B425F53E4E00B87DB1 /* SwiftRichString in Frameworks */ = {isa = PBXBuildFile; productRef = F72DA9B325F53E4E00B87DB1 /* SwiftRichString */; };
+		F72EA95228B7BA2A00C88F0C /* DashboardWidgetProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72EA95128B7BA2A00C88F0C /* DashboardWidgetProvider.swift */; };
+		F72EA95428B7BABA00C88F0C /* NextcloudWidgetProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72EA95328B7BABA00C88F0C /* NextcloudWidgetProvider.swift */; };
+		F72EA95828B7BC4F00C88F0C /* NextcloudData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72EA95728B7BC4F00C88F0C /* NextcloudData.swift */; };
+		F72EA95A28B7BD0D00C88F0C /* NextcloudWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72EA95928B7BD0D00C88F0C /* NextcloudWidgetView.swift */; };
 		F732D23327CF8AED000B0F1B /* NCPlayerToolBar.xib in Resources */ = {isa = PBXBuildFile; fileRef = F732D23227CF8AED000B0F1B /* NCPlayerToolBar.xib */; };
 		F733598125C1C188002ABA72 /* NCAskAuthorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = F733598025C1C188002ABA72 /* NCAskAuthorization.swift */; };
+		F7346E1228B0EF5B006CE2D2 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7346E1128B0EF5B006CE2D2 /* WidgetKit.framework */; };
+		F7346E1328B0EF5B006CE2D2 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F79BCEEA270B49C800B5B71F /* SwiftUI.framework */; };
+		F7346E1628B0EF5C006CE2D2 /* Widget.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7346E1528B0EF5C006CE2D2 /* Widget.swift */; };
+		F7346E1C28B0EF5E006CE2D2 /* Widget.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = F7346E1028B0EF5B006CE2D2 /* Widget.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
+		F7346E2328B0FEBA006CE2D2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F7346E2228B0FEBA006CE2D2 /* Assets.xcassets */; };
+		F7346E2528B0FEFA006CE2D2 /* UICKeyChainStore in Frameworks */ = {isa = PBXBuildFile; productRef = F7346E2428B0FEFA006CE2D2 /* UICKeyChainStore */; };
+		F7346E2728B0FFF2006CE2D2 /* Realm in Frameworks */ = {isa = PBXBuildFile; productRef = F7346E2628B0FFF2006CE2D2 /* Realm */; };
+		F7346E2928B0FFF2006CE2D2 /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = F7346E2828B0FFF2006CE2D2 /* RealmSwift */; };
 		F7362A1F220C853A005101B5 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7362A1E220C853A005101B5 /* LaunchScreen.storyboard */; };
 		F7381EE1218218C9000B1560 /* NCOffline.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7381EDA218218C9000B1560 /* NCOffline.swift */; };
 		F7381EE5218218C9000B1560 /* NCOffline.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7381EDE218218C9000B1560 /* NCOffline.storyboard */; };
@@ -293,19 +311,39 @@
 		F77BB746289984CA0090FC19 /* UIViewController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77BB745289984CA0090FC19 /* UIViewController+Extension.swift */; };
 		F77BB748289985270090FC19 /* UITabBarController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77BB747289985270090FC19 /* UITabBarController+Extension.swift */; };
 		F77BB74A2899857B0090FC19 /* UINavigationController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77BB7492899857B0090FC19 /* UINavigationController+Extension.swift */; };
+		F77ED59128C9CE9D00E24ED0 /* ToolbarData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77ED59028C9CE9D00E24ED0 /* ToolbarData.swift */; };
+		F77ED59328C9CEA000E24ED0 /* ToolbarWidgetProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77ED59228C9CEA000E24ED0 /* ToolbarWidgetProvider.swift */; };
+		F77ED59528C9CEA400E24ED0 /* ToolbarWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77ED59428C9CEA300E24ED0 /* ToolbarWidgetView.swift */; };
 		F78071091EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m in Sources */ = {isa = PBXBuildFile; fileRef = F78071081EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m */; };
 		F780710A1EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m in Sources */ = {isa = PBXBuildFile; fileRef = F78071081EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m */; };
 		F78295311F962EFA00A572F5 /* NCEndToEndEncryption.m in Sources */ = {isa = PBXBuildFile; fileRef = F70CAE391F8CF31A008125FD /* NCEndToEndEncryption.m */; };
 		F782FDC424E6933900666099 /* NCUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70BFC7320E0FA7C00C67599 /* NCUtility.swift */; };
+		F78302F628B4C3C500B84583 /* NCDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB41ED5A87C00B7EAD4 /* NCDatabase.swift */; };
+		F78302F728B4C3C900B84583 /* NCManageDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB51ED5A87C00B7EAD4 /* NCManageDatabase.swift */; };
+		F78302F828B4C3E100B84583 /* NCManageDatabase+Activity.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF61D27562B3F0081CEEF /* NCManageDatabase+Activity.swift */; };
+		F78302F928B4C3E600B84583 /* NCManageDatabase+Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF613275629E20081CEEF /* NCManageDatabase+Account.swift */; };
+		F78302FA28B4C3EA00B84583 /* NCManageDatabase+Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF61827562A4B0081CEEF /* NCManageDatabase+Metadata.swift */; };
+		F78302FB28B4C3EE00B84583 /* NCManageDatabase+Video.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E98C1527E0D0FC001F9F19 /* NCManageDatabase+Video.swift */; };
+		F78302FC28B4C3F300B84583 /* NCElementsJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73D5E46246DE09200DF6467 /* NCElementsJSON.swift */; };
+		F78302FD28B4C42B00B84583 /* NCUserBaseUrl.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF817EF0274BC781009ED85B /* NCUserBaseUrl.swift */; };
+		F78302FE28B4C44700B84583 /* NCBrand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76B3CCD1EAE01BD00921AC9 /* NCBrand.swift */; };
+		F78302FF28B4C45000B84583 /* NCUtilityFileSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74AF3A3247FB6AE00AC767B /* NCUtilityFileSystem.swift */; };
+		F783030028B4C45800B84583 /* NCGlobal.swift in Sources */ = {isa = PBXBuildFile; fileRef = F702F2CE25EE5B5C008F8E80 /* NCGlobal.swift */; };
+		F783030128B4C49700B84583 /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extensions.swift */; };
+		F783030228B4C4B800B84583 /* NCUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70BFC7320E0FA7C00C67599 /* NCUtility.swift */; };
+		F783030328B4C4DD00B84583 /* ThreadSafeDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7245923289BB50B00474787 /* ThreadSafeDictionary.swift */; };
+		F783030528B4C50600B84583 /* SVGKit in Frameworks */ = {isa = PBXBuildFile; productRef = F783030428B4C50600B84583 /* SVGKit */; };
+		F783030628B4C51E00B84583 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extensions.swift */; };
+		F783030728B4C52800B84583 /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */; };
+		F783030B28B4C58600B84583 /* Queuer in Frameworks */ = {isa = PBXBuildFile; productRef = F783030A28B4C58600B84583 /* Queuer */; };
+		F783030D28B4C59A00B84583 /* SwiftEntryKit in Frameworks */ = {isa = PBXBuildFile; productRef = F783030C28B4C59A00B84583 /* SwiftEntryKit */; };
+		F783031228B4C8EC00B84583 /* CCUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = F7053E3D1C639DF500741EA5 /* CCUtility.m */; };
+		F783034428B5142B00B84583 /* NextcloudKit in Frameworks */ = {isa = PBXBuildFile; productRef = F783034328B5142B00B84583 /* NextcloudKit */; };
 		F785EE9D246196DF00B3F945 /* NCNetworkingE2EE.swift in Sources */ = {isa = PBXBuildFile; fileRef = F785EE9C246196DF00B3F945 /* NCNetworkingE2EE.swift */; };
 		F785EE9E2461A09900B3F945 /* NCNetworking.swift in Sources */ = {isa = PBXBuildFile; fileRef = F75A9EE523796C6F0044CFCE /* NCNetworking.swift */; };
 		F785EEA42461A4A600B3F945 /* NCUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70BFC7320E0FA7C00C67599 /* NCUtility.swift */; };
 		F785EEA52461A4CF00B3F945 /* CCUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = F7053E3D1C639DF500741EA5 /* CCUtility.m */; };
 		F785EEA62461A4FB00B3F945 /* CCUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = F7053E3D1C639DF500741EA5 /* CCUtility.m */; };
-		F786D58D253454BF00E3DD7B /* NCCommunication in Frameworks */ = {isa = PBXBuildFile; productRef = F786D58C253454BF00E3DD7B /* NCCommunication */; };
-		F786D593253454CE00E3DD7B /* NCCommunication in Frameworks */ = {isa = PBXBuildFile; productRef = F786D592253454CE00E3DD7B /* NCCommunication */; };
-		F786D595253454D300E3DD7B /* NCCommunication in Frameworks */ = {isa = PBXBuildFile; productRef = F786D594253454D300E3DD7B /* NCCommunication */; };
-		F786D597253454D800E3DD7B /* NCCommunication in Frameworks */ = {isa = PBXBuildFile; productRef = F786D596253454D800E3DD7B /* NCCommunication */; };
 		F787704F22E7019900F287A9 /* NCShareLinkCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F787704E22E7019900F287A9 /* NCShareLinkCell.xib */; };
 		F788ECC7263AAAFA00ADC67F /* MarkdownKit in Frameworks */ = {isa = PBXBuildFile; productRef = F788ECC6263AAAFA00ADC67F /* MarkdownKit */; };
 		F78A18B623CDD07D00F681F3 /* NCViewerRichWorkspaceWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78A18B523CDD07D00F681F3 /* NCViewerRichWorkspaceWebView.swift */; };
@@ -322,6 +360,14 @@
 		F78F74342163757000C2ADAD /* NCTrash.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F78F74332163757000C2ADAD /* NCTrash.storyboard */; };
 		F78F74362163781100C2ADAD /* NCTrash.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78F74352163781100C2ADAD /* NCTrash.swift */; };
 		F790110E21415BF600D7B136 /* NCViewerRichdocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = F790110D21415BF600D7B136 /* NCViewerRichdocument.swift */; };
+		F793E59B28B75FB0005E4B02 /* NCAutoUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72CD63925C19EBF00F46F9A /* NCAutoUpload.swift */; };
+		F793E59D28B761E7005E4B02 /* NCNetworking.swift in Sources */ = {isa = PBXBuildFile; fileRef = F75A9EE523796C6F0044CFCE /* NCNetworking.swift */; };
+		F793E59E28B763C2005E4B02 /* NCAskAuthorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = F733598025C1C188002ABA72 /* NCAskAuthorization.swift */; };
+		F793E59F28B764F6005E4B02 /* NCContentPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F765608E23BF813500765969 /* NCContentPresenter.swift */; };
+		F793E5A028B7651B005E4B02 /* NCViewCertificateDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BC287F26663F85004D46C5 /* NCViewCertificateDetails.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 */; };
+		F793E5A528B7698D005E4B02 /* NCNetworkingProcessUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70D8D8024A4A9BF000A5756 /* NCNetworkingProcessUpload.swift */; };
 		F798F0E225880608000DAFFD /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */; };
 		F798F0E725880609000DAFFD /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */; };
 		F798F0EC2588060A000DAFFD /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */; };
@@ -362,6 +408,8 @@
 		F7BC288026663F85004D46C5 /* NCViewCertificateDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BC287F26663F85004D46C5 /* NCViewCertificateDetails.swift */; };
 		F7BD71E62636EAFC00643C34 /* NCNetworkingE2EE.swift in Sources */ = {isa = PBXBuildFile; fileRef = F785EE9C246196DF00B3F945 /* NCNetworkingE2EE.swift */; };
 		F7C1EEA525053A9C00866ACC /* NCDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C1EEA425053A9C00866ACC /* NCDataSource.swift */; };
+		F7C7B25028B8AD4500E7115D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = F7E70DE91A24DE4100E1B66A /* Localizable.strings */; };
+		F7C7B25128B8B0C400E7115D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F7F67BB81A24D27800EE80DA /* Images.xcassets */; };
 		F7C7B489245EBA4100D93E60 /* NCViewerQuickLook.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C7B488245EBA4100D93E60 /* NCViewerQuickLook.swift */; };
 		F7C9555321F0C4CA0024296E /* NCActivity.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7C9555221F0C4CA0024296E /* NCActivity.storyboard */; };
 		F7C9555521F0C5470024296E /* NCActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C9555421F0C5470024296E /* NCActivity.swift */; };
@@ -378,6 +426,11 @@
 		F7DBC37C23325E02001A85BA /* NCAppConfigView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DBC37B23325E01001A85BA /* NCAppConfigView.swift */; };
 		F7DFB7F0219C5B8000680748 /* NCCreateFormUploadAssets.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DFB7EF219C5B8000680748 /* NCCreateFormUploadAssets.swift */; };
 		F7DFB7F4219C5CA800680748 /* NCCreateFormUploadScanDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DFB7F3219C5CA800680748 /* NCCreateFormUploadScanDocument.swift */; };
+		F7E03DBC28BB48E4009AFDA1 /* NCUtilityGUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E03DBB28BB48E4009AFDA1 /* NCUtilityGUI.swift */; };
+		F7E03DBD28BB48E4009AFDA1 /* NCUtilityGUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E03DBB28BB48E4009AFDA1 /* NCUtilityGUI.swift */; };
+		F7E03DBE28BB48E4009AFDA1 /* NCUtilityGUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E03DBB28BB48E4009AFDA1 /* NCUtilityGUI.swift */; };
+		F7E03DBF28BB48E4009AFDA1 /* NCUtilityGUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E03DBB28BB48E4009AFDA1 /* NCUtilityGUI.swift */; };
+		F7E0710128B13BB00001B882 /* DashboardData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E0710028B13BB00001B882 /* DashboardData.swift */; };
 		F7E0CDCF265CE8610044854E /* NCUserStatus.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7E0CDCE265CE8610044854E /* NCUserStatus.storyboard */; };
 		F7E4D9C422ED929B003675FD /* NCShareCommentsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E4D9C322ED929B003675FD /* NCShareCommentsCell.swift */; };
 		F7E572FD278F146C00F8C99E /* OpenSSL.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = F70B86802642CF5400ED5349 /* OpenSSL.xcframework */; };
@@ -422,6 +475,7 @@
 		F7F878AE1FB9E3B900599E4F /* NCEndToEndMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F878AD1FB9E3B900599E4F /* NCEndToEndMetadata.swift */; };
 		F7F878AF1FB9E3B900599E4F /* NCEndToEndMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F878AD1FB9E3B900599E4F /* NCEndToEndMetadata.swift */; };
 		F7F9D1BB25397CE000D9BFF5 /* NCViewer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F9D1BA25397CE000D9BFF5 /* NCViewer.swift */; };
+		F7FAFD3A28BFA948000777FE /* NCNotification+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7FAFD3928BFA947000777FE /* NCNotification+Menu.swift */; };
 		F7FF2CB12842159500EBB7A1 /* NCSectionHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7FF2CB02842159500EBB7A1 /* NCSectionHeader.xib */; };
 /* End PBXBuildFile section */
 
@@ -447,6 +501,13 @@
 			remoteGlobalIDString = F71459B41D12E3B700CAFEEC;
 			remoteInfo = "Share Ext Nextcloud";
 		};
+		F7346E1A28B0EF5E006CE2D2 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = F7F67BA01A24D27800EE80DA /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = F7346E0F28B0EF5B006CE2D2;
+			remoteInfo = DashboardWidgetExtension;
+		};
 		F771E3E920E2392E00AFB62D /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = F7F67BA01A24D27800EE80DA /* Project object */;
@@ -480,6 +541,7 @@
 				F771E3EB20E2392E00AFB62D /* File Provider Extension.appex in Embed App Extensions */,
 				F749E4E91DC1FB38009BA2FD /* Share.appex in Embed App Extensions */,
 				2C33C48623E2C475005F963B /* Notification Service Extension.appex in Embed App Extensions */,
+				F7346E1C28B0EF5E006CE2D2 /* Widget.appex in Embed App Extensions */,
 			);
 			name = "Embed App Extensions";
 			runOnlyForDeploymentPostprocessing = 0;
@@ -646,6 +708,7 @@
 		F718C24D254D507B00C5C256 /* NCViewerMediaDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCViewerMediaDetailView.swift; sourceTree = "<group>"; };
 		F719D9DF288D37A300762E33 /* NCColorPicker.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCColorPicker.storyboard; sourceTree = "<group>"; };
 		F719D9E1288D396100762E33 /* NCColorPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCColorPicker.swift; sourceTree = "<group>"; };
+		F71EB73628CA81D1007FAB9D /* Widget.intentdefinition */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.intentdefinition; path = Widget.intentdefinition; sourceTree = "<group>"; };
 		F7226EDB1EE4089300EBECB1 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = "<group>"; };
 		F723985B253C95CE00257F49 /* NCViewerRichdocument.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCViewerRichdocument.storyboard; sourceTree = "<group>"; };
 		F7239870253D86B600257F49 /* NCEmptyDataSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCEmptyDataSet.swift; sourceTree = "<group>"; };
@@ -658,17 +721,28 @@
 		F728B2BB23E83AD200E12DA0 /* Notification_Service_Extension.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Notification_Service_Extension.plist; sourceTree = "<group>"; };
 		F728B2BC23E83AD200E12DA0 /* Notification_Service_Extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Notification_Service_Extension.entitlements; sourceTree = "<group>"; };
 		F729289F253B0937009CA4FD /* NCMainNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMainNavigationController.swift; sourceTree = "<group>"; };
+		F72A17D728B221E300F3F159 /* DashboardWidgetView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DashboardWidgetView.swift; sourceTree = "<group>"; };
 		F72A47EB2487B06B005AD489 /* NCOperationQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCOperationQueue.swift; sourceTree = "<group>"; };
 		F72CD63925C19EBF00F46F9A /* NCAutoUpload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCAutoUpload.swift; sourceTree = "<group>"; };
 		F72D1005210B6882009C96B7 /* NCPushNotificationEncryption.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NCPushNotificationEncryption.m; sourceTree = "<group>"; };
 		F72D1006210B6882009C96B7 /* NCPushNotificationEncryption.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NCPushNotificationEncryption.h; sourceTree = "<group>"; };
 		F72D404823D2082500A97FD0 /* NCViewerNextcloudText.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCViewerNextcloudText.swift; sourceTree = "<group>"; };
 		F72E0B9C21AD60BC00898D7B /* WeScan.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WeScan.framework; path = Carthage/Build/iOS/WeScan.framework; sourceTree = "<group>"; };
+		F72EA95128B7BA2A00C88F0C /* DashboardWidgetProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardWidgetProvider.swift; sourceTree = "<group>"; };
+		F72EA95328B7BABA00C88F0C /* NextcloudWidgetProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextcloudWidgetProvider.swift; sourceTree = "<group>"; };
+		F72EA95728B7BC4F00C88F0C /* NextcloudData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextcloudData.swift; sourceTree = "<group>"; };
+		F72EA95928B7BD0D00C88F0C /* NextcloudWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextcloudWidgetView.swift; sourceTree = "<group>"; };
 		F7320934201B812F008A0888 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Localizable.strings; sourceTree = "<group>"; };
 		F732093B201B81E4008A0888 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/Localizable.strings"; sourceTree = "<group>"; };
 		F732D23227CF8AED000B0F1B /* NCPlayerToolBar.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCPlayerToolBar.xib; sourceTree = "<group>"; };
 		F733598025C1C188002ABA72 /* NCAskAuthorization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCAskAuthorization.swift; sourceTree = "<group>"; };
 		F733B65121997CC1001C1FFA /* TLPhotoPicker.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TLPhotoPicker.framework; path = Carthage/Build/iOS/TLPhotoPicker.framework; sourceTree = "<group>"; };
+		F7346E1028B0EF5B006CE2D2 /* Widget.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Widget.appex; sourceTree = BUILT_PRODUCTS_DIR; };
+		F7346E1128B0EF5B006CE2D2 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
+		F7346E1528B0EF5C006CE2D2 /* Widget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Widget.swift; sourceTree = "<group>"; };
+		F7346E2028B0FA3A006CE2D2 /* Widget-Brinding-header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Widget-Brinding-header.h"; sourceTree = "<group>"; };
+		F7346E2128B0FBEE006CE2D2 /* Widget.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Widget.plist; sourceTree = "<group>"; };
+		F7346E2228B0FEBA006CE2D2 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
 		F7362A1E220C853A005101B5 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
 		F736B551234DCF57008A5C9F /* Alamofire.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Alamofire.framework; path = Carthage/Build/iOS/Alamofire.framework; sourceTree = "<group>"; };
 		F7381EDA218218C9000B1560 /* NCOffline.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCOffline.swift; sourceTree = "<group>"; };
@@ -786,8 +860,15 @@
 		F77BB745289984CA0090FC19 /* UIViewController+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extension.swift"; sourceTree = "<group>"; };
 		F77BB747289985270090FC19 /* UITabBarController+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UITabBarController+Extension.swift"; sourceTree = "<group>"; };
 		F77BB7492899857B0090FC19 /* UINavigationController+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extension.swift"; sourceTree = "<group>"; };
+		F77ED59028C9CE9D00E24ED0 /* ToolbarData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolbarData.swift; sourceTree = "<group>"; };
+		F77ED59228C9CEA000E24ED0 /* ToolbarWidgetProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolbarWidgetProvider.swift; sourceTree = "<group>"; };
+		F77ED59428C9CEA300E24ED0 /* ToolbarWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolbarWidgetView.swift; sourceTree = "<group>"; };
 		F78071071EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNotificationCenter+MainThread.h"; sourceTree = "<group>"; };
 		F78071081EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSNotificationCenter+MainThread.m"; sourceTree = "<group>"; };
+		F783030E28B4C83F00B84583 /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
+		F783031028B4C86200B84583 /* libc++.1.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.1.tbd"; path = "usr/lib/libc++.1.tbd"; sourceTree = SDKROOT; };
+		F783031128B4C86200B84583 /* libc++abi.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++abi.tbd"; path = "usr/lib/libc++abi.tbd"; sourceTree = SDKROOT; };
+		F783033F28B50B7E00B84583 /* Widget.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Widget.entitlements; sourceTree = "<group>"; };
 		F785EE9C246196DF00B3F945 /* NCNetworkingE2EE.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCNetworkingE2EE.swift; sourceTree = "<group>"; };
 		F787704E22E7019900F287A9 /* NCShareLinkCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCShareLinkCell.xib; sourceTree = "<group>"; };
 		F78A18B523CDD07D00F681F3 /* NCViewerRichWorkspaceWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCViewerRichWorkspaceWebView.swift; sourceTree = "<group>"; };
@@ -929,6 +1010,8 @@
 		F7DE9AB01F482FA5008DFE10 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = "<group>"; };
 		F7DFB7EF219C5B8000680748 /* NCCreateFormUploadAssets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCreateFormUploadAssets.swift; sourceTree = "<group>"; };
 		F7DFB7F3219C5CA800680748 /* NCCreateFormUploadScanDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCreateFormUploadScanDocument.swift; sourceTree = "<group>"; };
+		F7E03DBB28BB48E4009AFDA1 /* NCUtilityGUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCUtilityGUI.swift; sourceTree = "<group>"; };
+		F7E0710028B13BB00001B882 /* DashboardData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardData.swift; sourceTree = "<group>"; };
 		F7E0CDCE265CE8610044854E /* NCUserStatus.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCUserStatus.storyboard; sourceTree = "<group>"; };
 		F7E45E6D21E75BF200579249 /* ja-JP */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ja-JP"; path = "ja-JP.lproj/Localizable.strings"; sourceTree = "<group>"; };
 		F7E4D9C322ED929B003675FD /* NCShareCommentsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareCommentsCell.swift; sourceTree = "<group>"; };
@@ -957,6 +1040,7 @@
 		F7F67BB81A24D27800EE80DA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
 		F7F878AD1FB9E3B900599E4F /* NCEndToEndMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCEndToEndMetadata.swift; sourceTree = "<group>"; };
 		F7F9D1BA25397CE000D9BFF5 /* NCViewer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCViewer.swift; sourceTree = "<group>"; };
+		F7FAFD3928BFA947000777FE /* NCNotification+Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCNotification+Menu.swift"; sourceTree = "<group>"; };
 		F7FC7D551DC1F93800BB2C6A /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
 		F7FF2CB02842159500EBB7A1 /* NCSectionHeader.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCSectionHeader.xib; sourceTree = "<group>"; };
 /* End PBXFileReference section */
@@ -966,12 +1050,12 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				F72AD71128C24BBB006CB92D /* NextcloudKit in Frameworks */,
 				F710FC88277B7D3F00AA9FBF /* RealmSwift in Frameworks */,
 				F7EBCDD9277B834F00A4EF67 /* Queuer in Frameworks */,
 				F710FC86277B7D3F00AA9FBF /* Realm in Frameworks */,
 				F7EBCDD3277B821700A4EF67 /* UICKeyChainStore in Frameworks */,
 				F75E57C325BF0ED2002B72C2 /* SVGKit in Frameworks */,
-				F786D597253454D800E3DD7B /* NCCommunication in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -988,17 +1072,33 @@
 			files = (
 				F7E57302278F14FF00F8C99E /* OpenSSL.xcframework in Frameworks */,
 				F710FC80277B7D2700AA9FBF /* RealmSwift in Frameworks */,
+				F72AD70F28C24BA1006CB92D /* NextcloudKit in Frameworks */,
 				F72CD01227A7E92400E59476 /* JGProgressHUD in Frameworks */,
 				F710FC7E277B7D2600AA9FBF /* Realm in Frameworks */,
 				F73ADD2126554F8E0069EA0D /* SwiftEntryKit in Frameworks */,
 				F7EBCDCF277B81FF00A4EF67 /* UICKeyChainStore in Frameworks */,
 				F75E57BF25BF0EC8002B72C2 /* SVGKit in Frameworks */,
 				F7EBCDD5277B82DE00A4EF67 /* Queuer in Frameworks */,
-				F786D593253454CE00E3DD7B /* NCCommunication in Frameworks */,
 				F72D7EB7263B1207000B3DFC /* MarkdownKit in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		F7346E0D28B0EF5B006CE2D2 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				F783030528B4C50600B84583 /* SVGKit in Frameworks */,
+				F7346E2528B0FEFA006CE2D2 /* UICKeyChainStore in Frameworks */,
+				F783034428B5142B00B84583 /* NextcloudKit in Frameworks */,
+				F7346E1328B0EF5B006CE2D2 /* SwiftUI.framework in Frameworks */,
+				F7346E2728B0FFF2006CE2D2 /* Realm in Frameworks */,
+				F7346E2928B0FFF2006CE2D2 /* RealmSwift in Frameworks */,
+				F783030D28B4C59A00B84583 /* SwiftEntryKit in Frameworks */,
+				F783030B28B4C58600B84583 /* Queuer in Frameworks */,
+				F7346E1228B0EF5B006CE2D2 /* WidgetKit.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		F771E3CD20E2392D00AFB62D /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
@@ -1009,7 +1109,7 @@
 				F73ADD2426554FE20069EA0D /* SwiftEntryKit in Frameworks */,
 				F710FC82277B7D3500AA9FBF /* Realm in Frameworks */,
 				F710FC84277B7D3500AA9FBF /* RealmSwift in Frameworks */,
-				F786D595253454D300E3DD7B /* NCCommunication in Frameworks */,
+				F72AD71328C24BCC006CB92D /* NextcloudKit in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1024,13 +1124,13 @@
 				F770768E263A8C3400A1BA94 /* FloatingPanel in Frameworks */,
 				F710FC7C277B7D0000AA9FBF /* RealmSwift in Frameworks */,
 				F7E572FD278F146C00F8C99E /* OpenSSL.xcframework in Frameworks */,
-				F786D58D253454BF00E3DD7B /* NCCommunication in Frameworks */,
 				F758A01227A7F03E0069468B /* JGProgressHUD in Frameworks */,
 				F76DA96F277B78AE0082465B /* TLPhotoPicker in Frameworks */,
 				F76DA966277B76F30082465B /* UICKeyChainStore in Frameworks */,
 				F753BA93281FD8020015BFB6 /* EasyTipView in Frameworks */,
 				F76DA95B277B75A90082465B /* TOPasscodeViewController.xcframework in Frameworks */,
 				F76DA963277B760E0082465B /* Queuer in Frameworks */,
+				F72AD70D28C24B93006CB92D /* NextcloudKit in Frameworks */,
 				F75E57BD25BF0EC1002B72C2 /* SVGKit in Frameworks */,
 				F70B86752642CE3B00ED5349 /* FirebaseCrashlytics in Frameworks */,
 				F76DA969277B77EA0082465B /* DropDown in Frameworks */,
@@ -1061,6 +1161,7 @@
 				3704EB2923D5A58400455C5B /* NCMenu.storyboard */,
 				371B5A2D23D0B04500FAFAE9 /* NCMenu.swift */,
 				AF68326927BE65A90010BF0B /* NCMenuAction.swift */,
+				F7FAFD3928BFA947000777FE /* NCNotification+Menu.swift */,
 				AF935066276B84E700BD078F /* NCMenu+FloatingPanel.swift */,
 				3781B9AF23DB2B7E006B4B1D /* AppDelegate+Menu.swift */,
 				8491B1CC273BBA82001C8C5B /* UIViewController+Menu.swift */,
@@ -1260,6 +1361,40 @@
 			name = Localizations;
 			sourceTree = "<group>";
 		};
+		F72EA95528B7BAD100C88F0C /* Dashboard */ = {
+			isa = PBXGroup;
+			children = (
+				F7E0710028B13BB00001B882 /* DashboardData.swift */,
+				F72EA95128B7BA2A00C88F0C /* DashboardWidgetProvider.swift */,
+				F72A17D728B221E300F3F159 /* DashboardWidgetView.swift */,
+			);
+			path = Dashboard;
+			sourceTree = "<group>";
+		};
+		F72EA95628B7BAE700C88F0C /* Nextcloud */ = {
+			isa = PBXGroup;
+			children = (
+				F72EA95728B7BC4F00C88F0C /* NextcloudData.swift */,
+				F72EA95328B7BABA00C88F0C /* NextcloudWidgetProvider.swift */,
+				F72EA95928B7BD0D00C88F0C /* NextcloudWidgetView.swift */,
+			);
+			path = Nextcloud;
+			sourceTree = "<group>";
+		};
+		F7346E1428B0EF5B006CE2D2 /* Widget */ = {
+			isa = PBXGroup;
+			children = (
+				F7346E2228B0FEBA006CE2D2 /* Assets.xcassets */,
+				F72EA95528B7BAD100C88F0C /* Dashboard */,
+				F72EA95628B7BAE700C88F0C /* Nextcloud */,
+				F77ED59628C9CEEE00E24ED0 /* Toolbar */,
+				F7346E2028B0FA3A006CE2D2 /* Widget-Brinding-header.h */,
+				F71EB73628CA81D1007FAB9D /* Widget.intentdefinition */,
+				F7346E1528B0EF5C006CE2D2 /* Widget.swift */,
+			);
+			path = Widget;
+			sourceTree = "<group>";
+		};
 		F7381ED9218218A4000B1560 /* Offline */ = {
 			isa = PBXGroup;
 			children = (
@@ -1371,6 +1506,16 @@
 			path = Files;
 			sourceTree = "<group>";
 		};
+		F77ED59628C9CEEE00E24ED0 /* Toolbar */ = {
+			isa = PBXGroup;
+			children = (
+				F77ED59028C9CE9D00E24ED0 /* ToolbarData.swift */,
+				F77ED59228C9CEA000E24ED0 /* ToolbarWidgetProvider.swift */,
+				F77ED59428C9CEA300E24ED0 /* ToolbarWidgetView.swift */,
+			);
+			path = Toolbar;
+			sourceTree = "<group>";
+		};
 		F78ACD4721903F850088454D /* Cell */ = {
 			isa = PBXGroup;
 			children = (
@@ -1574,6 +1719,7 @@
 				F70968A324212C4E00ED60E5 /* NCLivePhoto.swift */,
 				F707C26421A2DC5200F6181E /* NCStoreReview.swift */,
 				F70BFC7320E0FA7C00C67599 /* NCUtility.swift */,
+				F7E03DBB28BB48E4009AFDA1 /* NCUtilityGUI.swift */,
 				F76D364528A4F8BF00214537 /* NCActivityIndicator.swift */,
 				AF93474B27E34120002537EE /* NCUtility+Image.swift */,
 				AF817EF0274BC781009ED85B /* NCUserBaseUrl.swift */,
@@ -1627,6 +1773,8 @@
 		F7C742D31E7BD36600D9C973 /* Supporting Files */ = {
 			isa = PBXGroup;
 			children = (
+				F7346E2128B0FBEE006CE2D2 /* Widget.plist */,
+				F783033F28B50B7E00B84583 /* Widget.entitlements */,
 				F771E3FB20E23A8700AFB62D /* File_Provider_Extension.entitlements */,
 				F771E3FC20E23A8800AFB62D /* File_Provider_Extension.plist */,
 				F7C742C01E7BD01F00D9C973 /* iOSClient.entitlements */,
@@ -1758,11 +1906,13 @@
 				F7C0F46D1C8880540059EC54 /* Share */,
 				2C33C48023E2C475005F963B /* Notification Service Extension */,
 				AF8ED1FA2757821000B8DBC4 /* NextcloudTests */,
+				F7346E1428B0EF5B006CE2D2 /* Widget */,
 				F7FC7D651DC1F98700BB2C6A /* Products */,
 				F7FC7D541DC1F93700BB2C6A /* Frameworks */,
 				F771E3D020E2392D00AFB62D /* File Provider Extension.appex */,
 				2C33C47F23E2C475005F963B /* Notification Service Extension.appex */,
 				AF8ED1F92757821000B8DBC4 /* NextcloudTests.xctest */,
+				F7346E1028B0EF5B006CE2D2 /* Widget.appex */,
 			);
 			sourceTree = "<group>";
 		};
@@ -1823,6 +1973,9 @@
 		F7FC7D541DC1F93700BB2C6A /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
+				F783031028B4C86200B84583 /* libc++.1.tbd */,
+				F783031128B4C86200B84583 /* libc++abi.tbd */,
+				F783030E28B4C83F00B84583 /* libc++.tbd */,
 				F702867E2773609C00ADA8BE /* libiconv.tbd */,
 				F702864E27735D1400ADA8BE /* ffmpegkit.xcframework */,
 				F702865127735D1500ADA8BE /* gmp.xcframework */,
@@ -1916,6 +2069,7 @@
 				08EA97471E6554FC004C83FA /* GoogleToolboxForMac.framework */,
 				08DC3BD41E64727E00F036D3 /* AdSupport.framework */,
 				F7FC7D551DC1F93800BB2C6A /* libz.tbd */,
+				F7346E1128B0EF5B006CE2D2 /* WidgetKit.framework */,
 			);
 			name = Frameworks;
 			sourceTree = "<group>";
@@ -1960,12 +2114,12 @@
 			);
 			name = "Notification Service Extension";
 			packageProductDependencies = (
-				F786D596253454D800E3DD7B /* NCCommunication */,
 				F75E57C225BF0ED2002B72C2 /* SVGKit */,
 				F710FC85277B7D3F00AA9FBF /* Realm */,
 				F710FC87277B7D3F00AA9FBF /* RealmSwift */,
 				F7EBCDD2277B821700A4EF67 /* UICKeyChainStore */,
 				F7EBCDD8277B834F00A4EF67 /* Queuer */,
+				F72AD71028C24BBB006CB92D /* NextcloudKit */,
 			);
 			productName = "Notification Service Extension";
 			productReference = 2C33C47F23E2C475005F963B /* Notification Service Extension.appex */;
@@ -2003,7 +2157,6 @@
 			);
 			name = Share;
 			packageProductDependencies = (
-				F786D592253454CE00E3DD7B /* NCCommunication */,
 				F75E57BE25BF0EC8002B72C2 /* SVGKit */,
 				F72D7EB6263B1207000B3DFC /* MarkdownKit */,
 				F73ADD2026554F8E0069EA0D /* SwiftEntryKit */,
@@ -2012,11 +2165,38 @@
 				F7EBCDCE277B81FF00A4EF67 /* UICKeyChainStore */,
 				F7EBCDD4277B82DE00A4EF67 /* Queuer */,
 				F72CD01127A7E92400E59476 /* JGProgressHUD */,
+				F72AD70E28C24BA1006CB92D /* NextcloudKit */,
 			);
 			productName = "Share Ext";
 			productReference = F7CE8AFB1DC1F8D8009CAE48 /* Share.appex */;
 			productType = "com.apple.product-type.app-extension";
 		};
+		F7346E0F28B0EF5B006CE2D2 /* Widget */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = F7346E1F28B0EF5E006CE2D2 /* Build configuration list for PBXNativeTarget "Widget" */;
+			buildPhases = (
+				F7346E0C28B0EF5B006CE2D2 /* Sources */,
+				F7346E0D28B0EF5B006CE2D2 /* Frameworks */,
+				F7346E0E28B0EF5B006CE2D2 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = Widget;
+			packageProductDependencies = (
+				F7346E2428B0FEFA006CE2D2 /* UICKeyChainStore */,
+				F7346E2628B0FFF2006CE2D2 /* Realm */,
+				F7346E2828B0FFF2006CE2D2 /* RealmSwift */,
+				F783030428B4C50600B84583 /* SVGKit */,
+				F783030A28B4C58600B84583 /* Queuer */,
+				F783030C28B4C59A00B84583 /* SwiftEntryKit */,
+				F783034328B5142B00B84583 /* NextcloudKit */,
+			);
+			productName = DashboardWidgetExtension;
+			productReference = F7346E1028B0EF5B006CE2D2 /* Widget.appex */;
+			productType = "com.apple.product-type.app-extension";
+		};
 		F771E3CF20E2392D00AFB62D /* File Provider Extension */ = {
 			isa = PBXNativeTarget;
 			buildConfigurationList = F771E3EF20E2392E00AFB62D /* Build configuration list for PBXNativeTarget "File Provider Extension" */;
@@ -2031,13 +2211,13 @@
 			);
 			name = "File Provider Extension";
 			packageProductDependencies = (
-				F786D594253454D300E3DD7B /* NCCommunication */,
 				F75E57C025BF0ECD002B72C2 /* SVGKit */,
 				F73ADD2326554FE20069EA0D /* SwiftEntryKit */,
 				F710FC81277B7D3500AA9FBF /* Realm */,
 				F710FC83277B7D3500AA9FBF /* RealmSwift */,
 				F7EBCDD0277B820D00A4EF67 /* UICKeyChainStore */,
 				F7EBCDD6277B834400A4EF67 /* Queuer */,
+				F72AD71228C24BCC006CB92D /* NextcloudKit */,
 			);
 			productName = "File Provider Extension";
 			productReference = F771E3D020E2392D00AFB62D /* File Provider Extension.appex */;
@@ -2061,10 +2241,10 @@
 				F7145A321D12E65F00CAFEEC /* PBXTargetDependency */,
 				F771E3EA20E2392E00AFB62D /* PBXTargetDependency */,
 				2C33C48523E2C475005F963B /* PBXTargetDependency */,
+				F7346E1B28B0EF5E006CE2D2 /* PBXTargetDependency */,
 			);
 			name = Nextcloud;
 			packageProductDependencies = (
-				F786D58C253454BF00E3DD7B /* NCCommunication */,
 				F75E57BC25BF0EC1002B72C2 /* SVGKit */,
 				F7ED547B25EEA65400956C55 /* QRCodeReader */,
 				F72DA9B325F53E4E00B87DB1 /* SwiftRichString */,
@@ -2083,6 +2263,7 @@
 				F7BB7E4627A18C56009B9F29 /* Parchment */,
 				F758A01127A7F03E0069468B /* JGProgressHUD */,
 				F753BA92281FD8020015BFB6 /* EasyTipView */,
+				F72AD70C28C24B93006CB92D /* NextcloudKit */,
 			);
 			productName = "Crypto Cloud";
 			productReference = F7CE8AFA1DC1F8D8009CAE48 /* Nextcloud.app */;
@@ -2094,7 +2275,7 @@
 		F7F67BA01A24D27800EE80DA /* Project object */ = {
 			isa = PBXProject;
 			attributes = {
-				LastSwiftUpdateCheck = 1310;
+				LastSwiftUpdateCheck = 1340;
 				LastUpgradeCheck = 1330;
 				ORGANIZATIONNAME = "Marino Faggiana";
 				TargetAttributes = {
@@ -2117,6 +2298,9 @@
 							};
 						};
 					};
+					F7346E0F28B0EF5B006CE2D2 = {
+						CreatedOnToolsVersion = 13.4.1;
+					};
 					F771E3CF20E2392D00AFB62D = {
 						CreatedOnToolsVersion = 9.4.1;
 						LastSwiftMigration = 1020;
@@ -2189,7 +2373,6 @@
 			);
 			mainGroup = F7F67B9F1A24D27800EE80DA;
 			packageReferences = (
-				F786D58B253454BF00E3DD7B /* XCRemoteSwiftPackageReference "ios-communication-library" */,
 				F75E57A725BF0D61002B72C2 /* XCRemoteSwiftPackageReference "SVGKit" */,
 				F7ED547A25EEA65400956C55 /* XCRemoteSwiftPackageReference "QRCodeReader" */,
 				F72DA9B225F53E4E00B87DB1 /* XCRemoteSwiftPackageReference "SwiftRichString" */,
@@ -2207,12 +2390,14 @@
 				F7BB7E4527A18C56009B9F29 /* XCRemoteSwiftPackageReference "Parchment" */,
 				F72CD01027A7E92400E59476 /* XCRemoteSwiftPackageReference "JGProgressHUD" */,
 				F753BA91281FD8010015BFB6 /* XCRemoteSwiftPackageReference "EasyTipView" */,
+				F783034028B511D200B84583 /* XCRemoteSwiftPackageReference "NextcloudKit" */,
 			);
 			productRefGroup = F7F67B9F1A24D27800EE80DA;
 			projectDirPath = "";
 			projectRoot = "";
 			targets = (
 				F77B0DEB1D118A16002130FE /* Nextcloud */,
+				F7346E0F28B0EF5B006CE2D2 /* Widget */,
 				F71459B41D12E3B700CAFEEC /* Share */,
 				F771E3CF20E2392D00AFB62D /* File Provider Extension */,
 				2C33C47E23E2C475005F963B /* Notification Service Extension */,
@@ -2258,6 +2443,16 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		F7346E0E28B0EF5B006CE2D2 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				F7C7B25128B8B0C400E7115D /* Images.xcassets in Resources */,
+				F7C7B25028B8AD4500E7115D /* Localizable.strings in Resources */,
+				F7346E2328B0FEBA006CE2D2 /* Assets.xcassets in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		F771E3CE20E2392D00AFB62D /* Resources */ = {
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -2474,6 +2669,7 @@
 				AF730AFA27843E4C00B7520E /* NCShareExtension+NCDelegate.swift in Sources */,
 				F7EDE4E0262D7BAF00414FE6 /* NCGridCell.swift in Sources */,
 				F7A76DC8256A71CD00119AB3 /* UIImage+Extensions.swift in Sources */,
+				F7E03DBE28BB48E4009AFDA1 /* NCUtilityGUI.swift in Sources */,
 				F7B8CD96261AF401007C1359 /* NCNetworkingChunkedUpload.swift in Sources */,
 				F7BAADC91ED5A87C00B7EAD4 /* NCDatabase.swift in Sources */,
 				F7D57C8B26317BDE00DE301D /* NCAccountRequest.swift in Sources */,
@@ -2488,6 +2684,50 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		F7346E0C28B0EF5B006CE2D2 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				F78302FD28B4C42B00B84583 /* NCUserBaseUrl.swift in Sources */,
+				F793E5A128B76541005E4B02 /* NotificationCenter+MainThread.swift in Sources */,
+				F78302F928B4C3E600B84583 /* NCManageDatabase+Account.swift in Sources */,
+				F7E0710128B13BB00001B882 /* DashboardData.swift in Sources */,
+				F783030328B4C4DD00B84583 /* ThreadSafeDictionary.swift in Sources */,
+				F77ED59128C9CE9D00E24ED0 /* ToolbarData.swift in Sources */,
+				F7E03DBD28BB48E4009AFDA1 /* NCUtilityGUI.swift in Sources */,
+				F78302F728B4C3C900B84583 /* NCManageDatabase.swift in Sources */,
+				F7346E1628B0EF5C006CE2D2 /* Widget.swift in Sources */,
+				F78302F828B4C3E100B84583 /* NCManageDatabase+Activity.swift in Sources */,
+				F783030228B4C4B800B84583 /* NCUtility.swift in Sources */,
+				F72EA95A28B7BD0D00C88F0C /* NextcloudWidgetView.swift in Sources */,
+				F78302FE28B4C44700B84583 /* NCBrand.swift in Sources */,
+				F793E5A028B7651B005E4B02 /* NCViewCertificateDetails.swift in Sources */,
+				F71EB73728CA81D1007FAB9D /* Widget.intentdefinition in Sources */,
+				F793E59F28B764F6005E4B02 /* NCContentPresenter.swift in Sources */,
+				F78302FA28B4C3EA00B84583 /* NCManageDatabase+Metadata.swift in Sources */,
+				F783030728B4C52800B84583 /* UIColor+Extensions.swift in Sources */,
+				F783030028B4C45800B84583 /* NCGlobal.swift in Sources */,
+				F793E59D28B761E7005E4B02 /* NCNetworking.swift in Sources */,
+				F793E5A528B7698D005E4B02 /* NCNetworkingProcessUpload.swift in Sources */,
+				F78302FC28B4C3F300B84583 /* NCElementsJSON.swift in Sources */,
+				F783030628B4C51E00B84583 /* String+Extensions.swift in Sources */,
+				F77ED59328C9CEA000E24ED0 /* ToolbarWidgetProvider.swift in Sources */,
+				F72A17D828B221E300F3F159 /* DashboardWidgetView.swift in Sources */,
+				F77ED59528C9CEA400E24ED0 /* ToolbarWidgetView.swift in Sources */,
+				F793E59B28B75FB0005E4B02 /* NCAutoUpload.swift in Sources */,
+				F78302FB28B4C3EE00B84583 /* NCManageDatabase+Video.swift in Sources */,
+				F72EA95228B7BA2A00C88F0C /* DashboardWidgetProvider.swift in Sources */,
+				F793E5A228B76580005E4B02 /* NCNetworkingChunkedUpload.swift in Sources */,
+				F783031228B4C8EC00B84583 /* CCUtility.m in Sources */,
+				F72EA95828B7BC4F00C88F0C /* NextcloudData.swift in Sources */,
+				F793E59E28B763C2005E4B02 /* NCAskAuthorization.swift in Sources */,
+				F78302FF28B4C45000B84583 /* NCUtilityFileSystem.swift in Sources */,
+				F78302F628B4C3C500B84583 /* NCDatabase.swift in Sources */,
+				F783030128B4C49700B84583 /* UIImage+Extensions.swift in Sources */,
+				F72EA95428B7BABA00C88F0C /* NextcloudWidgetProvider.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		F771E3CC20E2392D00AFB62D /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -2515,6 +2755,7 @@
 				AF817EF3274BC781009ED85B /* NCUserBaseUrl.swift in Sources */,
 				F771E3F320E239A600AFB62D /* FileProviderData.swift in Sources */,
 				F7B8CD9B261AF401007C1359 /* NCNetworkingChunkedUpload.swift in Sources */,
+				F7E03DBF28BB48E4009AFDA1 /* NCUtilityGUI.swift in Sources */,
 				F7A0D1372591FBC5008F8A13 /* String+Extensions.swift in Sources */,
 				F771E3D720E2392D00AFB62D /* FileProviderEnumerator.swift in Sources */,
 				F74AF3A6247FB6AE00AC767B /* NCUtilityFileSystem.swift in Sources */,
@@ -2660,6 +2901,7 @@
 				F70CAE3A1F8CF31A008125FD /* NCEndToEndEncryption.m in Sources */,
 				AF93471B27E2361E002537EE /* NCShareAdvancePermission.swift in Sources */,
 				F70753EB2542A99800972D44 /* NCViewerMediaPage.swift in Sources */,
+				F7FAFD3A28BFA948000777FE /* NCNotification+Menu.swift in Sources */,
 				F74C0436253F1CDC009762AB /* NCShares.swift in Sources */,
 				F7AC1CB028AB94490032D99F /* Array+Extensions.swift in Sources */,
 				F7AE00F5230D5F9E007ACF8A /* NCLoginWeb.swift in Sources */,
@@ -2685,6 +2927,7 @@
 				F7F4F11027ECDC4A008676F9 /* UIDevice+Extensions.swift in Sources */,
 				F77B0ED11D118A16002130FE /* Acknowledgements.m in Sources */,
 				F70D8D8124A4A9BF000A5756 /* NCNetworkingProcessUpload.swift in Sources */,
+				F7E03DBC28BB48E4009AFDA1 /* NCUtilityGUI.swift in Sources */,
 				F7D96FCC246ED7E200536D73 /* NCNetworkingCheckRemoteUser.swift in Sources */,
 				F7E4D9C422ED929B003675FD /* NCShareCommentsCell.swift in Sources */,
 				F717402E24F699A5000C87D5 /* NCFavorite.swift in Sources */,
@@ -2714,6 +2957,11 @@
 			target = F71459B41D12E3B700CAFEEC /* Share */;
 			targetProxy = F7145A311D12E65F00CAFEEC /* PBXContainerItemProxy */;
 		};
+		F7346E1B28B0EF5E006CE2D2 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = F7346E0F28B0EF5B006CE2D2 /* Widget */;
+			targetProxy = F7346E1A28B0EF5E006CE2D2 /* PBXContainerItemProxy */;
+		};
 		F771E3EA20E2392E00AFB62D /* PBXTargetDependency */ = {
 			isa = PBXTargetDependency;
 			target = F771E3CF20E2392D00AFB62D /* File Provider Extension */;
@@ -2923,6 +3171,76 @@
 			};
 			name = Release;
 		};
+		F7346E1D28B0EF5E006CE2D2 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+				ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/iOSClient/Brand/Widget.entitlements";
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"$(inherited)",
+					EXTENSION,
+					EXTENSION_WIDGET,
+				);
+				GENERATE_INFOPLIST_FILE = YES;
+				INFOPLIST_FILE = "$(SRCROOT)/iOSClient/Brand/Widget.plist";
+				INFOPLIST_KEY_CFBundleDisplayName = Nextcloud;
+				INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Nextcloud. All rights reserved.";
+				IPHONEOS_DEPLOYMENT_TARGET = 15.5;
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+				MTL_FAST_MATH = YES;
+				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.Widget;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SKIP_INSTALL = YES;
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_WIDGET";
+				SWIFT_EMIT_LOC_STRINGS = YES;
+				SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/Widget/Widget-Brinding-header.h";
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Debug;
+		};
+		F7346E1E28B0EF5E006CE2D2 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+				ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/iOSClient/Brand/Widget.entitlements";
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"$(inherited)",
+					EXTENSION,
+					EXTENSION_WIDGET,
+				);
+				GENERATE_INFOPLIST_FILE = YES;
+				INFOPLIST_FILE = "$(SRCROOT)/iOSClient/Brand/Widget.plist";
+				INFOPLIST_KEY_CFBundleDisplayName = Nextcloud;
+				INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Nextcloud. All rights reserved.";
+				IPHONEOS_DEPLOYMENT_TARGET = 15.5;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				MTL_FAST_MATH = YES;
+				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.Widget;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SKIP_INSTALL = YES;
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_WIDGET";
+				SWIFT_EMIT_LOC_STRINGS = YES;
+				SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/Widget/Widget-Brinding-header.h";
+				TARGETED_DEVICE_FAMILY = "1,2";
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
 		F771E3F020E2392E00AFB62D /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
@@ -2960,6 +3278,7 @@
 		F77B0F9B1D118A16002130FE /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CODE_SIGN_ENTITLEMENTS = iOSClient/Brand/iOSClient.entitlements;
 				INFOPLIST_FILE = "$(SRCROOT)/iOSClient/Brand/iOSClient.plist";
@@ -2971,6 +3290,7 @@
 		F77B0F9C1D118A16002130FE /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CODE_SIGN_ENTITLEMENTS = iOSClient/Brand/iOSClient.entitlements;
 				INFOPLIST_FILE = "$(SRCROOT)/iOSClient/Brand/iOSClient.plist";
@@ -3008,7 +3328,7 @@
 				COPY_PHASE_STRIP = NO;
 				CURRENT_PROJECT_VERSION = 0;
 				DEVELOPMENT_TEAM = NKUJUXUJ3B;
-				ENABLE_BITCODE = YES;
+				ENABLE_BITCODE = NO;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_TESTABILITY = YES;
 				GCC_NO_COMMON_BLOCKS = YES;
@@ -3030,7 +3350,7 @@
 					"@executable_path/Frameworks",
 					"@executable_path/../../Frameworks",
 				);
-				MARKETING_VERSION = 4.4.3;
+				MARKETING_VERSION = 4.5.0;
 				ONLY_ACTIVE_ARCH = YES;
 				OTHER_LDFLAGS = "";
 				SDKROOT = iphoneos;
@@ -3071,7 +3391,7 @@
 				COPY_PHASE_STRIP = NO;
 				CURRENT_PROJECT_VERSION = 0;
 				DEVELOPMENT_TEAM = NKUJUXUJ3B;
-				ENABLE_BITCODE = YES;
+				ENABLE_BITCODE = NO;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_TESTABILITY = YES;
 				GCC_NO_COMMON_BLOCKS = YES;
@@ -3091,7 +3411,7 @@
 					"@executable_path/Frameworks",
 					"@executable_path/../../Frameworks",
 				);
-				MARKETING_VERSION = 4.4.3;
+				MARKETING_VERSION = 4.5.0;
 				ONLY_ACTIVE_ARCH = YES;
 				OTHER_LDFLAGS = "";
 				SDKROOT = iphoneos;
@@ -3134,6 +3454,15 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
+		F7346E1F28B0EF5E006CE2D2 /* Build configuration list for PBXNativeTarget "Widget" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				F7346E1D28B0EF5E006CE2D2 /* Debug */,
+				F7346E1E28B0EF5E006CE2D2 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 		F771E3EF20E2392E00AFB62D /* Build configuration list for PBXNativeTarget "File Provider Extension" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
@@ -3276,12 +3605,12 @@
 				minimumVersion = 2.0.0;
 			};
 		};
-		F786D58B253454BF00E3DD7B /* XCRemoteSwiftPackageReference "ios-communication-library" */ = {
+		F783034028B511D200B84583 /* XCRemoteSwiftPackageReference "NextcloudKit" */ = {
 			isa = XCRemoteSwiftPackageReference;
-			repositoryURL = "https://github.com/nextcloud/ios-communication-library/";
+			repositoryURL = "https://github.com/nextcloud/NextcloudKit";
 			requirement = {
-				kind = exactVersion;
-				version = 0.99.9;
+				branch = develop;
+				kind = branch;
 			};
 		};
 		F788ECC5263AAAF900ADC67F /* XCRemoteSwiftPackageReference "MarkdownKit" */ = {
@@ -3356,6 +3685,26 @@
 			package = F710FC78277B7CFF00AA9FBF /* XCRemoteSwiftPackageReference "realm-swift" */;
 			productName = RealmSwift;
 		};
+		F72AD70C28C24B93006CB92D /* NextcloudKit */ = {
+			isa = XCSwiftPackageProductDependency;
+			package = F783034028B511D200B84583 /* XCRemoteSwiftPackageReference "NextcloudKit" */;
+			productName = NextcloudKit;
+		};
+		F72AD70E28C24BA1006CB92D /* NextcloudKit */ = {
+			isa = XCSwiftPackageProductDependency;
+			package = F783034028B511D200B84583 /* XCRemoteSwiftPackageReference "NextcloudKit" */;
+			productName = NextcloudKit;
+		};
+		F72AD71028C24BBB006CB92D /* NextcloudKit */ = {
+			isa = XCSwiftPackageProductDependency;
+			package = F783034028B511D200B84583 /* XCRemoteSwiftPackageReference "NextcloudKit" */;
+			productName = NextcloudKit;
+		};
+		F72AD71228C24BCC006CB92D /* NextcloudKit */ = {
+			isa = XCSwiftPackageProductDependency;
+			package = F783034028B511D200B84583 /* XCRemoteSwiftPackageReference "NextcloudKit" */;
+			productName = NextcloudKit;
+		};
 		F72CD01127A7E92400E59476 /* JGProgressHUD */ = {
 			isa = XCSwiftPackageProductDependency;
 			package = F72CD01027A7E92400E59476 /* XCRemoteSwiftPackageReference "JGProgressHUD" */;
@@ -3371,6 +3720,21 @@
 			package = F72DA9B225F53E4E00B87DB1 /* XCRemoteSwiftPackageReference "SwiftRichString" */;
 			productName = SwiftRichString;
 		};
+		F7346E2428B0FEFA006CE2D2 /* UICKeyChainStore */ = {
+			isa = XCSwiftPackageProductDependency;
+			package = F76DA964277B76F10082465B /* XCRemoteSwiftPackageReference "UICKeyChainStore" */;
+			productName = UICKeyChainStore;
+		};
+		F7346E2628B0FFF2006CE2D2 /* Realm */ = {
+			isa = XCSwiftPackageProductDependency;
+			package = F710FC78277B7CFF00AA9FBF /* XCRemoteSwiftPackageReference "realm-swift" */;
+			productName = Realm;
+		};
+		F7346E2828B0FFF2006CE2D2 /* RealmSwift */ = {
+			isa = XCSwiftPackageProductDependency;
+			package = F710FC78277B7CFF00AA9FBF /* XCRemoteSwiftPackageReference "realm-swift" */;
+			productName = RealmSwift;
+		};
 		F73ADD1B265546890069EA0D /* SwiftEntryKit */ = {
 			isa = XCSwiftPackageProductDependency;
 			package = F73ADD1A265546880069EA0D /* XCRemoteSwiftPackageReference "SwiftEntryKit" */;
@@ -3451,25 +3815,25 @@
 			package = F770768C263A8C3400A1BA94 /* XCRemoteSwiftPackageReference "FloatingPanel" */;
 			productName = FloatingPanel;
 		};
-		F786D58C253454BF00E3DD7B /* NCCommunication */ = {
+		F783030428B4C50600B84583 /* SVGKit */ = {
 			isa = XCSwiftPackageProductDependency;
-			package = F786D58B253454BF00E3DD7B /* XCRemoteSwiftPackageReference "ios-communication-library" */;
-			productName = NCCommunication;
+			package = F75E57A725BF0D61002B72C2 /* XCRemoteSwiftPackageReference "SVGKit" */;
+			productName = SVGKit;
 		};
-		F786D592253454CE00E3DD7B /* NCCommunication */ = {
+		F783030A28B4C58600B84583 /* Queuer */ = {
 			isa = XCSwiftPackageProductDependency;
-			package = F786D58B253454BF00E3DD7B /* XCRemoteSwiftPackageReference "ios-communication-library" */;
-			productName = NCCommunication;
+			package = F76DA961277B760E0082465B /* XCRemoteSwiftPackageReference "Queuer" */;
+			productName = Queuer;
 		};
-		F786D594253454D300E3DD7B /* NCCommunication */ = {
+		F783030C28B4C59A00B84583 /* SwiftEntryKit */ = {
 			isa = XCSwiftPackageProductDependency;
-			package = F786D58B253454BF00E3DD7B /* XCRemoteSwiftPackageReference "ios-communication-library" */;
-			productName = NCCommunication;
+			package = F73ADD1A265546880069EA0D /* XCRemoteSwiftPackageReference "SwiftEntryKit" */;
+			productName = SwiftEntryKit;
 		};
-		F786D596253454D800E3DD7B /* NCCommunication */ = {
+		F783034328B5142B00B84583 /* NextcloudKit */ = {
 			isa = XCSwiftPackageProductDependency;
-			package = F786D58B253454BF00E3DD7B /* XCRemoteSwiftPackageReference "ios-communication-library" */;
-			productName = NCCommunication;
+			package = F783034028B511D200B84583 /* XCRemoteSwiftPackageReference "NextcloudKit" */;
+			productName = NextcloudKit;
 		};
 		F788ECC6263AAAFA00ADC67F /* MarkdownKit */ = {
 			isa = XCSwiftPackageProductDependency;

+ 97 - 0
Nextcloud.xcodeproj/xcshareddata/xcschemes/Notification Service Extension.xcscheme

@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1340"
+   wasCreatedForAppExtension = "YES"
+   version = "2.0">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "2C33C47E23E2C475005F963B"
+               BuildableName = "Notification Service Extension.appex"
+               BlueprintName = "Notification Service Extension"
+               ReferencedContainer = "container:Nextcloud.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "F77B0DEB1D118A16002130FE"
+               BuildableName = "Nextcloud.app"
+               BlueprintName = "Nextcloud"
+               ReferencedContainer = "container:Nextcloud.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = ""
+      selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
+      launchStyle = "0"
+      askForAppToLaunch = "Yes"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES"
+      launchAutomaticallySubstyle = "2">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "F77B0DEB1D118A16002130FE"
+            BuildableName = "Nextcloud.app"
+            BlueprintName = "Nextcloud"
+            ReferencedContainer = "container:Nextcloud.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      askForAppToLaunch = "Yes"
+      launchAutomaticallySubstyle = "2">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "F77B0DEB1D118A16002130FE"
+            BuildableName = "Nextcloud.app"
+            BlueprintName = "Nextcloud"
+            ReferencedContainer = "container:Nextcloud.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 124 - 0
Nextcloud.xcodeproj/xcshareddata/xcschemes/Widget.xcscheme

@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1340"
+   wasCreatedForAppExtension = "YES"
+   version = "2.0">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "F7346E0F28B0EF5B006CE2D2"
+               BuildableName = "Widget.appex"
+               BlueprintName = "Widget"
+               ReferencedContainer = "container:Nextcloud.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "F77B0DEB1D118A16002130FE"
+               BuildableName = "Nextcloud.app"
+               BlueprintName = "Nextcloud"
+               ReferencedContainer = "container:Nextcloud.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = ""
+      selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
+      launchStyle = "0"
+      askForAppToLaunch = "Yes"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES"
+      launchAutomaticallySubstyle = "2">
+      <RemoteRunnable
+         runnableDebuggingMode = "2"
+         BundleIdentifier = "com.apple.springboard">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "F7346E0F28B0EF5B006CE2D2"
+            BuildableName = "Widget.appex"
+            BlueprintName = "Widget"
+            ReferencedContainer = "container:Nextcloud.xcodeproj">
+         </BuildableReference>
+      </RemoteRunnable>
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "F77B0DEB1D118A16002130FE"
+            BuildableName = "Nextcloud.app"
+            BlueprintName = "Nextcloud"
+            ReferencedContainer = "container:Nextcloud.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "_XCWidgetKind"
+            value = ""
+            isEnabled = "YES">
+         </EnvironmentVariable>
+         <EnvironmentVariable
+            key = "_XCWidgetDefaultView"
+            value = "timeline"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+         <EnvironmentVariable
+            key = "_XCWidgetFamily"
+            value = "medium"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      askForAppToLaunch = "Yes"
+      launchAutomaticallySubstyle = "2">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "F77B0DEB1D118A16002130FE"
+            BuildableName = "Nextcloud.app"
+            BlueprintName = "Nextcloud"
+            ReferencedContainer = "container:Nextcloud.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 5 - 5
NextcloudTests/SharePermissionTest.swift

@@ -23,7 +23,7 @@
 
 @testable import Nextcloud
 import XCTest
-import NCCommunication
+import NextcloudKit
 
 class SharePermissionTest: XCTestCase {
     override func setUp() {
@@ -35,7 +35,7 @@ class SharePermissionTest: XCTestCase {
     }
 
     func testShareCellPermissionCell() throws {
-        let share = NCTableShareOptions(sharee: NCCommunicationSharee(), metadata: tableMetadata(), password: nil)
+        let share = NCTableShareOptions(sharee: NKSharee(), metadata: tableMetadata(), password: nil)
         let shareConfig = NCShareConfig(parentMetadata: tableMetadata(), share: share)
 
         for row in 0..<shareConfig.permissions.count {
@@ -48,7 +48,7 @@ class SharePermissionTest: XCTestCase {
 
         let meta = tableMetadata()
         meta.sharePermissionsCollaborationServices = 31
-        let fullShare = NCTableShareOptions(sharee: NCCommunicationSharee(), metadata: meta, password: nil)
+        let fullShare = NCTableShareOptions(sharee: NKSharee(), metadata: meta, password: nil)
         let shareFullConfig = NCShareConfig(parentMetadata: meta, share: fullShare)
 
         for row in 0..<shareFullConfig.permissions.count {
@@ -102,7 +102,7 @@ class SharePermissionTest: XCTestCase {
     func testUserShare() throws {
         let meta = tableMetadata()
         meta.directory = false
-        let sharee = NCCommunicationSharee()
+        let sharee = NKSharee()
         let share = NCTableShareOptions(sharee: sharee, metadata: meta, password: nil)
         let fileConfig = NCShareConfig(parentMetadata: meta, share: share)
         XCTAssertEqual(fileConfig.advanced, NCShareDetails.forUser)
@@ -126,7 +126,7 @@ class SharePermissionTest: XCTestCase {
         XCTAssertEqual(fileConfig.permissions as? [NCLinkPermission], NCLinkPermission.forFile)
 
         meta.directory = true
-        let sharee = NCCommunicationSharee()
+        let sharee = NKSharee()
         let folderShare = NCTableShareOptions(sharee: sharee, metadata: meta, password: nil)
         let folderConfig = NCShareConfig(parentMetadata: meta, share: folderShare)
         XCTAssertEqual(folderConfig.resharePermission, meta.sharePermissionsCollaborationServices)

+ 2 - 2
Share/NCShareCell.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 
 protocol NCShareCellDelegate: AnyObject {
     var uploadStarted: Bool { get }
@@ -40,7 +40,7 @@ class NCShareCell: UITableViewCell {
 
     func setup(fileName: String) {
         self.fileName = fileName
-        let resultInternalType = NCCommunicationCommon.shared.getInternalType(fileName: fileName, mimeType: "", directory: false)
+        let resultInternalType = NKCommon.shared.getInternalType(fileName: fileName, mimeType: "", directory: false)
 
         backgroundColor = NCBrandColor.shared.systemBackground
         imageCell?.layer.cornerRadius = 6

+ 1 - 1
Share/NCShareExtension+DataSource.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 
 // MARK: - Collection View (target folder)
 

+ 3 - 3
Share/NCShareExtension+Files.swift

@@ -73,11 +73,11 @@ extension NCShareExtension {
         networkInProgress = true
         collectionView.reloadData()
 
-        NCNetworking.shared.readFolder(serverUrl: serverUrl, account: activeAccount.account) { _, metadataFolder, _, _, _, _, errorCode, errorDescription in
+        NCNetworking.shared.readFolder(serverUrl: serverUrl, account: activeAccount.account) { _, metadataFolder, _, _, _, _, error in
 
             DispatchQueue.main.async {
-                if errorCode != 0 {
-                    self.showAlert(description: errorDescription)
+                if error != .success {
+                    self.showAlert(description: error.errorDescription)
                 }
                 self.networkInProgress = false
                 self.metadataFolder = metadataFolder

+ 3 - 4
Share/NCShareExtension+NCDelegate.swift

@@ -21,7 +21,7 @@
 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
 
-import NCCommunication
+import NextcloudKit
 import UIKit
 
 extension NCShareExtension: NCEmptyDataSetDelegate, NCAccountRequestDelegate {
@@ -81,14 +81,13 @@ extension NCShareExtension: NCEmptyDataSetDelegate, NCAccountRequestDelegate {
         NCBrandColor.shared.createUserColors()
 
         // NETWORKING
-        NCCommunicationCommon.shared.setup(
+        NKCommon.shared.setup(
             account: activeAccount.account,
             user: activeAccount.user,
             userId: activeAccount.userId,
             password: CCUtility.getPassword(activeAccount.account),
             urlBase: activeAccount.urlBase,
             userAgent: CCUtility.getUserAgent(),
-            webDav: NCUtilityFileSystem.shared.getWebDAV(account: activeAccount.account),
             nextcloudVersion: 0,
             delegate: NCNetworking.shared)
 
@@ -122,7 +121,7 @@ extension NCShareExtension: NCShareCellDelegate, NCRenameFileDelegate, NCListCel
     func renameFile(named fileName: String) {
         guard let vcRename = UIStoryboard(name: "NCRenameFile", bundle: nil).instantiateInitialViewController() as? NCRenameFile else { return }
 
-        let resultInternalType = NCCommunicationCommon.shared.getInternalType(fileName: fileName, mimeType: "", directory: false)
+        let resultInternalType = NKCommon.shared.getInternalType(fileName: fileName, mimeType: "", directory: false)
         vcRename.delegate = self
         vcRename.fileName = fileName
         if let previewImage = UIImage.downsample(imageAt: URL(fileURLWithPath: NSTemporaryDirectory() + fileName), to: CGSize(width: 140, height: 140)) {

+ 12 - 12
Share/NCShareExtension.swift

@@ -24,7 +24,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 import JGProgressHUD
 
 enum NCShareExtensionError: Error {
@@ -116,14 +116,14 @@ class NCShareExtension: UIViewController {
         let isSimulatorOrTestFlight = NCUtility.shared.isSimulatorOrTestFlight()
         let versionNextcloudiOS = String(format: NCBrandOptions.shared.textCopyrightNextcloudiOS, NCUtility.shared.getVersionApp())
 
-        NCCommunicationCommon.shared.levelLog = levelLog
+        NKCommon.shared.levelLog = levelLog
         if let pathDirectoryGroup = CCUtility.getDirectoryGroup()?.path {
-            NCCommunicationCommon.shared.pathLog = pathDirectoryGroup
+            NKCommon.shared.pathLog = pathDirectoryGroup
         }
         if isSimulatorOrTestFlight {
-            NCCommunicationCommon.shared.writeLog("Start Share session with level \(levelLog) " + versionNextcloudiOS + " (Simulator / TestFlight)")
+            NKCommon.shared.writeLog("Start Share session with level \(levelLog) " + versionNextcloudiOS + " (Simulator / TestFlight)")
         } else {
-            NCCommunicationCommon.shared.writeLog("Start Share session with level \(levelLog) " + versionNextcloudiOS)
+            NKCommon.shared.writeLog("Start Share session with level \(levelLog) " + versionNextcloudiOS)
         }
 
         // Colors
@@ -283,9 +283,9 @@ class NCShareExtension: UIViewController {
     }
 
     @objc func actionCreateFolder() {
-        let alertController = UIAlertController.createFolder(serverUrl: serverUrl, urlBase: activeAccount) { errorCode, errorDescription in
-            guard errorCode != 0 else { return }
-            self.showAlert(title: "_error_createsubfolders_upload_", description: errorDescription)
+        let alertController = UIAlertController.createFolder(serverUrl: serverUrl, urlBase: activeAccount) { error in
+            guard error != .success else { return }
+            self.showAlert(title: "_error_createsubfolders_upload_", description: error.errorDescription)
         }
         self.present(alertController, animated: true)
     }
@@ -312,7 +312,7 @@ extension NCShareExtension {
                 ocId: ocId,
                 serverUrl: serverUrl, urlBase: activeAccount.urlBase, url: "",
                 contentType: "")
-            metadata.session = NCCommunicationCommon.shared.sessionIdentifierUpload
+            metadata.session = NKCommon.shared.sessionIdentifierUpload
             metadata.sessionSelector = NCGlobal.shared.selectorUploadFileShareExtension
             metadata.size = NCUtilityFileSystem.shared.getFileSize(filePath: toPath)
             metadata.status = NCGlobal.shared.metadataStatusWaitUpload
@@ -339,7 +339,7 @@ extension NCShareExtension {
         guard uploadStarted else { return }
         guard uploadMetadata.count > counterUploaded else { return finishedUploading() }
         let metadata = uploadMetadata[counterUploaded]
-        let results = NCCommunicationCommon.shared.getInternalType(fileName: metadata.fileNameView, mimeType: metadata.contentType, directory: false)
+        let results = NKCommon.shared.getInternalType(fileName: metadata.fileNameView, mimeType: metadata.contentType, directory: false)
         metadata.contentType = results.mimeType
         metadata.iconName = results.iconName
         metadata.classFile = results.classFile
@@ -352,8 +352,8 @@ extension NCShareExtension {
         hud.progress = 0
         hud.show(in: self.view)
 
-        NCNetworking.shared.upload(metadata: metadata) { } completion: { errorCode, _ in
-            if errorCode != 0 {
+        NCNetworking.shared.upload(metadata: metadata) { } completion: { error in
+            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)

+ 11 - 0
Widget/Assets.xcassets/AccentColor.colorset/Contents.json

@@ -0,0 +1,11 @@
+{
+  "colors" : [
+    {
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 11 - 0
Widget/Assets.xcassets/AppIcon.imageset/Contents.json

@@ -0,0 +1,11 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 6 - 0
Widget/Assets.xcassets/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 11 - 0
Widget/Assets.xcassets/WidgetBackground.colorset/Contents.json

@@ -0,0 +1,11 @@
+{
+  "colors" : [
+    {
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 12 - 0
Widget/Assets.xcassets/nextcloud.imageset/Contents.json

@@ -0,0 +1,12 @@
+{
+  "images" : [
+    {
+      "filename" : "nextcloud-icon29@1x.png",
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
Widget/Assets.xcassets/nextcloud.imageset/nextcloud-icon29@1x.png


+ 137 - 0
Widget/Dashboard/DashboardData.swift

@@ -0,0 +1,137 @@
+//
+//  DashboardData.swift
+//  Widget
+//
+//  Created by Marino Faggiana on 20/08/22.
+//  Copyright © 2022 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 WidgetKit
+import NextcloudKit
+
+let dashboaardItems = 4
+
+struct DashboardDataEntry: TimelineEntry {
+    let date: Date
+    let datas: [DashboardData]
+    let isPlaceholder: Bool
+    let title: String
+    let footerImage: String
+    let footerText: String
+}
+
+struct DashboardData: Identifiable, Hashable {
+    var id: String
+    var image: UIImage
+    var title: String
+    var subTitle: String
+    var url: URL
+}
+
+let dashboardDatasTest: [DashboardData] = [
+    .init(id: "1", image: UIImage(named: "nextcloud")!, title: "title1", subTitle: "subTitle-description1", url: URL(string: "https://nextcloud.com/")!),
+    .init(id: "2", image: UIImage(named: "nextcloud")!, title: "title2", subTitle: "subTitle-description2", url: URL(string: "https://nextcloud.com/")!),
+    .init(id: "3", image: UIImage(named: "nextcloud")!, title: "title3", subTitle: "subTitle-description3", url: URL(string: "https://nextcloud.com/")!),
+    .init(id: "4", image: UIImage(named: "nextcloud")!, title: "title4", subTitle: "subTitle-description4", url: URL(string: "https://nextcloud.com/")!),
+    .init(id: "5", image: UIImage(named: "nextcloud")!, title: "title5", subTitle: "subTitle-description5", url: URL(string: "https://nextcloud.com/")!),
+    .init(id: "6", image: UIImage(named: "nextcloud")!, title: "title6", subTitle: "subTitle-description6", url: URL(string: "https://nextcloud.com/")!)
+]
+
+func getTitleDashboard() -> String {
+
+    let hour = Calendar.current.component(.hour, from: Date())
+    var good = ""
+
+    switch hour {
+    case 6..<12: good = NSLocalizedString("_good_morning_", value: "Good morning", comment: "")
+    case 12: good = NSLocalizedString("_good_noon_", value: "Good noon", comment: "")
+    case 13..<17: good = NSLocalizedString("_good_afternoon_", value: "Good afternoon", comment: "")
+    case 17..<22: good = NSLocalizedString("_good_evening_", value: "Good evening", comment: "")
+    default: good = NSLocalizedString("_good_night_", value: "Good night", comment: "")
+    }
+
+    if let account = NCManageDatabase.shared.getActiveAccount() {
+        return good + ", " + account.displayName
+    } else {
+        return good
+    }
+}
+
+func getDashboardDataEntry(isPreview: Bool, displaySize: CGSize, completion: @escaping (_ entry: DashboardDataEntry) -> Void) {
+
+    let datasPlaceholder = Array(dashboardDatasTest[0...dashboaardItems - 1])
+    
+    if isPreview {
+        return completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, title: getTitleDashboard(), footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " dashboard"))
+    }
+
+    guard let account = NCManageDatabase.shared.getActiveAccount() else {
+        return completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, title: getTitleDashboard(), footerImage: "xmark.icloud", footerText: NSLocalizedString("_no_active_account_", value: "No account found", comment: "")))
+    }
+    
+    // NETWORKING
+    let password = CCUtility.getPassword(account.account)!
+    NKCommon.shared.setup(
+        account: account.account,
+        user: account.user,
+        userId: account.userId,
+        password: password,
+        urlBase: account.urlBase,
+        userAgent: CCUtility.getUserAgent(),
+        nextcloudVersion: 0,
+        delegate: NCNetworking.shared)
+
+    // LOG
+    let levelLog = CCUtility.getLogLevel()
+    let isSimulatorOrTestFlight = NCUtility.shared.isSimulatorOrTestFlight()
+    let versionNextcloudiOS = String(format: NCBrandOptions.shared.textCopyrightNextcloudiOS, NCUtility.shared.getVersionApp())
+
+    NKCommon.shared.levelLog = levelLog
+    if let pathDirectoryGroup = CCUtility.getDirectoryGroup()?.path {
+        NKCommon.shared.pathLog = pathDirectoryGroup
+    }
+    if isSimulatorOrTestFlight {
+        NKCommon.shared.writeLog("Start \(NCBrandOptions.shared.brand) dashboard widget session with level \(levelLog) " + versionNextcloudiOS + " (Simulator / TestFlight)")
+    } else {
+        NKCommon.shared.writeLog("Start \(NCBrandOptions.shared.brand) dashboard widget session with level \(levelLog) " + versionNextcloudiOS)
+    }
+    
+    NextcloudKit.shared.getDashboard { account, dashboardResults, json, error in
+        
+        var datas = [DashboardData]()
+        
+        if let dashboardResults = dashboardResults {
+            for dashboardResult in dashboardResults {
+                let application = dashboardResult.application
+                if let entries = dashboardResult.dashboardEntries {
+                    for entry in entries {
+                        
+                    }
+                }
+            }
+        }
+        
+        if error != .success {
+            completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, title: getTitleDashboard(), footerImage: "xmark.icloud", footerText: error.errorDescription))
+        } else if datas.isEmpty {
+            completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, title: getTitleDashboard(), footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " dashboard"))
+        } else {
+            completion(DashboardDataEntry(date: Date(), datas: datas, isPlaceholder: false, title: getTitleDashboard(), footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " dashboard"))
+        }
+    }
+}

+ 48 - 0
Widget/Dashboard/DashboardWidgetProvider.swift

@@ -0,0 +1,48 @@
+//
+//  DashboardWidgetProvider.swift
+//  Widget
+//
+//  Created by Marino Faggiana on 25/08/22.
+//  Copyright © 2022 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 WidgetKit
+import SwiftUI
+
+struct DashboardWidgetProvider: TimelineProvider {
+
+    typealias Entry = DashboardDataEntry
+
+    func placeholder(in context: Context) -> Entry {
+        let datasPlaceholder = Array(dashboardDatasTest[0...nextcloudItems - 1])
+        return Entry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, title: getTitleDashboard(), footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " widget")
+    }
+
+    func getSnapshot(in context: Context, completion: @escaping (Entry) -> Void) {
+        getDashboardDataEntry(isPreview: false, displaySize: context.displaySize) { entry in
+            completion(entry)
+        }
+    }
+
+    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> Void) {
+        getDashboardDataEntry(isPreview: context.isPreview, displaySize: context.displaySize) { entry in
+            let timeLine = Timeline(entries: [entry], policy: .atEnd)
+            completion(timeLine)
+        }
+    }
+}

+ 75 - 0
Widget/Dashboard/DashboardWidgetView.swift

@@ -0,0 +1,75 @@
+//
+//  DashboardWidgetView.swift
+//  Widget
+//
+//  Created by Marino Faggiana on 20/08/22.
+//  Copyright © 2022 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 SwiftUI
+import WidgetKit
+
+struct DashboardWidgetView: View {
+    var entry: DashboardDataEntry
+    var body: some View {
+        ZStack(alignment: .top) {
+            VStack {
+                Text(entry.title)
+                    .font(.title3)
+                    .bold()
+                    .fixedSize(horizontal: false, vertical: true)
+                VStack(spacing: 5) {
+                    ForEach(entry.datas, id: \.id) { element in
+                        Link(destination: element.url) {
+                            HStack {
+                                Image(uiImage: element.image)
+                                    .resizable()
+                                    .aspectRatio(contentMode: .fit)
+                                    .frame(width: 40, height: 40)
+                                    .clipShape(Circle())
+                                VStack(alignment: .leading) {
+                                    Text(element.title)
+                                        .font(.headline)
+                                    Text(element.subTitle)
+                                        .font(.subheadline)
+                                        .foregroundColor(Color(white: 0.4745))
+                                }
+                                Spacer()
+                            }
+                            .padding(5)
+                        }
+                    }
+                }
+            }.padding(5)
+                .redacted(reason: entry.isPlaceholder ? .placeholder : [])
+            Text(entry.footerText)
+                    .font(.caption2)
+                    .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomTrailing)
+                    .padding(.trailing, 10.0)
+                    .padding(.bottom, 5.0)
+        }
+    }
+}
+
+struct DashboardWidget_Previews: PreviewProvider {
+    static var previews: some View {
+        let datas = Array(dashboardDatasTest[0...3])
+        let entry = DashboardDataEntry(date: Date(), datas: datas, isPlaceholder: false, title: "Dashboard", footerImage: "checkmark.icloud", footerText: "Nextcloud widget")
+        DashboardWidgetView(entry: entry).previewContext(WidgetPreviewContext(family: .systemLarge))
+    }
+}

+ 230 - 0
Widget/Nextcloud/NextcloudData.swift

@@ -0,0 +1,230 @@
+//
+//  NextcloudData.swift
+//  Widget
+//
+//  Created by Marino Faggiana on 25/08/22.
+//  Copyright © 2022 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 WidgetKit
+import NextcloudKit
+
+let nextcloudItems = 4
+
+struct NextcloudDataEntry: TimelineEntry {
+    let date: Date
+    let datas: [NextcloudRecentData]
+    let isPlaceholder: Bool
+    let tile: String
+    let footerImage: String
+    let footerText: String
+}
+
+struct NextcloudRecentData: Identifiable, Hashable {
+    var id: String
+    var image: UIImage
+    var title: String
+    var subTitle: String
+    var url: URL
+}
+
+let recentDatasTest: [NextcloudRecentData] = [
+    .init(id: "1", image: UIImage(named: "nextcloud")!, title: "title1", subTitle: "subTitle-description1", url: URL(string: "https://nextcloud.com/")!),
+    .init(id: "2", image: UIImage(named: "nextcloud")!, title: "title2", subTitle: "subTitle-description2", url: URL(string: "https://nextcloud.com/")!),
+    .init(id: "3", image: UIImage(named: "nextcloud")!, title: "title3", subTitle: "subTitle-description3", url: URL(string: "https://nextcloud.com/")!),
+    .init(id: "4", image: UIImage(named: "nextcloud")!, title: "title4", subTitle: "subTitle-description4", url: URL(string: "https://nextcloud.com/")!),
+    .init(id: "5", image: UIImage(named: "nextcloud")!, title: "title5", subTitle: "subTitle-description5", url: URL(string: "https://nextcloud.com/")!),
+    .init(id: "6", image: UIImage(named: "nextcloud")!, title: "title6", subTitle: "subTitle-description6", url: URL(string: "https://nextcloud.com/")!)
+]
+
+func getTitleNextcloudWidget() -> String {
+
+    let hour = Calendar.current.component(.hour, from: Date())
+    var good = ""
+
+    switch hour {
+    case 6..<12: good = NSLocalizedString("_good_morning_", value: "Good morning", comment: "")
+    case 12: good = NSLocalizedString("_good_noon_", value: "Good noon", comment: "")
+    case 13..<17: good = NSLocalizedString("_good_afternoon_", value: "Good afternoon", comment: "")
+    case 17..<22: good = NSLocalizedString("_good_evening_", value: "Good evening", comment: "")
+    default: good = NSLocalizedString("_good_night_", value: "Good night", comment: "")
+    }
+
+    if let account = NCManageDatabase.shared.getActiveAccount() {
+        return good + ", " + account.displayName
+    } else {
+        return good
+    }
+}
+
+func getNextcloudDataEntry(isPreview: Bool, displaySize: CGSize, completion: @escaping (_ entry: NextcloudDataEntry) -> Void) {
+
+    let datasPlaceholder = Array(recentDatasTest[0...nextcloudItems - 1])
+    let title = getTitleNextcloudWidget()
+    
+    if isPreview {
+        return completion(NextcloudDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, tile: title, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " widget"))
+    }
+
+    guard let account = NCManageDatabase.shared.getActiveAccount() else {
+        return completion(NextcloudDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, tile: title, footerImage: "xmark.icloud", footerText: NSLocalizedString("_no_active_account_", value: "No account found", comment: "")))
+    }
+
+    func isLive(file: NKFile, files: [NKFile]) -> Bool {
+
+        if file.ext.lowercased() != "mov" { return false }
+        if files.filter({ ($0.fileNameWithoutExt == file.fileNameWithoutExt) && ($0.ext.lowercased() == "jpg") }).first != nil {
+            return true
+        }
+        return false
+    }
+
+    // NETWORKING
+    let password = CCUtility.getPassword(account.account)!
+    NKCommon.shared.setup(
+        account: account.account,
+        user: account.user,
+        userId: account.userId,
+        password: password,
+        urlBase: account.urlBase,
+        userAgent: CCUtility.getUserAgent(),
+        nextcloudVersion: 0,
+        delegate: NCNetworking.shared)
+
+    let requestBodyRecent =
+    """
+    <?xml version=\"1.0\"?>
+    <d:searchrequest xmlns:d=\"DAV:\" xmlns:oc=\"http://owncloud.org/ns\" xmlns:nc=\"http://nextcloud.org/ns\">
+    <d:basicsearch>
+        <d:select>
+            <d:prop>
+                <d:displayname/>
+                <d:getcontenttype/>
+                <d:resourcetype/>
+                <d:getcontentlength/>
+                <d:getlastmodified/>
+                <d:getetag/>
+                <d:quota-used-bytes/>
+                <d:quota-available-bytes/>
+                <permissions xmlns=\"http://owncloud.org/ns\"/>
+                <id xmlns=\"http://owncloud.org/ns\"/>
+                <fileid xmlns=\"http://owncloud.org/ns\"/>
+                <size xmlns=\"http://owncloud.org/ns\"/>
+                <favorite xmlns=\"http://owncloud.org/ns\"/>
+                <creation_time xmlns=\"http://nextcloud.org/ns\"/>
+                <upload_time xmlns=\"http://nextcloud.org/ns\"/>
+                <is-encrypted xmlns=\"http://nextcloud.org/ns\"/>
+                <mount-type xmlns=\"http://nextcloud.org/ns\"/>
+                <owner-id xmlns=\"http://owncloud.org/ns\"/>
+                <owner-display-name xmlns=\"http://owncloud.org/ns\"/>
+                <comments-unread xmlns=\"http://owncloud.org/ns\"/>
+                <has-preview xmlns=\"http://nextcloud.org/ns\"/>
+                <trashbin-filename xmlns=\"http://nextcloud.org/ns\"/>
+                <trashbin-original-location xmlns=\"http://nextcloud.org/ns\"/>
+                <trashbin-deletion-time xmlns=\"http://nextcloud.org/ns\"/>
+            </d:prop>
+        </d:select>
+    <d:from>
+        <d:scope>
+            <d:href>%@</d:href>
+            <d:depth>infinity</d:depth>
+        </d:scope>
+    </d:from>
+    <d:where>
+        <d:lt>
+            <d:prop>
+                <d:getlastmodified/>
+            </d:prop>
+            <d:literal>%@</d:literal>
+        </d:lt>
+    </d:where>
+    <d:orderby>
+        <d:order>
+            <d:prop>
+                <d:getlastmodified/>
+            </d:prop>
+            <d:descending/>
+        </d:order>
+    </d:orderby>
+    <d:limit>
+        <d:nresults>50</d:nresults>
+    </d:limit>
+    </d:basicsearch>
+    </d:searchrequest>
+    """
+
+    let dateFormatter = DateFormatter()
+    dateFormatter.locale = Locale(identifier: "en_US_POSIX")
+    dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
+    let lessDateString = dateFormatter.string(from: Date())
+    let requestBody = String(format: requestBodyRecent, "/files/" + account.userId, lessDateString)
+
+    // LOG
+    let levelLog = CCUtility.getLogLevel()
+    let isSimulatorOrTestFlight = NCUtility.shared.isSimulatorOrTestFlight()
+    let versionNextcloudiOS = String(format: NCBrandOptions.shared.textCopyrightNextcloudiOS, NCUtility.shared.getVersionApp())
+
+    NKCommon.shared.levelLog = levelLog
+    if let pathDirectoryGroup = CCUtility.getDirectoryGroup()?.path {
+        NKCommon.shared.pathLog = pathDirectoryGroup
+    }
+    if isSimulatorOrTestFlight {
+        NKCommon.shared.writeLog("Start \(NCBrandOptions.shared.brand) widget session with level \(levelLog) " + versionNextcloudiOS + " (Simulator / TestFlight)")
+    } else {
+        NKCommon.shared.writeLog("Start \(NCBrandOptions.shared.brand) widget session with level \(levelLog) " + versionNextcloudiOS)
+    }
+    
+    NextcloudKit.shared.searchBodyRequest(serverUrl: account.urlBase, requestBody: requestBody, showHiddenFiles: CCUtility.getShowHiddenFiles()) { _, files, error in
+
+        var datas: [NextcloudRecentData] = []
+        
+        for file in files {
+            guard !file.directory else { continue }
+            guard !isLive(file: file, files: files) else { continue }
+            let subTitle = CCUtility.dateDiff(file.date as Date) + " · " + CCUtility.transformedSize(file.size)
+            // url: nextcloud://open-file?path=Talk/IMG_0000123.jpg&user=marinofaggiana&link=https://cloud.nextcloud.com/f/123
+            guard var path = NCUtilityFileSystem.shared.getPath(path: file.path, user: file.user, fileName: file.fileName).urlEncoded else { continue }
+            if path.first == "/" { path = String(path.dropFirst())}
+            guard let user = file.user.urlEncoded else { continue }
+            let link = file.urlBase + "/f/" + file.fileId
+            let urlString = "nextcloud://open-file?path=\(path)&user=\(user)&link=\(link)"
+            guard let url = URL(string: urlString) else { continue }
+            // Build Recent Data
+            var imageRecent = UIImage()
+            if let image = NCUtilityGUI().createFilePreviewImage(ocId: file.ocId, etag: file.etag, fileNameView: file.fileName, classFile: file.classFile, status: 0, createPreviewMedia: false) {
+                imageRecent = image
+            } else if !file.iconName.isEmpty {
+                imageRecent = UIImage(named: file.iconName)!
+            } else {
+                imageRecent = UIImage(named: "file")!
+            }
+            let recentData = NextcloudRecentData.init(id: file.ocId, image: imageRecent, title: file.fileName, subTitle: subTitle, url: url)
+            datas.append(recentData)
+            if datas.count == nextcloudItems { break}
+        }
+
+        if error != .success {
+            completion(NextcloudDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, tile: title, footerImage: "xmark.icloud", footerText: error.errorDescription))
+        } else if datas.isEmpty {
+            completion(NextcloudDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, tile: title, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " widget"))
+        } else {
+            completion(NextcloudDataEntry(date: Date(), datas: datas, isPlaceholder: false, tile: title, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " widget"))
+        }
+    }
+}
+

+ 49 - 0
Widget/Nextcloud/NextcloudWidgetProvider.swift

@@ -0,0 +1,49 @@
+//
+//  NextcloudWidgetProvider.swift
+//  Widget
+//
+//  Created by Marino Faggiana on 25/08/22.
+//  Copyright © 2022 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 WidgetKit
+import SwiftUI
+
+struct NextcloudWidgetProvider: TimelineProvider {
+
+    typealias Entry = NextcloudDataEntry
+
+    func placeholder(in context: Context) -> Entry {
+        let datasPlaceholder = Array(recentDatasTest[0...nextcloudItems - 1])
+        let title = getTitleNextcloudWidget()
+        return Entry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, tile: title, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " widget")
+    }
+
+    func getSnapshot(in context: Context, completion: @escaping (Entry) -> Void) {
+        getNextcloudDataEntry(isPreview: false, displaySize: context.displaySize) { entry in
+            completion(entry)
+        }
+    }
+
+    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> Void) {
+        getNextcloudDataEntry(isPreview: context.isPreview, displaySize: context.displaySize) { entry in
+            let timeLine = Timeline(entries: [entry], policy: .atEnd)
+            completion(timeLine)
+        }
+    }
+}

+ 182 - 0
Widget/Nextcloud/NextcloudWidgetView.swift

@@ -0,0 +1,182 @@
+//
+//  NextcloudWidgetView.swift
+//  Widget
+//
+//  Created by Marino Faggiana on 25/08/22.
+//  Copyright © 2022 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 SwiftUI
+import WidgetKit
+
+struct NextcloudWidgetView: View {
+    
+    var entry: NextcloudDataEntry
+    
+    var body: some View {
+        
+        GeometryReader { geo in
+            
+            ZStack(alignment: .topLeading) {
+                
+                HStack() {
+                    
+                    Text(entry.tile)
+                        .font(.system(size: 12))
+                        .fontWeight(.bold)
+                        .multilineTextAlignment(.center)
+                        .textCase(.uppercase)
+                        .lineLimit(1)
+                }
+                .frame(width: geo.size.width - 20)
+                .padding([.top, .leading, .trailing], 10)
+                
+                VStack(alignment: .leading) {
+                    
+                    VStack(spacing: 0) {
+                        
+                        let datasCount = CGFloat(entry.datas.count)
+                        let heightFrame = (geo.size.height - 120) / datasCount
+                        let addSizeIcon = heightFrame / datasCount
+                        let spacing = (addSizeIcon - datasCount) / 2
+                        
+                        ForEach(entry.datas, id: \.id) { element in
+                            
+                            Link(destination: element.url) {
+                                
+                                HStack {
+                                    
+                                    let subTitleColor = Color(white: 0.5)
+                                    let imageSize:CGFloat = 30
+                                    
+                                    Image(uiImage: element.image)
+                                        .resizable()
+                                        .scaledToFill()
+                                        .frame(width: imageSize+addSizeIcon, height: imageSize+addSizeIcon)
+                                        .clipped()
+                                        .cornerRadius(5)
+                                    
+                                    VStack(alignment: .leading, spacing: spacing) {
+                                        
+                                        Text(element.title)
+                                            .font(.system(size: 12))
+                                            .fontWeight(.regular)
+                                        
+                                        Text(element.subTitle)
+                                            .font(.system(size: CGFloat(10)))
+                                            .foregroundColor(subTitleColor)
+                                    }
+                                    Spacer()
+                                }
+                                .padding(.leading, 10)
+                                .frame(height: heightFrame)
+                            }
+                            Divider()
+                                .padding(.leading, 48 + addSizeIcon)
+                        }
+                    }
+                }
+                .padding(.top, 30)
+                .redacted(reason: entry.isPlaceholder ? .placeholder : [])
+
+                HStack(spacing: 0) {
+
+                    let sizeButton: CGFloat = 45
+                    let placeholderColor = Color(white: 0.8)
+                    let brandColor = Color(NCBrandColor.shared.brand)
+                    let brandTextColor = Color(NCBrandColor.shared.brandText)
+                    
+                    Link(destination: entry.isPlaceholder ? NCGlobal.shared.widgetActionNoAction : NCGlobal.shared.widgetActionUploadAsset, label: {
+                        Image("buttonAddImage")
+                            .resizable()
+                            .renderingMode(.template)
+                            .foregroundColor(entry.isPlaceholder ? placeholderColor : brandTextColor)
+                            .padding(10)
+                            .background(entry.isPlaceholder ? placeholderColor : brandColor)
+                            .clipShape(Circle())
+                            .scaledToFit()
+                            .frame(width: geo.size.width / 4, height: sizeButton)
+                    })
+
+                    Link(destination: entry.isPlaceholder ? NCGlobal.shared.widgetActionNoAction : NCGlobal.shared.widgetActionScanDocument, label: {
+                        Image("buttonAddScan")
+                            .resizable()
+                            .renderingMode(.template)
+                            .foregroundColor(entry.isPlaceholder ? placeholderColor : brandTextColor)
+                            .padding(10)
+                            .background(entry.isPlaceholder ? placeholderColor : brandColor)
+                            .clipShape(Circle())
+                            .scaledToFit()
+                            .frame(width: geo.size.width / 4, height: sizeButton)
+                    })
+
+                    Link(destination: entry.isPlaceholder ? NCGlobal.shared.widgetActionNoAction : NCGlobal.shared.widgetActionTextDocument, label: {
+                        Image("note.text")
+                            .resizable()
+                            .renderingMode(.template)
+                            .foregroundColor(entry.isPlaceholder ? placeholderColor : brandTextColor)
+                            .padding(10)
+                            .background(entry.isPlaceholder ? placeholderColor : brandColor)
+                            .clipShape(Circle())
+                            .scaledToFit()
+                            .frame(width: geo.size.width / 4, height: sizeButton)
+                    })
+
+                    Link(destination: entry.isPlaceholder ? NCGlobal.shared.widgetActionNoAction : NCGlobal.shared.widgetActionVoiceMemo, label: {
+                        Image("microphone")
+                            .resizable()
+                            .renderingMode(.template)
+                            .foregroundColor(entry.isPlaceholder ? placeholderColor : brandTextColor)
+                            .padding(10)
+                            .background(entry.isPlaceholder ? placeholderColor : brandColor)
+                            .clipShape(Circle())
+                            .scaledToFit()
+                            .frame(width: geo.size.width / 4, height: sizeButton)
+                    })
+                }
+                .frame(width: geo.size.width, height: geo.size.height - 25, alignment: .bottomTrailing)
+                .redacted(reason: entry.isPlaceholder ? .placeholder : [])
+
+                HStack {
+
+                    let placeholderColor = Color(white: 0.2)
+                    let brandColor = Color(NCBrandColor.shared.brand)
+
+                    Image(systemName: entry.footerImage)
+                        .resizable()
+                        .scaledToFit()
+                        .frame(width: 15, height: 15)
+                        .foregroundColor(entry.isPlaceholder ? placeholderColor : brandColor)
+                    
+                    Text(entry.footerText)
+                        .font(.caption2)
+                        .padding(.trailing, 13.0)
+                }
+                .frame(maxWidth: geo.size.width - 5, maxHeight: geo.size.height - 2, alignment: .bottomTrailing)
+            }
+        }
+    }
+}
+
+struct NextcloudWidget_Previews: PreviewProvider {
+    static var previews: some View {
+        let datas = Array(recentDatasTest[0...3])
+        let entry = NextcloudDataEntry(date: Date(), datas: datas, isPlaceholder: false, tile: "Good afternoon, Marino Faggiana", footerImage: "checkmark.icloud", footerText: "Nextcloud widget")
+        NextcloudWidgetView(entry: entry).previewContext(WidgetPreviewContext(family: .systemLarge))
+    }
+}

+ 44 - 0
Widget/Toolbar/ToolbarData.swift

@@ -0,0 +1,44 @@
+//
+//  ToolbarData.swift
+//  Widget
+//
+//  Created by Marino Faggiana on 25/08/22.
+//  Copyright © 2022 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 WidgetKit
+
+struct ToolbarDataEntry: TimelineEntry {
+    let date: Date
+    let isPlaceholder: Bool
+    let footerImage: String
+    let footerText: String
+}
+
+func getToolbarDataEntry(isPreview: Bool, completion: @escaping (_ entry: ToolbarDataEntry) -> Void) {
+
+    if isPreview {
+        return completion(ToolbarDataEntry(date: Date(), isPlaceholder: true, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " toolbar"))
+    }
+    
+    if NCManageDatabase.shared.getActiveAccount() == nil {
+        return completion(ToolbarDataEntry(date: Date(), isPlaceholder: true, footerImage: "xmark.icloud", footerText: NSLocalizedString("_no_active_account_", value: "No account found", comment: "")))
+    }
+
+    completion(ToolbarDataEntry(date: Date(), isPlaceholder: false, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " toolbar"))
+}

+ 47 - 0
Widget/Toolbar/ToolbarWidgetProvider.swift

@@ -0,0 +1,47 @@
+//
+//  ToolbarWidgetProvider.swift
+//  Widget
+//
+//  Created by Marino Faggiana on 25/08/22.
+//  Copyright © 2022 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 WidgetKit
+import SwiftUI
+
+struct ToolbarWidgetProvider: TimelineProvider {
+
+    typealias Entry = ToolbarDataEntry
+
+    func placeholder(in context: Context) -> Entry {
+        return Entry(date: Date(), isPlaceholder: true, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " toolbar")
+    }
+
+    func getSnapshot(in context: Context, completion: @escaping (Entry) -> Void) {
+        getToolbarDataEntry(isPreview: false) { entry in
+            completion(entry)
+        }
+    }
+
+    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> Void) {
+        getToolbarDataEntry(isPreview: context.isPreview) { entry in
+            let timeLine = Timeline(entries: [entry], policy: .atEnd)
+            completion(timeLine)
+        }
+    }
+}

+ 118 - 0
Widget/Toolbar/ToolbarWidgetView.swift

@@ -0,0 +1,118 @@
+//
+//  ToolbarWidgetView.swift
+//  Widget
+//
+//  Created by Marino Faggiana on 25/08/22.
+//  Copyright © 2022 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 SwiftUI
+import WidgetKit
+
+struct ToolbarWidgetView: View {
+
+    var entry: ToolbarDataEntry
+
+    var body: some View {
+
+        GeometryReader { geo in
+
+            ZStack(alignment: .topLeading) {
+
+                HStack(spacing: 0) {
+
+                    let sizeButton: CGFloat = 65
+                    let placeholderColor = Color(white: 0.8)
+                    let brandColor = Color(NCBrandColor.shared.brand)
+                    let brandTextColor = Color(NCBrandColor.shared.brandText)
+
+                    Link(destination: entry.isPlaceholder ? NCGlobal.shared.widgetActionNoAction : NCGlobal.shared.widgetActionUploadAsset, label: {
+                        Image("buttonAddImage")
+                            .resizable()
+                            .renderingMode(.template)
+                            .foregroundColor(entry.isPlaceholder ? placeholderColor : brandTextColor)
+                            .padding(10)
+                            .background(entry.isPlaceholder ? placeholderColor : brandColor)
+                            .clipShape(Circle())
+                            .scaledToFit()
+                            .frame(width: geo.size.width / 4, height: sizeButton)
+                    })
+
+                    Link(destination: entry.isPlaceholder ? NCGlobal.shared.widgetActionNoAction : NCGlobal.shared.widgetActionScanDocument, label: {
+                        Image("buttonAddScan")
+                            .resizable()
+                            .renderingMode(.template)
+                            .foregroundColor(entry.isPlaceholder ? placeholderColor : brandTextColor)
+                            .padding(10)
+                            .background(entry.isPlaceholder ? placeholderColor : brandColor)
+                            .clipShape(Circle())
+                            .scaledToFit()
+                            .frame(width: geo.size.width / 4, height: sizeButton)
+                    })
+
+                    Link(destination: entry.isPlaceholder ? NCGlobal.shared.widgetActionNoAction : NCGlobal.shared.widgetActionTextDocument, label: {
+                        Image("note.text")
+                            .resizable()
+                            .renderingMode(.template)
+                            .foregroundColor(entry.isPlaceholder ? placeholderColor : brandTextColor)
+                            .padding(10)
+                            .background(entry.isPlaceholder ? placeholderColor : brandColor)
+                            .clipShape(Circle())
+                            .scaledToFit()
+                            .frame(width: geo.size.width / 4, height: sizeButton)
+                    })
+
+                    Link(destination: entry.isPlaceholder ? NCGlobal.shared.widgetActionNoAction : NCGlobal.shared.widgetActionVoiceMemo, label: {
+                        Image("microphone")
+                            .resizable()
+                            .renderingMode(.template)
+                            .foregroundColor(entry.isPlaceholder ? placeholderColor : brandTextColor)
+                            .padding(10)
+                            .background(entry.isPlaceholder ? placeholderColor : brandColor)
+                            .clipShape(Circle())
+                            .scaledToFit()
+                            .frame(width: geo.size.width / 4, height: sizeButton)
+                    })
+                }
+                .frame(width: geo.size.width, height: geo.size.height, alignment: .center)
+                .redacted(reason: entry.isPlaceholder ? .placeholder : [])
+
+                HStack {
+
+                    Image(systemName: entry.footerImage)
+                        .resizable()
+                        .scaledToFit()
+                        .frame(width: 15, height: 15)
+                        .foregroundColor(entry.isPlaceholder ? Color(white: 0.2) : Color(NCBrandColor.shared.brand))
+
+                    Text(entry.footerText)
+                        .font(.caption2)
+                        .padding(.trailing, 13.0)
+                }
+                .frame(maxWidth: geo.size.width - 5, maxHeight: geo.size.height - 2, alignment: .bottomTrailing)
+            }.background(ContainerRelativeShape().fill(Color(.sRGB, red: 0.89, green: 0.89, blue: 0.89, opacity: 0.75)))
+        }
+    }
+}
+
+struct ToolbarWidget_Previews: PreviewProvider {
+    static var previews: some View {
+        let entry = ToolbarDataEntry(date: Date(), isPlaceholder: false, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " toolbar")
+        ToolbarWidgetView(entry: entry).previewContext(WidgetPreviewContext(family: .systemMedium))
+    }
+}

+ 5 - 0
Widget/Widget-Brinding-header.h

@@ -0,0 +1,5 @@
+//
+//  Use this file to import your target's public headers that you would like to expose to Swift.
+//
+
+#import "CCUtility.h"

+ 59 - 0
Widget/Widget.intentdefinition

@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>INEnums</key>
+	<array/>
+	<key>INIntentDefinitionModelVersion</key>
+	<string>1.2</string>
+	<key>INIntentDefinitionNamespace</key>
+	<string>88xZPY</string>
+	<key>INIntentDefinitionSystemVersion</key>
+	<string>20A294</string>
+	<key>INIntentDefinitionToolsBuildVersion</key>
+	<string>12A6144</string>
+	<key>INIntentDefinitionToolsVersion</key>
+	<string>12.0</string>
+	<key>INIntents</key>
+	<array>
+		<dict>
+			<key>INIntentCategory</key>
+			<string>information</string>
+			<key>INIntentDescriptionID</key>
+			<string>tVvJ9c</string>
+			<key>INIntentEligibleForWidgets</key>
+			<true/>
+			<key>INIntentIneligibleForSuggestions</key>
+			<true/>
+			<key>INIntentName</key>
+			<string>Configuration</string>
+			<key>INIntentResponse</key>
+			<dict>
+				<key>INIntentResponseCodes</key>
+				<array>
+					<dict>
+						<key>INIntentResponseCodeName</key>
+						<string>success</string>
+						<key>INIntentResponseCodeSuccess</key>
+						<true/>
+					</dict>
+					<dict>
+						<key>INIntentResponseCodeName</key>
+						<string>failure</string>
+					</dict>
+				</array>
+			</dict>
+			<key>INIntentTitle</key>
+			<string>Configuration</string>
+			<key>INIntentTitleID</key>
+			<string>gpCwrM</string>
+			<key>INIntentType</key>
+			<string>Custom</string>
+			<key>INIntentVerb</key>
+			<string>View</string>
+		</dict>
+	</array>
+	<key>INTypes</key>
+	<array/>
+</dict>
+</plist>

+ 75 - 0
Widget/Widget.swift

@@ -0,0 +1,75 @@
+//
+//  NextcloudWidget.swift
+//  NextcloudWidget
+//
+//  Created by Marino Faggiana on 20/08/22.
+//  Copyright © 2022 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 WidgetKit
+import SwiftUI
+
+@main
+struct NextcloudWidgetBundle: WidgetBundle {
+
+    @WidgetBundleBuilder
+    var body: some Widget {
+        DashboardWidget()
+        NextcloudWidget()
+        ToolbarWidget()
+    }
+}
+
+struct DashboardWidget: Widget {
+    let kind: String = "DashboardWidget"
+
+    var body: some WidgetConfiguration {
+        StaticConfiguration(kind: kind, provider: DashboardWidgetProvider()) { entry in
+            DashboardWidgetView(entry: entry)
+        }
+        .supportedFamilies([.systemLarge])
+        .configurationDisplayName(NCBrandOptions.shared.brand + " Dashboard")
+        .description(NSLocalizedString("_description_dashboardwidget_", comment: ""))
+    }
+}
+
+struct NextcloudWidget: Widget {
+    let kind: String = "NextcloudWidget"
+
+    var body: some WidgetConfiguration {
+        StaticConfiguration(kind: kind, provider: NextcloudWidgetProvider()) { entry in
+            NextcloudWidgetView(entry: entry)
+        }
+        .supportedFamilies([.systemLarge])
+        .configurationDisplayName(NCBrandOptions.shared.brand + " Widget")
+        .description(NSLocalizedString("_description_nextcloudwidget_", comment: ""))
+    }
+}
+
+struct ToolbarWidget: Widget {
+    let kind: String = "ToolbarWidget"
+
+    var body: some WidgetConfiguration {
+        StaticConfiguration(kind: kind, provider: ToolbarWidgetProvider()) { entry in
+            ToolbarWidgetView(entry: entry)
+        }
+        .supportedFamilies([.systemMedium])
+        .configurationDisplayName(NCBrandOptions.shared.brand + " Toolbar")
+        .description(NSLocalizedString("_description_toolbarwidget_", comment: ""))
+    }
+}

+ 1 - 1
iOSClient/Account Request/NCAccountRequest.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 
 public protocol NCAccountRequestDelegate: AnyObject {
     func accountRequestAddAccount()

+ 24 - 24
iOSClient/Activity/NCActivity.swift

@@ -24,7 +24,7 @@
 
 import UIKit
 import SwiftRichString
-import NCCommunication
+import NextcloudKit
 
 class NCActivity: UIViewController, NCSharePagingContent {
 
@@ -83,12 +83,12 @@ class NCActivity: UIViewController, NCSharePagingContent {
         commentView = Bundle.main.loadNibNamed("NCActivityCommentView", owner: self, options: nil)?.first as? NCActivityCommentView
         commentView?.setup(urlBase: appDelegate, account: activeAccount) { newComment in
             guard let newComment = newComment, !newComment.isEmpty, let metadata = self.metadata else { return }
-            NCCommunication.shared.putComments(fileId: metadata.fileId, message: newComment) { _, errorCode, errorDescription in
-                if errorCode == 0 {
+            NextcloudKit.shared.putComments(fileId: metadata.fileId, message: newComment) { _, error in
+                if error == .success {
                     self.commentView?.newCommentField.text?.removeAll()
                     self.loadComments()
                 } else {
-                    NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                    NCContentPresenter.shared.showError(error: error)
                 }
             }
         }
@@ -262,8 +262,8 @@ extension NCActivity: UITableViewDataSource {
                     cell.icon.image = image
                 }
             } else {
-                NCCommunication.shared.downloadContent(serverUrl: activity.icon) { _, data, errorCode, _ in
-                    if errorCode == 0 {
+                NextcloudKit.shared.downloadContent(serverUrl: activity.icon) { _, data, error in
+                    if error == .success {
                         do {
                             try data!.write(to: NSURL(fileURLWithPath: fileNameLocalPath) as URL, options: .atomic)
                             self.tableView.reloadData()
@@ -403,11 +403,11 @@ extension NCActivity {
         guard showComments, let metadata = metadata else { return }
         disptachGroup?.enter()
 
-        NCCommunication.shared.getComments(fileId: metadata.fileId) { account, comments, errorCode, errorDescription in
-            if errorCode == 0, let comments = comments {
+        NextcloudKit.shared.getComments(fileId: metadata.fileId) { account, comments, error in
+            if error == .success, let comments = comments {
                 NCManageDatabase.shared.addComments(comments, account: metadata.account, objectId: metadata.fileId)
-            } else if errorCode != NCGlobal.shared.errorResourceNotFound {
-                NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+            } else if error.errorCode != NCGlobal.shared.errorResourceNotFound {
+                NCContentPresenter.shared.showError(error: error)
             }
 
             if let disptachGroup = disptachGroup {
@@ -427,20 +427,20 @@ extension NCActivity {
 
         disptachGroup.enter()
 
-        NCCommunication.shared.getActivity(
+        NextcloudKit.shared.getActivity(
             since: 0,
             limit: 1,
             objectId: nil,
             objectType: objectType,
-            previews: true) { account, _, activityFirstKnown, activityLastGiven, errorCode, _ in
+            previews: true) { account, _, activityFirstKnown, activityLastGiven, error in
                 defer { disptachGroup.leave() }
 
                 let largestActivityId = max(activityFirstKnown, activityLastGiven)
-                guard errorCode == 0,
+                guard error == .success,
                       account == self.appDelegate.account,
                       largestActivityId > resultActivityId
                 else {
-                    self.hasActivityToLoad = errorCode == 304 ? false : self.hasActivityToLoad
+                    self.hasActivityToLoad = error.errorCode == NCGlobal.shared.errorNotModified ? false : self.hasActivityToLoad
                     return
                 }
 
@@ -454,18 +454,18 @@ extension NCActivity {
         var resultActivityId = 0
         disptachGroup.enter()
 
-        NCCommunication.shared.getActivity(
+        NextcloudKit.shared.getActivity(
             since: idActivity,
             limit: min(limit, 200),
             objectId: metadata?.fileId,
             objectType: objectType,
-            previews: true) { account, activities, activityFirstKnown, activityLastGiven, errorCode, _ in
+            previews: true) { account, activities, activityFirstKnown, activityLastGiven, error in
                 defer { disptachGroup.leave() }
-                guard errorCode == 0,
+                guard error == .success,
                       account == self.appDelegate.account,
                       !activities.isEmpty
                 else {
-                    self.hasActivityToLoad = errorCode == 304 ? false : self.hasActivityToLoad
+                    self.hasActivityToLoad = error.errorCode == NCGlobal.shared.errorNotModified ? false : self.hasActivityToLoad
                     return
                 }
                 NCManageDatabase.shared.addActivity(activities, account: account)
@@ -514,11 +514,11 @@ extension NCActivity: NCShareCommentsCellDelegate {
                     alert.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in
                         guard let message = alert.textFields?.first?.text, message != "" else { return }
 
-                        NCCommunication.shared.updateComments(fileId: metadata.fileId, messageId: tableComments.messageId, message: message) { _, errorCode, errorDescription in
-                            if errorCode == 0 {
+                        NextcloudKit.shared.updateComments(fileId: metadata.fileId, messageId: tableComments.messageId, message: message) { _, error in
+                            if error == .success {
                                 self.loadComments()
                             } else {
-                                NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                                NCContentPresenter.shared.showError(error: error)
                             }
                         }
                     }))
@@ -535,11 +535,11 @@ extension NCActivity: NCShareCommentsCellDelegate {
                 action: { _ in
                     guard let metadata = self.metadata, let tableComments = tableComments else { return }
 
-                    NCCommunication.shared.deleteComments(fileId: metadata.fileId, messageId: tableComments.messageId) { _, errorCode, errorDescription in
-                        if errorCode == 0 {
+                    NextcloudKit.shared.deleteComments(fileId: metadata.fileId, messageId: tableComments.messageId) { _, error in
+                        if error == .success {
                             self.loadComments()
                         } else {
-                            NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                            NCContentPresenter.shared.showError(error: error)
                         }
                     }
                 }

+ 8 - 7
iOSClient/Activity/NCActivityTableViewCell.swift

@@ -22,7 +22,7 @@
 //
 
 import Foundation
-import NCCommunication
+import NextcloudKit
 import FloatingPanel
 
 class NCActivityCollectionViewCell: UICollectionViewCell {
@@ -108,7 +108,8 @@ extension NCActivityTableViewCell: UICollectionViewDelegate {
                         viewController.trashPath = result.filePath
                         (responder as? UIViewController)!.navigationController?.pushViewController(viewController, animated: true)
                     } else {
-                        NCContentPresenter.shared.messageNotification("_error_", description: "_trash_file_not_found_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorInternalError)
+                        let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_trash_file_not_found_")
+                        NCContentPresenter.shared.showError(error: error)
                     }
                 }
             }
@@ -149,26 +150,26 @@ extension NCActivityTableViewCell: UICollectionViewDelegate {
                 NCActivityIndicator.shared.start(backgroundView: backgroundView)
             }
 
-            NCCommunication.shared.download(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, requestHandler: { _ in
+            NextcloudKit.shared.download(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, requestHandler: { _ in
 
             }, taskHandler: { _ in
 
             }, progressHandler: { _ in
 
-            }) { account, _, _, _, _, _, errorCode, _ in
+            }) { account, _, _, _, _, _, error in
 
-                if account == self.appDelegate.account && errorCode == 0 {
+                if account == self.appDelegate.account && error == .success {
 
                     let serverUrl = (serverUrlFileName as NSString).deletingLastPathComponent
                     let fileName = (serverUrlFileName as NSString).lastPathComponent
                     let serverUrlFileName = serverUrl + "/" + fileName
 
-                    NCNetworking.shared.readFile(serverUrlFileName: serverUrlFileName) { account, metadata, errorCode, _ in
+                    NCNetworking.shared.readFile(serverUrlFileName: serverUrlFileName) { account, metadata, error in
 
                         NCActivityIndicator.shared.stop()
 
                         DispatchQueue.main.async {
-                            if account == self.appDelegate.account, errorCode == 0, let metadata = metadata {
+                            if account == self.appDelegate.account, error == .success, let metadata = metadata {
 
                                 // move from id to oc:id + instanceid (ocId)
                                 let atPath = CCUtility.getDirectoryProviderStorage()! + "/" + activitySubjectRich.id

+ 114 - 33
iOSClient/AppDelegate.swift

@@ -23,10 +23,11 @@
 
 import UIKit
 import BackgroundTasks
-import NCCommunication
+import NextcloudKit
 import TOPasscodeViewController
 import LocalAuthentication
 import Firebase
+import WidgetKit
 
 @UIApplicationMain
 class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, TOPasscodeViewControllerDelegate, NCAccountRequestDelegate, NCViewCertificateDetailsDelegate, NCUserBaseUrl {
@@ -78,39 +79,39 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
         CCUtility.createDirectoryStandard()
         CCUtility.emptyTemporaryDirectory()
 
-        NCCommunicationCommon.shared.setup(delegate: NCNetworking.shared)
-        NCCommunicationCommon.shared.setup(userAgent: userAgent)
+        NKCommon.shared.setup(delegate: NCNetworking.shared)
+        NKCommon.shared.setup(userAgent: userAgent)
 
         startTimerErrorNetworking()
 
         // LOG
         var levelLog = 0
         if let pathDirectoryGroup = CCUtility.getDirectoryGroup()?.path {
-            NCCommunicationCommon.shared.pathLog = pathDirectoryGroup
+            NKCommon.shared.pathLog = pathDirectoryGroup
         }
 
         if NCBrandOptions.shared.disable_log {
 
-            NCUtilityFileSystem.shared.deleteFile(filePath: NCCommunicationCommon.shared.filenamePathLog)
-            NCUtilityFileSystem.shared.deleteFile(filePath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! + "/" + NCCommunicationCommon.shared.filenameLog)
+            NCUtilityFileSystem.shared.deleteFile(filePath: NKCommon.shared.filenamePathLog)
+            NCUtilityFileSystem.shared.deleteFile(filePath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! + "/" + NKCommon.shared.filenameLog)
 
         } else {
 
             levelLog = CCUtility.getLogLevel()
-            NCCommunicationCommon.shared.levelLog = levelLog
-            NCCommunicationCommon.shared.copyLogToDocumentDirectory = true
+            NKCommon.shared.levelLog = levelLog
+            NKCommon.shared.copyLogToDocumentDirectory = true
             if isSimulatorOrTestFlight {
-                NCCommunicationCommon.shared.writeLog("Start session with level \(levelLog) " + versionNextcloudiOS + " (Simulator / TestFlight)")
+                NKCommon.shared.writeLog("Start session with level \(levelLog) " + versionNextcloudiOS + " (Simulator / TestFlight)")
             } else {
-                NCCommunicationCommon.shared.writeLog("Start session with level \(levelLog) " + versionNextcloudiOS)
+                NKCommon.shared.writeLog("Start session with level \(levelLog) " + versionNextcloudiOS)
             }
         }
 
         // LOG Account
         if let account = NCManageDatabase.shared.getActiveAccount() {
-            NCCommunicationCommon.shared.writeLog("Account active \(account.account)")
+            NKCommon.shared.writeLog("Account active \(account.account)")
             if CCUtility.getPassword(account.account).isEmpty {
-                NCCommunicationCommon.shared.writeLog("PASSWORD NOT FOUND for \(account.account)")
+                NKCommon.shared.writeLog("PASSWORD NOT FOUND for \(account.account)")
             }
         }
 
@@ -238,7 +239,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
             NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterInitialize)
         }
 
-        NCCommunicationCommon.shared.writeLog("Application will enter in foreground")
+        NKCommon.shared.writeLog("Application will enter in foreground")
 
         // START TIMER UPLOAD PROCESS
         if NCUtility.shared.isSimulator() {
@@ -272,6 +273,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
             showPrivacyProtectionWindow()
         }
 
+        // Reload Widget
+        if #available(iOS 14.0, *) {
+            WidgetCenter.shared.reloadAllTimelines()
+        }
+
         // Clear operation queue
         NCOperationQueue.shared.cancelAllQueue()
         // Clear download
@@ -311,7 +317,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
     func applicationWillTerminate(_ application: UIApplication) {
 
         NCNetworking.shared.cancelAllDownloadTransfer()
-        NCCommunicationCommon.shared.writeLog("bye bye")
+        NKCommon.shared.writeLog("bye bye")
     }
 
     // MARK: -
@@ -319,7 +325,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
     @objc private func initialize() {
         guard !account.isEmpty else { return }
 
-        NCCommunicationCommon.shared.writeLog("initialize Main")
+        NKCommon.shared.writeLog("initialize Main")
 
         // Registeration push notification
         NCPushNotification.shared().pushNotification()
@@ -333,6 +339,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
         // close detail
         NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterMenuDetailClose)
 
+        // Reload Widget
+        if #available(iOS 14.0, *) {
+            WidgetCenter.shared.reloadAllTimelines()
+        }
+
         // Registeration domain File Provider
         // FileProviderDomain *fileProviderDomain = [FileProviderDomain new];
         // [fileProviderDomain removeAllDomains];
@@ -348,9 +359,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
         request.earliestBeginDate = Date(timeIntervalSinceNow: 5 * 60) // Refresh after 5 minutes.
         do {
             try BGTaskScheduler.shared.submit(request)
-            NCCommunicationCommon.shared.writeLog("Refresh task success submit request \(request)")
+            NKCommon.shared.writeLog("Refresh task success submit request \(request)")
         } catch {
-            NCCommunicationCommon.shared.writeLog("Refresh task failed to submit request: \(error)")
+            NKCommon.shared.writeLog("Refresh task failed to submit request: \(error)")
         }
     }
 
@@ -363,9 +374,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
         request.requiresExternalPower = false
         do {
             try BGTaskScheduler.shared.submit(request)
-            NCCommunicationCommon.shared.writeLog("Background Processing task success submit request \(request)")
+            NKCommon.shared.writeLog("Background Processing task success submit request \(request)")
         } catch {
-            NCCommunicationCommon.shared.writeLog("Background Processing task failed to submit request: \(error)")
+            NKCommon.shared.writeLog("Background Processing task failed to submit request: \(error)")
         }
     }
 
@@ -377,11 +388,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
             return
         }
 
-        NCCommunicationCommon.shared.writeLog("Start handler refresh task [Auto upload]")
+        NKCommon.shared.writeLog("Start handler refresh task [Auto upload]")
 
         NCAutoUpload.shared.initAutoUpload(viewController: nil) { _ in
             DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
-                NCCommunicationCommon.shared.writeLog("Completition handler refresh task with [Auto upload]")
+                NKCommon.shared.writeLog("Completition handler refresh task with [Auto upload]")
                 task.setTaskCompleted(success: true)
             }
         }
@@ -395,16 +406,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
             return
         }
 
-        NCCommunicationCommon.shared.writeLog("Start handler processing task [Synchronize Favorite & Offline]")
+        NKCommon.shared.writeLog("Start handler processing task [Synchronize Favorite & Offline]")
 
-        NCNetworking.shared.listingFavoritescompletion(selector: NCGlobal.shared.selectorReadFile) { _, _, errorCode, _ in
-            NCCommunicationCommon.shared.writeLog("Completition listing favorite with error: \(errorCode)")
+        NCNetworking.shared.listingFavoritescompletion(selector: NCGlobal.shared.selectorReadFile) { _, _, error in
+            NKCommon.shared.writeLog("Completition listing favorite with error: \(error.errorCode)")
         }
 
         NCService.shared.synchronizeOffline(account: account)
 
         DispatchQueue.main.asyncAfter(deadline: .now() + 25) {
-            NCCommunicationCommon.shared.writeLog("Completition handler processing task [Synchronize Favorite & Offline]")
+            NKCommon.shared.writeLog("Completition handler processing task [Synchronize Favorite & Offline]")
             task.setTaskCompleted(success: true)
         }
     }
@@ -418,10 +429,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
             return
         }
 
-        NCCommunicationCommon.shared.writeLog("Start perform Fetch [Auto upload]")
+        NKCommon.shared.writeLog("Start perform Fetch [Auto upload]")
 
         NCAutoUpload.shared.initAutoUpload(viewController: nil) { items in
-            NCCommunicationCommon.shared.writeLog("Completition perform Fetch with \(items) uploads [Auto upload]")
+            NKCommon.shared.writeLog("Completition perform Fetch with \(items) uploads [Auto upload]")
             if items == 0 {
                 completionHandler(UIBackgroundFetchResult.noData)
             } else {
@@ -434,7 +445,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
 
     func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
 
-        NCCommunicationCommon.shared.writeLog("Start handle Events For Background URLSession: \(identifier)")
+        NKCommon.shared.writeLog("Start handle Events For Background URLSession: \(identifier)")
         backgroundSessionCompletionHandler = completionHandler
     }
 
@@ -449,8 +460,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
     }
 
     func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
-        NCNetworking.shared.checkPushNotificationServerProxyCertificateUntrusted(viewController: self.window?.rootViewController) { errorCode in
-            if errorCode == 0 {
+        NCNetworking.shared.checkPushNotificationServerProxyCertificateUntrusted(viewController: self.window?.rootViewController) { error in
+            if error == .success {
                 NCPushNotification.shared().registerForRemoteNotifications(withDeviceToken: deviceToken)
             }
         }
@@ -617,10 +628,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
 
         _ = NCFunctionCenter.shared
 
-        NCCommunicationCommon.shared.setup(account: account, user: user, userId: userId, password: password, urlBase: urlBase)
+        NKCommon.shared.setup(account: account, user: user, userId: userId, password: password, urlBase: urlBase)
         let serverVersionMajor = NCManageDatabase.shared.getCapabilitiesServerInt(account: account, elements: NCElementsJSON.shared.capabilitiesVersionMajor)
         if serverVersionMajor > 0 {
-            NCCommunicationCommon.shared.setup(nextcloudVersion: serverVersionMajor)
+            NKCommon.shared.setup(nextcloudVersion: serverVersionMajor)
         }
         NCKTVHTTPCache.shared.restartProxy(user: user, password: password)
     }
@@ -823,7 +834,75 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
         var serverUrl: String = ""
         var matchedAccount: tableAccount?
 
-        if scheme == "nextcloud" && action == "open-file" {
+        /*
+         Example:
+         nextcloud://open-action?action=create-voice-memo
+         */
+
+        if scheme == "nextcloud" && action == "open-action" {
+
+            if let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false) {
+                let queryItems = urlComponents.queryItems
+                guard let actionScheme = CCUtility.value(forKey: "action", fromQueryItems: queryItems), let rootViewController = window?.rootViewController else { return false }
+                
+                switch actionScheme {
+                case NCGlobal.shared.actionUploadAsset:
+
+                    NCAskAuthorization.shared.askAuthorizationPhotoLibrary(viewController: rootViewController) { hasPermission in
+                        if hasPermission {
+                            NCPhotosPickerViewController.init(viewController: rootViewController, maxSelectedAssets: 0, singleSelectedMode: false)
+                        }
+                    }
+                    
+                case NCGlobal.shared.actionScanDocument:
+                    
+                    if #available(iOS 13.0, *) {
+                        NCCreateScanDocument.shared.openScannerDocument(viewController: rootViewController)
+                    }
+                    
+                case NCGlobal.shared.actionTextDocument:
+                    
+                    guard let navigationController = UIStoryboard(name: "NCCreateFormUploadDocuments", bundle: nil).instantiateInitialViewController(), let directEditingCreators = NCManageDatabase.shared.getDirectEditingCreators(account: account), let directEditingCreator = directEditingCreators.first(where: { $0.editor == NCGlobal.shared.editorText}) else { return false }
+                    
+                    navigationController.modalPresentationStyle = UIModalPresentationStyle.formSheet
+
+                    let viewController = (navigationController as! UINavigationController).topViewController as! NCCreateFormUploadDocuments
+                    viewController.editorId = NCGlobal.shared.editorText
+                    viewController.creatorId = directEditingCreator.identifier
+                    viewController.typeTemplate = NCGlobal.shared.templateDocument
+                    viewController.serverUrl = activeServerUrl
+                    viewController.titleForm = NSLocalizedString("_create_nextcloudtext_document_", comment: "")
+
+                    rootViewController.present(navigationController, animated: true, completion: nil)
+                    
+                case NCGlobal.shared.actionVoiceMemo:
+                    
+                    NCAskAuthorization.shared.askAuthorizationAudioRecord(viewController: rootViewController) { hasPermission in
+                        if hasPermission {
+                            let fileName = CCUtility.createFileNameDate(NSLocalizedString("_voice_memo_filename_", comment: ""), extension: "m4a")!
+                            let viewController = UIStoryboard(name: "NCAudioRecorderViewController", bundle: nil).instantiateInitialViewController() as! NCAudioRecorderViewController
+
+                            viewController.delegate = self
+                            viewController.createRecorder(fileName: fileName)
+                            viewController.modalTransitionStyle = .crossDissolve
+                            viewController.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
+
+                            rootViewController.present(viewController, animated: true, completion: nil)
+                        }
+                    }
+
+                default:
+                    print("No action")
+                }
+            }
+        }
+
+        /*
+         Example:
+         nextcloud://open-file?path=Talk/IMG_0000123.jpg&user=marinofaggiana&link=https://cloud.nextcloud.com/f/123
+         */
+
+        else if scheme == "nextcloud" && action == "open-file" {
 
             if !isSearchingMode, let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false) {
 
@@ -880,6 +959,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
                     }
                 }
             }
+        } else {
+            app.open(url)
         }
 
         return true

+ 3 - 3
iOSClient/Brand/NCBrand.swift

@@ -146,11 +146,11 @@ class NCBrandColor: NSObject {
     }
 
     // Color
-    @objc public let customer: UIColor = UIColor(red: 0.0/255.0, green: 130.0/255.0, blue: 201.0/255.0, alpha: 1.0)    // BLU NC : #0082c9
+    @objc public let customer: UIColor = UIColor(red: 0.0/255.0, green: 130.0/255.0, blue: 201.0/255.0, alpha: 1.0)     // BLU NC : #0082c9
     @objc public var customerText: UIColor = .white
 
-    @objc public var brand: UIColor                                                                                 // don't touch me
-    @objc public var brandElement: UIColor                                                                                 // don't touch me
+    @objc public var brand: UIColor                                                                                     // don't touch me
+    @objc public var brandElement: UIColor                                                                              // don't touch me
     @objc public var brandText: UIColor                                                                                 // don't touch me
 
     @objc public let nextcloud: UIColor = UIColor(red: 0.0/255.0, green: 130.0/255.0, blue: 201.0/255.0, alpha: 1.0)

+ 4 - 10
iOSClient/Brand/NCBridgeSwift.h

@@ -21,28 +21,22 @@
 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
 
-//
-// App bridge swift
-//
-// change 
-// from   : Nextcloud-Swift.h
-// to     : brand-Swift.h
-//
 #if !defined(EXTENSION)
 #import "Nextcloud-Swift.h"
 #endif
 
-// Nextcloud Share
 #if defined(EXTENSION_SHARE)
 #import "Share-Swift.h"
 #endif
 
-// Nextcloud File Provider Extension
 #if defined(EXTENSION_FILE_PROVIDER_EXTENSION)
 #import "File_Provider_Extension-Swift.h"
 #endif
 
-// Nextcloud Notification Service Extension
 #if defined(EXTENSION_NOTIFICATION_SERVICE)
 #import "Notification_Service_Extension-Swift.h"
 #endif
+
+#if defined(EXTENSION_WIDGET)
+#import "Widget-Swift.h"
+#endif

+ 14 - 0
iOSClient/Brand/Widget.entitlements

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>com.apple.security.application-groups</key>
+	<array>
+		<string>group.it.twsweb.Crypto-Cloud</string>
+	</array>
+    <key>keychain-access-groups</key>
+    <array>
+        <string>$(AppIdentifierPrefix)it.twsweb.Crypto-Cloud</string>
+    </array>
+</dict>
+</plist>

+ 16 - 0
iOSClient/Brand/Widget.plist

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>NSExtension</key>
+	<dict>
+		<key>NSExtensionPointIdentifier</key>
+		<string>com.apple.widgetkit-extension</string>
+	</dict>
+    <key>NSAppTransportSecurity</key>
+    <dict>
+        <key>NSAllowsArbitraryLoads</key>
+        <true/>
+    </dict>
+</dict>
+</plist>

+ 9 - 9
iOSClient/Data/NCDataSource.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 
 class NCDataSource: NSObject {
 
@@ -33,8 +33,8 @@ class NCDataSource: NSObject {
     var groupByField: String = ""
 
     private var sectionsValue: [String] = []
-    private var providers: [NCCSearchProvider]?
-    private var searchResults: [NCCSearchResult]?
+    private var providers: [NKSearchProvider]?
+    private var searchResults: [NKSearchResult]?
     private var shares: [tableShare] = []
     private var localFiles: [tableLocalFile] = []
 
@@ -48,7 +48,7 @@ class NCDataSource: NSObject {
         super.init()
     }
 
-    init(metadatas: [tableMetadata], account: String, directory: tableDirectory? = nil, sort: String? = "none", ascending: Bool? = false, directoryOnTop: Bool? = true, favoriteOnTop: Bool? = true, filterLivePhoto: Bool? = true, groupByField: String = "name", providers: [NCCSearchProvider]? = nil, searchResults: [NCCSearchResult]? = nil) {
+    init(metadatas: [tableMetadata], account: String, directory: tableDirectory? = nil, sort: String? = "none", ascending: Bool? = false, directoryOnTop: Bool? = true, favoriteOnTop: Bool? = true, filterLivePhoto: Bool? = true, groupByField: String = "name", providers: [NKSearchProvider]? = nil, searchResults: [NKSearchResult]? = nil) {
         super.init()
 
         self.metadatas = metadatas
@@ -98,7 +98,7 @@ class NCDataSource: NSObject {
         createSections()
     }
 
-    func addSection(metadatas: [tableMetadata], searchResult: NCCSearchResult?) {
+    func addSection(metadatas: [tableMetadata], searchResult: NKSearchResult?) {
 
         self.metadatas.append(contentsOf: metadatas)
 
@@ -169,7 +169,7 @@ class NCDataSource: NSObject {
 
     internal func createMetadataForSection(sectionValue: String) {
 
-        var searchResult: NCCSearchResult?
+        var searchResult: NKSearchResult?
         if let providers = self.providers, !providers.isEmpty, let searchResults = self.searchResults {
             searchResult = searchResults.filter({ $0.id == sectionValue}).first
         }
@@ -201,7 +201,7 @@ class NCDataSource: NSObject {
     // MARK: -
 
     @discardableResult
-    func appendMetadatasToSection(_ metadatas: [tableMetadata], metadataForSection: NCMetadataForSection, lastSearchResult: NCCSearchResult) -> [IndexPath] {
+    func appendMetadatasToSection(_ metadatas: [tableMetadata], metadataForSection: NCMetadataForSection, lastSearchResult: NKSearchResult) -> [IndexPath] {
         
         guard let sectionIndex =  getSectionIndex(metadataForSection.sectionValue) else { return [] }
         var indexPaths: [IndexPath] = []
@@ -423,7 +423,7 @@ class NCMetadataForSection: NSObject {
     var metadatas: [tableMetadata]
     var shares: [tableShare]
     var localFiles: [tableLocalFile]
-    var lastSearchResult: NCCSearchResult?
+    var lastSearchResult: NKSearchResult?
     var unifiedSearchInProgress: Bool = false
 
     private var sort : String
@@ -445,7 +445,7 @@ class NCMetadataForSection: NSObject {
     public var metadataOffLine: [String] = []
     public var directories: [tableDirectory]?
 
-    init(sectionValue: String, metadatas: [tableMetadata], shares: [tableShare], localFiles: [tableLocalFile], lastSearchResult: NCCSearchResult?, sort: String, ascending: Bool, directoryOnTop: Bool, favoriteOnTop: Bool, filterLivePhoto: Bool) {
+    init(sectionValue: String, metadatas: [tableMetadata], shares: [tableShare], localFiles: [tableLocalFile], lastSearchResult: NKSearchResult?, sort: String, ascending: Bool, directoryOnTop: Bool, favoriteOnTop: Bool, filterLivePhoto: Bool) {
 
         self.sectionValue = sectionValue
         self.metadatas = metadatas

+ 2 - 2
iOSClient/Data/NCDatabase.swift

@@ -24,7 +24,7 @@
 
 import UIKit
 import RealmSwift
-import NCCommunication
+import NextcloudKit
 
 protocol DateCompareable {
     var dateKey: Date { get }
@@ -433,7 +433,7 @@ extension tableMetadata {
     var fileExtension: String { (fileNameView as NSString).pathExtension }
 
     var isPrintable: Bool {
-        classFile == NCCommunicationCommon.typeClassFile.image.rawValue || ["application/pdf", "com.adobe.pdf"].contains(contentType) || contentType.hasPrefix("text/")
+        classFile == NKCommon.typeClassFile.image.rawValue || ["application/pdf", "com.adobe.pdf"].contains(contentType) || contentType.hasPrefix("text/")
     }
 
     /// Returns false if the user is lokced out of the file. I.e. The file is locked but by somone else

+ 15 - 15
iOSClient/Data/NCManageDatabase+Account.swift

@@ -23,7 +23,7 @@
 
 import Foundation
 import RealmSwift
-import NCCommunication
+import NextcloudKit
 
 extension NCManageDatabase {
 
@@ -59,7 +59,7 @@ extension NCManageDatabase {
                 realm.add(addObject, update: .all)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -72,7 +72,7 @@ extension NCManageDatabase {
                 realm.add(account, update: .all)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -87,7 +87,7 @@ extension NCManageDatabase {
                 realm.delete(result)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -211,7 +211,7 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
             return nil
         }
 
@@ -230,7 +230,7 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -247,7 +247,7 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -266,7 +266,7 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -285,11 +285,11 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
-    @objc func setAccountUserProfile(_ userProfile: NCCommunicationUserProfile) -> tableAccount? {
+    @objc func setAccountUserProfile(_ userProfile: NKUserProfile) -> tableAccount? {
 
         let realm = try! Realm()
 
@@ -333,7 +333,7 @@ extension NCManageDatabase {
                 returnAccount = result
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
 
         return tableAccount.init(value: returnAccount)
@@ -367,7 +367,7 @@ extension NCManageDatabase {
                 returnAccount = result
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
 
         return tableAccount.init(value: returnAccount)
@@ -383,7 +383,7 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -403,7 +403,7 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -423,7 +423,7 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 }

+ 6 - 6
iOSClient/Data/NCManageDatabase+Activity.swift

@@ -23,12 +23,12 @@
 
 import Foundation
 import RealmSwift
-import NCCommunication
+import NextcloudKit
 import SwiftyJSON
 
 extension NCManageDatabase {
     
-    @objc func addActivity(_ activities: [NCCommunicationActivity], account: String) {
+    @objc func addActivity(_ activities: [NKActivity], account: String) {
 
         let realm = try! Realm()
 
@@ -114,7 +114,7 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -186,7 +186,7 @@ extension NCManageDatabase {
                 realm.add(newRecentActivity, update: .all)
             }
         } catch {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -199,7 +199,7 @@ extension NCManageDatabase {
     // MARK: -
     // MARK: Table Comments
 
-    @objc func addComments(_ comments: [NCCommunicationComments], account: String, objectId: String) {
+    @objc func addComments(_ comments: [NKComments], account: String, objectId: String) {
 
         let realm = try! Realm()
 
@@ -230,7 +230,7 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 

+ 47 - 38
iOSClient/Data/NCManageDatabase+Metadata.swift

@@ -23,7 +23,7 @@
 
 import Foundation
 import RealmSwift
-import NCCommunication
+import NextcloudKit
 
 extension NCManageDatabase {
 
@@ -31,7 +31,7 @@ extension NCManageDatabase {
         return tableMetadata.init(value: metadata)
     }
 
-    @objc func convertNCFileToMetadata(_ file: NCCommunicationFile, isEncrypted: Bool, account: String) -> tableMetadata {
+    @objc func convertNCFileToMetadata(_ file: NKFile, isEncrypted: Bool, account: String) -> tableMetadata {
 
         let metadata = tableMetadata()
 
@@ -89,8 +89,8 @@ extension NCManageDatabase {
         metadata.size = file.size
         metadata.classFile = file.classFile
         //FIXME: iOS 12.0,* don't detect UTI text/markdown, text/x-markdown
-        if (metadata.contentType == "text/markdown" || metadata.contentType == "text/x-markdown") && metadata.classFile == NCCommunicationCommon.typeClassFile.unknow.rawValue {
-            metadata.classFile = NCCommunicationCommon.typeClassFile.document.rawValue
+        if (metadata.contentType == "text/markdown" || metadata.contentType == "text/x-markdown") && metadata.classFile == NKCommon.typeClassFile.unknow.rawValue {
+            metadata.classFile = NKCommon.typeClassFile.document.rawValue
         }
         if let date = file.uploadDate {
             metadata.uploadDate = date
@@ -105,7 +105,7 @@ extension NCManageDatabase {
         if isEncrypted || metadata.e2eEncrypted {
             if let tableE2eEncryption = NCManageDatabase.shared.getE2eEncryption(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileNameIdentifier == %@", account, file.serverUrl, file.fileName)) {
                 metadata.fileNameView = tableE2eEncryption.fileName
-                let results = NCCommunicationCommon.shared.getInternalType(fileName: metadata.fileNameView, mimeType: file.contentType, directory: file.directory)
+                let results = NKCommon.shared.getInternalType(fileName: metadata.fileNameView, mimeType: file.contentType, directory: file.directory)
                 metadata.contentType = results.mimeType
                 metadata.iconName = results.iconName
                 metadata.classFile = results.classFile
@@ -113,12 +113,12 @@ extension NCManageDatabase {
         }
 
         // Live Photo "DETECT"
-        if !metadata.directory && !metadata.livePhoto && (metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue) {
+        if !metadata.directory && !metadata.livePhoto && (metadata.classFile == NKCommon.typeClassFile.video.rawValue || metadata.classFile == NKCommon.typeClassFile.image.rawValue) {
             var classFile = metadata.classFile
-            if classFile == NCCommunicationCommon.typeClassFile.image.rawValue {
-                classFile = NCCommunicationCommon.typeClassFile.video.rawValue
+            if classFile == NKCommon.typeClassFile.image.rawValue {
+                classFile = NKCommon.typeClassFile.video.rawValue
             } else {
-                classFile = NCCommunicationCommon.typeClassFile.image.rawValue
+                classFile = NKCommon.typeClassFile.image.rawValue
             }
             if getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileNameWithoutExt == %@ AND ocId != %@ AND classFile == %@", metadata.account, metadata.serverUrl, metadata.fileNameWithoutExt, metadata.ocId, classFile)) != nil {
                 metadata.livePhoto = true
@@ -128,7 +128,7 @@ extension NCManageDatabase {
         return metadata
     }
 
-    @objc func convertNCCommunicationFilesToMetadatas(_ files: [NCCommunicationFile], useMetadataFolder: Bool, account: String, completion: @escaping (_ metadataFolder: tableMetadata, _ metadatasFolder: [tableMetadata], _ metadatas: [tableMetadata]) -> Void) {
+    @objc func convertNKFilesToMetadatas(_ files: [NKFile], useMetadataFolder: Bool, account: String, completion: @escaping (_ metadataFolder: tableMetadata, _ metadatasFolder: [tableMetadata], _ metadatas: [tableMetadata]) -> Void) {
 
         var counter: Int = 0
         var isEncrypted: Bool = false
@@ -172,18 +172,18 @@ extension NCManageDatabase {
             if let iconName = iconName {
                 metadata.iconName = iconName
             } else {
-                metadata.iconName = NCCommunicationCommon.typeIconFile.url.rawValue
+                metadata.iconName = NKCommon.typeIconFile.url.rawValue
             }
-            metadata.classFile = NCCommunicationCommon.typeClassFile.url.rawValue
+            metadata.classFile = NKCommon.typeClassFile.url.rawValue
         } else {
-            let (mimeType, classFile, iconName, _, _, _) = NCCommunicationCommon.shared.getInternalType(fileName: fileName, mimeType: contentType, directory: false)
+            let (mimeType, classFile, iconName, _, _, _) = NKCommon.shared.getInternalType(fileName: fileName, mimeType: contentType, directory: false)
             metadata.contentType = mimeType
             metadata.iconName = iconName
             metadata.classFile = classFile
             //FIXME: iOS 12.0,* don't detect UTI text/markdown, text/x-markdown
-            if classFile == NCCommunicationCommon.typeClassFile.unknow.rawValue && (mimeType == "text/x-markdown" || mimeType == "text/markdown") {
-                metadata.iconName = NCCommunicationCommon.typeIconFile.txt.rawValue
-                metadata.classFile = NCCommunicationCommon.typeClassFile.document.rawValue
+            if classFile == NKCommon.typeClassFile.unknow.rawValue && (mimeType == "text/x-markdown" || mimeType == "text/markdown") {
+                metadata.iconName = NKCommon.typeIconFile.txt.rawValue
+                metadata.classFile = NKCommon.typeClassFile.document.rawValue
             }
         }
         if let iconUrl = iconUrl {
@@ -232,7 +232,7 @@ extension NCManageDatabase {
                 realm.add(metadata, update: .all)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
             return nil
         }
         return returnMetadata
@@ -249,7 +249,7 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -263,7 +263,7 @@ extension NCManageDatabase {
                 realm.delete(results)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -278,7 +278,7 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -294,7 +294,7 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -305,7 +305,7 @@ extension NCManageDatabase {
         do {
             try realm.safeWrite {
                 if let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first {
-                    let resultsType = NCCommunicationCommon.shared.getInternalType(fileName: fileNameTo, mimeType: "", directory: result.directory)
+                    let resultsType = NKCommon.shared.getInternalType(fileName: fileNameTo, mimeType: "", directory: result.directory)
                     result.fileName = fileNameTo
                     result.fileNameView = fileNameTo
                     if result.directory {
@@ -321,7 +321,7 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -390,7 +390,7 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
 
         for ocId in ocIdsUdate {
@@ -436,7 +436,7 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -452,7 +452,7 @@ extension NCManageDatabase {
                 result?.status = status
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
 
         if let result = result {
@@ -474,7 +474,7 @@ extension NCManageDatabase {
                 result?.etagResource = etagResource
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -488,7 +488,7 @@ extension NCManageDatabase {
                 result?.favorite = favorite
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -507,7 +507,7 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -521,7 +521,7 @@ extension NCManageDatabase {
                 result?.e2eEncrypted = encrypted
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -535,7 +535,7 @@ extension NCManageDatabase {
                 result?.fileNameView = newFileNameView
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -579,7 +579,7 @@ extension NCManageDatabase {
 
         // For Live Photo
         var fileNameImages: [String] = []
-        let filtered = results.filter { $0.classFile.contains(NCCommunicationCommon.typeClassFile.image.rawValue) }
+        let filtered = results.filter { $0.classFile.contains(NKCommon.typeClassFile.image.rawValue) }
         filtered.forEach { print($0)
             let fileName = ($0.fileNameView as NSString).deletingPathExtension
             fileNameImages.append(fileName)
@@ -713,7 +713,7 @@ extension NCManageDatabase {
                 realm.delete(results)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -729,7 +729,7 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -761,7 +761,7 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -776,10 +776,10 @@ extension NCManageDatabase {
             return nil
         }
 
-        if classFile == NCCommunicationCommon.typeClassFile.image.rawValue {
-            classFile = NCCommunicationCommon.typeClassFile.video.rawValue
+        if classFile == NKCommon.typeClassFile.image.rawValue {
+            classFile = NKCommon.typeClassFile.video.rawValue
         } else {
-            classFile = NCCommunicationCommon.typeClassFile.image.rawValue
+            classFile = NKCommon.typeClassFile.image.rawValue
         }
 
         guard let result = realm.objects(tableMetadata.self).filter(NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileNameWithoutExt == %@ AND ocId != %@ AND classFile == %@", metadata.account, metadata.serverUrl, metadata.fileNameWithoutExt, metadata.ocId, classFile)).first else {
@@ -860,4 +860,13 @@ extension NCManageDatabase {
         }
         return(Array(results.map { tableMetadata.init(value: $0) }), Array(metadatas.map { tableMetadata.init(value: $0) }))
     }
+
+    func getNumMetadatasInUpload() -> Int {
+
+        let realm = try! Realm()
+
+        let num = realm.objects(tableMetadata.self).filter(NSPredicate(format: "status == %i || status == %i",  NCGlobal.shared.metadataStatusInUpload, NCGlobal.shared.metadataStatusUploading)).count
+
+        return num
+    }
 }

+ 4 - 4
iOSClient/Data/NCManageDatabase+Video.swift

@@ -23,7 +23,7 @@
 
 import Foundation
 import RealmSwift
-import NCCommunication
+import NextcloudKit
 
 extension NCManageDatabase {
 
@@ -60,7 +60,7 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -92,7 +92,7 @@ extension NCManageDatabase {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -146,7 +146,7 @@ extension NCManageDatabase {
                 realm.delete(result)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 }

+ 57 - 55
iOSClient/Data/NCManageDatabase.swift

@@ -24,7 +24,7 @@
 
 import UIKit
 import RealmSwift
-import NCCommunication
+import NextcloudKit
 import SwiftyJSON
 import CoreMedia
 import Photos
@@ -46,9 +46,9 @@ class NCManageDatabase: NSObject {
 
         if let databaseFilePath = databaseFileUrlPath?.path {
             if FileManager.default.fileExists(atPath: databaseFilePath) {
-                NCCommunicationCommon.shared.writeLog("DATABASE FOUND in " + databaseFilePath)
+                NKCommon.shared.writeLog("DATABASE FOUND in " + databaseFilePath)
             } else {
-                NCCommunicationCommon.shared.writeLog("DATABASE NOT FOUND in " + databaseFilePath)
+                NKCommon.shared.writeLog("DATABASE NOT FOUND in " + databaseFilePath)
             }
         }
 
@@ -70,7 +70,7 @@ class NCManageDatabase: NSObject {
             let config = Realm.Configuration(
                 fileURL: dirGroup?.appendingPathComponent(NCGlobal.shared.appDatabaseNextcloud + "/" + NCGlobal.shared.databaseDefault),
                 schemaVersion: NCGlobal.shared.databaseSchemaVersion,
-                objectTypes: [tableMetadata.self, tableLocalFile.self, tableDirectory.self, tableTag.self, tableAccount.self, tableCapabilities.self, tableE2eEncryption.self, tableE2eEncryptionLock.self, tableShare.self, tableChunk.self, tableAvatar.self]
+                objectTypes: [tableMetadata.self, tableLocalFile.self, tableDirectory.self, tableTag.self, tableAccount.self, tableCapabilities.self, tablePhotoLibrary.self, tableE2eEncryption.self, tableE2eEncryptionLock.self, tableShare.self, tableChunk.self, tableAvatar.self]
             )
 
             Realm.Configuration.defaultConfiguration = config
@@ -188,9 +188,10 @@ class NCManageDatabase: NSObject {
                 if let databaseFileUrlPath = databaseFileUrlPath {
                     do {
                         #if !EXTENSION
-                        NCContentPresenter.shared.messageNotification("_error_", description: "_database_corrupt_", delay: NCGlobal.shared.dismissAfterSecondLong, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorInternalError, priority: .max)
+                        let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_database_corrupt_")
+                        NCContentPresenter.shared.showError(error: error, priority: .max)
                         #endif
-                        NCCommunicationCommon.shared.writeLog("DATABASE CORRUPT: removed")
+                        NKCommon.shared.writeLog("DATABASE CORRUPT: removed")
                         try FileManager.default.removeItem(at: databaseFileUrlPath)
                     } catch {}
                 }
@@ -211,9 +212,10 @@ class NCManageDatabase: NSObject {
             if let databaseFileUrlPath = databaseFileUrlPath {
                 do {
                     #if !EXTENSION
-                    NCContentPresenter.shared.messageNotification("_error_", description: "_database_corrupt_", delay: NCGlobal.shared.dismissAfterSecondLong, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorInternalError, priority: .max)
+                    let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_database_corrupt_")
+                    NCContentPresenter.shared.showError(error: error, priority: .max)
                     #endif
-                    NCCommunicationCommon.shared.writeLog("DATABASE CORRUPT: removed")
+                    NKCommon.shared.writeLog("DATABASE CORRUPT: removed")
                     try FileManager.default.removeItem(at: databaseFileUrlPath)
                 } catch {}
             }
@@ -243,7 +245,7 @@ class NCManageDatabase: NSObject {
                 realm.delete(results)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -292,7 +294,7 @@ class NCManageDatabase: NSObject {
             do {
                 try FileManager.default.removeItem(at: URL)
             } catch let error {
-                NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+                NKCommon.shared.writeLog("Could not write to database: \(error)")
             }
         }
     }
@@ -337,7 +339,7 @@ class NCManageDatabase: NSObject {
                 realm.add(addObject, update: .all)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -366,7 +368,7 @@ class NCManageDatabase: NSObject {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -389,7 +391,7 @@ class NCManageDatabase: NSObject {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
 
         return image
@@ -428,7 +430,7 @@ class NCManageDatabase: NSObject {
                 realm.add(addObject, update: .all)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -570,7 +572,7 @@ class NCManageDatabase: NSObject {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -596,7 +598,7 @@ class NCManageDatabase: NSObject {
                 realm.delete(result)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -611,14 +613,14 @@ class NCManageDatabase: NSObject {
                 realm.delete(result)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
     // MARK: -
     // MARK: Table Direct Editing
 
-    @objc func addDirectEditing(account: String, editors: [NCCommunicationEditorDetailsEditors], creators: [NCCommunicationEditorDetailsCreators]) {
+    @objc func addDirectEditing(account: String, editors: [NKEditorDetailsEditors], creators: [NKEditorDetailsCreators]) {
 
         let realm = try! Realm()
 
@@ -669,7 +671,7 @@ class NCManageDatabase: NSObject {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -747,7 +749,7 @@ class NCManageDatabase: NSObject {
                 realm.add(addObject, update: .all)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -770,7 +772,7 @@ class NCManageDatabase: NSObject {
                 realm.delete(results)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -809,7 +811,7 @@ class NCManageDatabase: NSObject {
                 realm.add(directory, update: .all)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -847,7 +849,7 @@ class NCManageDatabase: NSObject {
                 result?.serverUrl = serverUrl
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -861,7 +863,7 @@ class NCManageDatabase: NSObject {
                 result?.offline = offline
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -877,7 +879,7 @@ class NCManageDatabase: NSObject {
                 result?.richWorkspace = richWorkspace
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
 
         if let result = result {
@@ -899,7 +901,7 @@ class NCManageDatabase: NSObject {
                 result?.colorFolder = colorFolder
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
 
         if let result = result {
@@ -921,7 +923,7 @@ class NCManageDatabase: NSObject {
                 realm.add(e2e, update: .all)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -936,7 +938,7 @@ class NCManageDatabase: NSObject {
                 realm.delete(results)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -997,7 +999,7 @@ class NCManageDatabase: NSObject {
         do {
             try realm.commitWrite()
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -1031,7 +1033,7 @@ class NCManageDatabase: NSObject {
                 realm.add(addObject, update: .all)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -1046,14 +1048,14 @@ class NCManageDatabase: NSObject {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
     // MARK: -
     // MARK: Table External Sites
 
-    @objc func addExternalSites(_ externalSite: NCCommunicationExternalSite, account: String) {
+    @objc func addExternalSites(_ externalSite: NKExternalSite, account: String) {
 
         let realm = try! Realm()
 
@@ -1072,7 +1074,7 @@ class NCManageDatabase: NSObject {
                 realm.add(addObject)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -1086,7 +1088,7 @@ class NCManageDatabase: NSObject {
                 realm.delete(results)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -1135,7 +1137,7 @@ class NCManageDatabase: NSObject {
         do {
             try realm.commitWrite()
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -1174,7 +1176,7 @@ class NCManageDatabase: NSObject {
                 realm.add(addObject, update: .all)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -1198,7 +1200,7 @@ class NCManageDatabase: NSObject {
                 realm.add(addObject, update: .all)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -1212,7 +1214,7 @@ class NCManageDatabase: NSObject {
                 realm.delete(results)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -1231,7 +1233,7 @@ class NCManageDatabase: NSObject {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -1251,7 +1253,7 @@ class NCManageDatabase: NSObject {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -1292,7 +1294,7 @@ class NCManageDatabase: NSObject {
                 result?.offline = offline
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -1334,7 +1336,7 @@ class NCManageDatabase: NSObject {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
             return false
         }
 
@@ -1369,7 +1371,7 @@ class NCManageDatabase: NSObject {
     // MARK: -
     // MARK: Table Share
 
-    @objc func addShare(urlBase: String, account: String, shares: [NCCommunicationShare]) {
+    @objc func addShare(urlBase: String, account: String, shares: [NKShare]) {
 
         let realm = try! Realm()
         realm.beginWrite()
@@ -1427,7 +1429,7 @@ class NCManageDatabase: NSObject {
         do {
             try realm.commitWrite()
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -1504,7 +1506,7 @@ class NCManageDatabase: NSObject {
         do {
             try realm.commitWrite()
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -1520,7 +1522,7 @@ class NCManageDatabase: NSObject {
         do {
             try realm.commitWrite()
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -1544,7 +1546,7 @@ class NCManageDatabase: NSObject {
                 realm.add(addObject, update: .all)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -1560,7 +1562,7 @@ class NCManageDatabase: NSObject {
         do {
             try realm.commitWrite()
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -1611,14 +1613,14 @@ class NCManageDatabase: NSObject {
                 realm.add(addObject, update: .all)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
     // MARK: -
     // MARK: Table Trash
 
-    @objc func addTrash(account: String, items: [NCCommunicationTrash]) {
+    @objc func addTrash(account: String, items: [NKTrash]) {
 
         let realm = try! Realm()
 
@@ -1646,7 +1648,7 @@ class NCManageDatabase: NSObject {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -1668,7 +1670,7 @@ class NCManageDatabase: NSObject {
                 realm.delete(result)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -1690,7 +1692,7 @@ class NCManageDatabase: NSObject {
                 realm.delete(result)
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 
@@ -1719,7 +1721,7 @@ class NCManageDatabase: NSObject {
     // MARK: -
     // MARK: Table UserStatus
 
-    @objc func addUserStatus(_ userStatuses: [NCCommunicationUserStatus], account: String, predefined: Bool) {
+    @objc func addUserStatus(_ userStatuses: [NKUserStatus], account: String, predefined: Bool) {
 
         let realm = try! Realm()
 
@@ -1748,7 +1750,7 @@ class NCManageDatabase: NSObject {
                 }
             }
         } catch let error {
-            NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
         }
     }
 }

+ 7 - 6
iOSClient/Diagnostics/NCCapabilitiesViewController.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 
 class NCCapabilitiesViewController: UIViewController, UIDocumentInteractionControllerDelegate {
 
@@ -180,7 +180,8 @@ class NCCapabilitiesViewController: UIViewController, UIDocumentInteractionContr
             capabilitiesText = text
             updateCapabilities()
         } else {
-            NCContentPresenter.shared.messageNotification("_error_", description: "_no_capabilities_found_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorInternalError, priority: .max)
+            let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_no_capabilities_found_")
+            NCContentPresenter.shared.showError(error: error, priority: .max)
 
             DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
                 self.dismiss(animated: true, completion: nil)
@@ -193,15 +194,15 @@ class NCCapabilitiesViewController: UIViewController, UIDocumentInteractionContr
 
     @objc func updateCapabilities() {
 
-        NCCommunication.shared.getCapabilities { account, data, errorCode, _ in
-            if errorCode == 0 && data != nil {
+        NextcloudKit.shared.getCapabilities { account, data, error in
+            if error == .success && data != nil {
                 NCManageDatabase.shared.addCapabilitiesJSon(data!, account: account)
 
                 // EDITORS
                 let serverVersionMajor = NCManageDatabase.shared.getCapabilitiesServerInt(account: account, elements: NCElementsJSON.shared.capabilitiesVersionMajor)
                 if serverVersionMajor >= NCGlobal.shared.nextcloudVersion18 {
-                    NCCommunication.shared.NCTextObtainEditorDetails { account, editors, creators, errorCode, _ in
-                        if errorCode == 0 && account == self.appDelegate.account {
+                    NextcloudKit.shared.NCTextObtainEditorDetails { account, editors, creators, error in
+                        if error == .success && account == self.appDelegate.account {
                             NCManageDatabase.shared.addDirectEditing(account: account, editors: editors, creators: creators)
                             self.readCapabilities()
                         }

+ 7 - 0
iOSClient/Extensions/String+Extensions.swift

@@ -69,6 +69,13 @@ extension String {
 
         return digestData.map { String(format: "%02hhx", $0) }.joined()
     }
+
+    var urlEncoded: String? {
+        // +        for historical reason, most web servers treat + as a replacement of whitespace
+        // ?, &     mark query pararmeter which should not be part of a url string, but added seperately
+        let urlAllowedCharSet = CharacterSet.urlQueryAllowed.subtracting(["+", "?", "&"])
+        return addingPercentEncoding(withAllowedCharacters: urlAllowedCharSet)
+    }
 }
 
 extension StringProtocol {

+ 6 - 5
iOSClient/Extensions/UIAlertController+Extension.swift

@@ -22,6 +22,7 @@
 //
 
 import UIKit
+import NextcloudKit
 
 extension UIAlertController {
     /// Creates a alert controller with a textfield, asking to create a new folder
@@ -30,16 +31,16 @@ extension UIAlertController {
     ///   - urlBase: UrlBase object
     ///   - completion: If not` nil` it overrides the default behavior which shows an error using `NCContentPresenter`
     /// - Returns: The presentable alert controller
-    static func createFolder(serverUrl: String, urlBase: NCUserBaseUrl, completion: ((_ errorCode: Int, _ errorDescription: String) -> Void)? = nil) -> UIAlertController {
+    static func createFolder(serverUrl: String, urlBase: NCUserBaseUrl, completion: ((_ error: NKError) -> Void)? = nil) -> UIAlertController {
         let alertController = UIAlertController(title: NSLocalizedString("_create_folder_", comment: ""), message: nil, preferredStyle: .alert)
 
         let okAction = UIAlertAction(title: NSLocalizedString("_save_", comment: ""), style: .default, handler: { _ in
             guard let fileNameFolder = alertController.textFields?.first?.text else { return }
-            NCNetworking.shared.createFolder(fileName: fileNameFolder, serverUrl: serverUrl, account: urlBase.account, urlBase: urlBase.urlBase, overwrite: false) { errorCode, errorDescription in
+            NCNetworking.shared.createFolder(fileName: fileNameFolder, serverUrl: serverUrl, account: urlBase.account, urlBase: urlBase.urlBase, overwrite: false) { error in
                 if let completion = completion {
-                    completion(errorCode, errorDescription)
-                } else if errorCode != 0 {
-                    NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                    completion(error)
+                } else if error != .success {
+                    NCContentPresenter.shared.showError(error: error)
                 } // else: successful, no action
             }
         })

+ 2 - 2
iOSClient/Extensions/UIControl+Extensions.swift

@@ -27,7 +27,7 @@ import Foundation
 public class ActionClosure {
 
     public let selector: Selector
-    private let closure : (_ sendersender: Any?) -> Void
+    private let closure: (_ sendersender: Any?) -> Void
 
     init(_ attachObj: AnyObject, closure: @escaping (_ sender: Any?) -> Void) {
         self.closure = closure
@@ -41,7 +41,7 @@ public class ActionClosure {
 }
 
 public extension UIControl {
-    func action(for event: UIControl.Event, _ closure : @escaping (_ object: Any?) -> Void) {
+    func action(for event: UIControl.Event, _ closure: @escaping (_ object: Any?) -> Void) {
         let actionClosure = ActionClosure(self, closure: closure)
         self.addTarget(actionClosure, action: actionClosure.selector, for: event)
     }

+ 6 - 6
iOSClient/Favorites/NCFavorite.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 
 class NCFavorite: NCCollectionViewCommon {
 
@@ -82,9 +82,9 @@ class NCFavorite: NCCollectionViewCommon {
 
         if serverUrl.isEmpty {
 
-            NCNetworking.shared.listingFavoritescompletion(selector: NCGlobal.shared.selectorListingFavorite) { _, _, errorCode, errorDescription in
-                if errorCode != 0 {
-                    NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+            NCNetworking.shared.listingFavoritescompletion(selector: NCGlobal.shared.selectorListingFavorite) { _, _, error in
+                if error != .success {
+                    NCContentPresenter.shared.showError(error: error)
                 }
 
                 DispatchQueue.main.async {
@@ -96,8 +96,8 @@ class NCFavorite: NCCollectionViewCommon {
 
         } else {
 
-            networkReadFolder(forced: forced) { tableDirectory, metadatas, metadatasUpdate, metadatasDelete, errorCode, _ in
-                if errorCode == 0 {
+            networkReadFolder(forced: forced) { tableDirectory, metadatas, metadatasUpdate, metadatasDelete, error in
+                if error == .success {
                     for metadata in metadatas ?? [] {
                         if !metadata.directory {
                             if NCManageDatabase.shared.isDownloadMetadata(metadata, download: false) {

+ 3 - 3
iOSClient/Files/NCFiles.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 
 class NCFiles: NCCollectionViewCommon {
 
@@ -135,8 +135,8 @@ class NCFiles: NCCollectionViewCommon {
         isReloadDataSourceNetworkInProgress = true
         collectionView?.reloadData()
 
-        networkReadFolder(forced: forced) { tableDirectory, metadatas, metadatasUpdate, metadatasDelete, errorCode, _ in
-            if errorCode == 0 {
+        networkReadFolder(forced: forced) { tableDirectory, metadatas, metadatasUpdate, metadatasDelete, error in
+            if error == .success {
                 for metadata in metadatas ?? [] {
                     if !metadata.directory, NCManageDatabase.shared.isDownloadMetadata(metadata, download: false) {
                         NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorDownloadFile)

+ 12 - 8
iOSClient/Login/NCAppConfigView.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 
 class NCAppConfigView: UIViewController {
 
@@ -63,21 +63,24 @@ class NCAppConfigView: UIViewController {
         appDelegate.timerErrorNetworking?.invalidate()
 
         guard let serverUrl = self.serverUrl else {
-            NCContentPresenter.shared.messageNotification("_error_", description: "User Default, serverUrl not found", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError)
+            let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "User Default, serverUrl not found")
+            NCContentPresenter.shared.showError(error: error)
             return
         }
         guard let username = self.username else {
-            NCContentPresenter.shared.messageNotification("_error_", description: "User Default, username not found", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError)
+            let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "User Default, username not found")
+            NCContentPresenter.shared.showError(error: error)
             return
         }
         guard let password = self.password else {
-            NCContentPresenter.shared.messageNotification("_error_", description: "User Default, password not found", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError)
+            let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "User Default, password not found")
+            NCContentPresenter.shared.showError(error: error)
             return
         }
 
-        NCCommunication.shared.getAppPassword(serverUrl: serverUrl, username: username, password: password, userAgent: nil) { token, errorCode, errorDescription in
+        NextcloudKit.shared.getAppPassword(serverUrl: serverUrl, username: username, password: password, userAgent: nil) { token, error in
             DispatchQueue.main.async {
-                if errorCode == 0 && token != nil {
+                if error == .success && token != nil {
                     let account: String = "\(username) \(serverUrl)"
 
                     // NO account found, clear
@@ -88,7 +91,8 @@ class NCAppConfigView: UIViewController {
                     NCManageDatabase.shared.addAccount(account, urlBase: serverUrl, user: username, password: token!)
 
                     guard let tableAccount = NCManageDatabase.shared.setAccountActive(account) else {
-                        NCContentPresenter.shared.messageNotification("_error_", description: "setAccountActive error", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError)
+                        let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "setAccountActive error")
+                        NCContentPresenter.shared.showError(error: error)
                         self.dismiss(animated: true, completion: nil)
                         return
                     }
@@ -98,7 +102,7 @@ class NCAppConfigView: UIViewController {
 
                     self.dismiss(animated: true) {}
                 } else {
-                    NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                    NCContentPresenter.shared.showError(error: error)
                 }
             }
         }

+ 13 - 13
iOSClient/Login/NCLogin.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 
 class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
 
@@ -215,20 +215,20 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
 
         loginButton.isEnabled = false
 
-        NCCommunication.shared.getServerStatus(serverUrl: url) { _, _, versionMajor, _, _, _, errorCode, errorDescription in
+        NextcloudKit.shared.getServerStatus(serverUrl: url) { _, _, versionMajor, _, _, _, error in
 
-            if errorCode == 0 {
+            if error == .success {
 
                 if let host = URL(string: url)?.host {
                     NCNetworking.shared.writeCertificate(host: host)
                 }
 
-                NCCommunication.shared.getLoginFlowV2(serverUrl: url) { token, endpoint, login, errorCode, _ in
+                NextcloudKit.shared.getLoginFlowV2(serverUrl: url) { token, endpoint, login, error in
 
                     self.loginButton.isEnabled = true
 
                     // Login Flow V2
-                    if errorCode == 0 && NCBrandOptions.shared.use_loginflowv2 && token != nil && endpoint != nil && login != nil {
+                    if error == .success && NCBrandOptions.shared.use_loginflowv2 && token != nil && endpoint != nil && login != nil {
 
                         if let loginWeb = UIStoryboard(name: "NCLogin", bundle: nil).instantiateViewController(withIdentifier: "NCLoginWeb") as? NCLoginWeb {
 
@@ -266,7 +266,7 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
 
                 self.loginButton.isEnabled = true
 
-                if errorCode == NSURLErrorServerCertificateUntrusted {
+                if error.errorCode == NSURLErrorServerCertificateUntrusted {
 
                     let alertController = UIAlertController(title: NSLocalizedString("_ssl_certificate_untrusted_", comment: ""), message: NSLocalizedString("_connect_server_anyway_", comment: ""), preferredStyle: .alert)
 
@@ -292,7 +292,7 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
 
                 } else {
 
-                    let alertController = UIAlertController(title: NSLocalizedString("_connection_error_", comment: ""), message: errorDescription, preferredStyle: .alert)
+                    let alertController = UIAlertController(title: NSLocalizedString("_connection_error_", comment: ""), message: error.errorDescription, preferredStyle: .alert)
 
                     alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in }))
 
@@ -324,18 +324,18 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
 
                 loginButton.isEnabled = false
 
-                NCCommunication.shared.checkServer(serverUrl: serverUrl) { errorCode, errorDescription in
+                NextcloudKit.shared.checkServer(serverUrl: serverUrl) { error in
 
                     self.loginButton.isEnabled = true
-                    self.standardLogin(url: urlBase, user: user, password: password, errorCode: errorCode, errorDescription: errorDescription)
+                    self.standardLogin(url: urlBase, user: user, password: password, error: error)
                 }
             }
         }
     }
 
-    func standardLogin(url: String, user: String, password: String, errorCode: Int, errorDescription: String) {
+    func standardLogin(url: String, user: String, password: String, error: NKError) {
 
-        if errorCode == 0 {
+        if error == .success {
 
             if let host = URL(string: url)?.host {
                 NCNetworking.shared.writeCertificate(host: host)
@@ -378,7 +378,7 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
                 }
             }
 
-        } else if errorCode == NSURLErrorServerCertificateUntrusted {
+        } else if error.errorCode == NSURLErrorServerCertificateUntrusted {
 
             let alertController = UIAlertController(title: NSLocalizedString("_ssl_certificate_untrusted_", comment: ""), message: NSLocalizedString("_connect_server_anyway_", comment: ""), preferredStyle: .alert)
 
@@ -400,7 +400,7 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
 
         } else {
 
-            let message = NSLocalizedString("_not_possible_connect_to_server_", comment: "") + ".\n" + errorDescription
+            let message = NSLocalizedString("_not_possible_connect_to_server_", comment: "") + ".\n" + error.errorDescription
             let alertController = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: message, preferredStyle: .alert)
 
             alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in }))

+ 5 - 4
iOSClient/Login/NCLoginWeb.swift

@@ -23,7 +23,7 @@
 
 import UIKit
 import WebKit
-import NCCommunication
+import NextcloudKit
 import FloatingPanel
 
 class NCLoginWeb: UIViewController {
@@ -93,7 +93,8 @@ class NCLoginWeb: UIViewController {
         if let url = URL(string: urlBase) {
             loadWebPage(webView: webView!, url: url)
         } else {
-            NCContentPresenter.shared.messageNotification("_error_", description: "_login_url_error_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError, priority: .max)
+            let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_login_url_error_")
+            NCContentPresenter.shared.showError(error: error, priority: .max)
         }
     }
 
@@ -272,8 +273,8 @@ extension NCLoginWeb: WKNavigationDelegate {
 
         if loginFlowV2Available {
             DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
-                NCCommunication.shared.getLoginFlowV2Poll(token: self.loginFlowV2Token, endpoint: self.loginFlowV2Endpoint) { server, loginName, appPassword, errorCode, _ in
-                    if errorCode == 0 && server != nil && loginName != nil && appPassword != nil {
+                NextcloudKit.shared.getLoginFlowV2Poll(token: self.loginFlowV2Token, endpoint: self.loginFlowV2Endpoint) { server, loginName, appPassword, error in
+                    if error == .success && server != nil && loginName != nil && appPassword != nil {
                         self.createAccount(server: server!, username: loginName!, password: appPassword!)
                     }
                 }

+ 43 - 57
iOSClient/Main/Collection Common/NCCollectionViewCommon.swift

@@ -23,7 +23,7 @@
 
 import UIKit
 import Realm
-import NCCommunication
+import NextcloudKit
 import EasyTipView
 
 class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UISearchResultsUpdating, UISearchControllerDelegate, UISearchBarDelegate, NCListCellDelegate, NCGridCellDelegate, NCSectionHeaderMenuDelegate, NCSectionFooterDelegate, UIAdaptivePresentationControllerDelegate, NCEmptyDataSetDelegate, UIContextMenuInteractionDelegate, NCAccountRequestDelegate, NCSelectableNavigationView {
@@ -52,8 +52,8 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
     private var autoUploadDirectory = ""
 
     internal var groupByField = "name"
-    internal var providers: [NCCSearchProvider]?
-    internal var searchResults: [NCCSearchResult]?
+    internal var providers: [NKSearchProvider]?
+    internal var searchResults: [NKSearchResult]?
 
     internal var listLayout: NCListLayout!
     internal var gridLayout: NCGridLayout!
@@ -546,7 +546,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
         else { return }
 
         guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { return }
-        if metadata.livePhoto && metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue { return }
+        if metadata.livePhoto && metadata.classFile == NKCommon.typeClassFile.video.rawValue { return }
         let (indexPath, sameSections) = dataSource.reloadMetadata(ocId: metadata.ocId, ocIdTemp: ocIdTemp)
         if let indexPath = indexPath {
             if sameSections && (indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section)) {
@@ -1012,8 +1012,8 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
 
         let serverVersionMajor = NCManageDatabase.shared.getCapabilitiesServerInt(account: appDelegate.account, elements: NCElementsJSON.shared.capabilitiesVersionMajor)
         if serverVersionMajor >= NCGlobal.shared.nextcloudVersion20 {
-            NCNetworking.shared.unifiedSearchFiles(urlBase: appDelegate, literal: literalSearch) { allProviders in
-                self.providers = allProviders
+            NCNetworking.shared.unifiedSearchFiles(userBaseUrl: appDelegate, literal: literalSearch) { account, searchProviders in
+                self.providers = searchProviders
                 self.searchResults = []
                 self.dataSource = NCDataSource(
                     metadatas: [] ,
@@ -1025,21 +1025,21 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
                     filterLivePhoto: true,
                     providers: self.providers,
                     searchResults: self.searchResults)
-            } update: { id, searchResult, metadatas in
+            } update: { account, id, searchResult, metadatas in
                 guard let metadatas = metadatas, metadatas.count > 0, self.appDelegate.isSearchingMode , let searchResult = searchResult else { return }
                 NCOperationQueue.shared.unifiedSearchAddSection(collectionViewCommon: self, metadatas: metadatas, searchResult: searchResult)
-            } completion: {errorCode, errorDescription in
+            } completion: { account, error in
                 self.refreshControl.endRefreshing()
                 self.isReloadDataSourceNetworkInProgress = false
                 self.collectionView.reloadData()
             }
         } else {
-            NCNetworking.shared.searchFiles(urlBase: appDelegate, literal: literalSearch) { metadatas, errorCode, errorDescription in
+            NCNetworking.shared.searchFiles(urlBase: appDelegate, literal: literalSearch) { metadatas, error in
                 DispatchQueue.main.async {
                     self.refreshControl.endRefreshing()
                     self.collectionView.reloadData()
                 }
-                guard let metadatas = metadatas, errorCode == 0, self.appDelegate.isSearchingMode else { return }
+                guard let metadatas = metadatas, error == .success, self.appDelegate.isSearchingMode else { return }
                 self.dataSource = NCDataSource(
                     metadatas: metadatas,
                     account: self.appDelegate.account,
@@ -1063,10 +1063,10 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
         metadataForSection.unifiedSearchInProgress = true
         self.collectionView?.reloadData()
 
-        NCNetworking.shared.unifiedSearchFilesProvider(urlBase: appDelegate, id: searchResult.id, term: term, limit: 5, cursor: cursor) { searchResult, metadatas, errorCode, errorDescription in
+        NCNetworking.shared.unifiedSearchFilesProvider(userBaseUrl: appDelegate, id: searchResult.id, term: term, limit: 5, cursor: cursor) { account, searchResult, metadatas, error in
 
-            if errorCode != 0 {
-                NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+            if error != .success {
+                NCContentPresenter.shared.showError(error: error)
             }
 
             metadataForSection.unifiedSearchInProgress = false
@@ -1079,13 +1079,13 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
         }
     }
 
-    @objc func networkReadFolder(forced: Bool, completion: @escaping(_ tableDirectory: tableDirectory?, _ metadatas: [tableMetadata]?, _ metadatasUpdate: [tableMetadata]?, _ metadatasDelete: [tableMetadata]?, _ errorCode: Int, _ errorDescription: String) -> Void) {
+    @objc func networkReadFolder(forced: Bool, completion: @escaping(_ tableDirectory: tableDirectory?, _ metadatas: [tableMetadata]?, _ metadatasUpdate: [tableMetadata]?, _ metadatasDelete: [tableMetadata]?, _ error: NKError) -> Void) {
 
         var tableDirectory: tableDirectory?
 
-        NCNetworking.shared.readFile(serverUrlFileName: serverUrl) { (account, metadataFolder, errorCode, errorDescription) in
-            guard errorCode == 0 else {
-                completion(nil, nil, nil, nil, errorCode, errorDescription)
+        NCNetworking.shared.readFile(serverUrlFileName: serverUrl) { (account, metadataFolder, error) in
+            guard error == .success else {
+                completion(nil, nil, nil, nil, error)
                 return
             }
 
@@ -1093,32 +1093,34 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
                 tableDirectory = NCManageDatabase.shared.setDirectory(serverUrl: self.serverUrl, richWorkspace: metadataFolder.richWorkspace, account: account)
             }
             if forced || tableDirectory?.etag != metadataFolder?.etag || metadataFolder?.e2eEncrypted ?? false {
-                NCNetworking.shared.readFolder(serverUrl: self.serverUrl, account: self.appDelegate.account) { account, metadataFolder, metadatas, metadatasUpdate, _, metadatasDelete, errorCode, errorDescription in
-                    guard errorCode == 0 else {
-                        completion(tableDirectory, nil, nil, nil, errorCode, errorDescription)
+                NCNetworking.shared.readFolder(serverUrl: self.serverUrl, account: self.appDelegate.account) { account, metadataFolder, metadatas, metadatasUpdate, _, metadatasDelete, error in
+                    guard error == .success else {
+                        completion(tableDirectory, nil, nil, nil, error)
                         return
                     }
                     self.metadataFolder = metadataFolder
                     // E2EE
                     if let metadataFolder = metadataFolder, metadataFolder.e2eEncrypted, CCUtility.isEnd(toEndEnabled: self.appDelegate.account) {
-                        NCCommunication.shared.getE2EEMetadata(fileId: metadataFolder.ocId, e2eToken: nil) { account, e2eMetadata, errorCode, errorDescription in
-                            if errorCode == 0, let e2eMetadata = e2eMetadata {
+                        NextcloudKit.shared.getE2EEMetadata(fileId: metadataFolder.ocId, e2eToken: nil) { account, e2eMetadata, error in
+                            if error == .success, let e2eMetadata = e2eMetadata {
                                 if NCEndToEndMetadata.shared.decoderMetadata(e2eMetadata, privateKey: CCUtility.getEndToEndPrivateKey(account), serverUrl: self.serverUrl, account: account, urlBase: self.appDelegate.urlBase) {
                                     self.reloadDataSource()
                                 } else {
-                                    NCContentPresenter.shared.messageNotification("_error_e2ee_", description: "_e2e_error_decode_metadata_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorDecodeMetadata)
+                                    let error = NKError(errorCode: NCGlobal.shared.errorDecodeMetadata, errorDescription: "_e2e_error_decode_metadata_")
+                                    NCContentPresenter.shared.messageNotification("_error_e2ee_", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error)
                                 }
-                            } else if errorCode != NCGlobal.shared.errorResourceNotFound {
-                                NCContentPresenter.shared.messageNotification("_error_e2ee_", description: "_e2e_error_decode_metadata_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorDecodeMetadata)
+                            } else if error.errorCode != NCGlobal.shared.errorResourceNotFound {
+                                let error = NKError(errorCode: NCGlobal.shared.errorDecodeMetadata, errorDescription: "_e2e_error_decode_metadata_")
+                                NCContentPresenter.shared.messageNotification("_error_e2ee_", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error)
                             }
-                            completion(tableDirectory, metadatas, metadatasUpdate, metadatasDelete, errorCode, errorDescription)
+                            completion(tableDirectory, metadatas, metadatasUpdate, metadatasDelete, error)
                         }
                     } else {
-                        completion(tableDirectory, metadatas, metadatasUpdate, metadatasDelete, errorCode, errorDescription)
+                        completion(tableDirectory, metadatas, metadatasUpdate, metadatasDelete, error)
                     }
                 }
             } else {
-                completion(tableDirectory, nil, nil, nil, 0, "")
+                completion(tableDirectory, nil, nil, nil, NKError())
             }
         }
     }
@@ -1272,7 +1274,8 @@ extension NCCollectionViewCommon: UICollectionViewDelegate {
         }
 
         if metadata.e2eEncrypted && !CCUtility.isEnd(toEndEnabled: appDelegate.account) {
-            NCContentPresenter.shared.messageNotification("_info_", description: "_e2e_goto_settings_for_enable_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorE2EENotEnabled)
+            let error = NKError(errorCode: NCGlobal.shared.errorE2EENotEnabled, errorDescription: "_e2e_goto_settings_for_enable_")
+            NCContentPresenter.shared.showInfo(error: error)
             return
         }
 
@@ -1284,10 +1287,10 @@ extension NCCollectionViewCommon: UICollectionViewDelegate {
             
             let imageIcon = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag))
 
-            if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
+            if metadata.classFile == NKCommon.typeClassFile.image.rawValue || metadata.classFile == NKCommon.typeClassFile.video.rawValue || metadata.classFile == NKCommon.typeClassFile.audio.rawValue {
                 var metadatas: [tableMetadata] = []
                 for metadata in metadataSourceForAllSections {
-                    if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
+                    if metadata.classFile == NKCommon.typeClassFile.image.rawValue || metadata.classFile == NKCommon.typeClassFile.video.rawValue || metadata.classFile == NKCommon.typeClassFile.audio.rawValue {
                         metadatas.append(metadata)
                     }
                 }
@@ -1297,10 +1300,11 @@ extension NCCollectionViewCommon: UICollectionViewDelegate {
 
             if CCUtility.fileProviderStorageExists(metadata) {
                 NCViewer.shared.view(viewController: self, metadata: metadata, metadatas: [metadata], imageIcon: imageIcon)
-            } else if NCCommunication.shared.isNetworkReachable() {
-                NCNetworking.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorLoadFileView) { _ in }
+            } else if NextcloudKit.shared.isNetworkReachable() {
+                NCNetworking.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorLoadFileView) { _, _ in }
             } else {
-                NCContentPresenter.shared.messageNotification("_info_", description: "_go_online_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorOffline)
+                let error = NKError(errorCode: NCGlobal.shared.errorOffline, errorDescription: "_go_online_")
+                NCContentPresenter.shared.showInfo(error: error)
             }
         }
     }
@@ -1316,7 +1320,7 @@ extension NCCollectionViewCommon: UICollectionViewDelegate {
     func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
 
         guard let metadata = dataSource.cellForItemAt(indexPath: indexPath) else { return nil }
-        if isEditMode || metadata.classFile == NCCommunicationCommon.typeClassFile.url.rawValue { return nil }
+        if isEditMode || metadata.classFile == NKCommon.typeClassFile.url.rawValue { return nil }
 
         let identifier = indexPath as NSCopying
         var image: UIImage?
@@ -1356,26 +1360,8 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
         // Thumbnail
         if !metadata.directory {
             if metadata.name == NCGlobal.shared.appName {
-
-                let filePath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
-                let iconImagePath = CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)!
-
-                if FileManager().fileExists(atPath: iconImagePath) {
-                    (cell as! NCCellProtocol).filePreviewImageView?.image =  UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag))
-                } else if metadata.status > NCGlobal.shared.metadataStatusNormal && metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && FileManager().fileExists(atPath: filePath) {
-                    if let image = UIImage(contentsOfFile: filePath), let image = image.resizeImage(size: CGSize(width: NCGlobal.shared.sizeIcon, height: NCGlobal.shared.sizeIcon), isAspectRation: true), let data = image.jpegData(compressionQuality: 0.5) {
-                        do {
-                            try data.write(to: URL.init(fileURLWithPath: iconImagePath), options: .atomic)
-                            (cell as! NCCellProtocol).filePreviewImageView?.image = image
-                        } catch { }
-                    }
-                } else if metadata.status > NCGlobal.shared.metadataStatusNormal && metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue && FileManager().fileExists(atPath: filePath) {
-                    if let image = NCUtility.shared.imageFromVideo(url: URL(fileURLWithPath: filePath), at: 0), let image = image.resizeImage(size: CGSize(width: NCGlobal.shared.sizeIcon, height: NCGlobal.shared.sizeIcon), isAspectRation: true), let data = image.jpegData(compressionQuality: 0.5) {
-                        do {
-                            try data.write(to: URL.init(fileURLWithPath: iconImagePath), options: .atomic)
-                            (cell as! NCCellProtocol).filePreviewImageView?.image = image
-                        } catch { }
-                    }
+                    if let image = NCUtilityGUI().createFilePreviewImage(ocId: metadata.ocId, etag: metadata.etag, fileNameView: metadata.fileNameView, classFile: metadata.classFile, status: metadata.status, createPreviewMedia: !metadata.hasPreview) {
+                    (cell as! NCCellProtocol).filePreviewImageView?.image = image
                 } else {
                     NCOperationQueue.shared.downloadThumbnail(metadata: metadata, placeholder: true, cell: cell, view: collectionView)
                 }
@@ -1491,7 +1477,7 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
             cell.fileTitleLabel?.text = metadata.fileName
             cell.fileTitleLabel?.lineBreakMode = .byTruncatingTail
             if metadata.name == NCGlobal.shared.appName {
-                cell.fileInfoLabel?.text = NSLocalizedString("_in_", comment: "") + " " + NCUtilityFileSystem.shared.getPath(metadata: metadata, withFileName: false)
+                cell.fileInfoLabel?.text = NSLocalizedString("_in_", comment: "") + " " + NCUtilityFileSystem.shared.getPath(path: metadata.path, user: metadata.user)
             } else {
                 cell.fileInfoLabel?.text = metadata.subline
                 cell.titleInfoTrailingFull()
@@ -1626,7 +1612,7 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
         }
 
         // URL
-        if metadata.classFile == NCCommunicationCommon.typeClassFile.url.rawValue {
+        if metadata.classFile == NKCommon.typeClassFile.url.rawValue {
             cell.fileLocalImage?.image = nil
             cell.hideButtonShare(true)
             cell.hideButtonMore(true)

+ 2 - 2
iOSClient/Main/Collection Common/NCSelectableNavigationView.swift

@@ -22,7 +22,7 @@
 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
 
-import NCCommunication
+import NextcloudKit
 import Realm
 import UIKit
 
@@ -106,7 +106,7 @@ extension NCSelectableNavigationView where Self: UIViewController {
         for ocId in selectOcId {
             guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { continue }
             selectedMetadatas.append(metadata)
-            if [NCCommunicationCommon.typeClassFile.image.rawValue, NCCommunicationCommon.typeClassFile.video.rawValue].contains(metadata.classFile) {
+            if [NKCommon.typeClassFile.image.rawValue, NKCommon.typeClassFile.video.rawValue].contains(metadata.classFile) {
                 selectedMediaMetadatas.append(metadata)
             }
             if metadata.directory { isAnyFolder = true }

+ 6 - 3
iOSClient/Main/Create cloud/NCCreateFormUploadAssets.swift

@@ -23,7 +23,7 @@
 
 import UIKit
 import Queuer
-import NCCommunication
+import NextcloudKit
 import XLForm
 import Photos
 
@@ -272,7 +272,8 @@ class NCCreateFormUploadAssets: XLFormViewController, NCSelectDelegate {
 
                     self.reloadFormRow(formRow)
 
-                    NCContentPresenter.shared.messageNotification("_info_", description: "_forbidden_characters_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorCharactersForbidden)
+                    let error = NKError(errorCode: NCGlobal.shared.errorCharactersForbidden, errorDescription: "_forbidden_characters_")
+                    NCContentPresenter.shared.showInfo(error: error)
                 }
             }
 
@@ -338,7 +339,9 @@ class NCCreateFormUploadAssets: XLFormViewController, NCSelectDelegate {
 
             if autoUploadPath == self.serverUrl {
                 if !NCNetworking.shared.createFolder(assets: self.assets, selector: NCGlobal.shared.selectorUploadFile, useSubFolder: useSubFolder, account: self.appDelegate.account, urlBase: self.appDelegate.urlBase) {
-                    NCContentPresenter.shared.messageNotification("_error_", description: "_error_createsubfolders_upload_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError)
+                    
+                    let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_error_createsubfolders_upload_")
+                    NCContentPresenter.shared.showError(error: error)
                     return
                 }
             }

+ 4 - 3
iOSClient/Main/Create cloud/NCCreateFormUploadConflict.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 import Photos
 
 @objc protocol NCCreateFormUploadConflictDelegate {
@@ -221,7 +221,8 @@ extension NCCreateFormUploadConflictDelegate {
             }
 
             switchAlreadyExistingFiles.isOn = true
-            NCContentPresenter.shared.messageNotification("_info_", description: "_file_not_rewite_doc_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorInternalError)
+            let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_file_not_rewite_doc_")
+            NCContentPresenter.shared.showInfo(error: error)
         }
 
         tableView.reloadData()
@@ -409,7 +410,7 @@ extension NCCreateFormUploadConflict: UITableViewDataSource {
             } else if FileManager().fileExists(atPath: filePathNewFile) {
 
                 do {
-                    if metadataNewFile.classFile ==  NCCommunicationCommon.typeClassFile.image.rawValue {
+                    if metadataNewFile.classFile ==  NKCommon.typeClassFile.image.rawValue {
                         // preserver memory especially for very large files in Share extension
                         if let image = UIImage.downsample(imageAt: URL(fileURLWithPath: filePathNewFile), to: cell.imageNewFile.frame.size) {
                             cell.imageNewFile.image = image

+ 34 - 35
iOSClient/Main/Create cloud/NCCreateFormUploadDocuments.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 import XLForm
 
 // MARK: -
@@ -44,8 +44,8 @@ import XLForm
     var fileName = ""
     var fileNameExtension = ""
     var titleForm = ""
-    var listOfTemplate: [NCCommunicationEditorTemplates] = []
-    var selectTemplate: NCCommunicationEditorTemplates?
+    var listOfTemplate: [NKEditorTemplates] = []
+    var selectTemplate: NKEditorTemplates?
 
     // Layout
     let numItems = 2
@@ -263,7 +263,7 @@ import XLForm
             //Trim whitespaces after checks above
             fileNameForm = (fileNameForm as! String).trimmingCharacters(in: .whitespacesAndNewlines)
 
-            let result = NCCommunicationCommon.shared.getInternalType(fileName: fileNameForm as! String, mimeType: "", directory: false)
+            let result = NKCommon.shared.getInternalType(fileName: fileNameForm as! String, mimeType: "", directory: false)
             if NCUtility.shared.isDirectEditing(account: appDelegate.account, contentType: result.mimeType).count == 0 {
                 fileNameForm = (fileNameForm as! NSString).deletingPathExtension + "." + fileNameExtension
             }
@@ -311,23 +311,22 @@ import XLForm
         self.navigationItem.rightBarButtonItem?.isEnabled = false
 
         if self.editorId == NCGlobal.shared.editorText || self.editorId == NCGlobal.shared.editorOnlyoffice {
-
-            var customUserAgent: String?
-
+            
+            var options = NKRequestOptions()
             if self.editorId == NCGlobal.shared.editorOnlyoffice {
-                customUserAgent = NCUtility.shared.getCustomUserAgentOnlyOffice()
+                options = NKRequestOptions(customUserAgent: NCUtility.shared.getCustomUserAgentOnlyOffice())
             } else if editorId == NCGlobal.shared.editorText {
-                customUserAgent = NCUtility.shared.getCustomUserAgentNCText()
-            } // else: use default
-
-            NCCommunication.shared.NCTextCreateFile(fileNamePath: fileNamePath, editorId: editorId, creatorId: creatorId, templateId: templateIdentifier, customUserAgent: customUserAgent) { account, url, errorCode, errorMessage in
-                guard errorCode == 0, account == self.appDelegate.account, let url = url else {
+                options = NKRequestOptions(customUserAgent: NCUtility.shared.getCustomUserAgentNCText())
+            }
+            
+            NextcloudKit.shared.NCTextCreateFile(fileNamePath: fileNamePath, editorId: editorId, creatorId: creatorId, templateId: templateIdentifier, options: options) { account, url, error in
+                guard error == .success, account == self.appDelegate.account, let url = url else {
                     self.navigationItem.rightBarButtonItem?.isEnabled = true
-                    NCContentPresenter.shared.messageNotification("_error_", description: errorMessage, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                    NCContentPresenter.shared.showError(error: error)
                     return
                 }
 
-                var results = NCCommunicationCommon.shared.getInternalType(fileName: fileName, mimeType: "", directory: false)
+                var results = NKCommon.shared.getInternalType(fileName: fileName, mimeType: "", directory: false)
                 //FIXME: iOS 12.0,* don't detect UTI text/markdown, text/x-markdown
                 if results.mimeType.isEmpty {
                     results.mimeType = "text/x-markdown"
@@ -344,10 +343,10 @@ import XLForm
 
         if self.editorId == NCGlobal.shared.editorCollabora {
 
-            NCCommunication.shared.createRichdocuments(path: fileNamePath, templateId: templateIdentifier) { account, url, errorCode, errorDescription in
-                guard errorCode == 0, account == self.appDelegate.account, let url = url else {
+            NextcloudKit.shared.createRichdocuments(path: fileNamePath, templateId: templateIdentifier) { account, url, error in
+                guard error == .success, account == self.appDelegate.account, let url = url else {
                     self.navigationItem.rightBarButtonItem?.isEnabled = true
-                    NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                    NCContentPresenter.shared.showError(error: error)
                     return
                 }
 
@@ -376,22 +375,22 @@ import XLForm
 
         if self.editorId == NCGlobal.shared.editorText || self.editorId == NCGlobal.shared.editorOnlyoffice {
 
-            var customUserAgent: String?
+            var options = NKRequestOptions()
             if self.editorId == NCGlobal.shared.editorOnlyoffice {
-                customUserAgent = NCUtility.shared.getCustomUserAgentOnlyOffice()
+                options = NKRequestOptions(customUserAgent: NCUtility.shared.getCustomUserAgentOnlyOffice())
             } else if editorId == NCGlobal.shared.editorText {
-                customUserAgent = NCUtility.shared.getCustomUserAgentNCText()
-            } // else: use default
+                options = NKRequestOptions(customUserAgent: NCUtility.shared.getCustomUserAgentNCText())
+            }
 
-            NCCommunication.shared.NCTextGetListOfTemplates(customUserAgent: customUserAgent) { account, templates, errorCode, _ in
+            NextcloudKit.shared.NCTextGetListOfTemplates(options: options) { account, templates, error in
 
                 self.indicator.stopAnimating()
 
-                if errorCode == 0 && account == self.appDelegate.account {
+                if error == .success && account == self.appDelegate.account {
 
                     for template in templates {
 
-                        let temp = NCCommunicationEditorTemplates()
+                        let temp = NKEditorTemplates()
 
                         temp.identifier = template.identifier
                         temp.ext = template.ext
@@ -411,7 +410,7 @@ import XLForm
 
                 if self.listOfTemplate.count == 0 {
 
-                    let temp = NCCommunicationEditorTemplates()
+                    let temp = NKEditorTemplates()
 
                     temp.identifier = ""
                     if self.editorId == NCGlobal.shared.editorText {
@@ -440,15 +439,15 @@ import XLForm
 
         if self.editorId == NCGlobal.shared.editorCollabora {
 
-            NCCommunication.shared.getTemplatesRichdocuments(typeTemplate: typeTemplate) { account, templates, errorCode, _ in
+            NextcloudKit.shared.getTemplatesRichdocuments(typeTemplate: typeTemplate) { account, templates, error in
 
                 self.indicator.stopAnimating()
 
-                if errorCode == 0 && account == self.appDelegate.account {
+                if error == .success && account == self.appDelegate.account {
 
                     for template in templates! {
 
-                        let temp = NCCommunicationEditorTemplates()
+                        let temp = NKEditorTemplates()
 
                         temp.identifier = "\(template.templateId)"
                         temp.delete = template.delete
@@ -470,7 +469,7 @@ import XLForm
 
                 if self.listOfTemplate.count == 0 {
 
-                    let temp = NCCommunicationEditorTemplates()
+                    let temp = NKEditorTemplates()
 
                     temp.identifier = ""
                     if self.typeTemplate == NCGlobal.shared.templateDocument {
@@ -499,18 +498,18 @@ import XLForm
 
         let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + name + ".png"
 
-        NCCommunication.shared.download(serverUrlFileName: preview, fileNameLocalPath: fileNameLocalPath, requestHandler: { _ in
+        NextcloudKit.shared.download(serverUrlFileName: preview, fileNameLocalPath: fileNameLocalPath, requestHandler: { _ in
 
         }, taskHandler: { _ in
 
         }, progressHandler: { _ in
 
-        }) { account, _, _, _, _, _, errorCode, _ in
+        }) { account, _, _, _, _, _, error in
 
-            if errorCode == 0 && account == self.appDelegate.account {
+            if error == .success && account == self.appDelegate.account {
                 self.collectionView.reloadItems(at: [indexPath])
-            } else if errorCode != 0 {
-                print("\(errorCode)")
+            } else if error != .success {
+                print("\(error.errorCode)")
             } else {
                 print("[LOG] It has been changed user during networking process, error.")
             }

+ 10 - 5
iOSClient/Main/Create cloud/NCCreateFormUploadScanDocument.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 import Vision
 import VisionKit
 import Photos
@@ -441,7 +441,9 @@ class NCCreateFormUploadScanDocument: XLFormViewController, NCSelectDelegate, NC
 
         guard let fileNameGenerateExport = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView) else {
             NCActivityIndicator.shared.stop()
-            NCContentPresenter.shared.messageNotification("_error_", description: "_error_creation_file_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorCreationFile)
+
+            let error = NKError(errorCode: NCGlobal.shared.errorCreationFile, errorDescription: "_error_creation_file_")
+            NCContentPresenter.shared.showError(error: error)
             return
         }
         let fileUrl = URL(fileURLWithPath: fileNameGenerateExport)
@@ -478,7 +480,8 @@ class NCCreateFormUploadScanDocument: XLFormViewController, NCSelectDelegate, NC
                 try textFile.write(to: fileUrl, atomically: true, encoding: .utf8)
             } catch {
                 NCActivityIndicator.shared.stop()
-                NCContentPresenter.shared.messageNotification("_error_", description: "_error_creation_file_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorCreationFile)
+                let error = NKError(errorCode: NCGlobal.shared.errorCreationFile, errorDescription: "_error_creation_file_")
+                NCContentPresenter.shared.showError(error: error)
                 return
             }
         }
@@ -560,7 +563,8 @@ class NCCreateFormUploadScanDocument: XLFormViewController, NCSelectDelegate, NC
 
             guard let data = image.jpegData(compressionQuality: CGFloat(0.5)) else {
                 NCActivityIndicator.shared.stop()
-                NCContentPresenter.shared.messageNotification("_error_", description: "_error_creation_file_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorCreationFile)
+                let error = NKError(errorCode: NCGlobal.shared.errorCreationFile, errorDescription: "_error_creation_file_")
+                NCContentPresenter.shared.showError(error: error)
                 return
             }
 
@@ -568,7 +572,8 @@ class NCCreateFormUploadScanDocument: XLFormViewController, NCSelectDelegate, NC
                 try data.write(to: fileUrl, options: .atomic)
             } catch {
                 NCActivityIndicator.shared.stop()
-                NCContentPresenter.shared.messageNotification("_error_", description: "_error_creation_file_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorCreationFile)
+                let error = NKError(errorCode: NCGlobal.shared.errorCreationFile, errorDescription: "_error_creation_file_")
+                NCContentPresenter.shared.showError(error: error)
                 return
             }
         }

+ 1 - 1
iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 
 class NCCreateFormUploadVoiceNote: XLFormViewController, NCSelectDelegate, AVAudioPlayerDelegate, NCCreateFormUploadConflictDelegate {
 

+ 62 - 56
iOSClient/Main/NCFunctionCenter.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 import Queuer
 import JGProgressHUD
 import SVGKit
@@ -47,15 +47,14 @@ import Photos
         guard let userInfo = notification.userInfo as NSDictionary?,
               let ocId = userInfo["ocId"] as? String,
               let selector = userInfo["selector"] as? String,
-              let errorCode = userInfo["errorCode"] as? Int,
-              let errorDescription = userInfo["errorDescription"] as? String,
+              let error = userInfo["error"] as? NKError,
               let account = userInfo["account"] as? String,
               account == appDelegate.account
         else { return }
 
-        guard errorCode == 0 else {
+        guard error == .success else {
             // File do not exists on server, remove in local
-            if errorCode == NCGlobal.shared.errorResourceNotFound || errorCode == NCGlobal.shared.errorBadServerResponse {
+            if error.errorCode == NCGlobal.shared.errorResourceNotFound || error.errorCode == NCGlobal.shared.errorBadServerResponse {
                 do {
                     try FileManager.default.removeItem(atPath: CCUtility.getDirectoryProviderStorageOcId(ocId))
                 } catch { }
@@ -63,7 +62,7 @@ import Photos
                 NCManageDatabase.shared.deleteLocalFile(predicate: NSPredicate(format: "ocId == %@", ocId))
                 
             } else {
-                NCContentPresenter.shared.messageNotification("_download_file_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode, priority: .max)
+                NCContentPresenter.shared.messageNotification("_download_file_", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)
             }
             return
         }
@@ -87,7 +86,7 @@ import Photos
 
             if metadata.contentType.contains("opendocument") && !NCUtility.shared.isRichDocument(metadata) {
                 self.openDocumentController(metadata: metadata)
-            } else if metadata.classFile == NCCommunicationCommon.typeClassFile.compress.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.unknow.rawValue {
+            } else if metadata.classFile == NKCommon.typeClassFile.compress.rawValue || metadata.classFile == NKCommon.typeClassFile.unknow.rawValue {
                 self.openDocumentController(metadata: metadata)
             } else {
                 if let viewController = self.appDelegate.activeViewController {
@@ -151,9 +150,9 @@ import Photos
             NCManageDatabase.shared.setDirectory(serverUrl: serverUrl, offline: true, account: self.appDelegate.account)
             NCOperationQueue.shared.synchronizationMetadata(metadata, selector: NCGlobal.shared.selectorDownloadAllFile)
         } else {
-            NCNetworking.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorLoadOffline) { _ in }
+            NCNetworking.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorLoadOffline) { _, _ in }
             if let metadataLivePhoto = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) {
-                NCNetworking.shared.download(metadata: metadataLivePhoto, selector: NCGlobal.shared.selectorLoadOffline) { _ in }
+                NCNetworking.shared.download(metadata: metadataLivePhoto, selector: NCGlobal.shared.selectorLoadOffline) { _, _ in }
             }
         }
     }
@@ -163,14 +162,13 @@ import Photos
     @objc func uploadedFile(_ notification: NSNotification) {
 
         guard let userInfo = notification.userInfo as NSDictionary?,
-              let errorCode = userInfo["errorCode"] as? Int,
-              let errorDescription = userInfo["errorDescription"] as? String,
+              let error = userInfo["error"] as? NKError,
               let account = userInfo["account"] as? String,
               account == appDelegate.account
         else { return }
 
-        if errorCode != 0, errorCode != -999, errorDescription != "" {
-            NCContentPresenter.shared.messageNotification("_upload_file_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode, priority: .max)
+        if error != .success, error.errorCode != NSURLErrorCancelled, error.errorCode != NCGlobal.shared.errorRequestExplicityCancelled {
+            NCContentPresenter.shared.messageNotification("_upload_file_", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)
         }
     }
 
@@ -180,9 +178,9 @@ import Photos
 
         let serverUrlFileName = metadata.serverUrl + "/" + metadata.fileName
         NCActivityIndicator.shared.start(backgroundView: viewController.view)
-        NCNetworking.shared.readFile(serverUrlFileName: serverUrlFileName, queue: .main) { account, metadata, errorCode, errorDescription in
+        NCNetworking.shared.readFile(serverUrlFileName: serverUrlFileName, queue: .main) { account, metadata, error in
             NCActivityIndicator.shared.stop()
-            if let metadata = metadata, errorCode == 0 {
+            if let metadata = metadata, error == .success {
                 let shareNavigationController = UIStoryboard(name: "NCShare", bundle: nil).instantiateInitialViewController() as! UINavigationController
                 let shareViewController = shareNavigationController.topViewController as! NCSharePaging
 
@@ -201,11 +199,11 @@ import Photos
 
         if CCUtility.fileProviderStorageExists(metadata) {
 
-            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadedFile, userInfo: ["ocId": metadata.ocId, "selector": selector, "errorCode": 0, "errorDescription": "", "account": metadata.account])
+            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadedFile, userInfo: ["ocId": metadata.ocId, "selector": selector, "error": NKError(), "account": metadata.account])
 
         } else {
 
-            NCNetworking.shared.download(metadata: metadata, selector: selector) { _ in }
+            NCNetworking.shared.download(metadata: metadata, selector: selector) { _, _ in }
         }
     }
 
@@ -234,7 +232,7 @@ import Photos
         let processor = ParallelWorker(n: 5, titleKey: "_downloading_", totalTasks: downloadMetadata.count, hudView: self.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: "", completion: { _, _ in
                     if CCUtility.fileProviderStorageExists(metadata) { items.append(url) }
                     completion()
                 })
@@ -276,7 +274,7 @@ import Photos
         let printController = UIPrintInteractionController.shared
         let printInfo = UIPrintInfo(dictionary: nil)
         printInfo.jobName = fileNameURL.lastPathComponent
-        printInfo.outputType = metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue ? .photo : .general
+        printInfo.outputType = metadata.classFile == NKCommon.typeClassFile.image.rawValue ? .photo : .general
         printController.printInfo = printInfo
         printController.showsNumberOfCopies = true
 
@@ -313,14 +311,16 @@ import Photos
 
         NCAskAuthorization.shared.askAuthorizationPhotoLibrary(viewController: appDelegate.mainTabBar?.window?.rootViewController) { hasPermission in
             guard hasPermission else {
-                return NCContentPresenter.shared.messageNotification("_access_photo_not_enabled_", description: "_access_photo_not_enabled_msg_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorFileNotSaved)
+                let error = NKError(errorCode: NCGlobal.shared.errorFileNotSaved, errorDescription: "_access_photo_not_enabled_msg_")
+                return NCContentPresenter.shared.messageNotification("_access_photo_not_enabled_", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error)
             }
-            if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue, let image = UIImage(contentsOfFile: fileNamePath) {
+            if metadata.classFile == NKCommon.typeClassFile.image.rawValue, let image = UIImage(contentsOfFile: fileNamePath) {
                 UIImageWriteToSavedPhotosAlbum(image, self, #selector(self.saveAlbum(_:didFinishSavingWithError:contextInfo:)), nil)
-            } else if metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue, UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(fileNamePath) {
+            } else if metadata.classFile == NKCommon.typeClassFile.video.rawValue, UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(fileNamePath) {
                 UISaveVideoAtPathToSavedPhotosAlbum(fileNamePath, self, #selector(self.saveAlbum(_:didFinishSavingWithError:contextInfo:)), nil)
             } else {
-                NCContentPresenter.shared.messageNotification("_save_selected_files_", description: "_file_not_saved_cameraroll_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorFileNotSaved)
+                let error = NKError(errorCode: NCGlobal.shared.errorFileNotSaved, errorDescription: "_file_not_saved_cameraroll_")
+                NCContentPresenter.shared.messageNotification("_save_selected_files_", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error)
             }
         }
     }
@@ -328,7 +328,8 @@ import Photos
     @objc private func saveAlbum(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
 
         if error != nil {
-            NCContentPresenter.shared.messageNotification("_save_selected_files_", description: "_file_not_saved_cameraroll_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorFileNotSaved)
+            let error = NKError(errorCode: NCGlobal.shared.errorFileNotSaved, errorDescription: "_file_not_saved_cameraroll_")
+            NCContentPresenter.shared.messageNotification("_save_selected_files_", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error)
         }
     }
 
@@ -411,7 +412,7 @@ import Photos
 
             for metadata in downloadMetadatas {
                 parallelizer.execute { completion in
-                    NCNetworking.shared.download(metadata: metadata, selector: "") { _ in completion() }
+                    NCNetworking.shared.download(metadata: metadata, selector: "") { _, _ in completion() }
                 }
             }
             parallelizer.completeWork {
@@ -421,28 +422,32 @@ import Photos
         }
     }
 
-    func upload(fileName: String, serverUrlFileName: String, fileNameLocalPath: String, serverUrl: String, completion: @escaping () -> Void) {
-        NCCommunication.shared.upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath) { _ in
-        } progressHandler: { progress in
-        } completionHandler: { account, ocId, etag, _, _, _, errorCode, errorDescription in
-            if errorCode == 0 && etag != nil && ocId != nil {
-                let toPath = CCUtility.getDirectoryProviderStorageOcId(ocId!, fileNameView: fileName)!
-                NCUtilityFileSystem.shared.moveFile(atPath: fileNameLocalPath, toPath: toPath)
-                NCManageDatabase.shared.addLocalFile(account: account, etag: etag!, ocId: ocId!, fileName: fileName)
-                NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSourceNetworkForced, userInfo: ["serverUrl": serverUrl])
-            } else {
-                NCContentPresenter.shared.showError(description: errorDescription, errorCode: errorCode)
-            }
-            completion()
-        }
-    }
-
     func pastePasteboard(serverUrl: String) {
         let parallelizer = ParallelWorker(n: 5, titleKey: "_uploading_", totalTasks: nil, hudView: appDelegate.window?.rootViewController?.view)
 
+        func uploadPastePasteboard(fileName: String, serverUrlFileName: String, fileNameLocalPath: String, serverUrl: String, completion: @escaping () -> Void) {
+            NextcloudKit.shared.upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath) { request in
+                NCNetworking.shared.uploadRequest[fileNameLocalPath] = request
+            } progressHandler: { progress in
+            } completionHandler: { account, ocId, etag, _, _, _, afError, error in
+                NCNetworking.shared.uploadRequest.removeValue(forKey: fileNameLocalPath)
+                if error == .success && etag != nil && ocId != nil {
+                    let toPath = CCUtility.getDirectoryProviderStorageOcId(ocId!, fileNameView: fileName)!
+                    NCUtilityFileSystem.shared.moveFile(atPath: fileNameLocalPath, toPath: toPath)
+                    NCManageDatabase.shared.addLocalFile(account: account, etag: etag!, ocId: ocId!, fileName: fileName)
+                    NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSourceNetworkForced, userInfo: ["serverUrl": serverUrl])
+                } else if afError?.isExplicitlyCancelledError ?? false {
+                    print("cancel")
+                } else {
+                    NCContentPresenter.shared.showError(error: error)
+                }
+                completion()
+            }
+        }
+
         for (index, items) in UIPasteboard.general.items.enumerated() {
             for item in items {
-                let results = NCCommunicationCommon.shared.getFileProperties(inUTI: item.key as CFString)
+                let results = NKCommon.shared.getFileProperties(inUTI: item.key as CFString)
                 guard !results.ext.isEmpty,
                       let data = UIPasteboard.general.data(forPasteboardType: item.key, inItemSet: IndexSet([index]))?.first
                 else { continue }
@@ -452,7 +457,7 @@ import Photos
                 let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(ocIdUpload, fileNameView: fileName)!
                 do { try data.write(to: URL(fileURLWithPath: fileNameLocalPath)) } catch { continue }
                 parallelizer.execute { completion in
-                    self.upload(fileName: fileName, serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, serverUrl: serverUrl, completion: completion)
+                    uploadPastePasteboard(fileName: fileName, serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, serverUrl: serverUrl, completion: completion)
                 }
             }
         }
@@ -618,8 +623,9 @@ import Photos
 
         let copyPath = UIAction(title: NSLocalizedString("_copy_path_", comment: ""), image: UIImage(systemName: "doc.on.clipboard")) { _ in
             let board = UIPasteboard.general
-            board.string = NCUtilityFileSystem.shared.getPath(metadata: metadata, withFileName: true)
-            NCContentPresenter.shared.messageNotification("", description: "_copied_path_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorNoError)
+            board.string = NCUtilityFileSystem.shared.getPath(path: metadata.path, user: metadata.user, fileName: metadata.fileName)
+            let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_copied_path_")
+            NCContentPresenter.shared.showInfo(error: error)
         }
 
         let detail = UIAction(title: NSLocalizedString("_details_", comment: ""), image: UIImage(systemName: "info")) { _ in
@@ -689,23 +695,23 @@ import Photos
 
         let favorite = UIAction(title: titleFavorite, image: NCUtility.shared.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite)) { _ in
 
-            NCNetworking.shared.favoriteMetadata(metadata) { errorCode, errorDescription in
-                if errorCode != 0 {
-                    NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+            NCNetworking.shared.favoriteMetadata(metadata) { error in
+                if error != .success {
+                    NCContentPresenter.shared.showError(error: error)
                 }
             }
         }
 
         let deleteConfirmFile = UIAction(title: titleDeleteConfirmFile, image: UIImage(systemName: "trash"), attributes: .destructive) { _ in
-            NCNetworking.shared.deleteMetadata(metadata, onlyLocalCache: false) { errorCode, errorDescription in
-                if errorCode != 0 {
-                    NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+            NCNetworking.shared.deleteMetadata(metadata, onlyLocalCache: false) { error in
+                if error != .success {
+                    NCContentPresenter.shared.showError(error: error)
                 }
             }
         }
 
         let deleteConfirmLocal = UIAction(title: NSLocalizedString("_remove_local_file_", comment: ""), image: UIImage(systemName: "trash"), attributes: .destructive) { _ in
-            NCNetworking.shared.deleteMetadata(metadata, onlyLocalCache: true) { _, _ in
+            NCNetworking.shared.deleteMetadata(metadata, onlyLocalCache: true) { _ in
             }
         }
 
@@ -747,15 +753,15 @@ import Photos
             children.insert(lockUnlock, at: metadata.lock ? 0 : 1)
         }
 
-        if (metadata.contentType != "image/svg+xml") && (metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue) {
+        if (metadata.contentType != "image/svg+xml") && (metadata.classFile == NKCommon.typeClassFile.image.rawValue || metadata.classFile == NKCommon.typeClassFile.video.rawValue) {
             children.insert(save, at: 2)
         }
 
-        if (metadata.contentType != "image/svg+xml") && (metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue) {
+        if (metadata.contentType != "image/svg+xml") && (metadata.classFile == NKCommon.typeClassFile.image.rawValue) {
             children.insert(saveAsScan, at: 2)
         }
 
-        if (metadata.contentType != "image/svg+xml") && (metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue || metadata.contentType == "application/pdf" || metadata.contentType == "com.adobe.pdf") {
+        if (metadata.contentType != "image/svg+xml") && (metadata.classFile == NKCommon.typeClassFile.image.rawValue || metadata.contentType == "application/pdf" || metadata.contentType == "com.adobe.pdf") {
             children.insert(print, at: 2)
         }
 
@@ -763,7 +769,7 @@ import Photos
             children.insert(viewInFolder, at: children.count - 1)
         }
 
-        if (!isFolderEncrypted && metadata.contentType != "image/gif" && metadata.contentType != "image/svg+xml") && (metadata.contentType == "com.adobe.pdf" || metadata.contentType == "application/pdf" || metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue) {
+        if (!isFolderEncrypted && metadata.contentType != "image/gif" && metadata.contentType != "image/svg+xml") && (metadata.contentType == "com.adobe.pdf" || metadata.contentType == "application/pdf" || metadata.classFile == NKCommon.typeClassFile.image.rawValue) {
             children.insert(modify, at: children.count - 1)
         }
 

+ 3 - 1
iOSClient/Main/NCMainTabBar.swift

@@ -22,6 +22,7 @@
 //
 
 import UIKit
+import NextcloudKit
 
 class NCMainTabBar: UITabBar {
 
@@ -194,7 +195,8 @@ class NCMainTabBar: UITabBar {
             if let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.appDelegate.activeServerUrl)) {
 
                 if !directory.permissions.contains("CK") {
-                    NCContentPresenter.shared.messageNotification("_warning_", description: "_no_permission_add_file_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorInternalError)
+                    let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_no_permission_add_file_")
+                    NCContentPresenter.shared.showWarning(error: error)
                     return
                 }
             }

+ 9 - 4
iOSClient/Main/NCPickerViewController.swift

@@ -25,6 +25,7 @@ import UIKit
 import TLPhotoPicker
 import MobileCoreServices
 import Photos
+import NextcloudKit
 
 // MARK: - Photo Picker
 
@@ -87,15 +88,18 @@ class NCPhotosPickerViewController: NSObject {
         }, didCancel: nil)
 
         viewController.didExceedMaximumNumberOfSelection = { _ in
-            NCContentPresenter.shared.messageNotification("_info_", description: "_limited_dimension_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError)
+            let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_limited_dimension_")
+            NCContentPresenter.shared.showError(error: error)
         }
 
         viewController.handleNoAlbumPermissions = { _ in
-            NCContentPresenter.shared.messageNotification("_info_", description: "_denied_album_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError)
+            let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_denied_album_")
+            NCContentPresenter.shared.showError(error: error)
         }
 
         viewController.handleNoCameraPermissions = { _ in
-            NCContentPresenter.shared.messageNotification("_info_", description: "_denied_camera_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError)
+            let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_denied_camera_")
+            NCContentPresenter.shared.showError(error: error)
         }
 
         viewController.configure = configure
@@ -173,7 +177,8 @@ class NCDocumentPickerViewController: NSObject, UIDocumentPickerDelegate {
                 }
 
             } else {
-                NCContentPresenter.shared.messageNotification("_error_", description: "_read_file_error_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError)
+                let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_read_file_error_")
+                NCContentPresenter.shared.showError(error: error)
             }
         }
     }

+ 22 - 17
iOSClient/Media/NCMedia.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 
 class NCMedia: UIViewController, NCEmptyDataSetDelegate, NCSelectDelegate {
 
@@ -214,7 +214,8 @@ class NCMedia: UIViewController, NCEmptyDataSetDelegate, NCSelectDelegate {
     @objc func uploadedFile(_ notification: NSNotification) {
 
         guard let userInfo = notification.userInfo as NSDictionary?,
-              let errorCode = userInfo["errorCode"] as? Int, errorCode == 0 ,
+              let error = userInfo["error"] as? NKError,
+              error == .success,
               let account = userInfo["account"] as? String,
               account == appDelegate.account
         else { return }
@@ -399,7 +400,7 @@ extension NCMedia: UICollectionViewDataSource {
             cell.fileObjectId = metadata.ocId
             cell.fileUser = metadata.ownerId
 
-            if metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
+            if metadata.classFile == NKCommon.typeClassFile.video.rawValue || metadata.classFile == NKCommon.typeClassFile.audio.rawValue {
                 cell.imageStatus.image = cacheImages.cellPlayImage
             } else if metadata.livePhoto && livePhoto {
                 cell.imageStatus.image = cacheImages.cellLivePhotoImage
@@ -457,12 +458,12 @@ extension NCMedia {
         }
         let startServerUrl = NCUtilityFileSystem.shared.getHomeServer(account: appDelegate.account) + mediaPath
 
-        predicateDefault = NSPredicate(format: "account == %@ AND serverUrl BEGINSWITH %@ AND (classFile == %@ OR classFile == %@) AND NOT (session CONTAINS[c] 'upload')", appDelegate.account, startServerUrl, NCCommunicationCommon.typeClassFile.image.rawValue, NCCommunicationCommon.typeClassFile.video.rawValue)
+        predicateDefault = NSPredicate(format: "account == %@ AND serverUrl BEGINSWITH %@ AND (classFile == %@ OR classFile == %@) AND NOT (session CONTAINS[c] 'upload')", appDelegate.account, startServerUrl, NKCommon.typeClassFile.image.rawValue, NKCommon.typeClassFile.video.rawValue)
 
         if filterClassTypeImage {
-            predicate = NSPredicate(format: "account == %@ AND serverUrl BEGINSWITH %@ AND classFile == %@ AND NOT (session CONTAINS[c] 'upload')", appDelegate.account, startServerUrl, NCCommunicationCommon.typeClassFile.video.rawValue)
+            predicate = NSPredicate(format: "account == %@ AND serverUrl BEGINSWITH %@ AND classFile == %@ AND NOT (session CONTAINS[c] 'upload')", appDelegate.account, startServerUrl, NKCommon.typeClassFile.video.rawValue)
         } else if filterClassTypeVideo {
-            predicate = NSPredicate(format: "account == %@ AND serverUrl BEGINSWITH %@ AND classFile == %@ AND NOT (session CONTAINS[c] 'upload')", appDelegate.account, startServerUrl, NCCommunicationCommon.typeClassFile.image.rawValue)
+            predicate = NSPredicate(format: "account == %@ AND serverUrl BEGINSWITH %@ AND classFile == %@ AND NOT (session CONTAINS[c] 'upload')", appDelegate.account, startServerUrl, NKCommon.typeClassFile.image.rawValue)
         } else {
             predicate = predicateDefault
         }
@@ -529,15 +530,17 @@ extension NCMedia {
         }
         NCActivityIndicator.shared.start(backgroundView: self.view, bottom: bottom-5, style: .gray)
 
-        NCCommunication.shared.searchMedia(path: mediaPath, lessDate: lessDate, greaterDate: greaterDate, elementDate: "d:getlastmodified/", limit: limit, showHiddenFiles: CCUtility.getShowHiddenFiles(), timeout: 300) { account, files, errorCode, errorDescription in
+        let options = NKRequestOptions(timeout: 300)
+        
+        NextcloudKit.shared.searchMedia(path: mediaPath, lessDate: lessDate, greaterDate: greaterDate, elementDate: "d:getlastmodified/", limit: limit, showHiddenFiles: CCUtility.getShowHiddenFiles(), options: options) { account, files, error in
 
             self.oldInProgress = false
             NCActivityIndicator.shared.stop()
             self.collectionView.reloadData()
 
-            if errorCode == 0 && account == self.appDelegate.account {
+            if error == .success && account == self.appDelegate.account {
                 if files.count > 0 {
-                    NCManageDatabase.shared.convertNCCommunicationFilesToMetadatas(files, useMetadataFolder: false, account: self.appDelegate.account) { _, _, metadatas in
+                    NCManageDatabase.shared.convertNKFilesToMetadatas(files, useMetadataFolder: false, account: self.appDelegate.account) { _, _, metadatas in
                         let predicateDate = NSPredicate(format: "date > %@ AND date < %@", greaterDate as NSDate, lessDate as NSDate)
                         let predicateResult = NSCompoundPredicate(andPredicateWithSubpredicates: [predicateDate, self.predicateDefault!])
                         let metadatasResult = NCManageDatabase.shared.getMetadatas(predicate: predicateResult)
@@ -551,8 +554,8 @@ extension NCMedia {
                 } else {
                     self.researchOldMedia(value: value, limit: limit, withElseReloadDataSource: false)
                 }
-            } else if errorCode != 0 {
-                NCCommunicationCommon.shared.writeLog("Media search old media error code \(errorCode) " + errorDescription)
+            } else if error != .success {
+                NKCommon.shared.writeLog("Media search old media error code \(error.errorCode) " + error.errorDescription)
             }
         }
     }
@@ -608,13 +611,15 @@ extension NCMedia {
 
         reloadDataThenPerform {
 
-            NCCommunication.shared.searchMedia(path: self.mediaPath, lessDate: lessDate, greaterDate: greaterDate, elementDate: "d:getlastmodified/", limit: limit, showHiddenFiles: CCUtility.getShowHiddenFiles(), timeout: 300) { account, files, errorCode, errorDescription in
+            let options = NKRequestOptions(timeout: 300)
+            
+            NextcloudKit.shared.searchMedia(path: self.mediaPath, lessDate: lessDate, greaterDate: greaterDate, elementDate: "d:getlastmodified/", limit: limit, showHiddenFiles: CCUtility.getShowHiddenFiles(), options: options) { account, files, error in
 
                 self.newInProgress = false
                 self.mediaCommandView?.activityIndicator.stopAnimating()
 
-                if errorCode == 0 && account == self.appDelegate.account && files.count > 0 {
-                    NCManageDatabase.shared.convertNCCommunicationFilesToMetadatas(files, useMetadataFolder: false, account: account) { _, _, metadatas in
+                if error == .success && account == self.appDelegate.account && files.count > 0 {
+                    NCManageDatabase.shared.convertNKFilesToMetadatas(files, useMetadataFolder: false, account: account) { _, _, metadatas in
                         let predicate = NSPredicate(format: "date > %@ AND date < %@", greaterDate as NSDate, lessDate as NSDate)
                         let predicateResult = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, self.predicate!])
                         let metadatasResult = NCManageDatabase.shared.getMetadatas(predicate: predicateResult)
@@ -623,10 +628,10 @@ extension NCMedia {
                             self.reloadDataSourceWithCompletion { _ in }
                         }
                     }
-                } else if errorCode == 0 && files.count == 0 && self.metadatas.count == 0 {
+                } else if error == .success && files.count == 0 && self.metadatas.count == 0 {
                     self.searchOldMedia()
-                } else if errorCode != 0 {
-                    NCCommunicationCommon.shared.writeLog("Media search new media error code \(errorCode) " + errorDescription)
+                } else if error != .success {
+                    NKCommon.shared.writeLog("Media search new media error code \(error.errorCode) " + error.errorDescription)
                 }
             }
         }

+ 7 - 8
iOSClient/Menu/AppDelegate+Menu.swift

@@ -25,7 +25,7 @@
 
 import UIKit
 import FloatingPanel
-import NCCommunication
+import NextcloudKit
 
 extension AppDelegate {
 
@@ -61,7 +61,7 @@ extension AppDelegate {
             )
         )
 
-        if NCCommunication.shared.isNetworkReachable() && directEditingCreators != nil && directEditingCreators!.contains(where: { $0.editor == NCGlobal.shared.editorText}) && !isEncrypted {
+        if NextcloudKit.shared.isNetworkReachable() && directEditingCreators != nil && directEditingCreators!.contains(where: { $0.editor == NCGlobal.shared.editorText}) && !isEncrypted {
             let directEditingCreator = directEditingCreators!.first(where: { $0.editor == NCGlobal.shared.editorText})!
             actions.append(
                 NCMenuAction(title: NSLocalizedString("_create_nextcloudtext_document_", comment: ""), icon: UIImage(named: "file_txt")!.image(color: NCBrandColor.shared.gray, size: 50), action: { _ in
@@ -97,7 +97,6 @@ extension AppDelegate {
         actions.append(
             NCMenuAction(
                 title: NSLocalizedString("_create_voice_memo_", comment: ""), icon: UIImage(named: "microphone")!.image(color: NCBrandColor.shared.gray, size: 50), action: { _ in
-
                     NCAskAuthorization.shared.askAuthorizationAudioRecord(viewController: viewController) { hasPermission in
                         if hasPermission {
                             let fileName = CCUtility.createFileNameDate(NSLocalizedString("_voice_memo_filename_", comment: ""), extension: "m4a")!
@@ -125,7 +124,7 @@ extension AppDelegate {
             )
         )
 
-        if serverVersionMajor >= NCGlobal.shared.nextcloudVersion18 && directory?.richWorkspace == nil && !isEncrypted && NCCommunication.shared.isNetworkReachable() {
+        if serverVersionMajor >= NCGlobal.shared.nextcloudVersion18 && directory?.richWorkspace == nil && !isEncrypted && NextcloudKit.shared.isNetworkReachable() {
             actions.append(
                 NCMenuAction(
                     title: NSLocalizedString("_add_folder_info_", comment: ""), icon: UIImage(named: "addFolderInfo")!.image(color: NCBrandColor.shared.gray, size: 50), action: { _ in
@@ -142,7 +141,7 @@ extension AppDelegate {
             )
         }
 
-        if NCCommunication.shared.isNetworkReachable() && directEditingCreators != nil && directEditingCreators!.contains(where: { $0.editor == NCGlobal.shared.editorOnlyoffice && $0.identifier == NCGlobal.shared.onlyofficeDocx}) && !isEncrypted {
+        if NextcloudKit.shared.isNetworkReachable() && directEditingCreators != nil && directEditingCreators!.contains(where: { $0.editor == NCGlobal.shared.editorOnlyoffice && $0.identifier == NCGlobal.shared.onlyofficeDocx}) && !isEncrypted {
             let directEditingCreator = directEditingCreators!.first(where: { $0.editor == NCGlobal.shared.editorOnlyoffice && $0.identifier == NCGlobal.shared.onlyofficeDocx})!
             actions.append(
                 NCMenuAction(
@@ -165,7 +164,7 @@ extension AppDelegate {
             )
         }
 
-        if NCCommunication.shared.isNetworkReachable() && directEditingCreators != nil && directEditingCreators!.contains(where: { $0.editor == NCGlobal.shared.editorOnlyoffice && $0.identifier == NCGlobal.shared.onlyofficeXlsx}) && !isEncrypted {
+        if NextcloudKit.shared.isNetworkReachable() && directEditingCreators != nil && directEditingCreators!.contains(where: { $0.editor == NCGlobal.shared.editorOnlyoffice && $0.identifier == NCGlobal.shared.onlyofficeXlsx}) && !isEncrypted {
             let directEditingCreator = directEditingCreators!.first(where: { $0.editor == NCGlobal.shared.editorOnlyoffice && $0.identifier == NCGlobal.shared.onlyofficeXlsx})!
             actions.append(
                 NCMenuAction(
@@ -188,7 +187,7 @@ extension AppDelegate {
             )
         }
 
-        if NCCommunication.shared.isNetworkReachable() && directEditingCreators != nil && directEditingCreators!.contains(where: { $0.editor == NCGlobal.shared.editorOnlyoffice && $0.identifier == NCGlobal.shared.onlyofficePptx}) && !isEncrypted {
+        if NextcloudKit.shared.isNetworkReachable() && directEditingCreators != nil && directEditingCreators!.contains(where: { $0.editor == NCGlobal.shared.editorOnlyoffice && $0.identifier == NCGlobal.shared.onlyofficePptx}) && !isEncrypted {
             let directEditingCreator = directEditingCreators!.first(where: { $0.editor == NCGlobal.shared.editorOnlyoffice && $0.identifier == NCGlobal.shared.onlyofficePptx})!
             actions.append(
                 NCMenuAction(
@@ -212,7 +211,7 @@ extension AppDelegate {
         }
 
         if let richdocumentsMimetypes = NCManageDatabase.shared.getCapabilitiesServerArray(account: appDelegate.account, elements: NCElementsJSON.shared.capabilitiesRichdocumentsMimetypes) {
-            if richdocumentsMimetypes.count > 0 &&  NCCommunication.shared.isNetworkReachable() && !isEncrypted {
+            if richdocumentsMimetypes.count > 0 &&  NextcloudKit.shared.isNetworkReachable() && !isEncrypted {
                 actions.append(
                     NCMenuAction(
                         title: NSLocalizedString("_create_new_document_", comment: ""), icon: UIImage(named: "create_file_document")!, action: { _ in

+ 14 - 14
iOSClient/Menu/NCCollectionViewCommon+Menu.swift

@@ -27,7 +27,7 @@
 
 import UIKit
 import FloatingPanel
-import NCCommunication
+import NextcloudKit
 import Queuer
 
 extension NCCollectionViewCommon {
@@ -115,9 +115,9 @@ extension NCCollectionViewCommon {
                     title: metadata.favorite ? NSLocalizedString("_remove_favorites_", comment: "") : NSLocalizedString("_add_favorites_", comment: ""),
                     icon: NCUtility.shared.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite),
                     action: { _ in
-                        NCNetworking.shared.favoriteMetadata(metadata) { errorCode, errorDescription in
-                            if errorCode != 0 {
-                                NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                        NCNetworking.shared.favoriteMetadata(metadata) { error in
+                            if error != .success {
+                                NCContentPresenter.shared.showError(error: error)
                             }
                         }
                     }
@@ -166,7 +166,7 @@ extension NCCollectionViewCommon {
         //
         // OPEN with external editor
         //
-        if metadata.classFile == NCCommunicationCommon.typeClassFile.document.rawValue && editors.contains(NCGlobal.shared.editorText) && ((editors.contains(NCGlobal.shared.editorOnlyoffice) || isRichDocument)) {
+        if metadata.classFile == NKCommon.typeClassFile.document.rawValue && editors.contains(NCGlobal.shared.editorText) && ((editors.contains(NCGlobal.shared.editorOnlyoffice) || isRichDocument)) {
 
             var editor = ""
             var title = ""
@@ -212,7 +212,7 @@ extension NCCollectionViewCommon {
         //
         // SAVE
         //
-        if (metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && metadata.contentType != "image/svg+xml") || metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue {
+        if (metadata.classFile == NKCommon.typeClassFile.image.rawValue && metadata.contentType != "image/svg+xml") || metadata.classFile == NKCommon.typeClassFile.video.rawValue {
             actions.append(.saveMediaAction(selectedMediaMetadatas: [metadata]))
         }
 
@@ -220,7 +220,7 @@ extension NCCollectionViewCommon {
         // SAVE AS SCAN
         //
         if #available(iOS 13.0, *) {
-            if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && metadata.contentType != "image/svg+xml" {
+            if metadata.classFile == NKCommon.typeClassFile.image.rawValue && metadata.contentType != "image/svg+xml" {
                 actions.append(
                     NCMenuAction(
                         title: NSLocalizedString("_save_as_scan_", comment: ""),
@@ -275,7 +275,7 @@ extension NCCollectionViewCommon {
         // MODIFY
         //
         if #available(iOS 13.0, *) {
-            if !isFolderEncrypted && metadata.contentType != "image/gif" && metadata.contentType != "image/svg+xml" && (metadata.contentType == "com.adobe.pdf" || metadata.contentType == "application/pdf" || metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue) {
+            if !isFolderEncrypted && metadata.contentType != "image/gif" && metadata.contentType != "image/svg+xml" && (metadata.contentType == "com.adobe.pdf" || metadata.contentType == "application/pdf" || metadata.classFile == NKCommon.typeClassFile.image.rawValue) {
                 actions.append(
                     NCMenuAction(
                         title: NSLocalizedString("_modify_", comment: ""),
@@ -322,15 +322,15 @@ extension NCCollectionViewCommon {
                     title: NSLocalizedString("_e2e_set_folder_encrypted_", comment: ""),
                     icon: NCUtility.shared.loadImage(named: "lock"),
                     action: { _ in
-                        NCCommunication.shared.markE2EEFolder(fileId: metadata.fileId, delete: false) { account, errorCode, errorDescription in
-                            if errorCode == 0 {
+                        NextcloudKit.shared.markE2EEFolder(fileId: metadata.fileId, delete: false) { account, error in
+                            if error == .success {
                                 NCManageDatabase.shared.deleteE2eEncryption(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, serverUrl))
                                 NCManageDatabase.shared.setDirectory(serverUrl: serverUrl, serverUrlTo: nil, etag: nil, ocId: nil, fileId: nil, encrypted: true, richWorkspace: nil, account: metadata.account)
                                 NCManageDatabase.shared.setMetadataEncrypted(ocId: metadata.ocId, encrypted: true)
 
                                 NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterChangeStatusFolderE2EE, userInfo: ["serverUrl": metadata.serverUrl])
                             } else {
-                                NCContentPresenter.shared.messageNotification(NSLocalizedString("_e2e_error_mark_folder_", comment: ""), description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: .error, errorCode: errorCode)
+                                NCContentPresenter.shared.messageNotification(NSLocalizedString("_e2e_error_mark_folder_", comment: ""), error: error, delay: NCGlobal.shared.dismissAfterSecond, type: .error)
                             }
                         }
                     }
@@ -347,15 +347,15 @@ extension NCCollectionViewCommon {
                     title: NSLocalizedString("_e2e_remove_folder_encrypted_", comment: ""),
                     icon: NCUtility.shared.loadImage(named: "lock"),
                     action: { _ in
-                        NCCommunication.shared.markE2EEFolder(fileId: metadata.fileId, delete: true) { account, errorCode, errorDescription in
-                            if errorCode == 0 {
+                        NextcloudKit.shared.markE2EEFolder(fileId: metadata.fileId, delete: true) { account, error in
+                            if error == .success {
                                 NCManageDatabase.shared.deleteE2eEncryption(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, serverUrl))
                                 NCManageDatabase.shared.setDirectory(serverUrl: serverUrl, serverUrlTo: nil, etag: nil, ocId: nil, fileId: nil, encrypted: false, richWorkspace: nil, account: metadata.account)
                                 NCManageDatabase.shared.setMetadataEncrypted(ocId: metadata.ocId, encrypted: false)
 
                                 NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterChangeStatusFolderE2EE, userInfo: ["serverUrl": metadata.serverUrl])
                             } else {
-                                NCContentPresenter.shared.messageNotification(NSLocalizedString("_e2e_error_delete_mark_folder_", comment: ""), description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: .error, errorCode: errorCode)
+                                NCContentPresenter.shared.messageNotification(NSLocalizedString("_e2e_error_delete_mark_folder_", comment: ""), error: error, delay: NCGlobal.shared.dismissAfterSecond, type: .error)
                             }
                         }
                     }

+ 1 - 1
iOSClient/Menu/NCMedia+Menu.swift

@@ -23,7 +23,7 @@
 
 import UIKit
 import FloatingPanel
-import NCCommunication
+import NextcloudKit
 
 extension NCMedia {
     func tapSelect() {

+ 1 - 1
iOSClient/Menu/NCMenuAction.swift

@@ -192,7 +192,7 @@ extension NCMenuAction {
     /// Set (or remove) a file as *available offline*. Downloads the file if not downloaded already
     static func setAvailableOfflineAction(selectedMetadatas: [tableMetadata], isAnyOffline: Bool, viewController: UIViewController, completion: (() -> Void)? = nil) -> NCMenuAction {
         NCMenuAction(
-            title: isAnyOffline ? NSLocalizedString("_remove_available_offline_", comment: "") :  NSLocalizedString("_set_available_offline_", comment: ""),
+            title: isAnyOffline ? NSLocalizedString("_remove_available_offline_", comment: "") : NSLocalizedString("_set_available_offline_", comment: ""),
             icon: NCUtility.shared.loadImage(named: "tray.and.arrow.down"),
             action: { _ in
                 if !isAnyOffline, selectedMetadatas.count > 3 {

+ 53 - 0
iOSClient/Menu/NCNotification+Menu.swift

@@ -0,0 +1,53 @@
+//
+//  NCNotification+Menu.swift
+//  Nextcloud
+//
+//  Created by Marino Faggiana on 31/08/2022.
+//  Copyright © 2022 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 FloatingPanel
+import SwiftyJSON
+import NextcloudKit
+
+extension NCNotification {
+
+    func toggleMenu(notification: NKNotifications) {
+
+        var actions = [NCMenuAction]()
+
+        if let notificationActions = notification.actions, let jsonNotificationActionsActions = JSON(notificationActions).array {
+
+            for action in jsonNotificationActionsActions {
+                let label = action["label"].stringValue
+                actions.append(
+                    NCMenuAction(
+                        title: action["label"].stringValue,
+                        icon: UIImage(),
+                        action: { _ in
+                            self.tapAction(with: notification, label: label)
+                        }
+                    )
+                )
+            }
+        }
+
+        presentMenu(with: actions)
+    }
+}

+ 1 - 1
iOSClient/Menu/NCSortMenu.swift

@@ -23,7 +23,7 @@
 
 import UIKit
 import FloatingPanel
-import NCCommunication
+import NextcloudKit
 
 class NCSortMenu: NSObject {
 

+ 1 - 1
iOSClient/Menu/NCTrash+Menu.swift

@@ -25,7 +25,7 @@
 
 import UIKit
 import FloatingPanel
-import NCCommunication
+import NextcloudKit
 
 extension NCTrash {
     var selectActions: [NCMenuAction] {

+ 11 - 11
iOSClient/Menu/NCViewer+Menu.swift

@@ -23,7 +23,7 @@
 
 import UIKit
 import FloatingPanel
-import NCCommunication
+import NextcloudKit
 
 extension NCViewer {
 
@@ -48,9 +48,9 @@ extension NCViewer {
                     title: titleFavorite,
                     icon: NCUtility.shared.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite),
                     action: { _ in
-                        NCNetworking.shared.favoriteMetadata(metadata) { errorCode, errorDescription in
-                            if errorCode != 0 {
-                                NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                        NCNetworking.shared.favoriteMetadata(metadata) { error in
+                            if error != .success {
+                                NCContentPresenter.shared.showError(error: error)
                             }
                         }
                     }
@@ -90,7 +90,7 @@ extension NCViewer {
         //
         // PRINT
         //
-        if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue || metadata.contentType == "application/pdf" || metadata.contentType == "com.adobe.pdf" {
+        if metadata.classFile == NKCommon.typeClassFile.image.rawValue || metadata.contentType == "application/pdf" || metadata.contentType == "com.adobe.pdf" {
             actions.append(
                 NCMenuAction(
                     title: NSLocalizedString("_print_", comment: ""),
@@ -106,7 +106,7 @@ extension NCViewer {
         // CONVERSION VIDEO TO MPEG4 (MFFF Lib)
         //
 #if MFFFLIB
-        if metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue {
+        if metadata.classFile == NKCommon.typeClassFile.video.rawValue {
             
             actions.append(
                 NCMenuAction(
@@ -125,7 +125,7 @@ extension NCViewer {
         //
         // SAVE IMAGE / VIDEO
         //
-        if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue {
+        if metadata.classFile == NKCommon.typeClassFile.image.rawValue || metadata.classFile == NKCommon.typeClassFile.video.rawValue {
             actions.append(.saveMediaAction(selectedMediaMetadatas: [metadata]))
         }
 
@@ -133,7 +133,7 @@ extension NCViewer {
         // SAVE AS SCAN
         //
         if #available(iOS 13.0, *) {
-            if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && metadata.contentType != "image/svg+xml" {
+            if metadata.classFile == NKCommon.typeClassFile.image.rawValue && metadata.contentType != "image/svg+xml" {
                 actions.append(
                     NCMenuAction(
                         title: NSLocalizedString("_save_as_scan_", comment: ""),
@@ -202,13 +202,13 @@ extension NCViewer {
         // DOWNLOAD IMAGE MAX RESOLUTION
         //
         if metadata.session == "" {
-            if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && !CCUtility.fileProviderStorageExists(metadata) && metadata.session == "" {
+            if metadata.classFile == NKCommon.typeClassFile.image.rawValue && !CCUtility.fileProviderStorageExists(metadata) && metadata.session == "" {
                 actions.append(
                     NCMenuAction(
                         title: NSLocalizedString("_download_image_max_", comment: ""),
                         icon: NCUtility.shared.loadImage(named: "square.and.arrow.down"),
                         action: { _ in
-                            NCNetworking.shared.download(metadata: metadata, selector: "") { _ in }
+                            NCNetworking.shared.download(metadata: metadata, selector: "") { _, _ in }
                         }
                     )
                 )
@@ -244,7 +244,7 @@ extension NCViewer {
         // MODIFY
         //
         if #available(iOS 13.0, *) {
-            if !isFolderEncrypted && metadata.contentType != "image/gif" && (metadata.contentType == "com.adobe.pdf" || metadata.contentType == "application/pdf" || metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue) {
+            if !isFolderEncrypted && metadata.contentType != "image/gif" && (metadata.contentType == "com.adobe.pdf" || metadata.contentType == "application/pdf" || metadata.classFile == NKCommon.typeClassFile.image.rawValue) {
                 actions.append(
                     NCMenuAction(
                         title: NSLocalizedString("_modify_", comment: ""),

+ 12 - 8
iOSClient/Menu/UIViewController+Menu.swift

@@ -23,11 +23,11 @@
 
 import Foundation
 import SVGKit
-import NCCommunication
+import NextcloudKit
 import UIKit
 
 extension UIViewController {
-    fileprivate func handleProfileAction(_ action: NCCHovercard.Action, for userId: String) {
+    fileprivate func handleProfileAction(_ action: NKHovercard.Action, for userId: String) {
         switch action.appId {
         case "email":
             guard
@@ -35,7 +35,8 @@ extension UIViewController {
                 url.scheme == "mailto",
                 let components = URLComponents(url: url, resolvingAgainstBaseURL: false)
             else {
-                NCContentPresenter.shared.showError(description: "_cannot_send_mail_error_")
+                let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_cannot_send_mail_error_")
+                NCContentPresenter.shared.showError(error: error)
                 return
             }
             sendEmail(to: components.path)
@@ -50,7 +51,8 @@ extension UIViewController {
 
         default:
             guard let url = action.hyperlinkUrl, UIApplication.shared.canOpenURL(url) else {
-                NCContentPresenter.shared.showError(description: "_open_url_error_")
+                let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_open_url_error_")
+                NCContentPresenter.shared.showError(error: error)
                 return
             }
             UIApplication.shared.open(url, options: [:])
@@ -63,8 +65,8 @@ extension UIViewController {
         let serverVersionMajor = NCManageDatabase.shared.getCapabilitiesServerInt(account: appDelegate.account, elements: NCElementsJSON.shared.capabilitiesVersionMajor)
         guard serverVersionMajor >= NCGlobal.shared.nextcloudVersion23 else { return }
 
-        NCCommunication.shared.getHovercard(for: userId) { card, _, _ in
-            guard let card = card else { return }
+        NextcloudKit.shared.getHovercard(for: userId) { account, card, _ in
+            guard let card = card, account == appDelegate.account else { return }
 
             let personHeader = NCMenuAction(
                 title: card.displayName,
@@ -94,7 +96,8 @@ extension UIViewController {
 
     func sendEmail(to email: String) {
         guard MFMailComposeViewController.canSendMail() else {
-            NCContentPresenter.shared.showError(description: "_cannot_send_mail_error_")
+            let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_cannot_send_mail_error_")
+            NCContentPresenter.shared.showError(error: error)
             return
         }
 
@@ -108,7 +111,8 @@ extension UIViewController {
     func presentMenu(with actions: [NCMenuAction]) {
         guard !actions.isEmpty else { return }
         guard let menuViewController = NCMenu.makeNCMenu(with: actions) else {
-            NCContentPresenter.shared.showError(description: "_internal_generic_error_")
+            let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_internal_generic_error_")
+            NCContentPresenter.shared.showError(error: error)
             return
         }
 

+ 19 - 19
iOSClient/More/NCMore.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 import MarqueeLabel
 
 class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
@@ -33,10 +33,10 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
     @IBOutlet weak var progressQuota: UIProgressView!
     @IBOutlet weak var viewQuota: UIView!
 
-    var functionMenu: [NCCommunicationExternalSite] = []
-    var externalSiteMenu: [NCCommunicationExternalSite] = []
-    var settingsMenu: [NCCommunicationExternalSite] = []
-    var quotaMenu: [NCCommunicationExternalSite] = []
+    var functionMenu: [NKExternalSite] = []
+    var externalSiteMenu: [NKExternalSite] = []
+    var settingsMenu: [NKExternalSite] = []
+    var quotaMenu: [NKExternalSite] = []
 
     let appDelegate = UIApplication.shared.delegate as! AppDelegate
 
@@ -84,7 +84,7 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
 
     func loadItems() {
 
-        var item = NCCommunicationExternalSite()
+        var item = NKExternalSite()
         var quota: String = ""
 
         // Clear
@@ -96,28 +96,28 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
         progressQuota.progressTintColor = NCBrandColor.shared.brandElement
 
         // ITEM : Transfer
-        item = NCCommunicationExternalSite()
+        item = NKExternalSite()
         item.name = "_transfers_"
         item.icon = "arrow.left.arrow.right"
         item.url = "segueTransfers"
         functionMenu.append(item)
 
         // ITEM : Recent
-        item = NCCommunicationExternalSite()
+        item = NKExternalSite()
         item.name = "_recent_"
         item.icon = "recent"
         item.url = "segueRecent"
         functionMenu.append(item)
 
         // ITEM : Notification
-        item = NCCommunicationExternalSite()
+        item = NKExternalSite()
         item.name = "_notification_"
         item.icon = "bell"
         item.url = "segueNotification"
         functionMenu.append(item)
 
         // ITEM : Activity
-        item = NCCommunicationExternalSite()
+        item = NKExternalSite()
         item.name = "_activity_"
         item.icon = "bolt"
         item.url = "segueActivity"
@@ -126,7 +126,7 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
         // ITEM : Shares
         let isFilesSharingEnabled = NCManageDatabase.shared.getCapabilitiesServerBool(account: appDelegate.account, elements: NCElementsJSON.shared.capabilitiesFileSharingApiEnabled, exists: false)
         if isFilesSharingEnabled {
-            item = NCCommunicationExternalSite()
+            item = NKExternalSite()
             item.name = "_list_shares_"
             item.icon = "share"
             item.url = "segueShares"
@@ -134,7 +134,7 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
         }
 
         // ITEM : Offline
-        item = NCCommunicationExternalSite()
+        item = NKExternalSite()
         item.name = "_manage_file_offline_"
         item.icon = "tray.and.arrow.down"
         item.url = "segueOffline"
@@ -142,7 +142,7 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
 
         // ITEM : Scan
         if #available(iOS 13.0, *) {
-            item = NCCommunicationExternalSite()
+            item = NKExternalSite()
             item.name = "_scanned_images_"
             item.icon = "doc.text.viewfinder"
             item.url = "openStoryboardNCScan"
@@ -153,7 +153,7 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
         let serverVersionMajor = NCManageDatabase.shared.getCapabilitiesServerInt(account: appDelegate.account, elements: NCElementsJSON.shared.capabilitiesVersionMajor)
         if serverVersionMajor >= NCGlobal.shared.nextcloudVersion15 {
 
-            item = NCCommunicationExternalSite()
+            item = NKExternalSite()
             item.name = "_trash_view_"
             item.icon = "trash"
             item.url = "segueTrash"
@@ -161,7 +161,7 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
         }
 
         // ITEM : Settings
-        item = NCCommunicationExternalSite()
+        item = NKExternalSite()
         item.name = "_settings_"
         item.icon = "gear"
         item.url = "segueSettings"
@@ -169,7 +169,7 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
 
         // ITEM: Test API
         if NCUtility.shared.isSimulator() {
-            item = NCCommunicationExternalSite()
+            item = NKExternalSite()
             item.name = "Test API"
             item.icon = "swift"
             item.url = "test"
@@ -214,7 +214,7 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
             if let externalSites = NCManageDatabase.shared.getAllExternalSites(account: appDelegate.account) {
                 for externalSite in externalSites {
                     if (externalSite.name != "" && externalSite.url != ""), let urlEncoded = externalSite.url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) {
-                        item = NCCommunicationExternalSite()
+                        item = NKExternalSite()
                         item.name = externalSite.name
                         item.url = urlEncoded
                         item.icon = "network"
@@ -310,7 +310,7 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
 
     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
 
-        var item = NCCommunicationExternalSite()
+        var item = NKExternalSite()
 
         // change color selection and disclosure indicator
         let selectionColor: UIView = UIView()
@@ -390,7 +390,7 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
     // method to run when table view cell is tapped
     func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
 
-        var item = NCCommunicationExternalSite()
+        var item = NKExternalSite()
 
         if indexPath.section == 0 {
             tapImageLogoManageAccount()

+ 23 - 4
iOSClient/NCGlobal.swift

@@ -220,14 +220,18 @@ class NCGlobal: NSObject {
 
     // Error
     //
-    @objc let errorNoError: Int                     = 0
     @objc let errorRequestExplicityCancelled: Int   = 15
     @objc let errorNotModified: Int                 = 304
     @objc let errorBadRequest: Int                  = 400
+    @objc let errorUnauthorized: Int                = 401
+    @objc let errorForbidden: Int                   = 403
     @objc let errorResourceNotFound: Int            = 404
     @objc let errordMethodNotSupported: Int         = 405
     @objc let errorConflict: Int                    = 409
+    @objc let errorPreconditionFailed: Int          = 412
+    @objc let errorNCUnauthorized: Int              = 997
     @objc let errorConnectionLost: Int              = -1005
+    @objc let errorNetworkNotAvailable: Int         = -1009
     @objc let errorBadServerResponse: Int           = -1011
     @objc let errorInternalError: Int               = -99999
     @objc let errorFileNotSaved: Int                = -99998
@@ -237,7 +241,6 @@ class NCGlobal: NSObject {
     @objc let errorCharactersForbidden: Int         = -99993
     @objc let errorCreationFile: Int                = -99992
     @objc let errorReadFile: Int                    = -99991
-    @objc let errorGeneric: Int                     = -99990
 
     // Constants to identify the different permissions of a file
     //
@@ -339,11 +342,11 @@ class NCGlobal: NSObject {
     let notificationCenterChangeStatusFolderE2EE                = "changeStatusFolderE2EE"          // userInfo: serverUrl
 
     let notificationCenterDownloadStartFile                     = "downloadStartFile"               // userInfo: ocId, serverUrl, account
-    let notificationCenterDownloadedFile                        = "downloadedFile"                  // userInfo: ocId, serverUrl, account, selector, errorCode, errorDescription
+    let notificationCenterDownloadedFile                        = "downloadedFile"                  // userInfo: ocId, serverUrl, account, selector, error
     let notificationCenterDownloadCancelFile                    = "downloadCancelFile"              // userInfo: ocId, serverUrl, account
 
     let notificationCenterUploadStartFile                       = "uploadStartFile"                 // userInfo: ocId, serverUrl, account, fileName, sessionSelector
-    @objc let notificationCenterUploadedFile                    = "uploadedFile"                    // userInfo: ocId, serverUrl, account, fileName, ocIdTemp, errorCode, errorDescription
+    @objc let notificationCenterUploadedFile                    = "uploadedFile"                    // userInfo: ocId, serverUrl, account, fileName, ocIdTemp, error
     let notificationCenterUploadCancelFile                      = "uploadCancelFile"                // userInfo: ocId, serverUrl, account
 
     let notificationCenterProgressTask                          = "progressTask"                    // userInfo: account, ocId, serverUrl, status, progress, totalBytes, totalBytesExpected
@@ -378,4 +381,20 @@ class NCGlobal: NSObject {
     let tipNCCollectionViewCommonAccountRequest                 = "tipnccollectionviewcommonaccountrequest"
     let tipNCScanAddImage                                       = "tipncscanaddimage"
     let tipNCViewerMediaDetailView                              = "tipncviewermediadetailview"
+    
+    // ACTION
+    //
+    let actionNoAction                                          = "no-action"
+    let actionUploadAsset                                       = "upload-asset"
+    let actionScanDocument                                      = "add-scan-document"
+    let actionTextDocument                                      = "create-text-document"
+    let actionVoiceMemo                                         = "create-voice-memo"
+    
+    // WIDGET ACTION
+    //
+    let widgetActionNoAction                                    = URL(string: "nextcloud://open-action?action=no-action")!
+    let widgetActionUploadAsset                                 = URL(string: "nextcloud://open-action?action=upload-asset")!
+    let widgetActionScanDocument                                = URL(string: "nextcloud://open-action?action=add-scan-document")!
+    let widgetActionTextDocument                                = URL(string: "nextcloud://open-action?action=create-text-document")!
+    let widgetActionVoiceMemo                                   = URL(string: "nextcloud://open-action?action=create-voice-memo")!
 }

+ 109 - 21
iOSClient/Networking/NCAutoUpload.swift

@@ -23,8 +23,9 @@
 
 import UIKit
 import CoreLocation
-import NCCommunication
+import NextcloudKit
 import Photos
+import Queuer
 
 class NCAutoUpload: NSObject {
     @objc static let shared: NCAutoUpload = {
@@ -32,13 +33,12 @@ class NCAutoUpload: NSObject {
         return instance
     }()
 
-    private let appDelegate = UIApplication.shared.delegate as! AppDelegate
     private var endForAssetToUpload: Bool = false
 
     // MARK: -
 
     @objc func initAutoUpload(viewController: UIViewController?, completion: @escaping (_ items: Int) -> Void) {
-        guard let activeAccount = NCManageDatabase.shared.getActiveAccount(), activeAccount.autoUpload else {
+        guard let account = NCManageDatabase.shared.getActiveAccount(), account.autoUpload else {
             completion(0)
             return
         }
@@ -58,23 +58,26 @@ class NCAutoUpload: NSObject {
 
     @objc func autoUploadFullPhotos(viewController: UIViewController?, log: String) {
 
-        NCAskAuthorization.shared.askAuthorizationPhotoLibrary(viewController: appDelegate.window?.rootViewController) { hasPermission in
+        NCAskAuthorization.shared.askAuthorizationPhotoLibrary(viewController: viewController) { hasPermission in
             guard hasPermission else { return }
-
-            NCContentPresenter.shared.messageNotification("_attention_", description: "_create_full_upload_", delay: NCGlobal.shared.dismissAfterSecondLong, type: .info, errorCode: NCGlobal.shared.errorNoError, priority: .max)
+            #if !EXTENSION
+            let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_create_full_upload_")
+            NCContentPresenter.shared.showWarning(error: error, priority: .max)
             NCActivityIndicator.shared.start()
+            #endif
             self.uploadAssetsNewAndFull(viewController: viewController, selector: NCGlobal.shared.selectorUploadAutoUploadAll, log: log) { _ in
+                #if !EXTENSION
                 NCActivityIndicator.shared.stop()
+                #endif
             }
         }
     }
 
     private func uploadAssetsNewAndFull(viewController: UIViewController?, selector: String, log: String, completion: @escaping (_ items: Int) -> Void) {
-        guard !appDelegate.account.isEmpty else {
+        guard let account = NCManageDatabase.shared.getActiveAccount() else {
             completion(0)
             return
         }
-        guard let account = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", appDelegate.account)) else { return }
 
         DispatchQueue.global(qos: .background).async {
 
@@ -83,17 +86,27 @@ class NCAutoUpload: NSObject {
 
             self.getCameraRollAssets(viewController: viewController, account: account, selector: selector, alignPhotoLibrary: false) { assets in
                 guard let assets = assets, !assets.isEmpty else {
-                    NCCommunicationCommon.shared.writeLog("Automatic upload, no new assets found [" + log + "]")
+                    #if EXTENSION_WIDGET
+                    NKCommon.shared.writeLog("Automatic upload widget, no new assets found [" + log + "]")
+                    #else
+                    NKCommon.shared.writeLog("Automatic upload, no new assets found [" + log + "]")
+                    #endif
                     completion(0)
                     return
                 }
-                NCCommunicationCommon.shared.writeLog("Automatic upload, new \(assets.count) assets found [" + log + "]")
-
+                #if EXTENSION_WIDGET
+                NKCommon.shared.writeLog("Automatic upload widget, new \(assets.count) assets found [" + log + "]")
+                #else
+                NKCommon.shared.writeLog("Automatic upload, new \(assets.count) assets found [" + log + "]")
+                #endif
                 // Create the folder for auto upload & if request the subfolders
                 if !NCNetworking.shared.createFolder(assets: assets, selector: selector, useSubFolder: account.autoUploadCreateSubfolder, account: account.account, urlBase: account.urlBase) {
+                    #if !EXTENSION
                     if selector == NCGlobal.shared.selectorUploadAutoUploadAll {
-                        NCContentPresenter.shared.messageNotification("_error_", description: "_error_createsubfolders_upload_", delay: NCGlobal.shared.dismissAfterSecond, type: .error, errorCode: NCGlobal.shared.errorInternalError, priority: .max)
+                        let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_error_createsubfolders_upload_")
+                        NCContentPresenter.shared.showError(error: error, priority: .max)
                     }
+                    #endif
                     return completion(0)
                 }
 
@@ -118,7 +131,7 @@ class NCAutoUpload: NSObject {
                     }
 
                     if selector == NCGlobal.shared.selectorUploadAutoUploadAll {
-                        session = NCCommunicationCommon.shared.sessionIdentifierUpload
+                        session = NKCommon.shared.sessionIdentifierUpload
                     } else {
                         if assetMediaType == PHAssetMediaType.image && account.autoUploadWWAnPhoto == false {
                             session = NCNetworking.shared.sessionIdentifierBackground
@@ -154,12 +167,16 @@ class NCAutoUpload: NSObject {
                         metadata.sessionSelector = selector
                         metadata.status = NCGlobal.shared.metadataStatusWaitUpload
                         if assetMediaType == PHAssetMediaType.video {
-                            metadata.classFile = NCCommunicationCommon.typeClassFile.video.rawValue
+                            metadata.classFile = NKCommon.typeClassFile.video.rawValue
                         } else if assetMediaType == PHAssetMediaType.image {
-                            metadata.classFile = NCCommunicationCommon.typeClassFile.image.rawValue
+                            metadata.classFile = NKCommon.typeClassFile.image.rawValue
                         }
                         if selector == NCGlobal.shared.selectorUploadAutoUpload {
-                            NCCommunicationCommon.shared.writeLog("Automatic upload added \(metadata.fileNameView) with Identifier \(metadata.assetLocalIdentifier)")
+                            #if EXTENSION_WIDGET
+                            NKCommon.shared.writeLog("Automatic upload widget added \(metadata.fileNameView) with Identifier \(metadata.assetLocalIdentifier)")
+                            #else
+                            NKCommon.shared.writeLog("Automatic upload added \(metadata.fileNameView) with Identifier \(metadata.assetLocalIdentifier)")
+                            #endif
                             NCManageDatabase.shared.addPhotoLibrary([asset], account: account.account)
                         }
                         metadatas.append(metadata)
@@ -167,18 +184,85 @@ class NCAutoUpload: NSObject {
                 }
 
                 self.endForAssetToUpload = true
+                // AUTO UPLOAD ALL
+                #if !EXTENSION
                 if selector == NCGlobal.shared.selectorUploadAutoUploadAll {
-                    self.appDelegate.networkingProcessUpload?.createProcessUploads(metadatas: metadatas)
-                } else {
-                    self.appDelegate.networkingProcessUpload?.createProcessUploads(metadatas: metadatas, verifyAlreadyExists: true)
+                    (UIApplication.shared.delegate as! AppDelegate).networkingProcessUpload?.createProcessUploads(metadatas: metadatas)
+                    completion(metadatas.count)
                 }
-                completion(metadatas.count)
+                #endif
+                // AUTO UPLOAD
+                self.createProcessUploads(metadatas: metadatas, completion: completion)
             }
         }
     }
 
     // MARK: -
 
+    func createProcessUploads(metadatas: [tableMetadata], completion: @escaping (_ items: Int) -> Void) {
+
+        var metadatasForUpload: [tableMetadata] = []
+        var numStartUpload: Int = 0
+        let maxConcurrentOperationUpload = 5
+
+        for metadata in metadatas {
+            if NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ && serverUrl == %@ && fileName == %@ && session != ''", metadata.account, metadata.serverUrl, metadata.fileName)) != nil {
+                continue
+            }
+            metadatasForUpload.append(metadata)
+        }
+        NCManageDatabase.shared.addMetadatas(metadatasForUpload)
+
+        // Max file in Uploadading
+
+        let metadatasInUpload = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "status == %d OR status == %d", NCGlobal.shared.metadataStatusInUpload, NCGlobal.shared.metadataStatusUploading))
+        let counterUpload = maxConcurrentOperationUpload - metadatasInUpload.count
+        if counterUpload <= 0 {
+            return completion(0)
+        }
+
+        // Extract file
+
+        let metadatas = NCManageDatabase.shared.getAdvancedMetadatas(predicate: NSPredicate(format: "sessionSelector == %@ AND status == %d", NCGlobal.shared.selectorUploadAutoUpload, NCGlobal.shared.metadataStatusWaitUpload), page: 0, limit: counterUpload, sorted: "date", ascending: true)
+
+        for metadata in metadatas {
+
+            let metadata = tableMetadata.init(value: metadata)
+            let semaphore = Semaphore()
+
+            NCUtility.shared.extractFiles(from: metadata) { metadatas in
+                if metadatas.isEmpty {
+                    NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
+                }
+                for metadata in metadatas {
+                    #if !EXTENSION
+                    if (metadata.e2eEncrypted || metadata.chunk) && UIApplication.shared.applicationState != .active {  continue }
+                    #else
+                    if (metadata.e2eEncrypted || metadata.chunk) { continue }
+                    #endif
+                    let isWiFi = NCNetworking.shared.networkReachability == NKCommon.typeReachability.reachableEthernetOrWiFi
+                    if metadata.session == NCNetworking.shared.sessionIdentifierBackgroundWWan && !isWiFi { continue }
+                    guard let metadata = NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusInUpload) else { continue }
+                    // Upload 
+                    let semaphoreUpload = Semaphore()
+                    NCNetworking.shared.upload(metadata: metadata) {
+                        numStartUpload += 1
+                    } completion: { error in
+                        semaphoreUpload.continue()
+                    }
+                    semaphoreUpload.wait()
+                }
+                semaphore.continue()
+            }
+            semaphore.wait()
+        }
+        DispatchQueue.main.async {
+            completion(numStartUpload)
+        }
+    }
+
+    // MARK: -
+
     @objc func alignPhotoLibrary(viewController: UIViewController?) {
         guard let activeAccount = NCManageDatabase.shared.getActiveAccount() else { return }
 
@@ -187,7 +271,11 @@ class NCAutoUpload: NSObject {
             guard let assets = assets else { return }
 
             NCManageDatabase.shared.addPhotoLibrary(assets, account: activeAccount.account)
-            NCCommunicationCommon.shared.writeLog("Align Photo Library \(assets.count)")
+            #if EXTENSION_WIDGET
+            NKCommon.shared.writeLog("Widget align Photo Library \(assets.count)")
+            #else
+            NKCommon.shared.writeLog("Align Photo Library \(assets.count)")
+            #endif
         }
     }
 

File diff suppressed because it is too large
+ 194 - 198
iOSClient/Networking/NCNetworking.swift


+ 32 - 48
iOSClient/Networking/NCNetworkingCheckRemoteUser.swift

@@ -21,78 +21,62 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 
-@objc class NCNetworkingCheckRemoteUser: NSObject {
-    @objc public static let shared: NCNetworkingCheckRemoteUser = {
-        let instance = NCNetworkingCheckRemoteUser()
-        return instance
-    }()
+class NCNetworkingCheckRemoteUser {
 
-    var checkRemoteUserInProgress = false
-
-    @objc func checkRemoteUser(account: String, errorCode: Int, errorDescription: String) {
-
-        if self.checkRemoteUserInProgress {
-            return
-        } else {
-            self.checkRemoteUserInProgress = true
-        }
+    func checkRemoteUser(account: String, error: NKError) {
 
         let serverVersionMajor = NCManageDatabase.shared.getCapabilitiesServerInt(account: account, elements: NCElementsJSON.shared.capabilitiesVersionMajor)
         guard let tableAccount = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", account)) else {
-            self.checkRemoteUserInProgress = false
             return
         }
 
-        if serverVersionMajor >= NCGlobal.shared.nextcloudVersion17 {
-
-            if errorCode == 401 {
-
-                let token = CCUtility.getPassword(account)!
-                if token == "" {
-                    self.checkRemoteUserInProgress = false
-                    return
-                }
+        // remove all process ----
 
-                NCCommunication.shared.getRemoteWipeStatus(serverUrl: tableAccount.urlBase, token: token) { account, wipe, errorCode, _ in
+        NCNetworking.shared.cancelAllTransfer(account: account) { }
+        NCOperationQueue.shared.cancelAllQueue()
+        NCNetworking.shared.cancelAllTask()
 
-                    let appDelegate = UIApplication.shared.delegate as! AppDelegate
-                    if wipe {
+        // -----------------------
 
-                        appDelegate.deleteAccount(account, wipe: true)
-                        NCContentPresenter.shared.messageNotification(tableAccount.user, description: "_wipe_account_", delay: NCGlobal.shared.dismissAfterSecondLong, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError, priority: .max)
-                        NCCommunication.shared.setRemoteWipeCompletition(serverUrl: tableAccount.urlBase, token: token) { _, _, _ in print("wipe") }
+        if serverVersionMajor >= NCGlobal.shared.nextcloudVersion17 {
 
-                    } else {
+            let token = CCUtility.getPassword(account)!
+            if token.isEmpty {
+                return
+            }
 
-                        if UIApplication.shared.applicationState == .active && NCCommunication.shared.isNetworkReachable() && !CCUtility.getPassword(account).isEmpty && !appDelegate.deletePasswordSession {
-                            let description = String.localizedStringWithFormat(NSLocalizedString("_error_check_remote_user_", comment: ""), tableAccount.user, tableAccount.urlBase)
-                            NCContentPresenter.shared.messageNotification("_error_", description: description, delay: NCGlobal.shared.dismissAfterSecondLong, type: NCContentPresenter.messageType.error, errorCode: errorCode, priority: .max)
-                            CCUtility.setPassword(account, password: nil)
-                            appDelegate.deletePasswordSession = true
-                        }
-                    }
+            NextcloudKit.shared.getRemoteWipeStatus(serverUrl: tableAccount.urlBase, token: token) { account, wipe, error in
 
-                    self.checkRemoteUserInProgress = false
-                }
+                let appDelegate = UIApplication.shared.delegate as! AppDelegate
+                if wipe {
 
-            } else {
+                    appDelegate.deleteAccount(account, wipe: true)
+                    let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_wipe_account_")
+                    NCContentPresenter.shared.messageNotification(tableAccount.user, error: error, delay: NCGlobal.shared.dismissAfterSecondLong, type: NCContentPresenter.messageType.error, priority: .max)
+                    NextcloudKit.shared.setRemoteWipeCompletition(serverUrl: tableAccount.urlBase, token: token) { _, _ in print("wipe") }
 
-                NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecondLong, type: NCContentPresenter.messageType.error, errorCode: errorCode, priority: .max)
+                } else {
 
-                self.checkRemoteUserInProgress = false
+                    if UIApplication.shared.applicationState == .active && NextcloudKit.shared.isNetworkReachable() && !CCUtility.getPassword(account).isEmpty && !appDelegate.deletePasswordSession {
+                        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)
+                        CCUtility.setPassword(account, password: nil)
+                        appDelegate.deletePasswordSession = true
+                    }
+                }
             }
 
         } else if CCUtility.getPassword(account) != "" {
 
-            if UIApplication.shared.applicationState == .active &&  NCCommunication.shared.isNetworkReachable() {
+            if UIApplication.shared.applicationState == .active &&  NextcloudKit.shared.isNetworkReachable() {
                 let description = String.localizedStringWithFormat(NSLocalizedString("_error_check_remote_user_", comment: ""), tableAccount.user, tableAccount.urlBase)
-                NCContentPresenter.shared.messageNotification("_error_", description: description, delay: NCGlobal.shared.dismissAfterSecondLong, type: NCContentPresenter.messageType.error, errorCode: errorCode, priority: .max)
+                let error = NKError(errorCode: error.errorCode, errorDescription: description)
+                NCContentPresenter.shared.showError(error: error, priority: .max)
                 CCUtility.setPassword(account, password: nil)
             }
-
-            self.checkRemoteUserInProgress = false
         }
     }
 }

+ 55 - 52
iOSClient/Networking/NCNetworkingChunkedUpload.swift

@@ -22,12 +22,12 @@
 //
 
 import UIKit
-import NCCommunication
 import Queuer
+import NextcloudKit
 
 extension NCNetworking {
 
-    internal func uploadChunkedFile(metadata: tableMetadata, start: @escaping () -> Void, completion: @escaping (_ errorCode: Int, _ errorDescription: String) -> Void) {
+    internal func uploadChunkedFile(metadata: tableMetadata, start: @escaping () -> Void, completion: @escaping (_ error: NKError) -> Void) {
 
         let directoryProviderStorageOcId = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId)!
         let chunkFolder = NCManageDatabase.shared.getChunkFolder(account: metadata.account, ocId: metadata.ocId)
@@ -37,34 +37,33 @@ extension NCNetworking {
         let fileSizeInGB = Double(metadata.size) / 1e9
         let ocIdTemp = metadata.ocId
         let selector = metadata.sessionSelector
-
-        var uploadErrorCode: Int = 0
-        var uploadErrorDescription: String = ""
+        var uploadError = NKError()
 
         var filesNames = NCManageDatabase.shared.getChunks(account: metadata.account, ocId: metadata.ocId)
         if filesNames.count == 0 {
             NCContentPresenter.shared.noteTop(text: NSLocalizedString("_upload_chunk_", comment: ""), image: nil, type: NCContentPresenter.messageType.info, delay: .infinity, priority: .max)
-            filesNames = NCCommunicationCommon.shared.chunkedFile(inputDirectory: directoryProviderStorageOcId, outputDirectory: directoryProviderStorageOcId, fileName: metadata.fileName, chunkSizeMB: chunkSize)
+            filesNames = NKCommon.shared.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()
-                NCContentPresenter.shared.messageNotification("_error_", description: "_err_file_not_found_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorReadFile)
+                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(uploadErrorCode, uploadErrorDescription)
+                return completion(uploadError)
             }
         } else {
             NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": metadata.serverUrl])
         }
 
-        createChunkedFolder(chunkFolderPath: chunkFolderPath, account: metadata.account) { errorCode, errorDescription in
+        createChunkedFolder(chunkFolderPath: chunkFolderPath, account: metadata.account) { error in
 
             NCContentPresenter.shared.dismiss(after: NCGlobal.shared.dismissAfterSecond)
             start()
 
-            guard errorCode == 0 else {
-                self.uploadChunkFileError(metadata: metadata, chunkFolderPath: chunkFolderPath, directoryProviderStorageOcId: directoryProviderStorageOcId, errorCode: errorCode, errorDescription: errorDescription)
-                completion(errorCode, errorDescription)
+            guard error == .success else {
+                self.uploadChunkFileError(metadata: metadata, chunkFolderPath: chunkFolderPath, directoryProviderStorageOcId: directoryProviderStorageOcId, error: error)
+                completion(error)
                 return
             }
 
@@ -82,14 +81,14 @@ extension NCNetworking {
 
                 let semaphore = Semaphore()
 
-                NCCommunication.shared.upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameChunkLocalPath, requestHandler: { request in
+                NextcloudKit.shared.upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameChunkLocalPath, requestHandler: { request in
 
                     self.uploadRequest[fileNameLocalPath] = request
 
                 }, taskHandler: { task in
 
                     NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, sessionError: "", sessionTaskIdentifier: task.taskIdentifier, status: NCGlobal.shared.metadataStatusUploading)
-                    NCCommunicationCommon.shared.writeLog("Upload chunk: " + fileName)
+                    NKCommon.shared.writeLog("Upload chunk: " + fileName)
 
                 }, progressHandler: { progress in
 
@@ -112,26 +111,25 @@ extension NCNetworking {
                                 "totalBytesExpected": NSNumber(value: totalBytesExpected)])
                     }
 
-                }) { _, _, _, _, _, _, _, errorCode, errorDescription in
+                }) { _, _, _, _, _, _, _, error in
 
                     self.uploadRequest.removeValue(forKey: fileNameLocalPath)
-                    uploadErrorCode = errorCode
-                    uploadErrorDescription = errorDescription
+                    uploadError = error
                     semaphore.continue()
                 }
 
                 semaphore.wait()
 
-                if uploadErrorCode == 0 {
+                if uploadError == .success {
                     NCManageDatabase.shared.deleteChunk(account: metadata.account, ocId: metadata.ocId, fileName: fileName)
                 } else {
                     break
                 }
             }
 
-            guard uploadErrorCode == 0 else {
-                self.uploadChunkFileError(metadata: metadata, chunkFolderPath: chunkFolderPath, directoryProviderStorageOcId: directoryProviderStorageOcId, errorCode: uploadErrorCode, errorDescription: uploadErrorDescription)
-                completion(errorCode, errorDescription)
+            guard uploadError == .success else {
+                self.uploadChunkFileError(metadata: metadata, chunkFolderPath: chunkFolderPath, directoryProviderStorageOcId: directoryProviderStorageOcId, error: uploadError)
+                completion(error)
                 return
             }
 
@@ -140,12 +138,12 @@ extension NCNetworking {
             let pathServerUrl = CCUtility.returnPathfromServerUrl(metadata.serverUrl, urlBase: metadata.urlBase, account: metadata.account)!
             let serverUrlFileNameDestination = metadata.urlBase + "/" + NCUtilityFileSystem.shared.getWebDAV(account: metadata.account) + "/files/" + metadata.userId + pathServerUrl + "/" + metadata.fileName
 
-            var addCustomHeaders: [String: String] = [:]
+            var customHeader: [String: String] = [:]
             let creationDate = "\(metadata.creationDate.timeIntervalSince1970)"
             let modificationDate = "\(metadata.date.timeIntervalSince1970)"
 
-            addCustomHeaders["X-OC-CTime"] = creationDate
-            addCustomHeaders["X-OC-MTime"] = modificationDate
+            customHeader["X-OC-CTime"] = creationDate
+            customHeader["X-OC-MTime"] = modificationDate
 
             // Calculate Assemble Timeout
             let ASSEMBLE_TIME_PER_GB: Double    = 3 * 60            // 3  min
@@ -153,13 +151,15 @@ extension NCNetworking {
             let ASSEMBLE_TIME_MAX: Double       = 30 * 60           // 30 min
             let timeout = max(ASSEMBLE_TIME_MIN, min(ASSEMBLE_TIME_PER_GB * fileSizeInGB, ASSEMBLE_TIME_MAX))
 
-            NCCommunication.shared.moveFileOrFolder(serverUrlFileNameSource: serverUrlFileNameSource, serverUrlFileNameDestination: serverUrlFileNameDestination, overwrite: true, addCustomHeaders: addCustomHeaders, timeout: timeout, queue: DispatchQueue.global(qos: .background)) { _, errorCode, errorDescription in
+            let options = NKRequestOptions(customHeader: customHeader, timeout: timeout, queue: DispatchQueue.global(qos: .background))
+            
+            NextcloudKit.shared.moveFileOrFolder(serverUrlFileNameSource: serverUrlFileNameSource, serverUrlFileNameDestination: serverUrlFileNameDestination, overwrite: true, options: options) { _, error in
 
-                NCCommunicationCommon.shared.writeLog("Assembling chunk with error code: \(errorCode)")
+                NKCommon.shared.writeLog("Assembling chunk with error code: \(error.errorCode)")
 
-                guard uploadErrorCode == 0 else {
-                    self.uploadChunkFileError(metadata: metadata, chunkFolderPath: chunkFolderPath, directoryProviderStorageOcId: directoryProviderStorageOcId, errorCode: errorCode, errorDescription: errorDescription)
-                    completion(errorCode, errorDescription)
+                guard error == .success else {
+                    self.uploadChunkFileError(metadata: metadata, chunkFolderPath: chunkFolderPath, directoryProviderStorageOcId: directoryProviderStorageOcId, error: error)
+                    completion(error)
                     return
                 }
 
@@ -173,9 +173,9 @@ extension NCNetworking {
                 NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp))
                 NCManageDatabase.shared.deleteChunks(account: metadata.account, ocId: ocIdTemp)
 
-                self.readFile(serverUrlFileName: serverUrlFileNameDestination) { (_, metadata, _, _) in
+                self.readFile(serverUrlFileName: serverUrlFileNameDestination) { (_, metadata, _) in
 
-                    if errorCode == 0, let metadata = metadata {
+                    if error == .success, let metadata = metadata {
 
                         metadata.assetLocalIdentifier = assetLocalIdentifier
                         metadata.e2eEncrypted = isE2eEncrypted
@@ -194,68 +194,71 @@ extension NCNetworking {
                         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, "errorCode": errorCode, "errorDescription": ""])
+                        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, userInfo: ["serverUrl": serverUrl])
-                        NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": ocIdTemp, "serverUrl": serverUrl, "account": account, "fileName": fileName, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
+                        NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": ocIdTemp, "serverUrl": serverUrl, "account": account, "fileName": fileName, "ocIdTemp": ocIdTemp, "error": error])
                     }
 
-                    completion(errorCode, errorDescription)
+                    completion(error)
                 }
             }
         }
     }
 
-    private func createChunkedFolder(chunkFolderPath: String, account: String, completion: @escaping (_ errorCode: Int, _ errorDescription: String) -> Void) {
+    private func createChunkedFolder(chunkFolderPath: String, account: String, completion: @escaping (_ errorCode: NKError) -> Void) {
 
-        NCCommunication.shared.readFileOrFolder(serverUrlFileName: chunkFolderPath, depth: "0", showHiddenFiles: CCUtility.getShowHiddenFiles(), queue: NCCommunicationCommon.shared.backgroundQueue) { _, _, _, errorCode, errorDescription in
+        let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
+        
+        NextcloudKit.shared.readFileOrFolder(serverUrlFileName: chunkFolderPath, depth: "0", showHiddenFiles: CCUtility.getShowHiddenFiles(), options: options) { _, _, _, error in
 
-            if errorCode == 0 {
-                completion(0, "")
-            } else if errorCode == NCGlobal.shared.errorResourceNotFound {
-                NCCommunication.shared.createFolder(chunkFolderPath, queue: NCCommunicationCommon.shared.backgroundQueue) { _, _, _, errorCode, errorDescription in
-                    completion(errorCode, errorDescription)
+            if error == .success {
+                completion(NKError())
+            } else if error.errorCode == NCGlobal.shared.errorResourceNotFound {
+                NextcloudKit.shared.createFolder(chunkFolderPath, options: options) { _, _, _, error in
+                    completion(error)
                 }
             } else {
-                completion(errorCode, errorDescription)
+                completion(error)
             }
         }
     }
 
-    private func uploadChunkFileError(metadata: tableMetadata, chunkFolderPath: String, directoryProviderStorageOcId: String, errorCode: Int, errorDescription: String) {
+    private func uploadChunkFileError(metadata: tableMetadata, chunkFolderPath: String, directoryProviderStorageOcId: String, error: NKError) {
 
-        var errorDescription = errorDescription
+        var errorDescription = error.errorDescription
 
-        NCCommunicationCommon.shared.writeLog("Upload chunk error code: \(errorCode)")
+        NKCommon.shared.writeLog("Upload chunk error code: \(error.errorCode)")
 
-        if errorCode == NSURLErrorCancelled || errorCode == NCGlobal.shared.errorRequestExplicityCancelled {
+        if error.errorCode == NSURLErrorCancelled || error.errorCode == NCGlobal.shared.errorRequestExplicityCancelled {
 
             // Delete chunk folder
-            NCCommunication.shared.deleteFileOrFolder(chunkFolderPath) { _, _, _ in }
+            NextcloudKit.shared.deleteFileOrFolder(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)
 
-            NCCommunication.shared.deleteFileOrFolder(chunkFolderPath) { _, _, _ in }
+            NextcloudKit.shared.deleteFileOrFolder(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 errorCode == NCGlobal.shared.errorConnectionLost {
+            if error.errorCode == NCGlobal.shared.errorConnectionLost {
                 errorDescription = ""
             } else {
-                let description = errorDescription + " code: \(errorCode)"
-                NCContentPresenter.shared.messageNotification("_error_", description: description, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError)
+                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, "errorCode": errorCode, "errorDescription": ""])
+        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])
     }
 }

+ 83 - 90
iOSClient/Networking/NCNetworkingE2EE.swift

@@ -21,7 +21,7 @@
 
 import UIKit
 import OpenSSL
-import NCCommunication
+import NextcloudKit
 import CFNetwork
 import Alamofire
 
@@ -33,7 +33,7 @@ import Alamofire
 
     // MARK: - WebDav Create Folder
 
-    func createFolder(fileName: String, serverUrl: String, account: String, urlBase: String, completion: @escaping (_ errorCode: Int, _ errorDescription: String) -> Void) {
+    func createFolder(fileName: String, serverUrl: String, account: String, urlBase: String, completion: @escaping (_ error: NKError) -> Void) {
 
         var fileNameFolder = CCUtility.removeForbiddenCharactersServer(fileName)!
         var fileNameFolderUrl = ""
@@ -43,25 +43,27 @@ import Alamofire
 
         fileNameFolder = NCUtilityFileSystem.shared.createFileName(fileNameFolder, serverUrl: serverUrl, account: account)
         if fileNameFolder.count == 0 {
-            return completion(0, "")
+            return completion(NKError())
         }
         fileNameIdentifier = CCUtility.generateRandomIdentifier()
         fileNameFolderUrl = serverUrl + "/" + fileNameIdentifier
 
-        self.lock(account: account, serverUrl: serverUrl) { directory, e2eToken, errorCode, errorDescription in
-            if errorCode == 0 && e2eToken != nil && directory != nil {
+        self.lock(account: account, serverUrl: serverUrl) { directory, e2eToken, error in
+            if error == .success && e2eToken != nil && directory != nil {
 
-                NCCommunication.shared.createFolder(fileNameFolderUrl, addCustomHeaders: ["e2e-token": e2eToken!]) { account, ocId, _, errorCode, errorDescription in
-                    if errorCode == 0 {
+                let options = NKRequestOptions(customHeader: ["e2e-token": e2eToken!])
+                
+                NextcloudKit.shared.createFolder(fileNameFolderUrl, options: options) { account, ocId, _, error in
+                    if error == .success {
                         guard let fileId = NCUtility.shared.ocIdToFileId(ocId: ocId) else {
                             // unlock
                             if let tableLock = NCManageDatabase.shared.getE2ETokenLock(account: account, serverUrl: serverUrl) {
-                                NCCommunication.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _, _ in }
+                                NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _ in }
                             }
-                            return completion(NCGlobal.shared.errorInternalError, "Error convert ocId")
+                            return completion(NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "Error convert ocId"))
                         }
-                        NCCommunication.shared.markE2EEFolder(fileId: fileId, delete: false) { account, errorCode, errorDescription in
-                            if errorCode == 0 {
+                        NextcloudKit.shared.markE2EEFolder(fileId: fileId, delete: false) { account, error in
+                            if error == .success {
 
                                 let object = tableE2eEncryption()
 
@@ -88,86 +90,87 @@ import Alamofire
 
                                 NCManageDatabase.shared.addE2eEncryption(object)
 
-                                self.sendE2EMetadata(account: account, serverUrl: serverUrl, fileNameRename: nil, fileNameNewRename: nil, deleteE2eEncryption: nil, urlBase: urlBase) { e2eToken, errorCode, errorDescription in
+                                self.sendE2EMetadata(account: account, serverUrl: serverUrl, fileNameRename: nil, fileNameNewRename: nil, deleteE2eEncryption: nil, urlBase: urlBase) { e2eToken, error in
                                     // unlock
                                     if let tableLock = NCManageDatabase.shared.getE2ETokenLock(account: account, serverUrl: serverUrl) {
-                                        NCCommunication.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _, _ in }
+                                        NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _ in }
                                     }
-                                    if errorCode == 0 {
+                                    if error == .success {
                                         NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterCreateFolder, userInfo: nil)
                                     }
-                                    completion(errorCode, errorDescription)
+                                    completion(error)
                                 }
 
                             } else {
                                 // unlock
                                 if let tableLock = NCManageDatabase.shared.getE2ETokenLock(account: account, serverUrl: serverUrl) {
-                                    NCCommunication.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _, _ in }
+                                    NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _ in }
                                 }
-                                completion(errorCode, errorDescription)
+                                completion(error)
                             }
                         }
 
                     } else {
                         // unlock
                         if let tableLock = NCManageDatabase.shared.getE2ETokenLock(account: account, serverUrl: serverUrl) {
-                            NCCommunication.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _, _ in }
+                            NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _ in }
                         }
-                        completion(errorCode, errorDescription)
+                        completion(error)
                     }
                 }
             } else {
-                completion(errorCode, errorDescription ?? "")
+                completion(error)
             }
         }
     }
 
     // MARK: - WebDav Delete
 
-    func deleteMetadata(_ metadata: tableMetadata, completion: @escaping (_ errorCode: Int, _ errorDescription: String) -> Void) {
+    func deleteMetadata(_ metadata: tableMetadata, completion: @escaping (_ error: NKError) -> Void) {
 
-        self.lock(account: metadata.account, serverUrl: metadata.serverUrl) { directory, e2eToken, errorCode, errorDescription in
-            if errorCode == 0 && e2eToken != nil && directory != nil {
+        self.lock(account: metadata.account, serverUrl: metadata.serverUrl) { directory, e2eToken, error in
+            if error == .success && e2eToken != nil && directory != nil {
+                
                 let deleteE2eEncryption = NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileNameIdentifier == %@", metadata.account, metadata.serverUrl, metadata.fileName)
-                NCNetworking.shared.deleteMetadataPlain(metadata, addCustomHeaders: ["e2e-token": e2eToken!]) { errorCode, errorDescription in
+                NCNetworking.shared.deleteMetadataPlain(metadata, customHeader: ["e2e-token": e2eToken!]) { error in
 
                     let home = NCUtilityFileSystem.shared.getHomeServer(account: metadata.account)
                     if metadata.serverUrl != home {
-                        self.sendE2EMetadata(account: metadata.account, serverUrl: metadata.serverUrl, fileNameRename: nil, fileNameNewRename: nil, deleteE2eEncryption: deleteE2eEncryption, urlBase: metadata.urlBase) { e2eToken, errorCode, errorDescription in
+                        self.sendE2EMetadata(account: metadata.account, serverUrl: metadata.serverUrl, fileNameRename: nil, fileNameNewRename: nil, deleteE2eEncryption: deleteE2eEncryption, urlBase: metadata.urlBase) { e2eToken, error in
                             // unlock
                             if let tableLock = NCManageDatabase.shared.getE2ETokenLock(account: metadata.account, serverUrl: metadata.serverUrl) {
-                                NCCommunication.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _, _ in }
+                                NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _ in }
                             }
-                            completion(errorCode, errorDescription)
+                            completion(error)
                         }
                     } else {
                         // unlock
                         if let tableLock = NCManageDatabase.shared.getE2ETokenLock(account: metadata.account, serverUrl: metadata.serverUrl) {
-                            NCCommunication.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _, _ in }
+                            NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _ in }
                         }
-                        completion(errorCode, errorDescription)
+                        completion(error)
                     }
                 }
             } else {
-                completion(errorCode, errorDescription ?? "")
+                completion(error)
             }
         }
     }
 
     // MARK: - WebDav Rename
 
-    func renameMetadata(_ metadata: tableMetadata, fileNameNew: String, completion: @escaping (_ errorCode: Int, _ errorDescription: String?) -> Void) {
+    func renameMetadata(_ metadata: tableMetadata, fileNameNew: String, completion: @escaping (_ error: NKError) -> Void) {
 
         // verify if exists the new fileName
         if NCManageDatabase.shared.getE2eEncryption(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", metadata.account, metadata.serverUrl, fileNameNew)) != nil {
 
-            completion(NCGlobal.shared.errorInternalError, "_file_already_exists_")
+            return completion(NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_file_already_exists_"))
 
         } else {
 
-            self.sendE2EMetadata(account: metadata.account, serverUrl: metadata.serverUrl, fileNameRename: metadata.fileName, fileNameNewRename: fileNameNew, deleteE2eEncryption: nil, urlBase: metadata.urlBase) { e2eToken, errorCode, errorDescription in
+            self.sendE2EMetadata(account: metadata.account, serverUrl: metadata.serverUrl, fileNameRename: metadata.fileName, fileNameNewRename: fileNameNew, deleteE2eEncryption: nil, urlBase: metadata.urlBase) { e2eToken, error in
 
-                if errorCode == 0 {
+                if error == .success {
                     NCManageDatabase.shared.setMetadataFileNameView(serverUrl: metadata.serverUrl, fileName: metadata.fileName, newFileNameView: fileNameNew, account: metadata.account)
 
                     // Move file system
@@ -182,17 +185,17 @@ import Alamofire
 
                 // unlock
                 if let tableLock = NCManageDatabase.shared.getE2ETokenLock(account: metadata.account, serverUrl: metadata.serverUrl) {
-                    NCCommunication.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _, _ in }
+                    NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _ in }
                 }
 
-                completion(errorCode, errorDescription)
+                completion(error)
             }
         }
     }
 
     // MARK: - Upload
 
-    func upload(metadata: tableMetadata, start: @escaping () -> Void, completion: @escaping (_ errorCode: Int, _ errorDescription: String) -> Void) {
+    func upload(metadata: tableMetadata, start: @escaping () -> Void, completion: @escaping (_ error: NKError) -> Void) {
 
         let objectE2eEncryption = tableE2eEncryption()
         var key: NSString?, initializationVector: NSString?, authenticationTag: NSString?
@@ -202,16 +205,16 @@ import Alamofire
         // Verify max size
         if metadata.size > NCGlobal.shared.e2eeMaxFileSize {
             NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp))
-            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "errorCode": NCGlobal.shared.errorInternalError, "errorDescription": "E2E Error file too big"])
+            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "error": NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "E2E Error file too big")])
             start()
-            return completion(NCGlobal.shared.errorInternalError, "E2E Error file too big")
+            return completion(NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "E2E Error file too big"))
         }
 
         // Update metadata
         var metadata = tableMetadata.init(value: metadata)
         metadata.fileName = CCUtility.generateRandomIdentifier()!
         metadata.e2eEncrypted = true
-        metadata.session = NCCommunicationCommon.shared.sessionIdentifierUpload
+        metadata.session = NKCommon.shared.sessionIdentifierUpload
         metadata.sessionError = ""
         NCManageDatabase.shared.addMetadata(metadata)
 
@@ -221,9 +224,9 @@ import Alamofire
 
         if NCEndToEndEncryption.sharedManager()?.encryptFileName(metadata.fileNameView, fileNameIdentifier: metadata.fileName, directory: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId), key: &key, initializationVector: &initializationVector, authenticationTag: &authenticationTag) == false {
             NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp))
-            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "errorCode": NCGlobal.shared.errorInternalError, "errorDescription": "_e2e_error_create_encrypted_"])
+            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "error": NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_e2e_error_create_encrypted_")])
             start()
-            return completion(NCGlobal.shared.errorInternalError, "_e2e_error_create_encrypted_")
+            return completion(NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_e2e_error_create_encrypted_"))
         }
 
         if let result = NCManageDatabase.shared.getE2eEncryption(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, serverUrl)) {
@@ -252,18 +255,18 @@ import Alamofire
             metadata = getMetadata
         } else {
             start()
-            return completion(NCGlobal.shared.errorInternalError, "_e2e_error_create_encrypted_")
+            return completion(NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_e2e_error_create_encrypted_"))
         }
 
         NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": metadata.serverUrl])
         NCContentPresenter.shared.noteTop(text: NSLocalizedString("_upload_e2ee_", comment: ""), image: nil, type: NCContentPresenter.messageType.info, delay: NCGlobal.shared.dismissAfterSecond, priority: .max)
-        NCNetworkingE2EE.shared.sendE2EMetadata(account: metadata.account, serverUrl: serverUrl, fileNameRename: nil, fileNameNewRename: nil, deleteE2eEncryption: nil, urlBase: metadata.urlBase, upload: true) { e2eToken, errorCode, errorDescription in
+        NCNetworkingE2EE.shared.sendE2EMetadata(account: metadata.account, serverUrl: serverUrl, fileNameRename: nil, fileNameNewRename: nil, deleteE2eEncryption: nil, urlBase: metadata.urlBase, upload: true) { e2eToken, error in
 
             start()
 
-            if errorCode == 0 && e2eToken != nil {
+            if error == .success && e2eToken != nil {
 
-                NCCommunication.shared.upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, dateCreationFile: metadata.date as Date, dateModificationFile: metadata.date as Date, addCustomHeaders: ["e2e-token": e2eToken!], requestHandler: { request in
+                NextcloudKit.shared.upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, dateCreationFile: metadata.date as Date, dateModificationFile: metadata.date as Date, addCustomHeaders: ["e2e-token": e2eToken!], requestHandler: { request in
 
                     NCNetworking.shared.uploadRequest[fileNameLocalPathRequest] = request
                     NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: nil, sessionSelector: nil, sessionTaskIdentifier: nil, status: NCGlobal.shared.metadataStatusUploading)
@@ -285,18 +288,18 @@ import Alamofire
                             "totalBytes": NSNumber(value: progress.totalUnitCount),
                             "totalBytesExpected": NSNumber(value: progress.completedUnitCount)])
 
-                }) { account, ocId, etag, date, _, _, error, errorCode, errorDescription in
+                }) { account, ocId, etag, date, _, _, afError, error in
 
                     NCNetworking.shared.uploadRequest.removeValue(forKey: fileNameLocalPath)
                     if let metadata = NCManageDatabase.shared.getMetadataFromOcId(metadata.ocId) {
-                        if error?.isExplicitlyCancelledError ?? false {
+                        if afError?.isExplicitlyCancelledError ?? false {
 
                             CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
                             NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
-                            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
-                            completion(0, "")
+                            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "error": error])
+                            completion(NKError())
 
-                        } else if errorCode == 0 && ocId != nil {
+                        } else if error == .success && ocId != nil {
 
                             NCUtilityFileSystem.shared.moveFileInBackground(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId), toPath: CCUtility.getDirectoryProviderStorageOcId(ocId))
 
@@ -314,95 +317,85 @@ import Alamofire
                             NCManageDatabase.shared.addLocalFile(metadata: metadata)
 
                             NCUtility.shared.createImageFrom(fileNameView: metadata.fileNameView, ocId: metadata.ocId, etag: metadata.etag, classFile: metadata.classFile)
-                            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
+                            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 {
 
-                            if errorCode == 401 || errorCode == 403 {
+                            NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: error.errorDescription, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusUploadError)
 
-                                #if !EXTENSION
-                                NCNetworkingCheckRemoteUser.shared.checkRemoteUser(account: metadata.account, errorCode: errorCode, errorDescription: errorDescription)
-                                #endif
-                                NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: errorDescription, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusUploadError)
-                                
-                            } else {
-
-                                NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: errorDescription, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusUploadError)
-                            }
-
-                            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
+                            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "error": error])
                         }
                     }
-                    NCNetworkingE2EE.shared.unlock(account: metadata.account, serverUrl: serverUrl) { _, _, _, _ in
-                        completion(errorCode, errorDescription)
+                    NCNetworkingE2EE.shared.unlock(account: metadata.account, serverUrl: serverUrl) { _, _, _ in
+                        completion(error)
                     }
                 }
 
             } else {
 
                 if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocIdTemp) {
-                    NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: errorDescription, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusUploadError)
-                    NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": errorDescription])
+                    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])
                 }
-                completion(errorCode, errorDescription)
+                completion(error)
             }
         }
     }
 
     // MARK: - E2EE
 
-    @objc func lock(account: String, serverUrl: String, completion: @escaping (_ direcrtory: tableDirectory?, _ e2eToken: String?, _ errorCode: Int, _ errorDescription: String?) -> Void) {
+    @objc func lock(account: String, serverUrl: String, completion: @escaping (_ direcrtory: tableDirectory?, _ e2eToken: String?, _ error: NKError) -> Void) {
 
         var e2eToken: String?
 
         guard let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", account, serverUrl)) else {
-            return completion(nil, nil, 0, "")
+            return completion(nil, nil, NKError())
         }
 
         if let tableLock = NCManageDatabase.shared.getE2ETokenLock(account: account, serverUrl: serverUrl) {
             e2eToken = tableLock.e2eToken
         }
 
-        NCCommunication.shared.lockE2EEFolder(fileId: directory.fileId, e2eToken: e2eToken, method: "POST") { account, e2eToken, errorCode, errorDescription in
-            if errorCode == 0 && e2eToken != nil {
+        NextcloudKit.shared.lockE2EEFolder(fileId: directory.fileId, e2eToken: e2eToken, method: "POST") { account, e2eToken, error in
+            if error == .success && e2eToken != nil {
                 NCManageDatabase.shared.setE2ETokenLock(account: account, serverUrl: serverUrl, fileId: directory.fileId, e2eToken: e2eToken!)
             }
-            completion(directory, e2eToken, errorCode, errorDescription)
+            completion(directory, e2eToken, error)
         }
     }
 
-    @objc func unlock(account: String, serverUrl: String, completion: @escaping (_ direcrtory: tableDirectory?, _ e2eToken: String?, _ errorCode: Int, _ errorDescription: String?) -> Void) {
+    @objc func unlock(account: String, serverUrl: String, completion: @escaping (_ direcrtory: tableDirectory?, _ e2eToken: String?, _ error: NKError) -> Void) {
 
         var e2eToken: String?
 
         guard let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", account, serverUrl)) else {
-            return completion(nil, nil, 0, "")
+            return completion(nil, nil, NKError())
         }
 
         if let tableLock = NCManageDatabase.shared.getE2ETokenLock(account: account, serverUrl: serverUrl) {
             e2eToken = tableLock.e2eToken
         }
 
-        NCCommunication.shared.lockE2EEFolder(fileId: directory.fileId, e2eToken: e2eToken, method: "DELETE") { account, e2eToken, errorCode, errorDescription in
-            if errorCode == 0 {
+        NextcloudKit.shared.lockE2EEFolder(fileId: directory.fileId, e2eToken: e2eToken, method: "DELETE") { account, e2eToken, error in
+            if error == .success {
                 NCManageDatabase.shared.deteleE2ETokenLock(account: account, serverUrl: serverUrl)
             }
-            completion(directory, e2eToken, errorCode, errorDescription)
+            completion(directory, e2eToken, error)
         }
     }
 
-    @objc func sendE2EMetadata(account: String, serverUrl: String, fileNameRename: String?, fileNameNewRename: String?, deleteE2eEncryption: NSPredicate?, urlBase: String, upload: Bool = false, completion: @escaping (_ e2eToken: String?, _ errorCode: Int, _ errorDescription: String) -> Void) {
+    @objc func sendE2EMetadata(account: String, serverUrl: String, fileNameRename: String?, fileNameNewRename: String?, deleteE2eEncryption: NSPredicate?, urlBase: String, upload: Bool = false, completion: @escaping (_ e2eToken: String?, _ error: NKError) -> Void) {
 
-        self.lock(account: account, serverUrl: serverUrl) { directory, e2eToken, errorCode, errorDescription in
-            if errorCode == 0 && e2eToken != nil && directory != nil {
+        self.lock(account: account, serverUrl: serverUrl) { directory, e2eToken, error in
+            if error == .success && e2eToken != nil && directory != nil {
 
-                NCCommunication.shared.getE2EEMetadata(fileId: directory!.fileId, e2eToken: e2eToken) { account, e2eMetadata, errorCode, errorDescription in
+                NextcloudKit.shared.getE2EEMetadata(fileId: directory!.fileId, e2eToken: e2eToken) { account, e2eMetadata, error in
                     var method = "POST"
                     var e2eMetadataNew: String?
 
-                    if errorCode == 0 && e2eMetadata != nil {
+                    if error == .success && e2eMetadata != nil {
                         if !NCEndToEndMetadata.shared.decoderMetadata(e2eMetadata!, privateKey: CCUtility.getEndToEndPrivateKey(account), serverUrl: serverUrl, account: account, urlBase: urlBase) {
-                            return completion(e2eToken, NCGlobal.shared.errorInternalError, NSLocalizedString("_e2e_error_encode_metadata_", comment: ""))
+                            return completion(e2eToken, NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: NSLocalizedString("_e2e_error_encode_metadata_", comment: "")))
                         }
                         method = "PUT"
                     }
@@ -425,19 +418,19 @@ import Alamofire
                         method = "DELETE"
                     }
 
-                    NCCommunication.shared.putE2EEMetadata(fileId: directory!.fileId, e2eToken: e2eToken!, e2eMetadata: e2eMetadataNew, method: method) { account, _, errorCode, errorDescription in
+                    NextcloudKit.shared.putE2EEMetadata(fileId: directory!.fileId, e2eToken: e2eToken!, e2eMetadata: e2eMetadataNew, method: method) { account, _, error in
 
                         if upload {
-                            completion(e2eToken, errorCode, errorDescription)
+                            completion(e2eToken, error)
                         } else {
-                            self.unlock(account: account, serverUrl: serverUrl) { _, e2eToken, _, _ in
-                                completion(e2eToken, errorCode, errorDescription)
+                            self.unlock(account: account, serverUrl: serverUrl) { _, e2eToken, _ in
+                                completion(e2eToken, error)
                             }
                         }
                     }
                 }
             } else {
-                completion(e2eToken, errorCode, errorDescription ?? "")
+                completion(e2eToken, error)
             }
         }
     }

+ 24 - 65
iOSClient/Networking/NCNetworkingProcessUpload.swift

@@ -22,13 +22,12 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 import Photos
 import Queuer
 
 class NCNetworkingProcessUpload: NSObject {
 
-    let appDelegate = UIApplication.shared.delegate as! AppDelegate
     var timerProcess: Timer?
 
     let maxConcurrentOperationUpload = 5
@@ -54,11 +53,12 @@ class NCNetworkingProcessUpload: NSObject {
     }
 
     @objc private func process() {
-        guard !appDelegate.account.isEmpty else { return }
+        guard let account = NCManageDatabase.shared.getActiveAccount() else {
+            return
+        }
 
         stopTimer()
 
-        let applicationState = UIApplication.shared.applicationState
         var counterUpload: Int = 0
         let sessionSelectors = [NCGlobal.shared.selectorUploadFileNODelete, NCGlobal.shared.selectorUploadFile, NCGlobal.shared.selectorUploadAutoUpload, NCGlobal.shared.selectorUploadAutoUploadAll]
         let metadatasUpload = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "status == %d OR status == %d", NCGlobal.shared.metadataStatusInUpload, NCGlobal.shared.metadataStatusUploading))
@@ -78,20 +78,20 @@ class NCNetworkingProcessUpload: NSObject {
                     let limit = self.maxConcurrentOperationUpload - counterUpload
                     let metadatas = NCManageDatabase.shared.getAdvancedMetadatas(predicate: NSPredicate(format: "sessionSelector == %@ AND status == %d", sessionSelector, NCGlobal.shared.metadataStatusWaitUpload), page: 1, limit: limit, sorted: "date", ascending: true)
                     if metadatas.count > 0 {
-                        NCCommunicationCommon.shared.writeLog("PROCESS-UPLOAD find \(metadatas.count) items")
+                        NKCommon.shared.writeLog("PROCESS-UPLOAD find \(metadatas.count) items")
                     }
 
                     for metadata in metadatas {
 
                         // Different account
-                        if self.appDelegate.account != metadata.account {
-                            NCCommunicationCommon.shared.writeLog("Process auto upload skipped file: \(metadata.serverUrl)/\(metadata.fileNameView) on account: \(metadata.account), because the actual account is \(self.appDelegate.account).")
+                        if account.account != metadata.account {
+                            NKCommon.shared.writeLog("Process auto upload skipped file: \(metadata.serverUrl)/\(metadata.fileNameView) on account: \(metadata.account), because the actual account is \(account.account).")
                             continue
                         }
 
                         // Is already in upload background? skipped
                         if listOcId.contains(metadata.ocId) {
-                            NCCommunicationCommon.shared.writeLog("Process auto upload skipped file: \(metadata.serverUrl)/\(metadata.fileNameView), because is already in session.")
+                            NKCommon.shared.writeLog("Process auto upload skipped file: \(metadata.serverUrl)/\(metadata.fileNameView), because is already in session.")
                             continue
                         }
 
@@ -109,13 +109,17 @@ class NCNetworkingProcessUpload: NSObject {
                         }
 
                         let semaphore = Semaphore()
-                        self.extractFiles(from: metadata) { metadatas in
+                        NCUtility.shared.extractFiles(from: metadata) { metadatas in
                             if metadatas.isEmpty {
                                 NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
                             }
                             for metadata in metadatas {
-                                if (metadata.e2eEncrypted || metadata.chunk) && applicationState != .active {  continue }
-                                let isWiFi = NCNetworking.shared.networkReachability == NCCommunicationCommon.typeReachability.reachableEthernetOrWiFi
+                                #if !EXTENSION
+                                if (metadata.e2eEncrypted || metadata.chunk) && UIApplication.shared.applicationState != .active {  continue }
+                                #else
+                                if (metadata.e2eEncrypted || metadata.chunk) { continue }
+                                #endif
+                                let isWiFi = NCNetworking.shared.networkReachability == NKCommon.typeReachability.reachableEthernetOrWiFi
                                 if metadata.session == NCNetworking.shared.sessionIdentifierBackgroundWWan && !isWiFi { continue }
                                 if let metadata = NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusInUpload) {
                                     NCNetworking.shared.upload(metadata: metadata)
@@ -142,18 +146,21 @@ class NCNetworkingProcessUpload: NSObject {
             }
              
             // verify delete Asset Local Identifiers in auto upload (DELETE Photos album)
+            #if !EXTENSION
             DispatchQueue.main.async {
-                if (counterUpload == 0 && !self.appDelegate.isPasscodePresented()) {
-                    self.deleteAssetLocalIdentifiers(account: self.appDelegate.account) {
+                if (counterUpload == 0 && !(UIApplication.shared.delegate as! AppDelegate).isPasscodePresented()) {
+                    self.deleteAssetLocalIdentifiers(account: account.account) {
                         self.startTimer()
                     }
                 } else {
                     self.startTimer()
                 }
             }
+            #endif
         })
     }
 
+    #if !EXTENSION
     private func deleteAssetLocalIdentifiers(account: String, completition: @escaping () -> Void) {
 
         if UIApplication.shared.applicationState != .active {
@@ -181,55 +188,7 @@ class NCNetworkingProcessUpload: NSObject {
             }
         })
     }
-
-    // MARK: -
-
-    func extractFiles(from metadata: tableMetadata, completition: @escaping (_ metadatas: [tableMetadata]) -> Void) {
-
-        let chunckSize = CCUtility.getChunkSize() * 1000000
-        var metadatas: [tableMetadata] = []
-        let metadataSource = tableMetadata.init(value: metadata)
-
-        guard !metadata.isExtractFile else { return  completition([metadataSource]) }
-        guard !metadataSource.assetLocalIdentifier.isEmpty else {
-            let filePath = CCUtility.getDirectoryProviderStorageOcId(metadataSource.ocId, fileNameView: metadataSource.fileName)!
-            metadataSource.size = NCUtilityFileSystem.shared.getFileSize(filePath: filePath)
-            let results = NCCommunicationCommon.shared.getInternalType(fileName: metadataSource.fileNameView, mimeType: metadataSource.contentType, directory: false)
-            metadataSource.contentType = results.mimeType
-            metadataSource.iconName = results.iconName
-            metadataSource.classFile = results.classFile
-            if let date = NCUtilityFileSystem.shared.getFileCreationDate(filePath: filePath) { metadataSource.creationDate = date }
-            if let date =  NCUtilityFileSystem.shared.getFileModificationDate(filePath: filePath) { metadataSource.date = date }
-            metadataSource.chunk = chunckSize != 0 && metadata.size > chunckSize
-            metadataSource.e2eEncrypted = CCUtility.isFolderEncrypted(metadata.serverUrl, e2eEncrypted: metadata.e2eEncrypted, account: metadata.account, urlBase: metadata.urlBase)
-            metadataSource.isExtractFile = true
-            if let metadata = NCManageDatabase.shared.addMetadata(metadataSource) {
-                metadatas.append(metadata)
-            }
-            return completition(metadatas)
-        }
-
-        NCUtility.shared.extractImageVideoFromAssetLocalIdentifier(metadata: metadataSource, modifyMetadataForUpload: true) { metadata, fileNamePath, returnError in
-            if let metadata = metadata, let fileNamePath = fileNamePath, !returnError {
-                metadatas.append(metadata)
-                let toPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
-                NCUtilityFileSystem.shared.moveFile(atPath: fileNamePath, toPath: toPath)
-            } else {
-                return completition(metadatas)
-            }
-            let fetchAssets = PHAsset.fetchAssets(withLocalIdentifiers: [metadataSource.assetLocalIdentifier], options: nil)
-            if metadataSource.livePhoto, fetchAssets.count > 0  {
-                NCUtility.shared.createMetadataLivePhotoFromMetadata(metadataSource, asset: fetchAssets.firstObject) { metadata in
-                    if let metadata = metadata, let metadata = NCManageDatabase.shared.addMetadata(metadata) {
-                        metadatas.append(metadata)
-                    }
-                    completition(metadatas)
-                }
-            } else {
-                completition(metadatas)
-            }
-        }
-    }
+    #endif
 
     // MARK: -
 
@@ -255,7 +214,7 @@ class NCNetworkingProcessUpload: NSObject {
         var session: URLSession?
 
         // remove leaning upload share extension
-        let metadatasUploadShareExtension = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "session == %@ AND sessionSelector == %@", NCCommunicationCommon.shared.sessionIdentifierUpload, NCGlobal.shared.selectorUploadFileShareExtension))
+        let metadatasUploadShareExtension = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "session == %@ AND sessionSelector == %@", NKCommon.shared.sessionIdentifierUpload, NCGlobal.shared.selectorUploadFileShareExtension))
         for metadata in metadatasUploadShareExtension {
             let path = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId)!
             NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
@@ -307,7 +266,7 @@ class NCNetworkingProcessUpload: NSObject {
         }
 
         // metadataStatusUploading OR metadataStatusInUpload (FOREGROUND)
-        let metadatasUploading = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "session == %@ AND (status == %d OR status == %d)", NCCommunicationCommon.shared.sessionIdentifierUpload, NCGlobal.shared.metadataStatusUploading, NCGlobal.shared.metadataStatusInUpload))
+        let metadatasUploading = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "session == %@ AND (status == %d OR status == %d)", NKCommon.shared.sessionIdentifierUpload, NCGlobal.shared.metadataStatusUploading, NCGlobal.shared.metadataStatusInUpload))
         for metadata in metadatasUploading {
             let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
             if NCNetworking.shared.uploadRequest[fileNameLocalPath] == nil {
@@ -316,7 +275,7 @@ class NCNetworkingProcessUpload: NSObject {
         }
 
         // download
-        let metadatasDownload = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "session == %@", NCCommunicationCommon.shared.sessionIdentifierDownload))
+        let metadatasDownload = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "session == %@", NKCommon.shared.sessionIdentifierDownload))
         for metadata in metadatasDownload {
             NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: "", sessionError: "", sessionSelector: "", sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusNormal)
         }

+ 37 - 29
iOSClient/Networking/NCOperationQueue.swift

@@ -23,7 +23,7 @@
 
 import UIKit
 import Queuer
-import NCCommunication
+import NextcloudKit
 
 @objc class NCOperationQueue: NSObject {
     @objc public static let shared: NCOperationQueue = {
@@ -220,7 +220,7 @@ import NCCommunication
 
     // MARK: - Unified Search
 
-    func unifiedSearchAddSection(collectionViewCommon: NCCollectionViewCommon, metadatas: [tableMetadata], searchResult: NCCSearchResult) {
+    func unifiedSearchAddSection(collectionViewCommon: NCCollectionViewCommon, metadatas: [tableMetadata], searchResult: NKSearchResult) {
         unifiedSearchQueue.addOperation(NCOperationUnifiedSearch.init(collectionViewCommon: collectionViewCommon, metadatas: metadatas, searchResult: searchResult))
     }
 
@@ -245,7 +245,7 @@ class NCOperationDownload: ConcurrentOperation {
         if isCancelled {
             self.finish()
         } else {
-            NCNetworking.shared.download(metadata: metadata, selector: self.selector) { _ in
+            NCNetworking.shared.download(metadata: metadata, selector: self.selector) { _, _ in
                 self.finish()
             }
         }
@@ -268,9 +268,9 @@ class NCOperationDelete: ConcurrentOperation {
         if isCancelled {
             self.finish()
         } else {
-            NCNetworking.shared.deleteMetadata(metadata, onlyLocalCache: onlyLocalCache) { errorCode, errorDescription in
-                if errorCode != 0 {
-                    NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+            NCNetworking.shared.deleteMetadata(metadata, onlyLocalCache: onlyLocalCache) { error in
+                if error != .success {
+                    NCContentPresenter.shared.showError(error: error)
                 }
                 self.finish()
             }
@@ -299,16 +299,16 @@ class NCOperationCopyMove: ConcurrentOperation {
             self.finish()
         } else {
             if move {
-                NCNetworking.shared.moveMetadata(metadata, serverUrlTo: serverUrlTo, overwrite: overwrite) { errorCode, errorDescription in
-                    if errorCode != 0 {
-                        NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                NCNetworking.shared.moveMetadata(metadata, serverUrlTo: serverUrlTo, overwrite: overwrite) { error in
+                    if error != .success {
+                        NCContentPresenter.shared.showError(error: error)
                     }
                     self.finish()
                 }
             } else {
-                NCNetworking.shared.copyMetadata(metadata, serverUrlTo: serverUrlTo, overwrite: overwrite) { errorCode, errorDescription in
-                    if errorCode != 0 {
-                        NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                NCNetworking.shared.copyMetadata(metadata, serverUrlTo: serverUrlTo, overwrite: overwrite) { error in
+                    if error != .success {
+                        NCContentPresenter.shared.showError(error: error)
                     }
                     self.finish()
                 }
@@ -344,15 +344,17 @@ class NCOperationSynchronization: ConcurrentOperation {
                 let serverUrl = metadata.serverUrl + "/" + metadata.fileName
                 let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, serverUrl))
 
-                NCCommunication.shared.readFileOrFolder(serverUrlFileName: serverUrl, depth: "0", showHiddenFiles: CCUtility.getShowHiddenFiles()) { account, files, _, errorCode, _ in
+                NextcloudKit.shared.readFileOrFolder(serverUrlFileName: serverUrl, depth: "0", showHiddenFiles: CCUtility.getShowHiddenFiles()) { account, files, _, error in
 
-                    if (errorCode == 0) && (directory?.etag != files.first?.etag || self.selector == NCGlobal.shared.selectorDownloadAllFile) {
+                    if (error == .success) && (directory?.etag != files.first?.etag || self.selector == NCGlobal.shared.selectorDownloadAllFile) {
 
-                        NCCommunication.shared.readFileOrFolder(serverUrlFileName: serverUrl, depth: "1", showHiddenFiles: CCUtility.getShowHiddenFiles(), queue: NCCommunicationCommon.shared.backgroundQueue) { account, files, _, errorCode, _ in
+                        let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
 
-                            if errorCode == 0 {
+                        NextcloudKit.shared.readFileOrFolder(serverUrlFileName: serverUrl, depth: "1", showHiddenFiles: CCUtility.getShowHiddenFiles(), options: options) { account, files, _, error in
 
-                                NCManageDatabase.shared.convertNCCommunicationFilesToMetadatas(files, useMetadataFolder: true, account: account) { metadataFolder, _, metadatas in
+                            if error == .success {
+
+                                NCManageDatabase.shared.convertNKFilesToMetadatas(files, useMetadataFolder: true, account: account) { metadataFolder, _, metadatas in
 
                                     let metadatasResult = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND status == %d", account, serverUrl, NCGlobal.shared.metadataStatusNormal))
 
@@ -389,7 +391,7 @@ class NCOperationSynchronization: ConcurrentOperation {
                                     NCManageDatabase.shared.addDirectory(encrypted: metadataFolder.e2eEncrypted, favorite: metadataFolder.favorite, ocId: metadataFolder.ocId, fileId: metadataFolder.fileId, etag: metadataFolder.etag, permissions: metadataFolder.permissions, serverUrl: serverUrl, account: metadataFolder.account)
                                 }
 
-                            } else if errorCode == NCGlobal.shared.errorResourceNotFound && self.metadata.directory {
+                            } else if error.errorCode == NCGlobal.shared.errorResourceNotFound && self.metadata.directory {
                                 NCManageDatabase.shared.deleteDirectoryAndSubDirectory(serverUrl: self.metadata.serverUrl, account: self.metadata.account)
                             }
 
@@ -452,7 +454,8 @@ class NCOperationDownloadThumbnail: ConcurrentOperation {
             if FileManager.default.fileExists(atPath: fileNameIconLocalPath) && FileManager.default.fileExists(atPath: fileNamePreviewLocalPath) {
                 etagResource = metadata.etagResource
             }
-            NCCommunication.shared.downloadPreview(
+            let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
+            NextcloudKit.shared.downloadPreview(
                 fileNamePathOrFileId: fileNamePath,
                 fileNamePreviewLocalPath: fileNamePreviewLocalPath,
                 widthPreview: NCGlobal.shared.sizePreview,
@@ -460,9 +463,9 @@ class NCOperationDownloadThumbnail: ConcurrentOperation {
                 fileNameIconLocalPath: fileNameIconLocalPath,
                 sizeIcon: NCGlobal.shared.sizeIcon,
                 etag: etagResource,
-                queue: NCCommunicationCommon.shared.backgroundQueue) { _, _, imageIcon, _, etag, errorCode, _ in
+                options: options) { _, _, imageIcon, _, etag, error in
 
-                    if errorCode == 0, let imageIcon = imageIcon {
+                    if error == .success, let imageIcon = imageIcon {
                         NCManageDatabase.shared.setMetadataEtagResource(ocId: self.metadata.ocId, etagResource: etag)
                         DispatchQueue.main.async {
                             if self.metadata.ocId == self.cell?.fileObjectId, let filePreviewImageView = self.cell?.filePreviewImageView {
@@ -511,16 +514,18 @@ class NCOperationDownloadThumbnailActivity: ConcurrentOperation {
             self.finish()
         } else {
 
-            NCCommunication.shared.downloadPreview(
+            let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
+
+            NextcloudKit.shared.downloadPreview(
                 fileNamePathOrFileId: fileNamePathOrFileId,
                 fileNamePreviewLocalPath: fileNamePreviewLocalPath,
                 widthPreview: 0,
                 heightPreview: 0,
                 etag: nil,
                 useInternalEndpoint: false,
-                queue: NCCommunicationCommon.shared.backgroundQueue) { _, imagePreview, _, _, _, errorCode, _ in
+                options: options) { _, imagePreview, _, _, _, error in
 
-                    if errorCode == 0, let imagePreview = imagePreview {
+                    if error == .success, let imagePreview = imagePreview {
                         DispatchQueue.main.async {
                             if self.fileId == self.cell?.fileId, let imageView = self.cell?.imageView {
                                 UIView.transition(with: imageView,
@@ -566,9 +571,12 @@ class NCOperationDownloadAvatar: ConcurrentOperation {
         if isCancelled {
             self.finish()
         } else {
-            NCCommunication.shared.downloadAvatar(user: user, fileNameLocalPath: fileNameLocalPath, sizeImage: NCGlobal.shared.avatarSize, avatarSizeRounded: NCGlobal.shared.avatarSizeRounded, etag: self.etag, queue: NCCommunicationCommon.shared.backgroundQueue) { _, imageAvatar, _, etag, errorCode, _ in
+            
+            let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
+
+            NextcloudKit.shared.downloadAvatar(user: user, fileNameLocalPath: fileNameLocalPath, sizeImage: NCGlobal.shared.avatarSize, avatarSizeRounded: NCGlobal.shared.avatarSizeRounded, etag: self.etag, options: options) { _, imageAvatar, _, etag, error in
 
-                if errorCode == 0, let imageAvatar = imageAvatar, let etag = etag {
+                if error == .success, let imageAvatar = imageAvatar, let etag = etag {
                     NCManageDatabase.shared.addAvatar(fileName: self.fileName, etag: etag)
                     DispatchQueue.main.async {
                         if self.user == self.cell.fileUser, let avatarImageView = self.cellImageView {
@@ -585,7 +593,7 @@ class NCOperationDownloadAvatar: ConcurrentOperation {
                             }
                         }
                     }
-                } else if errorCode == NCGlobal.shared.errorNotModified {
+                } else if error.errorCode == NCGlobal.shared.errorNotModified {
                     NCManageDatabase.shared.setAvatarLoaded(fileName: self.fileName)
                 }
                 self.finish()
@@ -600,9 +608,9 @@ class NCOperationUnifiedSearch: ConcurrentOperation {
 
     var collectionViewCommon: NCCollectionViewCommon
     var metadatas: [tableMetadata]
-    var searchResult: NCCSearchResult
+    var searchResult: NKSearchResult
 
-    init(collectionViewCommon: NCCollectionViewCommon, metadatas: [tableMetadata], searchResult: NCCSearchResult) {
+    init(collectionViewCommon: NCCollectionViewCommon, metadatas: [tableMetadata], searchResult: NKSearchResult) {
         self.collectionViewCommon = collectionViewCommon
         self.metadatas = metadatas
         self.searchResult = searchResult

+ 77 - 50
iOSClient/Networking/NCService.swift

@@ -23,7 +23,8 @@
 
 import UIKit
 import SVGKit
-import NCCommunication
+import NextcloudKit
+import SwiftyJSON
 
 class NCService: NSObject {
     @objc static let shared: NCService = {
@@ -51,45 +52,49 @@ class NCService: NSObject {
     func addInternalTypeIdentifier() {
 
         // txt
-        NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: "text/plain", classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorText, iconName: NCCommunicationCommon.typeIconFile.document.rawValue, name: "markdown")
+        NKCommon.shared.addInternalTypeIdentifier(typeIdentifier: "text/plain", classFile: NKCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorText, iconName: NKCommon.typeIconFile.document.rawValue, name: "markdown")
 
         // html
-        NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: "text/html", classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorText, iconName: NCCommunicationCommon.typeIconFile.document.rawValue, name: "markdown")
+        NKCommon.shared.addInternalTypeIdentifier(typeIdentifier: "text/html", classFile: NKCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorText, iconName: NKCommon.typeIconFile.document.rawValue, name: "markdown")
 
         // markdown
-        NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: "net.daringfireball.markdown", classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorText, iconName: NCCommunicationCommon.typeIconFile.document.rawValue, name: "markdown")
-        NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: "text/x-markdown", classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorText, iconName: NCCommunicationCommon.typeIconFile.document.rawValue, name: "markdown")
+        NKCommon.shared.addInternalTypeIdentifier(typeIdentifier: "net.daringfireball.markdown", classFile: NKCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorText, iconName: NKCommon.typeIconFile.document.rawValue, name: "markdown")
+        NKCommon.shared.addInternalTypeIdentifier(typeIdentifier: "text/x-markdown", classFile: NKCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorText, iconName: NKCommon.typeIconFile.document.rawValue, name: "markdown")
 
         // document: text
-        NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: "org.oasis-open.opendocument.text", classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorCollabora, iconName: NCCommunicationCommon.typeIconFile.document.rawValue, name: "document")
-        NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: "org.openxmlformats.wordprocessingml.document", classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorOnlyoffice, iconName: NCCommunicationCommon.typeIconFile.document.rawValue, name: "document")
-        NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: "com.microsoft.word.doc", classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorQuickLook, iconName: NCCommunicationCommon.typeIconFile.document.rawValue, name: "document")
-        NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: "com.apple.iwork.pages.pages", classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorQuickLook, iconName: NCCommunicationCommon.typeIconFile.document.rawValue, name: "pages")
+        NKCommon.shared.addInternalTypeIdentifier(typeIdentifier: "org.oasis-open.opendocument.text", classFile: NKCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorCollabora, iconName: NKCommon.typeIconFile.document.rawValue, name: "document")
+        NKCommon.shared.addInternalTypeIdentifier(typeIdentifier: "org.openxmlformats.wordprocessingml.document", classFile: NKCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorOnlyoffice, iconName: NKCommon.typeIconFile.document.rawValue, name: "document")
+        NKCommon.shared.addInternalTypeIdentifier(typeIdentifier: "com.microsoft.word.doc", classFile: NKCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorQuickLook, iconName: NKCommon.typeIconFile.document.rawValue, name: "document")
+        NKCommon.shared.addInternalTypeIdentifier(typeIdentifier: "com.apple.iwork.pages.pages", classFile: NKCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorQuickLook, iconName: NKCommon.typeIconFile.document.rawValue, name: "pages")
 
         // document: sheet
-        NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: "org.oasis-open.opendocument.spreadsheet", classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorCollabora, iconName: NCCommunicationCommon.typeIconFile.xls.rawValue, name: "sheet")
-        NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: "org.openxmlformats.spreadsheetml.sheet", classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorOnlyoffice, iconName: NCCommunicationCommon.typeIconFile.xls.rawValue, name: "sheet")
-        NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: "com.microsoft.excel.xls", classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorQuickLook, iconName: NCCommunicationCommon.typeIconFile.xls.rawValue, name: "sheet")
-        NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: "com.apple.iwork.numbers.numbers", classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorQuickLook, iconName: NCCommunicationCommon.typeIconFile.xls.rawValue, name: "numbers")
+        NKCommon.shared.addInternalTypeIdentifier(typeIdentifier: "org.oasis-open.opendocument.spreadsheet", classFile: NKCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorCollabora, iconName: NKCommon.typeIconFile.xls.rawValue, name: "sheet")
+        NKCommon.shared.addInternalTypeIdentifier(typeIdentifier: "org.openxmlformats.spreadsheetml.sheet", classFile: NKCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorOnlyoffice, iconName: NKCommon.typeIconFile.xls.rawValue, name: "sheet")
+        NKCommon.shared.addInternalTypeIdentifier(typeIdentifier: "com.microsoft.excel.xls", classFile: NKCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorQuickLook, iconName: NKCommon.typeIconFile.xls.rawValue, name: "sheet")
+        NKCommon.shared.addInternalTypeIdentifier(typeIdentifier: "com.apple.iwork.numbers.numbers", classFile: NKCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorQuickLook, iconName: NKCommon.typeIconFile.xls.rawValue, name: "numbers")
 
         // document: presentation
-        NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: "org.oasis-open.opendocument.presentation", classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorCollabora, iconName: NCCommunicationCommon.typeIconFile.ppt.rawValue, name: "presentation")
-        NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: "org.openxmlformats.presentationml.presentation", classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorOnlyoffice, iconName: NCCommunicationCommon.typeIconFile.ppt.rawValue, name: "presentation")
-        NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: "com.microsoft.powerpoint.ppt", classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorQuickLook, iconName: NCCommunicationCommon.typeIconFile.ppt.rawValue, name: "presentation")
-        NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: "com.apple.iwork.keynote.key", classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorQuickLook, iconName: NCCommunicationCommon.typeIconFile.ppt.rawValue, name: "keynote")
+        NKCommon.shared.addInternalTypeIdentifier(typeIdentifier: "org.oasis-open.opendocument.presentation", classFile: NKCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorCollabora, iconName: NKCommon.typeIconFile.ppt.rawValue, name: "presentation")
+        NKCommon.shared.addInternalTypeIdentifier(typeIdentifier: "org.openxmlformats.presentationml.presentation", classFile: NKCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorOnlyoffice, iconName: NKCommon.typeIconFile.ppt.rawValue, name: "presentation")
+        NKCommon.shared.addInternalTypeIdentifier(typeIdentifier: "com.microsoft.powerpoint.ppt", classFile: NKCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorQuickLook, iconName: NKCommon.typeIconFile.ppt.rawValue, name: "presentation")
+        NKCommon.shared.addInternalTypeIdentifier(typeIdentifier: "com.apple.iwork.keynote.key", classFile: NKCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorQuickLook, iconName: NKCommon.typeIconFile.ppt.rawValue, name: "keynote")
     }
 
     private func requestServerStatus() {
 
-        NCCommunication.shared.getServerStatus(serverUrl: appDelegate.urlBase, queue: NCCommunicationCommon.shared.backgroundQueue) { serverProductName, _, versionMajor, _, _, extendedSupport, errorCode, _ in
-            guard errorCode == 0, extendedSupport == false else {
+        let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
+
+        NextcloudKit.shared.getServerStatus(serverUrl: appDelegate.urlBase, options: options) { serverProductName, _, versionMajor, _, _, extendedSupport, error in
+            guard error == .success, extendedSupport == false else {
                 return
             }
 
             if serverProductName == "owncloud" {
-                NCContentPresenter.shared.messageNotification("_warning_", description: "_warning_owncloud_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorInternalError, priority: .max)
+                let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_warning_owncloud_")
+                NCContentPresenter.shared.showWarning(error: error, priority: .max)
             } else if versionMajor <=  NCGlobal.shared.nextcloud_unsupported_version {
-                NCContentPresenter.shared.messageNotification("_warning_", description: "_warning_unsupported_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorInternalError, priority: .max)
+                let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_warning_unsupported_")
+                NCContentPresenter.shared.showWarning(error: error, priority: .max)
             }
         }
     }
@@ -97,25 +102,28 @@ class NCService: NSObject {
     private func requestUserProfile() {
         guard !appDelegate.account.isEmpty else { return }
 
-        NCCommunication.shared.getUserProfile(queue: NCCommunicationCommon.shared.backgroundQueue) { account, userProfile, errorCode, errorDescription in
-            guard errorCode == 0, account == self.appDelegate.account else {
+        let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
+
+        NextcloudKit.shared.getUserProfile(options: options) { account, userProfile, error in
+            guard error == .success, account == self.appDelegate.account else {
                 NCBrandColor.shared.settingThemingColor(account: account)
-                if errorCode == 401 || errorCode == 403 {
-                    NCNetworkingCheckRemoteUser.shared.checkRemoteUser(account: account, errorCode: errorCode, errorDescription: errorDescription)
+                if error.errorCode == NCGlobal.shared.errorNCUnauthorized || error.errorCode == NCGlobal.shared.errorUnauthorized || error.errorCode == NCGlobal.shared.errorForbidden {
+                    NCNetworkingCheckRemoteUser().checkRemoteUser(account: account, error: error)
                 }
                 return
             }
 
             // Update User (+ userProfile.id) & active account & account network
             guard let tableAccount = NCManageDatabase.shared.setAccountUserProfile(userProfile!) else {
-                NCContentPresenter.shared.messageNotification("Account", description: "Internal error : account not found on DB", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError, priority: .max)
+                let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "Internal error : account not found on DB")
+                NCContentPresenter.shared.showError(error: error, priority: .max)
                 return
             }
 
             self.appDelegate.settingAccount(tableAccount.account, urlBase: tableAccount.urlBase, user: tableAccount.user, userId: tableAccount.userId, password: CCUtility.getPassword(tableAccount.account))
 
             // Synchronize favorite
-            NCNetworking.shared.listingFavoritescompletion(selector: NCGlobal.shared.selectorReadFile) { _, _, _, _ in }
+            NCNetworking.shared.listingFavoritescompletion(selector: NCGlobal.shared.selectorReadFile) { _, _, _ in }
 
             // Synchronize Offline
             self.synchronizeOffline(account: tableAccount.account)
@@ -124,10 +132,11 @@ class NCService: NSObject {
             let fileName = tableAccount.userBaseUrl + "-" + self.appDelegate.user + ".png"
             let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName
             let etag = NCManageDatabase.shared.getTableAvatar(fileName: fileName)?.etag
+            let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
 
-            NCCommunication.shared.downloadAvatar(user: tableAccount.userId, fileNameLocalPath: fileNameLocalPath, sizeImage: NCGlobal.shared.avatarSize, avatarSizeRounded: NCGlobal.shared.avatarSizeRounded, etag: etag, queue: NCCommunicationCommon.shared.backgroundQueue) { _, _, _, etag, errorCode, _ in
-                guard let etag = etag, errorCode == 0 else {
-                    if errorCode == NCGlobal.shared.errorNotModified {
+            NextcloudKit.shared.downloadAvatar(user: tableAccount.userId, fileNameLocalPath: fileNameLocalPath, sizeImage: NCGlobal.shared.avatarSize, avatarSizeRounded: NCGlobal.shared.avatarSizeRounded, etag: etag, options: options) { _, _, _, etag, error in
+                guard let etag = etag, error == .success else {
+                    if error.errorCode == NCGlobal.shared.errorNotModified {
                         NCManageDatabase.shared.setAvatarLoaded(fileName: fileName)
                     }
                     return
@@ -143,12 +152,11 @@ class NCService: NSObject {
     private func requestServerCapabilities() {
         guard !appDelegate.account.isEmpty else { return }
 
-        NCCommunication.shared.getCapabilities(queue: NCCommunicationCommon.shared.backgroundQueue) { account, data, errorCode, errorDescription in
-            guard errorCode == 0, let data = data else {
+        let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
+
+        NextcloudKit.shared.getCapabilities(options: options) { account, data, error in
+            guard error == .success, let data = data else {
                 NCBrandColor.shared.settingThemingColor(account: account)
-                if errorCode == 401 || errorCode == 403 {
-                    NCNetworkingCheckRemoteUser.shared.checkRemoteUser(account: account, errorCode: errorCode, errorDescription: errorDescription)
-                }
                 return
             }
 
@@ -157,7 +165,7 @@ class NCService: NSObject {
 
             // Setup communication
             if serverVersionMajor > 0 {
-                NCCommunicationCommon.shared.setup(nextcloudVersion: serverVersionMajor)
+                NKCommon.shared.setup(nextcloudVersion: serverVersionMajor)
             }
 
             // Theming
@@ -171,15 +179,13 @@ class NCService: NSObject {
             // File Sharing
             let isFilesSharingEnabled = NCManageDatabase.shared.getCapabilitiesServerBool(account: account, elements: NCElementsJSON.shared.capabilitiesFileSharingApiEnabled, exists: false)
             if isFilesSharingEnabled {
-                NCCommunication.shared.readShares(parameters: NCCShareParameter(), queue: NCCommunicationCommon.shared.backgroundQueue) { account, shares, errorCode, errorDescription in
-                    if errorCode == 0 {
+                NextcloudKit.shared.readShares(parameters: NKShareParameter(), options: options) { account, shares, error in
+                    if error == .success {
                         NCManageDatabase.shared.deleteTableShare(account: account)
-                        if shares != nil {
-                            NCManageDatabase.shared.addShare(urlBase: self.appDelegate.urlBase, account: account, shares: shares!)
+                        if let shares = shares, !shares.isEmpty {
+                            NCManageDatabase.shared.addShare(urlBase: self.appDelegate.urlBase, account: account, shares: shares)
                         }
                         self.appDelegate.shares = NCManageDatabase.shared.getTableShares(account: account)
-                    } else {
-                        NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
                     }
                 }
             }
@@ -195,8 +201,9 @@ class NCService: NSObject {
 
             // Text direct editor detail
             if serverVersionMajor >= NCGlobal.shared.nextcloudVersion18 {
-                NCCommunication.shared.NCTextObtainEditorDetails(queue: NCCommunicationCommon.shared.backgroundQueue) { account, editors, creators, errorCode, _ in
-                    if errorCode == 0 && account == self.appDelegate.account {
+                let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
+                NextcloudKit.shared.NCTextObtainEditorDetails(options: options) { account, editors, creators, error in
+                    if error == .success && account == self.appDelegate.account {
                         NCManageDatabase.shared.addDirectEditing(account: account, editors: editors, creators: creators)
                     }
                 }
@@ -205,8 +212,8 @@ class NCService: NSObject {
             // External file Server
             let isExternalSitesServerEnabled = NCManageDatabase.shared.getCapabilitiesServerBool(account: account, elements: NCElementsJSON.shared.capabilitiesExternalSitesExists, exists: true)
             if isExternalSitesServerEnabled {
-                NCCommunication.shared.getExternalSite(queue: NCCommunicationCommon.shared.backgroundQueue) { account, externalSites, errorCode, _ in
-                    if errorCode == 0 && account == self.appDelegate.account {
+                NextcloudKit.shared.getExternalSite(options: options) { account, externalSites, error in
+                    if error == .success && account == self.appDelegate.account {
                         NCManageDatabase.shared.deleteExternalSites(account: account)
                         for externalSite in externalSites {
                             NCManageDatabase.shared.addExternalSites(externalSite, account: account)
@@ -220,8 +227,8 @@ class NCService: NSObject {
             // User Status
             let userStatus = NCManageDatabase.shared.getCapabilitiesServerBool(account: account, elements: NCElementsJSON.shared.capabilitiesUserStatusEnabled, exists: false)
             if userStatus {
-                NCCommunication.shared.getUserStatus(queue: NCCommunicationCommon.shared.backgroundQueue) { account, clearAt, icon, message, messageId, messageIsPredefined, status, statusIsUserDefined, userId, errorCode, _ in
-                    if errorCode == 0 && account == self.appDelegate.account && userId == self.appDelegate.userId {
+                NextcloudKit.shared.getUserStatus(options: options) { account, clearAt, icon, message, messageId, messageIsPredefined, status, statusIsUserDefined, userId, error in
+                    if error == .success && account == self.appDelegate.account && userId == self.appDelegate.userId {
                         NCManageDatabase.shared.setAccountUserStatus(userStatusClearAt: clearAt, userStatusIcon: icon, userStatusMessage: message, userStatusMessageId: messageId, userStatusMessageIsPredefined: messageIsPredefined, userStatusStatus: status, userStatusStatusIsUserDefined: statusIsUserDefined, account: account)
                     }
                 }
@@ -230,16 +237,36 @@ class NCService: NSObject {
             // Added UTI for Collabora
             if let richdocumentsMimetypes = NCManageDatabase.shared.getCapabilitiesServerArray(account: account, elements: NCElementsJSON.shared.capabilitiesRichdocumentsMimetypes) {
                 for mimeType in richdocumentsMimetypes {
-                    NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: mimeType, classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorCollabora, iconName: NCCommunicationCommon.typeIconFile.document.rawValue, name: "document")
+                    NKCommon.shared.addInternalTypeIdentifier(typeIdentifier: mimeType, classFile: NKCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorCollabora, iconName: NKCommon.typeIconFile.document.rawValue, name: "document")
                 }
             }
 
             // Added UTI for ONLYOFFICE & Text
             if let directEditingCreators = NCManageDatabase.shared.getDirectEditingCreators(account: account) {
                 for directEditing in directEditingCreators {
-                    NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: directEditing.mimetype, classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: directEditing.editor, iconName: NCCommunicationCommon.typeIconFile.document.rawValue, name: "document")
+                    NKCommon.shared.addInternalTypeIdentifier(typeIdentifier: directEditing.mimetype, classFile: NKCommon.typeClassFile.document.rawValue, editor: directEditing.editor, iconName: NKCommon.typeIconFile.document.rawValue, name: "document")
+                }
+            }
+
+            //TODO: Test DASHBOARD
+            /*
+            if #available(iOS 15.0, *) {
+                NextcloudKit.shared.getDashboard { request in
+                } completion: { dashboardResults, json, errorCode, errorDescription in
+                    if let dashboardResults = dashboardResults {
+                        for result in dashboardResults {
+                            for entry in result.dashboardEntries ?? [] {
+                                if let url = URL(string: entry.iconUrl) {
+                                    NextcloudKit.shared.getPreview(url: url) { account, data, errorCode, errorDescription in
+
+                                    }
+                                }
+                            }
+                        }
+                    }
                 }
             }
+            */
         }
     }
 

+ 16 - 2
iOSClient/Notification/NCNotification.storyboard

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19455" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="c26-Us-IIn">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="c26-Us-IIn">
     <device id="retina4_7" orientation="portrait" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19454"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <scenes>
@@ -91,6 +91,17 @@
                                                 <action selector="touchUpInsideSecondary:" destination="R1c-h5-BOp" eventType="touchUpInside" id="Vy9-uI-sth"/>
                                             </connections>
                                         </button>
+                                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="4Ca-NL-V78" userLabel="More">
+                                            <rect key="frame" x="285" y="142" width="80" height="30"/>
+                                            <constraints>
+                                                <constraint firstAttribute="width" constant="80" id="2cb-3v-up9"/>
+                                                <constraint firstAttribute="height" constant="30" id="w4c-JV-GCL"/>
+                                            </constraints>
+                                            <state key="normal" title="more"/>
+                                            <connections>
+                                                <action selector="touchUpInsideMore:" destination="R1c-h5-BOp" eventType="touchUpInside" id="tzH-nO-8bt"/>
+                                            </connections>
+                                        </button>
                                         <imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="j3P-Mn-NRk" userLabel="avatar">
                                             <rect key="frame" x="10" y="40" width="25" height="25"/>
                                             <constraints>
@@ -103,11 +114,13 @@
                                     <constraints>
                                         <constraint firstItem="j3P-Mn-NRk" firstAttribute="leading" secondItem="9Bv-1W-yVV" secondAttribute="leading" constant="10" id="05B-JK-v6T"/>
                                         <constraint firstAttribute="trailing" secondItem="sMh-G7-FLo" secondAttribute="trailing" constant="10" id="4W9-Xm-fxY"/>
+                                        <constraint firstAttribute="bottom" secondItem="4Ca-NL-V78" secondAttribute="bottom" constant="15" id="4nu-oj-CtH"/>
                                         <constraint firstItem="9mD-Qe-1wu" firstAttribute="centerY" secondItem="YM1-uH-2Cz" secondAttribute="centerY" id="6VB-EF-GQs"/>
                                         <constraint firstItem="sMh-G7-FLo" firstAttribute="top" secondItem="9fz-sr-8Gv" secondAttribute="bottom" constant="5" id="EOH-W7-TBv"/>
                                         <constraint firstItem="pg1-7p-7Rz" firstAttribute="leading" secondItem="j3P-Mn-NRk" secondAttribute="trailing" constant="15" id="FHX-rf-Z0E"/>
                                         <constraint firstAttribute="trailing" secondItem="9mD-Qe-1wu" secondAttribute="trailing" constant="10" id="L9w-kA-Ypv"/>
                                         <constraint firstItem="sMh-G7-FLo" firstAttribute="leading" secondItem="obR-h7-TUC" secondAttribute="trailing" constant="10" id="MZG-Fc-cbL"/>
+                                        <constraint firstAttribute="trailing" secondItem="4Ca-NL-V78" secondAttribute="trailing" constant="10" id="RD1-Ox-wZH"/>
                                         <constraint firstAttribute="bottom" secondItem="sMh-G7-FLo" secondAttribute="bottom" constant="15" id="RKX-zp-kja"/>
                                         <constraint firstItem="9fz-sr-8Gv" firstAttribute="leading" secondItem="9Bv-1W-yVV" secondAttribute="leading" constant="50" id="ZxC-VD-ZtU"/>
                                         <constraint firstAttribute="trailing" secondItem="pg1-7p-7Rz" secondAttribute="trailing" constant="10" id="bwL-co-8gM"/>
@@ -130,6 +143,7 @@
                                     <outlet property="date" destination="YPu-No-c8x" id="CfW-Pz-jdL"/>
                                     <outlet property="icon" destination="YM1-uH-2Cz" id="MPX-ZL-wVR"/>
                                     <outlet property="message" destination="9fz-sr-8Gv" id="3Zx-pz-gEK"/>
+                                    <outlet property="more" destination="4Ca-NL-V78" id="b8O-Zg-dcf"/>
                                     <outlet property="primary" destination="sMh-G7-FLo" id="oyl-c8-sTP"/>
                                     <outlet property="primaryWidth" destination="tiI-55-Qu5" id="8H6-cf-vtP"/>
                                     <outlet property="remove" destination="9mD-Qe-1wu" id="r1h-mr-5U9"/>

+ 43 - 19
iOSClient/Notification/NCNotification.swift

@@ -23,13 +23,13 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 import SwiftyJSON
 
 class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmptyDataSetDelegate {
 
     let appDelegate = UIApplication.shared.delegate as! AppDelegate
-    var notifications: [NCCommunicationNotifications] = []
+    var notifications: [NKNotifications] = []
     var emptyDataSet: NCEmptyDataSet?
 
     // MARK: - View Life Cycle
@@ -161,6 +161,14 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty
         cell.primary.layer.backgroundColor = NCBrandColor.shared.brandElement.cgColor
         cell.primary.setTitleColor(NCBrandColor.shared.brandText, for: .normal)
 
+        cell.more.isEnabled = false
+        cell.more.isHidden = true
+        cell.more.titleLabel?.font = .systemFont(ofSize: 15)
+        cell.more.layer.cornerRadius = 15
+        cell.more.layer.masksToBounds = true
+        cell.more.layer.backgroundColor = NCBrandColor.shared.brandElement.cgColor
+        cell.more.setTitleColor(NCBrandColor.shared.brandText, for: .normal)
+
         cell.secondary.isEnabled = false
         cell.secondary.isHidden = true
         cell.secondary.titleLabel?.font = .systemFont(ofSize: 15)
@@ -200,6 +208,11 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty
                         cell.secondary.setTitle(label, for: .normal)
                     }
                 }
+            } else if jsonActions.count >= 3 {
+
+                cell.more.isEnabled = true
+                cell.more.isHidden = false
+                cell.more.setTitle("…", for: .normal)
             }
 
             var buttonWidth = max(cell.primary.intrinsicContentSize.width, cell.secondary.intrinsicContentSize.width)
@@ -213,10 +226,10 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty
 
     // MARK: - tap Action
 
-    func tapRemove(with notification: NCCommunicationNotifications) {
+    func tapRemove(with notification: NKNotifications) {
 
-        NCCommunication.shared.setNotification(serverUrl: nil, idNotification: notification.idNotification , method: "DELETE") { (account, errorCode, errorDescription) in
-            if errorCode == 0 && account == self.appDelegate.account {
+        NextcloudKit.shared.setNotification(serverUrl: nil, idNotification: notification.idNotification , method: "DELETE") { (account, error) in
+            if error == .success && account == self.appDelegate.account {
 
                 if let index = self.notifications
                     .firstIndex(where: { $0.idNotification == notification.idNotification })  {
@@ -225,15 +238,15 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty
 
                 self.reloadDatasource()
 
-            } else if errorCode != 0 {
-                NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+            } else if error != .success {
+                NCContentPresenter.shared.showError(error: error)
             } else {
                 print("[Error] The user has been changed during networking process.")
             }
         }
     }
 
-    func tapAction(with notification: NCCommunicationNotifications, label: String) {
+    func tapAction(with notification: NKNotifications, label: String) {
         if notification.app == "spreed",
            let roomToken = notification.objectId.split(separator: "/").first,
            let talkUrl = URL(string: "nextcloudtalk://open-conversation?server=\(appDelegate.urlBase)&user=\(appDelegate.userId)&withRoomToken=\(roomToken)"),
@@ -250,17 +263,17 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty
                 return
             }
 
-            NCCommunication.shared.setNotification(serverUrl: serverUrl, idNotification: 0, method: method) { (account, errorCode, errorDescription) in
+            NextcloudKit.shared.setNotification(serverUrl: serverUrl, idNotification: 0, method: method) { (account, error) in
 
-                if errorCode == 0 && account == self.appDelegate.account {
+                if error == .success && account == self.appDelegate.account {
                     if let index = self.notifications.firstIndex(where: { $0.idNotification == notification.idNotification }) {
                         self.notifications.remove(at: index)
                     }
 
                     self.reloadDatasource()
 
-                } else if errorCode != 0 {
-                    NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                } else if error != .success {
+                    NCContentPresenter.shared.showError(error: error)
                 } else {
                     print("[Error] The user has been changed during networking process.")
                 }
@@ -268,22 +281,26 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty
         } // else: Action not found
     }
 
+    func tapMore(with notification: NKNotifications) {
+       toggleMenu(notification: notification)
+    }
+
     // MARK: - Load notification networking
 
     func getNetwokingNotification() {
 
-        NCCommunication.shared.getNotifications { account, notifications, errorCode, _ in
+        NextcloudKit.shared.getNotifications { account, notifications, error in
 
-            if errorCode == 0 && account == self.appDelegate.account {
+            if error == .success && account == self.appDelegate.account {
 
                 self.notifications.removeAll()
                 let sortedListOfNotifications = (notifications! as NSArray).sortedArray(using: [NSSortDescriptor(key: "date", ascending: false)])
 
                 for notification in sortedListOfNotifications {
-                    if let icon = (notification as! NCCommunicationNotifications).icon {
+                    if let icon = (notification as! NKNotifications).icon {
                         NCUtility.shared.convertSVGtoPNGWriteToUserData(svgUrlString: icon, fileName: nil, width: 25, rewrite: false, account: self.appDelegate.account, closure: { _ in })
                     }
-                    self.notifications.append(notification as! NCCommunicationNotifications)
+                    self.notifications.append(notification as! NKNotifications)
                 }
 
                 self.reloadDatasource()
@@ -304,6 +321,7 @@ class NCNotificationCell: UITableViewCell, NCCellProtocol {
     @IBOutlet weak var remove: UIButton!
     @IBOutlet weak var primary: UIButton!
     @IBOutlet weak var secondary: UIButton!
+    @IBOutlet weak var more: UIButton!
     @IBOutlet weak var avatarLeadingMargin: NSLayoutConstraint!
     @IBOutlet weak var primaryWidth: NSLayoutConstraint!
     @IBOutlet weak var secondaryWidth: NSLayoutConstraint!
@@ -311,7 +329,7 @@ class NCNotificationCell: UITableViewCell, NCCellProtocol {
     private var user = ""
 
     weak var delegate: NCNotificationCellDelegate?
-    var notification: NCCommunicationNotifications?
+    var notification: NKNotifications?
 
     var fileAvatarImageView: UIImageView? {
         get { return avatar }
@@ -345,9 +363,15 @@ class NCNotificationCell: UITableViewCell, NCCellProtocol {
         else { return }
         delegate?.tapAction(with: notification, label: label)
     }
+
+    @IBAction func touchUpInsideMore(_ sender: Any) {
+        guard let notification = notification else { return }
+        delegate?.tapMore(with: notification)
+    }
 }
 
 protocol NCNotificationCellDelegate: AnyObject {
-    func tapRemove(with notification: NCCommunicationNotifications)
-    func tapAction(with notification: NCCommunicationNotifications, label: String)
+    func tapRemove(with notification: NKNotifications)
+    func tapAction(with notification: NKNotifications, label: String)
+    func tapMore(with notification: NKNotifications)
 }

+ 3 - 3
iOSClient/Offline/NCOffline.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 
 class NCOffline: NCCollectionViewCommon {
 
@@ -96,8 +96,8 @@ class NCOffline: NCCollectionViewCommon {
         isReloadDataSourceNetworkInProgress = true
         collectionView?.reloadData()
 
-        networkReadFolder(forced: forced) { tableDirectory, metadatas, metadatasUpdate, metadatasDelete, errorCode, _ in
-            if errorCode == 0 {
+        networkReadFolder(forced: forced) { tableDirectory, metadatas, metadatasUpdate, metadatasDelete, error in
+            if error == .success {
                 for metadata in metadatas ?? [] {
                     if !metadata.directory {
                         if NCManageDatabase.shared.isDownloadMetadata(metadata, download: true) {

+ 10 - 10
iOSClient/PushNotification/NCPushNotification.m

@@ -106,13 +106,13 @@
     NSString *pushDevicePublicKey = [[NSString alloc] initWithData:pushPublicKey encoding:NSUTF8StringEncoding];
     NSString *proxyServerPath = [NCBrandOptions shared].pushNotificationServerProxy;
     
-    [[NCCommunication shared] subscribingPushNotificationWithServerUrl:urlBase account:account user:user password:[CCUtility getPassword:account] pushTokenHash:pushTokenHash devicePublicKey:pushDevicePublicKey proxyServerUrl:proxyServerPath customUserAgent:nil addCustomHeaders:nil queue:dispatch_get_main_queue() completionHandler:^(NSString *account, NSString *deviceIdentifier, NSString *signature, NSString *publicKey, NSInteger errorCode, NSString *errorDescription) {
-        if (errorCode == 0) {
+    [[NextcloudKit shared] subscribingPushNotificationWithServerUrl:urlBase account:account user:user password:[CCUtility getPassword:account] pushTokenHash:pushTokenHash devicePublicKey:pushDevicePublicKey proxyServerUrl:proxyServerPath customUserAgent:nil addCustomHeaders:nil queue:dispatch_get_main_queue() completion:^(NSString *account, NSString *deviceIdentifier, NSString *signature, NSString *publicKey, NKError *error) {
+        if (error == NKError.success) {
             NSString *userAgent = [NSString stringWithFormat:@"%@  (Strict VoIP)", [CCUtility getUserAgent]];
-            [[NCCommunication shared] subscribingPushProxyWithProxyServerUrl:proxyServerPath pushToken:self.pushKitToken deviceIdentifier:deviceIdentifier signature:signature publicKey:publicKey userAgent:userAgent queue:dispatch_get_main_queue() completionHandler:^(NSInteger errorCode, NSString *errorDescription) {
-                if (errorCode == 0) {
+            [[NextcloudKit shared] subscribingPushProxyWithProxyServerUrl:proxyServerPath pushToken:self.pushKitToken deviceIdentifier:deviceIdentifier signature:signature publicKey:publicKey userAgent:userAgent queue:dispatch_get_main_queue() completion:^(NKError *error) {
+                if (error == NKError.success) {
                     
-                    [[NCCommunicationCommon shared] writeLog:@"Subscribed to Push Notification server & proxy successfully"];
+                    [[NKCommon shared] writeLog:@"Subscribed to Push Notification server & proxy successfully"];
 
                     [CCUtility setPushNotificationToken:account token:self.pushKitToken];
                     [CCUtility setPushNotificationDeviceIdentifier:account deviceIdentifier:deviceIdentifier];
@@ -132,14 +132,14 @@
     NSString *signature = [CCUtility getPushNotificationDeviceIdentifierSignature:account];
     NSString *publicKey = [CCUtility getPushNotificationSubscribingPublicKey:account];
 
-    [[NCCommunication shared] unsubscribingPushNotificationWithServerUrl:urlBase account:account user:user password:[CCUtility getPassword:account] customUserAgent:nil addCustomHeaders:nil queue:dispatch_get_main_queue() completionHandler:^(NSString *account, NSInteger errorCode, NSString *errorDescription) {
-        if (errorCode == 0) {
+    [[NextcloudKit shared] unsubscribingPushNotificationWithServerUrl:urlBase account:account user:user password:[CCUtility getPassword:account] customUserAgent:nil addCustomHeaders:nil queue:dispatch_get_main_queue() completion:^(NSString *account, NKError *error) {
+        if (error == NKError.success) {
             NSString *userAgent = [NSString stringWithFormat:@"%@  (Strict VoIP)", [CCUtility getUserAgent]];
             NSString *proxyServerPath = [NCBrandOptions shared].pushNotificationServerProxy;
-            [[NCCommunication shared] unsubscribingPushProxyWithProxyServerUrl:proxyServerPath deviceIdentifier:deviceIdentifier signature:signature publicKey:publicKey userAgent:userAgent queue:dispatch_get_main_queue() completionHandler:^(NSInteger errorCode, NSString *errorDescription) {
-                if (errorCode == 0) {
+            [[NextcloudKit shared] unsubscribingPushProxyWithProxyServerUrl:proxyServerPath deviceIdentifier:deviceIdentifier signature:signature publicKey:publicKey userAgent:userAgent queue:dispatch_get_main_queue() completion:^(NKError *error) {
+                if (error == NKError.success) {
                 
-                    [[NCCommunicationCommon shared] writeLog:@"Unsubscribed to Push Notification server & proxy successfully."];
+                    [[NKCommon shared] writeLog:@"Unsubscribed to Push Notification server & proxy successfully."];
                     
                     [CCUtility setPushNotificationPublicKey:account data:nil];
                     [CCUtility setPushNotificationSubscribingPublicKey:account publicKey:nil];

+ 6 - 4
iOSClient/Recent/NCRecent.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 
 class NCRecent: NCCollectionViewCommon {
 
@@ -138,10 +138,12 @@ class NCRecent: NCCollectionViewCommon {
         isReloadDataSourceNetworkInProgress = true
         collectionView?.reloadData()
 
-        NCCommunication.shared.searchBodyRequest(serverUrl: appDelegate.urlBase, requestBody: requestBody, showHiddenFiles: CCUtility.getShowHiddenFiles(), queue: NCCommunicationCommon.shared.backgroundQueue) { account, files, errorCode, _ in
+        let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
 
-            if errorCode == 0 {
-                NCManageDatabase.shared.convertNCCommunicationFilesToMetadatas(files, useMetadataFolder: false, account: account) { _, metadatasFolder, metadatas in
+        NextcloudKit.shared.searchBodyRequest(serverUrl: appDelegate.urlBase, requestBody: requestBody, showHiddenFiles: CCUtility.getShowHiddenFiles(), options: options) { account, files, error in
+
+            if error == .success {
+                NCManageDatabase.shared.convertNKFilesToMetadatas(files, useMetadataFolder: false, account: account) { _, metadatasFolder, metadatas in
 
                     // Update sub directories
                     for metadata in metadatasFolder {

+ 4 - 4
iOSClient/Rename file/NCRenameFile.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 
 public protocol NCRenameFileDelegate: AnyObject {
     func rename(fileName: String, fileNameNew: String)
@@ -233,17 +233,17 @@ class NCRenameFile: UIViewController, UITextFieldDelegate {
 
         NCActivityIndicator.shared.start()
 
-        NCNetworking.shared.renameMetadata(metadata, fileNameNew: fileNameNew, viewController: self) { errorCode, errorDescription in
+        NCNetworking.shared.renameMetadata(metadata, fileNameNew: fileNameNew, viewController: self) { error in
 
             NCActivityIndicator.shared.stop()
 
-            if errorCode == 0 {
+            if error == .success {
 
                 self.dismiss(animated: true)
 
             } else {
 
-                NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                NCContentPresenter.shared.showError(error: error)
             }
         }
     }

+ 15 - 14
iOSClient/RichWorkspace/NCRichWorkspaceCommon.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 
 @objc class NCRichWorkspaceCommon: NSObject {
 
@@ -30,8 +30,9 @@ import NCCommunication
 
     @objc func createViewerNextcloudText(serverUrl: String, viewController: UIViewController) {
 
-        if !NCCommunication.shared.isNetworkReachable() {
-            NCContentPresenter.shared.messageNotification("_error_", description: "_go_online_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorInternalError)
+        if !NextcloudKit.shared.isNetworkReachable() {
+            let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_go_online_")
+            NCContentPresenter.shared.showError(error: error)
             return
         }
 
@@ -40,11 +41,11 @@ import NCCommunication
         NCActivityIndicator.shared.start(backgroundView: viewController.view)
 
         let fileNamePath = CCUtility.returnFileNamePath(fromFileName: NCGlobal.shared.fileNameRichWorkspace, serverUrl: serverUrl, urlBase: appDelegate.urlBase, account: appDelegate.account)!
-        NCCommunication.shared.NCTextCreateFile(fileNamePath: fileNamePath, editorId: directEditingCreator.editor, creatorId: directEditingCreator.identifier, templateId: "") { account, url, errorCode, errorMessage in
+        NextcloudKit.shared.NCTextCreateFile(fileNamePath: fileNamePath, editorId: directEditingCreator.editor, creatorId: directEditingCreator.identifier, templateId: "") { account, url, error in
 
             NCActivityIndicator.shared.stop()
 
-            if errorCode == 0 && account == self.appDelegate.account {
+            if error == .success && account == self.appDelegate.account {
 
                 if let viewerRichWorkspaceWebView = UIStoryboard(name: "NCViewerRichWorkspace", bundle: nil).instantiateViewController(withIdentifier: "NCViewerRichWorkspaceWebView") as? NCViewerRichWorkspaceWebView {
 
@@ -54,17 +55,17 @@ import NCCommunication
                     viewController.present(viewerRichWorkspaceWebView, animated: true, completion: nil)
                 }
 
-            } else if errorCode != 0 {
-                NCContentPresenter.shared.messageNotification("_error_", description: errorMessage, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: errorCode)
+            } else if error != .success {
+                NCContentPresenter.shared.showError(error: error)
             }
         }
     }
 
     @objc func openViewerNextcloudText(serverUrl: String, viewController: UIViewController) {
 
-        if !NCCommunication.shared.isNetworkReachable() {
-
-            NCContentPresenter.shared.messageNotification("_error_", description: "_go_online_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorInternalError)
+        if !NextcloudKit.shared.isNetworkReachable() {
+            let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_go_online_")
+            NCContentPresenter.shared.showError(error: error)
             return
         }
 
@@ -75,11 +76,11 @@ import NCCommunication
                 NCActivityIndicator.shared.start(backgroundView: viewController.view)
 
                 let fileNamePath = CCUtility.returnFileNamePath(fromFileName: metadata.fileName, serverUrl: metadata.serverUrl, urlBase: appDelegate.urlBase, account: appDelegate.account)!
-                NCCommunication.shared.NCTextOpenFile(fileNamePath: fileNamePath, editor: "text") { account, url, errorCode, errorMessage in
+                NextcloudKit.shared.NCTextOpenFile(fileNamePath: fileNamePath, editor: "text") { account, url, error in
 
                     NCActivityIndicator.shared.stop()
 
-                    if errorCode == 0 && account == self.appDelegate.account {
+                    if error == .success && account == self.appDelegate.account {
 
                         if let viewerRichWorkspaceWebView = UIStoryboard(name: "NCViewerRichWorkspace", bundle: nil).instantiateViewController(withIdentifier: "NCViewerRichWorkspaceWebView") as? NCViewerRichWorkspaceWebView {
 
@@ -90,8 +91,8 @@ import NCCommunication
                             viewController.present(viewerRichWorkspaceWebView, animated: true, completion: nil)
                         }
 
-                    } else if errorCode != 0 {
-                        NCContentPresenter.shared.messageNotification("_error_", description: errorMessage, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: errorCode)
+                    } else if error != .success {
+                        NCContentPresenter.shared.showError(error: error)
                     }
                 }
 

+ 3 - 3
iOSClient/RichWorkspace/NCViewerRichWorkspace.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 import MarkdownKit
 
 @objc class NCViewerRichWorkspace: UIViewController, UIAdaptivePresentationControllerDelegate {
@@ -61,9 +61,9 @@ import MarkdownKit
     override func viewWillAppear(_ animated: Bool) {
         super.viewWillAppear(animated)
 
-        NCNetworking.shared.readFile(serverUrlFileName: serverUrl) { (account, metadata, errorCode, errorDescription) in
+        NCNetworking.shared.readFile(serverUrlFileName: serverUrl) { (account, metadata, error) in
 
-            if errorCode == 0 && account == self.appDelegate.account {
+            if error == .success && account == self.appDelegate.account {
                 guard let metadata = metadata else { return }
                 NCManageDatabase.shared.setDirectory(serverUrl: self.serverUrl, richWorkspace: metadata.richWorkspace, account: account)
                 if self.richWorkspaceText != metadata.richWorkspace && metadata.richWorkspace != nil {

+ 2 - 2
iOSClient/Security/NCEndToEndMetadata.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 
 class NCEndToEndMetadata: NSObject {
 
@@ -219,7 +219,7 @@ class NCEndToEndMetadata: NSObject {
                         metadata.fileNameView = encryptedFileAttributes.filename
                         metadata.fileNameWithoutExt = (encryptedFileAttributes.filename as NSString).deletingPathExtension
 
-                        let results = NCCommunicationCommon.shared.getInternalType(fileName: encryptedFileAttributes.filename, mimeType: metadata.contentType, directory: metadata.directory)
+                        let results = NKCommon.shared.getInternalType(fileName: encryptedFileAttributes.filename, mimeType: metadata.contentType, directory: metadata.directory)
 
                         metadata.contentType = results.mimeType
                         metadata.iconName = results.iconName

+ 4 - 4
iOSClient/Select/NCSelect.swift

@@ -22,7 +22,7 @@
 //
 
 import UIKit
-import NCCommunication
+import NextcloudKit
 
 @objc protocol NCSelectDelegate {
     @objc func dismissSelect(serverUrl: String?, metadata: tableMetadata?, type: String, items: [Any], overwrite: Bool, copy: Bool, move: Bool)
@@ -756,9 +756,9 @@ extension NCSelect {
         networkInProgress = true
         collectionView.reloadData()
 
-        NCNetworking.shared.readFolder(serverUrl: serverUrl, account: activeAccount.account) { _, _, _, _, _, _, errorCode, errorDescription in
-            if errorCode != 0 {
-                NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+        NCNetworking.shared.readFolder(serverUrl: serverUrl, account: activeAccount.account) { _, _, _, _, _, _, error in
+            if error != .success {
+                NCContentPresenter.shared.showError(error: error)
             }
             self.networkInProgress = false
             self.loadDatasource(withLoadFolder: false)

+ 6 - 6
iOSClient/Settings/CCAdvanced.m

@@ -142,7 +142,7 @@
     section = [XLFormSectionDescriptor formSectionWithTitle:NSLocalizedString(@"_diagnostics_", nil)];
     [form addFormSection:section];
         
-    if ([[NSFileManager defaultManager] fileExistsAtPath:NCCommunicationCommon.shared.filenamePathLog] && NCBrandOptions.shared.disable_log == false) {
+    if ([[NSFileManager defaultManager] fileExistsAtPath:NKCommon.shared.filenamePathLog] && NCBrandOptions.shared.disable_log == false) {
         
         row = [XLFormRowDescriptor formRowDescriptorWithTag:@"log" rowType:XLFormRowDescriptorTypeButton title:NSLocalizedString(@"_view_log_", nil)];
         row.cellConfigAtConfigure[@"backgroundColor"] = NCBrandColor.shared.secondarySystemGroupedBackground;
@@ -153,7 +153,7 @@
         row.action.formBlock = ^(XLFormRowDescriptor * sender) {
                     
             [self deselectFormRow:sender];
-            NCViewerQuickLook *viewerQuickLook = [[NCViewerQuickLook alloc] initWith:[NSURL fileURLWithPath:NCCommunicationCommon.shared.filenamePathLog] isEditingEnabled:false metadata:nil];
+            NCViewerQuickLook *viewerQuickLook = [[NCViewerQuickLook alloc] initWith:[NSURL fileURLWithPath:NKCommon.shared.filenamePathLog] isEditingEnabled:false metadata:nil];
             [self presentViewController:viewerQuickLook animated:YES completion:nil];
         };
         [section addFormRow:row];
@@ -168,15 +168,15 @@
                     
             [self deselectFormRow:sender];
 
-            [[NCCommunicationCommon shared] clearFileLog];
+            [[NKCommon shared] clearFileLog];
             
             NSInteger logLevel = [CCUtility getLogLevel];
             BOOL isSimulatorOrTestFlight = [[NCUtility shared] isSimulatorOrTestFlight];
             NSString *versionNextcloudiOS = [NSString stringWithFormat:[NCBrandOptions shared].textCopyrightNextcloudiOS, [[NCUtility shared] getVersionAppWithBuild:true]];
             if (isSimulatorOrTestFlight) {
-                [[NCCommunicationCommon shared] writeLog:[NSString stringWithFormat:@"Clear log with level %lu %@ (Simulator / TestFlight)", (unsigned long)logLevel, versionNextcloudiOS]];
+                [[NKCommon shared] writeLog:[NSString stringWithFormat:@"Clear log with level %lu %@ (Simulator / TestFlight)", (unsigned long)logLevel, versionNextcloudiOS]];
             } else {
-                [[NCCommunicationCommon shared] writeLog:[NSString stringWithFormat:@"Clear log with level %lu %@", (unsigned long)logLevel, versionNextcloudiOS]];
+                [[NKCommon shared] writeLog:[NSString stringWithFormat:@"Clear log with level %lu %@", (unsigned long)logLevel, versionNextcloudiOS]];
             }
         };
         [section addFormRow:row];
@@ -359,7 +359,7 @@
         
         NSInteger levelLog = [[rowDescriptor.value valueData] intValue];
         [CCUtility setLogLevel:levelLog];
-        [[NCCommunicationCommon shared] setLevelLog:levelLog];
+        [[NKCommon shared] setLevelLog:levelLog];
     }
     
     if ([rowDescriptor.tag isEqualToString:@"chunk"]) {

+ 2 - 1
iOSClient/Settings/CCManageAutoUpload.m

@@ -396,7 +396,8 @@
     if (serverUrl != nil) {
         
         if ([serverUrl isEqualToString:[[NCUtilityFileSystem shared] getHomeServerWithAccount:appDelegate.account]]) {
-            [[NCContentPresenter shared] messageNotification:@"_error_" description:@"_autoupload_error_select_folder_" delay:[[NCGlobal shared] dismissAfterSecond] type:messageTypeError errorCode:NCGlobal.shared.errorInternalError];
+            NKError *error = [[NKError alloc] initWithErrorCode:NCGlobal.shared.errorInternalError errorDescription:@"_autoupload_error_select_folder_"];
+            [[NCContentPresenter shared] messageNotification:@"_error_" error:error delay:[[NCGlobal shared] dismissAfterSecond] type:messageTypeError];
             return;
         }
         

Some files were not shown because too many files changed in this diff