Merge pull request #62 from tootsuite/feature/gifVideoSupport-patch
Patch for delegate chain
This commit is contained in:
commit
37db8784bd
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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 }
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue