The launch records two history entries, so the first back press does nothing (and does not exit on Android) #142

Closed
opened 2026-08-19 21:45:06 +00:00 by logan · 0 comments
Collaborator

Report

The app records two history entries before the user has touched
anything, so the first back press at the root does nothing visible —
and on Android it is swallowed rather than exiting the app.

Measured on make dev-headless SEED=default, at launch, with no
interaction:

history.state  ->  { yjNav: { view: 'home' }, yjIdx: 1 }
history.back()
history.state  ->  { yjNav: { view: 'home' }, yjIdx: 0 }   // same view

Why

frontend/index.ts navigates twice on startup, and both are
deliberate in isolation:

  1. the unconditional navigate → home at the foot of the file (H-8,
    "Land on Home"), which paints without waiting for the backend; and
  2. GetDefaultPage().then(...), which navigates to the configured
    launch page when the call returns.

The first replaces the launch entry, which is the rule that keeps one
back press exiting the app. The second is an ordinary navigation and
therefore pushes — even when it resolves to the same page, which is
the default. So the stack is [home, home] and the app is one entry
deep before anybody has done anything.

Consequences

  • On Android, MainActivity.onBackPressed asks webView.canGoBack(),
    which is now true at the root: the first press replays home over home
    and only the second exits. The "back does not quit from the root"
    rule is defeated by there being two launch navigations rather than
    one.
  • On desktop it was invisible until #6 gave the chrome a Back button
    with a disabled state: it renders enabled at launch and does
    nothing when pressed, which is how this was found.
  • Where the configured launch page is not Home, the phantom entry is
    Home — so back from a fresh launch lands somewhere the user never
    chose.

Direction

The configured-page navigation is part of launching, not a
navigation away from something, so it should replace the launch entry
rather than push. recordNavigation takes a _replace detail flag,
honoured only while the session is still at index 0 — if the user has
already navigated (the call is asynchronous and they can), it pushes as
any other navigation would, or a slow backend call would clobber an
entry they made.

Fixed as part of #6, since the Back button's disabled state cannot be
correct without it. Filed separately because it is a distinct defect
with its own reproduction, and it predates that work by five phases.

**Report** The app records **two** history entries before the user has touched anything, so the first back press at the root does nothing visible — and on Android it is swallowed rather than exiting the app. Measured on `make dev-headless SEED=default`, at launch, with no interaction: ``` history.state -> { yjNav: { view: 'home' }, yjIdx: 1 } history.back() history.state -> { yjNav: { view: 'home' }, yjIdx: 0 } // same view ``` **Why** `frontend/index.ts` navigates twice on startup, and both are deliberate in isolation: 1. the unconditional `navigate → home` at the foot of the file (H-8, "Land on Home"), which paints without waiting for the backend; and 2. `GetDefaultPage().then(...)`, which navigates to the *configured* launch page when the call returns. The first *replaces* the launch entry, which is the rule that keeps one back press exiting the app. The second is an ordinary navigation and therefore **pushes** — even when it resolves to the same page, which is the default. So the stack is `[home, home]` and the app is one entry deep before anybody has done anything. **Consequences** - On Android, `MainActivity.onBackPressed` asks `webView.canGoBack()`, which is now true at the root: the first press replays home over home and only the second exits. The "back does not quit from the root" rule is defeated by there being two launch navigations rather than one. - On desktop it was invisible until #6 gave the chrome a Back button with a disabled state: it renders *enabled* at launch and does nothing when pressed, which is how this was found. - Where the configured launch page is not Home, the phantom entry is Home — so back from a fresh launch lands somewhere the user never chose. **Direction** The configured-page navigation is part of *launching*, not a navigation away from something, so it should replace the launch entry rather than push. `recordNavigation` takes a `_replace` detail flag, honoured only while the session is still at index 0 — if the user has already navigated (the call is asynchronous and they can), it pushes as any other navigation would, or a slow backend call would clobber an entry they made. Fixed as part of #6, since the Back button's disabled state cannot be correct without it. Filed separately because it is a distinct defect with its own reproduction, and it predates that work by five phases.
logan closed this issue 2026-08-19 22:27:39 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: yonlu/yellowjacket#142