mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 17:45:20 +00:00
simplify and tor icon change
This commit is contained in:
@@ -598,36 +598,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
PoWPreferenceManager.init(this@MainActivity)
|
PoWPreferenceManager.init(this@MainActivity)
|
||||||
Log.d("MainActivity", "PoW preferences initialized")
|
Log.d("MainActivity", "PoW preferences initialized")
|
||||||
|
|
||||||
// Initialize Location Notes Counter (iOS parity)
|
// SIMPLIFIED: Initialize Location Notes Manager only (no separate counter)
|
||||||
com.bitchat.android.nostr.LocationNotesCounter.initialize(
|
|
||||||
relayManager = { com.bitchat.android.nostr.NostrRelayManager.getInstance(this@MainActivity) },
|
|
||||||
subscribe = { filter, id, handler ->
|
|
||||||
// CRITICAL FIX: Extract geohash properly from filter (not from debug string!)
|
|
||||||
val geohashFromFilter = filter.getGeohash() ?: run {
|
|
||||||
Log.e("MainActivity", "Cannot extract geohash from filter for location notes counter")
|
|
||||||
""
|
|
||||||
}
|
|
||||||
|
|
||||||
if (geohashFromFilter.isNotEmpty()) {
|
|
||||||
com.bitchat.android.nostr.NostrRelayManager.getInstance(this@MainActivity).subscribeForGeohash(
|
|
||||||
geohash = geohashFromFilter,
|
|
||||||
filter = filter,
|
|
||||||
id = id,
|
|
||||||
handler = handler,
|
|
||||||
includeDefaults = true,
|
|
||||||
nRelays = 5
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
},
|
|
||||||
unsubscribe = { id ->
|
|
||||||
com.bitchat.android.nostr.NostrRelayManager.getInstance(this@MainActivity).unsubscribe(id)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
Log.d("MainActivity", "Location Notes Counter initialized")
|
|
||||||
|
|
||||||
// CRITICAL FIX: Initialize Location Notes Manager (iOS parity)
|
|
||||||
com.bitchat.android.nostr.LocationNotesManager.getInstance().initialize(
|
com.bitchat.android.nostr.LocationNotesManager.getInstance().initialize(
|
||||||
relayManager = { com.bitchat.android.nostr.NostrRelayManager.getInstance(this@MainActivity) },
|
relayManager = { com.bitchat.android.nostr.NostrRelayManager.getInstance(this@MainActivity) },
|
||||||
subscribe = { filter, id, handler ->
|
subscribe = { filter, id, handler ->
|
||||||
|
|||||||
@@ -1,187 +0,0 @@
|
|||||||
package com.bitchat.android.nostr
|
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.lifecycle.LiveData
|
|
||||||
import androidx.lifecycle.MutableLiveData
|
|
||||||
import kotlinx.coroutines.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Lightweight counter for location notes
|
|
||||||
* Singleton manager for counting unique notes per geohash
|
|
||||||
* iOS-compatible implementation
|
|
||||||
*/
|
|
||||||
object LocationNotesCounter {
|
|
||||||
|
|
||||||
private const val TAG = "LocationNotesCounter"
|
|
||||||
|
|
||||||
// Published state
|
|
||||||
private val _geohash = MutableLiveData<String?>(null)
|
|
||||||
val geohash: LiveData<String?> = _geohash
|
|
||||||
|
|
||||||
private val _count = MutableLiveData(0)
|
|
||||||
val count: LiveData<Int> = _count
|
|
||||||
|
|
||||||
private val _initialLoadComplete = MutableLiveData(false)
|
|
||||||
val initialLoadComplete: LiveData<Boolean> = _initialLoadComplete
|
|
||||||
|
|
||||||
private val _relayAvailable = MutableLiveData(false)
|
|
||||||
val relayAvailable: LiveData<Boolean> = _relayAvailable
|
|
||||||
|
|
||||||
// Private state
|
|
||||||
private var subscriptionID: String? = null
|
|
||||||
private val eventIDs = mutableSetOf<String>() // For deduplication
|
|
||||||
|
|
||||||
// Dependencies (injected)
|
|
||||||
private var relayLookup: (() -> NostrRelayManager)? = null
|
|
||||||
private var subscribeFunc: ((NostrFilter, String, (NostrEvent) -> Unit) -> String)? = null
|
|
||||||
private var unsubscribeFunc: ((String) -> Unit)? = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize dependencies
|
|
||||||
*/
|
|
||||||
fun initialize(
|
|
||||||
relayManager: () -> NostrRelayManager,
|
|
||||||
subscribe: (NostrFilter, String, (NostrEvent) -> Unit) -> String,
|
|
||||||
unsubscribe: (String) -> Unit
|
|
||||||
) {
|
|
||||||
this.relayLookup = relayManager
|
|
||||||
this.subscribeFunc = subscribe
|
|
||||||
this.unsubscribeFunc = unsubscribe
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subscribe to count notes for a specific geohash
|
|
||||||
* iOS: Validates building-level precision (8 chars) and checks for relay availability
|
|
||||||
*/
|
|
||||||
fun subscribe(geohash: String) {
|
|
||||||
val normalized = geohash.lowercase()
|
|
||||||
|
|
||||||
// Skip if already subscribed to this geohash
|
|
||||||
if (_geohash.value == normalized && subscriptionID != null) {
|
|
||||||
Log.d(TAG, "Already subscribed to geohash: $normalized")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate geohash (building-level precision: 8 chars) - matches iOS
|
|
||||||
if (!isValidBuildingGeohash(normalized)) {
|
|
||||||
Log.w(TAG, "LocationNotesCounter: rejecting invalid geohash '$normalized' (expected 8 valid base32 chars)")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.d(TAG, "Subscribing to count notes for geohash: $normalized")
|
|
||||||
|
|
||||||
// Unsubscribe previous without clearing count to avoid flicker (iOS pattern)
|
|
||||||
subscriptionID?.let { subId ->
|
|
||||||
unsubscribeFunc?.invoke(subId)
|
|
||||||
}
|
|
||||||
subscriptionID = null
|
|
||||||
|
|
||||||
// Reset state
|
|
||||||
_geohash.value = normalized
|
|
||||||
eventIDs.clear()
|
|
||||||
_initialLoadComplete.value = false
|
|
||||||
_relayAvailable.value = true
|
|
||||||
|
|
||||||
// Get geo-specific relays (iOS pattern: dependencies.relayLookup(norm, TransportConfig.nostrGeoRelayCount))
|
|
||||||
val relays = try {
|
|
||||||
com.bitchat.android.nostr.RelayDirectory.closestRelaysForGeohash(normalized, 5)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e(TAG, "Failed to lookup relays for geohash $normalized: ${e.message}")
|
|
||||||
emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we have relays (iOS pattern: guard !relays.isEmpty())
|
|
||||||
if (relays.isEmpty()) {
|
|
||||||
Log.w(TAG, "LocationNotesCounter: no geo relays for geohash=$normalized")
|
|
||||||
_relayAvailable.value = false
|
|
||||||
_initialLoadComplete.value = true
|
|
||||||
_count.value = 0
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val subscribe = subscribeFunc
|
|
||||||
if (subscribe == null) {
|
|
||||||
Log.e(TAG, "Cannot subscribe - subscribe function not initialized")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val filter = NostrFilter.geohashNotes(
|
|
||||||
geohash = normalized,
|
|
||||||
since = null,
|
|
||||||
limit = 200 // Count up to 200 recent notes
|
|
||||||
)
|
|
||||||
|
|
||||||
// iOS format: "locnotes-count-\(norm)-\(UUID().uuidString.prefix(6))"
|
|
||||||
val subId = "locnotes-count-$normalized-${java.util.UUID.randomUUID().toString().take(6)}"
|
|
||||||
|
|
||||||
subscriptionID = subscribe(filter, subId) { event ->
|
|
||||||
handleEvent(event, normalized)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark initial load complete after brief delay
|
|
||||||
kotlinx.coroutines.MainScope().launch {
|
|
||||||
kotlinx.coroutines.delay(1500)
|
|
||||||
if (!_initialLoadComplete.value!!) {
|
|
||||||
_initialLoadComplete.value = true
|
|
||||||
Log.d(TAG, "Initial count load complete: ${_count.value} notes")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate building-level geohash (precision 8) - matches iOS Geohash.isValidBuildingGeohash
|
|
||||||
*/
|
|
||||||
private fun isValidBuildingGeohash(geohash: String): Boolean {
|
|
||||||
if (geohash.length != 8) return false
|
|
||||||
val base32Chars = "0123456789bcdefghjkmnpqrstuvwxyz"
|
|
||||||
return geohash.all { it in base32Chars }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle incoming event
|
|
||||||
*/
|
|
||||||
private fun handleEvent(event: NostrEvent, expectedGeohash: String) {
|
|
||||||
// Validate event
|
|
||||||
if (event.kind != NostrKind.TEXT_NOTE) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for geohash tag
|
|
||||||
val geohashTag = event.tags.firstOrNull { it.size >= 2 && it[0] == "g" }
|
|
||||||
if (geohashTag == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if matches expected geohash
|
|
||||||
val eventGeohash = geohashTag[1]
|
|
||||||
if (eventGeohash != expectedGeohash) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deduplicate and count
|
|
||||||
if (!eventIDs.contains(event.id)) {
|
|
||||||
eventIDs.add(event.id)
|
|
||||||
_count.value = eventIDs.size
|
|
||||||
|
|
||||||
if (!_initialLoadComplete.value!!) {
|
|
||||||
_initialLoadComplete.value = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancel subscription
|
|
||||||
*/
|
|
||||||
fun cancel() {
|
|
||||||
subscriptionID?.let { subId ->
|
|
||||||
Log.d(TAG, "🚫 Canceling counter subscription: $subId")
|
|
||||||
unsubscribeFunc?.invoke(subId)
|
|
||||||
subscriptionID = null
|
|
||||||
}
|
|
||||||
|
|
||||||
_geohash.value = null
|
|
||||||
_count.value = 0
|
|
||||||
eventIDs.clear()
|
|
||||||
_initialLoadComplete.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -29,6 +29,8 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.bitchat.android.core.ui.utils.singleOrTripleClickable
|
import com.bitchat.android.core.ui.utils.singleOrTripleClickable
|
||||||
import com.bitchat.android.geohash.LocationChannelManager.PermissionState
|
import com.bitchat.android.geohash.LocationChannelManager.PermissionState
|
||||||
|
import androidx.compose.foundation.Canvas
|
||||||
|
import androidx.compose.ui.geometry.Offset
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Header components for ChatScreen
|
* Header components for ChatScreen
|
||||||
@@ -54,24 +56,28 @@ fun isFavoriteReactive(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TorStatusIcon(
|
fun TorStatusDot(
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val torStatus by com.bitchat.android.net.TorManager.statusFlow.collectAsState()
|
val torStatus by com.bitchat.android.net.TorManager.statusFlow.collectAsState()
|
||||||
|
|
||||||
if (torStatus.mode != com.bitchat.android.net.TorMode.OFF) {
|
if (torStatus.mode != com.bitchat.android.net.TorMode.OFF) {
|
||||||
val cableColor = when {
|
val dotColor = when {
|
||||||
torStatus.running && torStatus.bootstrapPercent < 100 -> Color(0xFFFF9500)
|
torStatus.running && torStatus.bootstrapPercent < 100 -> Color(0xFFFF9500) // Orange - bootstrapping
|
||||||
torStatus.running && torStatus.bootstrapPercent >= 100 -> Color(0xFF00C851)
|
torStatus.running && torStatus.bootstrapPercent >= 100 -> Color(0xFF00C851) // Green - connected
|
||||||
else -> Color.Red
|
else -> Color.Red // Red - error/disconnected
|
||||||
}
|
}
|
||||||
Icon(
|
Canvas(
|
||||||
imageVector = Icons.Outlined.Cable,
|
modifier = modifier
|
||||||
contentDescription = stringResource(R.string.cd_tor_status),
|
) {
|
||||||
modifier = modifier,
|
val radius = size.minDimension / 2
|
||||||
tint = cableColor
|
drawCircle(
|
||||||
|
color = dotColor,
|
||||||
|
radius = radius,
|
||||||
|
center = Offset(size.width / 2, size.height / 2)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -156,6 +162,10 @@ fun NicknameEditor(
|
|||||||
.widthIn(max = 120.dp)
|
.widthIn(max = 120.dp)
|
||||||
.horizontalScroll(scrollState)
|
.horizontalScroll(scrollState)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Tor status dot - constant distance from nickname end
|
||||||
|
Spacer(modifier = Modifier.width(6.dp))
|
||||||
|
TorStatusDot(modifier = Modifier.size(6.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,9 +540,10 @@ private fun MainHeader(
|
|||||||
val bookmarksStore = remember { com.bitchat.android.geohash.GeohashBookmarksStore.getInstance(context) }
|
val bookmarksStore = remember { com.bitchat.android.geohash.GeohashBookmarksStore.getInstance(context) }
|
||||||
val bookmarks by bookmarksStore.bookmarks.observeAsState(emptyList())
|
val bookmarks by bookmarksStore.bookmarks.observeAsState(emptyList())
|
||||||
|
|
||||||
// Location notes counter (iOS parity)
|
// SIMPLIFIED: Get notes count directly from LocationNotesManager (no separate counter)
|
||||||
val notesCounter = remember { com.bitchat.android.nostr.LocationNotesCounter }
|
val notesManager = remember { com.bitchat.android.nostr.LocationNotesManager.getInstance() }
|
||||||
val notesCount by notesCounter.count.observeAsState(0)
|
val notes by notesManager.notes.observeAsState(emptyList())
|
||||||
|
val notesCount = notes.size
|
||||||
|
|
||||||
// Location channel manager for permission state
|
// Location channel manager for permission state
|
||||||
val locationManager = remember { com.bitchat.android.geohash.LocationChannelManager.getInstance(context) }
|
val locationManager = remember { com.bitchat.android.geohash.LocationChannelManager.getInstance(context) }
|
||||||
@@ -633,9 +644,6 @@ private fun MainHeader(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tor status cable icon when Tor is enabled
|
|
||||||
TorStatusIcon(modifier = Modifier.size(14.dp))
|
|
||||||
|
|
||||||
// PoW status indicator
|
// PoW status indicator
|
||||||
PoWStatusIndicator(
|
PoWStatusIndicator(
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
|
|||||||
@@ -148,8 +148,8 @@ class ChatViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize location notes counter subscription management (iOS parity)
|
// SIMPLIFIED: Initialize location notes manager subscription (no separate counter)
|
||||||
initializeLocationNotesCounterSubscription()
|
initializeLocationNotesManagerSubscription()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun cancelMediaSend(messageId: String) {
|
fun cancelMediaSend(messageId: String) {
|
||||||
@@ -595,24 +595,23 @@ class ChatViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize location notes counter subscription management (iOS parity)
|
* SIMPLIFIED: Initialize location notes manager subscription (no separate counter)
|
||||||
* Subscribes/unsubscribes based on channel selection and location permission
|
* Subscribes/unsubscribes based on channel selection and location permission
|
||||||
*/
|
*/
|
||||||
private fun initializeLocationNotesCounterSubscription() {
|
private fun initializeLocationNotesManagerSubscription() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
// Observe channel changes
|
// Observe channel changes
|
||||||
selectedLocationChannel.observeForever { channel ->
|
selectedLocationChannel.observeForever { channel ->
|
||||||
updateNotesCounterSubscription(channel)
|
updateLocationNotesSubscription(channel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update notes counter subscription based on current channel and location permission
|
* SIMPLIFIED: Update location notes subscription based on current channel and location permission
|
||||||
* iOS pattern: Subscribe when in mesh mode and location is authorized
|
* iOS pattern: Subscribe when in mesh mode and location is authorized
|
||||||
* ENHANCEMENT: Also subscribe LocationNotesManager to load actual notes in background
|
|
||||||
*/
|
*/
|
||||||
private fun updateNotesCounterSubscription(channel: com.bitchat.android.geohash.ChannelID?) {
|
private fun updateLocationNotesSubscription(channel: com.bitchat.android.geohash.ChannelID?) {
|
||||||
try {
|
try {
|
||||||
val locationManager = com.bitchat.android.geohash.LocationChannelManager.getInstance(getApplication())
|
val locationManager = com.bitchat.android.geohash.LocationChannelManager.getInstance(getApplication())
|
||||||
val permissionState = locationManager.permissionState.value
|
val permissionState = locationManager.permissionState.value
|
||||||
@@ -620,9 +619,9 @@ class ChatViewModel(
|
|||||||
|
|
||||||
when (channel) {
|
when (channel) {
|
||||||
is com.bitchat.android.geohash.ChannelID.Mesh -> {
|
is com.bitchat.android.geohash.ChannelID.Mesh -> {
|
||||||
// Mesh mode: subscribe to block-level geohash notes if location authorized
|
// Mesh mode: subscribe to building-level geohash notes if location authorized
|
||||||
if (locationPermissionGranted) {
|
if (locationPermissionGranted) {
|
||||||
// Refresh location to get current block geohash
|
// Refresh location to get current building geohash
|
||||||
locationManager.refreshChannels()
|
locationManager.refreshChannels()
|
||||||
|
|
||||||
// Get building-level geohash (precision 8, same as iOS)
|
// Get building-level geohash (precision 8, same as iOS)
|
||||||
@@ -632,25 +631,19 @@ class ChatViewModel(
|
|||||||
|
|
||||||
if (buildingGeohash != null) {
|
if (buildingGeohash != null) {
|
||||||
Log.d(TAG, "📍 Subscribing to location notes for building geohash: $buildingGeohash")
|
Log.d(TAG, "📍 Subscribing to location notes for building geohash: $buildingGeohash")
|
||||||
// Subscribe counter for badge
|
|
||||||
com.bitchat.android.nostr.LocationNotesCounter.subscribe(buildingGeohash)
|
|
||||||
// ALSO subscribe manager to load actual notes in background
|
|
||||||
com.bitchat.android.nostr.LocationNotesManager.getInstance().setGeohash(buildingGeohash)
|
com.bitchat.android.nostr.LocationNotesManager.getInstance().setGeohash(buildingGeohash)
|
||||||
} else {
|
} else {
|
||||||
// Keep existing subscription if we had one (avoid flicker)
|
// Cancel if no building geohash available
|
||||||
if (com.bitchat.android.nostr.LocationNotesCounter.geohash.value == null) {
|
if (com.bitchat.android.nostr.LocationNotesManager.getInstance().geohash.value == null) {
|
||||||
com.bitchat.android.nostr.LocationNotesCounter.cancel()
|
|
||||||
com.bitchat.android.nostr.LocationNotesManager.getInstance().cancel()
|
com.bitchat.android.nostr.LocationNotesManager.getInstance().cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
com.bitchat.android.nostr.LocationNotesCounter.cancel()
|
|
||||||
com.bitchat.android.nostr.LocationNotesManager.getInstance().cancel()
|
com.bitchat.android.nostr.LocationNotesManager.getInstance().cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is com.bitchat.android.geohash.ChannelID.Location -> {
|
is com.bitchat.android.geohash.ChannelID.Location -> {
|
||||||
// Location channel mode: cancel counter (only show in mesh mode)
|
// Location channel mode: cancel (only show in mesh mode)
|
||||||
com.bitchat.android.nostr.LocationNotesCounter.cancel()
|
|
||||||
com.bitchat.android.nostr.LocationNotesManager.getInstance().cancel()
|
com.bitchat.android.nostr.LocationNotesManager.getInstance().cancel()
|
||||||
}
|
}
|
||||||
null -> {
|
null -> {
|
||||||
@@ -661,7 +654,7 @@ class ChatViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.w(TAG, "updateNotesCounterSubscription failed: ${e.message}")
|
Log.w(TAG, "updateLocationNotesSubscription failed: ${e.message}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.bitchat.android.geohash.GeohashChannelLevel
|
import com.bitchat.android.geohash.GeohashChannelLevel
|
||||||
import com.bitchat.android.geohash.LocationChannelManager
|
import com.bitchat.android.geohash.LocationChannelManager
|
||||||
import com.bitchat.android.nostr.LocationNotesCounter
|
|
||||||
import com.bitchat.android.nostr.LocationNotesManager
|
import com.bitchat.android.nostr.LocationNotesManager
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -52,16 +51,17 @@ fun LocationNotesSheet(
|
|||||||
|
|
||||||
// Managers
|
// Managers
|
||||||
val notesManager = remember { LocationNotesManager.getInstance() }
|
val notesManager = remember { LocationNotesManager.getInstance() }
|
||||||
val counter = remember { LocationNotesCounter }
|
|
||||||
val locationManager = remember { LocationChannelManager.getInstance(context) }
|
val locationManager = remember { LocationChannelManager.getInstance(context) }
|
||||||
|
|
||||||
// State
|
// State
|
||||||
val notes by notesManager.notes.observeAsState(emptyList())
|
val notes by notesManager.notes.observeAsState(emptyList())
|
||||||
val state by notesManager.state.observeAsState(LocationNotesManager.State.IDLE)
|
val state by notesManager.state.observeAsState(LocationNotesManager.State.IDLE)
|
||||||
val errorMessage by notesManager.errorMessage.observeAsState()
|
val errorMessage by notesManager.errorMessage.observeAsState()
|
||||||
val count by counter.count.observeAsState(0)
|
|
||||||
val initialLoadComplete by notesManager.initialLoadComplete.observeAsState(false)
|
val initialLoadComplete by notesManager.initialLoadComplete.observeAsState(false)
|
||||||
|
|
||||||
|
// SIMPLIFIED: Get count directly from notes list (no separate counter needed)
|
||||||
|
val count = notes.size
|
||||||
|
|
||||||
// Get location name (building or block) - matches iOS locationNames lookup
|
// Get location name (building or block) - matches iOS locationNames lookup
|
||||||
val locationNames by locationManager.locationNames.observeAsState(emptyMap())
|
val locationNames by locationManager.locationNames.observeAsState(emptyMap())
|
||||||
val displayLocationName = locationNames[GeohashChannelLevel.BUILDING]?.takeIf { it.isNotEmpty() }
|
val displayLocationName = locationNames[GeohashChannelLevel.BUILDING]?.takeIf { it.isNotEmpty() }
|
||||||
@@ -77,7 +77,6 @@ fun LocationNotesSheet(
|
|||||||
// Effect to set geohash when sheet opens
|
// Effect to set geohash when sheet opens
|
||||||
LaunchedEffect(geohash) {
|
LaunchedEffect(geohash) {
|
||||||
notesManager.setGeohash(geohash)
|
notesManager.setGeohash(geohash)
|
||||||
counter.subscribe(geohash)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup when sheet closes
|
// Cleanup when sheet closes
|
||||||
|
|||||||
Reference in New Issue
Block a user