Skip to content

Commit 7f45ca4

Browse files
committed
feat: rework android mentions with space
1 parent 42ca7f7 commit 7f45ca4

2 files changed

Lines changed: 40 additions & 12 deletions

File tree

android/src/main/java/com/swmansion/enriched/styles/ParametrizedStyles.kt

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ class ParametrizedStyles(private val view: EnrichedTextInputView) {
8585
}
8686
}
8787

88-
private fun getWordAtIndex(s: Editable, index: Int): TextRange? {
88+
private fun getWordAtIndex(s: CharSequence, index: Int): TextRange? {
8989
if (index < 0 ) return null
9090

9191
var start = index
@@ -141,33 +141,57 @@ class ParametrizedStyles(private val view: EnrichedTextInputView) {
141141
}
142142
}
143143

144-
private fun afterTextChangedMentions(result: TextRange) {
144+
private fun afterTextChangedMentions(currentWord: TextRange) {
145145
val mentionHandler = view.mentionHandler ?: return
146146
val spannable = view.text as Spannable
147-
val (word, start, end) = result
148147

149148
val indicatorsPattern = mentionIndicators.joinToString("|") { Regex.escape(it) }
150149
val mentionIndicatorRegex = Regex("^($indicatorsPattern)")
151150
val mentionRegex= Regex("^($indicatorsPattern)\\w*")
152151

153-
val spans = spannable.getSpans(start, end, EnrichedMentionSpan::class.java)
152+
val spans = spannable.getSpans(currentWord.start, currentWord.end, EnrichedMentionSpan::class.java)
154153
for (span in spans) {
155154
spannable.removeSpan(span)
156155
}
157156

158-
if (mentionRegex.matches(word)) {
159-
val indicator = mentionIndicatorRegex.find(word)?.value ?: ""
160-
val text = word.replaceFirst(indicator, "")
157+
var indicator: String
158+
var finalStart: Int
159+
val finalEnd = currentWord.end
160+
161+
// No mention in the current word, check previous one
162+
if (!mentionRegex.matches(currentWord.text)) {
163+
val previousWord = getWordAtIndex(spannable, currentWord.start - 1)
164+
165+
// No previous word -> no mention to be detected
166+
if (previousWord == null) {
167+
mentionHandler.endMention()
168+
return
169+
}
161170

162-
// Means we are starting mention
163-
if (text.isEmpty()) {
164-
mentionStart = start
171+
// Previous word is not a mention -> end mention
172+
if (!mentionRegex.matches(previousWord.text)) {
173+
mentionHandler.endMention()
174+
return
165175
}
166176

167-
mentionHandler.onMention(indicator, text)
177+
// Previous word is a mention -> use it
178+
finalStart = previousWord.start
179+
indicator = mentionIndicatorRegex.find(previousWord.text)?.value ?: ""
168180
} else {
169-
mentionHandler.endMention()
181+
// Current word is a mention -> use it
182+
finalStart = currentWord.start
183+
indicator = mentionIndicatorRegex.find(currentWord.text)?.value ?: ""
170184
}
185+
186+
// Extract text without indicator
187+
val text = spannable.subSequence(finalStart, finalEnd).toString().replaceFirst(indicator, "")
188+
189+
// Means we are starting mention
190+
if (text.isEmpty()) {
191+
mentionStart = finalStart
192+
}
193+
194+
mentionHandler.onMention(indicator, text)
171195
}
172196

173197
fun setImageSpan(src: String) {

example/src/useChannelMention.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ const MOCKED_DATA = [
1313
id: '3',
1414
name: 'Engineering',
1515
},
16+
{
17+
id: '4',
18+
name: 'Private channel',
19+
},
1620
];
1721

1822
export const useChannelMention = () => {

0 commit comments

Comments
 (0)