-
Notifications
You must be signed in to change notification settings - Fork 5.7k
fix: enable composer autocorrect except on / @ # tokens #1690
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| import Foundation | ||
|
|
||
| /// When the composer should suppress system autocorrect. | ||
| /// | ||
| /// `/commands`, `@mentions`, and `#geohash` tokens need the exact typed text | ||
| /// for autocomplete. Prose should still get autocorrect. The token under the | ||
| /// cursor is the substring after the last whitespace before `cursor`. | ||
| enum ComposerAutocorrectPolicy { | ||
| static func shouldDisable(for text: String, cursor: Int) -> Bool { | ||
| guard let first = currentToken(in: text, cursor: cursor).first else { return false } | ||
| return first == "/" || first == "@" || first == "#" | ||
| } | ||
|
|
||
| static func currentToken(in text: String, cursor: Int) -> String { | ||
| guard !text.isEmpty else { return "" } | ||
| let clamped = max(0, min(cursor, text.count)) | ||
| let idx = text.index(text.startIndex, offsetBy: clamped) | ||
| let before = text[..<idx] | ||
| if let lastWhitespace = before.lastIndex(where: { $0.isWhitespace }) { | ||
| return String(before[before.index(after: lastWhitespace)...]) | ||
| } | ||
| return String(before) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -76,7 +76,12 @@ struct ContentComposerView: View { | |
| .bitchatFont(size: 15) | ||
| .foregroundColor(palette.primary) | ||
| .focused(isTextFieldFocused) | ||
| .autocorrectionDisabled(true) | ||
| .autocorrectionDisabled( | ||
| ComposerAutocorrectPolicy.shouldDisable( | ||
| for: messageText, | ||
| cursor: messageText.count | ||
| ) | ||
|
Comment on lines
+80
to
+83
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a user moves the caret back into a token that is not at the end of the message—for example, editing Useful? React with 👍 / 👎. |
||
| ) | ||
| #if os(iOS) | ||
| .textInputAutocapitalization(.sentences) | ||
| #endif | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import Testing | ||
| @testable import bitchat | ||
|
|
||
| struct ComposerAutocorrectPolicyTests { | ||
| @Test func proseLeavesAutocorrectEnabled() { | ||
| #expect(!ComposerAutocorrectPolicy.shouldDisable(for: "hello there", cursor: 11)) | ||
| #expect(!ComposerAutocorrectPolicy.shouldDisable(for: "", cursor: 0)) | ||
| #expect(!ComposerAutocorrectPolicy.shouldDisable(for: "hello ", cursor: 6)) | ||
| } | ||
|
|
||
| @Test func commandMentionAndGeohashTokensDisableAutocorrect() { | ||
| #expect(ComposerAutocorrectPolicy.shouldDisable(for: "/msg", cursor: 4)) | ||
| #expect(ComposerAutocorrectPolicy.shouldDisable(for: "hi @al", cursor: 6)) | ||
| #expect(ComposerAutocorrectPolicy.shouldDisable(for: "see #u4pr", cursor: 9)) | ||
| } | ||
|
|
||
| @Test func completedCommandArgumentIsProseAgain() { | ||
| #expect(!ComposerAutocorrectPolicy.shouldDisable(for: "/msg alice", cursor: 10)) | ||
| } | ||
|
|
||
| @Test func currentTokenIsTheRunBeforeTheCursor() { | ||
| #expect(ComposerAutocorrectPolicy.currentToken(in: "hello /j", cursor: 8) == "/j") | ||
| #expect(ComposerAutocorrectPolicy.currentToken(in: "hello ", cursor: 6) == "") | ||
| #expect(ComposerAutocorrectPolicy.currentToken(in: "/msg", cursor: 2) == "/m") | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a valid token follows punctuation instead of whitespace, such as
hello,@alor(#u4pr, this returns the entire whitespace-delimited run and its first character is not@or#, so autocorrection is enabled. The existing mention and hashtag regexes recognize these substrings without requiring preceding whitespace, meaning this newly enables corrections for supported autocomplete/formatting tokens; locate the marker within the run or use the same token-boundary rules as those parsers.Useful? React with 👍 / 👎.