Fix detecting mentions while typing
This commit is contained in:
parent
cad074bcc3
commit
7d47f1f259
|
@ -101,6 +101,9 @@ private struct NewMainTextViewRepresentable: UIViewRepresentable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// laxer than the CharacterCounter regex, because we want to find mentions that are being typed but aren't yet complete (e.g., "@a@b")
|
||||||
|
private let mentionRegex = try! NSRegularExpression(pattern: "(@[a-z0-9_]+)(?:@[a-z0-9\\-\\.]+)?", options: .caseInsensitive)
|
||||||
|
|
||||||
private final class WrappedTextViewCoordinator: NSObject {
|
private final class WrappedTextViewCoordinator: NSObject {
|
||||||
private static let attachment: NSTextAttachment = {
|
private static let attachment: NSTextAttachment = {
|
||||||
let font = UIFont.systemFont(ofSize: 20)
|
let font = UIFont.systemFont(ofSize: 20)
|
||||||
|
@ -149,6 +152,7 @@ private final class WrappedTextViewCoordinator: NSObject {
|
||||||
private func updateAttributes(in textView: UITextView) {
|
private func updateAttributes(in textView: UITextView) {
|
||||||
let str = NSMutableAttributedString(attributedString: textView.attributedText!)
|
let str = NSMutableAttributedString(attributedString: textView.attributedText!)
|
||||||
var changed = false
|
var changed = false
|
||||||
|
var cursorOffset = 0
|
||||||
|
|
||||||
// remove existing mentions that aren't valid
|
// remove existing mentions that aren't valid
|
||||||
str.enumerateAttribute(.mention, in: NSRange(location: 0, length: str.length), options: .reverse) { value, range, stop in
|
str.enumerateAttribute(.mention, in: NSRange(location: 0, length: str.length), options: .reverse) { value, range, stop in
|
||||||
|
@ -157,18 +161,19 @@ private final class WrappedTextViewCoordinator: NSObject {
|
||||||
if hasTextAttachment {
|
if hasTextAttachment {
|
||||||
substr = String(substr.dropFirst())
|
substr = String(substr.dropFirst())
|
||||||
}
|
}
|
||||||
if CharacterCounter.mention.numberOfMatches(in: substr, range: NSRange(location: 0, length: substr.utf16.count)) == 0 {
|
if mentionRegex.numberOfMatches(in: substr, range: NSRange(location: 0, length: substr.utf16.count)) == 0 {
|
||||||
changed = true
|
changed = true
|
||||||
str.removeAttribute(.mention, range: range)
|
str.removeAttribute(.mention, range: range)
|
||||||
str.removeAttribute(.foregroundColor, range: range)
|
str.removeAttribute(.foregroundColor, range: range)
|
||||||
if hasTextAttachment {
|
if hasTextAttachment {
|
||||||
str.deleteCharacters(in: NSRange(location: range.location, length: 1))
|
str.deleteCharacters(in: NSRange(location: range.location, length: 1))
|
||||||
|
cursorOffset -= 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add mentions for those missing
|
// add mentions for those missing
|
||||||
let mentionMatches = CharacterCounter.mention.matches(in: str.string, range: NSRange(location: 0, length: str.length))
|
let mentionMatches = mentionRegex.matches(in: str.string, range: NSRange(location: 0, length: str.length))
|
||||||
for match in mentionMatches.reversed() {
|
for match in mentionMatches.reversed() {
|
||||||
var attributeRange = NSRange()
|
var attributeRange = NSRange()
|
||||||
let attribute = str.attribute(.mention, at: match.range.location, effectiveRange: &attributeRange)
|
let attribute = str.attribute(.mention, at: match.range.location, effectiveRange: &attributeRange)
|
||||||
|
@ -179,6 +184,7 @@ private final class WrappedTextViewCoordinator: NSObject {
|
||||||
if attribute == nil {
|
if attribute == nil {
|
||||||
str.insert(NSAttributedString(attachment: Self.attachment), at: match.range.location)
|
str.insert(NSAttributedString(attachment: Self.attachment), at: match.range.location)
|
||||||
newAttributeRange = NSRange(location: match.range.location, length: match.range.length + 1)
|
newAttributeRange = NSRange(location: match.range.location, length: match.range.length + 1)
|
||||||
|
cursorOffset += 1
|
||||||
} else {
|
} else {
|
||||||
newAttributeRange = match.range
|
newAttributeRange = match.range
|
||||||
}
|
}
|
||||||
|
@ -190,7 +196,11 @@ private final class WrappedTextViewCoordinator: NSObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
if changed {
|
if changed {
|
||||||
|
let selection = textView.selectedRange
|
||||||
|
|
||||||
textView.attributedText = str
|
textView.attributedText = str
|
||||||
|
|
||||||
|
textView.selectedRange = NSRange(location: selection.location + cursorOffset, length: selection.length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue