// // StatusTableViewCell.swift // Tusker // // Created by Shadowfacts on 8/16/18. // Copyright © 2018 Shadowfacts. All rights reserved. // import UIKit import MastodonKit import SwiftSoup class StatusTableViewCell: UITableViewCell { @IBOutlet weak var displayNameLabel: UILabel! @IBOutlet weak var usernameLabel: UILabel! @IBOutlet weak var contentLabel: StatusContentLabel! @IBOutlet weak var avatarImageView: UIImageView! var status: Status! var avatarURL: URL? var layoutManager: NSLayoutManager! var textContainer: NSTextContainer! var textStorage: NSTextStorage! var links: [NSRange: URL] = [:] func updateUI(for status: Status) { self.status = status let account: Account if let reblog = status.reblog { account = reblog.account } else { account = status.account } displayNameLabel.text = account.displayName usernameLabel.text = "@\(account.acct)" avatarImageView.layer.cornerRadius = 5 avatarImageView.layer.masksToBounds = true avatarImageView.image = nil if let url = URL(string: account.avatar) { AvatarCache.shared.get(url) { image in DispatchQueue.main.async { self.avatarImageView.image = image } } } contentLabel.text = status.content // let doc = try! SwiftSoup.parse(status.content) // let body = doc.body()! //// print("---") //// print(status.content) //// print("---") // // let (text, links) = attributedTextForNode(body) // self.links = links // contentLabel.attributedText = text // contentLabel.isUserInteractionEnabled = true // contentLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTapOnContentLabel(_:)))) // // // https://stackoverflow.com/a/28519273/4731558 // layoutManager = NSLayoutManager() // textContainer = NSTextContainer(size: .zero) // textStorage = NSTextStorage(attributedString: text) // // layoutManager.addTextContainer(textContainer) // textStorage.addLayoutManager(layoutManager) // // textContainer.lineFragmentPadding = 0 // textContainer.lineBreakMode = contentLabel.lineBreakMode // textContainer.maximumNumberOfLines = contentLabel.numberOfLines } // func attributedTextForNode(_ node: Node) -> (NSAttributedString, [NSRange: URL]) { // switch node { // case let node as TextNode: // return (NSAttributedString(string: node.text()), [:]) // case let node as Element: // var links = [NSRange: URL]() // let attributed = NSMutableAttributedString() // node.getChildNodes().forEach { child in // let (text, childLinks) = attributedTextForNode(child) // childLinks.forEach { range, url in // let newRange = NSRange(location: range.location + attributed.length, length: range.length) // links[newRange] = url // } // attributed.append(text) // } // // switch node.tagName() { // case "br": // attributed.append(NSAttributedString(string: "\n")) // case "a": // if let link = try? node.attr("href"), // let url = URL(string: link) { // let linkRange = NSRange(location: 0, length: attributed.length) // let linkAttributes: [NSAttributedString.Key: Any] = [ // .foregroundColor: UIColor.blue // ] // attributed.setAttributes(linkAttributes, range: linkRange) // // links[linkRange] = url // } // default: // break // } // // return (attributed, links) // default: // fatalError("Unexpected node type: \(type(of: node))") // } // } // @objc func handleTapOnContentLabel(_ tapGesture: UITapGestureRecognizer) { // guard let view = tapGesture.view else { fatalError() } // // let locationOfTouchInLabel = tapGesture.location(in: view) // let labelSize = view.bounds.size // let textBoundingBox = layoutManager.usedRect(for: textContainer) // let textContainerOffset = CGPoint(x: (labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x, // y: (labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y) // let locationOfTouchInTextContainer = CGPoint(x: locationOfTouchInLabel.x - textContainerOffset.x, // y: locationOfTouchInLabel.y - textContainerOffset.y) // let indexOfCharacter = layoutManager.characterIndex(for: locationOfTouchInTextContainer, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil) // // let link = links.first { (range, _) -> Bool in // range.contains(indexOfCharacter) // } // // if let (_, url) = link { // print("Open URL: \(url)") // } // } override func prepareForReuse() { if let url = avatarURL { AvatarCache.shared.cancel(url) } } }