android, desktop, ios: cap memberMentions at MAX so stale cache entries cannot overflow the server limit

With the sticky cache, manually typing an @name that happens to match a
stale cache entry could push memberMentions above maxSndMentions and have
the core reject the send with SEInvalidMention. The getter now walks
parsedMessage in text order and stops at MAX_NUMBER_OF_MENTIONS; later
@-tokens past the cap become visual-only formatting and the message still
goes through. Also hoists the iOS activeMentions computation out of the
per-row ForEach so it runs once per picker open rather than once per row.
This commit is contained in:
Narasimha-sc committed 2026-05-28 16:16:44 +00:00
1 parent 56ba1d0821
commit 3dc0c09d49
3 files changed
+19 -17

No files matched your search

@@ -134,12 +134,15 @@ struct ComposeState {
}
var memberMentions: [String: Int64] {
let usedMentions: Set<String> = Set(parsedMessage.compactMap { ft in
if case let .mention(n) = ft.format { n } else { nil }
})
return self.mentions
.filter { usedMentions.contains($0.key) }
.compactMapValues { $0.memberRef?.groupMemberId }
var result: [String: Int64] = [:]
for ft in parsedMessage {
if result.count >= MAX_NUMBER_OF_MENTIONS { break }
guard case let .mention(name) = ft.format else { continue }
if result[name] != nil { continue }
guard let id = self.mentions[name]?.memberRef?.groupMemberId else { continue }
result[name] = id
}
return result
}
var editing: Bool {
@@ -43,11 +43,11 @@ struct GroupMentionsView: View {
VStack(spacing: 0) {
Spacer()
Divider()
let activeMentions = composeState.parsedMessage.reduce(0) { n, ft in if case .mention = ft.format { n + 1 } else { n } }
let scroll = ScrollView {
LazyVStack(spacing: 0) {
ForEach(Array(filtered.enumerated()), id: \.element.wrapped.groupMemberId) { index, member in
let mentioned = mentionMemberId == member.wrapped.memberId
let activeMentions = composeState.parsedMessage.reduce(0) { n, ft in if case .mention = ft.format { n + 1 } else { n } }
let disabled = activeMentions >= MAX_NUMBER_OF_MENTIONS && !mentioned
ZStack(alignment: .bottom) {
memberRowView(member.wrapped, mentioned)
@@ -132,16 +132,15 @@ data class ComposeState(
val memberMentions: Map<String, Long>
get() {
val usedMentions = this.parsedMessage.mapNotNull { (it.format as? Format.Mention)?.memberName }.toSet()
return this.mentions.mapNotNull {
val memberRef = it.value.memberRef
if (memberRef != null && it.key in usedMentions) {
it.key to memberRef.groupMemberId
} else {
null
}
}.toMap()
val result = mutableMapOf<String, Long>()
for (ft in parsedMessage) {
if (result.size >= MAX_NUMBER_OF_MENTIONS) break
val name = (ft.format as? Format.Mention)?.memberName ?: continue
if (name in result) continue
val id = mentions[name]?.memberRef?.groupMemberId ?: continue
result[name] = id
}
return result
}
val editing: Boolean