summaryrefslogtreecommitdiff
path: root/android-app/app
diff options
context:
space:
mode:
authorClaude <noreply@anthropic.com>2026-04-11 09:48:52 +0000
committerClaude <noreply@anthropic.com>2026-04-11 09:48:52 +0000
commit3ddf436958ffde3198492895725fc0ca8ab0a1b2 (patch)
tree4406784c833a04a0a8e49fe2c75a379c8c95dc5e /android-app/app
parent021bc2418d698fe2fc08e108bcba85d609dfed4b (diff)
Show loading spinners next to each instrument value during conditions fetch
- Add _conditionsLoading StateFlow to MainViewModel; set true when loadConditions() fires, false when the fetch completes (success or fail) - Cancel any in-flight conditions job when a new loadConditions() call arrives (e.g. rapid map pans) so only the latest fetch drives the state - Add a 10dp ProgressBar after each of the six data values in layout_instruments_sheet.xml (wind, temp, baro, current, waves, swell); visibility GONE by default, alpha 0.5; header section tinted colorOnSurfaceVariant, forecast section tinted #5B9EC2 to match its labels - Observe conditionsLoading in MainActivity and toggle all six spinners together (all values come from one API call so they load in sync) https://claude.ai/code/session_01HXPjBsogsJVRwCiekDGkJX
Diffstat (limited to 'android-app/app')
-rw-r--r--android-app/app/src/main/kotlin/org/terst/nav/MainActivity.kt10
-rw-r--r--android-app/app/src/main/kotlin/org/terst/nav/ui/MainViewModel.kt19
-rw-r--r--android-app/app/src/main/res/layout/layout_instruments_sheet.xml60
3 files changed, 85 insertions, 4 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 d0b0d87..f531a68 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
@@ -514,6 +514,16 @@ class MainActivity : AppCompatActivity(), SafetyFragment.SafetyListener {
applyConditions(c)
}
}
+ val conditionSpinners = listOf(
+ R.id.spinner_tws, R.id.spinner_temp, R.id.spinner_baro,
+ R.id.spinner_curr, R.id.spinner_waves, R.id.spinner_swell
+ ).mapNotNull { findViewById<android.view.View>(it) }
+ lifecycleScope.launch {
+ viewModel.conditionsLoading.collect { loading ->
+ val vis = if (loading) android.view.View.VISIBLE else android.view.View.GONE
+ conditionSpinners.forEach { it.visibility = vis }
+ }
+ }
lifecycleScope.launch {
LocationService.nmeaDepthDataFlow.collect { depthData ->
lastDepthMeters = depthData.depthMeters
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 6ec8c76..36811f7 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
@@ -20,6 +20,7 @@ import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import org.terst.nav.track.TrackSummary
import retrofit2.Retrofit
@@ -52,6 +53,10 @@ class MainViewModel(
private val _marineConditions = MutableStateFlow<MarineConditions?>(null)
val marineConditions: StateFlow<MarineConditions?> = _marineConditions.asStateFlow()
+ private val _conditionsLoading = MutableStateFlow(false)
+ val conditionsLoading: StateFlow<Boolean> = _conditionsLoading.asStateFlow()
+ private var conditionsJob: Job? = null
+
private val _aisTargets = MutableStateFlow<List<AisVessel>>(emptyList())
val aisTargets: StateFlow<List<AisVessel>> = _aisTargets.asStateFlow()
@@ -166,10 +171,16 @@ class MainViewModel(
* Silently ignored on network failure — the UI keeps showing dashes.
*/
fun loadConditions(lat: Double, lon: Double) {
- viewModelScope.launch {
- repository.fetchCurrentConditions(lat, lon)
- .onSuccess { _marineConditions.value = it }
- .onFailure { android.util.Log.e("Nav", "fetchCurrentConditions failed", it) }
+ conditionsJob?.cancel()
+ conditionsJob = viewModelScope.launch {
+ _conditionsLoading.value = true
+ try {
+ repository.fetchCurrentConditions(lat, lon)
+ .onSuccess { _marineConditions.value = it }
+ .onFailure { android.util.Log.e("Nav", "fetchCurrentConditions failed", it) }
+ } finally {
+ _conditionsLoading.value = false
+ }
}
}
diff --git a/android-app/app/src/main/res/layout/layout_instruments_sheet.xml b/android-app/app/src/main/res/layout/layout_instruments_sheet.xml
index 03cefb7..edf0928 100644
--- a/android-app/app/src/main/res/layout/layout_instruments_sheet.xml
+++ b/android-app/app/src/main/res/layout/layout_instruments_sheet.xml
@@ -64,6 +64,16 @@
android:layout_marginStart="3dp"
android:layout_marginBottom="3dp"
android:layout_gravity="bottom" />
+ <ProgressBar
+ android:id="@+id/spinner_tws"
+ style="?android:attr/progressBarStyleSmall"
+ android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:indeterminate="true"
+ android:visibility="gone"
+ android:alpha="0.5"
+ android:indeterminateTint="?attr/colorOnSurfaceVariant"
+ android:layout_marginStart="4dp" />
</LinearLayout>
<TextView
android:id="@+id/bearing_tws"
@@ -96,6 +106,16 @@
style="@style/InstrumentPrimaryValue"
tools:text="18" />
<TextView android:id="@+id/unit_temp" style="@style/InstrumentUnit" android:text="°F" />
+ <ProgressBar
+ android:id="@+id/spinner_temp"
+ style="?android:attr/progressBarStyleSmall"
+ android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:indeterminate="true"
+ android:visibility="gone"
+ android:alpha="0.5"
+ android:indeterminateTint="?attr/colorOnSurfaceVariant"
+ android:layout_marginStart="4dp" />
</LinearLayout>
</LinearLayout>
@@ -124,6 +144,16 @@
style="@style/InstrumentPrimaryValue"
tools:text="1013" />
<TextView android:id="@+id/unit_baro" style="@style/InstrumentUnit" android:text="hPa" />
+ <ProgressBar
+ android:id="@+id/spinner_baro"
+ style="?android:attr/progressBarStyleSmall"
+ android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:indeterminate="true"
+ android:visibility="gone"
+ android:alpha="0.5"
+ android:indeterminateTint="?attr/colorOnSurfaceVariant"
+ android:layout_marginStart="4dp" />
</LinearLayout>
</LinearLayout>
@@ -176,6 +206,16 @@
style="@style/ForecastValue"
tools:text="0.8" />
<TextView android:id="@+id/unit_curr_spd" style="@style/ForecastUnit" android:text="kt" />
+ <ProgressBar
+ android:id="@+id/spinner_curr"
+ style="?android:attr/progressBarStyleSmall"
+ android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:indeterminate="true"
+ android:visibility="gone"
+ android:alpha="0.5"
+ android:indeterminateTint="#5B9EC2"
+ android:layout_marginStart="4dp" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
@@ -215,6 +255,16 @@
style="@style/ForecastValue"
tools:text="3.5" />
<TextView android:id="@+id/unit_wave_ht" style="@style/ForecastUnit" android:text="ft" />
+ <ProgressBar
+ android:id="@+id/spinner_waves"
+ style="?android:attr/progressBarStyleSmall"
+ android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:indeterminate="true"
+ android:visibility="gone"
+ android:alpha="0.5"
+ android:indeterminateTint="#5B9EC2"
+ android:layout_marginStart="4dp" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
@@ -254,6 +304,16 @@
style="@style/ForecastValue"
tools:text="5.2" />
<TextView android:id="@+id/unit_swell_ht" style="@style/ForecastUnit" android:text="ft" />
+ <ProgressBar
+ android:id="@+id/spinner_swell"
+ style="?android:attr/progressBarStyleSmall"
+ android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:indeterminate="true"
+ android:visibility="gone"
+ android:alpha="0.5"
+ android:indeterminateTint="#5B9EC2"
+ android:layout_marginStart="4dp" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"