Remove PullToRefresh from ScrollableList, wrap outer components instead
This commit is contained in:
parent
8566fad06f
commit
f4f34cf585
7 changed files with 104 additions and 98 deletions
|
@ -3,7 +3,6 @@ import React, { useEffect, useRef, useMemo, useCallback } from 'react';
|
|||
import { useHistory } from 'react-router-dom';
|
||||
import { Virtuoso, Components, VirtuosoProps, VirtuosoHandle, ListRange, IndexLocationWithAlign } from 'react-virtuoso';
|
||||
|
||||
import PullToRefresh from 'soapbox/components/pull-to-refresh';
|
||||
import { useSettings } from 'soapbox/hooks';
|
||||
|
||||
import LoadMore from './load_more';
|
||||
|
@ -63,7 +62,10 @@ interface IScrollableList extends VirtuosoProps<any, any> {
|
|||
placeholderComponent?: React.ComponentType | React.NamedExoticComponent,
|
||||
/** Number of placeholders to render while loading. */
|
||||
placeholderCount?: number,
|
||||
/** Pull to refresh callback. */
|
||||
/**
|
||||
* Pull to refresh callback.
|
||||
* @deprecated Put a PTR around the component instead.
|
||||
*/
|
||||
onRefresh?: () => Promise<any>,
|
||||
/** Extra class names on the Virtuoso element. */
|
||||
className?: string,
|
||||
|
@ -244,20 +246,12 @@ const ScrollableList = React.forwardRef<VirtuosoHandle, IScrollableList>(({
|
|||
/>
|
||||
);
|
||||
|
||||
/** Conditionally render inner elements. */
|
||||
const renderBody = (): JSX.Element => {
|
||||
if (isEmpty) {
|
||||
return renderEmpty();
|
||||
} else {
|
||||
return renderFeed();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<PullToRefresh onRefresh={onRefresh}>
|
||||
{renderBody()}
|
||||
</PullToRefresh>
|
||||
);
|
||||
// Conditionally render inner elements.
|
||||
if (isEmpty) {
|
||||
return renderEmpty();
|
||||
} else {
|
||||
return renderFeed();
|
||||
}
|
||||
});
|
||||
|
||||
export default ScrollableList;
|
||||
|
|
|
@ -3,6 +3,7 @@ import React from 'react';
|
|||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||
|
||||
import { fetchBookmarkedStatuses, expandBookmarkedStatuses } from 'soapbox/actions/bookmarks';
|
||||
import PullToRefresh from 'soapbox/components/pull-to-refresh';
|
||||
import StatusList from 'soapbox/components/status_list';
|
||||
import SubNavigation from 'soapbox/components/sub_navigation';
|
||||
import { Column } from 'soapbox/components/ui';
|
||||
|
@ -39,16 +40,17 @@ const Bookmarks: React.FC = () => {
|
|||
<div className='px-4 pt-4 sm:p-0'>
|
||||
<SubNavigation message={intl.formatMessage(messages.heading)} />
|
||||
</div>
|
||||
<StatusList
|
||||
statusIds={statusIds}
|
||||
scrollKey='bookmarked_statuses'
|
||||
hasMore={hasMore}
|
||||
isLoading={typeof isLoading === 'boolean' ? isLoading : true}
|
||||
onLoadMore={() => handleLoadMore(dispatch)}
|
||||
onRefresh={handleRefresh}
|
||||
emptyMessage={emptyMessage}
|
||||
divideType='space'
|
||||
/>
|
||||
<PullToRefresh onRefresh={handleRefresh}>
|
||||
<StatusList
|
||||
statusIds={statusIds}
|
||||
scrollKey='bookmarked_statuses'
|
||||
hasMore={hasMore}
|
||||
isLoading={typeof isLoading === 'boolean' ? isLoading : true}
|
||||
onLoadMore={() => handleLoadMore(dispatch)}
|
||||
emptyMessage={emptyMessage}
|
||||
divideType='space'
|
||||
/>
|
||||
</PullToRefresh>
|
||||
</Column>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -3,6 +3,7 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
|||
|
||||
import { connectCommunityStream } from 'soapbox/actions/streaming';
|
||||
import { expandCommunityTimeline } from 'soapbox/actions/timelines';
|
||||
import PullToRefresh from 'soapbox/components/pull-to-refresh';
|
||||
import SubNavigation from 'soapbox/components/sub_navigation';
|
||||
import { Column } from 'soapbox/components/ui';
|
||||
import { useAppDispatch, useSettings } from 'soapbox/hooks';
|
||||
|
@ -44,14 +45,15 @@ const CommunityTimeline = () => {
|
|||
return (
|
||||
<Column label={intl.formatMessage(messages.title)} transparent>
|
||||
<SubNavigation message={intl.formatMessage(messages.title)} settings={ColumnSettings} />
|
||||
<Timeline
|
||||
scrollKey={`${timelineId}_timeline`}
|
||||
timelineId={`${timelineId}${onlyMedia ? ':media' : ''}`}
|
||||
onLoadMore={handleLoadMore}
|
||||
onRefresh={handleRefresh}
|
||||
emptyMessage={<FormattedMessage id='empty_column.community' defaultMessage='The local timeline is empty. Write something publicly to get the ball rolling!' />}
|
||||
divideType='space'
|
||||
/>
|
||||
<PullToRefresh onRefresh={handleRefresh}>
|
||||
<Timeline
|
||||
scrollKey={`${timelineId}_timeline`}
|
||||
timelineId={`${timelineId}${onlyMedia ? ':media' : ''}`}
|
||||
onLoadMore={handleLoadMore}
|
||||
emptyMessage={<FormattedMessage id='empty_column.community' defaultMessage='The local timeline is empty. Write something publicly to get the ball rolling!' />}
|
||||
divideType='space'
|
||||
/>
|
||||
</PullToRefresh>
|
||||
</Column>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -3,6 +3,7 @@ import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
|||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { expandHomeTimeline } from 'soapbox/actions/timelines';
|
||||
import PullToRefresh from 'soapbox/components/pull-to-refresh';
|
||||
import { Column, Stack, Text } from 'soapbox/components/ui';
|
||||
import Timeline from 'soapbox/features/ui/components/timeline';
|
||||
import { useAppSelector, useAppDispatch, useFeatures } from 'soapbox/hooks';
|
||||
|
@ -59,47 +60,48 @@ const HomeTimeline: React.FC = () => {
|
|||
|
||||
return (
|
||||
<Column label={intl.formatMessage(messages.title)} transparent>
|
||||
<Timeline
|
||||
scrollKey='home_timeline'
|
||||
onLoadMore={handleLoadMore}
|
||||
onRefresh={handleRefresh}
|
||||
timelineId='home'
|
||||
divideType='space'
|
||||
emptyMessage={
|
||||
<Stack space={1}>
|
||||
<Text size='xl' weight='medium' align='center'>
|
||||
<FormattedMessage
|
||||
id='empty_column.home.title'
|
||||
defaultMessage="You're not following anyone yet"
|
||||
/>
|
||||
</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'>
|
||||
<PullToRefresh onRefresh={handleRefresh}>
|
||||
<Timeline
|
||||
scrollKey='home_timeline'
|
||||
onLoadMore={handleLoadMore}
|
||||
timelineId='home'
|
||||
divideType='space'
|
||||
emptyMessage={
|
||||
<Stack space={1}>
|
||||
<Text size='xl' weight='medium' 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>
|
||||
),
|
||||
}}
|
||||
id='empty_column.home.title'
|
||||
defaultMessage="You're not following anyone yet"
|
||||
/>
|
||||
</Text>
|
||||
)}
|
||||
</Stack>
|
||||
}
|
||||
/>
|
||||
|
||||
<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'>
|
||||
<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>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
dequeueNotifications,
|
||||
} from 'soapbox/actions/notifications';
|
||||
import { getSettings } from 'soapbox/actions/settings';
|
||||
import PullToRefresh from 'soapbox/components/pull-to-refresh';
|
||||
import ScrollTopButton from 'soapbox/components/scroll-top-button';
|
||||
import ScrollableList from 'soapbox/components/scrollable_list';
|
||||
import { Column } from 'soapbox/components/ui';
|
||||
|
@ -185,7 +186,6 @@ class Notifications extends React.PureComponent {
|
|||
placeholderComponent={PlaceholderNotification}
|
||||
placeholderCount={20}
|
||||
onLoadMore={this.handleLoadOlder}
|
||||
onRefresh={this.handleRefresh}
|
||||
onScrollToTop={this.handleScrollToTop}
|
||||
onScroll={this.handleScroll}
|
||||
className={classNames({
|
||||
|
@ -205,7 +205,9 @@ class Notifications extends React.PureComponent {
|
|||
count={totalQueuedNotificationsCount}
|
||||
message={messages.queue}
|
||||
/>
|
||||
{scrollContainer}
|
||||
<PullToRefresh onRefresh={this.handleRefresh}>
|
||||
{scrollContainer}
|
||||
</PullToRefresh>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import { Link } from 'react-router-dom';
|
|||
import { changeSetting } from 'soapbox/actions/settings';
|
||||
import { connectPublicStream } from 'soapbox/actions/streaming';
|
||||
import { expandPublicTimeline } from 'soapbox/actions/timelines';
|
||||
import PullToRefresh from 'soapbox/components/pull-to-refresh';
|
||||
import SubNavigation from 'soapbox/components/sub_navigation';
|
||||
import { Column } from 'soapbox/components/ui';
|
||||
import Accordion from 'soapbox/features/ui/components/accordion';
|
||||
|
@ -91,14 +92,15 @@ const CommunityTimeline = () => {
|
|||
/>
|
||||
</Accordion>
|
||||
</div>}
|
||||
<Timeline
|
||||
scrollKey={`${timelineId}_timeline`}
|
||||
timelineId={`${timelineId}${onlyMedia ? ':media' : ''}`}
|
||||
onLoadMore={handleLoadMore}
|
||||
onRefresh={handleRefresh}
|
||||
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'
|
||||
/>
|
||||
<PullToRefresh onRefresh={handleRefresh}>
|
||||
<Timeline
|
||||
scrollKey={`${timelineId}_timeline`}
|
||||
timelineId={`${timelineId}${onlyMedia ? ':media' : ''}`}
|
||||
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' />}
|
||||
divideType='space'
|
||||
/>
|
||||
</PullToRefresh>
|
||||
</Column>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -49,6 +49,7 @@ import {
|
|||
fetchNext,
|
||||
} from 'soapbox/actions/statuses';
|
||||
import MissingIndicator from 'soapbox/components/missing_indicator';
|
||||
import PullToRefresh from 'soapbox/components/pull-to-refresh';
|
||||
import ScrollableList from 'soapbox/components/scrollable_list';
|
||||
import { textForScreenReader } from 'soapbox/components/status';
|
||||
import SubNavigation from 'soapbox/components/sub_navigation';
|
||||
|
@ -796,23 +797,24 @@ class Status extends ImmutablePureComponent<IStatus, IStatusState> {
|
|||
<SubNavigation message={intl.formatMessage(titleMessage, { username })} />
|
||||
</div>
|
||||
|
||||
<Stack space={2}>
|
||||
<div ref={this.setRef} className='thread'>
|
||||
<ScrollableList
|
||||
id='thread'
|
||||
ref={this.setScrollerRef}
|
||||
onRefresh={this.handleRefresh}
|
||||
hasMore={!!this.state.next}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
placeholderComponent={() => <PlaceholderStatus thread />}
|
||||
initialTopMostItemIndex={ancestorsIds.size}
|
||||
>
|
||||
{children}
|
||||
</ScrollableList>
|
||||
</div>
|
||||
<PullToRefresh onRefresh={this.handleRefresh}>
|
||||
<Stack space={2}>
|
||||
<div ref={this.setRef} className='thread'>
|
||||
<ScrollableList
|
||||
id='thread'
|
||||
ref={this.setScrollerRef}
|
||||
hasMore={!!this.state.next}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
placeholderComponent={() => <PlaceholderStatus thread />}
|
||||
initialTopMostItemIndex={ancestorsIds.size}
|
||||
>
|
||||
{children}
|
||||
</ScrollableList>
|
||||
</div>
|
||||
|
||||
{!me && <ThreadLoginCta />}
|
||||
</Stack>
|
||||
{!me && <ThreadLoginCta />}
|
||||
</Stack>
|
||||
</PullToRefresh>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue