Add compose attachments preview

This commit is contained in:
Shadowfacts 2020-03-15 14:25:02 -04:00
parent 64f41ea2b7
commit 9ed05de3ee
Signed by untrusted user: shadowfacts
GPG Key ID: 94A5AB95422746E5
3 changed files with 80 additions and 30 deletions

View File

@ -177,10 +177,11 @@ class AssetCollectionViewController: UICollectionViewController {
} }
override func collectionView(_ collectionView: UICollectionView, previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? { override func collectionView(_ collectionView: UICollectionView, previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
if let indexPath = (configuration.identifier as? NSIndexPath) as IndexPath?, let cell = collectionView.cellForItem(at: indexPath) { if let indexPath = (configuration.identifier as? NSIndexPath) as IndexPath?,
let cell = collectionView.cellForItem(at: indexPath) as? AssetCollectionViewCell {
let parameters = UIPreviewParameters() let parameters = UIPreviewParameters()
parameters.backgroundColor = .black parameters.backgroundColor = .black
return UITargetedPreview(view: cell, parameters: parameters) return UITargetedPreview(view: cell.imageView, parameters: parameters)
} else { } else {
return nil return nil
} }

View File

@ -13,14 +13,18 @@ import AVKit
class AssetPreviewViewController: UIViewController { class AssetPreviewViewController: UIViewController {
let asset: PHAsset let attachment: CompositionAttachmentData
init(asset: PHAsset) { init(attachment: CompositionAttachmentData) {
self.asset = asset self.attachment = attachment
super.init(nibName: nil, bundle: nil) super.init(nibName: nil, bundle: nil)
} }
convenience init(asset: PHAsset) {
self.init(attachment: .asset(asset))
}
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
@ -30,21 +34,29 @@ class AssetPreviewViewController: UIViewController {
view.backgroundColor = .black view.backgroundColor = .black
if asset.mediaType == .image { switch attachment {
case let .image(image):
showImage(image)
case let .video(url):
showVideo(asset: AVURLAsset(url: url))
case let .asset(asset):
switch asset.mediaType {
case .image:
if asset.mediaSubtypes.contains(.photoLive) { if asset.mediaSubtypes.contains(.photoLive) {
showLivePhoto() showLivePhoto(asset)
} else { } else {
showImage() showAssetImage(asset)
} }
} else if asset.mediaType == .video { case .video:
playVideo() showAssetVideo(asset)
} else { default:
fatalError("asset mediaType must be image or video") fatalError("asset mediaType must be image or video")
} }
} }
}
func showImage() { func showImage(_ image: UIImage) {
let imageView = UIImageView() let imageView = UIImageView(image: image)
imageView.translatesAutoresizingMaskIntoConstraints = false imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFit imageView.contentMode = .scaleAspectFit
view.addSubview(imageView) view.addSubview(imageView)
@ -54,7 +66,10 @@ class AssetPreviewViewController: UIViewController {
imageView.topAnchor.constraint(equalTo: view.topAnchor), imageView.topAnchor.constraint(equalTo: view.topAnchor),
imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor) imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
]) ])
preferredContentSize = image.size
}
func showAssetImage(_ asset: PHAsset) {
let options = PHImageRequestOptions() let options = PHImageRequestOptions()
options.version = .current options.version = .current
options.deliveryMode = .opportunistic options.deliveryMode = .opportunistic
@ -62,13 +77,12 @@ class AssetPreviewViewController: UIViewController {
options.isNetworkAccessAllowed = true options.isNetworkAccessAllowed = true
PHImageManager.default().requestImage(for: asset, targetSize: view.bounds.size, contentMode: .aspectFit, options: options) { (image, _) in PHImageManager.default().requestImage(for: asset, targetSize: view.bounds.size, contentMode: .aspectFit, options: options) { (image, _) in
DispatchQueue.main.async { DispatchQueue.main.async {
imageView.image = image self.showImage(image!)
self.preferredContentSize = image!.size
} }
} }
} }
func showLivePhoto() { func showLivePhoto(_ asset: PHAsset) {
let options = PHLivePhotoRequestOptions() let options = PHLivePhotoRequestOptions()
options.deliveryMode = .opportunistic options.deliveryMode = .opportunistic
options.version = .current options.version = .current
@ -96,7 +110,18 @@ class AssetPreviewViewController: UIViewController {
} }
} }
func playVideo() { func showVideo(asset: AVAsset) {
let playerController = AVPlayerViewController()
let item = AVPlayerItem(asset: asset)
let player = AVPlayer(playerItem: item)
player.isMuted = true
player.play()
playerController.player = player
self.embedChild(playerController)
self.preferredContentSize = item.presentationSize
}
func showAssetVideo(_ asset: PHAsset) {
let options = PHVideoRequestOptions() let options = PHVideoRequestOptions()
options.deliveryMode = .automatic options.deliveryMode = .automatic
options.isNetworkAccessAllowed = true options.isNetworkAccessAllowed = true
@ -106,14 +131,7 @@ class AssetPreviewViewController: UIViewController {
fatalError("failed to get AVAsset") fatalError("failed to get AVAsset")
} }
DispatchQueue.main.async { DispatchQueue.main.async {
let playerController = AVPlayerViewController() self.showVideo(asset: avAsset)
let item = AVPlayerItem(asset: avAsset)
let player = AVPlayer(playerItem: item)
player.isMuted = true
player.play()
playerController.player = player
self.embedChild(playerController)
self.preferredContentSize = item.presentationSize
} }
} }
} }

View File

@ -265,6 +265,37 @@ class ComposeAttachmentsViewController: UITableViewController {
} }
} }
override func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
let attachment = attachments[indexPath.row]
// cast to NSIndexPath because identifier needs to conform to NSCopying
return UIContextMenuConfiguration(identifier: indexPath as NSIndexPath, previewProvider: { () -> UIViewController? in
return AssetPreviewViewController(attachment: attachment.data)
}) { (_) -> UIMenu? in
return nil
}
}
private func targetedPreview(forConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
if let indexPath = (configuration.identifier as? NSIndexPath) as IndexPath?,
let cell = tableView.cellForRow(at: indexPath) as? ComposeAttachmentTableViewCell {
let parameters = UIPreviewParameters()
parameters.backgroundColor = .black
return UITargetedPreview(view: cell.assetImageView, parameters: parameters)
} else {
return nil
}
}
override func tableView(_ tableView: UITableView, previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
return targetedPreview(forConfiguration: configuration)
}
override func tableView(_ tableView: UITableView, previewForDismissingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
return targetedPreview(forConfiguration: configuration)
}
// MARK: Interaction
func addAttachmentPressed() { func addAttachmentPressed() {
let sheetContainer = AssetPickerSheetContainerViewController() let sheetContainer = AssetPickerSheetContainerViewController()
sheetContainer.assetPicker.assetPickerDelegate = self sheetContainer.assetPicker.assetPickerDelegate = self