summaryrefslogtreecommitdiff
path: root/android-app/app/src/main
diff options
context:
space:
mode:
authorClaude <noreply@anthropic.com>2026-05-20 09:52:18 +0000
committerClaude <noreply@anthropic.com>2026-05-20 09:52:18 +0000
commitcdb3fa7c6167e108f46b4d411655f78a22e3bebe (patch)
tree393b7ffb45bad2eda862f192ae492e94f9f881fd /android-app/app/src/main
parent6dc2b16da127dd0a68907c037e8219eaacc8806c (diff)
Fix Recenter bleed-through; drop noisy speed events; track detail as bottom sheet
Recenter button was reappearing over overlays because the isFollowing flow kept calling fadeIn(fabRecenter) even when an overlay was visible. Added overlayShowing flag — the flow skips FAB updates while an overlay is shown. hideOverlays() now correctly restores fabRecenter visibility based on the actual following state instead of just resetting alpha. Speed up/Slow down events fired on every 1.5 kt GPS jitter, flooding the log with noise. Removed the detection loop entirely — no reliable motor on/off signal is available from GPS alone. TrackDetailSheet converted from a full-screen Fragment to a BottomSheetDialogFragment: opens at half-screen height so the track route is visible on the map behind it, draggable to full height, 20% background dim. SavedTracksFragment now calls hideOverlays() then sheet.show() instead of fragment-replacing the overlay container. https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
Diffstat (limited to 'android-app/app/src/main')
-rw-r--r--android-app/app/src/main/kotlin/org/terst/nav/MainActivity.kt19
-rw-r--r--android-app/app/src/main/kotlin/org/terst/nav/track/SavedTracksFragment.kt7
-rw-r--r--android-app/app/src/main/kotlin/org/terst/nav/track/TrackDetailSheet.kt36
-rw-r--r--android-app/app/src/main/res/layout/layout_track_detail_sheet.xml7
4 files changed, 36 insertions, 33 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 7ce417d..caabe40 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
@@ -114,6 +114,7 @@ class MainActivity : AppCompatActivity(), SafetyFragment.SafetyListener {
private val viewModel: MainViewModel by viewModels()
private var pendingServiceStart = false
private var serviceStarted = false
+ private var overlayShowing = false
override fun onResume() {
super.onResume()
@@ -418,6 +419,7 @@ class MainActivity : AppCompatActivity(), SafetyFragment.SafetyListener {
}
private fun showOverlay(fragment: androidx.fragment.app.Fragment) {
+ overlayShowing = true
fragmentContainer.visibility = View.VISIBLE
fabRecordTrack.visibility = View.GONE
fabLayers.visibility = View.GONE
@@ -432,9 +434,12 @@ class MainActivity : AppCompatActivity(), SafetyFragment.SafetyListener {
}
internal fun hideOverlays() {
+ overlayShowing = false
fragmentContainer.visibility = View.GONE
fabRecordTrack.visibility = View.VISIBLE
fabLayers.visibility = View.VISIBLE
+ val following = mapHandler?.isFollowing?.value ?: true
+ fabRecenter.visibility = if (following) View.GONE else View.VISIBLE
fabRecenter.alpha = 1f
bottomSheetBehavior.isHideable = false
bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
@@ -592,12 +597,14 @@ class MainActivity : AppCompatActivity(), SafetyFragment.SafetyListener {
lifecycleScope.launch {
mapHandler!!.isFollowing.collect { following ->
mapCrosshair.visibility = if (following) View.GONE else View.VISIBLE
- if (following) {
- fadeOut(fabRecenter, gone = true)
- fadeIn(fabRecordTrack)
- } else {
- fadeOut(fabRecordTrack, gone = true)
- fadeIn(fabRecenter)
+ if (!overlayShowing) {
+ if (following) {
+ fadeOut(fabRecenter, gone = true)
+ fadeIn(fabRecordTrack)
+ } else {
+ fadeOut(fabRecordTrack, gone = true)
+ fadeIn(fabRecenter)
+ }
}
}
}
diff --git a/android-app/app/src/main/kotlin/org/terst/nav/track/SavedTracksFragment.kt b/android-app/app/src/main/kotlin/org/terst/nav/track/SavedTracksFragment.kt
index d8b9858..f992e1e 100644
--- a/android-app/app/src/main/kotlin/org/terst/nav/track/SavedTracksFragment.kt
+++ b/android-app/app/src/main/kotlin/org/terst/nav/track/SavedTracksFragment.kt
@@ -44,11 +44,8 @@ class SavedTracksFragment : Fragment() {
val adapter = SavedTrackAdapter { track ->
viewModel.selectTrack(track)
- parentFragmentManager
- .beginTransaction()
- .replace(R.id.fragment_container, TrackDetailSheet.newInstance())
- .addToBackStack(null)
- .commit()
+ (requireActivity() as MainActivity).hideOverlays()
+ TrackDetailSheet.newInstance().show(parentFragmentManager, "track_detail")
}
rv.adapter = adapter
diff --git a/android-app/app/src/main/kotlin/org/terst/nav/track/TrackDetailSheet.kt b/android-app/app/src/main/kotlin/org/terst/nav/track/TrackDetailSheet.kt
index c1764a8..627ce89 100644
--- a/android-app/app/src/main/kotlin/org/terst/nav/track/TrackDetailSheet.kt
+++ b/android-app/app/src/main/kotlin/org/terst/nav/track/TrackDetailSheet.kt
@@ -5,11 +5,13 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
-import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
+import com.google.android.material.bottomsheet.BottomSheetBehavior
+import com.google.android.material.bottomsheet.BottomSheetDialog
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import org.terst.nav.R
import org.terst.nav.ui.MainViewModel
import java.time.Instant
@@ -28,7 +30,7 @@ data class LogEvent(
val detail: String
)
-class TrackDetailSheet : Fragment() {
+class TrackDetailSheet : BottomSheetDialogFragment() {
private val viewModel: MainViewModel by activityViewModels()
@@ -41,13 +43,11 @@ class TrackDetailSheet : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val track = viewModel.selectedTrack.value ?: run {
- parentFragmentManager.popBackStack()
+ dismiss()
return
}
- view.findViewById<View>(R.id.btn_back).setOnClickListener {
- parentFragmentManager.popBackStack()
- }
+ view.findViewById<View>(R.id.btn_back).setOnClickListener { dismiss() }
val titleFmt = DateTimeFormatter.ofPattern("dd MMM yyyy · HH:mm", Locale.getDefault())
.withZone(ZoneId.systemDefault())
@@ -70,6 +70,14 @@ class TrackDetailSheet : Fragment() {
rv.adapter = LogEventAdapter(events) { event ->
viewModel.panToTrackPoint(event.lat, event.lon)
}
+
+ (dialog as? BottomSheetDialog)?.behavior?.apply {
+ isFitToContents = false
+ halfExpandedRatio = 0.5f
+ skipCollapsed = true
+ state = BottomSheetBehavior.STATE_HALF_EXPANDED
+ }
+ dialog?.window?.setDimAmount(0.2f)
}
override fun onDestroyView() {
@@ -96,22 +104,6 @@ class TrackDetailSheet : Fragment() {
"%.0f° → %.0f° (Δ%.0f°)".format(t.cogBefore, t.cogAfter, abs(delta)))
}
- for (i in 1 until points.size - 1) {
- val prev = points[i - 1].sogKnots
- val curr = points[i].sogKnots
- val next = points[i + 1].sogKnots
- val rise = curr - prev
- val fall = curr - next
- val p = points[i]
- if (rise > 1.5 && rise > fall) {
- events += LogEvent(p.lat, p.lon, p.timestampMs, "↑",
- "Speed up", "%.1f → %.1f kt".format(prev, curr))
- } else if (fall > 1.5 && fall > rise) {
- events += LogEvent(p.lat, p.lon, p.timestampMs, "↓",
- "Slow down", "%.1f → %.1f kt".format(curr, next))
- }
- }
-
points.lastOrNull()?.let { p ->
events += LogEvent(p.lat, p.lon, p.timestampMs, "🏁", "End", formatPointDetail(p))
}
diff --git a/android-app/app/src/main/res/layout/layout_track_detail_sheet.xml b/android-app/app/src/main/res/layout/layout_track_detail_sheet.xml
index 6a2ba50..97b1da8 100644
--- a/android-app/app/src/main/res/layout/layout_track_detail_sheet.xml
+++ b/android-app/app/src/main/res/layout/layout_track_detail_sheet.xml
@@ -6,6 +6,13 @@
android:orientation="vertical"
android:background="?attr/colorSurface">
+ <!-- Drag handle -->
+ <View
+ android:layout_width="36dp"
+ android:layout_height="40dp"
+ android:layout_gravity="center_horizontal"
+ android:background="@drawable/drag_handle_bg" />
+
<!-- Header -->
<LinearLayout
android:layout_width="match_parent"