From 66ce4802ef359abc6fb5047b238d7e3718c22a3b Mon Sep 17 00:00:00 2001 From: Nathan Mattes Date: Fri, 12 May 2023 22:06:44 +0200 Subject: [PATCH] Cleanup/Style TableView (IOS-157) --- Mastodon.xcodeproj/project.pbxproj | 12 -- .../RecommendAccountSection.swift | 111 ---------------- .../SuggestionAccountCollectionViewCell.swift | 58 --------- .../SuggestionAccountViewController.swift | 53 ++------ .../SuggestionAccountViewModel+Diffable.swift | 2 +- ...estionAccountTableViewCell+ViewModel.swift | 122 +++++++++--------- .../SuggestionAccountTableViewCell.swift | 12 +- 7 files changed, 73 insertions(+), 297 deletions(-) delete mode 100644 Mastodon/Scene/SuggestionAccount/CollectionViewCell/SuggestionAccountCollectionViewCell.swift diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index eaa6de62f..15b8ff836 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -75,7 +75,6 @@ 2D38F1F725CD47AC00561493 /* HomeTimelineViewModel+LoadOldestState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D38F1F625CD47AC00561493 /* HomeTimelineViewModel+LoadOldestState.swift */; }; 2D38F20825CD491300561493 /* DisposeBagCollectable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D38F20725CD491300561493 /* DisposeBagCollectable.swift */; }; 2D3F9E0425DFA133004262D9 /* UITapGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D3F9E0325DFA133004262D9 /* UITapGestureRecognizer.swift */; }; - 2D4AD89C263165B500613EFC /* SuggestionAccountCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D4AD89B263165B500613EFC /* SuggestionAccountCollectionViewCell.swift */; }; 2D571B2F26004EC000540450 /* NavigationBarProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D571B2E26004EC000540450 /* NavigationBarProgressView.swift */; }; 2D59819B25E4A581000FB903 /* MastodonConfirmEmailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D59819A25E4A581000FB903 /* MastodonConfirmEmailViewController.swift */; }; 2D5981A125E4A593000FB903 /* MastodonConfirmEmailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D5981A025E4A593000FB903 /* MastodonConfirmEmailViewModel.swift */; }; @@ -692,7 +691,6 @@ 2D38F1F625CD47AC00561493 /* HomeTimelineViewModel+LoadOldestState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomeTimelineViewModel+LoadOldestState.swift"; sourceTree = ""; }; 2D38F20725CD491300561493 /* DisposeBagCollectable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisposeBagCollectable.swift; sourceTree = ""; }; 2D3F9E0325DFA133004262D9 /* UITapGestureRecognizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITapGestureRecognizer.swift; sourceTree = ""; }; - 2D4AD89B263165B500613EFC /* SuggestionAccountCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuggestionAccountCollectionViewCell.swift; sourceTree = ""; }; 2D571B2E26004EC000540450 /* NavigationBarProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBarProgressView.swift; sourceTree = ""; }; 2D59819A25E4A581000FB903 /* MastodonConfirmEmailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonConfirmEmailViewController.swift; sourceTree = ""; }; 2D5981A025E4A593000FB903 /* MastodonConfirmEmailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonConfirmEmailViewModel.swift; sourceTree = ""; }; @@ -1572,14 +1570,6 @@ path = Button; sourceTree = ""; }; - 2D4AD89A2631659400613EFC /* CollectionViewCell */ = { - isa = PBXGroup; - children = ( - 2D4AD89B263165B500613EFC /* SuggestionAccountCollectionViewCell.swift */, - ); - path = CollectionViewCell; - sourceTree = ""; - }; 2D59819925E4A55C000FB903 /* ConfirmEmail */ = { isa = PBXGroup; children = ( @@ -1681,7 +1671,6 @@ 2DAC9E37262FC2320062E1A6 /* SuggestionAccountViewController.swift */, 2DAC9E3D262FC2400062E1A6 /* SuggestionAccountViewModel.swift */, DBB45B6127B51112002DC5A7 /* SuggestionAccountViewModel+Diffable.swift */, - 2D4AD89A2631659400613EFC /* CollectionViewCell */, 2DAC9E43262FC9DE0062E1A6 /* TableViewCell */, ); path = SuggestionAccount; @@ -3841,7 +3830,6 @@ DB938F0326240EA300E5B6C1 /* CachedThreadViewModel.swift in Sources */, DBA5A53526F0A36A00CACBAA /* AddAccountTableViewCell.swift in Sources */, 2D35237A26256D920031AF25 /* NotificationSection.swift in Sources */, - 2D4AD89C263165B500613EFC /* SuggestionAccountCollectionViewCell.swift in Sources */, DB98EB6927B21A7C0082E365 /* ReportResultActionTableViewCell.swift in Sources */, DB9282B225F3222800823B15 /* PickServerEmptyStateView.swift in Sources */, DB697DDF278F524F004EF2F7 /* DataSourceFacade+Profile.swift in Sources */, diff --git a/Mastodon/Diffable/RecommandAccount/RecommendAccountSection.swift b/Mastodon/Diffable/RecommandAccount/RecommendAccountSection.swift index e5aa0a605..7d14aa4af 100644 --- a/Mastodon/Diffable/RecommandAccount/RecommendAccountSection.swift +++ b/Mastodon/Diffable/RecommandAccount/RecommendAccountSection.swift @@ -19,117 +19,6 @@ enum RecommendAccountSection: Equatable, Hashable { case main } -//extension RecommendAccountSection { -// static func collectionViewDiffableDataSource( -// for collectionView: UICollectionView, -// dependency: NeedsDependency, -// delegate: SearchRecommendAccountsCollectionViewCellDelegate, -// managedObjectContext: NSManagedObjectContext -// ) -> UICollectionViewDiffableDataSource { -// UICollectionViewDiffableDataSource(collectionView: collectionView) { [weak delegate] collectionView, indexPath, objectID -> UICollectionViewCell? in -// let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: SearchRecommendAccountsCollectionViewCell.self), for: indexPath) as! SearchRecommendAccountsCollectionViewCell -// managedObjectContext.performAndWait { -// let user = managedObjectContext.object(with: objectID) as! MastodonUser -// configure(cell: cell, user: user, dependency: dependency) -// } -// cell.delegate = delegate -// return cell -// } -// } -// -// static func configure( -// cell: SearchRecommendAccountsCollectionViewCell, -// user: MastodonUser, -// dependency: NeedsDependency -// ) { -// configureContent(cell: cell, user: user) -// -// if let currentMastodonUser = dependency.context.authenticationService.activeMastodonAuthentication.value?.user { -// configureFollowButton(with: user, currentMastodonUser: currentMastodonUser, followButton: cell.followButton) -// } -// -// Publishers.CombineLatest( -// ManagedObjectObserver.observe(object: user).eraseToAnyPublisher().mapError { $0 as Error }, -// dependency.context.authenticationService.activeMastodonAuthentication.setFailureType(to: Error.self) -// ) -// .receive(on: DispatchQueue.main) -// .sink { _ in -// // do nothing -// } receiveValue: { [weak cell] change, authentication in -// guard let cell = cell else { return } -// guard case .update(let object) = change.changeType, -// let user = object as? MastodonUser else { return } -// guard let currentMastodonUser = authentication?.user else { return } -// -// configureFollowButton(with: user, currentMastodonUser: currentMastodonUser, followButton: cell.followButton) -// } -// .store(in: &cell.disposeBag) -// -// } -// -// static func configureContent( -// cell: SearchRecommendAccountsCollectionViewCell, -// user: MastodonUser -// ) { -// do { -// let mastodonContent = MastodonContent(content: user.displayNameWithFallback, emojis: user.emojis.asDictionary) -// let metaContent = try MastodonMetaContent.convert(document: mastodonContent) -// cell.displayNameLabel.configure(content: metaContent) -// } catch { -// let metaContent = PlaintextMetaContent(string: user.displayNameWithFallback) -// cell.displayNameLabel.configure(content: metaContent) -// } -// cell.acctLabel.text = "@" + user.acct -// cell.avatarImageView.af.setImage( -// withURL: user.avatarImageURLWithFallback(domain: user.domain), -// placeholderImage: UIImage.placeholder(color: .systemFill), -// imageTransition: .crossDissolve(0.2) -// ) -// cell.headerImageView.af.setImage( -// withURL: URL(string: user.header)!, -// placeholderImage: UIImage.placeholder(color: .systemFill), -// imageTransition: .crossDissolve(0.2) -// ) -// } -// -// static func configureFollowButton( -// with mastodonUser: MastodonUser, -// currentMastodonUser: MastodonUser, -// followButton: HighlightDimmableButton -// ) { -// let relationshipActionSet = relationShipActionSet(mastodonUser: mastodonUser, currentMastodonUser: currentMastodonUser) -// followButton.setTitle(relationshipActionSet.title, for: .normal) -// } -// -// static func relationShipActionSet( -// mastodonUser: MastodonUser, -// currentMastodonUser: MastodonUser -// ) -> ProfileViewModel.RelationshipActionOptionSet { -// var relationshipActionSet = ProfileViewModel.RelationshipActionOptionSet([.follow]) -// let isFollowing = mastodonUser.followingBy.flatMap { $0.contains(currentMastodonUser) } ?? false -// if isFollowing { -// relationshipActionSet.insert(.following) -// } -// -// let isPending = mastodonUser.followRequestedBy.flatMap { $0.contains(currentMastodonUser) } ?? false -// if isPending { -// relationshipActionSet.insert(.pending) -// } -// -// let isBlocking = mastodonUser.blockingBy.flatMap { $0.contains(currentMastodonUser) } ?? false -// if isBlocking { -// relationshipActionSet.insert(.blocking) -// } -// -// let isBlockedBy = currentMastodonUser.blockingBy.flatMap { $0.contains(mastodonUser) } ?? false -// if isBlockedBy { -// relationshipActionSet.insert(.blocked) -// } -// return relationshipActionSet -// } -// -//} -// extension RecommendAccountSection { struct Configuration { diff --git a/Mastodon/Scene/SuggestionAccount/CollectionViewCell/SuggestionAccountCollectionViewCell.swift b/Mastodon/Scene/SuggestionAccount/CollectionViewCell/SuggestionAccountCollectionViewCell.swift deleted file mode 100644 index 296935521..000000000 --- a/Mastodon/Scene/SuggestionAccount/CollectionViewCell/SuggestionAccountCollectionViewCell.swift +++ /dev/null @@ -1,58 +0,0 @@ -// -// SuggestionAccountCollectionViewCell.swift -// Mastodon -// -// Created by sxiaojian on 2021/4/22. -// - -import CoreDataStack -import Foundation -import UIKit -import MastodonAsset -import MastodonLocalization - -class SuggestionAccountCollectionViewCell: UICollectionViewCell { - let imageView: UIImageView = { - let imageView = UIImageView() - imageView.tintColor = Asset.Colors.Label.tertiary.color - imageView.layer.cornerRadius = 4 - imageView.clipsToBounds = true - imageView.image = UIImage.placeholder(color: .systemFill) - return imageView - }() - - func configAsPlaceHolder() { - imageView.tintColor = Asset.Colors.Label.tertiary.color - imageView.image = UIImage.placeholder(color: .systemFill) - } - - func config(with mastodonUser: MastodonUser) { - imageView.af.setImage( - withURL: URL(string: mastodonUser.avatar)!, - placeholderImage: UIImage.placeholder(color: .systemFill), - imageTransition: .crossDissolve(0.2) - ) - } - - override func prepareForReuse() { - super.prepareForReuse() - } - - override init(frame: CGRect) { - super.init(frame: .zero) - configure() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - configure() - } -} - -extension SuggestionAccountCollectionViewCell { - private func configure() { - contentView.addSubview(imageView) - imageView.translatesAutoresizingMaskIntoConstraints = false - imageView.pinToParent() - } -} diff --git a/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewController.swift b/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewController.swift index 941b0f429..6d37a3f88 100644 --- a/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewController.swift +++ b/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewController.swift @@ -9,7 +9,6 @@ import Combine import CoreData import CoreDataStack import Foundation -import OSLog import UIKit import MastodonAsset import MastodonCore @@ -23,51 +22,19 @@ class SuggestionAccountViewController: UIViewController, NeedsDependency { var disposeBag = Set() var viewModel: SuggestionAccountViewModel! - - private static func createCollectionViewLayout() -> UICollectionViewLayout { - let itemSize = NSCollectionLayoutSize(widthDimension: .absolute(64), heightDimension: .absolute(64)) - let item = NSCollectionLayoutItem(layoutSize: itemSize) - - let group = NSCollectionLayoutGroup.horizontal(layoutSize: itemSize, subitems: [item]) - - let section = NSCollectionLayoutSection(group: group) - section.contentInsets = NSDirectionalEdgeInsets(top: 24, leading: 0, bottom: 24, trailing: 0) - section.orthogonalScrollingBehavior = .continuous - section.contentInsetsReference = .readableContent - section.interGroupSpacing = 16 - - return UICollectionViewCompositionalLayout(section: section) - } - let tableView: UITableView = { - let tableView = ControlContainableTableView() + let tableView = UITableView(frame: .zero, style: .insetGrouped) tableView.register(SuggestionAccountTableViewCell.self, forCellReuseIdentifier: String(describing: SuggestionAccountTableViewCell.self)) - tableView.rowHeight = UITableView.automaticDimension - tableView.tableFooterView = UIView() - tableView.separatorStyle = .singleLine - tableView.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) + tableView.separatorStyle = .none return tableView }() - deinit { - os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s:", (#file as NSString).lastPathComponent, #line, #function) - } -} + //TODO: Add "follow all"-footer-cell -extension SuggestionAccountViewController { override func viewDidLoad() { super.viewDidLoad() - setupBackgroundColor(theme: ThemeService.shared.currentTheme.value) - ThemeService.shared.currentTheme - .receive(on: DispatchQueue.main) - .sink { [weak self] theme in - guard let self = self else { return } - self.setupBackgroundColor(theme: theme) - } - .store(in: &disposeBag) - title = L10n.Scene.SuggestionAccount.title navigationItem.rightBarButtonItem = UIBarButtonItem( barButtonSystemItem: UIBarButtonItem.SystemItem.done, @@ -78,7 +45,7 @@ extension SuggestionAccountViewController { tableView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(tableView) NSLayoutConstraint.activate([ - tableView.topAnchor.constraint(equalTo: view.topAnchor), + tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), @@ -89,6 +56,11 @@ extension SuggestionAccountViewController { tableView: tableView, suggestionAccountTableViewCellDelegate: self ) + + view.backgroundColor = .secondarySystemBackground + tableView.backgroundColor = .secondarySystemBackground + navigationController?.navigationBar.prefersLargeTitles = true + navigationItem.largeTitleDisplayMode = .always } override func viewWillAppear(_ animated: Bool) { @@ -96,10 +68,6 @@ extension SuggestionAccountViewController { tableView.deselectRow(with: transitionCoordinator, animated: animated) } - - private func setupBackgroundColor(theme: Theme) { - view.backgroundColor = theme.systemBackgroundColor - } } // MARK: - UITableViewDelegate @@ -156,8 +124,5 @@ extension SuggestionAccountViewController: SuggestionAccountTableViewCellDelegat extension SuggestionAccountViewController { @objc func doneButtonDidClick(_ sender: UIButton) { dismiss(animated: true, completion: nil) -// if viewModel.selectedAccounts.value.count > 0 { -// viewModel.delegate?.homeTimelineNeedRefresh.send() -// } } } diff --git a/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewModel+Diffable.swift b/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewModel+Diffable.swift index 08ce749a4..b90240d66 100644 --- a/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewModel+Diffable.swift +++ b/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewModel+Diffable.swift @@ -21,7 +21,7 @@ extension SuggestionAccountViewModel { suggestionAccountTableViewCellDelegate: suggestionAccountTableViewCellDelegate ) ) - + userFetchedResultsController.$records .removeDuplicates() .receive(on: DispatchQueue.main) diff --git a/Mastodon/Scene/SuggestionAccount/TableViewCell/SuggestionAccountTableViewCell+ViewModel.swift b/Mastodon/Scene/SuggestionAccount/TableViewCell/SuggestionAccountTableViewCell+ViewModel.swift index 6d93be1a9..828449c6d 100644 --- a/Mastodon/Scene/SuggestionAccount/TableViewCell/SuggestionAccountTableViewCell+ViewModel.swift +++ b/Mastodon/Scene/SuggestionAccount/TableViewCell/SuggestionAccountTableViewCell+ViewModel.swift @@ -16,70 +16,6 @@ import Meta extension SuggestionAccountTableViewCell { - class ViewModel { - var disposeBag = Set() - - @Published public var userIdentifier: UserIdentifier? // me - - @Published var avatarImageURL: URL? - @Published public var authorName: MetaContent? - @Published public var authorUsername: String? - - @Published var isFollowing = false - @Published var isPending = false - - func prepareForReuse() { - isFollowing = false - isPending = false - } - } - -} - -extension SuggestionAccountTableViewCell.ViewModel { - func bind(cell: SuggestionAccountTableViewCell) { - // avatar - $avatarImageURL.removeDuplicates() - .sink { url in - let configuration = AvatarImageView.Configuration(url: url) - cell.avatarButton.avatarImageView.configure(configuration: configuration) - cell.avatarButton.avatarImageView.configure(cornerConfiguration: .init(corner: .fixed(radius: 12))) - } - .store(in: &disposeBag) - // name - $authorName - .sink { metaContent in - let metaContent = metaContent ?? PlaintextMetaContent(string: " ") - cell.titleLabel.configure(content: metaContent) - } - .store(in: &disposeBag) - // username - $authorUsername - .map { text -> String in - guard let text = text else { return "" } - return "@\(text)" - } - .sink { username in - cell.subTitleLabel.text = username - } - .store(in: &disposeBag) - // button - Publishers.CombineLatest( - $isFollowing, - $isPending - ) - .sink { isFollowing, isPending in - let isFollowState = isFollowing || isPending - let imageName = isFollowState ? "minus.circle.fill" : "plus.circle" - let image = UIImage(systemName: imageName, withConfiguration: UIImage.SymbolConfiguration(pointSize: 22, weight: .regular)) - cell.button.setImage(image, for: .normal) - cell.button.tintColor = isFollowState ? Asset.Colors.danger.color : Asset.Colors.Label.secondary.color - } - .store(in: &disposeBag) - } -} - -extension SuggestionAccountTableViewCell { func configure(user: MastodonUser) { // author avatar Publishers.CombineLatest( @@ -138,4 +74,62 @@ extension SuggestionAccountTableViewCell { .assign(to: \.isPending, on: viewModel) .store(in: &disposeBag) } + + class ViewModel { + var disposeBag = Set() + + @Published public var userIdentifier: UserIdentifier? // me + + @Published var avatarImageURL: URL? + @Published public var authorName: MetaContent? + @Published public var authorUsername: String? + + @Published var isFollowing = false + @Published var isPending = false + + func prepareForReuse() { + isFollowing = false + isPending = false + } + func bind(cell: SuggestionAccountTableViewCell) { + // avatar + $avatarImageURL.removeDuplicates() + .sink { url in + let configuration = AvatarImageView.Configuration(url: url) + cell.avatarButton.avatarImageView.configure(configuration: configuration) + cell.avatarButton.avatarImageView.configure(cornerConfiguration: .init(corner: .fixed(radius: 12))) + } + .store(in: &disposeBag) + // name + $authorName + .sink { metaContent in + let metaContent = metaContent ?? PlaintextMetaContent(string: " ") + cell.titleLabel.configure(content: metaContent) + } + .store(in: &disposeBag) + // username + $authorUsername + .map { text -> String in + guard let text = text else { return "" } + return "@\(text)" + } + .sink { username in + cell.subTitleLabel.text = username + } + .store(in: &disposeBag) + // button + Publishers.CombineLatest( + $isFollowing, + $isPending + ) + .sink { isFollowing, isPending in + let isFollowState = isFollowing || isPending + let imageName = isFollowState ? "minus.circle.fill" : "plus.circle" + let image = UIImage(systemName: imageName, withConfiguration: UIImage.SymbolConfiguration(pointSize: 22, weight: .regular)) + cell.button.setImage(image, for: .normal) + cell.button.tintColor = isFollowState ? Asset.Colors.danger.color : Asset.Colors.Label.secondary.color + } + .store(in: &disposeBag) + } + } } diff --git a/Mastodon/Scene/SuggestionAccount/TableViewCell/SuggestionAccountTableViewCell.swift b/Mastodon/Scene/SuggestionAccount/TableViewCell/SuggestionAccountTableViewCell.swift index d259ebed4..b65cdd193 100644 --- a/Mastodon/Scene/SuggestionAccount/TableViewCell/SuggestionAccountTableViewCell.swift +++ b/Mastodon/Scene/SuggestionAccount/TableViewCell/SuggestionAccountTableViewCell.swift @@ -5,7 +5,6 @@ // Created by sxiaojian on 2021/4/21. // -import os.log import Combine import CoreData import CoreDataStack @@ -23,9 +22,7 @@ protocol SuggestionAccountTableViewCellDelegate: AnyObject { } final class SuggestionAccountTableViewCell: UITableViewCell { - - let logger = Logger(subsystem: "SuggestionAccountTableViewCell", category: "View") - + var disposeBag = Set() weak var delegate: SuggestionAccountTableViewCellDelegate? @@ -35,7 +32,8 @@ final class SuggestionAccountTableViewCell: UITableViewCell { viewModel.bind(cell: self) return viewModel }() - + + //TODO: Replace this with user view let avatarButton = AvatarButton() let titleLabel = MetaLabel(style: .statusName) @@ -49,7 +47,6 @@ final class SuggestionAccountTableViewCell: UITableViewCell { let buttonContainer: UIView = { let view = UIView() - view.backgroundColor = .clear return view }() @@ -89,6 +86,8 @@ final class SuggestionAccountTableViewCell: UITableViewCell { extension SuggestionAccountTableViewCell { private func configure() { + + backgroundColor = .systemBackground let containerStackView = UIStackView() containerStackView.axis = .horizontal containerStackView.distribution = .fill @@ -147,7 +146,6 @@ extension SuggestionAccountTableViewCell { extension SuggestionAccountTableViewCell { @objc private func buttonDidPressed(_ sender: UIButton) { - logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)") delegate?.suggestionAccountTableViewCell(self, friendshipDidPressed: sender) } }