diff --git a/iOSClient/Main/Collection Common/NCSelectableNavigationView.swift b/iOSClient/Main/Collection Common/NCSelectableNavigationView.swift new file mode 100644 index 0000000000..6f337e7f5a --- /dev/null +++ b/iOSClient/Main/Collection Common/NCSelectableNavigationView.swift @@ -0,0 +1,104 @@ +// +// NCSelectableNavigationView.swift +// Nextcloud +// +// Created by Henrik Storch on 27.01.22. +// Copyright © 2022 Henrik Storch. All rights reserved. +// +// Author Marino Faggiana +// Author Henrik Storch +// +// 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 NextcloudKit +import Realm +import UIKit + +extension RealmSwiftObject { + var primaryKeyValue: String? { + guard let primaryKeyName = self.objectSchema.primaryKeyProperty?.name else { return nil } + return value(forKey: primaryKeyName) as? String + } +} + +public protocol NCSelectableViewTabBar { + var tabBarController: UITabBarController? { get } + var hostingController: UIViewController? { get } +} + +protocol NCSelectableNavigationView: AnyObject { + var viewController: UIViewController { get } + var appDelegate: AppDelegate { get } + var selectableDataSource: [RealmSwiftObject] { get } + var collectionView: UICollectionView! { get set } + var isEditMode: Bool { get set } + var selectOcId: [String] { get set } + var selectIndexPaths: [IndexPath] { get set } + var titleCurrentFolder: String { get } + var navigationItem: UINavigationItem { get } + var navigationController: UINavigationController? { get } + var layoutKey: String { get } + var serverUrl: String { get } + var tabBarSelect: NCSelectableViewTabBar? { get set } + + func reloadDataSource(withQueryDB: Bool) + func setNavigationLeftItems() + func setNavigationRightItems(enableMenu: Bool) + func createMenuActions() -> [NCMenuAction] + + func toggleSelect(isOn: Bool?) + func onListSelected() + func onGridSelected() +} + +extension NCSelectableNavigationView { + func setNavigationLeftItems() {} + + func saveLayout(_ layoutForView: NCDBLayoutForView) { + NCManageDatabase.shared.setLayoutForView(layoutForView: layoutForView) + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource) + setNavigationRightItems(enableMenu: false) + } + + /// If explicit `isOn` is not set, it will invert `isEditMode` + func toggleSelect(isOn: Bool? = nil) { + DispatchQueue.main.async { + self.isEditMode = isOn ?? !self.isEditMode + self.selectOcId.removeAll() + self.selectIndexPaths.removeAll() + self.setNavigationLeftItems() + self.setNavigationRightItems(enableMenu: true) + self.collectionView.reloadData() + } + } + + func collectionViewSelectAll() { + selectOcId = selectableDataSource.compactMap({ $0.primaryKeyValue }) + collectionView.reloadData() + setNavigationRightItems(enableMenu: false) + } + + func tapNotification() { + if let viewController = UIStoryboard(name: "NCNotification", bundle: nil).instantiateInitialViewController() as? NCNotification { + navigationController?.pushViewController(viewController, animated: true) + } + } +} + +extension NCSelectableNavigationView where Self: UIViewController { + var viewController: UIViewController { + self + } +} diff --git a/iOSClient/Menu/AppDelegate+Menu.swift b/iOSClient/Menu/AppDelegate+Menu.swift index 670b7da381..4567756815 100644 --- a/iOSClient/Menu/AppDelegate+Menu.swift +++ b/iOSClient/Menu/AppDelegate+Menu.swift @@ -39,7 +39,7 @@ extension AppDelegate { actions.append( NCMenuAction( - title: NSLocalizedString("_upload_photos_videos_", comment: ""), icon: UIImage(named: "file_photo")!.image(color: UIColor.systemGray, size: 50), action: { _ in + title: NSLocalizedString("_upload_photos_videos_", comment: ""), icon: UIImage(named: "file_photo_menu")!.image(color: NCBrandColor.shared.iconColor, size: 50), action: { _ in NCAskAuthorization().askAuthorizationPhotoLibrary(viewController: viewController) { hasPermission in if hasPermission {NCPhotosPickerViewController(viewController: viewController, maxSelectedAssets: 0, singleSelectedMode: false) } @@ -50,7 +50,7 @@ extension AppDelegate { actions.append( NCMenuAction( - title: NSLocalizedString("_upload_file_", comment: ""), icon: UIImage(named: "file")!.image(color: UIColor.systemGray, size: 50), action: { _ in + title: NSLocalizedString("_upload_file_", comment: ""), icon: UIImage(named: "uploadFile")!.image(color: NCBrandColor.shared.iconColor, size: 50), action: { _ in if let tabBarController = self.window?.rootViewController as? UITabBarController { self.documentPickerViewController = NCDocumentPickerViewController(tabBarController: tabBarController, isViewerMedia: false, allowsMultipleSelection: true) } @@ -60,14 +60,20 @@ extension AppDelegate { if NextcloudKit.shared.isNetworkReachable() && directEditingCreators != nil && directEditingCreators!.contains(where: { $0.editor == NCGlobal.shared.editorText}) && !isDirectoryE2EE { actions.append( - NCMenuAction(title: NSLocalizedString("_create_nextcloudtext_document_", comment: ""), icon: UIImage(named: "file_txt")!.image(color: UIColor.systemGray, size: 50), action: { _ in + NCMenuAction(title: NSLocalizedString("_create_nextcloudtext_document_", comment: ""), icon: UIImage(named: "file_txt_menu")!.image(color: NCBrandColor.shared.iconColor, size: 50), action: { _ in let directEditingCreator = directEditingCreators!.first(where: { $0.editor == NCGlobal.shared.editorText})! - - Task { - let fileName = await NCNetworking.shared.createFileName(fileNameBase: NSLocalizedString("_untitled_", comment: "") + ".md", account: appDelegate.account, serverUrl: self.activeServerUrl) - - let fileNamePath = NCUtilityFileSystem().getFileNamePath(String(describing: fileName), serverUrl: appDelegate.activeServerUrl, urlBase: appDelegate.urlBase, userId: appDelegate.userId) - self.createTextDocument(fileNamePath: fileNamePath, fileName: String(describing: fileName), creatorId: directEditingCreator.identifier) + guard let navigationController = UIStoryboard(name: "NCCreateFormUploadDocuments", bundle: nil).instantiateInitialViewController() else { + return + } + navigationController.modalPresentationStyle = UIModalPresentationStyle.formSheet + if let viewController = (navigationController as? UINavigationController)?.topViewController as? NCCreateFormUploadDocuments { + viewController.editorId = NCGlobal.shared.editorText + viewController.creatorId = directEditingCreator.identifier + viewController.typeTemplate = NCGlobal.shared.editorText + viewController.serverUrl = appDelegate.activeServerUrl + viewController.titleForm = NSLocalizedString("_create_nextcloudtext_document_", comment: "") + + appDelegate.window?.rootViewController?.present(navigationController, animated: true, completion: nil) } }) ) @@ -75,7 +81,7 @@ extension AppDelegate { actions.append( NCMenuAction( - title: NSLocalizedString("_scans_document_", comment: ""), icon: NCUtility().loadImage(named: "doc.text.viewfinder"), action: { _ in + title: NSLocalizedString("_scans_document_", comment: ""), icon: NCUtility().loadImage(named: "scan").image(color: NCBrandColor.shared.iconColor, size: 50), action: { _ in if let viewController = appDelegate.window?.rootViewController { NCDocumentCamera.shared.openScannerDocument(viewController: viewController) } @@ -85,7 +91,7 @@ extension AppDelegate { actions.append( NCMenuAction( - title: NSLocalizedString("_create_voice_memo_", comment: ""), icon: UIImage(named: "microphone")!.image(color: UIColor.systemGray, size: 50), action: { _ in + title: NSLocalizedString("_create_voice_memo_", comment: ""), icon: UIImage(named: "microphoneMenu")!.image(color: NCBrandColor.shared.iconColor, size: 50), action: { _ in NCAskAuthorization().askAuthorizationAudioRecord(viewController: viewController) { hasPermission in if hasPermission { if let viewController = UIStoryboard(name: "NCAudioRecorderViewController", bundle: nil).instantiateInitialViewController() as? NCAudioRecorderViewController { @@ -103,11 +109,11 @@ extension AppDelegate { actions.append(.seperator(order: 0)) } - let titleCreateFolder = isDirectoryE2EE ? NSLocalizedString("_create_folder_e2ee_", comment: "") : NSLocalizedString("_create_folder_", comment: "") - let imageCreateFolder = isDirectoryE2EE ? UIImage(named: "folderEncrypted")! : UIImage(named: "folder")! + let titleCreateFolder = NSLocalizedString("_create_folder_", comment: "") + let imageCreateFolder = UIImage(named: "addFolder")! actions.append( NCMenuAction(title: titleCreateFolder, - icon: imageCreateFolder.image(color: NCBrandColor.shared.brandElement, size: 50), action: { _ in + icon: imageCreateFolder, action: { _ in guard !appDelegate.activeServerUrl.isEmpty else { return } let alertController = UIAlertController.createFolder(serverUrl: appDelegate.activeServerUrl, urlBase: appDelegate) appDelegate.window?.rootViewController?.present(alertController, animated: true, completion: nil) @@ -115,11 +121,11 @@ extension AppDelegate { ) ) - // Folder encrypted - if !isDirectoryE2EE && NCKeychain().isEndToEndEnabled(account: appDelegate.account) { + // Folder encrypted (ONLY ROOT) + if !isDirectoryE2EE && NCKeychain().isEndToEndEnabled(account: appDelegate.account) && (NCUtilityFileSystem().getHomeServer(urlBase: appDelegate.urlBase, userId: appDelegate.userId) == appDelegate.activeServerUrl) { actions.append( NCMenuAction(title: NSLocalizedString("_create_folder_e2ee_", comment: ""), - icon: UIImage(named: "folderEncrypted")!.image(color: NCBrandColor.shared.brandElement, size: 50), + icon: UIImage(named: "encryptedfolder")!.image(color: NCBrandColor.shared.iconColor, size: 50), action: { _ in guard !appDelegate.activeServerUrl.isEmpty else { return } let alertController = UIAlertController.createFolder(serverUrl: appDelegate.activeServerUrl, urlBase: appDelegate, markE2ee: true) @@ -135,7 +141,7 @@ extension AppDelegate { if NCGlobal.shared.capabilityServerVersionMajor >= NCGlobal.shared.nextcloudVersion18 && directory?.richWorkspace == nil && !isDirectoryE2EE && NextcloudKit.shared.isNetworkReachable() { actions.append( NCMenuAction( - title: NSLocalizedString("_add_folder_info_", comment: ""), icon: UIImage(named: "addFolderInfo")!.image(color: UIColor.systemGray, size: 50), action: { _ in + title: NSLocalizedString("_add_folder_info_", comment: ""), icon: UIImage(named: "addFolderInfo")!.image(color: NCBrandColor.shared.iconColor, size: 50), action: { _ in let richWorkspaceCommon = NCRichWorkspaceCommon() if let viewController = self.activeViewController { if NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileNameView LIKE[c] %@", appDelegate.account, appDelegate.activeServerUrl, NCGlobal.shared.fileNameRichWorkspace.lowercased())) == nil { diff --git a/iOSClient/Menu/NCCollectionViewCommon+Menu.swift b/iOSClient/Menu/NCCollectionViewCommon+Menu.swift index fac9bd290a..66b4997f4a 100644 --- a/iOSClient/Menu/NCCollectionViewCommon+Menu.swift +++ b/iOSClient/Menu/NCCollectionViewCommon+Menu.swift @@ -46,8 +46,6 @@ extension NCCollectionViewCommon { isOffline = localFile.offline } - let editors = utility.isDirectEditing(account: metadata.account, contentType: metadata.contentType) - let isRichDocument = utility.isRichDocument(metadata) let applicationHandle = NCApplicationHandle() var iconHeader: UIImage! @@ -72,24 +70,6 @@ extension NCCollectionViewCommon { ) ) - actions.append(.seperator(order: 1)) - - // - // DETAILS - // - if !appDelegate.disableSharesView { - actions.append( - NCMenuAction( - title: NSLocalizedString("_details_", comment: ""), - icon: utility.loadImage(named: "info.circle"), - order: 10, - action: { _ in - NCActionCenter.shared.openShare(viewController: self, metadata: metadata, page: .activity) - } - ) - ) - } - if metadata.lock { var lockOwnerName = metadata.lockOwnerDisplayName.isEmpty ? metadata.lockOwner : metadata.lockOwnerDisplayName var lockIcon = utility.loadUserImage(for: metadata.lockOwner, displayName: lockOwnerName, userBaseUrl: metadata) @@ -130,7 +110,7 @@ extension NCCollectionViewCommon { actions.append( NCMenuAction( title: NSLocalizedString("_view_in_folder_", comment: ""), - icon: utility.loadImage(named: "questionmark.folder"), + icon: utility.loadImage(named: "arrow.forward.square", color: NCBrandColor.shared.iconColor), order: 21, action: { _ in NCActionCenter.shared.openFileViewInFolder(serverUrl: metadata.serverUrl, fileNameBlink: metadata.fileName, fileNameOpen: nil) @@ -149,11 +129,11 @@ extension NCCollectionViewCommon { // // SET FOLDER E2EE // - if metadata.canSetDirectoryAsE2EE { + if metadata.canSetDirectoryAsE2EE && (NCUtilityFileSystem().getHomeServer(urlBase: appDelegate.urlBase, userId: appDelegate.userId) == appDelegate.activeServerUrl) { actions.append( NCMenuAction( title: NSLocalizedString("_e2e_set_folder_encrypted_", comment: ""), - icon: utility.loadImage(named: "lock"), + icon: utility.loadImage(named: "lock", color: NCBrandColor.shared.iconColor), order: 30, action: { _ in Task { @@ -174,7 +154,7 @@ extension NCCollectionViewCommon { actions.append( NCMenuAction( title: NSLocalizedString("_e2e_remove_folder_encrypted_", comment: ""), - icon: utility.loadImage(named: "lock"), + icon: utility.loadImage(named: "lock", color: NCBrandColor.shared.iconColor), order: 30, action: { _ in NextcloudKit.shared.markE2EEFolder(fileId: metadata.fileId, delete: true) { _, error in @@ -197,11 +177,11 @@ extension NCCollectionViewCommon { // FAVORITE // FIXME: PROPPATCH doesn't work // https://github.com/nextcloud/files_lock/issues/68 - if !metadata.lock { + if !metadata.lock, !metadata.isDirectoryE2EE, !metadata.e2eEncrypted { actions.append( NCMenuAction( title: metadata.favorite ? NSLocalizedString("_remove_favorites_", comment: "") : NSLocalizedString("_add_favorites_", comment: ""), - icon: utility.loadImage(named: metadata.favorite ? "star.slash.fill" : "star.fill", color: NCBrandColor.shared.yellowFavorite), + icon: utility.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite), order: 50, action: { _ in NCNetworking.shared.favoriteMetadata(metadata) { error in @@ -224,89 +204,41 @@ extension NCCollectionViewCommon { } // - // OPEN with external editor + // OPEN IN // - if metadata.canOpenExternalEditor { - - var editor = "" - var title = "" - var icon: UIImage? - - if editors.contains(NCGlobal.shared.editorOnlyoffice) { - editor = NCGlobal.shared.editorOnlyoffice - title = NSLocalizedString("_open_in_onlyoffice_", comment: "") - icon = utility.loadImage(named: "onlyoffice") - } else if isRichDocument { - editor = NCGlobal.shared.editorCollabora - title = NSLocalizedString("_open_in_collabora_", comment: "") - icon = utility.loadImage(named: "collabora") - } - - if !editor.isEmpty { - actions.append( - NCMenuAction( - title: title, - icon: icon!, - order: 70, - action: { _ in - NCViewer().view(viewController: self, metadata: metadata, metadatas: [metadata], imageIcon: imageIcon, editor: editor, isRichDocument: isRichDocument) - } - ) - ) - } + if metadata.canShare { + actions.append(.share(selectedMetadatas: [metadata], viewController: self, order: 80)) } - + // - // SHARE + // PRINT // - if metadata.canShare { - actions.append(.share(selectedMetadatas: [metadata], viewController: self, order: 80)) + if metadata.isPrintable { + actions.append(.printAction(metadata: metadata, order: 90)) } - + // - // SAVE LIVE PHOTO + // SAVE CAMERA ROLL // - if let metadataMOV = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) { - actions.append( - NCMenuAction( - title: NSLocalizedString("_livephoto_save_", comment: ""), - icon: NCUtility().loadImage(named: "livephoto"), - order: 100, - action: { _ in - NCNetworking.shared.saveLivePhotoQueue.addOperation(NCOperationSaveLivePhoto(metadata: metadata, metadataMOV: metadataMOV)) - } - ) - ) + if metadata.isSavebleInCameraRoll { + actions.append(.saveMediaAction(selectedMediaMetadatas: [metadata], order: 100)) } // - // SAVE AS SCAN + // SAVE LIVE PHOTO // - if metadata.isSavebleAsImage { - actions.append( - NCMenuAction( - title: NSLocalizedString("_save_as_scan_", comment: ""), - icon: utility.loadImage(named: "doc.viewfinder"), - order: 110, - action: { _ in - if self.utilityFileSystem.fileProviderStorageExists(metadata) { - NotificationCenter.default.post( - name: Notification.Name(rawValue: NCGlobal.shared.notificationCenterDownloadedFile), - object: nil, - userInfo: ["ocId": metadata.ocId, - "selector": NCGlobal.shared.selectorSaveAsScan, - "error": NKError(), - "account": metadata.account]) - } else { - guard let metadata = NCManageDatabase.shared.setMetadatasSessionInWaitDownload(metadatas: [metadata], - session: NextcloudKit.shared.nkCommonInstance.sessionIdentifierDownload, - selector: NCGlobal.shared.selectorSaveAsScan) else { return } - NCNetworking.shared.download(metadata: metadata, withNotificationProgressTask: true) - } - } - ) - ) - } +// if let metadataMOV = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) { +// actions.append( +// NCMenuAction( +// title: NSLocalizedString("_livephoto_save_", comment: ""), +// icon: NCUtility().loadImage(named: "livephoto"), +// order: 100, +// action: { _ in +// NCNetworking.shared.saveLivePhotoQueue.addOperation(NCOperationSaveLivePhoto(metadata: metadata, metadataMOV: metadataMOV)) +// } +// ) +// ) +// } // // RENAME @@ -315,7 +247,7 @@ extension NCCollectionViewCommon { actions.append( NCMenuAction( title: NSLocalizedString("_rename_", comment: ""), - icon: utility.loadImage(named: "text.cursor"), + icon: utility.loadImage(named: "rename", color: NCBrandColor.shared.iconColor), order: 120, action: { _ in @@ -341,6 +273,13 @@ extension NCCollectionViewCommon { actions.append(.moveOrCopyAction(selectedMetadatas: [metadata], indexPath: [indexPath], order: 130)) } + // + // COPY IN PASTEBOARD + // + if metadata.isCopyableInPasteboard, !metadata.isDirectoryE2EE { + actions.append(.copyAction(selectOcId: [metadata.ocId], order: 140)) + } + // // MODIFY WITH QUICK LOOK // @@ -348,7 +287,7 @@ extension NCCollectionViewCommon { actions.append( NCMenuAction( title: NSLocalizedString("_modify_", comment: ""), - icon: utility.loadImage(named: "pencil.tip.crop.circle"), + icon: utility.loadImage(named: "pencil.tip.crop.circle", color: NCBrandColor.shared.iconColor), order: 150, action: { _ in if self.utilityFileSystem.fileProviderStorageExists(metadata) { @@ -370,32 +309,11 @@ extension NCCollectionViewCommon { ) } - // - // COLOR FOLDER - // - if self is NCFiles, metadata.directory { - actions.append( - NCMenuAction( - title: NSLocalizedString("_change_color_", comment: ""), - icon: utility.loadImage(named: "paintpalette"), - order: 160, - action: { _ in - if let picker = UIStoryboard(name: "NCColorPicker", bundle: nil).instantiateInitialViewController() as? NCColorPicker { - picker.metadata = metadata - let popup = NCPopupViewController(contentController: picker, popupWidth: 200, popupHeight: 320) - popup.backgroundAlpha = 0 - self.present(popup, animated: true) - } - } - ) - ) - } - // // DELETE // if metadata.isDeletable { - actions.append(.deleteAction(selectedMetadatas: [metadata], indexPaths: [indexPath], metadataFolder: metadataFolder, viewController: self, order: 170)) + actions.append(.deleteAction(selectedMetadatas: [metadata], indexPath: [indexPath], metadataFolder: metadataFolder, viewController: self, order: 170)) } applicationHandle.addCollectionViewCommonMenu(metadata: metadata, imageIcon: imageIcon, actions: &actions) diff --git a/iOSClient/Menu/NCMenuAction.swift b/iOSClient/Menu/NCMenuAction.swift index 179a993c52..16429f9452 100644 --- a/iOSClient/Menu/NCMenuAction.swift +++ b/iOSClient/Menu/NCMenuAction.swift @@ -84,7 +84,7 @@ extension NCMenuAction { static func selectAllAction(action: @escaping () -> Void) -> NCMenuAction { NCMenuAction( title: NSLocalizedString("_select_all_", comment: ""), - icon: NCUtility().loadImage(named: "checkmark.circle.fill"), + icon: NCUtility().loadImage(named: "checkmark.circle.fill", color: NCBrandColor.shared.iconColor), action: { _ in action() } ) } @@ -93,32 +93,43 @@ extension NCMenuAction { static func cancelAction(action: @escaping () -> Void) -> NCMenuAction { NCMenuAction( title: NSLocalizedString("_cancel_", comment: ""), - icon: NCUtility().loadImage(named: "xmark"), + icon: NCUtility().loadImage(named: "xmark", color: NCBrandColor.shared.iconColor), action: { _ in action() } ) } + /// Copy files to pasteboard + static func copyAction(selectOcId: [String], order: Int = 0, completion: (() -> Void)? = nil) -> NCMenuAction { + NCMenuAction( + title: NSLocalizedString("_copy_file_", comment: ""), + icon: NCUtility().loadImage(named: "copy", color: NCBrandColor.shared.iconColor), + order: order, + action: { _ in + NCActionCenter.shared.copyPasteboard(pasteboardOcIds: selectOcId) + completion?() + } + ) + } + /// Delete files either from cache or from Nextcloud - static func deleteAction(selectedMetadatas: [tableMetadata], indexPaths: [IndexPath], metadataFolder: tableMetadata? = nil, viewController: UIViewController, order: Int = 0, completion: (() -> Void)? = nil) -> NCMenuAction { + static func deleteAction(selectedMetadatas: [tableMetadata], indexPath: [IndexPath], metadataFolder: tableMetadata? = nil, viewController: UIViewController, order: Int = 0, completion: (() -> Void)? = nil) -> NCMenuAction { var titleDelete = NSLocalizedString("_delete_", comment: "") - var message = NSLocalizedString("_want_delete_", comment: "") var icon = "trash" var destructive = false if selectedMetadatas.count > 1 { titleDelete = NSLocalizedString("_delete_selected_files_", comment: "") - destructive = true + destructive = false } else if let metadata = selectedMetadatas.first { if NCManageDatabase.shared.isMetadataShareOrMounted(metadata: metadata, metadataFolder: metadataFolder) { titleDelete = NSLocalizedString("_leave_share_", comment: "") - message = NSLocalizedString("_want_leave_share_", comment: "") icon = "person.2.slash" } else if metadata.directory { titleDelete = NSLocalizedString("_delete_folder_", comment: "") - destructive = true + destructive = false } else { titleDelete = NSLocalizedString("_delete_file_", comment: "") - destructive = true + destructive = false } if let metadataFolder = metadataFolder { @@ -141,22 +152,76 @@ extension NCMenuAction { return NCMenuAction( title: titleDelete, destructive: destructive, - icon: NCUtility().loadImage(named: icon), + icon: NCUtility().loadImage(named: "trash", color: NCBrandColor.shared.iconColor), order: order, action: { _ in - let alertController = UIAlertController.deleteFileOrFolder(titleString: titleDelete + "?", message: message + fileList, canDeleteServer: canDeleteServer, selectedMetadatas: selectedMetadatas) { _ in - completion?() + let alertController = UIAlertController( + title: titleDelete, + message: NSLocalizedString("_want_delete_", comment: "") + fileList, + preferredStyle: .alert) + if canDeleteServer { + alertController.addAction(UIAlertAction(title: NSLocalizedString("_yes_delete_", comment: ""), style: .default) { (_: UIAlertAction) in + Task { + var error = NKError() + var ocId: [String] = [] + for metadata in selectedMetadatas where error == .success { + NCActivityIndicator.shared.start() + error = await NCNetworking.shared.deleteMetadata(metadata, onlyLocalCache: false) + NCActivityIndicator.shared.stop() + if error == .success { + ocId.append(metadata.ocId) + } + } + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDeleteFile, userInfo: ["ocId": ocId, "indexPath": indexPath, "onlyLocalCache": false, "error": error]) + } + completion?() + }) } + // NCMedia removes image from collection view if removed from cache + if !(viewController is NCMedia) { + alertController.addAction(UIAlertAction(title: NSLocalizedString("_remove_local_file_", comment: ""), style: .default) { (_: UIAlertAction) in + Task { + var error = NKError() + var ocId: [String] = [] + for metadata in selectedMetadatas where error == .success { + error = await NCNetworking.shared.deleteMetadata(metadata, onlyLocalCache: true) + if error == .success { + ocId.append(metadata.ocId) + } + } + if error != .success { + NCContentPresenter().showError(error: error) + } + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDeleteFile, userInfo: ["ocId": ocId, "indexPath": indexPath, "onlyLocalCache": true, "error": error]) + } + completion?() + }) + } + alertController.addAction(UIAlertAction(title: NSLocalizedString("_no_delete_", comment: ""), style: .default) { (_: UIAlertAction) in }) viewController.present(alertController, animated: true, completion: nil) - }) + } + ) + } + + /// Open "share view" (activity VC) to open files in another app + static func openInAction(selectedMetadatas: [tableMetadata], viewController: UIViewController, order: Int = 0, completion: (() -> Void)? = nil) -> NCMenuAction { + NCMenuAction( + title: NSLocalizedString("_open_in_", comment: ""), + icon: NCUtility().loadImage(named: "open_file",color: NCBrandColor.shared.iconColor), + order: order, + action: { _ in + NCActionCenter.shared.openActivityViewController(selectedMetadata: selectedMetadatas) + completion?() + } + ) } /// Open "share view" (activity VC) to open files in another app static func share(selectedMetadatas: [tableMetadata], viewController: UIViewController, order: Int = 0, completion: (() -> Void)? = nil) -> NCMenuAction { NCMenuAction( - title: NSLocalizedString("_share_", comment: ""), - icon: NCUtility().loadImage(named: "square.and.arrow.up"), + title: NSLocalizedString("_open_in_", comment: ""), + icon: NCUtility().loadImage(named: "open_file",color: NCBrandColor.shared.iconColor), order: order, action: { _ in NCActionCenter.shared.openActivityViewController(selectedMetadata: selectedMetadatas) @@ -168,7 +233,7 @@ extension NCMenuAction { /// Save selected files to user's photo library static func saveMediaAction(selectedMediaMetadatas: [tableMetadata], order: Int = 0, completion: (() -> Void)? = nil) -> NCMenuAction { var title: String = NSLocalizedString("_save_selected_files_", comment: "") - var icon = NCUtility().loadImage(named: "square.and.arrow.down") + var icon = NCUtility().loadImage(named: "save_files",color: NCBrandColor.shared.iconColor) if selectedMediaMetadatas.allSatisfy({ NCManageDatabase.shared.getMetadataLivePhoto(metadata: $0) != nil }) { title = NSLocalizedString("_livephoto_save_", comment: "") icon = NCUtility().loadImage(named: "livephoto") @@ -201,7 +266,7 @@ extension NCMenuAction { static func setAvailableOfflineAction(selectedMetadatas: [tableMetadata], isAnyOffline: Bool, viewController: UIViewController, order: Int = 0, completion: (() -> Void)? = nil) -> NCMenuAction { NCMenuAction( title: isAnyOffline ? NSLocalizedString("_remove_available_offline_", comment: "") : NSLocalizedString("_set_available_offline_", comment: ""), - icon: NCUtility().loadImage(named: "icloud.and.arrow.down"), + icon: NCUtility().loadImage(named: "offlineMenu", color: NCBrandColor.shared.iconColor), order: order, action: { _ in if !isAnyOffline, selectedMetadatas.count > 3 { @@ -225,16 +290,32 @@ extension NCMenuAction { /// Open view that lets the user move or copy the files within Nextcloud static func moveOrCopyAction(selectedMetadatas: [tableMetadata], indexPath: [IndexPath], order: Int = 0, completion: (() -> Void)? = nil) -> NCMenuAction { NCMenuAction( - title: NSLocalizedString("_move_or_copy_", comment: ""), - icon: NCUtility().loadImage(named: "rectangle.portrait.and.arrow.right"), + title: NSLocalizedString("_move_or_copy_selected_files_", comment: ""), + icon: NCUtility().loadImage(named: "move", color: NCBrandColor.shared.iconColor), order: order, action: { _ in - NCActionCenter.shared.openSelectView(items: selectedMetadatas) + NCActionCenter.shared.openSelectView(items: selectedMetadatas, indexPath: indexPath) completion?() } ) } + /// Open AirPrint view to print a single file + static func printAction(metadata: tableMetadata, order: Int = 0) -> NCMenuAction { + NCMenuAction( + title: NSLocalizedString("_print_", comment: ""), + icon: NCUtility().loadImage(named: "printer", color: NCBrandColor.shared.iconColor), + order: order, + action: { _ in + if NCUtilityFileSystem().fileProviderStorageExists(metadata) { + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadedFile, userInfo: ["ocId": metadata.ocId, "selector": NCGlobal.shared.selectorPrint, "error": NKError(), "account": metadata.account]) + } else { + NCNetworking.shared.downloadQueue.addOperation(NCOperationDownload(metadata: metadata, selector: NCGlobal.shared.selectorPrint)) + } + } + ) + } + /// Lock or unlock a file using *files_lock* static func lockUnlockFiles(shouldLock: Bool, metadatas: [tableMetadata], order: Int = 0, completion: (() -> Void)? = nil) -> NCMenuAction { let titleKey: String diff --git a/iOSClient/Menu/NCViewer+Menu.swift b/iOSClient/Menu/NCViewer+Menu.swift index 42ffdfa179..92b7bce473 100644 --- a/iOSClient/Menu/NCViewer+Menu.swift +++ b/iOSClient/Menu/NCViewer+Menu.swift @@ -58,7 +58,7 @@ extension NCViewer { actions.append( NCMenuAction( title: NSLocalizedString("_view_in_folder_", comment: ""), - icon: utility.loadImage(named: "questionmark.folder"), + icon: utility.loadImage(named: "arrow.forward.square", color: NCBrandColor.shared.iconColor), action: { _ in NCActionCenter.shared.openFileViewInFolder(serverUrl: metadata.serverUrl, fileNameBlink: metadata.fileName, fileNameOpen: nil) } @@ -70,7 +70,7 @@ extension NCViewer { // FAVORITE // Workaround: PROPPATCH doesn't work // https://github.com/nextcloud/files_lock/issues/68 - if !metadata.lock { + if !metadata.lock, !metadata.isDirectoryE2EE{ actions.append( NCMenuAction( title: metadata.favorite ? NSLocalizedString("_remove_favorites_", comment: "") : NSLocalizedString("_add_favorites_", comment: ""), @@ -106,8 +106,8 @@ extension NCViewer { if let metadataMOV = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) { actions.append( NCMenuAction( - title: NSLocalizedString("_livephoto_save_", comment: ""), - icon: NCUtility().loadImage(named: "livephoto"), + title: NSLocalizedString("_print_", comment: ""), + icon: utility.loadImage(named: "printer", color: NCBrandColor.shared.iconColor), action: { _ in NCNetworking.shared.saveLivePhotoQueue.addOperation(NCOperationSaveLivePhoto(metadata: metadata, metadataMOV: metadataMOV)) } @@ -146,11 +146,11 @@ extension NCViewer { // // RENAME // - if !webView, metadata.isRenameable { + if !webView, metadata.isRenameable, !metadata.isDirectoryE2EE { actions.append( NCMenuAction( title: NSLocalizedString("_rename_", comment: ""), - icon: utility.loadImage(named: "text.cursor"), + icon: utility.loadImage(named: "rename", color: NCBrandColor.shared.iconColor), action: { _ in if let vcRename = UIStoryboard(name: "NCRenameFile", bundle: nil).instantiateInitialViewController() as? NCRenameFile { @@ -176,6 +176,13 @@ extension NCViewer { actions.append(.moveOrCopyAction(selectedMetadatas: [metadata], indexPath: [])) } + // + // COPY IN PASTEBOARD + // + if !webView, metadata.isCopyableInPasteboard, !metadata.isDirectoryE2EE { + actions.append(.copyAction(selectOcId: [metadata.ocId])) + } + // // DOWNLOAD FULL RESOLUTION // @@ -201,7 +208,7 @@ extension NCViewer { actions.append( NCMenuAction( title: NSLocalizedString("_search_", comment: ""), - icon: UIImage(named: "search")!.image(color: UIColor.systemGray, size: 50), + icon: UIImage(named: "search")!.image(color: NCBrandColor.shared.iconColor, size: 50), action: { _ in NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterMenuSearchTextPDF) } @@ -211,7 +218,7 @@ extension NCViewer { actions.append( NCMenuAction( title: NSLocalizedString("_go_to_page_", comment: ""), - icon: utility.loadImage(named: "repeat"), + icon: utility.loadImage(named: "go-to-page", color: NCBrandColor.shared.iconColor), action: { _ in NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterMenuGotToPageInPDF) } @@ -226,7 +233,7 @@ extension NCViewer { actions.append( NCMenuAction( title: NSLocalizedString("_modify_", comment: ""), - icon: utility.loadImage(named: "pencil.tip.crop.circle"), + icon: utility.loadImage(named: "pencil.tip.crop.circle", color: NCBrandColor.shared.iconColor), action: { _ in if self.utilityFileSystem.fileProviderStorageExists(metadata) { NotificationCenter.default.post(