From 9ed05de3ee60e9f47a406699759fb2ba3d6333fb Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sun, 15 Mar 2020 14:25:02 -0400 Subject: [PATCH] Add compose attachments preview --- .../AssetCollectionViewController.swift | 5 +- .../AssetPreviewViewController.swift | 74 ++++++++++++------- .../ComposeAttachmentsViewController.swift | 31 ++++++++ 3 files changed, 80 insertions(+), 30 deletions(-) diff --git a/Tusker/Screens/Asset Picker/AssetCollectionViewController.swift b/Tusker/Screens/Asset Picker/AssetCollectionViewController.swift index a53eb62d..8c6ea1fa 100644 --- a/Tusker/Screens/Asset Picker/AssetCollectionViewController.swift +++ b/Tusker/Screens/Asset Picker/AssetCollectionViewController.swift @@ -177,10 +177,11 @@ class AssetCollectionViewController: UICollectionViewController { } 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() parameters.backgroundColor = .black - return UITargetedPreview(view: cell, parameters: parameters) + return UITargetedPreview(view: cell.imageView, parameters: parameters) } else { return nil } diff --git a/Tusker/Screens/Asset Picker/AssetPreviewViewController.swift b/Tusker/Screens/Asset Picker/AssetPreviewViewController.swift index a2272226..eab2e45c 100644 --- a/Tusker/Screens/Asset Picker/AssetPreviewViewController.swift +++ b/Tusker/Screens/Asset Picker/AssetPreviewViewController.swift @@ -13,14 +13,18 @@ import AVKit class AssetPreviewViewController: UIViewController { - let asset: PHAsset + let attachment: CompositionAttachmentData - init(asset: PHAsset) { - self.asset = asset - + init(attachment: CompositionAttachmentData) { + self.attachment = attachment + super.init(nibName: nil, bundle: nil) } + convenience init(asset: PHAsset) { + self.init(attachment: .asset(asset)) + } + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } @@ -30,21 +34,29 @@ class AssetPreviewViewController: UIViewController { view.backgroundColor = .black - if asset.mediaType == .image { - if asset.mediaSubtypes.contains(.photoLive) { - showLivePhoto() - } else { - showImage() + 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) { + showLivePhoto(asset) + } else { + showAssetImage(asset) + } + case .video: + showAssetVideo(asset) + default: + fatalError("asset mediaType must be image or video") } - } else if asset.mediaType == .video { - playVideo() - } else { - fatalError("asset mediaType must be image or video") } } - func showImage() { - let imageView = UIImageView() + func showImage(_ image: UIImage) { + let imageView = UIImageView(image: image) imageView.translatesAutoresizingMaskIntoConstraints = false imageView.contentMode = .scaleAspectFit view.addSubview(imageView) @@ -54,7 +66,10 @@ class AssetPreviewViewController: UIViewController { imageView.topAnchor.constraint(equalTo: view.topAnchor), imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor) ]) - + preferredContentSize = image.size + } + + func showAssetImage(_ asset: PHAsset) { let options = PHImageRequestOptions() options.version = .current options.deliveryMode = .opportunistic @@ -62,13 +77,12 @@ class AssetPreviewViewController: UIViewController { options.isNetworkAccessAllowed = true PHImageManager.default().requestImage(for: asset, targetSize: view.bounds.size, contentMode: .aspectFit, options: options) { (image, _) in DispatchQueue.main.async { - imageView.image = image - self.preferredContentSize = image!.size + self.showImage(image!) } } } - func showLivePhoto() { + func showLivePhoto(_ asset: PHAsset) { let options = PHLivePhotoRequestOptions() options.deliveryMode = .opportunistic 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() options.deliveryMode = .automatic options.isNetworkAccessAllowed = true @@ -106,14 +131,7 @@ class AssetPreviewViewController: UIViewController { fatalError("failed to get AVAsset") } DispatchQueue.main.async { - let playerController = AVPlayerViewController() - 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 + self.showVideo(asset: avAsset) } } } diff --git a/Tusker/Screens/Compose/ComposeAttachmentsViewController.swift b/Tusker/Screens/Compose/ComposeAttachmentsViewController.swift index be3bfee3..920d2aef 100644 --- a/Tusker/Screens/Compose/ComposeAttachmentsViewController.swift +++ b/Tusker/Screens/Compose/ComposeAttachmentsViewController.swift @@ -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() { let sheetContainer = AssetPickerSheetContainerViewController() sheetContainer.assetPicker.assetPickerDelegate = self