Fix and Improve LocationManager logic (#599)

* location manager improvements

* fix: resolve compilation errors and improve location state handling

- Fix missing imports and stray braces in LocationChannelManager
- Implement checkSystemLocationEnabled and BroadcastReceiver for location state
- Order class members for correct initialization
- Consolidate UI refresh logic in LocationChannelsSheet

* fix: guard against stale geocoding results on legacy devices

- Add isActive check after blocking Geocoder.getFromLocation call
- Prevent stale results from overwriting state after job cancellation
This commit is contained in:
callebtc
2026-01-15 11:11:56 +07:00
committed by GitHub
parent e769a03634
commit 5ec02c99fd
4 changed files with 191 additions and 169 deletions
@@ -63,7 +63,9 @@ fun LocationChannelsSheet(
val availableChannels by locationManager.availableChannels.collectAsStateWithLifecycle()
val selectedChannel by locationManager.selectedChannel.collectAsStateWithLifecycle()
val locationNames by locationManager.locationNames.collectAsStateWithLifecycle()
val locationServicesEnabled by locationManager.locationServicesEnabled.collectAsStateWithLifecycle()
val appLocationEnabled by locationManager.locationServicesEnabled.collectAsStateWithLifecycle()
val systemLocationEnabled by locationManager.systemLocationEnabled.collectAsStateWithLifecycle()
val locationServicesEnabled by locationManager.effectiveLocationEnabled.collectAsStateWithLifecycle()
// Observe bookmarks state
val bookmarks by bookmarksStore.bookmarks.collectAsStateWithLifecycle()
@@ -162,24 +164,7 @@ fun LocationChannelsSheet(
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
when (permissionState) {
LocationChannelManager.PermissionState.NOT_DETERMINED -> {
Button(
onClick = { locationManager.enableLocationChannels() },
colors = ButtonDefaults.buttonColors(
containerColor = standardGreen.copy(alpha = 0.12f),
contentColor = standardGreen
),
modifier = Modifier.fillMaxWidth()
) {
Text(
text = stringResource(R.string.grant_location_permission),
fontSize = 12.sp,
fontFamily = FontFamily.Monospace
)
}
}
LocationChannelManager.PermissionState.DENIED,
LocationChannelManager.PermissionState.RESTRICTED -> {
LocationChannelManager.PermissionState.DENIED -> {
Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
Text(
text = stringResource(R.string.location_permission_denied),
@@ -211,20 +196,6 @@ fun LocationChannelsSheet(
color = standardGreen
)
}
null -> {
Row(
horizontalArrangement = Arrangement.spacedBy(4.dp),
verticalAlignment = Alignment.CenterVertically
) {
CircularProgressIndicator(modifier = Modifier.size(12.dp))
Text(
text = stringResource(R.string.checking_permissions),
fontSize = 11.sp,
fontFamily = FontFamily.Monospace,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f)
)
}
}
}
}
}
@@ -562,34 +533,27 @@ fun LocationChannelsSheet(
}
}
// Lifecycle management: when presented, sample both nearby and bookmarked geohashes
// Lifecycle management: when presented, manage location updates
DisposableEffect(isPresented, permissionState, locationServicesEnabled) {
if (isPresented && permissionState == LocationChannelManager.PermissionState.AUTHORIZED && locationServicesEnabled) {
locationManager.refreshChannels()
locationManager.beginLiveRefresh()
}
onDispose {
locationManager.endLiveRefresh()
}
}
// Sampling management: update sampling when channels/bookmarks change
LaunchedEffect(isPresented, availableChannels, bookmarks) {
if (isPresented) {
if (permissionState == LocationChannelManager.PermissionState.AUTHORIZED && locationServicesEnabled) {
locationManager.refreshChannels()
locationManager.beginLiveRefresh()
}
val geohashes = (availableChannels.map { it.geohash } + bookmarks).toSet().toList()
viewModel.beginGeohashSampling(geohashes)
} else {
locationManager.endLiveRefresh()
viewModel.endGeohashSampling()
}
}
// React to permission changes
LaunchedEffect(permissionState) {
if (permissionState == LocationChannelManager.PermissionState.AUTHORIZED && locationServicesEnabled) {
locationManager.refreshChannels()
}
}
// React to location services enable/disable
LaunchedEffect(locationServicesEnabled) {
if (locationServicesEnabled && permissionState == LocationChannelManager.PermissionState.AUTHORIZED) {
locationManager.refreshChannels()
}
}
}
@Composable