Merge branch 'ptr-fix' into 'develop'

Remove PullToRefresh from ScrollableList, wrap outer components instead

See merge request soapbox-pub/soapbox-fe!1633
environments/review-develop-3zknud/deployments/553
Alex Gleason 2 years ago
commit 489792e1f3

@ -3,7 +3,6 @@ import React, { useEffect, useRef, useMemo, useCallback } from 'react';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import { Virtuoso, Components, VirtuosoProps, VirtuosoHandle, ListRange, IndexLocationWithAlign } from 'react-virtuoso'; import { Virtuoso, Components, VirtuosoProps, VirtuosoHandle, ListRange, IndexLocationWithAlign } from 'react-virtuoso';
import PullToRefresh from 'soapbox/components/pull-to-refresh';
import { useSettings } from 'soapbox/hooks'; import { useSettings } from 'soapbox/hooks';
import LoadMore from './load_more'; import LoadMore from './load_more';
@ -63,7 +62,10 @@ interface IScrollableList extends VirtuosoProps<any, any> {
placeholderComponent?: React.ComponentType | React.NamedExoticComponent, placeholderComponent?: React.ComponentType | React.NamedExoticComponent,
/** Number of placeholders to render while loading. */ /** Number of placeholders to render while loading. */
placeholderCount?: number, placeholderCount?: number,
/** Pull to refresh callback. */ /**
* Pull to refresh callback.
* @deprecated Put a PTR around the component instead.
*/
onRefresh?: () => Promise<any>, onRefresh?: () => Promise<any>,
/** Extra class names on the Virtuoso element. */ /** Extra class names on the Virtuoso element. */
className?: string, className?: string,
@ -244,20 +246,12 @@ const ScrollableList = React.forwardRef<VirtuosoHandle, IScrollableList>(({
/> />
); );
/** Conditionally render inner elements. */ // Conditionally render inner elements.
const renderBody = (): JSX.Element => { if (isEmpty) {
if (isEmpty) { return renderEmpty();
return renderEmpty(); } else {
} else { return renderFeed();
return renderFeed(); }
}
};
return (
<PullToRefresh onRefresh={onRefresh}>
{renderBody()}
</PullToRefresh>
);
}); });
export default ScrollableList; export default ScrollableList;

@ -3,6 +3,7 @@ import React from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { fetchBookmarkedStatuses, expandBookmarkedStatuses } from 'soapbox/actions/bookmarks'; import { fetchBookmarkedStatuses, expandBookmarkedStatuses } from 'soapbox/actions/bookmarks';
import PullToRefresh from 'soapbox/components/pull-to-refresh';
import StatusList from 'soapbox/components/status_list'; import StatusList from 'soapbox/components/status_list';
import SubNavigation from 'soapbox/components/sub_navigation'; import SubNavigation from 'soapbox/components/sub_navigation';
import { Column } from 'soapbox/components/ui'; import { Column } from 'soapbox/components/ui';
@ -39,16 +40,17 @@ const Bookmarks: React.FC = () => {
<div className='px-4 pt-4 sm:p-0'> <div className='px-4 pt-4 sm:p-0'>
<SubNavigation message={intl.formatMessage(messages.heading)} /> <SubNavigation message={intl.formatMessage(messages.heading)} />
</div> </div>
<StatusList <PullToRefresh onRefresh={handleRefresh}>
statusIds={statusIds} <StatusList
scrollKey='bookmarked_statuses' statusIds={statusIds}
hasMore={hasMore} scrollKey='bookmarked_statuses'
isLoading={typeof isLoading === 'boolean' ? isLoading : true} hasMore={hasMore}
onLoadMore={() => handleLoadMore(dispatch)} isLoading={typeof isLoading === 'boolean' ? isLoading : true}
onRefresh={handleRefresh} onLoadMore={() => handleLoadMore(dispatch)}
emptyMessage={emptyMessage} emptyMessage={emptyMessage}
divideType='space' divideType='space'
/> />
</PullToRefresh>
</Column> </Column>
); );
}; };

