mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
perf: abstract reply modal logic into hook for post page and board page
This commit is contained in:
@@ -0,0 +1,29 @@
|
|||||||
|
import { useState, useCallback } from 'react';
|
||||||
|
|
||||||
|
const useReplyModal = () => {
|
||||||
|
const [showReplyModal, setShowReplyModal] = useState(false);
|
||||||
|
const [activeCid, setActiveCid] = useState<string | null>(null);
|
||||||
|
|
||||||
|
const openReplyModal = useCallback(
|
||||||
|
(cid: string) => {
|
||||||
|
if (activeCid && activeCid !== cid) {
|
||||||
|
closeModal(); // close modal if a different CID is clicked
|
||||||
|
setActiveCid(cid);
|
||||||
|
setShowReplyModal(true);
|
||||||
|
} else if (!activeCid) {
|
||||||
|
setActiveCid(cid);
|
||||||
|
setShowReplyModal(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[activeCid],
|
||||||
|
);
|
||||||
|
|
||||||
|
const closeModal = useCallback(() => {
|
||||||
|
setActiveCid(null);
|
||||||
|
setShowReplyModal(false);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return { showReplyModal, activeCid, openReplyModal, closeModal };
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useReplyModal;
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
import { useEffect, useMemo, useRef } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { useFeed, useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
import { useFeed, useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
||||||
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
|
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import styles from './board.module.css';
|
import styles from './board.module.css';
|
||||||
import useFeedStateString from '../../hooks/use-feed-state-string';
|
import useFeedStateString from '../../hooks/use-feed-state-string';
|
||||||
|
import useReplyModal from '../../hooks/use-reply-modal';
|
||||||
import LoadingEllipsis from '../../components/loading-ellipsis';
|
import LoadingEllipsis from '../../components/loading-ellipsis';
|
||||||
import Post from '../../components/post';
|
import Post from '../../components/post';
|
||||||
import ReplyModal from '../../components/reply-modal';
|
import ReplyModal from '../../components/reply-modal';
|
||||||
@@ -23,6 +24,8 @@ const Board = () => {
|
|||||||
const subplebbit = useSubplebbit({ subplebbitAddress });
|
const subplebbit = useSubplebbit({ subplebbitAddress });
|
||||||
const { createdAt, description, rules, shortAddress, state, suggested, title } = subplebbit || {};
|
const { createdAt, description, rules, shortAddress, state, suggested, title } = subplebbit || {};
|
||||||
|
|
||||||
|
const { showReplyModal, activeCid, openReplyModal, closeModal } = useReplyModal();
|
||||||
|
|
||||||
const loadingStateString = useFeedStateString(subplebbitAddresses) || t('loading');
|
const loadingStateString = useFeedStateString(subplebbitAddresses) || t('loading');
|
||||||
const loadingString = <div className={styles.stateString}>{state === 'failed' ? state : <LoadingEllipsis string={loadingStateString} />}</div>;
|
const loadingString = <div className={styles.stateString}>{state === 'failed' ? state : <LoadingEllipsis string={loadingStateString} />}</div>;
|
||||||
|
|
||||||
@@ -53,27 +56,6 @@ const Board = () => {
|
|||||||
|
|
||||||
const lastVirtuosoState = lastVirtuosoStates?.[subplebbitAddress + sortType];
|
const lastVirtuosoState = lastVirtuosoStates?.[subplebbitAddress + sortType];
|
||||||
|
|
||||||
const [showReplyModal, setShowReplyModal] = useState(false);
|
|
||||||
const [activeCid, setActiveCid] = useState<string | null>(null);
|
|
||||||
|
|
||||||
const openReplyModal = (cid: string) => {
|
|
||||||
if (activeCid && activeCid !== cid) {
|
|
||||||
closeModal();
|
|
||||||
setActiveCid(cid);
|
|
||||||
setShowReplyModal(true);
|
|
||||||
} else if (!activeCid) {
|
|
||||||
setActiveCid(cid);
|
|
||||||
setShowReplyModal(true);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const closeModal = () => {
|
|
||||||
setActiveCid(null);
|
|
||||||
setShowReplyModal(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.title = title ? title : shortAddress;
|
document.title = title ? title : shortAddress;
|
||||||
}, [title, shortAddress]);
|
}, [title, shortAddress]);
|
||||||
@@ -95,9 +77,9 @@ const Board = () => {
|
|||||||
data={feed}
|
data={feed}
|
||||||
itemContent={(index, post) => {
|
itemContent={(index, post) => {
|
||||||
const { deleted, locked, removed } = post || {};
|
const { deleted, locked, removed } = post || {};
|
||||||
const isThreadLocked = deleted || locked || removed;
|
const isThreadClosed = deleted || locked || removed;
|
||||||
|
|
||||||
return <Post index={index} post={post} openReplyModal={isThreadLocked ? () => alert(t('thread_closed_alert')) : openReplyModal} />;
|
return <Post index={index} post={post} openReplyModal={isThreadClosed ? () => alert(t('thread_closed_alert')) : openReplyModal} />;
|
||||||
}}
|
}}
|
||||||
useWindowScroll={true}
|
useWindowScroll={true}
|
||||||
components={{ Footer }}
|
components={{ Footer }}
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useComment, useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
import { useComment, useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
||||||
import { useLocation, useParams } from 'react-router-dom';
|
import { useLocation, useParams } from 'react-router-dom';
|
||||||
import { isDescriptionView, isRulesView } from '../../lib/utils/view-utils';
|
|
||||||
import styles from './post-page.module.css';
|
import styles from './post-page.module.css';
|
||||||
|
import { isDescriptionView, isRulesView } from '../../lib/utils/view-utils';
|
||||||
|
import useReplyModal from '../../hooks/use-reply-modal';
|
||||||
import Post from '../../components/post';
|
import Post from '../../components/post';
|
||||||
|
import ReplyModal from '../../components/reply-modal';
|
||||||
import SubplebbitDescription from '../../components/subplebbit-description';
|
import SubplebbitDescription from '../../components/subplebbit-description';
|
||||||
import SubplebbitRules from '../../components/subplebbit-rules';
|
import SubplebbitRules from '../../components/subplebbit-rules';
|
||||||
|
|
||||||
const PostPage = () => {
|
const PostPage = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const { commentCid, subplebbitAddress } = params;
|
const { commentCid, subplebbitAddress } = params;
|
||||||
|
|
||||||
@@ -18,7 +22,11 @@ const PostPage = () => {
|
|||||||
const isInDescriptionView = isDescriptionView(location.pathname, params);
|
const isInDescriptionView = isDescriptionView(location.pathname, params);
|
||||||
const isInRulesView = isRulesView(location.pathname, params);
|
const isInRulesView = isRulesView(location.pathname, params);
|
||||||
|
|
||||||
|
const { showReplyModal, activeCid, openReplyModal, closeModal } = useReplyModal();
|
||||||
|
|
||||||
const post = useComment({ commentCid });
|
const post = useComment({ commentCid });
|
||||||
|
const { deleted, locked, removed } = post || {};
|
||||||
|
const isThreadClosed = deleted || locked || removed;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
@@ -26,12 +34,13 @@ const PostPage = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.content}>
|
<div className={styles.content}>
|
||||||
|
{showReplyModal && activeCid && <ReplyModal closeModal={closeModal} parentCid={activeCid} />}
|
||||||
{isInDescriptionView ? (
|
{isInDescriptionView ? (
|
||||||
<SubplebbitDescription avatarUrl={suggested?.avatarUrl} createdAt={createdAt} description={description} subplebbitAddress={subplebbitAddress} title={title} />
|
<SubplebbitDescription avatarUrl={suggested?.avatarUrl} createdAt={createdAt} description={description} subplebbitAddress={subplebbitAddress} title={title} />
|
||||||
) : isInRulesView ? (
|
) : isInRulesView ? (
|
||||||
<SubplebbitRules createdAt={createdAt} rules={rules} subplebbitAddress={subplebbitAddress} />
|
<SubplebbitRules createdAt={createdAt} rules={rules} subplebbitAddress={subplebbitAddress} />
|
||||||
) : (
|
) : (
|
||||||
<Post post={post} showAllReplies={true} />
|
<Post post={post} showAllReplies={true} openReplyModal={isThreadClosed ? () => alert(t('thread_closed_alert')) : openReplyModal} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user