From 707eef959e9ccd22fb4ca29e4aa5e2c9deec94cf Mon Sep 17 00:00:00 2001 From: Justin Mazzocchi <2831158+jzzocc@users.noreply.github.com> Date: Fri, 5 Mar 2021 13:50:01 -0800 Subject: [PATCH] Preview video and audio captions while captioning --- Extensions/AVAudioSession+Extensions.swift | 27 +++++++++++ Metatext.xcodeproj/project.pbxproj | 6 +++ .../EditAttachmentViewController.swift | 48 +++++++++++++++---- View Controllers/TableViewController.swift | 4 +- 4 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 Extensions/AVAudioSession+Extensions.swift diff --git a/Extensions/AVAudioSession+Extensions.swift b/Extensions/AVAudioSession+Extensions.swift new file mode 100644 index 0000000..6ba9219 --- /dev/null +++ b/Extensions/AVAudioSession+Extensions.swift @@ -0,0 +1,27 @@ +// Copyright © 2021 Metabolist. All rights reserved. + +import AVKit + +extension AVAudioSession { + static func incrementPresentedPlayerViewControllerCount() { + presentedPlayerViewControllerCount += 1 + } + + static func decrementPresentedPlayerViewControllerCount() { + presentedPlayerViewControllerCount -= 1 + } +} + +private extension AVAudioSession { + static var presentedPlayerViewControllerCount = 0 { + didSet { + let instance = sharedInstance() + + if presentedPlayerViewControllerCount > 0, instance.category != .playback { + try? instance.setCategory(.playback, mode: .default) + } else if instance.category != .ambient { + try? instance.setCategory(.ambient, mode: .default) + } + } + } +} diff --git a/Metatext.xcodeproj/project.pbxproj b/Metatext.xcodeproj/project.pbxproj index 44ba9cc..1d2f162 100644 --- a/Metatext.xcodeproj/project.pbxproj +++ b/Metatext.xcodeproj/project.pbxproj @@ -142,6 +142,8 @@ D0B5FE9B251583DB00478838 /* ProfileCollection+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B5FE9A251583DB00478838 /* ProfileCollection+Extensions.swift */; }; D0B8510C25259E56004E0744 /* LoadMoreTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B8510B25259E56004E0744 /* LoadMoreTableViewCell.swift */; }; D0BE633125F2C409001139FA /* CapsuleLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0477F4525C72E50005C5368 /* CapsuleLabel.swift */; }; + D0BE633725F2D95E001139FA /* AVAudioSession+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE633625F2D95E001139FA /* AVAudioSession+Extensions.swift */; }; + D0BE634025F2DB98001139FA /* AVAudioSession+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE633625F2D95E001139FA /* AVAudioSession+Extensions.swift */; }; D0BE97A325CF44310057E161 /* CGRect+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE97A225CF44310057E161 /* CGRect+Extensions.swift */; }; D0BE97D725D0863E0057E161 /* ImagePastableTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE97D625D0863E0057E161 /* ImagePastableTextView.swift */; }; D0BE97E025D086F80057E161 /* ImagePastableTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE97D625D0863E0057E161 /* ImagePastableTextView.swift */; }; @@ -376,6 +378,7 @@ D0B5FE9A251583DB00478838 /* ProfileCollection+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProfileCollection+Extensions.swift"; sourceTree = ""; }; D0B8510B25259E56004E0744 /* LoadMoreTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadMoreTableViewCell.swift; sourceTree = ""; }; D0BDF66524FD7A6400C7FA1C /* ServiceLayer */ = {isa = PBXFileReference; lastKnownFileType = folder; path = ServiceLayer; sourceTree = ""; }; + D0BE633625F2D95E001139FA /* AVAudioSession+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AVAudioSession+Extensions.swift"; sourceTree = ""; }; D0BE97A225CF44310057E161 /* CGRect+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGRect+Extensions.swift"; sourceTree = ""; }; D0BE97D625D0863E0057E161 /* ImagePastableTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePastableTextView.swift; sourceTree = ""; }; D0BE980325D229D50057E161 /* SeparatorConfiguredTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorConfiguredTableViewCell.swift; sourceTree = ""; }; @@ -819,6 +822,7 @@ isa = PBXGroup; children = ( D00CB22925C92C0F008EF267 /* Attachment+Extensions.swift */, + D0BE633625F2D95E001139FA /* AVAudioSession+Extensions.swift */, D05E688425B55AE8001FB2C6 /* AVURLAsset+Extensions.swift */, D0BE97A225CF44310057E161 /* CGRect+Extensions.swift */, D0F0B135251AA12700942152 /* CollectionItem+Extensions.swift */, @@ -1125,6 +1129,7 @@ D0C7D49A24F7616A001EBDBB /* TableView.swift in Sources */, D08B8D622540DE3B00B1EBEF /* ZoomTransitionController.swift in Sources */, D0F0B12E251A97E400942152 /* TableViewController.swift in Sources */, + D0BE633725F2D95E001139FA /* AVAudioSession+Extensions.swift in Sources */, D0477F2C25C6EBAD005C5368 /* OpenInDefaultBrowserActivity.swift in Sources */, D07F4D9825D493E300F61133 /* MuteView.swift in Sources */, D02D338D25EDA593000A35CC /* CopyableLabel.swift in Sources */, @@ -1278,6 +1283,7 @@ D05936D025A8D79800754FDF /* EditAttachmentViewController.swift in Sources */, D0CEC10A25E3381500FEF5A6 /* AnimatedTextAttachment.swift in Sources */, D08E52EF257D757100FA2C5F /* CompositionView.swift in Sources */, + D0BE634025F2DB98001139FA /* AVAudioSession+Extensions.swift in Sources */, D07EC7FE25B16994006DF726 /* EmojiCategoryHeaderView.swift in Sources */, D0CE9F88258B076900E3A6B6 /* AttachmentUploadView.swift in Sources */, D0CEC11A25E34BFE00FEF5A6 /* AnimatingLayoutManager.swift in Sources */, diff --git a/View Controllers/EditAttachmentViewController.swift b/View Controllers/EditAttachmentViewController.swift index de779f0..9d888bc 100644 --- a/View Controllers/EditAttachmentViewController.swift +++ b/View Controllers/EditAttachmentViewController.swift @@ -1,5 +1,6 @@ // Copyright © 2021 Metabolist. All rights reserved. +import AVKit import Combine import UIKit import ViewModels @@ -21,16 +22,47 @@ final class EditAttachmentViewController: UIViewController { fatalError("init(coder:) has not been implemented") } + deinit { + if let playerViewController = + children.first(where: { $0 is AVPlayerViewController }) as? AVPlayerViewController { + playerViewController.player?.isMuted = true + AVAudioSession.decrementPresentedPlayerViewControllerCount() + } + } + // swiftlint:disable:next function_body_length override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBackground - let editThumbnailView = EditThumbnailView(viewModel: viewModel) + let trailingView: UIView - view.addSubview(editThumbnailView) - editThumbnailView.translatesAutoresizingMaskIntoConstraints = false + switch viewModel.attachment.type { + case .image, .gifv: + trailingView = EditThumbnailView(viewModel: viewModel) + view.addSubview(trailingView) + default: + let playerViewController = AVPlayerViewController() + let player: AVPlayer + + if viewModel.attachment.type == .video { + player = PlayerCache.shared.player(url: viewModel.attachment.url) + } else { + player = AVPlayer(url: viewModel.attachment.url) + } + + player.isMuted = false + playerViewController.player = player + + trailingView = playerViewController.view + addChild(playerViewController) + view.addSubview(trailingView) + playerViewController.didMove(toParent: self) + AVAudioSession.incrementPresentedPlayerViewControllerCount() + } + + trailingView.translatesAutoresizingMaskIntoConstraints = false let stackView = UIStackView() @@ -76,14 +108,14 @@ final class EditAttachmentViewController: UIViewController { NSLayoutConstraint.activate([ stackView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor), stackView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor, constant: .defaultSpacing), - editThumbnailView.leadingAnchor.constraint(equalTo: stackView.trailingAnchor, constant: .defaultSpacing), + trailingView.leadingAnchor.constraint(equalTo: stackView.trailingAnchor, constant: .defaultSpacing), stackView.bottomAnchor.constraint( equalTo: view.layoutMarginsGuide.bottomAnchor, constant: -.defaultSpacing), - editThumbnailView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), - editThumbnailView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), - editThumbnailView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), - editThumbnailView.widthAnchor.constraint(equalTo: stackView.widthAnchor, multiplier: 3 / 2) + trailingView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + trailingView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + trailingView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), + trailingView.widthAnchor.constraint(equalTo: stackView.widthAnchor, multiplier: 3 / 2) ]) viewModel.$descriptionRemainingCharacters diff --git a/View Controllers/TableViewController.swift b/View Controllers/TableViewController.swift index 9615a70..3c11ec5 100644 --- a/View Controllers/TableViewController.swift +++ b/View Controllers/TableViewController.swift @@ -320,8 +320,8 @@ extension TableViewController: AVPlayerViewControllerDelegate { func playerViewController( _ playerViewController: AVPlayerViewController, willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) { - try? AVAudioSession.sharedInstance().setCategory(.ambient, mode: .default) playerViewController.player?.isMuted = true + AVAudioSession.decrementPresentedPlayerViewControllerCount() coordinator.animate(alongsideTransition: nil) { _ in if self.shouldKeepPlayingVideoAfterDismissal { @@ -586,7 +586,7 @@ private extension TableViewController { shouldKeepPlayingVideoAfterDismissal = attachmentViewModel.shouldAutoplay present(playerViewController, animated: true) { - try? AVAudioSession.sharedInstance().setCategory(.playback, mode: .default) + AVAudioSession.incrementPresentedPlayerViewControllerCount() player.isMuted = false player.play() }