summaryrefslogtreecommitdiff
path: root/android-app/app/src/main/kotlin
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-06-30 18:38:29 +0000
committerPeter Stone <thepeterstone@gmail.com>2026-06-30 18:38:29 +0000
commit23163f67deb71f4cc4e53d670254a45b59fd4f6b (patch)
tree1f1de2385d8a55488273c61c9df6f225d9715bb0 /android-app/app/src/main/kotlin
parent82112d0c0b8c31ad436f52c9003d480b7132a3f1 (diff)
feat(fishing): SST raster layer from NOAA CoastWatch
Adds SST source/layer to MapLayerManager, SST toggle to LayerPickerSheet UI and wires it up in MainActivity. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'android-app/app/src/main/kotlin')
-rw-r--r--android-app/app/src/main/kotlin/org/terst/nav/MainActivity.kt4
-rw-r--r--android-app/app/src/main/kotlin/org/terst/nav/ui/LayerPickerSheet.kt6
-rw-r--r--android-app/app/src/main/kotlin/org/terst/nav/ui/MapLayerManager.kt26
3 files changed, 36 insertions, 0 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 fcfc96a..cfc8d6d 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
@@ -427,6 +427,10 @@ class MainActivity : AppCompatActivity(), SafetyFragment.SafetyListener {
val style = loadedStyleFlow.value ?: return@LayerPickerSheet
mapHandler?.setFadLayerVisible(style, enabled)
},
+ onSstChanged = { enabled ->
+ val style = loadedStyleFlow.value ?: return@LayerPickerSheet
+ layerManager.setSstEnabled(style, enabled)
+ },
unitPrefs = unitPrefs,
onUnitsChanged = { refreshUnits() }
)
diff --git a/android-app/app/src/main/kotlin/org/terst/nav/ui/LayerPickerSheet.kt b/android-app/app/src/main/kotlin/org/terst/nav/ui/LayerPickerSheet.kt
index a9dcca8..b654184 100644
--- a/android-app/app/src/main/kotlin/org/terst/nav/ui/LayerPickerSheet.kt
+++ b/android-app/app/src/main/kotlin/org/terst/nav/ui/LayerPickerSheet.kt
@@ -23,6 +23,7 @@ class LayerPickerSheet(
private val onSeamarksChanged: (Boolean) -> Unit,
private val onDepthChanged: (Boolean) -> Unit,
private val onFadsChanged: (Boolean) -> Unit,
+ private val onSstChanged: (Boolean) -> Unit,
private val unitPrefs: UnitPrefs,
private val onUnitsChanged: () -> Unit
) : BottomSheetDialogFragment() {
@@ -78,6 +79,11 @@ class LayerPickerSheet(
fadsSwitch.isChecked = manager.fadsEnabled
fadsSwitch.setOnCheckedChangeListener { _, checked -> onFadsChanged(checked) }
+ // ── SST switch ────────────────────────────────────────────────────────
+ val sstSwitch = view.findViewById<SwitchMaterial>(R.id.switch_sst)
+ sstSwitch.isChecked = manager.sstEnabled
+ sstSwitch.setOnCheckedChangeListener { _, checked -> onSstChanged(checked) }
+
// ── Temperature chips ─────────────────────────────────────────────────
val chipTemp = view.findViewById<ChipGroup>(R.id.chip_group_temp)
chipTemp.check(when (unitPrefs.tempUnit) {
diff --git a/android-app/app/src/main/kotlin/org/terst/nav/ui/MapLayerManager.kt b/android-app/app/src/main/kotlin/org/terst/nav/ui/MapLayerManager.kt
index 33072c4..9f7e819 100644
--- a/android-app/app/src/main/kotlin/org/terst/nav/ui/MapLayerManager.kt
+++ b/android-app/app/src/main/kotlin/org/terst/nav/ui/MapLayerManager.kt
@@ -38,6 +38,8 @@ class MapLayerManager(context: Context) {
private set
var fadsEnabled: Boolean = prefs.getBoolean(KEY_FADS, false)
private set
+ var sstEnabled: Boolean = prefs.getBoolean(KEY_SST, false)
+ private set
// ── Source / Layer IDs ────────────────────────────────────────────────────
@@ -53,6 +55,8 @@ class MapLayerManager(context: Context) {
const val LAYER_WIND = "wind-layer"
const val LAYER_SEAMARKS = "openseamap-layer"
const val LAYER_DEPTH = "osm-depth-layer"
+ const val SOURCE_SST = "sst-source"
+ const val LAYER_SST = "sst-layer"
private const val KEY_BASE = "base_preset"
private const val KEY_WIND = "wind_enabled"
@@ -61,6 +65,7 @@ class MapLayerManager(context: Context) {
private const val KEY_SEAMARKS = "seamarks_enabled"
private const val KEY_DEPTH = "depth_enabled"
private const val KEY_FADS = "fads_enabled"
+ private const val KEY_SST = "sst_enabled"
// Tile URLs
private const val URL_SATELLITE =
@@ -74,6 +79,12 @@ class MapLayerManager(context: Context) {
// Depth soundings + contours from OpenSeaMap (zoom 3–18, coverage varies by region)
private const val URL_DEPTH =
"https://tiles.openseamap.org/depth/{z}/{x}/{y}.png"
+ // Sea Surface Temperature from NOAA CoastWatch (WMS-style raster)
+ private const val URL_SST =
+ "https://coastwatch.pfeg.noaa.gov/erddap/wms/jplMURSST41/request" +
+ "?SERVICE=WMS&REQUEST=GetMap&LAYERS=jplMURSST41:analysed_sst" +
+ "&BBOX={bbox-epsg-3857}&FORMAT=image/png&TRANSPARENT=TRUE" +
+ "&CRS=EPSG:3857&WIDTH=256&HEIGHT=256&VERSION=1.3.0&STYLES="
}
/**
@@ -98,6 +109,9 @@ class MapLayerManager(context: Context) {
builder.withSource(RasterSource(SOURCE_DEPTH,
TileSet("2.2.0", URL_DEPTH).also { it.setMinZoom(3f); it.setMaxZoom(18f) }, 256))
+ builder.withSource(RasterSource(SOURCE_SST,
+ TileSet("2.2.0", URL_SST), 256))
+
// ── Layers (bottom → top within raster stack) ─────────────────────────
builder.withLayer(RasterLayer(LAYER_SATELLITE, SOURCE_SATELLITE).apply {
setProperties(PropertyFactory.rasterOpacity(1f))
@@ -114,6 +128,11 @@ class MapLayerManager(context: Context) {
setProperties(PropertyFactory.visibility(if (windEnabled) "visible" else "none"))
})
+ builder.withLayer(RasterLayer(LAYER_SST, SOURCE_SST).apply {
+ setProperties(PropertyFactory.rasterOpacity(0.65f))
+ setProperties(PropertyFactory.visibility(if (sstEnabled) "visible" else "none"))
+ })
+
// Depth contours sit below seamarks so soundings don't obscure nav aid symbols
builder.withLayer(RasterLayer(LAYER_DEPTH, SOURCE_DEPTH).apply {
setProperties(PropertyFactory.rasterOpacity(0.85f))
@@ -159,6 +178,13 @@ class MapLayerManager(context: Context) {
PropertyFactory.visibility(if (enabled) "visible" else "none"))
}
+ fun setSstEnabled(style: Style, enabled: Boolean) {
+ sstEnabled = enabled
+ prefs.edit().putBoolean(KEY_SST, enabled).apply()
+ style.getLayer(LAYER_SST)?.setProperties(
+ PropertyFactory.visibility(if (enabled) "visible" else "none"))
+ }
+
/** FADs are a GeoJSON vector layer in MapHandler; this just persists the pref. */
fun setFadsEnabled(enabled: Boolean) {
fadsEnabled = enabled