chore: remove UIView+Contraint

This commit is contained in:
sunxiaojian 2021-04-19 11:41:50 +08:00
parent 5ae2c44642
commit f6be51dd0f
11 changed files with 191 additions and 342 deletions

View File

@ -132,7 +132,6 @@
2DF75BC725D1475D00694EC8 /* ManagedObjectContextObjectsDidChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DF75BC625D1475D00694EC8 /* ManagedObjectContextObjectsDidChange.swift */; }; 2DF75BC725D1475D00694EC8 /* ManagedObjectContextObjectsDidChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DF75BC625D1475D00694EC8 /* ManagedObjectContextObjectsDidChange.swift */; };
2DFAD5272616F9D300F9EE7C /* SearchViewController+Searching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DFAD5262616F9D300F9EE7C /* SearchViewController+Searching.swift */; }; 2DFAD5272616F9D300F9EE7C /* SearchViewController+Searching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DFAD5262616F9D300F9EE7C /* SearchViewController+Searching.swift */; };
2DFAD5372617010500F9EE7C /* SearchingTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DFAD5362617010500F9EE7C /* SearchingTableViewCell.swift */; }; 2DFAD5372617010500F9EE7C /* SearchingTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DFAD5362617010500F9EE7C /* SearchingTableViewCell.swift */; };
2DFF41892614A4DC00F776A4 /* UIView+Constraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DFF41882614A4DC00F776A4 /* UIView+Constraint.swift */; };
5D0393902612D259007FE196 /* WebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D03938F2612D259007FE196 /* WebViewController.swift */; }; 5D0393902612D259007FE196 /* WebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D03938F2612D259007FE196 /* WebViewController.swift */; };
5D0393962612D266007FE196 /* WebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D0393952612D266007FE196 /* WebViewModel.swift */; }; 5D0393962612D266007FE196 /* WebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D0393952612D266007FE196 /* WebViewModel.swift */; };
5D526FE225BE9AC400460CB9 /* MastodonSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 5D526FE125BE9AC400460CB9 /* MastodonSDK */; }; 5D526FE225BE9AC400460CB9 /* MastodonSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 5D526FE125BE9AC400460CB9 /* MastodonSDK */; };
@ -531,7 +530,6 @@
2DF75BC625D1475D00694EC8 /* ManagedObjectContextObjectsDidChange.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManagedObjectContextObjectsDidChange.swift; sourceTree = "<group>"; }; 2DF75BC625D1475D00694EC8 /* ManagedObjectContextObjectsDidChange.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManagedObjectContextObjectsDidChange.swift; sourceTree = "<group>"; };
2DFAD5262616F9D300F9EE7C /* SearchViewController+Searching.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SearchViewController+Searching.swift"; sourceTree = "<group>"; }; 2DFAD5262616F9D300F9EE7C /* SearchViewController+Searching.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SearchViewController+Searching.swift"; sourceTree = "<group>"; };
2DFAD5362617010500F9EE7C /* SearchingTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchingTableViewCell.swift; sourceTree = "<group>"; }; 2DFAD5362617010500F9EE7C /* SearchingTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchingTableViewCell.swift; sourceTree = "<group>"; };
2DFF41882614A4DC00F776A4 /* UIView+Constraint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Constraint.swift"; sourceTree = "<group>"; };
2E1F6A67FDF9771D3E064FDC /* Pods-Mastodon.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.debug.xcconfig"; sourceTree = "<group>"; }; 2E1F6A67FDF9771D3E064FDC /* Pods-Mastodon.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.debug.xcconfig"; sourceTree = "<group>"; };
3C030226D3C73DCC23D67452 /* Pods_Mastodon_MastodonUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Mastodon_MastodonUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3C030226D3C73DCC23D67452 /* Pods_Mastodon_MastodonUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Mastodon_MastodonUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
452147B2903DF38070FE56A2 /* Pods_MastodonTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MastodonTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 452147B2903DF38070FE56A2 /* Pods_MastodonTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MastodonTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@ -1646,7 +1644,6 @@
DB47229625F9EFAD00DA7F53 /* NSManagedObjectContext.swift */, DB47229625F9EFAD00DA7F53 /* NSManagedObjectContext.swift */,
2D32EAB925CB9B0500C9ED86 /* UIView.swift */, 2D32EAB925CB9B0500C9ED86 /* UIView.swift */,
5DA732CB2629CEF500A92342 /* UIView+Remove.swift */, 5DA732CB2629CEF500A92342 /* UIView+Remove.swift */,
2DFF41882614A4DC00F776A4 /* UIView+Constraint.swift */,
DB8AF55C25C138B7002E6C99 /* UIViewController.swift */, DB8AF55C25C138B7002E6C99 /* UIViewController.swift */,
2D24E1222626ED9D00A59D4F /* UIView+Gesture.swift */, 2D24E1222626ED9D00A59D4F /* UIView+Gesture.swift */,
2D3F9E0325DFA133004262D9 /* UITapGestureRecognizer.swift */, 2D3F9E0325DFA133004262D9 /* UITapGestureRecognizer.swift */,
@ -2476,7 +2473,6 @@
2D7867192625B77500211898 /* NotificationItem.swift in Sources */, 2D7867192625B77500211898 /* NotificationItem.swift in Sources */,
DB45FAB625CA5485005A8AC7 /* UIAlertController.swift in Sources */, DB45FAB625CA5485005A8AC7 /* UIAlertController.swift in Sources */,
DBE0821525CD382600FD6BBD /* MastodonRegisterViewController.swift in Sources */, DBE0821525CD382600FD6BBD /* MastodonRegisterViewController.swift in Sources */,
2DFF41892614A4DC00F776A4 /* UIView+Constraint.swift in Sources */,
2D5A3D0325CF8742002347D6 /* ControlContainableScrollViews.swift in Sources */, 2D5A3D0325CF8742002347D6 /* ControlContainableScrollViews.swift in Sources */,
DB98336B25C9420100AD9700 /* APIService+App.swift in Sources */, DB98336B25C9420100AD9700 /* APIService+App.swift in Sources */,
DBA0A11325FB3FC10079C110 /* ComposeToolbarView.swift in Sources */, DBA0A11325FB3FC10079C110 /* ComposeToolbarView.swift in Sources */,

