mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-24 23:25:19 +00:00
parse geohashes in messages
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
package com.bitchat.android.ui
|
||||
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
|
||||
/**
|
||||
* Utilities for parsing special tokens in chat messages (geohashes, etc.).
|
||||
*/
|
||||
object MessageSpecialParser {
|
||||
// Standalone geohash pattern like "#9q" or longer. Word boundaries enforced.
|
||||
// Geohash alphabet is base32: 0123456789bcdefghjkmnpqrstuvwxyz
|
||||
private val standaloneGeohashRegex = Regex("(^|[^A-Za-z0-9_#])#([0-9bcdefghjkmnpqrstuvwxyz]{2,})($|[^A-Za-z0-9_])", RegexOption.IGNORE_CASE)
|
||||
|
||||
data class GeohashMatch(val start: Int, val endExclusive: Int, val geohash: String)
|
||||
|
||||
/**
|
||||
* Finds standalone geohashes within [text]. A match is returned only when
|
||||
* the '#' token is not part of another word (e.g., not in '@anon#9qk2').
|
||||
*/
|
||||
fun findStandaloneGeohashes(text: String): List<GeohashMatch> {
|
||||
if (text.isEmpty()) return emptyList()
|
||||
val matches = mutableListOf<GeohashMatch>()
|
||||
var index = 0
|
||||
while (index < text.length) {
|
||||
val m = standaloneGeohashRegex.find(text, index) ?: break
|
||||
// Adjust to only cover the geohash token starting at '#'
|
||||
val fullRange = m.range
|
||||
// Find the '#' within this match substring
|
||||
val sub = text.substring(fullRange)
|
||||
val hashPos = sub.indexOf('#')
|
||||
if (hashPos >= 0) {
|
||||
val tokenStart = fullRange.first + hashPos
|
||||
// Consume '#' + geohash letters
|
||||
var cursor = tokenStart + 1
|
||||
while (cursor < text.length) {
|
||||
val ch = text[cursor].lowercaseChar()
|
||||
val isGeoChar = (ch in '0'..'9') || (ch in "bcdefghjkmnpqrstuvwxyz")
|
||||
if (!isGeoChar) break
|
||||
cursor++
|
||||
}
|
||||
val token = text.substring(tokenStart + 1, cursor)
|
||||
if (token.length >= 2) {
|
||||
matches.add(GeohashMatch(tokenStart, cursor, token.lowercase()))
|
||||
}
|
||||
index = cursor
|
||||
} else {
|
||||
index = fullRange.last + 1
|
||||
}
|
||||
}
|
||||
return matches
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user