From aaa34b797bb4f24a6e88b4880b8bbab11047e260 Mon Sep 17 00:00:00 2001 From: "Tom (plebeius.eth)" Date: Sun, 27 Oct 2024 15:28:32 +0100 Subject: [PATCH] fix(home): auto time filter didn't show posts from last visit --- src/app.tsx | 64 +++++++++++++---------- src/components/header/header.tsx | 4 +- src/components/sidebar/sidebar.tsx | 2 +- src/components/topbar/topbar.tsx | 16 ++---- src/hooks/use-redirect-to-default-sort.ts | 22 ++++++++ src/hooks/use-time-filter.ts | 43 ++++++++++++--- src/lib/utils/view-utils.ts | 16 ++++-- src/views/home/home.tsx | 2 + 8 files changed, 114 insertions(+), 55 deletions(-) create mode 100644 src/hooks/use-redirect-to-default-sort.ts diff --git a/src/app.tsx b/src/app.tsx index 5d97983f..153e0782 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,5 +1,5 @@ import { useEffect } from 'react'; -import { Outlet, Route, Routes, useParams } from 'react-router-dom'; +import { Outlet, Route, Routes, useLocation, useParams } from 'react-router-dom'; import useTheme from './hooks/use-theme'; import useTimeFilter from './hooks/use-time-filter'; import styles from './app.module.css'; @@ -23,6 +23,7 @@ import ChallengeModal from './components/challenge-modal'; import Header from './components/header'; import StickyHeader from './components/sticky-header'; import TopBar from './components/topbar'; +import { isAboutView } from './lib/utils/view-utils'; export const sortTypes = ['hot', 'new', 'active', 'controversialAll', 'topAll']; @@ -31,10 +32,16 @@ const CheckRouteParams = () => { const { timeFilterNames, lastVisitTimeFilterName } = useTimeFilter(); const isValidAccountCommentIndex = !accountCommentIndex || (!isNaN(parseInt(accountCommentIndex)) && parseInt(accountCommentIndex) >= 0); const isSortTypeValid = !sortType || sortTypes.includes(sortType); - const isTimeFilterNameValid = !timeFilterName || timeFilterNames.includes(timeFilterName as any) || timeFilterName === lastVisitTimeFilterName; - const isAccountCommentIndexValid = !accountCommentIndex || !isNaN(parseInt(accountCommentIndex)); - if (!isValidAccountCommentIndex || !isSortTypeValid || !isTimeFilterNameValid || !isAccountCommentIndexValid) { + const isDynamicTimeFilter = (filter: string) => /^\d+[dwmy]$/.test(filter); + const isTimeFilterNameValid = + !timeFilterName || timeFilterNames.includes(timeFilterName as any) || timeFilterName === lastVisitTimeFilterName || isDynamicTimeFilter(timeFilterName); + + const isAccountCommentIndexValid = !accountCommentIndex || !isNaN(parseInt(accountCommentIndex)); + const location = useLocation(); + const isInAboutView = isAboutView(location.pathname); + + if (!isValidAccountCommentIndex || (!isSortTypeValid && !isInAboutView) || !isTimeFilterNameValid || !isAccountCommentIndexValid) { return ; } @@ -77,32 +84,9 @@ const App = () => {
- - }> - } /> - - } /> - - } /> - - } /> - - }> - } /> - } /> - } /> - } /> - } /> - } /> - - - } /> - } /> - } /> - - } /> + } /> } /> } /> @@ -141,6 +125,30 @@ const App = () => { } /> + + }> + } /> + + } /> + + } /> + + } /> + + }> + } /> + } /> + } /> + } /> + } /> + } /> + + + } /> + } /> + } /> + +
diff --git a/src/components/header/header.tsx b/src/components/header/header.tsx index e11b1261..4ef73612 100644 --- a/src/components/header/header.tsx +++ b/src/components/header/header.tsx @@ -254,7 +254,7 @@ const HeaderTabs = () => { const isInAllView = isAllView(location.pathname); const isInAuthorView = isAuthorView(location.pathname); const isInHomeSidebarView = isHomeSidebarView(location.pathname); - const isInHomeView = isHomeView(location.pathname, params); + const isInHomeView = isHomeView(location.pathname); const isInInboxView = isInboxView(location.pathname); const isInPendingView = isPendingView(location.pathname, params); const isInPostView = isPostView(location.pathname, params); @@ -359,7 +359,7 @@ const Header = () => { const isInAllSidebarView = isAllSidebarView(location.pathname); const isInAllView = isAllView(location.pathname); const isInAuthorView = isAuthorView(location.pathname); - const isInHomeView = isHomeView(location.pathname, params); + const isInHomeView = isHomeView(location.pathname); const isInHomeSidebarView = isHomeSidebarView(location.pathname); const isInInboxView = isInboxView(location.pathname); const isInPostView = isPostView(location.pathname, params); diff --git a/src/components/sidebar/sidebar.tsx b/src/components/sidebar/sidebar.tsx index 8153d659..73d9dee1 100644 --- a/src/components/sidebar/sidebar.tsx +++ b/src/components/sidebar/sidebar.tsx @@ -159,7 +159,7 @@ const Sidebar = ({ comment, isSubCreatedButNotYetPublished, settings, subplebbit const isInAllView = isAllView(location.pathname); const isInHomeSidebarView = isHomeSidebarView(location.pathname); const isInAboutView = isAboutView(location.pathname); - const isInHomeView = isHomeView(location.pathname, params); + const isInHomeView = isHomeView(location.pathname); const isInPendingView = isPendingView(location.pathname, params); const isInPostView = isPostView(location.pathname, params); const isInSubplebbitsView = isSubplebbitsView(location.pathname); diff --git a/src/components/topbar/topbar.tsx b/src/components/topbar/topbar.tsx index e4cda04f..882a8743 100644 --- a/src/components/topbar/topbar.tsx +++ b/src/components/topbar/topbar.tsx @@ -19,7 +19,7 @@ const TopBar = () => { const params = useParams(); const subscriptions = account?.subscriptions; const isinAllView = isAllView(location.pathname); - const isInHomeView = isHomeView(location.pathname, params); + const isInHomeView = isHomeView(location.pathname); const isInSubplebbitView = isSubplebbitView(location.pathname, params); const homeButtonClass = isInHomeView ? styles.selected : styles.choice; @@ -93,14 +93,6 @@ const TopBar = () => { }; }, [handleClickOutside]); - let homeLink = '/'; - let allLink = '/p/all'; - - if (timeFilterName && !isInSubplebbitView) { - homeLink += `${selectedSortType}/${timeFilterName}`; - allLink += `/${selectedSortType}/${timeFilterName}`; - } - const isConnectedToRpc = !!account?.plebbitOptions.plebbitRpcClientsOptions; const navigate = useNavigate(); const handleCreateCommunity = () => { @@ -162,7 +154,7 @@ const TopBar = () => {
{selectedTimeFilter}
- {timeFilterNames.map((timeFilterName, index) => ( + {timeFilterNames.slice(0, -1).map((timeFilterName, index) => ( {timeFilterNames[index]} @@ -172,13 +164,13 @@ const TopBar = () => {
  • - + {t('home')}
  • - - + {t('all')}
  • diff --git a/src/hooks/use-redirect-to-default-sort.ts b/src/hooks/use-redirect-to-default-sort.ts new file mode 100644 index 00000000..c0acb70e --- /dev/null +++ b/src/hooks/use-redirect-to-default-sort.ts @@ -0,0 +1,22 @@ +import { useEffect } from 'react'; +import { useLocation, useNavigate } from 'react-router-dom'; + +const DEFAULT_SORT = 'hot'; + +const useRedirectToDefaultSort = () => { + const location = useLocation(); + const navigate = useNavigate(); + + useEffect(() => { + const path = location.pathname; + const parts = path.split('/').filter(Boolean); + + // If we're at the root or the path doesn't start with a sort type + if (path === '/' || (parts.length > 0 && !['hot', 'new', 'active', 'controversialAll', 'topAll'].includes(parts[0]))) { + const newPath = path === '/' ? `/${DEFAULT_SORT}` : `/${DEFAULT_SORT}${path}`; + navigate(newPath, { replace: true }); + } + }, [location.pathname, navigate]); +}; + +export default useRedirectToDefaultSort; diff --git a/src/hooks/use-time-filter.ts b/src/hooks/use-time-filter.ts index d328c9e4..0fbe709a 100644 --- a/src/hooks/use-time-filter.ts +++ b/src/hooks/use-time-filter.ts @@ -49,16 +49,45 @@ const useTimeFilter = () => { let timeFilterName = params.timeFilterName; // the default time filter is the last visit time filter if (!timeFilterName) { - if (isInSubplebbitView) { - timeFilterName = 'all'; - } else { - timeFilterName = lastVisitTimeFilterName; + timeFilterName = isInSubplebbitView ? 'all' : lastVisitTimeFilterName; + } + + let timeFilterSeconds: number | undefined; + + if (timeFilterName === 'all') { + timeFilterSeconds = undefined; + } else if (timeFilterName && timeFilterName in timeFilterNamesToSeconds) { + timeFilterSeconds = timeFilterNamesToSeconds[timeFilterName as keyof typeof timeFilterNamesToSeconds]; + } else if (timeFilterName) { + // Handle dynamic time filters (e.g., "3d", "2w") + const match = timeFilterName.match(/^(\d+)([dwmy])$/); + if (match) { + const [, value, unit] = match; + const numValue = parseInt(value, 10); + switch (unit) { + case 'd': + timeFilterSeconds = numValue * 24 * 60 * 60; + break; + case 'w': + timeFilterSeconds = numValue * 7 * 24 * 60 * 60; + break; + case 'm': + timeFilterSeconds = numValue * 30 * 24 * 60 * 60; + break; + case 'y': + timeFilterSeconds = numValue * 365 * 24 * 60 * 60; + break; + } } } - assert(!timeFilterName || typeof timeFilterName === 'string', `useTimeFilter timeFilterName argument '${timeFilterName}' not a string`); - const timeFilterSeconds = timeFilterNamesToSeconds[timeFilterName as keyof typeof timeFilterNamesToSeconds]; - assert(!timeFilterName || timeFilterName === 'all' || timeFilterSeconds !== undefined, `useTimeFilter no filter for timeFilterName '${timeFilterName}'`); + // If we still don't have a valid timeFilterSeconds, use the default (24h) + if (timeFilterSeconds === undefined && timeFilterName !== 'all') { + timeFilterSeconds = timeFilterNamesToSeconds['24h']; + } + + assert(timeFilterName === 'all' || timeFilterSeconds !== undefined, `useTimeFilter no filter for timeFilterName '${timeFilterName}'`); + return { timeFilterSeconds, timeFilterNames, timeFilterName, lastVisitTimeFilterName }; }; diff --git a/src/lib/utils/view-utils.ts b/src/lib/utils/view-utils.ts index 30595954..34d0e3ac 100644 --- a/src/lib/utils/view-utils.ts +++ b/src/lib/utils/view-utils.ts @@ -1,5 +1,3 @@ -import { timeFilterNames } from '../../hooks/use-time-filter'; - export type ParamsType = { accountCommentIndex?: string; authorAddress?: string; @@ -32,7 +30,7 @@ export const getSidebarLink = (pathname: string, params: ParamsType): string => }; export const isAboutView = (pathname: string): boolean => { - return pathname === '/about'; + return pathname.startsWith('/about'); }; export const isSidebarView = (pathname: string): boolean => { @@ -63,8 +61,16 @@ export const isCreateSubplebbitView = (pathname: string): boolean => { return pathname === '/communities/create'; }; -export const isHomeView = (pathname: string, params: ParamsType): boolean => { - return pathname === '/' || sortTypes.includes(pathname) || (timeFilterNames.includes(params.timeFilterName || '') && !pathname.startsWith('/p/')); +export const isHomeView = (pathname: string): boolean => { + if (pathname === '/') return true; + + const pathParts = pathname.split('/'); + if (pathParts.length >= 2) { + const potentialSortType = '/' + pathParts[1]; + return sortTypes.includes(potentialSortType); + } + + return false; }; export const isHomeSidebarView = (pathname: string): boolean => { diff --git a/src/views/home/home.tsx b/src/views/home/home.tsx index c40df127..c04eac82 100644 --- a/src/views/home/home.tsx +++ b/src/views/home/home.tsx @@ -10,11 +10,13 @@ import Sidebar from '../../components/sidebar'; import { useDefaultAndSubscriptionsSubplebbitAddresses } from '../../hooks/use-default-subplebbits'; import useFeedStateString from '../../hooks/use-feed-state-string'; import useTimeFilter from '../../hooks/use-time-filter'; +import useRedirectToDefaultSort from '../../hooks/use-redirect-to-default-sort'; const lastVirtuosoStates: { [key: string]: StateSnapshot } = {}; const Home = () => { const { t } = useTranslation(); + useRedirectToDefaultSort(); const subplebbitAddresses = useDefaultAndSubscriptionsSubplebbitAddresses(); const params = useParams<{ sortType?: string; timeFilterName?: string }>(); const sortType = params?.sortType || 'hot';