Dyanmic type support in profile header view

This commit is contained in:
Shadowfacts 2022-11-04 21:32:49 -04:00
parent a991e0f429
commit 11233f7d25
6 changed files with 229 additions and 79 deletions

View File

@ -125,6 +125,7 @@
D64D0AAD2128D88B005A6F37 /* LocalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AAC2128D88B005A6F37 /* LocalData.swift */; }; D64D0AAD2128D88B005A6F37 /* LocalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AAC2128D88B005A6F37 /* LocalData.swift */; };
D64D0AB12128D9AE005A6F37 /* OnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */; }; D64D0AB12128D9AE005A6F37 /* OnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */; };
D64D8CA92463B494006B0BAA /* MultiThreadDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D8CA82463B494006B0BAA /* MultiThreadDictionary.swift */; }; D64D8CA92463B494006B0BAA /* MultiThreadDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D8CA82463B494006B0BAA /* MultiThreadDictionary.swift */; };
D651C5B42915B00400236EF6 /* ProfileFieldsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D651C5B32915B00400236EF6 /* ProfileFieldsView.swift */; };
D65234E12561AA68001AF9CF /* NotificationsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65234E02561AA68001AF9CF /* NotificationsTableViewController.swift */; }; D65234E12561AA68001AF9CF /* NotificationsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65234E02561AA68001AF9CF /* NotificationsTableViewController.swift */; };
D6531DEE246B81C9000F9538 /* GifvAttachmentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6531DED246B81C9000F9538 /* GifvAttachmentView.swift */; }; D6531DEE246B81C9000F9538 /* GifvAttachmentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6531DED246B81C9000F9538 /* GifvAttachmentView.swift */; };
D6531DF0246B867E000F9538 /* GifvAttachmentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6531DEF246B867E000F9538 /* GifvAttachmentViewController.swift */; }; D6531DF0246B867E000F9538 /* GifvAttachmentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6531DEF246B867E000F9538 /* GifvAttachmentViewController.swift */; };
@ -479,6 +480,7 @@
D64D0AAC2128D88B005A6F37 /* LocalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalData.swift; sourceTree = "<group>"; }; D64D0AAC2128D88B005A6F37 /* LocalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalData.swift; sourceTree = "<group>"; };
D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewController.swift; sourceTree = "<group>"; }; D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewController.swift; sourceTree = "<group>"; };
D64D8CA82463B494006B0BAA /* MultiThreadDictionary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiThreadDictionary.swift; sourceTree = "<group>"; }; D64D8CA82463B494006B0BAA /* MultiThreadDictionary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiThreadDictionary.swift; sourceTree = "<group>"; };
D651C5B32915B00400236EF6 /* ProfileFieldsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileFieldsView.swift; sourceTree = "<group>"; };
D65234E02561AA68001AF9CF /* NotificationsTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsTableViewController.swift; sourceTree = "<group>"; }; D65234E02561AA68001AF9CF /* NotificationsTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsTableViewController.swift; sourceTree = "<group>"; };
D6531DED246B81C9000F9538 /* GifvAttachmentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GifvAttachmentView.swift; sourceTree = "<group>"; }; D6531DED246B81C9000F9538 /* GifvAttachmentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GifvAttachmentView.swift; sourceTree = "<group>"; };
D6531DEF246B867E000F9538 /* GifvAttachmentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GifvAttachmentViewController.swift; sourceTree = "<group>"; }; D6531DEF246B867E000F9538 /* GifvAttachmentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GifvAttachmentViewController.swift; sourceTree = "<group>"; };
@ -1061,6 +1063,7 @@
children = ( children = (
D6412B0A24B0D4C600F5412E /* ProfileHeaderView.xib */, D6412B0A24B0D4C600F5412E /* ProfileHeaderView.xib */,
D6412B0C24B0D4CF00F5412E /* ProfileHeaderView.swift */, D6412B0C24B0D4CF00F5412E /* ProfileHeaderView.swift */,
D651C5B32915B00400236EF6 /* ProfileFieldsView.swift */,
); );
path = "Profile Header"; path = "Profile Header";
sourceTree = "<group>"; sourceTree = "<group>";
@ -1816,6 +1819,7 @@
D6BC9DD7232D7811002CA326 /* TimelinesPageViewController.swift in Sources */, D6BC9DD7232D7811002CA326 /* TimelinesPageViewController.swift in Sources */,
D60E2F2E244248BF005F8713 /* MastodonCachePersistentStore.swift in Sources */, D60E2F2E244248BF005F8713 /* MastodonCachePersistentStore.swift in Sources */,
D620483623D38075008A63EF /* ContentTextView.swift in Sources */, D620483623D38075008A63EF /* ContentTextView.swift in Sources */,
D651C5B42915B00400236EF6 /* ProfileFieldsView.swift in Sources */,
D6F2E965249E8BFD005846BB /* IssueReporterViewController.swift in Sources */, D6F2E965249E8BFD005846BB /* IssueReporterViewController.swift in Sources */,
D6A57408255C53EC00674551 /* ComposeTextViewCaretScrolling.swift in Sources */, D6A57408255C53EC00674551 /* ComposeTextViewCaretScrolling.swift in Sources */,
D6CA6A94249FADE700AD45C1 /* GalleryPlayerViewController.swift in Sources */, D6CA6A94249FADE700AD45C1 /* GalleryPlayerViewController.swift in Sources */,

