refactor(map): remove fixed zoom level for offline downloads (#694)

This commit is contained in:
Andre K 2023-08-27 06:31:27 -03:00 committed by GitHub
parent 80cee441c6
commit ef11af6e0b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 30 additions and 175 deletions

View file

@ -1,25 +0,0 @@
package com.geeksville.mesh.model.map
import android.view.MotionEvent
import org.osmdroid.views.MapView
import org.osmdroid.views.overlay.DefaultOverlayManager
import org.osmdroid.views.overlay.TilesOverlay
/**
* CustomOverlayManager with disabled double taps events
*/
class CustomOverlayManager(tilesOverlay: TilesOverlay?) : DefaultOverlayManager(tilesOverlay) {
/**
* Override event & do nothing
*/
override fun onDoubleTap(e: MotionEvent?, pMapView: MapView?): Boolean {
return true
}
/**
* Override event & do nothing
*/
override fun onDoubleTapEvent(e: MotionEvent?, pMapView: MapView?): Boolean {
return true
}
}

View file

@ -49,7 +49,6 @@ import com.geeksville.mesh.android.hasLocationPermission
import com.geeksville.mesh.copy
import com.geeksville.mesh.database.entity.Packet
import com.geeksville.mesh.model.UIViewModel
import com.geeksville.mesh.model.map.CustomOverlayManager
import com.geeksville.mesh.model.map.CustomTileSource
import com.geeksville.mesh.model.map.MarkerWithLabel
import com.geeksville.mesh.ui.ScreenFragment
@ -69,6 +68,9 @@ import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.delay
import org.osmdroid.config.Configuration
import org.osmdroid.events.MapEventsReceiver
import org.osmdroid.events.MapListener
import org.osmdroid.events.ScrollEvent
import org.osmdroid.events.ZoomEvent
import org.osmdroid.tileprovider.cachemanager.CacheManager
import org.osmdroid.tileprovider.modules.SqliteArchiveTileWriter
import org.osmdroid.tileprovider.tilesource.ITileSource
@ -119,16 +121,9 @@ fun MapView(model: UIViewModel = viewModel()) {
var cacheEstimate by remember { mutableStateOf("") }
// constants
val defaultMinZoom = 1.5
val defaultMaxZoom = 18.0
val prefsName = "org.geeksville.osm.prefs"
val mapStyleId = "map_style_id"
// Distance of bottom corner to top corner of bounding box
val zoomLevelLowest = 13.0 // approx 5 miles long
val zoomLevelMiddle = 12.25 // approx 10 miles long
val zoomLevelHighest = 11.5 // approx 15 miles long
var zoomLevelMin = 0.0
var zoomLevelMax = 0.0
@ -488,6 +483,7 @@ fun MapView(model: UIViewModel = viewModel()) {
val id = mPrefs.getInt(mapStyleId, 1)
debug("mapStyleId from prefs: $id")
return CustomTileSource.getTileSource(id).also {
map.maxZoomLevel = it.maximumZoomLevel.toDouble()
showDownloadButton =
if (it is OnlineTileSourceBase) it.tileSourcePolicy.acceptsBulkDownload() else false
}
@ -496,18 +492,11 @@ fun MapView(model: UIViewModel = viewModel()) {
/**
* Creates Box overlay showing what area can be downloaded
*/
fun MapView.generateBoxOverlay(zoomLevel: Double) {
if (overlayManager !is CustomOverlayManager) {
overlayManager = CustomOverlayManager(TilesOverlay(tileProvider, context))
setMultiTouchControls(false)
zoomLevelMax = tileProvider.tileSource.maximumZoomLevel.toDouble()
drawOverlays()
} else {
overlays.removeAll(overlays.filterIsInstance<Polygon>())
}
fun MapView.generateBoxOverlay() {
overlays.removeAll(overlays.filterIsInstance<Polygon>())
val zoomFactor = 1.3 // zoom difference between view and download area polygon
controller.setZoom(zoomLevel - zoomFactor)
zoomLevelMin = zoomLevel
zoomLevelMax = maxZoomLevel
zoomLevelMin = maxOf(zoomLevelDouble, maxZoomLevel)
downloadRegionBoundingBox = boundingBox.zoomIn(zoomFactor)
val polygon = Polygon().apply {
points = Polygon.pointsAsRect(downloadRegionBoundingBox).map {
@ -518,7 +507,7 @@ fun MapView(model: UIViewModel = viewModel()) {
val tileCount: Int = CacheManager(this).possibleTilesInArea(
downloadRegionBoundingBox,
zoomLevelMin.toInt(),
zoomLevelMax.toInt()
zoomLevelMax.toInt(),
)
cacheEstimate = context.getString(R.string.map_cache_tiles, tileCount)
}
@ -577,7 +566,7 @@ fun MapView(model: UIViewModel = viewModel()) {
when (which) {
0 -> showCurrentCacheInfo = true
1 -> {
map.generateBoxOverlay(zoomLevelHighest)
map.generateBoxOverlay()
dialog.dismiss()
}
@ -615,17 +604,25 @@ fun MapView(model: UIViewModel = viewModel()) {
// 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 = defaultMinZoom
maxZoomLevel = defaultMaxZoom
minZoomLevel = 1.5
// Disables default +/- button for zooming
zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER)
addMapListener(object : MapListener {
override fun onScroll(event: ScrollEvent): Boolean {
if (downloadRegionBoundingBox != null) generateBoxOverlay()
return true
}
override fun onZoom(event: ZoomEvent): Boolean {
return false
}
})
zoomToNodes()
}
},
modifier = Modifier.fillMaxSize(),
update = { map ->
if (downloadRegionBoundingBox == null) map.drawOverlays()
else map.generateBoxOverlay(zoomLevelMin)
},
)
if (downloadRegionBoundingBox != null) CacheLayout(
@ -633,10 +630,7 @@ fun MapView(model: UIViewModel = viewModel()) {
onExecuteJob = { startDownload() },
onCancelDownload = {
downloadRegionBoundingBox = null
map.apply {
overlayManager = DefaultOverlayManager(TilesOverlay(tileProvider, context))
setMultiTouchControls(true)
}
map.overlays.removeAll(map.overlays.filterIsInstance<Polygon>())
},
modifier = Modifier.align(Alignment.BottomCenter)
) else Column(

View file

@ -8,23 +8,16 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.ContentAlpha
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.geeksville.mesh.R
@ -36,8 +29,6 @@ fun CacheLayout(
onCancelDownload: () -> Unit,
modifier: Modifier = Modifier,
) {
var selectedDistance by remember { mutableStateOf(5) }
Column(
modifier = modifier
.fillMaxWidth()
@ -50,106 +41,55 @@ fun CacheLayout(
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.h5,
color = MaterialTheme.colors.onBackground.copy(alpha = ContentAlpha.medium)
color = MaterialTheme.colors.onBackground.copy(alpha = ContentAlpha.medium),
)
Spacer(modifier = Modifier.height(8.dp))
val distances = listOf(5, 10, 15)
val selectedDistanceIndex = distances.indexOf(selectedDistance)
// ToggleButton(
// options = distances.map { it.toString() },
// selectedOptionIndex = selectedDistanceIndex,
// onOptionSelected = { selectedDistance = distances[it] },
// )
// Spacer(modifier = Modifier.height(16.dp))
Text(
text = stringResource(R.string.map_tile_download_estimate) + " " + cacheEstimate,
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.body1,
color = MaterialTheme.colors.onBackground.copy(alpha = ContentAlpha.medium)
color = MaterialTheme.colors.onBackground.copy(alpha = ContentAlpha.medium),
)
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
horizontalArrangement = Arrangement.SpaceBetween,
) {
Button(
onClick = onCancelDownload,
modifier = Modifier
.weight(1f)
.padding(start = 8.dp)
.padding(start = 8.dp),
) {
Text(
text = stringResource(id = R.string.cancel),
color = MaterialTheme.colors.onPrimary
color = MaterialTheme.colors.onPrimary,
)
}
Button(
onClick = onExecuteJob,
modifier = Modifier
.weight(1f)
.padding(end = 8.dp)
.padding(end = 8.dp),
) {
Text(
text = stringResource(id = R.string.map_start_download),
color = MaterialTheme.colors.onPrimary
color = MaterialTheme.colors.onPrimary,
)
}
}
}
}
@Composable
fun ToggleButton(
options: List<String>,
selectedOptionIndex: Int,
onOptionSelected: (Int) -> Unit
) {
val backgroundColor = MaterialTheme.colors.background
val selectedColor = MaterialTheme.colors.primary
val textColor = MaterialTheme.colors.onBackground.copy(alpha = ContentAlpha.medium)
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
options.forEachIndexed { index, option ->
val isSelected = index == selectedOptionIndex
Button(
onClick = { onOptionSelected(index) },
colors = ButtonDefaults.buttonColors(
backgroundColor = if (isSelected) selectedColor else backgroundColor,
contentColor = textColor
),
modifier = Modifier.weight(1f)
) {
Text(
text = option,
textAlign = TextAlign.Center,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
if (index != options.lastIndex) {
Spacer(modifier = Modifier.width(8.dp))
}
}
}
}
@Preview(showBackground = true)
@Composable
private fun CacheLayoutPreview() {
CacheLayout(
cacheEstimate = "100 tiles",
onExecuteJob = { },
onCancelDownload = { }
onCancelDownload = { },
)
}