fix: make blurhash display before video thumbnail ready

This commit is contained in:
CMK 2021-06-17 19:29:48 +08:00
parent a1b553a05d
commit f2795c035a
3 changed files with 51 additions and 5 deletions

View File

@ -27,7 +27,7 @@ public final class Attachment: NSManagedObject {
@NSManaged public private(set) var updatedAt: Date
@NSManaged public private(set) var index: NSNumber
// many-to-one relastionship
// many-to-one relationship
@NSManaged public private(set) var status: Status?
}

View File

@ -375,7 +375,7 @@ extension StatusSection {
return containerFrame.width
}()
let scale: CGFloat = 1.3
return CGSize(width: maxWidth, height: maxWidth * scale)
return CGSize(width: maxWidth, height: floor(maxWidth * scale))
}()
if let videoAttachment = mediaAttachments.filter({ $0.type == .gifv || $0.type == .video }).first,
@ -415,6 +415,28 @@ extension StatusSection {
}
playerContainerView.isHidden = false
// set blurhash overlay
playerContainerView.isReadyForDisplay
.receive(on: DispatchQueue.main)
.sink { [weak playerContainerView] isReadyForDisplay in
guard let playerContainerView = playerContainerView else { return }
playerContainerView.blurhashOverlayImageView.alpha = isReadyForDisplay ? 0 : 1
}
.store(in: &cell.disposeBag)
if let blurhash = videoAttachment.blurhash,
let url = URL(string: videoAttachment.url) {
AppContext.shared.blurhashImageCacheService.image(
blurhash: blurhash,
size: playerContainerView.playerViewController.view.frame.size,
url: url
)
.sink { image in
playerContainerView.blurhashOverlayImageView.image = image
}
.store(in: &cell.disposeBag)
}
} else {
cell.statusView.playerContainerView.playerViewController.player?.pause()
cell.statusView.playerContainerView.playerViewController.player = nil

View File

@ -8,6 +8,7 @@
import os.log
import AVKit
import UIKit
import Combine
protocol PlayerContainerViewDelegate: AnyObject {
func playerContainerView(_ playerContainerView: PlayerContainerView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView)
@ -28,10 +29,14 @@ final class PlayerContainerView: UIView {
let playerViewController = AVPlayerViewController()
let blurhashOverlayImageView = UIImageView()
let mediaTypeIndicatorView = MediaTypeIndicatorView()
weak var delegate: PlayerContainerViewDelegate?
private var isReadyForDisplayObservation: NSKeyValueObservation?
let isReadyForDisplay = CurrentValueSubject<Bool, Never>(false)
override init(frame: CGRect) {
super.init(frame: frame)
_init()
@ -64,6 +69,15 @@ extension PlayerContainerView {
playerViewController.view.layer.cornerRadius = PlayerContainerView.cornerRadius
playerViewController.view.layer.cornerCurve = .continuous
blurhashOverlayImageView.translatesAutoresizingMaskIntoConstraints = false
playerViewController.contentOverlayView!.addSubview(blurhashOverlayImageView)
NSLayoutConstraint.activate([
blurhashOverlayImageView.topAnchor.constraint(equalTo: playerViewController.contentOverlayView!.topAnchor),
blurhashOverlayImageView.leadingAnchor.constraint(equalTo: playerViewController.contentOverlayView!.leadingAnchor),
blurhashOverlayImageView.trailingAnchor.constraint(equalTo: playerViewController.contentOverlayView!.trailingAnchor),
blurhashOverlayImageView.bottomAnchor.constraint(equalTo: playerViewController.contentOverlayView!.bottomAnchor),
])
// mediaType
mediaTypeIndicatorView.translatesAutoresizingMaskIntoConstraints = false
playerViewController.contentOverlayView!.addSubview(mediaTypeIndicatorView)
@ -74,6 +88,12 @@ extension PlayerContainerView {
mediaTypeIndicatorView.widthAnchor.constraint(equalToConstant: MediaTypeIndicatorView.indicatorViewSize.width).priority(.required - 1),
])
isReadyForDisplayObservation = playerViewController.observe(\.isReadyForDisplay, options: [.initial, .new]) { [weak self] playerViewController, _ in
guard let self = self else { return }
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: isReadyForDisplay: %s", (#file as NSString).lastPathComponent, #line, #function, playerViewController.isReadyForDisplay.description)
self.isReadyForDisplay.value = playerViewController.isReadyForDisplay
}
contentWarningOverlayView.delegate = self
}
}
@ -94,6 +114,8 @@ extension PlayerContainerView {
playerViewController.view.removeFromSuperview()
playerViewController.removeFromParent()
blurhashOverlayImageView.image = nil
container.subviews.forEach { subview in
subview.removeFromSuperview()
}
@ -113,7 +135,7 @@ extension PlayerContainerView {
let rect = AVMakeRect(
aspectRatio: aspectRatio,
insideRect: CGRect(origin: .zero, size: maxSize)
)
).integral
parent?.addChild(playerViewController)
playerViewController.view.translatesAutoresizingMaskIntoConstraints = false
@ -124,11 +146,13 @@ extension PlayerContainerView {
playerViewController.view.leadingAnchor.constraint(equalTo: touchBlockingView.leadingAnchor),
playerViewController.view.trailingAnchor.constraint(equalTo: touchBlockingView.trailingAnchor),
playerViewController.view.bottomAnchor.constraint(equalTo: touchBlockingView.bottomAnchor),
touchBlockingView.widthAnchor.constraint(equalToConstant: floor(rect.width)).priority(.required - 1),
touchBlockingView.widthAnchor.constraint(equalToConstant: rect.width).priority(.required - 1),
])
containerHeightLayoutConstraint.constant = floor(rect.height)
containerHeightLayoutConstraint.constant = rect.height
containerHeightLayoutConstraint.isActive = true
playerViewController.view.frame.size = rect.size
contentWarningOverlayView.removeFromSuperview()
contentWarningOverlayView.translatesAutoresizingMaskIntoConstraints = false
addSubview(contentWarningOverlayView)