// // ExpandThreadTableViewCell.swift // Tusker // // Created by Shadowfacts on 1/30/21. // Copyright © 2021 Shadowfacts. All rights reserved. // import UIKit class ExpandThreadTableViewCell: UITableViewCell { @IBOutlet weak var avatarContainerView: UIView! @IBOutlet weak var avatarContainerWidthConstraint: NSLayoutConstraint! @IBOutlet weak var replyCountLabel: UILabel! var avatarImageViews: [UIImageView] = [] private var avatarRequests: [ImageCache.Request] = [] override func awakeFromNib() { super.awakeFromNib() let prevThreadLinkView = UIView() prevThreadLinkView.translatesAutoresizingMaskIntoConstraints = false prevThreadLinkView.backgroundColor = tintColor.withAlphaComponent(0.5) prevThreadLinkView.layer.cornerRadius = 2.5 prevThreadLinkView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner] contentView.addSubview(prevThreadLinkView) NSLayoutConstraint.activate([ prevThreadLinkView.widthAnchor.constraint(equalToConstant: 5), prevThreadLinkView.centerXAnchor.constraint(equalTo: leadingAnchor, constant: 16 + 25), prevThreadLinkView.topAnchor.constraint(equalTo: topAnchor), prevThreadLinkView.bottomAnchor.constraint(equalTo: avatarContainerView.topAnchor, constant: -2), ]) NotificationCenter.default.addObserver(self, selector: #selector(preferencesChanged), name: .preferencesChanged, object: nil) } func updateUI(childThreads: [ConversationNode]) { let format = NSLocalizedString("expand threads count", comment: "expand conversation threads button label") replyCountLabel.text = String.localizedStringWithFormat(format, childThreads.count) let accounts = childThreads.map(\.status.account).uniques().prefix(3) avatarImageViews.forEach { $0.removeFromSuperview() } avatarImageViews = [] avatarRequests = [] let avatarImageSize: CGFloat = 44 - 12 if accounts.count == 1 { avatarContainerWidthConstraint.constant = avatarImageSize } else { avatarContainerWidthConstraint.constant = CGFloat(accounts.count) * avatarImageSize * 3 / 4 } for (index, account) in accounts.enumerated() { let accountImageView = UIImageView() accountImageView.translatesAutoresizingMaskIntoConstraints = false accountImageView.contentMode = .scaleAspectFit accountImageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadiusFraction * avatarImageSize accountImageView.layer.masksToBounds = true accountImageView.layer.borderWidth = 1 accountImageView.layer.borderColor = UIColor.secondarySystemBackground.cgColor // need a solid background color so semi-transparent avatars don't look bad accountImageView.backgroundColor = .secondarySystemBackground avatarContainerView.addSubview(accountImageView) avatarImageViews.append(accountImageView) accountImageView.layer.zPosition = CGFloat(-index) let xConstraint: NSLayoutConstraint if index == 0 { xConstraint = accountImageView.leadingAnchor.constraint(equalTo: avatarContainerView.leadingAnchor) } else if index == accounts.count - 1 { xConstraint = accountImageView.trailingAnchor.constraint(equalTo: avatarContainerView.trailingAnchor) } else { xConstraint = accountImageView.centerXAnchor.constraint(equalTo: avatarContainerView.centerXAnchor) } NSLayoutConstraint.activate([ accountImageView.widthAnchor.constraint(equalToConstant: avatarImageSize), accountImageView.heightAnchor.constraint(equalToConstant: avatarImageSize), accountImageView.centerYAnchor.constraint(equalTo: avatarContainerView.centerYAnchor), xConstraint ]) let req = ImageCache.avatars.get(account.avatar) { [weak accountImageView] (_, image) in DispatchQueue.main.async { accountImageView?.image = image } } if let req = req { avatarRequests.append(req) } } } @objc private func preferencesChanged() { avatarImageViews.forEach { $0.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: $0) } } override func prepareForReuse() { super.prepareForReuse() avatarRequests.forEach { $0.cancel() } } }