@ -3,6 +3,7 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { connectCommunityStream } from 'soapbox/actions/streaming'; import { connectCommunityStream } from 'soapbox/actions/streaming';
import { expandCommunityTimeline } from 'soapbox/actions/timelines'; import { expandCommunityTimeline } from 'soapbox/actions/timelines';
import PullToRefresh from 'soapbox/components/pull-to-refresh';
import SubNavigation from 'soapbox/components/sub_navigation'; import SubNavigation from 'soapbox/components/sub_navigation';
import { Column } from 'soapbox/components/ui'; import { Column } from 'soapbox/components/ui';
import { useAppDispatch, useSettings } from 'soapbox/hooks'; import { useAppDispatch, useSettings } from 'soapbox/hooks';
@ -44,14 +45,15 @@ const CommunityTimeline = () => {
return ( return (
<Column label={intl.formatMessage(messages.title)} transparent> <Column label={intl.formatMessage(messages.title)} transparent>
<SubNavigation message={intl.formatMessage(messages.title)} settings={ColumnSettings} /> <SubNavigation message={intl.formatMessage(messages.title)} settings={ColumnSettings} />
<Timeline <PullToRefresh onRefresh={handleRefresh}>
scrollKey={`${timelineId}_timeline`} <Timeline
timelineId={`${timelineId}${onlyMedia ? ':media' : ''}`} scrollKey={`${timelineId}_timeline`}
onLoadMore={handleLoadMore} timelineId={`${timelineId}${onlyMedia ? ':media' : ''}`}
onRefresh={handleRefresh} onLoadMore={handleLoadMore}
emptyMessage={<FormattedMessage id='empty_column.community' defaultMessage='The local timeline is empty. Write something publicly to get the ball rolling!' />} emptyMessage={<FormattedMessage id='empty_column.community' defaultMessage='The local timeline is empty. Write something publicly to get the ball rolling!' />}
divideType='space' divideType='space'
/> />
</PullToRefresh>
</Column> </Column>
); );
}; };

@ -3,6 +3,7 @@ import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { expandHomeTimeline } from 'soapbox/actions/timelines'; import { expandHomeTimeline } from 'soapbox/actions/timelines';
import PullToRefresh from 'soapbox/components/pull-to-refresh';
import { Column, Stack, Text } from 'soapbox/components/ui'; import { Column, Stack, Text } from 'soapbox/components/ui';
import Timeline from 'soapbox/features/ui/components/timeline'; import Timeline from 'soapbox/features/ui/components/timeline';
import { useAppSelector, useAppDispatch, useFeatures } from 'soapbox/hooks'; import { useAppSelector, useAppDispatch, useFeatures } from 'soapbox/hooks';
@ -59,47 +60,48 @@ const HomeTimeline: React.FC = () => {
return ( return (
<Column label={intl.formatMessage(messages.title)} transparent> <Column label={intl.formatMessage(messages.title)} transparent>
<Timeline <PullToRefresh onRefresh={handleRefresh}>
scrollKey='home_timeline' <Timeline
onLoadMore={handleLoadMore} scrollKey='home_timeline'
onRefresh={handleRefresh} onLoadMore={handleLoadMore}
timelineId='home' timelineId='home'
divideType='space' divideType='space'
emptyMessage={ emptyMessage={
<Stack space={1}> <Stack space={1}>
<Text size='xl' weight='medium' align='center'> <Text size='xl' weight='medium' align='center'>
<FormattedMessage <FormattedMessage
id='empty_column.home.title' id='empty_column.home.title'
defaultMessage="You're not following anyone yet" defaultMessage="You're not following anyone yet"
/> />
</Text> </Text>
<Text theme='muted' align='center'>
<FormattedMessage
id='empty_column.home.subtitle'
defaultMessage='{siteTitle} gets more interesting once you follow other users.'
values={{ siteTitle }}
/>
</Text>
{features.federating && (
<Text theme='muted' align='center'> <Text theme='muted' align='center'>
<FormattedMessage <FormattedMessage
id='empty_column.home' id='empty_column.home.subtitle'
defaultMessage='Or you can visit {public} to get started and meet other users.' defaultMessage='{siteTitle} gets more interesting once you follow other users.'
values={{ values={{ siteTitle }}
public: (
<Link to='/timeline/local' className='text-primary-600 dark:text-primary-400 hover:underline'>
<FormattedMessage id='empty_column.home.local_tab' defaultMessage='the {site_title} tab' values={{ site_title: siteTitle }} />
</Link>
),
}}
/> />
</Text> </Text>
)}
</Stack> {features.federating && (
} <Text theme='muted' align='center'>
/> <FormattedMessage
id='empty_column.home'
defaultMessage='Or you can visit {public} to get started and meet other users.'
values={{
public: (
<Link to='/timeline/local' className='text-primary-600 dark:text-primary-400 hover:underline'>
<FormattedMessage id='empty_column.home.local_tab' defaultMessage='the {site_title} tab' values={{ site_title: siteTitle }} />
</Link>
),
}}
/>
</Text>
)}
</Stack>
}
/>
</PullToRefresh>
</Column> </Column>
); );
}; };

