Say it over the app when the app is what somebody is looking at

The notification stream now has three places to land instead of two, decided
in one function. Nothing at all for the session on screen, as before. A
banner over the app while the app is up. Android's drawer otherwise. Never
two of them for one moment: a drawer filling up behind an app that showed
you each one is a drawer nobody reads.

The banners queue, one per session replacing that session's own -- the rule
the drawer already followed, and for the same reason. Each can be tapped,
which opens the session by the same path a tapped notification takes;
pushed off either side; or left alone, in which case the bar across its foot
retires it. The bar and the retiring are one value rather than a bar beside
a timer, so a banner cannot outlive the countdown drawn under it. They clear
when the app goes away, since a claim that a session wants somebody *now*
does not survive an absence -- and the drawer has the job back by then.

Which of the three applies needs no flag anybody keeps level. The session on
screen is registered by the one composable that draws one, and "the app is
up" is the queue being collected, which happens exactly while it is.

Also: tapping a model or permission button while its own menu is open now
closes it. A non-focusable popup does not swallow the press that dismisses
it, so the same finger was reopening what it had just closed -- measured at
3ms between the two, which is what the guard is sized against.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
irisandClaude Opus 5 committed 2026-08-30 02:40:32 -04:00
1 parent e0eaa4b3f8
commit be47beb0ff
6 files changed
+296 -11

No files matched your search

@@ -212,4 +212,11 @@ fun AppRoot(settingsVersion: Int, openRequest: SessionOpenRequest?) {
onBack = goToMain,
)
}
// Last, so it draws over the screen above rather than under it: these are stacked in the Box
// the activity puts around this, and that Box paints in the order it was given. A session
// wanting attention is not a fact about the page somebody happens to be on, so it is not the
// page's job to leave room for it. Tapping one is the same act as tapping a notification, so
// it goes through the same `open`, failure dialog included.
SessionAlerts(onOpen = { request -> scope.launch { open(request) } })
}