mirror of
https://github.com/metabolist/metatext.git
synced 2024-11-24 09:10:59 +00:00
Media playing
This commit is contained in:
parent
fe6aa0f115
commit
f4cd293ec2
6 changed files with 67 additions and 11 deletions
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,5 +6,6 @@ import ServiceLayer
|
|||
public enum CollectionItemEvent {
|
||||
case ignorableOutput
|
||||
case navigation(Navigation)
|
||||
case attachment(AttachmentViewModel, StatusViewModel)
|
||||
case share(URL)
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue