Skip to content

feat(android): global quick-toggle to hide all on-video Home Assistant overlays - #488

Merged
badbread merged 4 commits into
mainfrom
feat/ha-hide-toggle-android
Aug 7, 2026
Merged

feat(android): global quick-toggle to hide all on-video Home Assistant overlays#488
badbread merged 4 commits into
mainfrom
feat/ha-hide-toggle-android

Conversation

@badbread

@badbread badbread commented Aug 6, 2026

Copy link
Copy Markdown
Owner

What

One tap hides every Home Assistant badge on live video, on every camera; tap again brings them back. The choice persists across app restarts.

The toggle is offered in two places, and they are the same switch:

  • an eye button on the Live wall's action row, beside the grid-density / snapshot / fullscreen icons;
  • a matching one in the fullscreen view's top-right controls, next to audio / PTZ / playback (shown only for cameras that actually have placed badges — the wall's button is the global entry point).

Both use HintTooltip like their neighbours: "Hide Home Assistant overlays" / "Show Home Assistant overlays", with Icons.Default.Visibility / VisibilityOff.

How

State lives in a process-scoped HaOverlayVisibility holder in AppContainer, seeded from and written back to SecureStore.showHaOverlays (key show_ha_overlays, default true = overlays shown, so nothing changes for an existing install). Both screens observe its StateFlow, so a flip from either surface recomposes both immediately — no restart, no re-entry.

The holder exists rather than a per-screen remember because the Live wall stays on the nav back stack while the user is inside a camera: a local mirror seeded from the store would keep serving the pre-toggle value after the fullscreen button flipped it, and the wall's icon would lie.

Scope: display only

Entity linking, badge placement, the per-camera entities sheet, and the detail/control popups reachable from it are untouched. Inspecting entities has to keep working precisely when an operator has decided the video should stay clean, so the HA sheet button is deliberately not gated on the toggle. The badge tap / long-press targets simply cease to exist along with the badges they sit on.

One perf nicety: while the overlays are hidden and no HA sheet or dialog is open, the /ha/states poll stands down — there is nothing on screen left to keep converged. Any open sheet/dialog still holds the poll up exactly as before.

Files

  • apps/android/.../data/SecureStore.ktshowHaOverlays (mirrors the showHaEntityId / showHaDeviceType pattern; device-level, not cleared on logout)
  • apps/android/.../feature/live/HaOverlayVisibility.kt — new; the shared holder + rememberHaOverlaysVisible()
  • apps/android/.../di/AppContainer.kt — wires the holder to the store
  • apps/android/.../feature/live/LiveScreen.kt — the wall's eye button
  • apps/android/.../feature/live/LiveFullscreenScreen.kt — the fullscreen eye button, the overlay-layer gate, the poll gate
  • apps/android/.../test/.../HaOverlayVisibilityTest.kt — new; seeding does not write, toggle flips + persists, redundant set is a no-op
  • docs/COMPONENT-MAP.md — HA-overlay row, Android cell (desktop/iOS equivalents marked deferred)

Gate

dev2, JDK 17 + /opt/android-sdk: :app:testDebugUnitTest :app:assembleDebugBUILD SUCCESSFUL, HaOverlayVisibilityTest 3/3 passing, no new warnings.

One tap hides every Home Assistant badge on live video, on every camera;
tap again brings them back. The choice persists across app restarts.

The switch is offered in two places, and they are the same switch: an eye
button on the Live wall's action row (beside the grid/fullscreen icons)
and a matching one in the fullscreen view's top-right controls, next to
audio/PTZ. Because the Live wall stays on the nav back stack while the
user is inside a camera, a per-screen `remember` seeded from the store
would keep serving the pre-toggle value and the wall's icon would lie, so
the state lives in a process-scoped HaOverlayVisibility holder in
AppContainer, seeded from and written back to SecureStore
(`show_ha_overlays`, default true = shown). Both screens observe its
StateFlow, so a flip from either recomposes both immediately.

Display-only by design: entity linking, badge placement, the per-camera
entities sheet, and the detail/control popups reachable from it are all
untouched — inspecting entities has to keep working precisely when an
operator has decided the video should stay clean. The badge tap and
long-press targets simply cease to exist along with the badges they sit
on. While the overlays are hidden and no HA sheet or dialog is open, the
`/ha/states` poll also stands down: there is nothing on screen left to
keep converged.

The fullscreen button appears only for cameras that actually have placed
badges; the wall's button is the global one.

Signed-off-by: badbread <badbread@users.noreply.github.com>
…the sole affordance

Owner call during testing: Android wall tiles never render HA badges (badges
are fullscreen-only until #444's mobile badge work), so an eye button on the
wall action row toggled something invisible from where it sat. Remove it; the
in-fullscreen toggle (next to the HA sheet button) is the single affordance,
and the persisted state/store plumbing is unchanged.

Signed-off-by: badbread <badbread@users.noreply.github.com>
…s runs

Signed-off-by: badbread <badbread@users.noreply.github.com>
Signed-off-by: badbread <badbread@users.noreply.github.com>

# Conflicts:
#	docs/COMPONENT-MAP.md
@badbread
badbread merged commit 7ff960d into main Aug 7, 2026
7 checks passed
@badbread
badbread deleted the feat/ha-hide-toggle-android branch August 7, 2026 02:26
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