fix(home): auto time filter didn't show posts from last visit

This commit is contained in:
Tom (plebeius.eth)
2024-10-27 15:28:32 +01:00
parent c19011c07d
commit aaa34b797b
8 changed files with 114 additions and 55 deletions

View File

@@ -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 <NotFound />;
}
@@ -77,32 +84,9 @@ const App = () => {
<div className={`${styles.app} ${theme}`}>
<Routes>
<Route element={globalLayout}>
<Route element={feedLayout}>
<Route element={<CheckRouteParams />}>
<Route path='/:sortType?/:timeFilterName?' element={<Home />} />
<Route path='/p/all/:sortType?/:timeFilterName?' element={<All />} />
<Route path='/p/:subplebbitAddress/:sortType?/:timeFilterName?' element={<Subplebbit />} />
<Route path='/profile/:accountCommentIndex' element={<PendingPost />} />
<Route path='/profile' element={<Profile />}>
<Route index element={<Profile.Overview />} />
<Route path='upvoted' element={<Profile.VotedComments voteType={1} />} />
<Route path='downvoted' element={<Profile.VotedComments voteType={-1} />} />
<Route path='hidden' element={<Profile.HiddenComments />} />
<Route path='comments' element={<Profile.Comments />} />
<Route path='submitted' element={<Profile.Submitted />} />
</Route>
<Route path='/u/:authorAddress/c/:commentCid?/:sortType?/:timeFilterName?' element={<Author />} />
<Route path='/u/:authorAddress/c/:commentCid?/comments/:sortType?/:timeFilterName?' element={<Author />} />
<Route path='/u/:authorAddress/c/:commentCid?/submitted/:sortType?/:timeFilterName?' element={<Author />} />
</Route>
</Route>
<Route element={pagesLayout}>
<Route path='/about' element={<About />} />
<Route path='/about/index:hash' element={<About />} />
<Route path='/submit' element={<SubmitPage />} />
<Route path='/sidebar' element={<SidebarView />} />
@@ -141,6 +125,30 @@ const App = () => {
<Route path='*' element={<NotFound />} />
</Route>
<Route element={feedLayout}>
<Route element={<CheckRouteParams />}>
<Route path='/:sortType?/:timeFilterName?' element={<Home />} />
<Route path='/p/all/:sortType?/:timeFilterName?' element={<All />} />
<Route path='/p/:subplebbitAddress/:sortType?/:timeFilterName?' element={<Subplebbit />} />
<Route path='/profile/:accountCommentIndex' element={<PendingPost />} />
<Route path='/profile' element={<Profile />}>
<Route index element={<Profile.Overview />} />
<Route path='upvoted' element={<Profile.VotedComments voteType={1} />} />
<Route path='downvoted' element={<Profile.VotedComments voteType={-1} />} />
<Route path='hidden' element={<Profile.HiddenComments />} />
<Route path='comments' element={<Profile.Comments />} />
<Route path='submitted' element={<Profile.Submitted />} />
</Route>
<Route path='/u/:authorAddress/c/:commentCid?/:sortType?/:timeFilterName?' element={<Author />} />
<Route path='/u/:authorAddress/c/:commentCid?/comments/:sortType?/:timeFilterName?' element={<Author />} />
<Route path='/u/:authorAddress/c/:commentCid?/submitted/:sortType?/:timeFilterName?' element={<Author />} />
</Route>
</Route>
</Route>
</Routes>
</div>

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 = () => {
<div className={styles.dropdown} ref={filterDropdownRef} onClick={toggleFilterDropdown}>
<span className={styles.selectedTitle}>{selectedTimeFilter}</span>
<div className={`${styles.dropChoices} ${styles.filterDropChoices} ${filterDropdownClass}`} ref={filterdropdownItemsRef}>
{timeFilterNames.map((timeFilterName, index) => (
{timeFilterNames.slice(0, -1).map((timeFilterName, index) => (
<Link to={getTimeFilterLink(timeFilterName)} key={index} className={styles.dropdownItem}>
{timeFilterNames[index]}
</Link>
@@ -172,13 +164,13 @@ const TopBar = () => {
<div className={styles.srList}>
<ul className={styles.srBar}>
<li>
<Link to={homeLink} className={`${styles.homeButton} ${homeButtonClass}`}>
<Link to='/' className={`${styles.homeButton} ${homeButtonClass}`}>
{t('home')}
</Link>
</li>
<li>
<span className={styles.separator}>-</span>
<Link to={allLink} className={isinAllView ? styles.selected : styles.choice}>
<Link to='/p/all' className={isinAllView ? styles.selected : styles.choice}>
{t('all')}
</Link>
</li>

View File

@@ -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;

View File

@@ -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 };
};

View File

@@ -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 => {

View File

@@ -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';