diff --git a/Mastodon/Diffiable/Discovery/DiscoverySection.swift b/Mastodon/Diffiable/Discovery/DiscoverySection.swift index f0c358a1..76cc9c03 100644 --- a/Mastodon/Diffiable/Discovery/DiscoverySection.swift +++ b/Mastodon/Diffiable/Discovery/DiscoverySection.swift @@ -20,7 +20,13 @@ extension DiscoverySection { static let logger = Logger(subsystem: "DiscoverySection", category: "logic") - struct Configuration { } + class Configuration { + weak var profileCardTableViewCellDelegate: ProfileCardTableViewCellDelegate? + + public init(profileCardTableViewCellDelegate: ProfileCardTableViewCellDelegate? = nil) { + self.profileCardTableViewCellDelegate = profileCardTableViewCellDelegate + } + } static func diffableDataSource( tableView: UITableView, @@ -52,6 +58,7 @@ extension DiscoverySection { .map { $0?.user } .assign(to: \.me, on: cell.profileCardView.viewModel.relationshipViewModel) .store(in: &cell.disposeBag) + cell.delegate = configuration.profileCardTableViewCellDelegate return cell case .bottomLoader: let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self), for: indexPath) as! TimelineBottomLoaderTableViewCell diff --git a/Mastodon/Protocol/Provider/DataSourceFacade+Profile.swift b/Mastodon/Protocol/Provider/DataSourceFacade+Profile.swift index 36eaab62..66259a09 100644 --- a/Mastodon/Protocol/Provider/DataSourceFacade+Profile.swift +++ b/Mastodon/Protocol/Provider/DataSourceFacade+Profile.swift @@ -122,12 +122,12 @@ extension DataSourceFacade { let barButtonItem: UIBarButtonItem? } - @MainActor - static func createProfileActionMenu( - dependency: NeedsDependency, - user: ManagedObjectRecord - ) -> UIMenu { - var children: [UIMenuElement] = [] +// @MainActor +// static func createProfileActionMenu( +// dependency: NeedsDependency, +// user: ManagedObjectRecord +// ) -> UIMenu { +// var children: [UIMenuElement] = [] // let name = mastodonUser.displayNameWithFallback // // if let shareUser = shareUser { @@ -339,9 +339,9 @@ extension DataSourceFacade { // } // children.append(deleteAction) // } - - return UIMenu(title: "", options: [], children: children) - } +// +// return UIMenu(title: "", options: [], children: children) +// } static func createActivityViewController( dependency: NeedsDependency, diff --git a/Mastodon/Scene/Discovery/DiscoveryViewController.swift b/Mastodon/Scene/Discovery/DiscoveryViewController.swift index dac2c99c..8e3aab64 100644 --- a/Mastodon/Scene/Discovery/DiscoveryViewController.swift +++ b/Mastodon/Scene/Discovery/DiscoveryViewController.swift @@ -29,13 +29,54 @@ public class DiscoveryViewController: TabmanViewController, NeedsDependency { coordinator: coordinator ) - let buttonBar: TMBar.ButtonBar = { + private(set) lazy var buttonBar: TMBar.ButtonBar = { let buttonBar = TMBar.ButtonBar() - buttonBar.indicator.backgroundColor = Asset.Colors.Label.primary.color + buttonBar.backgroundView.style = .custom(view: buttonBarBackgroundView) + buttonBar.layout.interButtonSpacing = 0 buttonBar.layout.contentInset = .zero + buttonBar.indicator.backgroundColor = Asset.Colors.Label.primary.color + buttonBar.indicator.weight = .custom(value: 2) return buttonBar }() + let buttonBarBackgroundView: UIView = { + let view = UIView() + let barBottomLine = UIView.separatorLine + barBottomLine.backgroundColor = Asset.Colors.Label.secondary.color.withAlphaComponent(0.5) + barBottomLine.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(barBottomLine) + NSLayoutConstraint.activate([ + barBottomLine.leadingAnchor.constraint(equalTo: view.leadingAnchor), + barBottomLine.trailingAnchor.constraint(equalTo: view.trailingAnchor), + barBottomLine.bottomAnchor.constraint(equalTo: view.bottomAnchor), + barBottomLine.heightAnchor.constraint(equalToConstant: 2).priority(.required - 1), + ]) + return view + }() + + func customizeButtonBarAppearance() { + // The implmention use CATextlayer. Adapt for Dark Mode without dynamic colors + // Needs trigger update when `userInterfaceStyle` chagnes + let userInterfaceStyle = traitCollection.userInterfaceStyle + buttonBar.buttons.customize { button in + switch userInterfaceStyle { + case .dark: + // Asset.Colors.Label.primary.color + button.selectedTintColor = UIColor(red: 238.0/255.0, green: 238.0/255.0, blue: 238.0/255.0, alpha: 1.0) + // Asset.Colors.Label.secondary.color + button.tintColor = UIColor(red: 151.0/255.0, green: 157.0/255.0, blue: 173.0/255.0, alpha: 1.0) + default: + // Asset.Colors.Label.primary.color + button.selectedTintColor = UIColor(red: 40.0/255.0, green: 44.0/255.0, blue: 55.0/255.0, alpha: 1.0) + // Asset.Colors.Label.secondary.color + button.tintColor = UIColor(red: 60.0/255.0, green: 60.0/255.0, blue: 67.0/255.0, alpha: 0.6) + } + + button.backgroundColor = .clear + button.contentInset = UIEdgeInsets(top: 12, left: 26, bottom: 12, right: 26) + } + } + } extension DiscoveryViewController { @@ -58,13 +99,21 @@ extension DiscoveryViewController { dataSource: viewModel, at: .top ) - updateBarButtonInsets() + customizeButtonBarAppearance() + + viewModel.$viewControllers + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in + guard let self = self else { return } + self.reloadData() + } + .store(in: &disposeBag) } public override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) - - updateBarButtonInsets() + + customizeButtonBarAppearance() } } @@ -72,24 +121,8 @@ extension DiscoveryViewController { extension DiscoveryViewController { private func setupAppearance(theme: Theme) { - view.backgroundColor = ThemeService.shared.currentTheme.value.secondarySystemBackgroundColor - buttonBar.backgroundView.style = .flat(color: theme.systemBackgroundColor) - } - - private func updateBarButtonInsets() { - let margin: CGFloat = { - switch traitCollection.userInterfaceIdiom { - case .phone: - return DiscoveryViewController.containerViewMarginForCompactHorizontalSizeClass - default: - return traitCollection.horizontalSizeClass == .regular ? - DiscoveryViewController.containerViewMarginForRegularHorizontalSizeClass : - DiscoveryViewController.containerViewMarginForCompactHorizontalSizeClass - } - }() - - buttonBar.layout.contentInset.left = margin - buttonBar.layout.contentInset.right = margin + view.backgroundColor = theme.secondarySystemBackgroundColor + buttonBarBackgroundView.backgroundColor = theme.systemBackgroundColor } } diff --git a/Mastodon/Scene/Discovery/DiscoveryViewModel.swift b/Mastodon/Scene/Discovery/DiscoveryViewModel.swift index 187d7311..ae31797e 100644 --- a/Mastodon/Scene/Discovery/DiscoveryViewModel.swift +++ b/Mastodon/Scene/Discovery/DiscoveryViewModel.swift @@ -6,11 +6,14 @@ // import UIKit +import Combine import Tabman import Pageboy final class DiscoveryViewModel { + var disposeBag = Set() + // input let context: AppContext let discoveryPostsViewController: DiscoveryPostsViewController @@ -18,25 +21,7 @@ final class DiscoveryViewModel { let discoveryNewsViewController: DiscoveryNewsViewController let discoveryForYouViewController: DiscoveryForYouViewController - // output - let barItems: [TMBarItemable] = { - let items = [ - TMBarItem(title: "Posts"), - TMBarItem(title: "Hashtags"), - TMBarItem(title: "News"), - TMBarItem(title: "For You"), - ] - return items - }() - - var viewControllers: [ScrollViewContainer] { - return [ - discoveryPostsViewController, - discoveryHashtagsViewController, - discoveryNewsViewController, - discoveryForYouViewController, - ] - } + @Published var viewControllers: [ScrollViewContainer & PageViewController] init(context: AppContext, coordinator: SceneCoordinator) { func setupDependency(_ needsDependency: NeedsDependency) { @@ -69,7 +54,35 @@ final class DiscoveryViewModel { viewController.viewModel = DiscoveryForYouViewModel(context: context) return viewController }() + self.viewControllers = [ + discoveryPostsViewController, + discoveryHashtagsViewController, + discoveryNewsViewController, + discoveryForYouViewController, + ] // end init + + discoveryPostsViewController.viewModel.$isServerSupportEndpoint + .receive(on: DispatchQueue.main) + .sink { [weak self] isServerSupportEndpoint in + guard let self = self else { return } + if !isServerSupportEndpoint { + self.viewControllers.removeAll(where: { + $0 === self.discoveryPostsViewController || $0 === self.discoveryPostsViewController + }) + } + } + .store(in: &disposeBag) + + discoveryNewsViewController.viewModel.$isServerSupportEndpoint + .receive(on: DispatchQueue.main) + .sink { [weak self] isServerSupportEndpoint in + guard let self = self else { return } + if !isServerSupportEndpoint { + self.viewControllers.removeAll(where: { $0 === self.discoveryNewsViewController }) + } + } + .store(in: &disposeBag) } } @@ -95,6 +108,49 @@ extension DiscoveryViewModel: PageboyViewControllerDataSource { // MARK: - TMBarDataSource extension DiscoveryViewModel: TMBarDataSource { func barItem(for bar: TMBar, at index: Int) -> TMBarItemable { - return barItems[index] + guard !viewControllers.isEmpty, index < viewControllers.count else { + assertionFailure() + return TMBarItem(title: "") + } + return viewControllers[index].tabItem + } +} + +protocol PageViewController: UIViewController { + var tabItemTitle: String { get } + var tabItem: TMBarItemable { get } +} + +// MARK: - PageViewController +extension DiscoveryPostsViewController: PageViewController { + var tabItemTitle: String { "Posts" } + var tabItem: TMBarItemable { + return TMBarItem(title: tabItemTitle) + } +} + + +// MARK: - PageViewController +extension DiscoveryHashtagsViewController: PageViewController { + var tabItemTitle: String { "Hashtags" } + var tabItem: TMBarItemable { + + return TMBarItem(title: tabItemTitle) + } +} + +// MARK: - PageViewController +extension DiscoveryNewsViewController: PageViewController { + var tabItemTitle: String { "News" } + var tabItem: TMBarItemable { + return TMBarItem(title: tabItemTitle) + } +} + +// MARK: - PageViewController +extension DiscoveryForYouViewController: PageViewController { + var tabItemTitle: String { "For You" } + var tabItem: TMBarItemable { + return TMBarItem(title: tabItemTitle) } } diff --git a/Mastodon/Scene/Discovery/ForYou/DiscoveryForYouViewController.swift b/Mastodon/Scene/Discovery/ForYou/DiscoveryForYouViewController.swift index 4654769d..b8b8f25a 100644 --- a/Mastodon/Scene/Discovery/ForYou/DiscoveryForYouViewController.swift +++ b/Mastodon/Scene/Discovery/ForYou/DiscoveryForYouViewController.swift @@ -64,7 +64,8 @@ extension DiscoveryForYouViewController { tableView.delegate = self viewModel.setupDiffableDataSource( - tableView: tableView + tableView: tableView, + profileCardTableViewCellDelegate: self ) tableView.refreshControl = refreshControl @@ -119,9 +120,27 @@ extension DiscoveryForYouViewController: UITableViewDelegate { } +// MARK: - ProfileCardTableViewCellDelegate +extension DiscoveryForYouViewController: ProfileCardTableViewCellDelegate { + func profileCardTableViewCell(_ cell: ProfileCardTableViewCell, profileCardView: ProfileCardView, relationshipButtonDidPressed button: ProfileRelationshipActionButton) { + guard let authenticationBox = viewModel.context.authenticationService.activeMastodonAuthenticationBox.value else { return } + guard let indexPath = tableView.indexPath(for: cell) else { return } + guard case let .user(record) = viewModel.diffableDataSource?.itemIdentifier(for: indexPath) else { return } + + Task { + try await DataSourceFacade.responseToUserFollowAction( + dependency: self, + user: record, + authenticationBox: authenticationBox + ) + } // end Task + } +} + // MARK: ScrollViewContainer extension DiscoveryForYouViewController: ScrollViewContainer { var scrollView: UIScrollView? { tableView } } + diff --git a/Mastodon/Scene/Discovery/ForYou/DiscoveryForYouViewModel+Diffable.swift b/Mastodon/Scene/Discovery/ForYou/DiscoveryForYouViewModel+Diffable.swift index 23114073..fe53cf22 100644 --- a/Mastodon/Scene/Discovery/ForYou/DiscoveryForYouViewModel+Diffable.swift +++ b/Mastodon/Scene/Discovery/ForYou/DiscoveryForYouViewModel+Diffable.swift @@ -7,16 +7,20 @@ import UIKit import Combine +import MastodonUI extension DiscoveryForYouViewModel { func setupDiffableDataSource( - tableView: UITableView + tableView: UITableView, + profileCardTableViewCellDelegate: ProfileCardTableViewCellDelegate ) { diffableDataSource = DiscoverySection.diffableDataSource( tableView: tableView, context: context, - configuration: DiscoverySection.Configuration() + configuration: DiscoverySection.Configuration( + profileCardTableViewCellDelegate: profileCardTableViewCellDelegate + ) ) Task { diff --git a/Mastodon/Scene/Discovery/News/DiscoveryNewsViewModel+State.swift b/Mastodon/Scene/Discovery/News/DiscoveryNewsViewModel+State.swift index 37d93e5b..8da975de 100644 --- a/Mastodon/Scene/Discovery/News/DiscoveryNewsViewModel+State.swift +++ b/Mastodon/Scene/Discovery/News/DiscoveryNewsViewModel+State.swift @@ -183,7 +183,13 @@ extension DiscoveryNewsViewModel.State { viewModel.didLoadLatest.send() } catch { logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): fetch news fail: \(error.localizedDescription)") - await enter(state: Fail.self) + if let error = error as? Mastodon.API.Error, error.httpResponseStatus.code == 404 { + viewModel.isServerSupportEndpoint = false + await enter(state: NoMore.self) + } else { + await enter(state: Fail.self) + } + viewModel.didLoadLatest.send() } } // end Task diff --git a/Mastodon/Scene/Discovery/News/DiscoveryNewsViewModel.swift b/Mastodon/Scene/Discovery/News/DiscoveryNewsViewModel.swift index b87e7c05..2c4d89dc 100644 --- a/Mastodon/Scene/Discovery/News/DiscoveryNewsViewModel.swift +++ b/Mastodon/Scene/Discovery/News/DiscoveryNewsViewModel.swift @@ -38,10 +38,15 @@ final class DiscoveryNewsViewModel { }() let didLoadLatest = PassthroughSubject() - + @Published var isServerSupportEndpoint = true + init(context: AppContext) { self.context = context // end init + + Task { + await checkServerEndpoint() + } // end Task } deinit { @@ -49,3 +54,21 @@ final class DiscoveryNewsViewModel { } } + + +extension DiscoveryNewsViewModel { + func checkServerEndpoint() async { + guard let authenticationBox = context.authenticationService.activeMastodonAuthenticationBox.value else { return } + + do { + _ = try await context.apiService.trendLinks( + domain: authenticationBox.domain, + query: .init(offset: nil, limit: nil) + ) + } catch let error as Mastodon.API.Error where error.httpResponseStatus.code == 404 { + isServerSupportEndpoint = false + } catch { + // do nothing + } + } +} diff --git a/Mastodon/Scene/Discovery/Posts/DiscoveryPostsViewModel+State.swift b/Mastodon/Scene/Discovery/Posts/DiscoveryPostsViewModel+State.swift index a8e2e7c2..d91c5adc 100644 --- a/Mastodon/Scene/Discovery/Posts/DiscoveryPostsViewModel+State.swift +++ b/Mastodon/Scene/Discovery/Posts/DiscoveryPostsViewModel+State.swift @@ -180,9 +180,16 @@ extension DiscoveryPostsViewModel.State { } viewModel.statusFetchedResultsController.statusIDs.value = statusIDs viewModel.didLoadLatest.send() +// } catch let error as? } catch { logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): fetch posts fail: \(error.localizedDescription)") - await enter(state: Fail.self) + if let error = error as? Mastodon.API.Error, error.httpResponseStatus.code == 404 { + viewModel.isServerSupportEndpoint = false + await enter(state: NoMore.self) + } else { + await enter(state: Fail.self) + } + viewModel.didLoadLatest.send() } } // end Task diff --git a/Mastodon/Scene/Discovery/Posts/DiscoveryPostsViewModel.swift b/Mastodon/Scene/Discovery/Posts/DiscoveryPostsViewModel.swift index 590ccc16..c001bb7b 100644 --- a/Mastodon/Scene/Discovery/Posts/DiscoveryPostsViewModel.swift +++ b/Mastodon/Scene/Discovery/Posts/DiscoveryPostsViewModel.swift @@ -38,6 +38,7 @@ final class DiscoveryPostsViewModel { }() let didLoadLatest = PassthroughSubject() + @Published var isServerSupportEndpoint = true init(context: AppContext) { self.context = context @@ -52,6 +53,10 @@ final class DiscoveryPostsViewModel { .map { $0?.domain } .assign(to: \.value, on: statusFetchedResultsController.domain) .store(in: &disposeBag) + + Task { + await checkServerEndpoint() + } // end Task } deinit { @@ -59,3 +64,20 @@ final class DiscoveryPostsViewModel { } } + +extension DiscoveryPostsViewModel { + func checkServerEndpoint() async { + guard let authenticationBox = context.authenticationService.activeMastodonAuthenticationBox.value else { return } + + do { + _ = try await context.apiService.trendStatuses( + domain: authenticationBox.domain, + query: .init(offset: nil, limit: nil) + ) + } catch let error as Mastodon.API.Error where error.httpResponseStatus.code == 404 { + isServerSupportEndpoint = false + } catch { + // do nothing + } + } +} diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/ProfileCardView+ViewModel.swift b/MastodonSDK/Sources/MastodonUI/View/Content/ProfileCardView+ViewModel.swift index 0e01161d..99eb27a5 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/ProfileCardView+ViewModel.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/ProfileCardView+ViewModel.swift @@ -12,6 +12,7 @@ import Meta import AlamofireImage import CoreDataStack import MastodonLocalization +import MastodonAsset extension ProfileCardView { public class ViewModel: ObservableObject { @@ -19,6 +20,9 @@ extension ProfileCardView { var disposeBag = Set() public let relationshipViewModel = RelationshipViewModel() + + @Published public var userInterfaceStyle: UIUserInterfaceStyle? + @Published public var backgroundColor: UIColor? // Author @Published public var authorBannerImageURL: URL? @@ -37,11 +41,35 @@ extension ProfileCardView { @Published public var isMuting = false @Published public var isBlocking = false @Published public var isBlockedBy = false + + init() { + backgroundColor = ThemeService.shared.currentTheme.value.systemBackgroundColor + Publishers.CombineLatest( + ThemeService.shared.currentTheme, + $userInterfaceStyle + ) + .sink { [weak self] theme, userInterfaceStyle in + guard let self = self else { return } + guard let userInterfaceStyle = userInterfaceStyle else { return } + switch userInterfaceStyle { + case .dark: + self.backgroundColor = theme.systemBackgroundColor + case .light, .unspecified: + self.backgroundColor = Asset.Scene.Discovery.profileCardBackground.color + @unknown default: + self.backgroundColor = Asset.Scene.Discovery.profileCardBackground.color + assertionFailure() + // do nothing + } + } + .store(in: &disposeBag) + } } } extension ProfileCardView.ViewModel { func bind(view: ProfileCardView) { + bindAppearacne(view: view) bindHeader(view: view) bindUser(view: view) bindBio(view: view) @@ -49,6 +77,18 @@ extension ProfileCardView.ViewModel { bindDashboard(view: view) } + private func bindAppearacne(view: ProfileCardView) { + userInterfaceStyle = view.traitCollection.userInterfaceStyle + + $backgroundColor + .assign(to: \.backgroundColor, on: view.container) + .store(in: &disposeBag) + $backgroundColor + .assign(to: \.backgroundColor, on: view.avatarButtonBackgroundView) + .store(in: &disposeBag) + } + + private func bindHeader(view: ProfileCardView) { $authorBannerImageURL .sink { url in diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/ProfileCardView.swift b/MastodonSDK/Sources/MastodonUI/View/Content/ProfileCardView.swift index a8e90906..eb500b7c 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/ProfileCardView.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/ProfileCardView.swift @@ -5,17 +5,23 @@ // Created by MainasuK on 2022-4-14. // +import os.log import UIKit import Combine import MetaTextKit import MastodonAsset +public protocol ProfileCardViewDelegate: AnyObject { + func profileCardView(_ profileCardView: ProfileCardView, relationshipButtonDidPressed button: ProfileRelationshipActionButton) +} + public final class ProfileCardView: UIView { static let avatarSize = CGSize(width: 56, height: 56) static let friendshipActionButtonSize = CGSize(width: 108, height: 34) static let contentMargin: CGFloat = 16 + weak var delegate: ProfileCardViewDelegate? private var _disposeBag = Set() var disposeBag = Set() @@ -31,6 +37,7 @@ public final class ProfileCardView: UIView { }() // avatar + public let avatarButtonBackgroundView = UIView() public let avatarButton = AvatarButton() // author name @@ -115,7 +122,6 @@ extension ProfileCardView { statusDashboardView.isUserInteractionEnabled = false // container: V - [ bannerContainer | authorContainer | bioMetaText | infoContainer ] - container.backgroundColor = Asset.Scene.Discovery.profileCardBackground.color container.axis = .vertical container.spacing = 8 container.translatesAutoresizingMaskIntoConstraints = false @@ -171,8 +177,6 @@ extension ProfileCardView { avatarButton.heightAnchor.constraint(equalToConstant: ProfileCardView.avatarSize.height).priority(.required - 1), ]) - let avatarButtonBackgroundView = UIView() - avatarButtonBackgroundView.backgroundColor = Asset.Scene.Discovery.profileCardBackground.color avatarButtonBackgroundView.layer.masksToBounds = true avatarButtonBackgroundView.layer.cornerCurve = .continuous avatarButtonBackgroundView.layer.cornerRadius = 12 @@ -230,6 +234,22 @@ extension ProfileCardView { NSLayoutConstraint.activate([ bottomPadding.heightAnchor.constraint(equalToConstant: 16) ]) + + relationshipActionButton.addTarget(self, action: #selector(ProfileCardView.relationshipActionButtonDidPressed(_:)), for: .touchUpInside) + } + + public override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + + viewModel.userInterfaceStyle = traitCollection.userInterfaceStyle } } + +extension ProfileCardView { + @objc private func relationshipActionButtonDidPressed(_ sender: UIButton) { + os_log(.debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) + assert(sender === relationshipActionButton) + delegate?.profileCardView(self, relationshipButtonDidPressed: relationshipActionButton) + } +} diff --git a/MastodonSDK/Sources/MastodonUI/View/TableViewCell/ProfileCardTableViewCell.swift b/MastodonSDK/Sources/MastodonUI/View/TableViewCell/ProfileCardTableViewCell.swift index a793482a..d3c8f223 100644 --- a/MastodonSDK/Sources/MastodonUI/View/TableViewCell/ProfileCardTableViewCell.swift +++ b/MastodonSDK/Sources/MastodonUI/View/TableViewCell/ProfileCardTableViewCell.swift @@ -8,8 +8,13 @@ import UIKit import Combine +public protocol ProfileCardTableViewCellDelegate: AnyObject { + func profileCardTableViewCell(_ cell: ProfileCardTableViewCell, profileCardView: ProfileCardView, relationshipButtonDidPressed button: ProfileRelationshipActionButton) +} + public final class ProfileCardTableViewCell: UITableViewCell { + public weak var delegate: ProfileCardTableViewCellDelegate? public var disposeBag = Set() public let profileCardView: ProfileCardView = { @@ -63,6 +68,15 @@ extension ProfileCardTableViewCell { profileCardView.trailingAnchor.constraint(equalTo: shadowBackgroundContainer.trailingAnchor), profileCardView.bottomAnchor.constraint(equalTo: shadowBackgroundContainer.bottomAnchor), ]) + + profileCardView.delegate = self } } + +// MARK: - ProfileCardViewDelegate +extension ProfileCardTableViewCell: ProfileCardViewDelegate { + public func profileCardView(_ profileCardView: ProfileCardView, relationshipButtonDidPressed button: ProfileRelationshipActionButton) { + delegate?.profileCardTableViewCell(self, profileCardView: profileCardView, relationshipButtonDidPressed: button) + } +}