/
githubmirror
/
client
Обзор
Документация
Войти
/
githubmirror
/
client
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
shared/common-adapters/section-list.tsx
182 строки
6 KB
chrisnojima
build(mobile): harden gobuild.sh and go bind pipeline 2 (#29364)
08 июл 2026, 15:25
Не верифицирован
08 июл 2026, 15:25
19b55b3
Код
Авторство
О чём код?
import type * as React from 'react' import { SectionList as NativeSectionList, type SectionListProps, type ViewToken, type SectionListData, } from 'react-native' import noop from 'lodash/noop' export type SectionType<Item> = { title?: string | React.ReactElement data: ReadonlyArray<Item> keyExtractor?: (item: Item, index: number) => string renderItem?: ({ index, item, section, }: { index: number item: Item section: SectionType<Item> }) => React.ReactElement | null renderSectionHeader?: (info: {section: SectionType<Item>}) => React.ReactElement | null } type Props<ItemT, SectionT> = SectionListProps<ItemT, SectionT> & { getItemHeight?: (item: ItemT | undefined, sectionIndex: number, indexWithinSection: number) => number getSectionHeaderHeight?: (sectionIndex: number) => number onSectionChange?: (section: SectionT) => void } function defaultRenderSectionHeader<ItemT, SectionT>({section}: {section: SectionListData<ItemT, SectionT>}) { const s = section as unknown as SectionType<ItemT> // callers relying on this default use SectionType<ItemT> as their section shape return s.renderSectionHeader?.({section: s}) ?? null } function SectionListImpl<ItemT, SectionT>( props: Props<ItemT, SectionT> & {ref?: React.Ref<NativeSectionList<ItemT, SectionT>>} ) { const {ref} = props const {getItemHeight, getSectionHeaderHeight, onSectionChange, renderSectionHeader, ...rest} = props const getItemLayout = getItemHeight ? getGetItemLayout<ItemT, SectionT>({getItemHeight, getSectionHeaderHeight}) : undefined const onViewableItemsChanged = onSectionChange ? (e: {viewableItems: ViewToken<ItemT>[]}) => { const section = e.viewableItems[0]?.section as SectionT | undefined if (section) { onSectionChange(section) } } : undefined const resolvedRenderSectionHeader = renderSectionHeader ?? defaultRenderSectionHeader<ItemT, SectionT> return ( <NativeSectionList overScrollMode="never" contentInsetAdjustmentBehavior="automatic" getItemLayout={getItemLayout} onViewableItemsChanged={onViewableItemsChanged} onScrollToIndexFailed={noop} keyboardDismissMode="on-drag" ref={ref} {...rest} renderSectionHeader={resolvedRenderSectionHeader} /> ) } export type SectionListRef<ItemT, SectionT> = NativeSectionList<ItemT, SectionT> const SectionList = SectionListImpl as <ItemT, SectionT>( props: Props<ItemT, SectionT> & {ref?: React.Ref<NativeSectionList<ItemT, SectionT>>} ) => React.ReactElement export default SectionList // From https://github.com/jsoendermann/rn-section-list-get-item-layout // Author Jan Soendermann // Apache License, Version 2.0 interface SectionHeader { type: 'SECTION_HEADER' } interface Row { type: 'ROW' index: number } interface SectionFooter { type: 'SECTION_FOOTER' } type ListElement = SectionHeader | Row | SectionFooter interface Parameters<ItemT> { getItemHeight: (rowData: ItemT | undefined, sectionIndex: number, rowIndex: number) => number getSeparatorHeight?: (sectionIndex: number, rowIndex: number) => number getSectionHeaderHeight?: (sectionIndex: number) => number getSectionFooterHeight?: (sectionIndex: number) => number listHeaderHeight?: number | (() => number) } function getGetItemLayout<ItemT, SectionT>({ getItemHeight, getSeparatorHeight = () => 0, getSectionHeaderHeight = () => 0, getSectionFooterHeight = () => 0, listHeaderHeight = 0, }: Parameters<ItemT>) { return (data: SectionListData<ItemT, SectionT>[] | null, index: number) => { let i = 0 let sectionIndex = 0 let elementPointer: ListElement = {type: 'SECTION_HEADER'} let offset = typeof listHeaderHeight === 'function' ? listHeaderHeight() : listHeaderHeight while (i < index) { switch (elementPointer.type) { case 'SECTION_HEADER': { const sectionData = data?.[sectionIndex]?.data offset += getSectionHeaderHeight(sectionIndex) // If this section is empty, we go right to the footer... if (sectionData?.length === 0) { elementPointer = {type: 'SECTION_FOOTER'} // ...otherwise we make elementPointer point at the first row in this section } else { elementPointer = {index: 0, type: 'ROW'} } break } case 'ROW': { const sectionData = data?.[sectionIndex]?.data const rowIndex = elementPointer.index offset += getItemHeight(sectionData?.[rowIndex], sectionIndex, rowIndex) elementPointer.index += 1 if (rowIndex === (sectionData?.length ?? 0) - 1) { elementPointer = {type: 'SECTION_FOOTER'} } else { offset += getSeparatorHeight(sectionIndex, rowIndex) } break } case 'SECTION_FOOTER': { offset += getSectionFooterHeight(sectionIndex) sectionIndex += 1 elementPointer = {type: 'SECTION_HEADER'} break } } i += 1 } let length: number switch (elementPointer.type) { case 'SECTION_HEADER': length = getSectionHeaderHeight(sectionIndex) break case 'ROW': { const rowIndex = elementPointer.index length = getItemHeight(data?.[sectionIndex]?.data[rowIndex], sectionIndex, rowIndex) break } case 'SECTION_FOOTER': length = getSectionFooterHeight(sectionIndex) break default: throw new Error('Unknown elementPointer.type') } return {index, length, offset} } }