This commit is contained in:
plebeius.eth
2023-12-15 15:10:40 +01:00
10 changed files with 159 additions and 15 deletions

View File

@@ -109,11 +109,11 @@ const AuthorSidebar = () => {
<>
<div>
<span className={styles.karma}>{postScore}</span> post karma
{isAuthorPage && postScore && ' (estimated)'}
{isAuthorPage && postScore ? ' (estimated)' : null}
</div>
<div>
<span className={styles.karma}>{replyScore}</span> comment karma
{isAuthorPage && replyScore && ' (estimated)'}
{isAuthorPage && replyScore ? ' (estimated)' : null}
</div>
</>
) : null}

View File

@@ -313,7 +313,7 @@ const Header = () => {
<div className={`${styles.tabs} ${hasFewTabs ? styles.fewTabs : ''}`}>
<ul className={styles.tabMenu}>
<HeaderTabs />
{(isSubplebbitPage || isSubplebbitSubmitPage || isPostPage || isProfilePage || isAuthorPage) && <AboutButton />}
{(isSubplebbitPage || isSubplebbitSubmitPage || isPostPage) && <AboutButton />}
</ul>
</div>
)}

View File

@@ -0,0 +1 @@
export {default} from './sort-dropdown';

View File

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

View File

@@ -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<HTMLDivElement>(null);
const dropdownChoicesRef = useRef<HTMLDivElement>(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 (
<div className={styles.content}>
<span className={styles.dropdownTitle}>sorted by: </span>
<div
className={styles.dropdown}
onClick={() => {
setIsDropdownOpen(!isDropdownOpen);
}}
ref={dropdownRef}
>
<span className={styles.selected}>new</span>
</div>
<div className={`${styles.dropChoices} ${dropChoicesClass}`} ref={dropdownChoicesRef}>
{sortLabels.map((filter: string, index: number) => (
<div key={index} className={styles.filter} onClick={() => setIsDropdownOpen(false)}>
{filter}
</div>
))}
</div>
</div>
);
};
export default SortDropdown;

View File

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

View File

@@ -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 (
<div className={styles.content}>
<div className={styles.sidebar}>
<div className={isMobile ? styles.sidebarMobile : styles.sidebarDesktop}>
<AuthorSidebar />
</div>
<SortDropdown />
{authorComments?.length === 0 && !hasMore && <div className={styles.noPosts}>No posts found</div>}
<Virtuoso
increaseViewportBy={{ bottom: 1200, top: 600 }}

View File

@@ -1,4 +1,4 @@
import { useEffect, useRef } from 'react';
import { useEffect, useRef, useState } from 'react';
import { useParams } from 'react-router-dom';
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
import { useAccount, useFeed } from '@plebbit/plebbit-react-hooks';
@@ -16,20 +16,33 @@ const lastVirtuosoStates: { [key: string]: StateSnapshot } = {};
const NoPosts = () => 'no posts';
const Home = () => {
const { t } = useTranslation();
const account = useAccount();
const defaultSubplebbitAddresses = useDefaultSubplebbitAddresses();
const subplebbitAddresses = defaultSubplebbitAddresses.concat(account?.subscriptions || []);
const [subplebbitAddresses, setSubplebbitAddresses] = useState<string[] | undefined>(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 = (
<div className={styles.stateString}>
{subplebbitAddresses.length === 0 ? (
{subplebbitAddresses && subplebbitAddresses.length === 0 ? (
<div>
<Trans
i18nKey='no_communities_found'
@@ -52,7 +65,7 @@ const Home = () => {
if (feed?.length === 0) {
Footer = NoPosts;
}
if (hasMore || subplebbitAddresses.length === 0) {
if (hasMore || subplebbitAddresses && subplebbitAddresses.length === 0) {
Footer = () => loadingString;
}

View File

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

View File

@@ -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 (
<div className={styles.content}>
<div className={styles.sidebar}>
<div className={isMobile ? styles.sidebarMobile : styles.sidebarDesktop}>
<AuthorSidebar />
</div>
<SortDropdown />
{account && !accountComments.length ? (
'no posts'
) : (