From ddfeae7a5f109fc4e993e6697b961ea652360fc2 Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Tue, 30 Jun 2026 18:48:39 +0000 Subject: feat(fishing): wire fishing mode FAB and overlay in MainActivity Adds FishingOverlayView + fab_fishing to layout, initializes FishingModeManager, and wires FAB click to toggle fishing mode with SST layer and target overlay. Co-Authored-By: Claude Sonnet 4.6 --- .../src/main/kotlin/org/terst/nav/MainActivity.kt | 44 ++++++++++++++++++++++ .../app/src/main/res/layout/activity_main.xml | 25 ++++++++++++ 2 files changed, 69 insertions(+) (limited to 'android-app/app') 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 cfc8d6d..4b090e7 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 @@ -91,6 +91,10 @@ class MainActivity : AppCompatActivity(), SafetyFragment.SafetyListener { private lateinit var bottomNav: BottomNavigationView private lateinit var mapCrosshair: View private lateinit var inclinometerView: org.terst.nav.ui.InclinometerView + private lateinit var fishingOverlay: org.terst.nav.ui.fishing.FishingOverlayView + private lateinit var fabFishing: FloatingActionButton + private lateinit var fishingModeManager: org.terst.nav.ui.fishing.FishingModeManager + private var lastCogDeg: Double = 0.0 // HUD value TextViews private lateinit var hudSog: TextView @@ -275,6 +279,7 @@ class MainActivity : AppCompatActivity(), SafetyFragment.SafetyListener { setupBottomNavigation() setupHandlers() setupMap() + setupFishingMode() // Hidden dev log — long-press the drag handle on the instrument sheet findViewById(R.id.drag_handle).setOnLongClickListener { DevLogSheet().show(supportFragmentManager, "dev_log") @@ -689,6 +694,7 @@ class MainActivity : AppCompatActivity(), SafetyFragment.SafetyListener { mapHandler?.setupWindLayer(style, windArrowBitmap) mapHandler?.setupFadLayer(style, layerManager.fadsEnabled) mapHandler?.updateFadLayer(FadData.toFeatures()) + mapHandler?.setupFishingLayer(style) // 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 -> @@ -731,6 +737,42 @@ class MainActivity : AppCompatActivity(), SafetyFragment.SafetyListener { } } + private fun setupFishingMode() { + fishingOverlay = findViewById(R.id.fishing_overlay) + fabFishing = findViewById(R.id.fab_fishing) + fishingModeManager = org.terst.nav.ui.fishing.FishingModeManager(this) + + fabFishing.setOnClickListener { + val active = !fishingModeManager.isActive + fishingModeManager.isActive = active + fishingOverlay.visibility = if (active) View.VISIBLE else View.GONE + loadedStyleFlow.value?.let { style -> + layerManager.setSstEnabled(style, active) + } + updateFishingOverlay() + } + + if (fishingModeManager.isActive) { + fishingOverlay.visibility = View.VISIBLE + } + } + + private fun updateFishingOverlay() { + if (!fishingModeManager.isActive) return + val cond = viewModel.marineConditions.value ?: return + val pos = viewModel.currentPosition.value ?: return + val target = fishingModeManager.computeTarget( + boatLat = pos.first, + boatLon = pos.second, + boatCogDeg = lastCogDeg, + tempC = cond.tempC ?: return, + currentKt = cond.currentSpeedKt ?: 0.0, + currentDirDeg = cond.currentDirDeg ?: 0.0 + ) ?: return + fishingOverlay.bind(target) + mapHandler?.updateFishingBearing(pos.first, pos.second, target.bearingDeg) + } + private var thermalAlarmPlayer: MediaPlayer? = null private fun startThermalMonitoring() { @@ -797,6 +839,7 @@ class MainActivity : AppCompatActivity(), SafetyFragment.SafetyListener { mapHandler?.centerOnLocation(gpsData.latitude, gpsData.longitude) mapHandler?.updateUserPosition(gpsData.latitude, gpsData.longitude, gpsData.cog.toFloat()) viewModel.addGpsPoint(gpsData.latitude, gpsData.longitude, gpsData.sog, gpsData.cog) + lastCogDeg = gpsData.cog // HUD — SOG and COG from GPS lastSogKnots = gpsData.sog hudSog.text = unitPrefs.formatSpeed(gpsData.sog) @@ -854,6 +897,7 @@ class MainActivity : AppCompatActivity(), SafetyFragment.SafetyListener { if (c == null) return@collect lastConditions = c applyConditions(c) + updateFishingOverlay() } } val conditionSpinners = listOf( diff --git a/android-app/app/src/main/res/layout/activity_main.xml b/android-app/app/src/main/res/layout/activity_main.xml index d3b7942..1a54722 100644 --- a/android-app/app/src/main/res/layout/activity_main.xml +++ b/android-app/app/src/main/res/layout/activity_main.xml @@ -102,6 +102,31 @@ android:focusable="true" android:background="?attr/colorSurface" /> + + + + + +