mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 03:45:21 +00:00
refactor
This commit is contained in:
@@ -598,42 +598,8 @@ class MainActivity : ComponentActivity() {
|
||||
PoWPreferenceManager.init(this@MainActivity)
|
||||
Log.d("MainActivity", "PoW preferences initialized")
|
||||
|
||||
// SIMPLIFIED: Initialize Location Notes Manager only (no separate counter)
|
||||
com.bitchat.android.nostr.LocationNotesManager.getInstance().initialize(
|
||||
relayManager = { com.bitchat.android.nostr.NostrRelayManager.getInstance(this@MainActivity) },
|
||||
subscribe = { filter, id, handler ->
|
||||
// CRITICAL FIX: Extract geohash properly from filter using getGeohash() method
|
||||
val geohashFromFilter = filter.getGeohash() ?: run {
|
||||
Log.e("MainActivity", "❌ Cannot extract geohash from filter for location notes")
|
||||
return@initialize id // Return subscription ID even on error
|
||||
}
|
||||
|
||||
Log.d("MainActivity", "📍 Location Notes subscribing to geohash: $geohashFromFilter")
|
||||
|
||||
com.bitchat.android.nostr.NostrRelayManager.getInstance(this@MainActivity).subscribeForGeohash(
|
||||
geohash = geohashFromFilter,
|
||||
filter = filter,
|
||||
id = id,
|
||||
handler = handler,
|
||||
includeDefaults = true,
|
||||
nRelays = 5
|
||||
)
|
||||
},
|
||||
unsubscribe = { id ->
|
||||
com.bitchat.android.nostr.NostrRelayManager.getInstance(this@MainActivity).unsubscribe(id)
|
||||
},
|
||||
sendEvent = { event, relayUrls ->
|
||||
if (relayUrls != null) {
|
||||
com.bitchat.android.nostr.NostrRelayManager.getInstance(this@MainActivity).sendEvent(event, relayUrls)
|
||||
} else {
|
||||
com.bitchat.android.nostr.NostrRelayManager.getInstance(this@MainActivity).sendEvent(event)
|
||||
}
|
||||
},
|
||||
deriveIdentity = { geohash ->
|
||||
com.bitchat.android.nostr.NostrIdentityBridge.deriveIdentity(geohash, this@MainActivity)
|
||||
}
|
||||
)
|
||||
Log.d("MainActivity", "✅ Location Notes Manager initialized")
|
||||
// Initialize Location Notes Manager (extracted to separate file)
|
||||
com.bitchat.android.nostr.LocationNotesInitializer.initialize(this@MainActivity)
|
||||
|
||||
// Ensure all permissions are still granted (user might have revoked in settings)
|
||||
if (!permissionManager.areAllPermissionsGranted()) {
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.bitchat.android.nostr
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
|
||||
/**
|
||||
* Initializer for LocationNotesManager with all dependencies
|
||||
* Extracts initialization logic from MainActivity for better separation of concerns
|
||||
*/
|
||||
object LocationNotesInitializer {
|
||||
|
||||
private const val TAG = "LocationNotesInitializer"
|
||||
|
||||
/**
|
||||
* Initialize LocationNotesManager with all required dependencies
|
||||
*
|
||||
* @param context Application context
|
||||
* @return true if initialization succeeded, false otherwise
|
||||
*/
|
||||
fun initialize(context: Context): Boolean {
|
||||
return try {
|
||||
LocationNotesManager.getInstance().initialize(
|
||||
relayManager = { NostrRelayManager.getInstance(context) },
|
||||
subscribe = { filter, id, handler ->
|
||||
// CRITICAL FIX: Extract geohash properly from filter using getGeohash() method
|
||||
val geohashFromFilter = filter.getGeohash() ?: run {
|
||||
Log.e(TAG, "❌ Cannot extract geohash from filter for location notes")
|
||||
return@initialize id // Return subscription ID even on error
|
||||
}
|
||||
|
||||
Log.d(TAG, "📍 Location Notes subscribing to geohash: $geohashFromFilter")
|
||||
|
||||
NostrRelayManager.getInstance(context).subscribeForGeohash(
|
||||
geohash = geohashFromFilter,
|
||||
filter = filter,
|
||||
id = id,
|
||||
handler = handler,
|
||||
includeDefaults = true,
|
||||
nRelays = 5
|
||||
)
|
||||
},
|
||||
unsubscribe = { id ->
|
||||
NostrRelayManager.getInstance(context).unsubscribe(id)
|
||||
},
|
||||
sendEvent = { event, relayUrls ->
|
||||
if (relayUrls != null) {
|
||||
NostrRelayManager.getInstance(context).sendEvent(event, relayUrls)
|
||||
} else {
|
||||
NostrRelayManager.getInstance(context).sendEvent(event)
|
||||
}
|
||||
},
|
||||
deriveIdentity = { geohash ->
|
||||
NostrIdentityBridge.deriveIdentity(geohash, context)
|
||||
}
|
||||
)
|
||||
Log.d(TAG, "✅ Location Notes Manager initialized")
|
||||
true
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "❌ Failed to initialize Location Notes Manager: ${e.message}", e)
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -535,16 +535,6 @@ private fun MainHeader(
|
||||
val context = androidx.compose.ui.platform.LocalContext.current
|
||||
val bookmarksStore = remember { com.bitchat.android.geohash.GeohashBookmarksStore.getInstance(context) }
|
||||
val bookmarks by bookmarksStore.bookmarks.observeAsState(emptyList())
|
||||
|
||||
// SIMPLIFIED: Get notes count directly from LocationNotesManager (no separate counter)
|
||||
val notesManager = remember { com.bitchat.android.nostr.LocationNotesManager.getInstance() }
|
||||
val notes by notesManager.notes.observeAsState(emptyList())
|
||||
val notesCount = notes.size
|
||||
|
||||
// Location channel manager for permission state
|
||||
val locationManager = remember { com.bitchat.android.geohash.LocationChannelManager.getInstance(context) }
|
||||
val permissionState by locationManager.permissionState.observeAsState()
|
||||
val locationPermissionGranted = permissionState == PermissionState.AUTHORIZED
|
||||
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
@@ -623,22 +613,11 @@ private fun MainHeader(
|
||||
}
|
||||
}
|
||||
|
||||
// Location Notes button (mesh only, when location is authorized)
|
||||
// iOS: Shows to the left of #mesh badge when in mesh mode and location permitted
|
||||
if (selectedLocationChannel is com.bitchat.android.geohash.ChannelID.Mesh && locationPermissionGranted) {
|
||||
val hasNotes = (notesCount ?: 0) > 0
|
||||
IconButton(
|
||||
onClick = onLocationNotesClick,
|
||||
modifier = Modifier.size(24.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Description, // "long.text.page.and.pencil" equivalent
|
||||
contentDescription = stringResource(R.string.cd_location_notes),
|
||||
modifier = Modifier.size(16.dp),
|
||||
tint = if (hasNotes) colorScheme.primary else Color.Gray
|
||||
)
|
||||
}
|
||||
}
|
||||
// Location Notes button (extracted to separate component)
|
||||
LocationNotesButton(
|
||||
viewModel = viewModel,
|
||||
onClick = onLocationNotesClick
|
||||
)
|
||||
|
||||
// Tor status dot when Tor is enabled
|
||||
TorStatusDot(
|
||||
|
||||
@@ -539,61 +539,12 @@ private fun ChatDialogs(
|
||||
)
|
||||
}
|
||||
|
||||
// Location notes sheet - matches iOS pattern exactly
|
||||
// Location notes sheet (extracted to separate presenter)
|
||||
if (showLocationNotesSheet) {
|
||||
val context = androidx.compose.ui.platform.LocalContext.current
|
||||
val locationManager = remember { com.bitchat.android.geohash.LocationChannelManager.getInstance(context) }
|
||||
val availableChannels by locationManager.availableChannels.observeAsState(emptyList())
|
||||
val nickname by viewModel.nickname.observeAsState("")
|
||||
|
||||
// iOS pattern: notesGeohash ?? LocationChannelManager.shared.availableChannels.first(where: { $0.level == .building })?.geohash
|
||||
val buildingGeohash = availableChannels.firstOrNull { it.level == com.bitchat.android.geohash.GeohashChannelLevel.BUILDING }?.geohash
|
||||
|
||||
if (buildingGeohash != null) {
|
||||
// Get location name from locationManager
|
||||
val locationNames by locationManager.locationNames.observeAsState(emptyMap())
|
||||
val locationName = locationNames[com.bitchat.android.geohash.GeohashChannelLevel.BUILDING]
|
||||
?: locationNames[com.bitchat.android.geohash.GeohashChannelLevel.BLOCK]
|
||||
|
||||
LocationNotesSheet(
|
||||
geohash = buildingGeohash,
|
||||
locationName = locationName,
|
||||
nickname = nickname,
|
||||
onDismiss = onLocationNotesSheetDismiss
|
||||
)
|
||||
} else {
|
||||
// No building geohash available - show error state (matches iOS)
|
||||
ModalBottomSheet(
|
||||
onDismissRequest = onLocationNotesSheetDismiss,
|
||||
containerColor = MaterialTheme.colorScheme.surface
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(24.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text(
|
||||
text = "Location Unavailable",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
color = MaterialTheme.colorScheme.onSurface
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Text(
|
||||
text = "Location permission is required for notes",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
Button(onClick = {
|
||||
locationManager.enableLocationChannels()
|
||||
locationManager.refreshChannels()
|
||||
}) {
|
||||
Text("Enable Location")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LocationNotesSheetPresenter(
|
||||
viewModel = viewModel,
|
||||
onDismiss = onLocationNotesSheetDismiss
|
||||
)
|
||||
}
|
||||
|
||||
// User action sheet
|
||||
|
||||
@@ -594,69 +594,7 @@ class ChatViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SIMPLIFIED: Initialize location notes manager subscription (no separate counter)
|
||||
* Subscribes/unsubscribes based on channel selection and location permission
|
||||
*/
|
||||
private fun initializeLocationNotesManagerSubscription() {
|
||||
viewModelScope.launch {
|
||||
// Observe channel changes
|
||||
selectedLocationChannel.observeForever { channel ->
|
||||
updateLocationNotesSubscription(channel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SIMPLIFIED: Update location notes subscription based on current channel and location permission
|
||||
* iOS pattern: Subscribe when in mesh mode and location is authorized
|
||||
*/
|
||||
private fun updateLocationNotesSubscription(channel: com.bitchat.android.geohash.ChannelID?) {
|
||||
try {
|
||||
val locationManager = com.bitchat.android.geohash.LocationChannelManager.getInstance(getApplication())
|
||||
val permissionState = locationManager.permissionState.value
|
||||
val locationPermissionGranted = permissionState == com.bitchat.android.geohash.LocationChannelManager.PermissionState.AUTHORIZED
|
||||
|
||||
when (channel) {
|
||||
is com.bitchat.android.geohash.ChannelID.Mesh -> {
|
||||
// Mesh mode: subscribe to building-level geohash notes if location authorized
|
||||
if (locationPermissionGranted) {
|
||||
// Refresh location to get current building geohash
|
||||
locationManager.refreshChannels()
|
||||
|
||||
// Get building-level geohash (precision 8, same as iOS)
|
||||
val buildingGeohash = locationManager.availableChannels.value
|
||||
?.firstOrNull { it.level == com.bitchat.android.geohash.GeohashChannelLevel.BUILDING }
|
||||
?.geohash
|
||||
|
||||
if (buildingGeohash != null) {
|
||||
Log.d(TAG, "📍 Subscribing to location notes for building geohash: $buildingGeohash")
|
||||
com.bitchat.android.nostr.LocationNotesManager.getInstance().setGeohash(buildingGeohash)
|
||||
} else {
|
||||
// Cancel if no building geohash available
|
||||
if (com.bitchat.android.nostr.LocationNotesManager.getInstance().geohash.value == null) {
|
||||
com.bitchat.android.nostr.LocationNotesManager.getInstance().cancel()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
com.bitchat.android.nostr.LocationNotesManager.getInstance().cancel()
|
||||
}
|
||||
}
|
||||
is com.bitchat.android.geohash.ChannelID.Location -> {
|
||||
// Location channel mode: cancel (only show in mesh mode)
|
||||
com.bitchat.android.nostr.LocationNotesManager.getInstance().cancel()
|
||||
}
|
||||
null -> {
|
||||
// Default to mesh behavior
|
||||
if (locationPermissionGranted) {
|
||||
locationManager.refreshChannels()
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "updateLocationNotesSubscription failed: ${e.message}")
|
||||
}
|
||||
}
|
||||
// Location notes subscription management moved to LocationNotesViewModelExtensions.kt
|
||||
|
||||
/**
|
||||
* Update reactive states for all connected peers (session states, fingerprints, nicknames, RSSI)
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.bitchat.android.ui
|
||||
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Description
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.bitchat.android.R
|
||||
import com.bitchat.android.geohash.ChannelID
|
||||
import com.bitchat.android.geohash.LocationChannelManager
|
||||
import com.bitchat.android.nostr.LocationNotesManager
|
||||
|
||||
/**
|
||||
* Location Notes button component for MainHeader
|
||||
* Displays when in mesh mode and location permission is granted
|
||||
* Icon turns primary color when notes exist, gray otherwise
|
||||
*/
|
||||
@Composable
|
||||
fun LocationNotesButton(
|
||||
viewModel: ChatViewModel,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
val context = LocalContext.current
|
||||
|
||||
// Get channel and permission state
|
||||
val selectedLocationChannel by viewModel.selectedLocationChannel.observeAsState()
|
||||
val locationManager = remember { LocationChannelManager.getInstance(context) }
|
||||
val permissionState by locationManager.permissionState.observeAsState()
|
||||
val locationPermissionGranted = permissionState == LocationChannelManager.PermissionState.AUTHORIZED
|
||||
|
||||
// Get notes count from LocationNotesManager
|
||||
val notesManager = remember { LocationNotesManager.getInstance() }
|
||||
val notes by notesManager.notes.observeAsState(emptyList())
|
||||
val notesCount = notes.size
|
||||
|
||||
// Only show in mesh mode when location is authorized (iOS pattern)
|
||||
if (selectedLocationChannel is ChannelID.Mesh && locationPermissionGranted) {
|
||||
val hasNotes = (notesCount ?: 0) > 0
|
||||
IconButton(
|
||||
onClick = onClick,
|
||||
modifier = modifier.size(24.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Description, // "long.text.page.and.pencil" equivalent
|
||||
contentDescription = stringResource(R.string.cd_location_notes),
|
||||
modifier = Modifier.size(16.dp),
|
||||
tint = if (hasNotes) colorScheme.primary else Color.Gray
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.bitchat.android.ui
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.bitchat.android.geohash.GeohashChannelLevel
|
||||
import com.bitchat.android.geohash.LocationChannelManager
|
||||
|
||||
/**
|
||||
* Presenter component for LocationNotesSheet
|
||||
* Handles sheet presentation logic with proper error states
|
||||
* Extracts this logic from ChatScreen for better separation of concerns
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun LocationNotesSheetPresenter(
|
||||
viewModel: ChatViewModel,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val locationManager = remember { LocationChannelManager.getInstance(context) }
|
||||
val availableChannels by locationManager.availableChannels.observeAsState(emptyList())
|
||||
val nickname by viewModel.nickname.observeAsState("")
|
||||
|
||||
// iOS pattern: notesGeohash ?? LocationChannelManager.shared.availableChannels.first(where: { $0.level == .building })?.geohash
|
||||
val buildingGeohash = availableChannels.firstOrNull { it.level == GeohashChannelLevel.BUILDING }?.geohash
|
||||
|
||||
if (buildingGeohash != null) {
|
||||
// Get location name from locationManager
|
||||
val locationNames by locationManager.locationNames.observeAsState(emptyMap())
|
||||
val locationName = locationNames[GeohashChannelLevel.BUILDING]
|
||||
?: locationNames[GeohashChannelLevel.BLOCK]
|
||||
|
||||
LocationNotesSheet(
|
||||
geohash = buildingGeohash,
|
||||
locationName = locationName,
|
||||
nickname = nickname,
|
||||
onDismiss = onDismiss
|
||||
)
|
||||
} else {
|
||||
// No building geohash available - show error state (matches iOS)
|
||||
LocationNotesErrorSheet(
|
||||
onDismiss = onDismiss,
|
||||
locationManager = locationManager
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Error sheet when location is unavailable
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun LocationNotesErrorSheet(
|
||||
onDismiss: () -> Unit,
|
||||
locationManager: LocationChannelManager
|
||||
) {
|
||||
ModalBottomSheet(
|
||||
onDismissRequest = onDismiss,
|
||||
containerColor = MaterialTheme.colorScheme.surface
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(24.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text(
|
||||
text = "Location Unavailable",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
color = MaterialTheme.colorScheme.onSurface
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Text(
|
||||
text = "Location permission is required for notes",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
Button(onClick = {
|
||||
locationManager.enableLocationChannels()
|
||||
locationManager.refreshChannels()
|
||||
}) {
|
||||
Text("Enable Location")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.bitchat.android.ui
|
||||
|
||||
import android.app.Application
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.bitchat.android.geohash.ChannelID
|
||||
import com.bitchat.android.geohash.GeohashChannelLevel
|
||||
import com.bitchat.android.geohash.LocationChannelManager
|
||||
import com.bitchat.android.nostr.LocationNotesManager
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
* Extension functions for ChatViewModel to manage LocationNotesManager subscription
|
||||
* Extracts location notes subscription logic for better separation of concerns
|
||||
*/
|
||||
|
||||
private const val TAG = "LocationNotesVM"
|
||||
|
||||
/**
|
||||
* Initialize location notes manager subscription (no separate counter)
|
||||
* Subscribes/unsubscribes based on channel selection and location permission
|
||||
*/
|
||||
fun ChatViewModel.initializeLocationNotesManagerSubscription() {
|
||||
viewModelScope.launch {
|
||||
// Observe channel changes
|
||||
selectedLocationChannel.observeForever { channel ->
|
||||
updateLocationNotesSubscription(channel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update location notes subscription based on current channel and location permission
|
||||
* iOS pattern: Subscribe when in mesh mode and location is authorized
|
||||
*/
|
||||
private fun ChatViewModel.updateLocationNotesSubscription(channel: ChannelID?) {
|
||||
try {
|
||||
val locationManager = LocationChannelManager.getInstance(getApplication<Application>())
|
||||
val permissionState = locationManager.permissionState.value
|
||||
val locationPermissionGranted = permissionState == LocationChannelManager.PermissionState.AUTHORIZED
|
||||
|
||||
when (channel) {
|
||||
is ChannelID.Mesh -> {
|
||||
// Mesh mode: subscribe to building-level geohash notes if location authorized
|
||||
if (locationPermissionGranted) {
|
||||
// Refresh location to get current building geohash
|
||||
locationManager.refreshChannels()
|
||||
|
||||
// Get building-level geohash (precision 8, same as iOS)
|
||||
val buildingGeohash = locationManager.availableChannels.value
|
||||
?.firstOrNull { it.level == GeohashChannelLevel.BUILDING }
|
||||
?.geohash
|
||||
|
||||
if (buildingGeohash != null) {
|
||||
Log.d(TAG, "📍 Subscribing to location notes for building geohash: $buildingGeohash")
|
||||
LocationNotesManager.getInstance().setGeohash(buildingGeohash)
|
||||
} else {
|
||||
// Cancel if no building geohash available
|
||||
if (LocationNotesManager.getInstance().geohash.value == null) {
|
||||
LocationNotesManager.getInstance().cancel()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LocationNotesManager.getInstance().cancel()
|
||||
}
|
||||
}
|
||||
is ChannelID.Location -> {
|
||||
// Location channel mode: cancel (only show in mesh mode)
|
||||
LocationNotesManager.getInstance().cancel()
|
||||
}
|
||||
null -> {
|
||||
// Default to mesh behavior
|
||||
if (locationPermissionGranted) {
|
||||
locationManager.refreshChannels()
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "updateLocationNotesSubscription failed: ${e.message}")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user