summaryrefslogtreecommitdiff
path: root/docs/superpowers/specs
diff options
context:
space:
mode:
authorClaude <noreply@anthropic.com>2026-04-23 23:10:11 +0000
committerClaude <noreply@anthropic.com>2026-04-23 23:10:11 +0000
commite1db9200e9d44c10450361cc8984a45b2eda87b7 (patch)
tree21bdfca02491e6ff4cde7a22673c821c0a03e108 /docs/superpowers/specs
parent55509f579b4d074f01237dd90791b6d25aaec3cd (diff)
parenteb78d317c722234a7ef2c501c68c9aa730ec2758 (diff)
Merge origin/main — unite all work onto one branch
Brings in dev log (NavLogger), UnitPrefs, MapLayerManager, HUD views, conditions throttling, track save/load pipeline, improved ParticleWindView (antimeridian-aware, dynamic particle count), Snackbar error surfacing, and all other main-branch work from the prior session. Combined with master's hardware source flags, vessel registry, crew management, thermal alarm, CPA collision alerts, and track stats. Also documents primary branch policy in CLAUDE.md and .agent/config.md: all work merges to main, never master. https://claude.ai/code/session_011h2dXbgXg3PesQMmQUNTCW
Diffstat (limited to 'docs/superpowers/specs')
-rw-r--r--docs/superpowers/specs/2026-04-03-map-interaction-design.md59
-rw-r--r--docs/superpowers/specs/2026-04-04-instrument-sheet-visual-redesign.md156
2 files changed, 215 insertions, 0 deletions
diff --git a/docs/superpowers/specs/2026-04-03-map-interaction-design.md b/docs/superpowers/specs/2026-04-03-map-interaction-design.md
new file mode 100644
index 0000000..02e38e1
--- /dev/null
+++ b/docs/superpowers/specs/2026-04-03-map-interaction-design.md
@@ -0,0 +1,59 @@
+# Map Interaction Design
+_2026-04-03_
+
+## Overview
+
+Enable free map pan/zoom while keeping GPS auto-follow as the default. When the user gestures on the map, the UI hides and a Recenter button appears. Tapping Recenter restores auto-follow and the full UI.
+
+## State
+
+A single `isFollowing: Boolean` flag owned by `MapHandler`. Starts `true`. This is the only piece of new state.
+
+## Entering Manual Mode
+
+`MapLibreMap.addOnCameraMoveStartedListener` fires with `REASON_API_GESTURE` when the user initiates a pan, pinch-zoom, or rotate. On that event:
+
+- `MapHandler.isFollowing` → `false`
+- `MapHandler` emits via a new `StateFlow<Boolean> isFollowing` exposed to MainActivity
+- `MapHandler.centerOnLocation()` becomes a no-op while `!isFollowing` — GPS updates still arrive, last position is stored
+
+## Returning to Auto-Follow
+
+`fab_recenter` click handler:
+
+- Calls `MapHandler.recenter()` — sets `isFollowing = true`, calls `centerOnLocation(lastLat, lastLon)`
+- `isFollowing` StateFlow emits `true` → MainActivity restores UI
+
+## UI Changes
+
+### New element: `fab_recenter`
+
+- Pill-shaped button (`wrap_content` width, 40dp height, 20dp corner radius)
+- Label: "⊙ Recenter"
+- Position: centered horizontally, `24dp` above the bottom of the map `ConstraintLayout`
+- `android:visibility="gone"` by default
+- Elevation: 20dp (above the instrument sheet)
+
+### Visibility toggling (MainActivity)
+
+When `isFollowing` → `false`:
+- Fade out (alpha 0, 150ms): `instrument_bottom_sheet`, `bottom_navigation`, `fab_mob`, `fab_record_track`
+- Show `fab_recenter` (visibility VISIBLE, fade in 150ms)
+
+When `isFollowing` → `true`:
+- Hide `fab_recenter` (fade out 150ms, then GONE)
+- Fade in (alpha 1, 150ms): `instrument_bottom_sheet`, `bottom_navigation`, `fab_mob`, `fab_record_track`
+
+## Files to Change
+
+| File | Change |
+|------|--------|
+| `MapHandler.kt` | Add `isFollowing` StateFlow, `lastLat`/`lastLon` storage, `recenter()`, guard in `centerOnLocation()`, register `OnCameraMoveStartedListener` |
+| `activity_main.xml` | Add `fab_recenter` pill button |
+| `MainActivity.kt` | Observe `mapHandler.isFollowing`, animate UI in/out, wire `fab_recenter` click |
+
+## Out of Scope
+
+- Tapping the map (without gesture) to restore UI — not requested
+- Timeout to auto-restore UI — not requested
+- Zoom-level persistence across recenter — not requested
diff --git a/docs/superpowers/specs/2026-04-04-instrument-sheet-visual-redesign.md b/docs/superpowers/specs/2026-04-04-instrument-sheet-visual-redesign.md
new file mode 100644
index 0000000..4e4e0c4
--- /dev/null
+++ b/docs/superpowers/specs/2026-04-04-instrument-sheet-visual-redesign.md
@@ -0,0 +1,156 @@
+# Instrument Sheet Visual Redesign
+
+**Date:** 2026-04-04
+**Status:** Approved for implementation
+
+## Overview
+
+Redesign `layout_instruments_sheet.xml` and supporting code to replace the plain divider between the instrument grid and forecast section with an animated water-state canvas, enhance typography, add direction indicators, use imperial units, and prevent touch-through to the map.
+
+---
+
+## 1. Animated Wave Divider Canvas
+
+Replace the static `View` divider (and `FORECAST` section header) with a `WaveView` — a custom `View` subclass that draws an animated ocean scene.
+
+**Visual behaviour:**
+- Height: ~72dp
+- Top half gradient: surface background colour (`#1C1B1F`) → dark transitional blue (`#162433`)
+- Bottom half gradient: ocean blue (`#0B3050`) → ocean section background (`#0D2137`)
+- Primary sine wave: amplitude driven by **swell height (ft)**, wavelength proportional to **swell period (s)**
+- Secondary high-frequency sine: amplitude driven by **wind wave height (ft)**, wavelength ~35% of swell wavelength
+- Whitecaps: short curved strokes at wind-wave crests when amplitude exceeds threshold
+- Surface shimmer: thin semi-transparent cyan stroke along the wave waterline
+- Animated via `ValueAnimator` / `postInvalidateOnAnimation()` loop; paused when view is not visible
+
+**Data inputs** (passed from `InstrumentHandler`):
+- `swellHeightFt: Float`
+- `swellPeriodSec: Float`
+- `windWaveHeightFt: Float`
+
+**File:** `android-app/app/src/main/kotlin/org/terst/nav/ui/WaveView.kt`
+
+---
+
+## 2. Typography Enhancements
+
+**Instrument values (grid + depth/baro):**
+- Value: `26sp`, weight `300` (light), colour `#E6E1E5`
+- Unit label: `10sp`, weight `400`, colour `#79747E` — baseline-aligned, small gap after value
+
+**Heading/COG special case:**
+- The `°` symbol is part of the value string, not a separate unit label (e.g. `"247°"` rendered in the value style)
+
+**Forecast values (ocean section):**
+- Value: `22sp`, weight `300`, colour `#CAE8FF`
+- Unit: `10sp`, colour `#3B6785`
+
+**Forecast labels:**
+- `10sp`, weight `500`, letter-spacing `1.2sp`, colour `#5B9EC2`, uppercase
+
+---
+
+## 3. Direction Indicators
+
+A single reusable SVG-style drawable approach: a `DirectionArrowView` (custom `View`, ~14dp × 14dp) that draws:
+- Thin circle outline (stroke only, no fill)
+- Chevron arrow (notched polygon) pointing in the given bearing
+- Rotated via `bearing` property setter
+
+**Instrument section style:** outline `#3A3640`, arrow fill `#9A94A0`
+**Forecast section style:** outline `#1E4A6E`, arrow fill `#6FC3E8`
+
+Applied to:
+- AWS, TWS (wind speed cells) — bearing = apparent/true wind direction
+- HDG, COG (heading/course cells) — bearing = heading value itself
+- Current, Waves, Swell (forecast cells) — bearing from forecast data
+
+Cells without a direction (BSP, SOG, Depth, Baro) have no arrow.
+
+**File:** `android-app/app/src/main/kotlin/org/terst/nav/ui/DirectionArrowView.kt`
+
+---
+
+## 4. Forecast Cell Layout
+
+Each forecast cell (Current, Waves, Swell) is two lines:
+
+```
+CURRENT ← forecast-label style
+0.8 kts ← value + unit baseline-aligned
+[arrow] 185° ← DirectionArrowView + bearing text
+```
+
+Swell adds period to the direction line:
+```
+[arrow] 260° · 14s
+```
+
+`"Wave"` → `"Waves"`, `"Curr"` → `"Current"`.
+No section header ("FORECAST" label removed).
+
+---
+
+## 5. Units: Feet Instead of Metres
+
+All heights from the data layer are in metres and must be converted before display (`* 3.28084`):
+
+- `DepthData.depthMeters` — converted in `InstrumentHandler.updateDisplay()`
+- `MarineConditions.waveHeightM` — converted in `InstrumentHandler.updateConditions()`
+- `MarineConditions.swellHeightM` — converted in `InstrumentHandler.updateConditions()`
+
+The `WaveView` data inputs (`swellHeightFt`, `windWaveHeightFt`) therefore receive already-converted values.
+
+---
+
+## 6. Remove Reports Section
+
+Remove from `layout_instruments_sheet.xml`:
+- `reports_divider` View
+- `label_reports` TextView
+- `reports_row` LinearLayout (containing `btn_nav_pretrip` and `btn_nav_tripreport`)
+
+Remove corresponding wiring from `MainActivity` / wherever the button click listeners are set up.
+
+---
+
+## 7. Prevent Map Touch-Through
+
+The bottom sheet currently sits inside a `CoordinatorLayout`. Touch events on the sheet's non-interactive areas fall through to the `MapFragment` below.
+
+**Fix:** Set `android:clickable="true"` and `android:focusable="true"` on the root `ConstraintLayout` of `layout_instruments_sheet.xml`. This consumes all touch events on the sheet, preventing drag gestures from reaching the map.
+
+---
+
+## 8. Colour Palette Summary
+
+| Token | Value | Use |
+|---|---|---|
+| Surface | `#1C1B1F` | Instrument section background |
+| Outline dim | `#2B2930` | Subtle dividers within instrument grid |
+| Value | `#E6E1E5` | Instrument values |
+| Label | `#CAC4D0` | Instrument labels |
+| Unit | `#79747E` | Instrument unit labels |
+| Arrow outline (sky) | `#3A3640` | Arrow circle border in instrument section |
+| Arrow fill (sky) | `#9A94A0` | Arrow chevron in instrument section |
+| Ocean bg | `#0D2137` | Forecast section background |
+| Ocean value | `#CAE8FF` | Forecast values |
+| Ocean label | `#5B9EC2` | Forecast labels |
+| Ocean unit | `#3B6785` | Forecast unit labels |
+| Ocean arrow outline | `#1E4A6E` | Arrow circle border in forecast section |
+| Ocean arrow fill | `#6FC3E8` | Arrow chevron in forecast section |
+| Bearing text | `#6FC3E8` | Bearing degrees in forecast section |
+| Period text | `#4A7FA0` | Swell period in forecast section |
+
+---
+
+## Files Changed
+
+| File | Change |
+|---|---|
+| `layout_instruments_sheet.xml` | Major restructure: wave canvas, cell layout changes, remove reports |
+| `WaveView.kt` | New custom View |
+| `DirectionArrowView.kt` | New custom View |
+| `InstrumentHandler.kt` | Add `updateWave()`, `updateDirections()`, feet conversion for depth |
+| `MainActivity.kt` | Remove report button wiring |
+| `styles.xml` / `themes.xml` | Add/update `InstrumentLabel`, `InstrumentPrimaryValue` styles if needed |