Skip to content

Commit

Permalink
Merge pull request #497 from plebbit/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
plebeius-eth authored Jan 24, 2025
2 parents f66350e + 66a766b commit 1a40696
Show file tree
Hide file tree
Showing 13 changed files with 722 additions and 594 deletions.
19 changes: 17 additions & 2 deletions src/components/challenge-modal/challenge-modal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { FloatingFocusManager, useClick, useDismiss, useFloating, useId, useInteractions, useRole } from '@floating-ui/react';
import { Challenge as ChallengeType, useComment } from '@plebbit/plebbit-react-hooks';
import { useTranslation } from 'react-i18next';
Expand Down Expand Up @@ -46,13 +46,24 @@ const Challenge = ({ challenge, closeModal }: ChallengeProps) => {

const onEnterKey = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key !== 'Enter') return;
if (!answers[currentChallengeIndex]) return;
if (challenges[currentChallengeIndex + 1]) {
setCurrentChallengeIndex((prev) => prev + 1);
} else {
onSubmit();
}
};

useEffect(() => {
const onEscapeKey = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
closeModal();
}
};
document.addEventListener('keydown', onEscapeKey);
return () => document.removeEventListener('keydown', onEscapeKey);
}, [closeModal]);

return (
<div className={styles.container}>
<div className={styles.title}>{t('challenge_from', { subplebbit: shortSubplebbitAddress || subplebbitAddress })}</div>
Expand Down Expand Up @@ -80,7 +91,11 @@ const Challenge = ({ challenge, closeModal }: ChallengeProps) => {
<div className={styles.challengeFooter}>
<div className={styles.counter}>{t('challenge_counter', { index: currentChallengeIndex + 1, total: challenges?.length })}</div>
<span className={styles.buttons}>
{!challenges[currentChallengeIndex + 1] && <button onClick={onSubmit}>{t('submit')}</button>}
{!challenges[currentChallengeIndex + 1] && (
<button onClick={onSubmit} disabled={!answers[currentChallengeIndex]}>
{t('submit')}
</button>
)}
<button onClick={closeModal}>{t('cancel')}</button>
{challenges.length > 1 && (
<button disabled={!challenges[currentChallengeIndex - 1]} onClick={() => setCurrentChallengeIndex((prev) => prev - 1)}>
Expand Down
24 changes: 16 additions & 8 deletions src/components/post/comment-tools/comment-tools.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -222,16 +222,24 @@ const CommentToolsLabel = ({ cid, deleted, failed, editState, isReply, nsfw, rem
const failedEdit = editState === 'failed';
const pendingEdit = editState === 'pending';

const labels = [
{ show: nsfw, color: 'nsfw-red', text: t('nsfw') },
{ show: spoiler, color: 'black', text: t('spoiler') },
{ show: pending, color: 'yellow', text: t('pending') },
{ show: failed, color: 'red', text: t('failed') },
{ show: deleted, color: 'red', text: t('deleted') },
{ show: removed, color: 'red', text: t('removed') },
{ show: failedEdit, color: 'red', text: t('failed_edit') },
{ show: pendingEdit, color: 'yellow', text: t('pending_edit') },
];

const visibleLabels = labels.filter((label) => label.show);

return (
<>
{nsfw && <Label color='nsfw-red' text={t('nsfw')} />}
{spoiler && <Label color='black' text={t('spoiler')} />}
{pending && <Label color='yellow' text={t('pending')} />}
{failed && <Label color='red' text={t('failed')} />}
{deleted && <Label color='red' text={t('deleted')} />}
{removed && <Label color='red' text={t('removed')} />}
{failedEdit && <Label color='red' text={t('failed_edit')} />}
{pendingEdit && <Label color='yellow' text={t('pending_edit')} />}
{visibleLabels.map((label, index) => (
<Label key={label.text} color={label.color} text={label.text} isFirstInLine={index === 0} />
))}
</>
);
};
Expand Down
4 changes: 4 additions & 0 deletions src/components/post/label/label.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
padding: 0 5px;
}

.firstInLine {
padding-left: 0 !important;
}

.black {
color: var(--text);
border-color: currentColor;
Expand Down
5 changes: 3 additions & 2 deletions src/components/post/label/label.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import styles from './label.module.css';
interface LabelProps {
color: string;
text: string;
isFirstInLine?: boolean;
}

const Label = ({ color, text }: LabelProps) => {
const Label = ({ color, text, isFirstInLine = false }: LabelProps) => {
const { t } = useTranslation();

return (
<span className={styles.label}>
<span className={`${styles.label} ${isFirstInLine ? styles.firstInLine : ''}`}>
<span className={`${styles.stamp} ${styles[color]}`}>{t(text)}</span>
</span>
);
Expand Down
12 changes: 6 additions & 6 deletions src/components/reply-form/reply-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ const ReplyForm = ({ cid, isReplyingToReply, hideReplyForm, subplebbitAddress, p
const [showOptions, setShowOptions] = useState(false);
const [showFormattingHelp, setShowFormattingHelp] = useState(false);
const [isTextareaFocused, setIsTextareaFocused] = useState(false);
const { setContent, resetContent, replyIndex, publishReply } = usePublishReply({ cid, subplebbitAddress, postCid });
const { setPublishReplyOptions, resetPublishReplyOptions, replyIndex, publishReply } = usePublishReply({ cid, subplebbitAddress, postCid });

const mdContainerClass = isReplyingToReply ? `${styles.mdContainer} ${styles.mdContainerReplying}` : styles.mdContainer;
const urlClass = showOptions ? styles.urlVisible : styles.urlHidden;
Expand Down Expand Up @@ -137,34 +137,34 @@ const ReplyForm = ({ cid, isReplyingToReply, hideReplyForm, subplebbitAddress, p

useEffect(() => {
if (typeof replyIndex === 'number') {
resetContent();
resetPublishReplyOptions();

if (hideReplyForm) {
hideReplyForm();
}

resetFields();
}
}, [replyIndex, resetContent, hideReplyForm]);
}, [replyIndex, resetPublishReplyOptions, hideReplyForm]);

return (
<div className={mdContainerClass}>
<div className={styles.md}>
{isOffline && isTextareaFocused && <div className={styles.infobar}>{offlineTitle}</div>}
<div className={styles.options}>
<span className={urlClass}>
{t('media_url')}: <input className={`${styles.url} ${urlClass}`} ref={urlRef} onChange={(e) => setContent.link(e.target.value)} />
{t('media_url')}: <input className={`${styles.url} ${urlClass}`} ref={urlRef} onChange={(e) => setPublishReplyOptions.link(e.target.value)} />
</span>
<span className={`${styles.spoiler} ${spoilerClass}`}>
<label>
{t('spoiler')}: <input type='checkbox' className={styles.checkbox} ref={spoilerRef} onChange={(e) => setContent.spoiler(e.target.checked)} />
{t('spoiler')}: <input type='checkbox' className={styles.checkbox} ref={spoilerRef} onChange={(e) => setPublishReplyOptions.spoiler(e.target.checked)} />
</label>
</span>
</div>
<textarea
className={styles.textarea}
ref={textRef}
onChange={(e) => setContent.content(e.target.value)}
onChange={(e) => setPublishReplyOptions.content(e.target.value)}
onFocus={() => setIsTextareaFocused(true)}
onBlur={() => setIsTextareaFocused(false)}
/>
Expand Down
2 changes: 1 addition & 1 deletion src/components/sidebar/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ const Sidebar = ({ comment, isSubCreatedButNotYetPublished, settings, subplebbit
</div>
)}
{(isModerator || isOwner) && <ModerationTools address={address} />}
{roles && <ModeratorsList roles={roles} />}
{roles && Object.keys(roles).length > 0 && <ModeratorsList roles={roles} />}
<div className={styles.largeButton} onClick={handleCreateCommunity}>
{t('create_your_community')}
<div className={styles.nub} />
Expand Down
6 changes: 3 additions & 3 deletions src/hooks/use-publish-reply.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const usePublishReply = ({ cid, subplebbitAddress, postCid }: { cid: string; sub
const setReplyStore = usePublishReplyStore((state) => state.setReplyStore);
const resetReplyStore = usePublishReplyStore((state) => state.resetReplyStore);

const setContent = useMemo(
const setPublishReplyOptions = useMemo(
() => ({
content: (newContent: string) =>
setReplyStore({
Expand Down Expand Up @@ -47,11 +47,11 @@ const usePublishReply = ({ cid, subplebbitAddress, postCid }: { cid: string; sub
[subplebbitAddress, parentCid, setReplyStore, content, link, spoiler, postCid],
);

const resetContent = useMemo(() => () => resetReplyStore(parentCid), [parentCid, resetReplyStore]);
const resetPublishReplyOptions = useMemo(() => () => resetReplyStore(parentCid), [parentCid, resetReplyStore]);

const { index, publishComment } = usePublishComment(publishCommentOptions);

return { setContent, resetContent, replyIndex: index, publishReply: publishComment };
return { setPublishReplyOptions, resetPublishReplyOptions, replyIndex: index, publishReply: publishComment };
};

export default usePublishReply;
6 changes: 5 additions & 1 deletion src/views/home/home.module.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
.footer, .stateString {
padding-left: 5px;
}

.footer {
padding: 5px 0 20px 5px;
padding-top: 5px;
}

.stateString, .morePostsSuggestion {
Expand Down
98 changes: 68 additions & 30 deletions src/views/home/home.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useRef } from 'react';
import { useEffect, useRef, memo } from 'react';
import { Link, useParams } from 'react-router-dom';
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
import { useFeed } from '@plebbit/plebbit-react-hooks';
Expand All @@ -14,36 +14,31 @@ import useRedirectToDefaultSort from '../../hooks/use-redirect-to-default-sort';

const lastVirtuosoStates: { [key: string]: StateSnapshot } = {};

const Home = () => {
const LoadingStateFooter = () => {
const { t } = useTranslation();
useRedirectToDefaultSort();
const subplebbitAddresses = useDefaultAndSubscriptionsSubplebbitAddresses();
const params = useParams<{ sortType?: string; timeFilterName?: string }>();
const sortType = params?.sortType || 'hot';
const { timeFilterName, timeFilterSeconds } = useTimeFilter();
const { feed, hasMore, loadMore, reset, subplebbitAddressesWithNewerPosts } = useFeed({
newerThan: timeFilterSeconds,
postsPerPage: 10,
sortType,
subplebbitAddresses: subplebbitAddresses || [],
});

// suggest the user to change time filter if there aren't enough posts
const { feed: weeklyFeed } = useFeed({ subplebbitAddresses, sortType, newerThan: 60 * 60 * 24 * 7 });
const { feed: monthlyFeed } = useFeed({ subplebbitAddresses, sortType, newerThan: 60 * 60 * 24 * 30 });

const loadingStateString = useFeedStateString(subplebbitAddresses) || t('loading');

const handleNewerPostsButtonClick = () => {
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });
setTimeout(() => {
reset();
}, 300);
};

const currentTimeFilterName = params.timeFilterName || timeFilterName;
return (
<div className={styles.stateString}>
<LoadingEllipsis string={loadingStateString} />
</div>
);
};

const Footer = () => {
const Footer = memo(
({
feed,
hasMore,
subplebbitAddresses,
subplebbitAddressesWithNewerPosts,
handleNewerPostsButtonClick,
params,
weeklyFeed,
monthlyFeed,
currentTimeFilterName,
}: any) => {
const { t } = useTranslation();
let footerContent;
if (feed.length === 0) {
footerContent = t('no_posts');
Expand Down Expand Up @@ -84,15 +79,39 @@ const Home = () => {
</div>
))
)}
<div className={styles.stateString}>
<LoadingEllipsis string={loadingStateString} />
</div>
</>
);
}
return <div className={styles.footer}>{footerContent}</div>;
},
);

const Home = () => {
const { t } = useTranslation();
useRedirectToDefaultSort();
const subplebbitAddresses = useDefaultAndSubscriptionsSubplebbitAddresses();
const params = useParams<{ sortType?: string; timeFilterName?: string }>();
const sortType = params?.sortType || 'hot';
const { timeFilterName, timeFilterSeconds } = useTimeFilter();
const { feed, hasMore, loadMore, reset, subplebbitAddressesWithNewerPosts } = useFeed({
newerThan: timeFilterSeconds,
postsPerPage: 10,
sortType,
subplebbitAddresses: subplebbitAddresses || [],
});

const { feed: weeklyFeed } = useFeed({ subplebbitAddresses, sortType, newerThan: 60 * 60 * 24 * 7 });
const { feed: monthlyFeed } = useFeed({ subplebbitAddresses, sortType, newerThan: 60 * 60 * 24 * 30 });

const handleNewerPostsButtonClick = () => {
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });
setTimeout(() => {
reset();
}, 300);
};

const currentTimeFilterName = params.timeFilterName || timeFilterName;

const virtuosoRef = useRef<VirtuosoHandle | null>(null);

useEffect(() => {
Expand All @@ -113,6 +132,18 @@ const Home = () => {
document.title = `Seedit`;
}, [t]);

const footerProps = {
feed,
hasMore,
subplebbitAddresses,
subplebbitAddressesWithNewerPosts,
handleNewerPostsButtonClick,
params,
weeklyFeed,
monthlyFeed,
currentTimeFilterName,
};

return (
<div>
<div className={styles.content}>
Expand All @@ -126,7 +157,14 @@ const Home = () => {
data={feed}
itemContent={(index, post) => <Post index={index} post={post} />}
useWindowScroll={true}
components={{ Footer }}
components={{
Footer: () => (
<>
<Footer {...footerProps} />
<LoadingStateFooter />
</>
),
}}
endReached={loadMore}
ref={virtuosoRef}
restoreStateFrom={lastVirtuosoState}
Expand Down
9 changes: 4 additions & 5 deletions src/views/settings/account-settings/account-settings.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useEffect, useMemo, useRef, useState } from 'react';
import { createAccount, deleteAccount, exportAccount, importAccount, setAccount, setActiveAccount, useAccount, useAccounts } from '@plebbit/plebbit-react-hooks';
import stringify from 'json-stringify-pretty-compact';
import { Trans, useTranslation } from 'react-i18next';
Expand All @@ -8,19 +8,18 @@ const CreateAccountButton = () => {
const { accounts } = useAccounts();
const switchToNewAccountRef = useRef(false);

const switchToLastAccount = useCallback(async () => {
useEffect(() => {
if (switchToNewAccountRef.current && accounts.length > 0) {
const lastAccount = accounts[accounts.length - 1];
await setActiveAccount(lastAccount.name);
setActiveAccount(lastAccount.name);
switchToNewAccountRef.current = false;
}
}, [accounts]);

const handleCreateAccount = async () => {
try {
await createAccount();
switchToNewAccountRef.current = true;
switchToLastAccount();
await createAccount();
} catch (error) {
if (error instanceof Error) {
alert(error.message);
Expand Down
Loading

0 comments on commit 1a40696

Please sign in to comment.