From b4e7cbe3d90e317118535479c40e30eaadd6617b Mon Sep 17 00:00:00 2001 From: kean Date: Mon, 13 Jan 2025 17:02:01 -0500 Subject: [PATCH] Fix an issue with small tap area of the ellipsis in the post list --- .../ViewRelated/Post/Views/PostListCell.swift | 37 +++++++++++++++---- .../Post/Views/PostListHeaderView.swift | 33 +++-------------- 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Post/Views/PostListCell.swift b/WordPress/Classes/ViewRelated/Post/Views/PostListCell.swift index 431b482a3d9f..3f62292a9688 100644 --- a/WordPress/Classes/ViewRelated/Post/Views/PostListCell.swift +++ b/WordPress/Classes/ViewRelated/Post/Views/PostListCell.swift @@ -1,6 +1,7 @@ import Foundation import UIKit import AsyncImageKit +import WordPressUI protocol AbstractPostListCell { /// A post displayed by the cell. @@ -23,6 +24,7 @@ final class PostListCell: UITableViewCell, AbstractPostListCell, PostSearchResul }() private let headerView = PostListHeaderView() + private let ellipsisButton = UIButton(type: .system) private let contentLabel = UILabel() private let featuredImageView = AsyncImageView() private let statusLabel = UILabel() @@ -69,7 +71,7 @@ final class PostListCell: UITableViewCell, AbstractPostListCell, PostSearchResul } private func _configure(with viewModel: PostListItemViewModel, delegate: InteractivePostViewDelegate? = nil) { - headerView.configure(with: viewModel, delegate: delegate) + headerView.configure(with: viewModel) contentLabel.attributedText = viewModel.content featuredImageView.isHidden = viewModel.imageURL == nil @@ -87,12 +89,22 @@ final class PostListCell: UITableViewCell, AbstractPostListCell, PostSearchResul accessibilityLabel = viewModel.accessibilityLabel configure(with: viewModel.syncStateViewModel) + if let delegate { + configureEllipsisButton(with: viewModel.post, delegate: delegate) + } self.viewModel = viewModel } private func configure(with viewModel: PostSyncStateViewModel) { contentView.isUserInteractionEnabled = viewModel.isEditable headerView.configure(with: viewModel) + ellipsisButton.isHidden = !viewModel.isShowingEllipsis + } + + private func configureEllipsisButton(with post: Post, delegate: InteractivePostViewDelegate) { + let menuHelper = AbstractPostMenuHelper(post) + ellipsisButton.showsMenuAsPrimaryAction = true + ellipsisButton.menu = menuHelper.makeMenu(presentingView: ellipsisButton, delegate: delegate) } // MARK: - Setup @@ -102,7 +114,6 @@ final class PostListCell: UITableViewCell, AbstractPostListCell, PostSearchResul setupFeaturedImageView() setupStatusLabel() - contentStackView.translatesAutoresizingMaskIntoConstraints = false contentStackView.addArrangedSubviews([ contentLabel, featuredImageView @@ -110,7 +121,6 @@ final class PostListCell: UITableViewCell, AbstractPostListCell, PostSearchResul contentStackView.spacing = 16 contentStackView.alignment = .top - mainStackView.translatesAutoresizingMaskIntoConstraints = false mainStackView.addArrangedSubviews([ headerView, contentStackView, @@ -118,18 +128,19 @@ final class PostListCell: UITableViewCell, AbstractPostListCell, PostSearchResul ]) mainStackView.spacing = 4 contentView.addSubview(mainStackView) - contentView.pinSubviewToAllEdgeMargins(mainStackView) + mainStackView.pinEdges(to: contentView.layoutMarginsGuide) + + // It is added last to ensure it's tappable + setupEllipsisButton() } private func setupContentLabel() { - contentLabel.translatesAutoresizingMaskIntoConstraints = false contentLabel.adjustsFontForContentSizeCategory = true contentLabel.numberOfLines = 3 contentLabel.setContentHuggingPriority(.defaultHigh, for: .horizontal) } private func setupFeaturedImageView() { - featuredImageView.translatesAutoresizingMaskIntoConstraints = false featuredImageView.contentMode = .scaleAspectFill featuredImageView.layer.masksToBounds = true featuredImageView.layer.cornerRadius = 5 @@ -142,11 +153,23 @@ final class PostListCell: UITableViewCell, AbstractPostListCell, PostSearchResul } private func setupStatusLabel() { - statusLabel.translatesAutoresizingMaskIntoConstraints = false statusLabel.adjustsFontForContentSizeCategory = true statusLabel.numberOfLines = 1 statusLabel.font = WPStyleGuide.fontForTextStyle(.footnote, fontWeight: .regular) } + + private func setupEllipsisButton() { + ellipsisButton.setImage(UIImage(named: "more-horizontal-mobile"), for: .normal) + ellipsisButton.tintColor = .secondaryLabel + + NSLayoutConstraint.activate([ + ellipsisButton.heightAnchor.constraint(equalToConstant: 44), + ellipsisButton.widthAnchor.constraint(equalToConstant: 54) + ]) + + contentView.addSubview(ellipsisButton) + ellipsisButton.pinEdges([.top, .trailing]) + } } private enum Constants { diff --git a/WordPress/Classes/ViewRelated/Post/Views/PostListHeaderView.swift b/WordPress/Classes/ViewRelated/Post/Views/PostListHeaderView.swift index c46181e60a33..720356147bb5 100644 --- a/WordPress/Classes/ViewRelated/Post/Views/PostListHeaderView.swift +++ b/WordPress/Classes/ViewRelated/Post/Views/PostListHeaderView.swift @@ -1,4 +1,5 @@ import UIKit +import WordPressUI final class PostListHeaderView: UIView { @@ -7,7 +8,6 @@ final class PostListHeaderView: UIView { private let textLabel = UILabel() private let icon = UIImageView() private let indicator = UIActivityIndicatorView(style: .medium) - private let ellipsisButton = UIButton(type: .custom) // MARK: - Initializer @@ -22,10 +22,7 @@ final class PostListHeaderView: UIView { // MARK: - Public - func configure(with viewModel: PostListItemViewModel, delegate: InteractivePostViewDelegate? = nil) { - if let delegate { - configureEllipsisButton(with: viewModel.post, delegate: delegate) - } + func configure(with viewModel: PostListItemViewModel) { textLabel.attributedText = viewModel.badges configure(with: viewModel.syncStateViewModel) } @@ -35,8 +32,6 @@ final class PostListHeaderView: UIView { icon.image = iconInfo.image icon.tintColor = iconInfo.color } - - ellipsisButton.isHidden = !viewModel.isShowingEllipsis icon.isHidden = viewModel.iconInfo == nil indicator.isHidden = !viewModel.isShowingIndicator @@ -45,21 +40,15 @@ final class PostListHeaderView: UIView { } } - private func configureEllipsisButton(with post: Post, delegate: InteractivePostViewDelegate) { - let menuHelper = AbstractPostMenuHelper(post) - ellipsisButton.showsMenuAsPrimaryAction = true - ellipsisButton.menu = menuHelper.makeMenu(presentingView: ellipsisButton, delegate: delegate) - } - // MARK: - Setup private func setupView() { setupIcon() - setupEllipsisButton() - let innerStackView = UIStackView(arrangedSubviews: [icon, indicator, ellipsisButton]) - innerStackView.spacing = 4 - let stackView = UIStackView(arrangedSubviews: [textLabel, innerStackView]) + // Trailing spacer to allocate enough space for the "More" button. + let accessoriesStackView = UIStackView(arrangedSubviews: [icon, indicator, SpacerView(width: 40)]) + accessoriesStackView.spacing = 4 + let stackView = UIStackView(arrangedSubviews: [textLabel, accessoriesStackView]) indicator.transform = CGAffineTransform(scaleX: 0.8, y: 0.8) @@ -76,14 +65,4 @@ final class PostListHeaderView: UIView { ]) icon.contentMode = .scaleAspectFit } - - private func setupEllipsisButton() { - ellipsisButton.translatesAutoresizingMaskIntoConstraints = false - ellipsisButton.setImage(UIImage(named: "more-horizontal-mobile"), for: .normal) - ellipsisButton.tintColor = .secondaryLabel - - NSLayoutConstraint.activate([ - ellipsisButton.widthAnchor.constraint(equalToConstant: 24) - ]) - } }