Tusker/Tusker/Views/Account Cell/AccountCollectionViewCell.s...

150 lines
5.0 KiB
Swift

//
// AccountCollectionViewCell.swift
// Tusker
//
// Created by Shadowfacts on 11/22/22.
// Copyright © 2022 Shadowfacts. All rights reserved.
//
import UIKit
import HTMLStreamer
class AccountCollectionViewCell: UICollectionViewListCell {
private lazy var hStack = UIStackView(arrangedSubviews: [
avatarImageView,
vStack,
]).configure {
$0.axis = .horizontal
$0.spacing = 8
$0.alignment = .leading
}
private let avatarImageView = CachedImageView(cache: .avatars).configure {
$0.layer.masksToBounds = true
$0.layer.cornerCurve = .continuous
NSLayoutConstraint.activate([
$0.widthAnchor.constraint(equalToConstant: 50),
$0.heightAnchor.constraint(equalToConstant: 50),
])
}
private lazy var vStack = UIStackView(arrangedSubviews: [
displayNameLabel,
usernameLabel,
noteLabel,
]).configure {
$0.axis = .vertical
$0.spacing = 4
$0.alignment = .leading
}
private let displayNameLabel = EmojiLabel().configure {
$0.font = .preferredFont(forTextStyle: .body)
$0.adjustsFontSizeToFitWidth = true
$0.adjustsFontForContentSizeCategory = true
}
private let usernameLabel = UILabel().configure {
$0.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .light))
$0.textColor = .secondaryLabel
$0.adjustsFontSizeToFitWidth = true
$0.adjustsFontForContentSizeCategory = true
}
private let noteLabel = EmojiLabel().configure {
$0.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15))
$0.numberOfLines = 2
}
weak var delegate: (TuskerNavigationDelegate & MenuActionProvider)?
var mastodonController: MastodonController! { delegate?.apiController }
private var accountID: String?
private var isGrayscale = false
override init(frame: CGRect) {
super.init(frame: .zero)
hStack.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(hStack)
NSLayoutConstraint.activate([
hStack.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8),
hStack.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -8),
hStack.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8),
hStack.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8),
])
NotificationCenter.default.addObserver(self, selector: #selector(preferencesChanged), name: .preferencesChanged, object: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: Accessibility
override var isAccessibilityElement: Bool {
get { true }
set {}
}
override var accessibilityAttributedLabel: NSAttributedString? {
get {
guard let accountID,
let account = mastodonController.persistentContainer.account(for: accountID) else {
return nil
}
var str = AttributedString(account.displayNameWithoutCustomEmoji)
str += ", @"
str += AttributedString(account.acct)
return NSAttributedString(str)
}
set {}
}
override func accessibilityActivate() -> Bool {
guard let accountID else {
return false
}
delegate?.selected(account: accountID)
return true
}
// MARK: Configure UI
func updateUI(accountID: String) {
guard let account = mastodonController.persistentContainer.account(for: accountID) else {
fatalError()
}
self.accountID = accountID
avatarImageView.update(for: account.avatar)
usernameLabel.text = "@\(account.acct)"
updateUIForPreferences(account: account)
}
private func updateUIForPreferences(account: AccountMO) {
avatarImageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadiusFraction * 50
isGrayscale = Preferences.shared.grayscaleImages
if Preferences.shared.hideCustomEmojiInUsernames {
displayNameLabel.text = account.displayNameWithoutCustomEmoji
} else {
displayNameLabel.text = account.displayOrUserName
displayNameLabel.setEmojis(account.emojis, identifier: account.id)
}
var converter = TextConverter(callbacks: HTMLConverter.Callbacks.self)
noteLabel.text = converter.convert(html: account.note)
noteLabel.setEmojis(account.emojis, identifier: account.id)
}
@objc private func preferencesChanged() {
if let accountID,
let account = mastodonController?.persistentContainer.account(for: accountID) {
updateUIForPreferences(account: account)
}
}
}