Skip to content

Commit

Permalink
Ensure completionBlock is called in all paths from `ImagePickerUpl…
Browse files Browse the repository at this point in the history
…oadController` and `URLPickerUploadController`.

Show cancel button on navigation bar's left side in picker.
Present alert when trying to use camera source from simulator instead of crashing.
Minor updates in demo project.
  • Loading branch information
rnine committed Oct 27, 2021
1 parent 3526852 commit 5796f02
Show file tree
Hide file tree
Showing 11 changed files with 65 additions and 29 deletions.
2 changes: 1 addition & 1 deletion Demo/FilestackDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0900;
LastUpgradeCheck = 1300;
LastUpgradeCheck = 1310;
ORGANIZATIONNAME = Filestack;
TargetAttributes = {
454054801F98A69A00C12B2F = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1300"
LastUpgradeVersion = "1310"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
2 changes: 1 addition & 1 deletion Demo/FilestackDemo/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ private extension AppDelegate {
// Enable image editor for files picked from the photo library.
.withEditorEnabled()
// Enable a list of cloud sources.
.with(availableCloudSources: [.dropbox, .googleDrive, .googlePhotos, .customSource])
.with(availableCloudSources: [.dropbox, .googleDrive, .googlePhotos, .unsplash, .customSource])
// Enable a list of local sources.
.with(availableLocalSources: [.camera, .photoLibrary, .documents, customLocalSource()])
// Specify what UTIs are allowed for documents picked from Apple's Document Picker (aka iOS Files.)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ class MyCustomSourceProvider: UICollectionViewController, SourceProvider {
private var cellSize = CGSize(width: 100, height: 100)

private var urls: Set<URL> = Set<URL>() {
didSet { updateUploadButton() }
didSet { updateAddButton() }
}

private lazy var cancelBarButton: UIBarButtonItem = {
UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancel))
}()

