NCMenuAction.swift 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. //
  2. // NCMenuAction.swift
  3. // Nextcloud
  4. //
  5. // Created by Henrik Storch on 17.02.22.
  6. // Copyright © 2022 Marino Faggiana. All rights reserved.
  7. //
  8. import Foundation
  9. import UIKit
  10. class NCMenuAction {
  11. let title: String
  12. let details: String?
  13. let icon: UIImage
  14. let selectable: Bool
  15. var onTitle: String?
  16. var onIcon: UIImage?
  17. var selected: Bool = false
  18. var isOn: Bool = false
  19. var action: ((_ menuAction: NCMenuAction) -> Void)?
  20. var rowHeight: CGFloat { self.title == NCMenuAction.seperatorIdentifier ? 3 : self.details != nil ? 80 : 60 }
  21. init(title: String, details: String? = nil, icon: UIImage, action: ((_ menuAction: NCMenuAction) -> Void)?) {
  22. self.title = title
  23. self.details = details
  24. self.icon = icon
  25. self.action = action
  26. self.selectable = false
  27. }
  28. init(title: String, details: String? = nil, icon: UIImage, onTitle: String? = nil, onIcon: UIImage? = nil, selected: Bool, on: Bool, action: ((_ menuAction: NCMenuAction) -> Void)?) {
  29. self.title = title
  30. self.details = details
  31. self.icon = icon
  32. self.onTitle = onTitle ?? title
  33. self.onIcon = onIcon ?? icon
  34. self.action = action
  35. self.selected = selected
  36. self.isOn = on
  37. self.selectable = true
  38. }
  39. }
  40. // MARK: - Actions
  41. extension NCMenuAction {
  42. static let seperatorIdentifier = "NCMenuAction.SEPERATOR"
  43. /// A static seperator, with no actions, text, or icons
  44. static var seperator: NCMenuAction {
  45. return NCMenuAction(title: seperatorIdentifier, icon: UIImage(), action: nil)
  46. }
  47. /// Select all items
  48. static func selectAllAction(action: @escaping () -> Void) -> NCMenuAction {
  49. NCMenuAction(
  50. title: NSLocalizedString("_select_all_", comment: ""),
  51. icon: NCUtility.shared.loadImage(named: "checkmark.circle.fill"),
  52. action: { _ in action() }
  53. )
  54. }
  55. /// Copy files to pasteboard
  56. static func copyAction(selectOcId: [String], hudView: UIView, completion: (() -> Void)? = nil) -> NCMenuAction {
  57. NCMenuAction(
  58. title: NSLocalizedString("_copy_file_", comment: ""),
  59. icon: NCUtility.shared.loadImage(named: "doc.on.doc"),
  60. action: { _ in
  61. NCFunctionCenter.shared.copyPasteboard(pasteboardOcIds: selectOcId, hudView: hudView)
  62. completion?()
  63. }
  64. )
  65. }
  66. /// Delete files either from cache or from Nextcloud
  67. static func deleteAction(selectedMetadatas: [tableMetadata], metadataFolder: tableMetadata? = nil, viewController: UIViewController, completion: (() -> Void)? = nil) -> NCMenuAction {
  68. var titleDelete = NSLocalizedString("_delete_", comment: "")
  69. if selectedMetadatas.count > 1 {
  70. titleDelete = NSLocalizedString("_delete_selected_files_", comment: "")
  71. } else if let metadata = selectedMetadatas.first {
  72. if NCManageDatabase.shared.isMetadataShareOrMounted(metadata: metadata, metadataFolder: metadataFolder) {
  73. titleDelete = NSLocalizedString("_leave_share_", comment: "")
  74. } else if metadata.directory {
  75. titleDelete = NSLocalizedString("_delete_folder_", comment: "")
  76. } else {
  77. titleDelete = NSLocalizedString("_delete_file_", comment: "")
  78. }
  79. if let metadataFolder = metadataFolder {
  80. let isShare = metadata.permissions.contains(NCGlobal.shared.permissionShared) && !metadataFolder.permissions.contains(NCGlobal.shared.permissionShared)
  81. let isMounted = metadata.permissions.contains(NCGlobal.shared.permissionMounted) && !metadataFolder.permissions.contains(NCGlobal.shared.permissionMounted)
  82. if isShare || isMounted {
  83. titleDelete = NSLocalizedString("_leave_share_", comment: "")
  84. }
  85. }
  86. } // else: no metadata selected
  87. let canDeleteServer = selectedMetadatas.contains(
  88. where: { $0.canUnlock(as: (UIApplication.shared.delegate as? AppDelegate)?.userId ?? "") })
  89. var fileList = ""
  90. for (ix, metadata) in selectedMetadatas.enumerated() {
  91. guard ix < 3 else { fileList += "\n - ..."; break }
  92. fileList += "\n - " + metadata.fileName
  93. }
  94. return NCMenuAction(
  95. title: titleDelete,
  96. icon: NCUtility.shared.loadImage(named: "trash"),
  97. action: { _ in
  98. let alertController = UIAlertController(
  99. title: titleDelete,
  100. message: NSLocalizedString("_want_delete_", comment: "") + fileList,
  101. preferredStyle: .alert)
  102. if canDeleteServer {
  103. alertController.addAction(UIAlertAction(title: NSLocalizedString("_yes_delete_", comment: ""), style: .default) { (_: UIAlertAction) in
  104. selectedMetadatas.forEach({ NCOperationQueue.shared.delete(metadata: $0, onlyLocalCache: false) })
  105. completion?()
  106. })
  107. }
  108. // NCMedia removes image from collection view if removed from cache
  109. if !(viewController is NCMedia) {
  110. alertController.addAction(UIAlertAction(title: NSLocalizedString("_remove_local_file_", comment: ""), style: .default) { (_: UIAlertAction) in
  111. selectedMetadatas.forEach({ NCOperationQueue.shared.delete(metadata: $0, onlyLocalCache: true) })
  112. completion?()
  113. })
  114. }
  115. alertController.addAction(UIAlertAction(title: NSLocalizedString("_no_delete_", comment: ""), style: .default) { (_: UIAlertAction) in })
  116. viewController.present(alertController, animated: true, completion: nil)
  117. }
  118. )
  119. }
  120. /// Open "share view" (activity VC) to open files in another app
  121. static func openInAction(selectedMetadatas: [tableMetadata], viewController: UIViewController, completion: (() -> Void)? = nil) -> NCMenuAction {
  122. NCMenuAction(
  123. title: NSLocalizedString("_open_in_", comment: ""),
  124. icon: NCUtility.shared.loadImage(named: "square.and.arrow.up"),
  125. action: { _ in
  126. if viewController is NCFileViewInFolder {
  127. viewController.dismiss(animated: true) {
  128. NCFunctionCenter.shared.openActivityViewController(selectedMetadata: selectedMetadatas)
  129. }
  130. } else {
  131. NCFunctionCenter.shared.openActivityViewController(selectedMetadata: selectedMetadatas)
  132. }
  133. completion?()
  134. }
  135. )
  136. }
  137. /// Save selected files to user's photo library
  138. static func saveMediaAction(selectedMediaMetadatas: [tableMetadata], completion: (() -> Void)? = nil) -> NCMenuAction {
  139. var title: String = NSLocalizedString("_save_selected_files_", comment: "")
  140. var icon = NCUtility.shared.loadImage(named: "square.and.arrow.down")
  141. if selectedMediaMetadatas.allSatisfy({ NCManageDatabase.shared.getMetadataLivePhoto(metadata: $0) != nil }) {
  142. title = NSLocalizedString("_livephoto_save_", comment: "")
  143. icon = NCUtility.shared.loadImage(named: "livephoto")
  144. }
  145. return NCMenuAction(
  146. title: title,
  147. icon: icon,
  148. action: { _ in
  149. for metadata in selectedMediaMetadatas {
  150. if let metadataMOV = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) {
  151. NCFunctionCenter.shared.saveLivePhoto(metadata: metadata, metadataMOV: metadataMOV)
  152. } else {
  153. if CCUtility.fileProviderStorageExists(metadata) {
  154. NCFunctionCenter.shared.saveAlbum(metadata: metadata)
  155. } else {
  156. NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorSaveAlbum)
  157. }
  158. }
  159. }
  160. completion?()
  161. }
  162. )
  163. }
  164. /// Set (or remove) a file as *available offline*. Downloads the file if not downloaded already
  165. static func setAvailableOfflineAction(selectedMetadatas: [tableMetadata], isAnyOffline: Bool, viewController: UIViewController, completion: (() -> Void)? = nil) -> NCMenuAction {
  166. NCMenuAction(
  167. title: isAnyOffline ? NSLocalizedString("_remove_available_offline_", comment: "") : NSLocalizedString("_set_available_offline_", comment: ""),
  168. icon: NCUtility.shared.loadImage(named: "tray.and.arrow.down"),
  169. action: { _ in
  170. if !isAnyOffline, selectedMetadatas.count > 3 {
  171. let alert = UIAlertController(
  172. title: NSLocalizedString("_set_available_offline_", comment: ""),
  173. message: NSLocalizedString("_select_offline_warning_", comment: ""),
  174. preferredStyle: .alert)
  175. alert.addAction(UIAlertAction(title: NSLocalizedString("_continue_", comment: ""), style: .default, handler: { _ in
  176. selectedMetadatas.forEach { NCFunctionCenter.shared.setMetadataAvalableOffline($0, isOffline: isAnyOffline) }
  177. completion?()
  178. }))
  179. alert.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel))
  180. viewController.present(alert, animated: true)
  181. } else {
  182. selectedMetadatas.forEach { NCFunctionCenter.shared.setMetadataAvalableOffline($0, isOffline: isAnyOffline) }
  183. completion?()
  184. }
  185. }
  186. )
  187. }
  188. /// Open view that lets the user move or copy the files within Nextcloud
  189. static func moveOrCopyAction(selectedMetadatas: [tableMetadata], completion: (() -> Void)? = nil) -> NCMenuAction {
  190. NCMenuAction(
  191. title: NSLocalizedString("_move_or_copy_selected_files_", comment: ""),
  192. icon: NCUtility.shared.loadImage(named: "arrow.up.right.square"),
  193. action: { _ in
  194. NCFunctionCenter.shared.openSelectView(items: selectedMetadatas)
  195. completion?()
  196. }
  197. )
  198. }
  199. /// Open AirPrint view to print a single file
  200. static func printAction(metadata: tableMetadata) -> NCMenuAction {
  201. NCMenuAction(
  202. title: NSLocalizedString("_print_", comment: ""),
  203. icon: NCUtility.shared.loadImage(named: "printer"),
  204. action: { _ in
  205. NCFunctionCenter.shared.openDownload(metadata: metadata, selector: NCGlobal.shared.selectorPrint)
  206. }
  207. )
  208. }
  209. /// Lock or unlock a file using files_lock
  210. static func lockUnlockFiles(shouldLock: Bool, metadatas: [tableMetadata], completion: (() -> Void)? = nil) -> NCMenuAction {
  211. let imageName = !shouldLock ? "lock.open" : "lock"
  212. return NCMenuAction(
  213. title: NSLocalizedString(shouldLock ? "_lock_action_" : "_unlock_action_", comment: ""),
  214. icon: NCUtility.shared.loadImage(named: imageName),
  215. action: { _ in
  216. for metadata in metadatas where metadata.lock != shouldLock {
  217. NCNetworking.shared.lockUnlockFile(metadata, shoulLock: shouldLock)
  218. }
  219. completion?()
  220. }
  221. )
  222. }
  223. }