summaryrefslogtreecommitdiff
path: root/android-app/app/src
diff options
context:
space:
mode:
Diffstat (limited to 'android-app/app/src')
-rw-r--r--android-app/app/src/main/kotlin/org/terst/nav/MainActivity.kt37
-rw-r--r--android-app/app/src/main/kotlin/org/terst/nav/ui/MainViewModel.kt15
2 files changed, 36 insertions, 16 deletions
diff --git a/android-app/app/src/main/kotlin/org/terst/nav/MainActivity.kt b/android-app/app/src/main/kotlin/org/terst/nav/MainActivity.kt
index 5e7ce82..1752fe8 100644
--- a/android-app/app/src/main/kotlin/org/terst/nav/MainActivity.kt
+++ b/android-app/app/src/main/kotlin/org/terst/nav/MainActivity.kt
@@ -60,6 +60,7 @@ class MainActivity : AppCompatActivity(), SafetyFragment.SafetyListener {
private lateinit var layerManager: MapLayerManager
private var particleWindView: ParticleWindView? = null
private var weatherLoaded = false
+ private var cameraIdleJob: kotlinx.coroutines.Job? = null
private lateinit var bottomSheetBehavior: BottomSheetBehavior<View>
private lateinit var fragmentContainer: FrameLayout
@@ -492,23 +493,27 @@ class MainActivity : AppCompatActivity(), SafetyFragment.SafetyListener {
}
maplibreMap.addOnCameraIdleListener {
- val corners = listOfNotNull(
- maplibreMap.projection.visibleRegion.nearLeft,
- maplibreMap.projection.visibleRegion.nearRight,
- maplibreMap.projection.visibleRegion.farLeft,
- maplibreMap.projection.visibleRegion.farRight
- )
- if (corners.size == 4) {
- viewModel.loadWindGrid(
- corners.minOf { it.latitude }, corners.maxOf { it.latitude },
- corners.minOf { it.longitude }, corners.maxOf { it.longitude }
+ cameraIdleJob?.cancel()
+ cameraIdleJob = lifecycleScope.launch {
+ kotlinx.coroutines.delay(1_500)
+ val corners = listOfNotNull(
+ maplibreMap.projection.visibleRegion.nearLeft,
+ maplibreMap.projection.visibleRegion.nearRight,
+ maplibreMap.projection.visibleRegion.farLeft,
+ maplibreMap.projection.visibleRegion.farRight
)
- }
- maplibreMap.cameraPosition.target?.let { center ->
- // Only refresh conditions when the user has manually panned —
- // in following mode the GPS handler already triggers the load.
- if (mapHandler?.isFollowing?.value == false) {
- viewModel.loadConditions(center.latitude, center.longitude)
+ if (corners.size == 4) {
+ viewModel.loadWindGrid(
+ corners.minOf { it.latitude }, corners.maxOf { it.latitude },
+ corners.minOf { it.longitude }, corners.maxOf { it.longitude }
+ )
+ }
+ maplibreMap.cameraPosition.target?.let { center ->
+ // Only refresh conditions when the user has manually panned —
+ // in following mode the GPS handler already triggers the load.
+ if (mapHandler?.isFollowing?.value == false) {
+ viewModel.loadConditions(center.latitude, center.longitude)
+ }
}
}
}
diff --git a/android-app/app/src/main/kotlin/org/terst/nav/ui/MainViewModel.kt b/android-app/app/src/main/kotlin/org/terst/nav/ui/MainViewModel.kt
index 88689e0..530af39 100644
--- a/android-app/app/src/main/kotlin/org/terst/nav/ui/MainViewModel.kt
+++ b/android-app/app/src/main/kotlin/org/terst/nav/ui/MainViewModel.kt
@@ -236,6 +236,10 @@ class MainViewModel(
private var lastConditionsLon = Double.NaN
private var lastConditionsMs = 0L
+ private var lastWindGridLat = Double.NaN
+ private var lastWindGridLon = Double.NaN
+ private var lastWindGridMs = 0L
+
/**
* Fetches current conditions snapshot for [lat]/[lon] and exposes it via [marineConditions].
* Throttled: skips if conditions loaded < 5 min ago and position < 2 nm from last load.
@@ -312,9 +316,20 @@ class MainViewModel(
/**
* Fetch wind arrows for a 4×5 grid covering the visible map bounds.
+ * Throttled: skips if grid center < 10 nm from last fetch and < 15 min old.
* Fires-and-forgets; silently ignores network failures (grid is decorative).
*/
fun loadWindGrid(latMin: Double, latMax: Double, lonMin: Double, lonMax: Double) {
+ val centerLat = (latMin + latMax) / 2.0
+ val centerLon = (lonMin + lonMax) / 2.0
+ val nowMs = System.currentTimeMillis()
+ val ageMs = nowMs - lastWindGridMs
+ val distNm = if (lastWindGridLat.isNaN()) Double.MAX_VALUE
+ else distanceNm(lastWindGridLat, lastWindGridLon, centerLat, centerLon)
+ if (ageMs < 15 * 60_000L && distNm < 10.0) return
+ lastWindGridLat = centerLat
+ lastWindGridLon = centerLon
+ lastWindGridMs = nowMs
viewModelScope.launch {
val points = buildGrid(latMin, latMax, lonMin, lonMax, cols = 4, rows = 5)
repository.fetchWindGrid(points).getOrNull()?.let { _windGrid.value = it }