From 03de6f3519df77bcc7dca8cd3fd80f3be861a880 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Wed, 29 Jul 2026 20:21:12 +0200 Subject: [PATCH] fix: allow targeting polar geohashes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Relaxes the view-center clamp from ±80° to ±89°. Previously opening or tapping a geohash above 80°N/S clamped the fly-in and syncSelection() encoded the clamped center, silently returning a different cell than the user picked. Verified with p2 (87°N) and p6 (85°S) cells: the view now centers on the requested cell and selects it correctly. --- .../java/com/bitchat/android/ui/globe/GlobeState.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/bitchat/android/ui/globe/GlobeState.kt b/app/src/main/java/com/bitchat/android/ui/globe/GlobeState.kt index f50a33ff..6908c716 100644 --- a/app/src/main/java/com/bitchat/android/ui/globe/GlobeState.kt +++ b/app/src/main/java/com/bitchat/android/ui/globe/GlobeState.kt @@ -76,7 +76,7 @@ class GlobeState( if (r <= 0f) return val degPerPx = 180.0 / (Math.PI * r) centerLon = GlobeMath.normalizeLon(centerLon - dxPx * degPerPx).toFloat() - centerLat = (centerLat + dyPx * degPerPx).toFloat().coerceIn(-80f, 80f) + centerLat = (centerLat + dyPx * degPerPx).toFloat().coerceIn(MIN_LAT, MAX_LAT) syncSelection() } @@ -112,7 +112,7 @@ class GlobeState( val anim = Animatable(0f) anim.animateTo(1f, tween(durationMs, easing = FastOutSlowInEasing)) { val t = value - centerLat = (startLat + (lat.toFloat() - startLat) * t).coerceIn(-80f, 80f) + centerLat = (startLat + (lat.toFloat() - startLat) * t).coerceIn(MIN_LAT, MAX_LAT) centerLon = GlobeMath.normalizeLon(startLon + dLon * t).toFloat() // exponential interpolation feels natural for zoom zoom = startZoom * (endZoom / startZoom).pow(t) @@ -170,6 +170,13 @@ class GlobeState( animJob?.cancel() } + private companion object { + // Close to the projection limit so polar geohash cells remain selectable; + // clamping tighter would make syncSelection() encode the wrong cell. + const val MIN_LAT = -89f + const val MAX_LAT = 89f + } + private fun syncSelection() { if (baseRadiusPx <= 0f) return val gh = Geohash.encode(centerLat.toDouble(), centerLon.toDouble(), precision)