Tusker/Tusker/Screens/Conversation/ExpandThreadCollectionViewC...

154 lines
6.9 KiB
Swift

//
// ExpandThreadCollectionViewCell.swift
// Tusker
//
// Created by Shadowfacts on 1/30/21.
// Copyright © 2021 Shadowfacts. All rights reserved.
//
import UIKit
class ExpandThreadCollectionViewCell: UICollectionViewListCell {
private var avatarContainerView: UIView!
private var avatarContainerWidthConstraint: NSLayoutConstraint!
private var replyCountLabel: UILabel!
private var hStack: UIStackView!
private var stackViewLeadingConstraint: NSLayoutConstraint!
private var threadLinkView: UIView!
private var threadLinkViewFullHeightConstraint: NSLayoutConstraint!
private var threadLinkViewShortHeightConstraint: NSLayoutConstraint!
private var avatarImageViews: [UIImageView] = []
override init(frame: CGRect) {
super.init(frame: frame)
avatarContainerView = UIView()
avatarContainerView.backgroundColor = .clear
avatarContainerWidthConstraint = avatarContainerView.widthAnchor.constraint(equalToConstant: 100)
replyCountLabel = UILabel()
replyCountLabel.textColor = .tintColor
replyCountLabel.font = .preferredFont(forTextStyle: .body)
replyCountLabel.adjustsFontForContentSizeCategory = true
hStack = UIStackView(arrangedSubviews: [
avatarContainerView,
replyCountLabel,
])
hStack.spacing = 8
hStack.alignment = .center
hStack.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(hStack)
stackViewLeadingConstraint = hStack.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16)
threadLinkView = UIView()
threadLinkView.backgroundColor = .tintColor.withAlphaComponent(0.5)
threadLinkView.layer.cornerRadius = 2.5
threadLinkView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(threadLinkView)
threadLinkViewFullHeightConstraint = threadLinkView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
threadLinkViewShortHeightConstraint = threadLinkView.bottomAnchor.constraint(equalTo: avatarContainerView.topAnchor, constant: -2)
NSLayoutConstraint.activate([
avatarContainerWidthConstraint,
avatarContainerView.heightAnchor.constraint(equalToConstant: 32),
stackViewLeadingConstraint,
hStack.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16),
hStack.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8),
hStack.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8),
threadLinkView.widthAnchor.constraint(equalToConstant: 5),
threadLinkView.topAnchor.constraint(equalTo: contentView.topAnchor),
threadLinkView.centerXAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16 + (50 / 2))
])
NotificationCenter.default.addObserver(self, selector: #selector(preferencesChanged), name: .preferencesChanged, object: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func updateUI(childThreads: [ConversationNode], inline: Bool) {
stackViewLeadingConstraint.constant = 16 + (inline ? 50 + 4 : 0)
threadLinkView.layer.maskedCorners = inline ? [] : [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
threadLinkViewFullHeightConstraint.isActive = inline
threadLinkViewShortHeightConstraint.isActive = !inline
let format: String
if inline {
format = NSLocalizedString("expand threads inline count", comment: "expand conversation threads inline button label")
} else {
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 = []
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 = CachedImageView(cache: .avatars)
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,
])
accountImageView.update(for: account.avatar)
}
}
@objc private func preferencesChanged() {
for view in avatarImageViews {
view.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: view)
}
}
override func updateConfiguration(using state: UICellConfigurationState) {
var config = UIBackgroundConfiguration.listPlainCell().updated(for: state)
if state.isSelected || state.isHighlighted {
config.backgroundColor = .appSelectedCellBackground
} else {
config.backgroundColor = .appSecondaryBackground
}
backgroundConfiguration = config
}
}