@@ -3183,12 +3183,28 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
31833183 let token = String ( matchText. dropFirst ( ) ) . lowercased ( )
31843184 let allowed = Set ( " 0123456789bcdefghjkmnpqrstuvwxyz " )
31853185 let isGeohash = ( 2 ... 12 ) . contains ( token. count) && token. allSatisfy { allowed. contains ( $0) }
3186+ // Do not link if this hashtag is directly attached to an @mention (e.g., @name#geohash)
3187+ let attachedToMention : Bool = {
3188+ // nsRange is the Range<String.Index> for this match within content
3189+ // Walk left until whitespace/newline; if we encounter '@' first, treat as part of mention
3190+ if nsRange. lowerBound > content. startIndex {
3191+ var i = content. index ( before: nsRange. lowerBound)
3192+ while true {
3193+ let ch = content [ i]
3194+ if ch. isWhitespace || ch. isNewline { break }
3195+ if ch == " @ " { return true }
3196+ if i == content. startIndex { break }
3197+ i = content. index ( before: i)
3198+ }
3199+ }
3200+ return false
3201+ } ( )
31863202 var tagStyle = AttributeContainer ( )
31873203 tagStyle. font = isSelf
31883204 ? . system( size: 14 , weight: . bold, design: . monospaced)
31893205 : . system( size: 14 , design: . monospaced)
31903206 tagStyle. foregroundColor = baseColor
3191- if isGeohash, let url = URL ( string: " bitchat://geohash/ \( token) " ) {
3207+ if isGeohash && !attachedToMention , let url = URL ( string: " bitchat://geohash/ \( token) " ) {
31923208 tagStyle. link = url
31933209 tagStyle. underlineStyle = . single
31943210 }
0 commit comments