From ffcfe37ce6ddb90e53dba7499d2007a57cc7e70c Mon Sep 17 00:00:00 2001 From: "plebeius.eth" Date: Fri, 22 Dec 2023 16:05:51 +0100 Subject: [PATCH] feat(inbox): add filters for "comment replies", "post replies", unread --- src/app.tsx | 3 ++ src/components/header/header.tsx | 29 +++++++------ src/lib/utils/view-utils.ts | 12 ++++++ src/views/inbox/inbox.module.css | 36 ++++++++++++++++ src/views/inbox/inbox.tsx | 72 ++++++++++++++++++++++++++++---- src/views/profile/profile.tsx | 3 -- 6 files changed, 131 insertions(+), 24 deletions(-) diff --git a/src/app.tsx b/src/app.tsx index 8a1c1543..98437a39 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -93,6 +93,9 @@ function App() { } /> } /> + } /> + } /> + } /> diff --git a/src/components/header/header.tsx b/src/components/header/header.tsx index 917a8cb6..f1486d84 100644 --- a/src/components/header/header.tsx +++ b/src/components/header/header.tsx @@ -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 = {title || shortAddress}; const submitTitle = {t('submit')}; const profileTitle = {account?.author?.shortAddress}; const authorTitle = {params.authorAddress && getShortAddress(params.authorAddress)}; - 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; }; diff --git a/src/lib/utils/view-utils.ts b/src/lib/utils/view-utils.ts index 0666916a..4f7b8e52 100644 --- a/src/lib/utils/view-utils.ts +++ b/src/lib/utils/view-utils.ts @@ -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}`; }; diff --git a/src/views/inbox/inbox.module.css b/src/views/inbox/inbox.module.css index c4fe836a..cda07f9c 100644 --- a/src/views/inbox/inbox.module.css +++ b/src/views/inbox/inbox.module.css @@ -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; } \ No newline at end of file diff --git a/src/views/inbox/inbox.tsx b/src/views/inbox/inbox.tsx index 69194f3d..b820ecca 100644 --- a/src/views/inbox/inbox.tsx +++ b/src/views/inbox/inbox.tsx @@ -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 ( +
+ + all + + | + + unread + + | + + comment replies + + | + + post replies + +
+ ); +}; + const Inbox = () => { const account = useAccount(); const { unreadNotificationCount } = account || {}; const { notifications, markAsRead } = useNotifications(); - const virtuosoRef = useRef(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(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 (
- + +
+ +
(
diff --git a/src/views/profile/profile.tsx b/src/views/profile/profile.tsx index f9abc279..9fcdc967 100644 --- a/src/views/profile/profile.tsx +++ b/src/views/profile/profile.tsx @@ -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') {