diff options
| author | Claude <noreply@anthropic.com> | 2026-04-09 09:39:20 +0000 |
|---|---|---|
| committer | Claude <noreply@anthropic.com> | 2026-04-09 09:39:20 +0000 |
| commit | e109271f563327e461191c7c2988243c75cd58ab (patch) | |
| tree | e8401f41bb7f96421175d242bee77245eb68c738 /docs/superpowers/specs | |
| parent | 3cddcd3b0a8719da5e828734a1d3054cef803235 (diff) | |
| parent | 5ee2dd8925afa858f466ae63db3f7df5c7516953 (diff) | |
merge: reconcile master particle-wind work with origin/main redesign
Merged divergent branches (common ancestor a9d87b6). Took origin/main
as base (layer manager, recenter, quit button, GPX tracks, marine
conditions, dark theme, user position layer, active/past track layers)
and layered in particle wind simulation work:
- MapHandler: added setupWindLayer, updateWindLayer, updateWindGridLayer;
kept their user-pos layer, follow/recenter state, active+past tracks
- WeatherRepository: kept their fetchCurrentConditions, added fetchWindGrid
- MainViewModel: kept their track/marine/summary changes, added windGrid
StateFlow, loadWindGrid, buildGrid
- MainActivity: kept their full UI (layer picker, quit, recenter, fade
animations), added particleWindView wiring, weatherLoaded guard,
windArrow/windGrid observers
- activity_main.xml: took their LinearLayout redesign, added ParticleWindView
overlay inside ConstraintLayout
https://claude.ai/code/session_01HXPjBsogsJVRwCiekDGkJX
Diffstat (limited to 'docs/superpowers/specs')
| -rw-r--r-- | docs/superpowers/specs/2026-04-03-map-interaction-design.md | 59 | ||||
| -rw-r--r-- | docs/superpowers/specs/2026-04-04-instrument-sheet-visual-redesign.md | 156 |
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 | |
