diff --git a/Signal/src/ViewControllers/PhotoLibrary/ImagePickerController.swift b/Signal/src/ViewControllers/PhotoLibrary/ImagePickerController.swift index 28f9c6629..6f181c926 100644 --- a/Signal/src/ViewControllers/PhotoLibrary/ImagePickerController.swift +++ b/Signal/src/ViewControllers/PhotoLibrary/ImagePickerController.swift @@ -319,9 +319,6 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat private func didComplete(withAttachments attachments: [SignalAttachment]) { AssertIsOnMainThread() - // If we re-enter image picking, do so in batch mode. - isInBatchSelectMode = true - for attachment in attachments { guard let assetId = attachment.assetId else { owsFailDebug("Attachment is missing asset id.") @@ -376,17 +373,6 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat self.doneButton.isEnabled = false } - @objc - func didCancelSelect(_ sender: Any) { - endSelectMode() - } - - func endSelectMode() { - isInBatchSelectMode = false - - deselectAnySelected() - } - func deselectAnySelected() { guard let collectionView = self.collectionView else { owsFailDebug("collectionView was unexpectedly nil") @@ -520,6 +506,11 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + if !isInBatchSelectMode { + // Clear previous selection, if any. + selectedIds.removeAllObjects() + } + let asset = photoCollectionContents.asset(at: indexPath.item) let assetId = asset.localIdentifier selectedIds.add(assetId) @@ -577,6 +568,9 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat } func attachmentApproval(_ attachmentApproval: AttachmentApprovalViewController, addMoreToAttachments attachments: [SignalAttachment]) { + // If we re-enter image picking via "add more" button, do so in batch mode. + isInBatchSelectMode = true + navigationController?.popToViewController(self, animated: true) } diff --git a/Signal/src/ViewControllers/PhotoLibrary/PhotoLibrary.swift b/Signal/src/ViewControllers/PhotoLibrary/PhotoLibrary.swift index 86a45d86d..14d79b05f 100644 --- a/Signal/src/ViewControllers/PhotoLibrary/PhotoLibrary.swift +++ b/Signal/src/ViewControllers/PhotoLibrary/PhotoLibrary.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// Copyright (c) 2019 Open Whisper Systems. All rights reserved. // import Foundation @@ -48,12 +48,24 @@ class PhotoPickerAssetItem: PhotoGridItem { func asyncThumbnail(completion: @escaping (UIImage?) -> Void) -> UIImage? { var syncImageResult: UIImage? + var hasLoadedImage = false // Surprisingly, iOS will opportunistically run the completion block sync if the image is - // already available + // already available. photoCollectionContents.requestThumbnail(for: self.asset, thumbnailSize: photoMediaSize.thumbnailSize) { image, _ in - syncImageResult = image - completion(image) + DispatchMainThreadSafe({ + syncImageResult = image + + // Once we've _successfully_ completed (e.g. invoked the completion with + // a non-nil image), don't invoke the completion again with a nil argument. + if !hasLoadedImage || image != nil { + completion(image) + + if image != nil { + hasLoadedImage = true + } + } + }) } return syncImageResult } @@ -294,7 +306,7 @@ class PhotoLibrary: NSObject, PHPhotoLibraryChangeObserver { let processPHAssetCollections: (PHFetchResult) -> Void = { (fetchResult) in // undocumented constant - fetchResult.enumerateObjects { (assetCollection, index, stop) in + fetchResult.enumerateObjects { (assetCollection, _, _) in // We're already sorting albums by last-updated. "Recently Added" is mostly redundant guard assetCollection.assetCollectionSubtype != .smartAlbumRecentlyAdded else { return