2022-06-02 13:15:30 -07:00
|
|
|
import { OrderedSet as ImmutableOrderedSet } from 'immutable';
|
2022-06-16 12:32:17 -07:00
|
|
|
import debounce from 'lodash/debounce';
|
2022-06-02 13:15:30 -07:00
|
|
|
import React, { useCallback } from 'react';
|
2022-06-02 13:29:20 -07:00
|
|
|
import { defineMessages } from 'react-intl';
|
2022-06-02 13:15:30 -07:00
|
|
|
|
2022-06-07 13:21:18 -07:00
|
|
|
import { dequeueTimeline, scrollTopTimeline } from 'soapbox/actions/timelines';
|
2022-06-03 10:34:30 -07:00
|
|
|
import ScrollTopButton from 'soapbox/components/scroll-top-button';
|
2022-06-02 13:15:30 -07:00
|
|
|
import StatusList, { IStatusList } from 'soapbox/components/status_list';
|
|
|
|
import { useAppSelector, useAppDispatch } from 'soapbox/hooks';
|
|
|
|
import { makeGetStatusIds } from 'soapbox/selectors';
|
|
|
|
|
2022-06-02 13:29:20 -07:00
|
|
|
const messages = defineMessages({
|
|
|
|
queue: { id: 'status_list.queue_label', defaultMessage: 'Click to see {count} new {count, plural, one {post} other {posts}}' },
|
|
|
|
});
|
|
|
|
|
2022-06-03 10:31:23 -07:00
|
|
|
interface ITimeline extends Omit<IStatusList, 'statusIds' | 'isLoading' | 'hasMore'> {
|
2022-06-03 11:09:46 -07:00
|
|
|
/** ID of the timeline in Redux. */
|
2022-06-02 13:15:30 -07:00
|
|
|
timelineId: string,
|
|
|
|
}
|
|
|
|
|
2022-06-03 11:09:46 -07:00
|
|
|
/** Scrollable list of statuses from a timeline in the Redux store. */
|
2022-06-03 10:31:23 -07:00
|
|
|
const Timeline: React.FC<ITimeline> = ({
|
2022-06-02 13:15:30 -07:00
|
|
|
timelineId,
|
|
|
|
onLoadMore,
|
|
|
|
...rest
|
|
|
|
}) => {
|
|
|
|
const dispatch = useAppDispatch();
|
|
|
|
const getStatusIds = useCallback(makeGetStatusIds, [])();
|
|
|
|
|
|
|
|
const lastStatusId = useAppSelector(state => state.timelines.getIn([timelineId, 'items'], ImmutableOrderedSet()).last() as string | undefined);
|
|
|
|
const statusIds = useAppSelector(state => getStatusIds(state, { type: timelineId }));
|
|
|
|
const isLoading = useAppSelector(state => state.timelines.getIn([timelineId, 'isLoading'], true) === true);
|
|
|
|
const isPartial = useAppSelector(state => state.timelines.getIn([timelineId, 'isPartial'], false) === true);
|
|
|
|
const hasMore = useAppSelector(state => state.timelines.getIn([timelineId, 'hasMore']) === true);
|
2022-06-03 10:38:54 -07:00
|
|
|
const totalQueuedItemsCount = useAppSelector(state => state.timelines.getIn([timelineId, 'totalQueuedItemsCount']));
|
2022-06-02 13:15:30 -07:00
|
|
|
|
2022-06-02 13:29:20 -07:00
|
|
|
const handleDequeueTimeline = () => {
|
2022-06-02 13:15:30 -07:00
|
|
|
dispatch(dequeueTimeline(timelineId, onLoadMore));
|
|
|
|
};
|
|
|
|
|
|
|
|
const handleScrollToTop = useCallback(debounce(() => {
|
|
|
|
dispatch(scrollTopTimeline(timelineId, true));
|
2022-06-03 10:25:59 -07:00
|
|
|
}, 100), [timelineId]);
|
2022-06-02 13:15:30 -07:00
|
|
|
|
|
|
|
const handleScroll = useCallback(debounce(() => {
|
|
|
|
dispatch(scrollTopTimeline(timelineId, false));
|
2022-06-03 10:25:59 -07:00
|
|
|
}, 100), [timelineId]);
|
2022-06-02 13:15:30 -07:00
|
|
|
|
|
|
|
return (
|
2022-06-02 13:29:20 -07:00
|
|
|
<>
|
2022-06-03 10:34:30 -07:00
|
|
|
<ScrollTopButton
|
2022-06-02 13:29:20 -07:00
|
|
|
key='timeline-queue-button-header'
|
|
|
|
onClick={handleDequeueTimeline}
|
2022-06-03 10:38:54 -07:00
|
|
|
count={totalQueuedItemsCount}
|
2022-06-02 13:29:20 -07:00
|
|
|
message={messages.queue}
|
|
|
|
/>
|
|
|
|
|
|
|
|
<StatusList
|
2022-06-03 11:09:46 -07:00
|
|
|
timelineId={timelineId}
|
2022-06-02 13:29:20 -07:00
|
|
|
onScrollToTop={handleScrollToTop}
|
|
|
|
onScroll={handleScroll}
|
|
|
|
lastStatusId={lastStatusId}
|
|
|
|
statusIds={statusIds}
|
|
|
|
isLoading={isLoading}
|
|
|
|
isPartial={isPartial}
|
|
|
|
hasMore={hasMore}
|
|
|
|
onLoadMore={onLoadMore}
|
|
|
|
{...rest}
|
|
|
|
/>
|
|
|
|
</>
|
2022-06-02 13:15:30 -07:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2022-06-03 10:31:23 -07:00
|
|
|
export default Timeline;
|