Haven Docs

Home-screen widget

A small home-screen widget showing Sam: his current growth stage, whatever cosmetics are equipped, his resting mood, one neutral line, and a bare day count. Tapping anywhere opens Haven.

Free, and not gated on a subscription — although it does show Pro-granted cosmetics, because that is simply what the user's Sam looks like.

The quietest surface Haven has#

The launcher is public. Anyone who picks up the phone, glances at it on a desk, or looks over a shoulder sees it.

So the widget is held to a stricter rule than any screen inside the app:

  • Zero gambling language. Never "blocked", never "protected", never "days clean", never anything a bystander could read something into. Only Sam, a neutral thought, and a plain "x days".
  • It reads nothing sensitive. No block log, no protection status, no site names, no app names, no financial data. It cannot leak what it never loads.
  • The widget's accessibility description is "Sam" — a name, not a status. The description stays as quiet as the pixels.
  • Its label and description in the launcher's widget picker are brand-neutral in both supported languages.

If there is no streak to show, the layout simply ends. There is no empty slot and no "sign in to see your streak" nudge.

How it renders#

Android widgets are RemoteViews and cannot run live animation. Sam is therefore rendered once, at rest, into a bitmap — using the exact same drawing code as the in-app Sam, with the clocks frozen. There is one Sam in the codebase, not two that could drift apart.

The widget also has to resolve its colours and its language explicitly, because a widget runs outside the app's own theme and locale context. It follows the appearance mode the user chose in Haven, using the launcher's own night-mode signal for "follow system", and it speaks the language chosen in Haven rather than the phone's language.

When it refreshes#

Two mechanisms, and neither is the system's own widget alarm:

  • On change. Haven observes the stores that hold anything the widget displays — feeding, growth, cosmetics, the chosen trick, the streak, subscription state and language — and re-renders when any of them changes. Bursts are coalesced into a single redraw.
  • Every six hours. A background worker as a safety net, which also keeps the time-of-day and day-of-year parts of the display from going stale.

Refreshing when the widget is not placed on any home screen is a cheap no-op, so this runs unconditionally rather than being conditioned on widget state.