diff --git a/Brand/Database.swift b/Brand/Database.swift index 3a2f4ed488..81e9028b7f 100644 --- a/Brand/Database.swift +++ b/Brand/Database.swift @@ -26,4 +26,4 @@ import Foundation // Database Realm // let databaseName = "nextcloud.realm" -let databaseSchemaVersion: UInt64 = 348 +let databaseSchemaVersion: UInt64 = 354 diff --git a/Brand/NCBrand.swift b/Brand/NCBrand.swift index 7277e85951..cfeef5ca6d 100755 --- a/Brand/NCBrand.swift +++ b/Brand/NCBrand.swift @@ -52,7 +52,7 @@ let userAgent: String = { var folderDefaultAutoUpload: String = "Photos" // Capabilities Group - var capabilitiesGroups: String = "group.it.twsweb.Crypto-Cloud" + var capabilitiesGroup: String = "group.it.twsweb.Crypto-Cloud" var capabilitiesGroupApps: String = "group.com.nextcloud.apps" // BRAND ONLY @@ -257,6 +257,7 @@ class NCBrandColor: NSObject { private func stepCalc(steps: Int, color1: CGColor, color2: CGColor) -> [CGFloat] { var step = [CGFloat](repeating: 0, count: 3) + step[0] = (color2.components![0] - color1.components![0]) / CGFloat(steps) step[1] = (color2.components![1] - color1.components![1]) / CGFloat(steps) step[2] = (color2.components![2] - color1.components![2]) / CGFloat(steps) @@ -266,8 +267,8 @@ class NCBrandColor: NSObject { private func mixPalette(steps: Int, color1: CGColor, color2: CGColor) -> [CGColor] { var palette = [color1] let step = stepCalc(steps: steps, color1: color1, color2: color2) - let c1Components = color1.components! + for i in 1 ..< steps { let r = c1Components[0] + step[0] * CGFloat(i) let g = c1Components[1] + step[1] * CGFloat(i) @@ -292,6 +293,7 @@ class NCBrandColor: NSObject { let palette1 = mixPalette(steps: steps, color1: red, color2: yellow) let palette2 = mixPalette(steps: steps, color1: yellow, color2: blue) let palette3 = mixPalette(steps: steps, color1: blue, color2: red) + return palette1 + palette2 + palette3 } } diff --git a/Cartfile.resolved b/Cartfile.resolved index 955d19125d..a19f7cdae1 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,2 +1,2 @@ -binary "https://code.videolan.org/videolan/VLCKit/raw/master/Packaging/MobileVLCKit.json" "3.5.1" +binary "https://code.videolan.org/videolan/VLCKit/raw/master/Packaging/MobileVLCKit.json" "3.6.0" github "marinofaggiana/TOPasscodeViewController" "ed795637acd2b1ef154e011a04ebab4686d0523c" diff --git a/File Provider Extension/FileProviderData.swift b/File Provider Extension/FileProviderData.swift index eb03a93c06..bc271a4649 100644 --- a/File Provider Extension/FileProviderData.swift +++ b/File Provider Extension/FileProviderData.swift @@ -40,36 +40,30 @@ class fileProviderData: NSObject { var accountUrlBase = "" var homeServerUrl = "" - // Max item for page - let itemForPage = 100 - - // Anchor - var currentAnchor: UInt64 = 0 - - // Rank favorite var listFavoriteIdentifierRank: [String: NSNumber] = [:] - // Item for signalEnumerator var fileProviderSignalDeleteContainerItemIdentifier: [NSFileProviderItemIdentifier: NSFileProviderItemIdentifier] = [:] var fileProviderSignalUpdateContainerItem: [NSFileProviderItemIdentifier: FileProviderItem] = [:] var fileProviderSignalDeleteWorkingSetItemIdentifier: [NSFileProviderItemIdentifier: NSFileProviderItemIdentifier] = [:] var fileProviderSignalUpdateWorkingSetItem: [NSFileProviderItemIdentifier: FileProviderItem] = [:] - // Error enum FileProviderError: Error { case downloadError case uploadError } + enum TypeSignal: String { + case delete + case update + case workingSet + } + // MARK: - func setupAccount(domain: NSFileProviderDomain?, providerExtension: NSFileProviderExtension) -> tableAccount? { - self.domain = domain - if domain != nil { - if let fileProviderManager = NSFileProviderManager(for: domain!) { - self.fileProviderManager = fileProviderManager - } + if let domain, let fileProviderManager = NSFileProviderManager(for: domain) { + self.fileProviderManager = fileProviderManager } // LOG @@ -81,9 +75,7 @@ class fileProviderData: NSObject { // NO DOMAIN -> Set default account if domain == nil { - guard let activeAccount = NCManageDatabase.shared.getActiveAccount() else { return nil } - account = activeAccount.account user = activeAccount.user userId = activeAccount.userId @@ -91,8 +83,8 @@ class fileProviderData: NSObject { homeServerUrl = utilityFileSystem.getHomeServer(urlBase: activeAccount.urlBase, userId: activeAccount.userId) NCManageDatabase.shared.setCapabilities(account: account) - - NextcloudKit.shared.setup(account: activeAccount.account, user: activeAccount.user, userId: activeAccount.userId, password: NCKeychain().getPassword(account: activeAccount.account), urlBase: activeAccount.urlBase, userAgent: userAgent, nextcloudVersion: NCGlobal.shared.capabilityServerVersionMajor, delegate: NCNetworking.shared) + NextcloudKit.shared.setup(account: activeAccount.account, user: activeAccount.user, userId: activeAccount.userId, password: NCKeychain().getPassword(account: activeAccount.account), urlBase: activeAccount.urlBase, userAgent: userAgent, nextcloudVersion: NCGlobal.shared.capabilityServerVersionMajor, groupIdentifier: NCBrandOptions.shared.capabilitiesGroup, delegate: NCNetworking.shared) + NCNetworking.shared.delegate = providerExtension as? NCNetworkingDelegate return tableAccount.init(value: activeAccount) } @@ -106,7 +98,6 @@ class fileProviderData: NSObject { guard let host = url.host else { continue } let accountDomain = activeAccount.userId + " (" + host + ")" if accountDomain == domain!.identifier.rawValue { - account = activeAccount.account user = activeAccount.user userId = activeAccount.userId @@ -115,84 +106,38 @@ class fileProviderData: NSObject { NCManageDatabase.shared.setCapabilities(account: account) - NextcloudKit.shared.setup(account: activeAccount.account, user: activeAccount.user, userId: activeAccount.userId, password: NCKeychain().getPassword(account: activeAccount.account), urlBase: activeAccount.urlBase, userAgent: userAgent, nextcloudVersion: NCGlobal.shared.capabilityServerVersionMajor, delegate: NCNetworking.shared) + NextcloudKit.shared.setup(account: activeAccount.account, user: activeAccount.user, userId: activeAccount.userId, password: NCKeychain().getPassword(account: activeAccount.account), urlBase: activeAccount.urlBase, userAgent: userAgent, nextcloudVersion: NCGlobal.shared.capabilityServerVersionMajor, groupIdentifier: NCBrandOptions.shared.capabilitiesGroup, delegate: NCNetworking.shared) + NCNetworking.shared.delegate = providerExtension as? NCNetworkingDelegate return tableAccount.init(value: activeAccount) } } - return nil } // MARK: - @discardableResult - func signalEnumerator(ocId: String, delete: Bool = false, update: Bool = false) -> FileProviderItem? { - - guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { return nil } - - guard let parentItemIdentifier = fileProviderUtility().getParentItemIdentifier(metadata: metadata) else { return nil } - + func signalEnumerator(ocId: String, type: TypeSignal) -> FileProviderItem? { + guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId), + let parentItemIdentifier = fileProviderUtility().getParentItemIdentifier(metadata: metadata) else { return nil } let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier) - if delete { + if type == .delete { fileProviderData.shared.fileProviderSignalDeleteContainerItemIdentifier[item.itemIdentifier] = item.itemIdentifier fileProviderData.shared.fileProviderSignalDeleteWorkingSetItemIdentifier[item.itemIdentifier] = item.itemIdentifier } - - if update { + if type == .update { fileProviderData.shared.fileProviderSignalUpdateContainerItem[item.itemIdentifier] = item fileProviderData.shared.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item } - - if !update && !delete { + if type == .workingSet { fileProviderData.shared.fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item } - - if update || delete { - currentAnchor += 1 + if type == .delete || type == .update { fileProviderManager.signalEnumerator(for: parentItemIdentifier) { _ in } } - fileProviderManager.signalEnumerator(for: .workingSet) { _ in } - return item } - - /* - func updateFavoriteForWorkingSet() { - - var updateWorkingSet = false - let oldListFavoriteIdentifierRank = listFavoriteIdentifierRank - listFavoriteIdentifierRank = NCManageDatabase.shared.getTableMetadatasDirectoryFavoriteIdentifierRank(account: account) - - // (ADD) - for (identifier, _) in listFavoriteIdentifierRank { - - guard let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "ocId == %@", identifier)) else { continue } - guard let parentItemIdentifier = fileProviderUtility.sharedInstance.getParentItemIdentifier(metadata: metadata, homeServerUrl: homeServerUrl) else { continue } - let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier) - - fileProviderSignalUpdateWorkingSetItem[item.itemIdentifier] = item - updateWorkingSet = true - } - - // (REMOVE) - for (identifier, _) in oldListFavoriteIdentifierRank { - - if !listFavoriteIdentifierRank.keys.contains(identifier) { - - guard let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "ocId == %@", identifier)) else { continue } - let itemIdentifier = fileProviderUtility.sharedInstance.getItemIdentifier(metadata: metadata) - - fileProviderSignalDeleteWorkingSetItemIdentifier[itemIdentifier] = itemIdentifier - updateWorkingSet = true - } - } - - if updateWorkingSet { - signalEnumerator(for: [.workingSet]) - } - } - */ } diff --git a/File Provider Extension/FileProviderDomain.swift b/File Provider Extension/FileProviderDomain.swift index 4810416ddb..17c03bccb0 100644 --- a/File Provider Extension/FileProviderDomain.swift +++ b/File Provider Extension/FileProviderDomain.swift @@ -24,11 +24,8 @@ import UIKit class FileProviderDomain: NSObject { - func registerDomains() { - NSFileProviderManager.getDomainsWithCompletionHandler { fileProviderDomain, error in - var domains: [String] = [] let pathRelativeToDocumentStorage = NSFileProviderManager.default.documentStorageURL.absoluteString let accounts = NCManageDatabase.shared.getAllAccount() @@ -50,10 +47,10 @@ class FileProviderDomain: NSObject { } } if !domainFound { - let domainRawValue = NSFileProviderDomain(identifier: NSFileProviderDomainIdentifier(rawValue: domain), displayName: domain, pathRelativeToDocumentStorage: pathRelativeToDocumentStorage) - NSFileProviderManager.remove(domainRawValue, completionHandler: { error in - if error != nil { - print("Error domain: \(domainRawValue) error: \(String(describing: error))") + let fileProviderDomain = NSFileProviderDomain(identifier: NSFileProviderDomainIdentifier(rawValue: domain), displayName: domain, pathRelativeToDocumentStorage: pathRelativeToDocumentStorage) + NSFileProviderManager.remove(fileProviderDomain, completionHandler: { error in + if let error { + print("Error domain: \(fileProviderDomain) error: \(String(describing: error))") } }) } @@ -72,19 +69,14 @@ class FileProviderDomain: NSObject { } } if !domainFound { - let domainRawValue = NSFileProviderDomain(identifier: NSFileProviderDomainIdentifier(rawValue: accountDomain), displayName: accountDomain, pathRelativeToDocumentStorage: pathRelativeToDocumentStorage) - NSFileProviderManager.add(domainRawValue, completionHandler: { error in - if error != nil { - print("Error domain: \(domainRawValue) error: \(String(describing: error))") + let fileProviderDomain = NSFileProviderDomain(identifier: NSFileProviderDomainIdentifier(rawValue: accountDomain), displayName: accountDomain, pathRelativeToDocumentStorage: pathRelativeToDocumentStorage) + NSFileProviderManager.add(fileProviderDomain, completionHandler: { error in + if let error { + print("Error domain: \(fileProviderDomain) error: \(String(describing: error))") } }) } } } } - - func removeAllDomains() { - - NSFileProviderManager.removeAllDomains { _ in } - } } diff --git a/File Provider Extension/FileProviderEnumerator.swift b/File Provider Extension/FileProviderEnumerator.swift index 08179e2aa0..1f2058e681 100644 --- a/File Provider Extension/FileProviderEnumerator.swift +++ b/File Provider Extension/FileProviderEnumerator.swift @@ -23,87 +23,93 @@ import UIKit import FileProvider +import RealmSwift import NextcloudKit class FileProviderEnumerator: NSObject, NSFileProviderEnumerator { var enumeratedItemIdentifier: NSFileProviderItemIdentifier var serverUrl: String? - let fpUtility = fileProviderUtility() + let providerUtility = fileProviderUtility() + var recordsPerPage: Int = 20 + var anchor: UInt64 = 0 init(enumeratedItemIdentifier: NSFileProviderItemIdentifier) { self.enumeratedItemIdentifier = enumeratedItemIdentifier - - // Select ServerUrl if enumeratedItemIdentifier == .rootContainer { serverUrl = fileProviderData.shared.homeServerUrl } else { - let metadata = fpUtility.getTableMetadataFromItemIdentifier(enumeratedItemIdentifier) - if metadata != nil { - if let directorySource = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata!.account, metadata!.serverUrl)) { - serverUrl = directorySource.serverUrl + "/" + metadata!.fileName - } + if let metadata = providerUtility.getTableMetadataFromItemIdentifier(enumeratedItemIdentifier), + let directorySource = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, metadata.serverUrl)) { + serverUrl = directorySource.serverUrl + "/" + metadata.fileName + } } - super.init() } - func invalidate() { - - } + func invalidate() { } func enumerateItems(for observer: NSFileProviderEnumerationObserver, startingAt page: NSFileProviderPage) { var items: [NSFileProviderItemProtocol] = [] - - /*** WorkingSet ***/ + /// WorkingSet if enumeratedItemIdentifier == .workingSet { var itemIdentifierMetadata: [NSFileProviderItemIdentifier: tableMetadata] = [:] - - // ***** Tags ***** + /// Tags let tags = NCManageDatabase.shared.getTags(predicate: NSPredicate(format: "account == %@", fileProviderData.shared.account)) for tag in tags { - guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(tag.ocId) else { continue } - fpUtility.createocIdentifierOnFileSystem(metadata: metadata) - itemIdentifierMetadata[fpUtility.getItemIdentifier(metadata: metadata)] = metadata + itemIdentifierMetadata[providerUtility.getItemIdentifier(metadata: metadata)] = metadata } - - // ***** Favorite ***** + /// Favorite fileProviderData.shared.listFavoriteIdentifierRank = NCManageDatabase.shared.getTableMetadatasDirectoryFavoriteIdentifierRank(account: fileProviderData.shared.account) for (identifier, _) in fileProviderData.shared.listFavoriteIdentifierRank { - guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(identifier) else { continue } - itemIdentifierMetadata[fpUtility.getItemIdentifier(metadata: metadata)] = metadata + itemIdentifierMetadata[providerUtility.getItemIdentifier(metadata: metadata)] = metadata } - - // create items + /// Create items for (_, metadata) in itemIdentifierMetadata { - let parentItemIdentifier = fpUtility.getParentItemIdentifier(metadata: metadata) - if parentItemIdentifier != nil { - let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier!) + if let parentItemIdentifier = providerUtility.getParentItemIdentifier(metadata: metadata) { + let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier) items.append(item) } } - observer.didEnumerate(items) observer.finishEnumerating(upTo: nil) - } else { - - /*** ServerUrl ***/ - + /// ServerUrl guard let serverUrl = serverUrl else { observer.finishEnumerating(upTo: nil) return } + var pageNumber = 1 + if let stringPage = String(data: page.rawValue, encoding: .utf8), + let intPage = Int(stringPage) { + pageNumber = intPage + } - if page == NSFileProviderPage.initialPageSortedByDate as NSFileProviderPage || page == NSFileProviderPage.initialPageSortedByName as NSFileProviderPage { - self.readFileOrFolder(serverUrl: serverUrl) { metadatas in - self.completeObserver(observer, numPage: 1, metadatas: metadatas) + self.fetchItemsForPage(serverUrl: serverUrl, pageNumber: pageNumber) { metadatas in + if let metadatas { + for metadata in metadatas { + if metadata.e2eEncrypted || (!metadata.session.isEmpty && metadata.session != NCNetworking.shared.sessionUploadBackgroundExtension) { + continue + } + if let parentItemIdentifier = self.providerUtility.getParentItemIdentifier(metadata: metadata) { + let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier) + items.append(item) + } + } + } + + observer.didEnumerate(items) + + if let metadatas, + metadatas.count == self.recordsPerPage { + pageNumber += 1 + let providerPage = NSFileProviderPage("\(pageNumber)".data(using: .utf8)!) + observer.finishEnumerating(upTo: providerPage) + } else { + observer.finishEnumerating(upTo: nil) } - } else { - let numPage = Int(String(data: page.rawValue, encoding: .utf8)!)! - completeObserver(observer, numPage: numPage, metadatas: nil) } } } @@ -111,7 +117,6 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator { func enumerateChanges(for observer: NSFileProviderChangeObserver, from anchor: NSFileProviderSyncAnchor) { var itemsDelete: [NSFileProviderItemIdentifier] = [] var itemsUpdate: [FileProviderItem] = [] - // Report the deleted items // if self.enumeratedItemIdentifier == .workingSet { @@ -125,7 +130,6 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator { } fileProviderData.shared.fileProviderSignalDeleteContainerItemIdentifier.removeAll() } - // Report the updated items // if self.enumeratedItemIdentifier == .workingSet { @@ -143,64 +147,36 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator { observer.didDeleteItems(withIdentifiers: itemsDelete) observer.didUpdate(itemsUpdate) - let data = "\(fileProviderData.shared.currentAnchor)".data(using: .utf8) + let data = "\(self.anchor)".data(using: .utf8) observer.finishEnumeratingChanges(upTo: NSFileProviderSyncAnchor(data!), moreComing: false) } func currentSyncAnchor(completionHandler: @escaping (NSFileProviderSyncAnchor?) -> Void) { - let data = "\(fileProviderData.shared.currentAnchor)".data(using: .utf8) + let data = "\(self.anchor)".data(using: .utf8) completionHandler(NSFileProviderSyncAnchor(data!)) } - // -------------------------------------------------------------------------------------------- - // MARK: - User Function + Network - // -------------------------------------------------------------------------------------------- - - func completeObserver(_ observer: NSFileProviderEnumerationObserver, numPage: Int, metadatas: [tableMetadata]?) { - var numPage = numPage - var items: [NSFileProviderItemProtocol] = [] - - if metadatas != nil { - for metadata in metadatas! { - if metadata.e2eEncrypted || (!metadata.session.isEmpty && metadata.session != NCNetworking.shared.sessionUploadBackgroundExtension) { continue } - fpUtility.createocIdentifierOnFileSystem(metadata: metadata) - let parentItemIdentifier = fpUtility.getParentItemIdentifier(metadata: metadata) - if parentItemIdentifier != nil { - let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier!) - items.append(item) - } - } - observer.didEnumerate(items) - } - - if items.count == fileProviderData.shared.itemForPage { - numPage += 1 - let providerPage = NSFileProviderPage("\(numPage)".data(using: .utf8)!) - observer.finishEnumerating(upTo: providerPage) - } else { - observer.finishEnumerating(upTo: nil) - } - } + func fetchItemsForPage(serverUrl: String, pageNumber: Int, completionHandler: @escaping (_ metadatas: Results?) -> Void) { + let predicate = NSPredicate(format: "account == %@ AND serverUrl == %@", fileProviderData.shared.account, serverUrl) - func readFileOrFolder(serverUrl: String, completionHandler: @escaping (_ metadatas: [tableMetadata]?) -> Void) { - NextcloudKit.shared.readFileOrFolder(serverUrlFileName: serverUrl, depth: "1", showHiddenFiles: NCKeychain().showHiddenFiles) { account, files, _, error in - if error == .success { - DispatchQueue.global().async { + if pageNumber == 1 { + NextcloudKit.shared.readFileOrFolder(serverUrlFileName: serverUrl, depth: "1", showHiddenFiles: NCKeychain().showHiddenFiles) { _, files, _, error in + if error == .success { NCManageDatabase.shared.convertFilesToMetadatas(files, useFirstAsMetadataFolder: true) { metadataFolder, metadatas in /// FOLDER NCManageDatabase.shared.addMetadata(metadataFolder) NCManageDatabase.shared.addDirectory(e2eEncrypted: metadataFolder.e2eEncrypted, favorite: metadataFolder.favorite, ocId: metadataFolder.ocId, fileId: metadataFolder.fileId, etag: metadataFolder.etag, permissions: metadataFolder.permissions, richWorkspace: metadataFolder.richWorkspace, serverUrl: serverUrl, account: metadataFolder.account) /// FILES - let predicate = NSPredicate(format: "account == %@ AND serverUrl == %@ AND status == %d", account, serverUrl, NCGlobal.shared.metadataStatusNormal) - NCManageDatabase.shared.updateMetadatas(metadatas, predicate: predicate) - let metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", fileProviderData.shared.account, serverUrl), sorted: "fileName", ascending: true) - completionHandler(metadatas) + NCManageDatabase.shared.deleteMetadata(predicate: predicate) + NCManageDatabase.shared.addMetadatas(metadatas) } } - } else { - let metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", fileProviderData.shared.account, serverUrl), sorted: "fileName", ascending: true) - completionHandler(metadatas) + let resultsMetadata = NCManageDatabase.shared.fetchPagedResults(ofType: tableMetadata.self, primaryKey: "ocId", recordsPerPage: self.recordsPerPage, pageNumber: pageNumber, filter: predicate, sortedByKeyPath: "fileName") + completionHandler(resultsMetadata) } + } else { + let resultsMetadata = NCManageDatabase.shared.fetchPagedResults(ofType: tableMetadata.self, primaryKey: "ocId", recordsPerPage: recordsPerPage, pageNumber: pageNumber, filter: predicate, sortedByKeyPath: "fileName") + completionHandler(resultsMetadata) } } } diff --git a/File Provider Extension/FileProviderExtension+Actions.swift b/File Provider Extension/FileProviderExtension+Actions.swift index d3126e0467..b1e7921454 100644 --- a/File Provider Extension/FileProviderExtension+Actions.swift +++ b/File Provider Extension/FileProviderExtension+Actions.swift @@ -26,49 +26,33 @@ import FileProvider import NextcloudKit extension FileProviderExtension { - override func createDirectory(withName directoryName: String, inParentItemIdentifier parentItemIdentifier: NSFileProviderItemIdentifier, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) { - - guard let tableDirectory = fpUtility.getTableDirectoryFromParentItemIdentifier(parentItemIdentifier, account: fileProviderData.shared.account, homeServerUrl: fileProviderData.shared.homeServerUrl) else { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return + guard let tableDirectory = providerUtility.getTableDirectoryFromParentItemIdentifier(parentItemIdentifier, account: fileProviderData.shared.account, homeServerUrl: fileProviderData.shared.homeServerUrl) else { + return completionHandler(nil, NSFileProviderError(.noSuchItem)) } - let directoryName = utilityFileSystem.createFileName(directoryName, serverUrl: tableDirectory.serverUrl, account: fileProviderData.shared.account) let serverUrlFileName = tableDirectory.serverUrl + "/" + directoryName NextcloudKit.shared.createFolder(serverUrlFileName: serverUrlFileName) { _, ocId, _, error in - if error == .success { - NextcloudKit.shared.readFileOrFolder(serverUrlFileName: serverUrlFileName, depth: "0", showHiddenFiles: NCKeychain().showHiddenFiles) { _, files, _, error in - if error == .success, let file = files.first { - let isDirectoryEncrypted = self.utilityFileSystem.isDirectoryE2EE(file: file) let metadata = NCManageDatabase.shared.convertFileToMetadata(file, isDirectoryE2EE: isDirectoryEncrypted) NCManageDatabase.shared.addDirectory(e2eEncrypted: false, favorite: false, ocId: ocId!, fileId: metadata.fileId, etag: metadata.etag, permissions: metadata.permissions, serverUrl: serverUrlFileName, account: metadata.account) NCManageDatabase.shared.addMetadata(metadata) - guard let metadataInsert = NCManageDatabase.shared.getMetadataFromOcId(ocId!) else { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return - } - - guard let parentItemIdentifier = self.fpUtility.getParentItemIdentifier(metadata: metadataInsert) else { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return + guard let metadataInsert = NCManageDatabase.shared.getMetadataFromOcId(ocId!), + let parentItemIdentifier = self.providerUtility.getParentItemIdentifier(metadata: metadataInsert) else { + return completionHandler(nil, NSFileProviderError(.noSuchItem)) } - let item = FileProviderItem(metadata: metadataInsert, parentItemIdentifier: parentItemIdentifier) completionHandler(item, nil) - } else { completionHandler(nil, NSFileProviderError(.serverUnreachable)) } } - } else { completionHandler(nil, NSFileProviderError(.serverUnreachable)) } @@ -76,12 +60,9 @@ extension FileProviderExtension { } override func deleteItem(withIdentifier itemIdentifier: NSFileProviderItemIdentifier, completionHandler: @escaping (Error?) -> Void) { - - guard let metadata = fpUtility.getTableMetadataFromItemIdentifier(itemIdentifier) else { - completionHandler(NSFileProviderError(.noSuchItem)) - return + guard let metadata = providerUtility.getTableMetadataFromItemIdentifier(itemIdentifier) else { + return completionHandler(NSFileProviderError(.noSuchItem)) } - let ocId = metadata.ocId let serverUrlFileName = metadata.serverUrl + "/" + metadata.fileName let isDirectory = metadata.directory @@ -89,12 +70,11 @@ extension FileProviderExtension { let fileName = metadata.fileName NextcloudKit.shared.deleteFileOrFolder(serverUrlFileName: serverUrlFileName) { account, error in - if error == .success { // || error == kOCErrorServerPathNotFound { - let fileNamePath = self.utilityFileSystem.getDirectoryProviderStorageOcId(itemIdentifier.rawValue) + do { - try self.fpUtility.fileManager.removeItem(atPath: fileNamePath) + try self.providerUtility.fileManager.removeItem(atPath: fileNamePath) } catch let error { print("error: \(error)") } @@ -106,9 +86,7 @@ extension FileProviderExtension { NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocId)) NCManageDatabase.shared.deleteLocalFile(predicate: NSPredicate(format: "ocId == %@", ocId)) - completionHandler(nil) - } else { completionHandler(NSFileProviderError(.serverUnreachable)) } @@ -116,47 +94,34 @@ extension FileProviderExtension { } override func reparentItem(withIdentifier itemIdentifier: NSFileProviderItemIdentifier, toParentItemWithIdentifier parentItemIdentifier: NSFileProviderItemIdentifier, newName: String?, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) { - - guard let itemFrom = try? item(for: itemIdentifier) else { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return - } - - guard let metadataFrom = fpUtility.getTableMetadataFromItemIdentifier(itemIdentifier) else { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return + guard let itemFrom = try? item(for: itemIdentifier), + let metadataFrom = providerUtility.getTableMetadataFromItemIdentifier(itemIdentifier) else { + return completionHandler(nil, NSFileProviderError(.noSuchItem)) } - let ocIdFrom = metadataFrom.ocId let serverUrlFrom = metadataFrom.serverUrl let fileNameFrom = serverUrlFrom + "/" + itemFrom.filename - - guard let tableDirectoryTo = fpUtility.getTableDirectoryFromParentItemIdentifier(parentItemIdentifier, account: fileProviderData.shared.account, homeServerUrl: fileProviderData.shared.homeServerUrl) else { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return + guard let tableDirectoryTo = providerUtility.getTableDirectoryFromParentItemIdentifier(parentItemIdentifier, account: fileProviderData.shared.account, homeServerUrl: fileProviderData.shared.homeServerUrl) else { + return completionHandler(nil, NSFileProviderError(.noSuchItem)) } let serverUrlTo = tableDirectoryTo.serverUrl let fileNameTo = serverUrlTo + "/" + itemFrom.filename NextcloudKit.shared.moveFileOrFolder(serverUrlFileNameSource: fileNameFrom, serverUrlFileNameDestination: fileNameTo, overwrite: false) { account, error in - if error == .success { - if metadataFrom.directory { NCManageDatabase.shared.deleteDirectoryAndSubDirectory(serverUrl: serverUrlFrom, account: account) NCManageDatabase.shared.renameDirectory(ocId: ocIdFrom, serverUrl: serverUrlTo) } - NCManageDatabase.shared.moveMetadata(ocId: ocIdFrom, serverUrlTo: serverUrlTo) guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocIdFrom) else { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return - } + return completionHandler(nil, NSFileProviderError(.noSuchItem)) + } let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier) - completionHandler(item, nil) + completionHandler(item, nil) } else { completionHandler(nil, NSFileProviderError(.serverUnreachable)) } @@ -164,60 +129,38 @@ extension FileProviderExtension { } override func renameItem(withIdentifier itemIdentifier: NSFileProviderItemIdentifier, toName itemName: String, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) { - - guard let metadata = fpUtility.getTableMetadataFromItemIdentifier(itemIdentifier) else { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return + guard let metadata = providerUtility.getTableMetadataFromItemIdentifier(itemIdentifier), + let directoryTable = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, metadata.serverUrl)) else { + return completionHandler(nil, NSFileProviderError(.noSuchItem)) } - - guard let directoryTable = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, metadata.serverUrl)) else { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return - } - let fileNameFrom = metadata.fileNameView let fileNamePathFrom = metadata.serverUrl + "/" + fileNameFrom let fileNamePathTo = metadata.serverUrl + "/" + itemName let ocId = metadata.ocId NextcloudKit.shared.moveFileOrFolder(serverUrlFileNameSource: fileNamePathFrom, serverUrlFileNameDestination: fileNamePathTo, overwrite: false) { account, error in - if error == .success { - // Rename metadata NCManageDatabase.shared.renameMetadata(fileNameTo: itemName, ocId: ocId) guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return + return completionHandler(nil, NSFileProviderError(.noSuchItem)) } - if metadata.directory { - NCManageDatabase.shared.setDirectory(serverUrl: fileNamePathFrom, serverUrlTo: fileNamePathTo, encrypted: directoryTable.e2eEncrypted, account: account) - } else { - - let itemIdentifier = self.fpUtility.getItemIdentifier(metadata: metadata) - - // rename file - _ = self.fpUtility.moveFile(self.utilityFileSystem.getDirectoryProviderStorageOcId(itemIdentifier.rawValue, fileNameView: fileNameFrom), toPath: self.utilityFileSystem.getDirectoryProviderStorageOcId(itemIdentifier.rawValue, fileNameView: itemName)) - - _ = self.fpUtility.moveFile(self.utilityFileSystem.getDirectoryProviderStoragePreviewOcId(itemIdentifier.rawValue, etag: metadata.etag), toPath: self.utilityFileSystem.getDirectoryProviderStoragePreviewOcId(itemIdentifier.rawValue, etag: metadata.etag)) - - _ = self.fpUtility.moveFile(self.utilityFileSystem.getDirectoryProviderStorageIconOcId(itemIdentifier.rawValue, etag: metadata.etag), toPath: self.utilityFileSystem.getDirectoryProviderStorageIconOcId(itemIdentifier.rawValue, etag: metadata.etag)) - + let itemIdentifier = self.providerUtility.getItemIdentifier(metadata: metadata) + self.providerUtility.moveFile(self.utilityFileSystem.getDirectoryProviderStorageOcId(itemIdentifier.rawValue, fileNameView: fileNameFrom), toPath: self.utilityFileSystem.getDirectoryProviderStorageOcId(itemIdentifier.rawValue, fileNameView: itemName)) + self.providerUtility.moveFile(self.utilityFileSystem.getDirectoryProviderStoragePreviewOcId(itemIdentifier.rawValue, etag: metadata.etag), toPath: self.utilityFileSystem.getDirectoryProviderStoragePreviewOcId(itemIdentifier.rawValue, etag: metadata.etag)) + self.providerUtility.moveFile(self.utilityFileSystem.getDirectoryProviderStorageIconOcId(itemIdentifier.rawValue, etag: metadata.etag), toPath: self.utilityFileSystem.getDirectoryProviderStorageIconOcId(itemIdentifier.rawValue, etag: metadata.etag)) NCManageDatabase.shared.setLocalFile(ocId: ocId, fileName: itemName) } - guard let parentItemIdentifier = self.fpUtility.getParentItemIdentifier(metadata: metadata) else { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return + guard let parentItemIdentifier = self.providerUtility.getParentItemIdentifier(metadata: metadata) else { + return completionHandler(nil, NSFileProviderError(.noSuchItem)) } - let item = FileProviderItem(metadata: tableMetadata.init(value: metadata), parentItemIdentifier: parentItemIdentifier) completionHandler(item, nil) - } else { completionHandler(nil, NSFileProviderError(.serverUnreachable)) } @@ -225,20 +168,16 @@ extension FileProviderExtension { } override func setFavoriteRank(_ favoriteRank: NSNumber?, forItemIdentifier itemIdentifier: NSFileProviderItemIdentifier, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) { - - guard let metadata = fpUtility.getTableMetadataFromItemIdentifier(itemIdentifier) else { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return + guard let metadata = providerUtility.getTableMetadataFromItemIdentifier(itemIdentifier) else { + return completionHandler(nil, NSFileProviderError(.noSuchItem)) } - var favorite = false let ocId = metadata.ocId if favoriteRank == nil { fileProviderData.shared.listFavoriteIdentifierRank.removeValue(forKey: itemIdentifier.rawValue) } else { - let rank = fileProviderData.shared.listFavoriteIdentifierRank[itemIdentifier.rawValue] - if rank == nil { + if fileProviderData.shared.listFavoriteIdentifierRank[itemIdentifier.rawValue] == nil { fileProviderData.shared.listFavoriteIdentifierRank[itemIdentifier.rawValue] = favoriteRank } favorite = true @@ -246,35 +185,25 @@ extension FileProviderExtension { if (favorite == true && metadata.favorite == false) || (favorite == false && metadata.favorite == true) { let fileNamePath = utilityFileSystem.getFileNamePath(metadata.fileName, serverUrl: metadata.serverUrl, urlBase: metadata.urlBase, userId: metadata.userId) - NextcloudKit.shared.setFavorite(fileName: fileNamePath, favorite: favorite) { _, error in - if error == .success { - - guard let metadataTemp = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return + guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { + return completionHandler(nil, NSFileProviderError(.noSuchItem)) } - let metadata = tableMetadata.init(value: metadataTemp) - // Change DB metadata.favorite = favorite NCManageDatabase.shared.addMetadata(metadata) - - let item = fileProviderData.shared.signalEnumerator(ocId: metadata.ocId) + /// SIGNAL + let item = fileProviderData.shared.signalEnumerator(ocId: metadata.ocId, type: .workingSet) completionHandler(item, nil) - } else { - guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return + return completionHandler(nil, NSFileProviderError(.noSuchItem)) } - // Errore, remove from listFavoriteIdentifierRank fileProviderData.shared.listFavoriteIdentifierRank.removeValue(forKey: itemIdentifier.rawValue) - - let item = fileProviderData.shared.signalEnumerator(ocId: metadata.ocId) + /// SIGNAL + let item = fileProviderData.shared.signalEnumerator(ocId: metadata.ocId, type: .workingSet) completionHandler(item, NSFileProviderError(.serverUnreachable)) } } @@ -282,33 +211,23 @@ extension FileProviderExtension { } override func setTagData(_ tagData: Data?, forItemIdentifier itemIdentifier: NSFileProviderItemIdentifier, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) { - - guard let metadataForTag = fpUtility.getTableMetadataFromItemIdentifier(itemIdentifier) else { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return + guard let metadataForTag = providerUtility.getTableMetadataFromItemIdentifier(itemIdentifier) else { + return completionHandler(nil, NSFileProviderError(.noSuchItem)) } let ocId = metadataForTag.ocId let account = metadataForTag.account - // Add, Remove (nil) NCManageDatabase.shared.addTag(ocId, tagIOS: tagData, account: account) - - let item = fileProviderData.shared.signalEnumerator(ocId: ocId) + /// SIGNAL WORKINGSET + let item = fileProviderData.shared.signalEnumerator(ocId: ocId, type: .workingSet) completionHandler(item, nil) } override func setLastUsedDate(_ lastUsedDate: Date?, forItemIdentifier itemIdentifier: NSFileProviderItemIdentifier, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) { - - guard let metadata = fpUtility.getTableMetadataFromItemIdentifier(itemIdentifier) else { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return - } - - guard let parentItemIdentifier = fpUtility.getParentItemIdentifier(metadata: metadata) else { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return + guard let metadata = providerUtility.getTableMetadataFromItemIdentifier(itemIdentifier), + let parentItemIdentifier = providerUtility.getParentItemIdentifier(metadata: metadata) else { + return completionHandler(nil, NSFileProviderError(.noSuchItem)) } - let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier) completionHandler(item, nil) } diff --git a/File Provider Extension/FileProviderExtension+NetworkingDelegate.swift b/File Provider Extension/FileProviderExtension+NetworkingDelegate.swift new file mode 100644 index 0000000000..5fbf694170 --- /dev/null +++ b/File Provider Extension/FileProviderExtension+NetworkingDelegate.swift @@ -0,0 +1,72 @@ +// +// FileProviderExtension+x.swift +// File Provider Extension +// +// Created by Marino Faggiana on 11/07/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 UIKit +import UniformTypeIdentifiers +import FileProvider +import NextcloudKit +import Alamofire + +extension FileProviderExtension: NCNetworkingDelegate { + func downloadComplete(fileName: String, serverUrl: String, etag: String?, date: Date?, dateLastModified: Date?, length: Int64, task: URLSessionTask, error: NKError) { } + func downloadProgress(_ progress: Float, totalBytes: Int64, totalBytesExpected: Int64, fileName: String, serverUrl: String, session: URLSession, task: URLSessionTask) { } + func uploadProgress(_ progress: Float, totalBytes: Int64, totalBytesExpected: Int64, fileName: String, serverUrl: String, session: URLSession, task: URLSessionTask) { } + + func uploadComplete(fileName: String, serverUrl: String, ocId: String?, etag: String?, date: Date?, size: Int64, task: URLSessionTask, error: NKError) { + guard let url = task.currentRequest?.url, + let metadata = NCManageDatabase.shared.getMetadata(from: url, sessionTaskIdentifier: task.taskIdentifier) else { return } + if error == .success, let ocId { + /// SIGNAL + fileProviderData.shared.signalEnumerator(ocId: metadata.ocIdTemp, type: .delete) + metadata.fileName = fileName + metadata.serverUrl = serverUrl + metadata.uploadDate = (date as? NSDate) ?? NSDate() + metadata.etag = etag ?? "" + metadata.ocId = ocId + metadata.size = size + if let fileId = NCUtility().ocIdToFileId(ocId: ocId) { + metadata.fileId = fileId + } + metadata.session = "" + metadata.sessionError = "" + metadata.status = NCGlobal.shared.metadataStatusNormal + + NCManageDatabase.shared.addMetadata(metadata) + NCManageDatabase.shared.addLocalFile(metadata: metadata) + /// NEW File + if ocId != metadata.ocIdTemp { + let atPath = utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocIdTemp) + let toPath = utilityFileSystem.getDirectoryProviderStorageOcId(ocId) + utilityFileSystem.copyFile(atPath: atPath, toPath: toPath) + NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocIdTemp)) + } + /// SIGNAL + fileProviderData.shared.signalEnumerator(ocId: metadata.ocId, type: .update) + } else { + NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocIdTemp)) + /// SIGNAL + fileProviderData.shared.signalEnumerator(ocId: metadata.ocIdTemp, type: .delete) + } + } +} diff --git a/File Provider Extension/FileProviderExtension+Thumbnail.swift b/File Provider Extension/FileProviderExtension+Thumbnail.swift index a12114b351..17a9d9d055 100644 --- a/File Provider Extension/FileProviderExtension+Thumbnail.swift +++ b/File Provider Extension/FileProviderExtension+Thumbnail.swift @@ -26,54 +26,34 @@ import FileProvider import NextcloudKit extension FileProviderExtension { - override func fetchThumbnails(for itemIdentifiers: [NSFileProviderItemIdentifier], requestedSize size: CGSize, perThumbnailCompletionHandler: @escaping (NSFileProviderItemIdentifier, Data?, Error?) -> Void, completionHandler: @escaping (Error?) -> Void) -> Progress { - let progress = Progress(totalUnitCount: Int64(itemIdentifiers.count)) var counterProgress: Int64 = 0 for itemIdentifier in itemIdentifiers { - - guard let metadata = fpUtility.getTableMetadataFromItemIdentifier(itemIdentifier) else { + guard let metadata = providerUtility.getTableMetadataFromItemIdentifier(itemIdentifier), metadata.hasPreview else { counterProgress += 1 if counterProgress == progress.totalUnitCount { completionHandler(nil) } continue } - - if metadata.hasPreview { - - let fileNamePath = utilityFileSystem.getFileNamePath(metadata.fileName, serverUrl: metadata.serverUrl, urlBase: metadata.urlBase, userId: metadata.userId) - let fileNameIconLocalPath = utilityFileSystem.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag) - - if let urlBase = metadata.urlBase.urlEncoded, - let fileNamePath = fileNamePath.urlEncoded, - let url = URL(string: "\(urlBase)/index.php/core/preview.png?file=\(fileNamePath)&x=\(size.width)&y=\(size.height)&a=1&mode=cover") { - - NextcloudKit.shared.getPreview(url: url) { _, data, error in - if error == .success && data != nil { - do { - try data!.write(to: URL(fileURLWithPath: fileNameIconLocalPath), options: .atomic) - } catch { } - perThumbnailCompletionHandler(itemIdentifier, data, nil) - } else { - perThumbnailCompletionHandler(itemIdentifier, nil, NSFileProviderError(.serverUnreachable)) - } - counterProgress += 1 - if counterProgress == progress.totalUnitCount { - completionHandler(nil) - } - } + let fileNameIconLocalPath = utilityFileSystem.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag) + + NextcloudKit.shared.downloadPreview(fileId: metadata.fileId, widthPreview: Int(size.width), heightPreview: Int(size.height), etag: metadata.etag) { _ in + } completion: { _, data, error in + if error == .success, let data { + do { + try data.write(to: URL(fileURLWithPath: fileNameIconLocalPath), options: .atomic) + } catch { } + perThumbnailCompletionHandler(itemIdentifier, data, nil) + } else { + perThumbnailCompletionHandler(itemIdentifier, nil, NSFileProviderError(.serverUnreachable)) } - - } else { counterProgress += 1 if counterProgress == progress.totalUnitCount { completionHandler(nil) } } } - return progress } - } diff --git a/File Provider Extension/FileProviderExtension.swift b/File Provider Extension/FileProviderExtension.swift index bd876d60f3..276d010c09 100644 --- a/File Provider Extension/FileProviderExtension.swift +++ b/File Provider Extension/FileProviderExtension.swift @@ -53,10 +53,7 @@ import Alamofire -------------------------------------------------------------------------------------------------------------------------------------------- */ class FileProviderExtension: NSFileProviderExtension { - - var outstandingSessionTasks: [URL: URLSessionTask] = [:] - var outstandingOcIdTemp: [String: String] = [:] - var fpUtility = fileProviderUtility() + let providerUtility = fileProviderUtility() let utilityFileSystem = NCUtilityFileSystem() override init() { @@ -66,6 +63,8 @@ class FileProviderExtension: NSFileProviderExtension { _ = utilityFileSystem.directoryProviderStorage // Configure URLSession _ = NCNetworking.shared.sessionManagerUploadBackgroundExtension + // Domains + // FileProviderDomain().registerDomains() } deinit { @@ -75,7 +74,6 @@ class FileProviderExtension: NSFileProviderExtension { // MARK: - Enumeration override func enumerator(for containerItemIdentifier: NSFileProviderItemIdentifier) throws -> NSFileProviderEnumerator { - var maybeEnumerator: NSFileProviderEnumerator? if containerItemIdentifier != NSFileProviderItemIdentifier.workingSet { @@ -114,11 +112,8 @@ class FileProviderExtension: NSFileProviderExtension { // MARK: - Item override func item(for identifier: NSFileProviderItemIdentifier) throws -> NSFileProviderItem { - if identifier == .rootContainer { - let metadata = tableMetadata() - metadata.account = fileProviderData.shared.account metadata.directory = true metadata.ocId = NSFileProviderItemIdentifier.rootContainer.rawValue @@ -126,15 +121,10 @@ class FileProviderExtension: NSFileProviderExtension { metadata.fileNameView = "root" metadata.serverUrl = fileProviderData.shared.homeServerUrl metadata.classFile = NKCommon.TypeClassFile.directory.rawValue - return FileProviderItem(metadata: metadata, parentItemIdentifier: NSFileProviderItemIdentifier(NSFileProviderItemIdentifier.rootContainer.rawValue)) - } else { - - guard let metadata = fpUtility.getTableMetadataFromItemIdentifier(identifier) else { - throw NSFileProviderError(.noSuchItem) - } - guard let parentItemIdentifier = fpUtility.getParentItemIdentifier(metadata: metadata) else { + guard let metadata = providerUtility.getTableMetadataFromItemIdentifier(identifier), + let parentItemIdentifier = providerUtility.getParentItemIdentifier(metadata: metadata) else { throw NSFileProviderError(.noSuchItem) } let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier) @@ -143,40 +133,26 @@ class FileProviderExtension: NSFileProviderExtension { } override func urlForItem(withPersistentIdentifier identifier: NSFileProviderItemIdentifier) -> URL? { - - // resolve the given identifier to a file on disk - guard let item = try? item(for: identifier) else { - return nil - } - + guard let item = try? item(for: identifier) else { return nil } var url = fileProviderData.shared.fileProviderManager.documentStorageURL.appendingPathComponent(identifier.rawValue, isDirectory: true) - // (fix copy/paste directory -> isDirectory = false) url = url.appendingPathComponent(item.filename, isDirectory: false) - return url } override func persistentIdentifierForItem(at url: URL) -> NSFileProviderItemIdentifier? { - - // resolve the given URL to a persistent identifier using a database let pathComponents = url.pathComponents - // exploit the fact that the path structure has been defined as // // above assert(pathComponents.count > 2) - let itemIdentifier = NSFileProviderItemIdentifier(pathComponents[pathComponents.count - 2]) return itemIdentifier } override func providePlaceholder(at url: URL, completionHandler: @escaping (Error?) -> Void) { - guard let identifier = persistentIdentifierForItem(at: url) else { - completionHandler(NSFileProviderError(.noSuchItem)) - return + return completionHandler(NSFileProviderError(.noSuchItem)) } - do { let fileProviderItem = try item(for: identifier) let placeholderURL = NSFileProviderManager.placeholderURL(for: url) @@ -188,169 +164,127 @@ class FileProviderExtension: NSFileProviderExtension { } override func startProvidingItem(at url: URL, completionHandler: @escaping ((_ error: Error?) -> Void)) { - let pathComponents = url.pathComponents - let identifier = NSFileProviderItemIdentifier(pathComponents[pathComponents.count - 2]) - - if outstandingSessionTasks[url] != nil { - return completionHandler(nil) - } - - guard let metadata = fpUtility.getTableMetadataFromItemIdentifier(identifier) else { - return completionHandler(NSFileProviderError(.noSuchItem)) - } - - // Document VIEW ONLY - if metadata.isDocumentViewableOnly { + let itemIdentifier = NSFileProviderItemIdentifier(pathComponents[pathComponents.count - 2]) + guard let metadata = providerUtility.getTableMetadataFromItemIdentifier(itemIdentifier) else { return completionHandler(NSFileProviderError(.noSuchItem)) } - - let tableLocalFile = NCManageDatabase.shared.getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) - if tableLocalFile != nil && utilityFileSystem.fileProviderStorageExists(metadata) && tableLocalFile?.etag == metadata.etag { + if metadata.session == NCNetworking.shared.sessionUploadBackgroundExtension { return completionHandler(nil) } - let serverUrlFileName = metadata.serverUrl + "/" + metadata.fileName let fileNameLocalPath = utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileName) - - // Update status - NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusDownloading) - fileProviderData.shared.signalEnumerator(ocId: metadata.ocId, update: true) + // Exists ? return + if let tableLocalFile = NCManageDatabase.shared.getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)), + utilityFileSystem.fileProviderStorageExists(metadata), + tableLocalFile.etag == metadata.etag { + return completionHandler(nil) + } else { + NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, + session: NextcloudKit.shared.nkCommonInstance.sessionIdentifierDownload, + sessionError: "", + selector: "", + status: NCGlobal.shared.metadataStatusDownloading) + } + /// SIGNAL + fileProviderData.shared.signalEnumerator(ocId: metadata.ocId, type: .update) NextcloudKit.shared.download(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, requestHandler: { _ in - }, taskHandler: { task in - - self.outstandingSessionTasks[url] = task - fileProviderData.shared.fileProviderManager.register(task, forItemWithIdentifier: NSFileProviderItemIdentifier(identifier.rawValue)) { _ in } - + NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, + taskIdentifier: task.taskIdentifier) + fileProviderData.shared.fileProviderManager.register(task, forItemWithIdentifier: NSFileProviderItemIdentifier(itemIdentifier.rawValue)) { _ in } }, progressHandler: { _ in - }) { _, etag, date, _, _, _, error in - - self.outstandingSessionTasks.removeValue(forKey: url) - guard var metadata = self.fpUtility.getTableMetadataFromItemIdentifier(identifier) else { - completionHandler(NSFileProviderError(.noSuchItem)) - return + guard let metadata = self.providerUtility.getTableMetadataFromItemIdentifier(itemIdentifier) else { + return completionHandler(NSFileProviderError(.noSuchItem)) } - metadata = tableMetadata.init(value: metadata) - if error == .success { - metadata.status = NCGlobal.shared.metadataStatusNormal - metadata.date = date ?? NSDate() + metadata.date = (date as? NSDate) ?? NSDate() metadata.etag = etag ?? "" - NCManageDatabase.shared.addLocalFile(metadata: metadata) NCManageDatabase.shared.addMetadata(metadata) - completionHandler(nil) - } else if error.errorCode == 200 { - NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusNormal) - completionHandler(nil) - } else { - metadata.status = NCGlobal.shared.metadataStatusDownloadError metadata.sessionError = error.errorDescription NCManageDatabase.shared.addMetadata(metadata) - completionHandler(NSFileProviderError(.noSuchItem)) } - - fileProviderData.shared.signalEnumerator(ocId: metadata.ocId, update: true) + /// SIGNAL + fileProviderData.shared.signalEnumerator(ocId: metadata.ocId, type: .update) } } + /// Upload the changed file override func itemChanged(at url: URL) { - let pathComponents = url.pathComponents assert(pathComponents.count > 2) let itemIdentifier = NSFileProviderItemIdentifier(pathComponents[pathComponents.count - 2]) let fileName = pathComponents[pathComponents.count - 1] - var ocId = itemIdentifier.rawValue - - // Temp ocId ? - if outstandingOcIdTemp[ocId] != nil && outstandingOcIdTemp[ocId] != ocId { - ocId = outstandingOcIdTemp[ocId]! - let atPath = utilityFileSystem.getDirectoryProviderStorageOcId(itemIdentifier.rawValue, fileNameView: fileName) - let toPath = utilityFileSystem.getDirectoryProviderStorageOcId(ocId, fileNameView: fileName) - utilityFileSystem.copyFile(atPath: atPath, toPath: toPath) - } - guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { return } - + guard let metadata = NCManageDatabase.shared.getMetadataFromOcIdAndOcIdTemp(itemIdentifier.rawValue) else { return } let serverUrlFileName = metadata.serverUrl + "/" + fileName - let fileNameLocalPath = url.path - + let fileNameLocalPath = utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: fileName) + utilityFileSystem.copyFile(atPath: url.path, toPath: fileNameLocalPath) + NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, + session: NCNetworking.shared.sessionUploadBackgroundExtension, + sessionError: "", + selector: "", + status: NCGlobal.shared.metadataStatusUploading) if let task = NKBackground(nkCommonInstance: NextcloudKit.shared.nkCommonInstance).upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, dateCreationFile: nil, dateModificationFile: nil, session: NCNetworking.shared.sessionManagerUploadBackgroundExtension) { - + NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, + status: NCGlobal.shared.metadataStatusUploading, + taskIdentifier: task.taskIdentifier) fileProviderData.shared.fileProviderManager.register(task, forItemWithIdentifier: NSFileProviderItemIdentifier(metadata.fileId)) { _ in } } } override func stopProvidingItem(at url: URL) { - - let fileHasLocalChanges = false - - if !fileHasLocalChanges { - // remove the existing file to free up space - do { - _ = try fpUtility.fileManager.removeItem(at: url) - } catch let error { - print("error: \(error)") + let pathComponents = url.pathComponents + assert(pathComponents.count > 2) + let itemIdentifier = NSFileProviderItemIdentifier(pathComponents[pathComponents.count - 2]) + guard let metadata = NCManageDatabase.shared.getMetadataFromOcIdAndOcIdTemp(itemIdentifier.rawValue) else { return } + if metadata.session == NextcloudKit.shared.nkCommonInstance.sessionIdentifierDownload { + NextcloudKit.shared.sessionManager.session.getTasksWithCompletionHandler { _, _, downloadTasks in + downloadTasks.forEach { task in + if metadata.sessionTaskIdentifier == task.taskIdentifier { + task.cancel() + } + } } - - // write out a placeholder to facilitate future property lookups - self.providePlaceholder(at: url, completionHandler: { _ in - // handle any error, do any necessary cleanup - }) - } - - // Download task - if let downloadTask = outstandingSessionTasks[url] { - downloadTask.cancel() - outstandingSessionTasks.removeValue(forKey: url) } } override func importDocument(at fileURL: URL, toParentItemIdentifier parentItemIdentifier: NSFileProviderItemIdentifier, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) { - DispatchQueue.main.async { - autoreleasepool { - + guard let tableDirectory = self.providerUtility.getTableDirectoryFromParentItemIdentifier(parentItemIdentifier, account: fileProviderData.shared.account, homeServerUrl: fileProviderData.shared.homeServerUrl) else { + return completionHandler(nil, NSFileProviderError(.noSuchItem)) + } var size = 0 as Int64 var error: NSError? - - guard let tableDirectory = self.fpUtility.getTableDirectoryFromParentItemIdentifier(parentItemIdentifier, account: fileProviderData.shared.account, homeServerUrl: fileProviderData.shared.homeServerUrl) else { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return - } - _ = fileURL.startAccessingSecurityScopedResource() - // typefile directory ? (NOT PERMITTED) do { - let attributes = try self.fpUtility.fileManager.attributesOfItem(atPath: fileURL.path) + let attributes = try self.providerUtility.fileManager.attributesOfItem(atPath: fileURL.path) size = attributes[FileAttributeKey.size] as? Int64 ?? 0 let typeFile = attributes[FileAttributeKey.type] as? FileAttributeType if typeFile == FileAttributeType.typeDirectory { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return + return completionHandler(nil, NSFileProviderError(.noSuchItem)) } } catch { - completionHandler(nil, NSFileProviderError(.noSuchItem)) - return + return completionHandler(nil, NSFileProviderError(.noSuchItem)) } let fileName = self.utilityFileSystem.createFileName(fileURL.lastPathComponent, serverUrl: tableDirectory.serverUrl, account: fileProviderData.shared.account) let ocIdTemp = NSUUID().uuidString.lowercased() NSFileCoordinator().coordinate(readingItemAt: fileURL, options: .withoutChanges, error: &error) { url in - _ = self.fpUtility.copyFile(url.path, toPath: self.utilityFileSystem.getDirectoryProviderStorageOcId(ocIdTemp, fileNameView: fileName)) + self.providerUtility.copyFile(url.path, toPath: self.utilityFileSystem.getDirectoryProviderStorageOcId(ocIdTemp, fileNameView: fileName)) } fileURL.stopAccessingSecurityScopedResource() @@ -366,71 +300,15 @@ class FileProviderExtension: NSFileProviderExtension { 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, session: NCNetworking.shared.sessionManagerUploadBackgroundExtension) { - - self.outstandingSessionTasks[URL(fileURLWithPath: fileNameLocalPath)] = task as URLSessionTask - + NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, + status: NCGlobal.shared.metadataStatusUploading, + taskIdentifier: task.taskIdentifier) fileProviderData.shared.fileProviderManager.register(task, forItemWithIdentifier: NSFileProviderItemIdentifier(ocIdTemp)) { _ in } } let item = FileProviderItem(metadata: tableMetadata.init(value: metadata), parentItemIdentifier: parentItemIdentifier) - completionHandler(item, nil) } } } - - func uploadComplete(fileName: String, serverUrl: String, ocId: String?, etag: String?, date: NSDate?, size: Int64, fileNameLocalPath: String?, task: URLSessionTask, error: NKError) { - - guard let metadataTemp = NCManageDatabase.shared.getMetadataFromFileNameLocalPath(fileNameLocalPath) else { return } - let ocIdTemp = metadataTemp.ocId - let metadata = tableMetadata.init(value: metadataTemp) - - let url = URL(fileURLWithPath: utilityFileSystem.getDirectoryProviderStorageOcId(ocIdTemp, fileNameView: fileName)) - DispatchQueue.main.asyncAfter(deadline: .now() + 1) { - self.outstandingSessionTasks.removeValue(forKey: url) - } - outstandingOcIdTemp[ocIdTemp] = ocId - - if error == .success { - - // New file - if ocId != ocIdTemp { - // Signal update - fileProviderData.shared.signalEnumerator(ocId: metadata.ocId, delete: true) - } - - metadata.fileName = fileName - metadata.serverUrl = serverUrl - if let etag = etag { metadata.etag = etag } - if let ocId = ocId { metadata.ocId = ocId } - if let date = date { metadata.date = date } - metadata.permissions = "RGDNVW" - metadata.session = "" - metadata.size = size - metadata.status = NCGlobal.shared.metadataStatusNormal - - NCManageDatabase.shared.addMetadata(metadata) - NCManageDatabase.shared.addLocalFile(metadata: metadata) - - // New file - if let ocId, ocId != ocIdTemp { - - NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp)) - - // File system - let atPath = utilityFileSystem.getDirectoryProviderStorageOcId(ocIdTemp) - let toPath = utilityFileSystem.getDirectoryProviderStorageOcId(ocId) - utilityFileSystem.copyFile(atPath: atPath, toPath: toPath) - } - - fileProviderData.shared.signalEnumerator(ocId: metadata.ocId, update: true) - - } else { - - NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp)) - - fileProviderData.shared.signalEnumerator(ocId: ocIdTemp, delete: true) - } - } - } diff --git a/File Provider Extension/FileProviderItem.swift b/File Provider Extension/FileProviderItem.swift index c9ef7274a3..e5f2ba0cc9 100644 --- a/File Provider Extension/FileProviderItem.swift +++ b/File Provider Extension/FileProviderItem.swift @@ -24,102 +24,101 @@ import UIKit import FileProvider import NextcloudKit +import UniformTypeIdentifiers class FileProviderItem: NSObject, NSFileProviderItem { - var metadata: tableMetadata - var parentItemIdentifier: NSFileProviderItemIdentifier - + /// Providing Required Properties var itemIdentifier: NSFileProviderItemIdentifier { return fileProviderUtility().getItemIdentifier(metadata: metadata) } - var filename: String { return metadata.fileNameView } - - var documentSize: NSNumber? { - return NSNumber(value: metadata.size) - } - var typeIdentifier: String { let results = NextcloudKit.shared.nkCommonInstance.getInternalType(fileName: metadata.fileNameView, mimeType: "", directory: metadata.directory) return results.typeIdentifier } - - var contentModificationDate: Date? { - return metadata.date as Date - } - - var creationDate: Date? { - return metadata.creationDate as Date - } - - var lastUsedDate: Date? { - return metadata.date as Date - } - var capabilities: NSFileProviderItemCapabilities { - guard !metadata.directory else { + if metadata.directory { return [ .allowsAddingSubItems, .allowsContentEnumerating, .allowsReading, .allowsDeleting, .allowsRenaming ] - } - guard !metadata.lock else { + } else if metadata.lock { return [ .allowsReading ] } return [ .allowsWriting, .allowsReading, .allowsDeleting, .allowsRenaming, .allowsReparenting ] } - + /// Managing Content + var childItemCount: NSNumber? { + return metadata.directory ? nil : nil + } + var documentSize: NSNumber? { + return metadata.directory ? nil : NSNumber(value: metadata.size) + } + /// Specifying Content Location + var parentItemIdentifier: NSFileProviderItemIdentifier var isTrashed: Bool { return false } - - var childItemCount: NSNumber? { + var symlinkTargetPath: String? { return nil } - + /// Tracking Usage + var contentModificationDate: Date? { + return metadata.date as Date + } + var creationDate: Date? { + return metadata.creationDate as Date + } + var lastUsedDate: Date? { + return metadata.date as Date + } + /// Tracking Versions var versionIdentifier: Data? { return metadata.etag.data(using: .utf8) } - - var tagData: Data? { - if let tableTag = NCManageDatabase.shared.getTag(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) { - return tableTag.tagIOS + var isMostRecentVersionDownloaded: Bool { + if NCManageDatabase.shared.getTableLocalFile(ocId: metadata.ocId) == nil { + return false } else { - return nil + return true } } - - var favoriteRank: NSNumber? { - if let rank = fileProviderData.shared.listFavoriteIdentifierRank[metadata.ocId] { - return rank + /// Monitoring File Transfers + var isUploading: Bool { + if metadata.status == NCGlobal.shared.metadataStatusWaitUpload || metadata.status == NCGlobal.shared.metadataStatusUploading { + return true } else { - return nil + return false } } - - var isMostRecentVersionDownloaded: Bool { - return true - } - - var isDownloaded: Bool { - if metadata.directory { + var isUploaded: Bool { + if metadata.status == NCGlobal.shared.metadataStatusWaitUpload || metadata.status == NCGlobal.shared.metadataStatusUploading || metadata.status == NCGlobal.shared.metadataStatusUploadError { + return false + } else { return true } - if NCUtilityFileSystem().fileProviderStorageExists(metadata) { + } + var uploadingError: Error? { + if metadata.status == NCGlobal.shared.metadataStatusUploadError { + return fileProviderData.FileProviderError.uploadError + } else { + return nil + } + } + var isDownloading: Bool { + if metadata.status == NCGlobal.shared.metadataStatusWaitDownload || metadata.status == NCGlobal.shared.metadataStatusDownloading { return true } else { return false } } - - var isDownloading: Bool { - if metadata.status == NCGlobal.shared.metadataStatusDownloading { + var isDownloaded: Bool { + if NCUtilityFileSystem().fileProviderStorageExists(metadata) { return true } else { return false } } - var downloadingError: Error? { if metadata.status == NCGlobal.shared.metadataStatusDownloadError { return fileProviderData.FileProviderError.downloadError @@ -127,33 +126,25 @@ class FileProviderItem: NSObject, NSFileProviderItem { return nil } } - - var isUploaded: Bool { - if NCManageDatabase.shared.getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) != nil { - return true - } else { - return false - } - } - - var isUploading: Bool { - if metadata.status == NCGlobal.shared.metadataStatusUploading { - return true + /// Sharing + /// Managing Metadata + var tagData: Data? { + if let tableTag = NCManageDatabase.shared.getTag(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) { + return tableTag.tagIOS } else { - return false + return nil } } - - var uploadingError: Error? { - if metadata.status == NCGlobal.shared.metadataStatusUploadError { - return fileProviderData.FileProviderError.uploadError + var favoriteRank: NSNumber? { + if let rank = fileProviderData.shared.listFavoriteIdentifierRank[metadata.ocId] { + return rank } else { return nil } } init(metadata: tableMetadata, parentItemIdentifier: NSFileProviderItemIdentifier) { - self.metadata = metadata + self.metadata = tableMetadata(value: metadata) self.parentItemIdentifier = parentItemIdentifier } } diff --git a/File Provider Extension/FileProviderUtility.swift b/File Provider Extension/FileProviderUtility.swift index baa27d27d0..68c05440bd 100644 --- a/File Provider Extension/FileProviderUtility.swift +++ b/File Provider Extension/FileProviderUtility.swift @@ -24,40 +24,24 @@ import UIKit class fileProviderUtility: NSObject { - let fileManager = FileManager() let utilityFileSystem = NCUtilityFileSystem() func getAccountFromItemIdentifier(_ itemIdentifier: NSFileProviderItemIdentifier) -> String? { - let ocId = itemIdentifier.rawValue return NCManageDatabase.shared.getMetadataFromOcId(ocId)?.account } func getTableMetadataFromItemIdentifier(_ itemIdentifier: NSFileProviderItemIdentifier) -> tableMetadata? { - let ocId = itemIdentifier.rawValue return NCManageDatabase.shared.getMetadataFromOcId(ocId) } func getItemIdentifier(metadata: tableMetadata) -> NSFileProviderItemIdentifier { - return NSFileProviderItemIdentifier(metadata.ocId) } - func createocIdentifierOnFileSystem(metadata: tableMetadata) { - - let itemIdentifier = getItemIdentifier(metadata: metadata) - - if metadata.directory { - _ = utilityFileSystem.getDirectoryProviderStorageOcId(itemIdentifier.rawValue) - } else { - _ = utilityFileSystem.getDirectoryProviderStorageOcId(itemIdentifier.rawValue, fileNameView: metadata.fileNameView) - } - } - func getParentItemIdentifier(metadata: tableMetadata) -> NSFileProviderItemIdentifier? { - let homeServerUrl = utilityFileSystem.getHomeServer(urlBase: metadata.urlBase, userId: metadata.userId) if let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, metadata.serverUrl)) { if directory.serverUrl == homeServerUrl { @@ -70,36 +54,23 @@ class fileProviderUtility: NSObject { } } } - return nil } func getTableDirectoryFromParentItemIdentifier(_ parentItemIdentifier: NSFileProviderItemIdentifier, account: String, homeServerUrl: String) -> tableDirectory? { - var predicate: NSPredicate - if parentItemIdentifier == .rootContainer { - predicate = NSPredicate(format: "account == %@ AND serverUrl == %@", account, homeServerUrl) - } else { - guard let metadata = getTableMetadataFromItemIdentifier(parentItemIdentifier) else { return nil } predicate = NSPredicate(format: "ocId == %@", metadata.ocId) } - guard let directory = NCManageDatabase.shared.getTableDirectory(predicate: predicate) else { return nil } - return directory } - // MARK: - - - func copyFile(_ atPath: String, toPath: String) -> Error? { - - var errorResult: Error? - - if !fileManager.fileExists(atPath: atPath) { return NSError(domain: NSCocoaErrorDomain, code: NSFileNoSuchFileError, userInfo: [:]) } + func copyFile(_ atPath: String, toPath: String) { + if !fileManager.fileExists(atPath: atPath) { return } do { try fileManager.removeItem(atPath: toPath) @@ -109,18 +80,12 @@ class fileProviderUtility: NSObject { do { try fileManager.copyItem(atPath: atPath, toPath: toPath) } catch let error { - errorResult = error + print("error: \(error)") } - - return errorResult } - func moveFile(_ atPath: String, toPath: String) -> Error? { - - var errorResult: Error? - - if atPath == toPath { return nil } - if !fileManager.fileExists(atPath: atPath) { return NSError(domain: NSCocoaErrorDomain, code: NSFileNoSuchFileError, userInfo: [:]) } + func moveFile(_ atPath: String, toPath: String) { + if !fileManager.fileExists(atPath: atPath) { return } do { try fileManager.removeItem(atPath: toPath) @@ -130,26 +95,7 @@ class fileProviderUtility: NSObject { do { try fileManager.moveItem(atPath: atPath, toPath: toPath) } catch let error { - errorResult = error - } - - return errorResult - } - - func deleteFile(_ atPath: String) -> Error? { - - var errorResult: Error? - - do { - try fileManager.removeItem(atPath: atPath) - } catch let error { - errorResult = error + print("error: \(error)") } - - return errorResult - } - - func fileExists(atPath: String) -> Bool { - return fileManager.fileExists(atPath: atPath) } } diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index c1d332c641..c563b89e3f 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -53,9 +53,9 @@ AF8ED1FC2757821000B8DBC4 /* NextcloudUnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF8ED1FB2757821000B8DBC4 /* NextcloudUnitTests.swift */; }; AF93471227E2341B002537EE /* NCShare+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF93471127E2341B002537EE /* NCShare+Menu.swift */; }; AF93471927E2361E002537EE /* NCShareAdvancePermissionFooter.xib in Resources */ = {isa = PBXBuildFile; fileRef = AF93471427E2361E002537EE /* NCShareAdvancePermissionFooter.xib */; }; - AF93471A27E2361E002537EE /* NCShareAdvancePermissionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF93471527E2361E002537EE /* NCShareAdvancePermissionHeader.swift */; }; + AF93471A27E2361E002537EE /* NCShareHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF93471527E2361E002537EE /* NCShareHeader.swift */; }; AF93471B27E2361E002537EE /* NCShareAdvancePermission.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF93471627E2361E002537EE /* NCShareAdvancePermission.swift */; }; - AF93471C27E2361E002537EE /* NCShareAdvancePermissionHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = AF93471727E2361E002537EE /* NCShareAdvancePermissionHeader.xib */; }; + AF93471C27E2361E002537EE /* NCShareHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = AF93471727E2361E002537EE /* NCShareHeader.xib */; }; AF93471D27E2361E002537EE /* NCShareAdvancePermissionFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF93471827E2361E002537EE /* NCShareAdvancePermissionFooter.swift */; }; AF93474C27E34120002537EE /* NCUtility+Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF93474B27E34120002537EE /* NCUtility+Image.swift */; }; AF93474E27E3F212002537EE /* NCShareNewUserAddComment.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF93474D27E3F211002537EE /* NCShareNewUserAddComment.swift */; }; @@ -113,7 +113,7 @@ F359D86B2A7D03420023F405 /* NCUtility+Exif.swift in Sources */ = {isa = PBXBuildFile; fileRef = F359D8662A7D03420023F405 /* NCUtility+Exif.swift */; }; F359D86C2A7D03420023F405 /* NCUtility+Exif.swift in Sources */ = {isa = PBXBuildFile; fileRef = F359D8662A7D03420023F405 /* NCUtility+Exif.swift */; }; F359D86D2A7D03420023F405 /* NCUtility+Exif.swift in Sources */ = {isa = PBXBuildFile; fileRef = F359D8662A7D03420023F405 /* NCUtility+Exif.swift */; }; - F36E64F72B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBarDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36E64F62B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBarDelegate.swift */; }; + F36E64F72B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36E64F62B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBar.swift */; }; F36E64FA2B96236C0085ABB5 /* UIView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E41315294A19B300839300 /* UIView+Extension.swift */; }; F36E64FB2B9733F10085ABB5 /* UIView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E41315294A19B300839300 /* UIView+Extension.swift */; }; F36E64FC2B9733F20085ABB5 /* UIView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E41315294A19B300839300 /* UIView+Extension.swift */; }; @@ -218,12 +218,15 @@ F711A4EB2AF9327D00095DD8 /* UIImage+animatedGIF.m in Sources */ = {isa = PBXBuildFile; fileRef = F713FEFF2472764100214AF6 /* UIImage+animatedGIF.m */; }; F711A4EF2AF932B900095DD8 /* SVGKitSwift in Frameworks */ = {isa = PBXBuildFile; productRef = F711A4EE2AF932B900095DD8 /* SVGKitSwift */; }; F711D63128F44801003F43C8 /* IntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C9739428F17131002C43E2 /* IntentHandler.swift */; }; + F713FBE52C31645200F10760 /* NCNetworking+AsyncAwait.swift in Sources */ = {isa = PBXBuildFile; fileRef = F713FBE42C31645200F10760 /* NCNetworking+AsyncAwait.swift */; }; + F713FBE62C31646400F10760 /* NCNetworking+AsyncAwait.swift in Sources */ = {isa = PBXBuildFile; fileRef = F713FBE42C31645200F10760 /* NCNetworking+AsyncAwait.swift */; }; + F713FBE72C31646500F10760 /* NCNetworking+AsyncAwait.swift in Sources */ = {isa = PBXBuildFile; fileRef = F713FBE42C31645200F10760 /* NCNetworking+AsyncAwait.swift */; }; + F713FBE82C31646600F10760 /* NCNetworking+AsyncAwait.swift in Sources */ = {isa = PBXBuildFile; fileRef = F713FBE42C31645200F10760 /* NCNetworking+AsyncAwait.swift */; }; F713FF002472764100214AF6 /* UIImage+animatedGIF.m in Sources */ = {isa = PBXBuildFile; fileRef = F713FEFF2472764100214AF6 /* UIImage+animatedGIF.m */; }; F7145610296433C80038D028 /* NCDocumentCamera.swift in Sources */ = {isa = PBXBuildFile; fileRef = F714560F296433C80038D028 /* NCDocumentCamera.swift */; }; F7145A231D12E3B700CAFEEC /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = F7E70DE91A24DE4100E1B66A /* Localizable.strings */; }; F714803B262EBE3900693E51 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F714803A262EBE3900693E51 /* MainInterface.storyboard */; }; F7148041262EBE4000693E51 /* NCShareExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7148040262EBE4000693E51 /* NCShareExtension.swift */; }; - F714804F262ED4F900693E51 /* NCGridCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F78ACD4521903D010088454D /* NCGridCell.xib */; }; F7148054262ED51000693E51 /* NCListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F78ACD4321903CF20088454D /* NCListCell.xib */; }; F714805E262ED52900693E51 /* NCSectionFooter.xib in Resources */ = {isa = PBXBuildFile; fileRef = F78ACD53219047D40088454D /* NCSectionFooter.xib */; }; F7160A7D2BE931DE0034DCB3 /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = F7160A7C2BE931DE0034DCB3 /* RealmSwift */; }; @@ -407,6 +410,7 @@ F746EC51273906C40052598D /* NCViewCertificateDetails.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7BC287D26663F6C004D46C5 /* NCViewCertificateDetails.storyboard */; }; F746EC52273906C40052598D /* NCViewCertificateDetails.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7BC287D26663F6C004D46C5 /* NCViewCertificateDetails.storyboard */; }; F746EC53273906C50052598D /* NCViewCertificateDetails.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7BC287D26663F6C004D46C5 /* NCViewCertificateDetails.storyboard */; }; + F747EB0D2C4AC1FF00F959A8 /* NCCollectionViewCommon+CollectionViewDelegateFlowLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = F747EB0C2C4AC1FF00F959A8 /* NCCollectionViewCommon+CollectionViewDelegateFlowLayout.swift */; }; F7490E6B29882A92009DCE94 /* NCGlobal.swift in Sources */ = {isa = PBXBuildFile; fileRef = F702F2CE25EE5B5C008F8E80 /* NCGlobal.swift */; }; F7490E6C29882AEA009DCE94 /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extension.swift */; }; F7490E6E29882B56009DCE94 /* NCBrand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76B3CCD1EAE01BD00921AC9 /* NCBrand.swift */; }; @@ -463,6 +467,8 @@ F74DE14425135B6800917068 /* NCTransfers.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F74DE14225135B6800917068 /* NCTransfers.storyboard */; }; F7501C322212E57500FB1415 /* NCMedia.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7501C302212E57400FB1415 /* NCMedia.storyboard */; }; F7501C332212E57500FB1415 /* NCMedia.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7501C312212E57400FB1415 /* NCMedia.swift */; }; + F751247C2C42919C00E63DB8 /* NCPhotoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F751247A2C42919C00E63DB8 /* NCPhotoCell.swift */; }; + F751247E2C42919C00E63DB8 /* NCPhotoCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F751247B2C42919C00E63DB8 /* NCPhotoCell.xib */; }; F75379202AE2AD9400C0250E /* JGProgressHUD in Frameworks */ = {isa = PBXBuildFile; productRef = F753791F2AE2AD9400C0250E /* JGProgressHUD */; }; F75379222AE2ADA100C0250E /* JGProgressHUD in Frameworks */ = {isa = PBXBuildFile; productRef = F75379212AE2ADA100C0250E /* JGProgressHUD */; }; F753BA93281FD8020015BFB6 /* EasyTipView in Frameworks */ = {isa = PBXBuildFile; productRef = F753BA92281FD8020015BFB6 /* EasyTipView */; }; @@ -515,7 +521,6 @@ F765E9CD295C585800A09ED8 /* NCUploadScanDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = F765E9CC295C585800A09ED8 /* NCUploadScanDocument.swift */; }; F765F73125237E3F00391DBE /* NCRecent.swift in Sources */ = {isa = PBXBuildFile; fileRef = F765F72F25237E3F00391DBE /* NCRecent.swift */; }; F765F73225237E3F00391DBE /* NCRecent.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F765F73025237E3F00391DBE /* NCRecent.storyboard */; }; - F76673ED22C901F6007ED366 /* FileProviderDomain.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76673EC22C901F5007ED366 /* FileProviderDomain.swift */; }; F76673F022C90434007ED366 /* FileProviderUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76673EF22C90433007ED366 /* FileProviderUtility.swift */; }; F76687072B7D067400779E3F /* NCAudioRecorderViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76687052B7D067400779E3F /* NCAudioRecorderViewController.swift */; }; F76687082B7D067400779E3F /* NCAudioRecorderViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F76687062B7D067400779E3F /* NCAudioRecorderViewController.storyboard */; }; @@ -588,9 +593,12 @@ F7725A61251F33BB00D125E0 /* NCFiles.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7725A5F251F33BB00D125E0 /* NCFiles.storyboard */; }; F77333882927A72100466E35 /* OpenSSL in Frameworks */ = {isa = PBXBuildFile; productRef = F77333872927A72100466E35 /* OpenSSL */; }; F774264A22EB4D0000B23912 /* NCSearchUserDropDownCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F774264822EB4D0000B23912 /* NCSearchUserDropDownCell.xib */; }; + F7743A122C33F0A20034F670 /* NCCollectionViewCommon+CollectionViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7743A112C33F0A20034F670 /* NCCollectionViewCommon+CollectionViewDelegate.swift */; }; + F7743A142C33F13A0034F670 /* NCCollectionViewCommon+CollectionViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7743A132C33F13A0034F670 /* NCCollectionViewCommon+CollectionViewDataSource.swift */; }; F77444F522281649000D5EB0 /* NCGridMediaCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77444F322281649000D5EB0 /* NCGridMediaCell.swift */; }; F77444F622281649000D5EB0 /* NCGridMediaCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F77444F422281649000D5EB0 /* NCGridMediaCell.xib */; }; F77444F8222816D5000D5EB0 /* NCPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77444F7222816D5000D5EB0 /* NCPickerViewController.swift */; }; + F778231E2C42C07C001BB94F /* NCCollectionViewCommon+MediaLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = F778231D2C42C07C001BB94F /* NCCollectionViewCommon+MediaLayout.swift */; }; F77A697D250A0FBC00FF1708 /* NCCollectionViewCommon+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77A697C250A0FBC00FF1708 /* NCCollectionViewCommon+Menu.swift */; }; F77B0F631D118A16002130FE /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = F7E70DE91A24DE4100E1B66A /* Localizable.strings */; }; F77B0F7D1D118A16002130FE /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F7F67BB81A24D27800EE80DA /* Images.xcassets */; }; @@ -664,7 +672,7 @@ F78ACD4621903D010088454D /* NCGridCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F78ACD4521903D010088454D /* NCGridCell.xib */; }; F78ACD4A21903F850088454D /* NCTrashListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD4821903F850088454D /* NCTrashListCell.swift */; }; F78ACD4B21903F850088454D /* NCTrashListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F78ACD4921903F850088454D /* NCTrashListCell.xib */; }; - F78ACD52219046DC0088454D /* NCSectionHeaderMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD51219046DC0088454D /* NCSectionHeaderMenu.swift */; }; + F78ACD52219046DC0088454D /* NCSectionFirstHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD51219046DC0088454D /* NCSectionFirstHeader.swift */; }; F78ACD54219047D40088454D /* NCSectionFooter.xib in Resources */ = {isa = PBXBuildFile; fileRef = F78ACD53219047D40088454D /* NCSectionFooter.xib */; }; F78AF1E72BE938C100F3F060 /* MobileVLCKit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7792DE429EEE02D005930CE /* MobileVLCKit.xcframework */; }; F78AF1E82BE938C100F3F060 /* MobileVLCKit.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F7792DE429EEE02D005930CE /* MobileVLCKit.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -691,6 +699,12 @@ F798F0E225880608000DAFFD /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extension.swift */; }; F798F0E725880609000DAFFD /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extension.swift */; }; F798F0EC2588060A000DAFFD /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extension.swift */; }; + F799DF822C4B7DCC003410B5 /* NCSectionFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F799DF812C4B7DCC003410B5 /* NCSectionFooter.swift */; }; + F799DF832C4B7DCC003410B5 /* NCSectionFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F799DF812C4B7DCC003410B5 /* NCSectionFooter.swift */; }; + F799DF852C4B7E56003410B5 /* NCSectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F799DF842C4B7E56003410B5 /* NCSectionHeader.swift */; }; + F799DF862C4B7E56003410B5 /* NCSectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F799DF842C4B7E56003410B5 /* NCSectionHeader.swift */; }; + F799DF882C4B83CC003410B5 /* NCCollectionViewCommon+EasyTipView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F799DF872C4B83CC003410B5 /* NCCollectionViewCommon+EasyTipView.swift */; }; + F799DF8B2C4B84EB003410B5 /* NCCollectionViewCommon+EndToEndInitialize.swift in Sources */ = {isa = PBXBuildFile; fileRef = F799DF8A2C4B84EB003410B5 /* NCCollectionViewCommon+EndToEndInitialize.swift */; }; F79A65C32191D90F00FF6DCC /* NCSelect.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F79A65C22191D90F00FF6DCC /* NCSelect.storyboard */; }; F79A65C62191D95E00FF6DCC /* NCSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = F79A65C52191D95E00FF6DCC /* NCSelect.swift */; }; F79B646026CA661600838ACA /* UIControl+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F79B645F26CA661600838ACA /* UIControl+Extension.swift */; }; @@ -716,6 +730,7 @@ F7A560442AE15D2900BE8FD6 /* Queuer in Frameworks */ = {isa = PBXBuildFile; productRef = F7A560432AE15D2900BE8FD6 /* Queuer */; }; F7A560462AE15D3D00BE8FD6 /* Queuer in Frameworks */ = {isa = PBXBuildFile; productRef = F7A560452AE15D3D00BE8FD6 /* Queuer */; }; F7A560482AE15D5000BE8FD6 /* Queuer in Frameworks */ = {isa = PBXBuildFile; productRef = F7A560472AE15D5000BE8FD6 /* Queuer */; }; + F7A5DF052C3FD11800753FC4 /* FileProviderExtension+NetworkingDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A5DF042C3FD11800753FC4 /* FileProviderExtension+NetworkingDelegate.swift */; }; F7A60F86292D215000FCE1F2 /* NCShareAccounts.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A60F84292D215000FCE1F2 /* NCShareAccounts.swift */; }; F7A60F87292D215000FCE1F2 /* NCShareAccounts.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7A60F85292D215000FCE1F2 /* NCShareAccounts.storyboard */; }; F7A76DC8256A71CD00119AB3 /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extension.swift */; }; @@ -746,8 +761,8 @@ F7AE00FA230E81EB007ACF8A /* NCBrowserWeb.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7AE00F9230E81EB007ACF8A /* NCBrowserWeb.storyboard */; }; F7AEEAA62C11DBAF00011412 /* NCAccountSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7AEEAA52C11DBAF00011412 /* NCAccountSettingsView.swift */; }; F7AEEAA82C11DBFD00011412 /* NCAccountSettingsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7AEEAA72C11DBFD00011412 /* NCAccountSettingsModel.swift */; }; - F7B398422A6A91D5007538D6 /* NCSectionHeaderMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7B398412A6A91D5007538D6 /* NCSectionHeaderMenu.xib */; }; - F7B398432A6A91D5007538D6 /* NCSectionHeaderMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7B398412A6A91D5007538D6 /* NCSectionHeaderMenu.xib */; }; + F7B398422A6A91D5007538D6 /* NCSectionFirstHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7B398412A6A91D5007538D6 /* NCSectionFirstHeader.xib */; }; + F7B398432A6A91D5007538D6 /* NCSectionFirstHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7B398412A6A91D5007538D6 /* NCSectionFirstHeader.xib */; }; F7B6B70427C4E7FA00A7F6EB /* NCScan+CollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B6B70327C4E7FA00A7F6EB /* NCScan+CollectionView.swift */; }; F7B7504B2397D38F004E13EC /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extension.swift */; }; F7B769A82B7A0B2000C1AAEB /* NCManageDatabase+Metadata+Session.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B769A72B7A0B2000C1AAEB /* NCManageDatabase+Metadata+Session.swift */; }; @@ -764,6 +779,9 @@ 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 */; }; + F7BD0A002C468925003A4A6D /* NCMedia+CollectionViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BD09FF2C468925003A4A6D /* NCMedia+CollectionViewDataSource.swift */; }; + F7BD0A022C4689A4003A4A6D /* NCMedia+CollectionViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BD0A012C4689A4003A4A6D /* NCMedia+CollectionViewDelegate.swift */; }; + F7BD0A042C4689E9003A4A6D /* NCMedia+MediaLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BD0A032C4689E9003A4A6D /* NCMedia+MediaLayout.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 */; }; @@ -771,6 +789,7 @@ F7BF9D852934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BF9D812934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift */; }; F7BF9D862934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BF9D812934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift */; }; F7BF9D872934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BF9D812934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift */; }; + F7C1DAEF2C3D1DF4000BDC69 /* FileProviderDomain.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76673EC22C901F5007ED366 /* FileProviderDomain.swift */; }; F7C1EEA525053A9C00866ACC /* NCDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C1EEA425053A9C00866ACC /* NCDataSource.swift */; }; F7C30DF6291BC0CA0017149B /* NCNetworkingE2EEUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C30DF5291BC0CA0017149B /* NCNetworkingE2EEUpload.swift */; }; F7C30DF7291BC0D30017149B /* NCNetworkingE2EEUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C30DF5291BC0CA0017149B /* NCNetworkingE2EEUpload.swift */; }; @@ -798,10 +817,10 @@ 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 */; }; - F7CBC1232BAC8B0000EC1D55 /* NCSectionHeaderEmptyData.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7CBC1212BAC8B0000EC1D55 /* NCSectionHeaderEmptyData.xib */; }; - F7CBC1242BAC8B0000EC1D55 /* NCSectionHeaderEmptyData.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7CBC1212BAC8B0000EC1D55 /* NCSectionHeaderEmptyData.xib */; }; - F7CBC1252BAC8B0000EC1D55 /* NCSectionHeaderEmptyData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CBC1222BAC8B0000EC1D55 /* NCSectionHeaderEmptyData.swift */; }; - F7CBC1262BAC8B0000EC1D55 /* NCSectionHeaderEmptyData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CBC1222BAC8B0000EC1D55 /* NCSectionHeaderEmptyData.swift */; }; + F7CBC1232BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7CBC1212BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.xib */; }; + F7CBC1242BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7CBC1212BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.xib */; }; + F7CBC1252BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CBC1222BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.swift */; }; + F7CBC1262BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CBC1222BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.swift */; }; F7CEE6002BA9A5C9003EFD89 /* NCTrashGridCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7CEE5FE2BA9A5C9003EFD89 /* NCTrashGridCell.xib */; }; F7CEE6012BA9A5C9003EFD89 /* NCTrashGridCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CEE5FF2BA9A5C9003EFD89 /* NCTrashGridCell.swift */; }; F7D1612023CF19E30039EBBF /* NCViewerRichWorkspace.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7D1611F23CF19E30039EBBF /* NCViewerRichWorkspace.storyboard */; }; @@ -840,8 +859,7 @@ F7EDE4D1262D7B8400414FE6 /* NCDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C1EEA425053A9C00866ACC /* NCDataSource.swift */; }; F7EDE4D6262D7B9600414FE6 /* NCListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD4121903CE00088454D /* NCListCell.swift */; }; F7EDE4DB262D7BA200414FE6 /* NCCellProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370D26AE248A3D7A00121797 /* NCCellProtocol.swift */; }; - F7EDE4E0262D7BAF00414FE6 /* NCGridCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD3F21903CC20088454D /* NCGridCell.swift */; }; - F7EDE4E5262D7BBE00414FE6 /* NCSectionHeaderMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD51219046DC0088454D /* NCSectionHeaderMenu.swift */; }; + F7EDE4E5262D7BBE00414FE6 /* NCSectionFirstHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD51219046DC0088454D /* NCSectionFirstHeader.swift */; }; F7EDE509262DA9D600414FE6 /* NCSelectCommandViewSelect.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7EDE508262DA9D600414FE6 /* NCSelectCommandViewSelect.xib */; }; F7EDE514262DC2CD00414FE6 /* NCSelectCommandViewSelect+CreateFolder.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7EDE513262DC2CD00414FE6 /* NCSelectCommandViewSelect+CreateFolder.xib */; }; F7EDE51B262DD0C400414FE6 /* NCSelectCommandViewCopyMove.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7EDE51A262DD0C400414FE6 /* NCSelectCommandViewCopyMove.xib */; }; @@ -1093,9 +1111,9 @@ AF8ED1FB2757821000B8DBC4 /* NextcloudUnitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextcloudUnitTests.swift; sourceTree = ""; }; AF93471127E2341B002537EE /* NCShare+Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Menu.swift"; sourceTree = ""; }; AF93471427E2361E002537EE /* NCShareAdvancePermissionFooter.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCShareAdvancePermissionFooter.xib; sourceTree = ""; }; - AF93471527E2361E002537EE /* NCShareAdvancePermissionHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCShareAdvancePermissionHeader.swift; sourceTree = ""; }; + AF93471527E2361E002537EE /* NCShareHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCShareHeader.swift; sourceTree = ""; }; AF93471627E2361E002537EE /* NCShareAdvancePermission.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCShareAdvancePermission.swift; sourceTree = ""; }; - AF93471727E2361E002537EE /* NCShareAdvancePermissionHeader.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCShareAdvancePermissionHeader.xib; sourceTree = ""; }; + AF93471727E2361E002537EE /* NCShareHeader.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCShareHeader.xib; sourceTree = ""; }; AF93471827E2361E002537EE /* NCShareAdvancePermissionFooter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCShareAdvancePermissionFooter.swift; sourceTree = ""; }; AF93474B27E34120002537EE /* NCUtility+Image.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCUtility+Image.swift"; sourceTree = ""; }; AF93474D27E3F211002537EE /* NCShareNewUserAddComment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCShareNewUserAddComment.swift; sourceTree = ""; }; @@ -1118,7 +1136,7 @@ F343A4B22A1E01FF00DDA874 /* PHAsset+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PHAsset+Extension.swift"; sourceTree = ""; }; F343A4BA2A1E734600DDA874 /* Optional+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Optional+Extension.swift"; sourceTree = ""; }; F359D8662A7D03420023F405 /* NCUtility+Exif.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCUtility+Exif.swift"; sourceTree = ""; }; - F36E64F62B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBarDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCCollectionViewCommon+SelectTabBarDelegate.swift"; sourceTree = ""; }; + F36E64F62B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCCollectionViewCommon+SelectTabBar.swift"; sourceTree = ""; }; F37208742BAB4AB0006B5430 /* TestConstants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestConstants.swift; sourceTree = ""; }; F37208772BAB4B5D006B5430 /* BaseXCTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseXCTestCase.swift; sourceTree = ""; }; F38F71242B6BBDC300473CDC /* NCCollectionViewCommonSelectTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCollectionViewCommonSelectTabBar.swift; sourceTree = ""; }; @@ -1208,6 +1226,7 @@ F710D1F42405770F00A6033D /* NCViewerPDF.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCViewerPDF.swift; sourceTree = ""; }; F710D2012405826100A6033D /* NCViewer+Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCViewer+Menu.swift"; sourceTree = ""; }; F711A4DB2AF92CAD00095DD8 /* NCUtility+Date.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCUtility+Date.swift"; sourceTree = ""; }; + F713FBE42C31645200F10760 /* NCNetworking+AsyncAwait.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCNetworking+AsyncAwait.swift"; sourceTree = ""; }; F713FEFE2472764000214AF6 /* UIImage+animatedGIF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+animatedGIF.h"; sourceTree = ""; }; F713FEFF2472764100214AF6 /* UIImage+animatedGIF.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+animatedGIF.m"; sourceTree = ""; }; F714560F296433C80038D028 /* NCDocumentCamera.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCDocumentCamera.swift; sourceTree = ""; }; @@ -1299,6 +1318,7 @@ F7421EAE2294044B00C4B7C1 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; F745B250222D871800346520 /* QRCodeReader.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QRCodeReader.framework; path = Carthage/Build/iOS/QRCodeReader.framework; sourceTree = ""; }; F745B252222D88AE00346520 /* NCLoginQRCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCLoginQRCode.swift; sourceTree = ""; }; + F747EB0C2C4AC1FF00F959A8 /* NCCollectionViewCommon+CollectionViewDelegateFlowLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCCollectionViewCommon+CollectionViewDelegateFlowLayout.swift"; sourceTree = ""; }; F749B649297B0CBB00087535 /* NCManageDatabase+Share.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+Share.swift"; sourceTree = ""; }; F749B650297B0F2400087535 /* NCManageDatabase+Avatar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+Avatar.swift"; sourceTree = ""; }; F74AF3A3247FB6AE00AC767B /* NCUtilityFileSystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCUtilityFileSystem.swift; sourceTree = ""; }; @@ -1311,6 +1331,8 @@ F74DE14225135B6800917068 /* NCTransfers.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCTransfers.storyboard; sourceTree = ""; }; F7501C302212E57400FB1415 /* NCMedia.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCMedia.storyboard; sourceTree = ""; }; F7501C312212E57400FB1415 /* NCMedia.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCMedia.swift; sourceTree = ""; }; + F751247A2C42919C00E63DB8 /* NCPhotoCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCPhotoCell.swift; sourceTree = ""; }; + F751247B2C42919C00E63DB8 /* NCPhotoCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCPhotoCell.xib; sourceTree = ""; }; F75153232226920200323DDC /* FastScroll.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FastScroll.framework; path = Carthage/Build/iOS/FastScroll.framework; sourceTree = ""; }; F753701822723D620041C76C /* gl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = gl; path = gl.lproj/Localizable.strings; sourceTree = ""; }; F753701922723E0D0041C76C /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/Localizable.strings; sourceTree = ""; }; @@ -1420,9 +1442,12 @@ F77439541FCD6D6100662C46 /* es-PY */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-PY"; path = "es-PY.lproj/Localizable.strings"; sourceTree = ""; }; F774395B1FCD6D8200662C46 /* es-SV */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-SV"; path = "es-SV.lproj/Localizable.strings"; sourceTree = ""; }; F77439621FCD6D9C00662C46 /* es-UY */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-UY"; path = "es-UY.lproj/Localizable.strings"; sourceTree = ""; }; + F7743A112C33F0A20034F670 /* NCCollectionViewCommon+CollectionViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCCollectionViewCommon+CollectionViewDelegate.swift"; sourceTree = ""; }; + F7743A132C33F13A0034F670 /* NCCollectionViewCommon+CollectionViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCCollectionViewCommon+CollectionViewDataSource.swift"; sourceTree = ""; }; F77444F322281649000D5EB0 /* NCGridMediaCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCGridMediaCell.swift; sourceTree = ""; }; F77444F422281649000D5EB0 /* NCGridMediaCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCGridMediaCell.xib; sourceTree = ""; }; F77444F7222816D5000D5EB0 /* NCPickerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCPickerViewController.swift; sourceTree = ""; }; + F778231D2C42C07C001BB94F /* NCCollectionViewCommon+MediaLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCCollectionViewCommon+MediaLayout.swift"; sourceTree = ""; }; F7792DE429EEE02D005930CE /* MobileVLCKit.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = MobileVLCKit.xcframework; path = Carthage/Build/MobileVLCKit.xcframework; sourceTree = ""; }; F77A697C250A0FBC00FF1708 /* NCCollectionViewCommon+Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCCollectionViewCommon+Menu.swift"; sourceTree = ""; }; F77BB745289984CA0090FC19 /* UIViewController+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extension.swift"; sourceTree = ""; }; @@ -1452,7 +1477,7 @@ F78ACD4521903D010088454D /* NCGridCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCGridCell.xib; sourceTree = ""; }; F78ACD4821903F850088454D /* NCTrashListCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCTrashListCell.swift; sourceTree = ""; }; 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 = ""; }; + F78ACD51219046DC0088454D /* NCSectionFirstHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSectionFirstHeader.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 = ""; }; @@ -1471,6 +1496,10 @@ F794E13E2BBC0F70003693D7 /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; F79918A021997F9000C2E308 /* UICKeyChainStore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UICKeyChainStore.framework; path = Carthage/Build/iOS/UICKeyChainStore.framework; sourceTree = ""; }; F79918A72199840500C2E308 /* Sheeeeeeeeet.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sheeeeeeeeet.framework; path = Carthage/Build/iOS/Sheeeeeeeeet.framework; sourceTree = ""; }; + F799DF812C4B7DCC003410B5 /* NCSectionFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSectionFooter.swift; sourceTree = ""; }; + F799DF842C4B7E56003410B5 /* NCSectionHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSectionHeader.swift; sourceTree = ""; }; + F799DF872C4B83CC003410B5 /* NCCollectionViewCommon+EasyTipView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCCollectionViewCommon+EasyTipView.swift"; sourceTree = ""; }; + F799DF8A2C4B84EB003410B5 /* NCCollectionViewCommon+EndToEndInitialize.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCCollectionViewCommon+EndToEndInitialize.swift"; sourceTree = ""; }; F79A65C22191D90F00FF6DCC /* NCSelect.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCSelect.storyboard; sourceTree = ""; }; F79A65C52191D95E00FF6DCC /* NCSelect.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSelect.swift; sourceTree = ""; }; F79B645F26CA661600838ACA /* UIControl+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIControl+Extension.swift"; sourceTree = ""; }; @@ -1483,6 +1512,7 @@ F7A48414297028FC00BD1B49 /* Nextcloud Hub.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Nextcloud Hub.png"; sourceTree = SOURCE_ROOT; }; F7A509242C26BD5D00326106 /* NCCreateDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCreateDocument.swift; sourceTree = ""; }; F7A560412AE1593700BE8FD6 /* NCOperationSaveLivePhoto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCOperationSaveLivePhoto.swift; sourceTree = ""; }; + F7A5DF042C3FD11800753FC4 /* FileProviderExtension+NetworkingDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileProviderExtension+NetworkingDelegate.swift"; sourceTree = ""; }; F7A60F84292D215000FCE1F2 /* NCShareAccounts.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCShareAccounts.swift; sourceTree = ""; }; F7A60F85292D215000FCE1F2 /* NCShareAccounts.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCShareAccounts.storyboard; sourceTree = ""; }; F7A7FDDB2C2DBD6200E9A93A /* NCDeepLinkHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCDeepLinkHandler.swift; sourceTree = ""; }; @@ -1539,7 +1569,7 @@ F7AF7632246BEDFE00B86E3C /* TOPasscodeViewController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TOPasscodeViewController.framework; path = Carthage/Build/iOS/TOPasscodeViewController.framework; sourceTree = ""; }; F7B1076C25D3CF2800E72DE2 /* BackgroundTasks.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BackgroundTasks.framework; path = System/Library/Frameworks/BackgroundTasks.framework; sourceTree = SDKROOT; }; F7B1A7761EBB3C8000BFB6D1 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; - F7B398412A6A91D5007538D6 /* NCSectionHeaderMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCSectionHeaderMenu.xib; sourceTree = ""; }; + F7B398412A6A91D5007538D6 /* NCSectionFirstHeader.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCSectionFirstHeader.xib; sourceTree = ""; }; F7B6B70327C4E7FA00A7F6EB /* NCScan+CollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCScan+CollectionView.swift"; sourceTree = ""; }; F7B7504A2397D38E004E13EC /* UIImage+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Extension.swift"; sourceTree = ""; }; F7B769A72B7A0B2000C1AAEB /* NCManageDatabase+Metadata+Session.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+Metadata+Session.swift"; sourceTree = ""; }; @@ -1549,6 +1579,9 @@ 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 = ""; }; + F7BD09FF2C468925003A4A6D /* NCMedia+CollectionViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCMedia+CollectionViewDataSource.swift"; sourceTree = ""; }; + F7BD0A012C4689A4003A4A6D /* NCMedia+CollectionViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCMedia+CollectionViewDelegate.swift"; sourceTree = ""; }; + F7BD0A032C4689E9003A4A6D /* NCMedia+MediaLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCMedia+MediaLayout.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 = ""; }; @@ -1620,8 +1653,8 @@ 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 = ""; }; - F7CBC1212BAC8B0000EC1D55 /* NCSectionHeaderEmptyData.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCSectionHeaderEmptyData.xib; sourceTree = ""; }; - F7CBC1222BAC8B0000EC1D55 /* NCSectionHeaderEmptyData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCSectionHeaderEmptyData.swift; sourceTree = ""; }; + F7CBC1212BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCSectionFirstHeaderEmptyData.xib; sourceTree = ""; }; + F7CBC1222BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCSectionFirstHeaderEmptyData.swift; sourceTree = ""; }; F7CC04E61F5AD50D00378CEF /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; F7CE8AFA1DC1F8D8009CAE48 /* Nextcloud.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Nextcloud.app; sourceTree = BUILT_PRODUCTS_DIR; }; F7CE8AFB1DC1F8D8009CAE48 /* Share.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Share.appex; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1899,8 +1932,6 @@ AF93471627E2361E002537EE /* NCShareAdvancePermission.swift */, AF93471827E2361E002537EE /* NCShareAdvancePermissionFooter.swift */, AF93471427E2361E002537EE /* NCShareAdvancePermissionFooter.xib */, - AF93471527E2361E002537EE /* NCShareAdvancePermissionHeader.swift */, - AF93471727E2361E002537EE /* NCShareAdvancePermissionHeader.xib */, AFCE353627E4ED7B00FEA6C2 /* NCShareCells.swift */, AF93474D27E3F211002537EE /* NCShareNewUserAddComment.swift */, ); @@ -2126,6 +2157,8 @@ F774264822EB4D0000B23912 /* NCSearchUserDropDownCell.xib */, F769453B22E9CFFF000A798A /* NCShareUserCell.xib */, AF2D7C7D2742559100ADF566 /* NCShareUserCell.swift */, + AF93471727E2361E002537EE /* NCShareHeader.xib */, + AF93471527E2361E002537EE /* NCShareHeader.swift */, ); path = Share; sourceTree = ""; @@ -2199,6 +2232,7 @@ F72CD63925C19EBF00F46F9A /* NCAutoUpload.swift */, F77BC3EC293E528A005F2B08 /* NCConfigServer.swift */, F75A9EE523796C6F0044CFCE /* NCNetworking.swift */, + F713FBE42C31645200F10760 /* NCNetworking+AsyncAwait.swift */, F7327E1F2B73A42F00A462C7 /* NCNetworking+Download.swift */, F7327E272B73A53400A462C7 /* NCNetworking+Upload.swift */, F7327E2F2B73A86700A462C7 /* NCNetworking+WebDAV.swift */, @@ -2245,6 +2279,8 @@ isa = PBXGroup; children = ( 370D26AE248A3D7A00121797 /* NCCellProtocol.swift */, + F751247A2C42919C00E63DB8 /* NCPhotoCell.swift */, + F751247B2C42919C00E63DB8 /* NCPhotoCell.xib */, F78ACD3F21903CC20088454D /* NCGridCell.swift */, F78ACD4521903D010088454D /* NCGridCell.xib */, F78ACD4121903CE00088454D /* NCListCell.swift */, @@ -2259,8 +2295,14 @@ F75FE06B2BB01D0D00A0EFEF /* Cell */, F78ACD50219046AC0088454D /* Section Header Footer */, F70D7C3525FFBF81002B9E34 /* NCCollectionViewCommon.swift */, + F799DF8A2C4B84EB003410B5 /* NCCollectionViewCommon+EndToEndInitialize.swift */, + F799DF872C4B83CC003410B5 /* NCCollectionViewCommon+EasyTipView.swift */, + F747EB0C2C4AC1FF00F959A8 /* NCCollectionViewCommon+CollectionViewDelegateFlowLayout.swift */, + F7743A132C33F13A0034F670 /* NCCollectionViewCommon+CollectionViewDataSource.swift */, + F7743A112C33F0A20034F670 /* NCCollectionViewCommon+CollectionViewDelegate.swift */, + F778231D2C42C07C001BB94F /* NCCollectionViewCommon+MediaLayout.swift */, F7D890742BD25C570050B8A6 /* NCCollectionViewCommon+DragDrop.swift */, - F36E64F62B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBarDelegate.swift */, + F36E64F62B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBar.swift */, F38F71242B6BBDC300473CDC /* NCCollectionViewCommonSelectTabBar.swift */, F7E7AEA42BA32C6500512E52 /* NCCollectionViewDownloadThumbnail.swift */, F7E7AEA62BA32D0000512E52 /* NCCollectionViewUnifiedSearch.swift */, @@ -2428,6 +2470,7 @@ F76673EC22C901F5007ED366 /* FileProviderDomain.swift */, F771E3D620E2392D00AFB62D /* FileProviderEnumerator.swift */, F771E3D220E2392D00AFB62D /* FileProviderExtension.swift */, + F7A5DF042C3FD11800753FC4 /* FileProviderExtension+NetworkingDelegate.swift */, F771E3F420E239B400AFB62D /* FileProviderExtension+Actions.swift */, F771E3F520E239B400AFB62D /* FileProviderExtension+Thumbnail.swift */, F771E3D420E2392D00AFB62D /* FileProviderItem.swift */, @@ -2470,12 +2513,14 @@ F78ACD50219046AC0088454D /* Section Header Footer */ = { isa = PBXGroup; children = ( + F78ACD51219046DC0088454D /* NCSectionFirstHeader.swift */, + F7B398412A6A91D5007538D6 /* NCSectionFirstHeader.xib */, + F7CBC1222BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.swift */, + F7CBC1212BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.xib */, + F799DF812C4B7DCC003410B5 /* NCSectionFooter.swift */, F78ACD53219047D40088454D /* NCSectionFooter.xib */, + F799DF842C4B7E56003410B5 /* NCSectionHeader.swift */, F7FF2CB02842159500EBB7A1 /* NCSectionHeader.xib */, - F7CBC1222BAC8B0000EC1D55 /* NCSectionHeaderEmptyData.swift */, - F7CBC1212BAC8B0000EC1D55 /* NCSectionHeaderEmptyData.xib */, - F7B398412A6A91D5007538D6 /* NCSectionHeaderMenu.xib */, - F78ACD51219046DC0088454D /* NCSectionHeaderMenu.swift */, ); path = "Section Header Footer"; sourceTree = ""; @@ -2595,8 +2640,8 @@ isa = PBXGroup; children = ( F7C9555221F0C4CA0024296E /* NCActivity.storyboard */, - AF56C1DB2784856200D8BAE2 /* NCActivityCommentView.xib */, F7C9555421F0C5470024296E /* NCActivity.swift */, + AF56C1DB2784856200D8BAE2 /* NCActivityCommentView.xib */, AFA2AC8427849604008E1EA7 /* NCActivityCommentView.swift */, D5B6AA7727200C7200D49C24 /* NCActivityTableViewCell.swift */, ); @@ -2826,8 +2871,11 @@ F720B5B72507B9A5008C94E5 /* Cell */, F7501C302212E57400FB1415 /* NCMedia.storyboard */, F7501C312212E57400FB1415 /* NCMedia.swift */, + F7BD09FF2C468925003A4A6D /* NCMedia+CollectionViewDataSource.swift */, + F7BD0A012C4689A4003A4A6D /* NCMedia+CollectionViewDelegate.swift */, F72408322B8A27C900F128E2 /* NCMedia+Command.swift */, F7802B312BD5584F00D74270 /* NCMedia+DragDrop.swift */, + F7BD0A032C4689E9003A4A6D /* NCMedia+MediaLayout.swift */, F78B87E62B62527100C65ADC /* NCMediaDataSource.swift */, F78B87E82B62550800C65ADC /* NCMediaDownloadThumbnaill.swift */, F755CB3F2B8CB13C00CE27E9 /* NCMediaLayout.swift */, @@ -3614,14 +3662,13 @@ F7D57C8626317BDA00DE301D /* NCAccountRequest.storyboard in Resources */, F7E4022C2BA85D1D007E5609 /* PrivacyInfo.xcprivacy in Resources */, AF22B209277B4E4C00DAB0CC /* NCCreateFormUploadConflictCell.xib in Resources */, - F7CBC1242BAC8B0000EC1D55 /* NCSectionHeaderEmptyData.xib in Resources */, - F7B398432A6A91D5007538D6 /* NCSectionHeaderMenu.xib in Resources */, + F7CBC1242BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.xib in Resources */, + F7B398432A6A91D5007538D6 /* NCSectionFirstHeader.xib in Resources */, AF22B207277B4E4C00DAB0CC /* NCCreateFormUploadConflict.storyboard in Resources */, F7145A231D12E3B700CAFEEC /* Localizable.strings in Resources */, F746EC51273906C40052598D /* NCViewCertificateDetails.storyboard in Resources */, F76C26A62850D3A500E42BDF /* Images.xcassets in Resources */, F79EC784263161BA004E59D6 /* NCRenameFile.storyboard in Resources */, - F714804F262ED4F900693E51 /* NCGridCell.xib in Resources */, F714805E262ED52900693E51 /* NCSectionFooter.xib in Resources */, F700222D1EC479840080073F /* Custom.xcassets in Resources */, ); @@ -3678,7 +3725,7 @@ F7F4F10B27ECDBDB008676F9 /* Inconsolata-Light.ttf in Resources */, F7CEE6002BA9A5C9003EFD89 /* NCTrashGridCell.xib in Resources */, 3704EB2A23D5A58400455C5B /* NCMenu.storyboard in Resources */, - AF93471C27E2361E002537EE /* NCShareAdvancePermissionHeader.xib in Resources */, + AF93471C27E2361E002537EE /* NCShareHeader.xib in Resources */, F76032A0252F0F8E0015A421 /* NCTransferCell.xib in Resources */, F7F4F10527ECDBDB008676F9 /* Inconsolata-SemiBold.ttf in Resources */, F7A48415297028FC00BD1B49 /* Nextcloud Hub.png in Resources */, @@ -3695,7 +3742,7 @@ F78ACD4B21903F850088454D /* NCTrashListCell.xib in Resources */, AF93471927E2361E002537EE /* NCShareAdvancePermissionFooter.xib in Resources */, F7725A61251F33BB00D125E0 /* NCFiles.storyboard in Resources */, - F7CBC1232BAC8B0000EC1D55 /* NCSectionHeaderEmptyData.xib in Resources */, + F7CBC1232BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.xib in Resources */, F700510122DF63AC003A3356 /* NCShare.storyboard in Resources */, F787704F22E7019900F287A9 /* NCShareLinkCell.xib in Resources */, F70753F72542A9C000972D44 /* NCViewerMediaPage.storyboard in Resources */, @@ -3710,6 +3757,7 @@ F7C9555321F0C4CA0024296E /* NCActivity.storyboard in Resources */, F7BC287E26663F6C004D46C5 /* NCViewCertificateDetails.storyboard in Resources */, F78ACD54219047D40088454D /* NCSectionFooter.xib in Resources */, + F751247E2C42919C00E63DB8 /* NCPhotoCell.xib in Resources */, F704B5E32430AA6F00632F5F /* NCCreateFormUploadConflict.storyboard in Resources */, F7EDE509262DA9D600414FE6 /* NCSelectCommandViewSelect.xib in Resources */, F732D23327CF8AED000B0F1B /* NCPlayerToolBar.xib in Resources */, @@ -3726,7 +3774,7 @@ F73CB3B222E072A000AD728E /* NCShareHeaderView.xib in Resources */, F7AE00FA230E81EB007ACF8A /* NCBrowserWeb.storyboard in Resources */, F7EDE514262DC2CD00414FE6 /* NCSelectCommandViewSelect+CreateFolder.xib in Resources */, - F7B398422A6A91D5007538D6 /* NCSectionHeaderMenu.xib in Resources */, + F7B398422A6A91D5007538D6 /* NCSectionFirstHeader.xib in Resources */, F7501C322212E57500FB1415 /* NCMedia.storyboard in Resources */, F74DE14425135B6800917068 /* NCTransfers.storyboard in Resources */, F76687082B7D067400779E3F /* NCAudioRecorderViewController.storyboard in Resources */, @@ -3916,7 +3964,7 @@ F7864ACF2A78FE73004870E0 /* NCManageDatabase+LocalFile.swift in Sources */, F71F6D0A2B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */, F7245925289BB59100474787 /* ThreadSafeDictionary.swift in Sources */, - F7EDE4E5262D7BBE00414FE6 /* NCSectionHeaderMenu.swift in Sources */, + F7EDE4E5262D7BBE00414FE6 /* NCSectionFirstHeader.swift in Sources */, F7BF9D852934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */, F79EC78926316AC4004E59D6 /* NCPopupViewController.swift in Sources */, F7C30DFB291BCF790017149B /* NCNetworkingE2EECreateFolder.swift in Sources */, @@ -3924,7 +3972,7 @@ F7817CFB29801A3500FFBC65 /* Data+Extension.swift in Sources */, F72429362AFE39860040AEF3 /* NCLivePhoto.swift in Sources */, AF4BF61F27562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */, - F7CBC1262BAC8B0000EC1D55 /* NCSectionHeaderEmptyData.swift in Sources */, + F7CBC1262BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.swift in Sources */, F7A0D1362591FBC5008F8A13 /* String+Extension.swift in Sources */, F7EDE4D6262D7B9600414FE6 /* NCListCell.swift in Sources */, F7327E372B73AEDE00A462C7 /* NCNetworking+LivePhoto.swift in Sources */, @@ -3960,7 +4008,9 @@ F7BD71E62636EAFC00643C34 /* NCNetworkingE2EE.swift in Sources */, F7F878AF1FB9E3B900599E4F /* NCEndToEndMetadata.swift in Sources */, F7327E3B2B73B8D600A462C7 /* Array+Extension.swift in Sources */, + F799DF832C4B7DCC003410B5 /* NCSectionFooter.swift in Sources */, AF22B218277D196700DAB0CC /* NCShareExtension+Files.swift in Sources */, + F799DF862C4B7E56003410B5 /* NCSectionHeader.swift in Sources */, F702F2D025EE5B5C008F8E80 /* NCGlobal.swift in Sources */, F343A4BE2A1E734600DDA874 /* Optional+Extension.swift in Sources */, F72437802C10B92400C7C68D /* NCPermissions.swift in Sources */, @@ -3975,7 +4025,6 @@ F7327E232B73A42F00A462C7 /* NCNetworking+Download.swift in Sources */, F749B64D297B0CBB00087535 /* NCManageDatabase+Share.swift in Sources */, F72FD3B8297ED49A00075D28 /* NCManageDatabase+E2EE.swift in Sources */, - F7EDE4E0262D7BAF00414FE6 /* NCGridCell.swift in Sources */, F7A76DC8256A71CD00119AB3 /* UIImage+Extension.swift in Sources */, F711A4E52AF9310500095DD8 /* NCUtility+Image.swift in Sources */, F73EF7AA2B0223900087E6E9 /* NCManageDatabase+Comments.swift in Sources */, @@ -3987,6 +4036,7 @@ F7D57C8B26317BDE00DE301D /* NCAccountRequest.swift in Sources */, F7C30DF7291BC0D30017149B /* NCNetworkingE2EEUpload.swift in Sources */, F78A10C229322E8A008499B8 /* NCManageDatabase+Directory.swift in Sources */, + F713FBE72C31646500F10760 /* NCNetworking+AsyncAwait.swift in Sources */, F79FFB272A97C24A0055EEA4 /* NCNetworkingE2EEMarkFolder.swift in Sources */, F7D68FCE28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */, F73EF7B22B0224350087E6E9 /* NCManageDatabase+DirectEditing.swift in Sources */, @@ -4025,6 +4075,7 @@ F359D8682A7D03420023F405 /* NCUtility+Exif.swift in Sources */, F7346E1628B0EF5C006CE2D2 /* Widget.swift in Sources */, F78302F828B4C3E100B84583 /* NCManageDatabase+Activity.swift in Sources */, + F713FBE62C31646400F10760 /* NCNetworking+AsyncAwait.swift in Sources */, F711A4E92AF9327600095DD8 /* UIImage+animatedGIF.m in Sources */, F73EF7D02B0225BA0087E6E9 /* NCManageDatabase+Tag.swift in Sources */, F783030228B4C4B800B84583 /* NCUtility.swift in Sources */, @@ -4096,6 +4147,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + F713FBE82C31646600F10760 /* NCNetworking+AsyncAwait.swift in Sources */, F36E64FC2B9733F20085ABB5 /* UIView+Extension.swift in Sources */, F771E3F720E239B500AFB62D /* FileProviderExtension+Actions.swift in Sources */, F7245926289BB59300474787 /* ThreadSafeDictionary.swift in Sources */, @@ -4124,6 +4176,7 @@ F7327E2C2B73A53400A462C7 /* NCNetworking+Upload.swift in Sources */, F7D68FCF28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */, F73EF7CB2B0225610087E6E9 /* NCManageDatabase+PhotoLibrary.swift in Sources */, + F7A5DF052C3FD11800753FC4 /* FileProviderExtension+NetworkingDelegate.swift in Sources */, F33EE6F62BF4C9B200CA1A51 /* PKCS12.swift in Sources */, F73EF7C32B02250B0087E6E9 /* NCManageDatabase+GPS.swift in Sources */, F7C9B9212B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */, @@ -4138,6 +4191,7 @@ F7E98C1827E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */, F785EEA42461A4A600B3F945 /* NCUtility.swift in Sources */, F79B646226CA661600838ACA /* UIControl+Extension.swift in Sources */, + F7C1DAEF2C3D1DF4000BDC69 /* FileProviderDomain.swift in Sources */, F73EF7AB2B0223900087E6E9 /* NCManageDatabase+Comments.swift in Sources */, F7327E392B73B8D400A462C7 /* Array+Extension.swift in Sources */, F78E2D6929AF02DB0024D4F3 /* Database.swift in Sources */, @@ -4175,6 +4229,7 @@ F7E402332BA89551007E5609 /* NCTrash+Networking.swift in Sources */, F7E7AEA72BA32D0000512E52 /* NCCollectionViewUnifiedSearch.swift in Sources */, F73EF7A72B0223900087E6E9 /* NCManageDatabase+Comments.swift in Sources */, + F799DF882C4B83CC003410B5 /* NCCollectionViewCommon+EasyTipView.swift in Sources */, F7AE00F8230E81CB007ACF8A /* NCBrowserWeb.swift in Sources */, F702F30825EE5D47008F8E80 /* NCPopupViewController.swift in Sources */, F733598125C1C188002ABA72 /* NCAskAuthorization.swift in Sources */, @@ -4187,7 +4242,9 @@ F790110E21415BF600D7B136 /* NCViewerRichDocument.swift in Sources */, F78ACD4021903CC20088454D /* NCGridCell.swift in Sources */, F7D890752BD25C570050B8A6 /* NCCollectionViewCommon+DragDrop.swift in Sources */, + F7BD0A042C4689E9003A4A6D /* NCMedia+MediaLayout.swift in Sources */, F761856B29E98543006EB3B0 /* NCIntroViewController.swift in Sources */, + F7743A142C33F13A0034F670 /* NCCollectionViewCommon+CollectionViewDataSource.swift in Sources */, F75B0ABD244C4DBB00E58DCA /* NCActionCenter.swift in Sources */, AF935067276B84E700BD078F /* NCMenu+FloatingPanel.swift in Sources */, F321DA8A2B71205A00DDA0E6 /* NCTrashSelectTabBar.swift in Sources */, @@ -4197,6 +4254,7 @@ F7802B322BD5584F00D74270 /* NCMedia+DragDrop.swift in Sources */, F7EE66AD2A20B226009AE765 /* UILabel+Extension.swift in Sources */, F78ACD4221903CE00088454D /* NCListCell.swift in Sources */, + F7BD0A002C468925003A4A6D /* NCMedia+CollectionViewDataSource.swift in Sources */, F76D3CF12428B40E005DFA87 /* NCViewerPDFSearch.swift in Sources */, F7245924289BB50C00474787 /* ThreadSafeDictionary.swift in Sources */, F73F537F1E929C8500F8678D /* NCMore.swift in Sources */, @@ -4214,11 +4272,13 @@ F7B769A82B7A0B2000C1AAEB /* NCManageDatabase+Metadata+Session.swift in Sources */, F79EDAA326B004980007D134 /* NCPlayerToolBar.swift in Sources */, F7B934FE2BDCFE1E002B2FC9 /* NCDragDrop.swift in Sources */, + F713FBE52C31645200F10760 /* NCNetworking+AsyncAwait.swift in Sources */, F77444F8222816D5000D5EB0 /* NCPickerViewController.swift in Sources */, F77BB74A2899857B0090FC19 /* UINavigationController+Extension.swift in Sources */, F7327E282B73A53400A462C7 /* NCNetworking+Upload.swift in Sources */, F769454622E9F1B0000A798A /* NCShareCommon.swift in Sources */, F70753F12542A9A200972D44 /* NCViewerMedia.swift in Sources */, + F799DF822C4B7DCC003410B5 /* NCSectionFooter.swift in Sources */, F76B649C2ADFFAED00014640 /* NCImageCache.swift in Sources */, F78A18B823CDE2B300F681F3 /* NCViewerRichWorkspace.swift in Sources */, F768822E2C0DD1E7001CF441 /* NCSettingsBundleHelper.swift in Sources */, @@ -4235,7 +4295,7 @@ F75A9EE623796C6F0044CFCE /* NCNetworking.swift in Sources */, F758B460212C56A400515F55 /* NCScan.swift in Sources */, F76882262C0DD1E7001CF441 /* NCSettingsView.swift in Sources */, - F78ACD52219046DC0088454D /* NCSectionHeaderMenu.swift in Sources */, + F78ACD52219046DC0088454D /* NCSectionFirstHeader.swift in Sources */, F72944F52A8424F800246839 /* NCEndToEndMetadataV1.swift in Sources */, F710D2022405826100A6033D /* NCViewer+Menu.swift in Sources */, F765E9CD295C585800A09ED8 /* NCUploadScanDocument.swift in Sources */, @@ -4244,7 +4304,9 @@ F7BF9D822934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */, AF7E504E27A2D8FF00B5E4AF /* UIBarButton+Extension.swift in Sources */, F7A846DE2BB01ACB0024816F /* NCTrashCellProtocol.swift in Sources */, + F799DF852C4B7E56003410B5 /* NCSectionHeader.swift in Sources */, F78A10BF29322E8A008499B8 /* NCManageDatabase+Directory.swift in Sources */, + F7743A122C33F0A20034F670 /* NCCollectionViewCommon+CollectionViewDelegate.swift in Sources */, F704B5E92430C0B800632F5F /* NCCreateFormUploadConflictCell.swift in Sources */, F7327E3D2B73B92800A462C7 /* NCNetworking+Synchronization.swift in Sources */, F72D404923D2082500A97FD0 /* NCViewerNextcloudText.swift in Sources */, @@ -4255,9 +4317,8 @@ F76882362C0DD1E7001CF441 /* NCAcknowledgementsView.swift in Sources */, F785EE9D246196DF00B3F945 /* NCNetworkingE2EE.swift in Sources */, F724377B2C10B83E00C7C68D /* NCPermissions.swift in Sources */, - F76673ED22C901F6007ED366 /* FileProviderDomain.swift in Sources */, F794E13D2BBBFF2E003693D7 /* NCMainTabBarController.swift in Sources */, - F7CBC1252BAC8B0000EC1D55 /* NCSectionHeaderEmptyData.swift in Sources */, + F7CBC1252BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.swift in Sources */, F75C0C4823D1FAE300163CC8 /* NCRichWorkspaceCommon.swift in Sources */, F78ACD4A21903F850088454D /* NCTrashListCell.swift in Sources */, F76882352C0DD1E7001CF441 /* NCWebBrowserView.swift in Sources */, @@ -4294,9 +4355,10 @@ F7E98C1627E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */, F7F4F11227ECDC52008676F9 /* UIFont+Extension.swift in Sources */, F76882222C0DD1E7001CF441 /* NCCapabilitiesView.swift in Sources */, - AF93471A27E2361E002537EE /* NCShareAdvancePermissionHeader.swift in Sources */, + AF93471A27E2361E002537EE /* NCShareHeader.swift in Sources */, F7F878AE1FB9E3B900599E4F /* NCEndToEndMetadata.swift in Sources */, F7A7FDDD2C2DBD6200E9A93A /* NCDeepLinkHandler.swift in Sources */, + F778231E2C42C07C001BB94F /* NCCollectionViewCommon+MediaLayout.swift in Sources */, 3781B9B023DB2B7E006B4B1D /* AppDelegate+Menu.swift in Sources */, F710D1F52405770F00A6033D /* NCViewerPDF.swift in Sources */, F7B6B70427C4E7FA00A7F6EB /* NCScan+CollectionView.swift in Sources */, @@ -4315,6 +4377,7 @@ F7145610296433C80038D028 /* NCDocumentCamera.swift in Sources */, F76882312C0DD1E7001CF441 /* NCFileNameView.swift in Sources */, F7381EE1218218C9000B1560 /* NCOffline.swift in Sources */, + F751247C2C42919C00E63DB8 /* NCPhotoCell.swift in Sources */, F7A509252C26BD5D00326106 /* NCCreateDocument.swift in Sources */, F7FA80002C0F4F3B0072FC60 /* NCUploadAssetsModel.swift in Sources */, F719D9E2288D396100762E33 /* NCColorPicker.swift in Sources */, @@ -4322,6 +4385,7 @@ F79B646026CA661600838ACA /* UIControl+Extension.swift in Sources */, F768823E2C0DD305001CF441 /* LazyView.swift in Sources */, F7CA212D25F1333300826ABB /* NCAccountRequest.swift in Sources */, + F747EB0D2C4AC1FF00F959A8 /* NCCollectionViewCommon+CollectionViewDelegateFlowLayout.swift in Sources */, F765F73125237E3F00391DBE /* NCRecent.swift in Sources */, F76B3CCE1EAE01BD00921AC9 /* NCBrand.swift in Sources */, F7FA7FFC2C0F4EE40072FC60 /* NCViewerQuickLookView.swift in Sources */, @@ -4338,6 +4402,7 @@ F76882302C0DD1E7001CF441 /* NCFileNameModel.swift in Sources */, F72FD3B5297ED49A00075D28 /* NCManageDatabase+E2EE.swift in Sources */, F73EF7CF2B0225BA0087E6E9 /* NCManageDatabase+Tag.swift in Sources */, + F7BD0A022C4689A4003A4A6D /* NCMedia+CollectionViewDelegate.swift in Sources */, F3A047982BD2668800658E7B /* NCAssistantCreateNewTask.swift in Sources */, AF93471227E2341B002537EE /* NCShare+Menu.swift in Sources */, F7EFA47825ADBA500083159A /* NCViewerProviderContextMenu.swift in Sources */, @@ -4351,7 +4416,7 @@ F76D364628A4F8BF00214537 /* NCActivityIndicator.swift in Sources */, F3A047992BD2668800658E7B /* NCAssistantTask.swift in Sources */, F76882322C0DD1E7001CF441 /* NCAutoUploadView.swift in Sources */, - F36E64F72B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBarDelegate.swift in Sources */, + F36E64F72B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBar.swift in Sources */, F79A65C62191D95E00FF6DCC /* NCSelect.swift in Sources */, F75D19E325EFE09000D74598 /* NCTrash+Menu.swift in Sources */, F70CAE3A1F8CF31A008125FD /* NCEndToEndEncryption.m in Sources */, @@ -4393,6 +4458,7 @@ F76882232C0DD1E7001CF441 /* NCCapabilitiesModel.swift in Sources */, F7D68FCC28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */, F76882292C0DD1E7001CF441 /* NCManageE2EEModel.swift in Sources */, + F799DF8B2C4B84EB003410B5 /* NCCollectionViewCommon+EndToEndInitialize.swift in Sources */, F78E2D6529AF02DB0024D4F3 /* Database.swift in Sources */, F70CEF5623E9C7E50007035B /* UIColor+Extension.swift in Sources */, F76882242C0DD1E7001CF441 /* NCSettingsAdvancedView.swift in Sources */, @@ -5348,7 +5414,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0; + CURRENT_PROJECT_VERSION = 11; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = NKUJUXUJ3B; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -5375,7 +5441,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 5.4.2; + MARKETING_VERSION = 5.5.0; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = "-v"; OTHER_LDFLAGS = ""; @@ -5414,7 +5480,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0; + CURRENT_PROJECT_VERSION = 11; DEVELOPMENT_TEAM = NKUJUXUJ3B; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -5438,7 +5504,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 5.4.2; + MARKETING_VERSION = 5.5.0; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = "-v"; OTHER_LDFLAGS = ""; @@ -5713,7 +5779,7 @@ repositoryURL = "https://github.com/nextcloud/NextcloudKit"; requirement = { kind = exactVersion; - version = 3.0.2; + version = 4.0.3; }; }; F788ECC5263AAAF900ADC67F /* XCRemoteSwiftPackageReference "MarkdownKit" */ = { diff --git a/Nextcloud.xcodeproj/xcshareddata/xcschemes/File Provider Extension UI.xcscheme b/Nextcloud.xcodeproj/xcshareddata/xcschemes/File Provider Extension UI.xcscheme new file mode 100644 index 0000000000..c06627e268 --- /dev/null +++ b/Nextcloud.xcodeproj/xcshareddata/xcschemes/File Provider Extension UI.xcscheme @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Nextcloud.xcodeproj/xcshareddata/xcschemes/WidgetDashboardIntentHandler.xcscheme b/Nextcloud.xcodeproj/xcshareddata/xcschemes/WidgetDashboardIntentHandler.xcscheme new file mode 100644 index 0000000000..e7fe4caf7c --- /dev/null +++ b/Nextcloud.xcodeproj/xcshareddata/xcschemes/WidgetDashboardIntentHandler.xcscheme @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Notification Service Extension/NotificationService.swift b/Notification Service Extension/NotificationService.swift index 24efbc8e92..b2d6bc1490 100644 --- a/Notification Service Extension/NotificationService.swift +++ b/Notification Service Extension/NotificationService.swift @@ -46,7 +46,7 @@ class NotificationService: UNNotificationServiceExtension { if var json = try JSONSerialization.jsonObject(with: data) as? [String: AnyObject], let subject = json["subject"] as? String { bestAttemptContent.body = subject - if let pref = UserDefaults(suiteName: NCBrandOptions.shared.capabilitiesGroups) { + if let pref = UserDefaults(suiteName: NCBrandOptions.shared.capabilitiesGroup) { json["account"] = tableAccount.account as AnyObject pref.set(json, forKey: "NOTIFICATION_DATA") pref.synchronize() diff --git a/Share/NCShareCell.swift b/Share/NCShareCell.swift index 4b8c5f93f1..5ad6b759a0 100644 --- a/Share/NCShareCell.swift +++ b/Share/NCShareCell.swift @@ -50,12 +50,10 @@ class NCShareCell: UITableViewCell { if let image = UIImage.downsample(imageAt: URL(fileURLWithPath: NSTemporaryDirectory() + fileName), to: CGSize(width: 80, height: 80)) { imageCell.image = image + imageCell.contentMode = .scaleAspectFill } else { - if !resultInternalType.iconName.isEmpty { - imageCell?.image = UIImage(named: resultInternalType.iconName) - } else { - imageCell?.image = NCImageCache.images.file - } + imageCell.image = utility.loadImage(named: resultInternalType.iconName, useTypeIconFile: true) + imageCell.contentMode = .scaleAspectFit } fileNameCell?.text = fileName diff --git a/Share/NCShareExtension+DataSource.swift b/Share/NCShareExtension+DataSource.swift index 883a8b6e9e..2d10a75bf8 100644 --- a/Share/NCShareExtension+DataSource.swift +++ b/Share/NCShareExtension+DataSource.swift @@ -42,7 +42,7 @@ extension NCShareExtension: UICollectionViewDelegate { func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { if kind == UICollectionView.elementKindSectionHeader { - guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionHeaderEmptyData", for: indexPath) as? NCSectionHeaderEmptyData else { return NCSectionHeaderEmptyData() } + guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFirstHeaderEmptyData", for: indexPath) as? NCSectionFirstHeaderEmptyData else { return NCSectionFirstHeaderEmptyData() } if self.dataSourceTask?.state == .running { header.emptyImage.image = utility.loadImage(named: "wifi", colors: [NCBrandColor.shared.brandElement]) header.emptyTitle.text = NSLocalizedString("_request_in_progress_", comment: "") @@ -80,7 +80,6 @@ extension NCShareExtension: UICollectionViewDataSource { } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - guard let metadata = dataSource.cellForItemAt(indexPath: indexPath), let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "listCell", for: indexPath) as? NCListCell else { return UICollectionViewCell() } @@ -92,7 +91,6 @@ extension NCShareExtension: UICollectionViewDataSource { cell.fileUser = metadata.ownerId cell.labelTitle.text = metadata.fileNameView cell.labelTitle.textColor = NCBrandColor.shared.textColor - cell.imageSelect.image = nil cell.imageStatus.image = nil cell.imageLocal.image = nil @@ -101,14 +99,12 @@ extension NCShareExtension: UICollectionViewDataSource { cell.imageMore.image = nil cell.imageItem.image = nil cell.imageItem.backgroundColor = nil - cell.progressView.progress = 0.0 if metadata.directory { setupDirectoryCell(cell, indexPath: indexPath, with: metadata) } - // image Favorite if metadata.favorite { cell.imageFavorite.image = NCImageCache.images.favorite } @@ -117,17 +113,14 @@ extension NCShareExtension: UICollectionViewDataSource { cell.backgroundView = nil cell.hideButtonMore(true) cell.hideButtonShare(true) - cell.selectMode(false) + cell.selected(false, isEditMode: false) - // Live Photo if metadata.isLivePhoto { cell.imageStatus.image = NCImageCache.images.livePhoto } - // Add TAGS cell.setTags(tags: Array(metadata.tags)) - // Remove last separator cell.separator.isHidden = collectionView.numberOfItems(inSection: indexPath.section) == indexPath.row + 1 return cell diff --git a/Share/NCShareExtension+Files.swift b/Share/NCShareExtension+Files.swift index 6b66df2a22..3d8565c827 100644 --- a/Share/NCShareExtension+Files.swift +++ b/Share/NCShareExtension+Files.swift @@ -25,39 +25,20 @@ import Foundation import UniformTypeIdentifiers extension NCShareExtension { - @objc func reloadDatasource(withLoadFolder: Bool) { - - var groupByField = "name" - layoutForView = NCManageDatabase.shared.setLayoutForView(account: activeAccount.account, key: keyLayout, serverUrl: serverUrl) - - // set GroupField for Grid - if layoutForView?.layout == NCGlobal.shared.layoutGrid { - groupByField = "classFile" - } - let metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND directory == true", activeAccount.account, serverUrl)) - self.dataSource = NCDataSource( - metadatas: metadatas, - account: activeAccount.account, - sort: layoutForView?.sort, - ascending: layoutForView?.ascending, - directoryOnTop: layoutForView?.directoryOnTop, - favoriteOnTop: true, - groupByField: groupByField) + self.dataSource = NCDataSource(metadatas: metadatas, account: activeAccount.account, layoutForView: layoutForView) if withLoadFolder { loadFolder() } else { self.refreshControl.endRefreshing() } - collectionView.reloadData() } @objc func didCreateFolder(_ notification: NSNotification) { - guard let userInfo = notification.userInfo as NSDictionary?, let ocId = userInfo["ocId"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) @@ -69,7 +50,6 @@ extension NCShareExtension { } func loadFolder() { - NCNetworking.shared.readFolder(serverUrl: serverUrl, account: activeAccount.account) { task in self.dataSourceTask = task self.collectionView.reloadData() diff --git a/Share/NCShareExtension+NCDelegate.swift b/Share/NCShareExtension+NCDelegate.swift index 6c4db67854..d13e00f681 100644 --- a/Share/NCShareExtension+NCDelegate.swift +++ b/Share/NCShareExtension+NCDelegate.swift @@ -97,7 +97,6 @@ extension NCShareExtension: NCAccountRequestDelegate { } extension NCShareExtension: NCShareCellDelegate, NCRenameFileDelegate, NCListCellDelegate { - func removeFile(named fileName: String) { guard let index = self.filesName.firstIndex(of: fileName) else { return showAlert(title: "_file_not_found_", description: fileName) @@ -139,6 +138,15 @@ extension NCShareExtension: NCShareCellDelegate, NCRenameFileDelegate, NCListCel filesName[fileIx] = fileNameNew tableView.reloadData() } + + func tapShareListItem(with objectId: String, indexPath: IndexPath, sender: Any) { + } + + func tapMoreListItem(with objectId: String, namedButtonMore: String, image: UIImage?, indexPath: IndexPath, sender: Any) { + } + + func longPressListItem(with objectId: String, indexPath: IndexPath, gestureRecognizer: UILongPressGestureRecognizer) { + } } extension NCShareExtension: NCCreateFormUploadConflictDelegate { diff --git a/Share/NCShareExtension.swift b/Share/NCShareExtension.swift index 4bd442469e..f71371c2c1 100644 --- a/Share/NCShareExtension.swift +++ b/Share/NCShareExtension.swift @@ -81,7 +81,7 @@ class NCShareExtension: UIViewController { self.navigationController?.navigationBar.prefersLargeTitles = false - collectionView.register(UINib(nibName: "NCSectionHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderEmptyData") + collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") collectionView.register(UINib(nibName: "NCListCell", bundle: nil), forCellWithReuseIdentifier: "listCell") collectionView.collectionViewLayout = NCListLayout() @@ -395,7 +395,6 @@ extension NCShareExtension { } extension NCShareExtension: uploadE2EEDelegate { - func start() { self.hud.progress = 0 } diff --git a/Tests/Common/BaseXCTestCase.swift b/Tests/Common/BaseXCTestCase.swift index 853bb6ba3d..8d80e6dab3 100644 --- a/Tests/Common/BaseXCTestCase.swift +++ b/Tests/Common/BaseXCTestCase.swift @@ -18,7 +18,7 @@ class BaseXCTestCase: XCTestCase { func setupAppToken() { let expectation = expectation(description: "Should get app token") - NextcloudKit.shared.getAppPassword(serverUrl: TestConstants.server, username: TestConstants.username, password: TestConstants.password) { token, data, error in + NextcloudKit.shared.getAppPassword(url: TestConstants.server, user: TestConstants.username, password: TestConstants.password) { token, _, error in XCTAssertEqual(error.errorCode, 0) XCTAssertNotNil(token) diff --git a/Tests/NextcloudIntegrationTests/FilesIntegrationTests.swift b/Tests/NextcloudIntegrationTests/FilesIntegrationTests.swift index cb049761f4..f538479081 100644 --- a/Tests/NextcloudIntegrationTests/FilesIntegrationTests.swift +++ b/Tests/NextcloudIntegrationTests/FilesIntegrationTests.swift @@ -37,7 +37,7 @@ final class FilesIntegrationTests: BaseIntegrationXCTestCase { let serverUrl = "\(TestConstants.server)/remote.php/dav/files/\(TestConstants.username)" let serverUrlFileName = "\(serverUrl)/\(folderName)" - NextcloudKit.shared.setup(account: TestConstants.account, user: TestConstants.username, userId: TestConstants.username, password: appToken, urlBase: TestConstants.server) + NextcloudKit.shared.setup(account: TestConstants.account, user: TestConstants.username, userId: TestConstants.username, password: appToken, urlBase: TestConstants.server, groupIdentifier: NCBrandOptions.shared.capabilitiesGroup) // Test creating folder NCNetworking.shared.createFolder(fileName: folderName, serverUrl: serverUrl, account: TestConstants.account, urlBase: TestConstants.server, userId: TestConstants.username, withPush: true, sceneIdentifier: nil) { error in diff --git a/Widget/Dashboard/DashboardData.swift b/Widget/Dashboard/DashboardData.swift index 64e7acc115..ef8ebf9a09 100644 --- a/Widget/Dashboard/DashboardData.swift +++ b/Widget/Dashboard/DashboardData.swift @@ -21,6 +21,7 @@ // along with this program. If not, see . // +import UIKit import WidgetKit import Intents import NextcloudKit @@ -75,7 +76,6 @@ func getDashboardItems(displaySize: CGSize, withButton: Bool) -> Int { } func convertDataToImage(data: Data?, size: CGSize, fileNameToWrite: String?) -> UIImage? { - guard let data = data else { return nil } var imageData: UIImage? @@ -97,7 +97,6 @@ func convertDataToImage(data: Data?, size: CGSize, fileNameToWrite: String?) -> } func getDashboardDataEntry(configuration: DashboardIntent?, isPreview: Bool, displaySize: CGSize, completion: @escaping (_ entry: DashboardDataEntry) -> Void) { - let utilityFileSystem = NCUtilityFileSystem() let utility = NCUtility() let dashboardItems = getDashboardItems(displaySize: displaySize, withButton: false) @@ -170,7 +169,6 @@ func getDashboardDataEntry(configuration: DashboardIntent?, isPreview: Bool, dis let options = NKRequestOptions(timeout: 90, queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue) NextcloudKit.shared.getDashboardWidgetsApplication(id, options: options) { _, results, data, error in - Task { var datas = [DashboardData]() var numberItems = 0 @@ -227,8 +225,9 @@ func getDashboardDataEntry(configuration: DashboardIntent?, isPreview: Bool, dis if FileManager().fileExists(atPath: fileNamePath), let image = UIImage(contentsOfFile: fileNamePath) { icon = image } else { - let (_, data, _) = await NextcloudKit.shared.getPreview(url: url) - if let image = convertDataToImage(data: data, size: CGSize(width: 256, height: 256), fileNameToWrite: fileName) { + let (_, data, error) = await NCNetworking.shared.downloadPreview(url: url) + if error == .success, + let image = convertDataToImage(data: data, size: CGSize(width: 256, height: 256), fileNameToWrite: fileName) { icon = image } } diff --git a/Widget/Dashboard/DashboardWidgetProvider.swift b/Widget/Dashboard/DashboardWidgetProvider.swift index acfcb13c62..6a2ad42796 100644 --- a/Widget/Dashboard/DashboardWidgetProvider.swift +++ b/Widget/Dashboard/DashboardWidgetProvider.swift @@ -21,12 +21,12 @@ // along with this program. If not, see . // +import UIKit import WidgetKit import Intents import SwiftUI struct DashboardWidgetProvider: IntentTimelineProvider { - typealias Intent = DashboardIntent typealias Entry = DashboardDataEntry diff --git a/Widget/Files/FilesData.swift b/Widget/Files/FilesData.swift index 19180076ff..85fbfa99f4 100644 --- a/Widget/Files/FilesData.swift +++ b/Widget/Files/FilesData.swift @@ -21,6 +21,7 @@ // along with this program. If not, see . // +import UIKit import WidgetKit import Intents import NextcloudKit @@ -60,7 +61,6 @@ let filesDatasTest: [FilesData] = [ ] func getTitleFilesWidget(account: tableAccount?) -> String { - let hour = Calendar.current.component(.hour, from: Date()) var good = "" @@ -85,7 +85,6 @@ func getFilesItems(displaySize: CGSize) -> Int { } func getFilesDataEntry(configuration: AccountIntent?, isPreview: Bool, displaySize: CGSize, completion: @escaping (_ entry: FilesDataEntry) -> Void) { - let utilityFileSystem = NCUtilityFileSystem() let utility = NCUtility() let filesItems = getFilesItems(displaySize: displaySize) @@ -131,6 +130,7 @@ func getFilesDataEntry(configuration: AccountIntent?, isPreview: Bool, displaySi + @@ -163,7 +163,7 @@ func getFilesDataEntry(configuration: AccountIntent?, isPreview: Bool, displaySi - 25 + 50 @@ -197,8 +197,8 @@ func getFilesDataEntry(configuration: AccountIntent?, isPreview: Bool, displaySi let files = files.sorted(by: { ($0.date as Date) > ($1.date as Date) }) for file in files { - var image: UIImage? var useTypeIconFile = false + var image: UIImage? if file.directory || (!file.livePhotoFile.isEmpty && file.classFile == NKCommon.TypeClassFile.video.rawValue) { continue @@ -216,17 +216,15 @@ func getFilesDataEntry(configuration: AccountIntent?, isPreview: Bool, displaySi guard let url = URL(string: urlString) else { continue } // IMAGE - if let result = utility.createFilePreviewImage(ocId: file.ocId, etag: file.etag, fileNameView: file.fileName, classFile: file.classFile, status: 0, createPreviewMedia: false) { - image = result - } else if file.hasPreview { - - let fileNamePreviewLocalPath = utilityFileSystem.getDirectoryProviderStoragePreviewOcId(file.ocId, etag: file.etag) - let fileNameIconLocalPath = utilityFileSystem.getDirectoryProviderStorageIconOcId(file.ocId, etag: file.etag) + let fileNamePreviewLocalPath = utilityFileSystem.getDirectoryProviderStoragePreviewOcId(file.ocId, etag: file.etag) + let fileNameIconLocalPath = utilityFileSystem.getDirectoryProviderStorageIconOcId(file.ocId, etag: file.etag) + if FileManager.default.fileExists(atPath: fileNameIconLocalPath) { + image = UIImage(contentsOfFile: fileNameIconLocalPath) + } + if image == nil, file.hasPreview { let sizePreview = NCUtility().getSizePreview(width: Int(file.width), height: Int(file.height)) - let (_, _, imageIcon, _, _, _) = await NextcloudKit.shared.downloadPreview(fileId: file.fileId, fileNamePreviewLocalPath: fileNamePreviewLocalPath, fileNameIconLocalPath: fileNameIconLocalPath, widthPreview: Int(sizePreview.width), heightPreview: Int(sizePreview.height), sizeIcon: NCGlobal.shared.sizeIcon, options: options) - if let result = imageIcon { - image = result - } + let (_, _, imageIcon, _, _, _) = await NCNetworking.shared.downloadPreview(fileId: file.fileId, fileNamePreviewLocalPath: fileNamePreviewLocalPath, fileNameIconLocalPath: fileNameIconLocalPath, widthPreview: Int(sizePreview.width), heightPreview: Int(sizePreview.height), sizeIcon: NCGlobal.shared.sizeIcon, options: options) + image = imageIcon } if image == nil { image = utility.loadImage(named: file.iconName, useTypeIconFile: true) @@ -237,7 +235,7 @@ func getFilesDataEntry(configuration: AccountIntent?, isPreview: Bool, displaySi let metadata = NCManageDatabase.shared.convertFileToMetadata(file, isDirectoryE2EE: isDirectoryE2EE) // DATA - let data = FilesData(id: metadata.ocId, image: image!, title: metadata.fileNameView, subTitle: subTitle, url: url, useTypeIconFile: useTypeIconFile) + let data = FilesData(id: metadata.ocId, image: image ?? UIImage(), title: metadata.fileNameView, subTitle: subTitle, url: url, useTypeIconFile: useTypeIconFile) datas.append(data) if datas.count == filesItems { break} } diff --git a/Widget/Files/FilesWidgetProvider.swift b/Widget/Files/FilesWidgetProvider.swift index da49127f03..9935708d7b 100644 --- a/Widget/Files/FilesWidgetProvider.swift +++ b/Widget/Files/FilesWidgetProvider.swift @@ -21,12 +21,12 @@ // along with this program. If not, see . // +import UIKit import WidgetKit import Intents import SwiftUI struct FilesWidgetProvider: IntentTimelineProvider { - typealias Entry = FilesDataEntry typealias Intent = AccountIntent diff --git a/Widget/Lockscreen/LockscreenData.swift b/Widget/Lockscreen/LockscreenData.swift index fb907eaf91..48a971d645 100644 --- a/Widget/Lockscreen/LockscreenData.swift +++ b/Widget/Lockscreen/LockscreenData.swift @@ -21,6 +21,7 @@ // along with this program. If not, see . // +import UIKit import WidgetKit import NextcloudKit @@ -36,7 +37,6 @@ struct LockscreenData: TimelineEntry { } func getLockscreenDataEntry(configuration: AccountIntent?, isPreview: Bool, family: WidgetFamily, completion: @escaping (_ entry: LockscreenData) -> Void) { - let utilityFileSystem = NCUtilityFileSystem() var account: tableAccount? var quotaRelative: Float = 0 diff --git a/Widget/Lockscreen/LockscreenWidgetProvider.swift b/Widget/Lockscreen/LockscreenWidgetProvider.swift index 6d3ac5b897..92949263fa 100644 --- a/Widget/Lockscreen/LockscreenWidgetProvider.swift +++ b/Widget/Lockscreen/LockscreenWidgetProvider.swift @@ -21,12 +21,12 @@ // along with this program. If not, see . // +import UIKit import WidgetKit import Intents import SwiftUI struct LockscreenWidgetProvider: IntentTimelineProvider { - typealias Entry = LockscreenData typealias Intent = AccountIntent diff --git a/Widget/Toolbar/ToolbarData.swift b/Widget/Toolbar/ToolbarData.swift index 67146ea5d1..7fd87d29f3 100644 --- a/Widget/Toolbar/ToolbarData.swift +++ b/Widget/Toolbar/ToolbarData.swift @@ -21,6 +21,7 @@ // along with this program. If not, see . // +import UIKit import WidgetKit struct ToolbarDataEntry: TimelineEntry { @@ -33,7 +34,6 @@ struct ToolbarDataEntry: TimelineEntry { } func getToolbarDataEntry(isPreview: Bool, completion: @escaping (_ entry: ToolbarDataEntry) -> Void) { - var userId = "" var url = "" diff --git a/Widget/Toolbar/ToolbarWidgetProvider.swift b/Widget/Toolbar/ToolbarWidgetProvider.swift index 303b73eac7..b1842d81d3 100644 --- a/Widget/Toolbar/ToolbarWidgetProvider.swift +++ b/Widget/Toolbar/ToolbarWidgetProvider.swift @@ -21,11 +21,11 @@ // along with this program. If not, see . // +import UIKit import WidgetKit import SwiftUI struct ToolbarWidgetProvider: TimelineProvider { - typealias Entry = ToolbarDataEntry func placeholder(in context: Context) -> Entry { diff --git a/WidgetDashboardIntentHandler/IntentHandler.swift b/WidgetDashboardIntentHandler/IntentHandler.swift index 1e1b1430e7..03d8e669a2 100644 --- a/WidgetDashboardIntentHandler/IntentHandler.swift +++ b/WidgetDashboardIntentHandler/IntentHandler.swift @@ -28,10 +28,7 @@ class IntentHandler: INExtension, DashboardIntentHandling, AccountIntentHandling // MARK: - Account - // Account - func provideAccountsOptionsCollection(for intent: AccountIntent, with completion: @escaping (INObjectCollection?, Error?) -> Void) { - var accounts: [Accounts] = [] let results = NCManageDatabase.shared.getAllAccount() @@ -52,7 +49,6 @@ class IntentHandler: INExtension, DashboardIntentHandling, AccountIntentHandling } func defaultAccounts(for intent: AccountIntent) -> Accounts? { - if NCManageDatabase.shared.getActiveAccount() == nil { return nil } else { @@ -63,9 +59,7 @@ class IntentHandler: INExtension, DashboardIntentHandling, AccountIntentHandling // MARK: - Dashboard // Application - func provideApplicationsOptionsCollection(for intent: DashboardIntent, with completion: @escaping (INObjectCollection?, Error?) -> Void) { - var applications: [Applications] = [] var account: tableAccount? @@ -90,7 +84,6 @@ class IntentHandler: INExtension, DashboardIntentHandling, AccountIntentHandling } func defaultApplications(for intent: DashboardIntent) -> Applications? { - guard let account = NCManageDatabase.shared.getActiveAccount() else { return nil } @@ -101,9 +94,7 @@ class IntentHandler: INExtension, DashboardIntentHandling, AccountIntentHandling } // Account - func provideAccountsOptionsCollection(for intent: DashboardIntent, with completion: @escaping (INObjectCollection?, Error?) -> Void) { - var accounts: [Accounts] = [] let results = NCManageDatabase.shared.getAllAccount() @@ -124,7 +115,6 @@ class IntentHandler: INExtension, DashboardIntentHandling, AccountIntentHandling } func defaultAccounts(for intent: DashboardIntent) -> Accounts? { - if NCManageDatabase.shared.getActiveAccount() == nil { return nil } else { diff --git a/iOSClient/Account Settings/NCAccountSettingsModel.swift b/iOSClient/Account Settings/NCAccountSettingsModel.swift index cae70fd981..08fa601180 100644 --- a/iOSClient/Account Settings/NCAccountSettingsModel.swift +++ b/iOSClient/Account Settings/NCAccountSettingsModel.swift @@ -131,19 +131,19 @@ class NCAccountSettingsModel: ObservableObject, ViewOnAppearHandling { } /// Function to update the user data - func getUserStatus() -> (statusImage: UIImage, statusMessage: String, descriptionMessage: String) { + func getUserStatus() -> (statusImage: UIImage?, statusMessage: String, descriptionMessage: String) { guard let activeAccount else { return (UIImage(), "", "") } if NCGlobal.shared.capabilityUserStatusEnabled, let tableAccount = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", activeAccount.account)) { return NCUtility().getUserStatus(userIcon: tableAccount.userStatusIcon, userStatus: tableAccount.userStatusStatus, userMessage: tableAccount.userStatusMessage) } - return (UIImage(), "", "") + return (nil, "", "") } /// Function to know the height of "account" data func getTableViewHeight() -> CGFloat { guard let activeAccount else { return 0 } - var height: CGFloat = 190 + var height: CGFloat = NCGlobal.shared.capabilityUserStatusEnabled ? 190 : 220 if NCGlobal.shared.capabilityUserStatusEnabled, let tableAccount = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", activeAccount.account)) { if !tableAccount.email.isEmpty { height += 30 } @@ -168,20 +168,22 @@ class NCAccountSettingsModel: ObservableObject, ViewOnAppearHandling { @objc func changeAccount() { if let activeAccount { - self.appDelegate.changeAccount(activeAccount.account, userProfile: nil) + self.appDelegate.changeAccount(activeAccount.account, userProfile: nil) { } } } /// Function to delete the current account func deleteAccount() { if let activeAccount { - appDelegate.deleteAccount(activeAccount.account, wipe: false) + appDelegate.deleteAccount(activeAccount.account) if let account = NCManageDatabase.shared.getAllAccount().first?.account { - appDelegate.changeAccount(account, userProfile: nil) + appDelegate.changeAccount(account, userProfile: nil) { + onViewAppear() + } } else { dismissView = true + appDelegate.openLogin(selector: NCGlobal.shared.introLogin, openLoginWeb: false) } - onViewAppear() } } } diff --git a/iOSClient/Account Settings/NCAccountSettingsView.swift b/iOSClient/Account Settings/NCAccountSettingsView.swift index d398eea531..c8a9e500c7 100644 --- a/iOSClient/Account Settings/NCAccountSettingsView.swift +++ b/iOSClient/Account Settings/NCAccountSettingsView.swift @@ -52,16 +52,18 @@ struct NCAccountSettingsView: View { .resizable() .scaledToFit() .frame(width: UIScreen.main.bounds.width, height: 75) - ZStack { - Circle() - .fill(.white) - .frame(width: 30, height: 30) - Image(uiImage: status.statusImage) - .resizable() - .scaledToFit() - .frame(width: 30, height: 30) + if let statusImage = status.statusImage { + ZStack { + Circle() + .fill(.white) + .frame(width: 30, height: 30) + Image(uiImage: statusImage) + .resizable() + .scaledToFit() + .frame(width: 30, height: 30) } .offset(x: 30, y: 30) + } } .frame(maxWidth: .infinity, maxHeight: .infinity) Text(model.getUserName()) @@ -153,28 +155,30 @@ struct NCAccountSettingsView: View { } /// /// User Status - Button(action: { - showUserStatus = true - }, label: { - HStack { - Image(systemName: "moon.fill") - .resizable() - .scaledToFit() - .font(Font.system(.body).weight(.light)) - .frame(width: 20, height: 20) - .foregroundStyle(Color(NCBrandColor.shared.iconImageColor)) - Text(NSLocalizedString("_set_user_status_", comment: "")) - .lineLimit(1) - .truncationMode(.middle) - .foregroundStyle(Color(NCBrandColor.shared.textColor)) - .padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 20)) + if NCGlobal.shared.capabilityUserStatusEnabled { + Button(action: { + showUserStatus = true + }, label: { + HStack { + Image(systemName: "moon.fill") + .resizable() + .scaledToFit() + .font(Font.system(.body).weight(.light)) + .frame(width: 20, height: 20) + .foregroundStyle(Color(NCBrandColor.shared.iconImageColor)) + Text(NSLocalizedString("_set_user_status_", comment: "")) + .lineLimit(1) + .truncationMode(.middle) + .foregroundStyle(Color(NCBrandColor.shared.textColor)) + .padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 20)) + } + .font(.system(size: 14)) + }) + .sheet(isPresented: $showUserStatus) { + UserStatusView(showUserStatus: $showUserStatus) } - .font(.system(size: 14)) - }) - .sheet(isPresented: $showUserStatus) { - UserStatusView(showUserStatus: $showUserStatus) + .onChange(of: showUserStatus) { _ in } } - .onChange(of: showUserStatus) { _ in } /// /// Certificate server Button(action: { diff --git a/iOSClient/Activity/NCActivity.storyboard b/iOSClient/Activity/NCActivity.storyboard index 6e94864843..e68152fbbb 100644 --- a/iOSClient/Activity/NCActivity.storyboard +++ b/iOSClient/Activity/NCActivity.storyboard @@ -1,9 +1,9 @@ - + - + @@ -17,93 +17,52 @@ - + - - + + - + - - - + - - + - - - - + - - - - + @@ -115,10 +74,11 @@ + - + @@ -129,7 +89,7 @@ - + diff --git a/iOSClient/Activity/NCActivity.swift b/iOSClient/Activity/NCActivity.swift index 56f03776c0..02efd0c9a9 100644 --- a/iOSClient/Activity/NCActivity.swift +++ b/iOSClient/Activity/NCActivity.swift @@ -27,15 +27,12 @@ import SwiftRichString import NextcloudKit class NCActivity: UIViewController, NCSharePagingContent { - + @IBOutlet weak var viewContainerConstraint: NSLayoutConstraint! @IBOutlet weak var tableView: UITableView! var commentView: NCActivityCommentView? - var textField: UITextField? { commentView?.newCommentField } - - @IBOutlet weak var viewContainerConstraint: NSLayoutConstraint! + var textField: UIView? { commentView?.newCommentField } var height: CGFloat = 0 - var metadata: tableMetadata? var showComments: Bool = false @@ -46,7 +43,7 @@ class NCActivity: UIViewController, NCSharePagingContent { var sectionDates: [Date] = [] var dataSourceTask: URLSessionTask? - var insets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) + var insets = UIEdgeInsets(top: 8, left: 0, bottom: 0, right: 0) var didSelectItemEnable: Bool = true var objectType: String? @@ -117,7 +114,7 @@ class NCActivity: UIViewController, NCSharePagingContent { tableView.tableHeaderView = commentView commentView?.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true commentView?.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true - viewContainerConstraint.constant = height + viewContainerConstraint.constant = height - 10 } func makeTableFooterView() -> UIView { @@ -130,9 +127,12 @@ class NCActivity: UIViewController, NCSharePagingContent { label.textColor = NCBrandColor.shared.textColor2 label.textAlignment = .center label.text = NSLocalizedString("_no_activity_footer_", comment: "") - label.frame = CGRect(x: 0, y: 10, width: tableView.frame.width, height: 60) - view.addSubview(label) + label.translatesAutoresizingMaskIntoConstraints = false + label.topAnchor.constraint(equalTo: view.topAnchor, constant: 20).isActive = true + label.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true + label.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true + return view } } @@ -140,22 +140,16 @@ class NCActivity: UIViewController, NCSharePagingContent { // MARK: - Table View extension NCActivity: UITableViewDelegate { - - func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { - return 120 - } - func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - return 60 + return 50 } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return UITableView.automaticDimension + return 80 } func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - - let view = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 60)) + let view = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 50)) view.backgroundColor = .clear let label = UILabel() @@ -163,20 +157,33 @@ extension NCActivity: UITableViewDelegate { label.textColor = NCBrandColor.shared.textColor label.text = utility.getTitleFromDate(sectionDates[section]) label.textAlignment = .center - label.layer.cornerRadius = 11 - label.layer.masksToBounds = true - label.layer.backgroundColor = UIColor(red: 152.0 / 255.0, green: 167.0 / 255.0, blue: 181.0 / 255.0, alpha: 0.8).cgColor - let widthFrame = label.intrinsicContentSize.width + 30 - let xFrame = tableView.bounds.width / 2 - widthFrame / 2 - label.frame = CGRect(x: xFrame, y: 10, width: widthFrame, height: 22) + let blur = UIBlurEffect(style: .systemMaterial) + let blurredEffectView = UIVisualEffectView(effect: blur) + blurredEffectView.layer.cornerRadius = 11 + blurredEffectView.layer.masksToBounds = true + + view.addSubview(blurredEffectView) view.addSubview(label) + + blurredEffectView.translatesAutoresizingMaskIntoConstraints = false + label.translatesAutoresizingMaskIntoConstraints = false + + NSLayoutConstraint.activate([ + blurredEffectView.topAnchor.constraint(equalTo: view.topAnchor), + blurredEffectView.centerXAnchor.constraint(equalTo: view.centerXAnchor), + blurredEffectView.widthAnchor.constraint(equalToConstant: label.intrinsicContentSize.width + 30), + blurredEffectView.heightAnchor.constraint(equalToConstant: 22), + label.topAnchor.constraint(equalTo: view.topAnchor), + label.centerXAnchor.constraint(equalTo: view.centerXAnchor), + label.centerYAnchor.constraint(equalTo: blurredEffectView.centerYAnchor) + ]) + return view } } extension NCActivity: UITableViewDataSource { - func numberOfSections(in tableView: UITableView) -> Int { return sectionDates.count } @@ -237,27 +244,24 @@ extension NCActivity: UITableViewDataSource { guard let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as? NCActivityTableViewCell else { return UITableViewCell() } - var orderKeysId: [String] = [] cell.idActivity = activity.idActivity cell.indexPath = indexPath cell.avatar.image = nil cell.avatar.isHidden = true - cell.subjectTrailingConstraint.constant = 10 cell.didSelectItemEnable = self.didSelectItemEnable cell.subject.textColor = NCBrandColor.shared.textColor cell.viewController = self // icon if !activity.icon.isEmpty { - let fileNameIcon = (activity.icon as NSString).lastPathComponent let fileNameLocalPath = utilityFileSystem.directoryUserData + "/" + fileNameIcon if FileManager.default.fileExists(atPath: fileNameLocalPath) { if let image = UIImage(contentsOfFile: fileNameLocalPath) { - cell.icon.image = image + cell.icon.image = image.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) } } else { NextcloudKit.shared.downloadContent(serverUrl: activity.icon) { _, data, error in @@ -273,20 +277,18 @@ extension NCActivity: UITableViewDataSource { // avatar if !activity.user.isEmpty && activity.user != appDelegate.userId { - - cell.subjectTrailingConstraint.constant = 50 cell.avatar.isHidden = false cell.fileUser = activity.user - let fileName = appDelegate.userBaseUrl + "-" + activity.user + ".png" - NCNetworking.shared.downloadAvatar(user: activity.user, dispalyName: nil, fileName: fileName, cell: cell, view: tableView) + cell.subjectLeadingConstraint.constant = 15 + } else { + cell.subjectLeadingConstraint.constant = -30 } // subject cell.subject.text = activity.subject if !activity.subjectRich.isEmpty { - var subject = activity.subjectRich var keys: [String] = [] @@ -317,15 +319,6 @@ extension NCActivity: UITableViewDataSource { cell.subject.attributedText = subject.set(style: StyleGroup(base: normal, ["bold": bold, "date": date])) } - // CollectionView - cell.activityPreviews = NCManageDatabase.shared.getActivityPreview(account: activity.account, idActivity: activity.idActivity, orderKeysId: orderKeysId) - if cell.activityPreviews.isEmpty { - cell.collectionViewHeightConstraint.constant = 0 - } else { - cell.collectionViewHeightConstraint.constant = 60 - } - cell.collectionView.reloadData() - return cell } } @@ -345,16 +338,15 @@ extension NCActivity: UIScrollViewDelegate { // MARK: - NC API & Algorithm extension NCActivity { - func fetchAll(isInitial: Bool) { guard !isFetchingActivity else { return } self.isFetchingActivity = true - var bottom: CGFloat = 0 + if let mainTabBar = self.tabBarController?.tabBar as? NCMainTabBar { bottom = -mainTabBar.getHeight() } - NCActivityIndicator.shared.start(backgroundView: self.view, bottom: bottom - 5, style: .medium) + NCActivityIndicator.shared.start(backgroundView: self.view, bottom: bottom - 35, style: .medium) let dispatchGroup = DispatchGroup() loadComments(disptachGroup: dispatchGroup) @@ -377,8 +369,8 @@ extension NCActivity { } func loadDataSource() { - var newItems = [DateCompareable]() + if showComments, let metadata = metadata, let account = NCManageDatabase.shared.getActiveAccount() { let comments = NCManageDatabase.shared.getComments(account: account.account, objectId: metadata.fileId) newItems += comments @@ -450,10 +442,9 @@ extension NCActivity { func loadActivity(idActivity: Int, limit: Int = 200, disptachGroup: DispatchGroup) { guard hasActivityToLoad else { return } - var resultActivityId = 0 - disptachGroup.enter() + disptachGroup.enter() NextcloudKit.shared.getActivity( since: idActivity, limit: min(limit, 200), diff --git a/iOSClient/Activity/NCActivityCommentView.swift b/iOSClient/Activity/NCActivityCommentView.swift index 22f9072798..d308940641 100644 --- a/iOSClient/Activity/NCActivityCommentView.swift +++ b/iOSClient/Activity/NCActivityCommentView.swift @@ -25,7 +25,6 @@ import UIKit class NCActivityCommentView: UIView, UITextFieldDelegate { @IBOutlet weak var imageItem: UIImageView! - @IBOutlet weak var labelUser: UILabel! @IBOutlet weak var newCommentField: UITextField! var completionHandler: ((String?) -> Void)? @@ -42,13 +41,6 @@ class NCActivityCommentView: UIView, UITextFieldDelegate { } else { imageItem.image = NCUtility().loadImage(named: "person.crop.circle", colors: [NCBrandColor.shared.iconImageColor]) } - - if account.displayName.isEmpty { - labelUser.text = account.user - } else { - labelUser.text = account.displayName - } - labelUser.textColor = NCBrandColor.shared.textColor } func textFieldShouldReturn(_ textField: UITextField) -> Bool { @@ -57,3 +49,12 @@ class NCActivityCommentView: UIView, UITextFieldDelegate { return true } } + +extension NCActivityCommentView: UISearchBarDelegate { + func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { + searchBar.resignFirstResponder() + completionHandler?(searchBar.text) + } + + func searchBarTextDidEndEditing(_ searchBar: UISearchBar) { } +} diff --git a/iOSClient/Activity/NCActivityCommentView.xib b/iOSClient/Activity/NCActivityCommentView.xib index 0eba994ad3..e60f0514d4 100644 --- a/iOSClient/Activity/NCActivityCommentView.xib +++ b/iOSClient/Activity/NCActivityCommentView.xib @@ -1,60 +1,61 @@ - + - + + - + - + - - + + - - + + + - + - + - - - - - - - - - + + + + + + - + + + + + + + + diff --git a/iOSClient/Activity/NCActivityTableViewCell.swift b/iOSClient/Activity/NCActivityTableViewCell.swift index 4286b25902..13aa77ace8 100644 --- a/iOSClient/Activity/NCActivityTableViewCell.swift +++ b/iOSClient/Activity/NCActivityTableViewCell.swift @@ -28,7 +28,6 @@ import JGProgressHUD import Queuer class NCActivityCollectionViewCell: UICollectionViewCell { - @IBOutlet weak var imageView: UIImageView! var fileId = "" @@ -40,13 +39,10 @@ class NCActivityCollectionViewCell: UICollectionViewCell { } class NCActivityTableViewCell: UITableViewCell, NCCellProtocol { - - @IBOutlet weak var collectionView: UICollectionView! @IBOutlet weak var icon: UIImageView! @IBOutlet weak var avatar: UIImageView! @IBOutlet weak var subject: UILabel! - @IBOutlet weak var subjectTrailingConstraint: NSLayoutConstraint! - @IBOutlet weak var collectionViewHeightConstraint: NSLayoutConstraint! + @IBOutlet weak var subjectLeadingConstraint: NSLayoutConstraint! private let appDelegate = (UIApplication.shared.delegate as? AppDelegate)! private var user: String = "" @@ -73,8 +69,6 @@ class NCActivityTableViewCell: UITableViewCell, NCCellProtocol { override func awakeFromNib() { super.awakeFromNib() - collectionView.delegate = self - collectionView.dataSource = self let avatarRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapAvatarImage)) avatar.addGestureRecognizer(avatarRecognizer) } @@ -88,19 +82,16 @@ class NCActivityTableViewCell: UITableViewCell, NCCellProtocol { // MARK: - Collection View extension NCActivityTableViewCell: UICollectionViewDelegate { - func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - // Select not permitted if !didSelectItemEnable { return } - let activityPreview = activityPreviews[indexPath.row] if activityPreview.view == "trashbin" { - var responder: UIResponder? = collectionView + while !(responder is UIViewController) { responder = responder?.next if responder == nil { @@ -119,23 +110,19 @@ extension NCActivityTableViewCell: UICollectionViewDelegate { } } } - return } if activityPreview.view == NCGlobal.shared.appName && activityPreview.mimeType != "dir" { - guard let activitySubjectRich = NCManageDatabase.shared.getActivitySubjectRich(account: activityPreview.account, idActivity: activityPreview.idActivity, id: String(activityPreview.fileId)) else { return } - NCActionCenter.shared.viewerFile(account: appDelegate.account, fileId: activitySubjectRich.id, viewController: viewController) } } } extension NCActivityTableViewCell: UICollectionViewDataSource { - func numberOfSections(in collectionView: UICollectionView) -> Int { return 1 } @@ -146,7 +133,6 @@ extension NCActivityTableViewCell: UICollectionViewDataSource { } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - guard let cell: NCActivityCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as? NCActivityCollectionViewCell else { return UICollectionViewCell() } @@ -159,7 +145,6 @@ extension NCActivityTableViewCell: UICollectionViewDataSource { // Trashbin if activityPreview.view == "trashbin" { - let source = activityPreview.source utility.convertSVGtoPNGWriteToUserData(svgUrlString: source, width: 100, rewrite: false, account: appDelegate.account, id: idActivity) { imageNamePath, id in @@ -169,11 +154,8 @@ extension NCActivityTableViewCell: UICollectionViewDataSource { cell.imageView.image = NCImageCache.images.file } } - } else { - if activityPreview.isMimeTypeIcon { - let source = activityPreview.source utility.convertSVGtoPNGWriteToUserData(svgUrlString: source, width: 150, rewrite: false, account: appDelegate.account, id: idActivity) { imageNamePath, id in @@ -183,11 +165,8 @@ extension NCActivityTableViewCell: UICollectionViewDataSource { cell.imageView.image = NCImageCache.images.file } } - } else { - if let activitySubjectRich = NCManageDatabase.shared.getActivitySubjectRich(account: activityPreview.account, idActivity: idActivity, id: fileId) { - let fileNamePath = NCUtilityFileSystem().directoryUserData + "/" + activitySubjectRich.name if FileManager.default.fileExists(atPath: fileNamePath), let image = UIImage(contentsOfFile: fileNamePath) { @@ -206,20 +185,17 @@ extension NCActivityTableViewCell: UICollectionViewDataSource { } } } - return cell } - } extension NCActivityTableViewCell: UICollectionViewDelegateFlowLayout { - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { - return CGSize(width: 50, height: 50) + return CGSize(width: 50, height: 30) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { - return 20 + return 0 } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { @@ -228,7 +204,6 @@ extension NCActivityTableViewCell: UICollectionViewDelegateFlowLayout { } class NCOperationDownloadThumbnailActivity: ConcurrentOperation { - var cell: NCActivityCollectionViewCell? var collectionView: UICollectionView? var fileNamePreviewLocalPath: String @@ -243,10 +218,10 @@ class NCOperationDownloadThumbnailActivity: ConcurrentOperation { override func start() { guard !isCancelled else { return self.finish() } + NextcloudKit.shared.downloadPreview(fileId: fileId, fileNamePreviewLocalPath: fileNamePreviewLocalPath, options: NKRequestOptions(queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)) { _, imagePreview, _, _, _, error in - if error == .success, let imagePreview = imagePreview { DispatchQueue.main.async { if self.fileId == self.cell?.fileId, let imageView = self.cell?.imageView { diff --git a/iOSClient/AppDelegate.swift b/iOSClient/AppDelegate.swift index 54e7ed0a3d..5d1afabd3d 100644 --- a/iOSClient/AppDelegate.swift +++ b/iOSClient/AppDelegate.swift @@ -87,12 +87,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD NextcloudKit.shared.nkCommonInstance.pathLog = utilityFileSystem.directoryGroup if NCBrandOptions.shared.disable_log { - utilityFileSystem.removeFile(atPath: NextcloudKit.shared.nkCommonInstance.filenamePathLog) utilityFileSystem.removeFile(atPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! + "/" + NextcloudKit.shared.nkCommonInstance.filenameLog) - } else { - levelLog = NCKeychain().logLevel NextcloudKit.shared.nkCommonInstance.levelLog = levelLog NextcloudKit.shared.nkCommonInstance.copyLogToDocumentDirectory = true @@ -101,6 +98,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD if let activeAccount = NCManageDatabase.shared.getActiveAccount() { NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Account active \(activeAccount.account)") + if NCKeychain().getPassword(account: activeAccount.account).isEmpty { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] PASSWORD NOT FOUND for \(activeAccount.account)") } @@ -111,16 +109,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD userId = activeAccount.userId password = NCKeychain().getPassword(account: account) - NextcloudKit.shared.setup(account: account, user: user, userId: userId, password: password, urlBase: urlBase) + NextcloudKit.shared.setup(account: account, user: user, userId: userId, password: password, urlBase: urlBase, groupIdentifier: NCBrandOptions.shared.capabilitiesGroup) NCManageDatabase.shared.setCapabilities(account: account) NCBrandColor.shared.settingThemingColor(account: activeAccount.account) DispatchQueue.global().async { NCImageCache.shared.createMediaCache(account: self.account, withCacheSize: true) } - } else { - NCKeychain().removeAll() if let bundleID = Bundle.main.bundleIdentifier { UserDefaults.standard.removePersistentDomain(forName: bundleID) @@ -287,7 +283,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD } func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { - if let pref = UserDefaults(suiteName: NCBrandOptions.shared.capabilitiesGroups), + if let pref = UserDefaults(suiteName: NCBrandOptions.shared.capabilitiesGroup), let data = pref.object(forKey: "NOTIFICATION_DATA") as? [String: AnyObject] { nextcloudPushNotificationAction(data: data) pref.set(nil, forKey: "NOTIFICATION_DATA") @@ -321,8 +317,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD let accounts = NCManageDatabase.shared.getAllAccount() for account in accounts { if account.account == accountPush { - self.changeAccount(account.account, userProfile: nil) - findAccount = true + self.changeAccount(account.account, userProfile: nil) { + findAccount = true + } } } } @@ -363,22 +360,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD } } - // [WEBPersonalized] [AppConfig] - if NCBrandOptions.shared.use_AppConfig { - if activeLogin?.view.window == nil { - urlBase = NCBrandOptions.shared.loginBaseUrl - NextcloudKit.shared.getLoginFlowV2(serverUrl: urlBase) { token, endpoint, login, _, error in - // Login Flow V2 - if error == .success, let token, let endpoint, let login { - let vc = UIHostingController(rootView: NCLoginPoll(loginFlowV2Token: token, loginFlowV2Endpoint: endpoint, loginFlowV2Login: login, cancelButtonDisabled: NCManageDatabase.shared.getAccounts().isEmptyOrNil)) - UIApplication.shared.firstWindow?.rootViewController?.present(vc, animated: true) - } - } - - return - } - } - // Nextcloud standard login if selector == NCGlobal.shared.introSignup { if activeLogin?.view.window == nil { @@ -394,7 +375,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD } } - } else if NCBrandOptions.shared.disable_intro && NCBrandOptions.shared.disable_request_login_url { + } else if NCBrandOptions.shared.disable_request_login_url { if activeLogin?.view.window == nil { activeLogin = UIStoryboard(name: "NCLogin", bundle: nil).instantiateViewController(withIdentifier: "NCLogin") as? NCLogin activeLogin?.urlBase = NCBrandOptions.shared.loginBaseUrl @@ -468,42 +449,45 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD // MARK: - Account - func createAccount(server: String, username: String, password: String, completion: @escaping (_ error: NKError) -> Void) { - var urlBase = server + func createAccount(urlBase: String, + user: String, + password: String, + completion: @escaping (_ error: NKError) -> Void) { + var urlBase = urlBase if urlBase.last == "/" { urlBase = String(urlBase.dropLast()) } - let account: String = "\(username) \(urlBase)" - let user = username + let account: String = "\(user) \(urlBase)" - NextcloudKit.shared.setup(account: account, user: user, userId: user, password: password, urlBase: urlBase) + NextcloudKit.shared.setup(account: account, user: user, userId: user, password: password, urlBase: urlBase, groupIdentifier: NCBrandOptions.shared.capabilitiesGroup) NextcloudKit.shared.getUserProfile { _, userProfile, _, error in - if error == .success, let userProfile { - NCManageDatabase.shared.deleteAccount(account) NCManageDatabase.shared.addAccount(account, urlBase: urlBase, user: user, userId: userProfile.userId, password: password) - NCKeychain().setClientCertificate(account: account, p12Data: NCNetworking.shared.p12Data, p12Password: NCNetworking.shared.p12Password) - - self.changeAccount(account, userProfile: userProfile) + self.changeAccount(account, userProfile: userProfile) { + completion(error) + } } else { - + NextcloudKit.shared.setup(account: self.account, user: self.user, userId: self.userId, password: self.password, urlBase: self.urlBase, groupIdentifier: NCBrandOptions.shared.capabilitiesGroup) let alertController = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: error.errorDescription, preferredStyle: .alert) alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in })) UIApplication.shared.firstWindow?.rootViewController?.present(alertController, animated: true) + completion(error) } - - completion(error) } } - func changeAccount(_ account: String, userProfile: NKUserProfile?) { + func changeAccount(_ account: String, + userProfile: NKUserProfile?, + completion: () -> Void) { + guard let tableAccount = NCManageDatabase.shared.setAccountActive(account) else { + return completion() + } + NCNetworking.shared.cancelAllQueue() NCNetworking.shared.cancelDataTask() NCNetworking.shared.cancelDownloadTasks() NCNetworking.shared.cancelUploadTasks() - guard let tableAccount = NCManageDatabase.shared.setAccountActive(account) else { return } - if account != self.account { DispatchQueue.global().async { if NCManageDatabase.shared.getAccounts()?.count == 1 { @@ -520,7 +504,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD self.userId = tableAccount.userId self.password = NCKeychain().getPassword(account: tableAccount.account) - NextcloudKit.shared.setup(account: account, user: user, userId: userId, password: password, urlBase: urlBase) + NextcloudKit.shared.setup(account: account, user: user, userId: userId, password: password, urlBase: urlBase, groupIdentifier: NCBrandOptions.shared.capabilitiesGroup) NCManageDatabase.shared.setCapabilities(account: account) if let userProfile { @@ -528,7 +512,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD } NCPushNotification.shared.pushNotification() - NCService().startRequestServicesServer() NCAutoUpload.shared.initAutoUpload(viewController: nil) { items in @@ -536,19 +519,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD } NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterChangeUser) + completion() } - func deleteAccount(_ account: String, wipe: Bool) { + func deleteAccount(_ account: String) { UIApplication.shared.allSceneSessionDestructionExceptFirst() if let account = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", account)) { NCPushNotification.shared.unsubscribingNextcloudServerPushNotification(account: account.account, urlBase: account.urlBase, user: account.user, withSubscribing: false) } - NextcloudKit.shared.deleteAppPassword(serverUrl: urlBase, username: userId, password: password) { _, error in - print(error) - } - let results = NCManageDatabase.shared.getTableLocalFiles(predicate: NSPredicate(format: "account == %@", account), sorted: "ocId", ascending: false) let utilityFileSystem = NCUtilityFileSystem() for result in results { @@ -566,22 +546,17 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD self.userId = "" self.password = "" - if wipe { - let accounts = NCManageDatabase.shared.getAccounts() - if accounts?.count ?? 0 > 0 { - if let newAccount = accounts?.first { - self.changeAccount(newAccount, userProfile: nil) - } - } else { - openLogin(selector: NCGlobal.shared.introLogin, openLoginWeb: false) - } + /* + NextcloudKit.shared.deleteAppPassword(serverUrl: urlBase, username: userId, password: password) { _, error in + print(error) } + */ } func deleteAllAccounts() { let accounts = NCManageDatabase.shared.getAccounts() accounts?.forEach({ account in - deleteAccount(account, wipe: true) + deleteAccount(account) }) } diff --git a/iOSClient/Data/NCDataSource.swift b/iOSClient/Data/NCDataSource.swift index 1c235ce1b1..5575aca838 100644 --- a/iOSClient/Data/NCDataSource.swift +++ b/iOSClient/Data/NCDataSource.swift @@ -25,13 +25,13 @@ import UIKit import NextcloudKit class NCDataSource: NSObject { - var metadatas: [tableMetadata] = [] var metadatasForSection: [NCMetadataForSection] = [] - var directory: tableDirectory? - var groupByField: String = "" + var groupBy: String? + var layout: String? + private let utilityFileSystem = NCUtilityFileSystem() private var sectionsValue: [String] = [] private var providers: [NKSearchProvider]? private var searchResults: [NKSearchResult]? @@ -45,18 +45,25 @@ class NCDataSource: NSObject { super.init() } - init(metadatas: [tableMetadata], account: String, directory: tableDirectory? = nil, sort: String? = "none", ascending: Bool? = false, directoryOnTop: Bool? = true, favoriteOnTop: Bool? = true, groupByField: String = "name", providers: [NKSearchProvider]? = nil, searchResults: [NKSearchResult]? = nil) { + init(metadatas: [tableMetadata], + account: String, + directory: tableDirectory? = nil, + layoutForView: NCDBLayoutForView?, + favoriteOnTop: Bool = true, + providers: [NKSearchProvider]? = nil, + searchResults: [NKSearchResult]? = nil) { super.init() self.metadatas = metadatas.filter({ !(NCGlobal.shared.includeHiddenFiles.contains($0.fileNameView) || $0.isTransferInForeground) }) self.directory = directory - self.sort = sort ?? "none" - self.ascending = ascending ?? false - self.directoryOnTop = directoryOnTop ?? true - self.favoriteOnTop = favoriteOnTop ?? true - self.groupByField = groupByField + self.sort = layoutForView?.sort ?? "none" + self.ascending = layoutForView?.ascending ?? false + self.directoryOnTop = layoutForView?.directoryOnTop ?? true + self.favoriteOnTop = favoriteOnTop + self.groupBy = layoutForView?.groupBy ?? "none" + self.layout = layoutForView?.layout // unified search self.providers = providers self.searchResults = searchResults @@ -67,7 +74,6 @@ class NCDataSource: NSObject { // MARK: - func clearDataSource() { - self.metadatas.removeAll() self.metadatasForSection.removeAll() self.directory = nil @@ -77,14 +83,12 @@ class NCDataSource: NSObject { } func clearDirectory() { - self.directory = nil } - func changeGroupByField(_ groupByField: String) { - - self.groupByField = groupByField - print("DATASOURCE: set group by filed " + groupByField) + func changeGroupByField(_ groupBy: String) { + self.groupBy = groupBy + print("DATASOURCE: set group by filed " + groupBy) self.metadatasForSection.removeAll() self.sectionsValue.removeAll() print("DATASOURCE: remove all sections") @@ -93,7 +97,6 @@ class NCDataSource: NSObject { } func addSection(metadatas: [tableMetadata], searchResult: NKSearchResult?) { - self.metadatas.append(contentsOf: metadatas) if let searchResult = searchResult { @@ -104,7 +107,6 @@ class NCDataSource: NSObject { } internal func createSections() { - // get all Section for metadata in self.metadatas { // skipped livePhoto VIDEO part @@ -115,8 +117,14 @@ class NCDataSource: NSObject { if !self.sectionsValue.contains(section) { self.sectionsValue.append(section) } + // image Cache + if (layout == NCGlobal.shared.layoutPhotoRatio || layout == NCGlobal.shared.layoutPhotoSquare), + (metadata.isVideo || metadata.isImage), + NCImageCache.shared.getPreviewImageCache(ocId: metadata.ocId, etag: metadata.etag) == nil, + let image = UIImage(contentsOfFile: self.utilityFileSystem.getDirectoryProviderStoragePreviewOcId(metadata.ocId, etag: metadata.etag)) { + NCImageCache.shared.addPreviewImageCache(metadata: metadata, image: image) + } } - // Unified search if let providers = self.providers, !providers.isEmpty { let sectionsDictionary = ThreadSafeDictionary() @@ -134,9 +142,7 @@ class NCDataSource: NSObject { self.sectionsValue.append(section.key) } } - } else { - // normal let directory = NSLocalizedString("directory", comment: "").lowercased().firstUppercased self.sectionsValue = self.sectionsValue.sorted { @@ -162,7 +168,6 @@ class NCDataSource: NSObject { } internal func createMetadataForSection(sectionValue: String) { - var searchResult: NKSearchResult? if let providers = self.providers, !providers.isEmpty, let searchResults = self.searchResults { searchResult = searchResults.filter({ $0.id == sectionValue}).first @@ -179,20 +184,17 @@ class NCDataSource: NSObject { } func getMetadataSourceForAllSections() -> [tableMetadata] { - var metadatas: [tableMetadata] = [] for section in metadatasForSection { metadatas.append(contentsOf: section.metadatas) } - return metadatas } // MARK: - func appendMetadatasToSection(_ metadatas: [tableMetadata], metadataForSection: NCMetadataForSection, lastSearchResult: NKSearchResult) { - guard let sectionIndex = getSectionIndex(metadataForSection.sectionValue) else { return } var indexPaths: [IndexPath] = [] @@ -241,7 +243,6 @@ class NCDataSource: NSObject { } func getFooterInformationAllMetadatas() -> (directories: Int, files: Int, size: Int64) { - var directories: Int = 0 var files: Int = 0 var size: Int64 = 0 @@ -251,7 +252,6 @@ class NCDataSource: NSObject { files += metadataForSection.numFile size += metadataForSection.totalSize } - return (directories, files, size) } @@ -263,14 +263,13 @@ class NCDataSource: NSObject { } internal func getSectionValue(metadata: tableMetadata) -> String { - - switch self.groupByField { - case "name": + switch self.groupBy { + case "name", "none": return NSLocalizedString(metadata.name, comment: "") case "classFile": return NSLocalizedString(metadata.classFile, comment: "").lowercased().firstUppercased default: - return NSLocalizedString(metadata.classFile, comment: "") + return NSLocalizedString(metadata.name, comment: "") } } @@ -300,7 +299,6 @@ class NCDataSource: NSObject { // MARK: - class NCMetadataForSection: NSObject { - var sectionValue: String var metadatas: [tableMetadata] var lastSearchResult: NKSearchResult? @@ -337,7 +335,6 @@ class NCMetadataForSection: NSObject { } func createMetadatas() { - // Clear // metadatasSorted.removeAll() @@ -357,7 +354,6 @@ class NCMetadataForSection: NSObject { // if sort != "none" && !sort.isEmpty { metadatasSorted = metadatas.sorted { - switch sort { case "date": if ascending { diff --git a/iOSClient/Data/NCManageDatabase+Account.swift b/iOSClient/Data/NCManageDatabase+Account.swift index 6d2c7f4f31..567b60dfc0 100644 --- a/iOSClient/Data/NCManageDatabase+Account.swift +++ b/iOSClient/Data/NCManageDatabase+Account.swift @@ -80,22 +80,16 @@ class tableAccount: Object, NCUserBaseUrl { } extension NCManageDatabase { - func addAccount(_ account: String, urlBase: String, user: String, userId: String, password: String) { - do { let realm = try Realm() try realm.write { let addObject = tableAccount() - addObject.account = account - NCKeychain().setPassword(account: account, password: password) - addObject.urlBase = urlBase addObject.user = user addObject.userId = userId - realm.add(addObject, update: .all) } } catch let error { @@ -103,8 +97,7 @@ extension NCManageDatabase { } } - @objc func updateAccount(_ account: tableAccount) { - + func updateAccount(_ account: tableAccount) { do { let realm = try Realm() try realm.write { @@ -115,8 +108,7 @@ extension NCManageDatabase { } } - @objc func deleteAccount(_ account: String) { - + func deleteAccount(_ account: String) { do { let realm = try Realm() try realm.write { @@ -128,8 +120,7 @@ extension NCManageDatabase { } } - @objc func getActiveAccount() -> tableAccount? { - + func getActiveAccount() -> tableAccount? { do { let realm = try Realm() guard let result = realm.objects(tableAccount.self).filter("active == true").first else { return nil } @@ -137,12 +128,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } - @objc func getAccounts() -> [String]? { - + func getAccounts() -> [String]? { do { let realm = try Realm() let results = realm.objects(tableAccount.self).sorted(byKeyPath: "account", ascending: true) @@ -152,12 +141,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } - @objc func getAccount(predicate: NSPredicate) -> tableAccount? { - + func getAccount(predicate: NSPredicate) -> tableAccount? { do { let realm = try Realm() guard let result = realm.objects(tableAccount.self).filter(predicate).first else { return nil } @@ -165,12 +152,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } - @objc func getAllAccount() -> [tableAccount] { - + func getAllAccount() -> [tableAccount] { do { let realm = try Realm() let sorted = [SortDescriptor(keyPath: "active", ascending: false), SortDescriptor(keyPath: "user", ascending: true)] @@ -179,12 +164,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return [] } - @objc func getAllAccountOrderAlias() -> [tableAccount] { - + func getAllAccountOrderAlias() -> [tableAccount] { do { let realm = try Realm() let sorted = [SortDescriptor(keyPath: "active", ascending: false), SortDescriptor(keyPath: "alias", ascending: true), SortDescriptor(keyPath: "user", ascending: true)] @@ -193,12 +176,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return [] } - @objc func getAccountAutoUploadFileName() -> String { - + func getAccountAutoUploadFileName() -> String { do { let realm = try Realm() guard let result = realm.objects(tableAccount.self).filter("active == true").first else { return "" } @@ -210,12 +191,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return "" } - @objc func getAccountAutoUploadDirectory(urlBase: String, userId: String, account: String) -> String { - + func getAccountAutoUploadDirectory(urlBase: String, userId: String, account: String) -> String { do { let realm = try Realm() guard let result = realm.objects(tableAccount.self).filter("active == true").first else { return "" } @@ -232,21 +211,17 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return "" } - @objc func getAccountAutoUploadPath(urlBase: String, userId: String, account: String) -> String { - + func getAccountAutoUploadPath(urlBase: String, userId: String, account: String) -> String { let cameraFileName = self.getAccountAutoUploadFileName() let cameraDirectory = self.getAccountAutoUploadDirectory(urlBase: urlBase, userId: userId, account: account) let folderPhotos = utilityFileSystem.stringAppendServerUrl(cameraDirectory, addFileName: cameraFileName) - return folderPhotos } - @objc func getAccountAutoUploadSubfolderGranularity() -> Int { - + func getAccountAutoUploadSubfolderGranularity() -> Int { do { let realm = try Realm() guard let result = realm.objects(tableAccount.self).filter("active == true").first else { return NCGlobal.shared.subfolderGranularityMonthly } @@ -254,12 +229,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return NCGlobal.shared.subfolderGranularityMonthly } func setAccountActive(_ account: String) -> tableAccount? { - var accountReturn = tableAccount() do { @@ -279,12 +252,10 @@ extension NCManageDatabase { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") return nil } - return tableAccount.init(value: accountReturn) } - @objc func removePasswordAccount(_ account: String) { - + func removePasswordAccount(_ account: String) { do { let realm = try Realm() try realm.write { @@ -297,8 +268,7 @@ extension NCManageDatabase { } } - @objc func setAccountAutoUploadProperty(_ property: String, state: Bool) { - + func setAccountAutoUploadProperty(_ property: String, state: Bool) { do { let realm = try Realm() try realm.write { @@ -313,8 +283,7 @@ extension NCManageDatabase { } } - @objc func setAccountAutoUploadGranularity(_ property: String, state: Int) { - + func setAccountAutoUploadGranularity(_ property: String, state: Int) { do { let realm = try Realm() try realm.write { @@ -327,8 +296,7 @@ extension NCManageDatabase { } } - @objc func setAccountAutoUploadFileName(_ fileName: String) { - + func setAccountAutoUploadFileName(_ fileName: String) { do { let realm = try Realm() try realm.write { @@ -341,8 +309,7 @@ extension NCManageDatabase { } } - @objc func setAccountAutoUploadDirectory(_ serverUrl: String?, urlBase: String, userId: String, account: String) { - + func setAccountAutoUploadDirectory(_ serverUrl: String?, urlBase: String, userId: String, account: String) { do { let realm = try Realm() try realm.write { @@ -359,8 +326,7 @@ extension NCManageDatabase { } } - @objc func setAccountUserProfile(account: String, userProfile: NKUserProfile) { - + func setAccountUserProfile(account: String, userProfile: NKUserProfile) { do { let realm = try Realm() try realm.write { @@ -395,8 +361,7 @@ extension NCManageDatabase { } } - @objc func setAccountMediaPath(_ path: String, account: String) { - + func setAccountMediaPath(_ path: String, account: String) { do { let realm = try Realm() try realm.write { @@ -409,13 +374,12 @@ extension NCManageDatabase { } } - @objc func setAccountUserStatus(userStatusClearAt: NSDate?, userStatusIcon: String?, userStatusMessage: String?, userStatusMessageId: String?, userStatusMessageIsPredefined: Bool, userStatusStatus: String?, userStatusStatusIsUserDefined: Bool, account: String) { - + func setAccountUserStatus(userStatusClearAt: Date?, userStatusIcon: String?, userStatusMessage: String?, userStatusMessageId: String?, userStatusMessageIsPredefined: Bool, userStatusStatus: String?, userStatusStatusIsUserDefined: Bool, account: String) { do { let realm = try Realm() try realm.write { if let result = realm.objects(tableAccount.self).filter("account == %@", account).first { - result.userStatusClearAt = userStatusClearAt + result.userStatusClearAt = userStatusClearAt as? NSDate result.userStatusIcon = userStatusIcon result.userStatusMessage = userStatusMessage result.userStatusMessageId = userStatusMessageId @@ -429,7 +393,7 @@ extension NCManageDatabase { } } - @objc func setAccountAlias(_ account: String, alias: String) { + func setAccountAlias(_ account: String, alias: String) { let alias = alias.trimmingCharacters(in: .whitespacesAndNewlines) do { diff --git a/iOSClient/Data/NCManageDatabase+Activity.swift b/iOSClient/Data/NCManageDatabase+Activity.swift index 2392027075..543a02b40c 100644 --- a/iOSClient/Data/NCManageDatabase+Activity.swift +++ b/iOSClient/Data/NCManageDatabase+Activity.swift @@ -56,7 +56,6 @@ class tableActivity: Object, DateCompareable { } class tableActivityLatestId: Object { - @objc dynamic var account = "" @objc dynamic var activityFirstKnown: Int = 0 @objc dynamic var activityLastGiven: Int = 0 @@ -67,7 +66,6 @@ class tableActivityLatestId: Object { } class tableActivityPreview: Object { - @objc dynamic var account = "" @objc dynamic var filename = "" @objc dynamic var idPrimaryKey = "" @@ -85,7 +83,6 @@ class tableActivityPreview: Object { } class tableActivitySubjectRich: Object { - @objc dynamic var account = "" @objc dynamic var idActivity: Int = 0 @objc dynamic var idPrimaryKey = "" @@ -102,21 +99,17 @@ class tableActivitySubjectRich: Object { } extension NCManageDatabase { - func addActivity(_ activities: [NKActivity], account: String) { - do { let realm = try Realm() try realm.write { - for activity in activities { - let addObjectActivity = tableActivity() addObjectActivity.account = account addObjectActivity.idActivity = activity.idActivity addObjectActivity.idPrimaryKey = account + String(activity.idActivity) - addObjectActivity.date = activity.date + addObjectActivity.date = activity.date as NSDate addObjectActivity.app = activity.app addObjectActivity.type = activity.type addObjectActivity.user = activity.user @@ -193,7 +186,6 @@ extension NCManageDatabase { } func getActivity(predicate: NSPredicate, filterFileId: String?) -> (all: [tableActivity], filter: [tableActivity]) { - do { let realm = try Realm() realm.refresh() @@ -208,12 +200,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return([], []) } func getActivitySubjectRich(account: String, idActivity: Int, key: String) -> tableActivitySubjectRich? { - do { let realm = try Realm() realm.refresh() @@ -222,12 +212,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } func getActivitySubjectRich(account: String, idActivity: Int, id: String) -> tableActivitySubjectRich? { - do { let realm = try Realm() realm.refresh() @@ -244,12 +232,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } func getActivityPreview(account: String, idActivity: Int, orderKeysId: [String]) -> [tableActivityPreview] { - var results: [tableActivityPreview] = [] do { @@ -264,12 +250,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return [] } func updateLatestActivityId(activityFirstKnown: Int, activityLastGiven: Int, account: String) { - do { let realm = try Realm() try realm.write { @@ -285,7 +269,6 @@ extension NCManageDatabase { } func getLatestActivityId(account: String) -> tableActivityLatestId? { - do { let realm = try Realm() realm.refresh() @@ -293,7 +276,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } } diff --git a/iOSClient/Data/NCManageDatabase+Avatar.swift b/iOSClient/Data/NCManageDatabase+Avatar.swift index bf43e0ceeb..6f398043a0 100644 --- a/iOSClient/Data/NCManageDatabase+Avatar.swift +++ b/iOSClient/Data/NCManageDatabase+Avatar.swift @@ -63,7 +63,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } @@ -102,7 +101,6 @@ extension NCManageDatabase { } catch let error { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") } - return image } diff --git a/iOSClient/Data/NCManageDatabase+Capabilities.swift b/iOSClient/Data/NCManageDatabase+Capabilities.swift index e3617650b5..73820d709a 100644 --- a/iOSClient/Data/NCManageDatabase+Capabilities.swift +++ b/iOSClient/Data/NCManageDatabase+Capabilities.swift @@ -26,7 +26,6 @@ import RealmSwift import NextcloudKit class tableCapabilities: Object { - @objc dynamic var account = "" @objc dynamic var jsondata: Data? @@ -36,9 +35,7 @@ class tableCapabilities: Object { } extension NCManageDatabase { - func addCapabilitiesJSon(_ data: Data, account: String) { - do { let realm = try Realm() try realm.write { @@ -53,7 +50,6 @@ extension NCManageDatabase { } func getCapabilities(account: String) -> Data? { - do { let realm = try Realm() realm.refresh() @@ -67,11 +63,9 @@ extension NCManageDatabase { } func setCapabilities(account: String, data: Data? = nil) { - let jsonData: Data? struct CapabilityNextcloud: Codable { - struct Ocs: Codable { let meta: Meta let data: Data @@ -360,7 +354,7 @@ extension NCManageDatabase { global.capabilityFilesComments = data.capabilities.files?.comments ?? false global.capabilityFilesBigfilechunking = data.capabilities.files?.bigfilechunking ?? false - global.capabilityUserStatusEnabled = data.capabilities.files?.undelete ?? false + global.capabilityUserStatusEnabled = data.capabilities.userstatus?.enabled ?? false if data.capabilities.external != nil { global.capabilityExternalSites = true } diff --git a/iOSClient/Data/NCManageDatabase+Chunk.swift b/iOSClient/Data/NCManageDatabase+Chunk.swift index 1bd8a87e1c..58468af836 100644 --- a/iOSClient/Data/NCManageDatabase+Chunk.swift +++ b/iOSClient/Data/NCManageDatabase+Chunk.swift @@ -26,7 +26,6 @@ import RealmSwift import NextcloudKit class tableChunk: Object { - @Persisted var account = "" @Persisted var chunkFolder = "" @Persisted(primaryKey: true) var index = "" @@ -36,9 +35,7 @@ class tableChunk: Object { } extension NCManageDatabase { - func getChunkFolder(account: String, ocId: String) -> String { - do { let realm = try Realm() realm.refresh() @@ -47,12 +44,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access to database: \(error)") } - return NSUUID().uuidString } func getChunks(account: String, ocId: String) -> [(fileName: String, size: Int64)] { - var filesChunk: [(fileName: String, size: Int64)] = [] do { @@ -65,12 +60,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access to database: \(error)") } - return filesChunk } func addChunks(account: String, ocId: String, chunkFolder: String, filesChunk: [(fileName: String, size: Int64)]) { - do { let realm = try Realm() try realm.write { @@ -93,7 +86,6 @@ extension NCManageDatabase { } func deleteChunk(account: String, ocId: String, fileChunk: (fileName: String, size: Int64), directory: String) { - do { let realm = try Realm() try realm.write { @@ -108,7 +100,6 @@ extension NCManageDatabase { } func deleteChunks(account: String, ocId: String, directory: String) { - do { let realm = try Realm() try realm.write { @@ -123,5 +114,4 @@ extension NCManageDatabase { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") } } - } diff --git a/iOSClient/Data/NCManageDatabase+Comments.swift b/iOSClient/Data/NCManageDatabase+Comments.swift index 8141c1081d..0af3955943 100644 --- a/iOSClient/Data/NCManageDatabase+Comments.swift +++ b/iOSClient/Data/NCManageDatabase+Comments.swift @@ -47,9 +47,7 @@ class tableComments: Object, DateCompareable { } extension NCManageDatabase { - func addComments(_ comments: [NKComments], account: String, objectId: String) { - do { let realm = try Realm() try realm.write { @@ -78,7 +76,6 @@ extension NCManageDatabase { } func getComments(account: String, objectId: String) -> [tableComments] { - do { let realm = try Realm() realm.refresh() @@ -87,7 +84,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return [] } } diff --git a/iOSClient/Data/NCManageDatabase+DashboardWidget.swift b/iOSClient/Data/NCManageDatabase+DashboardWidget.swift index b770269828..70f0c0ec50 100644 --- a/iOSClient/Data/NCManageDatabase+DashboardWidget.swift +++ b/iOSClient/Data/NCManageDatabase+DashboardWidget.swift @@ -26,7 +26,6 @@ import RealmSwift import NextcloudKit class tableDashboardWidget: Object { - @Persisted(primaryKey: true) var index = "" @Persisted var account = "" @Persisted var id = "" @@ -39,7 +38,6 @@ class tableDashboardWidget: Object { } class tableDashboardWidgetButton: Object { - @Persisted(primaryKey: true) var index = "" @Persisted var account = "" @Persisted var id = "" @@ -49,9 +47,7 @@ class tableDashboardWidgetButton: Object { } extension NCManageDatabase { - func getDashboardWidget(account: String, id: String) -> (tableDashboardWidget?, [tableDashboardWidgetButton]?) { - do { let realm = try Realm() realm.refresh() @@ -61,12 +57,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return (nil, nil) } func getDashboardWidgetApplications(account: String) -> [tableDashboardWidget] { - do { let realm = try Realm() realm.refresh() @@ -76,19 +70,15 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return [] } func addDashboardWidget(account: String, dashboardWidgets: [NCCDashboardWidget]) { - do { let realm = try Realm() try realm.write { - let resultDashboard = realm.objects(tableDashboardWidget.self).filter("account == %@", account) realm.delete(resultDashboard) - let resultDashboardButton = realm.objects(tableDashboardWidgetButton.self).filter("account == %@", account) realm.delete(resultDashboardButton) diff --git a/iOSClient/Data/NCManageDatabase+DirectEditing.swift b/iOSClient/Data/NCManageDatabase+DirectEditing.swift index c104da3bce..6226375539 100644 --- a/iOSClient/Data/NCManageDatabase+DirectEditing.swift +++ b/iOSClient/Data/NCManageDatabase+DirectEditing.swift @@ -26,7 +26,6 @@ import RealmSwift import NextcloudKit class tableDirectEditingCreators: Object { - @objc dynamic var account = "" @objc dynamic var editor = "" @objc dynamic var ext = "" @@ -37,7 +36,6 @@ class tableDirectEditingCreators: Object { } class tableDirectEditingEditors: Object { - @objc dynamic var account = "" @objc dynamic var editor = "" let mimetypes = List() @@ -47,21 +45,16 @@ class tableDirectEditingEditors: Object { } extension NCManageDatabase { - func addDirectEditing(account: String, editors: [NKEditorDetailsEditors], creators: [NKEditorDetailsCreators]) { - do { let realm = try Realm() try realm.write { - let resultsCreators = realm.objects(tableDirectEditingCreators.self).filter("account == %@", account) realm.delete(resultsCreators) - let resultsEditors = realm.objects(tableDirectEditingEditors.self).filter("account == %@", account) realm.delete(resultsEditors) for creator in creators { - let addObject = tableDirectEditingCreators() addObject.account = account @@ -71,12 +64,10 @@ extension NCManageDatabase { addObject.mimetype = creator.mimetype addObject.name = creator.name addObject.templates = creator.templates - realm.add(addObject) } for editor in editors { - let addObject = tableDirectEditingEditors() addObject.account = account @@ -93,7 +84,6 @@ extension NCManageDatabase { addObject.optionalMimetypes.append(mimeType) } addObject.secure = editor.secure - realm.add(addObject) } } @@ -103,7 +93,6 @@ extension NCManageDatabase { } func getDirectEditingCreators(account: String) -> [tableDirectEditingCreators]? { - do { let realm = try Realm() realm.refresh() @@ -116,12 +105,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access to database: \(error)") } - return nil } func getDirectEditingCreators(predicate: NSPredicate) -> [tableDirectEditingCreators]? { - do { let realm = try Realm() realm.refresh() @@ -134,12 +121,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access to database: \(error)") } - return nil } func getDirectEditingEditors(account: String) -> [tableDirectEditingEditors]? { - do { let realm = try Realm() realm.refresh() @@ -152,7 +137,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access to database: \(error)") } - return nil } } diff --git a/iOSClient/Data/NCManageDatabase+Directory.swift b/iOSClient/Data/NCManageDatabase+Directory.swift index b65e076e4e..cdd8ec70ec 100644 --- a/iOSClient/Data/NCManageDatabase+Directory.swift +++ b/iOSClient/Data/NCManageDatabase+Directory.swift @@ -26,7 +26,6 @@ import RealmSwift import NextcloudKit class tableDirectory: Object { - @objc dynamic var account = "" @objc dynamic var colorFolder: String? @objc dynamic var e2eEncrypted: Bool = false @@ -46,7 +45,6 @@ class tableDirectory: Object { } extension NCManageDatabase { - func addDirectory(e2eEncrypted: Bool, favorite: Bool, ocId: String, fileId: String, etag: String? = nil, permissions: String? = nil, richWorkspace: String? = nil, serverUrl: String, account: String) { do { let realm = try Realm() @@ -88,7 +86,6 @@ extension NCManageDatabase { } func deleteDirectoryAndSubDirectory(serverUrl: String, account: String) { - #if !EXTENSION DispatchQueue.main.async { let windowScenes = UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene } @@ -208,7 +205,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } @@ -235,7 +231,7 @@ extension NCManageDatabase { directory.serverUrl = serverUrl directory.offline = offline addDirectory(directory: directory, metadata: metadata) - realm.add(directory) + realm.add(directory, update: .all) } } } catch let error { diff --git a/iOSClient/Data/NCManageDatabase+E2EE.swift b/iOSClient/Data/NCManageDatabase+E2EE.swift index 0ed415176c..86346cc5c3 100644 --- a/iOSClient/Data/NCManageDatabase+E2EE.swift +++ b/iOSClient/Data/NCManageDatabase+E2EE.swift @@ -26,7 +26,6 @@ import RealmSwift import NextcloudKit class tableE2eEncryptionLock: Object { - @Persisted(primaryKey: true) var fileId = "" @Persisted var account = "" @Persisted var date = Date() @@ -36,7 +35,6 @@ class tableE2eEncryptionLock: Object { typealias tableE2eEncryption = tableE2eEncryptionV4 class tableE2eEncryptionV4: Object { - @Persisted(primaryKey: true) var primaryKey = "" @Persisted var account = "" @Persisted var authenticationTag: String = "" @@ -65,7 +63,6 @@ class tableE2eEncryptionV4: Object { // MARK: Table V1, V1.2 class tableE2eMetadata12: Object { - @Persisted(primaryKey: true) var serverUrl = "" @Persisted var account = "" @Persisted var metadataKey = "" @@ -77,7 +74,6 @@ class tableE2eMetadata12: Object { typealias tableE2eMetadata = tableE2eMetadataV2 class tableE2eMetadataV2: Object { - @Persisted(primaryKey: true) var primaryKey = "" @Persisted var account = "" @Persisted var deleted: Bool = false @@ -96,7 +92,6 @@ class tableE2eMetadataV2: Object { } class tableE2eCounter: Object { - @Persisted(primaryKey: true) var primaryKey: String @Persisted var account: String @Persisted var counter: Int @@ -112,7 +107,6 @@ class tableE2eCounter: Object { } class tableE2eUsers: Object { - @Persisted(primaryKey: true) var primaryKey = "" @Persisted var account = "" @Persisted var certificate = "" @@ -132,12 +126,9 @@ class tableE2eUsers: Object { } extension NCManageDatabase { - // MARK: - // MARK: tableE2eEncryption - func addE2eEncryption(_ object: tableE2eEncryption) { - do { let realm = try Realm() try realm.write { @@ -149,7 +140,6 @@ extension NCManageDatabase { } func deleteE2eEncryption(predicate: NSPredicate) { - do { let realm = try Realm() try realm.write { @@ -162,7 +152,6 @@ extension NCManageDatabase { } func getE2eEncryption(predicate: NSPredicate) -> tableE2eEncryption? { - do { let realm = try Realm() guard let result = realm.objects(tableE2eEncryption.self).filter(predicate).sorted(byKeyPath: "metadataKeyIndex", ascending: false).first else { return nil } @@ -170,12 +159,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } func getE2eEncryptions(predicate: NSPredicate) -> [tableE2eEncryption] { - do { let realm = try Realm() let results: Results @@ -184,12 +171,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return [] } func renameFileE2eEncryption(account: String, serverUrl: String, fileNameIdentifier: String, newFileName: String, newFileNamePath: String) { - do { let realm = try Realm() try realm.write { @@ -206,7 +191,6 @@ extension NCManageDatabase { // MARK: Table e2e Encryption Lock func getE2ETokenLock(account: String, serverUrl: String) -> tableE2eEncryptionLock? { - do { let realm = try Realm() guard let result = realm.objects(tableE2eEncryptionLock.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first else { return nil } @@ -214,12 +198,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } func getE2EAllTokenLock(account: String) -> [tableE2eEncryptionLock] { - do { let realm = try Realm() let results = realm.objects(tableE2eEncryptionLock.self).filter("account == %@", account) @@ -231,12 +213,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return [] } func setE2ETokenLock(account: String, serverUrl: String, fileId: String, e2eToken: String) { - do { let realm = try Realm() try realm.write { @@ -253,7 +233,6 @@ extension NCManageDatabase { } func deleteE2ETokenLock(account: String, serverUrl: String) { - do { let realm = try Realm() try realm.write { @@ -270,7 +249,6 @@ extension NCManageDatabase { // MARK: V1 func getE2eMetadata(account: String, serverUrl: String) -> tableE2eMetadata12? { - do { let realm = try Realm() guard let result = realm.objects(tableE2eMetadata12.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first else { return nil } @@ -278,12 +256,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } func setE2eMetadata(account: String, serverUrl: String, metadataKey: String, version: Double) { - do { let realm = try Realm() try realm.write { @@ -309,7 +285,6 @@ extension NCManageDatabase { certificate: String, encryptedMetadataKey: String?, metadataKey: Data?) { - do { let realm = try Realm() try realm.write { @@ -326,7 +301,6 @@ extension NCManageDatabase { } func deleteE2EUsers(account: String, ocIdServerUrl: String, userId: String) { - do { let realm = try Realm() try realm.write { @@ -340,43 +314,36 @@ extension NCManageDatabase { } func getE2EUsers(account: String, ocIdServerUrl: String) -> Results? { - do { let realm = try Realm() return realm.objects(tableE2eUsers.self).filter("account == %@ AND ocIdServerUrl == %@", account, ocIdServerUrl) } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } func getE2EUser(account: String, ocIdServerUrl: String, userId: String) -> tableE2eUsers? { - do { let realm = try Realm() return realm.objects(tableE2eUsers.self).filter("account == %@ && ocIdServerUrl == %@ AND userId == %@", account, ocIdServerUrl, userId).first } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } func getE2eMetadata(account: String, ocIdServerUrl: String) -> tableE2eMetadata? { - do { let realm = try Realm() return realm.objects(tableE2eMetadata.self).filter("account == %@ && ocIdServerUrl == %@", account, ocIdServerUrl).first } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } func addE2eMetadata(account: String, serverUrl: String, ocIdServerUrl: String, keyChecksums: [String]?, deleted: Bool, folders: [String: String]?, version: String) { - do { let realm = try Realm() try realm.write { @@ -401,7 +368,6 @@ extension NCManageDatabase { } func updateCounterE2eMetadata(account: String, ocIdServerUrl: String, counter: Int) { - do { let realm = try Realm() try realm.write { @@ -414,14 +380,12 @@ extension NCManageDatabase { } func getCounterE2eMetadata(account: String, ocIdServerUrl: String) -> Int? { - do { let realm = try Realm() return realm.objects(tableE2eCounter.self).filter("account == %@ && ocIdServerUrl == %@", account, ocIdServerUrl).first?.counter } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } } diff --git a/iOSClient/Data/NCManageDatabase+ExternalSites.swift b/iOSClient/Data/NCManageDatabase+ExternalSites.swift index 098042da56..3cb09b85f8 100644 --- a/iOSClient/Data/NCManageDatabase+ExternalSites.swift +++ b/iOSClient/Data/NCManageDatabase+ExternalSites.swift @@ -26,7 +26,6 @@ import RealmSwift import NextcloudKit class tableExternalSites: Object { - @objc dynamic var account = "" @objc dynamic var icon = "" @objc dynamic var idExternalSite: Int = 0 @@ -37,9 +36,7 @@ class tableExternalSites: Object { } extension NCManageDatabase { - func addExternalSites(_ externalSite: NKExternalSite, account: String) { - do { let realm = try Realm() try realm.write { @@ -61,7 +58,6 @@ extension NCManageDatabase { } func deleteExternalSites(account: String) { - do { let realm = try Realm() try realm.write { @@ -74,7 +70,6 @@ extension NCManageDatabase { } func getAllExternalSites(account: String) -> [tableExternalSites]? { - do { let realm = try Realm() realm.refresh() @@ -87,7 +82,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access to database: \(error)") } - return nil } } diff --git a/iOSClient/Data/NCManageDatabase+GPS.swift b/iOSClient/Data/NCManageDatabase+GPS.swift index fae9896fbf..4e0c3928b6 100644 --- a/iOSClient/Data/NCManageDatabase+GPS.swift +++ b/iOSClient/Data/NCManageDatabase+GPS.swift @@ -33,9 +33,7 @@ class tableGPSV2: Object { } extension NCManageDatabase { - - @objc func addGeocoderLocation(_ location: String, latitude: Double, longitude: Double) { - + func addGeocoderLocation(_ location: String, latitude: Double, longitude: Double) { do { let realm = try Realm() realm.refresh() @@ -52,7 +50,7 @@ extension NCManageDatabase { } } - @objc func getLocationFromLatAndLong(latitude: Double, longitude: Double) -> String? { + func getLocationFromLatAndLong(latitude: Double, longitude: Double) -> String? { do { let realm = try Realm() realm.refresh() @@ -61,7 +59,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access to database: \(error)") } - return nil } } diff --git a/iOSClient/Data/NCManageDatabase+Groupfolders.swift b/iOSClient/Data/NCManageDatabase+Groupfolders.swift index 83b2bf5a43..6251e02800 100644 --- a/iOSClient/Data/NCManageDatabase+Groupfolders.swift +++ b/iOSClient/Data/NCManageDatabase+Groupfolders.swift @@ -26,7 +26,6 @@ import RealmSwift import NextcloudKit class TableGroupfolders: Object { - @Persisted var account = "" @Persisted var acl: Bool = false @Persisted var groups: List @@ -38,7 +37,6 @@ class TableGroupfolders: Object { } class TableGroupfoldersGroups: Object { - @Persisted var account = "" @Persisted var group = "" @Persisted var permission: Int = 0 @@ -53,9 +51,7 @@ class TableGroupfoldersGroups: Object { } extension NCManageDatabase { - func addGroupfolders(account: String, groupfolders: [NKGroupfolders]) { - do { let realm = try Realm() try realm.write { diff --git a/iOSClient/Data/NCManageDatabase+LayoutForView.swift b/iOSClient/Data/NCManageDatabase+LayoutForView.swift index cbbbcff2e1..4286a84695 100644 --- a/iOSClient/Data/NCManageDatabase+LayoutForView.swift +++ b/iOSClient/Data/NCManageDatabase+LayoutForView.swift @@ -26,7 +26,6 @@ import RealmSwift import NextcloudKit class NCDBLayoutForView: Object { - @Persisted(primaryKey: true) var index = "" @Persisted var account = "" @Persisted var keyStore = "" @@ -36,14 +35,23 @@ class NCDBLayoutForView: Object { @Persisted var groupBy: String = "none" @Persisted var directoryOnTop: Bool = true @Persisted var titleButtonHeader: String = "_sorted_by_name_a_z_" - @Persisted var itemForLine: Int = 3 + @Persisted var columnGrid: Int = 3 + @Persisted var columnPhoto: Int = 3 } extension NCManageDatabase { - @discardableResult - func setLayoutForView(account: String, key: String, serverUrl: String, layout: String? = nil, sort: String? = nil, ascending: Bool? = nil, groupBy: String? = nil, directoryOnTop: Bool? = nil, titleButtonHeader: String? = nil, itemForLine: Int? = nil) -> NCDBLayoutForView? { - + func setLayoutForView(account: String, + key: String, + serverUrl: String, + layout: String? = nil, + sort: String? = nil, + ascending: Bool? = nil, + groupBy: String? = nil, + directoryOnTop: Bool? = nil, + titleButtonHeader: String? = nil, + columnGrid: Int? = nil, + columnPhoto: Int? = nil) -> NCDBLayoutForView? { var keyStore = key if !serverUrl.isEmpty { keyStore = serverUrl} let index = account + " " + keyStore @@ -59,42 +67,43 @@ extension NCManageDatabase { } addObject.account = account addObject.keyStore = keyStore - if let layout = layout { + if let layout { addObject.layout = layout } - if let sort = sort { + if let sort { addObject.sort = sort } - if let sort = sort { + if let sort { addObject.sort = sort } - if let ascending = ascending { + if let ascending { addObject.ascending = ascending } - if let groupBy = groupBy { + if let groupBy { addObject.groupBy = groupBy } - if let directoryOnTop = directoryOnTop { + if let directoryOnTop { addObject.directoryOnTop = directoryOnTop } - if let titleButtonHeader = titleButtonHeader { + if let titleButtonHeader { addObject.titleButtonHeader = titleButtonHeader } - if let itemForLine = itemForLine { - addObject.itemForLine = itemForLine + if let columnGrid { + addObject.columnGrid = columnGrid + } + if let columnPhoto { + addObject.columnPhoto = columnPhoto } realm.add(addObject, update: .all) } } catch let error { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") } - return NCDBLayoutForView(value: addObject) } @discardableResult func setLayoutForView(layoutForView: NCDBLayoutForView) -> NCDBLayoutForView? { - let result = NCDBLayoutForView(value: layoutForView) do { @@ -110,7 +119,6 @@ extension NCManageDatabase { } func getLayoutForView(account: String, key: String, serverUrl: String) -> NCDBLayoutForView? { - var keyStore = key if !serverUrl.isEmpty { keyStore = serverUrl} let index = account + " " + keyStore @@ -126,7 +134,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return setLayoutForView(account: account, key: key, serverUrl: serverUrl) } } diff --git a/iOSClient/Data/NCManageDatabase+LocalFile.swift b/iOSClient/Data/NCManageDatabase+LocalFile.swift index 387470112d..608bae383b 100644 --- a/iOSClient/Data/NCManageDatabase+LocalFile.swift +++ b/iOSClient/Data/NCManageDatabase+LocalFile.swift @@ -26,7 +26,6 @@ import RealmSwift import NextcloudKit class tableLocalFile: Object { - @objc dynamic var account = "" @objc dynamic var etag = "" @objc dynamic var exifDate: NSDate? @@ -43,13 +42,11 @@ class tableLocalFile: Object { return "ocId" } } -extension NCManageDatabase { +extension NCManageDatabase { // MARK: - // MARK: Table LocalFile - return RESULT - func getTableLocalFile(ocId: String) -> tableLocalFile? { - do { let realm = try Realm() return realm.objects(tableLocalFile.self).filter("ocId == %@", ocId).first @@ -63,7 +60,6 @@ extension NCManageDatabase { // MARK: Table LocalFile func addLocalFile(metadata: tableMetadata, offline: Bool? = nil) { - do { let realm = try Realm() try realm.write { @@ -86,7 +82,6 @@ extension NCManageDatabase { } func addLocalFile(account: String, etag: String, ocId: String, fileName: String) { - do { let realm = try Realm() try realm.write { @@ -106,7 +101,6 @@ extension NCManageDatabase { } func deleteLocalFile(predicate: NSPredicate) { - do { let realm = try Realm() try realm.write { @@ -119,7 +113,6 @@ extension NCManageDatabase { } func setLocalFile(ocId: String, fileName: String?) { - do { let realm = try Realm() try realm.write { @@ -134,7 +127,6 @@ extension NCManageDatabase { } @objc func setLocalFile(ocId: String, exifDate: NSDate?, exifLatitude: String, exifLongitude: String, exifLensModel: String?) { - do { let realm = try Realm() try realm.write { @@ -153,7 +145,6 @@ extension NCManageDatabase { } func setOffLocalFile(ocId: String) { - do { let realm = try Realm() try realm.write { @@ -166,7 +157,6 @@ extension NCManageDatabase { } func getTableLocalFile(account: String) -> [tableLocalFile] { - do { let realm = try Realm() let results = realm.objects(tableLocalFile.self).filter("account == %@", account) @@ -174,12 +164,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return [] } func getTableLocalFile(predicate: NSPredicate) -> tableLocalFile? { - do { let realm = try Realm() guard let result = realm.objects(tableLocalFile.self).filter(predicate).first else { return nil } @@ -187,24 +175,20 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } func getResultsTableLocalFile(predicate: NSPredicate) -> Results? { - do { let realm = try Realm() return realm.objects(tableLocalFile.self).filter(predicate) } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } func getTableLocalFiles(predicate: NSPredicate, sorted: String, ascending: Bool) -> [tableLocalFile] { - do { let realm = try Realm() let results = realm.objects(tableLocalFile.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending) @@ -212,24 +196,20 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return [] } func getResultsTableLocalFile(predicate: NSPredicate, sorted: String, ascending: Bool) -> Results? { - do { let realm = try Realm() return realm.objects(tableLocalFile.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending) } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } func setLastOpeningDate(metadata: tableMetadata) { - do { let realm = try Realm() try realm.write { diff --git a/iOSClient/Data/NCManageDatabase+Metadata+Session.swift b/iOSClient/Data/NCManageDatabase+Metadata+Session.swift index 924d0afd80..2d4328ed35 100644 --- a/iOSClient/Data/NCManageDatabase+Metadata+Session.swift +++ b/iOSClient/Data/NCManageDatabase+Metadata+Session.swift @@ -26,7 +26,6 @@ import RealmSwift import NextcloudKit extension NCManageDatabase { - func setMetadataSession(ocId: String, newFileName: String? = nil, session: String? = nil, @@ -80,7 +79,6 @@ extension NCManageDatabase { func setMetadataSession(ocId: String, status: Int? = nil, taskIdentifier: Int? = nil) { - do { let realm = try Realm() try realm.write { @@ -160,6 +158,7 @@ extension NCManageDatabase { @discardableResult func setMetadataStatus(ocId: String, status: Int) -> tableMetadata? { var result: tableMetadata? + do { let realm = try Realm() try realm.write { diff --git a/iOSClient/Data/NCManageDatabase+Metadata.swift b/iOSClient/Data/NCManageDatabase+Metadata.swift index 16c5716bd6..c1a1092a09 100644 --- a/iOSClient/Data/NCManageDatabase+Metadata.swift +++ b/iOSClient/Data/NCManageDatabase+Metadata.swift @@ -42,6 +42,11 @@ class tableMetadata: Object, NCUserBaseUrl { self.favorite == object.favorite, self.livePhotoFile == object.livePhotoFile, self.sharePermissionsCollaborationServices == object.sharePermissionsCollaborationServices, + self.height == object.height, + self.width == object.width, + self.latitude == object.latitude, + self.longitude == object.longitude, + self.altitude == object.altitude, Array(self.tags).elementsEqual(Array(object.tags)), Array(self.shareType).elementsEqual(Array(object.shareType)), Array(self.sharePermissionsCloudMesh).elementsEqual(Array(object.sharePermissionsCloudMesh)) { @@ -82,6 +87,7 @@ class tableMetadata: Object, NCUserBaseUrl { @objc dynamic var name = "" // for unifiedSearch is the provider.id @objc dynamic var note = "" @objc dynamic var ocId = "" + @objc dynamic var ocIdTemp = "" @objc dynamic var ownerId = "" @objc dynamic var ownerDisplayName = "" @objc public var lock = false @@ -132,7 +138,6 @@ class tableMetadata: Object, NCUserBaseUrl { } extension tableMetadata { - var fileExtension: String { (fileNameView as NSString).pathExtension } @@ -227,16 +232,6 @@ extension tableMetadata { return !isDirectoryE2EE && directory && size == 0 && e2eEncrypted && NCKeychain().isEndToEndEnabled(account: account) } - var canOpenExternalEditor: Bool { - if isDocumentViewableOnly { - return false - } - let utility = NCUtility() - let editors = utility.isDirectEditing(account: account, contentType: contentType) - let isRichDocument = utility.isRichDocument(self) - return classFile == NKCommon.TypeClassFile.document.rawValue && editors.contains(NCGlobal.shared.editorText) && ((editors.contains(NCGlobal.shared.editorOnlyoffice) || isRichDocument)) - } - var isWaitingTransfer: Bool { status == NCGlobal.shared.metadataStatusWaitDownload || status == NCGlobal.shared.metadataStatusWaitUpload || status == NCGlobal.shared.metadataStatusUploadError } @@ -281,6 +276,41 @@ extension tableMetadata { !isImage && !isAudioOrVideo && hasPreview && NCUtilityFileSystem().fileProviderStoragePreviewIconExists(ocId, etag: etag) } + var isAvailableEditorView: Bool { + guard (classFile == NKCommon.TypeClassFile.document.rawValue) && NextcloudKit.shared.isNetworkReachable() else { return false } + let utility = NCUtility() + let directEditingEditors = utility.editorsDirectEditing(account: account, contentType: contentType) + let richDocumentEditor = utility.isTypeFileRichDocument(self) + + if NCGlobal.shared.capabilityRichDocumentsEnabled && richDocumentEditor && directEditingEditors.isEmpty { + // RichDocument: Collabora + return true + } else if directEditingEditors.contains(NCGlobal.shared.editorText) || directEditingEditors.contains(NCGlobal.shared.editorOnlyoffice) { + // DirectEditing: Nextcloud Text - OnlyOffice + return true + } + return false + } + + var isAvailableRichDocumentEditorView: Bool { + guard (classFile == NKCommon.TypeClassFile.document.rawValue) && NCGlobal.shared.capabilityRichDocumentsEnabled && NextcloudKit.shared.isNetworkReachable() else { return false } + + if NCUtility().isTypeFileRichDocument(self) { + return true + } + return false + } + + var isAvailableDirectEditingEditorView: Bool { + guard (classFile == NKCommon.TypeClassFile.document.rawValue) && NextcloudKit.shared.isNetworkReachable() else { return false } + let editors = NCUtility().editorsDirectEditing(account: account, contentType: contentType) + + if editors.contains(NCGlobal.shared.editorText) || editors.contains(NCGlobal.shared.editorOnlyoffice) { + 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) @@ -296,9 +326,7 @@ extension tableMetadata { } extension NCManageDatabase { - func convertFileToMetadata(_ file: NKFile, isDirectoryE2EE: Bool) -> tableMetadata { - let metadata = tableMetadata() metadata.account = file.account @@ -306,12 +334,12 @@ extension NCManageDatabase { metadata.commentsUnread = file.commentsUnread metadata.contentType = file.contentType if let date = file.creationDate { - metadata.creationDate = date + metadata.creationDate = date as NSDate } else { - metadata.creationDate = file.date + metadata.creationDate = file.date as NSDate } metadata.dataFingerprint = file.dataFingerprint - metadata.date = file.date + metadata.date = file.date as NSDate metadata.directory = file.directory metadata.downloadURL = file.downloadURL metadata.e2eEncrypted = file.e2eEncrypted @@ -360,9 +388,9 @@ extension NCManageDatabase { metadata.classFile = NKCommon.TypeClassFile.document.rawValue } if let date = file.uploadDate { - metadata.uploadDate = date + metadata.uploadDate = date as NSDate } else { - metadata.uploadDate = file.date + metadata.uploadDate = file.date as NSDate } metadata.urlBase = file.urlBase metadata.user = file.user @@ -385,21 +413,17 @@ extension NCManageDatabase { metadata.classFile = results.classFile } } - return metadata } func convertFilesToMetadatas(_ files: [NKFile], useFirstAsMetadataFolder: Bool, completion: @escaping (_ metadataFolder: tableMetadata, _ metadatas: [tableMetadata]) -> Void) { - var counter: Int = 0 var isDirectoryE2EE: Bool = false let listServerUrl = ThreadSafeDictionary() - var metadataFolder = tableMetadata() var metadatas: [tableMetadata] = [] for file in files { - if let key = listServerUrl[file.serverUrl] { isDirectoryE2EE = key } else { @@ -417,12 +441,10 @@ extension NCManageDatabase { counter += 1 } - completion(metadataFolder, metadatas) } func convertFilesToMetadatas(_ files: [NKFile], useFirstAsMetadataFolder: Bool) async -> (metadataFolder: tableMetadata, metadatas: [tableMetadata]) { - await withUnsafeContinuation({ continuation in convertFilesToMetadatas(files, useFirstAsMetadataFolder: useFirstAsMetadataFolder) { metadataFolder, metadatas in continuation.resume(returning: (metadataFolder, metadatas)) @@ -431,8 +453,8 @@ extension NCManageDatabase { } 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() + if isUrl { metadata.contentType = "text/uri-list" if let iconName = iconName { @@ -467,6 +489,7 @@ extension NCManageDatabase { metadata.fileNameView = fileName metadata.name = name metadata.ocId = ocId + metadata.ocIdTemp = ocId metadata.permissions = "RGDNVW" metadata.serverUrl = serverUrl metadata.subline = subline @@ -479,7 +502,6 @@ extension NCManageDatabase { if !metadata.urlBase.isEmpty, metadata.serverUrl.hasPrefix(metadata.urlBase) { metadata.path = String(metadata.serverUrl.dropFirst(metadata.urlBase.count)) + "/" } - return metadata } @@ -689,12 +711,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } func getMetadatas(predicate: NSPredicate) -> [tableMetadata] { - do { let realm = try Realm() realm.refresh() @@ -703,12 +723,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - 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) @@ -716,7 +734,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } @@ -731,31 +748,26 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - 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("[ERROR] Could not access database: \(error)") } - return nil } func getResultMetadata(predicate: NSPredicate) -> tableMetadata? { - do { let realm = try Realm() return realm.objects(tableMetadata.self).filter(predicate).first } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } @@ -774,12 +786,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return metadatas } func getMetadataAtIndex(predicate: NSPredicate, sorted: String, ascending: Bool, index: Int) -> tableMetadata? { - do { let realm = try Realm() realm.refresh() @@ -792,13 +802,12 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } func getMetadataFromOcId(_ ocId: String?) -> tableMetadata? { - guard let ocId else { return nil } + do { let realm = try Realm() realm.refresh() @@ -807,12 +816,28 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } + return nil + } + + func getMetadataFromOcIdAndOcIdTemp(_ ocId: String?) -> tableMetadata? { + guard let ocId else { return nil } + do { + let realm = try Realm() + realm.refresh() + if let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first { + return tableMetadata(value: result) + } + if let result = realm.objects(tableMetadata.self).filter("ocIdTemp == %@", ocId).first { + return tableMetadata(value: result) + } + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") + } return nil } func getMetadataFromFileName(_ fileName: String, serverUrl: String) -> tableMetadata? { - do { let realm = try Realm() realm.refresh() @@ -821,13 +846,12 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } func getMetadataFromFileNameLocalPath(_ fileNameLocalPath: String?) -> tableMetadata? { - let components = fileNameLocalPath?.components(separatedBy: "/") + if let count = components?.count, components?.count ?? 0 > 2, let ocId = components?[count - 2] { @@ -840,13 +864,12 @@ extension NCManageDatabase { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } } - return nil } func getTableMetadataFromOcId(_ ocId: String?) -> tableMetadata? { - guard let ocId else { return nil } + do { let realm = try Realm() realm.refresh() @@ -858,7 +881,6 @@ extension NCManageDatabase { } func getMetadataFromFileId(_ fileId: String?) -> tableMetadata? { - do { let realm = try Realm() realm.refresh() @@ -868,16 +890,14 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } func getMetadataFolder(account: String, urlBase: String, userId: String, serverUrl: String) -> tableMetadata? { - var serverUrl = serverUrl var fileName = "" - let serverUrlHome = utilityFileSystem.getHomeServer(urlBase: urlBase, userId: userId) + if serverUrlHome == serverUrl { fileName = "." serverUrl = ".." @@ -896,7 +916,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } @@ -915,7 +934,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return listIdentifierRank } @@ -958,7 +976,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } @@ -986,7 +1003,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } @@ -996,12 +1012,9 @@ extension NCManageDatabase { var isMounted = false if metadataFolder != nil { - isShare = metadata.permissions.contains(permissions.permissionShared) && !metadataFolder!.permissions.contains(permissions.permissionShared) isMounted = metadata.permissions.contains(permissions.permissionMounted) && !metadataFolder!.permissions.contains(permissions.permissionMounted) - } else if let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, metadata.serverUrl)) { - isShare = metadata.permissions.contains(permissions.permissionShared) && !directory.permissions.contains(permissions.permissionShared) isMounted = metadata.permissions.contains(permissions.permissionMounted) && !directory.permissions.contains(permissions.permissionMounted) } @@ -1026,7 +1039,6 @@ extension NCManageDatabase { } func getNumMetadatasInUpload() -> Int { - do { let realm = try Realm() realm.refresh() @@ -1034,7 +1046,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return 0 } @@ -1048,7 +1059,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } @@ -1071,7 +1081,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return metadatas } @@ -1083,7 +1092,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } @@ -1114,7 +1122,6 @@ extension NCManageDatabase { } catch let error { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") } - return (metadatasDifferentCount, metadatasModified) } @@ -1145,7 +1152,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } } diff --git a/iOSClient/Data/NCManageDatabase+PhotoLibrary.swift b/iOSClient/Data/NCManageDatabase+PhotoLibrary.swift index c97d5cc795..11656d3d90 100644 --- a/iOSClient/Data/NCManageDatabase+PhotoLibrary.swift +++ b/iOSClient/Data/NCManageDatabase+PhotoLibrary.swift @@ -28,7 +28,6 @@ import RealmSwift import NextcloudKit class tablePhotoLibrary: Object { - @objc dynamic var account = "" @objc dynamic var assetLocalIdentifier = "" @objc dynamic var creationDate: NSDate? @@ -42,10 +41,8 @@ class tablePhotoLibrary: Object { } extension NCManageDatabase { - @discardableResult func addPhotoLibrary(_ assets: [PHAsset], account: String) -> Bool { - do { let realm = try Realm() try realm.write { @@ -70,12 +67,10 @@ extension NCManageDatabase { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") return false } - return true } func getPhotoLibraryIdAsset(image: Bool, video: Bool, account: String) -> [String]? { - var predicate = NSPredicate() if image && video { @@ -95,8 +90,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access to database: \(error)") } - return nil } - } diff --git a/iOSClient/Data/NCManageDatabase+SecurityGuard.swift b/iOSClient/Data/NCManageDatabase+SecurityGuard.swift index fc4380a6f5..647ef65592 100644 --- a/iOSClient/Data/NCManageDatabase+SecurityGuard.swift +++ b/iOSClient/Data/NCManageDatabase+SecurityGuard.swift @@ -26,7 +26,6 @@ import RealmSwift import NextcloudKit class TableSecurityGuardDiagnostics: Object { - @Persisted var account = "" @Persisted(primaryKey: true) var primaryKey = "" @Persisted var issue: String = "" @@ -48,9 +47,7 @@ class TableSecurityGuardDiagnostics: Object { } extension NCManageDatabase { - func addDiagnostic(account: String, issue: String, error: String? = nil) { - do { let realm = try Realm() try realm.write { @@ -69,7 +66,6 @@ extension NCManageDatabase { } func existsDiagnostics(account: String) -> Bool { - do { let realm = try Realm() let results = realm.objects(TableSecurityGuardDiagnostics.self).where({ @@ -79,12 +75,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] 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({ @@ -94,12 +88,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } func deleteDiagnostics(account: String, ids: [ObjectId]) { - do { let realm = try Realm() try realm.write { diff --git a/iOSClient/Data/NCManageDatabase+Share.swift b/iOSClient/Data/NCManageDatabase+Share.swift index 14ebc82f5d..9618a80ad6 100644 --- a/iOSClient/Data/NCManageDatabase+Share.swift +++ b/iOSClient/Data/NCManageDatabase+Share.swift @@ -27,7 +27,6 @@ import NextcloudKit typealias tableShare = tableShareV2 class tableShareV2: Object { - @objc dynamic var account = "" @objc dynamic var canEdit: Bool = false @objc dynamic var canDelete: Bool = false @@ -75,9 +74,7 @@ class tableShareV2: Object { } extension NCManageDatabase { - func addShare(account: String, home: String, shares: [NKShare]) { - do { let realm = try Realm() try realm.write { @@ -92,7 +89,7 @@ extension NCManageDatabase { object.serverUrl = serverUrl object.canEdit = share.canEdit object.canDelete = share.canDelete - object.date = share.date + object.date = share.date as? NSDate object.displaynameFileOwner = share.displaynameFileOwner object.displaynameOwner = share.displaynameOwner object.expirationDate = share.expirationDate @@ -122,7 +119,7 @@ extension NCManageDatabase { object.uidOwner = share.uidOwner object.uidFileOwner = share.uidFileOwner object.url = share.url - object.userClearAt = share.userClearAt + object.userClearAt = share.userClearAt as? NSDate object.userIcon = share.userIcon object.userMessage = share.userMessage object.userStatus = share.userStatus @@ -136,7 +133,6 @@ extension NCManageDatabase { } func getTableShares(account: String) -> [tableShare] { - do { let realm = try Realm() realm.refresh() @@ -146,12 +142,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return [] } func getTableShares(metadata: tableMetadata) -> (firstShareLink: tableShare?, share: [tableShare]?) { - do { let realm = try Realm() realm.refresh() @@ -167,12 +161,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return (nil, nil) } func getTableShare(account: String, idShare: Int) -> tableShare? { - do { let realm = try Realm() realm.refresh() @@ -181,12 +173,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } func getTableShares(account: String, serverUrl: String) -> [tableShare] { - do { let realm = try Realm() realm.refresh() @@ -196,12 +186,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return [] } func getTableShares(account: String, serverUrl: String, fileName: String) -> [tableShare] { - do { let realm = try Realm() realm.refresh() @@ -216,7 +204,6 @@ extension NCManageDatabase { } func deleteTableShare(account: String, idShare: Int) { - do { let realm = try Realm() try realm.write { @@ -229,7 +216,6 @@ extension NCManageDatabase { } func deleteTableShare(account: String, path: String) { - do { let realm = try Realm() try realm.write { @@ -242,7 +228,6 @@ extension NCManageDatabase { } func deleteTableShare(account: String) { - do { let realm = try Realm() try realm.write { @@ -280,5 +265,4 @@ extension NCManageDatabase { } return true } - } diff --git a/iOSClient/Data/NCManageDatabase+Tag.swift b/iOSClient/Data/NCManageDatabase+Tag.swift index 51f05476c5..b92db45f0d 100644 --- a/iOSClient/Data/NCManageDatabase+Tag.swift +++ b/iOSClient/Data/NCManageDatabase+Tag.swift @@ -26,7 +26,6 @@ import RealmSwift import NextcloudKit class tableTag: Object { - @objc dynamic var account = "" @objc dynamic var ocId = "" @objc dynamic var tagIOS: Data? @@ -37,9 +36,7 @@ class tableTag: Object { } extension NCManageDatabase { - func addTag(_ ocId: String, tagIOS: Data?, account: String) { - do { let realm = try Realm() try realm.write { @@ -55,7 +52,6 @@ extension NCManageDatabase { } func deleteTag(_ ocId: String) { - do { let realm = try Realm() try realm.write { @@ -68,7 +64,6 @@ extension NCManageDatabase { } func getTags(predicate: NSPredicate) -> [tableTag] { - do { let realm = try Realm() realm.refresh() @@ -77,12 +72,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access to database: \(error)") } - return [] } func getTag(predicate: NSPredicate) -> tableTag? { - do { let realm = try Realm() realm.refresh() @@ -91,7 +84,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not acess to database: \(error)") } - return nil } } diff --git a/iOSClient/Data/NCManageDatabase+Tip.swift b/iOSClient/Data/NCManageDatabase+Tip.swift index c6160b8c56..163a8d2a36 100644 --- a/iOSClient/Data/NCManageDatabase+Tip.swift +++ b/iOSClient/Data/NCManageDatabase+Tip.swift @@ -41,7 +41,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access to database: \(error)") } - return false } diff --git a/iOSClient/Data/NCManageDatabase+Trash.swift b/iOSClient/Data/NCManageDatabase+Trash.swift index 39bbcf396d..186f031bae 100644 --- a/iOSClient/Data/NCManageDatabase+Trash.swift +++ b/iOSClient/Data/NCManageDatabase+Trash.swift @@ -26,7 +26,6 @@ import RealmSwift import NextcloudKit class tableTrash: Object { - @objc dynamic var account = "" @objc dynamic var classFile = "" @objc dynamic var contentType = "" @@ -48,9 +47,7 @@ class tableTrash: Object { } extension NCManageDatabase { - func addTrash(account: String, items: [NKTrash]) { - do { let realm = try Realm() try realm.write { @@ -58,7 +55,7 @@ extension NCManageDatabase { let object = tableTrash() object.account = account object.contentType = trash.contentType - object.date = trash.date + object.date = trash.date as NSDate object.directory = trash.directory object.fileId = trash.fileId object.fileName = trash.fileName @@ -66,7 +63,7 @@ extension NCManageDatabase { object.hasPreview = trash.hasPreview object.iconName = trash.iconName object.size = trash.size - object.trashbinDeletionTime = trash.trashbinDeletionTime + object.trashbinDeletionTime = trash.trashbinDeletionTime as NSDate object.trashbinFileName = trash.trashbinFileName object.trashbinOriginalLocation = trash.trashbinOriginalLocation object.classFile = trash.classFile @@ -79,7 +76,6 @@ extension NCManageDatabase { } func deleteTrash(filePath: String?, account: String) { - var predicate = NSPredicate() do { @@ -99,7 +95,6 @@ extension NCManageDatabase { } func deleteTrash(fileId: String?, account: String) { - var predicate = NSPredicate() do { @@ -127,12 +122,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access to database: \(error)") } - return [] } func getTrashItem(fileId: String, account: String) -> tableTrash? { - do { let realm = try Realm() realm.refresh() @@ -141,7 +134,6 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access to database: \(error)") } - return nil } } diff --git a/iOSClient/Data/NCManageDatabase+UserStatus.swift b/iOSClient/Data/NCManageDatabase+UserStatus.swift index 0aeceb9c47..67babd1c31 100644 --- a/iOSClient/Data/NCManageDatabase+UserStatus.swift +++ b/iOSClient/Data/NCManageDatabase+UserStatus.swift @@ -26,7 +26,6 @@ import RealmSwift import NextcloudKit class tableUserStatus: Object { - @objc dynamic var account = "" @objc dynamic var clearAt: NSDate? @objc dynamic var clearAtTime: String? @@ -40,9 +39,7 @@ class tableUserStatus: Object { } extension NCManageDatabase { - func addUserStatus(_ userStatuses: [NKUserStatus], account: String, predefined: Bool) { - do { let realm = try Realm() try realm.write { @@ -51,7 +48,7 @@ extension NCManageDatabase { for userStatus in userStatuses { let object = tableUserStatus() object.account = account - object.clearAt = userStatus.clearAt + object.clearAt = userStatus.clearAt as? NSDate object.clearAtTime = userStatus.clearAtTime object.clearAtType = userStatus.clearAtType object.icon = userStatus.icon diff --git a/iOSClient/Data/NCManageDatabase+Video.swift b/iOSClient/Data/NCManageDatabase+Video.swift index 65f15dac29..9034b2cddb 100644 --- a/iOSClient/Data/NCManageDatabase+Video.swift +++ b/iOSClient/Data/NCManageDatabase+Video.swift @@ -27,7 +27,6 @@ import NextcloudKit typealias tableVideo = tableVideoV4 class tableVideoV4: Object { - @Persisted var account = "" @Persisted(primaryKey: true) var ocId = "" @Persisted var position: Float? @@ -45,9 +44,7 @@ class tableVideoV4: Object { } extension NCManageDatabase { - func addVideo(metadata: tableMetadata, position: Float? = nil, width: Int? = nil, height: Int? = nil, length: Int? = nil, currentAudioTrackIndex: Int? = nil, currentVideoSubTitleIndex: Int? = nil) { - if metadata.isLivePhoto { return } do { @@ -104,7 +101,6 @@ extension NCManageDatabase { } func addVideoCodec(metadata: tableMetadata, codecNameVideo: String?, codecNameAudio: String?, codecAudioChannelLayout: String?, codecAudioLanguage: String?, codecMaxCompatibility: Bool, codecQuality: String?) { - do { let realm = try Realm() try realm.write { @@ -135,7 +131,6 @@ extension NCManageDatabase { } func getVideo(metadata: tableMetadata?) -> tableVideo? { - guard let metadata = metadata else { return nil } do { @@ -146,12 +141,10 @@ extension NCManageDatabase { } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return nil } func deleteVideo(metadata: tableMetadata) { - do { let realm = try Realm() try realm.write { diff --git a/iOSClient/Data/NCManageDatabase.swift b/iOSClient/Data/NCManageDatabase.swift index cdac63760b..44ce135ab7 100644 --- a/iOSClient/Data/NCManageDatabase.swift +++ b/iOSClient/Data/NCManageDatabase.swift @@ -37,18 +37,12 @@ class NCManageDatabase: NSObject { let instance = NCManageDatabase() return instance }() - let utilityFileSystem = NCUtilityFileSystem() override init() { - - let dirGroup = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: NCBrandOptions.shared.capabilitiesGroups) + let dirGroup = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: NCBrandOptions.shared.capabilitiesGroup) let databaseFileUrlPath = dirGroup?.appendingPathComponent(NCGlobal.shared.appDatabaseNextcloud + "/" + databaseName) - let bundleUrl: URL = Bundle.main.bundleURL - let bundlePathExtension: String = bundleUrl.pathExtension - let isAppex: Bool = bundlePathExtension == "appex" - if let databaseFilePath = databaseFileUrlPath?.path { if FileManager.default.fileExists(atPath: databaseFilePath) { NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] DATABASE FOUND in " + databaseFilePath) @@ -68,98 +62,40 @@ class NCManageDatabase: NSObject { } } - if isAppex { - - Realm.Configuration.defaultConfiguration = Realm.Configuration( - fileURL: dirGroup?.appendingPathComponent(NCGlobal.shared.appDatabaseNextcloud + "/" + databaseName), + do { + _ = try Realm(configuration: Realm.Configuration( + fileURL: databaseFileUrlPath, schemaVersion: databaseSchemaVersion, - objectTypes: [tableMetadata.self, - tableLocalFile.self, - tableDirectory.self, - tableTag.self, - tableAccount.self, - tableCapabilities.self, - tablePhotoLibrary.self, - tableE2eEncryption.self, - tableE2eEncryptionLock.self, - tableE2eMetadata12.self, - tableE2eMetadata.self, - tableE2eUsers.self, - tableE2eCounter.self, - tableShare.self, - tableChunk.self, - tableAvatar.self, - tableDashboardWidget.self, - tableDashboardWidgetButton.self, - NCDBLayoutForView.self, - TableSecurityGuardDiagnostics.self] - ) - - } else { - - do { - _ = try Realm(configuration: Realm.Configuration( - - fileURL: databaseFileUrlPath, - schemaVersion: databaseSchemaVersion, - - migrationBlock: { migration, oldSchemaVersion in - - if oldSchemaVersion < 255 { - migration.deleteData(forType: tableActivity.className()) - migration.deleteData(forType: tableActivityLatestId.className()) - migration.deleteData(forType: tableActivityPreview.className()) - migration.deleteData(forType: tableActivitySubjectRich.className()) - } - - if oldSchemaVersion < 292 { - migration.deleteData(forType: tableVideo.className()) - } - - if oldSchemaVersion < 319 { - migration.deleteData(forType: tableChunk.className()) - migration.deleteData(forType: tableDirectory.className()) - migration.deleteData(forType: tableE2eEncryptionLock.className()) - migration.deleteData(forType: tableGPS.className()) - } - - if oldSchemaVersion < 333 { - migration.deleteData(forType: tableMetadata.className()) - migration.enumerateObjects(ofType: tableDirectory.className()) { _, newObject in - newObject?["etag"] = "" - } - } - - }, shouldCompactOnLaunch: { totalBytes, usedBytes in - - // totalBytes refers to the size of the file on disk in bytes (data + free space) - // usedBytes refers to the number of bytes used by data in the file - - // Compact if the file is over 100MB in size and less than 50% 'used' - let oneHundredMB = 100 * 1024 * 1024 - return (totalBytes > oneHundredMB) && (Double(usedBytes) / Double(totalBytes)) < 0.5 + migrationBlock: { migration, oldSchemaVersion in + if oldSchemaVersion < 354 { + migration.deleteData(forType: NCDBLayoutForView.className()) } - )) - - } catch let error { - if let databaseFileUrlPath = databaseFileUrlPath { - do { + }, shouldCompactOnLaunch: { totalBytes, usedBytes in + // totalBytes refers to the size of the file on disk in bytes (data + free space) + // usedBytes refers to the number of bytes used by data in the file + // Compact if the file is over 100MB in size and less than 50% 'used' + let oneHundredMB = 100 * 1024 * 1024 + return (totalBytes > oneHundredMB) && (Double(usedBytes) / Double(totalBytes)) < 0.5 + } + )) + } catch let error { + if let databaseFileUrlPath = databaseFileUrlPath { + do { #if !EXTENSION - let nkError = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: error.localizedDescription) - NCContentPresenter().showError(error: nkError, priority: .max) + let nkError = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: error.localizedDescription) + NCContentPresenter().showError(error: nkError, priority: .max) #endif - NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] DATABASE ERROR: \(error.localizedDescription)") - try FileManager.default.removeItem(at: databaseFileUrlPath) - } catch {} - } + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] DATABASE ERROR: \(error.localizedDescription)") + try FileManager.default.removeItem(at: databaseFileUrlPath) + } catch {} } - - Realm.Configuration.defaultConfiguration = Realm.Configuration( - fileURL: dirGroup?.appendingPathComponent(NCGlobal.shared.appDatabaseNextcloud + "/" + databaseName), - schemaVersion: databaseSchemaVersion - ) } + Realm.Configuration.defaultConfiguration = Realm.Configuration( + fileURL: dirGroup?.appendingPathComponent(NCGlobal.shared.appDatabaseNextcloud + "/" + databaseName), + schemaVersion: databaseSchemaVersion + ) + // Verify Database, if corrupt remove it do { _ = try Realm() @@ -228,7 +164,6 @@ class NCManageDatabase: NSObject { self.clearTable(tableGPS.self, account: nil) self.clearTable(TableGroupfolders.self, account: account) self.clearTable(TableGroupfoldersGroups.self, account: account) - self.clearTable(NCDBLayoutForView.self, account: account) self.clearTable(tableLocalFile.self, account: account) self.clearTable(tableMetadata.self, account: account) self.clearTable(tablePhotoLibrary.self, account: account) @@ -241,7 +176,6 @@ class NCManageDatabase: NSObject { } func clearTablesE2EE(account: String?) { - self.clearTable(tableE2eEncryption.self, account: account) self.clearTable(tableE2eEncryptionLock.self, account: account) self.clearTable(tableE2eMetadata12.self, account: account) @@ -251,7 +185,6 @@ class NCManageDatabase: NSObject { } @objc func removeDB() { - let realmURL = Realm.Configuration.defaultConfiguration.fileURL! let realmURLs = [ realmURL, @@ -259,6 +192,7 @@ class NCManageDatabase: NSObject { realmURL.appendingPathExtension("note"), realmURL.appendingPathExtension("management") ] + for URL in realmURLs { do { try FileManager.default.removeItem(at: URL) @@ -269,22 +203,46 @@ class NCManageDatabase: NSObject { } func getThreadConfined(_ object: Object) -> Any { - return ThreadSafeReference(to: object) } func putThreadConfined(_ tableRef: ThreadSafeReference) -> Object? { - do { let realm = try Realm() return realm.resolve(tableRef) } catch let error as NSError { NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") } - return nil } + // MARK: - + // MARK: Func T + + func fetchPagedResults(ofType type: T.Type, primaryKey: String, recordsPerPage: Int, pageNumber: Int, filter: NSPredicate? = nil, sortedByKeyPath: String? = nil, sortedAscending: Bool = true) -> Results? { + let startIndex = recordsPerPage * (pageNumber - 1) + + do { + let realm = try Realm() + var results = realm.objects(type) + + if let filter, let sortedByKeyPath { + results = results.filter(filter).sorted(byKeyPath: sortedByKeyPath, ascending: sortedAscending) + } + + guard startIndex < results.count else { + return nil + } + let pagedResults = results.dropFirst(startIndex).prefix(recordsPerPage) + let pagedResultsKeys = pagedResults.compactMap { $0.value(forKey: primaryKey) as? String } + + return realm.objects(type).filter("\(primaryKey) IN %@", Array(pagedResultsKeys)) + } catch { + print("Error opening Realm: \(error)") + return nil + } + } + // MARK: - // MARK: SWIFTUI PREVIEW diff --git a/iOSClient/Extensions/UIAlertController+Extension.swift b/iOSClient/Extensions/UIAlertController+Extension.swift index f75fac1cce..755c8f7ee9 100644 --- a/iOSClient/Extensions/UIAlertController+Extension.swift +++ b/iOSClient/Extensions/UIAlertController+Extension.swift @@ -39,7 +39,7 @@ extension UIAlertController { guard let fileNameFolder = alertController.textFields?.first?.text else { return } if markE2ee { Task { - let createFolderResults = await NextcloudKit.shared.createFolder(serverUrlFileName: serverUrl + "/" + fileNameFolder) + let createFolderResults = await NCNetworking.shared.createFolder(serverUrlFileName: serverUrl + "/" + fileNameFolder) if createFolderResults.error == .success { let error = await NCNetworkingE2EEMarkFolder().markFolderE2ee(account: urlBase.account, fileName: fileNameFolder, serverUrl: serverUrl, userId: urlBase.userId) if error != .success { diff --git a/iOSClient/Extensions/UIView+Extension.swift b/iOSClient/Extensions/UIView+Extension.swift index a57cde15fc..a49d1300f0 100644 --- a/iOSClient/Extensions/UIView+Extension.swift +++ b/iOSClient/Extensions/UIView+Extension.swift @@ -55,6 +55,15 @@ extension UIView { self.addSubview(blurredEffectView) } + func insertBlur(style: UIBlurEffect.Style) { + let blur = UIBlurEffect(style: style) + let blurredEffectView = UIVisualEffectView(effect: blur) + blurredEffectView.frame = self.bounds + blurredEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + blurredEffectView.isUserInteractionEnabled = false + self.insertSubview(blurredEffectView, at: 0) + } + func makeCircularBackground(withColor backgroundColor: UIColor) { self.backgroundColor = backgroundColor self.layer.cornerRadius = self.frame.size.width / 2 diff --git a/iOSClient/Favorites/NCFavorite.swift b/iOSClient/Favorites/NCFavorite.swift index ff2b5f39ea..f7b79bc8cd 100644 --- a/iOSClient/Favorites/NCFavorite.swift +++ b/iOSClient/Favorites/NCFavorite.swift @@ -62,15 +62,7 @@ class NCFavorite: NCCollectionViewCommon { metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl)) } - self.dataSource = NCDataSource(metadatas: metadatas, - account: self.appDelegate.account, - sort: self.layoutForView?.sort, - ascending: self.layoutForView?.ascending, - directoryOnTop: self.layoutForView?.directoryOnTop, - favoriteOnTop: true, - groupByField: self.groupByField, - providers: self.providers, - searchResults: self.searchResults) + self.dataSource = NCDataSource(metadatas: metadatas, account: self.appDelegate.account, layoutForView: layoutForView, providers: self.providers, searchResults: self.searchResults) } override func reloadDataSourceNetwork(withQueryDB: Bool = false) { diff --git a/iOSClient/Files/NCFiles.swift b/iOSClient/Files/NCFiles.swift index d5084f6a1c..b6c6a181bf 100644 --- a/iOSClient/Files/NCFiles.swift +++ b/iOSClient/Files/NCFiles.swift @@ -58,11 +58,12 @@ class NCFiles: NCCollectionViewCommon { self.selectOcId.removeAll() self.layoutForView = NCManageDatabase.shared.getLayoutForView(account: self.appDelegate.account, key: self.layoutKey, serverUrl: self.serverUrl) - self.gridLayout.itemForLine = CGFloat(self.layoutForView?.itemForLine ?? 3) if self.layoutForView?.layout == NCGlobal.shared.layoutList { self.collectionView?.collectionViewLayout = self.listLayout - } else { + } else if self.layoutForView?.layout == NCGlobal.shared.layoutGrid { self.collectionView?.collectionViewLayout = self.gridLayout + } else if self.layoutForView?.layout == NCGlobal.shared.layoutPhotoSquare || self.layoutForView?.layout == NCGlobal.shared.layoutPhotoRatio { + self.collectionView?.collectionViewLayout = self.mediaLayout } self.titleCurrentFolder = self.getNavigationTitle() @@ -111,17 +112,7 @@ class NCFiles: NCCollectionViewCommon { } self.richWorkspaceText = directory?.richWorkspace - self.dataSource = NCDataSource( - metadatas: metadatas, - account: self.appDelegate.account, - directory: directory, - sort: self.layoutForView?.sort, - ascending: self.layoutForView?.ascending, - directoryOnTop: self.layoutForView?.directoryOnTop, - favoriteOnTop: true, - groupByField: self.groupByField, - providers: self.providers, - searchResults: self.searchResults) + self.dataSource = NCDataSource(metadatas: metadatas, account: self.appDelegate.account, layoutForView: layoutForView, providers: self.providers, searchResults: self.searchResults) } override func reloadDataSource(withQueryDB: Bool = true) { @@ -298,7 +289,7 @@ class NCFiles: NCCollectionViewCommon { if NCManageDatabase.shared.getAllAccount().isEmpty { appDelegate.openLogin(selector: NCGlobal.shared.introLogin, openLoginWeb: false) } else if let account = tableAccount?.account, account != appDelegate.account { - appDelegate.changeAccount(account, userProfile: nil) + appDelegate.changeAccount(account, userProfile: nil) { } } else if isRoot { titleCurrentFolder = getNavigationTitle() navigationItem.title = titleCurrentFolder diff --git a/iOSClient/Groupfolders/NCGroupfolders.swift b/iOSClient/Groupfolders/NCGroupfolders.swift index 8263ac7415..b067e4aac4 100644 --- a/iOSClient/Groupfolders/NCGroupfolders.swift +++ b/iOSClient/Groupfolders/NCGroupfolders.swift @@ -62,16 +62,7 @@ class NCGroupfolders: NCCollectionViewCommon { metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl)) } - self.dataSource = NCDataSource( - metadatas: metadatas, - account: self.appDelegate.account, - sort: self.layoutForView?.sort, - ascending: self.layoutForView?.ascending, - directoryOnTop: self.layoutForView?.directoryOnTop, - favoriteOnTop: true, - groupByField: self.groupByField, - providers: self.providers, - searchResults: self.searchResults) + self.dataSource = NCDataSource(metadatas: metadatas, account: self.appDelegate.account, layoutForView: layoutForView, providers: self.providers, searchResults: self.searchResults) } override func reloadDataSourceNetwork(withQueryDB: Bool = false) { @@ -90,7 +81,7 @@ class NCGroupfolders: NCCollectionViewCommon { let mountPoint = groupfolder.mountPoint.hasPrefix("/") ? groupfolder.mountPoint : "/" + groupfolder.mountPoint let serverUrlFileName = homeServerUrl + mountPoint if NCManageDatabase.shared.getMetadataFromDirectory(account: self.appDelegate.account, serverUrl: serverUrlFileName) == nil { - let results = await NextcloudKit.shared.readFileOrFolder(serverUrlFileName: serverUrlFileName, depth: "0", showHiddenFiles: NCKeychain().showHiddenFiles) + let results = await NCNetworking.shared.readFileOrFolder(serverUrlFileName: serverUrlFileName, depth: "0", showHiddenFiles: NCKeychain().showHiddenFiles) if results.error == .success, let file = results.files.first { let isDirectoryE2EE = self.utilityFileSystem.isDirectoryE2EE(file: file) let metadata = NCManageDatabase.shared.convertFileToMetadata(file, isDirectoryE2EE: isDirectoryE2EE) diff --git a/iOSClient/Images.xcassets/qrcode.imageset/Contents.json b/iOSClient/Images.xcassets/qrcode.imageset/Contents.json deleted file mode 100644 index 3d370c566d..0000000000 --- a/iOSClient/Images.xcassets/qrcode.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "filename" : "qrcode.pdf", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "preserves-vector-representation" : true - } -} diff --git a/iOSClient/Images.xcassets/qrcode.imageset/qrcode.pdf b/iOSClient/Images.xcassets/qrcode.imageset/qrcode.pdf deleted file mode 100644 index d2c7194a64..0000000000 Binary files a/iOSClient/Images.xcassets/qrcode.imageset/qrcode.pdf and /dev/null differ diff --git a/iOSClient/Login/NCLogin.swift b/iOSClient/Login/NCLogin.swift index 8a510faea1..5f7b45f28e 100644 --- a/iOSClient/Login/NCLogin.swift +++ b/iOSClient/Login/NCLogin.swift @@ -28,7 +28,6 @@ import SwiftEntryKit import SwiftUI class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate { - @IBOutlet weak var imageBrand: UIImageView! @IBOutlet weak var imageBrandConstraintY: NSLayoutConstraint! @IBOutlet weak var baseUrl: UITextField! @@ -108,11 +107,13 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate { // brand if NCBrandOptions.shared.disable_request_login_url { baseUrl.text = NCBrandOptions.shared.loginBaseUrl - baseUrl.isHidden = true + baseUrl.isEnabled = false + baseUrl.isUserInteractionEnabled = false + baseUrl.alpha = 0.5 } // qrcode - qrCode.setImage(UIImage(named: "qrcode")?.image(color: textColor, size: 100), for: .normal) + qrCode.setImage(UIImage(systemName: "qrcode.viewfinder")?.image(color: textColor, size: 100), for: .normal) // certificate certificate.setImage(UIImage(named: "certificate")?.image(color: textColor, size: 100), for: .normal) @@ -165,10 +166,7 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate { NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil) - NCNetworking.shared.delegate = self - handleLoginWithAppConfig() - baseUrl.text = urlBase } @@ -201,15 +199,12 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate { if let serverUrl = configurationManaged[NCGlobal.shared.configuration_serverUrl] as? String { self.configServerUrl = serverUrl } - if let username = configurationManaged[NCGlobal.shared.configuration_username] as? String, !username.isEmpty, username.lowercased() != "username" { self.configUsername = username } - if let password = configurationManaged[NCGlobal.shared.configuration_password] as? String, !password.isEmpty, password.lowercased() != "password" { self.configPassword = password } - if let apppassword = configurationManaged[NCGlobal.shared.configuration_apppassword] as? String, !apppassword.isEmpty, apppassword.lowercased() != "apppassword" { self.configAppPassword = apppassword } @@ -217,15 +212,13 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate { } // AppConfig - if let serverUrl = configServerUrl { - if let username = self.configUsername, let password = configAppPassword { - createAccount(server: serverUrl, username: username, password: password) - return - } else if let username = self.configUsername, let password = configPassword { - getAppPassword(serverUrl: serverUrl, username: username, password: password) - return + if let url = configServerUrl { + if let user = self.configUsername, let password = configAppPassword { + return createAccount(urlBase: url, user: user, password: password) + } else if let user = self.configUsername, let password = configPassword { + return getAppPassword(urlBase: url, user: user, password: password) } else { - urlBase = serverUrl + urlBase = url } } } @@ -239,16 +232,13 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate { } func textFieldDidBeginEditing(_ textField: UITextField) { - self.activeTextField = textField } // MARK: - Keyboard notification @objc internal func keyboardWillShow(_ notification: Notification?) { - activeTextfieldDiff = 0 - if let info = notification?.userInfo, let centerObject = self.activeTextField.superview?.convert(self.activeTextField.center, to: nil) { let frameEndUserInfoKey = UIResponder.keyboardFrameEndUserInfoKey @@ -291,9 +281,7 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate { // MARK: - Share accounts View Controller @objc func openShareAccountsViewController() { - if let shareAccounts = self.shareAccounts, let vc = UIStoryboard(name: "NCShareAccounts", bundle: nil).instantiateInitialViewController() as? NCShareAccounts { - vc.accounts = shareAccounts vc.enableTimerProgress = false vc.dismissDidEnterBackground = false @@ -302,7 +290,6 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate { let screenHeighMax = UIScreen.main.bounds.height - (UIScreen.main.bounds.height / 5) let numberCell = shareAccounts.count let height = min(CGFloat(numberCell * Int(vc.heightCell) + 45), screenHeighMax) - let popup = NCPopupViewController(contentController: vc, popupWidth: 300, popupHeight: height + 20) self.present(popup, animated: true) @@ -315,7 +302,6 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate { guard var url = baseUrl.text?.trimmingCharacters(in: .whitespacesAndNewlines) else { return } if url.hasSuffix("/") { url = String(url.dropLast()) } if url.isEmpty { return } - // Check whether baseUrl contain protocol. If not add https:// by default. if url.hasPrefix("https") == false && url.hasPrefix("http") == false { url = "https://" + url @@ -325,53 +311,35 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate { } func isUrlValid(url: String, user: String? = nil) { - loginButton.isEnabled = false - NextcloudKit.shared.getServerStatus(serverUrl: url) { serverInfoResult in - switch serverInfoResult { case .success(let serverInfo): - if let host = URL(string: url)?.host { NCNetworking.shared.writeCertificate(host: host) } - NextcloudKit.shared.getLoginFlowV2(serverUrl: url) { token, endpoint, login, _, error in - self.loginButton.isEnabled = true - // Login Flow V2 if error == .success, let token, let endpoint, let login { let vc = UIHostingController(rootView: NCLoginPoll(loginFlowV2Token: token, loginFlowV2Endpoint: endpoint, loginFlowV2Login: login)) - self.present(vc, animated: true) } else if serverInfo.versionMajor < NCGlobal.shared.nextcloudVersion12 { // No login flow available - let alertController = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: NSLocalizedString("_webflow_not_available_", comment: ""), preferredStyle: .alert) - alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in })) - self.present(alertController, animated: true, completion: { }) } } - case .failure(let error): - self.loginButton.isEnabled = true - if error.errorCode == NSURLErrorServerCertificateUntrusted { - let alertController = UIAlertController(title: NSLocalizedString("_ssl_certificate_untrusted_", comment: ""), message: NSLocalizedString("_connect_server_anyway_", comment: ""), preferredStyle: .alert) - alertController.addAction(UIAlertAction(title: NSLocalizedString("_yes_", comment: ""), style: .default, handler: { _ in if let host = URL(string: url)?.host { NCNetworking.shared.writeCertificate(host: host) } })) - alertController.addAction(UIAlertAction(title: NSLocalizedString("_no_", comment: ""), style: .default, handler: { _ in })) - alertController.addAction(UIAlertAction(title: NSLocalizedString("_certificate_details_", comment: ""), style: .default, handler: { _ in if let navigationController = UIStoryboard(name: "NCViewCertificateDetails", bundle: nil).instantiateInitialViewController() as? UINavigationController, let viewController = navigationController.topViewController as? NCViewCertificateDetails { @@ -381,15 +349,10 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate { self.present(navigationController, animated: true) } })) - self.present(alertController, animated: true) - } else { - let alertController = UIAlertController(title: NSLocalizedString("_connection_error_", comment: ""), message: error.errorDescription, preferredStyle: .alert) - alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in })) - self.present(alertController, animated: true, completion: { }) } } @@ -399,135 +362,70 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate { // MARK: - QRCode func dismissQRCode(_ value: String?, metadataType: String?) { - guard var value = value else { return } - let protocolLogin = NCBrandOptions.shared.webLoginAutenticationProtocol + "login/" - if value.hasPrefix(protocolLogin) && value.contains("user:") && value.contains("password:") && value.contains("server:") { - value = value.replacingOccurrences(of: protocolLogin, with: "") let valueArray = value.components(separatedBy: "&") if valueArray.count == 3 { - let user = valueArray[0].replacingOccurrences(of: "user:", with: "") let password = valueArray[1].replacingOccurrences(of: "password:", with: "") let urlBase = valueArray[2].replacingOccurrences(of: "server:", with: "") let serverUrl = urlBase + "/" + NextcloudKit.shared.nkCommonInstance.dav - loginButton.isEnabled = false - NextcloudKit.shared.checkServer(serverUrl: serverUrl) { error in - self.loginButton.isEnabled = true - self.standardLogin(url: urlBase, user: user, password: password, error: error) + if error == .success { + self.createAccount(urlBase: urlBase, user: user, password: password) + } else { + let alertController = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: error.errorDescription, preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in })) + self.present(alertController, animated: true) + } } } } } - func standardLogin(url: String, user: String, password: String, error: NKError) { - - if error == .success { - - if let host = URL(string: url)?.host { - NCNetworking.shared.writeCertificate(host: host) - } - let urlBase = url - let account = user + " " + user - - NextcloudKit.shared.setup(account: account, user: user, userId: user, password: password, urlBase: urlBase) - NextcloudKit.shared.getUserProfile { _, userProfile, _, error in - - if error == .success, let userProfile { - - NCManageDatabase.shared.deleteAccount(account) - NCManageDatabase.shared.addAccount(account, urlBase: url, user: user, userId: userProfile.userId, password: password) - - self.appDelegate.changeAccount(account, userProfile: userProfile) - - let window = UIApplication.shared.firstWindow - if window?.rootViewController is NCMainTabBarController { - self.dismiss(animated: true) - } else { - if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() as? NCMainTabBarController { - controller.modalPresentationStyle = .fullScreen - controller.view.alpha = 0 - window?.rootViewController = controller - window?.makeKeyAndVisible() - UIView.animate(withDuration: 0.5) { - controller.view.alpha = 1 - } - } - } - } else { - - let alertController = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: error.errorDescription, preferredStyle: .alert) - alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in })) - self.present(alertController, animated: true) - } + private func getAppPassword(urlBase: String, user: String, password: String) { + NextcloudKit.shared.getAppPassword(url: urlBase, user: user, password: password) { token, _, error in + if error == .success, let password = token { + self.createAccount(urlBase: urlBase, user: user, password: password) + } else { + NCContentPresenter().showError(error: error) + self.dismiss(animated: true, completion: nil) } - - } else if error.errorCode == NSURLErrorServerCertificateUntrusted { - - let alertController = UIAlertController(title: NSLocalizedString("_ssl_certificate_untrusted_", comment: ""), message: NSLocalizedString("_connect_server_anyway_", comment: ""), preferredStyle: .alert) - - alertController.addAction(UIAlertAction(title: NSLocalizedString("_yes_", comment: ""), style: .default, handler: { _ in - if let host = URL(string: url)?.host { - NCNetworking.shared.writeCertificate(host: host) - } - })) - - alertController.addAction(UIAlertAction(title: NSLocalizedString("_no_", comment: ""), style: .default, handler: { _ in })) - - alertController.addAction(UIAlertAction(title: NSLocalizedString("_certificate_details_", comment: ""), style: .default, handler: { _ in - if let navigationController = UIStoryboard(name: "NCViewCertificateDetails", bundle: nil).instantiateInitialViewController() { - self.present(navigationController, animated: true) - } - })) - - self.present(alertController, animated: true) - - } else { - - let message = NSLocalizedString("_not_possible_connect_to_server_", comment: "") + ".\n" + error.errorDescription - let alertController = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: message, preferredStyle: .alert) - alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in })) - self.present(alertController, animated: true, completion: { }) } } - private func createAccount(server: String, username: String, password: String) { - appDelegate.createAccount(server: server, username: username, password: password) { error in + private func createAccount(urlBase: String, user: String, password: String) { + if let host = URL(string: urlBase)?.host { + NCNetworking.shared.writeCertificate(host: host) + } + self.appDelegate.createAccount(urlBase: urlBase, user: user, password: password) { error in if error == .success { let window = UIApplication.shared.firstWindow if window?.rootViewController is NCMainTabBarController { self.dismiss(animated: true) } else { - if let mainTabBarController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() as? NCMainTabBarController { - mainTabBarController.modalPresentationStyle = .fullScreen - mainTabBarController.view.alpha = 0 - window?.rootViewController = mainTabBarController + if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() as? NCMainTabBarController { + controller.modalPresentationStyle = .fullScreen + controller.view.alpha = 0 + window?.rootViewController = controller window?.makeKeyAndVisible() UIView.animate(withDuration: 0.5) { - mainTabBarController.view.alpha = 1 + controller.view.alpha = 1 } } } - } - } - } - - private func getAppPassword(serverUrl: String, username: String, password: String) { - NextcloudKit.shared.getAppPassword(serverUrl: serverUrl, username: username, password: password) { token, _, error in - if error == .success, let password = token { - self.createAccount(server: serverUrl, username: username, password: password) } else { - NCContentPresenter().showError(error: error) - self.dismiss(animated: true, completion: nil) + let alertController = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: error.errorDescription, preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in })) + self.present(alertController, animated: true) } } } + } extension NCLogin: NCShareAccountsDelegate { @@ -539,47 +437,35 @@ extension NCLogin: NCShareAccountsDelegate { extension NCLogin: ClientCertificateDelegate, UIDocumentPickerDelegate { func didAskForClientCertificate() { let alertNoCertFound = UIAlertController(title: NSLocalizedString("_no_client_cert_found_", comment: ""), message: NSLocalizedString("_no_client_cert_found_desc_", comment: ""), preferredStyle: .alert) - alertNoCertFound.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel, handler: nil)) - alertNoCertFound.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in let documentProviderMenu = UIDocumentPickerViewController(forOpeningContentTypes: [UTType.pkcs12]) documentProviderMenu.delegate = self - self.present(documentProviderMenu, animated: true, completion: nil) })) - present(alertNoCertFound, animated: true) } func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { let alertEnterPassword = UIAlertController(title: NSLocalizedString("_client_cert_enter_password_", comment: ""), message: "", preferredStyle: .alert) - alertEnterPassword.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel, handler: nil)) - alertEnterPassword.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in // let documentProviderMenu = UIDocumentPickerViewController(forOpeningContentTypes: [UTType.pkcs12]) NCNetworking.shared.p12Data = try? Data(contentsOf: urls[0]) NCNetworking.shared.p12Password = alertEnterPassword.textFields?[0].text - self.login() })) - alertEnterPassword.addTextField { textField in textField.isSecureTextEntry = true } - present(alertEnterPassword, animated: true) } func onIncorrectPassword() { NCNetworking.shared.p12Data = nil NCNetworking.shared.p12Password = nil - let alertWrongPassword = UIAlertController(title: NSLocalizedString("_client_cert_wrong_password_", comment: ""), message: "", preferredStyle: .alert) - alertWrongPassword.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default)) - present(alertWrongPassword, animated: true) } } diff --git a/iOSClient/Login/NCLoginPoll.swift b/iOSClient/Login/NCLoginPoll.swift index c7a7a4edaa..d1d38d0d79 100644 --- a/iOSClient/Login/NCLoginPoll.swift +++ b/iOSClient/Login/NCLoginPoll.swift @@ -125,9 +125,13 @@ private class LoginManager: ObservableObject { func poll() { NextcloudKit.shared.getLoginFlowV2Poll(token: self.loginFlowV2Token, endpoint: self.loginFlowV2Endpoint) { server, loginName, appPassword, _, error in - if error == .success, let server, let loginName, let appPassword { + if error == .success, let urlBase = server, let user = loginName, let appPassword { self.isLoading = true - self.createAccount(server: server, username: loginName, password: appPassword) + self.appDelegate.createAccount(urlBase: urlBase, user: user, password: appPassword) { error in + if error == .success { + self.pollFinished = true + } + } } } } @@ -135,12 +139,4 @@ private class LoginManager: ObservableObject { func openLoginInBrowser() { UIApplication.shared.open(URL(string: loginFlowV2Login)!) } - - private func createAccount(server: String, username: String, password: String) { - appDelegate.createAccount(server: server, username: username, password: password) { error in - if error == .success { - self.pollFinished = true - } - } - } } diff --git a/iOSClient/Login/NCLoginProvider.swift b/iOSClient/Login/NCLoginProvider.swift index ed231ffec3..a7deec3ce2 100644 --- a/iOSClient/Login/NCLoginProvider.swift +++ b/iOSClient/Login/NCLoginProvider.swift @@ -128,11 +128,9 @@ extension NCLoginProvider: WKNavigationDelegate { } if !server.isEmpty, !user.isEmpty, !password.isEmpty { - let server: String = server.replacingOccurrences(of: "/server:", with: "") let username: String = user.replacingOccurrences(of: "user:", with: "").replacingOccurrences(of: "+", with: " ") let password: String = password.replacingOccurrences(of: "password:", with: "") - createAccount(server: server, username: username, password: password) } } @@ -170,14 +168,10 @@ extension NCLoginProvider: WKNavigationDelegate { NextcloudKit.shared.setup(account: account, user: user, userId: user, password: password, urlBase: urlBase) NextcloudKit.shared.getUserProfile { _, userProfile, _, error in - if error == .success, let userProfile { - NCManageDatabase.shared.deleteAccount(account) NCManageDatabase.shared.addAccount(account, urlBase: urlBase, user: user, userId: userProfile.userId, password: password) - - self.appDelegate.changeAccount(account, userProfile: userProfile) - + self.appDelegate.changeAccount(account, userProfile: userProfile) { } let window = UIApplication.shared.firstWindow if window?.rootViewController is NCMainTabBarController { self.dismiss(animated: true) @@ -192,7 +186,6 @@ extension NCLoginProvider: WKNavigationDelegate { } } } - } else { let alertController = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: error.errorDescription, preferredStyle: .alert) alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in })) diff --git a/iOSClient/Login/NCLoginQRCode.swift b/iOSClient/Login/NCLoginQRCode.swift index 1c80918c7f..9712befe4d 100644 --- a/iOSClient/Login/NCLoginQRCode.swift +++ b/iOSClient/Login/NCLoginQRCode.swift @@ -59,7 +59,6 @@ class NCLoginQRCode: NSObject, QRCodeReaderViewControllerDelegate { readerVC.completionBlock = { (_: QRCodeReaderResult?) in self.readerVC.dismiss(animated: true, completion: nil) } - delegate?.present(readerVC, animated: true, completion: nil) } @@ -68,11 +67,9 @@ class NCLoginQRCode: NSObject, QRCodeReaderViewControllerDelegate { return try QRCodeReader.supportsMetadataObjectTypes() } catch let error as NSError { let alert: UIAlertController - switch error.code { case -11852: alert = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: NSLocalizedString("_qrcode_not_authorized_", comment: ""), preferredStyle: .alert) - alert.addAction(UIAlertAction(title: NSLocalizedString("_settings_", comment: ""), style: .default, handler: { _ in DispatchQueue.main.async { if let settingsURL = URL(string: UIApplication.openSettingsURLString) { @@ -86,9 +83,7 @@ class NCLoginQRCode: NSObject, QRCodeReaderViewControllerDelegate { alert = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: NSLocalizedString("_qrcode_not_supported_", comment: ""), preferredStyle: .alert) alert.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .cancel, handler: nil)) } - delegate?.present(alert, animated: true, completion: nil) - return false } } diff --git a/iOSClient/Main/Collection Common/Cell/NCCellProtocol.swift b/iOSClient/Main/Collection Common/Cell/NCCellProtocol.swift index 9dd1c4ac4e..8a315baa1d 100644 --- a/iOSClient/Main/Collection Common/Cell/NCCellProtocol.swift +++ b/iOSClient/Main/Collection Common/Cell/NCCellProtocol.swift @@ -24,16 +24,15 @@ import UIKit protocol NCCellProtocol { - var fileAvatarImageView: UIImageView? { get } var fileObjectId: String? { get set } var filePreviewImageView: UIImageView? { get set } + var filePreviewImageBottom: NSLayoutConstraint? { get set } var fileUser: String? { get set } var fileTitleLabel: UILabel? { get set } var fileInfoLabel: UILabel? { get set } var fileSubinfoLabel: UILabel? { get set } var fileProgressView: UIProgressView? { get set } - var fileSelectImage: UIImageView? { get set } var fileStatusImage: UIImageView? { get set } var fileLocalImage: UIImageView? { get set } var fileFavoriteImage: UIImageView? { get set } @@ -48,8 +47,7 @@ protocol NCCellProtocol { func setButtonMore(named: String, image: UIImage) func hideButtonShare(_ status: Bool) func hideButtonMore(_ status: Bool) - func selectMode(_ status: Bool) - func selected(_ status: Bool) + func selected(_ status: Bool, isEditMode: Bool) func setAccessibility(label: String, value: String) func setTags(tags: [String]) func setIconOutlines() @@ -68,6 +66,10 @@ extension NCCellProtocol { get { return nil } set {} } + var filePreviewImageBottom: NSLayoutConstraint? { + get { return nil } + set {} + } var fileTitleLabel: UILabel? { get { return nil } set {} @@ -84,10 +86,6 @@ extension NCCellProtocol { get { return nil } set {} } - var fileSelectImage: UIImageView? { - get { return nil } - set {} - } var fileStatusImage: UIImageView? { get { return nil } set {} @@ -119,8 +117,7 @@ extension NCCellProtocol { func setButtonMore(named: String, image: UIImage) {} func hideButtonShare(_ status: Bool) {} func hideButtonMore(_ status: Bool) {} - func selectMode(_ status: Bool) {} - func selected(_ status: Bool) {} + func selected(_ status: Bool, isEditMode: Bool) {} func setAccessibility(label: String, value: String) {} func setTags(tags: [String]) {} func setIconOutlines() {} diff --git a/iOSClient/Main/Collection Common/Cell/NCGridCell.swift b/iOSClient/Main/Collection Common/Cell/NCGridCell.swift index 7198938b74..2e262ed129 100644 --- a/iOSClient/Main/Collection Common/Cell/NCGridCell.swift +++ b/iOSClient/Main/Collection Common/Cell/NCGridCell.swift @@ -24,7 +24,6 @@ import UIKit class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProtocol { - @IBOutlet weak var imageItem: UIImageView! @IBOutlet weak var imageSelect: UIImageView! @IBOutlet weak var imageStatus: UIImageView! @@ -67,10 +66,6 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto get { return labelSubinfo } set { labelSubinfo = newValue } } - var fileSelectImage: UIImageView? { - get { return imageSelect } - set { imageSelect = newValue } - } var fileStatusImage: UIImageView? { get { return imageStatus } set { imageStatus = newValue } @@ -86,8 +81,15 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto override func awakeFromNib() { super.awakeFromNib() + initCell() + } + + override func prepareForReuse() { + super.prepareForReuse() + initCell() + } - // use entire cell as accessibility element + func initCell() { accessibilityHint = nil accessibilityLabel = nil accessibilityValue = nil @@ -100,31 +102,20 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto imageVisualEffect.clipsToBounds = true imageVisualEffect.alpha = 0.5 + imageSelect.isHidden = true + imageSelect.image = NCImageCache.images.checkedYes + let longPressedGesture = UILongPressGestureRecognizer(target: self, action: #selector(longPress(gestureRecognizer:))) longPressedGesture.minimumPressDuration = 0.5 longPressedGesture.delegate = self longPressedGesture.delaysTouchesBegan = true self.addGestureRecognizer(longPressedGesture) - let longPressedGestureMore = UILongPressGestureRecognizer(target: self, action: #selector(longPressInsideMore(gestureRecognizer:))) - longPressedGestureMore.minimumPressDuration = 0.5 - longPressedGestureMore.delegate = self - longPressedGestureMore.delaysTouchesBegan = true - buttonMore.addGestureRecognizer(longPressedGestureMore) - labelTitle.text = "" labelInfo.text = "" labelSubinfo.text = "" } - override func prepareForReuse() { - super.prepareForReuse() - imageItem.backgroundColor = nil - accessibilityHint = nil - accessibilityLabel = nil - accessibilityValue = nil - } - override func snapshotView(afterScreenUpdates afterUpdates: Bool) -> UIView? { return nil } @@ -133,10 +124,6 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto gridCellDelegate?.tapMoreGridItem(with: objectId, namedButtonMore: namedButtonMore, image: imageItem.image, indexPath: indexPath, sender: sender) } - @objc func longPressInsideMore(gestureRecognizer: UILongPressGestureRecognizer) { - gridCellDelegate?.longPressMoreGridItem(with: objectId, namedButtonMore: namedButtonMore, indexPath: indexPath, gestureRecognizer: gestureRecognizer) - } - @objc func longPress(gestureRecognizer: UILongPressGestureRecognizer) { gridCellDelegate?.longPressGridItem(with: objectId, indexPath: indexPath, gestureRecognizer: gestureRecognizer) } @@ -162,34 +149,16 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto buttonMore.isHidden = status } - func selectMode(_ status: Bool) { - if status { - imageSelect.isHidden = false + func selected(_ status: Bool, isEditMode: Bool) { + if isEditMode { buttonMore.isHidden = true accessibilityCustomActions = nil } else { - imageSelect.isHidden = true - imageVisualEffect.isHidden = true buttonMore.isHidden = false setA11yActions() } - } - - func selected(_ status: Bool) { - guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(objectId), !metadata.isInTransfer else { - imageSelect.isHidden = true - imageVisualEffect.isHidden = true - return - } if status { - if traitCollection.userInterfaceStyle == .dark { - imageVisualEffect.effect = UIBlurEffect(style: .dark) - imageVisualEffect.backgroundColor = .black - } else { - imageVisualEffect.effect = UIBlurEffect(style: .extraLight) - imageVisualEffect.backgroundColor = .lightGray - } - imageSelect.image = NCImageCache.images.checkedYes + imageSelect.isHidden = false imageVisualEffect.isHidden = false } else { imageSelect.isHidden = true @@ -198,7 +167,6 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto } func writeInfoDateSize(date: NSDate, size: Int64) { - let dateFormatter = DateFormatter() dateFormatter.dateStyle = .short dateFormatter.timeStyle = .none @@ -224,28 +192,17 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto protocol NCGridCellDelegate: AnyObject { func tapMoreGridItem(with objectId: String, namedButtonMore: String, image: UIImage?, indexPath: IndexPath, sender: Any) - func longPressMoreGridItem(with objectId: String, namedButtonMore: String, indexPath: IndexPath, gestureRecognizer: UILongPressGestureRecognizer) func longPressGridItem(with objectId: String, indexPath: IndexPath, gestureRecognizer: UILongPressGestureRecognizer) } -// optional func -extension NCGridCellDelegate { - func tapMoreGridItem(with objectId: String, namedButtonMore: String, image: UIImage?, indexPath: IndexPath, sender: Any) {} - func longPressMoreGridItem(with objectId: String, namedButtonMore: String, indexPath: IndexPath, gestureRecognizer: UILongPressGestureRecognizer) {} - func longPressGridItem(with objectId: String, indexPath: IndexPath, gestureRecognizer: UILongPressGestureRecognizer) {} -} - // MARK: - Grid Layout class NCGridLayout: UICollectionViewFlowLayout { - var heightLabelPlusButton: CGFloat = 60 var marginLeftRight: CGFloat = 10 - var itemForLine: CGFloat = 3 + var column: CGFloat = 3 var itemWidthDefault: CGFloat = 140 - // MARK: - View Life Cycle - override init() { super.init() @@ -265,20 +222,15 @@ class NCGridLayout: UICollectionViewFlowLayout { override var itemSize: CGSize { get { if let collectionView = collectionView { - if collectionView.frame.width < 400 { - itemForLine = 3 + column = 3 } else { - itemForLine = collectionView.frame.width / itemWidthDefault + column = collectionView.frame.width / itemWidthDefault } - - let itemWidth: CGFloat = (collectionView.frame.width - marginLeftRight * 2 - marginLeftRight * (itemForLine - 1)) / itemForLine + let itemWidth: CGFloat = (collectionView.frame.width - marginLeftRight * 2 - marginLeftRight * (column - 1)) / column let itemHeight: CGFloat = itemWidth + heightLabelPlusButton - return CGSize(width: itemWidth, height: itemHeight) } - - // Default fallback return CGSize(width: itemWidthDefault, height: itemWidthDefault) } set { diff --git a/iOSClient/Main/Collection Common/Cell/NCGridCell.xib b/iOSClient/Main/Collection Common/Cell/NCGridCell.xib index a69853c857..8a2beec3a7 100644 --- a/iOSClient/Main/Collection Common/Cell/NCGridCell.xib +++ b/iOSClient/Main/Collection Common/Cell/NCGridCell.xib @@ -18,43 +18,18 @@ + - - - - - - - - - - - - - - - - - - - @@ -77,14 +52,6 @@ - @@ -92,6 +59,32 @@ + + + + + + + + + + + + - + - + - - - - - + + + + + @@ -157,11 +129,11 @@ - + - + @@ -170,8 +142,6 @@ - - @@ -179,7 +149,7 @@ - + @@ -306,28 +276,22 @@ - - - - - - - + - + - + diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift index 477a1ced20..921fe5b7ff 100644 --- a/iOSClient/Share/NCShare.swift +++ b/iOSClient/Share/NCShare.swift @@ -31,16 +31,13 @@ import MarqueeLabel import ContactsUI class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent { - @IBOutlet weak var viewContainerConstraint: NSLayoutConstraint! @IBOutlet weak var sharedWithYouByView: UIView! @IBOutlet weak var sharedWithYouByImage: UIImageView! @IBOutlet weak var sharedWithYouByLabel: UILabel! - @IBOutlet weak var sharedWithYouByNoteImage: UIImageView! - @IBOutlet weak var sharedWithYouByNote: MarqueeLabel! @IBOutlet weak var searchFieldTopConstraint: NSLayoutConstraint! - @IBOutlet weak var searchField: UITextField! - var textField: UITextField? { searchField } + @IBOutlet weak var searchField: UISearchBar! + var textField: UIView? { searchField } @IBOutlet weak var tableView: UITableView! @IBOutlet weak var btnContact: UIButton! @@ -72,7 +69,7 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent view.backgroundColor = .systemBackground viewContainerConstraint.constant = height - searchFieldTopConstraint.constant = 10 + searchFieldTopConstraint.constant = 0 searchField.placeholder = NSLocalizedString("_shareLinksearch_placeholder_", comment: "") searchField.autocorrectionType = .no @@ -81,6 +78,7 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent tableView.delegate = self tableView.allowsSelection = false tableView.backgroundColor = .systemBackground + tableView.contentInset = UIEdgeInsets(top: 8, left: 0, bottom: 10, right: 0) tableView.register(UINib(nibName: "NCShareLinkCell", bundle: nil), forCellReuseIdentifier: "cellLink") tableView.register(UINib(nibName: "NCShareUserCell", bundle: nil), forCellReuseIdentifier: "cellUser") @@ -93,9 +91,9 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent let direcrory = NCManageDatabase.shared.getTableDirectory(account: metadata.account, serverUrl: metadata.serverUrl) if NCGlobal.shared.capabilityE2EEApiVersion == NCGlobal.shared.e2eeVersionV12 || (NCGlobal.shared.capabilityE2EEApiVersion == NCGlobal.shared.e2eeVersionV20 && direcrory?.e2eEncrypted ?? false) { - // searchField.isEnabled = false searchFieldTopConstraint.constant = -50 - searchField.isHidden = true + searchField.alpha = 0 + btnContact.alpha = 0 } } else { checkSharedWithYou() @@ -108,6 +106,9 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent let isVisible = (self.navigationController?.topViewController as? NCSharePaging)?.page == .sharing networking?.readShare(showLoadingIndicator: isVisible) } + + searchField.searchTextField.font = .systemFont(ofSize: 14) + searchField.delegate = self } func makeNewLinkShare() { @@ -128,11 +129,12 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent guard let appDelegate = self.appDelegate, let metadata = metadata, !metadata.ownerId.isEmpty, metadata.ownerId != appDelegate.userId else { return } if !canReshare { - searchField.isEnabled = false + searchField.isUserInteractionEnabled = false + searchField.alpha = 0.5 searchField.placeholder = NSLocalizedString("_share_reshare_disabled_", comment: "") } - searchFieldTopConstraint.constant = 65 + searchFieldTopConstraint.constant = 45 sharedWithYouByView.isHidden = false sharedWithYouByLabel.text = NSLocalizedString("_shared_with_you_by_", comment: "") + " " + metadata.ownerDisplayName sharedWithYouByImage.image = utility.loadUserImage( @@ -146,19 +148,6 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent let shareLabelAction = UITapGestureRecognizer(target: self, action: #selector(openShareProfile)) sharedWithYouByLabel.addGestureRecognizer(shareLabelAction) - if !metadata.note.isEmpty { - searchFieldTopConstraint.constant = 95 - sharedWithYouByNoteImage.isHidden = false - sharedWithYouByNoteImage.image = utility.loadImage(named: "note.text", colors: [NCBrandColor.shared.iconImageColor]) - sharedWithYouByNote.isHidden = false - sharedWithYouByNote.text = metadata.note - sharedWithYouByNote.textColor = NCBrandColor.shared.textColor - sharedWithYouByNote.trailingBuffer = sharedWithYouByNote.frame.width - } else { - sharedWithYouByNoteImage.isHidden = true - sharedWithYouByNote.isHidden = true - } - let fileName = appDelegate.userBaseUrl + "-" + metadata.ownerId + ".png" if NCManageDatabase.shared.getImageAvatarLoaded(fileName: fileName) == nil { @@ -253,14 +242,18 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent dropDown = DropDown() let appearance = DropDown.appearance() + // Setting up the blur effect + let blurEffect = UIBlurEffect(style: .light) // You can choose .dark, .extraLight, or .light + let blurEffectView = UIVisualEffectView(effect: blurEffect) + blurEffectView.frame = CGRect(x: 0, y: 0, width: 500, height: 20) + appearance.backgroundColor = .systemBackground appearance.cornerRadius = 10 - appearance.shadowColor = UIColor(white: 0.5, alpha: 1) - appearance.shadowOpacity = 0.9 - appearance.shadowRadius = 25 + appearance.shadowColor = .black + appearance.shadowOpacity = 0.2 + appearance.shadowRadius = 30 appearance.animationduration = 0.25 appearance.textColor = .darkGray - appearance.setupMaskedCorners([.layerMaxXMaxYCorner, .layerMinXMaxYCorner]) for sharee in sharees { var label = sharee.label @@ -271,8 +264,8 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent } dropDown.anchorView = searchField - dropDown.bottomOffset = CGPoint(x: 0, y: searchField.bounds.height) - dropDown.width = searchField.bounds.width + dropDown.bottomOffset = CGPoint(x: 10, y: searchField.bounds.height) + dropDown.width = searchField.bounds.width - 20 dropDown.direction = .bottom dropDown.cellNib = UINib(nibName: "NCSearchUserDropDownCell", bundle: nil) @@ -308,9 +301,9 @@ extension NCShare: UITableViewDelegate { func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { if indexPath.section == 0, indexPath.row == 0 { // internal cell has description - return 90 + return 40 } - return 70 + return 60 } } @@ -345,7 +338,7 @@ extension NCShare: UITableViewDataSource { if metadata.e2eEncrypted && NCGlobal.shared.capabilityE2EEApiVersion == NCGlobal.shared.e2eeVersionV12 { cell.tableShare = shares.firstShareLink } else { - if indexPath.row == 0 { + if indexPath.row == 1 { cell.isInternalLink = true } else if shares.firstShareLink?.isInvalidated != true { cell.tableShare = shares.firstShareLink @@ -390,7 +383,7 @@ extension NCShare: CNContactPickerDelegate { if contact.emailAddresses.count > 1 { showEmailList(arrEmail: contact.emailAddresses.map({$0.value as String})) } else if let email = contact.emailAddresses.first?.value as? String { - textField?.text = email + searchField?.text = email networking?.getSharees(searchString: email) } } @@ -405,7 +398,7 @@ extension NCShare: CNContactPickerDelegate { selected: false, on: false, action: { _ in - self.textField?.text = email + self.searchField?.text = email self.networking?.getSharees(searchString: email) } ) @@ -416,3 +409,28 @@ extension NCShare: CNContactPickerDelegate { } } } + +extension NCShare: UISearchBarDelegate { + func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { + NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(searchSharees), object: nil) + + if searchText.isEmpty { + dropDown.hide() + } else { + perform(#selector(searchSharees), with: nil, afterDelay: 0.5) + } + } + + @objc private func searchSharees() { + // https://stackoverflow.com/questions/25471114/how-to-validate-an-e-mail-address-in-swift + func isValidEmail(_ email: String) -> Bool { + + let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}" + let emailPred = NSPredicate(format: "SELF MATCHES %@", emailRegEx) + return emailPred.evaluate(with: email) + } + guard let searchString = searchField.text, !searchString.isEmpty else { return } + if searchString.contains("@"), !isValidEmail(searchString) { return } + networking?.getSharees(searchString: searchString) + } +} diff --git a/iOSClient/Share/NCShareCommentsCell.xib b/iOSClient/Share/NCShareCommentsCell.xib index 5ce95380a5..cceef5a118 100755 --- a/iOSClient/Share/NCShareCommentsCell.xib +++ b/iOSClient/Share/NCShareCommentsCell.xib @@ -1,9 +1,9 @@ - + - + @@ -11,22 +11,22 @@ - - + + - + - + - - + + - + - - + + - + - + - - - - - - + + + + + + @@ -96,7 +93,7 @@ - + diff --git a/iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.swift b/iOSClient/Share/NCShareHeader.swift similarity index 74% rename from iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.swift rename to iOSClient/Share/NCShareHeader.swift index b64a776af1..152a818cf8 100644 --- a/iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.swift +++ b/iOSClient/Share/NCShareHeader.swift @@ -1,5 +1,5 @@ // -// NCShareAdvancePermissionHeader.swift +// NCShareHeader.swift // Nextcloud // // Created by T-systems on 10/08/21. @@ -22,18 +22,25 @@ // import UIKit +import TagListView -class NCShareAdvancePermissionHeader: UIView { +class NCShareHeader: UIView { @IBOutlet weak var imageView: UIImageView! @IBOutlet weak var fileName: UILabel! @IBOutlet weak var info: UILabel! @IBOutlet weak var fullWidthImageView: UIImageView! + @IBOutlet weak var fileNameTopConstraint: NSLayoutConstraint! + @IBOutlet weak var tagListView: TagListView! + + private var heightConstraintWithImage: NSLayoutConstraint? + private var heightConstraintWithoutImage: NSLayoutConstraint? func setupUI(with metadata: tableMetadata) { let utilityFileSystem = NCUtilityFileSystem() if FileManager.default.fileExists(atPath: utilityFileSystem.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) { fullWidthImageView.image = NCUtility().getImageMetadata(metadata, for: frame.height) fullWidthImageView.contentMode = .scaleAspectFill + imageView.image = fullWidthImageView.image imageView.isHidden = true } else { if metadata.directory { @@ -43,10 +50,24 @@ class NCShareAdvancePermissionHeader: UIView { } else { imageView.image = NCImageCache.images.file } + + fileNameTopConstraint.constant -= 45 } + fileName.text = metadata.fileNameView fileName.textColor = NCBrandColor.shared.textColor info.textColor = NCBrandColor.shared.textColor2 info.text = utilityFileSystem.transformedSize(metadata.size) + ", " + NCUtility().dateDiff(metadata.date as Date) + + tagListView.addTags(Array(metadata.tags)) + + setNeedsLayout() + layoutIfNeeded() + } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + if fullWidthImageView.image != nil { + imageView.isHidden = traitCollection.verticalSizeClass != .compact + } } } diff --git a/iOSClient/Share/NCShareHeader.xib b/iOSClient/Share/NCShareHeader.xib new file mode 100644 index 0000000000..55ffce6cab --- /dev/null +++ b/iOSClient/Share/NCShareHeader.xib @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOSClient/Share/NCShareHeaderView.xib b/iOSClient/Share/NCShareHeaderView.xib index 3f7727099b..44b83d3fc7 100644 --- a/iOSClient/Share/NCShareHeaderView.xib +++ b/iOSClient/Share/NCShareHeaderView.xib @@ -1,9 +1,9 @@ - + - + diff --git a/iOSClient/Share/NCShareLinkCell.xib b/iOSClient/Share/NCShareLinkCell.xib index 32182dae50..a102ccf497 100755 --- a/iOSClient/Share/NCShareLinkCell.xib +++ b/iOSClient/Share/NCShareLinkCell.xib @@ -1,9 +1,9 @@ - - + + - + @@ -11,22 +11,24 @@ - - + + - + - - + + - + + + - + - - + + - - - + + - + @@ -110,21 +107,21 @@ - + - + - + - + diff --git a/iOSClient/Share/NCSharePaging.swift b/iOSClient/Share/NCSharePaging.swift index 537fbaaacf..8e0f556f57 100644 --- a/iOSClient/Share/NCSharePaging.swift +++ b/iOSClient/Share/NCSharePaging.swift @@ -29,7 +29,7 @@ import MarqueeLabel import TagListView protocol NCSharePagingContent { - var textField: UITextField? { get } + var textField: UIView? { get } } class NCSharePaging: UIViewController { @@ -63,8 +63,9 @@ class NCSharePaging: UIViewController { pagingViewController.backgroundColor = .systemBackground pagingViewController.menuBackgroundColor = .systemBackground pagingViewController.selectedBackgroundColor = .systemBackground + pagingViewController.indicatorColor = NCBrandColor.shared.brandElement pagingViewController.textColor = NCBrandColor.shared.textColor - pagingViewController.selectedTextColor = NCBrandColor.shared.textColor + pagingViewController.selectedTextColor = NCBrandColor.shared.brandElement // Pagination addChild(pagingViewController) @@ -76,14 +77,16 @@ class NCSharePaging: UIViewController { height: 1, zIndex: Int.max, spacing: .zero, - insets: UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5) + insets: .zero ) + pagingViewController.borderOptions = .visible(height: 1, zIndex: Int.max, insets: .zero) + // Contrain the paging view to all edges. pagingViewController.view.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ pagingViewController.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), - pagingViewController.view.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), + pagingViewController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor), pagingViewController.view.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), pagingViewController.view.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor) ]) @@ -97,7 +100,6 @@ class NCSharePaging: UIViewController { pagingViewController.select(index: 0) } - (pagingViewController.view as? NCSharePagingView)?.setupConstraints() pagingViewController.reloadMenu() } @@ -112,9 +114,9 @@ class NCSharePaging: UIViewController { self.dismiss(animated: false, completion: nil) } - pagingViewController.menuItemSize = .fixed( - width: self.view.bounds.width / CGFloat(self.pages.count), - height: 40) +// pagingViewController.menuItemSize = .fixed( +// width: self.view.bounds.width / CGFloat(self.pages.count), +// height: 40) } override func viewWillDisappear(_ animated: Bool) { @@ -130,13 +132,7 @@ class NCSharePaging: UIViewController { override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) - - coordinator.animate(alongsideTransition: nil) { _ in - self.pagingViewController.menuItemSize = .fixed( - width: self.view.bounds.width / CGFloat(self.pages.count), - height: 40) - self.currentVC?.textField?.resignFirstResponder() - } + self.currentVC?.textField?.resignFirstResponder() } // MARK: - NotificationCenter & Keyboard & TextField @@ -186,7 +182,7 @@ extension NCSharePaging: PagingViewControllerDataSource { func pagingViewController(_: PagingViewController, viewControllerAt index: Int) -> UIViewController { - let height = pagingViewController.options.menuHeight + NCSharePagingView.headerHeight + NCSharePagingView.tagHeaderHeight + let height: CGFloat = 50 if pages[index] == .activity { guard let viewController = UIStoryboard(name: "NCActivity", bundle: nil).instantiateInitialViewController() as? NCActivity else { @@ -248,13 +244,11 @@ class NCShareHeaderViewController: PagingViewController { } class NCSharePagingView: PagingView { - - static let headerHeight: CGFloat = 90 - static var tagHeaderHeight: CGFloat = 0 var metadata = tableMetadata() let utilityFileSystem = NCUtilityFileSystem() let utility = NCUtility() public var headerHeightConstraint: NSLayoutConstraint? + var header: NCShareHeader? // MARK: - View Life Cycle @@ -270,61 +264,68 @@ class NCSharePagingView: PagingView { override func setupConstraints() { - guard let headerView = Bundle.main.loadNibNamed("NCShareHeaderView", owner: self, options: nil)?.first as? NCShareHeaderView else { return } +// guard let headerView = Bundle.main.loadNibNamed("NCShareHeaderView", owner: self, options: nil)?.first as? NCShareHeaderView else { return } + + guard let headerView = Bundle.main.loadNibNamed("NCShareHeader", owner: self, options: nil)?.first as? NCShareHeader else { return } + header = headerView headerView.backgroundColor = .systemBackground - headerView.ocId = metadata.ocId +// headerView.ocId = metadata.ocId let dateFormatter = DateFormatter() dateFormatter.dateStyle = .short dateFormatter.timeStyle = .short dateFormatter.locale = Locale.current - if FileManager.default.fileExists(atPath: utilityFileSystem.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) { - headerView.imageView.image = UIImage(contentsOfFile: utilityFileSystem.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) - } else { - if metadata.directory { - let image = metadata.e2eEncrypted ? UIImage(named: "folderEncrypted") : UIImage(named: "folder") - headerView.imageView.image = image?.image(color: NCBrandColor.shared.brandElement, size: image?.size.width ?? 0) - headerView.imageView.image = headerView.imageView.image?.colorizeFolder(metadata: metadata) - } else if !metadata.iconName.isEmpty { - headerView.imageView.image = utility.loadImage(named: metadata.iconName, useTypeIconFile: true) - } else { - headerView.imageView.image = NCImageCache.images.file - } - } - headerView.path.text = utilityFileSystem.getPath(path: metadata.path, user: metadata.user, fileName: metadata.fileName) - headerView.path.textColor = NCBrandColor.shared.textColor - headerView.path.trailingBuffer = headerView.path.frame.width - if metadata.favorite { - headerView.favorite.setImage(utility.loadImage(named: "star.fill", colors: [NCBrandColor.shared.yellowFavorite], size: 20), for: .normal) - } else { - headerView.favorite.setImage(utility.loadImage(named: "star.fill", colors: [NCBrandColor.shared.iconImageColor2], size: 20), for: .normal) - } - headerView.info.text = utilityFileSystem.transformedSize(metadata.size) + ", " + NSLocalizedString("_modified_", comment: "") + " " + dateFormatter.string(from: metadata.date as Date) - headerView.info.textColor = NCBrandColor.shared.textColor2 - headerView.creation.text = NSLocalizedString("_creation_", comment: "") + " " + dateFormatter.string(from: metadata.creationDate as Date) - headerView.creation.textColor = NCBrandColor.shared.textColor2 - headerView.upload.text = NSLocalizedString("_upload_", comment: "") + " " + dateFormatter.string(from: metadata.uploadDate as Date) - headerView.upload.textColor = NCBrandColor.shared.textColor2 - - headerView.details.setTitleColor(NCBrandColor.shared.textColor, for: .normal) - headerView.details.setTitle(NSLocalizedString("_details_", comment: ""), for: .normal) - headerView.details.layer.cornerRadius = 9 - headerView.details.layer.masksToBounds = true - headerView.details.layer.backgroundColor = UIColor(red: 152.0 / 255.0, green: 167.0 / 255.0, blue: 181.0 / 255.0, alpha: 0.8).cgColor - - for tag in metadata.tags { - headerView.tagListView.addTag(tag) - } +// if FileManager.default.fileExists(atPath: utilityFileSystem.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) { +// headerView.imageView.image = UIImage(contentsOfFile: utilityFileSystem.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) +// } else { +// print(metadata.iconName) +// if metadata.directory { +// let image = metadata.e2eEncrypted ? UIImage(named: "folderEncrypted") : UIImage(named: "folder") +// headerView.imageView.image = image?.image(color: NCBrandColor.shared.brandElement, size: image?.size.width ?? 0) +// headerView.imageView.image = headerView.imageView.image?.colorizeFolder(metadata: metadata) +// } else if !metadata.iconName.isEmpty { +// headerView.imageView.image = utility.loadImage(named: metadata.iconName, useTypeIconFile: true) +// } else { +// headerView.imageView.image = NCImageCache.images.file +// } +// } +// headerView.path.text = utilityFileSystem.getPath(path: metadata.path, user: metadata.user, fileName: metadata.fileName) +// headerView.path.textColor = NCBrandColor.shared.textColor +// headerView.path.trailingBuffer = headerView.path.frame.width +// if metadata.favorite { +// headerView.favorite.setImage(utility.loadImage(named: "star.fill", colors: [NCBrandColor.shared.yellowFavorite], size: 20), for: .normal) +// } else { +// headerView.favorite.setImage(utility.loadImage(named: "star.fill", colors: [NCBrandColor.shared.iconImageColor2], size: 20), for: .normal) +// } +// headerView.info.text = utilityFileSystem.transformedSize(metadata.size) + ", " + NSLocalizedString("_modified_", comment: "") + " " + dateFormatter.string(from: metadata.date as Date) +// headerView.info.textColor = NCBrandColor.shared.textColor2 +// headerView.creation.text = NSLocalizedString("_creation_", comment: "") + " " + dateFormatter.string(from: metadata.creationDate as Date) +// headerView.creation.textColor = NCBrandColor.shared.textColor2 +// headerView.upload.text = NSLocalizedString("_upload_", comment: "") + " " + dateFormatter.string(from: metadata.uploadDate as Date) +// headerView.upload.textColor = NCBrandColor.shared.textColor2 +// +// headerView.details.setTitleColor(NCBrandColor.shared.textColor, for: .normal) +// headerView.details.setTitle(NSLocalizedString("_details_", comment: ""), for: .normal) +// headerView.details.layer.cornerRadius = 9 +// headerView.details.layer.masksToBounds = true +// headerView.details.layer.backgroundColor = UIColor(red: 152.0 / 255.0, green: 167.0 / 255.0, blue: 181.0 / 255.0, alpha: 0.8).cgColor - if metadata.tags.isEmpty { - NCSharePagingView.tagHeaderHeight = 0 - } else { - NCSharePagingView.tagHeaderHeight = headerView.tagListView.intrinsicContentSize.height + 10 - } +// for tag in metadata.tags { +//// headerView.tagListView.addTag(tag) +// } + +// if headerView.fullWidthImageView?.image == nil { +// NCSharePagingView.tagHeaderHeight = 80 +// } else { +// NCSharePagingView.tagHeaderHeight = 130 +// } + + headerView.setupUI(with: metadata) addSubview(headerView) +// recalculateHeaderHeight() collectionView.translatesAutoresizingMaskIntoConstraints = false headerView.translatesAutoresizingMaskIntoConstraints = false pageView.translatesAutoresizingMaskIntoConstraints = false @@ -335,17 +336,36 @@ class NCSharePagingView: PagingView { collectionView.heightAnchor.constraint(equalToConstant: options.menuHeight), collectionView.topAnchor.constraint(equalTo: headerView.bottomAnchor), - headerView.topAnchor.constraint(equalTo: topAnchor), - headerView.leadingAnchor.constraint(equalTo: leadingAnchor), - headerView.trailingAnchor.constraint(equalTo: trailingAnchor), - headerView.heightAnchor.constraint(equalToConstant: NCSharePagingView.headerHeight + NCSharePagingView.tagHeaderHeight), + headerView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor), + headerView.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor), + headerView.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor), +// headerView.heightAnchor.constraint(equalToConstant: 260), pageView.leadingAnchor.constraint(equalTo: leadingAnchor), pageView.trailingAnchor.constraint(equalTo: trailingAnchor), pageView.bottomAnchor.constraint(equalTo: bottomAnchor), - pageView.topAnchor.constraint(equalTo: topAnchor, constant: 10) + pageView.topAnchor.constraint(equalTo: headerView.bottomAnchor) ]) + + +// setNeedsLayout() +// layoutIfNeeded() } + +// func recalculateHeaderHeight() { +// guard let header else { return } +// // Deactivate existing height constraints +// for constraint in header.constraints { +// if constraint.firstAttribute == .height { +// constraint.isActive = false +// } +// } +// +// NSLayoutConstraint.activate([ +// header.heightAnchor.constraint(equalToConstant: header.heightWithImage.constant) +// ]) +// +// } } class NCShareHeaderView: UIView { @@ -383,7 +403,6 @@ class NCShareHeaderView: UIView { } @IBAction func touchUpInsideDetails(_ sender: UIButton) { - creation.isHidden = !creation.isHidden upload.isHidden = !upload.isHidden } diff --git a/iOSClient/Share/NCShareUserCell.swift b/iOSClient/Share/NCShareUserCell.swift index afa5eba26a..ad92b7d699 100644 --- a/iOSClient/Share/NCShareUserCell.swift +++ b/iOSClient/Share/NCShareUserCell.swift @@ -105,7 +105,7 @@ class NCShareUserCell: UITableViewCell, NCCellProtocol { imageItem?.addGestureRecognizer(tapGesture) labelQuickStatus.textColor = NCBrandColor.shared.customer - imageDownArrow.image = utility.loadImage(named: "arrowtriangle.down.fill", colors: [NCBrandColor.shared.customer]) + imageDownArrow.image = utility.loadImage(named: "arrowtriangle.down.circle", colors: [NCBrandColor.shared.customer]) } @objc func tapAvatarImage(_ sender: UITapGestureRecognizer) { @@ -157,7 +157,12 @@ class NCSearchUserDropDownCell: DropDownCell, NCCellProtocol { imageItem.image = NCShareCommon().getImageShareType(shareType: sharee.shareType) imageShareeType.image = NCShareCommon().getImageShareType(shareType: sharee.shareType) let status = utility.getUserStatus(userIcon: sharee.userIcon, userStatus: sharee.userStatus, userMessage: sharee.userMessage) - imageStatus.image = status.statusImage + + if let statusImage = status.statusImage { + imageStatus.image = statusImage + imageStatus.makeCircularBackground(withColor: .systemBackground) + } + self.status.text = status.statusMessage if self.status.text?.count ?? 0 > 0 { centerTitle.constant = -5 diff --git a/iOSClient/Share/NCShareUserCell.xib b/iOSClient/Share/NCShareUserCell.xib index 613ee026d9..df97e61950 100755 --- a/iOSClient/Share/NCShareUserCell.xib +++ b/iOSClient/Share/NCShareUserCell.xib @@ -1,9 +1,9 @@ - + - + @@ -12,18 +12,19 @@ - + - + - - + + - - + + + @@ -35,16 +36,16 @@ - + - - + +