mirror of
https://github.com/plebbit/seedit.git
synced 2026-02-06 12:01:04 -05:00
fix(home): auto time filter didn't show posts from last visit
This commit is contained in:
64
src/app.tsx
64
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 <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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
22
src/hooks/use-redirect-to-default-sort.ts
Normal file
22
src/hooks/use-redirect-to-default-sort.ts
Normal 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;
|
||||
@@ -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 };
|
||||
};
|
||||
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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';
|
||||
|
||||
Reference in New Issue
Block a user