Put CondensedUserView into their own class (IOS-141)

This commit is contained in:
Nathan Mattes 2023-09-18 17:21:36 +02:00
parent ce37a8eb47
commit dd569fe0ac
5 changed files with 220 additions and 298 deletions

View File

@ -1,170 +1,29 @@
// Copyright © 2023 Mastodon gGmbH. All rights reserved. // Copyright © 2023 Mastodon gGmbH. All rights reserved.
import UIKit import UIKit
import MastodonSDK
import MastodonUI import MastodonUI
import MetaTextKit
import MastodonLocalization
import MastodonMeta
import MastodonCore
import MastodonAsset
class SearchResultsProfileTableViewCell: UITableViewCell { class SearchResultsProfileTableViewCell: UITableViewCell {
static let reuseIdentifier = "SearchResultsProfileTableViewCell" static let reuseIdentifier = "SearchResultsProfileTableViewCell"
private static var metricFormatter = MastodonMetricFormatter() let condensedUserView: CondensedUserView
private let avatarImageWrapperView: UIView
let avatarImageView: AvatarImageView
private let metaInformationStackView: UIStackView
private let upperLineStackView: UIStackView
let displayNameLabel: MetaLabel
let acctLabel: UILabel
private let lowerLineStackView: UIStackView
let followersLabel: UILabel
let verifiedLinkImageView: UIImageView
let verifiedLinkLabel: MetaLabel
private let contentStackView: UIStackView
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
avatarImageView = AvatarImageView() condensedUserView = CondensedUserView(frame: .zero)
avatarImageView.cornerConfiguration = AvatarImageView.CornerConfiguration(corner: .fixed(radius: 8)) condensedUserView.translatesAutoresizingMaskIntoConstraints = false
avatarImageView.translatesAutoresizingMaskIntoConstraints = false
avatarImageWrapperView = UIView()
avatarImageWrapperView.translatesAutoresizingMaskIntoConstraints = false
avatarImageWrapperView.addSubview(avatarImageView)
displayNameLabel = MetaLabel(style: .statusName)
displayNameLabel.setContentCompressionResistancePriority(.required, for: .horizontal)
displayNameLabel.setContentHuggingPriority(.required, for: .horizontal)
acctLabel = UILabel()
acctLabel.textColor = .secondaryLabel
acctLabel.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .regular))
acctLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
upperLineStackView = UIStackView(arrangedSubviews: [displayNameLabel, acctLabel])
upperLineStackView.distribution = .fill
upperLineStackView.alignment = .center
followersLabel = UILabel()
followersLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
followersLabel.textColor = .secondaryLabel
followersLabel.setContentHuggingPriority(.required, for: .horizontal)
verifiedLinkImageView = UIImageView()
verifiedLinkImageView.setContentCompressionResistancePriority(.defaultHigh - 1, for: .vertical)
verifiedLinkImageView.setContentHuggingPriority(.required, for: .horizontal)
verifiedLinkImageView.contentMode = .scaleAspectFit
verifiedLinkLabel = MetaLabel(style: .profileFieldValue)
verifiedLinkLabel.setContentCompressionResistancePriority(.defaultHigh - 2, for: .horizontal)
verifiedLinkLabel.translatesAutoresizingMaskIntoConstraints = false
verifiedLinkLabel.textAttributes = [
.font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .regular)),
.foregroundColor: UIColor.secondaryLabel
]
verifiedLinkLabel.linkAttributes = [
.font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .regular)),
.foregroundColor: Asset.Colors.Brand.blurple.color
]
verifiedLinkLabel.isUserInteractionEnabled = false
lowerLineStackView = UIStackView(arrangedSubviews: [followersLabel, verifiedLinkImageView, verifiedLinkLabel])
lowerLineStackView.distribution = .fill
lowerLineStackView.alignment = .center
lowerLineStackView.spacing = 4
lowerLineStackView.setCustomSpacing(2, after: verifiedLinkImageView)
metaInformationStackView = UIStackView(arrangedSubviews: [upperLineStackView, lowerLineStackView])
metaInformationStackView.axis = .vertical
metaInformationStackView.alignment = .leading
contentStackView = UIStackView(arrangedSubviews: [avatarImageWrapperView, metaInformationStackView])
contentStackView.translatesAutoresizingMaskIntoConstraints = false
contentStackView.axis = .horizontal
contentStackView.alignment = .center
contentStackView.spacing = 16
super.init(style: style, reuseIdentifier: reuseIdentifier) super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(contentStackView) contentView.addSubview(condensedUserView)
setupConstraints() condensedUserView.pinToParent()
} }
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
private func setupConstraints() {
let constraints = [
contentStackView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8),
contentStackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16),
contentView.trailingAnchor.constraint(greaterThanOrEqualTo: contentStackView.trailingAnchor, constant: 16),
contentView.bottomAnchor.constraint(equalTo: contentStackView.bottomAnchor, constant: 8),
upperLineStackView.trailingAnchor.constraint(greaterThanOrEqualTo: metaInformationStackView.trailingAnchor),
lowerLineStackView.trailingAnchor.constraint(greaterThanOrEqualTo: metaInformationStackView.trailingAnchor),
metaInformationStackView.trailingAnchor.constraint(greaterThanOrEqualTo: contentStackView.trailingAnchor),
avatarImageView.widthAnchor.constraint(equalToConstant: 30),
avatarImageView.heightAnchor.constraint(equalTo: avatarImageView.widthAnchor),
avatarImageView.topAnchor.constraint(greaterThanOrEqualTo: avatarImageWrapperView.topAnchor),
avatarImageView.leadingAnchor.constraint(equalTo: avatarImageWrapperView.leadingAnchor),
avatarImageWrapperView.trailingAnchor.constraint(equalTo: avatarImageView.trailingAnchor),
avatarImageWrapperView.bottomAnchor.constraint(greaterThanOrEqualTo: avatarImageView.bottomAnchor),
avatarImageView.centerYAnchor.constraint(equalTo: avatarImageWrapperView.centerYAnchor),
]
NSLayoutConstraint.activate(constraints)
}
override func prepareForReuse() { override func prepareForReuse() {
super.prepareForReuse() super.prepareForReuse()
avatarImageView.prepareForReuse() condensedUserView.prepareForReuse()
}
func configure(with account: Mastodon.Entity.Account) {
let displayNameMetaContent: MetaContent
do {
let content = MastodonContent(content: account.displayNameWithFallback, emojis: account.emojis?.asDictionary ?? [:])
displayNameMetaContent = try MastodonMetaContent.convert(document: content)
} catch {
displayNameMetaContent = PlaintextMetaContent(string: account.displayNameWithFallback)
}
displayNameLabel.configure(content: displayNameMetaContent)
acctLabel.text = account.acct
followersLabel.attributedText = NSAttributedString(
format: NSAttributedString(string: L10n.Common.UserList.followersCount("%@"), attributes: [.font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .regular))]),
args: NSAttributedString(string: Self.metricFormatter.string(from: account.followersCount) ?? account.followersCount.formatted(), attributes: [.font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .bold))])
)
avatarImageView.setImage(url: account.avatarImageURL())
if let verifiedLink = account.verifiedLink?.value {
verifiedLinkImageView.image = UIImage(systemName: "checkmark")
verifiedLinkImageView.tintColor = Asset.Colors.Brand.blurple.color
let verifiedLinkMetaContent: MetaContent
do {
let mastodonContent = MastodonContent(content: verifiedLink, emojis: [:])
verifiedLinkMetaContent = try MastodonMetaContent.convert(document: mastodonContent)
} catch {
verifiedLinkMetaContent = PlaintextMetaContent(string: verifiedLink)
}
verifiedLinkLabel.configure(content: verifiedLinkMetaContent)
} else {
verifiedLinkImageView.image = UIImage(systemName: "questionmark.circle")
verifiedLinkImageView.tintColor = .secondaryLabel
verifiedLinkLabel.configure(content: PlaintextMetaContent(string: L10n.Common.UserList.noVerifiedLink))
}
} }
} }