View File

@ -10,9 +10,17 @@ import UIKit
class LinkTextView: UITextView { class LinkTextView: UITextView {
override func awakeFromNib() { override init(frame: CGRect, textContainer: NSTextContainer?) {
super.awakeFromNib() super.init(frame: frame, textContainer: textContainer)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
delaysContentTouches = false delaysContentTouches = false
isScrollEnabled = false isScrollEnabled = false
isEditable = false isEditable = false

View File

@ -0,0 +1,160 @@
//
// 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 {
traitCollection.preferredContentSizeCategory > .large
}
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)
}
}

View File

@ -36,9 +36,7 @@ class ProfileHeaderView: UIView {
@IBOutlet weak var usernameLabel: UILabel! @IBOutlet weak var usernameLabel: UILabel!
@IBOutlet weak var followsYouLabel: UILabel! @IBOutlet weak var followsYouLabel: UILabel!
@IBOutlet weak var noteTextView: StatusContentTextView! @IBOutlet weak var noteTextView: StatusContentTextView!
@IBOutlet weak var fieldsStackView: UIStackView! @IBOutlet weak var fieldsView: ProfileFieldsView!
@IBOutlet weak var fieldNamesStackView: UIStackView!
@IBOutlet weak var fieldValuesStackView: UIStackView!
@IBOutlet weak var pagesSegmentedControl: UISegmentedControl! @IBOutlet weak var pagesSegmentedControl: UISegmentedControl!
var accountID: String! var accountID: String!
@ -68,12 +66,23 @@ class ProfileHeaderView: UIView {
moreButton.layer.cornerRadius = 16 moreButton.layer.cornerRadius = 16
moreButton.layer.masksToBounds = true moreButton.layer.masksToBounds = true
NotificationCenter.default.addObserver(self, selector: #selector(updateUIForPreferences), name: .preferencesChanged, object: nil)
moreButton.addInteraction(UIPointerInteraction(delegate: self)) moreButton.addInteraction(UIPointerInteraction(delegate: self))
moreButton.showsMenuAsPrimaryAction = true moreButton.showsMenuAsPrimaryAction = true
moreButton.isContextMenuInteractionEnabled = true moreButton.isContextMenuInteractionEnabled = true
displayNameLabel.font = UIFontMetrics(forTextStyle: .title1).scaledFont(for: .systemFont(ofSize: 24, weight: .semibold))
displayNameLabel.adjustsFontForContentSizeCategory = true
usernameLabel.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .light))
usernameLabel.adjustsFontForContentSizeCategory = true
followsYouLabel.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 14))
followsYouLabel.adjustsFontForContentSizeCategory = true
noteTextView.defaultFont = .preferredFont(forTextStyle: .body)
noteTextView.adjustsFontForContentSizeCategory = true
NotificationCenter.default.addObserver(self, selector: #selector(updateUIForPreferences), name: .preferencesChanged, object: nil)
} }
private func createObservers() { private func createObservers() {
@ -128,43 +137,14 @@ class ProfileHeaderView: UIView {
} }
} }
fieldsStackView.isHidden = account.fields.isEmpty fieldsView.updateUI(account: account)
fieldNamesStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
fieldValuesStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
var fieldAccessibilityElements = [Any]()
for field in account.fields {
let nameLabel = EmojiLabel()
nameLabel.text = field.name
nameLabel.font = .boldSystemFont(ofSize: 17)
nameLabel.textAlignment = .right
nameLabel.numberOfLines = 0
nameLabel.lineBreakMode = .byWordWrapping
nameLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
nameLabel.setEmojis(account.emojis, identifier: "")
fieldNamesStackView.addArrangedSubview(nameLabel)
let valueTextView = ContentTextView()
valueTextView.isSelectable = false
valueTextView.font = .systemFont(ofSize: 17)
valueTextView.setTextFromHtml(field.value)
valueTextView.setEmojis(account.emojis, identifier: account.id)
valueTextView.textAlignment = .left
valueTextView.awakeFromNib()
valueTextView.navigationDelegate = delegate
valueTextView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
fieldValuesStackView.addArrangedSubview(valueTextView)
nameLabel.heightAnchor.constraint(equalTo: valueTextView.heightAnchor).isActive = true
fieldAccessibilityElements.append(nameLabel)
fieldAccessibilityElements.append(valueTextView)
}
accessibilityElements = [ accessibilityElements = [
displayNameLabel!, displayNameLabel!,
usernameLabel!, usernameLabel!,
noteTextView!, noteTextView!,
] + fieldAccessibilityElements + [ // TODO: voiceover for fieldsview
// fieldsView!,
moreButton!, moreButton!,
pagesSegmentedControl!, pagesSegmentedControl!,
] ]

