Merge pull request #62 from tootsuite/feature/gifVideoSupport-patch

Patch for delegate chain
This commit is contained in:
CMK 2021-03-12 10:20:19 +08:00 committed by GitHub
commit 37db8784bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 114 additions and 86 deletions

View File

@ -60,7 +60,7 @@
2D61335E25C1894B00CAE157 /* APIService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D61335D25C1894B00CAE157 /* APIService.swift */; }; 2D61335E25C1894B00CAE157 /* APIService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D61335D25C1894B00CAE157 /* APIService.swift */; };
2D61336925C18A4F00CAE157 /* AlamofireNetworkActivityIndicator in Frameworks */ = {isa = PBXBuildFile; productRef = 2D61336825C18A4F00CAE157 /* AlamofireNetworkActivityIndicator */; }; 2D61336925C18A4F00CAE157 /* AlamofireNetworkActivityIndicator in Frameworks */ = {isa = PBXBuildFile; productRef = 2D61336825C18A4F00CAE157 /* AlamofireNetworkActivityIndicator */; };
2D650FAB25ECDC9300851B58 /* Mastodon+Entity+Error+Detail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D650FAA25ECDC9300851B58 /* Mastodon+Entity+Error+Detail.swift */; }; 2D650FAB25ECDC9300851B58 /* Mastodon+Entity+Error+Detail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D650FAA25ECDC9300851B58 /* Mastodon+Entity+Error+Detail.swift */; };
2D694A7425F9EB4E0038ADDC /* MosaicBlurView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D694A7325F9EB4E0038ADDC /* MosaicBlurView.swift */; }; 2D694A7425F9EB4E0038ADDC /* ContentWarningOverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D694A7325F9EB4E0038ADDC /* ContentWarningOverlayView.swift */; };
2D69CFF425CA9E2200C3A1B2 /* LoadMoreConfigurableTableViewContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D69CFF325CA9E2200C3A1B2 /* LoadMoreConfigurableTableViewContainer.swift */; }; 2D69CFF425CA9E2200C3A1B2 /* LoadMoreConfigurableTableViewContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D69CFF325CA9E2200C3A1B2 /* LoadMoreConfigurableTableViewContainer.swift */; };
2D69D00A25CAA00300C3A1B2 /* APIService+CoreData+Toot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D69D00925CAA00300C3A1B2 /* APIService+CoreData+Toot.swift */; }; 2D69D00A25CAA00300C3A1B2 /* APIService+CoreData+Toot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D69D00925CAA00300C3A1B2 /* APIService+CoreData+Toot.swift */; };
2D76316525C14BD100929FB9 /* PublicTimelineViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D76316425C14BD100929FB9 /* PublicTimelineViewController.swift */; }; 2D76316525C14BD100929FB9 /* PublicTimelineViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D76316425C14BD100929FB9 /* PublicTimelineViewController.swift */; };
@ -94,7 +94,7 @@
5DF1054125F886D400D6C0D4 /* ViedeoPlaybackService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DF1054025F886D400D6C0D4 /* ViedeoPlaybackService.swift */; }; 5DF1054125F886D400D6C0D4 /* ViedeoPlaybackService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DF1054025F886D400D6C0D4 /* ViedeoPlaybackService.swift */; };
5DF1054725F8870E00D6C0D4 /* VideoPlayerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DF1054625F8870E00D6C0D4 /* VideoPlayerViewModel.swift */; }; 5DF1054725F8870E00D6C0D4 /* VideoPlayerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DF1054625F8870E00D6C0D4 /* VideoPlayerViewModel.swift */; };
5DF1056425F887CB00D6C0D4 /* AVPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DF1056325F887CB00D6C0D4 /* AVPlayer.swift */; }; 5DF1056425F887CB00D6C0D4 /* AVPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DF1056325F887CB00D6C0D4 /* AVPlayer.swift */; };
5DF1057925F88A1D00D6C0D4 /* MosaicPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DF1057825F88A1D00D6C0D4 /* MosaicPlayerView.swift */; }; 5DF1057925F88A1D00D6C0D4 /* PlayerContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DF1057825F88A1D00D6C0D4 /* PlayerContainerView.swift */; };
5DF1057F25F88A4100D6C0D4 /* TouchBlockingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DF1057E25F88A4100D6C0D4 /* TouchBlockingView.swift */; }; 5DF1057F25F88A4100D6C0D4 /* TouchBlockingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DF1057E25F88A4100D6C0D4 /* TouchBlockingView.swift */; };
5DF1058525F88AE500D6C0D4 /* NeedsDependency+AVPlayerViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DF1058425F88AE500D6C0D4 /* NeedsDependency+AVPlayerViewControllerDelegate.swift */; }; 5DF1058525F88AE500D6C0D4 /* NeedsDependency+AVPlayerViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DF1058425F88AE500D6C0D4 /* NeedsDependency+AVPlayerViewControllerDelegate.swift */; };
5E0DEC05797A7E6933788DDB /* Pods_MastodonTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 452147B2903DF38070FE56A2 /* Pods_MastodonTests.framework */; }; 5E0DEC05797A7E6933788DDB /* Pods_MastodonTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 452147B2903DF38070FE56A2 /* Pods_MastodonTests.framework */; };
@ -302,7 +302,7 @@
2D61335725C188A000CAE157 /* APIService+Persist+Timeline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Persist+Timeline.swift"; sourceTree = "<group>"; }; 2D61335725C188A000CAE157 /* APIService+Persist+Timeline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Persist+Timeline.swift"; sourceTree = "<group>"; };
2D61335D25C1894B00CAE157 /* APIService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIService.swift; sourceTree = "<group>"; }; 2D61335D25C1894B00CAE157 /* APIService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIService.swift; sourceTree = "<group>"; };
2D650FAA25ECDC9300851B58 /* Mastodon+Entity+Error+Detail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Mastodon+Entity+Error+Detail.swift"; sourceTree = "<group>"; }; 2D650FAA25ECDC9300851B58 /* Mastodon+Entity+Error+Detail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Mastodon+Entity+Error+Detail.swift"; sourceTree = "<group>"; };
2D694A7325F9EB4E0038ADDC /* MosaicBlurView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MosaicBlurView.swift; sourceTree = "<group>"; }; 2D694A7325F9EB4E0038ADDC /* ContentWarningOverlayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentWarningOverlayView.swift; sourceTree = "<group>"; };
2D69CFF325CA9E2200C3A1B2 /* LoadMoreConfigurableTableViewContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadMoreConfigurableTableViewContainer.swift; sourceTree = "<group>"; }; 2D69CFF325CA9E2200C3A1B2 /* LoadMoreConfigurableTableViewContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadMoreConfigurableTableViewContainer.swift; sourceTree = "<group>"; };
2D69D00925CAA00300C3A1B2 /* APIService+CoreData+Toot.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "APIService+CoreData+Toot.swift"; sourceTree = "<group>"; }; 2D69D00925CAA00300C3A1B2 /* APIService+CoreData+Toot.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "APIService+CoreData+Toot.swift"; sourceTree = "<group>"; };
2D76316425C14BD100929FB9 /* PublicTimelineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublicTimelineViewController.swift; sourceTree = "<group>"; }; 2D76316425C14BD100929FB9 /* PublicTimelineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublicTimelineViewController.swift; sourceTree = "<group>"; };
@ -339,7 +339,7 @@
5DF1054025F886D400D6C0D4 /* ViedeoPlaybackService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViedeoPlaybackService.swift; sourceTree = "<group>"; }; 5DF1054025F886D400D6C0D4 /* ViedeoPlaybackService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViedeoPlaybackService.swift; sourceTree = "<group>"; };
5DF1054625F8870E00D6C0D4 /* VideoPlayerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerViewModel.swift; sourceTree = "<group>"; }; 5DF1054625F8870E00D6C0D4 /* VideoPlayerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerViewModel.swift; sourceTree = "<group>"; };
5DF1056325F887CB00D6C0D4 /* AVPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AVPlayer.swift; sourceTree = "<group>"; }; 5DF1056325F887CB00D6C0D4 /* AVPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AVPlayer.swift; sourceTree = "<group>"; };
5DF1057825F88A1D00D6C0D4 /* MosaicPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MosaicPlayerView.swift; sourceTree = "<group>"; }; 5DF1057825F88A1D00D6C0D4 /* PlayerContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerContainerView.swift; sourceTree = "<group>"; };
5DF1057E25F88A4100D6C0D4 /* TouchBlockingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TouchBlockingView.swift; sourceTree = "<group>"; }; 5DF1057E25F88A4100D6C0D4 /* TouchBlockingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TouchBlockingView.swift; sourceTree = "<group>"; };
5DF1058425F88AE500D6C0D4 /* NeedsDependency+AVPlayerViewControllerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NeedsDependency+AVPlayerViewControllerDelegate.swift"; sourceTree = "<group>"; }; 5DF1058425F88AE500D6C0D4 /* NeedsDependency+AVPlayerViewControllerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NeedsDependency+AVPlayerViewControllerDelegate.swift"; sourceTree = "<group>"; };
75E3471C898DDD9631729B6E /* Pods-Mastodon.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.release.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.release.xcconfig"; sourceTree = "<group>"; }; 75E3471C898DDD9631729B6E /* Pods-Mastodon.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.release.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.release.xcconfig"; sourceTree = "<group>"; };
@ -578,6 +578,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
2D152A8B25C295CC009AA50C /* StatusView.swift */, 2D152A8B25C295CC009AA50C /* StatusView.swift */,
2D694A7325F9EB4E0038ADDC /* ContentWarningOverlayView.swift */,
); );
path = Content; path = Content;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1179,9 +1180,8 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
DB9D6C0D25E4F9780051B173 /* MosaicImageViewContainer.swift */, DB9D6C0D25E4F9780051B173 /* MosaicImageViewContainer.swift */,
2D694A7325F9EB4E0038ADDC /* MosaicBlurView.swift */,
2D206B7125F5D27F00143C56 /* AudioContainerView.swift */, 2D206B7125F5D27F00143C56 /* AudioContainerView.swift */,
5DF1057825F88A1D00D6C0D4 /* MosaicPlayerView.swift */, 5DF1057825F88A1D00D6C0D4 /* PlayerContainerView.swift */,
5DF1057E25F88A4100D6C0D4 /* TouchBlockingView.swift */, 5DF1057E25F88A4100D6C0D4 /* TouchBlockingView.swift */,
); );
path = Container; path = Container;
@ -1635,7 +1635,7 @@
2D45E5BF25C9549700A6D639 /* PublicTimelineViewModel+State.swift in Sources */, 2D45E5BF25C9549700A6D639 /* PublicTimelineViewModel+State.swift in Sources */,
DB8AF55D25C138B7002E6C99 /* UIViewController.swift in Sources */, DB8AF55D25C138B7002E6C99 /* UIViewController.swift in Sources */,
2D3F9E0425DFA133004262D9 /* UITapGestureRecognizer.swift in Sources */, 2D3F9E0425DFA133004262D9 /* UITapGestureRecognizer.swift in Sources */,
2D694A7425F9EB4E0038ADDC /* MosaicBlurView.swift in Sources */, 2D694A7425F9EB4E0038ADDC /* ContentWarningOverlayView.swift in Sources */,
DB4481CC25EE2AFE00BEFB67 /* PollItem.swift in Sources */, DB4481CC25EE2AFE00BEFB67 /* PollItem.swift in Sources */,
DB4563BD25E11A24004DA0B9 /* KeyboardResponderService.swift in Sources */, DB4563BD25E11A24004DA0B9 /* KeyboardResponderService.swift in Sources */,
DB5086BE25CC0D9900C2C187 /* SplashPreference.swift in Sources */, DB5086BE25CC0D9900C2C187 /* SplashPreference.swift in Sources */,
@ -1711,7 +1711,7 @@
0FB3D30825E524C600AAD544 /* PickServerCategoriesCell.swift in Sources */, 0FB3D30825E524C600AAD544 /* PickServerCategoriesCell.swift in Sources */,
2D38F1FE25CD481700561493 /* StatusProvider.swift in Sources */, 2D38F1FE25CD481700561493 /* StatusProvider.swift in Sources */,
0FB3D31E25E534C700AAD544 /* PickServerCategoryCollectionViewCell.swift in Sources */, 0FB3D31E25E534C700AAD544 /* PickServerCategoryCollectionViewCell.swift in Sources */,
5DF1057925F88A1D00D6C0D4 /* MosaicPlayerView.swift in Sources */, 5DF1057925F88A1D00D6C0D4 /* PlayerContainerView.swift in Sources */,
DB45FB0F25CA87D0005A8AC7 /* AuthenticationService.swift in Sources */, DB45FB0F25CA87D0005A8AC7 /* AuthenticationService.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;

View File

@ -193,22 +193,16 @@ extension StatusSection {
return CGSize(width: maxWidth, height: maxWidth * scale) return CGSize(width: maxWidth, height: maxWidth * scale)
}() }()
cell.statusView.mosaicPlayerView.mosaicBlurView.blurVisualEffectView.effect = isStatusSensitive ? MosaicImageViewContainer.blurVisualEffect : nil cell.statusView.playerContainerView.contentWarningOverlayView.blurVisualEffectView.effect = isStatusSensitive ? MosaicImageViewContainer.blurVisualEffect : nil
cell.statusView.mosaicPlayerView.mosaicBlurView.vibrancyVisualEffectView.alpha = isStatusSensitive ? 1.0 : 0.0 cell.statusView.playerContainerView.contentWarningOverlayView.vibrancyVisualEffectView.alpha = isStatusSensitive ? 1.0 : 0.0
cell.statusView.mosaicPlayerView.mosaicBlurView.isUserInteractionEnabled = isStatusSensitive cell.statusView.playerContainerView.contentWarningOverlayView.isUserInteractionEnabled = isStatusSensitive
cell.statusView.mosaicPlayerView.mosaicBlurView.tapButton.publisher(for: .touchUpInside)
.sink { [weak cell] _ in
guard let cell = cell else { return }
cell.delegate?.statusTableViewCell(cell, mosaicBlurView: cell.statusView.mosaicPlayerView.mosaicBlurView, didTapContentWarningVisualEffectView: cell.statusView.mosaicPlayerView.mosaicBlurView.blurVisualEffectView)
}
.store(in: &cell.disposeBag)
if let videoAttachment = mediaAttachments.filter({ $0.type == .gifv || $0.type == .video }).first, if let videoAttachment = mediaAttachments.filter({ $0.type == .gifv || $0.type == .video }).first,
let videoPlayerViewModel = dependency.context.videoPlaybackService.dequeueVideoPlayerViewModel(for: videoAttachment) let videoPlayerViewModel = dependency.context.videoPlaybackService.dequeueVideoPlayerViewModel(for: videoAttachment)
{ {
let parent = cell.delegate?.parent() let parent = cell.delegate?.parent()
let mosaicPlayerView = cell.statusView.mosaicPlayerView let playerContainerView = cell.statusView.playerContainerView
let playerViewController = mosaicPlayerView.setupPlayer( let playerViewController = playerContainerView.setupPlayer(
aspectRatio: videoPlayerViewModel.videoSize, aspectRatio: videoPlayerViewModel.videoSize,
maxSize: playerViewMaxSize, maxSize: playerViewMaxSize,
parent: parent parent: parent
@ -217,12 +211,12 @@ extension StatusSection {
playerViewController.player = videoPlayerViewModel.player playerViewController.player = videoPlayerViewModel.player
playerViewController.showsPlaybackControls = videoPlayerViewModel.videoKind != .gif playerViewController.showsPlaybackControls = videoPlayerViewModel.videoKind != .gif
mosaicPlayerView.gifIndicatorLabel.isHidden = videoPlayerViewModel.videoKind != .gif playerContainerView.gifIndicatorLabel.isHidden = videoPlayerViewModel.videoKind != .gif
mosaicPlayerView.isHidden = false playerContainerView.isHidden = false
} else { } else {
cell.statusView.mosaicPlayerView.playerViewController.player?.pause() cell.statusView.playerContainerView.playerViewController.player?.pause()
cell.statusView.mosaicPlayerView.playerViewController.player = nil cell.statusView.playerContainerView.playerViewController.player = nil
} }
// set poll // set poll
let poll = (toot.reblog ?? toot).poll let poll = (toot.reblog ?? toot).poll

View File

@ -46,29 +46,6 @@ extension StatusTableViewCellDelegate where Self: StatusProvider {
} }
func statusTableViewCell(_ cell: StatusTableViewCell, mosaicBlurView: MosaicBlurView, didTapContentWarningVisualEffectView visualEffectView: UIVisualEffectView) {
guard let diffableDataSource = self.tableViewDiffableDataSource else { return }
guard let item = item(for: cell, indexPath: nil) else { return }
switch item {
case .homeTimelineIndex(_, let attribute):
attribute.isStatusSensitive = false
case .toot(_, let attribute):
attribute.isStatusSensitive = false
default:
return
}
mosaicBlurView.isUserInteractionEnabled = false
var snapshot = diffableDataSource.snapshot()
snapshot.reloadItems([item])
UIView.animate(withDuration: 0.33) {
mosaicBlurView.blurVisualEffectView.effect = nil
mosaicBlurView.vibrancyVisualEffectView.alpha = 0.0
} completion: { _ in
diffableDataSource.apply(snapshot, animatingDifferences: false, completion: nil)
}
}
func statusTableViewCell(_ cell: StatusTableViewCell, mosaicImageViewContainer: MosaicImageViewContainer, didTapContentWarningVisualEffectView visualEffectView: UIVisualEffectView) { func statusTableViewCell(_ cell: StatusTableViewCell, mosaicImageViewContainer: MosaicImageViewContainer, didTapContentWarningVisualEffectView visualEffectView: UIVisualEffectView) {
guard let diffableDataSource = self.tableViewDiffableDataSource else { return } guard let diffableDataSource = self.tableViewDiffableDataSource else { return }
guard let item = item(for: cell, indexPath: nil) else { return } guard let item = item(for: cell, indexPath: nil) else { return }
@ -92,6 +69,29 @@ extension StatusTableViewCellDelegate where Self: StatusProvider {
} }
} }
func statusTableViewCell(_ cell: StatusTableViewCell, playerContainerView: PlayerContainerView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView) {
guard let diffableDataSource = self.tableViewDiffableDataSource else { return }
guard let item = item(for: cell, indexPath: nil) else { return }
switch item {
case .homeTimelineIndex(_, let attribute):
attribute.isStatusSensitive = false
case .toot(_, let attribute):
attribute.isStatusSensitive = false
default:
return
}
contentWarningOverlayView.isUserInteractionEnabled = false
var snapshot = diffableDataSource.snapshot()
snapshot.reloadItems([item])
UIView.animate(withDuration: 0.33) {
contentWarningOverlayView.blurVisualEffectView.effect = nil
contentWarningOverlayView.vibrancyVisualEffectView.alpha = 0.0
} completion: { _ in
diffableDataSource.apply(snapshot, animatingDifferences: false, completion: nil)
}
}
} }
// MARK: - PollTableView // MARK: - PollTableView

View File

@ -1,5 +1,5 @@
// //
// MosaicPlayerView.swift // PlayerContainerView.swift
// Mastodon // Mastodon
// //
// Created by xiaojian sun on 2021/3/10. // Created by xiaojian sun on 2021/3/10.
@ -8,16 +8,20 @@
import AVKit import AVKit
import UIKit import UIKit
final class MosaicPlayerView: UIView { protocol PlayerContainerViewDelegate: class {
func playerContainerView(_ playerContainerView: PlayerContainerView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView)
}
final class PlayerContainerView: UIView {
static let cornerRadius: CGFloat = 8 static let cornerRadius: CGFloat = 8
private let container = UIView() private let container = UIView()
private let touchBlockingView = TouchBlockingView() private let touchBlockingView = TouchBlockingView()
private var containerHeightLayoutConstraint: NSLayoutConstraint! private var containerHeightLayoutConstraint: NSLayoutConstraint!
let mosaicBlurView: MosaicBlurView = { let contentWarningOverlayView: ContentWarningOverlayView = {
let mosaicBlurView = MosaicBlurView() let contentWarningOverlayView = ContentWarningOverlayView()
return mosaicBlurView return contentWarningOverlayView
}() }()
let playerViewController = AVPlayerViewController() let playerViewController = AVPlayerViewController()
@ -30,6 +34,8 @@ final class MosaicPlayerView: UIView {
return label return label
}() }()
weak var delegate: PlayerContainerViewDelegate?
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
_init() _init()
@ -41,7 +47,7 @@ final class MosaicPlayerView: UIView {
} }
} }
extension MosaicPlayerView { extension PlayerContainerView {
private func _init() { private func _init() {
container.translatesAutoresizingMaskIntoConstraints = false container.translatesAutoresizingMaskIntoConstraints = false
addSubview(container) addSubview(container)
@ -64,20 +70,29 @@ extension MosaicPlayerView {
// will not influence full-screen playback // will not influence full-screen playback
playerViewController.view.layer.masksToBounds = true playerViewController.view.layer.masksToBounds = true
playerViewController.view.layer.cornerRadius = MosaicPlayerView.cornerRadius playerViewController.view.layer.cornerRadius = PlayerContainerView.cornerRadius
playerViewController.view.layer.cornerCurve = .continuous playerViewController.view.layer.cornerCurve = .continuous
addSubview(mosaicBlurView) addSubview(contentWarningOverlayView)
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
mosaicBlurView.topAnchor.constraint(equalTo: topAnchor), contentWarningOverlayView.topAnchor.constraint(equalTo: topAnchor),
mosaicBlurView.leadingAnchor.constraint(equalTo: leadingAnchor), contentWarningOverlayView.leadingAnchor.constraint(equalTo: leadingAnchor),
mosaicBlurView.trailingAnchor.constraint(equalTo: trailingAnchor), contentWarningOverlayView.trailingAnchor.constraint(equalTo: trailingAnchor),
mosaicBlurView.bottomAnchor.constraint(equalTo: bottomAnchor) contentWarningOverlayView.bottomAnchor.constraint(equalTo: bottomAnchor)
]) ])
contentWarningOverlayView.delegate = self
} }
} }
extension MosaicPlayerView { // MARK: - ContentWarningOverlayViewDelegate
extension PlayerContainerView: ContentWarningOverlayViewDelegate {
func contentWarningOverlayViewDidPressed(_ contentWarningOverlayView: ContentWarningOverlayView) {
delegate?.playerContainerView(self, contentWarningOverlayViewDidPressed: contentWarningOverlayView)
}
}
extension PlayerContainerView {
func reset() { func reset() {
// note: set playerViewController.player pause() and nil in data source configuration process make reloadData not break playing // note: set playerViewController.player pause() and nil in data source configuration process make reloadData not break playing

View File

@ -1,25 +1,24 @@
// //
// MosaicView.swift // ContentWarningOverlayView.swift
// Mastodon // Mastodon
// //
// Created by sxiaojian on 2021/3/11. // Created by sxiaojian on 2021/3/11.
// //
import os.log
import Foundation import Foundation
import UIKit import UIKit
class MosaicBlurView: UIView { protocol ContentWarningOverlayViewDelegate: class {
func contentWarningOverlayViewDidPressed(_ contentWarningOverlayView: ContentWarningOverlayView)
}
class ContentWarningOverlayView: UIView {
static let cornerRadius: CGFloat = 4 static let cornerRadius: CGFloat = 4
static let blurVisualEffect = UIBlurEffect(style: .systemUltraThinMaterial) static let blurVisualEffect = UIBlurEffect(style: .systemUltraThinMaterial)
let blurVisualEffectView = UIVisualEffectView(effect: MosaicBlurView.blurVisualEffect) let blurVisualEffectView = UIVisualEffectView(effect: ContentWarningOverlayView.blurVisualEffect)
let vibrancyVisualEffectView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: MosaicBlurView.blurVisualEffect)) let vibrancyVisualEffectView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: ContentWarningOverlayView.blurVisualEffect))
let tapButton: UIButton = {
let button = UIButton(type: .custom)
button.backgroundColor = .clear
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
let contentWarningLabel: UILabel = { let contentWarningLabel: UILabel = {
let label = UILabel() let label = UILabel()
@ -29,6 +28,10 @@ class MosaicBlurView: UIView {
return label return label
}() }()
let tapGestureRecognizer = UITapGestureRecognizer.singleTapGestureRecognizer
weak var delegate: ContentWarningOverlayViewDelegate?
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
_init() _init()
@ -40,14 +43,14 @@ class MosaicBlurView: UIView {
} }
} }
extension MosaicBlurView { extension ContentWarningOverlayView {
private func _init() { private func _init() {
backgroundColor = .clear backgroundColor = .clear
translatesAutoresizingMaskIntoConstraints = false translatesAutoresizingMaskIntoConstraints = false
// add blur visual effect view in the setup method // add blur visual effect view in the setup method
blurVisualEffectView.layer.masksToBounds = true blurVisualEffectView.layer.masksToBounds = true
blurVisualEffectView.layer.cornerRadius = MosaicBlurView.cornerRadius blurVisualEffectView.layer.cornerRadius = ContentWarningOverlayView.cornerRadius
blurVisualEffectView.layer.cornerCurve = .continuous blurVisualEffectView.layer.cornerCurve = .continuous
vibrancyVisualEffectView.translatesAutoresizingMaskIntoConstraints = false vibrancyVisualEffectView.translatesAutoresizingMaskIntoConstraints = false
@ -76,12 +79,14 @@ extension MosaicBlurView {
blurVisualEffectView.bottomAnchor.constraint(equalTo: bottomAnchor), blurVisualEffectView.bottomAnchor.constraint(equalTo: bottomAnchor),
]) ])
addSubview(tapButton) tapGestureRecognizer.addTarget(self, action: #selector(ContentWarningOverlayView.tapGestureRecognizerHandler(_:)))
NSLayoutConstraint.activate([ addGestureRecognizer(tapGestureRecognizer)
tapButton.topAnchor.constraint(equalTo: topAnchor), }
tapButton.trailingAnchor.constraint(equalTo: trailingAnchor), }
tapButton.bottomAnchor.constraint(equalTo: bottomAnchor),
tapButton.leadingAnchor.constraint(equalTo: leadingAnchor), extension ContentWarningOverlayView {
]) @objc private func tapGestureRecognizerHandler(_ sender: UITapGestureRecognizer) {
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
delegate?.contentWarningOverlayViewDidPressed(self)
} }
} }

View File

@ -13,6 +13,7 @@ import AlamofireImage
protocol StatusViewDelegate: class { protocol StatusViewDelegate: class {
func statusView(_ statusView: StatusView, contentWarningActionButtonPressed button: UIButton) func statusView(_ statusView: StatusView, contentWarningActionButtonPressed button: UIButton)
func statusView(_ statusView: StatusView, playerContainerView: PlayerContainerView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView)
func statusView(_ statusView: StatusView, pollVoteButtonPressed button: UIButton) func statusView(_ statusView: StatusView, pollVoteButtonPressed button: UIButton)
} }
@ -156,7 +157,7 @@ final class StatusView: UIView {
return imageView return imageView
}() }()
let mosaicPlayerView = MosaicPlayerView() let playerContainerView = PlayerContainerView()
let audioView: AudioContainerView = { let audioView: AudioContainerView = {
let audioView = AudioContainerView() let audioView = AudioContainerView()
@ -353,7 +354,7 @@ extension StatusView {
audioView.heightAnchor.constraint(equalToConstant: 44) audioView.heightAnchor.constraint(equalToConstant: 44)
]) ])
// video gif // video gif
statusContainerStackView.addArrangedSubview(mosaicPlayerView) statusContainerStackView.addArrangedSubview(playerContainerView)
// action toolbar container // action toolbar container
containerStackView.addArrangedSubview(actionToolbarContainer) containerStackView.addArrangedSubview(actionToolbarContainer)
@ -364,12 +365,14 @@ extension StatusView {
pollTableView.isHidden = true pollTableView.isHidden = true
pollStatusStackView.isHidden = true pollStatusStackView.isHidden = true
audioView.isHidden = true audioView.isHidden = true
mosaicPlayerView.isHidden = true playerContainerView.isHidden = true
contentWarningBlurContentImageView.isHidden = true contentWarningBlurContentImageView.isHidden = true
statusContentWarningContainerStackView.isHidden = true statusContentWarningContainerStackView.isHidden = true
statusContentWarningContainerStackViewBottomLayoutConstraint.isActive = false statusContentWarningContainerStackViewBottomLayoutConstraint.isActive = false
playerContainerView.delegate = self
contentWarningActionButton.addTarget(self, action: #selector(StatusView.contentWarningActionButtonPressed(_:)), for: .touchUpInside) contentWarningActionButton.addTarget(self, action: #selector(StatusView.contentWarningActionButtonPressed(_:)), for: .touchUpInside)
pollVoteButton.addTarget(self, action: #selector(StatusView.pollVoteButtonPressed(_:)), for: .touchUpInside) pollVoteButton.addTarget(self, action: #selector(StatusView.pollVoteButtonPressed(_:)), for: .touchUpInside)
} }
@ -420,6 +423,13 @@ extension StatusView {
} }
// MARK: - PlayerContainerViewDelegate
extension StatusView: PlayerContainerViewDelegate {
func playerContainerView(_ playerContainerView: PlayerContainerView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView) {
delegate?.statusView(self, playerContainerView: playerContainerView, contentWarningOverlayViewDidPressed: contentWarningOverlayView)
}
}
// MARK: - AvatarConfigurableView // MARK: - AvatarConfigurableView
extension StatusView: AvatarConfigurableView { extension StatusView: AvatarConfigurableView {
static var configurableAvatarImageSize: CGSize { return Self.avatarImageSize } static var configurableAvatarImageSize: CGSize { return Self.avatarImageSize }

View File

@ -23,8 +23,8 @@ protocol StatusTableViewCellDelegate: class {
func statusTableViewCell(_ cell: StatusTableViewCell, statusView: StatusView, contentWarningActionButtonPressed button: UIButton) func statusTableViewCell(_ cell: StatusTableViewCell, statusView: StatusView, contentWarningActionButtonPressed button: UIButton)
func statusTableViewCell(_ cell: StatusTableViewCell, mosaicImageViewContainer: MosaicImageViewContainer, didTapContentWarningVisualEffectView visualEffectView: UIVisualEffectView) func statusTableViewCell(_ cell: StatusTableViewCell, mosaicImageViewContainer: MosaicImageViewContainer, didTapContentWarningVisualEffectView visualEffectView: UIVisualEffectView)
func statusTableViewCell(_ cell: StatusTableViewCell, mosaicBlurView: MosaicBlurView, didTapContentWarningVisualEffectView visualEffectView: UIVisualEffectView)
func statusTableViewCell(_ cell: StatusTableViewCell, mosaicImageViewContainer: MosaicImageViewContainer, didTapImageView imageView: UIImageView, atIndex index: Int) func statusTableViewCell(_ cell: StatusTableViewCell, mosaicImageViewContainer: MosaicImageViewContainer, didTapImageView imageView: UIImageView, atIndex index: Int)
func statusTableViewCell(_ cell: StatusTableViewCell, playerContainerView: PlayerContainerView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView)
func statusTableViewCell(_ cell: StatusTableViewCell, actionToolbarContainer: ActionToolbarContainer, likeButtonDidPressed sender: UIButton) func statusTableViewCell(_ cell: StatusTableViewCell, actionToolbarContainer: ActionToolbarContainer, likeButtonDidPressed sender: UIButton)
func statusTableViewCell(_ cell: StatusTableViewCell, statusView: StatusView, pollVoteButtonPressed button: UIButton) func statusTableViewCell(_ cell: StatusTableViewCell, statusView: StatusView, pollVoteButtonPressed button: UIButton)
@ -55,8 +55,8 @@ final class StatusTableViewCell: UITableViewCell {
statusView.isStatusTextSensitive = false statusView.isStatusTextSensitive = false
statusView.cleanUpContentWarning() statusView.cleanUpContentWarning()
statusView.pollTableView.dataSource = nil statusView.pollTableView.dataSource = nil
statusView.mosaicPlayerView.reset() statusView.playerContainerView.reset()
statusView.mosaicPlayerView.isHidden = true statusView.playerContainerView.isHidden = true
disposeBag.removeAll() disposeBag.removeAll()
observations.removeAll() observations.removeAll()
} }
@ -198,6 +198,10 @@ extension StatusTableViewCell: StatusViewDelegate {
delegate?.statusTableViewCell(self, statusView: statusView, contentWarningActionButtonPressed: button) delegate?.statusTableViewCell(self, statusView: statusView, contentWarningActionButtonPressed: button)
} }
func statusView(_ statusView: StatusView, playerContainerView: PlayerContainerView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView) {
delegate?.statusTableViewCell(self, playerContainerView: playerContainerView, contentWarningOverlayViewDidPressed: contentWarningOverlayView)
}
func statusView(_ statusView: StatusView, pollVoteButtonPressed button: UIButton) { func statusView(_ statusView: StatusView, pollVoteButtonPressed button: UIButton) {
delegate?.statusTableViewCell(self, statusView: statusView, pollVoteButtonPressed: button) delegate?.statusTableViewCell(self, statusView: statusView, pollVoteButtonPressed: button)
} }