Media playing

This commit is contained in:
Justin Mazzocchi 2020-10-19 23:41:10 -07:00
parent fe6aa0f115
commit f4cd293ec2
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
6 changed files with 67 additions and 11 deletions

View file

@ -1,5 +1,6 @@
// Copyright © 2020 Metabolist. All rights reserved.
import AVKit
import Combine
import UIKit
@ -27,6 +28,8 @@ extension AppDelegate: UIApplicationDelegate {
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
self.application = application
try? AVAudioSession.sharedInstance().setCategory(.ambient, mode: .default)
return true
}

View file

@ -1,5 +1,6 @@
// Copyright © 2020 Metabolist. All rights reserved.
import AVKit
import Combine
import SafariServices
import SwiftUI
@ -170,6 +171,16 @@ extension TableViewController {
}
}
extension TableViewController: AVPlayerViewControllerDelegate {
func playerViewController(
_ playerViewController: AVPlayerViewController,
willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) {
try? AVAudioSession.sharedInstance().setCategory(.ambient, mode: .default)
playerViewController.player?.isMuted = true
updateAutoplayViews()
}
}
private extension TableViewController {
static let autoplayViews = [PlayerView](repeating: .init(), count: 4)
static var visibleVideoURLs = Set<URL>()
@ -250,7 +261,7 @@ private extension TableViewController {
break
case let .share(url):
share(url: url)
case let.navigation(navigation):
case let .navigation(navigation):
switch navigation {
case let .collection(collectionService):
show(TableViewController(
@ -273,6 +284,35 @@ private extension TableViewController {
case .webfingerEnd:
webfingerIndicatorView.stopAnimating()
}
case let .attachment(attachmentViewModel, statusViewModel):
present(attachmentViewModel: attachmentViewModel, statusViewModel: statusViewModel)
}
}
func present(attachmentViewModel: AttachmentViewModel, statusViewModel: StatusViewModel) {
switch attachmentViewModel.attachment.type {
case .audio, .video:
let playerViewController = AVPlayerViewController()
let player: AVPlayer
if attachmentViewModel.attachment.type == .video {
player = PlayerCache.shared.player(url: attachmentViewModel.attachment.url)
} else {
player = AVPlayer(url: attachmentViewModel.attachment.url)
}
playerViewController.delegate = self
playerViewController.player = player
present(playerViewController, animated: true) {
try? AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
player.isMuted = false
player.play()
}
case .image, .gifv:
break
case .unknown:
break
}
}

View file

@ -6,5 +6,6 @@ import ServiceLayer
public enum CollectionItemEvent {
case ignorableOutput
case navigation(Navigation)
case attachment(AttachmentViewModel, StatusViewModel)
case share(URL)
}

View file

@ -127,28 +127,28 @@ public extension StatusViewModel {
func toggleShowContent() {
eventsSubject.send(
statusService.toggleShowContent()
.map { _ in CollectionItemEvent.ignorableOutput }
.map { _ in .ignorableOutput }
.eraseToAnyPublisher())
}
func toggleShowAttachments() {
eventsSubject.send(
statusService.toggleShowAttachments()
.map { _ in CollectionItemEvent.ignorableOutput }
.map { _ in .ignorableOutput }
.eraseToAnyPublisher())
}
func urlSelected(_ url: URL) {
eventsSubject.send(
statusService.navigationService.item(url: url)
.map { CollectionItemEvent.navigation($0) }
.map { .navigation($0) }
.setFailureType(to: Error.self)
.eraseToAnyPublisher())
}
func accountSelected() {
eventsSubject.send(
Just(CollectionItemEvent.navigation(
Just(.navigation(
.profile(
statusService.navigationService.profileService(
account: statusService.status.displayStatus.account))))
@ -158,14 +158,14 @@ public extension StatusViewModel {
func rebloggedBySelected() {
eventsSubject.send(
Just(CollectionItemEvent.navigation(.collection(statusService.rebloggedByService())))
Just(.navigation(.collection(statusService.rebloggedByService())))
.setFailureType(to: Error.self)
.eraseToAnyPublisher())
}
func favoritedBySelected() {
eventsSubject.send(
Just(CollectionItemEvent.navigation(.collection(statusService.favoritedByService())))
Just(.navigation(.collection(statusService.favoritedByService())))
.setFailureType(to: Error.self)
.eraseToAnyPublisher())
}
@ -173,14 +173,18 @@ public extension StatusViewModel {
func toggleFavorited() {
eventsSubject.send(
statusService.toggleFavorited()
.map { _ in CollectionItemEvent.ignorableOutput }
.map { _ in .ignorableOutput }
.eraseToAnyPublisher())
}
func attachmentSelected(viewModel: AttachmentViewModel) {
eventsSubject.send(Just(.attachment(viewModel, self)).setFailureType(to: Error.self).eraseToAnyPublisher())
}
func shareStatus() {
guard let url = statusService.status.displayStatus.url else { return }
eventsSubject.send(Just(CollectionItemEvent.share(url)).setFailureType(to: Error.self).eraseToAnyPublisher())
eventsSubject.send(Just(.share(url)).setFailureType(to: Error.self).eraseToAnyPublisher())
}
}

View file

@ -109,6 +109,10 @@ private extension StatusAttachmentView {
switch viewModel.attachment.type {
case .image, .video, .gifv:
imageView.kf.setImage(with: viewModel.attachment.previewUrl)
case .audio:
playImageView.image = UIImage(systemName: "waveform.circle",
withConfiguration: UIImage.SymbolConfiguration(textStyle: .largeTitle))
backgroundColor = .secondarySystemBackground
default:
break
}

View file

@ -30,8 +30,12 @@ final class StatusAttachmentsView: UIView {
rightStackView.isHidden = attachmentCount == 1
for (index, viewModel) in attachmentViewModels.enumerated() {
let attachmentView = StatusAttachmentView(viewModel: viewModel)
for (index, attachmentViewModel) in attachmentViewModels.enumerated() {
let attachmentView = StatusAttachmentView(viewModel: attachmentViewModel)
attachmentView.button.addAction(
UIAction { [weak self] _ in self?.viewModel?.attachmentSelected(viewModel: attachmentViewModel) },
for: .touchUpInside)
if attachmentCount == 2 && index == 1
|| attachmentCount == 3 && index != 0