View File

@ -1,262 +0,0 @@
//
// UIView+Constraint.swift
// Mastodon
//
// Created by sxiaojian on 2021/3/31.
//
import UIKit
enum Dimension {
case width
case height
var layoutAttribute: NSLayoutConstraint.Attribute {
switch self {
case .width:
return .width
case .height:
return .height
}
}
}
extension UIView {
func constrain(toSuperviewEdges: UIEdgeInsets?) {
guard let view = superview else { assert(false, "Superview cannot be nil when adding contraints"); return}
translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
NSLayoutConstraint(item: self,
attribute: .leading,
relatedBy: .equal,
toItem: view,
attribute: .leading,
multiplier: 1.0,
constant: toSuperviewEdges?.left ?? 0.0),
NSLayoutConstraint(item: self,
attribute: .top,
relatedBy: .equal,
toItem: view,
attribute: .top,
multiplier: 1.0,
constant: toSuperviewEdges?.top ?? 0.0),
NSLayoutConstraint(item: view,
attribute: .trailing,
relatedBy: .equal,
toItem: self,
attribute: .trailing,
multiplier: 1.0,
constant: toSuperviewEdges?.right ?? 0.0),
NSLayoutConstraint(item: view,
attribute: .bottom,
relatedBy: .equal,
toItem: self,
attribute: .bottom,
multiplier: 1.0,
constant: toSuperviewEdges?.bottom ?? 0.0)
])
}
func constrain(_ constraints: [NSLayoutConstraint?]) {
guard superview != nil else { assert(false, "Superview cannot be nil when adding contraints"); return }
translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate(constraints.compactMap { $0 })
}
func constraint(_ attribute: NSLayoutConstraint.Attribute, toView: UIView, constant: CGFloat?) -> NSLayoutConstraint? {
guard superview != nil else { assert(false, "Superview cannot be nil when adding contraints"); return nil}
translatesAutoresizingMaskIntoConstraints = false
return NSLayoutConstraint(item: self, attribute: attribute, relatedBy: .equal, toItem: toView, attribute: attribute, multiplier: 1.0, constant: constant ?? 0.0)
}
func constraint(_ attribute: NSLayoutConstraint.Attribute, toView: UIView) -> NSLayoutConstraint? {
guard superview != nil else { assert(false, "Superview cannot be nil when adding contraints"); return nil}
translatesAutoresizingMaskIntoConstraints = false
return NSLayoutConstraint(item: self, attribute: attribute, relatedBy: .equal, toItem: toView, attribute: attribute, multiplier: 1.0, constant: 0.0)
}
func constraint(_ dimension: Dimension, constant: CGFloat) -> NSLayoutConstraint? {
guard superview != nil else { assert(false, "Superview cannot be nil when adding contraints"); return nil }
translatesAutoresizingMaskIntoConstraints = false
return NSLayoutConstraint(item: self,
attribute: dimension.layoutAttribute,
relatedBy: .equal,
toItem: nil,
attribute: .notAnAttribute,
multiplier: 1.0,
constant: constant)
}
func constrainTopCorners(sidePadding: CGFloat, topPadding: CGFloat, topLayoutGuide: UILayoutSupport) {
guard let view = superview else { assert(false, "Superview cannot be nil when adding contraints"); return }
translatesAutoresizingMaskIntoConstraints = false
constrain([
constraint(.leading, toView: view, constant: sidePadding),
NSLayoutConstraint(item: self, attribute: .top, relatedBy: .equal, toItem: topLayoutGuide, attribute: .bottom, multiplier: 1.0, constant: topPadding),
constraint(.trailing, toView: view, constant: -sidePadding)
])
}
func constrainTopCorners(sidePadding: CGFloat, topPadding: CGFloat) {
guard let view = superview else { assert(false, "Superview cannot be nil when adding contraints"); return }
translatesAutoresizingMaskIntoConstraints = false
constrain([
constraint(.leading, toView: view, constant: sidePadding),
constraint(.top, toView: view, constant: topPadding),
constraint(.trailing, toView: view, constant: -sidePadding)
])
}
func constrainTopCorners(height: CGFloat) {
guard let view = superview else { assert(false, "Superview cannot be nil when adding contraints"); return }
translatesAutoresizingMaskIntoConstraints = false
constrain([
constraint(.leading, toView: view),
constraint(.top, toView: view),
constraint(.trailing, toView: view),
constraint(.height, constant: height)
])
}
func constrainBottomCorners(sidePadding: CGFloat, bottomPadding: CGFloat) {
guard let view = superview else { assert(false, "Superview cannot be nil when adding contraints"); return }
translatesAutoresizingMaskIntoConstraints = false
constrain([
constraint(.leading, toView: view, constant: sidePadding),
constraint(.bottom, toView: view, constant: -bottomPadding),
constraint(.trailing, toView: view, constant: -sidePadding)
])
}
func constrainBottomCorners(height: CGFloat) {
guard let view = superview else { assert(false, "Superview cannot be nil when adding contraints"); return }
translatesAutoresizingMaskIntoConstraints = false
constrain([
constraint(.leading, toView: view),
constraint(.bottom, toView: view),
constraint(.trailing, toView: view),
constraint(.height, constant: height)
])
}
func constrainLeadingCorners() {
guard let view = superview else { assert(false, "Superview cannot be nil when adding contraints"); return }
translatesAutoresizingMaskIntoConstraints = false
constrain([
constraint(.top, toView: view),
constraint(.leading, toView: view),
constraint(.bottom, toView: view)
])
}
func constrainTrailingCorners() {
guard let view = superview else { assert(false, "Superview cannot be nil when adding contraints"); return }
translatesAutoresizingMaskIntoConstraints = false
constrain([
constraint(.top, toView: view),
constraint(.trailing, toView: view),
constraint(.bottom, toView: view)
])
}
func constrainToCenter() {
guard let view = superview else { assert(false, "Superview cannot be nil when adding contraints"); return }
translatesAutoresizingMaskIntoConstraints = false
constrain([
constraint(.centerX, toView: view),
constraint(.centerY, toView: view)
])
}
func pin(toSize: CGSize) {
guard superview != nil else { assert(false, "Superview cannot be nil when adding contraints"); return }
translatesAutoresizingMaskIntoConstraints = false
constrain([
widthAnchor.constraint(equalToConstant: toSize.width).priority(.required - 1),
heightAnchor.constraint(equalToConstant: toSize.height).priority(.required - 1)
])
}
func pin(top: CGFloat?,left: CGFloat?,bottom: CGFloat?, right: CGFloat?) {
guard let view = superview else { assert(false, "Superview cannot be nil when adding contraints"); return }
translatesAutoresizingMaskIntoConstraints = false
var constraints = [NSLayoutConstraint]()
if let topConstant = top {
constraints.append(topAnchor.constraint(equalTo: view.topAnchor, constant: topConstant))
}
if let leftConstant = left {
constraints.append(leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: leftConstant))
}
if let bottomConstant = bottom {
constraints.append(view.bottomAnchor.constraint(equalTo: bottomAnchor, constant: bottomConstant))
}
if let rightConstant = right {
constraints.append(view.trailingAnchor.constraint(equalTo: trailingAnchor, constant: rightConstant))
}
constrain(constraints)
}
func pinTopLeft(padding: CGFloat) {
guard let view = superview else { assert(false, "Superview cannot be nil when adding contraints"); return }
translatesAutoresizingMaskIntoConstraints = false
constrain([
leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: padding),
topAnchor.constraint(equalTo: view.topAnchor, constant: padding)])
}
func pinTopLeft(top: CGFloat, left: CGFloat) {
guard let view = superview else { assert(false, "Superview cannot be nil when adding contraints"); return }
translatesAutoresizingMaskIntoConstraints = false
constrain([
leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: left),
topAnchor.constraint(equalTo: view.topAnchor, constant: top)])
}
func pinTopRight(padding: CGFloat) {
guard let view = superview else { assert(false, "Superview cannot be nil when adding contraints"); return }
translatesAutoresizingMaskIntoConstraints = false
constrain([
view.trailingAnchor.constraint(equalTo: trailingAnchor, constant: padding),
topAnchor.constraint(equalTo: view.topAnchor, constant: padding)])
}
func pinTopRight(top: CGFloat, right: CGFloat) {
guard let view = superview else { assert(false, "Superview cannot be nil when adding contraints"); return }
translatesAutoresizingMaskIntoConstraints = false
constrain([
view.trailingAnchor.constraint(equalTo: trailingAnchor, constant: right),
topAnchor.constraint(equalTo: view.topAnchor, constant: top)])
}
func pinTopLeft(toView: UIView, topPadding: CGFloat) {
guard superview != nil else { assert(false, "Superview cannot be nil when adding contraints"); return }
translatesAutoresizingMaskIntoConstraints = false
constrain([
leadingAnchor.constraint(equalTo: toView.leadingAnchor),
topAnchor.constraint(equalTo: toView.bottomAnchor, constant: topPadding)])
}
/// Cross-fades between two views by animating their alpha then setting one or the other hidden.
/// - parameters:
/// - lhs: left view
/// - rhs: right view
/// - toRight: fade to the right view if true, fade to the left view if false
/// - duration: animation duration
///
static func crossfade(_ lhs: UIView, _ rhs: UIView, toRight: Bool, duration: TimeInterval) {
lhs.alpha = toRight ? 1.0 : 0.0
rhs.alpha = toRight ? 0.0 : 1.0
lhs.isHidden = false
rhs.isHidden = false
UIView.animate(withDuration: duration, animations: {
lhs.alpha = toRight ? 0.0 : 1.0
rhs.alpha = toRight ? 1.0 : 0.0
}, completion: { _ in
lhs.isHidden = toRight
rhs.isHidden = !toRight
})
}
}

