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-pixel
2026-05-16 09:24:35 -07:00
parent b187cf1f85
commit 3a9ece8d1e
@@ -325,20 +325,20 @@ private fun ModalData.NewChatSheetLayout(
item {
if (filteredContactChats.isNotEmpty() && searchText.value.text.isEmpty()) {
SectionDividerSpaced(maxTopPadding = false, maxBottomPadding = false)
SectionView(stringResource(MR.strings.contact_list_header_title).uppercase(), headerBottomPadding = DEFAULT_PADDING_HALF) {}
Spacer(Modifier.height(DEFAULT_PADDING_HALF))
}
}
item {
NoFilteredContactsItem()
}
itemsIndexed(filteredContactChats) { index, chat ->
val nextChatSelected = remember(chat.id, filteredContactChats) {
derivedStateOf {
chatModel.chatId.value != null && filteredContactChats.getOrNull(index + 1)?.id == chatModel.chatId.value
SectionView(stringResource(MR.strings.contact_list_header_title).uppercase(), headerBottomPadding = DEFAULT_PADDING_HALF) {
filteredContactChats.forEachIndexed { index, chat ->
val nextChatSelected = remember(chat.id, filteredContactChats) {
derivedStateOf {
chatModel.chatId.value != null && filteredContactChats.getOrNull(index + 1)?.id == chatModel.chatId.value
}
}
ContactListNavLinkView(chat, nextChatSelected, showDeletedChatIcon = true)
}
}
Spacer(Modifier.height(DEFAULT_PADDING_HALF))
} else {
NoFilteredContactsItem()
}
ContactListNavLinkView(chat, nextChatSelected, showDeletedChatIcon = true)
}
if (appPlatform.isAndroid) {
item {
@@ -410,19 +410,19 @@ private fun ModalData.NewChatSheetLayout(
item {
if (filteredContactChats.isNotEmpty() && searchText.value.text.isEmpty()) {
SectionDividerSpaced()
SectionView(stringResource(MR.strings.contact_list_header_title).uppercase(), headerBottomPadding = DEFAULT_PADDING_HALF) {}
}
}
item {
NoFilteredContactsItem()
}
itemsIndexed(filteredContactChats) { index, chat ->
val nextChatSelected = remember(chat.id, filteredContactChats) {
derivedStateOf {
chatModel.chatId.value != null && filteredContactChats.getOrNull(index + 1)?.id == chatModel.chatId.value
SectionView(stringResource(MR.strings.contact_list_header_title).uppercase(), headerBottomPadding = DEFAULT_PADDING_HALF) {
filteredContactChats.forEachIndexed { index, chat ->
val nextChatSelected = remember(chat.id, filteredContactChats) {
derivedStateOf {
chatModel.chatId.value != null && filteredContactChats.getOrNull(index + 1)?.id == chatModel.chatId.value
}
}
ContactListNavLinkView(chat, nextChatSelected, showDeletedChatIcon = true)
}
}
} else {
NoFilteredContactsItem()
}
ContactListNavLinkView(chat, nextChatSelected, showDeletedChatIcon = true)
}
if (appPlatform.isAndroid) {
item {