View File

@ -55,7 +55,7 @@ class SearchResultsOverviewTableViewController: UIViewController, NeedsDependenc
case .profile(let profile): case .profile(let profile):
guard let cell = tableView.dequeueReusableCell(withIdentifier: SearchResultsProfileTableViewCell.reuseIdentifier, for: indexPath) as? SearchResultsProfileTableViewCell else { fatalError() } guard let cell = tableView.dequeueReusableCell(withIdentifier: SearchResultsProfileTableViewCell.reuseIdentifier, for: indexPath) as? SearchResultsProfileTableViewCell else { fatalError() }
cell.configure(with: profile) cell.condensedUserView.configure(with: profile)
return cell return cell
} }

View File

@ -1,171 +1,29 @@
// Copyright © 2023 Mastodon gGmbH. All rights reserved. // Copyright © 2023 Mastodon gGmbH. All rights reserved.
import UIKit import UIKit
import MastodonSDK
import MastodonUI import MastodonUI
import MetaTextKit
import MastodonLocalization
import MastodonMeta
import MastodonCore import MastodonCore
import MastodonAsset
import CoreDataStack
class SearchHistoryUserCollectionViewCell: UICollectionViewCell { class SearchHistoryUserCollectionViewCell: UICollectionViewCell {
static let reuseIdentifier = "SearchHistoryUserCollectionViewCell" static let reuseIdentifier = "SearchHistoryUserCollectionViewCell"
private static var metricFormatter = MastodonMetricFormatter() let condensedUserView: CondensedUserView
private let avatarImageWrapperView: UIView
let avatarImageView: AvatarImageView
private let metaInformationStackView: UIStackView
private let upperLineStackView: UIStackView
let displayNameLabel: MetaLabel
let acctLabel: UILabel
private let lowerLineStackView: UIStackView
let followersLabel: UILabel
let verifiedLinkImageView: UIImageView
let verifiedLinkLabel: MetaLabel
private let contentStackView: UIStackView
override init(frame: CGRect) { override init(frame: CGRect) {
avatarImageView = AvatarImageView() condensedUserView = CondensedUserView(frame: .zero)
avatarImageView.cornerConfiguration = AvatarImageView.CornerConfiguration(corner: .fixed(radius: 8)) condensedUserView.translatesAutoresizingMaskIntoConstraints = false
avatarImageView.translatesAutoresizingMaskIntoConstraints = false super.init(frame: frame)
avatarImageWrapperView = UIView() contentView.addSubview(condensedUserView)
avatarImageWrapperView.translatesAutoresizingMaskIntoConstraints = false condensedUserView.pinToParent()
avatarImageWrapperView.addSubview(avatarImageView)
displayNameLabel = MetaLabel(style: .statusName)
displayNameLabel.setContentCompressionResistancePriority(.required, for: .horizontal)
displayNameLabel.setContentHuggingPriority(.required, for: .horizontal)
acctLabel = UILabel()
acctLabel.textColor = .secondaryLabel
acctLabel.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .regular))
acctLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
upperLineStackView = UIStackView(arrangedSubviews: [displayNameLabel, acctLabel])
upperLineStackView.distribution = .fill
upperLineStackView.alignment = .center
followersLabel = UILabel()
followersLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
followersLabel.textColor = .secondaryLabel
followersLabel.setContentHuggingPriority(.required, for: .horizontal)
verifiedLinkImageView = UIImageView()
verifiedLinkImageView.setContentCompressionResistancePriority(.defaultHigh - 1, for: .vertical)
verifiedLinkImageView.setContentHuggingPriority(.required, for: .horizontal)
verifiedLinkImageView.contentMode = .scaleAspectFit
verifiedLinkLabel = MetaLabel(style: .profileFieldValue)
verifiedLinkLabel.setContentCompressionResistancePriority(.defaultHigh - 2, for: .horizontal)
verifiedLinkLabel.translatesAutoresizingMaskIntoConstraints = false
verifiedLinkLabel.textAttributes = [
.font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .regular)),
.foregroundColor: UIColor.secondaryLabel
]
verifiedLinkLabel.linkAttributes = [
.font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .regular)),
.foregroundColor: Asset.Colors.Brand.blurple.color
]
verifiedLinkLabel.isUserInteractionEnabled = false
lowerLineStackView = UIStackView(arrangedSubviews: [followersLabel, verifiedLinkImageView, verifiedLinkLabel])
lowerLineStackView.distribution = .fill
lowerLineStackView.alignment = .center
lowerLineStackView.spacing = 4
lowerLineStackView.setCustomSpacing(2, after: verifiedLinkImageView)
metaInformationStackView = UIStackView(arrangedSubviews: [upperLineStackView, lowerLineStackView])
metaInformationStackView.axis = .vertical
metaInformationStackView.alignment = .leading
contentStackView = UIStackView(arrangedSubviews: [avatarImageWrapperView, metaInformationStackView])
contentStackView.translatesAutoresizingMaskIntoConstraints = false
contentStackView.axis = .horizontal
contentStackView.alignment = .center
contentStackView.spacing = 16
super.init(frame: .zero)
contentView.addSubview(contentStackView)
setupConstraints()
} }
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
private func setupConstraints() {
let constraints = [
contentStackView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8),
contentStackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16),
contentView.trailingAnchor.constraint(greaterThanOrEqualTo: contentStackView.trailingAnchor, constant: 16),
contentView.bottomAnchor.constraint(equalTo: contentStackView.bottomAnchor, constant: 8),
upperLineStackView.trailingAnchor.constraint(greaterThanOrEqualTo: metaInformationStackView.trailingAnchor),
lowerLineStackView.trailingAnchor.constraint(greaterThanOrEqualTo: metaInformationStackView.trailingAnchor),
metaInformationStackView.trailingAnchor.constraint(greaterThanOrEqualTo: contentStackView.trailingAnchor),
avatarImageView.widthAnchor.constraint(equalToConstant: 30),
avatarImageView.heightAnchor.constraint(equalTo: avatarImageView.widthAnchor),
avatarImageView.topAnchor.constraint(greaterThanOrEqualTo: avatarImageWrapperView.topAnchor),
avatarImageView.leadingAnchor.constraint(equalTo: avatarImageWrapperView.leadingAnchor),
avatarImageWrapperView.trailingAnchor.constraint(equalTo: avatarImageView.trailingAnchor),
avatarImageWrapperView.bottomAnchor.constraint(greaterThanOrEqualTo: avatarImageView.bottomAnchor),
avatarImageView.centerYAnchor.constraint(equalTo: avatarImageWrapperView.centerYAnchor),
]
NSLayoutConstraint.activate(constraints)
}
override func prepareForReuse() { override func prepareForReuse() {
super.prepareForReuse() super.prepareForReuse()
avatarImageView.prepareForReuse() condensedUserView.prepareForReuse()
}
func configure(with user: MastodonUser) {
let displayNameMetaContent: MetaContent
do {
let content = MastodonContent(content: user.displayNameWithFallback, emojis: user.emojis.asDictionary)
displayNameMetaContent = try MastodonMetaContent.convert(document: content)
} catch {
displayNameMetaContent = PlaintextMetaContent(string: user.displayNameWithFallback)
}
displayNameLabel.configure(content: displayNameMetaContent)
acctLabel.text = user.acct
followersLabel.attributedText = NSAttributedString(
format: NSAttributedString(string: L10n.Common.UserList.followersCount("%@"), attributes: [.font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .regular))]),
args: NSAttributedString(string: Self.metricFormatter.string(from: Int(user.followersCount)) ?? user.followersCount.formatted(), attributes: [.font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .bold))])
)
avatarImageView.setImage(url: user.avatarImageURL())
if let verifiedLink = user.verifiedLink?.value {
verifiedLinkImageView.image = UIImage(systemName: "checkmark")
verifiedLinkImageView.tintColor = Asset.Colors.Brand.blurple.color
let verifiedLinkMetaContent: MetaContent
do {
let mastodonContent = MastodonContent(content: verifiedLink, emojis: [:])
verifiedLinkMetaContent = try MastodonMetaContent.convert(document: mastodonContent)
} catch {
verifiedLinkMetaContent = PlaintextMetaContent(string: verifiedLink)
}
verifiedLinkLabel.configure(content: verifiedLinkMetaContent)
} else {
verifiedLinkImageView.image = UIImage(systemName: "questionmark.circle")
verifiedLinkImageView.tintColor = .secondaryLabel
verifiedLinkLabel.configure(content: PlaintextMetaContent(string: L10n.Common.UserList.noVerifiedLink))
}
} }
override func updateConfiguration(using state: UICellConfigurationState) { override func updateConfiguration(using state: UICellConfigurationState) {

View File

@ -31,7 +31,7 @@ extension SearchHistorySection {
let userCellRegister = UICollectionView.CellRegistration<SearchHistoryUserCollectionViewCell, ManagedObjectRecord<MastodonUser>> { cell, indexPath, item in let userCellRegister = UICollectionView.CellRegistration<SearchHistoryUserCollectionViewCell, ManagedObjectRecord<MastodonUser>> { cell, indexPath, item in
context.managedObjectContext.performAndWait { context.managedObjectContext.performAndWait {
guard let user = item.object(in: context.managedObjectContext) else { return } guard let user = item.object(in: context.managedObjectContext) else { return }
cell.configure(with: user) cell.condensedUserView.configure(with: user)
} }
} }

View File

@ -0,0 +1,205 @@
// Copyright © 2023 Mastodon gGmbH. All rights reserved.
import UIKit
import CoreDataStack
import MetaTextKit
import MastodonAsset
import MastodonLocalization
import MastodonMeta
import MastodonCore
import MastodonSDK
public class CondensedUserView: UIView {
private static var metricFormatter = MastodonMetricFormatter()
private let avatarImageWrapperView: UIView
let avatarImageView: AvatarImageView
private let metaInformationStackView: UIStackView
private let upperLineStackView: UIStackView
let displayNameLabel: MetaLabel
let acctLabel: UILabel
private let lowerLineStackView: UIStackView
let followersLabel: UILabel
let verifiedLinkImageView: UIImageView
let verifiedLinkLabel: MetaLabel
private let contentStackView: UIStackView
public override init(frame: CGRect) {
avatarImageView = AvatarImageView()
avatarImageView.cornerConfiguration = AvatarImageView.CornerConfiguration(corner: .fixed(radius: 8))
avatarImageView.translatesAutoresizingMaskIntoConstraints = false
avatarImageWrapperView = UIView()
avatarImageWrapperView.translatesAutoresizingMaskIntoConstraints = false
avatarImageWrapperView.addSubview(avatarImageView)
displayNameLabel = MetaLabel(style: .statusName)
displayNameLabel.setContentCompressionResistancePriority(.required, for: .horizontal)
displayNameLabel.setContentHuggingPriority(.required, for: .horizontal)
acctLabel = UILabel()
acctLabel.textColor = .secondaryLabel
acctLabel.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .regular))
acctLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
upperLineStackView = UIStackView(arrangedSubviews: [displayNameLabel, acctLabel])
upperLineStackView.distribution = .fill
upperLineStackView.alignment = .center
followersLabel = UILabel()
followersLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
followersLabel.textColor = .secondaryLabel
followersLabel.setContentHuggingPriority(.required, for: .horizontal)
verifiedLinkImageView = UIImageView()
verifiedLinkImageView.setContentCompressionResistancePriority(.defaultHigh - 1, for: .vertical)
verifiedLinkImageView.setContentHuggingPriority(.required, for: .horizontal)
verifiedLinkImageView.contentMode = .scaleAspectFit
verifiedLinkLabel = MetaLabel(style: .profileFieldValue)
verifiedLinkLabel.setContentCompressionResistancePriority(.defaultHigh - 2, for: .horizontal)
verifiedLinkLabel.translatesAutoresizingMaskIntoConstraints = false
verifiedLinkLabel.textAttributes = [
.font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .regular)),
.foregroundColor: UIColor.secondaryLabel
]
verifiedLinkLabel.linkAttributes = [
.font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .regular)),
.foregroundColor: Asset.Colors.Brand.blurple.color
]
verifiedLinkLabel.isUserInteractionEnabled = false
lowerLineStackView = UIStackView(arrangedSubviews: [followersLabel, verifiedLinkImageView, verifiedLinkLabel])
lowerLineStackView.distribution = .fill
lowerLineStackView.alignment = .center
lowerLineStackView.spacing = 4
lowerLineStackView.setCustomSpacing(2, after: verifiedLinkImageView)
metaInformationStackView = UIStackView(arrangedSubviews: [upperLineStackView, lowerLineStackView])
metaInformationStackView.axis = .vertical
metaInformationStackView.alignment = .leading
contentStackView = UIStackView(arrangedSubviews: [avatarImageWrapperView, metaInformationStackView])
contentStackView.translatesAutoresizingMaskIntoConstraints = false
contentStackView.axis = .horizontal
contentStackView.alignment = .center
contentStackView.spacing = 16
super.init(frame: .zero)
addSubview(contentStackView)
setupConstraints()
}
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
private func setupConstraints() {
let constraints = [
contentStackView.topAnchor.constraint(equalTo: topAnchor, constant: 8),
contentStackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
trailingAnchor.constraint(greaterThanOrEqualTo: contentStackView.trailingAnchor, constant: 16),
bottomAnchor.constraint(equalTo: contentStackView.bottomAnchor, constant: 8),
upperLineStackView.trailingAnchor.constraint(greaterThanOrEqualTo: metaInformationStackView.trailingAnchor),
lowerLineStackView.trailingAnchor.constraint(greaterThanOrEqualTo: metaInformationStackView.trailingAnchor),
metaInformationStackView.trailingAnchor.constraint(greaterThanOrEqualTo: contentStackView.trailingAnchor),
avatarImageView.widthAnchor.constraint(equalToConstant: 30),
avatarImageView.heightAnchor.constraint(equalTo: avatarImageView.widthAnchor),
avatarImageView.topAnchor.constraint(greaterThanOrEqualTo: avatarImageWrapperView.topAnchor),
avatarImageView.leadingAnchor.constraint(equalTo: avatarImageWrapperView.leadingAnchor),
avatarImageWrapperView.trailingAnchor.constraint(equalTo: avatarImageView.trailingAnchor),
avatarImageWrapperView.bottomAnchor.constraint(greaterThanOrEqualTo: avatarImageView.bottomAnchor),
avatarImageView.centerYAnchor.constraint(equalTo: avatarImageWrapperView.centerYAnchor),
]
NSLayoutConstraint.activate(constraints)
}
public func prepareForReuse() {
avatarImageView.prepareForReuse()
}
public func configure(with user: MastodonUser) {
let displayNameMetaContent: MetaContent
do {
let content = MastodonContent(content: user.displayNameWithFallback, emojis: user.emojis.asDictionary)
displayNameMetaContent = try MastodonMetaContent.convert(document: content)
} catch {
displayNameMetaContent = PlaintextMetaContent(string: user.displayNameWithFallback)
}
displayNameLabel.configure(content: displayNameMetaContent)
acctLabel.text = user.acct
followersLabel.attributedText = NSAttributedString(
format: NSAttributedString(string: L10n.Common.UserList.followersCount("%@"), attributes: [.font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .regular))]),
args: NSAttributedString(string: Self.metricFormatter.string(from: Int(user.followersCount)) ?? user.followersCount.formatted(), attributes: [.font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .bold))])
)
avatarImageView.setImage(url: user.avatarImageURL())
if let verifiedLink = user.verifiedLink?.value {
verifiedLinkImageView.image = UIImage(systemName: "checkmark")
verifiedLinkImageView.tintColor = Asset.Colors.Brand.blurple.color
let verifiedLinkMetaContent: MetaContent
do {
let mastodonContent = MastodonContent(content: verifiedLink, emojis: [:])
verifiedLinkMetaContent = try MastodonMetaContent.convert(document: mastodonContent)
} catch {
verifiedLinkMetaContent = PlaintextMetaContent(string: verifiedLink)
}
verifiedLinkLabel.configure(content: verifiedLinkMetaContent)
} else {
verifiedLinkImageView.image = UIImage(systemName: "questionmark.circle")
verifiedLinkImageView.tintColor = .secondaryLabel
verifiedLinkLabel.configure(content: PlaintextMetaContent(string: L10n.Common.UserList.noVerifiedLink))
}
}
public func configure(with account: Mastodon.Entity.Account) {
let displayNameMetaContent: MetaContent
do {
let content = MastodonContent(content: account.displayNameWithFallback, emojis: account.emojis?.asDictionary ?? [:])
displayNameMetaContent = try MastodonMetaContent.convert(document: content)
} catch {
displayNameMetaContent = PlaintextMetaContent(string: account.displayNameWithFallback)
}
displayNameLabel.configure(content: displayNameMetaContent)
acctLabel.text = account.acct
followersLabel.attributedText = NSAttributedString(
format: NSAttributedString(string: L10n.Common.UserList.followersCount("%@"), attributes: [.font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .regular))]),
args: NSAttributedString(string: Self.metricFormatter.string(from: account.followersCount) ?? account.followersCount.formatted(), attributes: [.font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .bold))])
)
avatarImageView.setImage(url: account.avatarImageURL())
if let verifiedLink = account.verifiedLink?.value {
verifiedLinkImageView.image = UIImage(systemName: "checkmark")
verifiedLinkImageView.tintColor = Asset.Colors.Brand.blurple.color
let verifiedLinkMetaContent: MetaContent
do {
let mastodonContent = MastodonContent(content: verifiedLink, emojis: [:])
verifiedLinkMetaContent = try MastodonMetaContent.convert(document: mastodonContent)
} catch {
verifiedLinkMetaContent = PlaintextMetaContent(string: verifiedLink)
}
verifiedLinkLabel.configure(content: verifiedLinkMetaContent)
} else {
verifiedLinkImageView.image = UIImage(systemName: "questionmark.circle")
verifiedLinkImageView.tintColor = .secondaryLabel
verifiedLinkLabel.configure(content: PlaintextMetaContent(string: L10n.Common.UserList.noVerifiedLink))
}
}
}