View File

@ -48,8 +48,9 @@ extension NotificationViewController {
view.backgroundColor = Asset.Colors.Background.systemBackground.color view.backgroundColor = Asset.Colors.Background.systemBackground.color
navigationItem.titleView = segmentControl navigationItem.titleView = segmentControl
segmentControl.addTarget(self, action: #selector(NotificationViewController.segmentedControlValueChanged(_:)), for: .valueChanged) segmentControl.addTarget(self, action: #selector(NotificationViewController.segmentedControlValueChanged(_:)), for: .valueChanged)
tableView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(tableView) view.addSubview(tableView)
tableView.constrain([ NSLayoutConstraint.activate([
tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),

View File

@ -104,43 +104,60 @@ extension SearchRecommendAccountsCollectionViewCell {
layer.cornerCurve = .continuous layer.cornerCurve = .continuous
clipsToBounds = false clipsToBounds = false
applyShadow(color: Asset.Colors.Shadow.searchCard.color, alpha: 0.1, x: 0, y: 3, blur: 12, spread: 0) applyShadow(color: Asset.Colors.Shadow.searchCard.color, alpha: 0.1, x: 0, y: 3, blur: 12, spread: 0)
headerImageView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(headerImageView) contentView.addSubview(headerImageView)
headerImageView.pin(top: 16, left: 0, bottom: 0, right: 0) NSLayoutConstraint.activate([
headerImageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 16),
headerImageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
headerImageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
headerImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
])
let containerStackView = UIStackView()
containerStackView.axis = .vertical
containerStackView.distribution = .fill
containerStackView.alignment = .center
containerStackView.spacing = 6
containerStackView.layoutMargins = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)
containerStackView.isLayoutMarginsRelativeArrangement = true
containerStackView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(containerStackView)
NSLayoutConstraint.activate([
containerStackView.topAnchor.constraint(equalTo: contentView.topAnchor),
containerStackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
containerStackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
])
avatarImageView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(avatarImageView) contentView.addSubview(avatarImageView)
avatarImageView.pin(toSize: CGSize(width: 88, height: 88)) NSLayoutConstraint.activate([
avatarImageView.constrain([ avatarImageView.widthAnchor.constraint(equalToConstant: 88),
avatarImageView.constraint(.top, toView: contentView), avatarImageView.heightAnchor.constraint(equalToConstant: 88)
avatarImageView.constraint(.centerX, toView: contentView)
]) ])
containerStackView.addArrangedSubview(avatarImageView)
containerStackView.setCustomSpacing(20, after: avatarImageView)
displayNameLabel.translatesAutoresizingMaskIntoConstraints = false
containerStackView.addArrangedSubview(displayNameLabel)
containerStackView.setCustomSpacing(0, after: displayNameLabel)
contentView.addSubview(displayNameLabel) acctLabel.translatesAutoresizingMaskIntoConstraints = false
displayNameLabel.constrain([ containerStackView.addArrangedSubview(acctLabel)
displayNameLabel.constraint(.top, toView: contentView, constant: 108), containerStackView.setCustomSpacing(7, after: acctLabel)
displayNameLabel.constraint(.leading, toView: contentView),
displayNameLabel.constraint(.trailing, toView: contentView),
displayNameLabel.constraint(.centerX, toView: contentView)
])
contentView.addSubview(acctLabel) followButton.translatesAutoresizingMaskIntoConstraints = false
acctLabel.constrain([ containerStackView.addArrangedSubview(followButton)
acctLabel.constraint(.top, toView: contentView, constant: 132), NSLayoutConstraint.activate([
acctLabel.constraint(.leading, toView: contentView), followButton.widthAnchor.constraint(equalToConstant: 76),
acctLabel.constraint(.trailing, toView: contentView), followButton.heightAnchor.constraint(equalToConstant: 24)
acctLabel.constraint(.centerX, toView: contentView)
])
contentView.addSubview(followButton)
followButton.pin(toSize: CGSize(width: 76, height: 24))
followButton.constrain([
followButton.constraint(.top, toView: contentView, constant: 159),
followButton.constraint(.centerX, toView: contentView)
]) ])
containerStackView.addArrangedSubview(followButton)
} }
func config(with mastodonUser: MastodonUser) { func config(with mastodonUser: MastodonUser) {
displayNameLabel.text = mastodonUser.displayName.isEmpty ? mastodonUser.username : mastodonUser.displayName displayNameLabel.text = mastodonUser.displayName.isEmpty ? mastodonUser.username : mastodonUser.displayName
acctLabel.text = mastodonUser.acct acctLabel.text = "@" + mastodonUser.acct
avatarImageView.af.setImage( avatarImageView.af.setImage(
withURL: URL(string: mastodonUser.avatar)!, withURL: URL(string: mastodonUser.avatar)!,
placeholderImage: UIImage.placeholder(color: .systemFill), placeholderImage: UIImage.placeholder(color: .systemFill),
@ -153,7 +170,13 @@ extension SearchRecommendAccountsCollectionViewCell {
) { [weak self] _ in ) { [weak self] _ in
guard let self = self else { return } guard let self = self else { return }
self.headerImageView.addSubview(self.visualEffectView) self.headerImageView.addSubview(self.visualEffectView)
self.visualEffectView.pin(top: 0, left: 0, bottom: 0, right: 0) self.visualEffectView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
self.visualEffectView.topAnchor.constraint(equalTo: self.headerImageView.topAnchor),
self.visualEffectView.leadingAnchor.constraint(equalTo: self.headerImageView.leadingAnchor),
self.visualEffectView.trailingAnchor.constraint(equalTo: self.headerImageView.trailingAnchor),
self.visualEffectView.bottomAnchor.constraint(equalTo: self.headerImageView.bottomAnchor)
])
} }
delegate?.configFollowButton(with: mastodonUser, followButton: followButton) delegate?.configFollowButton(with: mastodonUser, followButton: followButton)
followButton.publisher(for: .touchUpInside) followButton.publisher(for: .touchUpInside)

View File

@ -12,7 +12,6 @@ import UIKit
class SearchRecommendTagsCollectionViewCell: UICollectionViewCell { class SearchRecommendTagsCollectionViewCell: UICollectionViewCell {
let backgroundImageView: UIImageView = { let backgroundImageView: UIImageView = {
let imageView = UIImageView() let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView return imageView
}() }()
@ -20,7 +19,6 @@ class SearchRecommendTagsCollectionViewCell: UICollectionViewCell {
let label = UILabel() let label = UILabel()
label.textColor = .white label.textColor = .white
label.font = .systemFont(ofSize: 20, weight: .semibold) label.font = .systemFont(ofSize: 20, weight: .semibold)
label.translatesAutoresizingMaskIntoConstraints = false
label.lineBreakMode = .byTruncatingTail label.lineBreakMode = .byTruncatingTail
return label return label
}() }()
@ -29,7 +27,6 @@ class SearchRecommendTagsCollectionViewCell: UICollectionViewCell {
let label = UILabel() let label = UILabel()
label.textColor = .white label.textColor = .white
label.font = .preferredFont(forTextStyle: .body) label.font = .preferredFont(forTextStyle: .body)
label.translatesAutoresizingMaskIntoConstraints = false
return label return label
}() }()
@ -38,7 +35,6 @@ class SearchRecommendTagsCollectionViewCell: UICollectionViewCell {
let image = UIImage(systemName: "flame.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: 20, weight: .semibold))!.withRenderingMode(.alwaysTemplate) let image = UIImage(systemName: "flame.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: 20, weight: .semibold))!.withRenderingMode(.alwaysTemplate)
imageView.image = image imageView.image = image
imageView.tintColor = .white imageView.tintColor = .white
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView return imageView
}() }()
@ -74,17 +70,58 @@ extension SearchRecommendTagsCollectionViewCell {
layer.borderColor = Asset.Colors.Border.searchCard.color.cgColor layer.borderColor = Asset.Colors.Border.searchCard.color.cgColor
applyShadow(color: Asset.Colors.Shadow.searchCard.color, alpha: 0.1, x: 0, y: 3, blur: 12, spread: 0) applyShadow(color: Asset.Colors.Shadow.searchCard.color, alpha: 0.1, x: 0, y: 3, blur: 12, spread: 0)
backgroundImageView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(backgroundImageView) contentView.addSubview(backgroundImageView)
backgroundImageView.constrain(toSuperviewEdges: nil) NSLayoutConstraint.activate([
backgroundImageView.topAnchor.constraint(equalTo: contentView.topAnchor),
backgroundImageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
backgroundImageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
backgroundImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
])
contentView.addSubview(hashtagTitleLabel)
hashtagTitleLabel.pin(top: 16, left: 16, bottom: nil, right: 42)
contentView.addSubview(peopleLabel) let containerStackView = UIStackView()
peopleLabel.pinTopLeft(top: 46, left: 16) containerStackView.axis = .vertical
containerStackView.distribution = .fill
containerStackView.spacing = 6
containerStackView.layoutMargins = UIEdgeInsets(top: 16, left: 16, bottom: 0, right: 16)
containerStackView.isLayoutMarginsRelativeArrangement = true
containerStackView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(containerStackView)
NSLayoutConstraint.activate([
containerStackView.topAnchor.constraint(equalTo: contentView.topAnchor),
containerStackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
containerStackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
containerStackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
])
contentView.addSubview(flameIconView)
flameIconView.pinTopRight(padding: 16) let horizontalStackView = UIStackView()
horizontalStackView.axis = .horizontal
horizontalStackView.translatesAutoresizingMaskIntoConstraints = false
horizontalStackView.distribution = .fill
hashtagTitleLabel.translatesAutoresizingMaskIntoConstraints = false
hashtagTitleLabel.setContentHuggingPriority(.defaultLow - 1, for: .horizontal)
horizontalStackView.addArrangedSubview(hashtagTitleLabel)
horizontalStackView.setContentHuggingPriority(.required - 1, for: .vertical)
flameIconView.translatesAutoresizingMaskIntoConstraints = false
horizontalStackView.addArrangedSubview(flameIconView)
containerStackView.addArrangedSubview(horizontalStackView)
let peopleHorizontalStackView = UIStackView()
peopleHorizontalStackView.axis = .horizontal
peopleHorizontalStackView.translatesAutoresizingMaskIntoConstraints = false
peopleHorizontalStackView.distribution = .fill
peopleHorizontalStackView.alignment = .top
peopleLabel.translatesAutoresizingMaskIntoConstraints = false
peopleLabel.setContentHuggingPriority(.defaultLow - 1, for: .vertical)
peopleHorizontalStackView.addArrangedSubview(peopleLabel)
containerStackView.addArrangedSubview(peopleHorizontalStackView)
} }
func config(with tag: Mastodon.Entity.Tag) { func config(with tag: Mastodon.Entity.Tag) {

View File

@ -23,8 +23,9 @@ extension SearchViewController {
hashtagCollectionView.register(SearchRecommendTagsCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: SearchRecommendTagsCollectionViewCell.self)) hashtagCollectionView.register(SearchRecommendTagsCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: SearchRecommendTagsCollectionViewCell.self))
hashtagCollectionView.delegate = self hashtagCollectionView.delegate = self
hashtagCollectionView.translatesAutoresizingMaskIntoConstraints = false
stackView.addArrangedSubview(hashtagCollectionView) stackView.addArrangedSubview(hashtagCollectionView)
hashtagCollectionView.constrain([ NSLayoutConstraint.activate([
hashtagCollectionView.frameLayoutGuide.heightAnchor.constraint(equalToConstant: 130) hashtagCollectionView.frameLayoutGuide.heightAnchor.constraint(equalToConstant: 130)
]) ])
} }
@ -39,8 +40,9 @@ extension SearchViewController {
accountsCollectionView.register(SearchRecommendAccountsCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: SearchRecommendAccountsCollectionViewCell.self)) accountsCollectionView.register(SearchRecommendAccountsCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: SearchRecommendAccountsCollectionViewCell.self))
accountsCollectionView.delegate = self accountsCollectionView.delegate = self
accountsCollectionView.translatesAutoresizingMaskIntoConstraints = false
stackView.addArrangedSubview(accountsCollectionView) stackView.addArrangedSubview(accountsCollectionView)
accountsCollectionView.constrain([ NSLayoutConstraint.activate([
accountsCollectionView.frameLayoutGuide.heightAnchor.constraint(equalToConstant: 202) accountsCollectionView.frameLayoutGuide.heightAnchor.constraint(equalToConstant: 202)
]) ])
} }

