From 083b3c22d0fb89e0f529416a554364433d832f06 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Fri, 22 Apr 2022 12:56:06 -0500 Subject: [PATCH] ScrollableList: render emptyMessage inside the PullToRefresh --- app/soapbox/components/scrollable_list.tsx | 85 +++++++++++++--------- 1 file changed, 51 insertions(+), 34 deletions(-) diff --git a/app/soapbox/components/scrollable_list.tsx b/app/soapbox/components/scrollable_list.tsx index b1626d966e..3264c53693 100644 --- a/app/soapbox/components/scrollable_list.tsx +++ b/app/soapbox/components/scrollable_list.tsx @@ -68,11 +68,26 @@ const ScrollableList: React.FC = ({ // const settings = useSettings(); // const autoload = settings.get('autoloadMore'); + /** Normalized children */ + const elements = Array.from(children || []); + const showPlaceholder = showLoading && Placeholder && placeholderCount > 0; - const data = showPlaceholder ? Array(placeholderCount).fill('') : Array.from(children || []); + + // NOTE: We are doing some trickery to load a feed of placeholders + // Virtuoso's `EmptyPlaceholder` unfortunately doesn't work for our use-case + const data = showPlaceholder ? Array(placeholderCount).fill('') : elements; + const isEmpty = data.length === 0; // Yes, if it has placeholders it isn't "empty" + + // Add a placeholder at the bottom for loading + // (Don't use Virtuoso's `Footer` component because it doesn't preserve its height) + if (hasMore && Placeholder) { + data.push(); + } else if (hasMore) { + data.push(); + } /* Render an empty state instead of the scrollable list */ - const renderEmpty = () => { + const renderEmpty = (): JSX.Element => { return (
{alwaysPrepend && prepend} @@ -88,8 +103,8 @@ const ScrollableList: React.FC = ({ ); }; - /** Render the actual item */ - const renderItem = (_i: number, element: JSX.Element) => { + /** Render a single item */ + const renderItem = (_i: number, element: JSX.Element): JSX.Element => { if (showPlaceholder) { return ; } else { @@ -97,40 +112,42 @@ const ScrollableList: React.FC = ({ } }; - // Don't use Virtuoso's EmptyPlaceholder component so it preserves height - if (data.length === 0) { - return renderEmpty(); - } + /** Render the actual Virtuoso list */ + const renderFeed = (): JSX.Element => ( + isScrolling && onScroll && onScroll()} + itemContent={renderItem} + context={{ + listClassName: className, + itemClassName, + }} + components={{ + Header: () => prepend, + ScrollSeekPlaceholder: Placeholder as any, + EmptyPlaceholder: () => renderEmpty(), + List, + Item, + }} + /> + ); - // Don't use Virtuoso's Footer component so it preserves spacing - if (hasMore && Placeholder) { - data.push(); - } else if (hasMore) { - data.push(); - } + /** Conditionally render inner elements */ + const renderBody = (): JSX.Element => { + if (isEmpty) { + return renderEmpty(); + } else { + return renderFeed(); + } + }; return ( - isScrolling && onScroll && onScroll()} - itemContent={renderItem} - context={{ - listClassName: className, - itemClassName, - }} - components={{ - Header: () => prepend, - ScrollSeekPlaceholder: Placeholder as any, - EmptyPlaceholder: () => renderEmpty(), - List, - Item, - }} - /> + {renderBody()} ); };