From 209c27f5123079ba5187ada6bf1762a4d9f53a70 Mon Sep 17 00:00:00 2001 From: Narasimha-sc <166327228+Narasimha-sc@users.noreply.github.com> Date: Sat, 5 Sep 2026 15:29:51 +0000 Subject: [PATCH] android, desktop: clear the bottom bar under the profile picker list ModalView renders its app bar as an overlay, so with one-hand UI - the default - it obscures the last AppBarHeight + navigation bar of the list while reserving no space. The list's only clearance is its trailing DEFAULT_BOTTOM_PADDING of 48.dp against a 56.dp bar plus insets, so roughly one row is unreachable once the list is long enough to scroll. The casualty is the last profile row, which is why it went unnoticed. --- .../common/views/newchat/NewChatView.kt | 4 +- plans/2026-09-05-profile-picker-bottom-bar.md | 69 +++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 plans/2026-09-05-profile-picker-bottom-bar.md diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatView.kt index f3006d221b..657044040b 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatView.kt @@ -454,7 +454,9 @@ fun ActiveProfilePicker( } } item { - Spacer(Modifier.imePadding().padding(bottom = DEFAULT_BOTTOM_PADDING)) + val oneHandUI = remember { appPrefs.oneHandUI.state } + val bottomBarClearance = if (oneHandUI.value) WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() + AppBarHeight * fontSizeSqrtMultiplier else 0.dp + Spacer(Modifier.imePadding().padding(bottom = DEFAULT_BOTTOM_PADDING + bottomBarClearance)) } } } diff --git a/plans/2026-09-05-profile-picker-bottom-bar.md b/plans/2026-09-05-profile-picker-bottom-bar.md new file mode 100644 index 0000000000..c9d8355db1 --- /dev/null +++ b/plans/2026-09-05-profile-picker-bottom-bar.md @@ -0,0 +1,69 @@ +# The profile picker's last row is hidden under the bottom app bar + +`ActiveProfilePicker` in `newchat/NewChatView.kt` — the "Select chat profile" screen, +reached from an invitation link and from the share sheet. + +## The defect + +`ModalView` renders its app bar as an **overlay**, not as a layout sibling: + +```kotlin +Box(modifier) { content() } // list, full height +Box(Modifier.align(if (oneHandUI.value) BottomStart else TopStart)) { DefaultAppBar(...) } +``` + +With one-hand UI the bar sits at the **bottom**, so it obscures the last +`AppBarHeight + navigation bar insets` of the list while reserving no space for itself. +Against that, the list's only bottom clearance is its trailing spacer: + +| | | +|---|---| +| obscured by the bar | `AppBarHeight` 56.dp + navigation bar | +| clearance in the list | `DEFAULT_BOTTOM_PADDING` 48.dp | +| `LazyColumnWithScrollBar` `contentPadding` | `0.dp` (default, not overridden) | + +The shortfall is `8.dp` plus the navigation bar — commonly 32–56.dp, and the rows are +`DEFAULT_MIN_SECTION_ITEM_HEIGHT + 8 = 58.dp`, so roughly one whole row is unreachable. +It only shows once the list is long enough to scroll; with few profiles nothing is hidden, +which is why it survived. + +`oneHandUI` defaults to **true**, so this is the default layout on Android rather than an +opt-in configuration. + +## Why it went unnoticed + +The casualty on master is the **last profile row** — the least-used profile at the end of a +list. A row you were not looking for is not obviously missing, and the picker is otherwise +fully functional, so nothing draws attention to it. + +## Why it matters now + +#7329 adds an **"Add profile"** row at the end of this list. That moves a deliberately +sought affordance into the broken position: on a default Android install with enough +profiles to scroll, the button the feature exists for cannot be reached at all. The feature +is unusable on Android without this fix, so #7329 depends on it. + +Splitting it out anyway, because the defect is entirely pre-existing and worth fixing on +its own terms: it is not caused by, and does not require, the new row. + +## The fix + +Add the bar's height to the trailing spacer when one-hand UI is on, matching the clearance +idiom already used elsewhere (`AppBarHeight * fontSizeSqrtMultiplier`, e.g. +`UserProfileView`, `TerminalView`): + +```kotlin +val bottomBarClearance = if (oneHandUI.value) + WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() + AppBarHeight * fontSizeSqrtMultiplier + else 0.dp +``` + +`oneHandUI` is read inside the spacer's own `item` rather than hoisted, so no existing code +moves. No change when one-hand UI is off. + +## Testing + +Open "Select chat profile" from an invitation link on Android with one-hand UI on and +enough profiles that the list scrolls; the last row must be fully visible above the search +bar. Repeat with one-hand UI off — the layout must be unchanged. Repeat from the share +sheet, which uses the same picker with `contactConnection = null`.