From 27083669fa79e542de32700839ca89e416ed8051 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=E2=80=99Aquino?= Date: Wed, 21 Aug 2024 17:20:07 -0700 Subject: [PATCH] Improve handling of escape characters of mention suggestion menu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was noticed that adding a space inadvertently escapes the user mention suggestion menu (even though several users have an escape character in their name) This commit fixes that issue, and improves overall handling of user mention escape sequences, by allowing those sequences to be made up of multiple characters instead of a single one. Testing ------- Device: iPhone 13 Mini iOS: 17.6.1 Damus: This commit Steps: 1. Type normally. Make sure Text editing works normally 2. Try to type a mention with a long name with spaces. Make sure typing spaces does not cause the mention suggestions menu to be dismissed. 3. Select a user, make sure mention suggestions menu gets dismissed 4. Try to type a mention with a long name with spaces, but this time instead of selecting a user, just add a punctuation mark. Make sure the mention suggestions menu gets dismissed 5. Repeat the step above with the following escape sequences: 1. Newline 2. Another "@" 3. ", " 4. " " (double-space) 5. ". " 6. Delete characters all the way back to an existing mention. Make sure mention gets broken with a backspace, showing the mention suggestions menu once again. 7. Type a mention and select a user 8. Right after the new user mention, with a single space, start typing something else ("e.g. @daniel blah"). Make sure that the mention menu does NOT show up when cursor is at the end of "blah" 9. Right after the new user mention, with a single space, start typing a mention ("e.g. @daniel @jb"). Make sure the mention menu DOES show up, and suggests "@jb55" Changelog-Fixed: Fix inadvertent escape from mention suggestion menu when typing a space character Closes: https://github.com/damus-io/damus/issues/2008 Signed-off-by: Daniel D’Aquino --- damus/Views/TextViewWrapper.swift | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/damus/Views/TextViewWrapper.swift b/damus/Views/TextViewWrapper.swift index c3e87191..20ae430e 100644 --- a/damus/Views/TextViewWrapper.swift +++ b/damus/Views/TextViewWrapper.swift @@ -90,6 +90,7 @@ struct TextViewWrapper: UIViewRepresentable { let updateCursorPosition: ((Int) -> Void) let initialTextSuffix: String? var initialTextSuffixWasAdded: Bool = false + static let ESCAPE_SEQUENCES = ["\n", "@", " ", ", ", ". ", "! ", "? ", "; "] init(attributedText: Binding, getFocusWordForMention: ((String?, NSRange?) -> Void)?, @@ -142,17 +143,27 @@ struct TextViewWrapper: UIViewRepresentable { 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 { + let range = textView.textRange(from: previousPosition, to: position), + let text = textView.text(in: range), !text.isEmpty else { break } - - if [" ", "\n", "@"].contains(lastChar) { - break - } - + startPosition = previousPosition + + if let styling = textView.textStyling(at: previousPosition, in: .backward), + styling[NSAttributedString.Key.link] != nil { + break + } + + var found_escape_sequence = false + for escape_sequence in Self.ESCAPE_SEQUENCES { + if text.contains(escape_sequence) { + startPosition = textView.position(from: startPosition, offset: escape_sequence.count) ?? startPosition + found_escape_sequence = true + break + } + } + if found_escape_sequence { break } } return startPosition == position ? nil : textView.textRange(from: startPosition, to: position)