diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/MediaBadgesContainer.swift b/MastodonSDK/Sources/MastodonUI/View/Content/InlineMediaOverlayContainer.swift similarity index 69% rename from MastodonSDK/Sources/MastodonUI/View/Content/MediaBadgesContainer.swift rename to MastodonSDK/Sources/MastodonUI/View/Content/InlineMediaOverlayContainer.swift index acaddb164..16928d99e 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/MediaBadgesContainer.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/InlineMediaOverlayContainer.swift @@ -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) diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/MediaView.swift b/MastodonSDK/Sources/MastodonUI/View/Content/MediaView.swift index 2a61525e9..6155b0da5 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/MediaView.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/MediaView.swift @@ -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