fix(android): say what a prompt answer saves on the verdict buttons #3

Merged
salix merged 5 commits from feat/android-prompt-ui into master 2026-10-19 10:56:23 +02:00
Owner

(Supersedes #2 — its merge was reset off master before landing; the branch is unchanged.)

What & why

The prompt hid what a tap saves: Allow and Deny wrote "this domain · forever" — or silently "this address" — with the facts in a muted summary line below the buttons, a new app's first answer pinned its route from that same hidden line, and a lamp plus per-second waiting ticker sat above the question. The verdict buttons now name their effect (Allow · this domain, forever), the scope/lifetime chips stay behind Options, the whole-app prompt asks where the app connects, above its answers, and per-destination prompts leave the route to the app's page, and the ticker row is gone. Defaults are unchanged — the fix is legibility, not behavior.

Per-destination Before After
default before after
options expanded before after
scope changed live after
First contact Before After
whole app before after

Verify

  • cd android && ./gradlew :app:assembleDebug -Ptelltale.abis=x86_64, install on an emulator, start protection through the debug receiver and connect something through the VPN: the sheet states what Allow/Deny will save; Options folds the chips; a new app's whole-app prompt asks where it connects, above its answers
  • In the sheet: Options → This address flips the buttons to Allow · this address, forever live
  • Screenshots are from the real debug app on a headless Android 16 emulator, driven through the debug broadcast receiver
*(Supersedes #2 — its merge was reset off master before landing; the branch is unchanged.)* ## What & why The prompt hid what a tap saves: Allow and Deny wrote "this domain · forever" — or silently "this address" — with the facts in a muted summary line below the buttons, a new app's first answer pinned its route from that same hidden line, and a lamp plus per-second waiting ticker sat above the question. The verdict buttons now name their effect (`Allow · this domain, forever`), the scope/lifetime chips stay behind *Options*, the whole-app prompt asks where the app connects, above its answers, and per-destination prompts leave the route to the app's page, and the ticker row is gone. Defaults are unchanged — the fix is legibility, not behavior. | Per-destination | Before | After | |---|---|---| | default | ![before](https://git.salix.host/attachments/729335f6-1ec9-444e-bf8e-982e5d21266c) | ![after](https://git.salix.host/attachments/de2bde45-af66-4cb6-984d-e8d2e56401a0) | | options expanded | ![before](https://git.salix.host/attachments/a9eb5ecc-3572-4547-81c4-6fedeefbe30f) | ![after](https://git.salix.host/attachments/8cff6fc6-faa7-4561-b42c-2daa4ef23a69) | | scope changed live | | ![after](https://git.salix.host/attachments/ce228b7b-52bb-44a0-b362-753fce6be637) | | First contact | Before | After | |---|---|---| | whole app | ![before](https://git.salix.host/attachments/37843b46-7425-4099-868d-85b47a447a2f) | ![after](https://git.salix.host/attachments/c0d940b4-11a9-41fe-a8f9-1a7b31a88744) | ## Verify - `cd android && ./gradlew :app:assembleDebug -Ptelltale.abis=x86_64`, install on an emulator, start protection through the debug receiver and connect something through the VPN: the sheet states what Allow/Deny will save; *Options* folds the chips; a new app's whole-app prompt asks where it connects, above its answers - In the sheet: *Options* → *This address* flips the buttons to `Allow · this address, forever` live - Screenshots are from the real debug app on a headless Android 16 emulator, driven through the debug broadcast receiver
fix(android): say what a prompt answer saves on the verdict buttons
All checks were successful
Check / rust (pull_request) Successful in 48s
Check / android (pull_request) Successful in 1m45s
03bc6b0a2a
The prompt carried four decisions (verdict, scope, lifetime, route) in two
bare buttons, with the actual effect in a muted summary line below them: a
tap wrote "this domain · forever" — or "this address", silently, when the
app's own DNS lookup named nothing — and a new app's first Allow also
pinned its route from that same hidden line. The sheet also opened with a
breathing lamp and a per-second waiting ticker above the question, and the
host appeared twice in the first two rows.

The verdicts now name their effect ("Allow · this domain, forever"),
computed live from the scope and lifetime chips; the summary line is gone
and the chips stay behind an Options toggle. The scope an answer takes
still varies (domain when known, else the address), but now says so on the
button. The route picker is visible while the answer still chooses an
app's route — a first contact — instead of folded behind Change. The
lamp/ticker row is gone: the queue position and "New app" are one small
metadata line under the question, next to the abandoned notice, and the
per-second recomposition goes with it. Defaults are unchanged; the defect
was legibility, not behavior.

The notification and Decisions cards already answer with the prompt's
default and are unchanged.
fix(android): give Decide per destination equal standing in the first prompt
All checks were successful
Check / rust (pull_request) Successful in 48s
Check / android (pull_request) Successful in 1m43s
1dd0eaa2a3
The escape from a new app's whole-app question — answering one destination
at a time — was a footnote text button at the bottom of the sheet, easy to
miss entirely. It is the ask-first path and gets a full-width tonal button
of its own, distinct in color from the Allow all / Block app verdicts so
the three read as three answers, not a default plus two options.
fix(android): outline Decide per destination like the whole-app answers
Some checks failed
Check / rust (pull_request) Has been cancelled
Check / android (pull_request) Has been cancelled
527f403b6b
The tonal container stood out more than an equal answer should; an
outlined button in the verdicts' shape but without their color reads as
the third answer, not a call to action.
fix(android): ask the route on the whole-app prompt, above its answers
Some checks failed
Check / rust (pull_request) Has been cancelled
Check / android (pull_request) Has been cancelled
9db41e4612
The route is a whole-app choice, but it was picked at the bottom of the
sheet — folded under Change for the first-contact prompt and tucked below
Options for per-destination ones, where a destination answer could also
silently set it. The whole-app prompt now asks "Where the app connects"
in a tonal card above Allow all / Block app / Decide per destination, and
per-destination prompts carry no route picker at all: their answers save
rules for the destination, and the route stays on the app's page.
fix(android): outline the route question like the whole-app answers
All checks were successful
Check / rust (pull_request) Successful in 49s
Check / android (pull_request) Successful in 1m41s
f65c5bf68c
The tonal card made the route shout louder than the verdicts it precedes.
The picker now renders in the same outlined style as Allow all, Block app
and Decide per destination — one visual family, the route asked above them
with its consequence spelled out beneath it.
salix merged commit 042c8c683a into master 2026-10-19 10:56:23 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
salix/telltale!3
No description provided.