View File

@ -19,7 +19,8 @@ extension SearchViewController {
searchingTableView.register(SearchingTableViewCell.self, forCellReuseIdentifier: String(describing: SearchingTableViewCell.self)) searchingTableView.register(SearchingTableViewCell.self, forCellReuseIdentifier: String(describing: SearchingTableViewCell.self))
searchingTableView.register(TimelineBottomLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self)) searchingTableView.register(TimelineBottomLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self))
view.addSubview(searchingTableView) view.addSubview(searchingTableView)
searchingTableView.constrain([ searchingTableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
searchingTableView.frameLayoutGuide.topAnchor.constraint(equalTo: searchBar.bottomAnchor), searchingTableView.frameLayoutGuide.topAnchor.constraint(equalTo: searchBar.bottomAnchor),
searchingTableView.frameLayoutGuide.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), searchingTableView.frameLayoutGuide.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
searchingTableView.frameLayoutGuide.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), searchingTableView.frameLayoutGuide.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
@ -50,18 +51,23 @@ extension SearchViewController {
} }
func setupSearchHeader() { func setupSearchHeader() {
searchHeader.addSubview(recentSearchesLabel) let containerStackView = UIStackView()
recentSearchesLabel.constrain([ containerStackView.axis = .horizontal
recentSearchesLabel.constraint(.leading, toView: searchHeader, constant: 16), containerStackView.distribution = .fill
recentSearchesLabel.constraint(.centerY, toView: searchHeader) containerStackView.translatesAutoresizingMaskIntoConstraints = false
containerStackView.layoutMargins = UIEdgeInsets(top: 0, left: 12, bottom: 0, right: 12)
containerStackView.isLayoutMarginsRelativeArrangement = true
searchHeader.addSubview(containerStackView)
NSLayoutConstraint.activate([
containerStackView.topAnchor.constraint(equalTo: searchHeader.topAnchor),
containerStackView.leadingAnchor.constraint(equalTo: searchHeader.leadingAnchor),
containerStackView.trailingAnchor.constraint(equalTo: searchHeader.trailingAnchor),
containerStackView.bottomAnchor.constraint(equalTo: searchHeader.bottomAnchor)
]) ])
recentSearchesLabel.translatesAutoresizingMaskIntoConstraints = false
searchHeader.addSubview(clearSearchHistoryButton) containerStackView.addArrangedSubview(recentSearchesLabel)
recentSearchesLabel.constrain([ clearSearchHistoryButton.translatesAutoresizingMaskIntoConstraints = false
searchHeader.trailingAnchor.constraint(equalTo: clearSearchHistoryButton.trailingAnchor, constant: 16), containerStackView.addArrangedSubview(clearSearchHistoryButton)
clearSearchHistoryButton.constraint(.centerY, toView: searchHeader)
])
clearSearchHistoryButton.addTarget(self, action: #selector(SearchViewController.clearAction(_:)), for: .touchUpInside) clearSearchHistoryButton.addTarget(self, action: #selector(SearchViewController.clearAction(_:)), for: .touchUpInside)
} }
} }
@ -84,6 +90,7 @@ extension SearchViewController: UITableViewDelegate {
} }
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
guard let diffableDataSource = viewModel.searchResultDiffableDataSource else { return } guard let diffableDataSource = viewModel.searchResultDiffableDataSource else { return }
guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return } guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return }
viewModel.searchResultItemDidSelected(item: item, from: self) viewModel.searchResultItemDidSelected(item: item, from: self)

