mirror of
https://github.com/plebbit/seedit.git
synced 2026-04-29 03:25:16 -04:00
Merge branch 'master' of https://github.com/plebbit/seedit
This commit is contained in:
@@ -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}
|
||||
|
||||
@@ -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>
|
||||
)}
|
||||
|
||||
1
src/components/sort-dropdown/index.ts
Normal file
1
src/components/sort-dropdown/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export {default} from './sort-dropdown';
|
||||
59
src/components/sort-dropdown/sort-dropdown.module.css
Normal file
59
src/components/sort-dropdown/sort-dropdown.module.css
Normal 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;
|
||||
}
|
||||
53
src/components/sort-dropdown/sort-dropdown.tsx
Normal file
53
src/components/sort-dropdown/sort-dropdown.tsx
Normal 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;
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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'
|
||||
) : (
|
||||
|
||||
Reference in New Issue
Block a user