NewChatSheet: render filtered contact list inside SectionView card

The "Contacts" header was a SectionView with empty content lambda, and
the actual contact rows were rendered as separate LazyColumn items
OUTSIDE the SectionView — so they sat on canvas without card chrome.

Move filteredContactChats.forEachIndexed { ContactListNavLinkView }
INSIDE the SectionView lambda in both OneHandLazyColumn and
NonOneHandLazyColumn so the contacts read as a single card matching
the iOS-style facelift.

Same trade-off as GroupChatInfoView members fix (fa29bb7a): lazy
rendering of contact rows replaced with eager composition inside a
Column. For typical contact lists (<100) imperceptible; very long
lists may compose slower on open.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
another-simple-pixelandClaude Opus 4.7 committed 2026-05-16 09:24:35 -07:00
1 parent b187cf1f85
commit 3a9ece8d1e
1 file changed
+15 -15
@@ -325,14 +325,8 @@ private fun ModalData.NewChatSheetLayout(
item { item {
if (filteredContactChats.isNotEmpty() && searchText.value.text.isEmpty()) { if (filteredContactChats.isNotEmpty() && searchText.value.text.isEmpty()) {
SectionDividerSpaced(maxTopPadding = false, maxBottomPadding = false) SectionDividerSpaced(maxTopPadding = false, maxBottomPadding = false)
SectionView(stringResource(MR.strings.contact_list_header_title).uppercase(), headerBottomPadding = DEFAULT_PADDING_HALF) {} SectionView(stringResource(MR.strings.contact_list_header_title).uppercase(), headerBottomPadding = DEFAULT_PADDING_HALF) {
Spacer(Modifier.height(DEFAULT_PADDING_HALF)) filteredContactChats.forEachIndexed { index, chat ->
}
}
item {
NoFilteredContactsItem()
}
itemsIndexed(filteredContactChats) { index, chat ->
val nextChatSelected = remember(chat.id, filteredContactChats) { val nextChatSelected = remember(chat.id, filteredContactChats) {
derivedStateOf { derivedStateOf {
chatModel.chatId.value != null && filteredContactChats.getOrNull(index + 1)?.id == chatModel.chatId.value chatModel.chatId.value != null && filteredContactChats.getOrNull(index + 1)?.id == chatModel.chatId.value
@@ -340,6 +334,12 @@ private fun ModalData.NewChatSheetLayout(
} }
ContactListNavLinkView(chat, nextChatSelected, showDeletedChatIcon = true) ContactListNavLinkView(chat, nextChatSelected, showDeletedChatIcon = true)
} }
}
Spacer(Modifier.height(DEFAULT_PADDING_HALF))
} else {
NoFilteredContactsItem()
}
}
if (appPlatform.isAndroid) { if (appPlatform.isAndroid) {
item { item {
Spacer(Modifier.windowInsetsTopHeight(WindowInsets.statusBars)) Spacer(Modifier.windowInsetsTopHeight(WindowInsets.statusBars))
@@ -410,13 +410,8 @@ private fun ModalData.NewChatSheetLayout(
item { item {
if (filteredContactChats.isNotEmpty() && searchText.value.text.isEmpty()) { if (filteredContactChats.isNotEmpty() && searchText.value.text.isEmpty()) {
SectionDividerSpaced() SectionDividerSpaced()
SectionView(stringResource(MR.strings.contact_list_header_title).uppercase(), headerBottomPadding = DEFAULT_PADDING_HALF) {} SectionView(stringResource(MR.strings.contact_list_header_title).uppercase(), headerBottomPadding = DEFAULT_PADDING_HALF) {
} filteredContactChats.forEachIndexed { index, chat ->
}
item {
NoFilteredContactsItem()
}
itemsIndexed(filteredContactChats) { index, chat ->
val nextChatSelected = remember(chat.id, filteredContactChats) { val nextChatSelected = remember(chat.id, filteredContactChats) {
derivedStateOf { derivedStateOf {
chatModel.chatId.value != null && filteredContactChats.getOrNull(index + 1)?.id == chatModel.chatId.value chatModel.chatId.value != null && filteredContactChats.getOrNull(index + 1)?.id == chatModel.chatId.value
@@ -424,6 +419,11 @@ private fun ModalData.NewChatSheetLayout(
} }
ContactListNavLinkView(chat, nextChatSelected, showDeletedChatIcon = true) ContactListNavLinkView(chat, nextChatSelected, showDeletedChatIcon = true)
} }
}
} else {
NoFilteredContactsItem()
}
}
if (appPlatform.isAndroid) { if (appPlatform.isAndroid) {
item { item {
Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars)) Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))