summaryrefslogtreecommitdiff
path: root/android-app/app
diff options
context:
space:
mode:
Diffstat (limited to 'android-app/app')
-rw-r--r--android-app/app/src/main/kotlin/org/terst/nav/MainActivity.kt7
-rw-r--r--android-app/app/src/main/kotlin/org/terst/nav/data/repository/WeatherRepository.kt10
-rw-r--r--android-app/app/src/main/kotlin/org/terst/nav/ui/MainViewModel.kt1
-rw-r--r--android-app/app/src/main/kotlin/org/terst/nav/ui/learn/LearnFragment.kt16
-rw-r--r--android-app/app/src/main/res/layout/fragment_learn.xml154
5 files changed, 17 insertions, 171 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 e6355bd..01971a6 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
@@ -429,6 +429,13 @@ class MainActivity : AppCompatActivity(), SafetyFragment.SafetyListener {
val windArrowBitmap = rasterizeDrawable(R.drawable.ic_wind_arrow)
mapHandler?.setupLayers(style, anchorBitmap, arrowBitmap, userBitmap)
mapHandler?.setupWindLayer(style, windArrowBitmap)
+ // Eagerly load conditions at style-ready time so the HUD is never blank
+ // on startup — the camera-idle may fire before GPS fixes, this is the backstop.
+ maplibreMap.cameraPosition.target?.let { center ->
+ if (center.latitude != 0.0 || center.longitude != 0.0) {
+ viewModel.loadConditions(center.latitude, center.longitude)
+ }
+ }
}
maplibreMap.addOnCameraIdleListener {
diff --git a/android-app/app/src/main/kotlin/org/terst/nav/data/repository/WeatherRepository.kt b/android-app/app/src/main/kotlin/org/terst/nav/data/repository/WeatherRepository.kt
index dc47a20..26c5da7 100644
--- a/android-app/app/src/main/kotlin/org/terst/nav/data/repository/WeatherRepository.kt
+++ b/android-app/app/src/main/kotlin/org/terst/nav/data/repository/WeatherRepository.kt
@@ -1,5 +1,7 @@
package org.terst.nav.data.repository
+import kotlinx.coroutines.async
+import kotlinx.coroutines.coroutineScope
import org.terst.nav.data.api.MarineApiService
import org.terst.nav.data.api.WeatherApiService
import org.terst.nav.data.model.ForecastItem
@@ -52,8 +54,11 @@ class WeatherRepository(
*/
suspend fun fetchCurrentConditions(lat: Double, lon: Double): Result<MarineConditions> =
runCatching {
- val weather = weatherApi.getWeatherForecast(lat, lon, forecastDays = 1)
- val marine = marineApi.getMarineForecast(lat, lon)
+ coroutineScope {
+ val weatherDeferred = async { weatherApi.getWeatherForecast(lat, lon, forecastDays = 1) }
+ val marineDeferred = async { marineApi.getMarineForecast(lat, lon) }
+ val weather = weatherDeferred.await()
+ val marine = marineDeferred.await()
val w = weather.hourly
val m = marine.hourly
MarineConditions(
@@ -68,6 +73,7 @@ class WeatherRepository(
currentSpeedKt = m.oceanCurrentVelocity.firstOrNull()?.let { it * 1.94384 },
currentDirDeg = m.oceanCurrentDirection.firstOrNull()
)
+ }
}
/**
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 9bd660b..df31949 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
@@ -127,6 +127,7 @@ class MainViewModel(
viewModelScope.launch {
repository.fetchCurrentConditions(lat, lon)
.onSuccess { _marineConditions.value = it }
+ .onFailure { android.util.Log.e("Nav", "fetchCurrentConditions failed", it) }
}
}
diff --git a/android-app/app/src/main/kotlin/org/terst/nav/ui/learn/LearnFragment.kt b/android-app/app/src/main/kotlin/org/terst/nav/ui/learn/LearnFragment.kt
index da3f020..418246c 100644
--- a/android-app/app/src/main/kotlin/org/terst/nav/ui/learn/LearnFragment.kt
+++ b/android-app/app/src/main/kotlin/org/terst/nav/ui/learn/LearnFragment.kt
@@ -1,7 +1,5 @@
package org.terst.nav.ui.learn
-import android.content.Intent
-import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@@ -36,16 +34,6 @@ class LearnFragment : Fragment() {
openDoc("docs/sailing_reference.md")
}
- // ASA / external links — open in browser
- view.findViewById<MaterialCardView>(R.id.card_asa_courses).setOnClickListener {
- openUrl("https://www.asa.com/courses/")
- }
- view.findViewById<MaterialCardView>(R.id.card_asa_online).setOnClickListener {
- openUrl("https://www.asa.com/online-courses/")
- }
- view.findViewById<MaterialCardView>(R.id.card_flashcards).setOnClickListener {
- openUrl("https://quizlet.com/subject/sailing/")
- }
}
private fun openDoc(path: String) {
@@ -54,8 +42,4 @@ class LearnFragment : Fragment() {
.addToBackStack(null)
.commit()
}
-
- private fun openUrl(url: String) {
- startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
- }
}
diff --git a/android-app/app/src/main/res/layout/fragment_learn.xml b/android-app/app/src/main/res/layout/fragment_learn.xml
index 8813ba2..fa18c5d 100644
--- a/android-app/app/src/main/res/layout/fragment_learn.xml
+++ b/android-app/app/src/main/res/layout/fragment_learn.xml
@@ -158,7 +158,7 @@
android:id="@+id/card_sailing_reference"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginBottom="24dp"
+ android:layout_marginBottom="8dp"
app:cardCornerRadius="12dp"
app:cardElevation="2dp">
@@ -201,157 +201,5 @@
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
- <!-- ── ASA Training &amp; Practice (external links) ──────────── -->
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="ASA TRAINING &amp; PRACTICE"
- android:textSize="11sp"
- android:textAllCaps="true"
- android:letterSpacing="0.12"
- android:textColor="?attr/colorOnSurfaceVariant"
- android:layout_marginBottom="8dp" />
-
- <com.google.android.material.card.MaterialCardView
- android:id="@+id/card_asa_courses"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="8dp"
- app:cardCornerRadius="12dp"
- app:cardElevation="2dp">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:padding="16dp"
- android:gravity="center_vertical">
-
- <LinearLayout
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:orientation="vertical">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="ASA Course Catalog"
- android:textAppearance="?attr/textAppearanceTitleSmall" />
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="ASA 101–114: keelboat through offshore passagemaking"
- android:textSize="12sp"
- android:textColor="?attr/colorOnSurfaceVariant"
- android:layout_marginTop="2dp" />
-
- </LinearLayout>
-
- <ImageView
- android:layout_width="18dp"
- android:layout_height="18dp"
- android:src="@drawable/ic_open_in_new"
- android:tint="?attr/colorOnSurfaceVariant"
- android:contentDescription="Opens in browser" />
-
- </LinearLayout>
- </com.google.android.material.card.MaterialCardView>
-
- <com.google.android.material.card.MaterialCardView
- android:id="@+id/card_asa_online"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="8dp"
- app:cardCornerRadius="12dp"
- app:cardElevation="2dp">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:padding="16dp"
- android:gravity="center_vertical">
-
- <LinearLayout
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:orientation="vertical">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="ASA Online Learning"
- android:textAppearance="?attr/textAppearanceTitleSmall" />
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Self-paced online courses and study guides"
- android:textSize="12sp"
- android:textColor="?attr/colorOnSurfaceVariant"
- android:layout_marginTop="2dp" />
-
- </LinearLayout>
-
- <ImageView
- android:layout_width="18dp"
- android:layout_height="18dp"
- android:src="@drawable/ic_open_in_new"
- android:tint="?attr/colorOnSurfaceVariant"
- android:contentDescription="Opens in browser" />
-
- </LinearLayout>
- </com.google.android.material.card.MaterialCardView>
-
- <com.google.android.material.card.MaterialCardView
- android:id="@+id/card_flashcards"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="8dp"
- app:cardCornerRadius="12dp"
- app:cardElevation="2dp">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:padding="16dp"
- android:gravity="center_vertical">
-
- <LinearLayout
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:orientation="vertical">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Sailing Flashcards"
- android:textAppearance="?attr/textAppearanceTitleSmall" />
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Quizlet decks for knots, rules, lights &amp; signals"
- android:textSize="12sp"
- android:textColor="?attr/colorOnSurfaceVariant"
- android:layout_marginTop="2dp" />
-
- </LinearLayout>
-
- <ImageView
- android:layout_width="18dp"
- android:layout_height="18dp"
- android:src="@drawable/ic_open_in_new"
- android:tint="?attr/colorOnSurfaceVariant"
- android:contentDescription="Opens in browser" />
-
- </LinearLayout>
- </com.google.android.material.card.MaterialCardView>
-
</LinearLayout>
</ScrollView>