| Age | Commit message (Collapse) | Author |
|
|
|
|
|
|
|
|
|
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Replace Gson dependency in AtonData with org.json.JSONObject (Android SDK
built-in) and add testImplementation for org.json to support unit tests.
AtonRepository now falls back to stale cache data when the network is
unavailable rather than returning an empty list.
|
|
Implements AtonData (color mapping + Gson-based JSON parsing for NOAA
AtoN station data) and AtonRepository (disk-cached HTTP fetcher).
Uses Gson instead of org.json so unit tests run on the JVM classpath.
7/7 AtonDataTest assertions pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Code map updated for all 2026-06-30 changes: ui/fishing/ package, FadData,
MapLayerManager (SST/depth/ATON), SafetyFragment collapsible, PreTripReport
auto-generate, LogEntry.trackId, idle timer, NightVision vs dark mode.
New 5-task plan: NOAA chart tiles, ATON vector layer, TSS overlay.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Remove MODE_NIGHT_NO from NavApplication — system dark mode now respected;
NightVision toggle (red-on-black) is separate and unaffected
- Depth layer: swap empty OpenSeaMap depth tiles for NOAA CoastWatch ETOPO180
WMS which has full Pacific/Hawaii coverage
- FADs default to visible (was off) since Hawaii DAR data is loaded at startup
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Adds setupFishingLayer() and updateFishingBearing() to MapHandler with
destinationPoint() haversine helper. Draws dashed orange line from boat
toward the computed fishing target bearing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
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 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Adds SST source/layer to MapLayerManager, SST toggle to LayerPickerSheet
UI and wires it up in MainActivity.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Also fix pre-existing test compile errors in WeatherApiServiceTest (nullable list access)
and add missing metresToFeet/formatFt helpers to InstrumentHandler.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Dark mode:
- Force light mode (AppCompatDelegate.MODE_NIGHT_NO) in NavApplication
Log screen:
- Tracks sorted newest-first (sortedByDescending startMs)
- Photos/entries saved during a track tagged with trackId; ship's log
shows only standalone entries (trackId == null)
- "Plan Trip" button moved from safety screen to log screen header row
- Pre-trip report auto-generates (newAutoInstance) when a track starts
Safety screen:
- Removed "Plan Trip" button (now in log screen)
- Quit button moved to top title row
- Anchor Watch section collapses by default (tap header to expand)
- Hardware Data Sources section collapses by default (tap header to expand)
Notifications + idle:
- Tracking notification becomes persistent (setOngoing true) while recording
- Notification title changes to "Recording track" when active
- App exits automatically after 3 hours of idle (resetIdleTimer via
onUserInteraction + onResume; suspended while recording)
FAD layer:
- FadData.kt: 18 Hawaii Island DLNR FAD coordinates hardcoded
(source: DLNR Division of Aquatic Resources 6/14/07)
- FAD GeoJSON populated on style load from static data
Fishing mode plan:
- docs/superpowers/plans/2026-06-30-fishing-mode.md: 7-task plan for
RigAdvisor, SST tiles, FishingModeManager, FishingOverlayView, steering
bearing line, and FAB integration
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- MapLayerManager: depth contour tiles (OpenSeaMap), seamarks made
toggleable (was always visible), FAD pref; layer order is now
satellite → charts → wind → depth → seamarks
- MapHandler: FAD GeoJSON layer (orange circles + zoom-10 labels),
setupFadLayer / setFadLayerVisible / updateFadLayer helpers
- LayerPickerSheet: wire seamarks, depth, FAD switches; fix chip
binding direction bug (DepthUnit.METERS side was swapped)
- layout_layer_picker_sheet: add OCEAN LAYERS section with three
toggles (seamarks/nav aids, depth contours, FADs)
- MainActivity: call setupFadLayer on style load; wire all three
ocean layer callbacks in buildLayerPickerSheet
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
The batch wind-grid endpoint only requests windspeed_10m and
winddirection_10m, so temperature_2m, precipitation_probability, and
weathercode are absent from its response. Moshi required these fields
and threw, causing fetchWindGrid to silently fail.
Made those three fields nullable with null defaults in WeatherHourly.
Updated the two call sites in WeatherRepository that access them via
the full forecast endpoint to use safe-call syntax.
https://claude.ai/code/session_017TwkSjhzhmTcHKmVG5MWUa
|
|
retention
- Stop GPS updates entirely when backgrounded and idle (was: drop to 5s ECONOMY)
- Add PowerMode.NONE, ACTION_STOP_UPDATES; guard startLocationUpdatesInternal against NONE
- Fix _currentPowerMode initial value FULL→NONE for accurate state tracking
- Fix code-map GPS section (DeviceGpsProvider dead code, no No-GPS banner, replay=1 caveat)
- Add review-intent-reality.md audit prompt + Living Documentation mandates to config.md
https://claude.ai/code/session_0126zvB69ccVoFtx2o96oaE2
|
|
code-map.md:
- Correct the GPS gotcha section: DeviceGpsProvider uses LocationManager
(not FusedLocationProviderClient) and is dead code — never instantiated
- Remove the false claim that MainViewModel shows a "No GPS" banner
- Document locationFlow replay=1 staleness behaviour accurately
- Document ACTION_STOP_UPDATES background-idle behaviour added in this session
config.md:
- Add review-intent-reality.md to the directory table
- Add two Living Documentation mandates: code-map accuracy obligation
and intent-reality audit cadence
review-intent-reality.md (new):
- Structured audit prompt covering 6 categories: code-map vs implementation,
dead code with documented intent, lying comments, architectural invariants,
design-doc vs shipped code, worklog vs current state
- Standardised finding format (doc claim / code reality / severity / fix)
- Post-review commit convention
https://claude.ai/code/session_0126zvB69ccVoFtx2o96oaE2
|
|
The previous fix (48ae3b0) dropped to ECONOMY (5 s interval) on app
pause, but never stopped location requests. The fusedLocationClient
continued polling indefinitely in the background even with nothing
recording or anchor-watching — accessing location without any need.
Fix:
- Add PowerMode.NONE to represent "no updates in flight"
- Add ACTION_STOP_UPDATES to LocationService: calls
stopLocationUpdatesInternal() and parks _currentPowerMode at NONE
- Guard startLocationUpdatesInternal() against PowerMode.NONE so a
stray setPowerMode(NONE) call can never request zero-interval updates
- Change _currentPowerMode initial value from FULL to NONE (accurate:
no updates are running at process start)
- throttleLocationIfIdle() now sends ACTION_STOP_UPDATES instead of
ACTION_START_ECONOMY; the existing restoreLocationMode() on onResume
already sends ACTION_START_ECONOMY which transitions NONE→ECONOMY
correctly since NONE != ECONOMY bypasses the no-op guard
Tracking and anchor-watch paths are unchanged: throttleLocationIfIdle()
skips the stop if either is active, and onResume sends ACTION_START_FULL
when recording is still in progress.
https://claude.ai/code/session_0126zvB69ccVoFtx2o96oaE2
|
|
Two bugs prevented wind particles from rendering:
1. Retrofit URL-encoded commas in the batch lat/lon query strings
(%2C instead of ,), so Open-Meteo rejected every grid fetch silently.
Fixed with encoded=true on the @Query annotations.
2. loadWindGrid() was only called from onCameraIdleListener, so particles
never started unless the user manually panned. Added an eager trigger
on the first GPS fix using the map's current visible region.
Also added a log warning when fetchWindGrid fails so future failures are
visible in logcat.
https://claude.ai/code/session_017TwkSjhzhmTcHKmVG5MWUa
|
|
https://claude.ai/code/session_017TwkSjhzhmTcHKmVG5MWUa
|
|
- Particles now use bilinear interpolation of the 4×5 wind grid so
speed and direction vary by position, swirling around weather systems.
Particles are hidden until the first grid arrives (no stale fallback).
- Replace 150–300 per-particle toScreenLocation() JNI calls with a
single 3-point affine transform computed once per frame. Rendering
stays smooth during map panning.
- Per-particle tail direction is now derived from the local (u,v) wind
vector rotated into screen space by the map bearing.
- Density: N 300→600, activeN range [150,600] (was [60,300]).
- Opacity: max alpha 200→110, min 15→8; stroke 3.5→2.5 px.
Wire setWindGrid() in MainActivity windGrid.collect alongside the
existing updateWindGridLayer() call.
https://claude.ai/code/session_017TwkSjhzhmTcHKmVG5MWUa
|
|
https://claude.ai/code/session_017TwkSjhzhmTcHKmVG5MWUa
|
|
Two bugs caused particles to appear stationary:
1. Speed constant was 0.03 (particles moved ~7 px/s at 10 kt — barely
perceptible). Changed to 0.1 so a 10-kt particle crosses the full
viewport in MAX_AGE seconds (~24 px/s), producing clear streaming.
2. Individual respawn assigned a random age in [0, MAX_AGE). Half of
all newly spawned particles were born old and faded out almost
immediately without traversing visible distance, giving a "static
noise" look rather than flowing motion. Respawn now starts near age 0
(with a 0–2 s jitter to desynchronise simultaneous respawn bursts).
https://claude.ai/code/session_017TwkSjhzhmTcHKmVG5MWUa
|
|
https://claude.ai/code/session_015p2yh5CaTdjWWJatAz5NBY
|
|
Comprehensive bootstrap doc for future agent sessions: full package/file
table for every domain, architectural invariants (SAF source-of-truth,
NavLogger, MOB always-on-top, etc.), testing commands, CI/merge workflow,
and a gotchas section covering known tricky spots.
Updated config.md directory table and worklog.
https://claude.ai/code/session_015p2yh5CaTdjWWJatAz5NBY
|
|
Physical layout, parts list with costs, step-by-step wiring, RF chain,
BMP280 pressure vent, pre-close checklist, first power-on sequence,
and troubleshooting table. Complete pin summary at the end.
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
Transport:
- NmeaStreamManager supports TCP and UDP modes
- NmeaConnectionPrefs replaces hardcoded 192.168.1.1:10110; defaults
to UDP/10110 matching PMIM-1 spec (ESP32 AP at 192.168.4.1)
- LocationService reads prefs via startNmeaFromPrefs()
Parsing:
- NmeaParser.parseXdr() handles $IIXDR attitude (HEEL/PTCH in degrees)
and baro (pressure in bar → hPa, air temp °C)
- New AttitudeData and NmeaBaroData sensor types
UI:
- Heel + pitch row in instrument sheet (hidden until data arrives)
- InclinometerView: canvas circle with rotating waterline (heel) and
displaced dot (pitch), colorPrimary-tinted, respects night mode
- Inclinometer overlay top-left of map, appears on first attitude packet
- NMEA baro overrides device sensor reading when available
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
Single-tap moon FAB (stacked below layers FAB) toggles red-on-black
night vision mode. NightVision theme now has a full M3 color palette
(surface, surfaceVariant, outline, secondary, error) all in dark red
tones. Screen brightness is set to 30% in night mode and restored to
system default on exit. State persists across sessions; recreate()
applies the theme switch cleanly.
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
Replaces monospace text block with:
- Full-bleed MapLibre track map (260dp) at the top
- Structured stats row (distance / avg speed / max speed)
- Conditions row (wave height, temp) in user-preferred units
- Log entries with full-width photo thumbnails
- Pirate mode Easter egg preserved via long-press title
- Speed, temp, and depth formatted with UnitPrefs
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
entries
Layout:
- Stats displayed as three large-number columns (distance / avg kt / max kt)
- Date and time range as a clean header above stats
- Conditions row (seas + temp) conditionally shown
- Log entries rendered as a proper list with HH:mm timestamps
- No GENERATE REPORT button — report auto-generates on open; RETRY shown only on error
- Pirate mode (long-press title) still renders monospace narrative as before
Generator:
- Time format changed from 4-digit HHmm to HH:mm
- "(photo only)" entries display as 📷 instead of literal "(photo only) [photo]"
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
Each track row already has a REPORT button; the standalone button was redundant.
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
SavedTrackAdapter gained an onReport callback when the REPORT button was added
to the track list. VoiceLogFragment was still using the old single-lambda form.
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
LogbookRepository thread safety
Room fast-path (item 3):
- TrackEntity.toShallowSavedTrack() reconstructs SavedTrack from cached summary
data using two placeholder TrackPoints that preserve correct endMs for logbook
filtering without parsing GPX
- TrackRepository.getSavedTracksFromRoom() returns shallow tracks sorted by startMs
- MainViewModel.init{} now shows Room data immediately (no spinner on warm start),
then replaces with full GPX-parsed tracks once background load completes
AnchorWatchHandler orphan (item 4):
- Deleted ui/anchorwatch/AnchorWatchHandler.kt — the anchor depth/rode form was
inlined into SafetyFragment; this Fragment had no navigation entry points left
- Deleted layout/fragment_anchor_watch.xml (only referenced by the deleted Fragment)
LogbookRepository thread safety (item 6):
- Added @Synchronized to save(), getAll(), and reload() to prevent concurrent
mutation of the entries list and nextId counter across coroutine contexts
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
- Deleted com.example.androidapp ghost package (18 stale source files)
- Fixed tide model package declarations and HarmonicTideCalculator imports
- Symlinked test-runner TackDetector to android-app canonical source
- Fixed forecast to use current wall-clock hour slot instead of app-start hour
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
TackDetector, fix forecast current hour
- Deleted all 18 stale source files in com.example.androidapp (main + test)
that duplicated org.terst.nav implementations from an earlier namespace
- Fixed the 3 tide model files (TidePrediction/Station/Constituent) whose
package declarations read com.example.androidapp.data.model despite living
in org.terst.nav.data.model directories
- Fixed HarmonicTideCalculator.kt imports to match the corrected package
- Fixed TideModelTest.kt package declaration
- Migrated HarmonicTideCalculatorTest to org.terst.nav.tide with correct imports
- Replaced test-runner's TackDetector.kt copy with a symlink to the android-app
canonical source so the two can never diverge again
- Fixed addGpsPoint to pick the current wall-clock hour's forecast slot instead
of always using the app-start hour (first item in forecast list)
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
Uses marineConditions.windDirDeg (refreshed every 20 min / 10 nm) falling
back to forecast.windDirDeg (initial Open-Meteo fetch) to compute a
boat-relative true wind angle: twa = (windDirDeg - cogDeg + 360) % 360.
Stores windSpeedKnots, windAngleDeg, and isTrueWind=true on every GPS
fix that has forecast data, enabling proper Tack/Jibe classification in
buildLogEvents() instead of the "Maneuver" fallback.
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
- getSavedTracks() now returns tracks sorted by startMs ascending so
the overview list shows oldest→newest
- item_saved_track.xml gets a small REPORT text button below the stats row
- SavedTrackAdapter wires onReport callback; SavedTracksFragment navigates
to TripReportFragment.newInstanceForSavedTrack() after selecting the track
- TripReportViewModel.generateReportForSavedTrack(track) generates a
post-trip narrative from a completed SavedTrack's points + logbook entries
- TripReportFragment detects ARG_FOR_SAVED_TRACK, reads selectedTrack from
MainViewModel, and uses the saved-track variant; Refresh button re-runs
the same variant
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
LogbookRepository loaded entries once at init; after reinstall the SAF
tree URI pref is wiped, so it loaded empty from the cleared legacy path
and held that empty list for the session — even after the user re-granted
SAF access.
Fix: add LogbookRepository.reload() and call it in
MainViewModel.onSafDirectorySelected() alongside reloadPastTracks().
The logbook JSON and photos already live in the SAF tree and survive
reinstall; this just ensures they're read at the right moment.
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
Adds TrackEntity/TrackDao/NavDatabase (Room v2.6.1). TrackRepository
writes to Room on stopTrack() and importTrack(), and backfills existing
tracks on first cold-start when the Room cache is empty. GPX/SAF remains
source-of-truth for reinstall; Room is a fast metadata cache for future
list-view optimisation.
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
Replaces the "Configure Anchor Watch" button with depth and rode EditTexts
directly in the anchor card; radius updates live via TextWatcher.
Removes the separate AnchorWatchHandler overlay flow and onConfigureAnchor()
from SafetyListener.
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
Covers estimatedSogKt (hull-speed cap, point-of-sail ordering, light-air,
hull-length scaling, overpowered vs sweet-spot) and generateReport
(condition window size, Now label, heading range, outbound nm, sail plan
logic, watch items, similar trips).
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
Introduces TackMode enum (CRUISING/RACE) and per-mode Config, replacing
the previous single set of hardcoded constants.
RACE config: T_SETTLE=12s, T_MANEUVER=20s, STAB_MAX=30°, MIN_GAP=20s,
START_SKIP=20s — tighter windows for quick successive tacks at race
starts and mark roundings. CRUISING remains the default.
Two new tests demonstrate the behavioral difference: RACE fires earlier
(past 20s cold-start vs 60s) and keeps separate events for a 50s gap
that CRUISING deduplicates (50s < 60s MIN_GAP). 18/18 passing.
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
Long-press the "Trip Report" header flips the narrative into pirate
dialect (☠ VOYAGE header, "Made X nm by the log", "Avast!" log-entry
prefixes, closing "Fair winds and following seas. Arr."). Long-press
again returns to standard nav voice. Seamanlike output remains the
default; pirate mode is purely opt-in.
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|