refactor: let dialog lists compose their own pagination tail
1234556789101112131415151617181920212223242223242510 unmodified lines363738394344404142436 unmodified lines50515253596061626364656654555657585 unmodified linesimport { type ReactNode, useRef } from 'react';
import { clsx } from 'clsx';
import { CenteredSpinner } from '#/components/CenteredSpinner';import * as styles from '#/components/Dialog/Popup.css';import { List as BaseList, type ListRenderItem } from '#/components/List/List';
export type { ListRenderItem, ListRenderItemInfo } from '#/components/List/List';
export type ListProps<ItemT> = { data: readonly ItemT[]; keyExtractor: (item: ItemT, index: number) => string; /** shown in place of the rows when `data` is empty, below any header. */ ListEmptyComponent?: ReactNode; /** shown after non-empty data. */ /** shown after non-empty data; the place for a pagination spinner or retry. */ ListFooterComponent?: ReactNode; /** shown before items, including when `data` is empty. */ ListHeaderComponent?: ReactNode; className?: string; /** enables virtualization with this estimated row height. */ estimateHeight?: number; isFetchingNextPage?: boolean; /** required to show the pagination spinner. */ loadingLabel?: string; onEndReached?: () => void; renderItem: ListRenderItem<ItemT>;};
10 unmodified lines ListFooterComponent, ListHeaderComponent, className, estimateHeight, isFetchingNextPage, loadingLabel, onEndReached, renderItem,}: ListProps<ItemT>) { const scrollRef = useRef<HTMLDivElement>(null);6 unmodified lines data={data} estimateHeight={estimateHeight} keyExtractor={keyExtractor} ListEmptyComponent={ListEmptyComponent} ListFooterComponent={ !isEmpty && ( <> {ListFooterComponent} {isFetchingNextPage && loadingLabel && <CenteredSpinner label={loadingLabel} size="xl" />} </> ) } ListFooterComponent={!isEmpty && ListFooterComponent} ListHeaderComponent={ListHeaderComponent} onEndReached={onEndReached} onEndReachedThreshold={2} renderItem={renderItem}5 unmodified lines127 unmodified linesExpand all128129130131132133132133134135136137138155 unmodified linesExpand all127 unmodified linesExpand all } } }} onEndReached={onEndReached} isFetchingNextPage={isFetchingNextPage} loadingLabel={m['common.status.loading']()} ListFooterComponent={ isFetchingNextPage ? <CenteredSpinner label={m['common.status.loading']()} size="xl" /> : null } ListEmptyComponent={ isLoading ? ( <div className={css.loading}> <CenteredSpinner label={m['common.status.loading']()} size="xl" />155 unmodified linesExpand all137 unmodified linesExpand all138139140141142143142143144145146147148165 unmodified linesExpand all137 unmodified linesExpand all view={item} /> )} onEndReached={onEndReached} isFetchingNextPage={isFetchingNextPage} loadingLabel={m['common.status.loading']()} ListFooterComponent={ isFetchingNextPage ? <CenteredSpinner label={m['common.status.loading']()} size="xl" /> : null } ListHeaderComponent={ hasMutualGroupChats ? ( <Text className={css.groupsLabel} color="textContrastHigh" size="sm" weight="semiBold"> {m['components.moderation.chat.mutualGroups']()}165 unmodified linesExpand all78 unmodified lines798081828384838485867 unmodified lines9495969798100101102103104105106991001011021031041051061071081091101111 unmodified line78 unmodified lines <DraftItem draft={draft} onSelect={handleSelectDraft} onDelete={handleDeleteDraft} /> </div> )} onEndReached={onEndReached} isFetchingNextPage={isFetchingNextPage} loadingLabel={m['view.composer.drafts.loading']()} ListEmptyComponent={ isLoading ? ( <div className={styles.loading}> <CenteredSpinner label={m['view.composer.drafts.loading']()} size="xl" />7 unmodified lines </div> ) } ListFooterComponent={ <> drafts.length > 5 ? ( <div className={styles.footerNote}> <Text align="center" color="textContrastMedium"> {m['view.composer.text.placeholder']()} </Text> </div> ) : null {drafts.length > 5 && ( <div className={styles.footerNote}> <Text align="center" color="textContrastMedium"> {m['view.composer.text.placeholder']()} </Text> </div> )} {isFetchingNextPage && <CenteredSpinner label={m['view.composer.drafts.loading']()} size="xl" />} </> } /> </> );1 unmodified line