mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
feat(board): suggest user to switch time filter on p/all and p/subscription if there aren't enough posts
This commit is contained in:
@@ -14,9 +14,9 @@ const timeFilterNamesToSeconds: Record<string, number | undefined> = {
|
|||||||
'12h': 60 * 60 * 12,
|
'12h': 60 * 60 * 12,
|
||||||
'24h': 60 * 60 * 24,
|
'24h': 60 * 60 * 24,
|
||||||
'48h': 60 * 60 * 24 * 2,
|
'48h': 60 * 60 * 24 * 2,
|
||||||
week: 60 * 60 * 24 * 7,
|
'1w': 60 * 60 * 24 * 7,
|
||||||
month: 60 * 60 * 24 * 30,
|
'1m': 60 * 60 * 24 * 30,
|
||||||
year: 60 * 60 * 24 * 365,
|
'1y': 60 * 60 * 24 * 365,
|
||||||
all: undefined,
|
all: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -25,8 +25,8 @@ const secondsSinceLastVisit = lastVisitTimestamp ? (Date.now() - parseInt(lastVi
|
|||||||
const day = 24 * 60 * 60;
|
const day = 24 * 60 * 60;
|
||||||
let lastVisitTimeFilterName: string | undefined;
|
let lastVisitTimeFilterName: string | undefined;
|
||||||
if (secondsSinceLastVisit > 30 * day) {
|
if (secondsSinceLastVisit > 30 * day) {
|
||||||
lastVisitTimeFilterName = 'month';
|
lastVisitTimeFilterName = '1m';
|
||||||
timeFilterNamesToSeconds[lastVisitTimeFilterName] = timeFilterNamesToSeconds['month'];
|
timeFilterNamesToSeconds[lastVisitTimeFilterName] = timeFilterNamesToSeconds['1m'];
|
||||||
} else if (secondsSinceLastVisit > 7 * day) {
|
} else if (secondsSinceLastVisit > 7 * day) {
|
||||||
const weeks = Math.ceil(secondsSinceLastVisit / day / 7);
|
const weeks = Math.ceil(secondsSinceLastVisit / day / 7);
|
||||||
lastVisitTimeFilterName = `${weeks}w`;
|
lastVisitTimeFilterName = `${weeks}w`;
|
||||||
@@ -40,7 +40,7 @@ if (secondsSinceLastVisit > 30 * day) {
|
|||||||
timeFilterNamesToSeconds[lastVisitTimeFilterName] = timeFilterNamesToSeconds['24h'];
|
timeFilterNamesToSeconds[lastVisitTimeFilterName] = timeFilterNamesToSeconds['24h'];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const timeFilterNames = [lastVisitTimeFilterName, '1h', '12h', '24h', '48h', 'week', 'month', 'year', 'all'];
|
export const timeFilterNames = [lastVisitTimeFilterName, '1h', '12h', '24h', '48h', '1w', '1m', '1y', 'all'];
|
||||||
|
|
||||||
const useTimeFilter = () => {
|
const useTimeFilter = () => {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
.footer {
|
.footer {
|
||||||
padding-top: 10px;
|
padding: 15px 0 10px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer a {
|
||||||
|
text-decoration: var(--button-text-decoration);
|
||||||
|
color: var(--button-desktop-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer a:hover {
|
||||||
|
color: var(--button-desktop-text-color-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { useEffect, useMemo, useRef } from 'react';
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { useLocation, useParams } from 'react-router-dom';
|
import { Link, useLocation, useParams } from 'react-router-dom';
|
||||||
import { Comment, useAccount, useAccountComments, useBlock, useFeed, useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
import { Comment, useAccount, useAccountComments, useBlock, useFeed, useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
||||||
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
|
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { Trans, useTranslation } from 'react-i18next';
|
||||||
import styles from './board.module.css';
|
import styles from './board.module.css';
|
||||||
import { isAllView, isSubscriptionsView } from '../../lib/utils/view-utils';
|
import { isAllView, isSubscriptionsView } from '../../lib/utils/view-utils';
|
||||||
import { useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits';
|
import { useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits';
|
||||||
@@ -53,7 +53,7 @@ const Board = () => {
|
|||||||
}, [isInAllView, isInSubscriptionsView, subplebbitAddress, defaultSubplebbitAddresses, subscriptions]);
|
}, [isInAllView, isInSubscriptionsView, subplebbitAddress, defaultSubplebbitAddresses, subscriptions]);
|
||||||
|
|
||||||
const { sortType } = useSortingStore();
|
const { sortType } = useSortingStore();
|
||||||
const { timeFilterSeconds } = useTimeFilter();
|
const { timeFilterSeconds, timeFilterName } = useTimeFilter();
|
||||||
|
|
||||||
const feedOptions: any = useMemo(
|
const feedOptions: any = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
@@ -66,7 +66,7 @@ const Board = () => {
|
|||||||
[subplebbitAddresses, sortType, timeFilterSeconds, isInAllView, isInSubscriptionsView, hideThreadsWithoutImages],
|
[subplebbitAddresses, sortType, timeFilterSeconds, isInAllView, isInSubscriptionsView, hideThreadsWithoutImages],
|
||||||
);
|
);
|
||||||
|
|
||||||
const { feed, hasMore, loadMore, reset } = useFeed(feedOptions);
|
const { feed, hasMore, loadMore, reset, subplebbitAddressesWithNewerPosts } = useFeed(feedOptions);
|
||||||
const { accountComments } = useAccountComments();
|
const { accountComments } = useAccountComments();
|
||||||
|
|
||||||
const resetTriggeredRef = useRef(false);
|
const resetTriggeredRef = useRef(false);
|
||||||
@@ -142,8 +142,89 @@ const Board = () => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleNewerPostsButtonClick = () => {
|
||||||
|
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });
|
||||||
|
setTimeout(() => {
|
||||||
|
reset();
|
||||||
|
}, 300);
|
||||||
|
};
|
||||||
|
|
||||||
|
// suggest the user to change time filter if there aren't enough posts
|
||||||
|
const { feed: weeklyFeed } = useFeed({
|
||||||
|
subplebbitAddresses,
|
||||||
|
sortType,
|
||||||
|
newerThan: 60 * 60 * 24 * 7,
|
||||||
|
filter: hideThreadsWithoutImages ? threadsWithoutImagesFilter : undefined,
|
||||||
|
});
|
||||||
|
const { feed: monthlyFeed } = useFeed({
|
||||||
|
subplebbitAddresses,
|
||||||
|
sortType,
|
||||||
|
newerThan: 60 * 60 * 24 * 30,
|
||||||
|
filter: hideThreadsWithoutImages ? threadsWithoutImagesFilter : undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [showMorePostsSuggestion, setShowMorePostsSuggestion] = useState(false);
|
||||||
|
useEffect(() => {
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
setShowMorePostsSuggestion(true);
|
||||||
|
}, 5000);
|
||||||
|
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const params = useParams();
|
||||||
|
const currentTimeFilterName = params?.timeFilterName || timeFilterName;
|
||||||
|
|
||||||
const Footer = () => {
|
const Footer = () => {
|
||||||
return <div className={styles.footer}>{loadingString}</div>;
|
let footerContent;
|
||||||
|
if (feed.length === 0) {
|
||||||
|
footerContent = t('no_posts');
|
||||||
|
}
|
||||||
|
if (hasMore || (subplebbitAddresses && subplebbitAddresses.length === 0)) {
|
||||||
|
footerContent = (
|
||||||
|
<>
|
||||||
|
{subplebbitAddressesWithNewerPosts.length > 0 ? (
|
||||||
|
<div className={styles.stateString}>
|
||||||
|
<Trans
|
||||||
|
i18nKey='newer_posts_available'
|
||||||
|
components={{
|
||||||
|
1: <span onClick={handleNewerPostsButtonClick} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
(isInAllView || isInSubscriptionsView) &&
|
||||||
|
showMorePostsSuggestion &&
|
||||||
|
monthlyFeed.length > feed.length &&
|
||||||
|
(weeklyFeed.length > feed.length ? (
|
||||||
|
<div className={styles.stateString}>
|
||||||
|
<Trans
|
||||||
|
i18nKey='more_posts_last_week'
|
||||||
|
values={{ currentTimeFilterName }}
|
||||||
|
components={{
|
||||||
|
1: <Link to={(isInAllView ? '/p/all' : isInSubscriptionsView ? '/p/subs' : `/p/${subplebbitAddress}`) + '/1w'} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className={styles.stateString}>
|
||||||
|
<Trans
|
||||||
|
i18nKey='more_posts_last_month'
|
||||||
|
values={{ currentTimeFilterName }}
|
||||||
|
components={{
|
||||||
|
1: <Link to={(isInAllView ? '/p/all' : isInSubscriptionsView ? '/p/subs' : `/p/${subplebbitAddress}`) + '/1m'} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
<div className={styles.stateString}>
|
||||||
|
<LoadingEllipsis string={loadingStateString} />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <div className={styles.footer}>{footerContent}</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// save the last Virtuoso state to restore it when navigating back
|
// save the last Virtuoso state to restore it when navigating back
|
||||||
|
|||||||
Reference in New Issue
Block a user