Tusker/Tusker/Views/Attachments/GifvAttachmentView.swift

84 lines
2.6 KiB
Swift

//
// GifvAttachmentView.swift
// Tusker
//
// Created by Shadowfacts on 5/12/20.
// Copyright © 2020 Shadowfacts. All rights reserved.
//
import UIKit
import AVFoundation
class GifvAttachmentView: UIView {
override class var layerClass: AnyClass {
return AVPlayerLayer.self
}
private var playerLayer: AVPlayerLayer {
layer as! AVPlayerLayer
}
private var asset: AVAsset
private(set) var item: AVPlayerItem
let player: AVPlayer
private var isGrayscale = false
init(asset: AVAsset, gravity: AVLayerVideoGravity) {
self.asset = asset
item = GifvAttachmentView.createItem(asset: asset)
player = AVPlayer(playerItem: item)
isGrayscale = Preferences.shared.grayscaleImages
super.init(frame: .zero)
playerLayer.player = player
playerLayer.videoGravity = gravity
player.isMuted = true
NotificationCenter.default.addObserver(self, selector: #selector(restartItem), name: .AVPlayerItemDidPlayToEndTime, object: item)
NotificationCenter.default.addObserver(self, selector: #selector(preferencesChanged), name: .preferencesChanged, object: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private static func createItem(asset: AVAsset) -> AVPlayerItem {
let item = AVPlayerItem(asset: asset)
if Preferences.shared.grayscaleImages {
#if os(visionOS)
#warning("Use async AVVideoComposition CIFilter initializer")
#else
item.videoComposition = AVVideoComposition(asset: asset, applyingCIFiltersWithHandler: { (request) in
let filter = CIFilter(name: "CIColorMonochrome")!
filter.setValue(request.sourceImage, forKey: "inputImage")
filter.setValue(CIColor(red: 0.85, green: 0.85, blue: 0.85), forKey: "inputColor")
filter.setValue(1.0, forKey: "inputIntensity")
request.finish(with: filter.outputImage!, context: nil)
})
#endif
}
return item
}
@objc private func preferencesChanged() {
if isGrayscale != Preferences.shared.grayscaleImages {
isGrayscale = Preferences.shared.grayscaleImages
item = GifvAttachmentView.createItem(asset: asset)
player.replaceCurrentItem(with: item)
player.play()
}
}
@objc private func restartItem() {
item.seek(to: .zero) { (success) in
guard success else { return }
self.player.play()
}
}
}