From a6afe3e6ac1e3bcf60a8559336ecd48a45d355e8 Mon Sep 17 00:00:00 2001 From: CMK Date: Wed, 23 Jun 2021 23:34:38 +0800 Subject: [PATCH] fix: make content warning overlay toggle with cell height animation --- .../Section/NotificationSection.swift | 1 + .../Diffiable/Section/ReportSection.swift | 1 + .../Diffiable/Section/StatusSection.swift | 32 ++++++++++++++++--- .../Scene/Share/View/Content/StatusView.swift | 15 +++++---- 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/Mastodon/Diffiable/Section/NotificationSection.swift b/Mastodon/Diffiable/Section/NotificationSection.swift index 37a937f4f..984e8a54e 100644 --- a/Mastodon/Diffiable/Section/NotificationSection.swift +++ b/Mastodon/Diffiable/Section/NotificationSection.swift @@ -52,6 +52,7 @@ extension NotificationSection { let frame = CGRect(x: 0, y: 0, width: tableView.readableContentGuide.layoutFrame.width - NotificationStatusTableViewCell.statusPadding.left - NotificationStatusTableViewCell.statusPadding.right, height: tableView.readableContentGuide.layoutFrame.height) StatusSection.configure( cell: cell, + tableView: tableView, dependency: dependency, readableLayoutFrame: frame, status: status, diff --git a/Mastodon/Diffiable/Section/ReportSection.swift b/Mastodon/Diffiable/Section/ReportSection.swift index f45f4a79c..8a73aee0e 100644 --- a/Mastodon/Diffiable/Section/ReportSection.swift +++ b/Mastodon/Diffiable/Section/ReportSection.swift @@ -41,6 +41,7 @@ extension ReportSection { let status = managedObjectContext.object(with: objectID) as! Status StatusSection.configure( cell: cell, + tableView: tableView, dependency: dependency, readableLayoutFrame: tableView.readableContentGuide.layoutFrame, status: status, diff --git a/Mastodon/Diffiable/Section/StatusSection.swift b/Mastodon/Diffiable/Section/StatusSection.swift index 672022b17..acf14ca83 100644 --- a/Mastodon/Diffiable/Section/StatusSection.swift +++ b/Mastodon/Diffiable/Section/StatusSection.swift @@ -88,6 +88,7 @@ extension StatusSection { // configure cell configureStatusTableViewCell( cell: cell, + tableView: tableView, dependency: dependency, readableLayoutFrame: tableView.readableContentGuide.layoutFrame, status: status, @@ -109,6 +110,7 @@ extension StatusSection { let status = managedObjectContext.object(with: objectID) as! Status StatusSection.configure( cell: cell, + tableView: tableView, dependency: dependency, readableLayoutFrame: tableView.readableContentGuide.layoutFrame, status: status, @@ -189,6 +191,7 @@ extension StatusSection { static func configureStatusTableViewCell( cell: StatusTableViewCell, + tableView: UITableView, dependency: NeedsDependency, readableLayoutFrame: CGRect?, status: Status, @@ -197,6 +200,7 @@ extension StatusSection { ) { configure( cell: cell, + tableView: tableView, dependency: dependency, readableLayoutFrame: readableLayoutFrame, status: status, @@ -207,6 +211,7 @@ extension StatusSection { static func configure( cell: StatusCell, + tableView: UITableView, dependency: NeedsDependency, readableLayoutFrame: CGRect?, status: Status, @@ -253,6 +258,7 @@ extension StatusSection { StatusSection.configureContentWarningOverlay( statusView: cell.statusView, status: status, + tableView: tableView, attribute: statusItemAttribute, documentStore: dependency.context.documentStore, animated: false @@ -313,8 +319,9 @@ extension StatusSection { .receive(on: RunLoop.main) .sink { _ in // do nothing - } receiveValue: { [weak cell] change in + } receiveValue: { [weak cell, weak tableView] change in guard let cell = cell else { return } + guard let tableView = tableView else { return } guard case .update(let object) = change.changeType, let status = object as? Status, !status.isDeleted else { return @@ -323,6 +330,7 @@ extension StatusSection { StatusSection.configureContentWarningOverlay( statusView: cell.statusView, status: status, + tableView: tableView, attribute: statusItemAttribute, documentStore: dependency.context.documentStore, animated: true @@ -343,6 +351,7 @@ extension StatusSection { static func configureContentWarningOverlay( statusView: StatusView, status: Status, + tableView: UITableView, attribute: Item.StatusAttribute, documentStore: DocumentStore, animated: Bool @@ -370,13 +379,25 @@ extension StatusSection { statusView.playerContainerView.contentWarningOverlayView.isHidden = true if let revealedAt = status.revealedAt, revealedAt > appStartUpTimestamp { - statusView.updateRevealContentWarningButton(isRevealing: true) - statusView.updateContentWarningDisplay(isHidden: true, animated: animated) attribute.isRevealing.value = true + statusView.updateRevealContentWarningButton(isRevealing: true) + statusView.updateContentWarningDisplay(isHidden: true, animated: animated) { [weak tableView] in + guard animated else { return } + DispatchQueue.main.async { + tableView?.beginUpdates() + tableView?.endUpdates() + } + } } else { - statusView.updateRevealContentWarningButton(isRevealing: false) - statusView.updateContentWarningDisplay(isHidden: false, animated: animated) attribute.isRevealing.value = false + statusView.updateRevealContentWarningButton(isRevealing: false) + statusView.updateContentWarningDisplay(isHidden: false, animated: animated) { [weak tableView] in + guard animated else { return } + DispatchQueue.main.async { + tableView?.beginUpdates() + tableView?.endUpdates() + } + } } case .media(let isSensitive): if !isSensitive, documentStore.defaultRevealStatusDict[status.id] == nil { @@ -410,6 +431,7 @@ extension StatusSection { statusView.playerContainerView.contentWarningOverlayView.update(isRevealing: false, style: .media) } } + if animated { UIView.animate(withDuration: 0.33, delay: 0, options: .curveEaseInOut) { updateContentOverlay() diff --git a/Mastodon/Scene/Share/View/Content/StatusView.swift b/Mastodon/Scene/Share/View/Content/StatusView.swift index ef037e846..d6d3dfe25 100644 --- a/Mastodon/Scene/Share/View/Content/StatusView.swift +++ b/Mastodon/Scene/Share/View/Content/StatusView.swift @@ -349,7 +349,7 @@ extension StatusView { contentWarningOverlayView.translatesAutoresizingMaskIntoConstraints = false containerStackView.addSubview(contentWarningOverlayView) NSLayoutConstraint.activate([ - statusContainerStackView.topAnchor.constraint(equalTo: contentWarningOverlayView.topAnchor).priority(.defaultHigh), + statusContainerStackView.topAnchor.constraint(equalTo: contentWarningOverlayView.topAnchor).priority(.defaultHigh + 10), statusContainerStackView.leftAnchor.constraint(equalTo: contentWarningOverlayView.leftAnchor).priority(.defaultHigh), contentWarningOverlayView.rightAnchor.constraint(equalTo: statusContainerStackView.rightAnchor).priority(.defaultHigh), contentWarningOverlayView.bottomAnchor.constraint(equalTo: statusContainerStackView.bottomAnchor).priority(.defaultHigh), @@ -412,6 +412,7 @@ extension StatusView { containerStackView.addArrangedSubview(actionToolbarContainer) containerStackView.sendSubviewToBack(actionToolbarContainer) actionToolbarContainer.setContentCompressionResistancePriority(.defaultLow, for: .vertical) + actionToolbarContainer.setContentHuggingPriority(.required - 1, for: .vertical) headerContainerView.isHidden = true statusMosaicImageViewContainer.isHidden = true @@ -445,22 +446,24 @@ extension StatusView { extension StatusView { - func updateContentWarningDisplay(isHidden: Bool, animated: Bool) { + func updateContentWarningDisplay(isHidden: Bool, animated: Bool, completion: (() -> Void)? = nil) { func updateOverlayView() { contentWarningOverlayView.contentOverlayView.alpha = isHidden ? 0 : 1 contentWarningOverlayView.isUserInteractionEnabled = !isHidden } + contentWarningOverlayView.blurContentWarningTitleLabel.isHidden = isHidden + if animated { - let animator = UIViewPropertyAnimator(duration: 0.33, curve: .easeInOut) { + UIView.animate(withDuration: 0.33, delay: 0, options: .curveEaseInOut) { updateOverlayView() + } completion: { _ in + completion!() } - animator.startAnimation() } else { updateOverlayView() + completion?() } - - contentWarningOverlayView.blurContentWarningTitleLabel.isHidden = isHidden } func updateRevealContentWarningButton(isRevealing: Bool) {