mastodon-app-ufficiale-ipho.../MastodonSDK/Sources/MastodonUI/View/Content/NotificationView.swift

624 lines
29 KiB
Swift

//
// NotificationView.swift
//
//
// Created by MainasuK on 2022-1-21.
//
import os.log
import UIKit
import Combine
import MetaTextKit
import Meta
import MastodonCore
import MastodonAsset
import MastodonLocalization
public protocol NotificationViewDelegate: AnyObject {
func notificationView(_ notificationView: NotificationView, authorAvatarButtonDidPressed button: AvatarButton)
func notificationView(_ notificationView: NotificationView, menuButton button: UIButton, didSelectAction action: MastodonMenu.Action)
func notificationView(_ notificationView: NotificationView, acceptFollowRequestButtonDidPressed button: UIButton)
func notificationView(_ notificationView: NotificationView, rejectFollowRequestButtonDidPressed button: UIButton)
func notificationView(_ notificationView: NotificationView, statusView: StatusView, metaText: MetaText, didSelectMeta meta: Meta)
func notificationView(_ notificationView: NotificationView, statusView: StatusView, spoilerOverlayViewDidPressed overlayView: SpoilerOverlayView)
func notificationView(_ notificationView: NotificationView, statusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaView: MediaView, didSelectMediaViewAt index: Int)
func notificationView(_ notificationView: NotificationView, statusView: StatusView, actionToolbarContainer: ActionToolbarContainer, buttonDidPressed button: UIButton, action: ActionToolbarContainer.Action)
func notificationView(_ notificationView: NotificationView, quoteStatusView: StatusView, authorAvatarButtonDidPressed button: AvatarButton)
func notificationView(_ notificationView: NotificationView, quoteStatusView: StatusView, metaText: MetaText, didSelectMeta meta: Meta)
func notificationView(_ notificationView: NotificationView, quoteStatusView: StatusView, spoilerOverlayViewDidPressed overlayView: SpoilerOverlayView)
func notificationView(_ notificationView: NotificationView, quoteStatusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaView: MediaView, didSelectMediaViewAt index: Int)
// a11y
func notificationView(_ notificationView: NotificationView, accessibilityActivate: Void)
}
public final class NotificationView: UIView {
static let containerLayoutMargin = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)
let logger = Logger(subsystem: "NotificationView", category: "View")
public weak var delegate: NotificationViewDelegate?
var _disposeBag = Set<AnyCancellable>()
public var disposeBag = Set<AnyCancellable>()
var notificationActions = [UIAccessibilityCustomAction]()
var authorActions = [UIAccessibilityCustomAction]()
public private(set) lazy var viewModel: ViewModel = {
let viewModel = ViewModel()
viewModel.bind(notificationView: self)
return viewModel
}()
let containerStackView: UIStackView = {
let stackView = UIStackView()
stackView.axis = .vertical
stackView.spacing = 10
return stackView
}()
// author
let authorAdaptiveMarginContainerView = AdaptiveMarginContainerView()
let authorContainerView: UIStackView = {
let stackView = UIStackView()
stackView.axis = .horizontal
stackView.spacing = 12
return stackView
}()
let authorContainerViewBottomPaddingView = UIView()
// avatar
public let avatarButton = AvatarButton()
// author name
public let authorNameLabel = MetaLabel(style: .statusName)
// author username
public let authorUsernameLabel = MetaLabel(style: .statusUsername)
public let usernameTrialingDotLabel: MetaLabel = {
let label = MetaLabel(style: .statusUsername)
label.configure(content: PlaintextMetaContent(string: "·"))
return label
}()
// timestamp
public let dateLabel = MetaLabel(style: .statusUsername)
public let menuButton: UIButton = {
let button = HitTestExpandedButton(type: .system)
let image = UIImage(systemName: "ellipsis", withConfiguration: UIImage.SymbolConfiguration(font: .systemFont(ofSize: 15)))
button.setImage(image, for: .normal)
return button
}()
// notification type indicator imageView
public let notificationTypeIndicatorImageView: UIImageView = {
let imageView = UIImageView()
imageView.tintColor = Asset.Colors.Label.secondary.color
return imageView
}()
// notification type indicator imageView
public let notificationTypeIndicatorLabel = MetaLabel(style: .notificationTitle)
// follow request
let followRequestAdaptiveMarginContainerView = AdaptiveMarginContainerView()
let followRequestContainerView = UIStackView()
let acceptFollowRequestButtonShadowBackgroundContainer = ShadowBackgroundContainer()
private(set) lazy var acceptFollowRequestButton: UIButton = {
let button = HighlightDimmableButton()
button.titleLabel?.font = UIFont.systemFont(ofSize: 17, weight: .semibold)
button.setTitleColor(.white, for: .normal)
button.setTitle(L10n.Common.Controls.Actions.confirm, for: .normal)
button.setImage(Asset.Editing.checkmark20.image.withRenderingMode(.alwaysTemplate), for: .normal)
button.imageView?.contentMode = .scaleAspectFit
button.setBackgroundImage(.placeholder(color: Asset.Scene.Notification.confirmFollowRequestButtonBackground.color), for: .normal)
button.setInsets(forContentPadding: UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8), imageTitlePadding: 8)
button.tintColor = .white
button.layer.masksToBounds = true
button.layer.cornerCurve = .continuous
button.layer.cornerRadius = 10
button.accessibilityLabel = L10n.Scene.Notification.FollowRequest.accept
acceptFollowRequestButtonShadowBackgroundContainer.cornerRadius = 10
acceptFollowRequestButtonShadowBackgroundContainer.shadowAlpha = 0.1
button.addTarget(self, action: #selector(NotificationView.acceptFollowRequestButtonDidPressed(_:)), for: .touchUpInside)
return button
}()
let acceptFollowRequestActivityIndicatorView = UIActivityIndicatorView(style: .medium)
let rejectFollowRequestButtonShadowBackgroundContainer = ShadowBackgroundContainer()
private(set) lazy var rejectFollowRequestButton: UIButton = {
let button = HighlightDimmableButton()
button.titleLabel?.font = UIFont.systemFont(ofSize: 17, weight: .semibold)
button.setTitleColor(.black, for: .normal)
button.setTitle(L10n.Common.Controls.Actions.delete, for: .normal)
button.setImage(Asset.Circles.forbidden20.image.withRenderingMode(.alwaysTemplate), for: .normal)
button.imageView?.contentMode = .scaleAspectFit
button.setInsets(forContentPadding: UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8), imageTitlePadding: 8)
button.setBackgroundImage(.placeholder(color: Asset.Scene.Notification.deleteFollowRequestButtonBackground.color), for: .normal)
button.tintColor = .black
button.layer.masksToBounds = true
button.layer.cornerCurve = .continuous
button.layer.cornerRadius = 10
button.accessibilityLabel = L10n.Scene.Notification.FollowRequest.reject
rejectFollowRequestButtonShadowBackgroundContainer.cornerRadius = 10
rejectFollowRequestButtonShadowBackgroundContainer.shadowAlpha = 0.1
button.addTarget(self, action: #selector(NotificationView.rejectFollowRequestButtonDidPressed(_:)), for: .touchUpInside)
return button
}()
let rejectFollowRequestActivityIndicatorView = UIActivityIndicatorView(style: .medium)
// status
public let statusView = StatusView()
public let quoteStatusViewContainerView = UIView()
public let quoteBackgroundView = UIView()
public let quoteStatusView = StatusView()
public func prepareForReuse() {
disposeBag.removeAll()
viewModel.objects.removeAll()
viewModel.authContext = nil
viewModel.authorAvatarImageURL = nil
avatarButton.avatarImageView.cancelTask()
authorContainerViewBottomPaddingView.isHidden = true
followRequestAdaptiveMarginContainerView.isHidden = true
acceptFollowRequestButtonShadowBackgroundContainer.isHidden = false
rejectFollowRequestButtonShadowBackgroundContainer.isHidden = false
acceptFollowRequestActivityIndicatorView.stopAnimating()
rejectFollowRequestActivityIndicatorView.stopAnimating()
acceptFollowRequestButton.isUserInteractionEnabled = true
rejectFollowRequestButton.isUserInteractionEnabled = true
statusView.isHidden = true
statusView.prepareForReuse()
quoteStatusViewContainerView.isHidden = true
quoteStatusView.prepareForReuse()
}
override init(frame: CGRect) {
super.init(frame: frame)
_init()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
_init()
}
}
extension NotificationView {
private func _init() {
// container: V - [ author container | (authorContainerViewBottomPaddingView) | statusView | quoteStatusView ]
// containerStackView.layoutMargins = StatusView.containerLayoutMargin
containerStackView.translatesAutoresizingMaskIntoConstraints = false
addSubview(containerStackView)
NSLayoutConstraint.activate([
containerStackView.topAnchor.constraint(equalTo: topAnchor),
containerStackView.leadingAnchor.constraint(equalTo: leadingAnchor),
containerStackView.trailingAnchor.constraint(equalTo: trailingAnchor),
bottomAnchor.constraint(equalTo: containerStackView.bottomAnchor),
])
// author container: H - [ avatarButton | author meta container ]
authorAdaptiveMarginContainerView.contentView = authorContainerView
authorAdaptiveMarginContainerView.margin = StatusView.containerLayoutMargin
containerStackView.addArrangedSubview(authorAdaptiveMarginContainerView)
UIContentSizeCategory.publisher
.sink { [weak self] category in
guard let self = self else { return }
self.authorContainerView.axis = category > .accessibilityLarge ? .vertical : .horizontal
self.authorContainerView.alignment = category > .accessibilityLarge ? .leading : .center
}
.store(in: &_disposeBag)
// avatarButton
avatarButton.size = CGSize.authorAvatarButtonSize
avatarButton.avatarImageView.imageViewSize = CGSize.authorAvatarButtonSize
avatarButton.translatesAutoresizingMaskIntoConstraints = false
authorContainerView.addArrangedSubview(avatarButton)
NSLayoutConstraint.activate([
avatarButton.widthAnchor.constraint(equalToConstant: CGSize.authorAvatarButtonSize.width).priority(.required - 1),
avatarButton.heightAnchor.constraint(equalToConstant: CGSize.authorAvatarButtonSize.height).priority(.required - 1),
])
avatarButton.setContentHuggingPriority(.required - 1, for: .vertical)
avatarButton.setContentCompressionResistancePriority(.required - 1, for: .vertical)
// authrMetaContainer: V - [ authorPrimaryContainer | authorSecondaryMetaContainer ]
let authrMetaContainer = UIStackView()
authrMetaContainer.axis = .vertical
authrMetaContainer.spacing = 4
authorContainerView.addArrangedSubview(authrMetaContainer)
// authorPrimaryContainer: H - [ authorNameLabel | notificationTypeIndicatorLabel | (padding) | menuButton ]
let authorPrimaryContainer = UIStackView()
authorPrimaryContainer.axis = .horizontal
authrMetaContainer.addArrangedSubview(authorPrimaryContainer)
authorPrimaryContainer.addArrangedSubview(authorNameLabel)
authorPrimaryContainer.addArrangedSubview(notificationTypeIndicatorLabel)
authorPrimaryContainer.addArrangedSubview(UIView())
authorPrimaryContainer.addArrangedSubview(menuButton)
authorNameLabel.setContentHuggingPriority(.required - 10, for: .horizontal)
authorNameLabel.setContentCompressionResistancePriority(.required - 10, for: .horizontal)
notificationTypeIndicatorLabel.setContentHuggingPriority(.required - 4, for: .horizontal)
notificationTypeIndicatorLabel.setContentCompressionResistancePriority(.required - 4, for: .horizontal)
menuButton.setContentHuggingPriority(.required - 5, for: .horizontal)
menuButton.setContentCompressionResistancePriority(.required - 5, for: .horizontal)
// authorSecondaryMetaContainer: H - [ authorUsername | (padding) ]
let authorSecondaryMetaContainer = UIStackView()
authorSecondaryMetaContainer.axis = .horizontal
authorSecondaryMetaContainer.spacing = 4
authrMetaContainer.addArrangedSubview(authorSecondaryMetaContainer)
authrMetaContainer.setCustomSpacing(4, after: authorSecondaryMetaContainer)
authorSecondaryMetaContainer.addArrangedSubview(authorUsernameLabel)
authorUsernameLabel.setContentHuggingPriority(.required - 8, for: .horizontal)
authorUsernameLabel.setContentCompressionResistancePriority(.required - 8, for: .horizontal)
authorSecondaryMetaContainer.addArrangedSubview(usernameTrialingDotLabel)
usernameTrialingDotLabel.setContentHuggingPriority(.required - 2, for: .horizontal)
usernameTrialingDotLabel.setContentCompressionResistancePriority(.required - 2, for: .horizontal)
authorSecondaryMetaContainer.addArrangedSubview(dateLabel)
dateLabel.setContentHuggingPriority(.required - 1, for: .horizontal)
dateLabel.setContentCompressionResistancePriority(.required - 1, for: .horizontal)
authorSecondaryMetaContainer.addArrangedSubview(UIView())
// authorContainerViewBottomPaddingView
authorContainerViewBottomPaddingView.translatesAutoresizingMaskIntoConstraints = false
containerStackView.addArrangedSubview(authorContainerViewBottomPaddingView)
NSLayoutConstraint.activate([
authorContainerViewBottomPaddingView.heightAnchor.constraint(equalToConstant: 16).priority(.required - 1),
])
authorContainerViewBottomPaddingView.isHidden = true
// follow reqeust
followRequestAdaptiveMarginContainerView.contentView = followRequestContainerView
followRequestAdaptiveMarginContainerView.margin = StatusView.containerLayoutMargin
containerStackView.addArrangedSubview(followRequestAdaptiveMarginContainerView)
acceptFollowRequestButton.translatesAutoresizingMaskIntoConstraints = false
acceptFollowRequestButtonShadowBackgroundContainer.addSubview(acceptFollowRequestButton)
acceptFollowRequestButton.pinToParent()
rejectFollowRequestButton.translatesAutoresizingMaskIntoConstraints = false
rejectFollowRequestButtonShadowBackgroundContainer.addSubview(rejectFollowRequestButton)
rejectFollowRequestButton.pinToParent()
followRequestContainerView.axis = .horizontal
followRequestContainerView.distribution = .fillEqually
followRequestContainerView.spacing = 16
followRequestContainerView.isLayoutMarginsRelativeArrangement = true
followRequestContainerView.layoutMargins = UIEdgeInsets(top: 0, left: 0, bottom: 16, right: 0) // set bottom padding
followRequestContainerView.addArrangedSubview(acceptFollowRequestButtonShadowBackgroundContainer)
followRequestContainerView.addArrangedSubview(rejectFollowRequestButtonShadowBackgroundContainer)
followRequestAdaptiveMarginContainerView.isHidden = true
acceptFollowRequestActivityIndicatorView.translatesAutoresizingMaskIntoConstraints = false
acceptFollowRequestButton.addSubview(acceptFollowRequestActivityIndicatorView)
NSLayoutConstraint.activate([
acceptFollowRequestActivityIndicatorView.centerXAnchor.constraint(equalTo: acceptFollowRequestButton.centerXAnchor),
acceptFollowRequestActivityIndicatorView.centerYAnchor.constraint(equalTo: acceptFollowRequestButton.centerYAnchor),
])
acceptFollowRequestActivityIndicatorView.color = .white
acceptFollowRequestActivityIndicatorView.hidesWhenStopped = true
acceptFollowRequestActivityIndicatorView.stopAnimating()
rejectFollowRequestActivityIndicatorView.translatesAutoresizingMaskIntoConstraints = false
rejectFollowRequestButton.addSubview(rejectFollowRequestActivityIndicatorView)
NSLayoutConstraint.activate([
rejectFollowRequestActivityIndicatorView.centerXAnchor.constraint(equalTo: rejectFollowRequestButton.centerXAnchor),
rejectFollowRequestActivityIndicatorView.centerYAnchor.constraint(equalTo: rejectFollowRequestButton.centerYAnchor),
])
rejectFollowRequestActivityIndicatorView.color = .black
acceptFollowRequestActivityIndicatorView.hidesWhenStopped = true
rejectFollowRequestActivityIndicatorView.stopAnimating()
// statusView
containerStackView.addArrangedSubview(statusView)
statusView.setup(style: .notification)
// quoteStatusView
containerStackView.addArrangedSubview(quoteStatusViewContainerView)
quoteStatusViewContainerView.layoutMargins = UIEdgeInsets(top: 0, left: 0, bottom: 16, right: 0)
quoteBackgroundView.layoutMargins = UIEdgeInsets(top: 16, left: 0, bottom: 0, right: 0)
quoteBackgroundView.translatesAutoresizingMaskIntoConstraints = false
quoteStatusViewContainerView.addSubview(quoteBackgroundView)
NSLayoutConstraint.activate([
quoteBackgroundView.topAnchor.constraint(equalTo: quoteStatusViewContainerView.layoutMarginsGuide.topAnchor),
quoteBackgroundView.leadingAnchor.constraint(equalTo: quoteStatusViewContainerView.layoutMarginsGuide.leadingAnchor),
quoteBackgroundView.trailingAnchor.constraint(equalTo: quoteStatusViewContainerView.layoutMarginsGuide.trailingAnchor),
quoteBackgroundView.bottomAnchor.constraint(equalTo: quoteStatusViewContainerView.layoutMarginsGuide.bottomAnchor),
])
quoteBackgroundView.backgroundColor = .secondarySystemBackground
quoteBackgroundView.layer.masksToBounds = true
quoteBackgroundView.layer.cornerCurve = .continuous
quoteBackgroundView.layer.cornerRadius = 8
quoteBackgroundView.layer.borderWidth = 1
quoteBackgroundView.layer.borderColor = UIColor.separator.cgColor
quoteStatusView.translatesAutoresizingMaskIntoConstraints = false
quoteBackgroundView.addSubview(quoteStatusView)
NSLayoutConstraint.activate([
quoteStatusView.topAnchor.constraint(equalTo: quoteBackgroundView.layoutMarginsGuide.topAnchor),
quoteStatusView.leadingAnchor.constraint(equalTo: quoteBackgroundView.layoutMarginsGuide.leadingAnchor),
quoteStatusView.trailingAnchor.constraint(equalTo: quoteBackgroundView.layoutMarginsGuide.trailingAnchor),
quoteStatusView.bottomAnchor.constraint(equalTo: quoteBackgroundView.layoutMarginsGuide.bottomAnchor),
])
quoteStatusView.setup(style: .notificationQuote)
statusView.isHidden = true
quoteStatusViewContainerView.isHidden = true
authorNameLabel.isUserInteractionEnabled = false
authorUsernameLabel.isUserInteractionEnabled = false
notificationTypeIndicatorLabel.isUserInteractionEnabled = false
avatarButton.addTarget(self, action: #selector(NotificationView.avatarButtonDidPressed(_:)), for: .touchUpInside)
statusView.delegate = self
quoteStatusView.delegate = self
isAccessibilityElement = true
}
}
extension NotificationView {
public override var accessibilityElements: [Any]? {
get { [] }
set {}
}
public override var accessibilityCustomActions: [UIAccessibilityCustomAction]? {
get {
var actions = notificationActions
actions += authorActions
if !statusView.isHidden {
actions += statusView.accessibilityCustomActions ?? []
}
if !quoteStatusViewContainerView.isHidden {
actions += quoteStatusView.accessibilityCustomActions ?? []
}
return actions
}
set {}
}
}
extension NotificationView {
@objc private func avatarButtonDidPressed(_ sender: UIButton) {
logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)")
delegate?.notificationView(self, authorAvatarButtonDidPressed: avatarButton)
}
@objc private func acceptFollowRequestButtonDidPressed(_ sender: UIButton) {
logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)")
delegate?.notificationView(self, acceptFollowRequestButtonDidPressed: sender)
}
@objc private func rejectFollowRequestButtonDidPressed(_ sender: UIButton) {
logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)")
delegate?.notificationView(self, rejectFollowRequestButtonDidPressed: sender)
}
}
extension NotificationView {
public func setAuthorContainerBottomPaddingViewDisplay() {
authorContainerViewBottomPaddingView.isHidden = false
}
public func setFollowRequestAdaptiveMarginContainerViewDisplay() {
followRequestAdaptiveMarginContainerView.isHidden = false
}
public func setStatusViewDisplay() {
statusView.isHidden = false
}
public func setQuoteStatusViewDisplay() {
quoteStatusViewContainerView.isHidden = false
}
}
// MARK: - AdaptiveContainerView
extension NotificationView: AdaptiveContainerView {
public func updateContainerViewComponentsLayoutMarginsRelativeArrangementBehavior(isEnabled: Bool) {
let margin = isEnabled ? StatusView.containerLayoutMargin : .zero
authorAdaptiveMarginContainerView.margin = margin
quoteStatusViewContainerView.layoutMargins.left = margin
quoteStatusViewContainerView.layoutMargins.right = margin
statusView.updateContainerViewComponentsLayoutMarginsRelativeArrangementBehavior(isEnabled: isEnabled)
quoteStatusView.updateContainerViewComponentsLayoutMarginsRelativeArrangementBehavior(isEnabled: true) // always set margins
}
}
extension NotificationView {
public typealias AuthorMenuContext = StatusAuthorView.AuthorMenuContext
public func setupAuthorMenu(menuContext: AuthorMenuContext) -> (UIMenu, [UIAccessibilityCustomAction]) {
var actions: [MastodonMenu.Action] = []
actions = [
.muteUser(.init(
name: menuContext.name,
isMuting: menuContext.isMuting
)),
.blockUser(.init(
name: menuContext.name,
isBlocking: menuContext.isBlocking
)),
.reportUser(
.init(name: menuContext.name)
),
]
if menuContext.isMyself {
actions.append(.deleteStatus)
}
let menu = MastodonMenu.setupMenu(
actions: actions,
delegate: self
)
let accessibilityActions = MastodonMenu.setupAccessibilityActions(
actions: actions,
delegate: self
)
return (menu, accessibilityActions)
}
}
// MARK: - StatusViewDelegate
extension NotificationView: StatusViewDelegate {
public func statusView(_ statusView: StatusView, didTapCardWithURL url: URL) {
assertionFailure()
}
public func statusView(_ statusView: StatusView, headerDidPressed header: UIView) {
// do nothing
}
public func statusView(_ statusView: StatusView, authorAvatarButtonDidPressed button: AvatarButton) {
switch statusView {
case self.statusView:
assertionFailure()
case quoteStatusView:
delegate?.notificationView(self, quoteStatusView: statusView, authorAvatarButtonDidPressed: button)
default:
assertionFailure()
}
}
public func statusView(_ statusView: StatusView, contentSensitiveeToggleButtonDidPressed button: UIButton) {
assertionFailure()
}
public func statusView(_ statusView: StatusView, metaText: MetaText, didSelectMeta meta: Meta) {
switch statusView {
case self.statusView:
delegate?.notificationView(self, statusView: statusView, metaText: metaText, didSelectMeta: meta)
case quoteStatusView:
delegate?.notificationView(self, quoteStatusView: statusView, metaText: metaText, didSelectMeta: meta)
default:
assertionFailure()
}
}
public func statusView(_ statusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaView: MediaView, didSelectMediaViewAt index: Int) {
switch statusView {
case self.statusView:
delegate?.notificationView(self, statusView: statusView, mediaGridContainerView: mediaGridContainerView, mediaView: mediaView, didSelectMediaViewAt: index)
case quoteStatusView:
delegate?.notificationView(self, quoteStatusView: statusView, mediaGridContainerView: mediaGridContainerView, mediaView: mediaView, didSelectMediaViewAt: index)
default:
assertionFailure()
}
}
public func statusView(_ statusView: StatusView, pollTableView tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
assertionFailure()
}
public func statusView(_ statusView: StatusView, pollVoteButtonPressed button: UIButton) {
assertionFailure()
}
public func statusView(_ statusView: StatusView, actionToolbarContainer: ActionToolbarContainer, buttonDidPressed button: UIButton, action: ActionToolbarContainer.Action) {
switch statusView {
case self.statusView:
delegate?.notificationView(self, statusView: statusView, actionToolbarContainer: actionToolbarContainer, buttonDidPressed: button, action: action)
case quoteStatusView:
assertionFailure()
default:
assertionFailure()
}
}
public func statusView(_ statusView: StatusView, menuButton button: UIButton, didSelectAction action: MastodonMenu.Action) {
assertionFailure()
}
public func statusView(_ statusView: StatusView, spoilerOverlayViewDidPressed overlayView: SpoilerOverlayView) {
switch statusView {
case self.statusView:
delegate?.notificationView(self, statusView: statusView, spoilerOverlayViewDidPressed: overlayView)
case quoteStatusView:
delegate?.notificationView(self, quoteStatusView: statusView, spoilerOverlayViewDidPressed: overlayView)
default:
assertionFailure()
}
}
// public func statusView(_ statusView: StatusView, spoilerBannerViewDidPressed bannerView: SpoilerBannerView) {
// switch statusView {
// case self.statusView:
// delegate?.notificationView(self, statusView: statusView, spoilerBannerViewDidPressed: bannerView)
// case quoteStatusView:
// delegate?.notificationView(self, quoteStatusView: statusView, spoilerBannerViewDidPressed: bannerView)
// default:
// assertionFailure()
// }
// }
public func statusView(_ statusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaSensitiveButtonDidPressed button: UIButton) {
assertionFailure()
}
public func statusView(_ statusView: StatusView, statusMetricView: StatusMetricView, reblogButtonDidPressed button: UIButton) {
assertionFailure()
}
public func statusView(_ statusView: StatusView, statusMetricView: StatusMetricView, favoriteButtonDidPressed button: UIButton) {
assertionFailure()
}
public func statusView(_ statusView: StatusView, accessibilityActivate: Void) {
assertionFailure()
}
public func statusView(_ statusView: StatusView, cardControl: StatusCardControl, didTapURL url: URL) {
assertionFailure()
}
public func statusView(_ statusView: StatusView, cardControlMenu: StatusCardControl) -> UIMenu? {
assertionFailure()
return nil
}
}
// MARK: - MastodonMenuDelegate
extension NotificationView: MastodonMenuDelegate {
public func menuAction(_ action: MastodonMenu.Action) {
logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)")
delegate?.notificationView(self, menuButton: menuButton, didSelectAction: action)
}
}