fix: make link works in notification scene

This commit is contained in:
CMK 2021-07-01 18:57:05 +08:00
parent 205cc39af3
commit bdf5a7e859
10 changed files with 113 additions and 200 deletions

View File

@ -296,6 +296,7 @@
DB6180F626391D580018D199 /* MediaPreviewableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180F526391D580018D199 /* MediaPreviewableViewController.swift */; }; DB6180F626391D580018D199 /* MediaPreviewableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180F526391D580018D199 /* MediaPreviewableViewController.swift */; };
DB6180F826391D660018D199 /* MediaPreviewingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180F726391D660018D199 /* MediaPreviewingViewController.swift */; }; DB6180F826391D660018D199 /* MediaPreviewingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180F726391D660018D199 /* MediaPreviewingViewController.swift */; };
DB6180FA26391F2E0018D199 /* MediaPreviewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180F926391F2E0018D199 /* MediaPreviewViewModel.swift */; }; DB6180FA26391F2E0018D199 /* MediaPreviewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180F926391F2E0018D199 /* MediaPreviewViewModel.swift */; };
DB63BE7F268DD1070011D3F9 /* NotificationViewController+StatusProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB63BE7E268DD1070011D3F9 /* NotificationViewController+StatusProvider.swift */; };
DB66728C25F9F8DC00D60309 /* ComposeViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB66728B25F9F8DC00D60309 /* ComposeViewModel+Diffable.swift */; }; DB66728C25F9F8DC00D60309 /* ComposeViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB66728B25F9F8DC00D60309 /* ComposeViewModel+Diffable.swift */; };
DB66729625F9F91600D60309 /* ComposeStatusSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB66729525F9F91600D60309 /* ComposeStatusSection.swift */; }; DB66729625F9F91600D60309 /* ComposeStatusSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB66729525F9F91600D60309 /* ComposeStatusSection.swift */; };
DB66729C25F9F91F00D60309 /* ComposeStatusItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB66729B25F9F91F00D60309 /* ComposeStatusItem.swift */; }; DB66729C25F9F91F00D60309 /* ComposeStatusItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB66729B25F9F91F00D60309 /* ComposeStatusItem.swift */; };
@ -921,6 +922,7 @@
DB6180F526391D580018D199 /* MediaPreviewableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewableViewController.swift; sourceTree = "<group>"; }; DB6180F526391D580018D199 /* MediaPreviewableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewableViewController.swift; sourceTree = "<group>"; };
DB6180F726391D660018D199 /* MediaPreviewingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewingViewController.swift; sourceTree = "<group>"; }; DB6180F726391D660018D199 /* MediaPreviewingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewingViewController.swift; sourceTree = "<group>"; };
DB6180F926391F2E0018D199 /* MediaPreviewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewViewModel.swift; sourceTree = "<group>"; }; DB6180F926391F2E0018D199 /* MediaPreviewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewViewModel.swift; sourceTree = "<group>"; };
DB63BE7E268DD1070011D3F9 /* NotificationViewController+StatusProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NotificationViewController+StatusProvider.swift"; sourceTree = "<group>"; };
DB66728B25F9F8DC00D60309 /* ComposeViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ComposeViewModel+Diffable.swift"; sourceTree = "<group>"; }; DB66728B25F9F8DC00D60309 /* ComposeViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ComposeViewModel+Diffable.swift"; sourceTree = "<group>"; };
DB66729525F9F91600D60309 /* ComposeStatusSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusSection.swift; sourceTree = "<group>"; }; DB66729525F9F91600D60309 /* ComposeStatusSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusSection.swift; sourceTree = "<group>"; };
DB66729B25F9F91F00D60309 /* ComposeStatusItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusItem.swift; sourceTree = "<group>"; }; DB66729B25F9F91F00D60309 /* ComposeStatusItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusItem.swift; sourceTree = "<group>"; };
@ -2369,6 +2371,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
DB9D6BF725E4F5690051B173 /* NotificationViewController.swift */, DB9D6BF725E4F5690051B173 /* NotificationViewController.swift */,
DB63BE7E268DD1070011D3F9 /* NotificationViewController+StatusProvider.swift */,
2D607AD726242FC500B70763 /* NotificationViewModel.swift */, 2D607AD726242FC500B70763 /* NotificationViewModel.swift */,
2D084B8C26258EA3003AA3AF /* NotificationViewModel+Diffable.swift */, 2D084B8C26258EA3003AA3AF /* NotificationViewModel+Diffable.swift */,
2D084B9226259545003AA3AF /* NotificationViewModel+LoadLatestState.swift */, 2D084B9226259545003AA3AF /* NotificationViewModel+LoadLatestState.swift */,
@ -3177,6 +3180,7 @@
2D38F1F125CD477D00561493 /* HomeTimelineViewModel+LoadMiddleState.swift in Sources */, 2D38F1F125CD477D00561493 /* HomeTimelineViewModel+LoadMiddleState.swift in Sources */,
DB68A06325E905E000CFDF14 /* UIApplication.swift in Sources */, DB68A06325E905E000CFDF14 /* UIApplication.swift in Sources */,
DB02CDAB26256A9500D0A2AF /* ThreadReplyLoaderTableViewCell.swift in Sources */, DB02CDAB26256A9500D0A2AF /* ThreadReplyLoaderTableViewCell.swift in Sources */,
DB63BE7F268DD1070011D3F9 /* NotificationViewController+StatusProvider.swift in Sources */,
DBB5255E2611F07A002F1F29 /* ProfileViewModel.swift in Sources */, DBB5255E2611F07A002F1F29 /* ProfileViewModel.swift in Sources */,
DBAC648F267DC84D007FE9FD /* TableNodeDiffableDataSource.swift in Sources */, DBAC648F267DC84D007FE9FD /* TableNodeDiffableDataSource.swift in Sources */,
2D8434FB25FF46B300EECE90 /* HomeTimelineNavigationBarTitleView.swift in Sources */, 2D8434FB25FF46B300EECE90 /* HomeTimelineNavigationBarTitleView.swift in Sources */,

