From e51ce1152057e5fb44f2e216515ec507e3bf0383 Mon Sep 17 00:00:00 2001 From: Marino Faggiana Date: Thu, 1 Feb 2024 15:28:44 +0100 Subject: [PATCH] V 5.0.0 (#2768) V 5.0.0 --- .swiftlint.yml | 4 +- Brand/Database.swift | 2 +- Brand/NCBrand.swift | 6 +- ExternalResources/NCApplicationHandle.swift | 2 - .../FileProviderEnumerator.swift | 2 +- .../FileProviderExtension.swift | 8 +- Nextcloud.xcodeproj/project.pbxproj | 78 +- Widget/Files/FilesData.swift | 1 + iOSClient/Activity/NCActivity.swift | 2 +- iOSClient/AppDelegate.swift | 26 +- iOSClient/Data/NCDataSource.swift | 37 +- .../Data/NCManageDatabase+Capabilities.swift | 92 ++- .../Data/NCManageDatabase+Directory.swift | 23 +- iOSClient/Data/NCManageDatabase+E2EE.swift | 34 +- .../Data/NCManageDatabase+LocalFile.swift | 6 - .../Data/NCManageDatabase+Metadata.swift | 223 ++++-- .../Data/NCManageDatabase+SecurityGuard.swift | 117 +++ iOSClient/Data/NCManageDatabase+Video.swift | 5 +- iOSClient/Data/NCManageDatabase.swift | 6 +- .../Diagnostics/NCCapabilitiesView.swift | 3 + iOSClient/Extensions/String+Extension.swift | 6 + .../UIAlertController+Extension.swift | 1 - .../UINavigationController+Extension.swift | 3 +- iOSClient/Favorites/NCFavorite.swift | 33 +- iOSClient/Files/NCFiles.storyboard | 8 +- iOSClient/Files/NCFiles.swift | 132 ++-- iOSClient/Groupfolders/NCGroupfolders.swift | 32 +- iOSClient/Login/NCLogin.swift | 21 +- iOSClient/Login/NCLoginWeb.swift | 25 +- .../NCCollectionViewCommon.swift | 300 +++----- .../Main/Collection Common/NCListCell.xib | 66 +- .../NCSelectableNavigationView.swift | 10 +- .../NCCreateFormUploadDocuments.swift | 8 +- .../NCCreateFormUploadVoiceNote.swift | 2 +- .../Main/Create cloud/NCUploadAssets.swift | 2 +- iOSClient/Main/Main.storyboard | 4 +- iOSClient/Main/NCActionCenter.swift | 89 ++- iOSClient/Main/NCMainTabBar.swift | 88 ++- iOSClient/Main/NCPickerViewController.swift | 2 +- .../Section Header Footer/NCSectionFooter.xib | 21 +- .../NCSectionHeaderMenu.swift | 6 +- iOSClient/Media/NCMedia.storyboard | 8 +- iOSClient/Media/NCMedia.swift | 716 ++++------------- iOSClient/Media/NCMediaCommandView.swift | 252 ++++++ iOSClient/Media/NCMediaCommandView.xib | 174 +---- iOSClient/Media/NCMediaDataSource.swift | 137 ++++ .../Media/NCMediaDownloadThumbnaill.swift | 84 ++ iOSClient/Media/NCMediaGridLayout.swift | 64 ++ .../Menu/NCCollectionViewCommon+Menu.swift | 22 +- iOSClient/Menu/NCContextMenu.swift | 28 +- iOSClient/Menu/NCMedia+Menu.swift | 205 ----- iOSClient/Menu/NCMenuAction.swift | 11 +- iOSClient/Menu/NCOperationSaveLivePhoto.swift | 10 +- iOSClient/Menu/NCViewer+Menu.swift | 36 +- iOSClient/NCGlobal.swift | 37 +- iOSClient/NCImageCache.swift | 31 +- .../E2EE/NCEndToEndMetadataV1.swift | 5 +- .../E2EE/NCEndToEndMetadataV20.swift | 196 +++-- .../Networking/E2EE/NCNetworkingE2EE.swift | 28 +- .../E2EE/NCNetworkingE2EECreateFolder.swift | 2 +- .../E2EE/NCNetworkingE2EEMarkFolder.swift | 2 +- .../E2EE/NCNetworkingE2EEUpload.swift | 56 +- iOSClient/Networking/NCAutoUpload.swift | 14 +- iOSClient/Networking/NCNetworking.swift | 721 +++++++++++++----- .../NCNetworkingCheckRemoteUser.swift | 3 +- .../NCNetworkingProcessUpload.swift | 139 ++-- iOSClient/Networking/NCService.swift | 126 ++- iOSClient/Notification/NCNotification.swift | 2 +- iOSClient/Offline/NCOffline.swift | 23 +- .../PushNotification/NCPushNotification.m | 8 +- iOSClient/Recent/NCRecent.swift | 29 +- .../RichWorkspace/NCViewerRichWorkspace.swift | 17 +- .../Scan document/NCUploadScanDocument.swift | 2 +- iOSClient/Settings/CCAdvanced.m | 3 +- iOSClient/Settings/NCKeychain.swift | 26 +- iOSClient/Settings/NCSettings.m | 3 + iOSClient/Shares/NCShares.swift | 32 +- .../af.lproj/Localizable.strings | Bin 121828 -> 122324 bytes .../an.lproj/Localizable.strings | Bin 121200 -> 121696 bytes .../ar.lproj/Localizable.strings | Bin 120410 -> 120912 bytes .../ast.lproj/Localizable.strings | Bin 121220 -> 121716 bytes .../az.lproj/Localizable.strings | Bin 121526 -> 122020 bytes .../be.lproj/Localizable.strings | Bin 121280 -> 121776 bytes .../bg_BG.lproj/Localizable.strings | Bin 128804 -> 129300 bytes .../bn_BD.lproj/Localizable.strings | Bin 121450 -> 121946 bytes .../br.lproj/Localizable.strings | Bin 125472 -> 125968 bytes .../bs.lproj/Localizable.strings | Bin 121504 -> 122000 bytes .../ca.lproj/Localizable.strings | Bin 128526 -> 129022 bytes .../cs-CZ.lproj/Localizable.strings | Bin 125070 -> 125570 bytes .../cy_GB.lproj/Localizable.strings | Bin 121472 -> 121968 bytes .../da.lproj/Localizable.strings | Bin 122190 -> 122686 bytes .../de.lproj/Localizable.strings | Bin 132602 -> 133162 bytes .../el.lproj/Localizable.strings | Bin 132160 -> 132656 bytes .../en-GB.lproj/Localizable.strings | Bin 121300 -> 121796 bytes .../en.lproj/Localizable.strings | 7 +- .../eo.lproj/Localizable.strings | Bin 121940 -> 122436 bytes .../es-419.lproj/Localizable.strings | Bin 125358 -> 125854 bytes .../es-AR.lproj/Localizable.strings | Bin 124378 -> 124874 bytes .../es-CL.lproj/Localizable.strings | Bin 126082 -> 126578 bytes .../es-CO.lproj/Localizable.strings | Bin 125724 -> 126220 bytes .../es-CR.lproj/Localizable.strings | Bin 125716 -> 126212 bytes .../es-DO.lproj/Localizable.strings | Bin 125724 -> 126220 bytes .../es-EC.lproj/Localizable.strings | Bin 131142 -> 131638 bytes .../es-GT.lproj/Localizable.strings | Bin 125718 -> 126214 bytes .../es-HN.lproj/Localizable.strings | Bin 125342 -> 125838 bytes .../es-MX.lproj/Localizable.strings | Bin 125904 -> 126400 bytes .../es-NI.lproj/Localizable.strings | Bin 125332 -> 125828 bytes .../es-PA.lproj/Localizable.strings | Bin 125330 -> 125826 bytes .../es-PE.lproj/Localizable.strings | Bin 125330 -> 125826 bytes .../es-PR.lproj/Localizable.strings | Bin 125332 -> 125828 bytes .../es-PY.lproj/Localizable.strings | Bin 125358 -> 125854 bytes .../es-SV.lproj/Localizable.strings | Bin 125716 -> 126212 bytes .../es-UY.lproj/Localizable.strings | Bin 125356 -> 125852 bytes .../es.lproj/Localizable.strings | Bin 130286 -> 130934 bytes .../et_EE.lproj/Localizable.strings | Bin 121752 -> 122248 bytes .../eu.lproj/Localizable.strings | Bin 128614 -> 129110 bytes .../fa.lproj/Localizable.strings | Bin 122054 -> 122550 bytes .../fi-FI.lproj/Localizable.strings | Bin 124248 -> 124744 bytes .../fo.lproj/Localizable.strings | Bin 121210 -> 121706 bytes .../fr.lproj/Localizable.strings | Bin 135056 -> 135626 bytes .../gd.lproj/Localizable.strings | Bin 122710 -> 123206 bytes .../gl.lproj/Localizable.strings | Bin 130344 -> 130860 bytes .../he.lproj/Localizable.strings | Bin 119326 -> 119822 bytes .../hi_IN.lproj/Localizable.strings | Bin 121184 -> 121680 bytes .../hr.lproj/Localizable.strings | Bin 126016 -> 126512 bytes .../hsb.lproj/Localizable.strings | Bin 121190 -> 121686 bytes .../hu.lproj/Localizable.strings | Bin 127548 -> 128044 bytes .../hy.lproj/Localizable.strings | Bin 121466 -> 121962 bytes .../ia.lproj/Localizable.strings | Bin 121954 -> 122450 bytes .../id.lproj/Localizable.strings | Bin 122102 -> 122598 bytes .../ig.lproj/Localizable.strings | Bin 121160 -> 121656 bytes .../is.lproj/Localizable.strings | Bin 123480 -> 123976 bytes .../it.lproj/Localizable.strings | Bin 129638 -> 130274 bytes .../ja-JP.lproj/Localizable.strings | Bin 103934 -> 104430 bytes .../ka-GE.lproj/Localizable.strings | Bin 123918 -> 124414 bytes .../ka.lproj/Localizable.strings | Bin 121188 -> 121684 bytes .../kab.lproj/Localizable.strings | Bin 121244 -> 121740 bytes .../km.lproj/Localizable.strings | Bin 121442 -> 121938 bytes .../kn.lproj/Localizable.strings | Bin 121668 -> 122164 bytes .../ko.lproj/InfoPlist.strings | Bin 1356 -> 1064 bytes .../ko.lproj/Localizable.strings | Bin 101690 -> 99050 bytes .../la.lproj/Localizable.strings | Bin 121174 -> 121670 bytes .../lb.lproj/Localizable.strings | Bin 121592 -> 122088 bytes .../lo.lproj/Localizable.strings | Bin 119810 -> 120306 bytes .../lt_LT.lproj/Localizable.strings | Bin 123902 -> 124398 bytes .../lv.lproj/Localizable.strings | Bin 122298 -> 122794 bytes .../mk.lproj/Localizable.strings | Bin 122496 -> 122992 bytes .../mn.lproj/Localizable.strings | Bin 121962 -> 122458 bytes .../mr.lproj/Localizable.strings | Bin 121152 -> 121648 bytes .../ms_MY.lproj/Localizable.strings | Bin 121302 -> 121798 bytes .../my.lproj/Localizable.strings | Bin 121370 -> 121866 bytes .../nb-NO.lproj/Localizable.strings | Bin 122342 -> 124180 bytes .../ne.lproj/Localizable.strings | Bin 121204 -> 121700 bytes .../nl.lproj/Localizable.strings | Bin 126816 -> 127312 bytes .../nn_NO.lproj/Localizable.strings | Bin 121320 -> 121816 bytes .../oc.lproj/Localizable.strings | Bin 122294 -> 122820 bytes .../pl.lproj/Localizable.strings | Bin 126108 -> 126604 bytes .../ps.lproj/Localizable.strings | Bin 121216 -> 121712 bytes .../pt-BR.lproj/Localizable.strings | Bin 127632 -> 128306 bytes .../pt-PT.lproj/Localizable.strings | Bin 125090 -> 125586 bytes .../ro.lproj/Localizable.strings | Bin 124332 -> 124828 bytes .../ru.lproj/Localizable.strings | Bin 128068 -> 128564 bytes .../sc.lproj/Localizable.strings | Bin 130292 -> 130788 bytes .../si.lproj/Localizable.strings | Bin 122110 -> 122606 bytes .../sk-SK.lproj/Localizable.strings | Bin 125474 -> 125970 bytes .../sl.lproj/Localizable.strings | Bin 127116 -> 127612 bytes .../sq.lproj/Localizable.strings | Bin 122986 -> 123482 bytes .../sr.lproj/Localizable.strings | Bin 125072 -> 125590 bytes .../sr@latin.lproj/Localizable.strings | Bin 121488 -> 121984 bytes .../sv.lproj/Localizable.strings | Bin 123666 -> 124170 bytes .../sw.lproj/Localizable.strings | Bin 121184 -> 121680 bytes .../ta.lproj/Localizable.strings | Bin 121518 -> 122014 bytes .../th_TH.lproj/Localizable.strings | Bin 121070 -> 121566 bytes .../tk.lproj/Localizable.strings | Bin 121884 -> 122380 bytes .../tr.lproj/Localizable.strings | Bin 125932 -> 126524 bytes .../ug.lproj/Localizable.strings | Bin 121352 -> 121848 bytes .../uk.lproj/Localizable.strings | Bin 123528 -> 124062 bytes .../ur_PK.lproj/Localizable.strings | Bin 121232 -> 121728 bytes .../uz.lproj/Localizable.strings | Bin 121184 -> 121680 bytes .../vi.lproj/Localizable.strings | Bin 122062 -> 123068 bytes .../zh-Hans.lproj/Localizable.strings | Bin 89732 -> 90228 bytes .../zh-Hant-TW.lproj/Localizable.strings | Bin 100046 -> 100542 bytes .../zh_HK.lproj/Localizable.strings | Bin 90374 -> 90768 bytes .../zu_ZA.lproj/Localizable.strings | Bin 121184 -> 121680 bytes iOSClient/Transfers/NCTransfers.swift | 61 +- iOSClient/Trash/NCTrash.swift | 6 +- iOSClient/Utility/NCActivityIndicator.swift | 2 +- iOSClient/Utility/NCCameraRoll.swift | 1 - iOSClient/Utility/NCUtility+Image.swift | 2 +- iOSClient/Utility/ThreadSafeArray.swift | 338 ++++++++ iOSClient/Utility/ThreadSafeDictionary.swift | 2 +- .../Viewer/NCViewerMedia/NCViewerMedia.swift | 80 +- .../NCViewerMediaPage.storyboard | 88 +-- .../NCViewerMedia/NCViewerMediaPage.swift | 53 +- .../NCViewerNextcloudText.swift | 2 +- .../Viewer/NCViewerProviderContextMenu.swift | 6 +- .../NCViewerQuickLook/NCViewerQuickLook.swift | 2 +- .../NCViewerRichdocument.swift | 2 +- 198 files changed, 3139 insertions(+), 2301 deletions(-) create mode 100644 iOSClient/Data/NCManageDatabase+SecurityGuard.swift create mode 100644 iOSClient/Media/NCMediaCommandView.swift create mode 100644 iOSClient/Media/NCMediaDataSource.swift create mode 100644 iOSClient/Media/NCMediaDownloadThumbnaill.swift create mode 100644 iOSClient/Media/NCMediaGridLayout.swift delete mode 100644 iOSClient/Menu/NCMedia+Menu.swift create mode 100644 iOSClient/Utility/ThreadSafeArray.swift diff --git a/.swiftlint.yml b/.swiftlint.yml index 227f5743c8..f844ab07fb 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -17,8 +17,8 @@ function_body_length: warning: 400 type_body_length: - warning: 1500 - error: 2000 + warning: 2000 + error: 2500 file_length: warning: 2000 diff --git a/Brand/Database.swift b/Brand/Database.swift index fd5e3dbb3c..a6788be298 100644 --- a/Brand/Database.swift +++ b/Brand/Database.swift @@ -26,4 +26,4 @@ import Foundation // Database Realm // let databaseName = "nextcloud.realm" -let databaseSchemaVersion: UInt64 = 333 +let databaseSchemaVersion: UInt64 = 340 diff --git a/Brand/NCBrand.swift b/Brand/NCBrand.swift index 3f663e908b..2ba2363dbb 100755 --- a/Brand/NCBrand.swift +++ b/Brand/NCBrand.swift @@ -80,12 +80,14 @@ let userAgent: String = { @objc public var disable_log: Bool = false @objc public var disable_mobileconfig: Bool = false @objc public var disable_show_more_nextcloud_apps_in_settings: Bool = false + @objc public var doNotAskPasscodeAtStartup: Bool = false // Internal option behaviour @objc public var cleanUpDay: Int = 0 // Set default "Delete, in the cache, all files older than" possible days value are: 0, 1, 7, 30, 90, 180, 365 - // Max upload concurrent - public let maxConcurrentOperationUpload: Int = 10 + // Max download/upload concurrent + public let maxConcurrentOperationDownload: Int = 5 + public let maxConcurrentOperationUpload: Int = 5 // Number of failed attempts after reset app @objc public let resetAppPasscodeAttempts: Int = 10 diff --git a/ExternalResources/NCApplicationHandle.swift b/ExternalResources/NCApplicationHandle.swift index fb70c4905f..a2a85fcde7 100644 --- a/ExternalResources/NCApplicationHandle.swift +++ b/ExternalResources/NCApplicationHandle.swift @@ -28,8 +28,6 @@ import Parchment class NCApplicationHandle: NSObject { - let appDelegate = (UIApplication.shared.delegate as? AppDelegate)! - // class: AppDelegate // func nextcloudPushNotificationAction(data: [String: AnyObject]) func nextcloudPushNotificationAction(data: [String: AnyObject]) -> [String: AnyObject]? { diff --git a/File Provider Extension/FileProviderEnumerator.swift b/File Provider Extension/FileProviderEnumerator.swift index 88b40578e4..5c65bd55c2 100644 --- a/File Provider Extension/FileProviderEnumerator.swift +++ b/File Provider Extension/FileProviderEnumerator.swift @@ -174,7 +174,7 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator { for metadata in metadatas! { - if metadata.e2eEncrypted || (!metadata.session.isEmpty && metadata.session != NCNetworking.shared.sessionIdentifierBackgroundExtension) { continue } + if metadata.e2eEncrypted || (!metadata.session.isEmpty && metadata.session != NCNetworking.shared.sessionUploadBackgroundExtension) { continue } fpUtility.createocIdentifierOnFileSystem(metadata: metadata) diff --git a/File Provider Extension/FileProviderExtension.swift b/File Provider Extension/FileProviderExtension.swift index 4c7fcce254..3640ea810c 100644 --- a/File Provider Extension/FileProviderExtension.swift +++ b/File Provider Extension/FileProviderExtension.swift @@ -64,7 +64,7 @@ class FileProviderExtension: NSFileProviderExtension, NCNetworkingDelegate { // Create directory File Provider Storage _ = utilityFileSystem.directoryProviderStorage // Configure URLSession - _ = NCNetworking.shared.sessionManagerBackgroundExtension + _ = NCNetworking.shared.sessionManagerUploadBackgroundExtension } deinit { @@ -285,7 +285,7 @@ class FileProviderExtension: NSFileProviderExtension, NCNetworkingDelegate { let serverUrlFileName = metadata.serverUrl + "/" + fileName let fileNameLocalPath = url.path - if let task = NKBackground(nkCommonInstance: NextcloudKit.shared.nkCommonInstance).upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, dateCreationFile: nil, dateModificationFile: nil, description: metadata.ocId, session: NCNetworking.shared.sessionManagerBackgroundExtension) { + if let task = NKBackground(nkCommonInstance: NextcloudKit.shared.nkCommonInstance).upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, dateCreationFile: nil, dateModificationFile: nil, description: metadata.ocId, session: NCNetworking.shared.sessionManagerUploadBackgroundExtension) { fileProviderData.shared.fileProviderManager.register(task, forItemWithIdentifier: NSFileProviderItemIdentifier(metadata.fileId)) { _ in } } @@ -356,7 +356,7 @@ class FileProviderExtension: NSFileProviderExtension, NCNetworkingDelegate { fileURL.stopAccessingSecurityScopedResource() let metadata = NCManageDatabase.shared.createMetadata(account: fileProviderData.shared.account, user: fileProviderData.shared.user, userId: fileProviderData.shared.userId, fileName: fileName, fileNameView: fileName, ocId: ocIdTemp, serverUrl: tableDirectory.serverUrl, urlBase: fileProviderData.shared.accountUrlBase, url: "", contentType: "") - metadata.session = NCNetworking.shared.sessionIdentifierBackgroundExtension + metadata.session = NCNetworking.shared.sessionUploadBackgroundExtension metadata.size = size metadata.status = NCGlobal.shared.metadataStatusUploading @@ -365,7 +365,7 @@ class FileProviderExtension: NSFileProviderExtension, NCNetworkingDelegate { let serverUrlFileName = tableDirectory.serverUrl + "/" + fileName let fileNameLocalPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(ocIdTemp, fileNameView: fileName) - if let task = NKBackground(nkCommonInstance: NextcloudKit.shared.nkCommonInstance).upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, dateCreationFile: nil, dateModificationFile: nil, description: ocIdTemp, session: NCNetworking.shared.sessionManagerBackgroundExtension) { + if let task = NKBackground(nkCommonInstance: NextcloudKit.shared.nkCommonInstance).upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, dateCreationFile: nil, dateModificationFile: nil, description: ocIdTemp, session: NCNetworking.shared.sessionManagerUploadBackgroundExtension) { self.outstandingSessionTasks[URL(fileURLWithPath: fileNameLocalPath)] = task as URLSessionTask diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index ac58db313f..2ad1b37ef0 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -202,6 +202,13 @@ F719D9E0288D37A300762E33 /* NCColorPicker.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F719D9DF288D37A300762E33 /* NCColorPicker.storyboard */; }; F719D9E2288D396100762E33 /* NCColorPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = F719D9E1288D396100762E33 /* NCColorPicker.swift */; }; F71CD6CA2930D7B1006C95C1 /* NCApplicationHandle.swift in Sources */ = {isa = PBXBuildFile; fileRef = F71CD6C92930D7B1006C95C1 /* NCApplicationHandle.swift */; }; + F71F6D072B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = F71F6D062B6A6A5E00F1EB15 /* ThreadSafeArray.swift */; }; + F71F6D082B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = F71F6D062B6A6A5E00F1EB15 /* ThreadSafeArray.swift */; }; + F71F6D092B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = F71F6D062B6A6A5E00F1EB15 /* ThreadSafeArray.swift */; }; + F71F6D0A2B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = F71F6D062B6A6A5E00F1EB15 /* ThreadSafeArray.swift */; }; + F71F6D0B2B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = F71F6D062B6A6A5E00F1EB15 /* ThreadSafeArray.swift */; }; + F71F6D0C2B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = F71F6D062B6A6A5E00F1EB15 /* ThreadSafeArray.swift */; }; + F71F6D0D2B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = F71F6D062B6A6A5E00F1EB15 /* ThreadSafeArray.swift */; }; 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 */; }; @@ -409,7 +416,6 @@ F757CC8C29E82D0500F31428 /* NCGroupfolders.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F757CC8A29E82D0500F31428 /* NCGroupfolders.storyboard */; }; F757CC8D29E82D0500F31428 /* NCGroupfolders.swift in Sources */ = {isa = PBXBuildFile; fileRef = F757CC8B29E82D0500F31428 /* NCGroupfolders.swift */; }; F7581D1A25EFDA61004DC699 /* NCLoginWeb+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7581D1925EFDA60004DC699 /* NCLoginWeb+Menu.swift */; }; - F7581D2425EFDDDF004DC699 /* NCMedia+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7581D2325EFDDDF004DC699 /* NCMedia+Menu.swift */; }; F758A01227A7F03E0069468B /* JGProgressHUD in Frameworks */ = {isa = PBXBuildFile; productRef = F758A01127A7F03E0069468B /* JGProgressHUD */; }; F758B45A212C564000515F55 /* NCScan.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F758B457212C564000515F55 /* NCScan.storyboard */; }; F758B45E212C569D00515F55 /* NCScanCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F758B45D212C569C00515F55 /* NCScanCell.swift */; }; @@ -588,6 +594,9 @@ F78ACD4B21903F850088454D /* NCTrashListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F78ACD4921903F850088454D /* NCTrashListCell.xib */; }; F78ACD52219046DC0088454D /* NCSectionHeaderMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD51219046DC0088454D /* NCSectionHeaderMenu.swift */; }; F78ACD54219047D40088454D /* NCSectionFooter.xib in Resources */ = {isa = PBXBuildFile; fileRef = F78ACD53219047D40088454D /* NCSectionFooter.xib */; }; + F78B87E72B62527100C65ADC /* NCMediaDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78B87E62B62527100C65ADC /* NCMediaDataSource.swift */; }; + F78B87E92B62550800C65ADC /* NCMediaDownloadThumbnaill.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78B87E82B62550800C65ADC /* NCMediaDownloadThumbnaill.swift */; }; + F78B87EB2B627AA100C65ADC /* NCMediaCommandView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78B87EA2B627AA100C65ADC /* NCMediaCommandView.swift */; }; F78C6FDE296D677300C952C3 /* NCContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78C6FDD296D677300C952C3 /* NCContextMenu.swift */; }; F78E2D6529AF02DB0024D4F3 /* Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78E2D6429AF02DB0024D4F3 /* Database.swift */; }; F78E2D6629AF02DB0024D4F3 /* Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78E2D6429AF02DB0024D4F3 /* Database.swift */; }; @@ -670,6 +679,7 @@ F7BB7E4727A18C56009B9F29 /* Parchment in Frameworks */ = {isa = PBXBuildFile; productRef = F7BB7E4627A18C56009B9F29 /* Parchment */; }; F7BC287E26663F6C004D46C5 /* NCViewCertificateDetails.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7BC287D26663F6C004D46C5 /* NCViewCertificateDetails.storyboard */; }; F7BC288026663F85004D46C5 /* NCViewCertificateDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BC287F26663F85004D46C5 /* NCViewCertificateDetails.swift */; }; + F7BD50312B65216300D5AEF9 /* NCMediaGridLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BD50302B65216300D5AEF9 /* NCMediaGridLayout.swift */; }; F7BD71E62636EAFC00643C34 /* NCNetworkingE2EE.swift in Sources */ = {isa = PBXBuildFile; fileRef = F785EE9C246196DF00B3F945 /* NCNetworkingE2EE.swift */; }; F7BF9D822934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BF9D812934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift */; }; F7BF9D832934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BF9D812934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift */; }; @@ -694,6 +704,13 @@ F7C9739228F17131002C43E2 /* Intents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7C9739128F17131002C43E2 /* Intents.framework */; }; F7C9739528F17131002C43E2 /* IntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C9739428F17131002C43E2 /* IntentHandler.swift */; }; F7C9739928F17131002C43E2 /* WidgetDashboardIntentHandler.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = F7C9739028F17131002C43E2 /* WidgetDashboardIntentHandler.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + F7C9B91D2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C9B91C2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift */; }; + F7C9B91E2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C9B91C2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift */; }; + F7C9B91F2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C9B91C2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift */; }; + F7C9B9202B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C9B91C2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift */; }; + F7C9B9212B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C9B91C2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift */; }; + F7C9B9222B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C9B91C2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift */; }; + F7C9B9232B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C9B91C2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift */; }; F7CA212D25F1333300826ABB /* NCAccountRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CA212B25F1333200826ABB /* NCAccountRequest.swift */; }; F7CA212E25F1333300826ABB /* NCAccountRequest.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7CA212C25F1333200826ABB /* NCAccountRequest.storyboard */; }; F7CB689A2541676B0050EC94 /* NCMore.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7CB68992541676B0050EC94 /* NCMore.storyboard */; }; @@ -1038,6 +1055,7 @@ F719D9DF288D37A300762E33 /* NCColorPicker.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCColorPicker.storyboard; sourceTree = ""; }; F719D9E1288D396100762E33 /* NCColorPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCColorPicker.swift; sourceTree = ""; }; F71CD6C92930D7B1006C95C1 /* NCApplicationHandle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCApplicationHandle.swift; sourceTree = ""; }; + F71F6D062B6A6A5E00F1EB15 /* ThreadSafeArray.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadSafeArray.swift; sourceTree = ""; }; F7226EDB1EE4089300EBECB1 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; F723985B253C95CE00257F49 /* NCViewerRichdocument.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCViewerRichdocument.storyboard; sourceTree = ""; }; F7239870253D86B600257F49 /* NCEmptyDataSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCEmptyDataSet.swift; sourceTree = ""; }; @@ -1116,7 +1134,6 @@ F757CC8A29E82D0500F31428 /* NCGroupfolders.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCGroupfolders.storyboard; sourceTree = ""; }; F757CC8B29E82D0500F31428 /* NCGroupfolders.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCGroupfolders.swift; sourceTree = ""; }; F7581D1925EFDA60004DC699 /* NCLoginWeb+Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCLoginWeb+Menu.swift"; sourceTree = ""; }; - F7581D2325EFDDDF004DC699 /* NCMedia+Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCMedia+Menu.swift"; sourceTree = ""; }; F758B457212C564000515F55 /* NCScan.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCScan.storyboard; sourceTree = ""; }; F758B45D212C569C00515F55 /* NCScanCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCScanCell.swift; sourceTree = ""; }; F758B45F212C56A400515F55 /* NCScan.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCScan.swift; sourceTree = ""; }; @@ -1233,6 +1250,9 @@ F78ACD4921903F850088454D /* NCTrashListCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCTrashListCell.xib; sourceTree = ""; }; F78ACD51219046DC0088454D /* NCSectionHeaderMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSectionHeaderMenu.swift; sourceTree = ""; }; F78ACD53219047D40088454D /* NCSectionFooter.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCSectionFooter.xib; sourceTree = ""; }; + F78B87E62B62527100C65ADC /* NCMediaDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMediaDataSource.swift; sourceTree = ""; }; + F78B87E82B62550800C65ADC /* NCMediaDownloadThumbnaill.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMediaDownloadThumbnaill.swift; sourceTree = ""; }; + F78B87EA2B627AA100C65ADC /* NCMediaCommandView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMediaCommandView.swift; sourceTree = ""; }; F78C6FDD296D677300C952C3 /* NCContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCContextMenu.swift; sourceTree = ""; }; F78D6F461F0B7CB9002F9619 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/Localizable.strings"; sourceTree = ""; }; F78D6F4D1F0B7CE4002F9619 /* nb-NO */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "nb-NO"; path = "nb-NO.lproj/Localizable.strings"; sourceTree = ""; }; @@ -1331,6 +1351,7 @@ F7BB04851FD58ACB00BBFD2A /* cs-CZ */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "cs-CZ"; path = "cs-CZ.lproj/Localizable.strings"; sourceTree = ""; }; F7BC287D26663F6C004D46C5 /* NCViewCertificateDetails.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCViewCertificateDetails.storyboard; sourceTree = ""; }; F7BC287F26663F85004D46C5 /* NCViewCertificateDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCViewCertificateDetails.swift; sourceTree = ""; }; + F7BD50302B65216300D5AEF9 /* NCMediaGridLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMediaGridLayout.swift; sourceTree = ""; }; F7BE7C25290AC8C9002ABB61 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Intent.strings; sourceTree = ""; }; F7BE7C27290ADEFD002ABB61 /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/Intent.strings; sourceTree = ""; }; F7BE7C29290ADEFD002ABB61 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/Intent.strings; sourceTree = ""; }; @@ -1398,6 +1419,7 @@ F7C9739028F17131002C43E2 /* WidgetDashboardIntentHandler.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = WidgetDashboardIntentHandler.appex; sourceTree = BUILT_PRODUCTS_DIR; }; F7C9739128F17131002C43E2 /* Intents.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Intents.framework; path = System/Library/Frameworks/Intents.framework; sourceTree = SDKROOT; }; F7C9739428F17131002C43E2 /* IntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentHandler.swift; sourceTree = ""; }; + F7C9B91C2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+SecurityGuard.swift"; sourceTree = ""; }; F7CA212B25F1333200826ABB /* NCAccountRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCAccountRequest.swift; sourceTree = ""; }; F7CA212C25F1333200826ABB /* NCAccountRequest.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCAccountRequest.storyboard; sourceTree = ""; }; F7CB68992541676B0050EC94 /* NCMore.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCMore.storyboard; sourceTree = ""; }; @@ -1627,7 +1649,6 @@ 8491B1CC273BBA82001C8C5B /* UIViewController+Menu.swift */, F77A697C250A0FBC00FF1708 /* NCCollectionViewCommon+Menu.swift */, F7581D1925EFDA60004DC699 /* NCLoginWeb+Menu.swift */, - F7581D2325EFDDDF004DC699 /* NCMedia+Menu.swift */, F7CBC31B24F78E79004D3812 /* NCSortMenu.swift */, F75D19E225EFE09000D74598 /* NCTrash+Menu.swift */, AF93471127E2341B002537EE /* NCShare+Menu.swift */, @@ -2295,6 +2316,7 @@ F7864ACB2A78FE73004870E0 /* NCManageDatabase+LocalFile.swift */, AF4BF61827562A4B0081CEEF /* NCManageDatabase+Metadata.swift */, F73EF7C62B0225610087E6E9 /* NCManageDatabase+PhotoLibrary.swift */, + F7C9B91C2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift */, F749B649297B0CBB00087535 /* NCManageDatabase+Share.swift */, F73EF7CE2B0225BA0087E6E9 /* NCManageDatabase+Tag.swift */, F73EF7D62B0226080087E6E9 /* NCManageDatabase+Tip.swift */, @@ -2339,6 +2361,7 @@ F74AF3A3247FB6AE00AC767B /* NCUtilityFileSystem.swift */, F702F2FC25EE5D2C008F8E80 /* NYMnemonic */, AF36077027BFA4E8001A243D /* ParallelWorker.swift */, + F71F6D062B6A6A5E00F1EB15 /* ThreadSafeArray.swift */, F7245923289BB50B00474787 /* ThreadSafeDictionary.swift */, ); path = Utility; @@ -2471,7 +2494,11 @@ F720B5B72507B9A5008C94E5 /* Cell */, F7501C302212E57400FB1415 /* NCMedia.storyboard */, F7501C312212E57400FB1415 /* NCMedia.swift */, + F78B87EA2B627AA100C65ADC /* NCMediaCommandView.swift */, F7F1E54B2492369A00E42386 /* NCMediaCommandView.xib */, + F78B87E62B62527100C65ADC /* NCMediaDataSource.swift */, + F78B87E82B62550800C65ADC /* NCMediaDownloadThumbnaill.swift */, + F7BD50302B65216300D5AEF9 /* NCMediaGridLayout.swift */, ); path = Media; sourceTree = ""; @@ -3439,6 +3466,7 @@ F749B64F297B0CBB00087535 /* NCManageDatabase+Share.swift in Sources */, F359D86D2A7D03420023F405 /* NCUtility+Exif.swift in Sources */, F73EF7AD2B0223900087E6E9 /* NCManageDatabase+Comments.swift in Sources */, + F7C9B9232B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */, F73EF7CD2B0225610087E6E9 /* NCManageDatabase+PhotoLibrary.swift in Sources */, D575039F27146F93008DC9DC /* String+Extension.swift in Sources */, F769CA1A2966EA3C00039397 /* ComponentView.swift in Sources */, @@ -3456,6 +3484,7 @@ F343A4B92A1E084400DDA874 /* PHAsset+Extension.swift in Sources */, F73EF7E52B02266D0087E6E9 /* NCManageDatabase+Trash.swift in Sources */, F73EF7D52B0225BA0087E6E9 /* NCManageDatabase+Tag.swift in Sources */, + F71F6D0D2B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */, F763D2A32A249C4500A3C901 /* NCManageDatabase+Capabilities.swift in Sources */, F749B656297B0F2400087535 /* NCManageDatabase+Avatar.swift in Sources */, F782FDC424E6933900666099 /* NCUtility.swift in Sources */, @@ -3518,11 +3547,13 @@ F7183BD82AEBDCD8000CD020 /* NCKeychain.swift in Sources */, F7490E8129882C79009DCE94 /* NCManageDatabase+DashboardWidget.swift in Sources */, F73EF7D42B0225BA0087E6E9 /* NCManageDatabase+Tag.swift in Sources */, + F71F6D0C2B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */, F7490E8629882C99009DCE94 /* NCUtilityFileSystem.swift in Sources */, F763D2A22A249C4500A3C901 /* NCManageDatabase+Capabilities.swift in Sources */, F73EF7E42B02266D0087E6E9 /* NCManageDatabase+Trash.swift in Sources */, F343A4C02A1E734600DDA874 /* Optional+Extension.swift in Sources */, F711A4E12AF92CAE00095DD8 /* NCUtility+Date.swift in Sources */, + F7C9B9222B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */, F7490E8529882C8C009DCE94 /* NCManageDatabase+Video.swift in Sources */, F7490E8C29882D02009DCE94 /* CCUtility.m in Sources */, F7490E7729882C10009DCE94 /* UIColor+Extension.swift in Sources */, @@ -3555,6 +3586,7 @@ buildActionMask = 2147483647; files = ( F7864ACF2A78FE73004870E0 /* NCManageDatabase+LocalFile.swift in Sources */, + F71F6D0A2B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */, F7245925289BB59100474787 /* ThreadSafeDictionary.swift in Sources */, F7EDE4E5262D7BBE00414FE6 /* NCSectionHeaderMenu.swift in Sources */, F7BF9D852934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */, @@ -3585,6 +3617,7 @@ AF4BF615275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */, F798F0E225880608000DAFFD /* UIColor+Extension.swift in Sources */, AF3FDCC32796F3FB00710F60 /* NCTrashListCell+NCTrashCellProtocol.swift in Sources */, + F7C9B9202B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */, AF817EF2274BC781009ED85B /* NCUserBaseUrl.swift in Sources */, F78E2D6829AF02DB0024D4F3 /* Database.swift in Sources */, F711A4DF2AF92CAE00095DD8 /* NCUtility+Date.swift in Sources */, @@ -3662,6 +3695,7 @@ F711D63128F44801003F43C8 /* IntentHandler.swift in Sources */, F76DEE9728F808AF0041B1C9 /* LockscreenData.swift in Sources */, F72EA95A28B7BD0D00C88F0C /* FilesWidgetView.swift in Sources */, + F71F6D082B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */, F78302FE28B4C44700B84583 /* NCBrand.swift in Sources */, F749B64B297B0CBB00087535 /* NCManageDatabase+Share.swift in Sources */, F7075B682AE15F8100512300 /* NCCellProtocol.swift in Sources */, @@ -3705,6 +3739,7 @@ F73EF7E02B02266D0087E6E9 /* NCManageDatabase+Trash.swift in Sources */, F73EF7E82B0226B90087E6E9 /* NCManageDatabase+UserStatus.swift in Sources */, F73EF7D82B0226080087E6E9 /* NCManageDatabase+Tip.swift in Sources */, + F7C9B91E2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */, F72FD3B6297ED49A00075D28 /* NCManageDatabase+E2EE.swift in Sources */, F783030128B4C49700B84583 /* UIImage+Extension.swift in Sources */, F72EA95428B7BABA00C88F0C /* FilesWidgetProvider.swift in Sources */, @@ -3738,6 +3773,7 @@ F7D68FCF28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */, F73EF7CB2B0225610087E6E9 /* NCManageDatabase+PhotoLibrary.swift in Sources */, F73EF7C32B02250B0087E6E9 /* NCManageDatabase+GPS.swift in Sources */, + F7C9B9212B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */, F359D86B2A7D03420023F405 /* NCUtility+Exif.swift in Sources */, F7864AD02A78FE73004870E0 /* NCManageDatabase+LocalFile.swift in Sources */, F7183BD72AEBDCD8000CD020 /* NCKeychain.swift in Sources */, @@ -3763,6 +3799,7 @@ F72429372AFE39980040AEF3 /* NCLivePhoto.swift in Sources */, F7A76DCD256A71CE00119AB3 /* UIImage+Extension.swift in Sources */, F73EF7DB2B0226080087E6E9 /* NCManageDatabase+Tip.swift in Sources */, + F71F6D0B2B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */, F73EF7EB2B0226B90087E6E9 /* NCManageDatabase+UserStatus.swift in Sources */, F771E3F820E239B500AFB62D /* FileProviderExtension+Thumbnail.swift in Sources */, F343A4BF2A1E734600DDA874 /* Optional+Extension.swift in Sources */, @@ -3819,6 +3856,7 @@ F78A18B823CDE2B300F681F3 /* NCViewerRichWorkspace.swift in Sources */, F7A60F86292D215000FCE1F2 /* NCShareAccounts.swift in Sources */, F77910AB25DD53C700CEDB9E /* NCSettingsBundleHelper.swift in Sources */, + F78B87EB2B627AA100C65ADC /* NCMediaCommandView.swift in Sources */, F73EF7B72B0224AB0087E6E9 /* NCManageDatabase+ExternalSites.swift in Sources */, AF4BF61927562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */, F73EF7E72B0226B90087E6E9 /* NCManageDatabase+UserStatus.swift in Sources */, @@ -3872,6 +3910,7 @@ AFCE353327E4ED1900FEA6C2 /* UIToolbar+Extension.swift in Sources */, 8491B1CD273BBA82001C8C5B /* UIViewController+Menu.swift in Sources */, F73EF7BF2B02250B0087E6E9 /* NCManageDatabase+GPS.swift in Sources */, + F71F6D072B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */, F761856C29E98543006EB3B0 /* NCIntroCollectionViewCell.swift in Sources */, F75DD765290ABB25002EB562 /* Intent.intentdefinition in Sources */, F74B6D952A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */, @@ -3888,6 +3927,7 @@ F72944F22A84246400246839 /* NCEndToEndMetadataV20.swift in Sources */, F70BFC7420E0FA7D00C67599 /* NCUtility.swift in Sources */, F79EDAA526B004980007D134 /* NCPlayer.swift in Sources */, + F7BD50312B65216300D5AEF9 /* NCMediaGridLayout.swift in Sources */, F7C1EEA525053A9C00866ACC /* NCDataSource.swift in Sources */, F713FF002472764100214AF6 /* UIImage+animatedGIF.m in Sources */, AFCE353527E4ED5900FEA6C2 /* DateFormatter+Extension.swift in Sources */, @@ -3902,10 +3942,10 @@ F765F73125237E3F00391DBE /* NCRecent.swift in Sources */, F76B3CCE1EAE01BD00921AC9 /* NCBrand.swift in Sources */, F359D8672A7D03420023F405 /* NCUtility+Exif.swift in Sources */, - F7581D2425EFDDDF004DC699 /* NCMedia+Menu.swift in Sources */, F738D4902756740100CD1D38 /* NCLoginNavigationController.swift in Sources */, F77B0E981D118A16002130FE /* CCManageAccount.m in Sources */, F769CA192966EA3C00039397 /* ComponentView.swift in Sources */, + F7C9B91D2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */, AF93474C27E34120002537EE /* NCUtility+Image.swift in Sources */, F702F30125EE5D2C008F8E80 /* NYMnemonic.m in Sources */, AF93474E27E3F212002537EE /* NCShareNewUserAddComment.swift in Sources */, @@ -3947,6 +3987,7 @@ F70968A424212C4E00ED60E5 /* NCLivePhoto.swift in Sources */, F7C30DFA291BCF790017149B /* NCNetworkingE2EECreateFolder.swift in Sources */, F7BC288026663F85004D46C5 /* NCViewCertificateDetails.swift in Sources */, + F78B87E92B62550800C65ADC /* NCMediaDownloadThumbnaill.swift in Sources */, F73EF7AF2B0224350087E6E9 /* NCManageDatabase+DirectEditing.swift in Sources */, F702F2E625EE5C86008F8E80 /* NCAudioRecorderViewController.swift in Sources */, D5B6AA7827200C7200D49C24 /* NCActivityTableViewCell.swift in Sources */, @@ -3972,6 +4013,7 @@ F7A7FA6329265CF4000603EF /* NCManageE2EE.swift in Sources */, F7C7B489245EBA4100D93E60 /* NCViewerQuickLook.swift in Sources */, F758B45E212C569D00515F55 /* NCScanCell.swift in Sources */, + F78B87E72B62527100C65ADC /* NCMediaDataSource.swift in Sources */, F7581D1A25EFDA61004DC699 /* NCLoginWeb+Menu.swift in Sources */, F7864ACC2A78FE73004870E0 /* NCManageDatabase+LocalFile.swift in Sources */, F7F4F11027ECDC4A008676F9 /* UIDevice+Extension.swift in Sources */, @@ -4002,6 +4044,7 @@ F7C9739528F17131002C43E2 /* IntentHandler.swift in Sources */, F7A8D73D28F181D3008BBE1C /* NCUtilityFileSystem.swift in Sources */, F73EF7E12B02266D0087E6E9 /* NCManageDatabase+Trash.swift in Sources */, + F7C9B91F2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */, F7A8D74528F1828E008BBE1C /* CCUtility.m in Sources */, F75DD767290ABB25002EB562 /* Intent.intentdefinition in Sources */, F749B64C297B0CBB00087535 /* NCManageDatabase+Share.swift in Sources */, @@ -4034,6 +4077,7 @@ F73EF7D12B0225BA0087E6E9 /* NCManageDatabase+Tag.swift in Sources */, F73EF7C92B0225610087E6E9 /* NCManageDatabase+PhotoLibrary.swift in Sources */, F73EF7B92B0224AB0087E6E9 /* NCManageDatabase+ExternalSites.swift in Sources */, + F71F6D092B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */, F757CC8429E7F88B00F31428 /* NCManageDatabase+Groupfolders.swift in Sources */, F78E2D6729AF02DB0024D4F3 /* Database.swift in Sources */, F7A8D73628F17E1A008BBE1C /* NCManageDatabase+Activity.swift in Sources */, @@ -4308,7 +4352,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.2; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; OTHER_LDFLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudTests; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -4325,7 +4369,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.2; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; OTHER_LDFLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudTests; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -4360,7 +4404,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.2; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MARKETING_VERSION = 1.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; @@ -4398,7 +4442,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.2; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MARKETING_VERSION = 1.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; @@ -4441,7 +4485,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.2; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MARKETING_VERSION = 1.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; @@ -4480,7 +4524,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.2; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MARKETING_VERSION = 1.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; @@ -4522,7 +4566,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.2; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MARKETING_VERSION = 1.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; @@ -4561,7 +4605,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.2; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MARKETING_VERSION = 1.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; @@ -4873,7 +4917,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 4; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = NKUJUXUJ3B; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -4899,7 +4943,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 4.9.6; + MARKETING_VERSION = 5.0.0; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ""; SDKROOT = iphoneos; @@ -4938,7 +4982,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = NKUJUXUJ3B; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -4961,7 +5005,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 4.9.6; + MARKETING_VERSION = 5.0.0; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ""; SDKROOT = iphoneos; @@ -5253,7 +5297,7 @@ repositoryURL = "https://github.com/nextcloud/NextcloudKit"; requirement = { kind = exactVersion; - version = 2.9.4; + version = 2.9.5; }; }; F788ECC5263AAAF900ADC67F /* XCRemoteSwiftPackageReference "MarkdownKit" */ = { diff --git a/Widget/Files/FilesData.swift b/Widget/Files/FilesData.swift index a4de68a960..b86dff7337 100644 --- a/Widget/Files/FilesData.swift +++ b/Widget/Files/FilesData.swift @@ -213,6 +213,7 @@ func getFilesDataEntry(configuration: AccountIntent?, isPreview: Bool, displaySi var datas: [FilesData] = [] var imageRecent = UIImage(named: "file")! let title = getTitleFilesWidget(account: account) + let files = files.sorted(by: { ($0.date as Date) > ($1.date as Date) }) for file in files { diff --git a/iOSClient/Activity/NCActivity.swift b/iOSClient/Activity/NCActivity.swift index 7f2d073af2..4f3f93ac40 100644 --- a/iOSClient/Activity/NCActivity.swift +++ b/iOSClient/Activity/NCActivity.swift @@ -100,7 +100,7 @@ class NCActivity: UIViewController, NCSharePagingContent { appDelegate.activeViewController = self - navigationController?.setFileAppreance() + navigationController?.setNavigationBarAppearance() fetchAll(isInitial: true) } diff --git a/iOSClient/AppDelegate.swift b/iOSClient/AppDelegate.swift index 73b413483b..c5564b81dc 100644 --- a/iOSClient/AppDelegate.swift +++ b/iOSClient/AppDelegate.swift @@ -156,13 +156,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD self.handleProcessingTask(task) } - // Intro - if NCBrandOptions.shared.disable_intro { - if account.isEmpty { + if account.isEmpty { + if NCBrandOptions.shared.disable_intro { openLogin(viewController: nil, selector: NCGlobal.shared.introLogin, openLoginWeb: false) - } - } else { - if !NCKeychain().intro { + } else { if let viewController = UIStoryboard(name: "NCIntro", bundle: nil).instantiateInitialViewController() { let navigationController = NCLoginNavigationController(rootViewController: viewController) window?.rootViewController = navigationController @@ -272,6 +269,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD scheduleAppRefresh() scheduleAppProcessing() + NCNetworking.shared.cancelAllQueue() NCNetworking.shared.cancelDataTask() NCNetworking.shared.cancelDownloadTasks() presentPasscode { } @@ -579,6 +577,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD @objc func changeAccount(_ account: String, userProfile: NKUserProfile?) { + NCNetworking.shared.cancelAllQueue() NCNetworking.shared.cancelDataTask() NCNetworking.shared.cancelDownloadTasks() NCNetworking.shared.cancelUploadTasks() @@ -882,10 +881,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD let utilityFileSystem = NCUtilityFileSystem() + NCNetworking.shared.cancelAllQueue() NCNetworking.shared.cancelDataTask() NCNetworking.shared.cancelDownloadTasks() NCNetworking.shared.cancelUploadTasks() - NCNetworking.shared.cancelUploadBackgroundTask() + NCNetworking.shared.cancelUploadBackgroundTask(withNotification: false) URLCache.shared.memoryCapacity = 0 URLCache.shared.diskCapacity = 0 @@ -928,18 +928,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD } } - // MARK: - Queue - - @objc func cancelAllQueue() { - NCNetworking.shared.downloadQueue.cancelAll() - NCNetworking.shared.downloadThumbnailQueue.cancelAll() - NCNetworking.shared.downloadThumbnailActivityQueue.cancelAll() - NCNetworking.shared.downloadAvatarQueue.cancelAll() - NCNetworking.shared.unifiedSearchQueue.cancelAll() - NCNetworking.shared.saveLivePhotoQueue.cancelAll() - NCNetworking.shared.convertLivePhotoQueue.cancelAll() - } - // MARK: - Universal Links func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { diff --git a/iOSClient/Data/NCDataSource.swift b/iOSClient/Data/NCDataSource.swift index 571be838ab..1c235ce1b1 100644 --- a/iOSClient/Data/NCDataSource.swift +++ b/iOSClient/Data/NCDataSource.swift @@ -137,7 +137,7 @@ class NCDataSource: NSObject { } else { - // normal + // normal let directory = NSLocalizedString("directory", comment: "").lowercased().firstUppercased self.sectionsValue = self.sectionsValue.sorted { if directoryOnTop && $0 == directory { @@ -191,10 +191,9 @@ class NCDataSource: NSObject { // MARK: - - @discardableResult - func appendMetadatasToSection(_ metadatas: [tableMetadata], metadataForSection: NCMetadataForSection, lastSearchResult: NKSearchResult) -> [IndexPath] { + func appendMetadatasToSection(_ metadatas: [tableMetadata], metadataForSection: NCMetadataForSection, lastSearchResult: NKSearchResult) { - guard let sectionIndex = getSectionIndex(metadataForSection.sectionValue) else { return [] } + guard let sectionIndex = getSectionIndex(metadataForSection.sectionValue) else { return } var indexPaths: [IndexPath] = [] self.metadatas.append(contentsOf: metadatas) @@ -207,36 +206,6 @@ class NCDataSource: NSObject { indexPaths.append(IndexPath(row: rowIndex, section: sectionIndex)) } } - - return indexPaths - } - - @discardableResult - func reloadMetadata(ocId: String, ocIdTemp: String? = nil) -> (indexPath: IndexPath?, sameSections: Bool) { - - let numberOfSections = self.numberOfSections() - var ocIdSearch = ocId - - guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { return (nil, self.isSameNumbersOfSections(numberOfSections: numberOfSections)) } - - if let ocIdTemp = ocIdTemp { - ocIdSearch = ocIdTemp - } - - // UPDATE metadataForSection (IMPORTANT FIRST) - let (indexPath, metadataForSection) = self.getIndexPathMetadata(ocId: ocIdSearch) - if let indexPath = indexPath, let metadataForSection = metadataForSection { - metadataForSection.metadatas[indexPath.row] = metadata - metadataForSection.createMetadatas() - } - - // UPDATE metadatasSource (IMPORTANT LAST) - if let rowIndex = self.metadatas.firstIndex(where: {$0.ocId == ocIdSearch}) { - self.metadatas[rowIndex] = metadata - } - - let result = self.getIndexPathMetadata(ocId: ocId) - return (result.indexPath, self.isSameNumbersOfSections(numberOfSections: numberOfSections)) } // MARK: - diff --git a/iOSClient/Data/NCManageDatabase+Capabilities.swift b/iOSClient/Data/NCManageDatabase+Capabilities.swift index 371b87bada..c7ace85909 100644 --- a/iOSClient/Data/NCManageDatabase+Capabilities.swift +++ b/iOSClient/Data/NCManageDatabase+Capabilities.swift @@ -102,6 +102,7 @@ extension NCManageDatabase { let userstatus: UserStatus? let external: External? let groupfolders: GroupFolders? + let securityguard: SecurityGuard? enum CodingKeys: String, CodingKey { case filessharing = "files_sharing" @@ -110,6 +111,7 @@ extension NCManageDatabase { case richdocuments, activity, notifications, files case userstatus = "user_status" case external, groupfolders + case securityguard = "security_guard" } struct FilesSharing: Codable { @@ -263,6 +265,10 @@ extension NCManageDatabase { struct GroupFolders: Codable { let hasGroupFolders: Bool? } + + struct SecurityGuard: Codable { + let diagnostics: Bool? + } } } } @@ -288,65 +294,69 @@ extension NCManageDatabase { guard let jsonData = jsonData else { return } do { + var global = NCGlobal.shared let json = try JSONDecoder().decode(CapabilityNextcloud.self, from: jsonData) - NCGlobal.shared.capabilityServerVersion = json.ocs.data.version.string - NCGlobal.shared.capabilityServerVersionMajor = json.ocs.data.version.major + var data = json.ocs.data + + global.capabilityServerVersion = data.version.string + global.capabilityServerVersionMajor = data.version.major - if NCGlobal.shared.capabilityServerVersionMajor > 0 { - NextcloudKit.shared.setup(nextcloudVersion: NCGlobal.shared.capabilityServerVersionMajor) + if global.capabilityServerVersionMajor > 0 { + NextcloudKit.shared.setup(nextcloudVersion: global.capabilityServerVersionMajor) } - NCGlobal.shared.capabilityFileSharingApiEnabled = json.ocs.data.capabilities.filessharing?.apienabled ?? false - NCGlobal.shared.capabilityFileSharingDefaultPermission = json.ocs.data.capabilities.filessharing?.defaultpermissions ?? 0 - NCGlobal.shared.capabilityFileSharingPubPasswdEnforced = json.ocs.data.capabilities.filessharing?.ncpublic?.password?.enforced ?? false - NCGlobal.shared.capabilityFileSharingPubExpireDateEnforced = json.ocs.data.capabilities.filessharing?.ncpublic?.expiredate?.enforced ?? false - NCGlobal.shared.capabilityFileSharingPubExpireDateDays = json.ocs.data.capabilities.filessharing?.ncpublic?.expiredate?.days ?? 0 - NCGlobal.shared.capabilityFileSharingInternalExpireDateEnforced = json.ocs.data.capabilities.filessharing?.ncpublic?.expiredateinternal?.enforced ?? false - NCGlobal.shared.capabilityFileSharingInternalExpireDateDays = json.ocs.data.capabilities.filessharing?.ncpublic?.expiredateinternal?.days ?? 0 - NCGlobal.shared.capabilityFileSharingRemoteExpireDateEnforced = json.ocs.data.capabilities.filessharing?.ncpublic?.expiredateremote?.enforced ?? false - NCGlobal.shared.capabilityFileSharingRemoteExpireDateDays = json.ocs.data.capabilities.filessharing?.ncpublic?.expiredateremote?.days ?? 0 - - NCGlobal.shared.capabilityThemingColor = json.ocs.data.capabilities.theming?.color ?? "" - NCGlobal.shared.capabilityThemingColorElement = json.ocs.data.capabilities.theming?.colorelement ?? "" - NCGlobal.shared.capabilityThemingColorText = json.ocs.data.capabilities.theming?.colortext ?? "" - NCGlobal.shared.capabilityThemingName = json.ocs.data.capabilities.theming?.name ?? "" - NCGlobal.shared.capabilityThemingSlogan = json.ocs.data.capabilities.theming?.slogan ?? "" - - NCGlobal.shared.capabilityE2EEEnabled = json.ocs.data.capabilities.endtoendencryption?.enabled ?? false - NCGlobal.shared.capabilityE2EEApiVersion = json.ocs.data.capabilities.endtoendencryption?.apiversion ?? "" - - NCGlobal.shared.capabilityRichdocumentsEnabled = json.ocs.data.capabilities.richdocuments?.directediting ?? false - NCGlobal.shared.capabilityRichdocumentsMimetypes.removeAll() - if let mimetypes = json.ocs.data.capabilities.richdocuments?.mimetypes { + global.capabilityFileSharingApiEnabled = data.capabilities.filessharing?.apienabled ?? false + global.capabilityFileSharingDefaultPermission = data.capabilities.filessharing?.defaultpermissions ?? 0 + global.capabilityFileSharingPubPasswdEnforced = data.capabilities.filessharing?.ncpublic?.password?.enforced ?? false + global.capabilityFileSharingPubExpireDateEnforced = data.capabilities.filessharing?.ncpublic?.expiredate?.enforced ?? false + global.capabilityFileSharingPubExpireDateDays = data.capabilities.filessharing?.ncpublic?.expiredate?.days ?? 0 + global.capabilityFileSharingInternalExpireDateEnforced = data.capabilities.filessharing?.ncpublic?.expiredateinternal?.enforced ?? false + global.capabilityFileSharingInternalExpireDateDays = data.capabilities.filessharing?.ncpublic?.expiredateinternal?.days ?? 0 + global.capabilityFileSharingRemoteExpireDateEnforced = data.capabilities.filessharing?.ncpublic?.expiredateremote?.enforced ?? false + global.capabilityFileSharingRemoteExpireDateDays = data.capabilities.filessharing?.ncpublic?.expiredateremote?.days ?? 0 + + global.capabilityThemingColor = data.capabilities.theming?.color ?? "" + global.capabilityThemingColorElement = data.capabilities.theming?.colorelement ?? "" + global.capabilityThemingColorText = data.capabilities.theming?.colortext ?? "" + global.capabilityThemingName = data.capabilities.theming?.name ?? "" + global.capabilityThemingSlogan = data.capabilities.theming?.slogan ?? "" + + global.capabilityE2EEEnabled = data.capabilities.endtoendencryption?.enabled ?? false + global.capabilityE2EEApiVersion = data.capabilities.endtoendencryption?.apiversion ?? "" + + global.capabilityRichdocumentsEnabled = json.ocs.data.capabilities.richdocuments?.directediting ?? false + global.capabilityRichdocumentsMimetypes.removeAll() + if let mimetypes = data.capabilities.richdocuments?.mimetypes { for mimetype in mimetypes { - NCGlobal.shared.capabilityRichdocumentsMimetypes.append(mimetype) + global.capabilityRichdocumentsMimetypes.append(mimetype) } } - NCGlobal.shared.capabilityActivity.removeAll() - if let activities = json.ocs.data.capabilities.activity?.apiv2 { + global.capabilityActivity.removeAll() + if let activities = data.capabilities.activity?.apiv2 { for activity in activities { - NCGlobal.shared.capabilityActivity.append(activity) + global.capabilityActivity.append(activity) } } - NCGlobal.shared.capabilityNotification.removeAll() - if let notifications = json.ocs.data.capabilities.notifications?.ocsendpoints { + global.capabilityNotification.removeAll() + if let notifications = data.capabilities.notifications?.ocsendpoints { for notification in notifications { - NCGlobal.shared.capabilityNotification.append(notification) + global.capabilityNotification.append(notification) } } - NCGlobal.shared.capabilityFilesUndelete = json.ocs.data.capabilities.files?.undelete ?? false - NCGlobal.shared.capabilityFilesLockVersion = json.ocs.data.capabilities.files?.locking ?? "" - NCGlobal.shared.capabilityFilesComments = json.ocs.data.capabilities.files?.comments ?? false - NCGlobal.shared.capabilityFilesBigfilechunking = json.ocs.data.capabilities.files?.bigfilechunking ?? false + global.capabilityFilesUndelete = data.capabilities.files?.undelete ?? false + global.capabilityFilesLockVersion = data.capabilities.files?.locking ?? "" + global.capabilityFilesComments = data.capabilities.files?.comments ?? false + global.capabilityFilesBigfilechunking = data.capabilities.files?.bigfilechunking ?? false - NCGlobal.shared.capabilityUserStatusEnabled = json.ocs.data.capabilities.files?.undelete ?? false - if json.ocs.data.capabilities.external != nil { - NCGlobal.shared.capabilityExternalSites = true + global.capabilityUserStatusEnabled = data.capabilities.files?.undelete ?? false + if data.capabilities.external != nil { + global.capabilityExternalSites = true } - NCGlobal.shared.capabilityGroupfoldersEnabled = json.ocs.data.capabilities.groupfolders?.hasGroupFolders ?? false + global.capabilityGroupfoldersEnabled = data.capabilities.groupfolders?.hasGroupFolders ?? false + global.capabilitySecurityGuardDiagnostics = data.capabilities.securityguard?.diagnostics ?? false } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)") return diff --git a/iOSClient/Data/NCManageDatabase+Directory.swift b/iOSClient/Data/NCManageDatabase+Directory.swift index 954a59631a..8cb5f5d555 100644 --- a/iOSClient/Data/NCManageDatabase+Directory.swift +++ b/iOSClient/Data/NCManageDatabase+Directory.swift @@ -77,6 +77,14 @@ extension NCManageDatabase { func deleteDirectoryAndSubDirectory(serverUrl: String, account: String) { +#if !EXTENSION + DispatchQueue.main.async { + if let appDelegate = UIApplication.shared.delegate as? AppDelegate { + appDelegate.listFilesVC[serverUrl] = nil + } + } +#endif + do { let realm = try Realm() let results = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl BEGINSWITH %@", account, serverUrl) @@ -123,6 +131,20 @@ extension NCManageDatabase { } } + func cleanEtagDirectory(account: String, serverUrl: String) { + + do { + let realm = try Realm() + try realm.write { + if let result = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first { + result.etag = "" + } + } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)") + } + } + func getTableDirectory(predicate: NSPredicate) -> tableDirectory? { do { @@ -141,7 +163,6 @@ extension NCManageDatabase { do { let realm = try Realm() - realm.refresh() return realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)") diff --git a/iOSClient/Data/NCManageDatabase+E2EE.swift b/iOSClient/Data/NCManageDatabase+E2EE.swift index 36f27d9dc6..46851fd3fb 100644 --- a/iOSClient/Data/NCManageDatabase+E2EE.swift +++ b/iOSClient/Data/NCManageDatabase+E2EE.swift @@ -46,7 +46,6 @@ class tableE2eEncryptionV3: Object { @Persisted var key = "" @Persisted var initializationVector = "" @Persisted var metadataKey = "" - @Persisted var metadataKeyFiledrop = "" @Persisted var metadataKeyIndex: Int = 0 @Persisted var metadataVersion: Double = 0 @Persisted var mimeType = "" @@ -132,25 +131,6 @@ class tableE2eUsers: Object { } } -class tableE2eUsersFiledrop: Object { - - @Persisted(primaryKey: true) var primaryKey = "" - @Persisted var account = "" - @Persisted var certificate = "" - @Persisted var encryptedFiledropKey: String? - @Persisted var ocIdServerUrl: String = "" - @Persisted var serverUrl: String = "" - @Persisted var userId = "" - - convenience init(account: String, ocIdServerUrl: String, userId: String) { - self.init() - self.primaryKey = account + ocIdServerUrl + userId - self.account = account - self.ocIdServerUrl = ocIdServerUrl - self.userId = userId - } -} - extension NCManageDatabase { // MARK: - @@ -371,7 +351,7 @@ extension NCManageDatabase { return nil } - func getE2EUsers(account: String, ocIdServerUrl: String, userId: String) -> tableE2eUsers? { + func getE2EUser(account: String, ocIdServerUrl: String, userId: String) -> tableE2eUsers? { do { let realm = try Realm() @@ -383,18 +363,6 @@ extension NCManageDatabase { return nil } - func getE2EUsersFiledrop(account: String, ocIdServerUrl: String, userId: String) -> tableE2eUsersFiledrop? { - - do { - let realm = try Realm() - return realm.objects(tableE2eUsersFiledrop.self).filter("account == %@ && ocIdServerUrl == %@ AND userId == %@", account, ocIdServerUrl, userId).first - } catch let error as NSError { - NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)") - } - - return nil - } - func getE2eMetadata(account: String, ocIdServerUrl: String) -> tableE2eMetadata? { do { diff --git a/iOSClient/Data/NCManageDatabase+LocalFile.swift b/iOSClient/Data/NCManageDatabase+LocalFile.swift index b7266ac279..bd9cd85031 100644 --- a/iOSClient/Data/NCManageDatabase+LocalFile.swift +++ b/iOSClient/Data/NCManageDatabase+LocalFile.swift @@ -52,7 +52,6 @@ extension NCManageDatabase { do { let realm = try Realm() - realm.refresh() return realm.objects(tableLocalFile.self).filter("ocId == %@", ocId).first } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)") @@ -170,7 +169,6 @@ extension NCManageDatabase { do { let realm = try Realm() - realm.refresh() let results = realm.objects(tableLocalFile.self).filter("account == %@", account) return Array(results.map { tableLocalFile.init(value: $0) }) } catch let error as NSError { @@ -184,7 +182,6 @@ extension NCManageDatabase { do { let realm = try Realm() - realm.refresh() guard let result = realm.objects(tableLocalFile.self).filter(predicate).first else { return nil } return tableLocalFile.init(value: result) } catch let error as NSError { @@ -198,7 +195,6 @@ extension NCManageDatabase { do { let realm = try Realm() - realm.refresh() return realm.objects(tableLocalFile.self).filter(predicate) } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)") @@ -211,7 +207,6 @@ extension NCManageDatabase { do { let realm = try Realm() - realm.refresh() let results = realm.objects(tableLocalFile.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending) return Array(results.map { tableLocalFile.init(value: $0) }) } catch let error as NSError { @@ -225,7 +220,6 @@ extension NCManageDatabase { do { let realm = try Realm() - realm.refresh() return realm.objects(tableLocalFile.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending) } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)") diff --git a/iOSClient/Data/NCManageDatabase+Metadata.swift b/iOSClient/Data/NCManageDatabase+Metadata.swift index ab77d59ac1..76bb1b9d25 100644 --- a/iOSClient/Data/NCManageDatabase+Metadata.swift +++ b/iOSClient/Data/NCManageDatabase+Metadata.swift @@ -27,9 +27,25 @@ import NextcloudKit class tableMetadata: Object, NCUserBaseUrl { override func isEqual(_ object: Any?) -> Bool { - if let object = object as? tableMetadata { - return self.fileId == object.fileId && self.account == object.account - && self.path == object.path && self.fileName == object.fileName + if let object = object as? tableMetadata, + self.account == object.account, + self.etag == object.etag, + self.fileId == object.fileId, + self.path == object.path, + self.fileName == object.fileName, + self.fileNameView == object.fileNameView, + self.date == object.date, + self.permissions == object.permissions, + self.hasPreview == object.hasPreview, + self.note == object.note, + self.lock == object.lock, + self.favorite == object.favorite, + self.livePhotoFile == object.livePhotoFile, + self.sharePermissionsCollaborationServices == object.sharePermissionsCollaborationServices, + Array(self.tags).elementsEqual(Array(object.tags)), + Array(self.shareType).elementsEqual(Array(object.shareType)), + Array(self.sharePermissionsCloudMesh).elementsEqual(Array(object.sharePermissionsCloudMesh)) { + return true } else { return false } @@ -60,11 +76,11 @@ class tableMetadata: Object, NCUserBaseUrl { @objc dynamic var hidden: Bool = false @objc dynamic var iconName = "" @objc dynamic var iconUrl = "" - @objc dynamic var isFlaggedAsLivePhotoByServer: Bool = false + @objc dynamic var isFlaggedAsLivePhotoByServer: Bool = false // Indicating if the file is sent as a live photo from the server, or if we should detect it as such and convert it client-side @objc dynamic var isExtractFile: Bool = false - @objc dynamic var livePhotoFile = "" + @objc dynamic var livePhotoFile = "" // If this is not empty, the media is a live photo. New media gets this straight from server, but old media needs to be detected as live photo (look isFlaggedAsLivePhotoByServer) @objc dynamic var mountType = "" - @objc dynamic var name = "" // for unifiedSearch is the provider.id + @objc dynamic var name = "" // for unifiedSearch is the provider.id @objc dynamic var note = "" @objc dynamic var ocId = "" @objc dynamic var ownerId = "" @@ -107,8 +123,6 @@ class tableMetadata: Object, NCUserBaseUrl { @objc dynamic var height: Int = 0 @objc dynamic var width: Int = 0 @objc dynamic var errorCode: Int = 0 - @objc dynamic var errorCodeCounter: Int = 0 - @objc dynamic var errorCodeDate: Date? override static func primaryKey() -> String { return "ocId" @@ -226,7 +240,7 @@ extension tableMetadata { } var isInTransfer: Bool { - status == NCGlobal.shared.metadataStatusInDownload || status == NCGlobal.shared.metadataStatusDownloading || status == NCGlobal.shared.metadataStatusInUpload || status == NCGlobal.shared.metadataStatusUploading + status == NCGlobal.shared.metadataStatusDownloading || status == NCGlobal.shared.metadataStatusUploading } var isTransferInForeground: Bool { @@ -234,11 +248,11 @@ extension tableMetadata { } var isDownload: Bool { - status == NCGlobal.shared.metadataStatusInDownload || status == NCGlobal.shared.metadataStatusDownloading + status == NCGlobal.shared.metadataStatusDownloading } var isUpload: Bool { - status == NCGlobal.shared.metadataStatusInUpload || status == NCGlobal.shared.metadataStatusUploading + status == NCGlobal.shared.metadataStatusUploading } @objc var isDirectoryE2EE: Bool { @@ -257,6 +271,14 @@ extension tableMetadata { !isFlaggedAsLivePhotoByServer } + var isSynchronizable: Bool { + let localFile = NCManageDatabase.shared.getResultsTableLocalFile(predicate: NSPredicate(format: "ocId == %@", ocId))?.first + if localFile?.etag != etag || NCUtilityFileSystem().fileProviderStorageSize(ocId, fileNameView: fileNameView) == 0 { + return true + } + return false + } + /// Returns false if the user is lokced out of the file. I.e. The file is locked but by somone else func canUnlock(as user: String) -> Bool { return !lock || (lockOwner == user && lockOwnerType == 0) @@ -264,10 +286,8 @@ extension tableMetadata { // Return if is sharable func isSharable() -> Bool { - guard NCGlobal.shared.capabilityFileSharingApiEnabled else { return false } - if isDirectoryE2EE || e2eEncrypted { - guard directory, NCGlobal.shared.capabilityE2EEEnabled else { return false } - return true + if !NCGlobal.shared.capabilityFileSharingApiEnabled || (NCGlobal.shared.capabilityE2EEEnabled && isDirectoryE2EE) { + return false } return true } @@ -402,6 +422,15 @@ extension NCManageDatabase { completion(metadataFolder, metadataFolders, metadatas) } + func convertFilesToMetadatas(_ files: [NKFile], useMetadataFolder: Bool) async -> (metadataFolder: tableMetadata, metadatasFolder: [tableMetadata], metadatas: [tableMetadata]) { + + await withUnsafeContinuation({ continuation in + convertFilesToMetadatas(files, useMetadataFolder: useMetadataFolder) { metadataFolder, metadatasFolder, metadatas in + continuation.resume(returning: (metadataFolder, metadatasFolder, metadatas)) + } + }) + } + func createMetadata(account: String, user: String, userId: String, fileName: String, fileNameView: String, ocId: String, serverUrl: String, urlBase: String, url: String, contentType: String, isUrl: Bool = false, name: String = NCGlobal.shared.appName, subline: String? = nil, iconName: String? = nil, iconUrl: String? = nil) -> tableMetadata { let metadata = tableMetadata() @@ -497,6 +526,18 @@ extension NCManageDatabase { } } + func deleteMetadata(results: Results) { + + do { + let realm = try Realm() + try realm.write { + realm.delete(results) + } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)") + } + } + func moveMetadata(ocId: String, serverUrlTo: String) { do { @@ -530,7 +571,14 @@ extension NCManageDatabase { } } - func setMetadataSession(ocId: String, newFileName: String? = nil, session: String?, sessionError: String?, sessionSelector: String?, sessionTaskIdentifier: Int?, status: Int?, etag: String? = nil, errorCode: Int?) { + func setMetadataSession(ocId: String, + newFileName: String? = nil, + session: String? = nil, + sessionError: String? = nil, + selector: String? = nil, + status: Int? = nil, + etag: String? = nil, + errorCode: Int? = nil) { do { let realm = try Realm() @@ -546,11 +594,8 @@ extension NCManageDatabase { if let sessionError { result.sessionError = sessionError } - if let sessionSelector { - result.sessionSelector = sessionSelector - } - if let sessionTaskIdentifier { - result.sessionTaskIdentifier = sessionTaskIdentifier + if let selector { + result.sessionSelector = selector } if let status { result.status = status @@ -560,12 +605,6 @@ extension NCManageDatabase { } if let errorCode { result.errorCode = errorCode - if errorCode == 0 { - result.errorCodeCounter = 0 - } else { - result.errorCodeCounter += 1 - result.errorCodeDate = Date() - } } } } @@ -574,6 +613,49 @@ extension NCManageDatabase { } } + func setMetadataSession(ocId: String, + status: Int? = nil, + taskIdentifier: Int? = nil) { + + do { + let realm = try Realm() + try realm.write { + if let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first { + if let status { + result.status = status + } + if let taskIdentifier { + result.sessionTaskIdentifier = taskIdentifier + } + } + } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)") + } + } + + func setMetadataSessionInWaitDownload(ocId: String, selector: String) -> tableMetadata? { + + var metadata: tableMetadata? + + do { + let realm = try Realm() + try realm.write { + if let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first { + result.session = NextcloudKit.shared.nkCommonInstance.sessionIdentifierDownload + result.sessionError = "" + result.sessionSelector = selector + result.status = NCGlobal.shared.metadataStatusWaitDownload + metadata = tableMetadata(value: result) + } + } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)") + } + + return metadata + } + @discardableResult func setMetadataStatus(ocId: String, status: Int) -> tableMetadata? { @@ -629,9 +711,10 @@ extension NCManageDatabase { do { let realm = try Realm() try realm.write { - let result = realm.objects(tableMetadata.self).filter("account == %@ AND ocId == %@", account, ocId).first - result?.isFlaggedAsLivePhotoByServer = true - result?.livePhotoFile = livePhotoFile + if let result = realm.objects(tableMetadata.self).filter("account == %@ AND ocId == %@", account, ocId).first { + result.isFlaggedAsLivePhotoByServer = true + result.livePhotoFile = livePhotoFile + } } } catch let error { NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)") @@ -724,6 +807,19 @@ extension NCManageDatabase { return [] } + func getMetadatas(predicate: NSPredicate, sorted: String, ascending: Bool = false) -> [tableMetadata]? { + + do { + let realm = try Realm() + let results = realm.objects(tableMetadata.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending) + return Array(results.map { tableMetadata.init(value: $0) }) + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)") + } + + return nil + } + func getResultsMetadatas(predicate: NSPredicate, sorted: String? = nil, ascending: Bool = false) -> Results? { do { @@ -740,6 +836,18 @@ extension NCManageDatabase { return nil } + func getResultsMetadatas(predicate: NSPredicate, sorted: [RealmSwift.SortDescriptor]) -> Results? { + + do { + let realm = try Realm() + return realm.objects(tableMetadata.self).filter(predicate).sorted(by: sorted) + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)") + } + + return nil + } + func getResultMetadata(predicate: NSPredicate) -> tableMetadata? { do { @@ -1007,7 +1115,7 @@ extension NCManageDatabase { do { let realm = try Realm() realm.refresh() - return realm.objects(tableMetadata.self).filter(NSPredicate(format: "status == %i || status == %i", NCGlobal.shared.metadataStatusInUpload, NCGlobal.shared.metadataStatusUploading)).count + return realm.objects(tableMetadata.self).filter(NSPredicate(format: "status == %i", NCGlobal.shared.metadataStatusUploading)).count } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)") } @@ -1067,24 +1175,6 @@ extension NCManageDatabase { return nil } - func clearErrorCodeMetadatas(metadatas: Results?) { - - guard let metadatas else { return } - - do { - let realm = try Realm() - try realm.write { - for metadata in metadatas { - metadata.errorCode = 0 - metadata.errorCodeCounter = 0 - metadata.errorCodeDate = nil - } - } - } catch let error as NSError { - NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)") - } - } - @discardableResult func updateMetadatas(_ metadatas: [tableMetadata], predicate: NSPredicate) -> (metadatasChangedCount: Int, metadatasChanged: Bool) { @@ -1097,7 +1187,7 @@ extension NCManageDatabase { let results = realm.objects(tableMetadata.self).filter(predicate) metadatasChangedCount = metadatas.count - results.count for metadata in metadatas { - if let result = results.filter({ $0.ocId == metadata.ocId }).first, + if let result = results.first(where: { $0.ocId == metadata.ocId }), metadata.isEqual(result) { } else { metadatasChanged = true break @@ -1116,4 +1206,37 @@ extension NCManageDatabase { return (metadatasChangedCount, metadatasChanged) } + + func replaceMetadata(_ metadatas: [tableMetadata], predicate: NSPredicate) { + + do { + let realm = try Realm() + try realm.write { + let results = realm.objects(tableMetadata.self).filter(predicate) + realm.delete(results) + for metadata in metadatas { + if results.where({ $0.ocId == metadata.ocId }).isEmpty { + realm.add(tableMetadata(value: metadata), update: .modified) + } else { + continue + } + } + } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)") + } + } + + func getMediaMetadatas(predicate: NSPredicate) -> ThreadSafeArray? { + + do { + let realm = try Realm() + let results = realm.objects(tableMetadata.self).filter(predicate).sorted(byKeyPath: "date", ascending: false) + return ThreadSafeArray(results.map { tableMetadata.init(value: $0) }) + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)") + } + + return nil + } } diff --git a/iOSClient/Data/NCManageDatabase+SecurityGuard.swift b/iOSClient/Data/NCManageDatabase+SecurityGuard.swift new file mode 100644 index 0000000000..c89b6dd98a --- /dev/null +++ b/iOSClient/Data/NCManageDatabase+SecurityGuard.swift @@ -0,0 +1,117 @@ +// +// NCManageDatabase+SecurityGuard.swift +// Nextcloud +// +// Created by Marino Faggiana on 17/01/24. +// Copyright © 2024 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana +// +// 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 . +// + +import Foundation +import RealmSwift +import NextcloudKit + +class TableSecurityGuardDiagnostics: Object { + + @Persisted var account = "" + @Persisted(primaryKey: true) var primaryKey = "" + @Persisted var issue: String = "" + @Persisted var error: String? + @Persisted var counter: Int = 0 + @Persisted var oldest: TimeInterval + @Persisted var id: ObjectId + + convenience init(account: String, issue: String, error: String?, date: Date) { + self.init() + + self.account = account + self.primaryKey = account + issue + (error ?? "") + self.issue = issue + self.error = error + self.counter = 1 + self.oldest = date.timeIntervalSince1970 + } +} + +extension NCManageDatabase { + + func addDiagnostic(account: String, issue: String, error: String? = nil) { + + do { + let realm = try Realm() + try realm.write { + let primaryKey = account + issue + (error ?? "") + if let result = realm.object(ofType: TableSecurityGuardDiagnostics.self, forPrimaryKey: primaryKey) { + result.counter += 1 + result.oldest = Date().timeIntervalSince1970 + } else { + let table = TableSecurityGuardDiagnostics(account: account, issue: issue, error: error, date: Date()) + realm.add(table) + } + } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)") + } + } + + func existsDiagnostics(account: String) -> Bool { + + do { + let realm = try Realm() + let results = realm.objects(TableSecurityGuardDiagnostics.self).where({ + $0.account == account + }) + if !results.isEmpty { return true } + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)") + } + + return false + } + + func getDiagnostics(account: String, issue: String) -> Results? { + + do { + let realm = try Realm() + let results = realm.objects(TableSecurityGuardDiagnostics.self).where({ + $0.account == account && $0.issue == issue + }) + return results + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)") + } + + return nil + } + + func deleteDiagnostics(account: String, ids: [ObjectId]) { + + do { + let realm = try Realm() + try realm.write { + let results = realm.objects(TableSecurityGuardDiagnostics.self).where({ + $0.account == account + }) + for result in results where ids.contains(result.id) { + realm.delete(result) + } + } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)") + } + } +} diff --git a/iOSClient/Data/NCManageDatabase+Video.swift b/iOSClient/Data/NCManageDatabase+Video.swift index 9eb9616f16..52edf2fac0 100644 --- a/iOSClient/Data/NCManageDatabase+Video.swift +++ b/iOSClient/Data/NCManageDatabase+Video.swift @@ -155,8 +155,9 @@ extension NCManageDatabase { do { let realm = try Realm() try realm.write { - let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId) - realm.delete(result) + if let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId).first { + realm.delete(result) + } } } catch let error { NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)") diff --git a/iOSClient/Data/NCManageDatabase.swift b/iOSClient/Data/NCManageDatabase.swift index 19bd20fd6e..f031eb118a 100644 --- a/iOSClient/Data/NCManageDatabase.swift +++ b/iOSClient/Data/NCManageDatabase.swift @@ -86,13 +86,13 @@ class NCManageDatabase: NSObject { tableE2eMetadata.self, tableE2eUsers.self, tableE2eCounter.self, - tableE2eUsersFiledrop.self, tableShare.self, tableChunk.self, tableAvatar.self, tableDashboardWidget.self, tableDashboardWidgetButton.self, - NCDBLayoutForView.self] + NCDBLayoutForView.self, + TableSecurityGuardDiagnostics.self] ) } else { @@ -235,6 +235,7 @@ class NCManageDatabase: NSObject { self.clearTable(tableMetadata.self, account: account) self.clearTable(tablePhotoLibrary.self, account: account) self.clearTable(tableShare.self, account: account) + self.clearTable(TableSecurityGuardDiagnostics.self, account: account) self.clearTable(tableTag.self, account: account) self.clearTable(tableTip.self) self.clearTable(tableTrash.self, account: account) @@ -250,7 +251,6 @@ class NCManageDatabase: NSObject { self.clearTable(tableE2eMetadata.self, account: account) self.clearTable(tableE2eUsers.self, account: account) self.clearTable(tableE2eCounter.self, account: account) - self.clearTable(tableE2eUsersFiledrop.self, account: account) } @objc func removeDB() { diff --git a/iOSClient/Diagnostics/NCCapabilitiesView.swift b/iOSClient/Diagnostics/NCCapabilitiesView.swift index e58a865a2f..ee10db1343 100644 --- a/iOSClient/Diagnostics/NCCapabilitiesView.swift +++ b/iOSClient/Diagnostics/NCCapabilitiesView.swift @@ -115,6 +115,9 @@ class NCCapabilitiesViewOO: ObservableObject { if let image = UIImage(systemName: "person.2") { capabililies.append(Capability(text: "Group folders", image: image, resize: false, available: NCGlobal.shared.capabilityGroupfoldersEnabled)) } + if let image = UIImage(systemName: "shield") { + capabililies.append(Capability(text: "Security Guard Diagnostics", image: image, resize: false, available: NCGlobal.shared.capabilitySecurityGuardDiagnostics)) + } homeServer = utilityFileSystem.getHomeServer(urlBase: activeAccount.urlBase, userId: activeAccount.userId) + "/" } diff --git a/iOSClient/Extensions/String+Extension.swift b/iOSClient/Extensions/String+Extension.swift index 3a7f28f04b..55df4d4c1d 100644 --- a/iOSClient/Extensions/String+Extension.swift +++ b/iOSClient/Extensions/String+Extension.swift @@ -31,6 +31,12 @@ extension String { return self.components(separatedBy: CharacterSet.alphanumerics.inverted).joined().lowercased() } + var isNumber: Bool { + return self.allSatisfy { character in + character.isNumber + } + } + public var uppercaseInitials: String? { let initials = self.components(separatedBy: .whitespaces) .reduce("", { diff --git a/iOSClient/Extensions/UIAlertController+Extension.swift b/iOSClient/Extensions/UIAlertController+Extension.swift index 2bb26a7e06..d662fc699f 100644 --- a/iOSClient/Extensions/UIAlertController+Extension.swift +++ b/iOSClient/Extensions/UIAlertController+Extension.swift @@ -38,7 +38,6 @@ extension UIAlertController { guard let fileNameFolder = alertController.textFields?.first?.text else { return } if markE2ee { Task { - let createFolderResults = await NextcloudKit.shared.createFolder(serverUrlFileName: serverUrl + "/" + fileNameFolder) if createFolderResults.error == .success { let error = await NCNetworkingE2EEMarkFolder().markFolderE2ee(account: urlBase.account, fileName: fileNameFolder, serverUrl: serverUrl, userId: urlBase.userId) diff --git a/iOSClient/Extensions/UINavigationController+Extension.swift b/iOSClient/Extensions/UINavigationController+Extension.swift index a086bebfff..52ca108c2a 100644 --- a/iOSClient/Extensions/UINavigationController+Extension.swift +++ b/iOSClient/Extensions/UINavigationController+Extension.swift @@ -30,7 +30,7 @@ extension UINavigationController { return self.visibleViewController!.topMostViewController() } - func setFileAppreance() { + func setNavigationBarAppearance() { navigationBar.tintColor = .systemBlue @@ -39,7 +39,6 @@ extension UINavigationController { standardAppearance.largeTitleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.label] standardAppearance.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.label] - standardAppearance.backgroundColor = .systemGray6 navigationBar.standardAppearance = standardAppearance let scrollEdgeAppearance = UINavigationBarAppearance() diff --git a/iOSClient/Favorites/NCFavorite.swift b/iOSClient/Favorites/NCFavorite.swift index 8cb42a5cfd..7c138ce48f 100644 --- a/iOSClient/Favorites/NCFavorite.swift +++ b/iOSClient/Favorites/NCFavorite.swift @@ -44,12 +44,16 @@ class NCFavorite: NCCollectionViewCommon { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - navigationController?.setFileAppreance() + if dataSource.metadatas.isEmpty { + reloadDataSource() + } + reloadDataSourceNetwork() } // MARK: - DataSource + NC Endpoint - override func queryDB(isForced: Bool) { + override func queryDB() { + super.queryDB() var metadatas: [tableMetadata] = [] @@ -70,37 +74,20 @@ class NCFavorite: NCCollectionViewCommon { searchResults: self.searchResults) } - override func reloadDataSource(isForced: Bool = true) { - super.reloadDataSource() - - DispatchQueue.global().async { - self.queryDB(isForced: isForced) - DispatchQueue.main.async { - self.refreshControl.endRefreshing() - self.collectionView.reloadData() - } - } - } - - override func reloadDataSourceNetwork(isForced: Bool = false) { - super.reloadDataSourceNetwork(isForced: isForced) - - NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Reload data source network favorite forced \(isForced)") - - isReloadDataSourceNetworkInProgress = true - collectionView?.reloadData() + override func reloadDataSourceNetwork() { + super.reloadDataSourceNetwork() NextcloudKit.shared.listingFavorites(showHiddenFiles: NCKeychain().showHiddenFiles, options: NKRequestOptions(queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)) { account, files, _, error in - self.isReloadDataSourceNetworkInProgress = false if error == .success { NCManageDatabase.shared.convertFilesToMetadatas(files, useMetadataFolder: false) { _, _, metadatas in NCManageDatabase.shared.updateMetadatasFavorite(account: account, metadatas: metadatas) self.reloadDataSource() } + } else { + self.reloadDataSource(withQueryDB: false) } - self.reloadDataSource() } } } diff --git a/iOSClient/Files/NCFiles.storyboard b/iOSClient/Files/NCFiles.storyboard index 36ac54b23a..5795cc6cf5 100644 --- a/iOSClient/Files/NCFiles.storyboard +++ b/iOSClient/Files/NCFiles.storyboard @@ -1,9 +1,9 @@ - + - + @@ -17,7 +17,7 @@ - + @@ -37,7 +37,7 @@ - + diff --git a/iOSClient/Files/NCFiles.swift b/iOSClient/Files/NCFiles.swift index 07f0364a04..f15e947c14 100644 --- a/iOSClient/Files/NCFiles.swift +++ b/iOSClient/Files/NCFiles.swift @@ -71,9 +71,9 @@ class NCFiles: NCCollectionViewCommon { } self.titleCurrentFolder = self.getNavigationTitle() - self.setNavigationItem() + self.setNavigationItems() - self.reloadDataSource(isForced: false) + self.reloadDataSource() self.reloadDataSourceNetwork() } } @@ -86,7 +86,11 @@ class NCFiles: NCCollectionViewCommon { titleCurrentFolder = getNavigationTitle() } super.viewWillAppear(animated) - navigationController?.setFileAppreance() + + if dataSource.metadatas.isEmpty { + reloadDataSource() + } + reloadDataSourceNetwork() } override func viewWillDisappear(_ animated: Bool) { @@ -97,23 +101,16 @@ class NCFiles: NCCollectionViewCommon { } // MARK: - DataSource + NC Endpoint - // - // forced: do no make the etag of directory test (default) - // - override func queryDB(isForced: Bool) { + override func queryDB() { + super.queryDB() let metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl)) let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl)) - let metadataTransfer = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "status != %i AND serverUrl == %@", NCGlobal.shared.metadataStatusNormal, self.serverUrl)) if self.metadataFolder == nil { self.metadataFolder = NCManageDatabase.shared.getMetadataFolder(account: self.appDelegate.account, urlBase: self.appDelegate.urlBase, userId: self.appDelegate.userId, serverUrl: self.serverUrl) } - if !isForced, let directory, directory.etag == self.dataSource.directory?.etag, metadataTransfer == nil, self.fileNameBlink == nil, self.fileNameOpen == nil { - return - } - self.richWorkspaceText = directory?.richWorkspace self.dataSource = NCDataSource( metadatas: metadatas, @@ -128,32 +125,20 @@ class NCFiles: NCCollectionViewCommon { searchResults: self.searchResults) } - override func reloadDataSource(isForced: Bool = true) { - super.reloadDataSource() - - DispatchQueue.main.async { self.refreshControl.endRefreshing() } - DispatchQueue.global().async { - guard !self.isSearchingMode, !self.appDelegate.account.isEmpty, !self.appDelegate.urlBase.isEmpty, !self.serverUrl.isEmpty else { return } + override func reloadDataSource(withQueryDB: Bool = true) { + super.reloadDataSource(withQueryDB: withQueryDB) - self.queryDB(isForced: isForced) - - DispatchQueue.main.async { - self.collectionView.reloadData() - if !self.dataSource.metadatas.isEmpty { - self.blinkCell(fileName: self.fileNameBlink) - self.openFile(fileName: self.fileNameOpen) - self.fileNameBlink = nil - self.fileNameOpen = nil - } - } + if !self.dataSource.metadatas.isEmpty { + self.blinkCell(fileName: self.fileNameBlink) + self.openFile(fileName: self.fileNameOpen) + self.fileNameBlink = nil + self.fileNameOpen = nil } } - override func reloadDataSourceNetwork(isForced: Bool = false) { - super.reloadDataSourceNetwork(isForced: isForced) + override func reloadDataSourceNetwork() { guard !isSearchingMode else { - networkSearch() - return + return networkSearch() } func downloadMetadata(_ metadata: tableMetadata) -> Bool { @@ -170,29 +155,86 @@ class NCFiles: NCCollectionViewCommon { return false } - NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Reload data source network files forced \(isForced)") + super.reloadDataSourceNetwork() - isReloadDataSourceNetworkInProgress = true - collectionView?.reloadData() - - networkReadFolder(isForced: isForced) { tableDirectory, metadatas, metadatasChangedCount, metadatasChanged, error in + networkReadFolder { tableDirectory, metadatas, metadatasChangedCount, metadatasChanged, error in if error == .success { for metadata in metadatas ?? [] where !metadata.directory && downloadMetadata(metadata) { if NCNetworking.shared.downloadQueue.operations.filter({ ($0 as? NCOperationDownload)?.metadata.ocId == metadata.ocId }).isEmpty { NCNetworking.shared.downloadQueue.addOperation(NCOperationDownload(metadata: metadata, selector: NCGlobal.shared.selectorDownloadFile)) } } + self.richWorkspaceText = tableDirectory?.richWorkspace + + if metadatasChangedCount != 0 || metadatasChanged { + self.reloadDataSource() + } else { + self.reloadDataSource(withQueryDB: false) + } + } else { + self.reloadDataSource(withQueryDB: false) } + } + } - self.isReloadDataSourceNetworkInProgress = false - self.richWorkspaceText = tableDirectory?.richWorkspace + private func networkReadFolder(completion: @escaping(_ tableDirectory: tableDirectory?, _ metadatas: [tableMetadata]?, _ metadatasChangedCount: Int, _ metadatasChanged: Bool, _ error: NKError) -> Void) { - if metadatasChangedCount != 0 || metadatasChanged || isForced { - self.reloadDataSource() - } else if self.dataSource.getMetadataSourceForAllSections().isEmpty { - DispatchQueue.main.async { - self.collectionView.reloadData() + var tableDirectory: tableDirectory? + + NCNetworking.shared.readFile(serverUrlFileName: serverUrl) { account, metadataFolder, error in + + guard error == .success, let metadataFolder else { + return completion(nil, nil, 0, false, error) + } + tableDirectory = NCManageDatabase.shared.setDirectory(serverUrl: self.serverUrl, richWorkspace: metadataFolder.richWorkspace, account: account) + // swiftlint:disable empty_string + let forceReplaceMetadatas = tableDirectory?.etag == "" + // swiftlint:enable empty_string + + if tableDirectory?.etag != metadataFolder.etag || metadataFolder.e2eEncrypted { + NCNetworking.shared.readFolder(serverUrl: self.serverUrl, + account: self.appDelegate.account, + forceReplaceMetadatas: forceReplaceMetadatas) { _, metadataFolder, metadatas, metadatasChangedCount, metadatasChanged, error in + guard error == .success else { + return completion(tableDirectory, nil, 0, false, error) + } + self.metadataFolder = metadataFolder + // E2EE + if let metadataFolder = metadataFolder, + metadataFolder.e2eEncrypted, + NCKeychain().isEndToEndEnabled(account: self.appDelegate.account), + !NCNetworkingE2EE().isInUpload(account: self.appDelegate.account, serverUrl: self.serverUrl) { + let lock = NCManageDatabase.shared.getE2ETokenLock(account: self.appDelegate.account, serverUrl: self.serverUrl) + NextcloudKit.shared.getE2EEMetadata(fileId: metadataFolder.ocId, e2eToken: lock?.e2eToken, options: NCNetworkingE2EE().getOptions()) { account, e2eMetadata, signature, _, error in + if error == .success, let e2eMetadata = e2eMetadata { + let error = NCEndToEndMetadata().decodeMetadata(e2eMetadata, signature: signature, serverUrl: self.serverUrl, account: account, urlBase: self.appDelegate.urlBase, userId: self.appDelegate.userId) + if error == .success { + self.reloadDataSource() + } else { + // Client Diagnostic + NCManageDatabase.shared.addDiagnostic(account: account, issue: NCGlobal.shared.diagnosticIssueE2eeErrors) + NCContentPresenter().showError(error: error) + } + } else if error.errorCode == NCGlobal.shared.errorResourceNotFound { + // no metadata found, send a new metadata + Task { + let serverUrl = metadataFolder.serverUrl + "/" + metadataFolder.fileName + let error = await NCNetworkingE2EE().uploadMetadata(account: metadataFolder.account, serverUrl: serverUrl, userId: metadataFolder.userId) + if error != .success { + NCContentPresenter().showError(error: error) + } + } + } else { + NCContentPresenter().showError(error: NKError(errorCode: NCGlobal.shared.errorE2EEKeyDecodeMetadata, errorDescription: "_e2e_error_")) + } + completion(tableDirectory, metadatas, metadatasChangedCount, metadatasChanged, error) + } + } else { + completion(tableDirectory, metadatas, metadatasChangedCount, metadatasChanged, error) + } } + } else { + completion(tableDirectory, nil, 0, false, NKError()) } } } diff --git a/iOSClient/Groupfolders/NCGroupfolders.swift b/iOSClient/Groupfolders/NCGroupfolders.swift index 813b4ded9f..925b3bae69 100644 --- a/iOSClient/Groupfolders/NCGroupfolders.swift +++ b/iOSClient/Groupfolders/NCGroupfolders.swift @@ -44,12 +44,16 @@ class NCGroupfolders: NCCollectionViewCommon { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - navigationController?.setFileAppreance() + if dataSource.metadatas.isEmpty { + reloadDataSource() + } + reloadDataSourceNetwork() } // MARK: - DataSource + NC Endpoint - override func queryDB(isForced: Bool) { + override func queryDB() { + super.queryDB() var metadatas: [tableMetadata] = [] @@ -71,24 +75,8 @@ class NCGroupfolders: NCCollectionViewCommon { searchResults: self.searchResults) } - override func reloadDataSource(isForced: Bool = true) { - super.reloadDataSource() - - self.queryDB(isForced: isForced) - DispatchQueue.main.async { - self.isReloadDataSourceNetworkInProgress = false - self.refreshControl.endRefreshing() - self.collectionView.reloadData() - } - } - - override func reloadDataSourceNetwork(isForced: Bool = false) { - super.reloadDataSourceNetwork(isForced: isForced) - - NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Reload data source network groupfolders forced \(isForced)") - - isReloadDataSourceNetworkInProgress = true - collectionView?.reloadData() + override func reloadDataSourceNetwork() { + super.reloadDataSourceNetwork() let homeServerUrl = utilityFileSystem.getHomeServer(urlBase: self.appDelegate.urlBase, userId: self.appDelegate.userId) @@ -112,8 +100,8 @@ class NCGroupfolders: NCCollectionViewCommon { } self.reloadDataSource() } - } else if error != .success { - self.reloadDataSource() + } else { + self.reloadDataSource(withQueryDB: false) } } } diff --git a/iOSClient/Login/NCLogin.swift b/iOSClient/Login/NCLogin.swift index 28a9d3ba54..7133934c5a 100644 --- a/iOSClient/Login/NCLogin.swift +++ b/iOSClient/Login/NCLogin.swift @@ -400,19 +400,20 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate { self.appDelegate.changeAccount(account, userProfile: userProfile) - if NCKeychain().intro { - self.dismiss(animated: true) - } else { - NCKeychain().intro = true - if self.presentingViewController == nil { - let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() - viewController?.modalPresentationStyle = .fullScreen + if self.presentingViewController == nil { + if let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() { + viewController.modalPresentationStyle = .fullScreen + viewController.view.alpha = 0 self.appDelegate.window?.rootViewController = viewController - self.appDelegate.window?.makeKey() - } else { - self.dismiss(animated: true) + self.appDelegate.window?.makeKeyAndVisible() + UIView.animate(withDuration: 0.5) { + viewController.view.alpha = 1 + } } + } else { + self.dismiss(animated: true) } + } else { let alertController = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: error.errorDescription, preferredStyle: .alert) diff --git a/iOSClient/Login/NCLoginWeb.swift b/iOSClient/Login/NCLoginWeb.swift index 2c3f9072ce..8ced23e0ff 100644 --- a/iOSClient/Login/NCLoginWeb.swift +++ b/iOSClient/Login/NCLoginWeb.swift @@ -298,23 +298,18 @@ extension NCLoginWeb: WKNavigationDelegate { self.appDelegate.changeAccount(account, userProfile: userProfile) - if NCKeychain().intro { - self.dismiss(animated: true) - } else { - NCKeychain().intro = true - if self.presentingViewController == nil { - if let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() { - viewController.modalPresentationStyle = .fullScreen - viewController.view.alpha = 0 - self.appDelegate.window?.rootViewController = viewController - self.appDelegate.window?.makeKeyAndVisible() - UIView.animate(withDuration: 0.5) { - viewController.view.alpha = 1 - } + if self.presentingViewController == nil { + if let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() { + viewController.modalPresentationStyle = .fullScreen + viewController.view.alpha = 0 + self.appDelegate.window?.rootViewController = viewController + self.appDelegate.window?.makeKeyAndVisible() + UIView.animate(withDuration: 0.5) { + viewController.view.alpha = 1 } - } else { - self.dismiss(animated: true) } + } else { + self.dismiss(animated: true) } } else { diff --git a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift index 851265c26b..e50f9a69f4 100644 --- a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift +++ b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift @@ -48,25 +48,23 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS internal var richWorkspaceText: String? internal var headerMenu: NCSectionHeaderMenu? internal var isSearchingMode: Bool = false - internal var layoutForView: NCDBLayoutForView? internal var selectableDataSource: [RealmSwiftObject] { dataSource.getMetadataSourceForAllSections() } - private var autoUploadFileName = "" private var autoUploadDirectory = "" internal var groupByField = "name" internal var providers: [NKSearchProvider]? internal var searchResults: [NKSearchResult]? - internal var listLayout: NCListLayout! internal var gridLayout: NCGridLayout! - internal var literalSearch: String? - internal var isReloadDataSourceNetworkInProgress: Bool = false - private var pushed: Bool = false + internal var timerNotificationCenter: Timer? + internal var notificationReloadDataSource: Int = 0 + internal var notificationReloadDataSourceNetwork: Int = 0 + private var pushed: Bool = false private var tipView: EasyTipView? private var isTransitioning: Bool = false // DECLARE @@ -129,7 +127,8 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS collectionView.refreshControl = refreshControl refreshControl.action(for: .valueChanged) { _ in self.dataSource.clearDirectory() - self.reloadDataSourceNetwork(isForced: true) + NCManageDatabase.shared.cleanEtagDirectory(account: self.appDelegate.account, serverUrl: self.serverUrl) + self.reloadDataSourceNetwork() } // Empty @@ -174,14 +173,15 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS collectionView?.collectionViewLayout = gridLayout } + timerNotificationCenter = Timer.scheduledTimer(timeInterval: 1.5, target: self, selector: #selector(notificationCenterEvents), userInfo: nil, repeats: true) + NotificationCenter.default.addObserver(self, selector: #selector(applicationWillResignActive(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationWillResignActive), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(closeRichWorkspaceWebView), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterCloseRichWorkspaceWebView), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(changeStatusFolderE2EE(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeStatusFolderE2EE), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(reloadAvatar(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadAvatar), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSource(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSource), object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSourceNetwork), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSourceNetwork), object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSourceNetworkForced(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSourceNetworkForced), object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSourceNetwork(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSourceNetwork), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(deleteFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDeleteFile), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(moveFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMoveFile), object: nil) @@ -196,6 +196,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS NotificationCenter.default.addObserver(self, selector: #selector(uploadStartFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadStartFile), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(uploadedFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadedFile), object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(uploadedLivePhoto(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadedLivePhoto), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(uploadCancelFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadCancelFile), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(triggerProgressTask(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterProgressTask), object: nil) @@ -208,12 +209,8 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS navigationController?.navigationBar.prefersLargeTitles = true navigationController?.setNavigationBarHidden(false, animated: true) - setNavigationItem() - - reloadDataSource(isForced: false) - if !isSearchingMode { - reloadDataSourceNetwork() - } + navigationController?.setNavigationBarAppearance() + setNavigationItems() // FIXME: iPAD PDF landscape mode iOS 16 DispatchQueue.main.async { @@ -231,16 +228,26 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSource), object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSourceNetwork), object: nil) - NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSourceNetworkForced), object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDeleteFile), object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMoveFile), object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterCopyFile), object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterRenameFile), object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterCreateFolder), object: nil) + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterFavoriteFile), object: nil) + + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDownloadStartFile), object: nil) + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDownloadedFile), object: nil) + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDownloadCancelFile), object: nil) + + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadStartFile), object: nil) + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadedFile), object: nil) + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadedLivePhoto), object: nil) + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadCancelFile), object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterProgressTask), object: nil) + timerNotificationCenter?.invalidate() pushed = false // REQUEST @@ -276,6 +283,14 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS // MARK: - NotificationCenter + @objc func notificationCenterEvents() { + if notificationReloadDataSource > 0 { + print("notificationReloadDataSource: \(notificationReloadDataSource)") + reloadDataSource() + notificationReloadDataSource = 0 + } + } + @objc func applicationWillResignActive(_ notification: NSNotification) { self.refreshControl.endRefreshing() } @@ -290,7 +305,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS let error = userInfo["error"] as? NKError, error.errorCode != NCGlobal.shared.errorNotModified else { return } - setNavigationItem() + setNavigationItems() } @objc func changeTheming() { @@ -298,18 +313,17 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS } @objc func reloadDataSource(_ notification: NSNotification) { - reloadDataSource() + notificationReloadDataSource += 1 } - @objc func reloadDataSourceNetworkForced(_ notification: NSNotification) { - + @objc func reloadDataSourceNetwork(_ notification: NSNotification) { if !isSearchingMode { - reloadDataSourceNetwork(isForced: true) + reloadDataSourceNetwork() } } @objc func changeStatusFolderE2EE(_ notification: NSNotification) { - reloadDataSource() + notificationReloadDataSource += 1 } @objc func closeRichWorkspaceWebView() { @@ -321,8 +335,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS guard let userInfo = notification.userInfo as NSDictionary?, let error = userInfo["error"] as? NKError else { return } - self.queryDB(isForced: true) - self.collectionView?.reloadData() + notificationReloadDataSource += 1 if error != .success { NCContentPresenter().showError(error: error) @@ -350,7 +363,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS account == appDelegate.account else { return } - reloadDataSourceNetwork(isForced: true) + reloadDataSourceNetwork() } @objc func createFolder(_ notification: NSNotification) { @@ -364,29 +377,25 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS let withPush = userInfo["withPush"] as? Bool else { return } - if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) { - reloadDataSource() - if withPush { - pushMetadata(metadata) - } + notificationReloadDataSource += 1 + + if withPush, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) { + pushMetadata(metadata) } } @objc func favoriteFile(_ notification: NSNotification) { + if self is NCFavorite { + return notificationReloadDataSource += 1 + } + guard let userInfo = notification.userInfo as NSDictionary?, - let ocId = userInfo["ocId"] as? String, let serverUrl = userInfo["serverUrl"] as? String, serverUrl == self.serverUrl - else { - if self is NCFavorite { - reloadDataSource() - } - return - } + else { return } - dataSource.reloadMetadata(ocId: ocId) - collectionView?.reloadData() + notificationReloadDataSource += 1 } @objc func downloadStartFile(_ notification: NSNotification) { @@ -398,7 +407,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS account == appDelegate.account else { return } - reloadDataSource() + self.notificationReloadDataSource += 1 } @objc func downloadedFile(_ notification: NSNotification) { @@ -407,32 +416,27 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS let serverUrl = userInfo["serverUrl"] as? String, serverUrl == self.serverUrl, let account = userInfo["account"] as? String, - account == appDelegate.account + account == appDelegate.account, + let error = userInfo["error"] as? NKError else { return } - reloadDataSource() + if error != .success { + NCContentPresenter().showError(error: error) + } + + notificationReloadDataSource += 1 } @objc func downloadCancelFile(_ notification: NSNotification) { guard let userInfo = notification.userInfo as NSDictionary?, - let ocId = userInfo["ocId"] as? String, let serverUrl = userInfo["serverUrl"] as? String, serverUrl == self.serverUrl, let account = userInfo["account"] as? String, account == appDelegate.account else { return } - let (indexPath, sameSections) = dataSource.reloadMetadata(ocId: ocId) - if let indexPath = indexPath { - if sameSections && (indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section)) { - collectionView?.reloadItems(at: [indexPath]) - } else { - self.collectionView?.reloadData() - } - } else { - reloadDataSource() - } + notificationReloadDataSource += 1 } @objc func uploadStartFile(_ notification: NSNotification) { @@ -440,19 +444,19 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS guard let userInfo = notification.userInfo as NSDictionary?, let ocId = userInfo["ocId"] as? String, let serverUrl = userInfo["serverUrl"] as? String, - let account = userInfo["account"] as? String + let account = userInfo["account"] as? String, + !isSearchingMode, + let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { return } - guard !isSearchingMode, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { return } - // Header view trasfer if metadata.isTransferInForeground { NCNetworking.shared.transferInForegorund = NCNetworking.TransferInForegorund(ocId: ocId, progress: 0) - self.collectionView?.reloadData() + DispatchQueue.main.async { self.collectionView?.reloadData() } } if serverUrl == self.serverUrl, account == appDelegate.account { - reloadDataSource() + notificationReloadDataSource += 1 } } @@ -466,14 +470,26 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS if ocIdTemp == NCNetworking.shared.transferInForegorund?.ocId { NCNetworking.shared.transferInForegorund = nil - self.collectionView?.reloadData() + DispatchQueue.main.async { self.collectionView?.reloadData() } } if account == appDelegate.account, serverUrl == self.serverUrl { - reloadDataSource() + notificationReloadDataSource += 1 } } + @objc func uploadedLivePhoto(_ notification: NSNotification) { + + guard let userInfo = notification.userInfo as NSDictionary?, + let serverUrl = userInfo["serverUrl"] as? String, + serverUrl == self.serverUrl, + let account = userInfo["account"] as? String, + account == appDelegate.account + else { return } + + notificationReloadDataSource += 1 + } + @objc func uploadCancelFile(_ notification: NSNotification) { guard let userInfo = notification.userInfo as NSDictionary?, @@ -484,11 +500,11 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS if ocId == NCNetworking.shared.transferInForegorund?.ocId { NCNetworking.shared.transferInForegorund = nil - self.collectionView?.reloadData() + DispatchQueue.main.async { self.collectionView?.reloadData() } } if account == appDelegate.account, serverUrl == self.serverUrl { - reloadDataSource() + notificationReloadDataSource += 1 } } @@ -504,22 +520,22 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS let chunk: Int = userInfo["chunk"] as? Int ?? 0 let e2eEncrypted: Bool = userInfo["e2eEncrypted"] as? Bool ?? false - // Header Transfer - if headerMenuTransferView && (chunk > 0 || e2eEncrypted) { - if NCNetworking.shared.transferInForegorund?.ocId == ocId { - NCNetworking.shared.transferInForegorund?.progress = progressNumber.floatValue - } else { - NCNetworking.shared.transferInForegorund = NCNetworking.TransferInForegorund(ocId: ocId, progress: progressNumber.floatValue) - collectionView.reloadData() + if self.headerMenuTransferView && (chunk > 0 || e2eEncrypted) { + DispatchQueue.main.async { + if NCNetworking.shared.transferInForegorund?.ocId == ocId { + NCNetworking.shared.transferInForegorund?.progress = progressNumber.floatValue + } else { + NCNetworking.shared.transferInForegorund = NCNetworking.TransferInForegorund(ocId: ocId, progress: progressNumber.floatValue) + self.collectionView.reloadData() + } + self.headerMenu?.progressTransfer.progress = progressNumber.floatValue } - self.headerMenu?.progressTransfer.progress = progressNumber.floatValue - } - - let status = userInfo["status"] as? Int ?? NCGlobal.shared.metadataStatusNormal - - if let (indexPath, _) = self.dataSource.getIndexPathMetadata(ocId: ocId) as? (IndexPath, NCMetadataForSection?), - let cell = collectionView?.cellForItem(at: indexPath) { - if let cell = cell as? NCCellProtocol { + } else { + guard let indexPath = self.dataSource.getIndexPathMetadata(ocId: ocId).indexPath else { return } + let status = userInfo["status"] as? Int ?? NCGlobal.shared.metadataStatusNormal + DispatchQueue.main.async { + guard let cell = self.collectionView?.cellForItem(at: indexPath), + let cell = cell as? NCCellProtocol else { return } if progressNumber.floatValue == 1 && !(cell is NCTransferCell) { cell.fileProgressView?.isHidden = true cell.fileProgressView?.progress = .zero @@ -533,13 +549,13 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS cell.fileProgressView?.isHidden = false cell.fileProgressView?.progress = progressNumber.floatValue cell.setButtonMore(named: NCGlobal.shared.buttonMoreStop, image: NCImageCache.images.buttonStop) - if status == NCGlobal.shared.metadataStatusInDownload { - cell.fileInfoLabel?.text = utilityFileSystem.transformedSize(totalBytesExpected) + " - ↓ " + utilityFileSystem.transformedSize(totalBytes) - } else if status == NCGlobal.shared.metadataStatusInUpload { + if status == NCGlobal.shared.metadataStatusDownloading { + cell.fileInfoLabel?.text = self.utilityFileSystem.transformedSize(totalBytesExpected) + " - ↓ " + self.utilityFileSystem.transformedSize(totalBytes) + } else if status == NCGlobal.shared.metadataStatusUploading { if totalBytes > 0 { - cell.fileInfoLabel?.text = utilityFileSystem.transformedSize(totalBytesExpected) + " - ↑ " + utilityFileSystem.transformedSize(totalBytes) + cell.fileInfoLabel?.text = self.utilityFileSystem.transformedSize(totalBytesExpected) + " - ↑ " + self.utilityFileSystem.transformedSize(totalBytes) } else { - cell.fileInfoLabel?.text = utilityFileSystem.transformedSize(totalBytesExpected) + " - ↑ …" + cell.fileInfoLabel?.text = self.utilityFileSystem.transformedSize(totalBytesExpected) + " - ↑ …" } } } @@ -550,7 +566,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS // MARK: - Tip func showTip() { - if self is NCFiles, self.view.window != nil, !NCBrandOptions.shared.disable_multiaccount, !NCBrandOptions.shared.disable_manage_account, self.serverUrl == utilityFileSystem.getHomeServer(urlBase: appDelegate.urlBase, userId: appDelegate.userId), let view = self.navigationItem.leftBarButtonItem?.customView { if !NCManageDatabase.shared.tipExists(NCGlobal.shared.tipNCCollectionViewCommonAccountRequest), !NCManageDatabase.shared.getAllAccountOrderAlias().isEmpty { self.tipView?.show(forView: view) @@ -560,7 +575,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS // MARK: - Layout - func setNavigationItem() { + func setNavigationItems() { self.setNavigationRightItems() navigationItem.title = titleCurrentFolder @@ -579,20 +594,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS let button = UIButton(type: .custom) button.setImage(image, for: .normal) - if serverUrl == utilityFileSystem.getHomeServer(urlBase: appDelegate.urlBase, userId: appDelegate.userId) { - - var titleButton = " " - - if getNavigationTitle() == activeAccount?.alias { - titleButton = "" - } else { - titleButton += activeAccount?.displayName ?? "" - } - - button.setTitle(titleButton, for: .normal) - button.setTitleColor(.systemBlue, for: .normal) - } - button.semanticContentAttribute = .forceLeftToRight button.sizeToFit() button.action(for: .touchUpInside) { _ in @@ -622,13 +623,14 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS self.dismissTip() } } + navigationItem.setLeftBarButton(UIBarButtonItem(customView: button), animated: true) navigationItem.leftItemsSupplementBackButton = true - if titlePreviusFolder == nil { - navigationController?.navigationBar.topItem?.title = getNavigationTitle() - } else { + + if titlePreviusFolder != nil { navigationController?.navigationBar.topItem?.title = titlePreviusFolder } + navigationItem.title = titleCurrentFolder } @@ -699,12 +701,10 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS DispatchQueue.global().async { NCNetworking.shared.cancelUnifiedSearchFiles() - self.isSearchingMode = false self.literalSearch = "" self.providers?.removeAll() self.dataSource.clearDataSource() - self.reloadDataSource() } } @@ -883,10 +883,10 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS // MARK: - DataSource + NC Endpoint - func queryDB(isForced: Bool) { } + func queryDB() { } - @objc func reloadDataSource(isForced: Bool = true) { - guard !appDelegate.account.isEmpty else { return } + @objc func reloadDataSource(withQueryDB: Bool = true) { + guard !appDelegate.account.isEmpty, !self.isSearchingMode else { return } // get auto upload folder autoUploadFileName = NCManageDatabase.shared.getAccountAutoUploadFileName() @@ -901,16 +901,26 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS } else { groupByField = "name" } + + DispatchQueue.global().async { + if withQueryDB { self.queryDB() } + DispatchQueue.main.async { + self.isReloadDataSourceNetworkInProgress = false + self.refreshControl.endRefreshing() + self.collectionView.reloadData() + } + } } - @objc func reloadDataSourceNetwork(isForced: Bool = false) { } + @objc func reloadDataSourceNetwork() { + + isReloadDataSourceNetworkInProgress = true + collectionView?.reloadData() + } @objc func networkSearch() { guard !appDelegate.account.isEmpty, let literalSearch = literalSearch, !literalSearch.isEmpty - else { - self.refreshControl.endRefreshing() - return - } + else { return self.refreshControl.endRefreshing() } isReloadDataSourceNetworkInProgress = true self.dataSource.clearDataSource() @@ -982,65 +992,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS } } - @objc func networkReadFolder(isForced: Bool, completion: @escaping(_ tableDirectory: tableDirectory?, _ metadatas: [tableMetadata]?, _ metadatasChangedCount: Int, _ metadatasChanged: Bool, _ error: NKError) -> Void) { - - var tableDirectory: tableDirectory? - - NCNetworking.shared.readFile(serverUrlFileName: serverUrl) { account, metadataFolder, error in - guard error == .success else { - completion(nil, nil, 0, false, error) - return - } - - if let metadataFolder = metadataFolder { - tableDirectory = NCManageDatabase.shared.setDirectory(serverUrl: self.serverUrl, richWorkspace: metadataFolder.richWorkspace, account: account) - } - - if isForced || tableDirectory?.etag != metadataFolder?.etag || metadataFolder?.e2eEncrypted ?? true { - NCNetworking.shared.readFolder(serverUrl: self.serverUrl, account: self.appDelegate.account) { _, metadataFolder, metadatas, metadatasChangedCount, metadatasChanged, error in - guard error == .success else { - completion(tableDirectory, nil, 0, false, error) - return - } - self.metadataFolder = metadataFolder - // E2EE - if let metadataFolder = metadataFolder, - metadataFolder.e2eEncrypted, - NCKeychain().isEndToEndEnabled(account: self.appDelegate.account), - !NCNetworkingE2EE().isInUpload(account: self.appDelegate.account, serverUrl: self.serverUrl) { - let lock = NCManageDatabase.shared.getE2ETokenLock(account: self.appDelegate.account, serverUrl: self.serverUrl) - NextcloudKit.shared.getE2EEMetadata(fileId: metadataFolder.ocId, e2eToken: lock?.e2eToken) { _, e2eMetadata, signature, _, error in - if error == .success, let e2eMetadata = e2eMetadata { - let error = NCEndToEndMetadata().decodeMetadata(e2eMetadata, signature: signature, serverUrl: self.serverUrl, account: self.appDelegate.account, urlBase: self.appDelegate.urlBase, userId: self.appDelegate.userId) - if error == .success { - self.reloadDataSource() - } else { - NCContentPresenter().showError(error: error) - } - } else if error.errorCode == NCGlobal.shared.errorResourceNotFound { - // no metadata found, send a new metadata - Task { - let serverUrl = metadataFolder.serverUrl + "/" + metadataFolder.fileName - let error = await NCNetworkingE2EE().uploadMetadata(account: metadataFolder.account, serverUrl: serverUrl, userId: metadataFolder.userId) - if error != .success { - NCContentPresenter().showError(error: error) - } - } - } else { - NCContentPresenter().showError(error: NKError(errorCode: NCGlobal.shared.errorE2EEKeyDecodeMetadata, errorDescription: "_e2e_error_")) - } - completion(tableDirectory, metadatas, metadatasChangedCount, metadatasChanged, error) - } - } else { - completion(tableDirectory, metadatas, metadatasChangedCount, metadatasChanged, error) - } - } - } else { - completion(tableDirectory, nil, 0, false, NKError()) - } - } - } - // MARK: - Push metadata func pushMetadata(_ metadata: tableMetadata) { @@ -1131,8 +1082,8 @@ extension NCCollectionViewCommon: UICollectionViewDelegate { if utilityFileSystem.fileProviderStorageExists(metadata) { NCViewer().view(viewController: self, metadata: metadata, metadatas: [metadata], imageIcon: imageIcon) - } else if NextcloudKit.shared.isNetworkReachable() { - NCNetworking.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorLoadFileView) { _, _ in } + } else if NextcloudKit.shared.isNetworkReachable(), let metadata = NCManageDatabase.shared.setMetadataSessionInWaitDownload(ocId: metadata.ocId, selector: NCGlobal.shared.selectorLoadFileView) { + NCNetworking.shared.download(metadata: metadata, withNotificationProgressTask: true) } else { let error = NKError(errorCode: NCGlobal.shared.errorOffline, errorDescription: "_go_online_") NCContentPresenter().showInfo(error: error) @@ -1416,16 +1367,11 @@ extension NCCollectionViewCommon: UICollectionViewDataSource { switch metadata.status { case NCGlobal.shared.metadataStatusWaitDownload: cell.fileInfoLabel?.text = utilityFileSystem.transformedSize(metadata.size) + " - " + NSLocalizedString("_status_wait_download_", comment: "") - case NCGlobal.shared.metadataStatusInDownload: - cell.fileInfoLabel?.text = utilityFileSystem.transformedSize(metadata.size) + " - " + NSLocalizedString("_status_in_download_", comment: "") case NCGlobal.shared.metadataStatusDownloading: cell.fileInfoLabel?.text = utilityFileSystem.transformedSize(metadata.size) + " - ↓ …" case NCGlobal.shared.metadataStatusWaitUpload: cell.fileInfoLabel?.text = utilityFileSystem.transformedSize(metadata.size) + " - " + NSLocalizedString("_status_wait_upload_", comment: "") cell.fileLocalImage?.image = nil - case NCGlobal.shared.metadataStatusInUpload: - cell.fileInfoLabel?.text = utilityFileSystem.transformedSize(metadata.size) + " - " + NSLocalizedString("_status_in_upload_", comment: "") - cell.fileLocalImage?.image = nil case NCGlobal.shared.metadataStatusUploading: cell.fileInfoLabel?.text = utilityFileSystem.transformedSize(metadata.size) + " - ↑ …" cell.fileLocalImage?.image = nil diff --git a/iOSClient/Main/Collection Common/NCListCell.xib b/iOSClient/Main/Collection Common/NCListCell.xib index b32510775e..ed7e57d034 100755 --- a/iOSClient/Main/Collection Common/NCListCell.xib +++ b/iOSClient/Main/Collection Common/NCListCell.xib @@ -1,9 +1,9 @@ - + - + @@ -19,35 +19,35 @@ - + - + - + - + - + @@ -66,7 +66,7 @@ - + - + - + @@ -112,7 +112,7 @@ - + - + - + @@ -233,20 +233,20 @@ - + - + - + - + - + - + @@ -399,16 +399,16 @@ - + - + @@ -437,10 +437,10 @@ - +