From 52b081d5c71cccd5606a1cbae7e8e48aa7069143 Mon Sep 17 00:00:00 2001 From: Nick Kibysh Date: Wed, 22 Jul 2020 15:02:59 +0200 Subject: [PATCH] completed deleting items from DFU directory --- Podfile.lock | 2 +- .../FileSelectorViewController.swift | 80 +++++++++++++++++-- .../Utils/DocumentFileManager.swift | 4 + .../DFUFileSelector/Utils/FSDataSource.swift | 3 +- .../DFUFileSelector/Utils/UIImage+File.swift | 4 +- 5 files changed, 84 insertions(+), 9 deletions(-) diff --git a/Podfile.lock b/Podfile.lock index a1b0ef3d..2f1e5322 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -43,4 +43,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 231a987b95c8a931837051e6800bdf1778d188ee -COCOAPODS: 1.9.1 +COCOAPODS: 1.9.3 diff --git a/nRF Toolbox/Profiles/DeviceFirmwareUpdate/ViewConrollers/DFUFileSelector/FileSelectorViewController.swift b/nRF Toolbox/Profiles/DeviceFirmwareUpdate/ViewConrollers/DFUFileSelector/FileSelectorViewController.swift index cea8dfc1..6e5f77ab 100644 --- a/nRF Toolbox/Profiles/DeviceFirmwareUpdate/ViewConrollers/DFUFileSelector/FileSelectorViewController.swift +++ b/nRF Toolbox/Profiles/DeviceFirmwareUpdate/ViewConrollers/DFUFileSelector/FileSelectorViewController.swift @@ -65,11 +65,11 @@ class FileSelectorViewController: UIViewController, AlertPresenter, UITableVi tableView.registerCellNib(cell: FileTableViewCell.self) tableView.registerCellClass(cell: NordicActionTableViewCell.self) - NotificationCenter.default.addObserver(self, selector: #selector(reloadList), name: UIApplication.willEnterForegroundNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(reloadData), name: UIApplication.willEnterForegroundNotification, object: nil) selectButton.style = .mainAction - navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .refresh, target: self, action: #selector(reloadList)) + navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .refresh, target: self, action: #selector(reloadData)) if #available(iOS 13, *) { UIImage(systemName: "doc").map { self.docImage.image = $0 } @@ -82,11 +82,10 @@ class FileSelectorViewController: UIViewController, AlertPresenter, UITableVi override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - reloadList() + reloadData() } - @objc - func reloadList() { + private func reloadItemList() { do { let directory = try documentFileManager.buildDocumentDir() dataSource.updateItems(directory) @@ -94,6 +93,11 @@ class FileSelectorViewController: UIViewController, AlertPresenter, UITableVi displayErrorAlert(error: error) return } + } + + @objc + func reloadData() { + reloadItemList() if !dataSource.items.isEmpty { view = tableView @@ -158,12 +162,78 @@ class FileSelectorViewController: UIViewController, AlertPresenter, UITableVi } else if let file = dataSource.items[indexPath.row].node as? File, dataSource.items[indexPath.row].valid { fileWasSelected(file: file) } + + tableView.deselectRow(at: indexPath, animated: true) } func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { section == 0 ? "Documents Directory" : "" } + func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + indexPath.section == 0 + } + + func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { + guard editingStyle == .delete else { return } + let item = self.dataSource.items[indexPath.row] + + let deleteItem: (FSNode) -> (Error?) = { [weak self] node in + guard let `self` = self else { return QuickError(message: "Unknown Error") } + + do { + try self.documentFileManager.deleteNode(node) + } catch let error { + return error + } + return nil + } + + if let directory = item.node as? Directory { + let alert = UIAlertController(title: "Remove Directory", message: "Do you want to delete entire directory with all nested items?", preferredStyle: .alert) + let delete = UIAlertAction(title: "Delete", style: .destructive, handler: { _ in + self.removeDirectory(directory, rootItem: item, deleteAction: deleteItem) + }) + let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) + + alert.addAction(delete) + alert.addAction(cancel) + + self.present(alert, animated: true, completion: nil) + } else { + deleteFile(item.node, deleteAction: deleteItem) + } + + } + + private func removeDirectory(_ dir: Directory, rootItem: FSNodeRepresentation, deleteAction: (FSNode) -> (Error?)) { + let indexPaths = ([rootItem] + dataSource.items(dir)) + .compactMap { item in + self.dataSource.items.firstIndex { item.node.url == $0.node.url } + } + .map { IndexPath(row: $0, section: 0)} + if let error = deleteAction(rootItem.node) { + displayErrorAlert(error: error) + return + } + self.reloadItemList() + tableView.deleteRows(at: indexPaths, with: .automatic) + } + + private func deleteFile(_ item: FSNode, deleteAction: (FSNode) -> (Error?)) { + guard let ip = self.dataSource.items + .firstIndex (where: { item.url == $0.node.url }) + .map ({ IndexPath(row: $0, section: 0) }) else { + return + } + + if let error = deleteAction(item) { + displayErrorAlert(error: error) + return + } + self.reloadItemList() + tableView.deleteRows(at: [ip], with: .automatic) + } } class DFUFileSelectorViewController: FileSelectorViewController { diff --git a/nRF Toolbox/Profiles/DeviceFirmwareUpdate/ViewConrollers/DFUFileSelector/Utils/DocumentFileManager.swift b/nRF Toolbox/Profiles/DeviceFirmwareUpdate/ViewConrollers/DFUFileSelector/Utils/DocumentFileManager.swift index 7e9439da..3adf5c22 100644 --- a/nRF Toolbox/Profiles/DeviceFirmwareUpdate/ViewConrollers/DFUFileSelector/Utils/DocumentFileManager.swift +++ b/nRF Toolbox/Profiles/DeviceFirmwareUpdate/ViewConrollers/DFUFileSelector/Utils/DocumentFileManager.swift @@ -68,4 +68,8 @@ class DocumentFileManager: FileManager { return [] } } + + func deleteNode(_ node: FSNode) throws { + try removeItem(at: node.url) + } } diff --git a/nRF Toolbox/Profiles/DeviceFirmwareUpdate/ViewConrollers/DFUFileSelector/Utils/FSDataSource.swift b/nRF Toolbox/Profiles/DeviceFirmwareUpdate/ViewConrollers/DFUFileSelector/Utils/FSDataSource.swift index ba00da4c..eecf7c67 100644 --- a/nRF Toolbox/Profiles/DeviceFirmwareUpdate/ViewConrollers/DFUFileSelector/Utils/FSDataSource.swift +++ b/nRF Toolbox/Profiles/DeviceFirmwareUpdate/ViewConrollers/DFUFileSelector/Utils/FSDataSource.swift @@ -45,6 +45,7 @@ struct FSNodeRepresentation { var modificationDate: Date? var sizeInfo: String var valid: Bool + var isDirectory: Bool } struct FSDataSource { @@ -76,7 +77,7 @@ struct FSDataSource { infoText = ByteCountFormatter().string(fromByteCount: Int64((node as! File).size)) } - res.append(FSNodeRepresentation(node: node, level: level, name: node.name, collapsed: false, size: 0, image: image!, modificationDate: node.resourceModificationDate, sizeInfo: infoText, valid: valid)) + res.append(FSNodeRepresentation(node: node, level: level, name: node.name, collapsed: false, size: 0, image: image!, modificationDate: node.resourceModificationDate, sizeInfo: infoText, valid: valid, isDirectory: (node is Directory))) if let dir = node as? Directory { res.append(contentsOf: self.items(dir, level: level + 1)) } diff --git a/nRF Toolbox/Profiles/DeviceFirmwareUpdate/ViewConrollers/DFUFileSelector/Utils/UIImage+File.swift b/nRF Toolbox/Profiles/DeviceFirmwareUpdate/ViewConrollers/DFUFileSelector/Utils/UIImage+File.swift index fc3997ab..cb08d2bb 100644 --- a/nRF Toolbox/Profiles/DeviceFirmwareUpdate/ViewConrollers/DFUFileSelector/Utils/UIImage+File.swift +++ b/nRF Toolbox/Profiles/DeviceFirmwareUpdate/ViewConrollers/DFUFileSelector/Utils/UIImage+File.swift @@ -44,8 +44,8 @@ extension UIImage { // allIcons is guaranteed to have at least one image switch preferredSize { - case .smallest: return allIcons.first! - case .largest: return allIcons.last! + case .smallest: return allIcons.first ?? UIImage() + case .largest: return allIcons.last ?? UIImage() } } }