fix: make link works in notification scene
This commit is contained in:
parent
205cc39af3
commit
bdf5a7e859
|
@ -296,6 +296,7 @@
|
|||
DB6180F626391D580018D199 /* MediaPreviewableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180F526391D580018D199 /* MediaPreviewableViewController.swift */; };
|
||||
DB6180F826391D660018D199 /* MediaPreviewingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180F726391D660018D199 /* MediaPreviewingViewController.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 */; };
|
||||
DB66729625F9F91600D60309 /* ComposeStatusSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB66729525F9F91600D60309 /* ComposeStatusSection.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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -2369,6 +2371,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
DB9D6BF725E4F5690051B173 /* NotificationViewController.swift */,
|
||||
DB63BE7E268DD1070011D3F9 /* NotificationViewController+StatusProvider.swift */,
|
||||
2D607AD726242FC500B70763 /* NotificationViewModel.swift */,
|
||||
2D084B8C26258EA3003AA3AF /* NotificationViewModel+Diffable.swift */,
|
||||
2D084B9226259545003AA3AF /* NotificationViewModel+LoadLatestState.swift */,
|
||||
|
@ -3177,6 +3180,7 @@
|
|||
2D38F1F125CD477D00561493 /* HomeTimelineViewModel+LoadMiddleState.swift in Sources */,
|
||||
DB68A06325E905E000CFDF14 /* UIApplication.swift in Sources */,
|
||||
DB02CDAB26256A9500D0A2AF /* ThreadReplyLoaderTableViewCell.swift in Sources */,
|
||||
DB63BE7F268DD1070011D3F9 /* NotificationViewController+StatusProvider.swift in Sources */,
|
||||
DBB5255E2611F07A002F1F29 /* ProfileViewModel.swift in Sources */,
|
||||
DBAC648F267DC84D007FE9FD /* TableNodeDiffableDataSource.swift in Sources */,
|
||||
2D8434FB25FF46B300EECE90 /* HomeTimelineNavigationBarTitleView.swift in Sources */,
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<key>CoreDataStack.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>21</integer>
|
||||
<integer>27</integer>
|
||||
</dict>
|
||||
<key>Mastodon - ASDK.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
|
@ -37,7 +37,7 @@
|
|||
<key>NotificationService.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>20</integer>
|
||||
<integer>21</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
|
|
|
@ -60,7 +60,7 @@ extension NotificationSection {
|
|||
statusItemAttribute: attribute
|
||||
)
|
||||
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
|
||||
timestampUpdatePublisher
|
||||
.sink { [weak cell] _ in
|
||||
|
@ -109,15 +109,15 @@ extension NotificationSection {
|
|||
.store(in: &cell.disposeBag)
|
||||
cell.actionImageBackground.backgroundColor = color
|
||||
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() {
|
||||
cell.avatatImageView.af.setImage(
|
||||
cell.avatarImageView.af.setImage(
|
||||
withURL: url,
|
||||
placeholderImage: UIImage.placeholder(color: .systemFill),
|
||||
imageTransition: .crossDissolve(0.2)
|
||||
)
|
||||
}
|
||||
cell.avatatImageView.gesture().sink { [weak cell] _ in
|
||||
cell.avatarImageView.gesture().sink { [weak cell] _ in
|
||||
cell?.delegate?.userAvatarDidPressed(notification: notification)
|
||||
}
|
||||
.store(in: &cell.disposeBag)
|
||||
|
|
|
@ -523,32 +523,6 @@ 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) {
|
||||
_responseToStatusContentWarningRevealAction(
|
||||
dependency: provider,
|
||||
|
|
|
@ -12,7 +12,7 @@ final class AutoCompleteTableViewCell: UITableViewCell {
|
|||
static let avatarImageSize = CGSize(width: 42, height: 42)
|
||||
static let avatarImageCornerRadius: CGFloat = 4
|
||||
static let avatarToLabelSpacing: CGFloat = 12
|
||||
|
||||
|
||||
let containerStackView: UIStackView = {
|
||||
let stackView = UIStackView()
|
||||
stackView.axis = .horizontal
|
||||
|
@ -47,12 +47,6 @@ final class AutoCompleteTableViewCell: UITableViewCell {
|
|||
|
||||
let separatorLine = UIView.separatorLine
|
||||
|
||||
override func prepareForReuse() {
|
||||
super.prepareForReuse()
|
||||
avatarImageView.af.cancelImageRequest()
|
||||
avatarImageView.kf.cancelDownloadTask()
|
||||
}
|
||||
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
_init()
|
||||
|
|
|
@ -9,12 +9,11 @@ import os.log
|
|||
import UIKit
|
||||
import Combine
|
||||
import PhotosUI
|
||||
import Kingfisher
|
||||
import MastodonSDK
|
||||
import TwitterTextEditor
|
||||
import MetaTextView
|
||||
import MastodonMeta
|
||||
import Meta
|
||||
import Nuke
|
||||
|
||||
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
|
||||
extension ComposeViewController: ComposeToolbarViewDelegate {
|
||||
|
||||
|
|
|
@ -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 []
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -12,6 +12,8 @@ import GameplayKit
|
|||
import MastodonSDK
|
||||
import OSLog
|
||||
import UIKit
|
||||
import Meta
|
||||
import MetaTextView
|
||||
|
||||
final class NotificationViewController: UIViewController, NeedsDependency {
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
|
@ -271,6 +273,7 @@ extension NotificationViewController: ContentOffsetAdjustableTimelineViewControl
|
|||
|
||||
// MARK: - NotificationTableViewCellDelegate
|
||||
extension NotificationViewController: NotificationTableViewCellDelegate {
|
||||
|
||||
func notificationTableViewCell(_ cell: NotificationTableViewCell, notification: MastodonNotification, acceptButtonDidPressed button: UIButton) {
|
||||
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 {
|
||||
self
|
||||
}
|
||||
|
||||
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) {
|
||||
StatusProviderFacade.responseToStatusContentWarningRevealAction(dependency: self, cell: cell)
|
||||
StatusProviderFacade.responseToStatusContentWarningRevealAction(provider: self, cell: cell)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -57,8 +57,8 @@ final class NotificationStatusTableViewCell: UITableViewCell, StatusCell {
|
|||
return label
|
||||
}()
|
||||
|
||||
let nameLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
let nameLabel: ActiveLabel = {
|
||||
let label = ActiveLabel(style: .statusName)
|
||||
label.textColor = Asset.Colors.brandBlue.color
|
||||
label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .semibold), maximumPointSize: 20)
|
||||
label.lineBreakMode = .byTruncatingTail
|
||||
|
@ -259,7 +259,7 @@ extension NotificationStatusTableViewCell: StatusViewDelegate {
|
|||
}
|
||||
|
||||
func statusView(_ statusView: StatusView, metaText: MetaText, didSelectMeta meta: Meta) {
|
||||
// do nothing
|
||||
delegate?.notificationStatusTableViewCell(self, statusView: statusView, metaText: metaText, didSelectMeta: meta)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,6 +9,9 @@ import Combine
|
|||
import CoreDataStack
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Meta
|
||||
import MetaTextView
|
||||
import ActiveLabel
|
||||
|
||||
protocol NotificationTableViewCellDelegate: AnyObject {
|
||||
var context: AppContext! { get }
|
||||
|
@ -16,13 +19,14 @@ protocol NotificationTableViewCellDelegate: AnyObject {
|
|||
func parent() -> UIViewController
|
||||
|
||||
func userAvatarDidPressed(notification: MastodonNotification)
|
||||
func userNameLabelDidPressed(notification: MastodonNotification)
|
||||
|
||||
func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, statusView: StatusView, revealContentWarningButtonDidPressed button: UIButton)
|
||||
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, metaText: MetaText, didSelectMeta meta: Meta)
|
||||
|
||||
func notificationTableViewCell(_ cell: NotificationTableViewCell, notification: MastodonNotification, acceptButtonDidPressed button: UIButton)
|
||||
|
||||
func notificationTableViewCell(_ cell: NotificationTableViewCell, notification: MastodonNotification, rejectButtonDidPressed button: UIButton)
|
||||
|
||||
}
|
||||
|
@ -34,7 +38,7 @@ final class NotificationTableViewCell: UITableViewCell {
|
|||
|
||||
var delegate: NotificationTableViewCellDelegate?
|
||||
|
||||
let avatatImageView: UIImageView = {
|
||||
let avatarImageView: UIImageView = {
|
||||
let imageView = UIImageView()
|
||||
imageView.layer.cornerRadius = 4
|
||||
imageView.layer.cornerCurve = .continuous
|
||||
|
@ -72,8 +76,8 @@ final class NotificationTableViewCell: UITableViewCell {
|
|||
return label
|
||||
}()
|
||||
|
||||
let nameLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
let nameLabel: ActiveLabel = {
|
||||
let label = ActiveLabel()
|
||||
label.textColor = Asset.Colors.brandBlue.color
|
||||
label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .semibold), maximumPointSize: 20)
|
||||
label.lineBreakMode = .byTruncatingTail
|
||||
|
@ -108,7 +112,7 @@ final class NotificationTableViewCell: UITableViewCell {
|
|||
|
||||
override func prepareForReuse() {
|
||||
super.prepareForReuse()
|
||||
avatatImageView.af.cancelImageRequest()
|
||||
avatarImageView.af.cancelImageRequest()
|
||||
disposeBag.removeAll()
|
||||
}
|
||||
|
||||
|
@ -153,13 +157,13 @@ extension NotificationTableViewCell {
|
|||
avatarContainer.widthAnchor.constraint(equalToConstant: 47).priority(.required - 1)
|
||||
])
|
||||
|
||||
avatarContainer.addSubview(avatatImageView)
|
||||
avatatImageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
avatarContainer.addSubview(avatarImageView)
|
||||
avatarImageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
NSLayoutConstraint.activate([
|
||||
avatatImageView.heightAnchor.constraint(equalToConstant: 35).priority(.required - 1),
|
||||
avatatImageView.widthAnchor.constraint(equalToConstant: 35).priority(.required - 1),
|
||||
avatatImageView.topAnchor.constraint(equalTo: avatarContainer.topAnchor),
|
||||
avatatImageView.leadingAnchor.constraint(equalTo: avatarContainer.leadingAnchor)
|
||||
avatarImageView.heightAnchor.constraint(equalToConstant: 35).priority(.required - 1),
|
||||
avatarImageView.widthAnchor.constraint(equalToConstant: 35).priority(.required - 1),
|
||||
avatarImageView.topAnchor.constraint(equalTo: avatarContainer.topAnchor),
|
||||
avatarImageView.leadingAnchor.constraint(equalTo: avatarContainer.leadingAnchor)
|
||||
])
|
||||
|
||||
avatarContainer.addSubview(actionImageBackground)
|
||||
|
|
Loading…
Reference in New Issue