summaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
2026-04-10Add unit settings, wind particles toggle, and recenter-to-topClaude
- New UnitPrefs: persisted C/F, ft/m, hPa/inHg, kt/mph/kph — defaults to °F - InstrumentHandler now accepts raw values (knots, metres, hPa, °C) and formats via UnitPrefs on every update - LayerPickerSheet expanded with wind particles toggle and unit chip selectors; wrapped in ScrollView to handle the additional height - MapLayerManager tracks particlesEnabled (persisted); setParticlesEnabled() added - MainActivity: caches last raw values so refreshUnits() can reformat everything instantly when the user changes a unit without waiting for new sensor data - Recenter button moved to top (below HUD strip) so it's never obscured by the bottom sheet or bottom nav - Unit label TextViews given IDs in HUD and instrument sheet for live updates https://claude.ai/code/session_01HXPjBsogsJVRwCiekDGkJX
2026-04-10Area conditions HUD redesign: map-center conditions refresh + boat HUD stripClaude
- Persistent top-of-map HUD strip (SOG/COG/BSP/Depth) replaces instrument grid in bottom sheet - Bottom sheet now shows area conditions only (Wind/Temp/Baro + wave forecast) — always visible - loadConditions() fires on every camera idle event so panning the map refreshes conditions - Crosshair appears at map center while panning; hides when following GPS - Added tempC field to MarineConditions (already fetched from Open-Meteo hourly) - InstrumentHandler slimmed to area conditions only; updateDisplay() removed - LocationService pipes nmeaBoatSpeedData from NmeaStreamManager to companion flow https://claude.ai/code/session_01HXPjBsogsJVRwCiekDGkJX
2026-04-10Improve particle and wind overlay visibilityClaude
- Particles: vivid blue (30, 100, 255) instead of white — visible on light charts background; thicker stroke 3.5px vs 2.5px - Wind raster overlay: opacity 0.85 vs 0.60 https://claude.ai/code/session_01HXPjBsogsJVRwCiekDGkJX
2026-04-10Fix particle disappearance at antimeridian-crossing viewports; use whiteClaude
When the viewport crosses ±180° longitude (e.g. Pacific Ocean view), minOf/maxOf on raw longitudes produces lonWest/lonEast that are backwards. Every particle then satisfies the out-of-bounds check and is respawned on every frame → continue → never drawn. Fix: compute lonSpan from screen-ordered corners (left edge / right edge) with antimeridian wrap: lonSpan = lonEast >= lonWest ? span : span + 360. Bounds check uses normalized particle longitude relative to lonWest mod 360. Particle movement wraps longitude into [-180, 180] to stay consistent. Also change particle color to white so it contrasts against the blue wind raster overlay instead of blending into it. https://claude.ai/code/session_01HXPjBsogsJVRwCiekDGkJX
2026-04-10Default map to charts; fix synchronized particle flash on pan/zoomClaude
- MapLayerManager: default base preset changed from SATELLITE to CHARTS - ParticleWindView: respawned particles now get a random age (0..MAX_AGE) instead of always 0, preventing mass synchronized respawns after pan/zoom https://claude.ai/code/session_01HXPjBsogsJVRwCiekDGkJX
2026-04-09Fix startup crash: rename wind source ID to avoid collisionClaude
MapLayerManager registers SOURCE_WIND = "wind-source" as a RasterSource in the style builder. MapHandler was using the same ID for its GeoJsonSource, causing MapLibre to throw on duplicate source IDs at style-load time. Rename MapHandler's source to "wind-arrows-source". https://claude.ai/code/session_01HXPjBsogsJVRwCiekDGkJX
2026-04-09Fix nullable LatLng? crash in MainActivity camera idle listenerClaude
Same MapLibre 13.0.1 nullable corner fix — use listOfNotNull() and guard on size == 4 before calling loadWindGrid. https://claude.ai/code/session_01HXPjBsogsJVRwCiekDGkJX
2026-04-09Fix nullable LatLng? crash in ParticleWindViewClaude
MapLibre 13.0.1 types VisibleRegion corners as LatLng? (nullable). Use listOfNotNull() in both onDraw() and scatter() to guard against null corners — mirrors the same fix already applied to MainActivity. https://claude.ai/code/session_01HXPjBsogsJVRwCiekDGkJX
2026-04-09fix(build): replace LatLngBounds properties with VisibleRegion cornersClaude
LatLngBounds.latSouth/latNorth/lonWest/lonEast don't exist in MapLibre 13.0.1. Derive bounds from VisibleRegion corner LatLng points (.nearLeft/.nearRight/.farLeft/.farRight) which are stable across SDK versions. Fixes CI compilation failure in MainActivity and ParticleWindView. https://claude.ai/code/session_01HXPjBsogsJVRwCiekDGkJX
2026-04-09docs(agent): lock in main as canonical default branchClaude
Document that default branch is always main, CI triggers on main, and master must never be used. Prevents recurrence of the master/main confusion that broke Firebase distribution. https://claude.ai/code/session_01HXPjBsogsJVRwCiekDGkJX
2026-04-09merge: reconcile master particle-wind work with origin/main redesignClaude
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
2026-04-09fix(ci): trigger workflow on master branchClaude
2026-04-09fix(ci): trigger workflow on master, not mainClaude
Repo default branch is master; workflow was targeting main so CI never ran and Firebase distribution never fired. https://claude.ai/code/session_01HXPjBsogsJVRwCiekDGkJX
2026-04-08Merge branch 'claude/particle-wind-simulation-IMVxT' — Level 2 particle ↵Claude
simulation
2026-04-08feat(wind): Level 2 — canvas particle simulation (uniform field)Claude
- ParticleWindView: transparent View overlay on the map; tracks 300 particles as three FloatArrays (lat, lon, age) — no per-frame allocation; projects lat/lon → screen via MapLibreMap.projection each frame; draws a 14px tail segment in the wind travel direction with alpha fading by age; respawns out-of-bounds/aged particles randomly within visible bounds; speed scaled to viewport so animation is consistent at any zoom level; animates via postInvalidateOnAnimation() - activity_main.xml: ParticleWindView added above MapView, match_parent, non-interactive (clickable/focusable=false) - MainActivity: finds particle_wind_view; calls attachMap after getMapAsync; feeds directionDeg/speedKt from windArrow StateFlow https://claude.ai/code/session_01HXPjBsogsJVRwCiekDGkJX
2026-04-08Merge branch 'claude/particle-wind-simulation-IMVxT' — Level 1 wind gridClaude
2026-04-08feat(wind): Level 1 — 4×5 viewport grid of wind arrowsClaude
- WeatherApiService: batch endpoint getWeatherForecastBatch with comma-separated lat/lon → List<WeatherResponse> - WeatherRepository.fetchWindGrid: chunks 20 points into two calls of 10, maps each response to a WindArrow at its returned lat/lon - MainViewModel.loadWindGrid(bounds): builds a 4×5 grid from visible map bounds, calls fetchWindGrid, emits to windGrid StateFlow - MapHandler.setupWindGridLayer: GeoJSON source + SymbolLayer reusing the wind-arrow icon; MapHandler.updateWindGridLayer: pushes feature collection - MainActivity: stores mapLibreMapRef; calls setupWindGridLayer after style loads; addOnCameraIdleListener fires loadWindGrid on every pan/zoom; observes windGrid → updateWindGridLayer https://claude.ai/code/session_01HXPjBsogsJVRwCiekDGkJX
2026-04-08Merge branch 'claude/particle-wind-simulation-IMVxT' — Level 0 wind arrowClaude
2026-04-08feat(wind): Level 0 — single wind arrow at GPS positionClaude
- MapHandler.setupWindLayer: registers ic_wind_arrow bitmap, adds GeoJSON source + SymbolLayer with rotation/size driven by direction/speed_kt props - MapHandler.updateWindLayer(arrow): pushes updated feature to the source - MainActivity: calls setupWindLayer after style load; fires loadWeather once on first GPS fix (weatherLoaded flag); observes windArrow StateFlow to drive updateWindLayer https://claude.ai/code/session_01HXPjBsogsJVRwCiekDGkJX
2026-04-07fix(track): fix silent GPX save failure + add stop friction + quit buttonPeter Stone
TrackStorage: openOutputStream null returned true (file never written). Added IS_PENDING flag to fix Android 10-11 race where insert succeeds but file isn't physically created yet. Added storage-mounted guard. TrackRepository now logs save failures. Stop tracking now requires a long press (haptic feedback) — prevents accidental mid-sail stops from a single tap. Quit button (top-right, tonal X) stops LocationService and calls finishAffinity(). Prompts if a track is in progress. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06feat(nav): replace Map+Instruments with Map+Layers in bottom navPeter Stone
Layers acts as an action button — shows LayerPickerSheet and snaps back to Map so it never stays selected. Instruments tab removed; sheet expand/collapse via swipe as before. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06feat(map): layer manager — satellite/charts/hybrid + wind toggle, ↵Peter Stone
long-press picker MapLayerManager: all raster sources registered at style-build time, visibility toggled on demand. Persists base preset and wind state to SharedPreferences. Sources: Google satellite, NOAA RNC charts (tileservice.charts.noaa.gov), OWM wind, OpenSeaMap seamarks. LayerPickerSheet: bottom sheet with chip group (Satellite/Charts/Hybrid) and wind toggle, launched from map long-press. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06feat(map): switch wind layer to OpenWeatherMap wind_new tilesPeter Stone
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06feat(map): add Windy Map Forecast API key to wind tile URLPeter Stone
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06feat(tracks): show summary sheet on track stop; 2-min minimumPeter Stone
TrackSummarySheet: bottom sheet showing distance (nm), duration, max/avg speed, avg wind and waves (when available, waves in ft). Only shown for tracks ≥ 2 minutes — shorter tracks are discarded silently. MainViewModel: exposes trackSummary SharedFlow (replay=0) and trackStartMs. MainActivity: observes flow, shows sheet after stopTrack completes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06feat(tracks): persist tracks as GPX in Documents/Nav/ — survives uninstallPeter Stone
GpxSerializer/GpxParser: full round-trip of all TrackPoint fields via GPX 1.1 + nav: extensions namespace. 13 unit tests. TrackStorage: MediaStore on API 29+ (no permission needed), direct file I/O on API 24-28 (WRITE_EXTERNAL_STORAGE maxSdkVersion=28). TrackRepository: stopTrack() is now suspend, writes GPX and returns TrackSummary (distance nm, duration, max/avg SOG, avg wind, avg wave). getPastTracks() lazy-loads from Documents/Nav/ on first call. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06feat(ui): wave height scales view, period drives speed, whitecaps gated on windPeter Stone
WaveView: animation speed = 8/period so long swell animates slowly; amplitude ceiling raised to 42% of view height; whitecaps only when windSpeedKt >= 12 (Beaufort 4). InstrumentHandler.updateWaveState: sizes view height from swell height (1ft→56dp, 8ft→160dp) and forwards windSpeedKt to WaveView. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06feat(ui): dark theme — match instrument sheet to WaveView sky palettePeter Stone
Surface/background → #1C1B1F (WaveView sky), text tokens updated to light M3 dark-mode values, status bar icons set to light. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06feat(ui): wire redesigned instrument sheet — InstrumentHandler rewrite + ↵Peter Stone
MainActivity InstrumentHandler: direction arrows (SKY/OCEAN palettes), WaveView state, metres→feet conversion, bearing formatting, all helpers top-level for TDD. MainActivity: setupHandlers wires all new view refs; observeDataSources passes cogBearingDeg, twsBearingDeg, raw metres to handler; depth collector wired from nmeaDepthDataFlow. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06feat(ui): restructure instrument sheet layout — inline arrows, WaveView, ↵Peter Stone
ocean forecast section Full layout rewrite: 3×2 GridLayout instrument grid with inline DirectionArrowView for AWS/TWS/HDG/COG, depth+baro row, animated WaveView divider, and ocean-blue forecast section for Current/Waves/Swell. Stubs valueCurrDir/valueWaveDir as nullable in InstrumentHandler to compile; full handler rewrite follows in Task 6. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06feat(ui): add DirectionArrowView and WaveView custom viewsPeter Stone
DirectionArrowView: rotating notched-chevron compass indicator in SKY (grey) and OCEAN (blue) palettes, with bearing normalization. WaveView: animated swell + wind-chop canvas divider — sky/sea gradient fills, shimmer line, whitecap highlights; self-animates via postInvalidateOnAnimation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06chore: update worklog — instrument sheet redesign in progress, tasks 1-2 donePeter Stone
2026-04-05feat(ui): update instrument sheet typography — weight 300, unit labels, ↵Peter Stone
forecast styles
2026-04-05feat(ui): remove report section from instrument sheet, fix touch-throughPeter Stone
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05docs: add instrument sheet visual redesign spec and implementation planPeter Stone
2026-04-04chore: cleanup accidental log files from repoPeter Stone
2026-04-04fix(smoke): resolve MapView inflation crash and wire anchor config navigationPeter Stone
2026-04-04refactor: unify core models and finish org.terst.nav migrationPeter Stone
2026-04-04feat(ui): surface trip planning and reports in instrument sheetPeter Stone
2026-04-04refactor(ui): stabilize layout by moving BottomNav outside CoordinatorLayoutPeter Stone
2026-04-04chore: cleanup accidental temporary files from repositoryPeter Stone
2026-04-04feat(tripreport): add pre-trip planning and past track visualizationPeter Stone
- Fix compilation errors (missing imports for PropertyFactory and MaterialButton) - Implement Pre-Trip Report with weather summary, boat profile, and sail suggestions - Differentiate between active track (solid red) and past tracks (dotted red) on map - Add navigation to Pre-Trip Report from Safety Dashboard - Robustify track storage to preserve multiple tracks in session Co-Authored-By: Gemini CLI <gemini-cli@google.com>
2026-04-04feat(tripreport): add AI trip narrative generator with multiple stylesPeter Stone
- Consolidate track data, weather, and log entries into a TripSummary - Implement TripReportGenerator with Professional, Adventurous, Journal, and Pirate styles - Add TripReportFragment and ViewModel for UI interaction - Share TrackRepository and LogbookRepository via NavApplication singleton - Fix compilation error in MainViewModel rich metadata recording Co-Authored-By: Gemini CLI <gemini-cli@google.com>
2026-04-04feat(map): satellite view, windy/chart overlays, and rich track recordingPeter Stone
- Switch default map view to Satellite - Add Windy (partial alpha) and OpenSeaMap overlays - Add custom user position icon (ship arrow) with heading rotation - Update TrackPoint to support rich instrument/weather metadata - Change track visualization to a dotted red line - Robustify NavApplication.isTesting with Espresso detection Co-Authored-By: Gemini CLI <gemini-cli@google.com>
2026-04-04test(smoke): ensure isTesting flag is set before Activity launchPeter Stone
- Use BeforeClass to set isTesting in NavApplication - This ensures MapLibre is bypassed correctly even when ActivityScenarioRule starts before @Before. Co-Authored-By: Gemini CLI <gemini-cli@google.com>
2026-04-04fix(ui): resolve MainActivity crash in smoke tests by reordering ↵Peter Stone
initialization and guarding MapLibre - Ensure lateinit UI properties are assigned before setupMap() and setupHandlers() - Skip MapLibre initialization and lifecycle calls when NavApplication.isTesting is true to avoid emulator Vulkan crashes - Guard MapView lifecycle calls in onResume, onStart, etc. Co-Authored-By: Gemini CLI <gemini-cli@google.com>
2026-04-03chore(stories): add claudomator stories for unused results and faked dataPeter Stone
6 stories covering findings from codebase audit: - ct-remove-mock-tidal: remove random fake tidal currents near Solent - ct-wire-tidal-to-map: wire tidalCurrentState to MapHandler (never called) - ct-wire-anchor-to-map: wire anchorWatchState to map overlay (text-only) - ct-show-wind-direction: display TWD fetched but not shown in sheet - ct-show-swell-direction: display swell dir fetched but not shown - ct-fix-weather-fallback: remove silent SF fallback in WeatherActivity Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03feat(instruments): add forecast wind, wave, swell and current from Open-MeteoPeter Stone
- Add swell params to MarineApiService request - Add swell fields to MarineHourly model - Add MarineConditions snapshot model - Add WeatherRepository.fetchCurrentConditions() (first forecast hour) - Add MainViewModel.loadConditions() + marineConditions StateFlow - Add Forecast section to instrument sheet: Curr / Wave / Swell - Populate TWS from forecast wind speed on first GPS fix - Trigger loadConditions() once on first GPS position received Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03feat(instruments): replace simulation with real GPS and barometer dataPeter Stone
- Drop VMG, Polar %, and PolarDiagramView — no NMEA source on boat - Shrink grid to 3×2 (AWS/HDG/BSP / TWS/COG/SOG) - Move Depth + Baro to expanded section side by side - Initialize all instruments to "—" on startup - Wire LocationService.locationFlow → SOG + COG display (real GPS) - Wire LocationService.barometerStatus → Baro display (device sensor) - Delete startInstrumentSimulation() fake loop entirely Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03chore: allow gh:* in settings to stop permission promptsPeter Stone
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>