forked from shadowfacts/Tusker
Dynamic Type support in status cells
This commit is contained in:
parent
bfdce07d81
commit
a991e0f429
|
@ -292,6 +292,8 @@ class AttachmentsContainerView: UIView {
|
|||
let imageView = UIImageView(image: image)
|
||||
imageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
let label = UILabel()
|
||||
label.font = .preferredFont(forTextStyle: .body)
|
||||
label.adjustsFontForContentSizeCategory = true
|
||||
label.text = "Sensitive Content"
|
||||
let stack = UIStackView(arrangedSubviews: [
|
||||
imageView,
|
||||
|
|
|
@ -49,16 +49,35 @@ class ConversationMainStatusTableViewCell: BaseStatusTableViewCell {
|
|||
moreButton!,
|
||||
]
|
||||
|
||||
contentTextView.defaultFont = .systemFont(ofSize: 18)
|
||||
profileDetailContainerView.addInteraction(UIContextMenuInteraction(delegate: self))
|
||||
|
||||
displayNameLabel.font = UIFontMetrics(forTextStyle: .title1).scaledFont(for: .systemFont(ofSize: 24, weight: .semibold))
|
||||
displayNameLabel.adjustsFontForContentSizeCategory = true
|
||||
|
||||
usernameLabel.font = UIFontMetrics(forTextStyle: .title2).scaledFont(for: .systemFont(ofSize: 17, weight: .light))
|
||||
usernameLabel.adjustsFontForContentSizeCategory = true
|
||||
|
||||
metaIndicatorsView.allowedIndicators = [.visibility, .localOnly]
|
||||
metaIndicatorsView.squeezeHorizontal = true
|
||||
metaIndicatorsView.primaryAxis = .horizontal
|
||||
|
||||
contentWarningLabel.font = .preferredFont(forTextStyle: .body).withTraits(.traitBold)!
|
||||
contentWarningLabel.adjustsFontForContentSizeCategory = true
|
||||
|
||||
contentTextView.defaultFont = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 18))
|
||||
contentTextView.adjustsFontForContentSizeCategory = true
|
||||
contentTextView.dataDetectorTypes = [.flightNumber, .address, .shipmentTrackingNumber, .phoneNumber]
|
||||
if #available(iOS 16.0, *) {
|
||||
contentTextView.dataDetectorTypes.formUnion([.money, .physicalValue])
|
||||
}
|
||||
|
||||
profileDetailContainerView.addInteraction(UIContextMenuInteraction(delegate: self))
|
||||
|
||||
metaIndicatorsView.allowedIndicators = [.visibility, .localOnly]
|
||||
metaIndicatorsView.squeezeHorizontal = true
|
||||
let metaFont = UIFontMetrics(forTextStyle: .caption1).scaledFont(for: .systemFont(ofSize: 15))
|
||||
totalFavoritesButton.titleLabel!.font = metaFont
|
||||
totalFavoritesButton.titleLabel!.adjustsFontForContentSizeCategory = true
|
||||
totalReblogsButton.titleLabel!.font = metaFont
|
||||
totalReblogsButton.titleLabel!.adjustsFontForContentSizeCategory = true
|
||||
timestampAndClientLabel.font = metaFont
|
||||
timestampAndClientLabel.adjustsFontForContentSizeCategory = true
|
||||
}
|
||||
|
||||
override func doUpdateUI(status: StatusMO, state: StatusState) {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
|
||||
<capability name="Image references" minToolsVersion="12.0"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||
|
@ -261,13 +261,13 @@
|
|||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="arrowshape.turn.up.left.fill" catalog="system" width="128" height="106"/>
|
||||
<image name="chevron.down" catalog="system" width="128" height="72"/>
|
||||
<image name="arrowshape.turn.up.left.fill" catalog="system" width="128" height="104"/>
|
||||
<image name="chevron.down" catalog="system" width="128" height="70"/>
|
||||
<image name="ellipsis" catalog="system" width="128" height="37"/>
|
||||
<image name="repeat" catalog="system" width="128" height="98"/>
|
||||
<image name="star.fill" catalog="system" width="128" height="116"/>
|
||||
<systemColor name="labelColor">
|
||||
<color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</systemColor>
|
||||
<systemColor name="opaqueSeparatorColor">
|
||||
<color red="0.77647058823529413" green="0.77647058823529413" blue="0.78431372549019607" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
|
|
|
@ -51,10 +51,12 @@ class StatusCardView: UIView {
|
|||
|
||||
titleLabel = UILabel()
|
||||
titleLabel.font = UIFont(descriptor: UIFontDescriptor.preferredFontDescriptor(withTextStyle: .subheadline).withSymbolicTraits(.traitBold)!, size: 0)
|
||||
titleLabel.adjustsFontForContentSizeCategory = true
|
||||
titleLabel.numberOfLines = 2
|
||||
|
||||
descriptionLabel = UILabel()
|
||||
descriptionLabel.font = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: .caption1), size: 0)
|
||||
descriptionLabel.adjustsFontForContentSizeCategory = true
|
||||
descriptionLabel.numberOfLines = 2
|
||||
descriptionLabel.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
|
||||
|
||||
|
|
|
@ -11,7 +11,8 @@ import UIKit
|
|||
class StatusContentContainer: UIView {
|
||||
|
||||
let contentTextView = StatusContentTextView().configure {
|
||||
$0.defaultFont = .systemFont(ofSize: 16)
|
||||
$0.defaultFont = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 16))
|
||||
$0.adjustsFontForContentSizeCategory = true
|
||||
$0.isScrollEnabled = false
|
||||
$0.backgroundColor = nil
|
||||
$0.isEditable = false
|
||||
|
|
|
@ -13,11 +13,48 @@ class StatusMetaIndicatorsView: UIView {
|
|||
|
||||
var allowedIndicators: Indicator = .all
|
||||
var squeezeHorizontal = false
|
||||
// The axis in which the indicators grow
|
||||
var primaryAxis: NSLayoutConstraint.Axis = .vertical
|
||||
// Only used when using single axis mode
|
||||
var secondaryAxisAlignment: Alignment = .leading
|
||||
private var images: [UIImageView] = []
|
||||
private var isUsingSingleAxis = false
|
||||
|
||||
private var needsSingleAxis: Bool {
|
||||
traitCollection.preferredContentSizeCategory > .extraLarge
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
private func commonInit() {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(configureImageViews), name: UIAccessibility.boldTextStatusDidChangeNotification, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(configureImageViews), name: UIContentSizeCategory.didChangeNotification, object: nil)
|
||||
}
|
||||
|
||||
@objc private func configureImageViews() {
|
||||
for image in images {
|
||||
configureImageView(image)
|
||||
}
|
||||
if isUsingSingleAxis != needsSingleAxis {
|
||||
placeImageViews(images)
|
||||
}
|
||||
}
|
||||
|
||||
private func configureImageView(_ imageView: UIImageView) {
|
||||
let weight: UIImage.SymbolWeight = UIAccessibility.isBoldTextEnabled ? .regular : traitCollection.preferredContentSizeCategory > .large ? .light : .thin
|
||||
let scale: UIImage.SymbolScale = traitCollection.preferredContentSizeCategory > .extraLarge ? .large : .default
|
||||
imageView.preferredSymbolConfiguration = .init(pointSize: 0, weight: weight, scale: scale)
|
||||
}
|
||||
|
||||
func updateUI(status: StatusMO) {
|
||||
images.forEach { $0.removeFromSuperview() }
|
||||
|
||||
var images: [UIImage] = []
|
||||
|
||||
if allowedIndicators.contains(.reply) && Preferences.shared.showIsStatusReplyIcon && status.inReplyToID != nil {
|
||||
|
@ -32,13 +69,66 @@ class StatusMetaIndicatorsView: UIView {
|
|||
images.append(UIImage(named: "link.broken")!)
|
||||
}
|
||||
|
||||
self.images = []
|
||||
for (index, image) in images.enumerated() {
|
||||
let v = UIImageView(image: image)
|
||||
let views = images.map {
|
||||
let v = UIImageView(image: $0)
|
||||
v.translatesAutoresizingMaskIntoConstraints = false
|
||||
v.contentMode = .scaleAspectFit
|
||||
v.tintColor = .secondaryLabel
|
||||
v.preferredSymbolConfiguration = .init(weight: .thin)
|
||||
configureImageView(v)
|
||||
return v
|
||||
}
|
||||
placeImageViews(views)
|
||||
}
|
||||
|
||||
private func placeImageViews(_ imageViews: [UIImageView]) {
|
||||
images.forEach { $0.removeFromSuperview() }
|
||||
images = imageViews
|
||||
|
||||
guard !images.isEmpty else {
|
||||
return
|
||||
}
|
||||
|
||||
isUsingSingleAxis = needsSingleAxis
|
||||
|
||||
if needsSingleAxis {
|
||||
for v in images {
|
||||
addSubview(v)
|
||||
|
||||
switch (primaryAxis, secondaryAxisAlignment) {
|
||||
case (.horizontal, .leading):
|
||||
v.topAnchor.constraint(equalTo: topAnchor).isActive = true
|
||||
case (.horizontal, .trailing):
|
||||
v.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
|
||||
case (.vertical, .leading):
|
||||
v.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
|
||||
case (.vertical, .trailing):
|
||||
v.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
|
||||
case (_, _):
|
||||
fatalError()
|
||||
}
|
||||
}
|
||||
if primaryAxis == .vertical {
|
||||
images.first!.topAnchor.constraint(equalTo: topAnchor).isActive = true
|
||||
images.last!.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
|
||||
} else {
|
||||
images.first!.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
|
||||
images.last!.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
|
||||
}
|
||||
for (a, b) in zip(images, images.dropFirst()) {
|
||||
if primaryAxis == .vertical {
|
||||
b.topAnchor.constraint(equalTo: a.bottomAnchor, constant: 4).isActive = true
|
||||
} else {
|
||||
b.leadingAnchor.constraint(equalTo: a.trailingAnchor, constant: 4).isActive = true
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
guard primaryAxis == .vertical || imageViews.count <= 2 else {
|
||||
fatalError("StatusMetaIndicatorsView does not support horizontal primary axis with more than 2 views yet")
|
||||
}
|
||||
|
||||
for (index, v) in images.enumerated() {
|
||||
addSubview(v)
|
||||
|
||||
if index % 2 == 0 {
|
||||
|
@ -64,14 +154,9 @@ class StatusMetaIndicatorsView: UIView {
|
|||
v.topAnchor.constraint(equalTo: self.images[index - 1].bottomAnchor, constant: 4).isActive = true
|
||||
}
|
||||
v.bottomAnchor.constraint(lessThanOrEqualTo: bottomAnchor).isActive = true
|
||||
|
||||
self.images.append(v)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension StatusMetaIndicatorsView {
|
||||
struct Indicator: OptionSet {
|
||||
let rawValue: Int
|
||||
|
||||
|
@ -81,4 +166,8 @@ extension StatusMetaIndicatorsView {
|
|||
|
||||
static let all: Indicator = [.reply, .visibility, .localOnly]
|
||||
}
|
||||
|
||||
enum Alignment {
|
||||
case leading, trailing
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ class TimelineStatusCollectionViewCell: UICollectionViewListCell, StatusCollecti
|
|||
|
||||
private lazy var reblogLabel = EmojiLabel().configure {
|
||||
$0.textColor = .secondaryLabel
|
||||
$0.font = .preferredFont(forTextStyle: .body)
|
||||
$0.adjustsFontForContentSizeCategory = true
|
||||
// this needs to have a higher priorty than the content container's zero height constraint
|
||||
$0.setContentHuggingPriority(.defaultHigh, for: .vertical)
|
||||
$0.isUserInteractionEnabled = true
|
||||
|
@ -58,7 +60,10 @@ class TimelineStatusCollectionViewCell: UICollectionViewListCell, StatusCollecti
|
|||
$0.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(accountPressed)))
|
||||
}
|
||||
|
||||
private let metaIndicatorsView = StatusMetaIndicatorsView()
|
||||
private let metaIndicatorsView = StatusMetaIndicatorsView().configure {
|
||||
$0.primaryAxis = .vertical
|
||||
$0.secondaryAxisAlignment = .trailing
|
||||
}
|
||||
|
||||
private lazy var contentVStack = UIStackView(arrangedSubviews: [
|
||||
nameHStack,
|
||||
|
@ -87,6 +92,7 @@ class TimelineStatusCollectionViewCell: UICollectionViewListCell, StatusCollecti
|
|||
UIFontDescriptor.TraitKey.weight: UIFont.Weight.semibold.rawValue,
|
||||
]
|
||||
]), size: 0)
|
||||
$0.adjustsFontForContentSizeCategory = true
|
||||
$0.setContentHuggingPriority(.init(251), for: .horizontal)
|
||||
$0.setContentCompressionResistancePriority(.init(749), for: .horizontal)
|
||||
}
|
||||
|
@ -98,6 +104,7 @@ class TimelineStatusCollectionViewCell: UICollectionViewListCell, StatusCollecti
|
|||
UIFontDescriptor.TraitKey.weight: UIFont.Weight.light.rawValue,
|
||||
]
|
||||
]), size: 0)
|
||||
$0.adjustsFontForContentSizeCategory = true
|
||||
$0.setContentHuggingPriority(.init(249), for: .horizontal)
|
||||
$0.setContentCompressionResistancePriority(.init(748), for: .horizontal)
|
||||
}
|
||||
|
@ -114,6 +121,7 @@ class TimelineStatusCollectionViewCell: UICollectionViewListCell, StatusCollecti
|
|||
UIFontDescriptor.TraitKey.weight: UIFont.Weight.light.rawValue,
|
||||
]
|
||||
]), size: 0)
|
||||
$0.adjustsFontForContentSizeCategory = true
|
||||
}
|
||||
|
||||
private(set) lazy var contentWarningLabel = EmojiLabel().configure {
|
||||
|
@ -124,6 +132,7 @@ class TimelineStatusCollectionViewCell: UICollectionViewListCell, StatusCollecti
|
|||
UIFontDescriptor.TraitKey.weight: UIFont.Weight.bold.rawValue,
|
||||
]
|
||||
]), size: 0)
|
||||
$0.adjustsFontForContentSizeCategory = true
|
||||
// this needs to have a higher priorty than the content container's zero height constraint
|
||||
$0.setContentHuggingPriority(.defaultHigh, for: .vertical)
|
||||
$0.isUserInteractionEnabled = true
|
||||
|
|
|
@ -45,18 +45,52 @@ class TimelineStatusTableViewCell: BaseStatusTableViewCell {
|
|||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
reblogLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(reblogLabelPressed)))
|
||||
|
||||
isAccessibilityElement = true
|
||||
|
||||
// todo: double check this on RTL layouts
|
||||
replyButton.imageView!.leadingAnchor.constraint(equalTo: contentTextView.leadingAnchor).isActive = true
|
||||
|
||||
contentTextView.defaultFont = .systemFont(ofSize: 16)
|
||||
reblogLabel.font = .preferredFont(forTextStyle: .body)
|
||||
reblogLabel.adjustsFontForContentSizeCategory = true
|
||||
reblogLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(reblogLabelPressed)))
|
||||
|
||||
avatarImageView.addInteraction(UIContextMenuInteraction(delegate: self))
|
||||
|
||||
displayNameLabel.font = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: .body).addingAttributes([
|
||||
.traits: [
|
||||
UIFontDescriptor.TraitKey.weight: UIFont.Weight.semibold.rawValue,
|
||||
]
|
||||
]), size: 0)
|
||||
displayNameLabel.adjustsFontForContentSizeCategory = true
|
||||
|
||||
usernameLabel.font = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: .body).addingAttributes([
|
||||
.traits: [
|
||||
UIFontDescriptor.TraitKey.weight: UIFont.Weight.light.rawValue,
|
||||
]
|
||||
]), size: 0)
|
||||
usernameLabel.adjustsFontForContentSizeCategory = true
|
||||
|
||||
timestampLabel.font = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: .body).addingAttributes([
|
||||
.traits: [
|
||||
UIFontDescriptor.TraitKey.weight: UIFont.Weight.light.rawValue,
|
||||
]
|
||||
]), size: 0)
|
||||
timestampLabel.adjustsFontForContentSizeCategory = true
|
||||
|
||||
metaIndicatorsView.primaryAxis = .vertical
|
||||
metaIndicatorsView.secondaryAxisAlignment = .trailing
|
||||
|
||||
contentWarningLabel.font = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: .body).addingAttributes([
|
||||
.traits: [
|
||||
UIFontDescriptor.TraitKey.weight: UIFont.Weight.bold.rawValue,
|
||||
]
|
||||
]), size: 0)
|
||||
contentWarningLabel.adjustsFontForContentSizeCategory = true
|
||||
|
||||
contentTextView.defaultFont = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 16))
|
||||
contentTextView.adjustsFontForContentSizeCategory = true
|
||||
|
||||
// todo: double check this on RTL layouts
|
||||
replyButton.imageView!.leadingAnchor.constraint(equalTo: contentTextView.leadingAnchor).isActive = true
|
||||
|
||||
updateActionsVisibility()
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue