// // Copyright (c) 2019 Open Whisper Systems. All rights reserved. // import Foundation import SignalUtilitiesKit @objc public protocol LongTextViewDelegate { @objc func longTextViewMessageWasDeleted(_ longTextViewController: LongTextViewController) } @objc public class LongTextViewController: OWSViewController { // MARK: - Dependencies var uiDatabaseConnection: YapDatabaseConnection { return OWSPrimaryStorage.shared().uiDatabaseConnection } // MARK: - Properties @objc weak var delegate: LongTextViewDelegate? let viewItem: ConversationViewItem var messageTextView: UITextView! var displayableText: DisplayableText? { return viewItem.displayableBodyText } var fullText: String { return displayableText?.fullText ?? "" } // MARK: Initializers @available(*, unavailable, message:"use other constructor instead.") public required init?(coder aDecoder: NSCoder) { notImplemented() } @objc public required init(viewItem: ConversationViewItem) { self.viewItem = viewItem super.init(nibName: nil, bundle: nil) } // MARK: View Lifecycle public override func viewDidLoad() { super.viewDidLoad() ViewControllerUtilities.setUpDefaultSessionStyle(for: self, title: NSLocalizedString("LONG_TEXT_VIEW_TITLE", comment: ""), hasCustomBackButton: false) createViews() self.messageTextView.contentOffset = CGPoint(x: 0, y: self.messageTextView.contentInset.top) NotificationCenter.default.addObserver(self, selector: #selector(uiDatabaseDidUpdate), name: .OWSUIDatabaseConnectionDidUpdate, object: OWSPrimaryStorage.shared().dbNotificationObject) } // MARK: - DB @objc internal func uiDatabaseDidUpdate(notification: NSNotification) { AssertIsOnMainThread() guard let notifications = notification.userInfo?[OWSUIDatabaseConnectionNotificationsKey] as? [Notification] else { owsFailDebug("notifications was unexpectedly nil") return } guard let uniqueId = self.viewItem.interaction.uniqueId else { Logger.error("Message is missing uniqueId.") return } guard self.uiDatabaseConnection.hasChange(forKey: uniqueId, inCollection: TSInteraction.collection(), in: notifications) else { Logger.debug("No relevant changes.") return } do { try uiDatabaseConnection.read { transaction in guard TSInteraction.fetch(uniqueId: uniqueId, transaction: transaction) != nil else { Logger.error("Message was deleted") throw LongTextViewError.messageWasDeleted } } } catch LongTextViewError.messageWasDeleted { DispatchQueue.main.async { self.delegate?.longTextViewMessageWasDeleted(self) } } catch { owsFailDebug("unexpected error: \(error)") } } enum LongTextViewError: Error { case messageWasDeleted } // MARK: - Create Views private func createViews() { view.backgroundColor = Theme.backgroundColor let messageTextView = OWSTextView() self.messageTextView = messageTextView messageTextView.font = .systemFont(ofSize: Values.smallFontSize) messageTextView.backgroundColor = .clear messageTextView.isOpaque = true messageTextView.isEditable = false messageTextView.isSelectable = true messageTextView.isScrollEnabled = true messageTextView.showsHorizontalScrollIndicator = false messageTextView.showsVerticalScrollIndicator = true messageTextView.isUserInteractionEnabled = true messageTextView.textColor = Colors.text messageTextView.contentInset = UIEdgeInsets(top: Values.mediumSpacing, leading: 0, bottom: 0, trailing: 0) if let displayableText = displayableText { messageTextView.text = fullText messageTextView.ensureShouldLinkifyText(displayableText.shouldAllowLinkification) } else { owsFailDebug("displayableText was unexpectedly nil") messageTextView.text = "" } let linkTextAttributes: [NSAttributedString.Key: Any] = [ NSAttributedString.Key.foregroundColor: Colors.text, NSAttributedString.Key.underlineColor: Colors.text, NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue ] messageTextView.linkTextAttributes = linkTextAttributes view.addSubview(messageTextView) messageTextView.autoPinEdge(toSuperviewEdge: .top) messageTextView.autoPinEdge(toSuperviewEdge: .leading) messageTextView.autoPinEdge(toSuperviewEdge: .trailing) messageTextView.textContainerInset = UIEdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16) let footer = UIToolbar() view.addSubview(footer) footer.autoPinWidthToSuperview() footer.autoPinEdge(.top, to: .bottom, of: messageTextView) footer.autoPinEdge(toSuperviewSafeArea: .bottom) footer.items = [ UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil), UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(shareButtonPressed)), UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) ] } // MARK: - Actions @objc func shareButtonPressed() { AttachmentSharing.showShareUI(forText: fullText) } }