| Age | Commit message (Collapse) | Author |
|
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
|
|
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
|
|
- LogbookStorage: reads/writes nav_logbook.json and photos into the SAF
logbook/ subfolder, using the same saf_tree_uri pref as TrackStorage.
Automatically migrates legacy getExternalFilesDir JSON on first SAF
write. Falls back to external files when SAF is not yet configured.
- LogbookRepository: expose cameraDir (cache-backed temp for FileProvider),
copyPhoto(Uri), and importPhoto(File) instead of the old photoDir.
- VoiceLogFragment / TrackDetailSheet: camera writes temp to cacheDir then
imports to SAF after capture; gallery delegates to copyPhoto(); photo
display and decodeThumbnail handle both content:// URIs and file paths.
- file_paths.xml: add cache-path entry so FileProvider can serve camera
temp files from cacheDir/nav_camera/.
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
Gallery photos were always anchored to track.endMs with the final GPS
position. Now reads EXIF DateTimeOriginal (parsed in device local time)
after copying the file; if the timestamp falls within the track window
the note is positioned at the correct time and nearest track point.
Notes taken outside the window fall back to the previous behaviour.
Map note layer was never refreshed after saving — drawNotes() ran once
at style-load time and the GeoJsonSource was never updated. Added
refreshNoteLayer() which updates the existing source or creates it if
no notes existed before.
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
ANR: getSavedTracks() had no IO dispatcher — TackDetector ran on main
thread at O(n²) cost (~77M ops for a 2.5h track). Added withContext(IO).
TackDetector: replaced O(n) list.filter with O(log n) binary-search
subList for before/after windows; O(n²) → O(n log n). Raised MIN_DELTA
60°→75° to stop detecting ordinary course corrections as maneuvers.
Removed MAX_DELTA cap entirely — 180° crash-tacks are valid; the
circularMAD stability windows are the real quality gate.
TrackDetailSheet: dropped the arbitrary abs(delta)>70 Tack/Jibe
heuristic. Now uses true wind angle when available for classification;
falls back to "Maneuver" when TWD is absent.
SavedTracksFragment: added isLoadingTracks StateFlow (MainViewModel);
combine() suppresses the empty-state layout while the initial IO load
runs so it no longer flashes "No saved tracks yet" before data arrives.
16/16 TackDetector tests pass.
https://claude.ai/code/session_01KXYBuAHZkvv63DeUG6XaZD
|
|
Replace the point-count window (HALF_WIN=2) with 30s time-based settle
windows that give consistent reliability regardless of GPS update rate
(1 Hz FULL vs 0.2 Hz ECONOMY). Key changes:
- Before/after windows are time-based (T_SETTLE=30s) around a guard
zone (T_MANEUVER=30s), not point counts.
- Stability uses circularMAD (<20°) across all fixes in each window,
replacing the single-pair spread check. This correctly handles
0°/360° wrap and suppresses random anchor-watch COG noise (MAD≈90°).
- No SOG gate: averaging 30 fixes over 30s reduces noise by √30
regardless of boat speed. A boat at anchor has MAD≈90° and is
rejected by the stability check.
- MAX_DELTA raised to 160° (covers deep jibes the old 140° missed).
- START_SKIP reduced to 60s (stability check handles cold-start noise).
- De-duplication uses adjacent-candidate comparison so a long stream
of raw candidates from one maneuver stays in a single group even if
it spans >MIN_GAP_MS in total.
- Position refined to max instantaneous heading rate within the
maneuver zone.
- Mode: CRUISING (conservative). Race mode noted as future backlog.
16/16 unit tests pass at 1 Hz (FULL mode GPS rate).
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
- TrackDetailSheet: + Add note button opens a dialog with text, camera,
and gallery. Entry is saved with timestampMs=track.endMs so it lands
inside the track's time window and appears automatically in the event
log. logEventAdapter.update() refreshes the list after save.
- TripReportGenerator: removed NarrativeStyle enum and 4-style branch.
generateNarrative() now emits a concise PASSAGE header (date, time
range, duration), stats line (nm / avg kt / max kt), optional conditions
(seas, temp), and a timestamped deck log. Fragment and layout updated to
remove the ChipGroup style picker.
- TrackColors: replaced Expression.get("color") — which silently fails
for lineColor on LineLayer in MapLibre Android 11.x — with
Expression.step(Expression.get("speed"), ...) that maps the numeric
"speed" property directly to color literals. "color" string property
removed from speedSegments() features.
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
Camera:
- Replace ActivityResultContracts.TakePicture() with explicit
StartActivityForResult + Intent(ACTION_IMAGE_CAPTURE) + EXTRA_OUTPUT
so the full system camera app always opens (not a sub-view preview)
- FLAG_GRANT_WRITE_URI_PERMISSION added for camera app FileProvider access
LogbookStorage:
- getExternalFilesDir() can return null when external storage is
unavailable; fall back to filesDir for both storageFile and photoDir
so saves never silently fail on devices without external storage
Backlog (worklog.md):
- Add notes/photos to finished tracks + include in trip report
- Trip report voice: replace generic style picker with single Nav voice
- Fix tack detection false positives at low SOG
- Investigate/fix speed coloring in MapLibre Android 11.x
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
LocationService:
- Add _currentSpeedKt/_currentDirectionDeg to companion state
- Add setCurrentConditions() companion function
- snapshot() now returns real current data instead of null
- MainActivity.applyConditions() calls setCurrentConditions() on each
marine conditions update
TrackDetailSheet:
- buildLogEvents() filters NavApplication.logbookRepository entries by
track time window (startMs..endMs); entries without GPS snap to nearest
track point by timestamp
- Note/photo events added to the event log list with 📝/📷 icons
- drawNotes() adds a green CircleLayer for note/photo markers on the map
- LogEvent extended with photoPath field
- LogEventAdapter shows a downsampled photo thumbnail when present
item_log_entry.xml: add iv_log_thumb ImageView (hidden by default)
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
Bugs fixed:
- LogbookStorage.copyFromUri: return null when ContentResolver returns null
stream instead of returning a path to an unwritten file
- VoiceLogFragment adapter: decode photos as downsampled thumbnails
(128x96 target) using BitmapFactory inSampleSize instead of loading
full-resolution bitmaps on the main thread
Tests added:
- LogbookRepositoryTest: ID sequencing, insertion order, storage delegation,
reload from persisted state, lat/lon preservation
- TripReportGeneratorTest: log entry time-range filtering, distance
calculation, empty-points edge case, all narrative styles smoke-tested
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
Resolve conflict in TackDetector.kt: keep null-safe lastTackMs check
from main (branch had a NPE-unsafe subtraction on nullable Long).
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
- LogbookStorage: Moshi-backed JSON persistence to getExternalFilesDir,
photos saved to Pictures/Nav/ instead of cache
- LogbookRepository: file-backed replacement for in-memory store, loads
saved entries on init so they survive app restarts
- VoiceLogViewModel: expose entries StateFlow, accept lat/lon in save()
- VoiceLogFragment: switch camera to TakePicture(Uri) via FileProvider for
full-res photos; gallery copies content URI to persistent storage;
passes current GPS position to save(); shows scrollable entries list
- MainViewModel: expose currentPosition StateFlow updated on each GPS fix
- AndroidManifest: add FileProvider for Pictures/Nav/ directory
- TripReportViewModel: updated to use LogbookRepository
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
The speed-color expression approaches all failed silently. Reverting to
the exact pre-speed-color form (single Feature LineString, static
#2B8FC4) to re-establish a visible track line while diagnosing why the
FeatureCollection/expression approach doesn't render.
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
Instead of asking MapLibre to interpolate/step colors at render time
(which was silently failing), pre-compute the CSS hex color for each
segment in speedSegments() and store it as a "color" property.
speedColorExpression() is now Expression.get("color") — a simple
property lookup that MapLibre parses as a CSS color for line-color.
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
getSavedTracks() was called inside .onSuccess{} with no error boundary;
any exception from toSavedTrack() crashed the coroutine silently after
_pastTracks was already set, leaving _savedTracks empty (tracks visible
on the main map dim layer but missing from the Log tab list).
Wrap every getSavedTracks() call in runCatching, and make toSavedTrack()
inside getSavedTracks() skip individual bad tracks via mapNotNull so one
corrupt GPX can't blank the whole list.
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
Expression.color(Color.parseColor()) inside interpolate() stops was
silently failing to render on device. Replace with Expression.step()
and Expression.literal(hexString) which MapLibre's renderer handles
natively for line-color.
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
Each focused track is rendered as per-segment LineStrings tagged with
average SOG, interpolated blue→cyan→green→amber→red for 0→13+ knots.
Applies to both the main map focus layer and the track detail sheet.
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
subtraction overflow, filtering every tack
|
|
from VoiceLogFragment
|
|
from VoiceLogFragment
|
|
fixes, dim past tracks
* Fix tack detection and convert track detail to embedded-map fragment
TackDetector: revert STABILITY_MAX to 30° (was tightened too far to 20°),
add 120s start-skip to filter GPS cold-start false positives, keep 45s
minimum gap between tacks.
TrackDetailSheet: convert from BottomSheetDialogFragment to a regular
Fragment with an embedded MapLibreMap in the top half. This fixes the
map centering issue (the embedded map is always sized to its own frame),
eliminates accidental dismissal when dragging the map, and makes the
view self-contained — back navigation restores the track list via the
fragment back stack. Tack markers rendered on the embedded map; tapping
a log event pans the embedded map directly.
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
* Fix XML conflict markers left in layout_track_detail_sheet.xml
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
* Fix Kotlin conflict markers left in TrackDetailSheet.kt
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
* Fix compile errors on feature branch
- SavedTracksFragment/VoiceLogFragment: remove references to SafState,
safState, launchSafPicker, layout_empty, btn_setup_storage, and
layout_log_entry — none of these exist on this branch
- TrackStorage: add missing onCancellation lambda to cont.resume()
- build.gradle: enable buildConfig generation (fixes unresolved BuildConfig)
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
* Dim past tracks: dark navy 0.12 opacity, solid lines
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
---------
Co-authored-by: Claude <noreply@anthropic.com>
|
|
past track opacity
- Tack detector: STABILITY_MAX=30, START_SKIP_MS=120s cold-start filter (feature branch)
- TrackDetailSheet: embedded Fragment with MapView, back button pops stack (feature branch)
- layout_track_detail_sheet: MapView top half, detail panel bottom half (feature branch)
- MapHandler past track dim opacity: 0.12 (down from 0.22)
- SavedTracksFragment: fragment transaction to TrackDetailSheet + SAF setup (both)
- VoiceLogFragment: inline track list, logViewModel refs fixed (main)
|
|
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
- SavedTracksFragment/VoiceLogFragment: remove references to SafState,
safState, launchSafPicker, layout_empty, btn_setup_storage, and
layout_log_entry — none of these exist on this branch
- TrackStorage: add missing onCancellation lambda to cont.resume()
- build.gradle: enable buildConfig generation (fixes unresolved BuildConfig)
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
TackDetector: revert STABILITY_MAX to 30° (was tightened too far to 20°),
add 120s start-skip to filter GPS cold-start false positives, keep 45s
minimum gap between tacks.
TrackDetailSheet: convert from BottomSheetDialogFragment to a regular
Fragment with an embedded MapLibreMap in the top half. This fixes the
map centering issue (the embedded map is always sized to its own frame),
eliminates accidental dismissal when dragging the map, and makes the
view self-contained — back navigation restores the track list via the
fragment back stack. Tack markers rendered on the embedded map; tapping
a log event pans the embedded map directly.
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
Sheet: set isDraggable=false so scrolling the event list doesn't push
the sheet up over the map. Top 50% stays map, bottom 50% stays list.
Tack detector: replaced 5-index skip (~5 s at 1 Hz) with a 45-second
timestamp gap. Also tightened STABILITY_MAX from 30° to 20° to reduce
false positives from GPS heading noise.
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
Kotlin inferred Feature|FeatureCollection as their common supertype,
which didn't match any single setGeoJson overload. Split into two
explicit branches so each call site has an unambiguous type.
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
Removed the 'Saved Tracks' button that opened a separate overlay.
Tracks now appear directly on the Log screen in a RecyclerView below
the Generate Trip Report button. Tapping a track hides the overlay and
opens the existing TrackDetailSheet bottom sheet over the map.
The log entry section (text field, mic, camera, save/clear) is hidden
with visibility=gone when not recording and shown when a recording is
in progress. The storage-setup prompt is now surfaced here too.
SavedTrackAdapter and DATE_FMT widened to internal so VoiceLogFragment
can reuse them directly. SavedTracksFragment kept for the GPX import flow.
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
All past tracks render as solid dark navy (#0B3050) at 45% opacity,
2.5px — no dashes. A second focus layer (#2B8FC4, full opacity, 4px)
paints on top when a track is selected, making it pop without changing
the dim layer's data. Active recording stays red.
The dim layer always contains every past track; the focus layer gets
the selected track's points independently via setFocusedTrackPoints().
Cleared on dismiss so all tracks return to equal dim opacity.
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
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
|
|
Removed the spurious constraintBottom_toBottomOf="parent" from forecast_row:
ConstraintLayout was vertically centering it between the wave and the sheet
bottom (default bias 0.5) instead of placing it flush below the wave.
Also aligned light-mode wave_sea_bottom (#074B68 → #0D2137) with the
forecast_row background so the wave tail blends seamlessly in light theme.
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
- hideOverlays() now resets bottomSheetBehavior to COLLAPSED/not-hideable,
so the conditions sheet reappears correctly when returning from any overlay
(previously it stayed hidden after navigating away via the track browser)
- Remove btn_saved_tracks from the conditions sheet (layout + click handler)
- Add btn_saved_tracks to the Log screen layout and wire it in VoiceLogFragment
via MainActivity.showSavedTracks(); tracks live with the log, not with weather
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|
|
- SavedTracksFragment was missing adapter.submitList(tracks) after the
collect block rewrite — tracks loaded fine (16 found via SAF) but the
RecyclerView adapter never received them, leaving the list visually blank
- showOverlay() now also hides fabRecenter; it was not in the hide list so
the map's Recenter button remained visible on top of the fragment overlay
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
|