summaryrefslogtreecommitdiff
path: root/Juick/Views/MessageCell.swift
diff options
context:
space:
mode:
Diffstat (limited to 'Juick/Views/MessageCell.swift')
-rw-r--r--Juick/Views/MessageCell.swift181
1 files changed, 181 insertions, 0 deletions
diff --git a/Juick/Views/MessageCell.swift b/Juick/Views/MessageCell.swift
new file mode 100644
index 0000000..ebebec2
--- /dev/null
+++ b/Juick/Views/MessageCell.swift
@@ -0,0 +1,181 @@
+//
+// MessageCell.swift
+// Juick
+//
+// Created by Vitaly Takmazov on 13.05.2023.
+// Copyright © 2023 com.juick. All rights reserved.
+//
+
+import UIKit
+
+@objc protocol MessageCellDelegate {
+ @objc func avatarClicked(_ uname: String)
+ @objc func linkClicked(_ url: String)
+}
+
+@objc
+class MessageCell: UITableViewCell {
+ @IBOutlet weak var avatar: UIImageView!
+ @IBOutlet weak var message: UITextView!
+ @IBOutlet weak var title: UILabel!
+ @IBOutlet weak var timestamp: UILabel!
+ @IBOutlet weak var attach: UIImageView!
+ @IBOutlet weak var attachmentHeight: NSLayoutConstraint!
+ @IBOutlet weak var attachmentWidth: NSLayoutConstraint!
+ @IBOutlet weak var summary: UILabel!
+ @objc var delegate: MessageCellDelegate?
+
+ var _quoteStyle: NSMutableParagraphStyle?
+ var _boldFont: UIFont?
+ var _italicFont: UIFont?
+ var attachment: String?
+
+ @objc
+ func configure(msg: Message, selectable: Bool) {
+ updateAvatar(url: msg.user.avatar)
+ if (msg.user.uid == nil) {
+ AppDelegate.shared().api.getUserByUri(msg.user.uri) { user in
+ self.title.text = user?.uname
+ if let url = user?.avatar ?? API.defaultAvatarUrl() {
+ self.updateAvatar(url: url)
+ }
+ }
+ }
+ if (msg.attach != nil) {
+ self.attachment = msg.attachment.url
+ let imageHeight = msg.attachment.medium.height as! CGFloat / UIScreen.main.scale
+ let imageWidth = msg.attachment.medium.width as! CGFloat / UIScreen.main.scale
+ self.attach.image = UIImage.placeholderImage(with: UIColor(named: "Muted"), size: CGSizeMake(imageWidth, imageHeight))
+
+ self.attachmentHeight.constant = imageHeight
+ self.attachmentWidth.constant = imageWidth
+ AppDelegate.shared().api.fetchImage(with: URL(string: msg.attachment.medium.url)) { data in
+ if let imageData = data {
+ UIView.transition(with: self.attach, duration: 0.3, options: .transitionCrossDissolve, animations: {
+ self.attach.image = UIImage(data: imageData)
+ })
+ }
+ }
+ let attachmentTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(linkClicked(_:)))
+ attachmentTapGestureRecognizer.isEnabled = true
+ self.attach.addGestureRecognizer(attachmentTapGestureRecognizer)
+ self.attach.isUserInteractionEnabled = true
+ } else {
+ self.attachmentHeight.constant = 0
+ self.attach.image = nil
+ }
+ if (msg.user.premium) {
+ self.title.text = "\(msg.user.uname!) ☆"
+ } else {
+ self.title.text = msg.user.uname!
+ }
+
+ self.timestamp.text = (AppDelegate.shared().sharedDateFormatter.date(from: msg.timestamp)! as NSDate).timeAgo()
+ let count = msg.repliesCount?.uintValue ?? 0
+ if (count > 0) {
+ if (msg.repliesBy != nil) {
+ self.summary.text = "\(msg.repliesCount!) replies by \(msg.repliesBy!)"
+ } else {
+ self.summary.text = "\(msg.repliesCount!) replies"
+ }
+ } else {
+ self.summary.text = nil
+ }
+ if (msg.unread) {
+ self.summary.text = "\(unreadMarker) \(self.summary.text!)"
+ self.summary.textColor = UIColor(named: "Funny")
+ } else {
+ self.summary.textColor = UIColor(named: "Muted")
+ }
+ self.message.attributedText = nil
+ if (msg.text != nil) {
+ self.message.isHidden = false
+ self.message.isSelectable = selectable
+ self.message.isUserInteractionEnabled = selectable
+ let txt = NSMutableAttributedString(string: msg.text, attributes: [
+ NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .body),
+ NSAttributedString.Key.foregroundColor: UIColor(named: "Text")!
+ ])
+ txt.beginEditing()
+ for entity in msg.entities {
+ let start = entity.start?.intValue ?? 0
+ let end = entity.end?.intValue ?? 0
+ let text = entity.text ?? ""
+ let currentRange = NSMakeRange(start, end - start)
+ txt.addAttribute(NSAttributedString.Key(rawValue: "displayText"), value: text, range: currentRange)
+ if entity.type == "a" {
+ txt.addAttribute(NSAttributedString.Key.link, value:entity.link!, range:currentRange)
+ }
+ if entity.type == "q" {
+ txt.addAttribute(NSAttributedString.Key.foregroundColor, value:UIColor(named: "Muted")!, range:currentRange)
+ txt.addAttribute(NSAttributedString.Key.paragraphStyle, value:_quoteStyle!, range:currentRange)
+ }
+ if entity.type == "u" {
+ txt.addAttribute(NSAttributedString.Key.underlineStyle, value:NSUnderlineStyle.single, range:currentRange)
+ }
+
+ if entity.type == "b" {
+ txt.addAttribute(NSAttributedString.Key.font, value:_boldFont!, range:currentRange)
+ }
+ if entity.type == "i" {
+ txt.addAttribute(NSAttributedString.Key.font, value:_italicFont!, range:currentRange)
+ }
+ }
+ txt.enumerateAttribute(NSAttributedString.Key(rawValue: "displayText"), in: NSMakeRange(0, txt.length)) { value, range, stop in
+ if let text = value as? String {
+ txt.replaceCharacters(in: range, with:text)
+ }
+ }
+
+ if msg.tags != nil {
+ let tagsList = "\(msg.tags.joined(separator: ", "))\n"
+ txt.insert(NSAttributedString(string: tagsList, attributes: [
+ NSAttributedString.Key.font: _italicFont!,
+ NSAttributedString.Key.foregroundColor: UIColor(named: "Muted")!
+ ]), at: 0)
+ }
+ txt.endEditing()
+ self.message.attributedText = txt
+ } else {
+ self.message.isHidden = true
+ }
+ }
+
+ let unreadMarker = "●"
+
+ func updateAvatar(url: String) {
+ self.avatar.image = nil
+ AppDelegate.shared().api.fetchImage(with: URL(string: url)) { data in
+ if let imageData = data {
+ UIView.transition(with: self.avatar, duration: 0.3, options: .transitionCrossDissolve, animations: {
+ self.avatar.image = UIImage(data: imageData)
+ })
+ }
+ }
+ }
+
+ @objc func avatarClicked(_ sender: UITapGestureRecognizer) {
+ if let name = self.title.text {
+ self.delegate?.avatarClicked(name)
+ }
+ }
+ @objc func linkClicked(_ sender: UITapGestureRecognizer){
+ self.delegate?.linkClicked(self.attachment!)
+ }
+
+ override func awakeFromNib() {
+ let avatarTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(avatarClicked(_:)))
+ avatarTapRecognizer.isEnabled = true
+ self.avatar.addGestureRecognizer(avatarTapRecognizer)
+ self.avatar.isUserInteractionEnabled = true
+ _quoteStyle = NSParagraphStyle.default.mutableCopy() as? NSMutableParagraphStyle
+ _quoteStyle?.firstLineHeadIndent = 12.0
+ _quoteStyle?.headIndent = 12.0
+ _quoteStyle?.paragraphSpacing = 6.0
+ let fontDescriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .body)
+ guard let boldFontDescriptor = fontDescriptor.withSymbolicTraits(.traitBold) else { fatalError("Font error") }
+ _boldFont = UIFont(descriptor: boldFontDescriptor, size: 0.0)
+ guard let italicFontDescriptor = fontDescriptor.withSymbolicTraits(.traitItalic) else { fatalError("Font error") }
+ _italicFont = UIFont(descriptor: italicFontDescriptor, size: 0.0)
+ }
+}