View File

@ -135,14 +135,16 @@ extension SearchViewController {
func setupSearchBar() { func setupSearchBar() {
searchBar.delegate = self searchBar.delegate = self
view.addSubview(searchBar) view.addSubview(searchBar)
searchBar.constrain([ searchBar.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
searchBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), searchBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
searchBar.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), searchBar.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
searchBar.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), searchBar.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
]) ])
view.addSubview(statusBar)
statusBar.constrain([ statusBar.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(statusBar)
NSLayoutConstraint.activate([
statusBar.topAnchor.constraint(equalTo: view.topAnchor), statusBar.topAnchor.constraint(equalTo: view.topAnchor),
statusBar.leadingAnchor.constraint(equalTo: view.leadingAnchor), statusBar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
statusBar.trailingAnchor.constraint(equalTo: view.trailingAnchor), statusBar.trailingAnchor.constraint(equalTo: view.trailingAnchor),
@ -151,8 +153,9 @@ extension SearchViewController {
} }
func setupScrollView() { func setupScrollView() {
scrollView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView) view.addSubview(scrollView)
scrollView.constrain([ NSLayoutConstraint.activate([
scrollView.frameLayoutGuide.topAnchor.constraint(equalTo: searchBar.bottomAnchor), scrollView.frameLayoutGuide.topAnchor.constraint(equalTo: searchBar.bottomAnchor),
scrollView.frameLayoutGuide.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), scrollView.frameLayoutGuide.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
scrollView.frameLayoutGuide.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), scrollView.frameLayoutGuide.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
@ -160,8 +163,9 @@ extension SearchViewController {
scrollView.contentLayoutGuide.widthAnchor.constraint(equalTo: view.widthAnchor), scrollView.contentLayoutGuide.widthAnchor.constraint(equalTo: view.widthAnchor),
]) ])
stackView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(stackView) scrollView.addSubview(stackView)
stackView.constrain([ NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor), stackView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
stackView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor), stackView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor), stackView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor),

View File

@ -237,10 +237,10 @@ final class SearchViewModel: NSObject {
.sink { completion in .sink { completion in
switch completion { switch completion {
case .failure(let error): case .failure(let error):
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: recommendHashTags request fail: %s", (#file as NSString).lastPathComponent, #line, #function, error.localizedDescription) os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: recommendAccount request fail: %s", (#file as NSString).lastPathComponent, #line, #function, error.localizedDescription)
promise(.failure(error)) promise(.failure(error))
case .finished: case .finished:
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: recommendHashTags request success", (#file as NSString).lastPathComponent, #line, #function) os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: recommendAccount request success", (#file as NSString).lastPathComponent, #line, #function)
promise(.success(())) promise(.success(()))
} }
} receiveValue: { [weak self] accounts in } receiveValue: { [weak self] accounts in

View File

@ -55,19 +55,39 @@ final class SearchingTableViewCell: UITableViewCell {
extension SearchingTableViewCell { extension SearchingTableViewCell {
private func configure() { private func configure() {
backgroundColor = .clear backgroundColor = .clear
selectionStyle = .none
contentView.addSubview(_imageView) let containerStackView = UIStackView()
_imageView.pin(toSize: CGSize(width: 42, height: 42)) containerStackView.axis = .horizontal
_imageView.constrain([ containerStackView.distribution = .fill
_imageView.constraint(.leading, toView: contentView, constant: 21), containerStackView.spacing = 12
_imageView.constraint(.centerY, toView: contentView) containerStackView.layoutMargins = UIEdgeInsets(top: 12, left: 21, bottom: 12, right: 12)
containerStackView.isLayoutMarginsRelativeArrangement = true
containerStackView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(containerStackView)
NSLayoutConstraint.activate([
containerStackView.topAnchor.constraint(equalTo: contentView.topAnchor),
containerStackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
containerStackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
containerStackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
]) ])
contentView.addSubview(_titleLabel) _imageView.translatesAutoresizingMaskIntoConstraints = false
_titleLabel.pin(top: 12, left: 75, bottom: nil, right: 0) containerStackView.addArrangedSubview(_imageView)
NSLayoutConstraint.activate([
_imageView.widthAnchor.constraint(equalToConstant: 42),
_imageView.heightAnchor.constraint(equalToConstant: 42),
])
contentView.addSubview(_subTitleLabel) let textStackView = UIStackView()
_subTitleLabel.pin(top: 34, left: 75, bottom: nil, right: 0) textStackView.axis = .vertical
textStackView.distribution = .fill
textStackView.translatesAutoresizingMaskIntoConstraints = false
_titleLabel.translatesAutoresizingMaskIntoConstraints = false
textStackView.addArrangedSubview(_titleLabel)
_subTitleLabel.translatesAutoresizingMaskIntoConstraints = false
textStackView.addArrangedSubview(_subTitleLabel)
containerStackView.addArrangedSubview(textStackView)
} }
func config(with account: Mastodon.Entity.Account) { func config(with account: Mastodon.Entity.Account) {

View File

@ -47,14 +47,35 @@ extension SearchRecommendCollectionHeader {
private func configure() { private func configure() {
backgroundColor = .clear backgroundColor = .clear
translatesAutoresizingMaskIntoConstraints = false translatesAutoresizingMaskIntoConstraints = false
addSubview(titleLabel)
titleLabel.pinTopLeft(top: 31, left: 16)
addSubview(descriptionLabel) let containerStackView = UIStackView()
descriptionLabel.constrain(toSuperviewEdges: UIEdgeInsets(top: 60, left: 16, bottom: 16, right: 16)) containerStackView.axis = .vertical
containerStackView.layoutMargins = UIEdgeInsets(top: 31, left: 16, bottom: 16, right: 16)
containerStackView.isLayoutMarginsRelativeArrangement = true
containerStackView.translatesAutoresizingMaskIntoConstraints = false
addSubview(containerStackView)
NSLayoutConstraint.activate([
containerStackView.topAnchor.constraint(equalTo: topAnchor),
containerStackView.leadingAnchor.constraint(equalTo: leadingAnchor),
containerStackView.bottomAnchor.constraint(equalTo: bottomAnchor),
containerStackView.trailingAnchor.constraint(equalTo: trailingAnchor)
])
addSubview(seeAllButton) let horizontalStackView = UIStackView()
seeAllButton.pinTopRight(top: 26, right: 16) horizontalStackView.axis = .horizontal
horizontalStackView.alignment = .center
horizontalStackView.translatesAutoresizingMaskIntoConstraints = false
horizontalStackView.distribution = .fill
titleLabel.translatesAutoresizingMaskIntoConstraints = false
titleLabel.setContentHuggingPriority(.defaultLow - 1, for: .horizontal)
horizontalStackView.addArrangedSubview(titleLabel)
seeAllButton.translatesAutoresizingMaskIntoConstraints = false
horizontalStackView.addArrangedSubview(seeAllButton)
containerStackView.addArrangedSubview(horizontalStackView)
descriptionLabel.translatesAutoresizingMaskIntoConstraints = false
containerStackView.addArrangedSubview(descriptionLabel)
} }
} }