NCCollectionViewCommon+Menu.swift 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. //
  2. // NCCollectionViewCommon+Menu.swift
  3. // Nextcloud
  4. //
  5. // Created by Philippe Weidmann on 24.01.20.
  6. // Copyright © 2020 Philippe Weidmann. All rights reserved.
  7. // Copyright © 2020 Marino Faggiana All rights reserved.
  8. //
  9. // Author Philippe Weidmann
  10. // Author Marino Faggiana <marino.faggiana@nextcloud.com>
  11. //
  12. // This program is free software: you can redistribute it and/or modify
  13. // it under the terms of the GNU General Public License as published by
  14. // the Free Software Foundation, either version 3 of the License, or
  15. // (at your option) any later version.
  16. //
  17. // This program is distributed in the hope that it will be useful,
  18. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. // GNU General Public License for more details.
  21. //
  22. // You should have received a copy of the GNU General Public License
  23. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  24. //
  25. import FloatingPanel
  26. import NCCommunication
  27. extension NCCollectionViewCommon {
  28. func toggleMoreMenu(viewController: UIViewController, metadata: tableMetadata) {
  29. if let metadata = NCManageDatabase.sharedInstance.getMetadataFromOcId(metadata.ocId) {
  30. let mainMenuViewController = UIStoryboard.init(name: "NCMenu", bundle: nil).instantiateViewController(withIdentifier: "NCMainMenuTableViewController") as! NCMainMenuTableViewController
  31. mainMenuViewController.actions = self.initMenuMore(viewController: viewController, metadata: metadata)
  32. let menuPanelController = NCMenuPanelController()
  33. menuPanelController.parentPresenter = viewController
  34. menuPanelController.delegate = mainMenuViewController
  35. menuPanelController.set(contentViewController: mainMenuViewController)
  36. menuPanelController.track(scrollView: mainMenuViewController.tableView)
  37. viewController.present(menuPanelController, animated: true, completion: nil)
  38. }
  39. }
  40. private func initMenuMore(viewController: UIViewController, metadata: tableMetadata) -> [NCMenuAction] {
  41. var actions = [NCMenuAction]()
  42. let appDelegate = UIApplication.shared.delegate as! AppDelegate
  43. let serverUrl = metadata.serverUrl+"/"+metadata.fileName
  44. let isFolderEncrypted = CCUtility.isFolderEncrypted(metadata.serverUrl, e2eEncrypted: metadata.e2eEncrypted, account: metadata.account, urlBase: metadata.urlBase)
  45. let serverUrlHome = NCUtility.shared.getHomeServer(urlBase: appDelegate.urlBase, account: appDelegate.account)
  46. var isOffline = false
  47. if metadata.directory {
  48. if let directory = NCManageDatabase.sharedInstance.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", appDelegate.account, serverUrl)) {
  49. isOffline = directory.offline
  50. }
  51. } else {
  52. if let localFile = NCManageDatabase.sharedInstance.getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) {
  53. isOffline = localFile.offline
  54. }
  55. }
  56. var iconHeader: UIImage!
  57. if let icon = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) {
  58. iconHeader = icon
  59. } else {
  60. if metadata.directory {
  61. iconHeader = CCGraphics.changeThemingColorImage(UIImage(named: "folder"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon)
  62. } else {
  63. iconHeader = UIImage(named: metadata.iconName)
  64. }
  65. }
  66. actions.append(
  67. NCMenuAction(
  68. title: metadata.fileNameView,
  69. icon: iconHeader,
  70. action: nil
  71. )
  72. )
  73. //
  74. // FAVORITE
  75. //
  76. if (layoutKey == k_layout_view_favorite && serverUrl == "") || (layoutKey != k_layout_view_favorite) {
  77. actions.append(
  78. NCMenuAction(
  79. title: metadata.favorite ? NSLocalizedString("_remove_favorites_", comment: "") : NSLocalizedString("_add_favorites_", comment: ""),
  80. icon: CCGraphics.changeThemingColorImage(UIImage(named: "favorite"), width: 50, height: 50, color: NCBrandColor.sharedInstance.yellowFavorite),
  81. action: { menuAction in
  82. NCNetworking.shared.favoriteMetadata(metadata, urlBase: appDelegate.urlBase) { (errorCode, errorDescription) in
  83. if errorCode != 0 {
  84. NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: TimeInterval(k_dismissAfterSecond), type: NCContentPresenter.messageType.error, errorCode: errorCode)
  85. }
  86. }
  87. }
  88. )
  89. )
  90. }
  91. //
  92. // DETAIL
  93. //
  94. if !isFolderEncrypted {
  95. actions.append(
  96. NCMenuAction(
  97. title: NSLocalizedString("_details_", comment: ""),
  98. icon: CCGraphics.changeThemingColorImage(UIImage(named: "details"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon),
  99. action: { menuAction in
  100. NCMainCommon.shared.openShare(ViewController: self, metadata: metadata, indexPage: 0)
  101. }
  102. )
  103. )
  104. }
  105. //
  106. // OPEN IN
  107. //
  108. if !metadata.directory && !NCBrandOptions.sharedInstance.disable_openin_file {
  109. actions.append(
  110. NCMenuAction(
  111. title: NSLocalizedString("_open_in_", comment: ""),
  112. icon: CCGraphics.changeThemingColorImage(UIImage(named: "openFile"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon),
  113. action: { menuAction in
  114. NCMainCommon.shared.downloadOpen(metadata: metadata, selector: selectorOpenIn)
  115. }
  116. )
  117. )
  118. }
  119. //
  120. // RENAME
  121. //
  122. if !(isFolderEncrypted && metadata.serverUrl == serverUrlHome) {
  123. actions.append(
  124. NCMenuAction(
  125. title: NSLocalizedString("_rename_", comment: ""),
  126. icon: CCGraphics.changeThemingColorImage(UIImage(named: "rename"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon),
  127. action: { menuAction in
  128. let alertController = UIAlertController(title: NSLocalizedString("_rename_", comment: ""), message: nil, preferredStyle: .alert)
  129. alertController.addTextField { (textField) in
  130. textField.text = metadata.fileNameView
  131. }
  132. let cancelAction = UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel, handler: nil)
  133. let okAction = UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { action in
  134. if let fileNameNew = alertController.textFields?.first?.text {
  135. NCNetworking.shared.renameMetadata(metadata, fileNameNew: fileNameNew, urlBase: appDelegate.urlBase, viewController: self) { (errorCode, errorDescription) in
  136. if errorCode != 0 {
  137. NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: TimeInterval(k_dismissAfterSecond), type: NCContentPresenter.messageType.error, errorCode: errorCode)
  138. }
  139. }
  140. }
  141. })
  142. alertController.addAction(cancelAction)
  143. alertController.addAction(okAction)
  144. self.present(alertController, animated: true, completion: nil)
  145. }
  146. )
  147. )
  148. }
  149. //
  150. // COPY - MOVE
  151. //
  152. if !isFolderEncrypted && serverUrl != "" {
  153. actions.append(
  154. NCMenuAction(
  155. title: NSLocalizedString("_move_or_copy_", comment: ""),
  156. icon: CCGraphics.changeThemingColorImage(UIImage(named: "move"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon),
  157. action: { menuAction in
  158. NCCollectionCommon.shared.openSelectView(viewController: viewController, array: [metadata])
  159. }
  160. )
  161. )
  162. }
  163. //
  164. // OFFLINE
  165. //
  166. if !isFolderEncrypted && (layoutKey == k_layout_view_offline && serverUrl == "" || (layoutKey != k_layout_view_offline)) {
  167. actions.append(
  168. NCMenuAction(
  169. title: isOffline ? NSLocalizedString("_remove_available_offline_", comment: "") : NSLocalizedString("_set_available_offline_", comment: ""),
  170. icon: CCGraphics.changeThemingColorImage(UIImage(named: "offline"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon),
  171. action: { menuAction in
  172. if isOffline {
  173. if metadata.directory {
  174. NCManageDatabase.sharedInstance.setDirectory(serverUrl: serverUrl, offline: false, account: self.appDelegate.account)
  175. } else {
  176. NCManageDatabase.sharedInstance.setLocalFile(ocId: metadata.ocId, offline: false)
  177. }
  178. } else {
  179. if metadata.directory {
  180. NCManageDatabase.sharedInstance.setDirectory(serverUrl: serverUrl, offline: true, account: self.appDelegate.account)
  181. NCOperationQueue.shared.synchronizationMetadata(metadata, selector: selectorDownloadAllFile)
  182. } else {
  183. NCNetworking.shared.download(metadata: metadata, selector: selectorLoadOffline) { (_) in }
  184. if let metadataLivePhoto = NCManageDatabase.sharedInstance.isLivePhoto(metadata: metadata) {
  185. NCNetworking.shared.download(metadata: metadataLivePhoto, selector: selectorLoadOffline) { (_) in }
  186. }
  187. }
  188. }
  189. self.reloadDataSource()
  190. }
  191. )
  192. )
  193. }
  194. //
  195. // DELETE
  196. //
  197. actions.append(
  198. NCMenuAction(
  199. title: NSLocalizedString("_delete_", comment: ""),
  200. icon: CCGraphics.changeThemingColorImage(UIImage(named: "trash"), width: 50, height: 50, color: .red),
  201. action: { menuAction in
  202. let alertController = UIAlertController(title: "", message: NSLocalizedString("_want_delete_", comment: ""), preferredStyle: .alert)
  203. alertController.addAction(UIAlertAction(title: NSLocalizedString("_yes_delete_", comment: ""), style: .default) { (action:UIAlertAction) in
  204. NCOperationQueue.shared.delete(metadata: metadata, onlyLocal: false)
  205. })
  206. alertController.addAction(UIAlertAction(title: NSLocalizedString("_remove_local_file_", comment: ""), style: .default) { (action:UIAlertAction) in
  207. NCOperationQueue.shared.delete(metadata: metadata, onlyLocal: true)
  208. })
  209. alertController.addAction(UIAlertAction(title: NSLocalizedString("_no_delete_", comment: ""), style: .default) { (action:UIAlertAction) in })
  210. self.present(alertController, animated: true, completion:nil)
  211. }
  212. )
  213. )
  214. //
  215. // SET FOLDER E2EE
  216. //
  217. if !metadata.e2eEncrypted && metadata.directory && CCUtility.isEnd(toEndEnabled: appDelegate.account) && metadata.serverUrl == serverUrlHome {
  218. actions.append(
  219. NCMenuAction(
  220. title: NSLocalizedString("_e2e_set_folder_encrypted_", comment: ""),
  221. icon: CCGraphics.changeThemingColorImage(UIImage(named: "lock"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon),
  222. action: { menuAction in
  223. NCCommunication.shared.markE2EEFolder(fileId: metadata.fileId, delete: false) { (account, errorCode, errorDescription) in
  224. if errorCode == 0 {
  225. NCManageDatabase.sharedInstance.deleteE2eEncryption(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", appDelegate.account, serverUrl))
  226. NCManageDatabase.sharedInstance.setDirectory(serverUrl: serverUrl, serverUrlTo: nil, etag: nil, ocId: nil, fileId: nil, encrypted: true, richWorkspace: nil, account: metadata.account)
  227. NCManageDatabase.sharedInstance.setMetadataEncrypted(ocId: metadata.ocId, encrypted: true)
  228. NotificationCenter.default.postOnMainThread(name: k_notificationCenter_changeStatusFolderE2EE, userInfo: ["serverUrl":metadata.serverUrl])
  229. } else {
  230. NCContentPresenter.shared.messageNotification(NSLocalizedString("_e2e_error_mark_folder_", comment: ""), description: errorDescription, delay: TimeInterval(k_dismissAfterSecond), type: .error, errorCode: errorCode)
  231. }
  232. }
  233. }
  234. )
  235. )
  236. }
  237. //
  238. // UNSET FOLDER E2EE
  239. //
  240. if metadata.e2eEncrypted && metadata.directory && CCUtility.isEnd(toEndEnabled: appDelegate.account) && metadata.serverUrl == serverUrlHome {
  241. actions.append(
  242. NCMenuAction(
  243. title: NSLocalizedString("_e2e_remove_folder_encrypted_", comment: ""),
  244. icon: CCGraphics.changeThemingColorImage(UIImage(named: "lock"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon),
  245. action: { menuAction in
  246. NCCommunication.shared.markE2EEFolder(fileId: metadata.fileId, delete: true) { (account, errorCode, errorDescription) in
  247. if errorCode == 0 {
  248. NCManageDatabase.sharedInstance.deleteE2eEncryption(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", appDelegate.account, serverUrl))
  249. NCManageDatabase.sharedInstance.setDirectory(serverUrl: serverUrl, serverUrlTo: nil, etag: nil, ocId: nil, fileId: nil, encrypted: false, richWorkspace: nil, account: metadata.account)
  250. NCManageDatabase.sharedInstance.setMetadataEncrypted(ocId: metadata.ocId, encrypted: false)
  251. NotificationCenter.default.postOnMainThread(name: k_notificationCenter_changeStatusFolderE2EE, userInfo: ["serverUrl":metadata.serverUrl])
  252. } else {
  253. NCContentPresenter.shared.messageNotification(NSLocalizedString("_e2e_error_delete_mark_folder_", comment: ""), description: errorDescription, delay: TimeInterval(k_dismissAfterSecond), type: .error, errorCode: errorCode)
  254. }
  255. }
  256. }
  257. )
  258. )
  259. }
  260. return actions
  261. }
  262. func toggleMoreSelect(viewController: UIViewController, selectOcId: [String]) {
  263. let mainMenuViewController = UIStoryboard.init(name: "NCMenu", bundle: nil).instantiateViewController(withIdentifier: "NCMainMenuTableViewController") as! NCMainMenuTableViewController
  264. mainMenuViewController.actions = self.initMenuSelect(viewController: viewController, selectOcId: selectOcId)
  265. let menuPanelController = NCMenuPanelController()
  266. menuPanelController.parentPresenter = viewController
  267. menuPanelController.delegate = mainMenuViewController
  268. menuPanelController.set(contentViewController: mainMenuViewController)
  269. menuPanelController.track(scrollView: mainMenuViewController.tableView)
  270. viewController.present(menuPanelController, animated: true, completion: nil)
  271. }
  272. private func initMenuSelect(viewController: UIViewController, selectOcId: [String]) -> [NCMenuAction] {
  273. var actions = [NCMenuAction]()
  274. actions.append(
  275. NCMenuAction(
  276. title: NSLocalizedString("_select_all_", comment: ""),
  277. icon: CCGraphics.changeThemingColorImage(UIImage(named: "selectFull"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon),
  278. action: { menuAction in
  279. self.collectionViewSelectAll()
  280. }
  281. )
  282. )
  283. actions.append(
  284. NCMenuAction(
  285. title: NSLocalizedString("_move_or_copy_selected_files_", comment: ""),
  286. icon: CCGraphics.changeThemingColorImage(UIImage(named: "move"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon),
  287. action: { menuAction in
  288. var meradatasSelect = [tableMetadata]()
  289. for ocId in selectOcId {
  290. if let metadata = NCManageDatabase.sharedInstance.getMetadataFromOcId(ocId) {
  291. meradatasSelect.append(metadata)
  292. }
  293. }
  294. if meradatasSelect.count > 0 {
  295. NCCollectionCommon.shared.openSelectView(viewController: viewController, array: meradatasSelect)
  296. }
  297. self.tapSelect(sender: self)
  298. }
  299. )
  300. )
  301. actions.append(
  302. NCMenuAction(
  303. title: NSLocalizedString("_delete_selected_files_", comment: ""),
  304. icon: CCGraphics.changeThemingColorImage(UIImage(named: "trash"), width: 50, height: 50, color: .red),
  305. action: { menuAction in
  306. let alertController = UIAlertController(title: "", message: NSLocalizedString("_want_delete_", comment: ""), preferredStyle: .alert)
  307. alertController.addAction(UIAlertAction(title: NSLocalizedString("_yes_delete_", comment: ""), style: .default) { (action:UIAlertAction) in
  308. for ocId in selectOcId {
  309. if let metadata = NCManageDatabase.sharedInstance.getMetadataFromOcId(ocId) {
  310. NCOperationQueue.shared.delete(metadata: metadata, onlyLocal: false)
  311. }
  312. }
  313. self.tapSelect(sender: self)
  314. })
  315. alertController.addAction(UIAlertAction(title: NSLocalizedString("_remove_local_file_", comment: ""), style: .default) { (action:UIAlertAction) in
  316. for ocId in selectOcId {
  317. if let metadata = NCManageDatabase.sharedInstance.getMetadataFromOcId(ocId) {
  318. NCOperationQueue.shared.delete(metadata: metadata, onlyLocal: true)
  319. }
  320. }
  321. self.tapSelect(sender: self)
  322. })
  323. alertController.addAction(UIAlertAction(title: NSLocalizedString("_no_delete_", comment: ""), style: .default) { (action:UIAlertAction) in })
  324. self.present(alertController, animated: true, completion:nil)
  325. }
  326. )
  327. )
  328. actions.append(
  329. NCMenuAction(
  330. title: NSLocalizedString("_save_selected_files_", comment: ""),
  331. icon: CCGraphics.changeThemingColorImage(UIImage(named: "saveSelectedFiles"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon),
  332. action: { menuAction in
  333. for ocId in selectOcId {
  334. if let metadata = NCManageDatabase.sharedInstance.getMetadataFromOcId(ocId) {
  335. if metadata.typeFile == k_metadataTypeFile_image || metadata.typeFile == k_metadataTypeFile_video {
  336. NCOperationQueue.shared.download(metadata: metadata, selector: selectorSaveAlbum, setFavorite: false)
  337. }
  338. }
  339. }
  340. self.tapSelect(sender: self)
  341. }
  342. )
  343. )
  344. return actions
  345. }
  346. }