View File

@ -12,7 +12,7 @@
<key>CoreDataStack.xcscheme_^#shared#^_</key> <key>CoreDataStack.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>21</integer> <integer>27</integer>
</dict> </dict>
<key>Mastodon - ASDK.xcscheme_^#shared#^_</key> <key>Mastodon - ASDK.xcscheme_^#shared#^_</key>
<dict> <dict>
@ -37,7 +37,7 @@
<key>NotificationService.xcscheme_^#shared#^_</key> <key>NotificationService.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>20</integer> <integer>21</integer>
</dict> </dict>
</dict> </dict>
<key>SuppressBuildableAutocreation</key> <key>SuppressBuildableAutocreation</key>

View File

@ -60,7 +60,7 @@ extension NotificationSection {
statusItemAttribute: attribute statusItemAttribute: attribute
) )
cell.actionImageBackground.backgroundColor = color cell.actionImageBackground.backgroundColor = color
cell.nameLabel.text = notification.account.displayName.isEmpty ? notification.account.username : notification.account.displayName cell.nameLabel.configure(content: notification.account.displayNameWithFallback, emojiDict: notification.account.emojiDict)
cell.actionLabel.text = actionText + " · " + timeText cell.actionLabel.text = actionText + " · " + timeText
timestampUpdatePublisher timestampUpdatePublisher
.sink { [weak cell] _ in .sink { [weak cell] _ in
@ -109,15 +109,15 @@ extension NotificationSection {
.store(in: &cell.disposeBag) .store(in: &cell.disposeBag)
cell.actionImageBackground.backgroundColor = color cell.actionImageBackground.backgroundColor = color
cell.actionLabel.text = actionText + " · " + timeText cell.actionLabel.text = actionText + " · " + timeText
cell.nameLabel.text = notification.account.displayName.isEmpty ? notification.account.username : notification.account.displayName cell.nameLabel.configure(content: notification.account.displayNameWithFallback, emojiDict: notification.account.emojiDict)
if let url = notification.account.avatarImageURL() { if let url = notification.account.avatarImageURL() {
cell.avatatImageView.af.setImage( cell.avatarImageView.af.setImage(
withURL: url, withURL: url,
placeholderImage: UIImage.placeholder(color: .systemFill), placeholderImage: UIImage.placeholder(color: .systemFill),
imageTransition: .crossDissolve(0.2) imageTransition: .crossDissolve(0.2)
) )
} }
cell.avatatImageView.gesture().sink { [weak cell] _ in cell.avatarImageView.gesture().sink { [weak cell] _ in
cell?.delegate?.userAvatarDidPressed(notification: notification) cell?.delegate?.userAvatarDidPressed(notification: notification)
} }
.store(in: &cell.disposeBag) .store(in: &cell.disposeBag)

View File

@ -523,32 +523,6 @@ extension StatusProviderFacade {
extension StatusProviderFacade { extension StatusProviderFacade {
static func responseToStatusContentWarningRevealAction(dependency: NotificationViewController, cell: UITableViewCell) {
let status = Future<Status?, Never> { promise in
guard let diffableDataSource = dependency.viewModel.diffableDataSource,
let indexPath = dependency.tableView.indexPath(for: cell),
let item = diffableDataSource.itemIdentifier(for: indexPath) else {
promise(.success(nil))
return
}
switch item {
case .notification(let objectID, _):
dependency.viewModel.fetchedResultsController.managedObjectContext.perform {
let notification = dependency.viewModel.fetchedResultsController.managedObjectContext.object(with: objectID) as! MastodonNotification
promise(.success(notification.status))
}
default:
promise(.success(nil))
}
}
_responseToStatusContentWarningRevealAction(
dependency: dependency,
status: status
)
}
static func responseToStatusContentWarningRevealAction(provider: StatusProvider, cell: UITableViewCell) { static func responseToStatusContentWarningRevealAction(provider: StatusProvider, cell: UITableViewCell) {
_responseToStatusContentWarningRevealAction( _responseToStatusContentWarningRevealAction(
dependency: provider, dependency: provider,

View File

@ -12,7 +12,7 @@ final class AutoCompleteTableViewCell: UITableViewCell {
static let avatarImageSize = CGSize(width: 42, height: 42) static let avatarImageSize = CGSize(width: 42, height: 42)
static let avatarImageCornerRadius: CGFloat = 4 static let avatarImageCornerRadius: CGFloat = 4
static let avatarToLabelSpacing: CGFloat = 12 static let avatarToLabelSpacing: CGFloat = 12
let containerStackView: UIStackView = { let containerStackView: UIStackView = {
let stackView = UIStackView() let stackView = UIStackView()
stackView.axis = .horizontal stackView.axis = .horizontal
@ -47,12 +47,6 @@ final class AutoCompleteTableViewCell: UITableViewCell {
let separatorLine = UIView.separatorLine let separatorLine = UIView.separatorLine
override func prepareForReuse() {
super.prepareForReuse()
avatarImageView.af.cancelImageRequest()
avatarImageView.kf.cancelDownloadTask()
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier) super.init(style: style, reuseIdentifier: reuseIdentifier)
_init() _init()

View File

@ -9,12 +9,11 @@ import os.log
import UIKit import UIKit
import Combine import Combine
import PhotosUI import PhotosUI
import Kingfisher
import MastodonSDK import MastodonSDK
import TwitterTextEditor
import MetaTextView import MetaTextView
import MastodonMeta import MastodonMeta
import Meta import Meta
import Nuke
final class ComposeViewController: UIViewController, NeedsDependency { final class ComposeViewController: UIViewController, NeedsDependency {
@ -788,147 +787,6 @@ extension ComposeViewController: UITextViewDelegate {
} }
// MARK: - TextEditorViewTextAttributesDelegate
extension ComposeViewController: TextEditorViewTextAttributesDelegate {
func textEditorView(
_ textEditorView: TextEditorView,
updateAttributedString attributedString: NSAttributedString,
completion: @escaping (NSAttributedString?) -> Void
) {
// FIXME: needs O(1) update completion to fix performance issue
DispatchQueue.global().async {
let string = attributedString.string
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: update: %s", ((#file as NSString).lastPathComponent), #line, #function, string)
let stringRange = NSRange(location: 0, length: string.length)
let highlightMatches = string.matches(pattern: MastodonRegex.highlightPattern)
let emojiMatches = string.matches(pattern: MastodonRegex.emojiPattern)
// only accept http/https scheme
let urlMatches = string.matches(pattern: "(?i)https?://\\S+(?:/|\\b)")
DispatchQueue.main.async { [weak self] in
guard let self = self else {
completion(nil)
return
}
let customEmojiViewModel = self.viewModel.customEmojiViewModel.value
for view in self.suffixedAttachmentViews {
view.removeFromSuperview()
}
self.suffixedAttachmentViews.removeAll()
// set normal appearance
let attributedString = NSMutableAttributedString(attributedString: attributedString)
attributedString.removeAttribute(.suffixedAttachment, range: stringRange)
attributedString.removeAttribute(.underlineStyle, range: stringRange)
attributedString.addAttribute(.foregroundColor, value: Asset.Colors.Label.primary.color, range: stringRange)
attributedString.addAttribute(.font, value: UIFont.preferredFont(forTextStyle: .body), range: stringRange)
// hashtag
for match in highlightMatches {
// set highlight
var attributes = [NSAttributedString.Key: Any]()
attributes[.foregroundColor] = Asset.Colors.brandBlue.color
// See `traitCollectionDidChange(_:)`
// set accessibility
if #available(iOS 13.0, *) {
switch self.traitCollection.accessibilityContrast {
case .high:
attributes[.underlineStyle] = NSUnderlineStyle.single.rawValue
default:
break
}
}
attributedString.addAttributes(attributes, range: match.range)
}
// emoji
if let customEmojiViewModel = customEmojiViewModel, !customEmojiViewModel.emojiDict.value.isEmpty {
for match in emojiMatches {
guard let name = string.substring(with: match, at: 2) else { continue }
guard let emoji = customEmojiViewModel.emoji(shortcode: name) else { continue }
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: handle emoji: %s", ((#file as NSString).lastPathComponent), #line, #function, name)
// set emoji token invisible (without upper bounce space)
var attributes = [NSAttributedString.Key: Any]()
attributes[.font] = UIFont.systemFont(ofSize: 0.01)
attributedString.addAttributes(attributes, range: match.range)
// append emoji attachment
let imageViewSize = CGSize(width: 20, height: 20)
let imageView = UIImageView(frame: CGRect(origin: .zero, size: imageViewSize))
textEditorView.textContentView.addSubview(imageView)
self.suffixedAttachmentViews.append(imageView)
let processor = DownsamplingImageProcessor(size: imageViewSize)
imageView.kf.setImage(
with: URL(string: emoji.url),
placeholder: UIImage.placeholder(size: imageViewSize, color: .systemFill),
options: [
.processor(processor),
.scaleFactor(textEditorView.traitCollection.displayScale),
], completionHandler: nil
)
let layoutInTextContainer = { [weak textEditorView] (view: UIView, frame: CGRect) in
// `textEditorView` retains `textStorage`, which retains this block as a part of attributes.
guard let textEditorView = textEditorView else {
return
}
let insets = textEditorView.textContentInsets
view.frame = frame.offsetBy(dx: insets.left, dy: insets.top)
}
let attachment = TextAttributes.SuffixedAttachment(
size: imageViewSize,
attachment: .view(view: imageView, layoutInTextContainer: layoutInTextContainer)
)
let index = match.range.upperBound - 1
attributedString.addAttribute(
.suffixedAttachment,
value: attachment,
range: NSRange(location: index, length: 1)
)
}
}
// url
for match in urlMatches {
guard let name = string.substring(with: match, at: 0) else { continue }
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: handle emoji: %s", ((#file as NSString).lastPathComponent), #line, #function, name)
// set highlight
var attributes = [NSAttributedString.Key: Any]()
attributes[.foregroundColor] = Asset.Colors.brandBlue.color
// See `traitCollectionDidChange(_:)`
// set accessibility
if #available(iOS 13.0, *) {
switch self.traitCollection.accessibilityContrast {
case .high:
attributes[.underlineStyle] = NSUnderlineStyle.single.rawValue
default:
break
}
}
attributedString.addAttributes(attributes, range: match.range)
}
if string.count > ComposeViewModel.composeContentLimit {
var attributes = [NSAttributedString.Key: Any]()
attributes[.foregroundColor] = Asset.Colors.danger.color
let boundStart = string.index(string.startIndex, offsetBy: ComposeViewModel.composeContentLimit)
let boundEnd = string.endIndex
let range = boundStart..<boundEnd
attributedString.addAttributes(attributes, range: NSRange(range, in: string))
}
completion(attributedString)
}
}
}
}
// MARK: - ComposeToolbarViewDelegate // MARK: - ComposeToolbarViewDelegate
extension ComposeViewController: ComposeToolbarViewDelegate { extension ComposeViewController: ComposeToolbarViewDelegate {

View File

@ -0,0 +1,65 @@
//
// NotificationViewController+StatusProvider.swift
// Mastodon
//
// Created by MainasuK Cirno on 2021-7-1.
//
import UIKit
import Combine
import CoreData
import CoreDataStack
extension NotificationViewController: StatusProvider {
func status() -> Future<Status?, Never> {
return Future<Status?, Never> { promise in
promise(.success(nil))
}
}
func status(for cell: UITableViewCell?, indexPath: IndexPath?) -> Future<Status?, Never> {
return Future<Status?, Never> { promise in
guard let cell = cell,
let diffableDataSource = self.viewModel.diffableDataSource,
let indexPath = self.tableView.indexPath(for: cell),
let item = diffableDataSource.itemIdentifier(for: indexPath) else {
promise(.success(nil))
return
}
switch item {
case .notification(let objectID, _):
self.viewModel.fetchedResultsController.managedObjectContext.perform {
let notification = self.viewModel.fetchedResultsController.managedObjectContext.object(with: objectID) as! MastodonNotification
promise(.success(notification.status))
}
default:
promise(.success(nil))
}
}
}
func status(for cell: UICollectionViewCell) -> Future<Status?, Never> {
return Future<Status?, Never> { promise in
promise(.success(nil))
}
}
var managedObjectContext: NSManagedObjectContext {
viewModel.fetchedResultsController.managedObjectContext
}
var tableViewDiffableDataSource: UITableViewDiffableDataSource<StatusSection, Item>? {
return nil
}
func item(for cell: UITableViewCell?, indexPath: IndexPath?) -> Item? {
return nil
}
func items(indexPaths: [IndexPath]) -> [Item] {
return []
}
}

View File

@ -12,6 +12,8 @@ import GameplayKit
import MastodonSDK import MastodonSDK
import OSLog import OSLog
import UIKit import UIKit
import Meta
import MetaTextView
final class NotificationViewController: UIViewController, NeedsDependency { final class NotificationViewController: UIViewController, NeedsDependency {
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } } weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
@ -271,6 +273,7 @@ extension NotificationViewController: ContentOffsetAdjustableTimelineViewControl
// MARK: - NotificationTableViewCellDelegate // MARK: - NotificationTableViewCellDelegate
extension NotificationViewController: NotificationTableViewCellDelegate { extension NotificationViewController: NotificationTableViewCellDelegate {
func notificationTableViewCell(_ cell: NotificationTableViewCell, notification: MastodonNotification, acceptButtonDidPressed button: UIButton) { func notificationTableViewCell(_ cell: NotificationTableViewCell, notification: MastodonNotification, acceptButtonDidPressed button: UIButton) {
viewModel.acceptFollowRequest(notification: notification) viewModel.acceptFollowRequest(notification: notification)
} }
@ -286,20 +289,31 @@ extension NotificationViewController: NotificationTableViewCellDelegate {
} }
} }
func userNameLabelDidPressed(notification: MastodonNotification) {
let viewModel = CachedProfileViewModel(context: context, mastodonUser: notification.account)
DispatchQueue.main.async {
self.coordinator.present(scene: .profile(viewModel: viewModel), from: self, transition: .show)
}
}
func parent() -> UIViewController { func parent() -> UIViewController {
self self
} }
func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, statusView: StatusView, revealContentWarningButtonDidPressed button: UIButton) { func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, statusView: StatusView, revealContentWarningButtonDidPressed button: UIButton) {
StatusProviderFacade.responseToStatusContentWarningRevealAction(dependency: self, cell: cell) StatusProviderFacade.responseToStatusContentWarningRevealAction(provider: self, cell: cell)
} }
func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, statusView: StatusView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView) { func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, statusView: StatusView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView) {
StatusProviderFacade.responseToStatusContentWarningRevealAction(dependency: self, cell: cell) StatusProviderFacade.responseToStatusContentWarningRevealAction(provider: self, cell: cell)
} }
func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, statusView: StatusView, playerContainerView: PlayerContainerView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView) { func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, statusView: StatusView, playerContainerView: PlayerContainerView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView) {
StatusProviderFacade.responseToStatusContentWarningRevealAction(dependency: self, cell: cell) StatusProviderFacade.responseToStatusContentWarningRevealAction(provider: self, cell: cell)
}
func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, statusView: StatusView, metaText: MetaText, didSelectMeta meta: Meta) {
StatusProviderFacade.responseToStatusMetaTextAction(provider: self, cell: cell, metaText: metaText, didSelectMeta: meta)
} }
} }

View File

@ -57,8 +57,8 @@ final class NotificationStatusTableViewCell: UITableViewCell, StatusCell {
return label return label
}() }()
let nameLabel: UILabel = { let nameLabel: ActiveLabel = {
let label = UILabel() let label = ActiveLabel(style: .statusName)
label.textColor = Asset.Colors.brandBlue.color label.textColor = Asset.Colors.brandBlue.color
label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .semibold), maximumPointSize: 20) label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .semibold), maximumPointSize: 20)
label.lineBreakMode = .byTruncatingTail label.lineBreakMode = .byTruncatingTail
@ -259,7 +259,7 @@ extension NotificationStatusTableViewCell: StatusViewDelegate {
} }
func statusView(_ statusView: StatusView, metaText: MetaText, didSelectMeta meta: Meta) { func statusView(_ statusView: StatusView, metaText: MetaText, didSelectMeta meta: Meta) {
// do nothing delegate?.notificationStatusTableViewCell(self, statusView: statusView, metaText: metaText, didSelectMeta: meta)
} }
} }

