diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/MediaView+Configuration.swift b/MastodonSDK/Sources/MastodonUI/View/Content/MediaView+Configuration.swift index 0505b8077..a372ce558 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/MediaView+Configuration.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/MediaView+Configuration.swift @@ -180,7 +180,7 @@ extension MediaView.Configuration { } extension MediaView { - public static func configuration(status: MastodonStatus) -> [MediaView.Configuration] { + public static func configuration(status: MastodonStatus, contentDisplayMode: StatusView.ContentDisplayMode) -> [MediaView.Configuration] { func videoInfo(from attachment: MastodonAttachment) -> MediaView.Configuration.VideoInfo { MediaView.Configuration.VideoInfo( aspectRadio: attachment.size, @@ -234,6 +234,7 @@ extension MediaView { } // end switch }() + configuration.isReveal = !contentDisplayMode.shouldConcealMedia configuration.load() return configuration @@ -244,7 +245,7 @@ extension MediaView { } extension MediaView { - public static func configuration(status: Mastodon.Entity.StatusEdit) -> [MediaView.Configuration] { + public static func configuration(status: Mastodon.Entity.StatusEdit, contentDisplayMode: StatusView.ContentDisplayMode) -> [MediaView.Configuration] { func aspectRatio(from attachment: Mastodon.Entity.Attachment) -> CGSize? { if let width = attachment.meta?.original?.width, let height = attachment.meta?.original?.height { return CGSize(width: width, height: height) @@ -317,7 +318,7 @@ extension MediaView { }() configuration?.load() - configuration?.isReveal = true + configuration?.isReveal = !contentDisplayMode.shouldConcealMedia return configuration } diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/MediaView.swift b/MastodonSDK/Sources/MastodonUI/View/Content/MediaView.swift index a23fc4d55..6a0de9134 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/MediaView.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/MediaView.swift @@ -43,15 +43,17 @@ public final class MediaView: UIView { return imageView }() - private(set) lazy var playerViewController: AVPlayerViewController = { + private(set) var playerViewController: AVPlayerViewController? + private var playerLooper: AVPlayerLooper? + + private func createPlayerViewController() -> AVPlayerViewController { let playerViewController = AVPlayerViewController() playerViewController.view.layer.masksToBounds = true playerViewController.view.isUserInteractionEnabled = false playerViewController.videoGravity = .resizeAspectFill playerViewController.updatesNowPlayingInfoCenter = false return playerViewController - }() - private var playerLooper: AVPlayerLooper? + } let overlayViewController: UIHostingController = { let vc = UIHostingController(rootView: InlineMediaOverlayContainer()) @@ -152,6 +154,10 @@ extension MediaView { private func layoutGIF() { // use view controller as View here + if playerViewController == nil { + playerViewController = createPlayerViewController() + } + guard let playerViewController else { return } playerViewController.view.translatesAutoresizingMaskIntoConstraints = false container.addSubview(playerViewController.view) playerViewController.view.pinToParent() @@ -165,11 +171,21 @@ extension MediaView { guard let player = setupGIFPlayer(info: info) else { return } setupPlayerLooper(player: player) + + if playerViewController == nil { + playerViewController = createPlayerViewController() + } + guard let playerViewController else { return } playerViewController.player = player playerViewController.showsPlaybackControls = false // auto play for GIF - player.play() + if configuration.isReveal { + blurhashImageView.alpha = 0 + player.play() + } else { + blurhashImageView.alpha = 1 + } bindAlt(configuration: configuration, altDescription: info.altDescription) } @@ -241,12 +257,12 @@ extension MediaView { imageView.image = nil // reset player - playerViewController.view.removeFromSuperview() - playerViewController.contentOverlayView.flatMap { view in + playerViewController?.view.removeFromSuperview() + playerViewController?.contentOverlayView.flatMap { view in view.removeConstraints(view.constraints) } - playerViewController.player?.pause() - playerViewController.player = nil + playerViewController?.player?.pause() + playerViewController?.player = nil playerLooper = nil // blurhash diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/StatusView+Configuration.swift b/MastodonSDK/Sources/MastodonUI/View/Content/StatusView+Configuration.swift index fe5f6d5fe..5d69e757c 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/StatusView+Configuration.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/StatusView+Configuration.swift @@ -49,12 +49,12 @@ extension StatusView { configureAuthor(author: author) configureTimestamp(timestamp: (status.reblog ?? status).entity.createdAt) configureApplicationName(status.entity.application?.name) - configureMedia(status: status) + configureMedia(status: status, contentDisplayMode: contentDisplayMode) configurePollHistory(statusEdit: statusEdit) configureCard(status: status) configureToolbar(status: status) configureContent(statusEdit: statusEdit, status: status) - configureMedia(status: statusEdit) + configureMedia(status: statusEdit, contentDisplayMode: contentDisplayMode) actionToolbarAdaptiveMarginContainerView.isHidden = true authorView.menuButton.isHidden = true headerAdaptiveMarginContainerView.isHidden = true @@ -72,7 +72,7 @@ extension StatusView { configureTimestamp(timestamp: timestamp) configureApplicationName(status.entity.application?.name) configureContent(status: status) - configureMedia(status: status) + configureMedia(status: status, contentDisplayMode: contentDisplayMode) configurePoll(status: status) configureCard(status: status) configureToolbar(status: status) @@ -451,14 +451,14 @@ extension StatusView { viewModel.visibility = status.entity.mastodonVisibility } - private func configureMedia(status: MastodonStatus) { + private func configureMedia(status: MastodonStatus, contentDisplayMode: ContentDisplayMode) { let status = status.reblog ?? status - let configurations = MediaView.configuration(status: status) + let configurations = MediaView.configuration(status: status, contentDisplayMode: contentDisplayMode) viewModel.mediaViewConfigurations = configurations } - private func configureMedia(status: Mastodon.Entity.StatusEdit) { - let configurations = MediaView.configuration(status: status) + private func configureMedia(status: Mastodon.Entity.StatusEdit, contentDisplayMode: ContentDisplayMode) { + let configurations = MediaView.configuration(status: status, contentDisplayMode: contentDisplayMode) viewModel.mediaViewConfigurations = configurations }