View File

@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18121" 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="retina6_1" orientation="portrait" appearance="light"/> <device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies> <dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18091"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/> <capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/> <capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@ -14,13 +15,13 @@
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/> <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<subviews> <subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="dgG-dR-lSv"> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="dgG-dR-lSv">
<rect key="frame" x="0.0" y="44" width="414" height="150"/> <rect key="frame" x="0.0" y="48" width="414" height="150"/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="150" id="aCE-CA-XWm"/> <constraint firstAttribute="height" constant="150" id="aCE-CA-XWm"/>
</constraints> </constraints>
</imageView> </imageView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="wT9-2J-uSY"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="wT9-2J-uSY">
<rect key="frame" x="16" y="134" width="120" height="120"/> <rect key="frame" x="16" y="138" width="120" height="120"/>
<subviews> <subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="TkY-oK-if4"> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="TkY-oK-if4">
<rect key="frame" x="2" y="2" width="116" height="116"/> <rect key="frame" x="2" y="2" width="116" height="116"/>
@ -38,14 +39,14 @@
<constraint firstItem="TkY-oK-if4" firstAttribute="centerX" secondItem="wT9-2J-uSY" secondAttribute="centerX" id="ozz-sa-gSc"/> <constraint firstItem="TkY-oK-if4" firstAttribute="centerX" secondItem="wT9-2J-uSY" secondAttribute="centerX" id="ozz-sa-gSc"/>
</constraints> </constraints>
</view> </view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Display name" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumFontSize="10" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vcl-Gl-kXl" customClass="EmojiLabel" customModule="Tusker" customModuleProvider="target"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" text="Display name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vcl-Gl-kXl" customClass="EmojiLabel" customModule="Tusker" customModuleProvider="target">
<rect key="frame" x="144" y="202" width="254" height="24"/> <rect key="frame" x="144" y="206" width="254" height="32"/>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="20"/> <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="24"/>
<nil key="textColor"/> <nil key="textColor"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bRJ-Xf-kc9" customClass="VisualEffectImageButton" customModule="Tusker" customModuleProvider="target"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bRJ-Xf-kc9" customClass="VisualEffectImageButton" customModule="Tusker" customModuleProvider="target">
<rect key="frame" x="374" y="154" width="32" height="32"/> <rect key="frame" x="374" y="158" width="32" height="32"/>
<viewLayoutGuide key="safeArea" id="kQa-ou-pQz"/> <viewLayoutGuide key="safeArea" id="kQa-ou-pQz"/>
<accessibility key="accessibilityConfiguration" label="More Actions"> <accessibility key="accessibilityConfiguration" label="More Actions">
<accessibilityTraits key="traits" button="YES"/> <accessibilityTraits key="traits" button="YES"/>
@ -59,7 +60,7 @@
</userDefinedRuntimeAttributes> </userDefinedRuntimeAttributes>
</view> </view>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="top" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="u4P-3i-gEq"> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="top" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="u4P-3i-gEq">
<rect key="frame" x="16" y="262" width="398" height="600"/> <rect key="frame" x="16" y="419" width="398" height="443"/>
<subviews> <subviews>
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Follows you" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="UF8-nI-KVj"> <label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Follows you" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="UF8-nI-KVj">
<rect key="frame" x="0.0" y="0.0" width="75.5" height="0.0"/> <rect key="frame" x="0.0" y="0.0" width="75.5" height="0.0"/>
@ -68,29 +69,21 @@
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" horizontalHuggingPriority="249" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" scrollEnabled="NO" delaysContentTouches="NO" editable="NO" textAlignment="natural" selectable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1O8-2P-Gbf" customClass="StatusContentTextView" customModule="Tusker" customModuleProvider="target"> <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" horizontalHuggingPriority="249" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" scrollEnabled="NO" delaysContentTouches="NO" editable="NO" textAlignment="natural" selectable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1O8-2P-Gbf" customClass="StatusContentTextView" customModule="Tusker" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="382" height="186.5"/> <rect key="frame" x="0.0" y="0.0" width="382" height="259.5"/>
<string key="text">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string> <string key="text">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string>
<color key="textColor" systemColor="labelColor"/> <color key="textColor" systemColor="labelColor"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/> <fontDescription key="fontDescription" type="system" pointSize="17"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/> <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
</textView> </textView>
<stackView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="251" distribution="fillProportionally" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="sp4-Zb-00B"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="vKC-m1-Sbs" customClass="ProfileFieldsView" customModule="Tusker" customModuleProvider="target">
<rect key="frame" x="0.0" y="194.5" width="382" height="358"/> <rect key="frame" x="0.0" y="267.5" width="398" height="128"/>
<subviews> <color key="backgroundColor" systemColor="systemBackgroundColor"/>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="aqG-FA-so5">
<rect key="frame" x="0.0" y="0.0" width="186.5" height="358"/>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="EfH-Dj-Jmn">
<rect key="frame" x="194.5" y="0.0" width="187.5" height="358"/>
</stackView>
</subviews>
<constraints> <constraints>
<constraint firstItem="EfH-Dj-Jmn" firstAttribute="width" relation="greaterThanOrEqual" secondItem="aqG-FA-so5" secondAttribute="width" multiplier="0.5" id="2hZ-pF-C9b"/> <constraint firstAttribute="height" constant="128" placeholder="YES" id="xbR-M6-H0I"/>
<constraint firstItem="EfH-Dj-Jmn" firstAttribute="width" relation="lessThanOrEqual" secondItem="aqG-FA-so5" secondAttribute="width" multiplier="2" id="Lir-Ff-z0m"/>
</constraints> </constraints>
</stackView> </view>
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="n1M-vM-Cj0"> <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="n1M-vM-Cj0">
<rect key="frame" x="0.0" y="560.5" width="382" height="32"/> <rect key="frame" x="0.0" y="403.5" width="382" height="32"/>
<segments> <segments>
<segment title="Posts"/> <segment title="Posts"/>
<segment title="Posts and Replies"/> <segment title="Posts and Replies"/>
@ -101,7 +94,7 @@
</connections> </connections>
</segmentedControl> </segmentedControl>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5ja-fK-Fqz"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5ja-fK-Fqz">
<rect key="frame" x="0.0" y="599.5" width="398" height="0.5"/> <rect key="frame" x="0.0" y="442.5" width="398" height="0.5"/>
<color key="backgroundColor" systemColor="separatorColor"/> <color key="backgroundColor" systemColor="separatorColor"/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="0.5" id="VwS-gV-q8M"/> <constraint firstAttribute="height" constant="0.5" id="VwS-gV-q8M"/>
@ -109,14 +102,14 @@
</view> </view>
</subviews> </subviews>
<constraints> <constraints>
<constraint firstItem="vKC-m1-Sbs" firstAttribute="width" secondItem="u4P-3i-gEq" secondAttribute="width" id="0dI-ax-7eI"/>
<constraint firstItem="n1M-vM-Cj0" firstAttribute="width" secondItem="u4P-3i-gEq" secondAttribute="width" constant="-16" id="9Ds-zl-acc"/> <constraint firstItem="n1M-vM-Cj0" firstAttribute="width" secondItem="u4P-3i-gEq" secondAttribute="width" constant="-16" id="9Ds-zl-acc"/>
<constraint firstItem="sp4-Zb-00B" firstAttribute="width" secondItem="u4P-3i-gEq" secondAttribute="width" constant="-16" id="Qum-qT-goH"/>
<constraint firstItem="5ja-fK-Fqz" firstAttribute="width" secondItem="u4P-3i-gEq" secondAttribute="width" id="azv-le-93y"/> <constraint firstItem="5ja-fK-Fqz" firstAttribute="width" secondItem="u4P-3i-gEq" secondAttribute="width" id="azv-le-93y"/>
<constraint firstItem="1O8-2P-Gbf" firstAttribute="width" secondItem="u4P-3i-gEq" secondAttribute="width" constant="-16" id="hnA-3G-B9B"/> <constraint firstItem="1O8-2P-Gbf" firstAttribute="width" secondItem="u4P-3i-gEq" secondAttribute="width" constant="-16" id="hnA-3G-B9B"/>
</constraints> </constraints>
</stackView> </stackView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="@username" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1C3-Pd-QiL"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="@username" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1C3-Pd-QiL">
<rect key="frame" x="144" y="234" width="254" height="18"/> <rect key="frame" x="144" y="238" width="254" height="18"/>
<fontDescription key="fontDescription" type="system" weight="light" pointSize="15"/> <fontDescription key="fontDescription" type="system" weight="light" pointSize="15"/>
<color key="textColor" systemColor="secondaryLabelColor"/> <color key="textColor" systemColor="secondaryLabelColor"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
@ -132,25 +125,24 @@
<constraint firstItem="vcl-Gl-kXl" firstAttribute="leading" secondItem="wT9-2J-uSY" secondAttribute="trailing" constant="8" id="8ho-WU-MxW"/> <constraint firstItem="vcl-Gl-kXl" firstAttribute="leading" secondItem="wT9-2J-uSY" secondAttribute="trailing" constant="8" id="8ho-WU-MxW"/>
<constraint firstItem="vUN-kp-3ea" firstAttribute="bottom" secondItem="u4P-3i-gEq" secondAttribute="bottom" id="9zc-N2-mfI"/> <constraint firstItem="vUN-kp-3ea" firstAttribute="bottom" secondItem="u4P-3i-gEq" secondAttribute="bottom" id="9zc-N2-mfI"/>
<constraint firstItem="bRJ-Xf-kc9" firstAttribute="bottom" secondItem="dgG-dR-lSv" secondAttribute="bottom" constant="-8" id="AXS-bG-20Q"/> <constraint firstItem="bRJ-Xf-kc9" firstAttribute="bottom" secondItem="dgG-dR-lSv" secondAttribute="bottom" constant="-8" id="AXS-bG-20Q"/>
<constraint firstItem="1C3-Pd-QiL" firstAttribute="bottom" secondItem="TkY-oK-if4" secondAttribute="bottom" id="OpB-YM-gyu"/> <constraint firstItem="1C3-Pd-QiL" firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="TkY-oK-if4" secondAttribute="bottom" id="OpB-YM-gyu"/>
<constraint firstItem="dgG-dR-lSv" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="VD1-yc-KSa"/> <constraint firstItem="dgG-dR-lSv" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="VD1-yc-KSa"/>
<constraint firstItem="wT9-2J-uSY" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="16" id="WNS-AR-ff2"/> <constraint firstItem="wT9-2J-uSY" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="16" id="WNS-AR-ff2"/>
<constraint firstItem="bRJ-Xf-kc9" firstAttribute="trailing" secondItem="vUN-kp-3ea" secondAttribute="trailing" constant="-8" id="ZB4-ys-9zP"/> <constraint firstItem="bRJ-Xf-kc9" firstAttribute="trailing" secondItem="vUN-kp-3ea" secondAttribute="trailing" constant="-8" id="ZB4-ys-9zP"/>
<constraint firstItem="1C3-Pd-QiL" firstAttribute="top" relation="greaterThanOrEqual" secondItem="vcl-Gl-kXl" secondAttribute="bottom" id="d0z-X6-Sig"/> <constraint firstItem="1C3-Pd-QiL" firstAttribute="top" secondItem="vcl-Gl-kXl" secondAttribute="bottom" id="d0z-X6-Sig"/>
<constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="vcl-Gl-kXl" secondAttribute="trailing" constant="16" id="e38-Od-kPg"/> <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="vcl-Gl-kXl" secondAttribute="trailing" constant="16" id="e38-Od-kPg"/>
<constraint firstItem="u4P-3i-gEq" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="16" id="hgl-UR-o3W"/> <constraint firstItem="u4P-3i-gEq" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="16" id="hgl-UR-o3W"/>
<constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="dgG-dR-lSv" secondAttribute="trailing" id="j0d-hY-815"/> <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="dgG-dR-lSv" secondAttribute="trailing" id="j0d-hY-815"/>
<constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="1C3-Pd-QiL" secondAttribute="trailing" constant="16" id="pcH-vi-2zH"/> <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="1C3-Pd-QiL" secondAttribute="trailing" constant="16" id="pcH-vi-2zH"/>
<constraint firstAttribute="trailing" secondItem="u4P-3i-gEq" secondAttribute="trailing" id="ph6-NT-A02"/> <constraint firstAttribute="trailing" secondItem="u4P-3i-gEq" secondAttribute="trailing" id="ph6-NT-A02"/>
<constraint firstItem="u4P-3i-gEq" firstAttribute="top" secondItem="wT9-2J-uSY" secondAttribute="bottom" constant="8" id="tKQ-6d-Z55"/> <constraint firstItem="u4P-3i-gEq" firstAttribute="top" relation="greaterThanOrEqual" secondItem="wT9-2J-uSY" secondAttribute="bottom" constant="8" id="tKQ-6d-Z55"/>
<constraint firstItem="u4P-3i-gEq" firstAttribute="top" relation="greaterThanOrEqual" secondItem="vcl-Gl-kXl" secondAttribute="bottom" constant="8" id="xDD-rx-gC0"/>
</constraints> </constraints>
<connections> <connections>
<outlet property="avatarContainerView" destination="wT9-2J-uSY" id="yEm-h7-tfq"/> <outlet property="avatarContainerView" destination="wT9-2J-uSY" id="yEm-h7-tfq"/>
<outlet property="avatarImageView" destination="TkY-oK-if4" id="bSJ-7z-j4w"/> <outlet property="avatarImageView" destination="TkY-oK-if4" id="bSJ-7z-j4w"/>
<outlet property="displayNameLabel" destination="vcl-Gl-kXl" id="64n-a9-my0"/> <outlet property="displayNameLabel" destination="vcl-Gl-kXl" id="64n-a9-my0"/>
<outlet property="fieldNamesStackView" destination="aqG-FA-so5" id="prA-n7-blZ"/> <outlet property="fieldsView" destination="vKC-m1-Sbs" id="FeE-jh-lYH"/>
<outlet property="fieldValuesStackView" destination="EfH-Dj-Jmn" id="LMk-Hn-EkY"/>
<outlet property="fieldsStackView" destination="sp4-Zb-00B" id="eyx-GF-2Wf"/>
<outlet property="followsYouLabel" destination="UF8-nI-KVj" id="dTe-DQ-eJV"/> <outlet property="followsYouLabel" destination="UF8-nI-KVj" id="dTe-DQ-eJV"/>
<outlet property="headerImageView" destination="dgG-dR-lSv" id="HXT-v4-2iX"/> <outlet property="headerImageView" destination="dgG-dR-lSv" id="HXT-v4-2iX"/>
<outlet property="moreButton" destination="bRJ-Xf-kc9" id="zIN-pz-L7y"/> <outlet property="moreButton" destination="bRJ-Xf-kc9" id="zIN-pz-L7y"/>
@ -164,7 +156,7 @@
<resources> <resources>
<image name="ellipsis" catalog="system" width="128" height="37"/> <image name="ellipsis" catalog="system" width="128" height="37"/>
<systemColor name="labelColor"> <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>
<systemColor name="secondaryLabelColor"> <systemColor name="secondaryLabelColor">
<color red="0.23529411764705882" green="0.23529411764705882" blue="0.2627450980392157" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> <color red="0.23529411764705882" green="0.23529411764705882" blue="0.2627450980392157" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>

View File

@ -36,16 +36,22 @@ class StatusMetaIndicatorsView: UIView {
private func commonInit() { private func commonInit() {
NotificationCenter.default.addObserver(self, selector: #selector(configureImageViews), name: UIAccessibility.boldTextStatusDidChangeNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(configureImageViews), name: UIAccessibility.boldTextStatusDidChangeNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(configureImageViews), name: UIContentSizeCategory.didChangeNotification, object: nil) }
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
if isUsingSingleAxis != needsSingleAxis {
for image in images {
configureImageView(image)
}
placeImageViews(images)
}
} }
@objc private func configureImageViews() { @objc private func configureImageViews() {
for image in images { for image in images {
configureImageView(image) configureImageView(image)
} }
if isUsingSingleAxis != needsSingleAxis {
placeImageViews(images)
}
} }
private func configureImageView(_ imageView: UIImageView) { private func configureImageView(_ imageView: UIImageView) {