private lazy var uploadBarButton: UIBarButtonItem = {
UIBarButtonItem(title: "Upload", style: .plain, target: self, action: #selector(upload))
private lazy var addBarButton: UIBarButtonItem = {
UIBarButtonItem(title: "Add", style: .plain, target: self, action: #selector(add))
}()

// MARK: - Lifecycle
Expand All @@ -53,7 +53,7 @@ class MyCustomSourceProvider: UICollectionViewController, SourceProvider {
// MARK: - Actions

extension MyCustomSourceProvider {
@objc func upload() {
@objc func add() {
let urls = Array(urls)

dismiss(animated: true) {
Expand All @@ -71,8 +71,9 @@ extension MyCustomSourceProvider {
// MARK: - Private Functions

private extension MyCustomSourceProvider {
func updateUploadButton() {
uploadBarButton.title = "Upload (\(urls.count)/\(availableURLs.count))"
func updateAddButton() {
addBarButton.isEnabled = !urls.isEmpty
addBarButton.title = "Add (\(urls.count)/\(availableURLs.count))"
}
}

Expand All @@ -83,13 +84,13 @@ extension MyCustomSourceProvider {
super.viewDidLoad()

navigationItem.leftBarButtonItem = cancelBarButton
navigationItem.rightBarButtonItem = uploadBarButton
navigationItem.rightBarButtonItem = addBarButton

collectionView?.backgroundColor = UIColor.black
collectionView?.register(CustomCell.self, forCellWithReuseIdentifier: customCellID)
collectionView?.allowsMultipleSelection = true

updateUploadButton()
updateAddButton()
}

override func viewDidDisappear(_ animated: Bool) {
Expand Down
15 changes: 8 additions & 7 deletions Demo/FilestackDemo/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,8 @@ extension ViewController: PickerNavigationControllerDelegate {
// Dismiss the picker since we have finished picking files from the local device, and, in `storeOnly` mode,
// there's no upload phase.
DispatchQueue.main.async {
picker.dismiss(animated: true) {
self.presentAlert(titled: "Success", message: "Finished picking files: \(fileURLs)")
}
self.presentedViewController?
.presentAlert(titled: "Success", message: "Finished picking files: \(fileURLs)")
}
default:
break
Expand All @@ -76,13 +75,14 @@ extension ViewController: PickerNavigationControllerDelegate {
print("Uploaded file URLs: \(fileURLs)")

// Dismiss the picker since we finished uploading picked files.
picker.dismiss(animated: true) {
DispatchQueue.main.async {
let handles = responses.compactMap { $0.json?["handle"] as? String }

if !handles.isEmpty {
let joinedHandles = handles.joined(separator: ", ")

self.presentAlert(titled: "Success",
self.presentedViewController?
.presentAlert(titled: "Success",
message: "Finished uploading files with handles: \(joinedHandles)")
}
}
Expand All @@ -91,8 +91,9 @@ extension ViewController: PickerNavigationControllerDelegate {
/// Called when the picker finishes storing a file originating from a cloud source into the storage destination.
func pickerStoredFile(picker: PickerNavigationController, response: StoreResponse) {
if let handle = response.contents?["handle"] as? String {
picker.dismiss(animated: true) {
self.presentAlert(titled: "Success", message: "Finished storing file with handle: \(handle)")
DispatchQueue.main.async {
self.presentedViewController?
.presentAlert(titled: "Success", message: "Finished storing file with handle: \(handle)")
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion Filestack.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0900;
LastUpgradeCheck = 1300;
LastUpgradeCheck = 1310;
ORGANIZATIONNAME = Filestack;
TargetAttributes = {
457084FE1F975C6C00991340 = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1300"
LastUpgradeVersion = "1310"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ extension CustomPickerUploadController: SourceProviderDelegate {
}

func sourceProviderCancelled() {
// NO-OP
cancel()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class ImagePickerUploadController: NSObject, Cancellable, Monitorizable, Startab
func cancel() -> Bool {
urlExtractorOperation?.cancel()
trackingProgress.cancel()
completionBlock?([])

return uploader?.cancel() ?? true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@ class SourceTableViewController: UITableViewController {

private var filePicker: (Cancellable & Monitorizable)?
private var filePickerObserver: NSKeyValueObservation?

private var pickMonitorViewController: MonitorViewController?

override public func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = cancelBarButton

// Add cancel button to navigation bar.
navigationItem.leftBarButtonItem = cancelBarButton

// Try to obtain `Client` object from navigation controller
if let picker = navigationController as? PickerNavigationController {
Expand Down Expand Up @@ -198,6 +199,22 @@ private extension SourceTableViewController {
}

func pick(source: LocalSource) {
#if targetEnvironment(simulator)
guard source.provider != .camera else {
deselectTableViewRows()

let alert = UIAlertController(title: "Alert",
message: "Camera source is unavailable in simulator environment.",
preferredStyle: .alert)

alert.addAction(UIAlertAction(title: "OK", style: .default))

self.present(alert, animated: true)

return
}
#endif

guard let picker = navigationController as? PickerNavigationController else { return }

let pickCompletionHandler: (([URL]) -> Void) = { urls in
Expand Down Expand Up @@ -238,6 +255,7 @@ private extension SourceTableViewController {
}

func pickCompleted(picker: PickerNavigationController, urls: [URL]) -> Void {
deselectTableViewRows()
dispatchPrecondition(condition: .notOnQueue(.main))

switch picker.behavior {
Expand Down Expand Up @@ -265,7 +283,9 @@ private extension SourceTableViewController {
}

DispatchQueue.main.async {
picker.pickerDelegate?.pickerPickedFiles(picker: picker, fileURLs: urls)
if !urls.isEmpty {
picker.pickerDelegate?.pickerPickedFiles(picker: picker, fileURLs: urls)
}

if picker.behavior == .storeOnly {
// Remove any temporary files after returning from delegate call.
Expand Down Expand Up @@ -311,13 +331,15 @@ private extension SourceTableViewController {

semaphore.wait()

DispatchQueue.main.async {
picker.pickerDelegate?.pickerUploadedFiles(picker: picker, responses: responses)
if !responses.isEmpty {
DispatchQueue.main.async {
picker.pickerDelegate?.pickerUploadedFiles(picker: picker, responses: responses)

// Remove any temporary files after returning from delegate call.
let urls = responses.compactMap { $0.context as? URL }
// Remove any temporary files after returning from delegate call.
let urls = responses.compactMap { $0.context as? URL }

self.deleteTemporaryFiles(at: urls)
self.deleteTemporaryFiles(at: urls)
}
}
case .storeOnly:
// NO-OP
Expand All @@ -334,4 +356,12 @@ private extension SourceTableViewController {
}
}
}

func deselectTableViewRows() {
DispatchQueue.main.async {
if let selectedRow = self.tableView.indexPathForSelectedRow {
self.tableView.deselectRow(at: selectedRow, animated: true)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class URLPickerUploadController: NSObject, Cancellable, Monitorizable, Startable
@discardableResult
func cancel() -> Bool {
observers.removeAll()
completionBlock?([])

return uploader?.cancel() ?? true
}
Expand All @@ -58,6 +59,8 @@ extension URLPickerUploadController {
}

private func doUpload(urls: [URL]) {
completionBlock?(urls)

guard let uploader = uploader else { return }

let progress = Progress(totalUnitCount: Int64(urls.count * 100))
Expand Down

0 comments on commit 5796f02

Please sign in to comment.