diff --git a/Tusker/Views/ContentTextView.swift b/Tusker/Views/ContentTextView.swift index a138b0cc..edf1c04e 100644 --- a/Tusker/Views/ContentTextView.swift +++ b/Tusker/Views/ContentTextView.swift @@ -36,6 +36,8 @@ class ContentTextView: LinkTextView, BaseEmojiLabel { var emojiFont: UIFont = .preferredFont(forTextStyle: .body) var emojiTextColor: UIColor = .label + private let tapRecognizer = UITapGestureRecognizer() + // The link range currently being previewed private var currentPreviewedLinkRange: NSRange? // The preview created in the previewForHighlighting method, so that we can use the same one in previewForDismissing. @@ -78,8 +80,9 @@ class ContentTextView: LinkTextView, BaseEmojiLabel { updateLinkUnderlineStyle() // the text view's builtin link interaction code is tied to isSelectable, so we need to use our own tap recognizer - let recognizer = UITapGestureRecognizer(target: self, action: #selector(textTapped(_:))) - addGestureRecognizer(recognizer) + tapRecognizer.addTarget(self, action: #selector(textTapped(_:))) + tapRecognizer.delegate = self + addGestureRecognizer(tapRecognizer) NotificationCenter.default.addObserver(self, selector: #selector(_updateLinkUnderlineStyle), name: UIAccessibility.buttonShapesEnabledStatusDidChangeNotification, object: nil) underlineTextLinksCancellable = @@ -132,12 +135,6 @@ class ContentTextView: LinkTextView, BaseEmojiLabel { } @objc func textTapped(_ recognizer: UITapGestureRecognizer) { - // if there currently is a selection, deselct it on single-tap - if selectedRange.length > 0 { - // location doesn't matter since we are non-editable and the cursor isn't visible - selectedRange = NSRange(location: 0, length: 0) - } - let location = recognizer.location(in: self) if let (link, range) = getLinkAtPoint(location), link.scheme != dataDetectorsScheme { @@ -384,3 +381,25 @@ extension ContentTextView: UIContextMenuInteractionDelegate { } } } + +extension ContentTextView: UIGestureRecognizerDelegate { + override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { + // NB: This method is both a gesture recognizer delegate method and a UIView method. + // We only want to prevent our own tap gesture recognizer from beginning, but don't + // want to interfere with any other gestures that may begin over this view. + if gestureRecognizer === tapRecognizer { + let location = gestureRecognizer.location(in: self) + if let (link, _) = getLinkAtPoint(location) { + if link.scheme == dataDetectorsScheme { + return false + } else { + return true + } + } else { + return false + } + } else { + return true + } + } +}