Merge pull request #1058 from j-f1/video-play-button
IOS-119 Video attachment adjustments
This commit is contained in:
commit
8b69ff3acd
|
@ -1,17 +1,23 @@
|
|||
//
|
||||
// MediaBadgesContainer.swift
|
||||
// InlineMediaOverlayContainer.swift
|
||||
//
|
||||
// Created by Jed Fox on 2022-12-20.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct MediaBadgesContainer: View {
|
||||
struct InlineMediaOverlayContainer: View {
|
||||
var altDescription: String?
|
||||
var isGIF = false
|
||||
var mediaType: MediaType = .image
|
||||
var showDuration = false
|
||||
var mediaDuration: TimeInterval?
|
||||
|
||||
|
||||
enum MediaType {
|
||||
case image
|
||||
case gif
|
||||
case video
|
||||
}
|
||||
|
||||
@State private var showingAlt = false
|
||||
@State private var space = AnyHashable(UUID())
|
||||
|
||||
|
@ -35,7 +41,7 @@ struct MediaBadgesContainer: View {
|
|||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
}
|
||||
if isGIF {
|
||||
if mediaType == .gif {
|
||||
MediaBadge("GIF")
|
||||
}
|
||||
if showDuration {
|
||||
|
@ -52,6 +58,20 @@ struct MediaBadgesContainer: View {
|
|||
}
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.vertical, 8)
|
||||
.overlay {
|
||||
if mediaType == .video {
|
||||
Image(systemName: "play.circle.fill")
|
||||
.font(.system(size: 54))
|
||||
.foregroundColor(.white)
|
||||
.shadow(color: .black.opacity(0.5), radius: 32, x: 0, y: 0)
|
||||
.background(alignment: .center) {
|
||||
Circle()
|
||||
.fill(.ultraThinMaterial)
|
||||
.frame(width: 40, height: 40)
|
||||
.colorScheme(.light)
|
||||
}
|
||||
}
|
||||
}
|
||||
.onChange(of: altDescription) { _ in
|
||||
showingAlt = false
|
||||
}
|
||||
|
@ -60,7 +80,7 @@ struct MediaBadgesContainer: View {
|
|||
|
||||
struct MediaAltTextOverlay_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
MediaBadgesContainer(altDescription: "Hello, world!")
|
||||
InlineMediaOverlayContainer(altDescription: "Hello, world!")
|
||||
.frame(height: 300)
|
||||
.background(Color.gray)
|
||||
.previewLayout(.sizeThatFits)
|
|
@ -51,23 +51,8 @@ public final class MediaView: UIView {
|
|||
}()
|
||||
private var playerLooper: AVPlayerLooper?
|
||||
|
||||
private(set) lazy var playbackImageView: UIView = {
|
||||
let wrapper = UIView()
|
||||
|
||||
let imageView = UIImageView()
|
||||
imageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
imageView.image = UIImage(systemName: "play.circle.fill")
|
||||
imageView.tintColor = Asset.Colors.Label.primary.color
|
||||
wrapper.addSubview(imageView)
|
||||
imageView.pinToParent(padding: .init(top: 8, left: 8, bottom: 8, right: 8))
|
||||
wrapper.backgroundColor = Asset.Theme.Mastodon.systemBackground.color.withAlphaComponent(0.8)
|
||||
wrapper.applyCornerRadius(radius: 8)
|
||||
|
||||
return wrapper
|
||||
}()
|
||||
|
||||
let badgeViewController: UIHostingController<MediaBadgesContainer> = {
|
||||
let vc = UIHostingController(rootView: MediaBadgesContainer())
|
||||
let overlayViewController: UIHostingController<InlineMediaOverlayContainer> = {
|
||||
let vc = UIHostingController(rootView: InlineMediaOverlayContainer())
|
||||
vc.view.backgroundColor = .clear
|
||||
return vc
|
||||
}()
|
||||
|
@ -112,14 +97,17 @@ extension MediaView {
|
|||
switch configuration.info {
|
||||
case .image(let info):
|
||||
layoutImage()
|
||||
overlayViewController.rootView.mediaType = .image
|
||||
bindImage(configuration: configuration, info: info)
|
||||
accessibilityHint = L10n.Common.Controls.Status.Media.expandImageHint
|
||||
case .gif(let info):
|
||||
layoutGIF()
|
||||
overlayViewController.rootView.mediaType = .gif
|
||||
bindGIF(configuration: configuration, info: info)
|
||||
accessibilityHint = L10n.Common.Controls.Status.Media.expandGifHint
|
||||
case .video(let info):
|
||||
layoutVideo()
|
||||
overlayViewController.rootView.mediaType = .video
|
||||
bindVideo(configuration: configuration, info: info)
|
||||
accessibilityHint = L10n.Common.Controls.Status.Media.expandVideoHint
|
||||
}
|
||||
|
@ -167,8 +155,8 @@ extension MediaView {
|
|||
}
|
||||
|
||||
private func bindGIF(configuration: Configuration, info: Configuration.VideoInfo) {
|
||||
badgeViewController.rootView.mediaDuration = info.durationMS.map { Double($0) / 1000 }
|
||||
badgeViewController.rootView.showDuration = false
|
||||
overlayViewController.rootView.mediaDuration = info.durationMS.map { Double($0) / 1000 }
|
||||
overlayViewController.rootView.showDuration = false
|
||||
|
||||
guard let player = setupGIFPlayer(info: info) else { return }
|
||||
setupPlayerLooper(player: player)
|
||||
|
@ -178,27 +166,16 @@ extension MediaView {
|
|||
// auto play for GIF
|
||||
player.play()
|
||||
|
||||
badgeViewController.rootView.isGIF = true
|
||||
|
||||
bindAlt(configuration: configuration, altDescription: info.altDescription)
|
||||
}
|
||||
|
||||
private func layoutVideo() {
|
||||
layoutImage()
|
||||
|
||||
playbackImageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
container.addSubview(playbackImageView)
|
||||
NSLayoutConstraint.activate([
|
||||
playbackImageView.centerXAnchor.constraint(equalTo: container.centerXAnchor),
|
||||
playbackImageView.centerYAnchor.constraint(equalTo: container.centerYAnchor),
|
||||
playbackImageView.widthAnchor.constraint(equalToConstant: 88).priority(.required - 1),
|
||||
playbackImageView.heightAnchor.constraint(equalToConstant: 88).priority(.required - 1),
|
||||
])
|
||||
}
|
||||
|
||||
private func bindVideo(configuration: Configuration, info: Configuration.VideoInfo) {
|
||||
badgeViewController.rootView.mediaDuration = info.durationMS.map { Double($0) / 1000 }
|
||||
badgeViewController.rootView.showDuration = true
|
||||
overlayViewController.rootView.mediaDuration = info.durationMS.map { Double($0) / 1000 }
|
||||
overlayViewController.rootView.showDuration = true
|
||||
|
||||
let imageInfo = Configuration.ImageInfo(
|
||||
aspectRadio: info.aspectRadio,
|
||||
|
@ -219,7 +196,7 @@ extension MediaView {
|
|||
accessibilityLabel = altDescription
|
||||
}
|
||||
|
||||
badgeViewController.rootView.altDescription = altDescription
|
||||
overlayViewController.rootView.altDescription = altDescription
|
||||
}
|
||||
|
||||
private func layoutBlurhash() {
|
||||
|
@ -251,9 +228,9 @@ extension MediaView {
|
|||
}
|
||||
|
||||
private func layoutAlt() {
|
||||
badgeViewController.view.translatesAutoresizingMaskIntoConstraints = false
|
||||
container.addSubview(badgeViewController.view)
|
||||
badgeViewController.view.pinToParent()
|
||||
overlayViewController.view.translatesAutoresizingMaskIntoConstraints = false
|
||||
container.addSubview(overlayViewController.view)
|
||||
overlayViewController.view.pinToParent()
|
||||
}
|
||||
|
||||
public func prepareForReuse() {
|
||||
|
@ -277,8 +254,6 @@ extension MediaView {
|
|||
playerViewController.player = nil
|
||||
playerLooper = nil
|
||||
|
||||
playbackImageView.removeFromSuperview()
|
||||
|
||||
// blurhash
|
||||
blurhashImageView.removeFromSuperview()
|
||||
blurhashImageView.removeConstraints(blurhashImageView.constraints)
|
||||
|
@ -288,10 +263,9 @@ extension MediaView {
|
|||
container.removeFromSuperview()
|
||||
container.removeConstraints(container.constraints)
|
||||
|
||||
badgeViewController.rootView.altDescription = nil
|
||||
badgeViewController.rootView.isGIF = false
|
||||
badgeViewController.rootView.showDuration = false
|
||||
badgeViewController.rootView.mediaDuration = nil
|
||||
overlayViewController.rootView.altDescription = nil
|
||||
overlayViewController.rootView.showDuration = false
|
||||
overlayViewController.rootView.mediaDuration = nil
|
||||
|
||||
// reset configuration
|
||||
configuration = nil
|
||||
|
|
Loading…
Reference in New Issue