VLCDragAndDropManager.swift 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. /*****************************************************************************
  2. * VLCDragAndDropManager.swift
  3. * VLC for iOS
  4. *****************************************************************************
  5. * Copyright (c) 2017 VideoLAN. All rights reserved.
  6. * $Id$
  7. *
  8. * Authors: Carola Nitz <caro # videolan.org>
  9. *
  10. * Refer to the COPYING file of the official project for license.
  11. *****************************************************************************/
  12. import MobileCoreServices
  13. import UIKit
  14. @available(iOS 11.0, *)
  15. struct DropError: Error {
  16. enum ErrorKind {
  17. case moveFileToDocuments
  18. case loadFileRepresentationFailed
  19. }
  20. let kind: ErrorKind
  21. }
  22. @available(iOS 11.0, *)
  23. protocol VLCDragAndDropManagerDelegate: NSObjectProtocol {
  24. func dragAndDropManagerRequestsFile(manager: NSObject, atIndexPath indexPath: IndexPath) -> Any?
  25. func dragAndDropManagerInsertItem(manager: NSObject, item: NSManagedObject, atIndexPath indexPath: IndexPath)
  26. func dragAndDropManagerDeleteItem(manager: NSObject, atIndexPath indexPath: IndexPath)
  27. func dragAndDropManagerRemoveFileFromFolder(manager: NSObject, file: NSManagedObject)
  28. func dragAndDropManagerCurrentSelection(manager: NSObject) -> AnyObject?
  29. }
  30. @available(iOS 11.0, *)
  31. class VLCDragAndDropManager<ModelType>: NSObject {
  32. //, UICollectionViewDragDelegate, UITableViewDragDelegate, UICollectionViewDropDelegate, UITableViewDropDelegate, UIDropInteractionDelegate {
  33. // let utiTypeIdentifiers: [String] = VLCDragAndDropManager.supportedTypeIdentifiers()
  34. // var cateory: ModelType
  35. // /// Returns the supported type identifiers that VLC can process.
  36. // /// It fetches the identifiers in LSItemContentTypes from all the CFBundleDocumentTypes in the info.plist.
  37. // /// Video, Audio and Subtitle formats
  38. // ///
  39. // /// - Returns: Array of UTITypeIdentifiers
  40. // private class func supportedTypeIdentifiers() -> [String] {
  41. // var typeIdentifiers: [String] = []
  42. // if let documents = Bundle.main.infoDictionary?["CFBundleDocumentTypes"] as? [[String: Any]] {
  43. // for item in documents {
  44. // if let value = item["LSItemContentTypes"] as? [String] {
  45. // typeIdentifiers.append(contentsOf: value)
  46. // }
  47. // }
  48. // }
  49. // return typeIdentifiers
  50. // }
  51. //
  52. // @available(*, unavailable, message: "use init(category:)")
  53. // override init() {
  54. // fatalError()
  55. // }
  56. //
  57. // init(cateory: ModelType) {
  58. // self.cateory = cateory
  59. // super.init()
  60. // }
  61. //
  62. // // MARK: - TableView
  63. //
  64. // func tableView(_ tableView: UITableView, canHandle session: UIDropSession) -> Bool {
  65. // return canHandleDropSession(session: session)
  66. // }
  67. //
  68. // func tableView(_ tableView: UITableView, itemsForAddingTo session: UIDragSession, at indexPath: IndexPath, point: CGPoint) -> [UIDragItem] {
  69. // return dragItems(forIndexPath: indexPath)
  70. // }
  71. //
  72. // func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
  73. // return dragItems(forIndexPath: indexPath)
  74. // }
  75. //
  76. // func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal {
  77. // let operation = dropOperation(hasActiveDrag: tableView.hasActiveDrag, firstSessionItem: session.items.first, withDestinationIndexPath: destinationIndexPath)
  78. // return UITableViewDropProposal(operation: operation, intent: .insertIntoDestinationIndexPath)
  79. // }
  80. //
  81. // func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
  82. // let section = tableView.numberOfSections - 1
  83. // let row = tableView.numberOfRows(inSection: section)
  84. // let destinationPath = coordinator.destinationIndexPath ?? IndexPath(row: row, section: section)
  85. //
  86. // for item in coordinator.items {
  87. // let itemProvider = item.dragItem.itemProvider
  88. // // we're not gonna handle moving of folders
  89. // if let sourceItem = item.dragItem.localObject, fileIsCollection(file: sourceItem as AnyObject) {
  90. // continue
  91. // }
  92. //
  93. // if fileIsFolder(atIndexPath: destinationPath) { // handle dropping onto a folder
  94. // addDragItem(tableView: tableView, dragItem: item, toFolderAt: destinationPath)
  95. // continue
  96. // }
  97. //
  98. // if item.sourceIndexPath != nil { // element within VLC
  99. // moveItem(tableView: tableView, item: item, toIndexPath: destinationPath)
  100. // continue
  101. // }
  102. // // Element dragging from another App
  103. // let placeholder = UITableViewDropPlaceholder(insertionIndexPath: destinationPath, reuseIdentifier: VLCPlaylistTableViewCell.cellIdentifier(), rowHeight: VLCPlaylistTableViewCell.heightOfCell())
  104. // let placeholderContext = coordinator.drop(item.dragItem, to: placeholder)
  105. // createFileWith(itemProvider: itemProvider) {
  106. // [weak self] file, error in
  107. //
  108. // guard let strongSelf = self else { return }
  109. //
  110. // if let file = file {
  111. // placeholderContext.commitInsertion() {
  112. // insertionIndexPath in
  113. // strongSelf.cateory.dragAndDropManagerInsertItem(manager: strongSelf, item: file, atIndexPath: insertionIndexPath)
  114. // }
  115. // }
  116. // if let error = error as? DropError {
  117. // strongSelf.handleError(error: error, itemProvider: item.dragItem.itemProvider)
  118. // placeholderContext.deletePlaceholder()
  119. // }
  120. // }
  121. // }
  122. // }
  123. //
  124. // private func inFolder() -> Bool {
  125. // return cateory.dragAndDropManagerCurrentSelection(manager: self) as? MLLabel != nil
  126. // }
  127. //
  128. // private func moveItem(tableView: UITableView, item: UITableViewDropItem, toIndexPath destinationPath: IndexPath) {
  129. // if let mlFile = item.dragItem.localObject as? MLFile, !mlFile.labels.isEmpty && !inFolder() {
  130. // tableView.performBatchUpdates({
  131. // tableView.insertRows(at: [destinationPath], with: .automatic)
  132. // cateory.dragAndDropManagerInsertItem(manager: self, item: mlFile, atIndexPath: destinationPath)
  133. // cateory.dragAndDropManagerRemoveFileFromFolder(manager: self, file: mlFile)
  134. // }, completion: nil)
  135. // }
  136. // }
  137. //
  138. // private func addDragItem(tableView: UITableView, dragItem item: UITableViewDropItem, toFolderAt index: IndexPath) {
  139. // if let sourcepath = item.sourceIndexPath { // local file that just needs to be moved
  140. // tableView.performBatchUpdates({
  141. // if let file = cateory.dragAndDropManagerRequestsFile(manager: self, atIndexPath: sourcepath) as? MLFile {
  142. // tableView.deleteRows(at: [sourcepath], with: .automatic)
  143. // addFile(file: file, toFolderAt: index)
  144. // cateory.dragAndDropManagerDeleteItem(manager: self, atIndexPath: sourcepath)
  145. // }
  146. // }, completion: nil)
  147. // return
  148. // }
  149. // // file from other app
  150. // createFileWith(itemProvider: item.dragItem.itemProvider) {
  151. // [weak self] file, error in
  152. //
  153. // if let strongSelf = self, let file = file {
  154. // strongSelf.addFile(file: file, toFolderAt: index)
  155. // }
  156. // }
  157. // }
  158. //
  159. // // MARK: - Collectionview
  160. //
  161. // func collectionView(_ collectionView: UICollectionView, canHandle session: UIDropSession) -> Bool {
  162. // return canHandleDropSession(session: session)
  163. // }
  164. //
  165. // func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
  166. // return dragItems(forIndexPath: indexPath)
  167. // }
  168. //
  169. // func collectionView(_ collectionView: UICollectionView, itemsForAddingTo session: UIDragSession, at indexPath: IndexPath, point: CGPoint) -> [UIDragItem] {
  170. // return dragItems(forIndexPath: indexPath)
  171. // }
  172. //
  173. // func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal {
  174. // let operation = dropOperation(hasActiveDrag: collectionView.hasActiveDrag, firstSessionItem: session.items.first, withDestinationIndexPath: destinationIndexPath)
  175. // return UICollectionViewDropProposal(operation: operation, intent: .insertIntoDestinationIndexPath)
  176. // }
  177. //
  178. // func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) {
  179. // let section = collectionView.numberOfSections - 1
  180. // let row = collectionView.numberOfItems(inSection: section)
  181. // let destinationPath = coordinator.destinationIndexPath ?? IndexPath(row: row, section: section)
  182. //
  183. // for item in coordinator.items {
  184. // if let sourceItem = item.dragItem.localObject, fileIsCollection(file: sourceItem as AnyObject) { // We're not handling moving of Collection
  185. // continue
  186. // }
  187. // if fileIsFolder(atIndexPath: destinationPath) { // handle dropping onto a folder
  188. // addDragItem(collectionView: collectionView, dragItem: item, toFolderAt: destinationPath)
  189. // continue
  190. // }
  191. // if item.sourceIndexPath != nil { // element within VLC
  192. // moveItem(collectionView: collectionView, item: item, toIndexPath: destinationPath)
  193. // continue
  194. // }
  195. // // Element from another App
  196. // let placeholder = UICollectionViewDropPlaceholder(insertionIndexPath: destinationPath, reuseIdentifier: VLCPlaylistCollectionViewCell.cellIdentifier())
  197. // let placeholderContext = coordinator.drop(item.dragItem, to: placeholder)
  198. // createFileWith(itemProvider: item.dragItem.itemProvider) {
  199. // [weak self] file, error in
  200. //
  201. // guard let strongSelf = self else { return }
  202. //
  203. // if let file = file {
  204. // placeholderContext.commitInsertion() {
  205. // insertionIndexPath in
  206. // strongSelf.cateory.dragAndDropManagerInsertItem(manager: strongSelf, item: file, atIndexPath: insertionIndexPath)
  207. // }
  208. // }
  209. // if let error = error as? DropError {
  210. // strongSelf.handleError(error: error, itemProvider: item.dragItem.itemProvider)
  211. // placeholderContext.deletePlaceholder()
  212. // }
  213. // }
  214. // }
  215. // }
  216. //
  217. // private func moveItem(collectionView: UICollectionView, item: UICollectionViewDropItem, toIndexPath destinationPath: IndexPath) {
  218. // if let mlFile = item.dragItem.localObject as? MLFile, !mlFile.labels.isEmpty && !inFolder() {
  219. // collectionView.performBatchUpdates({
  220. // collectionView.insertItems(at: [destinationPath])
  221. // cateory.dragAndDropManagerInsertItem(manager: self, item: mlFile, atIndexPath: destinationPath)
  222. // cateory.dragAndDropManagerRemoveFileFromFolder(manager: self, file: mlFile)
  223. // }, completion: nil)
  224. // }
  225. // }
  226. //
  227. // private func addDragItem(collectionView: UICollectionView, dragItem item: UICollectionViewDropItem, toFolderAt index: IndexPath) {
  228. // if let sourcepath = item.sourceIndexPath {
  229. // // local file that just needs to be moved
  230. // collectionView.performBatchUpdates({
  231. // if let file = cateory.dragAndDropManagerRequestsFile(manager: self, atIndexPath: sourcepath) as? MLFile {
  232. // collectionView.deleteItems(at: [sourcepath])
  233. // addFile(file: file, toFolderAt: index)
  234. // cateory.dragAndDropManagerDeleteItem(manager: self, atIndexPath: sourcepath)
  235. // }
  236. // }, completion: nil)
  237. // } else {
  238. // // file from other app
  239. // createFileWith(itemProvider: item.dragItem.itemProvider) {
  240. // [weak self] file, error in
  241. // if let strongSelf = self, let file = file {
  242. // strongSelf.addFile(file: file, toFolderAt: index)
  243. // }
  244. // }
  245. // }
  246. // }
  247. //
  248. // // MARK: - DropInteractionDelegate for EmptyView
  249. //
  250. // func dropInteraction(_ interaction: UIDropInteraction, canHandle session: UIDropSession) -> Bool {
  251. // return canHandleDropSession(session: session)
  252. // }
  253. //
  254. // func dropInteraction(_ interaction: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal {
  255. // return UIDropProposal(operation: .copy)
  256. // }
  257. //
  258. // func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) {
  259. // for item in session.items {
  260. // createFileWith(itemProvider: item.itemProvider) {
  261. // [weak self] _, error in
  262. // if let error = error as? DropError {
  263. // self?.handleError(error: error, itemProvider: item.itemProvider)
  264. // }
  265. // // no need to handle the file case since the libraryVC updates itself after getting a file
  266. // }
  267. // }
  268. // }
  269. //
  270. // // MARK: - Shared Methods
  271. //
  272. // // Checks if the session has items conforming to typeidentifiers
  273. // private func canHandleDropSession(session: UIDropSession) -> Bool {
  274. // if session.localDragSession != nil {
  275. // return true
  276. // }
  277. // return session.hasItemsConforming(toTypeIdentifiers: utiTypeIdentifiers)
  278. // }
  279. //
  280. // /// Returns a drop operation type
  281. // ///
  282. // /// - Parameters:
  283. // /// - hasActiveDrag: State if the drag started within the app
  284. // /// - item: UIDragItem from session
  285. // /// - Returns: UIDropOperation
  286. // private func dropOperation(hasActiveDrag: Bool, firstSessionItem item: AnyObject?, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UIDropOperation {
  287. // let inAlbum = cateory.dragAndDropManagerCurrentSelection(manager: self) as? MLAlbum != nil
  288. // let inShow = cateory.dragAndDropManagerCurrentSelection(manager: self) as? MLShow != nil
  289. // // you can move files into a folder or copy from anothr app into a folder
  290. // if fileIsFolder(atIndexPath: destinationIndexPath) {
  291. // // no dragging entire shows and albums into folders
  292. // if let dragItem = item, let mlFile = dragItem.localObject as? MLFile, mlFile.isAlbumTrack() || mlFile.isShowEpisode() {
  293. // return .forbidden
  294. // }
  295. // return hasActiveDrag ? .move : .copy
  296. // }
  297. // // you can't reorder
  298. // if inFolder() {
  299. // return hasActiveDrag ? .forbidden : .copy
  300. // }
  301. // // you can't reorder in or drag into an Album or Show
  302. // if inAlbum || inShow {
  303. // return .cancel
  304. // }
  305. // // we're dragging a file out of a folder
  306. // if let dragItem = item, let mlFile = dragItem.localObject as? MLFile, !mlFile.labels.isEmpty {
  307. // return .copy
  308. // }
  309. // // no reorder from another app into the top layer
  310. // return hasActiveDrag ? .forbidden : .copy
  311. // }
  312. //
  313. // /// show an Alert when dropping failed
  314. // ///
  315. // /// - Parameters:
  316. // /// - error: the type of error that happend
  317. // /// - itemProvider: the itemProvider to retrieve the suggestedName
  318. // private func handleError(error: DropError, itemProvider: NSItemProvider) {
  319. // let message: String
  320. // let filename = itemProvider.suggestedName ?? NSLocalizedString("THIS_FILE", comment: "")
  321. // switch error.kind {
  322. // case .loadFileRepresentationFailed:
  323. // message = String(format: NSLocalizedString("NOT_SUPPORTED_FILETYPE", comment: ""), filename)
  324. // case .moveFileToDocuments:
  325. // message = String(format: NSLocalizedString("FILE_EXISTS", comment: ""), filename)
  326. // }
  327. // let alert = UIAlertController(title: NSLocalizedString("ERROR", comment: ""), message: message, preferredStyle: .alert)
  328. // alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
  329. // UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: true, completion: nil)
  330. // }
  331. //
  332. // private func fileIsFolder(atIndexPath indexPath: IndexPath?) -> Bool {
  333. // if let indexPath = indexPath {
  334. // let file = cateory.dragAndDropManagerRequestsFile(manager: self, atIndexPath: indexPath)
  335. // return file as? MLLabel != nil
  336. // }
  337. // return false
  338. // }
  339. //
  340. // private func fileIsCollection(file: Any?) -> Bool {
  341. // let isFolder = file as? MLLabel != nil
  342. // let isAlbum = file as? MLAlbum != nil
  343. // let isShow = file as? MLShow != nil
  344. // return isFolder || isAlbum || isShow
  345. // }
  346. //
  347. // private func fileIsCollection(atIndexPath indexPath: IndexPath?) -> Bool {
  348. // if let indexPath = indexPath {
  349. // if let file = cateory.dragAndDropManagerRequestsFile(manager: self, atIndexPath: indexPath) {
  350. // return fileIsCollection(file:file)
  351. // }
  352. // }
  353. // return false
  354. // }
  355. //
  356. // // creating dragItems for the file at indexpath
  357. // private func dragItems(forIndexPath indexPath: IndexPath) -> [UIDragItem] {
  358. // if let file = cateory.dragAndDropManagerRequestsFile(manager: self, atIndexPath: indexPath) {
  359. // if fileIsCollection(atIndexPath: indexPath) {
  360. // return dragItemsforCollection(file: file)
  361. // }
  362. // return dragItem(fromFile: file)
  363. // }
  364. // assert(false, "we can't generate a dragfile if the delegate can't return a file ")
  365. // return []
  366. // }
  367. //
  368. // /// Iterates over the items of a collection to create dragitems.
  369. // /// Since we're not storing collections as folders we have to provide single files
  370. // ///
  371. // /// - Parameter file: Can be of type MLAlbum, MLLabel or MLShow
  372. // /// - Returns: An array of UIDragItems
  373. // private func dragItemsforCollection(file: Any) -> [UIDragItem] {
  374. // var dragItems = [UIDragItem]()
  375. // var set = Set<AnyHashable>()
  376. // if let folder = file as? MLLabel {
  377. // set = folder.files
  378. // } else if let album = file as? MLAlbum {
  379. // for track in album.tracks {
  380. // if let mlfile = (track as? MLAlbumTrack)?.files.first {
  381. // _ = set.insert(mlfile)
  382. // }
  383. // }
  384. // } else if let show = file as? MLShow {
  385. // for episode in show.episodes {
  386. // if let mlfile = (episode as? MLShowEpisode)?.files {
  387. // set = set.union(mlfile)
  388. // }
  389. // }
  390. // } else {
  391. // assert(false, "can't get dragitems from a file that is not a collection")
  392. // }
  393. // for convertibleFile in set {
  394. // if let mlfile = convertibleFile as? MLFile, let item = dragItem(fromFile: mlfile).first {
  395. // dragItems.append(item)
  396. // }
  397. // }
  398. // return dragItems
  399. // }
  400. //
  401. // //Provides an item for other applications
  402. // private func dragItem(fromFile file: Any) -> [UIDragItem] {
  403. // guard let file = mlFile(from: file as AnyObject), let path = file.url else {
  404. // assert(false, "can't create a dragitem if there is no file or the file has no url")
  405. // return []
  406. // }
  407. //
  408. // let data = try? Data(contentsOf: path, options: .mappedIfSafe)
  409. // let itemProvider = NSItemProvider()
  410. // itemProvider.suggestedName = path.lastPathComponent
  411. // // maybe use UTTypeForFileURL
  412. // if let identifiers = try? path.resourceValues(forKeys: [.typeIdentifierKey]), let identifier = identifiers.typeIdentifier {
  413. // // here we can show progress
  414. // itemProvider.registerDataRepresentation(forTypeIdentifier: identifier, visibility: .all) { completion -> Progress? in
  415. // completion(data, nil)
  416. // return nil
  417. // }
  418. // let dragitem = UIDragItem(itemProvider: itemProvider)
  419. // dragitem.localObject = file
  420. // return [dragitem]
  421. // }
  422. // assert(false, "we can't provide a typeidentifier")
  423. // return []
  424. // }
  425. //
  426. // private func mlFile(from file: AnyObject) -> MLFile? {
  427. // if let episode = file as? MLShowEpisode, let convertedfile = episode.files.first as? MLFile {
  428. // return convertedfile
  429. // }
  430. //
  431. // if let track = file as? MLAlbumTrack, let convertedfile = track.files.first as? MLFile {
  432. // return convertedfile
  433. // }
  434. //
  435. // if let convertedfile = file as? MLFile {
  436. // return convertedfile
  437. // }
  438. // return nil
  439. // }
  440. //
  441. // private func addFile(file: MLFile, toFolderAt folderIndex: IndexPath) {
  442. // let label = cateory.dragAndDropManagerRequestsFile(manager: self, atIndexPath: folderIndex) as! MLLabel
  443. // DispatchQueue.main.async {
  444. // _ = label.files.insert(file)
  445. // file.labels = [label]
  446. // file.folderTrackNumber = NSNumber(integerLiteral: label.files.count - 1)
  447. // }
  448. // }
  449. //
  450. // /// try to create a file from the dropped item
  451. // ///
  452. // /// - Parameters:
  453. // /// - itemProvider: itemprovider which is used to load the files from
  454. // /// - completion: callback with the successfully created file or error if it failed
  455. // private func createFileWith(itemProvider: NSItemProvider, completion: @escaping ((MLFile?, Error?) -> Void)) {
  456. // itemProvider.loadFileRepresentation(forTypeIdentifier: kUTTypeData as String) {
  457. // [weak self] (url, error) in
  458. // guard let strongSelf = self else { return }
  459. //
  460. // guard let url = url else {
  461. // DispatchQueue.main.async {
  462. // completion(nil, DropError(kind: .loadFileRepresentationFailed))
  463. // }
  464. // return
  465. // }
  466. // // returns nil for local session but this should also not be called for a local session
  467. // guard let destinationURL = strongSelf.moveFileToDocuments(fromURL: url) else {
  468. // DispatchQueue.main.async {
  469. // completion(nil, DropError(kind: .moveFileToDocuments))
  470. // }
  471. // return
  472. // }
  473. // DispatchQueue.global(qos: .background).async {
  474. // let sharedlib = MLMediaLibrary.sharedMediaLibrary() as? MLMediaLibrary
  475. // sharedlib?.addFilePaths([destinationURL.path])
  476. //
  477. // if let file = MLFile.file(for: destinationURL).first as? MLFile {
  478. // DispatchQueue.main.async {
  479. // // we dragged into a folder
  480. // if let selection = strongSelf.cateory.dragAndDropManagerCurrentSelection(manager: strongSelf) as? MLLabel {
  481. // file.labels = [selection]
  482. // }
  483. // completion(file, nil)
  484. // }
  485. // }
  486. // }
  487. // }
  488. // }
  489. //
  490. // private func moveFileToDocuments(fromURL filepath: URL?) -> URL? {
  491. // let searchPaths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
  492. // let newDirectoryPath = searchPaths.first
  493. // guard let directoryPath = newDirectoryPath, let url = filepath else {
  494. // return nil
  495. // }
  496. // let destinationURL = URL(fileURLWithPath: "\(directoryPath)" + "/" + "\(url.lastPathComponent)")
  497. // do {
  498. // try FileManager.default.moveItem(at: url, to: destinationURL)
  499. // } catch let error {
  500. // print(error.localizedDescription)
  501. // return nil
  502. // }
  503. // return destinationURL
  504. // }
  505. }