123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- //
- // MediaPreviewVideoViewController.swift
- // Mastodon
- //
- // Created by MainasuK on 2022-2-9.
- //
- import os.log
- import UIKit
- import AVKit
- import Combine
- import func AVFoundation.AVMakeRect
- final class MediaPreviewVideoViewController: UIViewController {
-
- let logger = Logger(subsystem: "MediaPreviewVideoViewController", category: "ViewController")
-
- var disposeBag = Set<AnyCancellable>()
- var viewModel: MediaPreviewVideoViewModel!
-
- let playerViewController = AVPlayerViewController()
-
- let previewImageView = UIImageView()
-
- deinit {
- os_log("%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
- playerViewController.player?.pause()
- try? AVAudioSession.sharedInstance().setCategory(.ambient)
- try? AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
- }
-
- }
- extension MediaPreviewVideoViewController {
-
- override func viewDidLoad() {
- super.viewDidLoad()
-
- addChild(playerViewController)
- playerViewController.view.translatesAutoresizingMaskIntoConstraints = false
- view.addSubview(playerViewController.view)
- NSLayoutConstraint.activate([
- playerViewController.view.centerXAnchor.constraint(equalTo: view.centerXAnchor),
- playerViewController.view.centerYAnchor.constraint(equalTo: view.centerYAnchor),
- playerViewController.view.widthAnchor.constraint(equalTo: view.widthAnchor),
- playerViewController.view.heightAnchor.constraint(equalTo: view.heightAnchor),
- ])
-
- if let contentOverlayView = playerViewController.contentOverlayView {
- previewImageView.translatesAutoresizingMaskIntoConstraints = false
- contentOverlayView.addSubview(previewImageView)
- NSLayoutConstraint.activate([
- previewImageView.topAnchor.constraint(equalTo: contentOverlayView.topAnchor),
- previewImageView.leadingAnchor.constraint(equalTo: contentOverlayView.leadingAnchor),
- previewImageView.trailingAnchor.constraint(equalTo: contentOverlayView.trailingAnchor),
- previewImageView.bottomAnchor.constraint(equalTo: contentOverlayView.bottomAnchor),
- ])
- }
-
- playerViewController.delegate = self
- playerViewController.view.backgroundColor = .clear
- playerViewController.player = viewModel.player
- playerViewController.allowsPictureInPicturePlayback = true
-
- switch viewModel.item {
- case .video:
- break
- case .gif:
- playerViewController.showsPlaybackControls = false
- }
-
- viewModel.player?.play()
- viewModel.playbackState = .playing
-
- if let previewURL = viewModel.item.previewURL {
- previewImageView.contentMode = .scaleAspectFit
- previewImageView.af.setImage(
- withURL: previewURL,
- placeholderImage: .placeholder(color: .systemFill)
- )
-
- playerViewController.publisher(for: \.isReadyForDisplay)
- .receive(on: DispatchQueue.main)
- .sink { [weak self] isReadyForDisplay in
- guard let self = self else { return }
- self.previewImageView.isHidden = isReadyForDisplay
- }
- .store(in: &disposeBag)
- }
- }
-
- override func viewDidLayoutSubviews() {
- super.viewDidLayoutSubviews()
- playerViewController.didMove(toParent: self)
- }
-
- }
- // MARK: - ShareActivityProvider
- //extension MediaPreviewVideoViewController: ShareActivityProvider {
- // var activities: [Any] {
- // return []
- // }
- //
- // var applicationActivities: [UIActivity] {
- // switch viewModel.item {
- // case .gif(let mediaContext):
- // guard let url = mediaContext.assetURL else { return [] }
- // return [
- // SavePhotoActivity(context: viewModel.context, url: url, resourceType: .video)
- // ]
- // default:
- // return []
- // }
- // }
- //}
- // MARK: - AVPlayerViewControllerDelegate
- extension MediaPreviewVideoViewController: AVPlayerViewControllerDelegate {
-
- }
- // MARK: - MediaPreviewTransitionViewController
- extension MediaPreviewVideoViewController: MediaPreviewTransitionViewController {
- var mediaPreviewTransitionContext: MediaPreviewTransitionContext? {
- guard let playerView = playerViewController.view else { return nil }
- let _currentFrame: UIImage? = {
- guard let player = playerViewController.player else { return nil }
- guard let asset = player.currentItem?.asset else { return nil }
- let assetImageGenerator = AVAssetImageGenerator(asset: asset)
- assetImageGenerator.appliesPreferredTrackTransform = true // fix orientation
- do {
- let cgImage = try assetImageGenerator.copyCGImage(at: player.currentTime(), actualTime: nil)
- let image = UIImage(cgImage: cgImage)
- return image
- } catch {
- return previewImageView.image
- }
- }()
- let _snapshot: UIView? = {
- guard let currentFrame = _currentFrame else { return nil }
- let size = AVMakeRect(aspectRatio: currentFrame.size, insideRect: view.frame).size
- let imageView = UIImageView(frame: CGRect(origin: .zero, size: size))
- imageView.image = currentFrame
- return imageView
- }()
- guard let snapshot = _snapshot else {
- return nil
- }
-
- return MediaPreviewTransitionContext(
- transitionView: playerView,
- snapshot: snapshot,
- snapshotTransitioning: snapshot
- )
- }
- }
|