From 6bb4dc20a40653d291f59393db38f2f139040ed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Fri, 4 Oct 2024 00:00:43 +0200 Subject: [PATCH] Revert "pl-fe: Improve virtualization behavior" This reverts commit d2d18401199a27225eeceea29b828fdec1e340e3. --- .../pl-fe/src/components/scrollable-list.tsx | 115 +++++++++--------- packages/pl-fe/src/components/status-list.tsx | 6 +- .../features/chats/components/chat-list.tsx | 1 + .../chats/components/chat-message-list.tsx | 1 + .../chats/components/chat-search/results.tsx | 1 + .../steps/suggested-accounts-step.tsx | 1 + .../src/features/status/components/thread.tsx | 21 ++-- .../modals/familiar-followers-modal.tsx | 1 + .../ui/components/modals/favourites-modal.tsx | 1 + .../ui/components/modals/media-modal.tsx | 2 +- .../ui/components/modals/mentions-modal.tsx | 1 + .../ui/components/modals/reactions-modal.tsx | 1 + .../ui/components/modals/reblogs-modal.tsx | 1 + 13 files changed, 82 insertions(+), 71 deletions(-) diff --git a/packages/pl-fe/src/components/scrollable-list.tsx b/packages/pl-fe/src/components/scrollable-list.tsx index 4cc09aab7..edaf7e1af 100644 --- a/packages/pl-fe/src/components/scrollable-list.tsx +++ b/packages/pl-fe/src/components/scrollable-list.tsx @@ -1,5 +1,5 @@ /* eslint-disable react-hooks/rules-of-hooks */ -import { useVirtualizer, type Virtualizer } from '@tanstack/react-virtual'; +import { useVirtualizer, useWindowVirtualizer, type Virtualizer } from '@tanstack/react-virtual'; import clsx from 'clsx'; import React, { useEffect, useMemo } from 'react'; @@ -8,7 +8,16 @@ import { useSettings } from 'pl-fe/hooks'; import LoadMore from './load-more'; import { Card, Spinner } from './ui'; -interface IScrollableListBase { +type IScrollableListWindowScroll = { + /** Whether to use the window to scroll the content instead of the container. */ + useWindowScroll?: true; +} | { + /** Whether to use the window to scroll the content instead of the container. */ + useWindowScroll: false; + parentRef: React.RefObject; +}; + +interface IScrollableList { /** Pagination callback when the end of the list is reached. */ onLoadMore?: () => void; /** Whether the data is currently being fetched. */ @@ -33,6 +42,8 @@ interface IScrollableListBase { placeholderComponent?: React.ComponentType | React.NamedExoticComponent; /** Number of placeholders to render while loading. */ placeholderCount?: number; + /** Extra class names on the parent element. */ + className?: string; /** Extra class names on the list element. */ listClassName?: string; /** Class names on each item container. */ @@ -41,6 +52,8 @@ interface IScrollableListBase { loadMoreClassName?: string; /** `id` attribute on the parent element. */ id?: string; + /** CSS styles on the parent element. */ + style?: React.CSSProperties; /** Initial item index to scroll to. */ initialIndex?: number; /** Estimated size for items. */ @@ -49,20 +62,7 @@ interface IScrollableListBase { alignToBottom?: boolean; } -interface IScrollableListWithContainer extends IScrollableListBase { - /** Extra class names on the container element. */ - className?: string; - /** CSS styles on the container element. */ - style?: React.CSSProperties; -} - -interface IScrollableListWithoutContainer extends IScrollableListBase { - parentRef: React.RefObject; -} - -type IScrollableList = IScrollableListWithContainer | IScrollableListWithoutContainer; - -const ScrollableList = React.forwardRef, IScrollableList>(({ +const ScrollableList = React.forwardRef, IScrollableList & IScrollableListWindowScroll>(({ prepend = null, alwaysPrepend, children, @@ -72,6 +72,7 @@ const ScrollableList = React.forwardRef, IScrollableList>( showLoading, onScroll, onLoadMore, + className, listClassName, itemClassName, loadMoreClassName, @@ -80,6 +81,7 @@ const ScrollableList = React.forwardRef, IScrollableList>( placeholderComponent: Placeholder, placeholderCount = 0, initialIndex, + style = {}, estimatedSize = 300, alignToBottom, ...props @@ -95,11 +97,15 @@ const ScrollableList = React.forwardRef, IScrollableList>( const data = showPlaceholder ? Array(placeholderCount).fill('') : elements; - const virtualizer = useVirtualizer({ + const virtualizer = props.useWindowScroll === false ? useVirtualizer({ count: data.length + (hasMore ? 1 : 0), - overscan: 2, + overscan: 3, + estimateSize: () => estimatedSize, + getScrollElement: () => props.parentRef.current || parentRef.current, + }) : useWindowVirtualizer({ + count: data.length + (hasMore ? 1 : 0), + overscan: 3, estimateSize: () => estimatedSize, - getScrollElement: () => ('parentRef' in props && props.parentRef.current) || parentRef.current, }); useEffect(() => { @@ -164,51 +170,44 @@ const ScrollableList = React.forwardRef, IScrollableList>( const virtualItems = virtualizer.getVirtualItems(); - const body = ( -
- {(!showLoading || showPlaceholder) && data.length ? ( - <> - {prepend} - {virtualItems.map((item) => ( -
- {renderItem(item.index)} -
- ))} - - ) : renderEmpty()} -
- ); - - if ('parentRef' in props) return body; - return (
- {body} +
+ {(!showLoading || showPlaceholder) && data.length ? ( + <> + {prepend} + {virtualItems.map((item) => ( +
+ {renderItem(item.index)} +
+ ))} + + ) : renderEmpty()} +
); }); -export { type IScrollableList, type IScrollableListWithContainer, type IScrollableListWithoutContainer, ScrollableList as default }; +export { type IScrollableList, ScrollableList as default }; diff --git a/packages/pl-fe/src/components/status-list.tsx b/packages/pl-fe/src/components/status-list.tsx index 2f7d0ab6e..e44d5936b 100644 --- a/packages/pl-fe/src/components/status-list.tsx +++ b/packages/pl-fe/src/components/status-list.tsx @@ -14,9 +14,9 @@ import { usePlFeConfig } from 'pl-fe/hooks'; import { Stack, Text } from './ui'; import type { OrderedSet as ImmutableOrderedSet } from 'immutable'; -import type { IScrollableListWithContainer } from 'pl-fe/components/scrollable-list'; +import type { IScrollableList } from 'pl-fe/components/scrollable-list'; -interface IStatusList extends Omit { +interface IStatusList extends Omit { /** Unique key to preserve the scroll position when navigating back. */ scrollKey: string; /** List of status IDs to display. */ @@ -54,6 +54,7 @@ const StatusList: React.FC = ({ isLoading, isPartial, showGroup = true, + className, ...other }) => { const plFeConfig = usePlFeConfig(); @@ -219,6 +220,7 @@ const StatusList: React.FC = ({ onLoadMore={handleLoadOlder} placeholderComponent={() => } placeholderCount={20} + className={className} listClassName={clsx('divide-y divide-solid divide-gray-200 dark:divide-gray-800', { 'divide-none': divideType !== 'border', })} diff --git a/packages/pl-fe/src/features/chats/components/chat-list.tsx b/packages/pl-fe/src/features/chats/components/chat-list.tsx index 2810ad44a..d6f83feb3 100644 --- a/packages/pl-fe/src/features/chats/components/chat-list.tsx +++ b/packages/pl-fe/src/features/chats/components/chat-list.tsx @@ -59,6 +59,7 @@ const ChatList: React.FC = ({ onClickChat, parentRef, topOffset }) => hasMore={hasNextPage} onLoadMore={handleLoadMore} estimatedSize={64} + useWindowScroll={false} parentRef={parentRef} loadMoreClassName='mx-4 mb-4' > diff --git a/packages/pl-fe/src/features/chats/components/chat-message-list.tsx b/packages/pl-fe/src/features/chats/components/chat-message-list.tsx index 964fb938b..1cc1e148b 100644 --- a/packages/pl-fe/src/features/chats/components/chat-message-list.tsx +++ b/packages/pl-fe/src/features/chats/components/chat-message-list.tsx @@ -196,6 +196,7 @@ const ChatMessageList: React.FC = ({ chat }) => { isLoading={isFetching} showLoading={isFetching && !isFetchingNextPage} onLoadMore={handleStartReached} + useWindowScroll={false} parentRef={parentRef} > {cachedChatMessages.map((chatMessage, index) => { diff --git a/packages/pl-fe/src/features/chats/components/chat-search/results.tsx b/packages/pl-fe/src/features/chats/components/chat-search/results.tsx index e53f7c286..f78dd890c 100644 --- a/packages/pl-fe/src/features/chats/components/chat-search/results.tsx +++ b/packages/pl-fe/src/features/chats/components/chat-search/results.tsx @@ -61,6 +61,7 @@ const Results = ({ accountSearchResult, onSelect, parentRef }: IResults) => { isLoading={isFetching} hasMore={hasNextPage} onLoadMore={handleLoadMore} + useWindowScroll={false} parentRef={parentRef} > {(accounts || []).map((chat) => renderAccount(chat))} diff --git a/packages/pl-fe/src/features/onboarding/steps/suggested-accounts-step.tsx b/packages/pl-fe/src/features/onboarding/steps/suggested-accounts-step.tsx index 02681b36b..c0a89012d 100644 --- a/packages/pl-fe/src/features/onboarding/steps/suggested-accounts-step.tsx +++ b/packages/pl-fe/src/features/onboarding/steps/suggested-accounts-step.tsx @@ -21,6 +21,7 @@ const SuggestedAccountsStep = ({ onNext }: { onNext: () => void }) => { {data.map((suggestion) => ( diff --git a/packages/pl-fe/src/features/status/components/thread.tsx b/packages/pl-fe/src/features/status/components/thread.tsx index 8cc3ea812..70e956a44 100644 --- a/packages/pl-fe/src/features/status/components/thread.tsx +++ b/packages/pl-fe/src/features/status/components/thread.tsx @@ -78,14 +78,14 @@ const getDescendantsIds = createSelector([ interface IThread { status: SelectedStatus; withMedia?: boolean; - isModal?: boolean; + useWindowScroll?: boolean; itemClassName?: string; } const Thread: React.FC = ({ itemClassName, status, - isModal = false, + useWindowScroll = true, withMedia = true, }) => { const dispatch = useAppDispatch(); @@ -114,7 +114,7 @@ const Thread: React.FC = ({ }); let initialIndex = ancestorsIds.size; - if (isModal && initialIndex !== 0) initialIndex = ancestorsIds.size + 1; + if (!useWindowScroll && initialIndex !== 0) initialIndex = ancestorsIds.size + 1; const node = useRef(null); const statusRef = useRef(null); @@ -234,7 +234,7 @@ const Thread: React.FC = ({ }; const _selectChild = (index: number) => { - if (isModal) index = index + 1; + if (!useWindowScroll) index = index + 1; const selector = `[data-index="${index}"] .focusable`; const element = node.current?.querySelector(selector); @@ -341,7 +341,7 @@ const Thread: React.FC = ({ @@ -356,7 +356,7 @@ const Thread: React.FC = ({ const children: JSX.Element[] = []; - if (isModal) { + if (!useWindowScroll) { // Add padding to the top of the Thread (for Media Modal) children.push(
); } @@ -376,8 +376,8 @@ const Thread: React.FC = ({ space={2} className={ clsx({ - 'h-full': isModal, - 'mt-2': !isModal, + 'h-full': !useWindowScroll, + 'mt-2': useWindowScroll, }) } > @@ -391,7 +391,7 @@ const Thread: React.FC = ({ ref={node} className={ clsx('bg-white black:bg-black dark:bg-primary-900', { - 'h-full overflow-auto': isModal, + 'h-full overflow-auto': !useWindowScroll, }) } > @@ -403,9 +403,10 @@ const Thread: React.FC = ({ itemClassName={itemClassName} listClassName={ clsx({ - 'h-full': isModal, + 'h-full': !useWindowScroll, }) } + useWindowScroll={useWindowScroll} parentRef={node} > {children} diff --git a/packages/pl-fe/src/features/ui/components/modals/familiar-followers-modal.tsx b/packages/pl-fe/src/features/ui/components/modals/familiar-followers-modal.tsx index 87b006cf3..0596f88c2 100644 --- a/packages/pl-fe/src/features/ui/components/modals/familiar-followers-modal.tsx +++ b/packages/pl-fe/src/features/ui/components/modals/familiar-followers-modal.tsx @@ -38,6 +38,7 @@ const FamiliarFollowersModal: React.FC {familiarFollowerIds.map(id => diff --git a/packages/pl-fe/src/features/ui/components/modals/favourites-modal.tsx b/packages/pl-fe/src/features/ui/components/modals/favourites-modal.tsx index a3f6a3241..5cca93b98 100644 --- a/packages/pl-fe/src/features/ui/components/modals/favourites-modal.tsx +++ b/packages/pl-fe/src/features/ui/components/modals/favourites-modal.tsx @@ -54,6 +54,7 @@ const FavouritesModal: React.FC = ({ onCl onLoadMore={handleLoadMore} hasMore={!!next} estimatedSize={42} + useWindowScroll={false} parentRef={modalRef} > {accountIds.map(id => diff --git a/packages/pl-fe/src/features/ui/components/modals/media-modal.tsx b/packages/pl-fe/src/features/ui/components/modals/media-modal.tsx index 55b6cc8de..d99aba5ee 100644 --- a/packages/pl-fe/src/features/ui/components/modals/media-modal.tsx +++ b/packages/pl-fe/src/features/ui/components/modals/media-modal.tsx @@ -337,7 +337,7 @@ const MediaModal: React.FC = (props) => {
diff --git a/packages/pl-fe/src/features/ui/components/modals/mentions-modal.tsx b/packages/pl-fe/src/features/ui/components/modals/mentions-modal.tsx index ba559f169..6ab36dc96 100644 --- a/packages/pl-fe/src/features/ui/components/modals/mentions-modal.tsx +++ b/packages/pl-fe/src/features/ui/components/modals/mentions-modal.tsx @@ -46,6 +46,7 @@ const MentionsModal: React.FC = ({ onClose, listClassName='max-w-full' itemClassName='pb-3' estimatedSize={42} + useWindowScroll={false} parentRef={modalRef} > {accountIds.map(id => diff --git a/packages/pl-fe/src/features/ui/components/modals/reactions-modal.tsx b/packages/pl-fe/src/features/ui/components/modals/reactions-modal.tsx index 07d06894f..da5a30c42 100644 --- a/packages/pl-fe/src/features/ui/components/modals/reactions-modal.tsx +++ b/packages/pl-fe/src/features/ui/components/modals/reactions-modal.tsx @@ -95,6 +95,7 @@ const ReactionsModal: React.FC = ({ onClos itemClassName='pb-3' style={{ height: 'calc(80vh - 88px)' }} estimatedSize={42} + useWindowScroll={false} parentRef={modalRef} > {accounts.map((account) => diff --git a/packages/pl-fe/src/features/ui/components/modals/reblogs-modal.tsx b/packages/pl-fe/src/features/ui/components/modals/reblogs-modal.tsx index 6a8120c58..e0514763f 100644 --- a/packages/pl-fe/src/features/ui/components/modals/reblogs-modal.tsx +++ b/packages/pl-fe/src/features/ui/components/modals/reblogs-modal.tsx @@ -56,6 +56,7 @@ const ReblogsModal: React.FC = ({ onClose, s onLoadMore={handleLoadMore} hasMore={!!next} estimatedSize={42} + useWindowScroll={false} parentRef={modalRef} > {accountIds.map((id) =>