2022-11-05 01:32:49 +00:00
|
|
|
//
|
|
|
|
// ProfileFieldsView.swift
|
|
|
|
// Tusker
|
|
|
|
//
|
|
|
|
// Created by Shadowfacts on 11/4/22.
|
|
|
|
// Copyright © 2022 Shadowfacts. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
import UIKit
|
|
|
|
|
|
|
|
class ProfileFieldsView: UIView {
|
|
|
|
|
|
|
|
weak var delegate: ProfileHeaderViewDelegate?
|
|
|
|
|
|
|
|
private let stack = UIStackView()
|
|
|
|
private var fieldViews: [(EmojiLabel, ContentTextView)] = []
|
|
|
|
private var fieldConstraints: [NSLayoutConstraint] = []
|
|
|
|
|
|
|
|
private var isUsingSingleColumn: Bool = false
|
|
|
|
private var needsSingleColumn: Bool {
|
2022-11-11 23:26:59 +00:00
|
|
|
traitCollection.horizontalSizeClass == .compact && traitCollection.preferredContentSizeCategory > .extraLarge
|
2022-11-05 01:32:49 +00:00
|
|
|
}
|
|
|
|
|
2022-11-12 19:43:47 +00:00
|
|
|
override var accessibilityElements: [Any]? {
|
|
|
|
get {
|
|
|
|
fieldViews.flatMap { [$0.0, $0.1] }
|
|
|
|
}
|
|
|
|
set {}
|
|
|
|
}
|
|
|
|
|
2022-11-05 01:32:49 +00:00
|
|
|
override init(frame: CGRect) {
|
|
|
|
super.init(frame: frame)
|
|
|
|
commonInit()
|
|
|
|
}
|
|
|
|
|
|
|
|
required init?(coder: NSCoder) {
|
|
|
|
super.init(coder: coder)
|
|
|
|
commonInit()
|
|
|
|
}
|
|
|
|
|
|
|
|
private func commonInit() {
|
|
|
|
stack.axis = .vertical
|
|
|
|
stack.alignment = .fill
|
|
|
|
stack.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
addSubview(stack)
|
|
|
|
NSLayoutConstraint.activate([
|
|
|
|
stack.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
|
|
stack.trailingAnchor.constraint(equalTo: trailingAnchor),
|
|
|
|
stack.topAnchor.constraint(equalTo: topAnchor),
|
|
|
|
stack.bottomAnchor.constraint(equalTo: bottomAnchor),
|
|
|
|
])
|
|
|
|
}
|
|
|
|
|
|
|
|
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
|
|
|
|
super.traitCollectionDidChange(previousTraitCollection)
|
|
|
|
if isUsingSingleColumn != needsSingleColumn {
|
|
|
|
configureFields()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func updateUI(account: AccountMO) {
|
|
|
|
isHidden = account.fields.isEmpty
|
|
|
|
guard !account.fields.isEmpty else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
for (name, value) in fieldViews {
|
|
|
|
name.removeFromSuperview()
|
|
|
|
value.removeFromSuperview()
|
|
|
|
}
|
|
|
|
fieldViews = []
|
|
|
|
|
|
|
|
for field in account.fields {
|
|
|
|
let nameLabel = EmojiLabel()
|
|
|
|
nameLabel.text = field.name
|
|
|
|
nameLabel.font = .preferredFont(forTextStyle: .body).withTraits(.traitBold)!
|
|
|
|
nameLabel.adjustsFontForContentSizeCategory = true
|
|
|
|
nameLabel.numberOfLines = 0
|
|
|
|
nameLabel.lineBreakMode = .byWordWrapping
|
|
|
|
nameLabel.setEmojis(account.emojis, identifier: account.id)
|
|
|
|
nameLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
|
|
|
|
|
|
|
|
let valueTextView = ContentTextView()
|
|
|
|
valueTextView.isSelectable = false
|
|
|
|
valueTextView.defaultFont = .preferredFont(forTextStyle: .body)
|
|
|
|
valueTextView.adjustsFontForContentSizeCategory = true
|
|
|
|
valueTextView.setTextFromHtml(field.value)
|
|
|
|
valueTextView.setEmojis(account.emojis, identifier: account.id)
|
|
|
|
valueTextView.navigationDelegate = delegate
|
|
|
|
valueTextView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
|
|
|
|
|
|
|
|
fieldViews.append((nameLabel, valueTextView))
|
|
|
|
}
|
|
|
|
|
|
|
|
configureFields()
|
|
|
|
}
|
|
|
|
|
|
|
|
@objc private func configureFields() {
|
|
|
|
guard !isHidden else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
isUsingSingleColumn = needsSingleColumn
|
|
|
|
|
|
|
|
NSLayoutConstraint.deactivate(fieldConstraints)
|
|
|
|
fieldConstraints = []
|
|
|
|
|
|
|
|
stack.arrangedSubviews.forEach { $0.removeFromSuperview() }
|
|
|
|
|
|
|
|
if needsSingleColumn {
|
|
|
|
stack.spacing = 4
|
|
|
|
var isFirst = true
|
|
|
|
for (name, value) in fieldViews {
|
|
|
|
if isFirst {
|
|
|
|
isFirst = false
|
|
|
|
} else {
|
|
|
|
let spacer = UIView()
|
|
|
|
// don't need any height, since there's 4pts of padding on either side
|
|
|
|
spacer.heightAnchor.constraint(equalToConstant: 0).isActive = true
|
|
|
|
stack.addArrangedSubview(spacer)
|
|
|
|
}
|
|
|
|
name.textAlignment = .natural
|
|
|
|
stack.addArrangedSubview(name)
|
|
|
|
value.textAlignment = .natural
|
|
|
|
stack.addArrangedSubview(value)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
stack.spacing = 8
|
|
|
|
|
|
|
|
let dividerLayoutGuide = UILayoutGuide()
|
|
|
|
addLayoutGuide(dividerLayoutGuide)
|
|
|
|
fieldConstraints.append(contentsOf: [
|
|
|
|
dividerLayoutGuide.widthAnchor.constraint(equalToConstant: 8),
|
|
|
|
])
|
|
|
|
|
|
|
|
for (name, value) in fieldViews {
|
|
|
|
name.textAlignment = .right
|
|
|
|
name.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
|
|
|
|
value.textAlignment = .left
|
|
|
|
value.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
|
|
|
|
let fieldContainer = UIView()
|
|
|
|
fieldContainer.addSubview(name)
|
|
|
|
fieldContainer.addSubview(value)
|
|
|
|
stack.addArrangedSubview(fieldContainer)
|
|
|
|
fieldConstraints.append(contentsOf: [
|
|
|
|
name.leadingAnchor.constraint(equalTo: fieldContainer.leadingAnchor),
|
|
|
|
name.trailingAnchor.constraint(equalTo: dividerLayoutGuide.leadingAnchor),
|
|
|
|
name.topAnchor.constraint(equalTo: fieldContainer.topAnchor),
|
|
|
|
name.bottomAnchor.constraint(equalTo: fieldContainer.bottomAnchor),
|
|
|
|
|
|
|
|
value.leadingAnchor.constraint(equalTo: dividerLayoutGuide.trailingAnchor),
|
|
|
|
value.trailingAnchor.constraint(equalTo: fieldContainer.trailingAnchor),
|
|
|
|
value.topAnchor.constraint(equalTo: fieldContainer.topAnchor),
|
|
|
|
value.bottomAnchor.constraint(equalTo: fieldContainer.bottomAnchor),
|
|
|
|
|
|
|
|
name.widthAnchor.constraint(greaterThanOrEqualTo: value.widthAnchor, multiplier: 0.5),
|
|
|
|
name.widthAnchor.constraint(lessThanOrEqualTo: value.widthAnchor, multiplier: 2),
|
|
|
|
])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NSLayoutConstraint.activate(fieldConstraints)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|