Tusker/Tusker/Screens/Attachment Gallery/VideoGalleryContentViewCont...

133 lines
3.9 KiB
Swift

//
// VideoGalleryContentViewController.swift
// Tusker
//
// Created by Shadowfacts on 3/19/24.
// Copyright © 2024 Shadowfacts. All rights reserved.
//
import UIKit
import GalleryVC
import AVFoundation
class VideoGalleryContentViewController: UIViewController, GalleryContentViewController {
private let url: URL
let caption: String?
private let item: AVPlayerItem
private let player: AVPlayer
private var presentationSizeObservation: NSKeyValueObservation?
private var statusObservation: NSKeyValueObservation?
private var isFirstAppearance = true
init(url: URL, caption: String?) {
self.url = url
self.caption = caption
let asset = AVAsset(url: url)
self.item = AVPlayerItem(asset: asset)
self.player = AVPlayer(playerItem: item)
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
container?.setGalleryContentLoading(true)
let playerView = PlayerView(item: item, player: player)
playerView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(playerView)
NSLayoutConstraint.activate([
playerView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
playerView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
playerView.topAnchor.constraint(equalTo: view.topAnchor),
playerView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
])
presentationSizeObservation = item.observe(\.presentationSize, changeHandler: { [unowned self] _, _ in
MainActor.runUnsafely {
self.container?.galleryContentChanged()
}
})
statusObservation = item.observe(\.status, changeHandler: { [unowned self] item, _ in
MainActor.runUnsafely {
if item.status == .readyToPlay {
self.container?.setGalleryContentLoading(false)
statusObservation = nil
}
}
})
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if isFirstAppearance {
isFirstAppearance = false
player.play()
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
player.pause()
}
// MARK: GalleryContentViewController
var container: (any GalleryVC.GalleryContentViewControllerContainer)?
var contentSize: CGSize {
item.presentationSize
}
var activityItemsForSharing: [Any] {
// TODO: share videos
[]
}
}
private class PlayerView: UIView {
override class var layerClass: AnyClass {
AVPlayerLayer.self
}
private var playerLayer: AVPlayerLayer {
layer as! AVPlayerLayer
}
private let player: AVPlayer
private var presentationSizeObservation: NSKeyValueObservation?
override var intrinsicContentSize: CGSize {
player.currentItem?.presentationSize ?? CGSize(width: UIView.noIntrinsicMetric, height: UIView.noIntrinsicMetric)
}
init(item: AVPlayerItem, player: AVPlayer) {
self.player = player
super.init(frame: .zero)
playerLayer.player = player
playerLayer.videoGravity = .resizeAspect
presentationSizeObservation = item.observe(\.presentationSize, changeHandler: { [unowned self] _, _ in
MainActor.runUnsafely {
self.invalidateIntrinsicContentSize()
}
})
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}