Collapsible Cells

* Change the look of the collapsible cell
* Add a reason to the collapsed cell
This commit is contained in:
Fahim Farook 2023-01-25 15:25:53 +04:00
parent e68100eb71
commit ea30b9866d
6 changed files with 95 additions and 39 deletions

View File

@ -11,6 +11,7 @@ import Foundation
public class CollapseState: Equatable {
public var collapsible: Bool?
public var collapsed: Bool?
public var reason = ""
public var unknown: Bool {
collapsible == nil || collapsed == nil

View File

@ -16,6 +16,7 @@ extension CollapseState {
if Preferences.shared.collapseLongPosts,
height > 600 || (textLength != nil && textLength! > 500) {
longEnoughToCollapse = true
self.reason = "Read More ..."
} else {
longEnoughToCollapse = false
}
@ -25,13 +26,16 @@ extension CollapseState {
let collapseDueToContentWarning: Bool?
if contentWarningCollapsible {
let lowercased = status.spoilerText.lowercased()
let opposite = Preferences.shared.oppositeCollapseKeywords.contains { lowercased.contains($0.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()) }
let opposite = Preferences.shared.oppositeCollapseKeywords.contains { lowercased.contains($0.trimmingCharacters(in: .whitespacesAndNewlines).lowercased())
}
if Preferences.shared.expandAllContentWarnings {
collapseDueToContentWarning = opposite
} else {
collapseDueToContentWarning = !opposite
}
if let collapse = collapseDueToContentWarning, collapse {
self.reason = "Content Warning"
}
} else {
collapseDueToContentWarning = nil
}

View File

@ -104,16 +104,9 @@ class ConversationMainStatusCollectionViewCell: UICollectionViewListCell, Status
$0.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(collapseButtonPressed)))
}
private(set) lazy var collapseButton = StatusCollapseButton(configuration: {
var config = UIButton.Configuration.filled()
config.image = UIImage(systemName: "chevron.down")
return config
}()).configure {
// this button is so big that dimming its background color is visually distracting
$0.tintAdjustmentMode = .normal
$0.setContentHuggingPriority(.defaultHigh, for: .vertical)
$0.addTarget(self, action: #selector(collapseButtonPressed), for: .touchUpInside)
}
private(set) lazy var collapseButton = StatusCollapseButton {
self.toggleCollapse()
}
let contentContainer = StatusContentContainer(useTopSpacer: true).configure {
$0.contentTextView.defaultFont = ConversationMainStatusCollectionViewCell.contentFont

View File

@ -8,18 +8,85 @@
import UIKit
class StatusCollapseButton: UIButton {
class StatusCollapseButton: UIView {
var title: String {
get {
return lblTitle.text ?? ""
}
set {
lblTitle.text = newValue
}
}
private var action: (()->Void)!
private var lblTitle = UILabel()
private var imgView = UIImageView()
private var isCollapsed = true
convenience init(action: @escaping (()->Void)) {
self.init(frame: CGRect.zero)
self.action = action
}
private var interactionBounds: CGRect!
override func layoutSubviews() {
super.layoutSubviews()
interactionBounds = bounds.inset(by: UIEdgeInsets(top: -8, left: 0, bottom: 0, right: 0))
}
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
return interactionBounds.contains(point)
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// Eat event
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
// Eat event
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
// Eat event
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if isCollapsed {
imgView.image = UIImage(systemName: "chevron.compact.up")
} else {
imgView.image = UIImage(systemName: "chevron.compact.down")
}
isCollapsed.toggle()
action()
}
// MARK: - Private Methods
private func setup() {
self.isUserInteractionEnabled = true
layer.cornerRadius = 8
backgroundColor = .lightGray
// Title
lblTitle.translatesAutoresizingMaskIntoConstraints = false
lblTitle.textColor = .white
lblTitle.textAlignment = .center
addSubview(lblTitle)
// Chevron
imgView.translatesAutoresizingMaskIntoConstraints = false
imgView.tintColor = .white
imgView.image = UIImage(systemName: "chevron.compact.down")
addSubview(imgView)
NSLayoutConstraint.activate([
// Main view
heightAnchor.constraint(equalToConstant: 30),
// Title
lblTitle.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 8),
lblTitle.topAnchor.constraint(equalTo: topAnchor, constant: 8),
lblTitle.trailingAnchor.constraint(equalTo: imgView.leadingAnchor, constant: -4),
lblTitle.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8),
// Chevron
imgView.widthAnchor.constraint(equalToConstant: 20),
imgView.topAnchor.constraint(equalTo: topAnchor, constant: 5),
imgView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8),
imgView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -5)
])
}
}

View File

@ -113,17 +113,16 @@ extension StatusCollectionViewCell {
if statusState.collapsible! && showStatusAutomatically {
statusState.collapsed = false
}
}
}
collapseButton.title = statusState.reason
collapseButton.isHidden = !statusState.collapsible!
contentContainer.setCollapsed(statusState.collapsed!)
if statusState.collapsed! {
contentContainer.alpha = 0
// TODO: is this accessing the image view before the button's been laid out?
collapseButton.imageView!.transform = CGAffineTransform(rotationAngle: 0)
collapseButton.accessibilityLabel = NSLocalizedString("Expand Status", comment: "expand status button accessibility label")
} else {
contentContainer.alpha = 1
collapseButton.imageView!.transform = CGAffineTransform(rotationAngle: .pi)
collapseButton.accessibilityLabel = NSLocalizedString("Collapse Status", comment: "collapse status button accessibility label")
}
}

View File

@ -14,7 +14,6 @@ private let reblogIcon = UIImage(systemName: "repeat")
private let hashtagIcon = UIImage(systemName: "number")
class TimelineStatusCollectionViewCell: UICollectionViewListCell, StatusCollectionViewCell {
static let separatorInsets = NSDirectionalEdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 0)
static let contentFont = UIFontMetrics.default.scaledFont(for: .systemFont(ofSize: 16))
static let monospaceFont = UIFontMetrics.default.scaledFont(for: .monospacedSystemFont(ofSize: 16, weight: .regular))
@ -154,17 +153,10 @@ class TimelineStatusCollectionViewCell: UICollectionViewListCell, StatusCollecti
$0.isUserInteractionEnabled = true
$0.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(collapseButtonPressed)))
}
private(set) lazy var collapseButton = StatusCollapseButton(configuration: {
var config = UIButton.Configuration.filled()
config.image = UIImage(systemName: "chevron.down")
return config
}()).configure {
// this button is so big that dimming its background color is visually distracting
$0.tintAdjustmentMode = .normal
$0.setContentHuggingPriority(.defaultHigh, for: .vertical)
$0.addTarget(self, action: #selector(collapseButtonPressed), for: .touchUpInside)
}
private(set) lazy var collapseButton = StatusCollapseButton {
self.toggleCollapse()
}
let contentContainer = StatusContentContainer(useTopSpacer: false).configure {
$0.contentTextView.defaultFont = TimelineStatusCollectionViewCell.contentFont