From e3cf8762a6e983eb5594c760f4f40401a84e95b1 Mon Sep 17 00:00:00 2001 From: kean Date: Fri, 13 Dec 2024 10:35:06 -0500 Subject: [PATCH] Rework PostCompactCell --- .../Posts/DashboardPostsListCardCell.swift | 3 +- .../Cards/Posts/PostsCardViewModel.swift | 3 +- .../Post/Views/PostCompactCell.swift | 207 ++++-------------- .../Post/Views/PostCompactCell.xib | 172 --------------- 4 files changed, 45 insertions(+), 340 deletions(-) delete mode 100644 WordPress/Classes/ViewRelated/Post/Views/PostCompactCell.xib diff --git a/WordPress/Classes/ViewRelated/Blog/Blog Dashboard/Cards/Posts/DashboardPostsListCardCell.swift b/WordPress/Classes/ViewRelated/Blog/Blog Dashboard/Cards/Posts/DashboardPostsListCardCell.swift index 0d77b9bff0f4..cb07a51ff778 100644 --- a/WordPress/Classes/ViewRelated/Blog/Blog Dashboard/Cards/Posts/DashboardPostsListCardCell.swift +++ b/WordPress/Classes/ViewRelated/Blog/Blog Dashboard/Cards/Posts/DashboardPostsListCardCell.swift @@ -23,8 +23,7 @@ class DashboardPostsListCardCell: UICollectionViewCell, Reusable { tableView.translatesAutoresizingMaskIntoConstraints = false tableView.isScrollEnabled = false tableView.backgroundColor = nil - let postCompactCellNib = PostCompactCell.defaultNib - tableView.register(postCompactCellNib, forCellReuseIdentifier: PostCompactCell.defaultReuseID) + tableView.register(PostCompactCell.self, forCellReuseIdentifier: PostCompactCell.defaultReuseID) let ghostCellNib = BlogDashboardPostCardGhostCell.defaultNib tableView.register(ghostCellNib, forCellReuseIdentifier: BlogDashboardPostCardGhostCell.defaultReuseID) tableView.register(DashboardPostListErrorCell.self, forCellReuseIdentifier: DashboardPostListErrorCell.defaultReuseID) diff --git a/WordPress/Classes/ViewRelated/Blog/Blog Dashboard/Cards/Posts/PostsCardViewModel.swift b/WordPress/Classes/ViewRelated/Blog/Blog Dashboard/Cards/Posts/PostsCardViewModel.swift index b7b7507033e3..35900c7e0edf 100644 --- a/WordPress/Classes/ViewRelated/Blog/Blog Dashboard/Cards/Posts/PostsCardViewModel.swift +++ b/WordPress/Classes/ViewRelated/Blog/Blog Dashboard/Cards/Posts/PostsCardViewModel.swift @@ -127,8 +127,7 @@ private extension PostsCardViewModel { let cell = tableView.dequeueReusableCell(withIdentifier: PostCompactCell.defaultReuseID, for: indexPath) as? PostCompactCell - cell?.accessoryType = .none - cell?.configureForDashboard(with: post) + cell?.configure(with: post) return cell ?? UITableViewCell() } diff --git a/WordPress/Classes/ViewRelated/Post/Views/PostCompactCell.swift b/WordPress/Classes/ViewRelated/Post/Views/PostCompactCell.swift index 97fd0045d947..3ea6a301a827 100644 --- a/WordPress/Classes/ViewRelated/Post/Views/PostCompactCell.swift +++ b/WordPress/Classes/ViewRelated/Post/Views/PostCompactCell.swift @@ -1,107 +1,79 @@ import AutomatticTracks import UIKit -import Gridicons import WordPressShared import WordPressUI -class PostCompactCell: UITableViewCell { - @IBOutlet weak var titleLabel: UILabel! - @IBOutlet weak var timestampLabel: UILabel! - @IBOutlet weak var badgesLabel: UILabel! - @IBOutlet weak var menuButton: UIButton! - @IBOutlet weak var featuredImageView: CachedAnimatedImageView! - @IBOutlet weak var headerStackView: UIStackView! - @IBOutlet weak var innerView: UIView! - @IBOutlet weak var contentStackView: UIStackView! - @IBOutlet weak var ghostView: UIView! - @IBOutlet weak var separator: UIView! - - @IBOutlet weak var trailingContentConstraint: NSLayoutConstraint! - - private var iPadReadableLeadingAnchor: NSLayoutConstraint? - private var iPadReadableTrailingAnchor: NSLayoutConstraint? - - lazy var imageLoader: ImageLoader = { - return ImageLoader(imageView: featuredImageView, gifStrategy: .mediumGIFs) - }() +final class PostCompactCell: UITableViewCell, Reusable { + private let titleLabel = UILabel() + private let detailsLabel = UILabel() + private let featuredImageView = AsyncImageView() private var post: Post? { didSet { - guard let post, post != oldValue else { - return - } - + guard let post, post != oldValue else { return } viewModel = PostCardStatusViewModel(post: post) } } private var viewModel: PostCardStatusViewModel? - func configure(with post: Post) { - self.post = post + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) - resetGhostStyles() - configureTitle() - configureDate() - configureStatus() - configureFeaturedImage() - configureMenuInteraction() + setupStyles() + setupLayout() } - @IBAction func more(_ sender: Any) { - // Do nothing. The compact cell is only shown in the dashboard, where the more button is hidden. + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") } - override func awakeFromNib() { - super.awakeFromNib() - applyStyles() - setupReadableGuideForiPad() - setupSeparator() - setupAccessibility() - } + func configure(with post: Post) { + self.post = post - private func resetGhostStyles() { - toggleGhost(visible: false) - menuButton.layer.opacity = Constants.opacity + titleLabel.text = post.titleForDisplay() + detailsLabel.text = post.contentPreviewForDisplay() + configureFeaturedImage() } - private func applyStyles() { + private func setupStyles() { WPStyleGuide.configureTableViewCell(self) WPStyleGuide.applyPostCardStyle(self) - WPStyleGuide.configureLabel(timestampLabel, textStyle: .subheadline) - WPStyleGuide.configureLabel(badgesLabel, textStyle: .subheadline) - titleLabel.font = AppStyleGuide.prominentFont(textStyle: .headline, weight: .bold) + titleLabel.font = .preferredFont(forTextStyle: .headline) titleLabel.adjustsFontForContentSizeCategory = true - titleLabel.textColor = .label - timestampLabel.textColor = .secondaryLabel - menuButton.tintColor = .secondaryLabel + titleLabel.numberOfLines = 1 - menuButton.setImage(.gridicon(.ellipsis), for: .normal) + detailsLabel.font = .preferredFont(forTextStyle: .subheadline) + detailsLabel.textColor = .secondaryLabel + detailsLabel.numberOfLines = 1 featuredImageView.layer.cornerRadius = Constants.imageRadius + featuredImageView.layer.masksToBounds = true - innerView.backgroundColor = .secondarySystemGroupedBackground - backgroundColor = .secondarySystemGroupedBackground - contentView.backgroundColor = .secondarySystemGroupedBackground - } - - private func setupSeparator() { - WPStyleGuide.applyBorderStyle(separator) + contentView.backgroundColor = .systemBackground } - private func setupReadableGuideForiPad() { - guard WPDeviceIdentification.isiPad() else { return } - - iPadReadableLeadingAnchor = innerView.leadingAnchor.constraint(equalTo: readableContentGuide.leadingAnchor) - iPadReadableTrailingAnchor = innerView.trailingAnchor.constraint(equalTo: readableContentGuide.trailingAnchor) + private func setupLayout() { + let stackView = UIStackView(alignment: .top, spacing: 8, [ + UIStackView(axis: .vertical, alignment: .leading, spacing: 2, [ + titleLabel, detailsLabel + ]), + featuredImageView + ]) + contentView.addSubview(stackView) + stackView.pinEdges(insets: UIEdgeInsets(horizontal: 16, vertical: 8)) - iPadReadableLeadingAnchor?.isActive = true - iPadReadableTrailingAnchor?.isActive = true + NSLayoutConstraint.activate([ + featuredImageView.widthAnchor.constraint(equalToConstant: Constants.imageSize.width), + featuredImageView.heightAnchor.constraint(equalToConstant: Constants.imageSize.height), + ]) } private func configureFeaturedImage() { + featuredImageView.prepareForReuse() + if let post, let url = post.featuredImageURL { featuredImageView.isHidden = false @@ -110,108 +82,15 @@ class PostCompactCell: UITableViewCell { WordPressAppDelegate.crashLogging?.logError(error) }) - imageLoader.loadImage(with: url, from: host, preferredSize: CGSize(width: featuredImageView.frame.width, height: featuredImageView.frame.height)) + let targetSize = Constants.imageSize.scaled(by: traitCollection.displayScale) + featuredImageView.setImage(with: url, host: host, size: targetSize) } else { featuredImageView.isHidden = true } } - private func configureTitle() { - titleLabel.text = post?.titleForDisplay() - } - - private func configureDate() { - guard let post else { - return - } - - timestampLabel.text = post.latest().dateStringForDisplay() - timestampLabel.isHidden = false - } - - private func configureExcerpt() { - guard let post else { - return - } - - timestampLabel.text = post.contentPreviewForDisplay() - timestampLabel.isHidden = false - } - - private func configureStatus() { - guard let viewModel else { - return - } - badgesLabel.textColor = viewModel.statusColor - badgesLabel.text = viewModel.statusAndBadges(separatedBy: Constants.separator) - if badgesLabel.text?.isEmpty ?? true { - badgesLabel.isHidden = true - } else { - badgesLabel.isHidden = false - } - } - - private func configureMenuInteraction() { - menuButton.isEnabled = true - menuButton.alpha = 1.0 - } - - private func setupAccessibility() { - menuButton.accessibilityLabel = - NSLocalizedString("More", comment: "Accessibility label for the More button in Post List (compact view).") - } - private enum Constants { - static let separator = " · " - static let imageRadius: CGFloat = 2 - static let opacity: Float = 1 - static let margin: CGFloat = 16 - } -} - -extension PostCompactCell: GhostableView { - func ghostAnimationWillStart() { - toggleGhost(visible: true) - menuButton.layer.opacity = GhostConstants.opacity - } - - private func toggleGhost(visible: Bool) { - isUserInteractionEnabled = !visible - menuButton.isGhostableDisabled = true - separator.isGhostableDisabled = true - ghostView.isHidden = !visible - ghostView.backgroundColor = .secondarySystemGroupedBackground - contentStackView.isHidden = visible - } - - private enum GhostConstants { - static let opacity: Float = 0.5 - } -} - -extension PostCompactCell: NibReusable { } - -// MARK: - For display on the Posts Card (Dashboard) - -extension PostCompactCell { - /// Configure the cell to be displayed in the Posts Card - /// No "more" button and show a description, instead of a date - func configureForDashboard(with post: Post) { - configure(with: post) - separator.isHidden = true - menuButton.isHidden = true - trailingContentConstraint.constant = Constants.margin - headerStackView.spacing = Constants.margin - - disableiPadReadableMargin() - - if !post.isScheduled() { - configureExcerpt() - } - } - - func disableiPadReadableMargin() { - iPadReadableLeadingAnchor?.isActive = false - iPadReadableTrailingAnchor?.isActive = false + static let imageRadius: CGFloat = 4 + static let imageSize = CGSize(width: 40, height: 40) } } diff --git a/WordPress/Classes/ViewRelated/Post/Views/PostCompactCell.xib b/WordPress/Classes/ViewRelated/Post/Views/PostCompactCell.xib deleted file mode 100644 index aacee20ed9ce..000000000000 --- a/WordPress/Classes/ViewRelated/Post/Views/PostCompactCell.xib +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - - - NotoSerif-Bold - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -