You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
205 lines
8.4 KiB
205 lines
8.4 KiB
// |
|
// ActionNotificationTableViewCell.swift |
|
// Tusker |
|
// |
|
// Created by Shadowfacts on 9/2/18. |
|
// Copyright © 2018 Shadowfacts. All rights reserved. |
|
// |
|
|
|
import UIKit |
|
import Pachyderm |
|
|
|
class ActionNotificationTableViewCell: UITableViewCell, PreferencesAdaptive { |
|
|
|
var delegate: StatusTableViewCellDelegate? { |
|
didSet { |
|
contentLabel.navigationDelegate = delegate |
|
} |
|
} |
|
|
|
@IBOutlet weak var displayNameLabel: UILabel! |
|
@IBOutlet weak var usernameLabel: UILabel! |
|
@IBOutlet weak var contentLabel: StatusContentLabel! |
|
@IBOutlet weak var avatarContainerView: UIView! |
|
@IBOutlet weak var opAvatarImageView: UIImageView! |
|
@IBOutlet weak var actionAvatarImageView: UIImageView! |
|
@IBOutlet weak var actionLabel: UILabel! |
|
@IBOutlet weak var timestampLabel: UILabel! |
|
@IBOutlet weak var attachmentsView: UIStackView! |
|
|
|
var notification: Pachyderm.Notification! |
|
var statusID: String! |
|
|
|
var opAvatarURL: URL? |
|
var actionAvatarURL: URL? |
|
var updateTimestampWorkItem: DispatchWorkItem? |
|
|
|
override func awakeFromNib() { |
|
displayNameLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(accountPressed))) |
|
displayNameLabel.isUserInteractionEnabled = true |
|
usernameLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(accountPressed))) |
|
usernameLabel.isUserInteractionEnabled = true |
|
opAvatarImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(accountPressed))) |
|
opAvatarImageView.isUserInteractionEnabled = true |
|
opAvatarImageView.layer.masksToBounds = true |
|
actionAvatarImageView.layer.masksToBounds = true |
|
actionLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(actionPressed))) |
|
actionLabel.isUserInteractionEnabled = true |
|
} |
|
|
|
func updateUIForPreferences() { |
|
guard let status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") } |
|
|
|
opAvatarImageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: opAvatarImageView) |
|
actionAvatarImageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: actionAvatarImageView) |
|
displayNameLabel.text = status.account.realDisplayName |
|
|
|
let verb: String |
|
switch notification.kind { |
|
case .favourite: |
|
verb = "Liked" |
|
case .reblog: |
|
verb = "Reblogged" |
|
default: |
|
fatalError("Invalid notification type \(notification.kind) for ActionNotificationTableViewCell") |
|
} |
|
actionLabel.text = "\(verb) by \(notification.account.realDisplayName)" |
|
} |
|
|
|
func updateUI(for notification: Pachyderm.Notification) { |
|
guard notification.kind == .favourite || notification.kind == .reblog else { |
|
fatalError("Invalid notification type \(notification.kind) for ActionNotificationTableViewCell") |
|
} |
|
self.notification = notification |
|
let status = notification.status! |
|
self.statusID = status.id |
|
|
|
updateUIForPreferences() |
|
|
|
usernameLabel.text = "@\(status.account.acct)" |
|
opAvatarImageView.image = nil |
|
opAvatarURL = status.account.avatar |
|
ImageCache.avatars.get(status.account.avatar) { (data) in |
|
guard let data = data else { return } |
|
DispatchQueue.main.async { |
|
self.opAvatarImageView.image = UIImage(data: data) |
|
self.opAvatarURL = nil |
|
} |
|
} |
|
actionAvatarImageView.image = nil |
|
actionAvatarURL = notification.account.avatar |
|
ImageCache.avatars.get(notification.account.avatar) { (data) in |
|
guard let data = data else { return } |
|
DispatchQueue.main.async { |
|
self.actionAvatarImageView.image = UIImage(data: data) |
|
self.actionAvatarURL = nil |
|
} |
|
} |
|
updateTimestamp() |
|
let attachments = status.attachments.filter({ $0.kind == .image }) |
|
if attachments.count > 0 { |
|
attachmentsView.isHidden = false |
|
for attachment in attachments { |
|
let url = attachment.textURL ?? attachment.url |
|
let label = UILabel() |
|
label.textColor = .darkGray |
|
|
|
let textAttachment = InlineTextAttachment() |
|
textAttachment.image = UIImage(named: "Link")! |
|
textAttachment.bounds = CGRect(x: 0, y: 0, width: label.font.pointSize, height: label.font.pointSize) |
|
textAttachment.fontDescender = label.font.descender |
|
let attachmentStr = NSAttributedString(attachment: textAttachment) |
|
let text = NSMutableAttributedString(string: " ") |
|
text.append(attachmentStr) |
|
text.append(NSAttributedString(string: " ")) |
|
// text.addAttribute(.font, value: UIFont.systemFont(ofSize: 0), range: NSRange(location: 0, length: text.length)) |
|
|
|
text.append(NSAttributedString(string: "\(url.lastPathComponent)")) |
|
text.addAttribute(.foregroundColor, value: UIColor.red, range: NSRange(location: 0, length: 2)) |
|
|
|
|
|
|
|
// let text = NSMutableAttributedString(string: " \(url.lastPathComponent)") |
|
// let imageAttachment = InlineTextAttachment() |
|
// imageAttachment.image = UIImage(named: "Link")! |
|
// imageAttachment.bounds = CGRect(x: 0, y: 0, width: label.font.pointSize, height: label.font.pointSize) |
|
// imageAttachment.fontDescender = label.font.descender |
|
// let imageStr = NSMutableAttributedString(attachment: imageAttachment) |
|
// imageStr.setAttributes([.foregroundColor: UIColor.darkGray], range: ) |
|
// text.insert(imageStr, at: 0) |
|
|
|
label.attributedText = text |
|
attachmentsView.addArrangedSubview(label) |
|
} |
|
} else { |
|
attachmentsView.isHidden = true |
|
} |
|
|
|
// contentLabel.statusID = status.id |
|
contentLabel.setTextFromHtml(status.content) |
|
} |
|
|
|
func updateTimestamp() { |
|
guard let status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") } |
|
|
|
timestampLabel.text = status.createdAt.timeAgoString() |
|
let delay: DispatchTimeInterval? |
|
switch status.createdAt.timeAgo().1 { |
|
case .second: |
|
delay = .seconds(10) |
|
case .minute: |
|
delay = .seconds(60) |
|
default: |
|
delay = nil |
|
} |
|
if let delay = delay { |
|
updateTimestampWorkItem = DispatchWorkItem { |
|
self.updateTimestamp() |
|
} |
|
DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: updateTimestampWorkItem!) |
|
} else { |
|
updateTimestampWorkItem = nil |
|
} |
|
} |
|
|
|
override func prepareForReuse() { |
|
if let url = opAvatarURL { |
|
ImageCache.avatars.cancel(url) |
|
} |
|
if let url = actionAvatarURL { |
|
ImageCache.avatars.cancel(url) |
|
} |
|
updateTimestampWorkItem?.cancel() |
|
updateTimestampWorkItem = nil |
|
attachmentsView.subviews.forEach { $0.removeFromSuperview() } |
|
} |
|
|
|
override func setSelected(_ selected: Bool, animated: Bool) { |
|
super.setSelected(selected, animated: animated) |
|
|
|
if selected { |
|
delegate?.selected(status: statusID) |
|
} |
|
} |
|
|
|
@objc func accountPressed() { |
|
delegate?.selected(account: notification.status!.account.id) |
|
} |
|
|
|
@objc func actionPressed() { |
|
delegate?.selected(account: notification.account.id) |
|
} |
|
|
|
} |
|
|
|
extension ActionNotificationTableViewCell: PreviewViewControllerProvider { |
|
func getPreviewViewController(forLocation location: CGPoint, sourceViewController: UIViewController) -> UIViewController? { |
|
if avatarContainerView.frame.contains(location) { |
|
return delegate?.router.profile(for: notification.account.id) |
|
} else if contentLabel.frame.contains(location), |
|
let vc = contentLabel.getViewController(forLinkAt: contentLabel.convert(location, from: self)) { |
|
return vc |
|
} |
|
return delegate?.router.conversation(for: statusID) |
|
} |
|
}
|
|
|