NCCollectionViewCommon+DragDrop.swift 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. //
  2. // NCCollectionViewCommon+DragDrop.swift
  3. // Nextcloud
  4. //
  5. // Created by Marino Faggiana on 19/04/24.
  6. // Copyright © 2024 Marino Faggiana. All rights reserved.
  7. //
  8. // Author Marino Faggiana <marino.faggiana@nextcloud.com>
  9. //
  10. // This program is free software: you can redistribute it and/or modify
  11. // it under the terms of the GNU General Public License as published by
  12. // the Free Software Foundation, either version 3 of the License, or
  13. // (at your option) any later version.
  14. //
  15. // This program is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. // GNU General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License
  21. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. //
  23. import Foundation
  24. import NextcloudKit
  25. import JGProgressHUD
  26. // MARK: - Drag
  27. extension NCCollectionViewCommon: UICollectionViewDragDelegate {
  28. func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
  29. if isEditMode {
  30. return NCDragDrop().performDrag(selectOcId: selectOcId)
  31. } else if let metadata = dataSource.cellForItemAt(indexPath: indexPath) {
  32. return NCDragDrop().performDrag(metadata: metadata)
  33. }
  34. return []
  35. }
  36. func collectionView(_ collectionView: UICollectionView, dragPreviewParametersForItemAt indexPath: IndexPath) -> UIDragPreviewParameters? {
  37. let previewParameters = UIDragPreviewParameters()
  38. if layoutForView?.layout == NCGlobal.shared.layoutList, let cell = collectionView.cellForItem(at: indexPath) as? NCListCell {
  39. let width = (collectionView.frame.width / 3) * 2
  40. previewParameters.visiblePath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: width, height: cell.frame.height), cornerRadius: 10)
  41. return previewParameters
  42. } else if let cell = collectionView.cellForItem(at: indexPath) as? NCGridCell {
  43. previewParameters.visiblePath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: cell.frame.width, height: cell.frame.height - 40), cornerRadius: 10)
  44. return previewParameters
  45. }
  46. return nil
  47. }
  48. }
  49. // MARK: - Drop
  50. extension NCCollectionViewCommon: UICollectionViewDropDelegate {
  51. func collectionView(_ collectionView: UICollectionView, canHandle session: UIDropSession) -> Bool {
  52. return true
  53. }
  54. func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal {
  55. var destinationMetadata: tableMetadata?
  56. if let destinationIndexPath {
  57. destinationMetadata = dataSource.cellForItemAt(indexPath: destinationIndexPath)
  58. }
  59. DragDropHover.shared.destinationMetadata = destinationMetadata
  60. if let destinationMetadata {
  61. if destinationMetadata.e2eEncrypted || destinationMetadata.isDirectoryE2EE {
  62. DragDropHover.shared.cleanPushDragDropHover()
  63. return UICollectionViewDropProposal(operation: .forbidden)
  64. }
  65. if !destinationMetadata.directory && serverUrl.isEmpty {
  66. DragDropHover.shared.cleanPushDragDropHover()
  67. return UICollectionViewDropProposal(operation: .forbidden)
  68. }
  69. } else {
  70. if serverUrl.isEmpty || NCUtilityFileSystem().isDirectoryE2EE(account: appDelegate.account, urlBase: appDelegate.urlBase, userId: appDelegate.userId, serverUrl: serverUrl) {
  71. DragDropHover.shared.cleanPushDragDropHover()
  72. return UICollectionViewDropProposal(operation: .forbidden)
  73. }
  74. }
  75. // DIRECTORY - Push Metadata
  76. if DragDropHover.shared.pushIndexPath != destinationIndexPath || DragDropHover.shared.pushCollectionView != collectionView {
  77. DragDropHover.shared.pushIndexPath = destinationIndexPath
  78. DragDropHover.shared.pushCollectionView = collectionView
  79. DragDropHover.shared.pushTimerIndexPath?.invalidate()
  80. DragDropHover.shared.pushTimerIndexPath = Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { [weak self] _ in
  81. guard let self else { return }
  82. if let destinationIndexPath,
  83. DragDropHover.shared.pushIndexPath == destinationIndexPath,
  84. DragDropHover.shared.pushCollectionView == collectionView,
  85. let metadata = self.dataSource.cellForItemAt(indexPath: destinationIndexPath),
  86. metadata.directory {
  87. DragDropHover.shared.cleanPushDragDropHover()
  88. self.pushMetadata(metadata)
  89. }
  90. }
  91. }
  92. return UICollectionViewDropProposal(operation: .copy)
  93. }
  94. func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) {
  95. DragDropHover.shared.cleanPushDragDropHover()
  96. DragDropHover.shared.sourceMetadatas = nil
  97. if let metadatas = NCDragDrop().performDrop(collectionView, performDropWith: coordinator, serverUrl: self.serverUrl, isImageVideo: false) {
  98. DragDropHover.shared.sourceMetadatas = metadatas
  99. openMenu(collectionView: collectionView, location: coordinator.session.location(in: collectionView))
  100. }
  101. }
  102. func collectionView(_ collectionView: UICollectionView, dropSessionDidExit session: UIDropSession) {
  103. DragDropHover.shared.cleanPushDragDropHover()
  104. }
  105. func collectionView(_ collectionView: UICollectionView, dropSessionDidEnd session: UIDropSession) {
  106. DragDropHover.shared.cleanPushDragDropHover()
  107. }
  108. // MARK: -
  109. private func openMenu(collectionView: UICollectionView, location: CGPoint) {
  110. var listMenuItems: [UIMenuItem] = []
  111. listMenuItems.append(UIMenuItem(title: NSLocalizedString("_copy_", comment: ""), action: #selector(copyMenuFile)))
  112. listMenuItems.append(UIMenuItem(title: NSLocalizedString("_move_", comment: ""), action: #selector(moveMenuFile)))
  113. UIMenuController.shared.menuItems = listMenuItems
  114. UIMenuController.shared.showMenu(from: collectionView, rect: CGRect(x: location.x, y: location.y, width: 0, height: 0))
  115. }
  116. @objc func copyMenuFile() {
  117. guard let sourceMetadatas = DragDropHover.shared.sourceMetadatas else { return }
  118. var serverUrl: String = self.serverUrl
  119. if let destinationMetadata = DragDropHover.shared.destinationMetadata, destinationMetadata.directory {
  120. serverUrl = destinationMetadata.serverUrl + "/" + destinationMetadata.fileName
  121. }
  122. NCDragDrop().copyFile(metadatas: sourceMetadatas, serverUrl: serverUrl)
  123. }
  124. @objc func moveMenuFile() {
  125. guard let sourceMetadatas = DragDropHover.shared.sourceMetadatas else { return }
  126. var serverUrl: String = self.serverUrl
  127. if let destinationMetadata = DragDropHover.shared.destinationMetadata, destinationMetadata.directory {
  128. serverUrl = destinationMetadata.serverUrl + "/" + destinationMetadata.fileName
  129. }
  130. NCDragDrop().moveFile(metadatas: sourceMetadatas, serverUrl: serverUrl)
  131. }
  132. }
  133. // MARK: - Drop Interaction Delegate
  134. extension NCCollectionViewCommon: UIDropInteractionDelegate { }