From f6be51dd0fff8ba2b09b9f53da37235529e415b3 Mon Sep 17 00:00:00 2001 From: sunxiaojian Date: Mon, 19 Apr 2021 11:41:50 +0800 Subject: [PATCH] chore: remove UIView+Contraint --- Mastodon.xcodeproj/project.pbxproj | 4 - Mastodon/Extension/UIView+Constraint.swift | 262 ------------------ .../NotificationViewController.swift | 3 +- ...hRecommendAccountsCollectionViewCell.swift | 77 +++-- ...earchRecommendTagsCollectionViewCell.swift | 59 +++- .../SearchViewController+Recommend.swift | 6 +- .../SearchViewController+Searching.swift | 31 ++- .../Scene/Search/SearchViewController.swift | 14 +- Mastodon/Scene/Search/SearchViewModel.swift | 4 +- .../SearchingTableViewCell.swift | 40 ++- .../SearchRecommendCollectionHeader.swift | 33 ++- 11 files changed, 191 insertions(+), 342 deletions(-) delete mode 100644 Mastodon/Extension/UIView+Constraint.swift diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 427ffa0db..659d0d734 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -132,7 +132,6 @@ 2DF75BC725D1475D00694EC8 /* ManagedObjectContextObjectsDidChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DF75BC625D1475D00694EC8 /* ManagedObjectContextObjectsDidChange.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 */; }; - 2DFF41892614A4DC00F776A4 /* UIView+Constraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DFF41882614A4DC00F776A4 /* UIView+Constraint.swift */; }; 5D0393902612D259007FE196 /* WebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D03938F2612D259007FE196 /* WebViewController.swift */; }; 5D0393962612D266007FE196 /* WebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D0393952612D266007FE196 /* WebViewModel.swift */; }; 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 = ""; }; 2DFAD5262616F9D300F9EE7C /* SearchViewController+Searching.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SearchViewController+Searching.swift"; sourceTree = ""; }; 2DFAD5362617010500F9EE7C /* SearchingTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchingTableViewCell.swift; sourceTree = ""; }; - 2DFF41882614A4DC00F776A4 /* UIView+Constraint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Constraint.swift"; sourceTree = ""; }; 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 = ""; }; 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; }; @@ -1646,7 +1644,6 @@ DB47229625F9EFAD00DA7F53 /* NSManagedObjectContext.swift */, 2D32EAB925CB9B0500C9ED86 /* UIView.swift */, 5DA732CB2629CEF500A92342 /* UIView+Remove.swift */, - 2DFF41882614A4DC00F776A4 /* UIView+Constraint.swift */, DB8AF55C25C138B7002E6C99 /* UIViewController.swift */, 2D24E1222626ED9D00A59D4F /* UIView+Gesture.swift */, 2D3F9E0325DFA133004262D9 /* UITapGestureRecognizer.swift */, @@ -2476,7 +2473,6 @@ 2D7867192625B77500211898 /* NotificationItem.swift in Sources */, DB45FAB625CA5485005A8AC7 /* UIAlertController.swift in Sources */, DBE0821525CD382600FD6BBD /* MastodonRegisterViewController.swift in Sources */, - 2DFF41892614A4DC00F776A4 /* UIView+Constraint.swift in Sources */, 2D5A3D0325CF8742002347D6 /* ControlContainableScrollViews.swift in Sources */, DB98336B25C9420100AD9700 /* APIService+App.swift in Sources */, DBA0A11325FB3FC10079C110 /* ComposeToolbarView.swift in Sources */, diff --git a/Mastodon/Extension/UIView+Constraint.swift b/Mastodon/Extension/UIView+Constraint.swift deleted file mode 100644 index ded8846d4..000000000 --- a/Mastodon/Extension/UIView+Constraint.swift +++ /dev/null @@ -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 - }) - } -} diff --git a/Mastodon/Scene/Notification/NotificationViewController.swift b/Mastodon/Scene/Notification/NotificationViewController.swift index 68e69b4be..90d72afa5 100644 --- a/Mastodon/Scene/Notification/NotificationViewController.swift +++ b/Mastodon/Scene/Notification/NotificationViewController.swift @@ -48,8 +48,9 @@ extension NotificationViewController { view.backgroundColor = Asset.Colors.Background.systemBackground.color navigationItem.titleView = segmentControl segmentControl.addTarget(self, action: #selector(NotificationViewController.segmentedControlValueChanged(_:)), for: .valueChanged) + tableView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(tableView) - tableView.constrain([ + NSLayoutConstraint.activate([ tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), diff --git a/Mastodon/Scene/Search/CollectionViewCell/SearchRecommendAccountsCollectionViewCell.swift b/Mastodon/Scene/Search/CollectionViewCell/SearchRecommendAccountsCollectionViewCell.swift index f45124671..fdb1af562 100644 --- a/Mastodon/Scene/Search/CollectionViewCell/SearchRecommendAccountsCollectionViewCell.swift +++ b/Mastodon/Scene/Search/CollectionViewCell/SearchRecommendAccountsCollectionViewCell.swift @@ -104,43 +104,60 @@ extension SearchRecommendAccountsCollectionViewCell { layer.cornerCurve = .continuous clipsToBounds = false applyShadow(color: Asset.Colors.Shadow.searchCard.color, alpha: 0.1, x: 0, y: 3, blur: 12, spread: 0) + + headerImageView.translatesAutoresizingMaskIntoConstraints = false 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) - avatarImageView.pin(toSize: CGSize(width: 88, height: 88)) - avatarImageView.constrain([ - avatarImageView.constraint(.top, toView: contentView), - avatarImageView.constraint(.centerX, toView: contentView) + NSLayoutConstraint.activate([ + avatarImageView.widthAnchor.constraint(equalToConstant: 88), + avatarImageView.heightAnchor.constraint(equalToConstant: 88) ]) + containerStackView.addArrangedSubview(avatarImageView) + containerStackView.setCustomSpacing(20, after: avatarImageView) + displayNameLabel.translatesAutoresizingMaskIntoConstraints = false + containerStackView.addArrangedSubview(displayNameLabel) + containerStackView.setCustomSpacing(0, after: displayNameLabel) - contentView.addSubview(displayNameLabel) - displayNameLabel.constrain([ - displayNameLabel.constraint(.top, toView: contentView, constant: 108), - displayNameLabel.constraint(.leading, toView: contentView), - displayNameLabel.constraint(.trailing, toView: contentView), - displayNameLabel.constraint(.centerX, toView: contentView) - ]) + acctLabel.translatesAutoresizingMaskIntoConstraints = false + containerStackView.addArrangedSubview(acctLabel) + containerStackView.setCustomSpacing(7, after: acctLabel) - contentView.addSubview(acctLabel) - acctLabel.constrain([ - acctLabel.constraint(.top, toView: contentView, constant: 132), - acctLabel.constraint(.leading, toView: contentView), - acctLabel.constraint(.trailing, toView: contentView), - 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) + followButton.translatesAutoresizingMaskIntoConstraints = false + containerStackView.addArrangedSubview(followButton) + NSLayoutConstraint.activate([ + followButton.widthAnchor.constraint(equalToConstant: 76), + followButton.heightAnchor.constraint(equalToConstant: 24) ]) + containerStackView.addArrangedSubview(followButton) } func config(with mastodonUser: MastodonUser) { displayNameLabel.text = mastodonUser.displayName.isEmpty ? mastodonUser.username : mastodonUser.displayName - acctLabel.text = mastodonUser.acct + acctLabel.text = "@" + mastodonUser.acct avatarImageView.af.setImage( withURL: URL(string: mastodonUser.avatar)!, placeholderImage: UIImage.placeholder(color: .systemFill), @@ -153,7 +170,13 @@ extension SearchRecommendAccountsCollectionViewCell { ) { [weak self] _ in guard let self = self else { return } 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) followButton.publisher(for: .touchUpInside) diff --git a/Mastodon/Scene/Search/CollectionViewCell/SearchRecommendTagsCollectionViewCell.swift b/Mastodon/Scene/Search/CollectionViewCell/SearchRecommendTagsCollectionViewCell.swift index d00cb0504..81167ee6e 100644 --- a/Mastodon/Scene/Search/CollectionViewCell/SearchRecommendTagsCollectionViewCell.swift +++ b/Mastodon/Scene/Search/CollectionViewCell/SearchRecommendTagsCollectionViewCell.swift @@ -12,7 +12,6 @@ import UIKit class SearchRecommendTagsCollectionViewCell: UICollectionViewCell { let backgroundImageView: UIImageView = { let imageView = UIImageView() - imageView.translatesAutoresizingMaskIntoConstraints = false return imageView }() @@ -20,7 +19,6 @@ class SearchRecommendTagsCollectionViewCell: UICollectionViewCell { let label = UILabel() label.textColor = .white label.font = .systemFont(ofSize: 20, weight: .semibold) - label.translatesAutoresizingMaskIntoConstraints = false label.lineBreakMode = .byTruncatingTail return label }() @@ -29,7 +27,6 @@ class SearchRecommendTagsCollectionViewCell: UICollectionViewCell { let label = UILabel() label.textColor = .white label.font = .preferredFont(forTextStyle: .body) - label.translatesAutoresizingMaskIntoConstraints = false return label }() @@ -38,7 +35,6 @@ class SearchRecommendTagsCollectionViewCell: UICollectionViewCell { let image = UIImage(systemName: "flame.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: 20, weight: .semibold))!.withRenderingMode(.alwaysTemplate) imageView.image = image imageView.tintColor = .white - imageView.translatesAutoresizingMaskIntoConstraints = false return imageView }() @@ -74,17 +70,58 @@ extension SearchRecommendTagsCollectionViewCell { 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) + backgroundImageView.translatesAutoresizingMaskIntoConstraints = false 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) - peopleLabel.pinTopLeft(top: 46, left: 16) + let containerStackView = UIStackView() + 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) { diff --git a/Mastodon/Scene/Search/SearchViewController+Recommend.swift b/Mastodon/Scene/Search/SearchViewController+Recommend.swift index e941fa841..f394f09f1 100644 --- a/Mastodon/Scene/Search/SearchViewController+Recommend.swift +++ b/Mastodon/Scene/Search/SearchViewController+Recommend.swift @@ -23,8 +23,9 @@ extension SearchViewController { hashtagCollectionView.register(SearchRecommendTagsCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: SearchRecommendTagsCollectionViewCell.self)) hashtagCollectionView.delegate = self + hashtagCollectionView.translatesAutoresizingMaskIntoConstraints = false stackView.addArrangedSubview(hashtagCollectionView) - hashtagCollectionView.constrain([ + NSLayoutConstraint.activate([ hashtagCollectionView.frameLayoutGuide.heightAnchor.constraint(equalToConstant: 130) ]) } @@ -39,8 +40,9 @@ extension SearchViewController { accountsCollectionView.register(SearchRecommendAccountsCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: SearchRecommendAccountsCollectionViewCell.self)) accountsCollectionView.delegate = self + accountsCollectionView.translatesAutoresizingMaskIntoConstraints = false stackView.addArrangedSubview(accountsCollectionView) - accountsCollectionView.constrain([ + NSLayoutConstraint.activate([ accountsCollectionView.frameLayoutGuide.heightAnchor.constraint(equalToConstant: 202) ]) } diff --git a/Mastodon/Scene/Search/SearchViewController+Searching.swift b/Mastodon/Scene/Search/SearchViewController+Searching.swift index 86a27e03d..8eaf36326 100644 --- a/Mastodon/Scene/Search/SearchViewController+Searching.swift +++ b/Mastodon/Scene/Search/SearchViewController+Searching.swift @@ -19,7 +19,8 @@ extension SearchViewController { searchingTableView.register(SearchingTableViewCell.self, forCellReuseIdentifier: String(describing: SearchingTableViewCell.self)) searchingTableView.register(TimelineBottomLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self)) view.addSubview(searchingTableView) - searchingTableView.constrain([ + searchingTableView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ searchingTableView.frameLayoutGuide.topAnchor.constraint(equalTo: searchBar.bottomAnchor), searchingTableView.frameLayoutGuide.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), searchingTableView.frameLayoutGuide.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), @@ -50,18 +51,23 @@ extension SearchViewController { } func setupSearchHeader() { - searchHeader.addSubview(recentSearchesLabel) - recentSearchesLabel.constrain([ - recentSearchesLabel.constraint(.leading, toView: searchHeader, constant: 16), - recentSearchesLabel.constraint(.centerY, toView: searchHeader) + let containerStackView = UIStackView() + containerStackView.axis = .horizontal + containerStackView.distribution = .fill + 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) ]) - - searchHeader.addSubview(clearSearchHistoryButton) - recentSearchesLabel.constrain([ - searchHeader.trailingAnchor.constraint(equalTo: clearSearchHistoryButton.trailingAnchor, constant: 16), - clearSearchHistoryButton.constraint(.centerY, toView: searchHeader) - ]) - + recentSearchesLabel.translatesAutoresizingMaskIntoConstraints = false + containerStackView.addArrangedSubview(recentSearchesLabel) + clearSearchHistoryButton.translatesAutoresizingMaskIntoConstraints = false + containerStackView.addArrangedSubview(clearSearchHistoryButton) clearSearchHistoryButton.addTarget(self, action: #selector(SearchViewController.clearAction(_:)), for: .touchUpInside) } } @@ -84,6 +90,7 @@ extension SearchViewController: UITableViewDelegate { } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) guard let diffableDataSource = viewModel.searchResultDiffableDataSource else { return } guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return } viewModel.searchResultItemDidSelected(item: item, from: self) diff --git a/Mastodon/Scene/Search/SearchViewController.swift b/Mastodon/Scene/Search/SearchViewController.swift index 710808b52..770fb1da7 100644 --- a/Mastodon/Scene/Search/SearchViewController.swift +++ b/Mastodon/Scene/Search/SearchViewController.swift @@ -135,14 +135,16 @@ extension SearchViewController { func setupSearchBar() { searchBar.delegate = self view.addSubview(searchBar) - searchBar.constrain([ + searchBar.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ searchBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), searchBar.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), 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.leadingAnchor.constraint(equalTo: view.leadingAnchor), statusBar.trailingAnchor.constraint(equalTo: view.trailingAnchor), @@ -151,8 +153,9 @@ extension SearchViewController { } func setupScrollView() { + scrollView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(scrollView) - scrollView.constrain([ + NSLayoutConstraint.activate([ scrollView.frameLayoutGuide.topAnchor.constraint(equalTo: searchBar.bottomAnchor), scrollView.frameLayoutGuide.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), scrollView.frameLayoutGuide.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), @@ -160,8 +163,9 @@ extension SearchViewController { scrollView.contentLayoutGuide.widthAnchor.constraint(equalTo: view.widthAnchor), ]) + stackView.translatesAutoresizingMaskIntoConstraints = false scrollView.addSubview(stackView) - stackView.constrain([ + NSLayoutConstraint.activate([ stackView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor), stackView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor), stackView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor), diff --git a/Mastodon/Scene/Search/SearchViewModel.swift b/Mastodon/Scene/Search/SearchViewModel.swift index 1d87629ba..27c322c88 100644 --- a/Mastodon/Scene/Search/SearchViewModel.swift +++ b/Mastodon/Scene/Search/SearchViewModel.swift @@ -237,10 +237,10 @@ final class SearchViewModel: NSObject { .sink { completion in switch completion { 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)) 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(())) } } receiveValue: { [weak self] accounts in diff --git a/Mastodon/Scene/Search/TableViewCell/SearchingTableViewCell.swift b/Mastodon/Scene/Search/TableViewCell/SearchingTableViewCell.swift index 5a258d8a5..9339e6f2e 100644 --- a/Mastodon/Scene/Search/TableViewCell/SearchingTableViewCell.swift +++ b/Mastodon/Scene/Search/TableViewCell/SearchingTableViewCell.swift @@ -55,19 +55,39 @@ final class SearchingTableViewCell: UITableViewCell { extension SearchingTableViewCell { private func configure() { backgroundColor = .clear - selectionStyle = .none - contentView.addSubview(_imageView) - _imageView.pin(toSize: CGSize(width: 42, height: 42)) - _imageView.constrain([ - _imageView.constraint(.leading, toView: contentView, constant: 21), - _imageView.constraint(.centerY, toView: contentView) + + let containerStackView = UIStackView() + containerStackView.axis = .horizontal + containerStackView.distribution = .fill + containerStackView.spacing = 12 + 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) - _titleLabel.pin(top: 12, left: 75, bottom: nil, right: 0) + _imageView.translatesAutoresizingMaskIntoConstraints = false + containerStackView.addArrangedSubview(_imageView) + NSLayoutConstraint.activate([ + _imageView.widthAnchor.constraint(equalToConstant: 42), + _imageView.heightAnchor.constraint(equalToConstant: 42), + ]) - contentView.addSubview(_subTitleLabel) - _subTitleLabel.pin(top: 34, left: 75, bottom: nil, right: 0) + let textStackView = UIStackView() + 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) { diff --git a/Mastodon/Scene/Search/View/SearchRecommendCollectionHeader.swift b/Mastodon/Scene/Search/View/SearchRecommendCollectionHeader.swift index bc5bd7663..3db8c2800 100644 --- a/Mastodon/Scene/Search/View/SearchRecommendCollectionHeader.swift +++ b/Mastodon/Scene/Search/View/SearchRecommendCollectionHeader.swift @@ -47,14 +47,35 @@ extension SearchRecommendCollectionHeader { private func configure() { backgroundColor = .clear translatesAutoresizingMaskIntoConstraints = false - addSubview(titleLabel) - titleLabel.pinTopLeft(top: 31, left: 16) - addSubview(descriptionLabel) - descriptionLabel.constrain(toSuperviewEdges: UIEdgeInsets(top: 60, left: 16, bottom: 16, right: 16)) + let containerStackView = UIStackView() + 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) - seeAllButton.pinTopRight(top: 26, right: 16) + let horizontalStackView = UIStackView() + 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) + } }