View File

@ -9,6 +9,9 @@ import Combine
import CoreDataStack import CoreDataStack
import Foundation import Foundation
import UIKit import UIKit
import Meta
import MetaTextView
import ActiveLabel
protocol NotificationTableViewCellDelegate: AnyObject { protocol NotificationTableViewCellDelegate: AnyObject {
var context: AppContext! { get } var context: AppContext! { get }
@ -16,13 +19,14 @@ protocol NotificationTableViewCellDelegate: AnyObject {
func parent() -> UIViewController func parent() -> UIViewController
func userAvatarDidPressed(notification: MastodonNotification) func userAvatarDidPressed(notification: MastodonNotification)
func userNameLabelDidPressed(notification: MastodonNotification)
func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, statusView: StatusView, revealContentWarningButtonDidPressed button: UIButton) func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, statusView: StatusView, revealContentWarningButtonDidPressed button: UIButton)
func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, statusView: StatusView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView) func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, statusView: StatusView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView)
func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, statusView: StatusView, playerContainerView: PlayerContainerView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView) func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, statusView: StatusView, playerContainerView: PlayerContainerView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView)
func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, statusView: StatusView, metaText: MetaText, didSelectMeta meta: Meta)
func notificationTableViewCell(_ cell: NotificationTableViewCell, notification: MastodonNotification, acceptButtonDidPressed button: UIButton) func notificationTableViewCell(_ cell: NotificationTableViewCell, notification: MastodonNotification, acceptButtonDidPressed button: UIButton)
func notificationTableViewCell(_ cell: NotificationTableViewCell, notification: MastodonNotification, rejectButtonDidPressed button: UIButton) func notificationTableViewCell(_ cell: NotificationTableViewCell, notification: MastodonNotification, rejectButtonDidPressed button: UIButton)
} }
@ -34,7 +38,7 @@ final class NotificationTableViewCell: UITableViewCell {
var delegate: NotificationTableViewCellDelegate? var delegate: NotificationTableViewCellDelegate?
let avatatImageView: UIImageView = { let avatarImageView: UIImageView = {
let imageView = UIImageView() let imageView = UIImageView()
imageView.layer.cornerRadius = 4 imageView.layer.cornerRadius = 4
imageView.layer.cornerCurve = .continuous imageView.layer.cornerCurve = .continuous
@ -72,8 +76,8 @@ final class NotificationTableViewCell: UITableViewCell {
return label return label
}() }()
let nameLabel: UILabel = { let nameLabel: ActiveLabel = {
let label = UILabel() let label = ActiveLabel()
label.textColor = Asset.Colors.brandBlue.color label.textColor = Asset.Colors.brandBlue.color
label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .semibold), maximumPointSize: 20) label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .semibold), maximumPointSize: 20)
label.lineBreakMode = .byTruncatingTail label.lineBreakMode = .byTruncatingTail
@ -108,7 +112,7 @@ final class NotificationTableViewCell: UITableViewCell {
override func prepareForReuse() { override func prepareForReuse() {
super.prepareForReuse() super.prepareForReuse()
avatatImageView.af.cancelImageRequest() avatarImageView.af.cancelImageRequest()
disposeBag.removeAll() disposeBag.removeAll()
} }
@ -153,13 +157,13 @@ extension NotificationTableViewCell {
avatarContainer.widthAnchor.constraint(equalToConstant: 47).priority(.required - 1) avatarContainer.widthAnchor.constraint(equalToConstant: 47).priority(.required - 1)
]) ])
avatarContainer.addSubview(avatatImageView) avatarContainer.addSubview(avatarImageView)
avatatImageView.translatesAutoresizingMaskIntoConstraints = false avatarImageView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
avatatImageView.heightAnchor.constraint(equalToConstant: 35).priority(.required - 1), avatarImageView.heightAnchor.constraint(equalToConstant: 35).priority(.required - 1),
avatatImageView.widthAnchor.constraint(equalToConstant: 35).priority(.required - 1), avatarImageView.widthAnchor.constraint(equalToConstant: 35).priority(.required - 1),
avatatImageView.topAnchor.constraint(equalTo: avatarContainer.topAnchor), avatarImageView.topAnchor.constraint(equalTo: avatarContainer.topAnchor),
avatatImageView.leadingAnchor.constraint(equalTo: avatarContainer.leadingAnchor) avatarImageView.leadingAnchor.constraint(equalTo: avatarContainer.leadingAnchor)
]) ])
avatarContainer.addSubview(actionImageBackground) avatarContainer.addSubview(actionImageBackground)