Skip to content
Merged

mHUD #423

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions openpilot/selfdrive/carrot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,9 @@ web/js/realtime/
carrot_map.js
home_drive.js
hud_card.js
mini_hud.js
mini_hud_mode.js
mini_hud_model.js
nav_hud.js
raw_capnp.js
raw_capnp_worker.js
Expand All @@ -419,6 +422,9 @@ web/js/realtime/
| `realtime/app_realtime.js` | Live runtime polling/raw stream wiring and HUD bridge. |
| `realtime/home_drive.js` | Drive/Carrot Vision renderer and overlay canvas. |
| `realtime/hud_card.js` | HUD card data rendering. |
| `realtime/mini_hud_mode.js` | Compact HUD eligibility, viewport hysteresis, and activation events. |
| `realtime/mini_hud_model.js` | Pure STOCK/NAV/WAZE compact HUD data normalization. |
| `realtime/mini_hud.js` | Compact HUD DOM rendering and responsive typography. |
| `realtime/carrot_map.js` | Kakao minimap iframe bridge (kmap), `FRAME_VERSION` gated to limit SDK quota. |
| `realtime/nav_hud.js` | Carrot Nav HUD V2 — top-center guidance card from `carrotMan` state, no iframe/network. |
| `realtime/raw_capnp.js` | Raw capnp decode entry. |
Expand All @@ -428,6 +434,23 @@ web/js/realtime/
| `realtime/vision_raw.js` | Raw WebSocket client and worker bridge. |
| `realtime/vision_diag.js` | Silent WebRTC/video diagnostic recorder (localStorage ring buffer) feeding the vision diag upload. |

### Compact HUD mode

Compact HUD is an adaptive CWeb surface for resizable launcher panels and
Android multi-window use. By default it enters at viewport widths up to `480px`
when the viewport is at least 22% smaller than the exposed screen or outer
window. Widths up to `280px` are treated as unambiguously compact. The mode
stays active through `539px` and exits at `540px`.

`?mini_hud=auto` bypasses the windowed-evidence check but keeps the width
thresholds. `?mini_hud=force` always enables the surface, and `?mini_hud=off`
disables adaptive detection. Browser JavaScript has no reliable equivalent of
Android `Activity.isInMultiWindowMode()`, so the default evidence check keeps
ordinary full-screen phones out while supporting launcher panels, popup
windows, desktop responsive windows, and multi-window layouts. While active,
raw HUD realtime remains connected and Vision/WebRTC is suspended until the
window leaves Compact HUD mode.

### Translations JS

```text
Expand Down
2 changes: 1 addition & 1 deletion openpilot/selfdrive/carrot/web/css/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ body:has(.page-transitioning) {
line-height: 1.4;
}

@media (max-width: 640px), (orientation: portrait) {
@media (max-width: 640px), (aspect-ratio < 13/10) {
.settings-diff-summary {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
Expand Down
67 changes: 41 additions & 26 deletions openpilot/selfdrive/carrot/web/css/components.css
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,17 @@ body[data-page="terminal"] .app-toast-host {

.app-dialog {
position: fixed;
inset: 0;
/* Anchor to the *visual* viewport, not the layout viewport. With the
on-screen keyboard open, inset:0 centered the sheet in the full-screen
height — so it floated up behind the keyboard (the near-square/landscape
case never hit the bottom-sheet fallback below). viewport.js keeps
--app-vv-top / --app-vv-height in sync with visualViewport, so centering
here always lands in the visible area above the keyboard. Same pattern as
.setting-search-panel. */
top: var(--app-vv-top, 0px);
left: 0;
right: 0;
height: var(--app-vv-height, 100dvh);
z-index: var(--z-modal);
display: flex;
align-items: center;
Expand Down Expand Up @@ -334,7 +344,7 @@ body[data-page="terminal"] .app-toast-host {
line-height: 1.4;
}

@media (max-width: 640px) and (orientation: portrait) {
@media (max-width: 640px) and (aspect-ratio < 13/10) {
.app-dialog {
align-items: center;
padding: calc(12px + env(safe-area-inset-top, 0px)) 8px calc(12px + env(safe-area-inset-bottom, 0px));
Expand Down Expand Up @@ -368,30 +378,14 @@ body[data-page="terminal"] .app-toast-host {
min-height: 40px;
}

.app-dialog--form {
align-items: flex-end;
padding: env(safe-area-inset-top, 0px) 0 0;
}

.app-dialog--form .app-dialog__sheet {
width: 100vw;
max-height: min(72dvh, var(--dialog-sheet-mobile-max-height));
padding: var(--sp-lg) var(--sp-lg) calc(var(--sp-lg) + env(safe-area-inset-bottom, 0px));
border-right: 0;
border-bottom: 0;
border-left: 0;
border-radius: var(--dialog-sheet-radius-mobile) var(--dialog-sheet-radius-mobile) 0 0;
transform: translateY(24px);
}

.app-dialog--form .app-dialog__actions {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
}

.app-dialog--form .app-dialog__actions .smallBtn {
width: 100%;
}
/* Form dialogs (stream key, mapbox token, device actions, …) render as the
SAME centered floating card as every other dialog — no full-width bottom
sheet jammed onto the keyboard. They inherit the mobile card sheet above
(side margins, all corners rounded, full border) and the right-aligned
flex actions from .app-dialog__actions. Because .app-dialog is anchored to
--app-vv-height, the card floats just above the on-screen keyboard when one
is open, and simply centers when there is none — consistent across phone,
foldable and desktop (no keyboard-toolbar dependency). */
}

.app-branch-picker__sheet {
Expand Down Expand Up @@ -1069,6 +1063,27 @@ body[data-page="terminal"] .app-toast-host {
margin-top: var(--sp-sm);
}

/* Form dialogs anchor to the bottom of the visible area (which is
--app-vv-height = above the on-screen keyboard) so the floating card sits
just above the keyboard — the input auto-focuses and the keyboard opens
immediately — instead of floating centered far above it. The container's
bottom padding gives the breathing gap between card and keyboard. */
/* Any dialog that shows a text input (prompt OR form) centers when no keyboard
is up (desktop, keyboard-less devices, or before the field focuses), and hugs
just above the on-screen keyboard with a consistent gap when it is — toggled
by html[data-kb-open] from viewport.js. --kb-inset is the exact keyboard
height incl. the Samsung toolbar on Chromium (VirtualKeyboard API), 0
elsewhere (where --app-vv-height already excludes the keyboard). One shared
--kb-gap keeps this consistent with the terminal and search panel. */
.app-dialog--input {
align-items: center;
}

html[data-kb-open="1"] .app-dialog--input {
align-items: flex-end;
padding-bottom: calc(var(--kb-gap) + var(--kb-inset) + env(safe-area-inset-bottom, 0px));
}

.app-dialog__inputError {
color: var(--md-error);
font-size: var(--fs-label-sm);
Expand Down
Loading
Loading