fix/2552 Calculate initial mapView from filtered node list (#2553)

This commit is contained in:
Tristan Waddington 2025-07-29 11:00:08 -07:00 committed by GitHub
parent 2b5a2be48d
commit ca02624ad0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 45 additions and 42 deletions

View file

@ -452,15 +452,6 @@ constructor(
initialValue = 0,
)
val filteredNodeList: StateFlow<List<Node>> =
nodeList
.mapLatest { list -> list.filter { node -> !node.isIgnored } }
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = emptyList(),
)
data class MapFilterState(val onlyFavorites: Boolean, val showWaypoints: Boolean, val showPrecisionCircle: Boolean)
val mapFilterStateFlow: StateFlow<MapFilterState> =

View file

@ -249,11 +249,13 @@ fun MapView(model: UIViewModel = viewModel(), navigateToNodeDetails: (Int) -> Un
}
}
val cameraView = remember {
val geoPoints = model.nodesWithPosition.map { GeoPoint(it.latitude, it.longitude) }
val initialCameraView = remember {
val nodes = model.nodeList.value
val nodesWithPosition = nodes.filter { it.validPosition != null }
val geoPoints = nodesWithPosition.map { GeoPoint(it.latitude, it.longitude) }
BoundingBox.fromGeoPoints(geoPoints)
}
val map = rememberMapViewWithLifecycle(cameraView, loadOnlineTileSourceBase())
val map = rememberMapViewWithLifecycle(initialCameraView, loadOnlineTileSourceBase())
val nodeClusterer = remember { RadiusMarkerClusterer(context) }
@ -297,7 +299,7 @@ fun MapView(model: UIViewModel = viewModel(), navigateToNodeDetails: (Int) -> Un
}
}
val nodes by model.filteredNodeList.collectAsStateWithLifecycle()
val nodes by model.nodeList.collectAsStateWithLifecycle()
val waypoints by model.waypoints.collectAsStateWithLifecycle(emptyMap())
val markerIcon = remember { AppCompatResources.getDrawable(context, R.drawable.ic_baseline_location_on_24) }

View file

@ -46,56 +46,67 @@ import org.osmdroid.views.MapView
@SuppressLint("WakelockTimeout")
private fun PowerManager.WakeLock.safeAcquire() {
if (!isHeld) try {
acquire()
} catch (e: SecurityException) {
errormsg("WakeLock permission exception: ${e.message}")
} catch (e: IllegalStateException) {
errormsg("WakeLock acquire() exception: ${e.message}")
if (!isHeld) {
try {
acquire()
} catch (e: SecurityException) {
errormsg("WakeLock permission exception: ${e.message}")
} catch (e: IllegalStateException) {
errormsg("WakeLock acquire() exception: ${e.message}")
}
}
}
private fun PowerManager.WakeLock.safeRelease() {
if (isHeld) try {
release()
} catch (e: IllegalStateException) {
errormsg("WakeLock release() exception: ${e.message}")
if (isHeld) {
try {
release()
} catch (e: IllegalStateException) {
errormsg("WakeLock release() exception: ${e.message}")
}
}
}
const val MAP_STYLE_ID = "map_style_id"
private const val MinZoomLevel = 1.5
private const val MaxZoomLevel = 20.0
private const val DefaultZoomLevel = 15.0
private const val MIN_ZOOM_LEVEL = 1.5
private const val MAX_ZOOM_LEVEL = 20.0
private const val DEFAULT_ZOOM_LEVEL = 15.0
@Suppress("MagicNumber")
@Composable
internal fun rememberMapViewWithLifecycle(
box: BoundingBox,
tileSource: ITileSource = TileSourceFactory.DEFAULT_TILE_SOURCE,
): MapView {
val zoom = if (box.requiredZoomLevel().isFinite()) {
box.requiredZoomLevel()
} else {
DefaultZoomLevel
}
val zoom =
if (box.requiredZoomLevel().isFinite()) {
(box.requiredZoomLevel() - 0.5).coerceAtLeast(MIN_ZOOM_LEVEL)
} else {
DEFAULT_ZOOM_LEVEL
}
val center = GeoPoint(box.centerLatitude, box.centerLongitude)
return rememberMapViewWithLifecycle(zoom, center, tileSource)
}
@Suppress("LongMethod")
@Composable
internal fun rememberMapViewWithLifecycle(
zoomLevel: Double = MinZoomLevel,
zoomLevel: Double = MIN_ZOOM_LEVEL,
mapCenter: GeoPoint = GeoPoint(0.0, 0.0),
tileSource: ITileSource = TileSourceFactory.DEFAULT_TILE_SOURCE,
): MapView {
var savedZoom by rememberSaveable { mutableDoubleStateOf(zoomLevel) }
var savedCenter by rememberSaveable(
stateSaver = Saver(
save = { mapOf("latitude" to it.latitude, "longitude" to it.longitude) },
restore = { GeoPoint(it["latitude"] ?: 0.0, it["longitude"] ?: .0) }
)
) { mutableStateOf(mapCenter) }
var savedCenter by
rememberSaveable(
stateSaver =
Saver(
save = { mapOf("latitude" to it.latitude, "longitude" to it.longitude) },
restore = { GeoPoint(it["latitude"] ?: 0.0, it["longitude"] ?: .0) },
),
) {
mutableStateOf(mapCenter)
}
val context = LocalContext.current
val mapView = remember {
@ -112,8 +123,8 @@ internal fun rememberMapViewWithLifecycle(
// scales the map tiles to the display density of the screen
isTilesScaledToDpi = true
// sets the minimum zoom level (the furthest out you can zoom)
minZoomLevel = MinZoomLevel
maxZoomLevel = MaxZoomLevel
minZoomLevel = MIN_ZOOM_LEVEL
maxZoomLevel = MAX_ZOOM_LEVEL
// Disables default +/- button for zooming
zoomController.setVisibility(CustomZoomButtonsController.Visibility.SHOW_AND_FADEOUT)
@ -126,8 +137,7 @@ internal fun rememberMapViewWithLifecycle(
val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
@Suppress("DEPRECATION")
val wakeLock =
powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "Meshtastic:MapViewLock")
val wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "Meshtastic:MapViewLock")
wakeLock.safeAcquire()