// // SuggestionAccountTableViewCell.swift // Mastodon // // Created by sxiaojian on 2021/4/21. // import Combine import CoreData import CoreDataStack import Foundation import MastodonSDK import UIKit protocol SuggestionAccountTableViewCellDelegate: AnyObject { func accountButtonPressed(objectID: NSManagedObjectID, sender: UIButton) } final class SuggestionAccountTableViewCell: UITableViewCell { var disposeBag = Set() weak var delegate: SuggestionAccountTableViewCellDelegate? let _imageView: UIImageView = { let imageView = UIImageView() imageView.tintColor = Asset.Colors.Label.primary.color imageView.layer.cornerRadius = 4 imageView.clipsToBounds = true return imageView }() let titleLabel: UILabel = { let label = UILabel() label.textColor = Asset.Colors.brandBlue.color label.font = .systemFont(ofSize: 17, weight: .semibold) label.lineBreakMode = .byTruncatingTail return label }() let subTitleLabel: UILabel = { let label = UILabel() label.textColor = Asset.Colors.Label.secondary.color label.font = .preferredFont(forTextStyle: .body) return label }() lazy var button: HighlightDimmableButton = { let button = HighlightDimmableButton(type: .custom) if let plusImage = UIImage(systemName: "plus.circle", withConfiguration: UIImage.SymbolConfiguration(pointSize: 22, weight: .regular))?.withRenderingMode(.alwaysTemplate) { button.setImage(plusImage, for: .normal) } if let minusImage = UIImage(systemName: "minus.circle.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: 22, weight: .regular))?.withRenderingMode(.alwaysTemplate) { button.setImage(minusImage, for: .selected) } return button }() override func prepareForReuse() { super.prepareForReuse() _imageView.af.cancelImageRequest() _imageView.image = nil disposeBag.removeAll() } override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) configure() } required init?(coder: NSCoder) { super.init(coder: coder) configure() } } extension SuggestionAccountTableViewCell { private func configure() { backgroundColor = .clear let containerStackView = UIStackView() containerStackView.axis = .horizontal containerStackView.distribution = .fill containerStackView.spacing = 12 containerStackView.layoutMargins = UIEdgeInsets(top: 12, left: 21, bottom: 12, right: 12) containerStackView.isLayoutMarginsRelativeArrangement = true containerStackView.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(containerStackView) NSLayoutConstraint.activate([ containerStackView.topAnchor.constraint(equalTo: contentView.topAnchor), containerStackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), containerStackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), containerStackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor) ]) _imageView.translatesAutoresizingMaskIntoConstraints = false containerStackView.addArrangedSubview(_imageView) NSLayoutConstraint.activate([ _imageView.widthAnchor.constraint(equalToConstant: 42).priority(.required - 1), _imageView.heightAnchor.constraint(equalToConstant: 42).priority(.required - 1) ]) let textStackView = UIStackView() textStackView.axis = .vertical textStackView.distribution = .fill textStackView.alignment = .leading textStackView.translatesAutoresizingMaskIntoConstraints = false titleLabel.translatesAutoresizingMaskIntoConstraints = false textStackView.addArrangedSubview(titleLabel) subTitleLabel.translatesAutoresizingMaskIntoConstraints = false textStackView.addArrangedSubview(subTitleLabel) subTitleLabel.setContentHuggingPriority(.defaultLow - 1, for: .vertical) containerStackView.addArrangedSubview(textStackView) textStackView.setContentHuggingPriority(.defaultLow - 1, for: .horizontal) button.translatesAutoresizingMaskIntoConstraints = false containerStackView.addArrangedSubview(button) } func config(with account: MastodonUser, isSelected: Bool) { if let url = account.avatarImageURL() { _imageView.af.setImage( withURL: url, placeholderImage: UIImage.placeholder(color: .systemFill), imageTransition: .crossDissolve(0.2) ) } titleLabel.text = account.displayName.isEmpty ? account.username : account.displayName subTitleLabel.text = account.acct button.isSelected = isSelected button.publisher(for: .touchUpInside) .sink { [weak self] _ in guard let self = self else { return } self.delegate?.accountButtonPressed(objectID: account.objectID, sender: self.button) } .store(in: &disposeBag) button.publisher(for: \.isSelected) .sink { [weak self] isSelected in if isSelected { self?.button.tintColor = Asset.Colors.danger.color } else { self?.button.tintColor = Asset.Colors.Label.secondary.color } } .store(in: &self.disposeBag) } }