Tusker/Tusker/Views/Status/StatusContentContainer.swift

123 lines
4.1 KiB
Swift

//
// StatusContentContainer.swift
// Tusker
//
// Created by Shadowfacts on 10/2/22.
// Copyright © 2022 Shadowfacts. All rights reserved.
//
import UIKit
class StatusContentContainer: UIView {
let contentTextView = StatusContentTextView().configure {
$0.adjustsFontForContentSizeCategory = true
$0.isScrollEnabled = false
$0.backgroundColor = nil
$0.isEditable = false
$0.isSelectable = false
}
let cardView = StatusCardView().configure {
NSLayoutConstraint.activate([
$0.heightAnchor.constraint(equalToConstant: 65),
])
}
let attachmentsView = AttachmentsContainerView().configure {
NSLayoutConstraint.activate([
$0.heightAnchor.constraint(equalTo: $0.widthAnchor, multiplier: 9/16),
])
}
let pollView = StatusPollView()
private var arrangedSubviews: [UIView] {
[contentTextView, cardView, attachmentsView, pollView]
}
private var isHiddenObservations: [NSKeyValueObservation] = []
private var verticalConstraints: [NSLayoutConstraint] = []
private var lastSubviewBottomConstraint: NSLayoutConstraint?
private var zeroHeightConstraint: NSLayoutConstraint!
private var isCollapsed = false
override init(frame: CGRect) {
super.init(frame: frame)
for subview in arrangedSubviews {
subview.translatesAutoresizingMaskIntoConstraints = false
addSubview(subview)
NSLayoutConstraint.activate([
subview.leadingAnchor.constraint(equalTo: leadingAnchor),
subview.trailingAnchor.constraint(equalTo: trailingAnchor),
])
}
// this constraint needs to have low priority so that during the collapse/expand animation, the content container is the view that shrinks/expands
zeroHeightConstraint = heightAnchor.constraint(equalToConstant: 0)
zeroHeightConstraint.priority = .defaultLow
setNeedsUpdateConstraints()
isHiddenObservations = arrangedSubviews.map {
$0.observe(\.isHidden) { [unowned self] _, _ in
self.setNeedsUpdateConstraints()
}
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func updateConstraints() {
NSLayoutConstraint.deactivate(verticalConstraints)
verticalConstraints = []
var lastVisibleSubview: UIView?
for subview in arrangedSubviews {
guard !subview.isHidden else {
continue
}
if let lastVisibleSubview {
verticalConstraints.append(subview.topAnchor.constraint(equalTo: lastVisibleSubview.bottomAnchor, constant: 4))
} else {
verticalConstraints.append(subview.topAnchor.constraint(equalTo: topAnchor))
}
lastVisibleSubview = subview
}
NSLayoutConstraint.activate(verticalConstraints)
lastSubviewBottomConstraint?.isActive = false
// this constraint needs to have low priority so that during the collapse/expand animation, the content container is the view that shrinks/expands
lastSubviewBottomConstraint = subviews.last(where: { !$0.isHidden })!.bottomAnchor.constraint(equalTo: bottomAnchor)
lastSubviewBottomConstraint!.isActive = !isCollapsed
lastSubviewBottomConstraint!.priority = .defaultLow
zeroHeightConstraint.isActive = isCollapsed
super.updateConstraints()
}
func setCollapsed(_ collapsed: Bool) {
guard collapsed != isCollapsed else {
return
}
isCollapsed = collapsed
// ensure that we have a lastSubviewBottomConstraint
updateConstraintsIfNeeded()
// force unwrap because the content container should always have at least one view
lastSubviewBottomConstraint!.isActive = !collapsed
zeroHeightConstraint.isActive = collapsed
}
}