diff --git a/Brand/NCBrand.swift b/Brand/NCBrand.swift index 0fd9b5b6a7..00550b2a58 100755 --- a/Brand/NCBrand.swift +++ b/Brand/NCBrand.swift @@ -20,6 +20,43 @@ let userAgent: String = { The codename embodies the concept of dynamic, living matter — reflecting our vision of a platform that is not only powerful and reliable, but also capable of continuous transformation and intelligent adaptation. */ +struct NextcloudVersion: Comparable { + let major: Int + let minor: Int + let micro: Int + + init(_ major: Int, _ minor: Int = 0, _ micro: Int = 0) { + self.major = major + self.minor = minor + self.micro = micro + } + + init(_ capabilities: NKCapabilities.Capabilities) { + self.major = capabilities.serverVersionMajor + self.minor = capabilities.serverVersionMinor + self.micro = capabilities.serverVersionMicro + } + + static let v18 = NextcloudVersion(18) + static let v20 = NextcloudVersion(20) + static let v23 = NextcloudVersion(23) + static let v24 = NextcloudVersion(24) + static let v25 = NextcloudVersion(25) + static let v26 = NextcloudVersion(26) + static let v27 = NextcloudVersion(27) + static let v28 = NextcloudVersion(28) + static let v30 = NextcloudVersion(30) + static let v31 = NextcloudVersion(31) + static let v32 = NextcloudVersion(32) + static let v32_0_2 = NextcloudVersion(32, 0, 2) + static let v33 = NextcloudVersion(33) + static let v34 = NextcloudVersion(34) + + static func < (lhs: NextcloudVersion, rhs: NextcloudVersion) -> Bool { + (lhs.major, lhs.minor, lhs.micro) < (rhs.major, rhs.minor, rhs.micro) + } +} + final class NCBrandOptions: @unchecked Sendable { static let shared = NCBrandOptions() @@ -129,19 +166,8 @@ final class NCBrandOptions: @unchecked Sendable { } func isServerVersion(_ capabilities: NKCapabilities.Capabilities, - greaterOrEqualTo major: Int, - _ minor: Int, - _ micro: Int) -> Bool { - - let server = ( - capabilities.serverVersionMajor, - capabilities.serverVersionMinor, - capabilities.serverVersionMicro - ) - - let required = (major, minor, micro) - - return server >= required + greaterOrEqualTo version: NextcloudVersion) -> Bool { + return NextcloudVersion(capabilities) >= version } } diff --git a/File Provider Extension/FileProviderData.swift b/File Provider Extension/FileProviderData.swift index 9c36bb5bf0..172beb53fe 100644 --- a/File Provider Extension/FileProviderData.swift +++ b/File Provider Extension/FileProviderData.swift @@ -90,7 +90,7 @@ class FileProviderData: NSObject { return isPaginated } else if serverUrl == NCUtilityFileSystem().getHomeServer(session: session), let capabilities = await NextcloudKit.shared.getCapabilitiesAsync(account: session.account).capabilities, - NCBrandOptions.shared.isServerVersion(capabilities, greaterOrEqualTo: 32, 0, 2) { + NCBrandOptions.shared.isServerVersion(capabilities, greaterOrEqualTo: .v32_0_2) { isPaginated = true return true } @@ -147,10 +147,7 @@ class FileProviderData: NSObject { func downloadComplete(fileName: String, serverUrl: String, - etag: String?, - date: Date?, - dateLastModified: Date?, - length: Int64, + allHeaderFields: [AnyHashable: Any]?, task: URLSessionTask, error: NKError) async { let taskIdentifier = task.taskIdentifier @@ -165,6 +162,7 @@ class FileProviderData: NSObject { } let ocId = metadata.ocId + let etag = NextcloudKit.shared.nkCommonInstance.findHeader("oc-etag", allHeaderFields: allHeaderFields) await NCManageDatabase.shared.setMetadataSessionAsync(ocId: ocId, session: "", @@ -196,7 +194,8 @@ class FileProviderData: NSObject { ocId: String?, etag: String?, date: Date?, - size: Int64, + ownerId: String?, + permissions: String?, task: URLSessionTask, error: NKError) async { guard let metadata = await NCManageDatabase.shared.getMetadataAsync(predicate: NSPredicate(format: "serverUrl == %@ AND fileName == %@ AND sessionTaskIdentifier == %d", serverUrl, fileName, task.taskIdentifier)) else { @@ -225,11 +224,22 @@ class FileProviderData: NSObject { metadata.uploadDate = (date as? NSDate) ?? NSDate() metadata.etag = etag ?? "" metadata.ocId = ocId - metadata.size = size + if let fileId = fileProviderUtility().ocIdToFileId(ocId: ocId) { metadata.fileId = fileId } + if let ownerId, !ownerId.isEmpty { + metadata.ownerId = ownerId + if let ownerDisplayName = await NCManageDatabase.shared.getOwnerDisplayName(account: metadata.account, ownerId: ownerId) { + metadata.ownerDisplayName = ownerDisplayName + } + } + + if let permissions, !permissions.isEmpty { + metadata.permissions = permissions + } + metadata.sceneIdentifier = nil metadata.session = "" metadata.sessionError = "" diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index da11cd9ed5..a3788d3efc 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -441,6 +441,13 @@ F75DD765290ABB25002EB562 /* Intent.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = F75DD769290ABB25002EB562 /* Intent.intentdefinition */; }; F75DD766290ABB25002EB562 /* Intent.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = F75DD769290ABB25002EB562 /* Intent.intentdefinition */; }; F75DD767290ABB25002EB562 /* Intent.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = F75DD769290ABB25002EB562 /* Intent.intentdefinition */; }; + F75F4BC02FD008D7009E55ED /* Optional+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F343A4BA2A1E734600DDA874 /* Optional+Extension.swift */; }; + F75F4BC12FD008D7009E55ED /* Optional+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F343A4BA2A1E734600DDA874 /* Optional+Extension.swift */; }; + F75F4BC22FD008D7009E55ED /* Optional+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F343A4BA2A1E734600DDA874 /* Optional+Extension.swift */; }; + F75F4BC32FD008D7009E55ED /* Optional+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F343A4BA2A1E734600DDA874 /* Optional+Extension.swift */; }; + F75F4BC42FD008D7009E55ED /* Optional+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F343A4BA2A1E734600DDA874 /* Optional+Extension.swift */; }; + F75F4BC52FD008D7009E55ED /* Optional+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F343A4BA2A1E734600DDA874 /* Optional+Extension.swift */; }; + F75F4BC62FD008D7009E55ED /* Optional+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F343A4BA2A1E734600DDA874 /* Optional+Extension.swift */; }; F760DE032AE66EA80027D78A /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = F760DE022AE66EA80027D78A /* KeychainAccess */; }; F760DE052AE66EBE0027D78A /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = F760DE042AE66EBE0027D78A /* KeychainAccess */; }; F760DE072AE66EC70027D78A /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = F760DE062AE66EC70027D78A /* KeychainAccess */; }; @@ -4163,6 +4170,7 @@ buildActionMask = 2147483647; files = ( F73EF7BD2B0224AB0087E6E9 /* NCManageDatabase+ExternalSites.swift in Sources */, + F75F4BC62FD008D7009E55ED /* Optional+Extension.swift in Sources */, F73EF7C52B02250B0087E6E9 /* NCManageDatabase+GPS.swift in Sources */, 2C1D5D7923E2DE9100334ABB /* NCBrand.swift in Sources */, F770768A263A8A2500A1BA94 /* NCUtilityFileSystem.swift in Sources */, @@ -4257,6 +4265,7 @@ buildActionMask = 2147483647; files = ( F78E2D6A29AF02DB0024D4F3 /* Database.swift in Sources */, + F75F4BC52FD008D7009E55ED /* Optional+Extension.swift in Sources */, F7490E6E29882B56009DCE94 /* NCBrand.swift in Sources */, F7D61E942EBF1366007F865B /* UIColor+Extension.swift in Sources */, F71F6D0C2B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */, @@ -4327,6 +4336,7 @@ F77C973A2953143A00FDDD09 /* NCCameraRoll.swift in Sources */, F740BEF02A35C2AD00E9B6D5 /* UILabel+Extension.swift in Sources */, F7C30E01291BD2610017149B /* NCNetworkingE2EERename.swift in Sources */, + F75F4BC22FD008D7009E55ED /* Optional+Extension.swift in Sources */, AF4BF61A27562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */, AF4BF615275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */, F798F0E225880608000DAFFD /* UIColor+Extension.swift in Sources */, @@ -4477,6 +4487,7 @@ F72EA95228B7BA2A00C88F0C /* DashboardWidgetProvider.swift in Sources */, F77E8C242E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift in Sources */, F76340F72EBDE9760056F538 /* NCManageDatabaseCore.swift in Sources */, + F75F4BC02FD008D7009E55ED /* Optional+Extension.swift in Sources */, F7D496FD2EBFA6D9004F9823 /* String+Extension.swift in Sources */, F7D7A7702DCDD437003D2007 /* NCManageDatabase+AutoUpload.swift in Sources */, F72EA95828B7BC4F00C88F0C /* FilesData.swift in Sources */, @@ -4514,6 +4525,7 @@ F3E173C42C9B1067006D177A /* AwakeMode.swift in Sources */, F7D61E932EBF1366007F865B /* UIColor+Extension.swift in Sources */, F76340F42EBDE9760056F538 /* NCManageDatabaseCore.swift in Sources */, + F75F4BC42FD008D7009E55ED /* Optional+Extension.swift in Sources */, F7CAFE212F17A37C00DB35A5 /* NCNetworking+Actor.swift in Sources */, F76340EE2EBDE74C0056F538 /* NCManageDatabase.swift in Sources */, F763410A2EBDFCB10056F538 /* NCManageDatabase+CreateMetadata.swift in Sources */, @@ -4909,6 +4921,7 @@ F7C55C8E2FB5B03D004A974F /* NCGlobal.swift in Sources */, F7C55CC92FB5CE74004A974F /* ActionViewController.swift in Sources */, F7C55C9B2FB5B1A7004A974F /* UIColor+Extension.swift in Sources */, + F75F4BC32FD008D7009E55ED /* Optional+Extension.swift in Sources */, F7C55C8D2FB5B02C004A974F /* NCAssistantSharedTextStore.swift in Sources */, F7C55C9A2FB5B127004A974F /* ThreadSafeDictionary.swift in Sources */, ); @@ -4965,6 +4978,7 @@ F71F6D092B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */, F757CC8429E7F88B00F31428 /* NCManageDatabase+Groupfolders.swift in Sources */, F78E2D6729AF02DB0024D4F3 /* Database.swift in Sources */, + F75F4BC12FD008D7009E55ED /* Optional+Extension.swift in Sources */, F77DD6AA2C5CC093009448FB /* NCSession.swift in Sources */, F7A8D73628F17E1A008BBE1C /* NCManageDatabase+Activity.swift in Sources */, ); @@ -6346,7 +6360,7 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/nextcloud/NextcloudKit"; requirement = { - branch = 7.3.2; + branch = main; kind = branch; }; }; diff --git a/iOSClient/Assistant/NCAssistantModel.swift b/iOSClient/Assistant/NCAssistantModel.swift index 7b796643ca..02dbc8c11f 100644 --- a/iOSClient/Assistant/NCAssistantModel.swift +++ b/iOSClient/Assistant/NCAssistantModel.swift @@ -43,7 +43,7 @@ class NCAssistantModel { self.session = NCSession.shared.getSession(controller: controller) let capabilities = NCNetworking.shared.capabilities[session.account] ?? NKCapabilities.Capabilities() - useV2 = capabilities.serverVersionMajor >= NCGlobal.shared.nextcloudVersion30 + useV2 = NCBrandOptions.shared.isServerVersion(capabilities, greaterOrEqualTo: .v30) loadAllTypes() } diff --git a/iOSClient/Data/NCManageDatabase+Metadata.swift b/iOSClient/Data/NCManageDatabase+Metadata.swift index dc32ea891c..011ddbf681 100644 --- a/iOSClient/Data/NCManageDatabase+Metadata.swift +++ b/iOSClient/Data/NCManageDatabase+Metadata.swift @@ -1028,6 +1028,22 @@ extension NCManageDatabase { } } + func getOwnerDisplayName(account: String?, ownerId: String?) async -> String? { + guard let account = account.isNotEmpty, + let ownerId = ownerId.isNotEmpty else { + return nil + } + + return await core.performRealmReadAsync { realm in + let ownerDisplayName = realm.objects(tableMetadata.self) + .filter("account == %@ AND ownerId == %@", account, ownerId) + .first? + .ownerDisplayName + + return ownerDisplayName.isNotEmpty + } + } + /// Asynchronously retrieves the metadata for a folder, based on its session and serverUrl. /// Handles the home directory case rootFileName) and detaches the Realm object before returning. func getMetadataFolderAsync(session: NCSession.Session, serverUrl: String) async -> tableMetadata? { diff --git a/iOSClient/Data/NCMetadataTranfersSuccess.swift b/iOSClient/Data/NCMetadataTranfersSuccess.swift index 5b53798df9..fdd2d984dc 100644 --- a/iOSClient/Data/NCMetadataTranfersSuccess.swift +++ b/iOSClient/Data/NCMetadataTranfersSuccess.swift @@ -30,7 +30,12 @@ actor NCMetadataTranfersSuccess { delegates.removeAll { $0 as AnyObject === delegate as AnyObject } } - func append(metadata: tableMetadata, ocId: String, date: Date?, etag: String?) async { + func append(metadata: tableMetadata, + ocId: String, + date: Date?, + etag: String?, + ownerId: String? = nil, + permissions: String? = nil) async { let status = metadata.status metadata.ocId = ocId @@ -42,6 +47,17 @@ actor NCMetadataTranfersSuccess { metadata.fileId = fileId } + if let ownerId = ownerId.isNotEmpty { + metadata.ownerId = ownerId + if let ownerDisplayName = await NCManageDatabase.shared.getOwnerDisplayName(account: metadata.account, ownerId: ownerId) { + metadata.ownerDisplayName = ownerDisplayName + } + } + + if let permissions = permissions.isNotEmpty { + metadata.permissions = permissions + } + metadata.session = "" metadata.sessionError = "" metadata.sessionTaskIdentifier = 0 diff --git a/iOSClient/Extensions/Optional+Extension.swift b/iOSClient/Extensions/Optional+Extension.swift index 5a9b2e5f59..d7f7ed696d 100644 --- a/iOSClient/Extensions/Optional+Extension.swift +++ b/iOSClient/Extensions/Optional+Extension.swift @@ -28,4 +28,11 @@ extension Optional where Wrapped: Collection { var isEmptyOrNil: Bool { return self?.isEmpty ?? true } + + var isNotEmpty: Wrapped? { + guard let value = self, !value.isEmpty else { + return nil + } + return value + } } diff --git a/iOSClient/Main/Collection Common/NCCollectionViewCommon+CollectionViewDelegate.swift b/iOSClient/Main/Collection Common/NCCollectionViewCommon+CollectionViewDelegate.swift index 9b9a422625..4a57032ba3 100644 --- a/iOSClient/Main/Collection Common/NCCollectionViewCommon+CollectionViewDelegate.swift +++ b/iOSClient/Main/Collection Common/NCCollectionViewCommon+CollectionViewDelegate.swift @@ -78,7 +78,7 @@ extension NCCollectionViewCommon: UICollectionViewDelegate { await banner.dismissAsync() } - if results.nkError == .success || results.afError?.isExplicitlyCancelledError ?? false { + if results.nkError == .success || results.nkError == .cancelled { print("ok") } else { await showErrorBanner(windowScene: windowScene, text: results.nkError.errorDescription, errorCode: results.nkError.errorCode) diff --git a/iOSClient/Main/Collection Common/NCCollectionViewCommon+Search.swift b/iOSClient/Main/Collection Common/NCCollectionViewCommon+Search.swift index 4a836e1c82..d748b07ac6 100644 --- a/iOSClient/Main/Collection Common/NCCollectionViewCommon+Search.swift +++ b/iOSClient/Main/Collection Common/NCCollectionViewCommon+Search.swift @@ -29,7 +29,7 @@ extension NCCollectionViewCommon { setSearchBarLoading(true) networkSearchInProgress = true - if capabilities.serverVersionMajor >= global.nextcloudVersion20 { + if NCBrandOptions.shared.isServerVersion(capabilities, greaterOrEqualTo: .v20) { await unifiedSearch(text: text) } else { await searchLiteral(text: text) diff --git a/iOSClient/Main/Create/Upload Assets/NCUploadAssetsModel.swift b/iOSClient/Main/Create/Upload Assets/NCUploadAssetsModel.swift index 04f9521bd1..2172b5c7dc 100644 --- a/iOSClient/Main/Create/Upload Assets/NCUploadAssetsModel.swift +++ b/iOSClient/Main/Create/Upload Assets/NCUploadAssetsModel.swift @@ -172,7 +172,7 @@ class NCUploadAssetsModel: ObservableObject, NCCreateFormUploadConflictDelegate self.uploadInProgress.toggle() return } - let autoMkcol = capabilities.serverVersionMajor >= NCGlobal.shared.nextcloudVersion33 + let autoMkcol = NCBrandOptions.shared.isServerVersion(capabilities, greaterOrEqualTo: .v33) func createProcessUploads() { if !self.dismissView { diff --git a/iOSClient/Media/NCMedia+Netwoking.swift b/iOSClient/Media/NCMedia+Netwoking.swift index f64ad08fd5..e00c439176 100644 --- a/iOSClient/Media/NCMedia+Netwoking.swift +++ b/iOSClient/Media/NCMedia+Netwoking.swift @@ -18,23 +18,12 @@ extension NCMedia { guard let nkSession = NextcloudKit.shared.nkCommonInstance.nksessions.session(forAccount: account) else { return (account, nil, .urlError) } - let capabilities = await NKCapabilities.shared.getCapabilities(for: account) let files: [NKFile] = [] let href = "/files/" + nkSession.userId + path - let elementDate: String - var lessDateString: String - var greaterDateString: String - - if capabilities.serverVersionMajor >= self.global.nextcloudVersionFuture { - elementDate = "nc:metadata-photos-original_date_time" - lessDateString = String(lessDate.timeIntervalSince1970) - greaterDateString = String(greaterDate.timeIntervalSince1970) - } else { - elementDate = "d:getlastmodified" - lessDateString = lessDate.formatted(using: "yyyy-MM-dd'T'HH:mm:ssZZZZZ") - greaterDateString = greaterDate.formatted(using: "yyyy-MM-dd'T'HH:mm:ssZZZZZ") - } + let elementDate = "d:getlastmodified" + let lessDateString = lessDate.formatted(using: "yyyy-MM-dd'T'HH:mm:ssZZZZZ") + let greaterDateString = greaterDate.formatted(using: "yyyy-MM-dd'T'HH:mm:ssZZZZZ") let httpBodyString = String(format: getRequestBodySearchMedia( createProperties: options.createProperties, diff --git a/iOSClient/Media/NCMediaDataSource.swift b/iOSClient/Media/NCMediaDataSource.swift index ecbc2a9d6c..fee20fe315 100644 --- a/iOSClient/Media/NCMediaDataSource.swift +++ b/iOSClient/Media/NCMediaDataSource.swift @@ -11,17 +11,11 @@ extension NCMedia { guard let tblAccount = await self.database.getTableAccountAsync(predicate: NSPredicate(format: "account == %@", self.session.account)) else { return } - let capabilities = await NKCapabilities.shared.getCapabilities(for: self.session.account) let mediaPredicate = self.imageCache.getMediaPredicate(session: self.session, mediaPath: tblAccount.mediaPath, showOnlyImages: self.showOnlyImages, showOnlyVideos: self.showOnlyVideos) - var sortedByKeyPath: String - if capabilities.serverVersionMajor >= self.global.nextcloudVersionFuture { - sortedByKeyPath = "datePhotosOriginal" - } else { - sortedByKeyPath = "date" - } + let sortedByKeyPath = "date" if let metadatas = await self.database.getMetadatasAsync(predicate: mediaPredicate, sortedByKeyPath: sortedByKeyPath, ascending: false) { self.database.filterAndNormalizeLivePhotos(from: metadatas) { metadatas in @@ -71,7 +65,6 @@ extension NCMedia { return } - let capabilities = await NKCapabilities.shared.getCapabilities(for: session.account) var lessDate = Date.distantFuture var greaterDate = Date.distantPast var visibleCells: [NCMediaCell] = [] @@ -175,18 +168,11 @@ extension NCMedia { showOnlyImages: self.showOnlyImages, showOnlyVideos: self.showOnlyVideos) - var predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [ + let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [ NSPredicate(format: "date >= %@ AND date <= %@ AND mediaSearch == true", greaterDate as NSDate, lessDate as NSDate), mediaPredicate ]) - if capabilities.serverVersionMajor >= self.global.nextcloudVersionFuture { - predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [ - NSPredicate(format: "datePhotosOriginal >= %@ AND datePhotosOriginal <= %@ AND mediaSearch == true", greaterDate as NSDate, lessDate as NSDate), - mediaPredicate - ]) - } - let localMetadatas = await self.database.getMetadatasAsync(predicate: predicate) await MainActor.run { @@ -257,13 +243,7 @@ public class NCMediaDataSource: NSObject { } private func getMetadataFromTableMetadata(_ metadata: tableMetadata) -> Metadata { - let capabilities = NCNetworking.shared.capabilities[metadata.account] ?? NKCapabilities.Capabilities() - let date: Date - if capabilities.serverVersionMajor >= self.global.nextcloudVersionFuture { - date = metadata.datePhotosOriginal as Date - } else { - date = metadata.date as Date - } + let date = metadata.date as Date return Metadata(date: date, etag: metadata.etag, imageSize: CGSize(width: metadata.width, height: metadata.height), diff --git a/iOSClient/Menu/NCContextMenuPlus.swift b/iOSClient/Menu/NCContextMenuPlus.swift index 0782aed87d..19d41fd1d3 100644 --- a/iOSClient/Menu/NCContextMenuPlus.swift +++ b/iOSClient/Menu/NCContextMenuPlus.swift @@ -153,7 +153,7 @@ class NCContextMenuPlus: NSObject { // ------------------------------- RICHDOCUMENT TEXT - if capabilities.serverVersionMajor >= NCGlobal.shared.nextcloudVersion18, + if NCBrandOptions.shared.isServerVersion(capabilities, greaterOrEqualTo: .v18), directory?.richWorkspace == nil, !isDirectoryE2EE, isNetworkReachable { diff --git a/iOSClient/Menu/NCContextMenuProfile.swift b/iOSClient/Menu/NCContextMenuProfile.swift index bc4b64ab47..615b895fff 100644 --- a/iOSClient/Menu/NCContextMenuProfile.swift +++ b/iOSClient/Menu/NCContextMenuProfile.swift @@ -36,7 +36,7 @@ class NCContextMenuProfile: NSObject { func viewMenu() -> UIMenu { let capabilities = NCNetworking.shared.capabilities[session.account] ?? NKCapabilities.Capabilities() - guard capabilities.serverVersionMajor >= NCGlobal.shared.nextcloudVersion23 else { + guard NCBrandOptions.shared.isServerVersion(capabilities, greaterOrEqualTo: .v23) else { return UIMenu() } diff --git a/iOSClient/NCGlobal.swift b/iOSClient/NCGlobal.swift index 2e6ad38aee..81f58bb5f2 100644 --- a/iOSClient/NCGlobal.swift +++ b/iOSClient/NCGlobal.swift @@ -40,27 +40,6 @@ final class NCGlobal: Sendable { let twoFactorNotificatioName = "twofactor_nextcloud_notification" let termsOfServiceName = "terms_of_service" - // Nextcloud version - // - let nextcloudVersion18: Int = 18 - let nextcloudVersion20: Int = 20 - let nextcloudVersion23: Int = 23 - let nextcloudVersion24: Int = 24 - let nextcloudVersion25: Int = 25 - let nextcloudVersion26: Int = 26 - let nextcloudVersion27: Int = 27 - let nextcloudVersion28: Int = 28 - let nextcloudVersion30: Int = 30 - let nextcloudVersion31: Int = 31 - let nextcloudVersion32: Int = 32 - let nextcloudVersion33: Int = 33 - let nextcloudVersionFuture: Int = 99999 - - - // Nextcloud unsupported - // - let nextcloud_unsupported_version: Int = 20 - // Intro selector // let introLogin: Int = 0 @@ -146,7 +125,6 @@ final class NCGlobal: Sendable { // Error // - let errorRequestExplicityCancelled: Int = 15 let errorNotModified: Int = 304 let errorBadRequest: Int = 400 let errorUnauthorized401: Int = 401 diff --git a/iOSClient/Networking/E2EE/NCNetworkingE2EEUpload.swift b/iOSClient/Networking/E2EE/NCNetworkingE2EEUpload.swift index aa64cea15a..f43a4fbcd5 100644 --- a/iOSClient/Networking/E2EE/NCNetworkingE2EEUpload.swift +++ b/iOSClient/Networking/E2EE/NCNetworkingE2EEUpload.swift @@ -195,8 +195,16 @@ class NCNetworkingE2EEUpload: NSObject { if let fileId = self.utility.ocIdToFileId(ocId: ocId) { metadata.fileId = fileId } + if let ownerId = resultsSendFile.ownerId.isNotEmpty { + metadata.ownerId = ownerId + if let ownerDisplayName = await self.database.getOwnerDisplayName(account: metadata.account, ownerId: ownerId) { + metadata.ownerDisplayName = ownerDisplayName + } + } + if let permissions = resultsSendFile.permissions.isNotEmpty { + metadata.permissions = permissions + } metadata.chunk = 0 - metadata.session = "" metadata.sessionTaskIdentifier = 0 metadata.sessionError = "" @@ -238,7 +246,7 @@ class NCNetworkingE2EEUpload: NSObject { tokenBanner: Int?, requestHandle: @escaping (_ request: UploadRequest) -> Void = { _ in }, currentUploadTask: @escaping (_ task: Task<(account: String, file: NKFile?, error: NKError), Never>?) -> Void = { _ in }) - async -> (ocId: String?, etag: String?, date: Date?, error: NKError) { + async -> (ocId: String?, etag: String?, date: Date?, ownerId: String?, permissions: String?, error: NKError) { if metadata.chunk > 0 { let payload = LucidBannerPayload.Update( title: NSLocalizedString("_wait_file_preparation_", comment: ""), @@ -289,7 +297,12 @@ class NCNetworkingE2EEUpload: NSObject { currentUploadTask(task) let results = await task.value - return (results.file?.ocId, results.file?.etag, results.file?.date, results.error) + return (results.file?.ocId, + results.file?.etag, + results.file?.date, + results.file?.ownerId, + results.file?.permissions, + results.error) } else { let payload = LucidBannerPayload.Update( title: NSLocalizedString("_keep_active_for_upload_", comment: ""), @@ -320,7 +333,12 @@ class NCNetworkingE2EEUpload: NSObject { } } - return (results.ocId, results.etag, results.date, results.error) + return (results.ocId, + results.etag, + results.date, + results.ownerId, + results.permissions, + results.error) } } } diff --git a/iOSClient/Networking/NCAutoUpload.swift b/iOSClient/Networking/NCAutoUpload.swift index c99d1085e9..4e4fbe34c1 100644 --- a/iOSClient/Networking/NCAutoUpload.swift +++ b/iOSClient/Networking/NCAutoUpload.swift @@ -87,7 +87,7 @@ class NCAutoUpload: NSObject { assets: [PHAsset], fileNames: [String]) async -> Int { let capabilities = await NKCapabilities.shared.getCapabilities(for: tblAccount.account) - let autoMkcol = capabilities.serverVersionMajor >= NCGlobal.shared.nextcloudVersion33 + let autoMkcol = NCBrandOptions.shared.isServerVersion(capabilities, greaterOrEqualTo: .v33) let session = NCSession.shared.getSession(account: tblAccount.account) let autoUploadServerUrlBase = await self.database.getAccountAutoUploadServerUrlBaseAsync(account: tblAccount.account, urlBase: tblAccount.urlBase, userId: tblAccount.userId) var metadatas: [tableMetadata] = [] @@ -306,7 +306,7 @@ class NCAutoUpload: NSObject { // If server supports auto MKCOL (Nextcloud >= 33), skip manual folder creation. if let capabilities = capabilitiesByAccount[metadata.account] { - let autoMkcol = capabilities.serverVersionMajor >= NCGlobal.shared.nextcloudVersion33 + let autoMkcol = NCBrandOptions.shared.isServerVersion(capabilities, greaterOrEqualTo: .v33) if autoMkcol { continue } diff --git a/iOSClient/Networking/NCNetworking+Download.swift b/iOSClient/Networking/NCNetworking+Download.swift index 1889fe83ed..4d9fe0c51c 100644 --- a/iOSClient/Networking/NCNetworking+Download.swift +++ b/iOSClient/Networking/NCNetworking+Download.swift @@ -21,14 +21,12 @@ extension NCNetworking { etag: String?, date: Date?, length: Int64, - headers: [AnyHashable: Any]?, - afError: AFError?, nkError: NKError ) { - let options = NKRequestOptions(queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue) + let options = NKRequestOptions(queue: nkComm.backgroundQueue) let fileNameLocalPath = utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId, fileName: metadata.fileName, userId: metadata.userId, urlBase: metadata.urlBase) if metadata.status == global.metadataStatusDownloading || metadata.status == global.metadataStatusUploading { - return(metadata.account, metadata.etag, metadata.date as Date, metadata.size, nil, nil, .success) + return(metadata.account, metadata.etag, metadata.date as Date, metadata.size, .success) } let results = await NextcloudKit.shared.downloadAsync(serverUrlFileName: metadata.serverUrlFileName, @@ -76,22 +74,17 @@ extension NCNetworking { progressHandler(progress) } - Task { - await progressQuantizer.clear(serverUrlFileName: metadata.serverUrlFileName) - var error = NKError() + await progressQuantizer.clear(serverUrlFileName: metadata.serverUrlFileName) + let allHeaderFields = results.response?.response?.allHeaderFields + let etag = nkComm.normalizedETag(nkComm.findHeader("oc-etag", allHeaderFields: allHeaderFields)) - if results.afError?.isExplicitlyCancelledError ?? false || (results.afError?.underlyingError as? URLError)?.code.rawValue == -999 { - error = NKError(errorCode: self.global.errorRequestExplicityCancelled, errorDescription: "error request explicity cancelled") - } - - if error == .success { - await downloadSuccess(withMetadata: metadata, etag: results.etag) - } else { - await downloadError(withMetadata: metadata, error: error) - } + if results.nkError == .success { + await downloadSuccess(withMetadata: metadata, etag: etag) + } else { + await downloadError(withMetadata: metadata, error: results.nkError) } - return results + return(metadata.account, etag, metadata.date as Date, metadata.size, results.nkError) } // MARK: - Download file in background @@ -181,7 +174,7 @@ extension NCNetworking { // MARK: - DOWNLOAD ERROR func downloadError(withMetadata metadata: tableMetadata, error: NKError) async { - await NextcloudKit.shared.nkCommonInstance.appendServerErrorAccount(metadata.account, errorCode: error.errorCode) + await nkComm.appendServerErrorAccount(metadata.account, errorCode: error.errorCode) nkLog(error: "Downloaded file: " + metadata.serverUrlFileName + ", result: error \(error.errorCode)") @@ -190,7 +183,7 @@ extension NCNetworking { await NCManageDatabase.shared.deleteLocalFileAsync(id: metadata.ocId) await NCManageDatabase.shared.deleteMetadataAsync(id: metadata.ocId) - } else if error.errorCode == NSURLErrorCancelled || error.errorCode == self.global.errorRequestExplicityCancelled { + } else if error.errorCode == NSURLErrorCancelled { await NCManageDatabase.shared.setMetadataSessionAsync(ocId: metadata.ocId, session: "", sessionTaskIdentifier: 0, @@ -233,7 +226,7 @@ extension NCNetworking { internal func synchronizationDownload(account: String, serverUrl: String, userId: String, urlBase: String, metadatasInDownload: [tableMetadata]?) async { let showHiddenFiles = NCPreferences().getShowHiddenFiles(account: account) - let options = NKRequestOptions(timeout: 300, taskDescription: NCGlobal.shared.taskDescriptionSynchronization, queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue) + let options = NKRequestOptions(timeout: 300, taskDescription: NCGlobal.shared.taskDescriptionSynchronization, queue: nkComm.backgroundQueue) nkLog(tag: self.global.logTagSync, emoji: .start, message: "Start read infinite folder: \(serverUrl)") diff --git a/iOSClient/Networking/NCNetworking+NextcloudKitDelegate.swift b/iOSClient/Networking/NCNetworking+NextcloudKitDelegate.swift index 3b84a934eb..ffc8874b2c 100644 --- a/iOSClient/Networking/NCNetworking+NextcloudKitDelegate.swift +++ b/iOSClient/Networking/NCNetworking+NextcloudKitDelegate.swift @@ -9,7 +9,6 @@ import Alamofire import LucidBanner extension NCNetworking { - #if !EXTENSION func networkReachabilityObserver(_ typeReachability: NKTypeReachability) { if typeReachability == NKTypeReachability.reachableCellular || typeReachability == NKTypeReachability.reachableEthernetOrWiFi { @@ -38,24 +37,16 @@ extension NCNetworking { // MARK: - Download NextcloudKitDelegate - func downloadComplete(fileName: String, - serverUrl: String, - etag: String?, - date: Date?, - dateLastModified: Date?, - length: Int64, - task: URLSessionTask, - error: NKError) { + func downloadComplete(fileName: String, serverUrl: String, allHeaderFields: [AnyHashable: Any]?, task: URLSessionTask, error: NKError) { Task { await progressQuantizer.clear(serverUrlFileName: serverUrl + "/" + fileName) + let etag = nkComm.normalizedETag(nkComm.findHeader("oc-etag", allHeaderFields: allHeaderFields)) + #if EXTENSION_FILE_PROVIDER_EXTENSION await FileProviderData.shared.downloadComplete(fileName: fileName, serverUrl: serverUrl, - etag: etag, - date: date, - dateLastModified: dateLastModified, - length: length, + allHeaderFields: allHeaderFields, task: task, error: error) #else @@ -119,24 +110,24 @@ extension NCNetworking { // MARK: - Upload NextcloudKitDelegate - func uploadComplete(fileName: String, - serverUrl: String, - ocId: String?, - etag: String?, - date: Date?, - size: Int64, - task: URLSessionTask, - error: NKError) { + func uploadComplete(fileName: String, serverUrl: String, allHeaderFields: [AnyHashable: Any]?, task: URLSessionTask, error: NKError) { Task { await progressQuantizer.clear(serverUrlFileName: serverUrl + "/" + fileName) + let ocId = nkComm.findHeader("oc-fileid", allHeaderFields: allHeaderFields) + let etag = nkComm.normalizedETag(nkComm.findHeader("oc-etag", allHeaderFields: allHeaderFields)) + let date = nkComm.findHeader("date", allHeaderFields: allHeaderFields)?.parsedDate(using: "EEE, dd MMM y HH:mm:ss zzz") + let ownerId = nkComm.findHeader("x-nc-ownerid", allHeaderFields: allHeaderFields) + let permissions = nkComm.findHeader("x-nc-permissions", allHeaderFields: allHeaderFields) + #if EXTENSION_FILE_PROVIDER_EXTENSION await FileProviderData.shared.uploadComplete(fileName: fileName, serverUrl: serverUrl, ocId: ocId, etag: etag, date: date, - size: size, + ownerId: ownerId, + permissions: permissions, task: task, error: error) @@ -152,14 +143,18 @@ extension NCNetworking { await self.uploadSuccess(withMetadata: metadata, ocId: ocId, etag: etag, - date: date) + date: date, + ownerId: ownerId, + permissions: permissions) } else { #if !EXTENSION await NCManageDatabase.shared.deleteMetadataAsync(ocId: metadata.ocId) await NCNetworking.shared.metadataTranfersSuccess.append(metadata: metadata, ocId: ocId, date: date, - etag: etag) + etag: etag, + ownerId: ownerId, + permissions: permissions) #endif } } else { diff --git a/iOSClient/Networking/NCNetworking+ServerError.swift b/iOSClient/Networking/NCNetworking+ServerError.swift index 97a0697f4d..e427de3eb1 100644 --- a/iOSClient/Networking/NCNetworking+ServerError.swift +++ b/iOSClient/Networking/NCNetworking+ServerError.swift @@ -8,13 +8,13 @@ import NextcloudKit extension NCNetworking { func noServerErrorAccount(_ account: String) -> Bool { - guard let groupDefaults = UserDefaults(suiteName: NextcloudKit.shared.nkCommonInstance.groupIdentifier) + guard let groupDefaults = UserDefaults(suiteName: nkComm.groupIdentifier) else { return true } - let unavailableArray = groupDefaults.array(forKey: NextcloudKit.shared.nkCommonInstance.groupDefaultsUnavailable) as? [String] ?? [] - let unauthorizedArray = groupDefaults.array(forKey: NextcloudKit.shared.nkCommonInstance.groupDefaultsUnauthorized) as? [String] ?? [] - let tosArray = groupDefaults.array(forKey: NextcloudKit.shared.nkCommonInstance.groupDefaultsToS) as? [String] ?? [] + let unavailableArray = groupDefaults.array(forKey: nkComm.groupDefaultsUnavailable) as? [String] ?? [] + let unauthorizedArray = groupDefaults.array(forKey: nkComm.groupDefaultsUnauthorized) as? [String] ?? [] + let tosArray = groupDefaults.array(forKey: nkComm.groupDefaultsToS) as? [String] ?? [] if unavailableArray.contains(account) || unauthorizedArray.contains(account) || tosArray.contains(account) { return false @@ -24,34 +24,34 @@ extension NCNetworking { } func removeServerErrorAccount(_ account: String) { - guard let groupDefaults = UserDefaults(suiteName: NextcloudKit.shared.nkCommonInstance.groupIdentifier) + guard let groupDefaults = UserDefaults(suiteName: nkComm.groupIdentifier) else { return } - var unauthorizedArray = groupDefaults.array(forKey: NextcloudKit.shared.nkCommonInstance.groupDefaultsUnauthorized) as? [String] ?? [] - var unavailableArray = groupDefaults.array(forKey: NextcloudKit.shared.nkCommonInstance.groupDefaultsUnavailable) as? [String] ?? [] - var tosArray = groupDefaults.array(forKey: NextcloudKit.shared.nkCommonInstance.groupDefaultsToS) as? [String] ?? [] + var unauthorizedArray = groupDefaults.array(forKey: nkComm.groupDefaultsUnauthorized) as? [String] ?? [] + var unavailableArray = groupDefaults.array(forKey: nkComm.groupDefaultsUnavailable) as? [String] ?? [] + var tosArray = groupDefaults.array(forKey: nkComm.groupDefaultsToS) as? [String] ?? [] unauthorizedArray.removeAll { $0 == account } - groupDefaults.set(unauthorizedArray, forKey: NextcloudKit.shared.nkCommonInstance.groupDefaultsUnauthorized) + groupDefaults.set(unauthorizedArray, forKey: nkComm.groupDefaultsUnauthorized) unavailableArray.removeAll { $0 == account } - groupDefaults.set(unavailableArray, forKey: NextcloudKit.shared.nkCommonInstance.groupDefaultsUnavailable) + groupDefaults.set(unavailableArray, forKey: nkComm.groupDefaultsUnavailable) tosArray.removeAll { $0 == account } - groupDefaults.set(tosArray, forKey: NextcloudKit.shared.nkCommonInstance.groupDefaultsToS) + groupDefaults.set(tosArray, forKey: nkComm.groupDefaultsToS) groupDefaults.synchronize() } func checkServerError(account: String, controller: NCMainTabBarController?) async { - guard let groupDefaults = UserDefaults(suiteName: NextcloudKit.shared.nkCommonInstance.groupIdentifier) + guard let groupDefaults = UserDefaults(suiteName: nkComm.groupIdentifier) else { return } - var unavailableArray = groupDefaults.array(forKey: NextcloudKit.shared.nkCommonInstance.groupDefaultsUnavailable) as? [String] ?? [] - let unauthorizedArray = groupDefaults.array(forKey: NextcloudKit.shared.nkCommonInstance.groupDefaultsUnauthorized) as? [String] ?? [] - let tosArray = groupDefaults.array(forKey: NextcloudKit.shared.nkCommonInstance.groupDefaultsToS) as? [String] ?? [] + var unavailableArray = groupDefaults.array(forKey: nkComm.groupDefaultsUnavailable) as? [String] ?? [] + let unauthorizedArray = groupDefaults.array(forKey: nkComm.groupDefaultsUnauthorized) as? [String] ?? [] + let tosArray = groupDefaults.array(forKey: nkComm.groupDefaultsToS) as? [String] ?? [] // Unavailable if unavailableArray.contains(account) { @@ -65,9 +65,9 @@ extension NCNetworking { switch resultsServerStatus.result { case .success(let serverInfo): unavailableArray.removeAll { $0 == account } - groupDefaults.set(unavailableArray, forKey: NextcloudKit.shared.nkCommonInstance.groupDefaultsUnavailable) + groupDefaults.set(unavailableArray, forKey: nkComm.groupDefaultsUnavailable) unavailableArray.removeAll { $0 == account } - groupDefaults.set(unavailableArray, forKey: NextcloudKit.shared.nkCommonInstance.groupDefaultsUnavailable) + groupDefaults.set(unavailableArray, forKey: nkComm.groupDefaultsUnavailable) if serverInfo.maintenance { Task { diff --git a/iOSClient/Networking/NCNetworking+Task.swift b/iOSClient/Networking/NCNetworking+Task.swift index e6256aeca0..f28830b583 100644 --- a/iOSClient/Networking/NCNetworking+Task.swift +++ b/iOSClient/Networking/NCNetworking+Task.swift @@ -98,7 +98,7 @@ extension NCNetworking { } // UPLOAD } else if metadata.session.contains("upload") { - if metadata.session == NextcloudKit.shared.nkCommonInstance.identifierSessionUpload { + if metadata.session == nkComm.identifierSessionUpload { cancelUploadTasks(metadata: metadata) } else { cancelUploadBackgroundTask(metadata: metadata) @@ -125,7 +125,7 @@ extension NCNetworking { } func cancelAllDataTask() { - NextcloudKit.shared.nkCommonInstance.nksessions.forEach { session in + nkComm.nksessions.forEach { session in session.sessionData.session.getTasksWithCompletionHandler { dataTasks, _, _ in dataTasks.forEach { task in task.cancel() @@ -144,7 +144,7 @@ extension NCNetworking { self.global.metadataStatusDownloadError, sessionDownload) Task { - NextcloudKit.shared.nkCommonInstance.nksessions.forEach { session in + nkComm.nksessions.forEach { session in session.sessionData.session.getTasksWithCompletionHandler { _, _, downloadTasks in downloadTasks.forEach { task in if targetTaskId == nil || (task.taskIdentifier == targetTaskId) { @@ -169,7 +169,7 @@ extension NCNetworking { self.global.metadataStatusDownloadError, sessionDownloadBackground) - NextcloudKit.shared.nkCommonInstance.nksessions.forEach { session in + nkComm.nksessions.forEach { session in Task { let tasksBackground = await session.sessionDownloadBackground.tasks @@ -200,7 +200,7 @@ extension NCNetworking { sessionUpload) Task { - NextcloudKit.shared.nkCommonInstance.nksessions.forEach { nkSession in + nkComm.nksessions.forEach { nkSession in nkSession.sessionData.session.getTasksWithCompletionHandler { _, uploadTasks, _ in uploadTasks.forEach { task in if targetTaskId == nil || (account == nkSession.account && targetTaskId == task.taskIdentifier) { @@ -227,7 +227,7 @@ extension NCNetworking { sessionUploadBackgroundWWan, sessionUploadBackgroundExt) - NextcloudKit.shared.nkCommonInstance.nksessions.forEach { nkSession in + nkComm.nksessions.forEach { nkSession in Task { var nkSession = nkSession let tasksBackground = await nkSession.sessionUploadBackground.tasks @@ -269,7 +269,7 @@ extension NCNetworking { // MARK: - func getAllDataTask() async -> [URLSessionDataTask] { - let nkSessions = NextcloudKit.shared.nkCommonInstance.nksessions.all + let nkSessions = nkComm.nksessions.all var taskArray: [URLSessionDataTask] = [] for nkSession in nkSessions { @@ -291,7 +291,7 @@ extension NCNetworking { sessionUpload, self.global.metadataStatusUploading)) { for metadata in metadatas { - guard let nkSession = NextcloudKit.shared.nkCommonInstance.nksessions.session(forAccount: metadata.account) else { + guard let nkSession = nkComm.nksessions.session(forAccount: metadata.account) else { await NCManageDatabase.shared.deleteMetadataAsync(id: metadata.ocId) utilityFileSystem.removeFile(atPath: utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId, userId: metadata.userId, @@ -333,7 +333,7 @@ extension NCNetworking { sessionUploadBackgroundWWan, self.global.metadataStatusUploading)) { for metadata in metadatas { - guard var nkSession = NextcloudKit.shared.nkCommonInstance.nksessions.session(forAccount: metadata.account) else { + guard var nkSession = nkComm.nksessions.session(forAccount: metadata.account) else { await NCManageDatabase.shared.deleteMetadataAsync(id: metadata.ocId) utilityFileSystem.removeFile(atPath: utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId, userId: metadata.userId, @@ -384,7 +384,7 @@ extension NCNetworking { sessionDownload, self.global.metadataStatusDownloadingAllMode)) { for metadata in metadatas { - guard let nkSession = NextcloudKit.shared.nkCommonInstance.nksessions.session(forAccount: metadata.account) else { + guard let nkSession = nkComm.nksessions.session(forAccount: metadata.account) else { await NCManageDatabase.shared.deleteMetadataAsync(id: metadata.ocId) utilityFileSystem.removeFile(atPath: utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId, userId: metadata.userId, @@ -417,7 +417,7 @@ extension NCNetworking { sessionDownloadBackground, self.global.metadataStatusDownloading)) { for metadata in metadatas { - guard let nkSession = NextcloudKit.shared.nkCommonInstance.nksessions.session(forAccount: metadata.account) else { + guard let nkSession = nkComm.nksessions.session(forAccount: metadata.account) else { await NCManageDatabase.shared.deleteMetadataAsync(id: metadata.ocId) utilityFileSystem.removeFile(atPath: utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId, userId: metadata.userId, diff --git a/iOSClient/Networking/NCNetworking+TermsOfService.swift b/iOSClient/Networking/NCNetworking+TermsOfService.swift index add29d2807..5115dc0afa 100644 --- a/iOSClient/Networking/NCNetworking+TermsOfService.swift +++ b/iOSClient/Networking/NCNetworking+TermsOfService.swift @@ -12,14 +12,14 @@ extension NCNetworking { func termsOfService(account: String) async { let capabilities = await NKCapabilities.shared.getCapabilities(for: account) guard capabilities.termsOfService, - let groupDefaults = UserDefaults(suiteName: NextcloudKit.shared.nkCommonInstance.groupIdentifier), + let groupDefaults = UserDefaults(suiteName: nkComm.groupIdentifier), let controller = SceneManager.shared.getControllers().first(where: { $0.account == account }), controller.presentedViewController as? UIHostingController == nil else { return } - var tosArray = groupDefaults.array(forKey: NextcloudKit.shared.nkCommonInstance.groupDefaultsToS) as? [String] ?? [] + var tosArray = groupDefaults.array(forKey: nkComm.groupDefaultsToS) as? [String] ?? [] let options = NKRequestOptions(checkInterceptor: false) let resultsGetToS = await NextcloudKit.shared.getTermsOfServiceAsync(account: account, options: options, taskHandler: { task in @@ -31,7 +31,7 @@ extension NCNetworking { }) guard resultsGetToS.error == .success, let tos = resultsGetToS.tos, !tos.hasUserSigned() else { tosArray.removeAll { $0 == account } - groupDefaults.set(tosArray, forKey: NextcloudKit.shared.nkCommonInstance.groupDefaultsToS) + groupDefaults.set(tosArray, forKey: nkComm.groupDefaultsToS) return } @@ -45,11 +45,11 @@ extension NCNetworking { func signTermsOfService(account: String, termId: Int) async -> NKError? { let capabilities = await NKCapabilities.shared.getCapabilities(for: account) guard capabilities.termsOfService, - let groupDefaults = UserDefaults(suiteName: NextcloudKit.shared.nkCommonInstance.groupIdentifier) + let groupDefaults = UserDefaults(suiteName: nkComm.groupIdentifier) else { return nil } - var tosArray = groupDefaults.array(forKey: NextcloudKit.shared.nkCommonInstance.groupDefaultsToS) as? [String] ?? [] + var tosArray = groupDefaults.array(forKey: nkComm.groupDefaultsToS) as? [String] ?? [] let options = NKRequestOptions(checkInterceptor: false) let resultsSignToS = await NextcloudKit.shared.signTermsOfServiceAsync(termId: "\(termId)", account: account, options: options) { task in @@ -62,7 +62,7 @@ extension NCNetworking { } if resultsSignToS.error == .success { tosArray.removeAll { $0 == account } - groupDefaults.set(tosArray, forKey: NextcloudKit.shared.nkCommonInstance.groupDefaultsToS) + groupDefaults.set(tosArray, forKey: nkComm.groupDefaultsToS) } return resultsSignToS.error diff --git a/iOSClient/Networking/NCNetworking+TransferDelegate.swift b/iOSClient/Networking/NCNetworking+TransferDelegate.swift index 82362b7324..9e3ee32fc5 100644 --- a/iOSClient/Networking/NCNetworking+TransferDelegate.swift +++ b/iOSClient/Networking/NCNetworking+TransferDelegate.swift @@ -261,7 +261,7 @@ extension NCNetworking: NCTransferDelegate { return } - let download = await NextcloudKit.shared.downloadAsync( + let results = await NextcloudKit.shared.downloadAsync( serverUrlFileName: metadata.serverUrlFileName, fileNameLocalPath: fileNameLocalPath, account: account) { _ in @@ -281,14 +281,17 @@ extension NCNetworking: NCTransferDelegate { } + let allHeaderFields = results.response?.response?.allHeaderFields + let etag = nkComm.findHeader("oc-etag", allHeaderFields: allHeaderFields) + await NCManageDatabase.shared.setMetadataSessionAsync(ocId: metadata.ocId, session: "", sessionTaskIdentifier: 0, sessionError: "", status: self.global.metadataStatusNormal, - etag: download.etag) + etag: etag) - if download.nkError == .success { + if results.nkError == .success { await NCManageDatabase.shared.addLocalFilesAsync(metadatas: [metadata]) if let vc = await NCViewer().getViewerController(metadata: metadata, delegate: viewController) { viewController.navigationController?.pushViewController(vc, animated: true) diff --git a/iOSClient/Networking/NCNetworking+Upload.swift b/iOSClient/Networking/NCNetworking+Upload.swift index 50ba5fb80a..3bd13a4c56 100644 --- a/iOSClient/Networking/NCNetworking+Upload.swift +++ b/iOSClient/Networking/NCNetworking+Upload.swift @@ -24,10 +24,10 @@ extension NCNetworking { ocId: String?, etag: String?, date: Date?, - size: Int64, - response: AFDataResponse?, + ownerId: String?, + permissions: String?, error: NKError) { - let options = NKRequestOptions(customHeader: customHeaders, queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue) + let options = NKRequestOptions(customHeader: customHeaders, queue: nkComm.backgroundQueue) let results = await NextcloudKit.shared.uploadAsync(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, dateCreationFile: creationDate, @@ -48,7 +48,21 @@ extension NCNetworking { progressHandler(progress.completedUnitCount, progress.totalUnitCount, progress.fractionCompleted) } - return results + let allHeaderFields = results.response?.response?.allHeaderFields + + let ocId = nkComm.findHeader("oc-fileid", allHeaderFields: allHeaderFields) + let etag = nkComm.normalizedETag(nkComm.findHeader("oc-etag", allHeaderFields: allHeaderFields)) + let date = nkComm.findHeader("date", allHeaderFields: allHeaderFields)?.parsedDate(using: "EEE, dd MMM y HH:mm:ss zzz") + let ownerId = nkComm.findHeader("x-nc-ownerid", allHeaderFields: allHeaderFields) + let permissions = nkComm.findHeader("x-nc-permissions", allHeaderFields: allHeaderFields) + + return (results.account, + ocId, + etag, + date, + ownerId, + permissions, + results.error) } // MARK: - Upload chunk file in foreground @@ -72,7 +86,7 @@ extension NCNetworking { if networkReachability == NKTypeReachability.reachableEthernetOrWiFi { chunkSize = self.global.chunkSizeMBEthernetOrWiFi } - let options = NKRequestOptions(customHeader: customHeaders, queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue) + let options = NKRequestOptions(customHeader: customHeaders, queue: nkComm.backgroundQueue) var backupError = NKError() var backupFile: NKFile? @@ -148,7 +162,12 @@ extension NCNetworking { directory: directory) if performPostProcessing, let file { - await uploadSuccess(withMetadata: metadata, ocId: file.ocId, etag: file.etag, date: file.date) + await uploadSuccess(withMetadata: metadata, + ocId: file.ocId, + etag: file.etag, + date: file.date, + ownerId: file.ownerId, + permissions: file.permissions) } backupFile = file @@ -232,7 +251,9 @@ extension NCNetworking { func uploadSuccess(withMetadata metadata: tableMetadata, ocId: String, etag: String?, - date: Date?) async { + date: Date?, + ownerId: String? = nil, + permissions: String? = nil) async { nkLog(success: "Uploaded file: " + metadata.serverUrlFileName) metadata.uploadDate = (date as? NSDate) ?? NSDate() @@ -244,6 +265,17 @@ extension NCNetworking { metadata.fileId = fileId } + if let ownerId = ownerId.isNotEmpty { + metadata.ownerId = ownerId + if let ownerDisplayName = await NCManageDatabase.shared.getOwnerDisplayName(account: metadata.account, ownerId: ownerId) { + metadata.ownerDisplayName = ownerDisplayName + } + } + + if let permissions = permissions.isNotEmpty { + metadata.permissions = permissions + } + metadata.session = "" metadata.sessionError = "" metadata.sessionTaskIdentifier = 0 @@ -283,11 +315,11 @@ extension NCNetworking { // MARK: - UPLOAD ERROR func uploadError(withMetadata metadata: tableMetadata, error: NKError) async { - await NextcloudKit.shared.nkCommonInstance.appendServerErrorAccount(metadata.account, errorCode: error.errorCode) + await nkComm.appendServerErrorAccount(metadata.account, errorCode: error.errorCode) nkLog(error: "Upload file: " + metadata.serverUrlFileName + ", result: error \(error.errorCode)") - if error.errorCode == NSURLErrorCancelled || error.errorCode == self.global.errorRequestExplicityCancelled { + if error.errorCode == NSURLErrorCancelled { await uploadCancelFile(metadata: metadata) } else if (error.errorCode == self.global.errorBadRequest || error.errorCode == self.global.errorUnsupportedMediaType) && error.errorDescription.localizedCaseInsensitiveContains("virus") { await uploadCancelFile(metadata: metadata) @@ -504,4 +536,5 @@ extension NCNetworking { return (localFile: localFile, livePhoto: livePhoto, autoUpload: autoUpload) } + } diff --git a/iOSClient/Networking/NCNetworking+WebDAV.swift b/iOSClient/Networking/NCNetworking+WebDAV.swift index 3be5c033db..a495bb4f13 100644 --- a/iOSClient/Networking/NCNetworking+WebDAV.swift +++ b/iOSClient/Networking/NCNetworking+WebDAV.swift @@ -91,7 +91,7 @@ extension NCNetworking { } func fileExists(serverUrlFileName: String, account: String) async -> NKError { - let requestBody = NKDataFileXML(nkCommonInstance: NextcloudKit.shared.nkCommonInstance).getRequestBodyFileExists().data(using: .utf8) + let requestBody = NKDataFileXML(nkCommonInstance: nkComm).getRequestBodyFileExists().data(using: .utf8) let results = await NextcloudKit.shared.readFileOrFolderAsync(serverUrlFileName: serverUrlFileName, depth: "0", diff --git a/iOSClient/Networking/NCNetworking.swift b/iOSClient/Networking/NCNetworking.swift index fe827a1a34..516b0e64e1 100644 --- a/iOSClient/Networking/NCNetworking.swift +++ b/iOSClient/Networking/NCNetworking.swift @@ -57,6 +57,7 @@ class NCNetworking: @unchecked Sendable, NextcloudKitDelegate { let utilityFileSystem = NCUtilityFileSystem() let global = NCGlobal.shared let backgroundSession = NKBackground(nkCommonInstance: NextcloudKit.shared.nkCommonInstance) + let nkComm = NextcloudKit.shared.nkCommonInstance var lastReachability: Bool = true var networkReachability: NKTypeReachability? diff --git a/iOSClient/Networking/NCService.swift b/iOSClient/Networking/NCService.swift index 9c79b399d4..f6715693d3 100644 --- a/iOSClient/Networking/NCService.swift +++ b/iOSClient/Networking/NCService.swift @@ -69,7 +69,7 @@ class NCService: NSObject { systemImage: "xmark.icloud.fill", imageAnimation: .none) return false - } else if serverInfo.versionMajor <= NCGlobal.shared.nextcloud_unsupported_version { + } else if NextcloudVersion(serverInfo.versionMajor) <= .v20 { await showWarningBanner(windowScene: windowScene, subtitle: "_warning_unsupported_", systemImage: "xmark.icloud.fill", diff --git a/iOSClient/Utility/NCLivePhoto.swift b/iOSClient/Utility/NCLivePhoto.swift index b53706a253..6849887f53 100644 --- a/iOSClient/Utility/NCLivePhoto.swift +++ b/iOSClient/Utility/NCLivePhoto.swift @@ -723,7 +723,7 @@ extension NCLivePhoto { Task { let capabilities = await NKCapabilities.shared.getCapabilities(for: metadata1.account) - guard capabilities.serverVersionMajor >= NCGlobal.shared.nextcloudVersion28 else { + guard NCBrandOptions.shared.isServerVersion(capabilities, greaterOrEqualTo: .v28) else { return } diff --git a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift index 742d90fddf..7304ddafbb 100644 --- a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift +++ b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift @@ -373,13 +373,17 @@ extension NCPlayerToolBar: NCSelectDelegate { banner?.update(payload: LucidBannerPayload.Update(progress: Double(progress.fractionCompleted)), for: token) } - }) { _, etag, _, _, _, _, error in + }) { _, response, error in Task { if let banner { banner.dismiss() } let ocId = metadata.ocId + let allHeaderFields = response?.response?.allHeaderFields + let nkComm = NextcloudKit.shared.nkCommonInstance + let etag = nkComm.normalizedETag(nkComm.findHeader("oc-etag", allHeaderFields: allHeaderFields)) + await self.database.setMetadataSessionAsync(ocId: ocId, session: "", sessionTaskIdentifier: 0, diff --git a/iOSClient/Viewer/NCViewerRichdocument/NCViewerRichDocument.swift b/iOSClient/Viewer/NCViewerRichdocument/NCViewerRichDocument.swift index d26410c757..388c528524 100644 --- a/iOSClient/Viewer/NCViewerRichdocument/NCViewerRichDocument.swift +++ b/iOSClient/Viewer/NCViewerRichdocument/NCViewerRichDocument.swift @@ -220,10 +220,16 @@ class NCViewerRichDocument: UIViewController, WKNavigationDelegate, WKScriptMess status: self.global.metadataStatusDownloading) } }, progressHandler: { _ in - }, completionHandler: { account, etag, _, _, headers, _, error in + }, completionHandler: { account, response, error in NCActivityIndicator.shared.stop() + let allHeaderFields = response?.response?.allHeaderFields + Task { + let nkComm = NextcloudKit.shared.nkCommonInstance let ocId = self.metadata.ocId + let allHeaderFields = response?.response?.allHeaderFields + let etag = nkComm.normalizedETag(nkComm.findHeader("oc-etag", allHeaderFields: allHeaderFields)) + await self.database.setMetadataSessionAsync(ocId: ocId, session: "", sessionTaskIdentifier: 0, @@ -233,8 +239,15 @@ class NCViewerRichDocument: UIViewController, WKNavigationDelegate, WKScriptMess } if error == .success && account == self.metadata.account { var item = fileNameLocalPath + if let disposition = NextcloudKit.shared.nkCommonInstance.findHeader("Content-Disposition", allHeaderFields: allHeaderFields), + let filenameContentDisposition = self.filenameFromContentDisposition(disposition) { + fileName = filenameContentDisposition + item = self.utilityFileSystem.createServerUrl(serverUrl: self.utilityFileSystem.directoryUserData, fileName: fileName) + _ = self.utilityFileSystem.moveFile(atPath: fileNameLocalPath, toPath: item) + } - if let headers { + /* + if let allHeaderFields { if let disposition = headers["Content-Disposition"] as? String, let filenameContentDisposition = self.filenameFromContentDisposition(disposition) { fileName = filenameContentDisposition @@ -242,6 +255,7 @@ class NCViewerRichDocument: UIViewController, WKNavigationDelegate, WKScriptMess _ = self.utilityFileSystem.moveFile(atPath: fileNameLocalPath, toPath: item) } } + */ if type == "print" { let pic = UIPrintInteractionController.shared