@ -11,6 +11,7 @@ import {
dequeueNotifications, dequeueNotifications,
} from 'soapbox/actions/notifications'; } from 'soapbox/actions/notifications';
import { getSettings } from 'soapbox/actions/settings'; import { getSettings } from 'soapbox/actions/settings';
import PullToRefresh from 'soapbox/components/pull-to-refresh';
import ScrollTopButton from 'soapbox/components/scroll-top-button'; import ScrollTopButton from 'soapbox/components/scroll-top-button';
import ScrollableList from 'soapbox/components/scrollable_list'; import ScrollableList from 'soapbox/components/scrollable_list';
import { Column } from 'soapbox/components/ui'; import { Column } from 'soapbox/components/ui';
@ -161,7 +162,6 @@ const Notifications = () => {
placeholderComponent={PlaceholderNotification} placeholderComponent={PlaceholderNotification}
placeholderCount={20} placeholderCount={20}
onLoadMore={handleLoadOlder} onLoadMore={handleLoadOlder}
onRefresh={handleRefresh}
onScrollToTop={handleScrollToTop} onScrollToTop={handleScrollToTop}
onScroll={handleScroll} onScroll={handleScroll}
className={classNames({ className={classNames({
@ -181,7 +181,9 @@ const Notifications = () => {
count={totalQueuedNotificationsCount} count={totalQueuedNotificationsCount}
message={messages.queue} message={messages.queue}
/> />
{scrollContainer} <PullToRefresh onRefresh={handleRefresh}>
{scrollContainer}
</PullToRefresh>
</Column> </Column>
); );
}; };

@ -5,6 +5,7 @@ import { Link } from 'react-router-dom';
import { changeSetting } from 'soapbox/actions/settings'; import { changeSetting } from 'soapbox/actions/settings';
import { connectPublicStream } from 'soapbox/actions/streaming'; import { connectPublicStream } from 'soapbox/actions/streaming';
import { expandPublicTimeline } from 'soapbox/actions/timelines'; import { expandPublicTimeline } from 'soapbox/actions/timelines';
import PullToRefresh from 'soapbox/components/pull-to-refresh';
import SubNavigation from 'soapbox/components/sub_navigation'; import SubNavigation from 'soapbox/components/sub_navigation';
import { Column } from 'soapbox/components/ui'; import { Column } from 'soapbox/components/ui';
import Accordion from 'soapbox/features/ui/components/accordion'; import Accordion from 'soapbox/features/ui/components/accordion';
@ -91,14 +92,15 @@ const CommunityTimeline = () => {
/> />
</Accordion> </Accordion>
</div>} </div>}
<Timeline <PullToRefresh onRefresh={handleRefresh}>
scrollKey={`${timelineId}_timeline`} <Timeline
timelineId={`${timelineId}${onlyMedia ? ':media' : ''}`} scrollKey={`${timelineId}_timeline`}
onLoadMore={handleLoadMore} timelineId={`${timelineId}${onlyMedia ? ':media' : ''}`}
onRefresh={handleRefresh} onLoadMore={handleLoadMore}
emptyMessage={<FormattedMessage id='empty_column.public' defaultMessage='There is nothing here! Write something publicly, or manually follow users from other servers to fill it up' />} emptyMessage={<FormattedMessage id='empty_column.public' defaultMessage='There is nothing here! Write something publicly, or manually follow users from other servers to fill it up' />}
divideType='space' divideType='space'
/> />
</PullToRefresh>
</Column> </Column>
); );
}; };

@ -49,6 +49,7 @@ import {
fetchNext, fetchNext,
} from 'soapbox/actions/statuses'; } from 'soapbox/actions/statuses';
import MissingIndicator from 'soapbox/components/missing_indicator'; import MissingIndicator from 'soapbox/components/missing_indicator';
import PullToRefresh from 'soapbox/components/pull-to-refresh';
import ScrollableList from 'soapbox/components/scrollable_list'; import ScrollableList from 'soapbox/components/scrollable_list';
import { textForScreenReader } from 'soapbox/components/status'; import { textForScreenReader } from 'soapbox/components/status';
import SubNavigation from 'soapbox/components/sub_navigation'; import SubNavigation from 'soapbox/components/sub_navigation';
@ -796,23 +797,24 @@ class Status extends ImmutablePureComponent<IStatus, IStatusState> {
<SubNavigation message={intl.formatMessage(titleMessage, { username })} /> <SubNavigation message={intl.formatMessage(titleMessage, { username })} />
</div> </div>
<Stack space={2}> <PullToRefresh onRefresh={this.handleRefresh}>
<div ref={this.setRef} className='thread'> <Stack space={2}>
<ScrollableList <div ref={this.setRef} className='thread'>
id='thread' <ScrollableList
ref={this.setScrollerRef} id='thread'
onRefresh={this.handleRefresh} ref={this.setScrollerRef}
hasMore={!!this.state.next} hasMore={!!this.state.next}
onLoadMore={this.handleLoadMore} onLoadMore={this.handleLoadMore}
placeholderComponent={() => <PlaceholderStatus thread />} placeholderComponent={() => <PlaceholderStatus thread />}
initialTopMostItemIndex={ancestorsIds.size} initialTopMostItemIndex={ancestorsIds.size}
> >
{children} {children}
</ScrollableList> </ScrollableList>
</div> </div>
{!me && <ThreadLoginCta />} {!me && <ThreadLoginCta />}
</Stack> </Stack>
</PullToRefresh>
</Column> </Column>
); );
} }

Loading…
Cancel
Save