diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index b24d42ac75..7c6b8a6b57 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -12,7 +12,6 @@ 2C33C48223E2C475005F963B /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C33C48123E2C475005F963B /* NotificationService.swift */; }; 2C33C48623E2C475005F963B /* Notification Service Extension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 2C33C47F23E2C475005F963B /* Notification Service Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 2F96A1BAFB10ACFEAC68EF1C /* NCContextMenuPlayerTracks.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4C7A5B36D1ED178FB6B76CB /* NCContextMenuPlayerTracks.swift */; }; - 370D26AF248A3D7A00121797 /* NCCellMain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370D26AE248A3D7A00121797 /* NCCellMain.swift */; }; A5A87F9E4B0E4441A6A4BC20 /* NCContextMenuProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7697C94BA14450A0867940 /* NCContextMenuProfile.swift */; }; AA3C85E82D36B08C00F74F12 /* UITestBackend.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA3C85E72D36B08C00F74F12 /* UITestBackend.swift */; }; AA3C85EB2D36BBFB00F74F12 /* OCSResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA3C85EA2D36BBF400F74F12 /* OCSResponse.swift */; }; @@ -89,6 +88,10 @@ AFCE353527E4ED5900FEA6C2 /* DateFormatter+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353427E4ED5900FEA6C2 /* DateFormatter+Extension.swift */; }; AFCE353727E4ED7B00FEA6C2 /* NCShareCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353627E4ED7B00FEA6C2 /* NCShareCells.swift */; }; AFCE353927E5DE0500FEA6C2 /* Shareable.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* Shareable.swift */; }; + B55AFB502FE28B8000A1A1A4 /* NCCellProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B55AFB4F2FE28B8000A1A1A4 /* NCCellProtocol.swift */; }; + B55AFB512FE28B8000A1A1A4 /* NCCellProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B55AFB4F2FE28B8000A1A1A4 /* NCCellProtocol.swift */; }; + B55AFB542FE28C5100A1A1A4 /* NCSortMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = B55AFB532FE28C5100A1A1A4 /* NCSortMenu.swift */; }; + B55AFB552FE28C5100A1A1A4 /* NCMenuAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B55AFB522FE28C5100A1A1A4 /* NCMenuAction.swift */; }; CB3666201AF7550816B5CD6A /* NCContextMenuComment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8932E90EC4278026D86CCCC9 /* NCContextMenuComment.swift */; }; D5B6AA7827200C7200D49C24 /* NCActivityTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B6AA7727200C7200D49C24 /* NCActivityTableViewCell.swift */; }; F310B1EF2BA862F1001C42F5 /* NCViewerMedia+VisionKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = F310B1EE2BA862F1001C42F5 /* NCViewerMedia+VisionKit.swift */; }; @@ -910,7 +913,6 @@ F7E98C1927E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E98C1527E0D0FC001F9F19 /* NCManageDatabase+Video.swift */; }; F7ED547C25EEA65400956C55 /* QRCodeReader in Frameworks */ = {isa = PBXBuildFile; productRef = F7ED547B25EEA65400956C55 /* QRCodeReader */; }; F7EDE4D6262D7B9600414FE6 /* NCListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD4121903CE00088454D /* NCListCell.swift */; }; - F7EDE4DB262D7BA200414FE6 /* NCCellMain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370D26AE248A3D7A00121797 /* NCCellMain.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 */; }; @@ -1154,7 +1156,6 @@ 2C33C47F23E2C475005F963B /* Notification Service Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Notification Service Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 2C33C48123E2C475005F963B /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; }; 2C33C48A23E2CC26005F963B /* Notification_Service_Extension-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Notification_Service_Extension-Bridging-Header.h"; sourceTree = ""; }; - 370D26AE248A3D7A00121797 /* NCCellMain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCellMain.swift; sourceTree = ""; }; 8932E90EC4278026D86CCCC9 /* NCContextMenuComment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCContextMenuComment.swift; sourceTree = ""; }; AA3C85E72D36B08C00F74F12 /* UITestBackend.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestBackend.swift; sourceTree = ""; }; AA3C85EA2D36BBF400F74F12 /* OCSResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OCSResponse.swift; sourceTree = ""; }; @@ -1279,6 +1280,9 @@ AFCE353627E4ED7B00FEA6C2 /* NCShareCells.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareCells.swift; sourceTree = ""; }; AFCE353827E5DE0400FEA6C2 /* Shareable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Shareable.swift; sourceTree = ""; }; B4C7A5B36D1ED178FB6B76CB /* NCContextMenuPlayerTracks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCContextMenuPlayerTracks.swift; sourceTree = ""; }; + B55AFB4F2FE28B8000A1A1A4 /* NCCellProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCellProtocol.swift; sourceTree = ""; }; + B55AFB522FE28C5100A1A1A4 /* NCMenuAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMenuAction.swift; sourceTree = ""; }; + B55AFB532FE28C5100A1A1A4 /* NCSortMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSortMenu.swift; sourceTree = ""; }; BB7697C94BA14450A0867940 /* NCContextMenuProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCContextMenuProfile.swift; sourceTree = ""; }; C0046CDA2A17B98400D87C9D /* NextcloudUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NextcloudUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; C04E2F202A17BB4D001BAD85 /* NextcloudIntegrationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NextcloudIntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -2063,6 +2067,8 @@ 371B5A2F23D0B04B00FAFAE9 /* Menu */ = { isa = PBXGroup; children = ( + B55AFB522FE28C5100A1A1A4 /* NCMenuAction.swift */, + B55AFB532FE28C5100A1A1A4 /* NCSortMenu.swift */, F376A3732E5CC5FF0067EE25 /* ContextMenuActions.swift */, 8932E90EC4278026D86CCCC9 /* NCContextMenuComment.swift */, F78C6FDD296D677300C952C3 /* NCContextMenuMain.swift */, @@ -2558,7 +2564,7 @@ F75FE06B2BB01D0D00A0EFEF /* Cell */ = { isa = PBXGroup; children = ( - 370D26AE248A3D7A00121797 /* NCCellMain.swift */, + B55AFB4F2FE28B8000A1A1A4 /* NCCellProtocol.swift */, F78ACD4121903CE00088454D /* NCListCell.swift */, F78ACD3F21903CC20088454D /* NCGridCell.swift */, F751247A2C42919C00E63DB8 /* NCPhotoCell.swift */, @@ -4411,8 +4417,8 @@ F799DF862C4B7E56003410B5 /* NCSectionHeader.swift in Sources */, F702F2D025EE5B5C008F8E80 /* NCGlobal.swift in Sources */, F72437802C10B92400C7C68D /* NCSharePermissions.swift in Sources */, - F7EDE4DB262D7BA200414FE6 /* NCCellMain.swift in Sources */, F72944F62A8424F800246839 /* NCEndToEndMetadataV1.swift in Sources */, + B55AFB512FE28B8000A1A1A4 /* NCCellProtocol.swift in Sources */, F73EF7BA2B0224AB0087E6E9 /* NCManageDatabase+ExternalSites.swift in Sources */, F711A4EB2AF9327D00095DD8 /* UIImage+animatedGIF.m in Sources */, F36E64FA2B96236C0085ABB5 /* UIView+Extension.swift in Sources */, @@ -4588,7 +4594,6 @@ F3C6F6F62F34CC0900C531B6 /* NCAssistantChatConversationsModel.swift in Sources */, F76340FC2EBDF64D0056F538 /* NCManageDatabase+Tag.swift in Sources */, F733598125C1C188002ABA72 /* NCAskAuthorization.swift in Sources */, - 370D26AF248A3D7A00121797 /* NCCellMain.swift in Sources */, F32FADA92D1176E3007035E2 /* UIButton+Extension.swift in Sources */, F7DF7B3F2F1A2EF900514020 /* WarningBannerView.swift in Sources */, F768822C2C0DD1E7001CF441 /* NCPreferences.swift in Sources */, @@ -4752,6 +4757,7 @@ AF93471A27E2361E002537EE /* NCShareHeader.swift in Sources */, F7F878AE1FB9E3B900599E4F /* NCEndToEndMetadata.swift in Sources */, F7A7FDDD2C2DBD6200E9A93A /* NCDeepLinkHandler.swift in Sources */, + B55AFB502FE28B8000A1A1A4 /* NCCellProtocol.swift in Sources */, F778231E2C42C07C001BB94F /* NCCollectionViewCommon+MediaLayout.swift in Sources */, F710D1F52405770F00A6033D /* NCViewerPDF.swift in Sources */, F72EC7242F45C81600A2135C /* NotificationCenter+Extension.swift in Sources */, @@ -4851,6 +4857,8 @@ F74C0436253F1CDC009762AB /* NCShares.swift in Sources */, F79699E72E689F68000EC82A /* NCMediaNavigationController.swift in Sources */, F7AC1CB028AB94490032D99F /* Array+Extension.swift in Sources */, + B55AFB542FE28C5100A1A1A4 /* NCSortMenu.swift in Sources */, + B55AFB552FE28C5100A1A1A4 /* NCMenuAction.swift in Sources */, F7AE00F5230D5F9E007ACF8A /* NCLoginProvider.swift in Sources */, F707C26521A2DC5200F6181E /* NCStoreReview.swift in Sources */, F7814E972F3B5F170074DA3A /* NCSVGRenderer.swift in Sources */, diff --git a/iOSClient/Files/NCFiles.swift b/iOSClient/Files/NCFiles.swift index 68c13890b2..b18720b61c 100644 --- a/iOSClient/Files/NCFiles.swift +++ b/iOSClient/Files/NCFiles.swift @@ -8,7 +8,10 @@ import RealmSwift import SwiftUI class NCFiles: NCCollectionViewCommon { + internal var fileNameBlink: String? + internal var fileNameOpen: String? + internal var lastOffsetY: CGFloat = 0 internal var lastScrollTime: TimeInterval = 0 internal var accumulatedScrollDown: CGFloat = 0 @@ -107,15 +110,23 @@ class NCFiles: NCCollectionViewCommon { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) + // Re-evaluate in-app messages after viewDidAppear + MoEngageAnalytics.shared.displayInAppNotificationSafely(reason: "viewDidAppear") + + // Preload hidden NCMedia so it's ready without being shown +// NCMediaPreloader.shared.preloadIfNeeded() + if !self.dataSource.isEmpty() { - blinkCell(fileName: self.fileNameBlink) - fileNameBlink = nil + self.blinkCell(fileName: self.fileNameBlink) + self.openFile(fileName: self.fileNameOpen) + self.fileNameBlink = nil + self.fileNameOpen = nil } Task { // Plus Menu reload - await self.mainNavigationController?.menuPlus?.create(session: session) - + let capabilities = await database.getCapabilities(account: self.session.account) ?? NKCapabilities.Capabilities() + await mainNavigationController?.createPlusMenu(session: self.session, capabilities: capabilities) // Server data if !isSearchingMode { await getServerData() @@ -136,6 +147,7 @@ class NCFiles: NCCollectionViewCommon { super.viewDidDisappear(animated) fileNameBlink = nil + fileNameOpen = nil } // MARK: - DataSource @@ -183,13 +195,30 @@ class NCFiles: NCCollectionViewCommon { startSyncMetadata(metadatas: self.dataSource.getMetadatas()) } - await networking.networkingTasks.cancel(identifier: "\(self.serverUrl)_NCFiles") + Task { + await networking.networkingTasks.cancel(identifier: "\(self.serverUrl)_NCFiles") + } guard !isSearchingMode else { await self.search() return } + func downloadMetadata(_ metadata: tableMetadata) async -> Bool { + let fileSize = utilityFileSystem.fileProviderStorageSize(metadata.ocId, + fileName: metadata.fileNameView, + userId: metadata.userId, + urlBase: metadata.urlBase) + guard fileSize > 0 else { return false } + + if let tblLocalFile = await database.getTableLocalFileAsync(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) { + if tblLocalFile.etag != metadata.etag { + return true + } + } + return false + } + let resultsReadFolder = await networkReadFolderAsync(serverUrl: self.serverUrl, forced: forced) guard resultsReadFolder.error == .success, resultsReadFolder.reloadRequired else { return @@ -198,7 +227,7 @@ class NCFiles: NCCollectionViewCommon { let metadatasForDownload: [tableMetadata] = resultsReadFolder.metadatas ?? self.dataSource.getMetadatas() Task.detached(priority: .utility) { for metadata in metadatasForDownload where !metadata.directory { - if await self.downloadMetadata(metadata) { + if await downloadMetadata(metadata) { if let metadata = await self.database.setMetadataSessionInWaitDownloadAsync(ocId: metadata.ocId, session: NCNetworking.shared.sessionDownload, selector: NCGlobal.shared.selectorDownloadFile, @@ -212,27 +241,9 @@ class NCFiles: NCCollectionViewCommon { await self.reloadDataSource() } - private func downloadMetadata(_ metadata: tableMetadata) async -> Bool { - let fileSize = utilityFileSystem.fileProviderStorageSize(metadata.ocId, - fileName: metadata.fileNameView, - userId: metadata.userId, - urlBase: metadata.urlBase) - guard fileSize > 0 else { - return false - } - - if let tblLocalFile = await database.getTableLocalFileAsync(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) { - if tblLocalFile.etag != metadata.etag { - return true - } - } - return false - } - private func networkReadFolderAsync(serverUrl: String, forced: Bool) async -> (metadatas: [tableMetadata]?, error: NKError, reloadRequired: Bool) { var reloadRequired: Bool = false - let account = session.account - let resultsReadFile = await NCNetworking.shared.readFileAsync(serverUrlFileName: serverUrl, account: account) { task in + let resultsReadFile = await NCNetworking.shared.readFileAsync(serverUrlFileName: serverUrl, account: session.account) { task in Task { await NCNetworking.shared.networkingTasks.track(identifier: "\(self.serverUrl)_NCFiles", task: task) } @@ -247,12 +258,12 @@ class NCFiles: NCCollectionViewCommon { let e2eEncrypted = metadata.e2eEncrypted let ocId = metadata.ocId - await self.database.updateDirectoryRichWorkspaceAsync(metadata.richWorkspace, account: account, serverUrl: serverUrl) + await self.database.updateDirectoryRichWorkspaceAsync(metadata.richWorkspace, account: resultsReadFile.account, serverUrl: serverUrl) let tableDirectory = await self.database.getTableDirectoryAsync(ocId: metadata.ocId) // Verify LivePhoto // - reloadRequired = await networking.setLivePhoto(account: account) + reloadRequired = await networking.setLivePhoto(account: resultsReadFile.account) await NCManageDatabase.shared.deleteLivePhotoError() let shouldSkipUpdate: Bool = ( @@ -269,11 +280,9 @@ class NCFiles: NCCollectionViewCommon { startGUIGetServerData() let options = NKRequestOptions(timeout: 180) - let resultsReadFolder = await NCNetworking.shared.readFolderAsync( - serverUrl: serverUrl, - account: account, - options: options - ) { task in + let (account, metadataFolder, metadatas, error) = await NCNetworking.shared.readFolderAsync(serverUrl: serverUrl, + account: session.account, + options: options) { task in Task { await NCNetworking.shared.networkingTasks.track(identifier: "\(self.serverUrl)_NCFiles", task: task) } @@ -282,8 +291,8 @@ class NCFiles: NCCollectionViewCommon { } } - guard resultsReadFolder.error == .success else { - return(nil, resultsReadFolder.error, reloadRequired) + guard error == .success else { + return(nil, error, reloadRequired) } reloadRequired = true @@ -292,50 +301,57 @@ class NCFiles: NCCollectionViewCommon { self.richWorkspaceText = metadataFolder.richWorkspace } + // + // E2EE section + // + guard e2eEncrypted, - let metadatas = resultsReadFolder.metadatas, + let metadatas, + !metadatas.isEmpty, NCPreferences().isEndToEndEnabled(account: account), await !NCNetworkingE2EE().isInUpload(account: account, serverUrl: serverUrl) else { - return(resultsReadFolder.metadatas, resultsReadFolder.error, reloadRequired) + return(metadatas, error, reloadRequired) } - // - // E2EE section - // - let lock = await self.database.getE2ETokenLockAsync(account: account, serverUrl: serverUrl) - let resultsE2eeGetMetadata = await NCNetworkingE2EE().getMetadata(fileId: ocId, e2eToken: lock?.e2eToken, account: account) + if let e2eToken = lock?.e2eToken { + nkLog(tag: self.global.logTagE2EE, message: "Tocken: \(e2eToken)", minimumLogLevel: .verbose) + } + + let results = await NCNetworkingE2EE().getMetadata(fileId: ocId, e2eToken: lock?.e2eToken, account: account) + + nkLog(tag: self.global.logTagE2EE, message: "Get metadata with error: \(results.error.errorCode)") + nkLog(tag: self.global.logTagE2EE, message: "Get metadata with metadata: \(results.e2eMetadata ?? ""), signature: \(results.signature ?? ""), version \(results.version ?? "")", minimumLogLevel: .verbose) - guard resultsE2eeGetMetadata.error == .success, - let e2eMetadata = resultsE2eeGetMetadata.e2eMetadata, - let version = resultsE2eeGetMetadata.version else { - if resultsE2eeGetMetadata.error.errorCode == NCGlobal.shared.errorResourceNotFound { + guard results.error == .success, + let e2eMetadata = results.e2eMetadata, + let version = results.version else { + + // No metadata fount, re-send it + if results.error.errorCode == NCGlobal.shared.errorResourceNotFound { + await showInfoBanner(windowScene: windowScene, text: "Metadata not found") let error = await NCNetworkingE2EE().uploadMetadata(serverUrl: serverUrl, account: account) if error != .success { - await showErrorBanner(windowScene: windowScene, - text: error.errorDescription, - errorCode: error.errorCode) + await showErrorBanner(windowScene: windowScene, text: error.errorDescription, errorCode: error.errorCode) } } else { - await showErrorBanner(windowScene: windowScene, - text: resultsE2eeGetMetadata.error.errorDescription, - errorCode: resultsE2eeGetMetadata.error.errorCode) + await showErrorBanner(windowScene: windowScene, text: error.errorDescription, errorCode: error.errorCode) } - return(metadatas, resultsE2eeGetMetadata.error, reloadRequired) + + return(metadatas, error, reloadRequired) } - var error = await NCEndToEndMetadata().decodeMetadata(e2eMetadata, - signature: resultsE2eeGetMetadata.signature, - serverUrl: serverUrl, session: self.session) + let errorDecodeMetadata = await NCEndToEndMetadata().decodeMetadata(e2eMetadata, signature: results.signature, serverUrl: serverUrl, session: self.session) + nkLog(debug: "Decode e2ee metadata with error: \(errorDecodeMetadata.errorCode)") - if error == .success { + if errorDecodeMetadata == .success { let capabilities = await NKCapabilities.shared.getCapabilities(for: self.session.account) - if version == "v1", capabilities.e2EEApiVersion.hasPrefix("2.") { + if version == "v1", NCGlobal.shared.isE2eeVersion2(capabilities.e2EEApiVersion) { await showInfoBanner(windowScene: windowScene, text: "Conversion metadata v1 to v2 required, please wait...") nkLog(tag: self.global.logTagE2EE, message: "Conversion v1 to v2") NCActivityIndicator.shared.start() - error = await NCNetworkingE2EE().uploadMetadata(serverUrl: serverUrl, updateVersionV1V2: true, account: account) + let error = await NCNetworkingE2EE().uploadMetadata(serverUrl: serverUrl, updateVersionV1V2: true, account: account) if error != .success { await showErrorBanner(windowScene: windowScene, text: error.errorDescription, errorCode: error.errorCode) } @@ -344,13 +360,9 @@ class NCFiles: NCCollectionViewCommon { } else { // Client Diagnostic await self.database.addDiagnosticAsync(account: account, issue: NCGlobal.shared.diagnosticIssueE2eeErrors) - await showErrorBanner(windowScene: windowScene, text: error.errorDescription, errorCode: error.errorCode) + await showErrorBanner(windowScene: windowScene, text: errorDecodeMetadata.errorDescription, errorCode: errorDecodeMetadata.errorCode) } - // Error: Go back - if error != .success { - navigationController?.popViewController(animated: false) - } return (metadatas, error, reloadRequired) } @@ -375,11 +387,15 @@ class NCFiles: NCCollectionViewCommon { } } - func open(metadata: tableMetadata?) async { - guard let metadata else { - return + func openFile(fileName: String?) { + if let fileName = fileName, let metadata = database.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", session.account, self.serverUrl, fileName)) { + let indexPath = self.dataSource.getIndexPathMetadata(ocId: metadata.ocId) + if let indexPath = indexPath { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + self.collectionView(self.collectionView, didSelectItemAt: indexPath) + } + } } - await didSelectMetadata(metadata, withOcIds: false) } // MARK: - NCAccountSettingsModelDelegate @@ -411,3 +427,4 @@ class NCFiles: NCCollectionViewCommon { } } } + diff --git a/iOSClient/Main/Collection Common/Cell/NCCellMain.swift b/iOSClient/Main/Collection Common/Cell/NCCellMain.swift deleted file mode 100644 index 71b9ec76c6..0000000000 --- a/iOSClient/Main/Collection Common/Cell/NCCellMain.swift +++ /dev/null @@ -1,202 +0,0 @@ -// SPDX-FileCopyrightText: Nextcloud GmbH -// SPDX-FileCopyrightText: 2020 Marino Faggiana -// SPDX-License-Identifier: GPL-3.0-or-later - -import Foundation -import UIKit -import NextcloudKit -import RealmSwift - -protocol NCCellMainProtocol { - var metadata: tableMetadata? {get set } - var previewImg: UIImageView? { get set } - var localImg: UIImageView? { get set } - var statusImg: UIImageView? { get set } - var infoLbl: UILabel? { get set } - - func selected(_ status: Bool, isEditMode: Bool, color: UIColor) -} - -extension NCCellMainProtocol { - var metadata: tableMetadata? { - get { return nil } - set {} - } - var previewImg: UIImageView? { - get { return nil } - set {} - } - var localImg: UIImageView? { - get { return nil } - set {} - } - var statusImg: UIImageView? { - get { return nil } - set {} - } - var infoLbl: UILabel? { - get { return nil } - set {} - } -} - -#if !EXTENSION -extension NCCollectionViewCommon { - func cellMainStatus(cell: NCCellMainProtocol, - metadata: tableMetadata, - a11yValues: inout [String]) { - if metadata.isLivePhoto { - cell.statusImg?.image = utility.loadImage(named: "livephoto", colors: [NCBrandColor.shared.iconImageColor]) - a11yValues.append(NSLocalizedString("_upload_mov_livephoto_", comment: "")) - } else if metadata.isVideo { - cell.statusImg?.image = utility.loadImage(named: "play.circle.fill", colors: [.systemBackgroundInverted, .systemGray5]) - } - - switch metadata.status { - case global.metadataStatusWaitCreateFolder: - cell.statusImg?.image = utility.loadImage(named: "arrow.triangle.2.circlepath", colors: NCBrandColor.shared.iconImageMultiColors) - cell.infoLbl?.text = NSLocalizedString("_status_wait_create_folder_", comment: "") - case global.metadataStatusWaitFavorite: - cell.statusImg?.image = utility.loadImage(named: "star.circle", colors: NCBrandColor.shared.iconImageMultiColors) - cell.infoLbl?.text = NSLocalizedString("_status_wait_favorite_", comment: "") - case global.metadataStatusWaitCopy: - cell.statusImg?.image = utility.loadImage(named: "c.circle", colors: NCBrandColor.shared.iconImageMultiColors) - cell.infoLbl?.text = NSLocalizedString("_status_wait_copy_", comment: "") - case global.metadataStatusWaitMove: - cell.statusImg?.image = utility.loadImage(named: "m.circle", colors: NCBrandColor.shared.iconImageMultiColors) - cell.infoLbl?.text = NSLocalizedString("_status_wait_move_", comment: "") - case global.metadataStatusWaitRename: - cell.statusImg?.image = utility.loadImage(named: "a.circle", colors: NCBrandColor.shared.iconImageMultiColors) - cell.infoLbl?.text = NSLocalizedString("_status_wait_rename_", comment: "") - case global.metadataStatusWaitDownload: - cell.statusImg?.image = utility.loadImage(named: "arrow.triangle.2.circlepath", colors: NCBrandColor.shared.iconImageMultiColors) - case global.metadataStatusDownloading: - cell.statusImg?.image = utility.loadImage(named: "arrowshape.down.circle", colors: NCBrandColor.shared.iconImageMultiColors) - case global.metadataStatusDownloadError, global.metadataStatusUploadError: - cell.statusImg?.image = utility.loadImage(named: "exclamationmark.circle", colors: NCBrandColor.shared.iconImageMultiColors) - default: - break - } - - } - func cellMainDirectory(cell: NCCellMainProtocol, - metadata: tableMetadata, - isShare: Bool, - isMounted: Bool) { - let tblDirectory = database.getTableDirectory(ocId: metadata.ocId) - - if metadata.e2eEncrypted { - cell.previewImg?.image = imageCache.getFolderEncrypted(account: metadata.account) - } else if isShare { - cell.previewImg?.image = imageCache.getFolderSharedWithMe(account: metadata.account) - } else if !metadata.shareType.isEmpty { - metadata.shareType.contains(NKShare.ShareType.publicLink.rawValue) ? - (cell.previewImg?.image = imageCache.getFolderPublic(account: metadata.account)) : - (cell.previewImg?.image = imageCache.getFolderSharedWithMe(account: metadata.account)) - } else if !metadata.shareType.isEmpty && metadata.shareType.contains(NKShare.ShareType.publicLink.rawValue) { - cell.previewImg?.image = imageCache.getFolderPublic(account: metadata.account) - } else if metadata.mountType == "group" { - cell.previewImg?.image = imageCache.getFolderGroup(account: metadata.account) - } else if isMounted { - cell.previewImg?.image = imageCache.getFolderExternal(account: metadata.account) - } else if metadata.fileName == autoUploadFileName && metadata.serverUrl == autoUploadDirectory { - cell.previewImg?.image = imageCache.getFolderAutomaticUpload(account: metadata.account) - } else { - cell.previewImg?.image = imageCache.getFolder(account: metadata.account) - } - - // Local image: offline - metadata.isOffline = tblDirectory?.offline ?? false - - if metadata.isOffline { - cell.localImg?.image = imageCache.getImageOfflineFlag(colors: [.systemBackground, .systemGreen]) - } - - // color folder - cell.previewImg?.image = cell.previewImg?.image?.colorizeFolder(metadata: metadata, tblDirectory: tblDirectory) - } - - func cellMainFile(cell: NCCellMainProtocol, - metadata: tableMetadata, - a11yValues: inout [String]) { - let tableLocalFile = database.getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) - - if metadata.hasPreviewBorder { - cell.previewImg?.layer.borderWidth = 0.2 - cell.previewImg?.layer.borderColor = UIColor.lightGray.cgColor - } - - if metadata.name == global.appName { - let ext = global.getSizeExtension(column: self.numberOfColumns) - if let image = NCImageCache.shared.getImageCache(ocId: metadata.ocId, etag: metadata.etag, ext: ext) { - cell.previewImg?.image = image - } else if let image = utility.getImage(ocId: metadata.ocId, etag: metadata.etag, ext: ext, userId: metadata.userId, urlBase: metadata.urlBase) { - cell.previewImg?.image = image - } - - if cell.previewImg?.image == nil { - if metadata.iconName.isEmpty { - cell.previewImg?.image = NCImageCache.shared.getImageFile() - } else { - cell.previewImg?.image = utility.loadImage(named: metadata.iconName, useTypeIconFile: true, account: metadata.account) - } - } - } else { - // APP NAME - UNIFIED SEARCH - switch metadata.iconName { - case let str where str.contains("contacts"): - cell.previewImg?.image = utility.loadImage(named: "person.crop.rectangle.stack", colors: [NCBrandColor.shared.iconImageColor]) - case let str where str.contains("conversation"): - cell.previewImg?.image = UIImage(named: "talk-template")!.image(color: NCBrandColor.shared.getElement(account: metadata.account)) - case let str where str.contains("calendar"): - cell.previewImg?.image = utility.loadImage(named: "calendar", colors: [NCBrandColor.shared.iconImageColor]) - case let str where str.contains("deck"): - cell.previewImg?.image = utility.loadImage(named: "square.stack.fill", colors: [NCBrandColor.shared.iconImageColor]) - case let str where str.contains("mail"): - cell.previewImg?.image = utility.loadImage(named: "mail", colors: [NCBrandColor.shared.iconImageColor]) - case let str where str.contains("talk"): - cell.previewImg?.image = UIImage(named: "talk-template")!.image(color: NCBrandColor.shared.getElement(account: metadata.account)) - case let str where str.contains("confirm"): - cell.previewImg?.image = utility.loadImage(named: "arrow.right", colors: [NCBrandColor.shared.iconImageColor]) - case let str where str.contains("pages"): - cell.previewImg?.image = utility.loadImage(named: "doc.richtext", colors: [NCBrandColor.shared.iconImageColor]) - default: - cell.previewImg?.image = utility.loadImage(named: "doc", colors: [NCBrandColor.shared.iconImageColor]) - } - if !metadata.iconUrl.isEmpty { - if let ownerId = getAvatarFromIconUrl(metadata: metadata) { - let fileName = NCSession.shared.getFileName(urlBase: metadata.urlBase, user: ownerId) - if let image = NCImageCache.shared.getImageCache(key: fileName) { - cell.previewImg?.image = image - } else { - self.database.getImageAvatarLoaded(fileName: fileName) { image, tblAvatar in - if let image { - cell.previewImg?.image = image - NCImageCache.shared.addImageCache(image: image, key: fileName) - } else { - cell.previewImg?.image = self.utility.loadUserImage(for: ownerId, displayName: nil, urlBase: metadata.urlBase) - } - - if !(tblAvatar?.loaded ?? false), - self.networking.downloadAvatarQueue.operations.filter({ ($0 as? NCOperationDownloadAvatar)?.fileName == fileName }).isEmpty { - self.networking.downloadAvatarQueue.addOperation(NCOperationDownloadAvatar(user: ownerId, fileName: fileName, account: metadata.account, view: self.collectionView, isPreviewImage: true)) - } - } - } - } - } - } - - // Local image: offline - metadata.isOffline = tableLocalFile?.offline ?? false - - if metadata.isOffline { - a11yValues.append(NSLocalizedString("_offline_", comment: "")) - cell.localImg?.image = imageCache.getImageOfflineFlag(colors: [.systemBackground, .systemGreen]) - } else if utilityFileSystem.fileProviderStorageExists(metadata) { - cell.localImg?.image = imageCache.getImageLocal(colors: [.systemBackground, .systemGreen]) - } - } - -} -#endif diff --git a/iOSClient/Main/Collection Common/Cell/NCCellProtocol.swift b/iOSClient/Main/Collection Common/Cell/NCCellProtocol.swift new file mode 100644 index 0000000000..99ca24292c --- /dev/null +++ b/iOSClient/Main/Collection Common/Cell/NCCellProtocol.swift @@ -0,0 +1,99 @@ +// SPDX-FileCopyrightText: Nextcloud GmbH +// SPDX-FileCopyrightText: 2020 Marino Faggiana +// SPDX-License-Identifier: GPL-3.0-or-later + +import UIKit + +protocol NCCellProtocol { + var metadata: tableMetadata? {get set } + + var avatarImageView: UIImageView? { get } + var previewImageView: UIImageView? { get set } + var title: UILabel? { get set } + var info: UILabel? { get set } + var subInfo: UILabel? { get set } + var statusImageView: UIImageView? { get set } + var localImageView: UIImageView? { get set } + var favoriteImageView: UIImageView? { get set } + var shareImageView: UIImageView? { get set } + var separatorView: UIView? { get set } + + func titleInfoTrailingFull() + func writeInfoDateSize(date: NSDate, size: Int64) + func setButtonMore(image: UIImage) + func hideImageItem(_ status: Bool) + func hideImageFavorite(_ status: Bool) + func hideImageStatus(_ status: Bool) + func hideImageLocal(_ status: Bool) + func hideLabelInfo(_ status: Bool) + func hideLabelSubinfo(_ status: Bool) + func hideButtonShare(_ status: Bool) + func hideButtonMore(_ status: Bool) + func selected(_ status: Bool, isEditMode: Bool) + func setAccessibility(label: String, value: String) + func setTags(tags: [String]) + func setIconOutlines() +} + +extension NCCellProtocol { + var avatarImageView: UIImageView? { + return nil + } + var metadata: tableMetadata? { + get { return nil } + set {} + } + var previewImageView: UIImageView? { + get { return nil } + set {} + } + var title: UILabel? { + get { return nil } + set {} + } + var info: UILabel? { + get { return nil } + set { } + } + var subInfo: UILabel? { + get { return nil } + set { } + } + var statusImageView: UIImageView? { + get { return nil } + set {} + } + var localImageView: UIImageView? { + get { return nil } + set {} + } + var favoriteImageView: UIImageView? { + get { return nil } + set {} + } + var shareImageView: UIImageView? { + get { return nil } + set {} + } + + var separatorView: UIView? { + get { return nil } + set {} + } + + func titleInfoTrailingFull() {} + func writeInfoDateSize(date: NSDate, size: Int64) {} + func setButtonMore(image: UIImage) {} + func hideImageItem(_ status: Bool) {} + func hideImageFavorite(_ status: Bool) {} + func hideImageStatus(_ status: Bool) {} + func hideImageLocal(_ status: Bool) {} + func hideLabelInfo(_ status: Bool) {} + func hideLabelSubinfo(_ status: Bool) {} + func hideButtonShare(_ status: Bool) {} + func hideButtonMore(_ 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 57831aa19b..781c103b8c 100644 --- a/iOSClient/Main/Collection Common/Cell/NCGridCell.swift +++ b/iOSClient/Main/Collection Common/Cell/NCGridCell.swift @@ -2,56 +2,61 @@ // SPDX-FileCopyrightText: 2018 Marino Faggiana // SPDX-License-Identifier: GPL-3.0-or-later -import Foundation import UIKit -import NextcloudKit -import RealmSwift protocol NCGridCellDelegate: AnyObject { func onMenuIntent(with metadata: tableMetadata?) - func openContextMenu(with metadata: tableMetadata?, button: UIButton, sender: Any) + func contextMenu(with metadata: tableMetadata?, button: UIButton, sender: Any) } -class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellMainProtocol { +class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProtocol { @IBOutlet weak var imageItem: UIImageView! @IBOutlet weak var imageSelect: UIImageView! @IBOutlet weak var imageStatus: UIImageView! @IBOutlet weak var imageFavorite: UIImageView! @IBOutlet weak var imageLocal: UIImageView! - @IBOutlet weak var labelTitle: UILabel! @IBOutlet weak var labelInfo: UILabel! @IBOutlet weak var labelSubinfo: UILabel! - @IBOutlet weak var labelExtension: UILabel! - @IBOutlet weak var buttonMore: UIButton! - @IBOutlet weak var imageVisualEffect: UIVisualEffectView! @IBOutlet weak var iconsStackView: UIStackView! weak var delegate: NCGridCellDelegate? - // Cell Protocol var metadata: tableMetadata? { didSet { - delegate?.openContextMenu(with: metadata, button: buttonMore, sender: self) /* preconfigure UIMenu with each metadata */ + delegate?.contextMenu(with: metadata, button: buttonMore, sender: self) /* preconfigure UIMenu with each metadata */ } } - var previewImg: UIImageView? { + + var previewImageView: UIImageView? { get { return imageItem } set { imageItem = newValue } } - var localImg: UIImageView? { - get { return imageLocal } - set { imageLocal = newValue } + var title: UILabel? { + get { return labelTitle } + set { labelTitle = newValue } } - var statusImg: UIImageView? { + var info: UILabel? { + get { return labelInfo } + set { labelInfo = newValue } + } + var subInfo: UILabel? { + get { return labelSubinfo } + set { labelSubinfo = newValue } + } + var statusImageView: UIImageView? { get { return imageStatus } set { imageStatus = newValue } } - var infoLbl: UILabel? { - get { return labelInfo } - set { labelInfo = newValue } + var localImageView: UIImageView? { + get { return imageLocal } + set { imageLocal = newValue } + } + var favoriteImageView: UIImageView? { + get { return imageFavorite } + set { imageFavorite = newValue } } override func awakeFromNib() { @@ -67,7 +72,6 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellMainP override func prepareForReuse() { super.prepareForReuse() - initCell() } @@ -80,66 +84,26 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellMainP imageItem.image = nil imageItem.layer.cornerRadius = 6 imageItem.layer.masksToBounds = true - + imageSelect.isHidden = true + imageSelect.image = NCImageCache.shared.getImageCheckedYes() imageStatus.image = nil imageFavorite.image = nil imageLocal.image = nil + labelTitle.text = "" + labelInfo.text = "" + labelSubinfo.text = "" + imageVisualEffect.layer.cornerRadius = 6 + imageVisualEffect.clipsToBounds = true + imageVisualEffect.alpha = 0.5 iconsStackView.addBlurBackground(style: .systemMaterial) iconsStackView.layer.cornerRadius = 8 iconsStackView.clipsToBounds = true - imageVisualEffect.isHidden = false - imageVisualEffect.effect = nil - imageVisualEffect.alpha = 0 - imageVisualEffect.isUserInteractionEnabled = false - imageVisualEffect.backgroundColor = UIColor.white.withAlphaComponent(0.2) - buttonMore.menu = nil buttonMore.showsMenuAsPrimaryAction = true - // Dynamic Type Font Configuration - // - // These labels use fonts generated by the custom UIFont helpers defined in - // the UIFont extension (e.g. `.callout()`, `.caption1()`). - // - // Those helpers wrap `UIFontMetrics` to provide Dynamic Type scaling while - // applying an upper bound to the maximum font size. This ensures: - // - // - The text respects the user's preferred accessibility size. - // - The UI layout remains stable and does not grow indefinitely. - // - // `adjustsFontForContentSizeCategory` is enabled to allow UIKit to - // automatically update the font when the user changes the Dynamic Type - // setting while the application is running. - // - // Without this flag, the label would keep the initially computed font size - // and would not react to content size category changes. - // - // In summary: - // - // UIFont helper: - // Defines how the font scales and its maximum size. - // - // adjustsFontForContentSizeCategory: - // Enables live updates when accessibility settings change. - // - labelTitle.text = "" - labelTitle.font = .callout() - labelTitle.adjustsFontForContentSizeCategory = true - - labelExtension.text = "" - labelExtension.isHidden = true - labelExtension.font = .callout() - labelExtension.adjustsFontForContentSizeCategory = true - - labelInfo.text = "" - labelInfo.font = .footnote() - labelInfo.adjustsFontForContentSizeCategory = true - - labelSubinfo.text = "" - labelSubinfo.font = .footnote() - labelSubinfo.adjustsFontForContentSizeCategory = true + contentView.bringSubviewToFront(buttonMore) } override func snapshotView(afterScreenUpdates afterUpdates: Bool) -> UIView? { @@ -158,21 +122,55 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellMainP buttonMore.setImage(image, for: .normal) } - func setButtonMore(_ status: Bool) { + func hideImageItem(_ status: Bool) { + imageItem.isHidden = status + } + + func hideImageFavorite(_ status: Bool) { + imageFavorite.isHidden = status + } + + func hideImageStatus(_ status: Bool) { + imageStatus.isHidden = status + } + + func hideImageLocal(_ status: Bool) { + imageLocal.isHidden = status + } + + func hideLabelInfo(_ status: Bool) { + labelInfo.isHidden = status + } + + func hideLabelSubinfo(_ status: Bool) { + labelSubinfo.isHidden = status + } + + func hideButtonMore(_ status: Bool) { buttonMore.isHidden = status } - func selected(_ status: Bool, isEditMode: Bool, color: UIColor) { + func selected(_ status: Bool, isEditMode: Bool) { + // E2EE - remove encrypt folder selection + if let metadata = NCManageDatabase.shared.getMetadataFromOcId(self.metadata?.ocId), metadata.e2eEncrypted { + imageSelect.isHidden = true + } else { + imageSelect.isHidden = isEditMode ? false : true + } if isEditMode { buttonMore.isHidden = true accessibilityCustomActions = nil } else { buttonMore.isHidden = false } - - imageVisualEffect.alpha = status ? 1 : 0 - imageSelect.alpha = status ? 1 : 0 - imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) + if status { + imageSelect.image = NCImageCache.shared.getImageCheckedYes() + imageVisualEffect.isHidden = false + } else { + imageSelect.image = NCImageCache.shared.getImageCheckedNo() + backgroundView = nil + imageVisualEffect.isHidden = true + } } func writeInfoDateSize(date: NSDate, size: Int64) { @@ -189,6 +187,14 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellMainP accessibilityLabel = label accessibilityValue = value } + + func setIconOutlines() { + if imageStatus.image != nil { + imageStatus.makeCircularBackground(withColor: .systemBackground) + } else { + imageStatus.backgroundColor = .clear + } + } } // MARK: - Grid Layout @@ -238,101 +244,3 @@ class NCGridLayout: UICollectionViewFlowLayout { return proposedContentOffset } } - -extension NCCollectionViewCommon { - func gridCell(cell: NCGridCell, indexPath: IndexPath, metadata: tableMetadata) -> NCGridCell { - var isShare = false - var isMounted = false - var a11yValues: [String] = [] - let existsImagePreview = utilityFileSystem.fileProviderStorageImageExists(metadata.ocId, etag: metadata.etag, userId: metadata.userId, urlBase: metadata.urlBase) - - // CONTENT MODE - cell.previewImg?.layer.borderWidth = 0 - - if existsImagePreview && layoutForView?.layout != global.layoutPhotoRatio { - cell.previewImg?.contentMode = .scaleAspectFill - } else { - cell.previewImg?.contentMode = .scaleAspectFit - } - - guard let metadata = self.dataSource.getMetadata(indexPath: indexPath) else { - return cell - } - - if metadataFolder != nil { - isShare = metadata.permissions.contains(NCMetadataPermissions.permissionShared) && !metadataFolder!.permissions.contains(NCMetadataPermissions.permissionShared) - isMounted = metadata.permissions.contains(NCMetadataPermissions.permissionMounted) && !metadataFolder!.permissions.contains(NCMetadataPermissions.permissionMounted) - } - - if !metadata.sessionError.isEmpty, metadata.status != global.metadataStatusNormal { - cell.labelSubinfo.isHidden = false - cell.labelInfo.text = metadata.sessionError - } else { - cell.labelSubinfo.isHidden = false - cell.writeInfoDateSize(date: metadata.date, size: metadata.size) - } - - cell.setBidiSafeFilename(metadata.fileNameView, isDirectory: metadata.directory, titleLabel: cell.labelTitle, extensionLabel: cell.labelExtension) - - if cell.labelExtension?.isHidden ?? true { - cell.labelTitle.numberOfLines = 2 - cell.labelTitle.lineBreakMode = .byWordWrapping - } else { - cell.labelTitle.numberOfLines = 1 - cell.labelTitle.lineBreakMode = .byTruncatingTail - } - - // Accessibility [shared] if metadata.ownerId != appDelegate.userId, appDelegate.account == metadata.account { - if metadata.ownerId != metadata.userId { - a11yValues.append(NSLocalizedString("_shared_with_you_by_", comment: "") + " " + metadata.ownerDisplayName) - } - - if metadata.directory { - cellMainDirectory(cell: cell, metadata: metadata, isShare: isShare, isMounted: isMounted) - } else { - cellMainFile(cell: cell, metadata: metadata, a11yValues: &a11yValues) - } - - // image Favorite - if metadata.favorite { - cell.imageFavorite.image = imageCache.getImageFavorite() - a11yValues.append(NSLocalizedString("_favorite_short_", comment: "")) - } - - // Button More - if metadata.lock == true { - cell.setButtonMore(image: imageCache.getImageButtonMoreLock()) - a11yValues.append(String(format: NSLocalizedString("_locked_by_", comment: ""), metadata.lockOwnerDisplayName)) - } else { - cell.setButtonMore(image: imageCache.getImageButtonMore()) - } - - // Status - cellMainStatus(cell: cell, metadata: metadata, a11yValues: &a11yValues) - - // URL - if metadata.classFile == NKTypeClassFile.url.rawValue { - cell.imageLocal.image = nil - } - - // Edit mode - if fileSelect.contains(metadata.ocId) { - cell.selected(true, isEditMode: isEditMode, color: NCBrandColor.shared.getElement(account: session.account)) - a11yValues.append(NSLocalizedString("_selected_", comment: "")) - } else { - cell.selected(false, isEditMode: isEditMode, color: NCBrandColor.shared.getElement(account: session.account)) - } - - // Accessibility - cell.setAccessibility(label: metadata.fileNameView + ", " + (cell.labelInfo.text ?? "") + (cell.labelSubinfo.text ?? ""), value: a11yValues.joined(separator: ", ")) - - // Color string find in search - cell.labelTitle.textColor = NCBrandColor.shared.textColor - cell.labelExtension?.textColor = NCBrandColor.shared.textColor - - // Obligatory here, at the end !! - cell.metadata = metadata - - return cell - } -} diff --git a/iOSClient/Main/Collection Common/Cell/NCGridCell.xib b/iOSClient/Main/Collection Common/Cell/NCGridCell.xib index 7cb8863c41..b5cacdc258 100644 --- a/iOSClient/Main/Collection Common/Cell/NCGridCell.xib +++ b/iOSClient/Main/Collection Common/Cell/NCGridCell.xib @@ -1,8 +1,8 @@ - + - + @@ -20,37 +20,58 @@ + + + + + + + + - + - -