fix(toast): one host, painted on dark, clearing only the bar that is drawn - #185
Draft
cestercian wants to merge 2 commits into
Draft
fix(toast): one host, painted on dark, clearing only the bar that is drawn#185cestercian wants to merge 2 commits into
dark, clearing only the bar that is drawn#185cestercian wants to merge 2 commits into
Conversation
…s drawn Three findings from the Sep-2026 design QA, all in issue #179, all about the same capsule. F-SH-03 (P1) — the root host cleared the tab bar whenever the gate was `RootGate.Tabs`. That is "inside the tab shell", not "the bar is on screen": every pushed destination — chat, a booking, the press kit — lives under that gate with `showBottomBar` false, so their toasts floated 88dp above nothing. Only the scaffolds know the answer, so they now report `showBottomBar` up to the host, which keeps the gate check as the outer guard. The host's padding also moves from `vertical` to `bottom`: the top half padded an invisible node up to two tab bars taller than the capsule, and that node is a live region. F-PK-01 (P1) — the press kit mounted a SECOND `ToastHost` inside its own Box. It took the default bottom gap, so every "Pricing saved." on screens 23/87/76 drew underneath the tab bar. `statusNote` now goes through the same `ToastController` the root host observes and the local host is gone; there is one `ToastHost` call site in the app again. The state field stays where it is, so nothing in `EpkViewModel` or its callers moves — pushing the controller into that ViewModel is the tidier end state and a separate change. F-CC-06 (P3) — the capsule painted `colors.ink`, the TEXT colour, and cast a 12dp shadow on a design that has no shadows anywhere else. Now `colors.dark`, the palette's actual dark surface, flat. Verified: kotlinc 2.1.0 parses all five files clean (no syntax or structural diagnostics; every remaining message is an unresolved reference from compiling without the Android classpath). NOT compiled and NOT device-walked — the Gradle build needs `dl.google.com` for AGP, androidx and the SDK, and this environment's network policy denies that host, which also rules out the emulator. The green-tree gate still has to run before this merges. Addresses #179. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SQHtArE39dDg2TUDzwfBAW
|
Review catch on the first commit. `ToastController` is a `@Singleton`, so a toast that is up when the activity is recreated — a rotation, a theme switch, "don't keep activities" — comes straight back with the composition. But `tabBarVisible` was a plain `remember`, so it came back false, and the first restored frame drew the capsule OVER the tab bar before the scaffold's `LaunchedEffect` reported true and it jumped. `rememberSaveable` restores whatever was true at recreation, so it is right in both directions: true on a tab root, false on a pushed screen. `remember` has no other user in the file, so its import goes with it. Verified: kotlinc 2.1.0 parses the file clean — the only non-unresolved- reference diagnostic is the pre-existing "'when' expression must be exhaustive" on `themeRole`, which is `RootGate`'s sealed hierarchy being invisible without the Android classpath (it appears identically on the unmodified baseline). Still NOT compiled and NOT device-walked; see #185. Addresses #179. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SQHtArE39dDg2TUDzwfBAW
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses #179 — the toast theme from the Sep-2026 design QA (epic #161). All three of that issue's findings, all about the same capsule.
This has not been compiled and has not been on a device. The Gradle build needs
dl.google.comfor AGP, every androidx/Compose artifact and the SDK itself; this environment's network policy denies that host (CONNECT tunnel failed, response 403), andmaven.google.comis only a 301 redirector to it. Maven Central,services.gradle.organd GitHub are reachable; the Aliyun, Tencent and TUNA mirrors are not, and there is no/dev/kvm, so the emulator is out too. The repo has no.github/workflows/, so no check here will build it either.What I could verify: I pulled the standalone kotlinc 2.1.0 from GitHub releases and parsed all five changed files. No syntax and no structural diagnostics. Every message is either an unresolved reference from compiling without the Android classpath (
androidx,AppTheme,Modifier,hiltViewModel, …) or a knock-on of one — the single non-unresolved-reference diagnostic is'when' expression must be exhaustiveonthemeRole, which isRootGate's sealed hierarchy being invisible, and it appears identically on the unmodified baseline. That proves the files parse; it does not prove they type-check.Before this leaves draft:
No unit test touches
statusNote,showBottomBarorlightTabBarHeight, andToastControllerTestcovers the controller, which is unchanged — so I do not expect test movement, but that is an expectation, not a result.What changed
F-SH-03 (P1) — every toast from a pushed screen floated 88 dp above nothing.
ArtistantNavHostcleared the tab bar whenever the gate wasRootGate.Tabs. That is "inside the tab shell", which is a different fact from "the bar is on screen": every pushed destination — chat, a booking, the press kit — lives under that gate withshowBottomBarfalse. The host is a sibling of the scaffold, not a descendant, so aCompositionLocalcan't reach it; the scaffolds now reportshowBottomBarup through anonTabBarVisibilityChangecallback and the host keeps the gate check as the outer guard.The host's padding also moves from
vertical = bottomPaddingtobottom = bottomPadding. Nothing visible moved, butverticalpadded the top of the host's bounds by the same amount — on a tab shell that made the node up to two tab bars taller than the capsule, and that node is aLiveRegionMode.Politesemantics node.F-PK-01 (P1) — the press kit mounted a second toast host, under the tab bar.
EpkScreenhad its ownToastHostinside its Box, taking the default bottom gap, so every "Pricing saved." / "Photo added." / "Cover saved." on screens 23, 87 and 76 drew underneath the bar.statusNotenow goes through the same@Singleton ToastControllerthe root host observes, and the local host is deleted — there is oneToastHostcall site in the app again.I bridged it at the screen rather than injecting
ToastControllerintoEpkViewModel, because that would touch 18_state.update {}sites for no behavioural gain here. The ViewModel-side move is the tidier end state and belongs in its own change; noted below.F-CC-06 (P3) — the wrong black, and a shadow on a flat design.
The capsule painted
colors.ink(#14150F) — the text colour, used as a surface — and cast a 12 dp shadow. Nowcolors.dark(#16171A), the palette's actual dark surface, flat.docs/REDESIGN_2026-09.md§2 has no shadow anywhere and a near-black capsule on the off-white page separates without one.Files
designsystem/component/Toast.ktdarknotink, no shadow,bottomnotverticalnavigation/ArtistantNavHost.kttabBarVisible(rememberSaveable); padding driven by gate and visibilitynavigation/ClientTabsScaffold.ktshowBottomBarupnavigation/ArtistTabsScaffold.ktshowBottomBarupfeature/epk/EpkScreen.ktstatusNoteto the root host; local host deletedReview rounds
@Singleton, so a live toast survives an activity recreation, and a plainremembercame backfalseand drew that first restored frame over the bar. Fixed in 942aee2 withrememberSaveable, which restores whatever was true at recreation and so is right on a tab root and on a pushed screen alike. Thread resolved.Still open on #179 after this
dl.google.comis allowed.ToastIcon.Flag). Worth adding a rotation-with-a-toast-up pass for the round-1 fix. RELEASE.md §10, and rememberam start -S.ToastControllerintoEpkViewModeland dropstatusNotefromEpkState, so the press kit raises toasts the wayArtistProfileViewModelalready does.🤖 Generated with Claude Code
https://claude.ai/code/session_01SQHtArE39dDg2TUDzwfBAW