mention: allow mentioning users with punctuation characters in their names
Finds the range of characters which represents a mention the user is typing in PostView. Previously the tokenizer used the standard granularity UITextGranularity.word, but this is insufficient for our use case for detecting when a mention ends. The criteria is simple: a mention starts with the '@' character and ends when there is a space, line break, or @, instead of when there is a new word. Closes: https://github.com/damus-io/damus/issues/1721 Changelog-Fixed: Allow mentioning users with punctuation characters in their names Lightning-url: LNURL1DP68GURN8GHJ7EM9W3SKCCNE9E3K7MF0D3H82UNVWQHKWUN9V4HXGCTHDC6RZVGR8SW3G Signed-off-by: kernelkind <kernelkind@gmail.com> Reviewed-by: William Casarin <jb55@jb55.com> Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
committed by
William Casarin
parent
534969e616
commit
71b33fcd0b
@@ -119,7 +119,7 @@ struct TextViewWrapper: UIViewRepresentable {
|
|||||||
|
|
||||||
guard let selectedRange = textView.selectedTextRange else { return }
|
guard let selectedRange = textView.selectedTextRange else { return }
|
||||||
|
|
||||||
let wordRange = textView.tokenizer.rangeEnclosingPosition(selectedRange.start, with: .word, inDirection: .init(rawValue: UITextLayoutDirection.left.rawValue))
|
let wordRange = rangeOfMention(in: textView, from: selectedRange.start)
|
||||||
|
|
||||||
if let wordRange,
|
if let wordRange,
|
||||||
let startPosition = textView.position(from: wordRange.start, offset: -1),
|
let startPosition = textView.position(from: wordRange.start, offset: -1),
|
||||||
@@ -131,6 +131,27 @@ struct TextViewWrapper: UIViewRepresentable {
|
|||||||
|
|
||||||
getFocusWordForMention?(val.0, val.1)
|
getFocusWordForMention?(val.0, val.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func rangeOfMention(in textView: UITextView, from position: UITextPosition) -> UITextRange? {
|
||||||
|
var startPosition = position
|
||||||
|
|
||||||
|
while startPosition != textView.beginningOfDocument {
|
||||||
|
guard let previousPosition = textView.position(from: startPosition, offset: -1),
|
||||||
|
let range = textView.textRange(from: previousPosition, to: startPosition),
|
||||||
|
let text = textView.text(in: range), !text.isEmpty,
|
||||||
|
let lastChar = text.last else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if [" ", "\n", "@"].contains(lastChar) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
startPosition = previousPosition
|
||||||
|
}
|
||||||
|
|
||||||
|
return startPosition == position ? nil : textView.textRange(from: startPosition, to: position)
|
||||||
|
}
|
||||||
|
|
||||||
private func convertToNSRange( _ startPosition: UITextPosition, _ endPosition: UITextPosition, _ textView: UITextView) -> NSRange? {
|
private func convertToNSRange( _ startPosition: UITextPosition, _ endPosition: UITextPosition, _ textView: UITextView) -> NSRange? {
|
||||||
let startOffset = textView.offset(from: textView.beginningOfDocument, to: startPosition)
|
let startOffset = textView.offset(from: textView.beginningOfDocument, to: startPosition)
|
||||||
|
|||||||
Reference in New Issue
Block a user