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 { 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
|
|
||||||
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'>
|
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='empty_column.home'
|
id='empty_column.home.title'
|
||||||
defaultMessage='Or you can visit {public} to get started and meet other users.'
|
defaultMessage="You're not following anyone yet"
|
||||||
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>
|
</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>
|
</Column>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,6 +14,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';
|
||||||
|
@ -185,7 +186,6 @@ class Notifications extends React.PureComponent {
|
||||||
placeholderComponent={PlaceholderNotification}
|
placeholderComponent={PlaceholderNotification}
|
||||||
placeholderCount={20}
|
placeholderCount={20}
|
||||||
onLoadMore={this.handleLoadOlder}
|
onLoadMore={this.handleLoadOlder}
|
||||||
onRefresh={this.handleRefresh}
|
|
||||||
onScrollToTop={this.handleScrollToTop}
|
onScrollToTop={this.handleScrollToTop}
|
||||||
onScroll={this.handleScroll}
|
onScroll={this.handleScroll}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
|
@ -205,7 +205,9 @@ class Notifications extends React.PureComponent {
|
||||||
count={totalQueuedNotificationsCount}
|
count={totalQueuedNotificationsCount}
|
||||||
message={messages.queue}
|
message={messages.queue}
|
||||||
/>
|
/>
|
||||||
{scrollContainer}
|
<PullToRefresh onRefresh={this.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…
Reference in a new issue