diff --git a/src/components/author-sidebar/author-sidebar.tsx b/src/components/author-sidebar/author-sidebar.tsx index 76be5c02..2a9383e9 100644 --- a/src/components/author-sidebar/author-sidebar.tsx +++ b/src/components/author-sidebar/author-sidebar.tsx @@ -109,11 +109,11 @@ const AuthorSidebar = () => { <>
{postScore} post karma - {isAuthorPage && postScore && ' (estimated)'} + {isAuthorPage && postScore ? ' (estimated)' : null}
{replyScore} comment karma - {isAuthorPage && replyScore && ' (estimated)'} + {isAuthorPage && replyScore ? ' (estimated)' : null}
) : null} diff --git a/src/components/header/header.tsx b/src/components/header/header.tsx index d475220b..1d4413c2 100644 --- a/src/components/header/header.tsx +++ b/src/components/header/header.tsx @@ -313,7 +313,7 @@ const Header = () => {
)} diff --git a/src/components/sort-dropdown/index.ts b/src/components/sort-dropdown/index.ts new file mode 100644 index 00000000..f793bb71 --- /dev/null +++ b/src/components/sort-dropdown/index.ts @@ -0,0 +1 @@ +export {default} from './sort-dropdown'; \ No newline at end of file diff --git a/src/components/sort-dropdown/sort-dropdown.module.css b/src/components/sort-dropdown/sort-dropdown.module.css new file mode 100644 index 00000000..9c9b8495 --- /dev/null +++ b/src/components/sort-dropdown/sort-dropdown.module.css @@ -0,0 +1,59 @@ +.content { + border-bottom: 1px dotted gray; + padding: 5px 10px; + margin: 5px; + margin-top: 0; + overflow: hidden; + font-size: larger; +} + +.dropdownTitle { + color: var(--text) !important; +} + +.dropdown { + display: inline; + position: relative; + cursor: pointer; +} + +.selected { + position: relative; + background: none no-repeat scroll center right; + background-image: url("/public/assets/buttons/droparrowgray.gif"); + padding-right: 21px; + text-decoration: underline; + color: gray; + font-weight: bold; +} + +.dropChoices { + margin-top: 2px; + position: absolute; + left: 90px; + border: 1px solid gray; + z-index: 100; + background-color: var(--background); + white-space: nowrap; + line-height: normal; + margin-top: 3px; +} + +.filter { + cursor: pointer; + padding: 2px 3px 1px 3px; + display: block; + color: var(--text-primary); +} + +.filter:hover { + background-color: var(--background-primary); +} + +.dropChoicesHidden { + display: none; +} + +.dropChoicesVisible { + display: block; +} \ No newline at end of file diff --git a/src/components/sort-dropdown/sort-dropdown.tsx b/src/components/sort-dropdown/sort-dropdown.tsx new file mode 100644 index 00000000..98308192 --- /dev/null +++ b/src/components/sort-dropdown/sort-dropdown.tsx @@ -0,0 +1,53 @@ +import { useCallback, useEffect, useRef, useState } from 'react'; +import styles from './sort-dropdown.module.css'; + +const SortDropdown = () => { + const sortLabels = ['new', 'old']; + + const [isDropdownOpen, setIsDropdownOpen] = useState(false); + const dropdownRef = useRef(null); + const dropdownChoicesRef = useRef(null); + const dropChoicesClass = isDropdownOpen ? styles.dropChoicesVisible : styles.dropChoicesHidden; + + const handleClickOutside = useCallback((event: MouseEvent) => { + if ( + dropdownRef.current && + !dropdownRef.current.contains(event.target as Node) && + dropdownChoicesRef.current && + !dropdownChoicesRef.current.contains(event.target as Node) + ) { + setIsDropdownOpen(false); + } + }, []); + + useEffect(() => { + document.addEventListener('mousedown', handleClickOutside); + return () => { + document.removeEventListener('mousedown', handleClickOutside); + }; + }, [handleClickOutside]); + + return ( +
+ sorted by: +
{ + setIsDropdownOpen(!isDropdownOpen); + }} + ref={dropdownRef} + > + new +
+
+ {sortLabels.map((filter: string, index: number) => ( +
setIsDropdownOpen(false)}> + {filter} +
+ ))} +
+
+ ); +}; + +export default SortDropdown; diff --git a/src/views/author/author.module.css b/src/views/author/author.module.css index b443a519..02a010c8 100644 --- a/src/views/author/author.module.css +++ b/src/views/author/author.module.css @@ -7,7 +7,13 @@ div[data-viewport-type="window"] { } @media (max-width: 768px) { - .sidebar { + .sidebarDesktop { display: none; } + + .sidebarMobile { + width: 300px; + display: inline-block; + padding: 10px 0 0px 5px; + } } \ No newline at end of file diff --git a/src/views/author/author.tsx b/src/views/author/author.tsx index c9792543..17402241 100644 --- a/src/views/author/author.tsx +++ b/src/views/author/author.tsx @@ -8,6 +8,7 @@ import AuthorSidebar from '../../components/author-sidebar'; import LoadingEllipsis from '../../components/loading-ellipsis'; import Post from '../../components/post'; import Reply from '../../components/reply/'; +import SortDropdown from '../../components/sort-dropdown'; const lastVirtuosoStates: { [key: string]: StateSnapshot } = {}; @@ -19,6 +20,7 @@ const Author = () => { const params = useParams(); const isAuthorCommentsPage = isAuthorCommentsView(location.pathname, params); const isAuthorSubmittedPage = isAuthorSubmittedView(location.pathname, params); + const isMobile = window.innerWidth < 768; const { authorComments, lastCommentCid, hasMore, loadMore } = useAuthorComments({ commentCid, authorAddress }); @@ -71,9 +73,10 @@ const Author = () => { return (
-
+
+ {authorComments?.length === 0 && !hasMore &&
No posts found
} 'no posts'; const Home = () => { + const { t } = useTranslation(); const account = useAccount(); const defaultSubplebbitAddresses = useDefaultSubplebbitAddresses(); - const subplebbitAddresses = defaultSubplebbitAddresses.concat(account?.subscriptions || []); + const [subplebbitAddresses, setSubplebbitAddresses] = useState(undefined); + + useEffect(() => { + if (defaultSubplebbitAddresses && account?.subscriptions) { + setSubplebbitAddresses(defaultSubplebbitAddresses.concat(account.subscriptions)); + } + }, [defaultSubplebbitAddresses, account?.subscriptions]); + const params = useParams<{ sortType?: string; timeFilterName?: string }>(); const sortType = params?.sortType || 'hot'; const timeFilterName = (params.timeFilterName as TimeFilterKey) || 'all'; const { timeFilter } = useTimeFilter(sortType, timeFilterName); - const { feed, hasMore, loadMore } = useFeed({ subplebbitAddresses, sortType, filter: timeFilter }); - const { t } = useTranslation(); + + const { feed, hasMore, loadMore } = useFeed({ + subplebbitAddresses: subplebbitAddresses || [], + sortType, + filter: timeFilter + }); + let loadingStateString = useFeedStateString(subplebbitAddresses) || t('loading'); const loadingString = (
- {subplebbitAddresses.length === 0 ? ( + {subplebbitAddresses && subplebbitAddresses.length === 0 ? (
{ if (feed?.length === 0) { Footer = NoPosts; } - if (hasMore || subplebbitAddresses.length === 0) { + if (hasMore || subplebbitAddresses && subplebbitAddresses.length === 0) { Footer = () => loadingString; } diff --git a/src/views/profile/profile.module.css b/src/views/profile/profile.module.css index b443a519..02a010c8 100644 --- a/src/views/profile/profile.module.css +++ b/src/views/profile/profile.module.css @@ -7,7 +7,13 @@ div[data-viewport-type="window"] { } @media (max-width: 768px) { - .sidebar { + .sidebarDesktop { display: none; } + + .sidebarMobile { + width: 300px; + display: inline-block; + padding: 10px 0 0px 5px; + } } \ No newline at end of file diff --git a/src/views/profile/profile.tsx b/src/views/profile/profile.tsx index cbde4485..92f4997d 100644 --- a/src/views/profile/profile.tsx +++ b/src/views/profile/profile.tsx @@ -2,11 +2,12 @@ import { useEffect, useMemo, useRef } from 'react'; import { useLocation, useParams } from 'react-router-dom'; import { StateSnapshot, Virtuoso, VirtuosoHandle } from 'react-virtuoso'; import { useAccount, useAccountComments, useAccountVotes, useComments } from '@plebbit/plebbit-react-hooks'; +import { isDownvotedView, isUpvotedView, isProfileCommentsView, isProfileSubmittedView } from '../../lib/utils/view-utils'; import styles from './profile.module.css'; +import AuthorSidebar from '../../components/author-sidebar'; import Post from '../../components/post'; import Reply from '../../components/reply'; -import AuthorSidebar from '../../components/author-sidebar'; -import { isDownvotedView, isUpvotedView, isProfileCommentsView, isProfileSubmittedView } from '../../lib/utils/view-utils'; +import SortDropdown from '../../components/sort-dropdown'; const lastVirtuosoStates: { [key: string]: StateSnapshot } = {}; @@ -21,6 +22,7 @@ const Profile = () => { const isDownvotedPage = isDownvotedView(location.pathname); const isCommentsPage = isProfileCommentsView(location.pathname); const isSubmittedPage = isProfileSubmittedView(location.pathname); + const isMobile = window.innerWidth < 768; const upvotedCommentCids = useMemo(() => accountVotes?.filter((vote) => vote.vote === 1).map((vote) => vote.commentCid) || [], [accountVotes]); const downvotedCommentCids = useMemo(() => accountVotes?.filter((vote) => vote.vote === -1).map((vote) => vote.commentCid) || [], [accountVotes]); @@ -60,9 +62,10 @@ const Profile = () => { return (
-
+
+ {account && !accountComments.length ? ( 'no posts' ) : (