diff --git a/Mastodon/Diffiable/Section/ComposeStatusSection.swift b/Mastodon/Diffiable/Section/ComposeStatusSection.swift index 0e7c574b4..d42caa404 100644 --- a/Mastodon/Diffiable/Section/ComposeStatusSection.swift +++ b/Mastodon/Diffiable/Section/ComposeStatusSection.swift @@ -81,10 +81,10 @@ extension ComposeStatusSection { managedObjectContext.perform { guard let replyToStatusObjectID = replyToStatusObjectID, let replyTo = managedObjectContext.object(with: replyToStatusObjectID) as? Status else { - cell.statusView.headerContainerStackView.isHidden = true + cell.statusView.headerContainerView.isHidden = true return } - cell.statusView.headerContainerStackView.isHidden = false + cell.statusView.headerContainerView.isHidden = false cell.statusView.headerIconLabel.attributedText = StatusView.iconAttributedString(image: StatusView.replyIconImage) cell.statusView.headerInfoLabel.text = L10n.Scene.Compose.replyingToUser(replyTo.author.displayNameWithFallback) } diff --git a/Mastodon/Diffiable/Section/StatusSection.swift b/Mastodon/Diffiable/Section/StatusSection.swift index fc7b02c21..816f852ea 100644 --- a/Mastodon/Diffiable/Section/StatusSection.swift +++ b/Mastodon/Diffiable/Section/StatusSection.swift @@ -525,7 +525,7 @@ extension StatusSection { status: Status ) { if status.reblog != nil { - cell.statusView.headerContainerStackView.isHidden = false + cell.statusView.headerContainerView.isHidden = false cell.statusView.headerIconLabel.attributedText = StatusView.iconAttributedString(image: StatusView.reblogIconImage) cell.statusView.headerInfoLabel.text = { let author = status.author @@ -533,7 +533,7 @@ extension StatusSection { return L10n.Common.Controls.Status.userReblogged(name) }() } else if status.inReplyToID != nil { - cell.statusView.headerContainerStackView.isHidden = false + cell.statusView.headerContainerView.isHidden = false cell.statusView.headerIconLabel.attributedText = StatusView.iconAttributedString(image: StatusView.replyIconImage) cell.statusView.headerInfoLabel.text = { guard let replyTo = status.replyTo else { @@ -544,7 +544,7 @@ extension StatusSection { return L10n.Common.Controls.Status.userRepliedTo(name) }() } else { - cell.statusView.headerContainerStackView.isHidden = true + cell.statusView.headerContainerView.isHidden = true } } diff --git a/Mastodon/Extension/NSLayoutConstraint.swift b/Mastodon/Extension/NSLayoutConstraint.swift index cae353187..eea697e2b 100644 --- a/Mastodon/Extension/NSLayoutConstraint.swift +++ b/Mastodon/Extension/NSLayoutConstraint.swift @@ -12,4 +12,9 @@ extension NSLayoutConstraint { self.priority = priority return self } + + func identifier(_ identifier: String?) -> Self { + self.identifier = identifier + return self + } } diff --git a/Mastodon/Scene/Compose/CollectionViewCell/ComposeRepliedToStatusContentCollectionViewCell.swift b/Mastodon/Scene/Compose/CollectionViewCell/ComposeRepliedToStatusContentCollectionViewCell.swift index 506d61391..275f545df 100644 --- a/Mastodon/Scene/Compose/CollectionViewCell/ComposeRepliedToStatusContentCollectionViewCell.swift +++ b/Mastodon/Scene/Compose/CollectionViewCell/ComposeRepliedToStatusContentCollectionViewCell.swift @@ -45,16 +45,16 @@ extension ComposeRepliedToStatusContentCollectionViewCell { private func _init() { backgroundColor = .clear + statusView.actionToolbarContainer.isHidden = true + statusView.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(statusView) NSLayoutConstraint.activate([ - statusView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 20), + statusView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 20).identifier("statusView.top to ComposeRepliedToStatusContentCollectionViewCell.contentView.top"), statusView.leadingAnchor.constraint(equalTo: contentView.readableContentGuide.leadingAnchor), contentView.readableContentGuide.trailingAnchor.constraint(equalTo: statusView.trailingAnchor), - contentView.bottomAnchor.constraint(equalTo: statusView.bottomAnchor, constant: 10), + contentView.bottomAnchor.constraint(equalTo: statusView.bottomAnchor, constant: 10).identifier("ComposeRepliedToStatusContentCollectionViewCell.contentView.bottom to statusView.bottom"), ]) - - statusView.actionToolbarContainer.isHidden = true } } diff --git a/Mastodon/Scene/Compose/ComposeViewController.swift b/Mastodon/Scene/Compose/ComposeViewController.swift index b463f13ac..a18cf9216 100644 --- a/Mastodon/Scene/Compose/ComposeViewController.swift +++ b/Mastodon/Scene/Compose/ComposeViewController.swift @@ -182,7 +182,7 @@ extension ComposeViewController { ) // respond scrollView overlap change - view.layoutIfNeeded() + //view.layoutIfNeeded() // update layout when keyboard show/dismiss Publishers.CombineLatest4( KeyboardResponderService.shared.isShow.eraseToAnyPublisher(), @@ -210,7 +210,9 @@ extension ComposeViewController { self.collectionView.verticalScrollIndicatorInsets.bottom = self.view.safeAreaInsets.bottom + extraMargin UIView.animate(withDuration: 0.3) { self.composeToolbarViewBottomLayoutConstraint.constant = self.view.safeAreaInsets.bottom - self.view.layoutIfNeeded() + if self.view.window != nil { + self.view.layoutIfNeeded() + } } self.updateKeyboardBackground(isKeyboardDisplay: isShow) return diff --git a/Mastodon/Scene/Share/View/Container/PlayerContainerView.swift b/Mastodon/Scene/Share/View/Container/PlayerContainerView.swift index 2c2229466..9c59a7ebd 100644 --- a/Mastodon/Scene/Share/View/Container/PlayerContainerView.swift +++ b/Mastodon/Scene/Share/View/Container/PlayerContainerView.swift @@ -5,6 +5,7 @@ // Created by xiaojian sun on 2021/3/10. // +import os.log import AVKit import UIKit @@ -93,6 +94,7 @@ extension PlayerContainerView { // MARK: - ContentWarningOverlayViewDelegate extension PlayerContainerView: ContentWarningOverlayViewDelegate { func contentWarningOverlayViewDidPressed(_ contentWarningOverlayView: ContentWarningOverlayView) { + os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) delegate?.playerContainerView(self, contentWarningOverlayViewDidPressed: contentWarningOverlayView) } } diff --git a/Mastodon/Scene/Share/View/Content/StatusView.swift b/Mastodon/Scene/Share/View/Content/StatusView.swift index a58ad1247..40eb05a58 100644 --- a/Mastodon/Scene/Share/View/Content/StatusView.swift +++ b/Mastodon/Scene/Share/View/Content/StatusView.swift @@ -29,6 +29,16 @@ final class StatusView: UIView { static let avatarImageCornerRadius: CGFloat = 4 static let avatarToLabelSpacing: CGFloat = 5 static let contentWarningBlurRadius: CGFloat = 12 + static let containerStackViewSpacing: CGFloat = 10 + + weak var delegate: StatusViewDelegate? + private var needsDrawContentOverlay = false + var pollTableViewDataSource: UITableViewDiffableDataSource? + var pollTableViewHeightLaoutConstraint: NSLayoutConstraint! + + let containerStackView = UIStackView() + let headerContainerView = UIView() + let authorContainerView = UIView() static let reblogIconImage: UIImage = { let font = UIFont.systemFont(ofSize: 13, weight: .medium) @@ -53,13 +63,6 @@ final class StatusView: UIView { return attributedString } - weak var delegate: StatusViewDelegate? - private var needsDrawContentOverlay = false - var pollTableViewDataSource: UITableViewDiffableDataSource? - var pollTableViewHeightLaoutConstraint: NSLayoutConstraint! - - let headerContainerStackView = UIStackView() - let headerIconLabel: UILabel = { let label = UILabel() label.attributedText = StatusView.iconAttributedString(image: StatusView.reblogIconImage) @@ -221,9 +224,9 @@ extension StatusView { func _init() { // container: [reblog | author | status | action toolbar] - let containerStackView = UIStackView() + // note: do not set spacing for nested stackView to avoid SDK layout conflict issue containerStackView.axis = .vertical - containerStackView.spacing = 10 + // containerStackView.spacing = 10 containerStackView.translatesAutoresizingMaskIntoConstraints = false addSubview(containerStackView) NSLayoutConstraint.activate([ @@ -232,17 +235,27 @@ extension StatusView { trailingAnchor.constraint(equalTo: containerStackView.trailingAnchor), bottomAnchor.constraint(equalTo: containerStackView.bottomAnchor), ]) + containerStackView.setContentHuggingPriority(.required - 1, for: .vertical) // header container: [icon | info] - containerStackView.addArrangedSubview(headerContainerStackView) - headerContainerStackView.spacing = 4 + let headerContainerStackView = UIStackView() + headerContainerStackView.axis = .horizontal headerContainerStackView.addArrangedSubview(headerIconLabel) headerContainerStackView.addArrangedSubview(headerInfoLabel) headerIconLabel.setContentHuggingPriority(.defaultHigh, for: .horizontal) + headerContainerStackView.translatesAutoresizingMaskIntoConstraints = false + headerContainerView.addSubview(headerContainerStackView) + NSLayoutConstraint.activate([ + headerContainerStackView.topAnchor.constraint(equalTo: headerContainerView.topAnchor), + headerContainerStackView.leadingAnchor.constraint(equalTo: headerContainerView.leadingAnchor), + headerContainerStackView.trailingAnchor.constraint(equalTo: headerContainerView.trailingAnchor), + headerContainerView.bottomAnchor.constraint(equalTo: headerContainerStackView.bottomAnchor, constant: StatusView.containerStackViewSpacing).priority(.defaultHigh), + ]) + containerStackView.addArrangedSubview(headerContainerView) + // author container: [avatar | author meta container | reveal button] let authorContainerStackView = UIStackView() - containerStackView.addArrangedSubview(authorContainerStackView) authorContainerStackView.axis = .horizontal authorContainerStackView.spacing = StatusView.avatarToLabelSpacing authorContainerStackView.distribution = .fill @@ -306,6 +319,16 @@ extension StatusView { authorContainerStackView.addArrangedSubview(revealContentWarningButton) revealContentWarningButton.setContentHuggingPriority(.required - 2, for: .horizontal) + authorContainerStackView.translatesAutoresizingMaskIntoConstraints = false + authorContainerView.addSubview(authorContainerStackView) + NSLayoutConstraint.activate([ + authorContainerStackView.topAnchor.constraint(equalTo: authorContainerView.topAnchor), + authorContainerStackView.leadingAnchor.constraint(equalTo: authorContainerView.leadingAnchor), + authorContainerStackView.trailingAnchor.constraint(equalTo: authorContainerView.trailingAnchor), + authorContainerView.bottomAnchor.constraint(equalTo: authorContainerStackView.bottomAnchor, constant: StatusView.containerStackViewSpacing).priority(.defaultHigh), + ]) + containerStackView.addArrangedSubview(authorContainerView) + // status container: [status | image / video | audio | poll | poll status] (overlay with content warning) containerStackView.addArrangedSubview(statusContainerStackView) statusContainerStackView.axis = .vertical @@ -370,7 +393,7 @@ extension StatusView { containerStackView.addArrangedSubview(actionToolbarContainer) actionToolbarContainer.setContentCompressionResistancePriority(.defaultLow, for: .vertical) - headerContainerStackView.isHidden = true + headerContainerView.isHidden = true statusMosaicImageViewContainer.isHidden = true pollTableView.isHidden = true pollStatusStackView.isHidden = true @@ -543,7 +566,7 @@ struct StatusView_Previews: PreviewProvider { .previewDisplayName("Normal") UIViewPreview(width: 375) { let statusView = StatusView() - statusView.headerContainerStackView.isHidden = false + statusView.headerContainerView.isHidden = false statusView.avatarButton.isHidden = true statusView.avatarStackedContainerButton.isHidden = false statusView.avatarStackedContainerButton.topLeadingAvatarStackedImageView.configure( @@ -570,7 +593,7 @@ struct StatusView_Previews: PreviewProvider { placeholderImage: avatarFlora ) ) - statusView.headerContainerStackView.isHidden = false + statusView.headerContainerView.isHidden = false let images = MosaicImageView_Previews.images let mosaics = statusView.statusMosaicImageViewContainer.setupImageViews(count: 4, maxHeight: 162) for (i, mosaic) in mosaics.enumerated() { @@ -591,7 +614,7 @@ struct StatusView_Previews: PreviewProvider { placeholderImage: avatarFlora ) ) - statusView.headerContainerStackView.isHidden = false + statusView.headerContainerView.isHidden = false statusView.setNeedsLayout() statusView.layoutIfNeeded() statusView.updateContentWarningDisplay(isHidden: false, animated: false)