Skip to content

Sentry heatmap and address display#227

Merged
vide merged 18 commits intomainfrom
feature/sentry-heatmap-addresses
Apr 4, 2026
Merged

Sentry heatmap and address display#227
vide merged 18 commits intomainfrom
feature/sentry-heatmap-addresses

Conversation

@vide
Copy link
Copy Markdown
Owner

@vide vide commented Apr 4, 2026

Summary

  • Add a 12x6 heatmap (6 days, 2h blocks) at the top of the Sentry History screen showing event density with red intensity gradient
  • Show reverse-geocoded address (or TeslaMate geofence name) instead of repeating "Alert detected" in alert rows
  • Tapping a heatmap cell shows a tooltip with date, time range, and event count; tapping the tooltip scrolls to that time in the list
  • Future hours on today's row are transparent; heatmap colors and theme follow the system light/dark mode

Changes

  • DB migration v10→v11: added latitude, longitude, address columns to sentry_alert_log
  • SentryStateRepository: passes car coordinates and geofence at alert insert time
  • SentryHistoryViewModel: computes heatmap data, lazy address resolution via geocode cache then Nominatim
  • SentryHistoryScreen: heatmap composable with tooltip via PopupPositionProvider, address in alert rows

Test plan

  • Simulate sentry events from debug settings — verify address appears
  • Check heatmap renders correctly in both light and dark themes
  • Tap heatmap cells on all 6 rows — tooltip should appear below (rows 1-3) or above (rows 4-6)
  • Tap tooltip — should scroll to matching alerts in the list
  • Tap outside tooltip — should dismiss
  • Verify future hours on today's row are transparent
  • Verify X axis shows locale-appropriate time labels (00, 06, 12, 18, 23)

🤖 Generated with Claude Code

vide and others added 18 commits April 4, 2026 17:06
- Add 12x6 heatmap (72 hours) showing event density with red intensity
- Show reverse-geocoded address instead of "Alert detected" in alert rows
- Store lat/lon/address in SentryAlertLog (DB migration v10→v11)
- Pass car coordinates from status poll into sentry alert log
- Lazy reverse geocoding via Nominatim when history screen opens
- Tapping a heatmap cell scrolls to the corresponding time in the list

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The car's sentry position is always the end of the last drive, so
the geocode cache already has that grid cell. Check it first and
only fall back to Nominatim API if the cache misses.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a day spans two rows in the heatmap, the label is now offset
down by half a cell height so it visually centers between both rows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Same 12x6 grid (72 blocks), same color threshold (20+ = full red),
but each block now covers 2 hours instead of 1, giving 6 days of
history instead of 3.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The debug "Simulate Sentry Event" button now fetches the car's
current lat/lon from the API so simulated alerts also get
reverse-geocoded addresses.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Store the geofence name directly as the address at insert time,
matching the normal code path. Reverse geocode via cache/Nominatim
only kicks in for alerts without a geofence but with lat/lon.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each row is now one calendar day (midnight-aligned), so Y axis
labels are always clean day names (EEE d / Yesterday / Today).
X axis now shows 00, 06, 12, 18 matching the 2h-per-block layout.
Removed BoxWithConstraints and offset logic that are no longer needed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Labels now show 00, 06, 12, 18, 23 formatted with the system
locale (24h or 12h AM/PM depending on user settings).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use isSystemInDarkTheme() instead of hardcoded darkTheme=true.
Heatmap empty cell color now derives from the palette so it adapts
to light/dark mode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Empty-to-red interpolation now starts from palette.onSurfaceVariant
(theme-aware) and ends at StatusError, so the entire gradient
adapts to light/dark mode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Blocks for hours that haven't happened yet are now transparent
(showing the background), distinguishing them from past hours
with zero events.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tapping a heatmap cell now shows a tooltip with date, time range,
and event count. Tapping the tooltip scrolls to that time in the
history list. Tapping outside dismisses it. Tooltip uses Popup with
focusable=true for proper dismiss behavior.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Tooltip is now wider than tall with 3 no-wrap lines: date, time
  range, event count
- Selected cell gets a thick border highlight so it stays visible
- Tooltip placed below the cell, or above if in the bottom half
  of the grid, so the selected block is never obscured

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tooltip now measures its own height and subtracts it from the
offset when placing above the cell, so it sits correctly above
bottom-half rows and below top-half rows with a 4dp gap.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Popup coordinates are relative to the window, not the grid, causing
wrong positioning. Now uses a Box overlay inside the grid's own
Box, so boundsInParent() coordinates match the tooltip offset
coordinate space. Adds an invisible scrim for outside-tap dismiss.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Instead of calculating coordinates manually, the Popup is now
declared inside the tapped cell's Box. It auto-anchors to that
cell using Alignment.TopCenter (above) or BottomCenter (below)
based on row position. No coordinate math needed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Custom PopupPositionProvider receives both anchor bounds and popup
content size, enabling exact placement above or below the cell.
Centers horizontally with window-edge clamping. No more guessing
popup height or misaligned offsets.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vide vide merged commit e0dfe5f into main Apr 4, 2026
1 check passed
@vide vide deleted the feature/sentry-heatmap-addresses branch April 4, 2026 17:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant