Skip to content

Commit 5796f02

Browse files
committed
Ensure completionBlock is called in all paths from ImagePickerUploadController 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.
1 parent 3526852 commit 5796f02

File tree

11 files changed

+65
-29
lines changed

11 files changed

+65
-29
lines changed

Demo/FilestackDemo.xcodeproj/project.pbxproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@
185185
isa = PBXProject;
186186
attributes = {
187187
LastSwiftUpdateCheck = 0900;
188-
LastUpgradeCheck = 1300;
188+
LastUpgradeCheck = 1310;
189189
ORGANIZATIONNAME = Filestack;
190190
TargetAttributes = {
191191
454054801F98A69A00C12B2F = {

Demo/FilestackDemo.xcodeproj/xcshareddata/xcschemes/FilestackDemo.xcscheme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
3-
LastUpgradeVersion = "1300"
3+
LastUpgradeVersion = "1310"
44
version = "1.3">
55
<BuildAction
66
parallelizeBuildables = "YES"

Demo/FilestackDemo/AppDelegate.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ private extension AppDelegate {
8181
// Enable image editor for files picked from the photo library.
8282
.withEditorEnabled()
8383
// Enable a list of cloud sources.
84-
.with(availableCloudSources: [.dropbox, .googleDrive, .googlePhotos, .customSource])
84+
.with(availableCloudSources: [.dropbox, .googleDrive, .googlePhotos, .unsplash, .customSource])
8585
// Enable a list of local sources.
8686
.with(availableLocalSources: [.camera, .photoLibrary, .documents, customLocalSource()])
8787
// Specify what UTIs are allowed for documents picked from Apple's Document Picker (aka iOS Files.)

Demo/FilestackDemo/Custom Source Providers/View Controllers/MyCustomSourceProvider.swift

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ class MyCustomSourceProvider: UICollectionViewController, SourceProvider {
2828
private var cellSize = CGSize(width: 100, height: 100)
2929

3030
private var urls: Set<URL> = Set<URL>() {
31-
didSet { updateUploadButton() }
31+
didSet { updateAddButton() }
3232
}
3333

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

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

4242
// MARK: - Lifecycle
@@ -53,7 +53,7 @@ class MyCustomSourceProvider: UICollectionViewController, SourceProvider {
5353
// MARK: - Actions
5454

5555
extension MyCustomSourceProvider {
56-
@objc func upload() {
56+
@objc func add() {
5757
let urls = Array(urls)
5858

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

7373
private extension MyCustomSourceProvider {
74-
func updateUploadButton() {
75-
uploadBarButton.title = "Upload (\(urls.count)/\(availableURLs.count))"
74+
func updateAddButton() {
75+
addBarButton.isEnabled = !urls.isEmpty
76+
addBarButton.title = "Add (\(urls.count)/\(availableURLs.count))"
7677
}
7778
}
7879

@@ -83,13 +84,13 @@ extension MyCustomSourceProvider {
8384
super.viewDidLoad()
8485

8586
navigationItem.leftBarButtonItem = cancelBarButton
86-
navigationItem.rightBarButtonItem = uploadBarButton
87+
navigationItem.rightBarButtonItem = addBarButton
8788

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

92-
updateUploadButton()
93+
updateAddButton()
9394
}
9495

9596
override func viewDidDisappear(_ animated: Bool) {

Demo/FilestackDemo/ViewController.swift

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,8 @@ extension ViewController: PickerNavigationControllerDelegate {
5555
// Dismiss the picker since we have finished picking files from the local device, and, in `storeOnly` mode,
5656
// there's no upload phase.
5757
DispatchQueue.main.async {
58-
picker.dismiss(animated: true) {
59-
self.presentAlert(titled: "Success", message: "Finished picking files: \(fileURLs)")
60-
}
58+
self.presentedViewController?
59+
.presentAlert(titled: "Success", message: "Finished picking files: \(fileURLs)")
6160
}
6261
default:
6362
break
@@ -76,13 +75,14 @@ extension ViewController: PickerNavigationControllerDelegate {
7675
print("Uploaded file URLs: \(fileURLs)")
7776

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

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

85-
self.presentAlert(titled: "Success",
84+
self.presentedViewController?
85+
.presentAlert(titled: "Success",
8686
message: "Finished uploading files with handles: \(joinedHandles)")
8787
}
8888
}
@@ -91,8 +91,9 @@ extension ViewController: PickerNavigationControllerDelegate {
9191
/// Called when the picker finishes storing a file originating from a cloud source into the storage destination.
9292
func pickerStoredFile(picker: PickerNavigationController, response: StoreResponse) {
9393
if let handle = response.contents?["handle"] as? String {
94-
picker.dismiss(animated: true) {
95-
self.presentAlert(titled: "Success", message: "Finished storing file with handle: \(handle)")
94+
DispatchQueue.main.async {
95+
self.presentedViewController?
96+
.presentAlert(titled: "Success", message: "Finished storing file with handle: \(handle)")
9697
}
9798
}
9899
}

Filestack.xcodeproj/project.pbxproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,7 @@
821821
isa = PBXProject;
822822
attributes = {
823823
LastSwiftUpdateCheck = 0900;
824-
LastUpgradeCheck = 1300;
824+
LastUpgradeCheck = 1310;
825825
ORGANIZATIONNAME = Filestack;
826826
TargetAttributes = {
827827
457084FE1F975C6C00991340 = {

Filestack.xcodeproj/xcshareddata/xcschemes/Filestack.xcscheme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
3-
LastUpgradeVersion = "1300"
3+
LastUpgradeVersion = "1310"
44
version = "1.3">
55
<BuildAction
66
parallelizeBuildables = "YES"

Sources/Filestack/UI/Internal/Controllers/CustomPickerUploadController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,6 @@ extension CustomPickerUploadController: SourceProviderDelegate {
3535
}
3636

3737
func sourceProviderCancelled() {
38-
// NO-OP
38+
cancel()
3939
}
4040
}

Sources/Filestack/UI/Internal/Controllers/ImagePickerUploadController.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ class ImagePickerUploadController: NSObject, Cancellable, Monitorizable, Startab
6767
func cancel() -> Bool {
6868
urlExtractorOperation?.cancel()
6969
trackingProgress.cancel()
70+
completionBlock?([])
7071

7172
return uploader?.cancel() ?? true
7273
}

Sources/Filestack/UI/Internal/Controllers/SourceTableViewController.swift

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,13 @@ class SourceTableViewController: UITableViewController {
3030

3131
private var filePicker: (Cancellable & Monitorizable)?
3232
private var filePickerObserver: NSKeyValueObservation?
33-
3433
private var pickMonitorViewController: MonitorViewController?
3534

3635
override public func viewDidLoad() {
3736
super.viewDidLoad()
38-
navigationItem.rightBarButtonItem = cancelBarButton
37+
38+
// Add cancel button to navigation bar.
39+
navigationItem.leftBarButtonItem = cancelBarButton
3940

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

200201
func pick(source: LocalSource) {
202+
#if targetEnvironment(simulator)
203+
guard source.provider != .camera else {
204+
deselectTableViewRows()
205+
206+
let alert = UIAlertController(title: "Alert",
207+
message: "Camera source is unavailable in simulator environment.",
208+
preferredStyle: .alert)
209+
210+
alert.addAction(UIAlertAction(title: "OK", style: .default))
211+
212+
self.present(alert, animated: true)
213+
214+
return
215+
}
216+
#endif
217+
201218
guard let picker = navigationController as? PickerNavigationController else { return }
202219

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

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

243261
switch picker.behavior {
@@ -265,7 +283,9 @@ private extension SourceTableViewController {
265283
}
266284

267285
DispatchQueue.main.async {
268-
picker.pickerDelegate?.pickerPickedFiles(picker: picker, fileURLs: urls)
286+
if !urls.isEmpty {
287+
picker.pickerDelegate?.pickerPickedFiles(picker: picker, fileURLs: urls)
288+
}
269289

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

312332
semaphore.wait()
313333

314-
DispatchQueue.main.async {
315-
picker.pickerDelegate?.pickerUploadedFiles(picker: picker, responses: responses)
334+
if !responses.isEmpty {
335+
DispatchQueue.main.async {
336+
picker.pickerDelegate?.pickerUploadedFiles(picker: picker, responses: responses)
316337

317-
// Remove any temporary files after returning from delegate call.
318-
let urls = responses.compactMap { $0.context as? URL }
338+
// Remove any temporary files after returning from delegate call.
339+
let urls = responses.compactMap { $0.context as? URL }
319340

320-
self.deleteTemporaryFiles(at: urls)
341+
self.deleteTemporaryFiles(at: urls)
342+
}
321343
}
322344
case .storeOnly:
323345
// NO-OP
@@ -334,4 +356,12 @@ private extension SourceTableViewController {
334356
}
335357
}
336358
}
359+
360+
func deselectTableViewRows() {
361+
DispatchQueue.main.async {
362+
if let selectedRow = self.tableView.indexPathForSelectedRow {
363+
self.tableView.deselectRow(at: selectedRow, animated: true)
364+
}
365+
}
366+
}
337367
}

0 commit comments

Comments
 (0)