mirror of
https://github.com/plebbit/seedit.git
synced 2026-02-15 08:21:19 -05:00
feat(inbox): add filters for "comment replies", "post replies", unread
This commit is contained in:
@@ -93,6 +93,9 @@ function App() {
|
||||
<Route path='/u/:authorAddress/c/:commentCid/about' element={<About />} />
|
||||
|
||||
<Route path='/inbox' element={<Inbox />} />
|
||||
<Route path='inbox/unread' element={<Inbox />} />
|
||||
<Route path='inbox/commentreplies' element={<Inbox />} />
|
||||
<Route path='inbox/postreplies' element={<Inbox />} />
|
||||
</Route>
|
||||
</Route>
|
||||
</Routes>
|
||||
|
||||
@@ -208,35 +208,38 @@ const HeaderTitle = ({ title, shortAddress }: { title: string; shortAddress: str
|
||||
const { t } = useTranslation();
|
||||
const params = useParams();
|
||||
const location = useLocation();
|
||||
const isAuthor = isAuthorView(location.pathname);
|
||||
const isPost = isPostView(location.pathname, params);
|
||||
const isProfile = isProfileView(location.pathname);
|
||||
const isSubplebbit = isSubplebbitView(location.pathname, params);
|
||||
const isSubmit = isSubmitView(location.pathname);
|
||||
const isSubplebbitSubmit = isSubplebbitSubmitView(location.pathname, params);
|
||||
const isSettings = isSettingsView(location.pathname);
|
||||
const isAuthorPage = isAuthorView(location.pathname);
|
||||
const isInboxPage = isInboxView(location.pathname);
|
||||
const isPostPage = isPostView(location.pathname, params);
|
||||
const isProfilePage = isProfileView(location.pathname);
|
||||
const isSubplebbitPage = isSubplebbitView(location.pathname, params);
|
||||
const isSubmitPage = isSubmitView(location.pathname);
|
||||
const isSubplebbitSubmitPage = isSubplebbitSubmitView(location.pathname, params);
|
||||
const isSettingsPage = isSettingsView(location.pathname);
|
||||
|
||||
const subplebbitTitle = <Link to={`/p/${params.subplebbitAddress}`}>{title || shortAddress}</Link>;
|
||||
const submitTitle = <span className={styles.submitTitle}>{t('submit')}</span>;
|
||||
const profileTitle = <Link to='/profile'>{account?.author?.shortAddress}</Link>;
|
||||
const authorTitle = <Link to={`/u/${params.authorAddress}/c/${params.commentCid}`}>{params.authorAddress && getShortAddress(params.authorAddress)}</Link>;
|
||||
|
||||
if (isSubplebbitSubmit) {
|
||||
if (isSubplebbitSubmitPage) {
|
||||
return (
|
||||
<>
|
||||
{subplebbitTitle}: {submitTitle}
|
||||
</>
|
||||
);
|
||||
} else if (isPost || isSubplebbit) {
|
||||
} else if (isPostPage || isSubplebbitPage) {
|
||||
return subplebbitTitle;
|
||||
} else if (isSubmit) {
|
||||
} else if (isSubmitPage) {
|
||||
return submitTitle;
|
||||
} else if (isSettings) {
|
||||
} else if (isSettingsPage) {
|
||||
return t('preferences');
|
||||
} else if (isProfile) {
|
||||
} else if (isProfilePage) {
|
||||
return profileTitle;
|
||||
} else if (isAuthor) {
|
||||
} else if (isAuthorPage) {
|
||||
return authorTitle;
|
||||
} else if (isInboxPage) {
|
||||
return 'inbox';
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -58,6 +58,18 @@ export const isInboxView = (pathname: string): boolean => {
|
||||
return pathname.startsWith('/inbox');
|
||||
};
|
||||
|
||||
export const isInboxCommentRepliesView = (pathname: string): boolean => {
|
||||
return pathname === `/inbox/commentreplies`;
|
||||
};
|
||||
|
||||
export const isInboxPostRepliesView = (pathname: string): boolean => {
|
||||
return pathname === `/inbox/postreplies`;
|
||||
};
|
||||
|
||||
export const isInboxUnreadView = (pathname: string): boolean => {
|
||||
return pathname === `/inbox/unread`;
|
||||
};
|
||||
|
||||
export const isPendingView = (pathname: string, params: ParamsType): boolean => {
|
||||
return pathname === `/profile/${params.accountCommentIndex}`;
|
||||
};
|
||||
|
||||
@@ -4,8 +4,44 @@
|
||||
|
||||
.markAsReadButton {
|
||||
margin-bottom: 5px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.notification {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.markAllAsReadButton {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.inboxTabs {
|
||||
border-bottom: 1px dotted gray;
|
||||
padding: 5px 10px;
|
||||
margin-left: 5px;
|
||||
overflow: hidden;
|
||||
font-size: larger;
|
||||
display: inline-block;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.inboxTabs a span {
|
||||
display: inline;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.inboxTabs a {
|
||||
text-decoration: none;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.separator {
|
||||
color: var(--gray);
|
||||
margin: 0px .7ex 0px .7ex;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.selected {
|
||||
color: var(--green) !important;
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -1,18 +1,71 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useEffect, useMemo, useRef } from 'react';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { StateSnapshot, Virtuoso, VirtuosoHandle } from 'react-virtuoso';
|
||||
import { useAccount, useNotifications } from '@plebbit/plebbit-react-hooks';
|
||||
import styles from './inbox.module.css';
|
||||
import Reply from '../../components/reply/reply';
|
||||
import { isInboxCommentRepliesView, isInboxPostRepliesView, isInboxUnreadView } from '../../lib/utils/view-utils';
|
||||
|
||||
const lastVirtuosoStates: { [key: string]: StateSnapshot } = {};
|
||||
|
||||
const InboxTabs = () => {
|
||||
const location = useLocation();
|
||||
const isInboxCommentRepliesPage = isInboxCommentRepliesView(location.pathname);
|
||||
const isInboxPostRepliesPage = isInboxPostRepliesView(location.pathname);
|
||||
const isInboxUnreadPage = isInboxUnreadView(location.pathname);
|
||||
const isAllPage = !isInboxCommentRepliesPage && !isInboxPostRepliesPage && !isInboxUnreadPage;
|
||||
|
||||
return (
|
||||
<div className={styles.inboxTabs}>
|
||||
<Link to='/inbox' className={isAllPage ? styles.selected : styles.choice}>
|
||||
all
|
||||
</Link>
|
||||
<span className={styles.separator}>|</span>
|
||||
<Link to='/inbox/unread' className={isInboxUnreadPage ? styles.selected : styles.choice}>
|
||||
unread
|
||||
</Link>
|
||||
<span className={styles.separator}>|</span>
|
||||
<Link to='/inbox/commentreplies' className={isInboxCommentRepliesPage ? styles.selected : styles.choice}>
|
||||
comment replies
|
||||
</Link>
|
||||
<span className={styles.separator}>|</span>
|
||||
<Link to='/inbox/postreplies' className={isInboxPostRepliesPage ? styles.selected : styles.choice}>
|
||||
post replies
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const Inbox = () => {
|
||||
const account = useAccount();
|
||||
const { unreadNotificationCount } = account || {};
|
||||
const { notifications, markAsRead } = useNotifications();
|
||||
|
||||
const virtuosoRef = useRef<VirtuosoHandle | null>(null);
|
||||
const location = useLocation();
|
||||
const isInboxCommentRepliesPage = isInboxCommentRepliesView(location.pathname);
|
||||
const isInboxPostRepliesPage = isInboxPostRepliesView(location.pathname);
|
||||
const isInboxUnreadPage = isInboxUnreadView(location.pathname);
|
||||
|
||||
// get comments for unread/commentReplies/postReplies pages
|
||||
const repliesToUserReplies = useMemo(() => notifications?.filter((comment) => comment.parentCid !== comment.postCid) || [], [notifications]);
|
||||
const repliesToUserPosts = useMemo(() => notifications?.filter((comment) => comment.parentCid === comment.postCid) || [], [notifications]);
|
||||
const unreadNotifications = useMemo(() => notifications?.filter((comment) => !comment.markedAsRead) || [], [notifications]);
|
||||
|
||||
const comments = useMemo(() => {
|
||||
if (isInboxCommentRepliesPage) {
|
||||
return repliesToUserReplies;
|
||||
} else if (isInboxPostRepliesPage) {
|
||||
return repliesToUserPosts;
|
||||
} else if (isInboxUnreadPage) {
|
||||
return unreadNotifications;
|
||||
} else {
|
||||
return notifications;
|
||||
}
|
||||
}, [notifications, repliesToUserReplies, repliesToUserPosts, unreadNotifications, isInboxCommentRepliesPage, isInboxPostRepliesPage, isInboxUnreadPage]);
|
||||
|
||||
// save last virtuoso state on each scroll
|
||||
const virtuosoRef = useRef<VirtuosoHandle | null>(null);
|
||||
const lastVirtuosoState = lastVirtuosoStates?.[unreadNotificationCount];
|
||||
useEffect(() => {
|
||||
const setLastVirtuosoState = () =>
|
||||
virtuosoRef.current?.getState((snapshot) => {
|
||||
@@ -26,21 +79,24 @@ const Inbox = () => {
|
||||
return () => window.removeEventListener('scroll', setLastVirtuosoState);
|
||||
}, [unreadNotificationCount]);
|
||||
|
||||
const lastVirtuosoState = lastVirtuosoStates?.[unreadNotificationCount];
|
||||
|
||||
if (account && !notifications.length) {
|
||||
return 'empty';
|
||||
}
|
||||
|
||||
console.log(comments);
|
||||
|
||||
return (
|
||||
<div className={styles.content}>
|
||||
<button onClick={markAsRead} disabled={!unreadNotificationCount} className={styles.markAsReadButton}>
|
||||
mark all as read
|
||||
</button>
|
||||
<InboxTabs />
|
||||
<div className={styles.markAllAsReadButton}>
|
||||
<button onClick={markAsRead} disabled={!unreadNotificationCount} className={styles.markAsReadButton}>
|
||||
mark all as read
|
||||
</button>
|
||||
</div>
|
||||
<Virtuoso
|
||||
increaseViewportBy={{ bottom: 1200, top: 600 }}
|
||||
totalCount={notifications?.length || 0}
|
||||
data={notifications}
|
||||
data={comments}
|
||||
itemContent={(index, notification) => (
|
||||
<div className={styles.notification}>
|
||||
<Reply index={index} isSingle={true} reply={notification} isNotification={true} />
|
||||
|
||||
@@ -86,13 +86,11 @@ const Profile = () => {
|
||||
const { comments: upvotedComments } = useComments({ commentCids: upvotedCommentCids });
|
||||
const { comments: downvotedComments } = useComments({ commentCids: downvotedCommentCids });
|
||||
|
||||
// sort dropdown
|
||||
const [sortType, setSortType] = useState('new');
|
||||
const handleSortChange = (newSortType: string) => {
|
||||
setSortType(newSortType);
|
||||
};
|
||||
|
||||
// Define comments with useMemo to avoid redefinition on every render
|
||||
const comments = useMemo(() => {
|
||||
if (isUpvotedPage) {
|
||||
return upvotedComments;
|
||||
@@ -107,7 +105,6 @@ const Profile = () => {
|
||||
}
|
||||
}, [isUpvotedPage, isDownvotedPage, isCommentsPage, isSubmittedPage, upvotedComments, downvotedComments, replyComments, postComments, accountComments]);
|
||||
|
||||
// sort comments by sortType
|
||||
const virtuosoData = useMemo(() => {
|
||||
let sortedData = [...comments];
|
||||
if (sortType === 'new') {
|
||||
|
||||
Reference in New Issue
Block a user