diff --git a/iOSClient/Files/NCFiles.swift b/iOSClient/Files/NCFiles.swift index def75aab30..a5d7d6a7fa 100644 --- a/iOSClient/Files/NCFiles.swift +++ b/iOSClient/Files/NCFiles.swift @@ -34,7 +34,7 @@ class NCFiles: NCCollectionViewCommon { let account = userInfo["account"] as? String, self.controller?.account == account { // re-tint the + button - self.mainNavigationController?.menuPlusButton.setPlusButtonColor(NCBrandColor.shared.getElement(account: account)) + self.mainNavigationController?.menuPlus?.updatePlusButtonEnabled(session: NCSession.shared.getSession(account: account)) } } } @@ -64,7 +64,7 @@ class NCFiles: NCCollectionViewCommon { if let userInfo = notification.userInfo, let account = userInfo["account"] as? String { // re-tint the + button for the new account - self.mainNavigationController?.menuPlusButton.setPlusButtonColor(NCBrandColor.shared.getElement(account: account)) + self.mainNavigationController?.menuPlus?.updatePlusButtonEnabled(session: NCSession.shared.getSession(account: account)) } self.navigationController?.popToRootViewController(animated: false) @@ -139,13 +139,8 @@ class NCFiles: NCCollectionViewCommon { if let metadataFolder { nkLog(info: "Inside metadata folder \(metadataFolder.fileName) with permissions: \(metadataFolder.permissions)") - // disable + button if no create permission - let color = NCBrandColor.shared.getElement(account: self.session.account) - - if let menuPlusButton = self.mainNavigationController?.menuPlusButton { - menuPlusButton.isEnabled = metadataFolder.isCreatable - menuPlusButton.setPlusButtonColor(metadataFolder.isCreatable ? color : .lightGray) - } + // disable + button if no create permission or E2EE offline + self.mainNavigationController?.menuPlus?.updatePlusButtonEnabled(session: self.session) } let metadatas = await self.database.getMetadatasAsyncDataSource(withServerUrl: self.serverUrl, diff --git a/iOSClient/Main/Collection Common/NCCollectionViewCommon+CollectionViewDataSource.swift b/iOSClient/Main/Collection Common/NCCollectionViewCommon+CollectionViewDataSource.swift index 15a7c7e460..12aa777f1e 100644 --- a/iOSClient/Main/Collection Common/NCCollectionViewCommon+CollectionViewDataSource.swift +++ b/iOSClient/Main/Collection Common/NCCollectionViewCommon+CollectionViewDataSource.swift @@ -20,9 +20,9 @@ extension NCCollectionViewCommon: UICollectionViewDataSource { self.layoutForView = self.database.getLayoutForView(account: session.account, key: layoutKey, serverUrl: serverUrl) // is a Directory E2EE if isSearchingMode { - self.isDirectoryE2EE = false + self.isCurrentDirectoryE2EE = false } else { - self.isDirectoryE2EE = NCUtilityFileSystem().isDirectoryE2EE(serverUrl: serverUrl, urlBase: session.urlBase, userId: session.userId, account: session.account) + self.isCurrentDirectoryE2EE = NCUtilityFileSystem().isDirectoryE2EE(serverUrl: serverUrl, urlBase: session.urlBase, userId: session.userId, account: session.account) } return self.dataSource.numberOfItemsInSection(section) } @@ -119,7 +119,7 @@ extension NCCollectionViewCommon: UICollectionViewDataSource { let metadata = self.dataSource.getMetadata(indexPath: indexPath) ?? tableMetadata() // E2EE create preview - if self.isDirectoryE2EE, + if self.isCurrentDirectoryE2EE, metadata.isImageOrVideo, !utilityFileSystem.fileProviderStorageImageExists(metadata.ocId, etag: metadata.etag, userId: metadata.userId, urlBase: metadata.urlBase) { utility.createImageFileFrom(metadata: metadata) diff --git a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift index ce7856060d..89cd190bde 100644 --- a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift +++ b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift @@ -31,7 +31,8 @@ class NCCollectionViewCommon: UIViewController, NCAccountSettingsModelDelegate, internal var backgroundImageView = UIImageView() internal var serverUrl: String = "" internal var isEditMode = false - internal var isDirectoryE2EE = false + // whether the displayed folder is E2EE; refreshed on each collection view data-source pass + internal var isCurrentDirectoryE2EE = false internal var fileSelect: [String] = [] internal var metadataFolder: tableMetadata? internal var richWorkspaceText: String? diff --git a/iOSClient/Main/NCMainNavigationController.swift b/iOSClient/Main/NCMainNavigationController.swift index e4b9979b6a..1256b5312c 100644 --- a/iOSClient/Main/NCMainNavigationController.swift +++ b/iOSClient/Main/NCMainNavigationController.swift @@ -12,7 +12,7 @@ class NCMainNavigationController: UINavigationController, UINavigationController let utility = NCUtility() let utilityFileSystem = NCUtilityFileSystem() let appDelegate = (UIApplication.shared.delegate as? AppDelegate)! - let menuPlusButton = UIButton(type: .system) + let menuPlusButton: UIButton = NCMenuPlusButton(type: .system) var controller: NCMainTabBarController? { self.tabBarController as? NCMainTabBarController @@ -451,6 +451,27 @@ class NCMainNavigationController: UINavigationController, UINavigationController } } +private final class NCMenuPlusButton: UIButton { + // Keep hit testing so taps don't fall through if the button is disabled, hidden or low alpha. + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if let view = super.hitTest(point, with: event) { + return view + } + + guard !isEnabled, !isHidden, alpha >= 0.01, bounds.contains(point) else { + return nil + } + + return self + } + + override func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? { + guard isEnabled else { return nil } + + return super.contextMenuInteraction(interaction, configurationForMenuAtLocation: location) + } +} + extension UIButton { func setPlusButtonColor(_ color: UIColor) { if #available(iOS 26.0, *) { diff --git a/iOSClient/Menu/NCContextMenuPlus.swift b/iOSClient/Menu/NCContextMenuPlus.swift index 094f644a4f..e175e29dcd 100644 --- a/iOSClient/Menu/NCContextMenuPlus.swift +++ b/iOSClient/Menu/NCContextMenuPlus.swift @@ -427,6 +427,8 @@ class NCContextMenuPlus: NSObject { let plusMenu = UIMenu(children: plusMenuElements) // PLUS BUTTON + updatePlusButtonEnabled(session: session) + if menuPlusButton.menu != nil, !capabilitiesChanged { return @@ -434,11 +436,34 @@ class NCContextMenuPlus: NSObject { menuPlusButton.menu = plusMenu menuPlusButton.showsMenuAsPrimaryAction = true - menuPlusButton.setPlusButtonColor(NCBrandColor.shared.getElement(account: session.account)) menuPlusButton.alpha = 1 + } + + func updatePlusButtonEnabled(session: NCSession.Session) { + guard let controller, let menuPlusButton else { + return + } + + let isEnabled = isPlusButtonEnabled(for: controller) + + menuPlusButton.isEnabled = isEnabled + menuPlusButton.setPlusButtonColor(isEnabled ? NCBrandColor.shared.getElement(account: session.account) : .lightGray) + } + + private func isPlusButtonEnabled(for controller: NCMainTabBarController) -> Bool { + guard let metadataFolder = (controller.currentViewController() as? NCCollectionViewCommon)?.metadataFolder else { + return true + } + + guard metadataFolder.isCreatable else { + return false + } + + guard metadataFolder.e2eEncrypted else { + return true + } - // E2EE Offline disable - menuPlusButton.isEnabled = isNetworkReachable || !isDirectoryE2EE + return NextcloudKit.shared.isNetworkReachable() } @MainActor