mirror of
https://github.com/plebbit/seedit.git
synced 2026-04-21 15:48:43 -04:00
Binary file not shown.
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 6.5 KiB |
26
src/app.tsx
26
src/app.tsx
@@ -58,29 +58,39 @@ function App() {
|
||||
<Route element={feedLayout}>
|
||||
<Route path='/:sortType?' element={<Home />} />
|
||||
<Route path='/:sortType?/:timeFilterName?' element={<Home />} />
|
||||
|
||||
<Route path='/p/all/:sortType?' element={<All />} />
|
||||
<Route path='/p/all/:sortType?/:timeFilterName?' element={<All />} />
|
||||
|
||||
<Route path='/p/:subplebbitAddress/:sortType?' element={<Subplebbit />} />
|
||||
<Route path='/p/:subplebbitAddress/:sortType?/:timeFilterName?' element={<Subplebbit />} />
|
||||
<Route path='/profile' element={<Profile />} />
|
||||
<Route path='/profile/:sortType?' element={<Profile />} />
|
||||
<Route path='/profile/upvoted/:sortType?' element={<Profile />} />
|
||||
<Route path='/profile/downvoted/:sortType?' element={<Profile />} />
|
||||
<Route path='/profile/comments/:sortType?' element={<Profile />} />
|
||||
<Route path='/profile/submitted/:sortType?' element={<Profile />} />
|
||||
<Route path='u/:authorAddress/c/:commentCid?' element={<Author />} />
|
||||
<Route path='u/:authorAddress/c/:commentCid?/:sortType?' element={<Author />} />
|
||||
|
||||
<Route path='/profile/:sortType?/:timeFilterName?' element={<Profile />} />
|
||||
<Route path='/profile/upvoted/:sortType?/:timeFilterName?' element={<Profile />} />
|
||||
<Route path='/profile/downvoted/:sortType?/:timeFilterName?' element={<Profile />} />
|
||||
<Route path='/profile/comments/:sortType?/:timeFilterName?' element={<Profile />} />
|
||||
<Route path='/profile/submitted/:sortType?/:timeFilterName?' element={<Profile />} />
|
||||
|
||||
<Route path='u/:authorAddress/c/:commentCid?/:sortType?/:timeFilterName?' element={<Author />} />
|
||||
<Route path='u/:authorAddress/c/:commentCid?/comments/:sortType?/:timeFilterName?' element={<Author />} />
|
||||
<Route path='u/:authorAddress/c/:commentCid?/submitted/:sortType?/:timeFilterName?' element={<Author />} />
|
||||
</Route>
|
||||
<Route element={pagesLayout}>
|
||||
<Route path='/submit' element={<Submit />} />
|
||||
|
||||
<Route path='/p/:subplebbitAddress/c/:commentCid' element={<Post />} />
|
||||
<Route path='/p/:subplebbitAddress/c/:commentCid/about' element={<About />} />
|
||||
|
||||
<Route path='/p/:subplebbitAddress/submit' element={<Submit />} />
|
||||
<Route path='/p/:subplebbitAddress/about' element={<About />} />
|
||||
|
||||
<Route path='/settings' element={<Settings />} />
|
||||
|
||||
<Route path='/profile/:accountCommentIndex' element={<PendingPost />} />
|
||||
<Route path='/profile/about' element={<About />} />
|
||||
|
||||
<Route path='/u/:authorAddress/c/:commentCid/about' element={<About />} />
|
||||
|
||||
<Route path='/inbox' element={<Inbox />} />
|
||||
</Route>
|
||||
</Route>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.modal {
|
||||
z-index: 1;
|
||||
z-index: 7;
|
||||
outline: unset;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAccount, useComment, usePublishCommentEdit, useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
||||
import { PublishCommentEditOptions, useAccount, useComment, usePublishCommentEdit, useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
||||
import { autoUpdate, flip, FloatingFocusManager, offset, shift, useClick, useDismiss, useFloating, useId, useInteractions, useRole } from '@floating-ui/react';
|
||||
import styles from './comment-tools.module.css';
|
||||
import { FailedLabel, PendingLabel, SpoilerLabel } from '../label';
|
||||
import challengesStore from '../../../hooks/use-challenges';
|
||||
import { alertChallengeVerificationFailed } from '../../../lib/utils/challenge-utils';
|
||||
import { getShareLink } from '../../../lib/utils/url-utils';
|
||||
|
||||
const { addChallenge } = challengesStore.getState();
|
||||
|
||||
interface CommentToolsProps {
|
||||
@@ -26,7 +27,7 @@ const ModTools = ({ cid }: CommentToolsProps) => {
|
||||
const post = useComment({ commentCid: cid });
|
||||
const [isModToolsOpen, setIsModToolsOpen] = useState(false);
|
||||
|
||||
const defaultPublishOptions = {
|
||||
const defaultPublishOptions: PublishCommentEditOptions = {
|
||||
removed: post?.removed,
|
||||
locked: post?.locked,
|
||||
spoiler: post?.spoiler,
|
||||
@@ -37,11 +38,12 @@ const ModTools = ({ cid }: CommentToolsProps) => {
|
||||
onChallengeVerification: alertChallengeVerificationFailed,
|
||||
onError: (error: Error) => {
|
||||
console.warn(error);
|
||||
alert(error);
|
||||
alert(error.message);
|
||||
},
|
||||
};
|
||||
|
||||
const [publishCommentEditOptions, setPublishCommentEditOptions] = useState(defaultPublishOptions);
|
||||
const { state, publishCommentEdit } = usePublishCommentEdit({ publishCommentEditOptions });
|
||||
const { state, publishCommentEdit } = usePublishCommentEdit(publishCommentEditOptions);
|
||||
|
||||
// close the modal after publishing
|
||||
useEffect(() => {
|
||||
@@ -82,25 +84,25 @@ const ModTools = ({ cid }: CommentToolsProps) => {
|
||||
<div className={styles.modTools}>
|
||||
<div className={styles.menuItem}>
|
||||
<label>
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.removed} type='checkbox' />
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.removed} type='checkbox' id='removed' />
|
||||
{t('removed')}
|
||||
</label>
|
||||
</div>
|
||||
<div className={styles.menuItem}>
|
||||
<label>
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.locked} type='checkbox' />
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.locked} type='checkbox' id='locked' />
|
||||
locked
|
||||
</label>
|
||||
</div>
|
||||
<div className={styles.menuItem}>
|
||||
<label>
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.spoiler} type='checkbox' />
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.spoiler} type='checkbox' id='spoiler' />
|
||||
{t('spoiler')}
|
||||
</label>
|
||||
</div>
|
||||
<div className={styles.menuItem}>
|
||||
<label>
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.pinned} type='checkbox' />
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.pinned} type='checkbox' id='pinned' />
|
||||
{t('announcement')}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -37,10 +37,7 @@ const ReplyAuthor = ({ address, authorRole, cid, displayName, shortAuthorAddress
|
||||
return (
|
||||
<>
|
||||
{displayName && <span className={`${styles.author} ${moderatorClass}`}>{displayName}</span>}
|
||||
<Link
|
||||
to={`/u/${address}/c/${cid}`}
|
||||
className={`${styles.author} ${moderatorClass}`}
|
||||
>
|
||||
<Link to={`/u/${address}/c/${cid}`} className={`${styles.author} ${moderatorClass}`}>
|
||||
{displayName ? `u/${shortAuthorAddress}` : shortAuthorAddress}
|
||||
</Link>
|
||||
{authorRole && (
|
||||
@@ -131,21 +128,7 @@ const ParentLink = ({ reply }: { reply: Comment }) => {
|
||||
};
|
||||
|
||||
const Reply = ({ depth = 0, isSingle, reply = {} }: ReplyProps) => {
|
||||
const {
|
||||
author,
|
||||
cid,
|
||||
content,
|
||||
downvoteCount,
|
||||
flair,
|
||||
link,
|
||||
linkHeight,
|
||||
linkWidth,
|
||||
removed,
|
||||
spoiler,
|
||||
subplebbitAddress,
|
||||
timestamp,
|
||||
upvoteCount,
|
||||
} = reply || {};
|
||||
const { author, cid, content, downvoteCount, flair, link, linkHeight, linkWidth, removed, spoiler, subplebbitAddress, timestamp, upvoteCount } = reply || {};
|
||||
const subplebbit = useSubplebbit({ subplebbitAddress });
|
||||
|
||||
const authorRole = subplebbit?.roles?.[reply.author.address]?.role;
|
||||
|
||||
@@ -150,6 +150,12 @@ a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.bottom button {
|
||||
padding: 0px 2px 0px 2px;
|
||||
font-size: 9px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.listMore {
|
||||
color: var(--text-info) !important;
|
||||
text-align: right;
|
||||
|
||||
@@ -90,6 +90,10 @@ const Sidebar = ({ address, cid, createdAt, description, downvoteCount = 0, role
|
||||
const creatorAddress = subplebbitCreator === 'anonymous' ? 'anonymous' : `${getShortAddress(subplebbitCreator)}`;
|
||||
const submitRoute = isHome || isAll ? '/submit' : `/p/${address}/submit`;
|
||||
|
||||
const alertAnonymousCreator = () => {
|
||||
alert('This community has no owner role set.');
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`${isAbout ? styles.about : styles.sidebar}`}>
|
||||
<SearchBar />
|
||||
@@ -134,6 +138,7 @@ const Sidebar = ({ address, cid, createdAt, description, downvoteCount = 0, role
|
||||
<div className={styles.bottom}>
|
||||
{t('created_by', { creatorAddress: '' })}
|
||||
<Link to={`/u/${creatorAddress}`} onClick={(e) => e.preventDefault()}>{`u/${creatorAddress}`}</Link>
|
||||
{creatorAddress === 'anonymous' && <button onClick={alertAnonymousCreator}>?</button>}
|
||||
{createdAt && <span className={styles.age}> {t('community_for', { date: getFormattedDuration(createdAt) })}</span>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,15 +2,15 @@ import { useEffect, useMemo, useRef } from 'react';
|
||||
import { useLocation, useNavigate, useParams } from 'react-router-dom';
|
||||
import { useAuthorComments } from '@plebbit/plebbit-react-hooks';
|
||||
import { StateSnapshot, Virtuoso, VirtuosoHandle } from 'react-virtuoso';
|
||||
import { isAuthorCommentsView, isAuthorSubmittedView } from '../../lib/utils/view-utils';
|
||||
import styles from './author.module.css';
|
||||
import AuthorSidebar from '../../components/author-sidebar';
|
||||
import LoadingEllipsis from '../../components/loading-ellipsis';
|
||||
import Post from '../../components/post';
|
||||
import { isAuthorCommentsView, isAuthorSubmittedView } from '../../lib/utils/view-utils';
|
||||
import Reply from '../../components/reply/';
|
||||
|
||||
const lastVirtuosoStates: { [key: string]: StateSnapshot } = {};
|
||||
|
||||
const Loading = () => 'loading...';
|
||||
|
||||
const Author = () => {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
@@ -24,7 +24,9 @@ const Author = () => {
|
||||
const replyComments = useMemo(() => authorComments?.filter((comment) => comment && comment.parentCid) || [], [authorComments]);
|
||||
const postComments = useMemo(() => authorComments?.filter((comment) => comment && !comment.parentCid) || [], [authorComments]);
|
||||
|
||||
const Footer = hasMore ? Loading : undefined;
|
||||
const Footer = () => {
|
||||
return hasMore ? <LoadingEllipsis string={'loading'} /> : null;
|
||||
};
|
||||
|
||||
const virtuosoRef = useRef<VirtuosoHandle | null>(null);
|
||||
|
||||
@@ -64,12 +66,15 @@ const Author = () => {
|
||||
<div className={styles.sidebar}>
|
||||
<AuthorSidebar />
|
||||
</div>
|
||||
{authorComments?.length === 0 && <div className={styles.noPosts}>No posts found</div>}
|
||||
{authorComments?.length === 0 && !hasMore && <div className={styles.noPosts}>No posts found</div>}
|
||||
<Virtuoso
|
||||
increaseViewportBy={{ bottom: 1200, top: 600 }}
|
||||
totalCount={authorComments?.length || 0}
|
||||
data={virtuosoData}
|
||||
itemContent={(index, post) => post && <Post index={index} post={post} />}
|
||||
itemContent={(index, post) => {
|
||||
const isReply = post?.parentCid;
|
||||
return !isReply ? <Post index={index} post={post} /> : <Reply index={index} isSingle={true} reply={post} />;
|
||||
}}
|
||||
useWindowScroll={true}
|
||||
components={{ Footer }}
|
||||
endReached={loadMore}
|
||||
|
||||
@@ -11,3 +11,9 @@
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.stateString {
|
||||
max-width: calc(100% - 305px);
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,7 @@ h1 {
|
||||
|
||||
.boxTitleRequired::before {
|
||||
content: "*";
|
||||
color: red;
|
||||
color: var(--red);
|
||||
}
|
||||
|
||||
.boxContent {
|
||||
|
||||
@@ -169,6 +169,12 @@ const Submit = () => {
|
||||
}
|
||||
}, [inputAddress]);
|
||||
|
||||
useEffect(() => {
|
||||
if (paramsSubplebbitAddress) {
|
||||
setSubmitStore({ subplebbitAddress: paramsSubplebbitAddress });
|
||||
}
|
||||
}, [paramsSubplebbitAddress, setSubmitStore]);
|
||||
|
||||
return (
|
||||
<div className={styles.content}>
|
||||
<h1>
|
||||
|
||||
@@ -6,8 +6,19 @@ div[data-viewport-type="window"] {
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
.stateString {
|
||||
text-transform: lowercase;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.sidebar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.stateString {
|
||||
max-width: calc(100% - 305px);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user