forked from zelo72/mastodon-ios
feat: add discovery endpoint check logic and handle relationship action
This commit is contained in:
parent
b0fca49413
commit
f5aaf2737f
|
@ -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
|
||||
|
|
|
@ -122,12 +122,12 @@ extension DataSourceFacade {
|
|||
let barButtonItem: UIBarButtonItem?
|
||||
}
|
||||
|
||||
@MainActor
|
||||
static func createProfileActionMenu(
|
||||
dependency: NeedsDependency,
|
||||
user: ManagedObjectRecord<MastodonUser>
|
||||
) -> UIMenu {
|
||||
var children: [UIMenuElement] = []
|
||||
// @MainActor
|
||||
// static func createProfileActionMenu(
|
||||
// dependency: NeedsDependency,
|
||||
// user: ManagedObjectRecord<MastodonUser>
|
||||
// ) -> 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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,11 +6,14 @@
|
|||
//
|
||||
|
||||
import UIKit
|
||||
import Combine
|
||||
import Tabman
|
||||
import Pageboy
|
||||
|
||||
final class DiscoveryViewModel {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)")
|
||||
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
|
||||
|
|
|
@ -38,10 +38,15 @@ final class DiscoveryNewsViewModel {
|
|||
}()
|
||||
|
||||
let didLoadLatest = PassthroughSubject<Void, Never>()
|
||||
@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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)")
|
||||
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
|
||||
|
|
|
@ -38,6 +38,7 @@ final class DiscoveryPostsViewModel {
|
|||
}()
|
||||
|
||||
let didLoadLatest = PassthroughSubject<Void, Never>()
|
||||
@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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import Meta
|
|||
import AlamofireImage
|
||||
import CoreDataStack
|
||||
import MastodonLocalization
|
||||
import MastodonAsset
|
||||
|
||||
extension ProfileCardView {
|
||||
public class ViewModel: ObservableObject {
|
||||
|
@ -20,6 +21,9 @@ extension ProfileCardView {
|
|||
|
||||
public let relationshipViewModel = RelationshipViewModel()
|
||||
|
||||
@Published public var userInterfaceStyle: UIUserInterfaceStyle?
|
||||
@Published public var backgroundColor: UIColor?
|
||||
|
||||
// Author
|
||||
@Published public var authorBannerImageURL: URL?
|
||||
@Published public var authorAvatarImageURL: 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
|
||||
|
|
|
@ -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<AnyCancellable>()
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<AnyCancellable>()
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue