NCCollectionViewCommon+DragDrop.swift 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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,
  39. let cell = collectionView.cellForItem(at: indexPath) as? NCListCell {
  40. let width = (collectionView.frame.width / 3) * 2
  41. previewParameters.visiblePath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: width, height: cell.frame.height), cornerRadius: 10)
  42. return previewParameters
  43. } else if let cell = collectionView.cellForItem(at: indexPath) as? NCGridCell {
  44. previewParameters.visiblePath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: cell.frame.width, height: cell.frame.height - 40), cornerRadius: 10)
  45. return previewParameters
  46. } else if let cell = collectionView.cellForItem(at: indexPath) as? NCPhotoCell {
  47. previewParameters.visiblePath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: cell.frame.width, height: cell.frame.height), cornerRadius: 10)
  48. return previewParameters
  49. }
  50. return nil
  51. }
  52. }
  53. // MARK: - Drop
  54. extension NCCollectionViewCommon: UICollectionViewDropDelegate {
  55. func collectionView(_ collectionView: UICollectionView, canHandle session: UIDropSession) -> Bool {
  56. return true
  57. }
  58. func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal {
  59. var destinationMetadata: tableMetadata?
  60. if let destinationIndexPath {
  61. destinationMetadata = dataSource.cellForItemAt(indexPath: destinationIndexPath)
  62. }
  63. DragDropHover.shared.destinationMetadata = destinationMetadata
  64. if let destinationMetadata {
  65. if destinationMetadata.e2eEncrypted || destinationMetadata.isDirectoryE2EE {
  66. DragDropHover.shared.cleanPushDragDropHover()
  67. return UICollectionViewDropProposal(operation: .forbidden)
  68. }
  69. if !destinationMetadata.directory && serverUrl.isEmpty {
  70. DragDropHover.shared.cleanPushDragDropHover()
  71. return UICollectionViewDropProposal(operation: .forbidden)
  72. }
  73. } else {
  74. if serverUrl.isEmpty || NCUtilityFileSystem().isDirectoryE2EE(account: appDelegate.account, urlBase: appDelegate.urlBase, userId: appDelegate.userId, serverUrl: serverUrl) {
  75. DragDropHover.shared.cleanPushDragDropHover()
  76. return UICollectionViewDropProposal(operation: .forbidden)
  77. }
  78. }
  79. // DIRECTORY - Push Metadata
  80. if DragDropHover.shared.pushIndexPath != destinationIndexPath || DragDropHover.shared.pushCollectionView != collectionView {
  81. DragDropHover.shared.pushIndexPath = destinationIndexPath
  82. DragDropHover.shared.pushCollectionView = collectionView
  83. DragDropHover.shared.pushTimerIndexPath?.invalidate()
  84. DragDropHover.shared.pushTimerIndexPath = Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { [weak self] _ in
  85. guard let self else { return }
  86. if let destinationIndexPath,
  87. DragDropHover.shared.pushIndexPath == destinationIndexPath,
  88. DragDropHover.shared.pushCollectionView == collectionView,
  89. let metadata = self.dataSource.cellForItemAt(indexPath: destinationIndexPath),
  90. metadata.directory {
  91. DragDropHover.shared.cleanPushDragDropHover()
  92. self.pushMetadata(metadata)
  93. }
  94. }
  95. }
  96. return UICollectionViewDropProposal(operation: .copy)
  97. }
  98. func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) {
  99. DragDropHover.shared.cleanPushDragDropHover()
  100. DragDropHover.shared.sourceMetadatas = nil
  101. if let metadatas = NCDragDrop().performDrop(collectionView, performDropWith: coordinator, serverUrl: self.serverUrl, isImageVideo: false) {
  102. DragDropHover.shared.sourceMetadatas = metadatas
  103. openMenu(collectionView: collectionView, location: coordinator.session.location(in: collectionView))
  104. }
  105. }
  106. func collectionView(_ collectionView: UICollectionView, dropSessionDidExit session: UIDropSession) {
  107. DragDropHover.shared.cleanPushDragDropHover()
  108. }
  109. func collectionView(_ collectionView: UICollectionView, dropSessionDidEnd session: UIDropSession) {
  110. DragDropHover.shared.cleanPushDragDropHover()
  111. }
  112. // MARK: -
  113. private func openMenu(collectionView: UICollectionView, location: CGPoint) {
  114. var listMenuItems: [UIMenuItem] = []
  115. listMenuItems.append(UIMenuItem(title: NSLocalizedString("_copy_", comment: ""), action: #selector(copyMenuFile)))
  116. listMenuItems.append(UIMenuItem(title: NSLocalizedString("_move_", comment: ""), action: #selector(moveMenuFile)))
  117. UIMenuController.shared.menuItems = listMenuItems
  118. UIMenuController.shared.showMenu(from: collectionView, rect: CGRect(x: location.x, y: location.y, width: 0, height: 0))
  119. }
  120. @objc func copyMenuFile() {
  121. guard let sourceMetadatas = DragDropHover.shared.sourceMetadatas else { return }
  122. var serverUrl: String = self.serverUrl
  123. if let destinationMetadata = DragDropHover.shared.destinationMetadata, destinationMetadata.directory {
  124. serverUrl = destinationMetadata.serverUrl + "/" + destinationMetadata.fileName
  125. }
  126. NCDragDrop().copyFile(metadatas: sourceMetadatas, serverUrl: serverUrl)
  127. }
  128. @objc func moveMenuFile() {
  129. guard let sourceMetadatas = DragDropHover.shared.sourceMetadatas else { return }
  130. var serverUrl: String = self.serverUrl
  131. if let destinationMetadata = DragDropHover.shared.destinationMetadata, destinationMetadata.directory {
  132. serverUrl = destinationMetadata.serverUrl + "/" + destinationMetadata.fileName
  133. }
  134. NCDragDrop().moveFile(metadatas: sourceMetadatas, serverUrl: serverUrl)
  135. }
  136. }
  137. // MARK: - Drop Interaction Delegate
  138. extension NCCollectionViewCommon: UIDropInteractionDelegate { }