diff --git a/src/components/views/AllCatalog.jsx b/src/components/views/AllCatalog.jsx index 76fc0cff..fa43eaad 100755 --- a/src/components/views/AllCatalog.jsx +++ b/src/components/views/AllCatalog.jsx @@ -1,32 +1,32 @@ +import { useAccount, useFeed, usePublishCommentEdit, useSubplebbits } from '@plebbit/plebbit-react-hooks'; +import InfiniteScroll from 'react-infinite-scroller'; +import { debounce } from 'lodash'; import React, { useCallback, useEffect, useRef, useState } from 'react'; +import { confirmAlert } from 'react-confirm-alert'; import { createPortal } from 'react-dom'; import { Helmet } from 'react-helmet-async'; -import { Link, useNavigate} from 'react-router-dom'; -import { confirmAlert } from 'react-confirm-alert'; +import { Link, useNavigate } from 'react-router-dom'; import { Tooltip } from 'react-tooltip'; -import { VirtuosoGrid } from 'react-virtuoso'; -import { useAccount, useFeed, usePublishCommentEdit, useSubplebbits } from '@plebbit/plebbit-react-hooks'; -import { debounce } from 'lodash'; -import { Container, NavBar, Header, Break, PostMenu, BoardForm } from '../styled/views/Board.styled'; -import { Threads, PostMenuCatalog, GridContainer } from '../styled/views/Catalog.styled'; -import { TopBar, Footer, AuthorDeleteAlert } from '../styled/views/Thread.styled'; -import CatalogLoader from '../CatalogLoader'; -import EditModal from '../modals/EditModal'; -import ImageBanner from '../ImageBanner'; -import VerifiedAuthor from '../VerifiedAuthor'; -import CreateBoardModal from '../modals/CreateBoardModal'; -import ModerationModal from '../modals/ModerationModal'; -import OfflineIndicator from '../OfflineIndicator'; -import SettingsModal from '../modals/SettingsModal'; -import countLinks from '../../utils/countLinks'; -import getCommentMediaInfo from '../../utils/getCommentMediaInfo'; -import handleStyleChange from '../../utils/handleStyleChange'; +import packageJson from '../../../package.json'; +import useGeneralStore from '../../hooks/stores/useGeneralStore'; import useError from '../../hooks/useError'; import useFeedStateString from '../../hooks/useFeedStateString'; import useSuccess from '../../hooks/useSuccess'; -import useGeneralStore from '../../hooks/stores/useGeneralStore'; -import packageJson from '../../../package.json' -const {version} = packageJson +import countLinks from '../../utils/countLinks'; +import getCommentMediaInfo from '../../utils/getCommentMediaInfo'; +import handleStyleChange from '../../utils/handleStyleChange'; +import CatalogLoader from '../CatalogLoader'; +import ImageBanner from '../ImageBanner'; +import OfflineIndicator from '../OfflineIndicator'; +import VerifiedAuthor from '../VerifiedAuthor'; +import CreateBoardModal from '../modals/CreateBoardModal'; +import EditModal from '../modals/EditModal'; +import ModerationModal from '../modals/ModerationModal'; +import SettingsModal from '../modals/SettingsModal'; +import { BoardForm, Break, Container, Header, NavBar, PostMenu } from '../styled/views/Board.styled'; +import { PostMenuCatalog, Threads } from '../styled/views/Catalog.styled'; +import { AuthorDeleteAlert, Footer, TopBar } from '../styled/views/Thread.styled'; +const { version } = packageJson const AllCatalog = () => { @@ -47,7 +47,7 @@ const AllCatalog = () => { setSelectedThread, setSelectedTitle, } = useGeneralStore(state => state); - + const threadMenuRefs = useRef({}); const postMenuRef = useRef(null); @@ -57,7 +57,7 @@ const AllCatalog = () => { const navigate = useNavigate(); const [, setNewErrorMessage] = useError(); const [, setNewSuccessMessage] = useSuccess(); - + const [prevScrollPos, setPrevScrollPos] = useState(0); const [visible, setVisible] = useState(true); const [isHoveringOnThread, setIsHoveringOnThread] = useState(false); @@ -68,14 +68,14 @@ const AllCatalog = () => { const [deletePost, setDeletePost] = useState(false); const [isImageSearchOpen, setIsImageSearchOpen] = useState(false); const [commentCid, setCommentCid] = useState(null); - const [menuPosition, setMenuPosition] = useState({top: 0, left: 0}); + const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 }); const [openMenuCid, setOpenMenuCid] = useState(null); const [moderatorPermissions, setModeratorPermissions] = useState({}); const [isCreateBoardOpen, setIsCreateBoardOpen] = useState(false); const addresses = defaultSubplebbits.map(subplebbit => subplebbit.address); - const { feed, loadMore } = useFeed({subplebbitAddresses: addresses, sortType: 'active'}); - const {subplebbits} = useSubplebbits({subplebbitAddresses: addresses, sortType: 'active'}); + const { feed, hasMore, loadMore } = useFeed({ subplebbitAddresses: addresses, sortType: 'active' }); + const { subplebbits } = useSubplebbits({ subplebbitAddresses: addresses, sortType: 'active' }); const [selectedFeed, setSelectedFeed] = useState(feed.sort((a, b) => b.timestamp - a.timestamp)); const stateString = useFeedStateString(subplebbits); @@ -83,13 +83,13 @@ const AllCatalog = () => { useEffect(() => { let permissions = {}; - + selectedFeed.forEach(thread => { const subplebbit = subplebbits.find(s => s && s.address === thread.subplebbitAddress); - - if (subplebbit && subplebbit.roles) { + + if (subplebbit && subplebbit.roles) { const role = subplebbit.roles[account?.author.address]?.role; - + if (role === 'moderator' || role === 'admin' || role === 'owner') { permissions[thread.subplebbitAddress] = true; } else { @@ -97,9 +97,9 @@ const AllCatalog = () => { } } }); - + setModeratorPermissions(permissions); - }, [account?.author.address, selectedFeed, subplebbits]); + }, [account?.author.address, selectedFeed, subplebbits]); const handleOptionClick = () => { @@ -120,7 +120,7 @@ const AllCatalog = () => { } else { document.removeEventListener('click', handleOutsideClick); } - + return () => { document.removeEventListener('click', handleOutsideClick); }; @@ -134,24 +134,23 @@ const AllCatalog = () => { setVisible(prevScrollPos > currentScrollPos || currentScrollPos < 10); setPrevScrollPos(currentScrollPos); }, 50); - + window.addEventListener('scroll', debouncedHandleScroll); - + return () => window.removeEventListener('scroll', debouncedHandleScroll); }, [prevScrollPos, visible]); const tryLoadMore = async () => { - try {loadMore()} - catch (e) - {await new Promise(resolve => setTimeout(resolve, 1000))} + try { loadMore() } + catch (e) { await new Promise(resolve => setTimeout(resolve, 1000)) } }; const onChallengeVerification = (challengeVerification) => { if (challengeVerification.challengeSuccess === true) { - setNewSuccessMessage('Challenge Success'); - } + setNewSuccessMessage('Challenge Success'); + } else if (challengeVerification.challengeSuccess === false) { setNewErrorMessage(`Challenge Failed, reason: ${challengeVerification.reason}. Errors: ${challengeVerification.errors}`); console.log('challenge failed', challengeVerification); @@ -175,16 +174,16 @@ const AllCatalog = () => { const getChallengeAnswersFromUser = async (challenges) => { setChallengesArray(challenges); - + return new Promise((resolve, reject) => { const imageString = challenges?.challenges[0].challenge; const imageSource = `data:image/png;base64,${imageString}`; const challengeImg = new Image(); challengeImg.src = imageSource; - + challengeImg.onload = () => { setIsCaptchaOpen(true); - + const handleKeyDown = async (event) => { if (event.key === 'Enter') { const currentCaptchaResponse = useGeneralStore.getState().captchaResponse; @@ -200,7 +199,7 @@ const AllCatalog = () => { setResolveCaptchaPromise(resolve); }; - + challengeImg.onerror = () => { reject(setNewErrorMessage('Could not load challenges')); }; @@ -217,8 +216,8 @@ const AllCatalog = () => { setNewErrorMessage(error.message); console.log(error); }, }); - - + + const { publishCommentEdit } = usePublishCommentEdit(publishCommentEditOptions); @@ -265,8 +264,8 @@ const AllCatalog = () => { setOriginalCommentContent(comment.content); setIsEditModalOpen(true); } - - + + useEffect(() => { setPublishCommentEditOptions((prevOptions) => ({ ...prevOptions, @@ -282,7 +281,7 @@ const AllCatalog = () => { } }, [editedComment, setIsAuthorEdit]); - + useEffect(() => { let isActive = true; if (publishCommentEditOptions && triggerPublishCommentEdit) { @@ -329,69 +328,69 @@ const AllCatalog = () => { return ( <> - p/All - Catalog - plebchan + p/All - Catalog - plebchan setIsCreateBoardOpen(false)} /> + selectedStyle={selectedStyle} + isOpen={isCreateBoardOpen} + closeModal={() => setIsCreateBoardOpen(false)} /> setIsSettingsOpen(false)} /> - {setIsModerationOpen(false); setDeletePost(false)}} - deletePost={deletePost} /> + selectedStyle={selectedStyle} + isOpen={isSettingsOpen} + closeModal={() => setIsSettingsOpen(false)} /> + { setIsModerationOpen(false); setDeletePost(false) }} + deletePost={deletePost} /> setIsEditModalOpen(false)} - originalCommentContent={originalCommentContent} /> + selectedStyle={selectedStyle} + isOpen={isEditModalOpen} + closeModal={() => setIsEditModalOpen(false)} + originalCommentContent={originalCommentContent} /> <> - - [ + + [ window.scrollTo(0, 0)}>All -  /  + / window.scrollTo(0, 0)}>Subscriptions - ] [ - {defaultSubplebbits.map((subplebbit, index) => ( - - {index === 0 ? null : "\u00a0"} - { - setSelectedTitle(subplebbit.title); - setSelectedAddress(subplebbit.address); - }} - >{subplebbit.title ? subplebbit.title : subplebbit.address} - {index !== defaultSubplebbits.length - 1 ? " /" : null} - - ))} - ] - - - [ - { - window.electron && window.electron.isElectron ? ( - setIsCreateBoardOpen(true) - ) : ( - alert( - 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n' - ) - ) - } - }>Create Board - ] - [ - setIsSettingsOpen(true)}>Settings - ] - [ - Home + ] [ + {defaultSubplebbits.map((subplebbit, index) => ( + + {index === 0 ? null : "\u00a0"} + { + setSelectedTitle(subplebbit.title); + setSelectedAddress(subplebbit.address); + }} + >{subplebbit.title ? subplebbit.title : subplebbit.address} + {index !== defaultSubplebbits.length - 1 ? " /" : null} + + ))} ] + + [ + { + window.electron && window.electron.isElectron ? ( + setIsCreateBoardOpen(true) + ) : ( + alert( + 'You can create a board with the desktop version of plebchan, which you can download from here: https://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can also run a board (called "subplebbit") using plebbit-cli: https://github.com/plebbit/plebbit-cli\n\n' + ) + ) + } + }>Create Board + ] +[ + setIsSettingsOpen(true)}>Settings +] +[ + Home +] +
@@ -401,27 +400,27 @@ const AllCatalog = () => { {defaultSubplebbits.map(subplebbit => ( - - ))} -   - alert( - 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n' + + ))} + + alert( + 'You can create a board with the desktop version of plebchan, which you can download from here: https://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can also run a board (called "subplebbit") using plebbit-cli: https://github.com/plebbit/plebbit-cli\n\n' ) }>Create Board
setIsSettingsOpen(true)}>Settings   - {handleStyleChange({target: {value: "Yotsuba"}}); window.scrollTo(0, 0);}}>Home + { handleStyleChange({ target: { value: "Yotsuba" } }); window.scrollTo(0, 0); }}>Home
 
 
-
+
<>
@@ -436,7 +435,7 @@ const AllCatalog = () => {
Style: -   + - - - - - - - - - - <> - - [ - window.scrollTo(0, 0)}>All -  /  - window.scrollTo(0, 0)}>Subscriptions - ] [ - {defaultSubplebbits.map((subplebbit, index) => ( - - {index === 0 ? null : "\u00a0"} - handleClickTitle(subplebbit.title, subplebbit.address)} - >{subplebbit.title ? subplebbit.title : subplebbit.address} - {index !== defaultSubplebbits.length - 1 ? " /" : null} - - ))} - ] - - - [ - { - window.electron && window.electron.isElectron ? ( - setIsCreateBoardOpen(true) + {feed ? ( + + {feed.map((thread, index) => { + const commentMediaInfo = getCommentMediaInfo(thread); + const fallbackImgUrl = "assets/filedeleted-res.gif"; + const isModerator = moderatorPermissions[thread.subplebbitAddress]; + const linkCount = countLinks(thread); + return ( +
{ setIsHoveringOnThread(thread.cid) }} + onMouseLeave={() => { setIsHoveringOnThread('') }}> + {commentMediaInfo?.url ? ( + setSelectedThread(thread.cid)}> + {commentMediaInfo?.type === "webpage" ? ( + thread.thumbnailUrl ? ( + {commentMediaInfo.type} { + e.target.src = fallbackImgUrl + e.target.onerror = null; + }} /> + ) : null + ) : null} + {commentMediaInfo?.type === "image" ? ( + {commentMediaInfo.type} { + e.target.src = fallbackImgUrl + e.target.onerror = null; + }} /> + ) : null} + {commentMediaInfo?.type === "video" ? ( +
) - } - }>Create Board
- ] + })} + + ) : ( + + )} + +
+ + + + Style: + + + + + <> + + [ + window.scrollTo(0, 0)}>All + / + window.scrollTo(0, 0)}>Subscriptions + ] [ + {defaultSubplebbits.map((subplebbit, index) => ( + + {index === 0 ? null : "\u00a0"} + handleClickTitle(subplebbit.title, subplebbit.address)} + >{subplebbit.title ? subplebbit.title : subplebbit.address} + {index !== defaultSubplebbits.length - 1 ? " /" : null} + + ))} + ] + + [ - setIsSettingsOpen(true)}>Settings + { + window.electron && window.electron.isElectron ? ( + setIsCreateBoardOpen(true) + ) : ( + alert( + 'You can create a board with the desktop version of plebchan, which you can download from here: https://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can also run a board (called "subplebbit") using plebbit-cli: https://github.com/plebbit/plebbit-cli\n\n' + ) + ) + } + }>Create Board ] - [ - handleStyleChange({target: {value: "Yotsuba"}} - )}>Home - ] - +[ + setIsSettingsOpen(true)}>Settings +] +[ + handleStyleChange({ target: { value: "Yotsuba" } } + )}>Home +] + - +
plebchan v{version}. GPL-2.0
@@ -748,16 +763,16 @@ const AllCatalog = () => { marginTop: "5px", marginBottom: "15px", }}> - About -  •  - App + About  •  - Twitter -  •  - Telegram + App +  •  + Twitter +  •  + Telegram
- - + + ); } diff --git a/src/components/views/Catalog.jsx b/src/components/views/Catalog.jsx index 029a9dc3..1f585d69 100755 --- a/src/components/views/Catalog.jsx +++ b/src/components/views/Catalog.jsx @@ -1,4 +1,5 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import InfiniteScroll from 'react-infinite-scroller'; import { createPortal } from 'react-dom'; import { Helmet } from 'react-helmet-async'; import { Link, useNavigate, useParams } from 'react-router-dom'; @@ -29,7 +30,7 @@ import useSuccess from '../../hooks/useSuccess'; import useAnonModeStore from '../../hooks/stores/useAnonModeStore'; import useGeneralStore from '../../hooks/stores/useGeneralStore'; import packageJson from '../../../package.json' -const {version} = packageJson +const { version } = packageJson const Catalog = () => { @@ -56,7 +57,7 @@ const Catalog = () => { } = useGeneralStore(state => state); const { anonymousMode } = useAnonModeStore(); - + const nameRef = useRef(); const subjectRef = useRef(); const commentRef = useRef(); @@ -67,10 +68,10 @@ const Catalog = () => { const selectedThreadCidRef = useRef(null); const navigate = useNavigate(); - + const [, setNewErrorMessage] = useError(); const [, setNewSuccessMessage] = useSuccess(); - + const [triggerPublishComment, setTriggerPublishComment] = useState(false); const [prevScrollPos, setPrevScrollPos] = useState(0); const [visible, setVisible] = useState(true); @@ -82,15 +83,16 @@ const Catalog = () => { const [deletePost, setDeletePost] = useState(false); const [isImageSearchOpen, setIsImageSearchOpen] = useState(false); const [commentCid, setCommentCid] = useState(null); - const [menuPosition, setMenuPosition] = useState({top: 0, left: 0}); + const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 }); const [openMenuCid, setOpenMenuCid] = useState(null); const [executeAnonMode, setExecuteAnonMode] = useState(false); const [isCreateBoardOpen, setIsCreateBoardOpen] = useState(false); - const account = useAccount(); - const { feed, loadMore } = useFeed({subplebbitAddresses: [`${selectedAddress}`], sortType: 'active'}); + const { feed, hasMore, loadMore } = useFeed({ subplebbitAddresses: [`${selectedAddress}`], sortType: 'active' }); const { subplebbitAddress } = useParams(); - const subplebbit = useSubplebbit({subplebbitAddress: selectedAddress}); + const subplebbit = useSubplebbit({ subplebbitAddress: selectedAddress }); + const account = useAccount(); + const stateString = useStateString(subplebbit); let feedWithDescriptionAndRules = []; @@ -98,18 +100,18 @@ const Catalog = () => { if (subplebbit.rules) { - feedWithDescriptionAndRules.push({type: 'rules', content: subplebbit.rules}); + feedWithDescriptionAndRules.push({ type: 'rules', content: subplebbit.rules }); } if (subplebbit.description) { - feedWithDescriptionAndRules.push({type: 'description', content: subplebbit.description}); -} + feedWithDescriptionAndRules.push({ type: 'description', content: subplebbit.description }); + } useEffect(() => { - if (subplebbit.roles !== undefined) { + if (subplebbit.roles !== undefined) { const role = subplebbit.roles[account?.author.address]?.role; - + if (role === 'moderator' || role === 'admin' || role === 'owner') { setIsModerator(true); } else { @@ -135,12 +137,12 @@ const Catalog = () => { } else { document.removeEventListener('click', handleOutsideClick); } - + return () => { document.removeEventListener('click', handleOutsideClick); }; }, [openMenuCid, handleOutsideClick]); - + useEffect(() => { @@ -165,8 +167,8 @@ const Catalog = () => { } }, [errorString, setNewErrorMessage]); - - const { subscribed, subscribe, unsubscribe } = useSubscribe({subplebbitAddress: selectedAddress}); + + const { subscribed, subscribe, unsubscribe } = useSubscribe({ subplebbitAddress: selectedAddress }); useEffect(() => { @@ -190,17 +192,16 @@ const Catalog = () => { setVisible(prevScrollPos > currentScrollPos || currentScrollPos < 10); setPrevScrollPos(currentScrollPos); }, 50); - + window.addEventListener('scroll', debouncedHandleScroll); - + return () => window.removeEventListener('scroll', debouncedHandleScroll); }, [prevScrollPos, visible]); const tryLoadMore = async () => { - try {loadMore()} - catch (e) - {await new Promise(resolve => setTimeout(resolve, 1000))} + try { loadMore() } + catch (e) { await new Promise(resolve => setTimeout(resolve, 1000)) } }; @@ -223,7 +224,7 @@ const Catalog = () => { const onChallenge = async (challenges, comment) => { setPendingComment(comment); let challengeAnswers = []; - + try { challengeAnswers = await getChallengeAnswersFromUser(challenges) } @@ -234,7 +235,7 @@ const Catalog = () => { await comment.publishChallengeAnswers(challengeAnswers) } }; - + useEffect(() => { setPublishCommentOptions((prevPublishCommentOptions) => ({ @@ -242,7 +243,7 @@ const Catalog = () => { subplebbitAddress: selectedAddress, })); }, [selectedAddress]); - + const [publishCommentOptions, setPublishCommentOptions] = useState({ subplebbitAddress: selectedAddress, @@ -252,7 +253,7 @@ const Catalog = () => { setNewErrorMessage(error.message); console.log(error); }, }); - + const { publishComment, index } = usePublishComment(publishCommentOptions); @@ -263,7 +264,7 @@ const Catalog = () => { } }, [index, navigate, setPendingCommentIndex]); - + const resetFields = useCallback(() => { if (nameRef.current) { nameRef.current.value = ''; @@ -282,7 +283,7 @@ const Catalog = () => { const handleSubmit = async (event) => { event.preventDefault(); - + if (subjectRef.current.value === "") { setNewErrorMessage('Subject field is mandatory'); return; @@ -305,24 +306,24 @@ const Catalog = () => { const updateSigner = useCallback(async () => { if (anonymousMode) { setExecuteAnonMode(true); - + let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {}; let signer; - + if (!storedSigners[selectedThreadCidRef]) { signer = await account?.plebbit.createSigner(); storedSigners[selectedThreadCidRef] = { privateKey: signer?.privateKey, address: signer?.address }; localStorage.setItem('storedSigners', JSON.stringify(storedSigners)); } else { const signerPrivateKey = storedSigners[selectedThreadCidRef].privateKey; - + try { - signer = await account?.plebbit.createSigner({type: 'ed25519', privateKey: signerPrivateKey}); + signer = await account?.plebbit.createSigner({ type: 'ed25519', privateKey: signerPrivateKey }); } catch (error) { console.log(error); } } - + setPublishCommentOptions(prevPublishCommentOptions => { const newPublishCommentOptions = { ...prevPublishCommentOptions, @@ -332,16 +333,16 @@ const Catalog = () => { address: signer?.address }, }; - + if (JSON.stringify(prevPublishCommentOptions) !== JSON.stringify(newPublishCommentOptions)) { return newPublishCommentOptions; } - + return prevPublishCommentOptions; }); } }, [selectedThreadCidRef, anonymousMode, account]); - + useEffect(() => { updateSigner(); }, [updateSigner]); @@ -357,20 +358,20 @@ const Catalog = () => { setExecuteAnonMode(false); } }, [publishCommentOptions, triggerPublishComment, publishComment, resetFields]); - - + + const getChallengeAnswersFromUser = async (challenges) => { setChallengesArray(challenges); - + return new Promise((resolve, reject) => { const imageString = challenges?.challenges[0].challenge; const imageSource = `data:image/png;base64,${imageString}`; const challengeImg = new Image(); challengeImg.src = imageSource; - + challengeImg.onload = () => { setIsCaptchaOpen(true); - + const handleKeyDown = async (event) => { if (event.key === 'Enter') { const currentCaptchaResponse = captchaResponse; @@ -383,10 +384,10 @@ const Catalog = () => { setCaptchaResponse(''); document.addEventListener('keydown', handleKeyDown); - + setResolveCaptchaPromise(resolve); }; - + challengeImg.onerror = () => { reject(setNewErrorMessage('Could not load challenges')); }; @@ -404,8 +405,8 @@ const Catalog = () => { setNewErrorMessage(error.message); console.log(error); }, }); - - + + const { publishCommentEdit } = usePublishCommentEdit(publishCommentEditOptions); @@ -453,8 +454,8 @@ const Catalog = () => { setOriginalCommentContent(comment.content); setIsEditModalOpen(true); } - - + + useEffect(() => { setPublishCommentEditOptions((prevOptions) => ({ ...prevOptions, @@ -470,7 +471,7 @@ const Catalog = () => { } }, [editedComment]); - + useEffect(() => { if (publishCommentEditOptions && triggerPublishCommentEdit) { (async () => { @@ -518,56 +519,56 @@ const Catalog = () => { setIsCreateBoardOpen(false)} /> + selectedStyle={selectedStyle} + isOpen={isCreateBoardOpen} + closeModal={() => setIsCreateBoardOpen(false)} /> setIsSettingsOpen(false)} /> - {setIsModerationOpen(false); setDeletePost(false)}} - deletePost={deletePost} /> + selectedStyle={selectedStyle} + isOpen={isSettingsOpen} + closeModal={() => setIsSettingsOpen(false)} /> + { setIsModerationOpen(false); setDeletePost(false) }} + deletePost={deletePost} /> setIsEditModalOpen(false)} - originalCommentContent={originalCommentContent} /> + selectedStyle={selectedStyle} + isOpen={isEditModalOpen} + closeModal={() => setIsEditModalOpen(false)} + originalCommentContent={originalCommentContent} /> <> - - [ + + [ window.scrollTo(0, 0)}>All -  /  + / window.scrollTo(0, 0)}>Subscriptions - ] [ - {defaultSubplebbits.map((subplebbit, index) => ( - - {index === 0 ? null : "\u00a0"} - { - setSelectedTitle(subplebbit.title); - setSelectedAddress(subplebbit.address); - }} - >{subplebbit.title ? subplebbit.title : subplebbit.address} - {index !== defaultSubplebbits.length - 1 ? " /" : null} - - ))} - ] - + ] [ + {defaultSubplebbits.map((subplebbit, index) => ( + + {index === 0 ? null : "\u00a0"} + { + setSelectedTitle(subplebbit.title); + setSelectedAddress(subplebbit.address); + }} + >{subplebbit.title ? subplebbit.title : subplebbit.address} + {index !== defaultSubplebbits.length - 1 ? " /" : null} + + ))} + ] + [ - { - window.electron && window.electron.isElectron ? ( - setIsCreateBoardOpen(true) - ) : ( - alert( - 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n' + { + window.electron && window.electron.isElectron ? ( + setIsCreateBoardOpen(true) + ) : ( + alert( + 'You can create a board with the desktop version of plebchan, which you can download from here: https://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can also run a board (called "subplebbit") using plebbit-cli: https://github.com/plebbit/plebbit-cli\n\n' + ) ) - ) - } + } }>Create Board ] [ @@ -586,20 +587,20 @@ const Catalog = () => { {defaultSubplebbits.map(subplebbit => ( - - ))} -   - alert( - 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n' + + ))} + + alert( + 'You can create a board with the desktop version of plebchan, which you can download from here: https://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can also run a board (called "subplebbit") using plebbit-cli: https://github.com/plebbit/plebbit-cli\n\n' ) }>Create Board
setIsSettingsOpen(true)}>Settings   - {handleStyleChange({target: {value: "Yotsuba"}}); window.scrollTo(0, 0);}}>Home + { handleStyleChange({ target: { value: "Yotsuba" } }); window.scrollTo(0, 0); }}>Home
@@ -612,15 +613,15 @@ const Catalog = () => {
- <> + <>
{subplebbit.title ?? null}
p/{subplebbit.address} - +
- +
@@ -628,12 +629,12 @@ const Catalog = () => {
[ - event.target.style.cursor='pointer'}>Start a New Thread + event.target.style.cursor = 'pointer'}>Start a New Thread ]
- event.target.style.cursor='pointer'}>Start a New Thread + event.target.style.cursor = 'pointer'}>Start a New Thread
@@ -652,9 +653,9 @@ const Catalog = () => { Subject - - + + @@ -679,7 +680,7 @@ const Catalog = () => {
Style: -   + @@ -1163,43 +1187,43 @@ const Catalog = () => { marginTop: "42px", }}> <> - - [ + + [ window.scrollTo(0, 0)}>All -  /  + / window.scrollTo(0, 0)}>Subscriptions - ]  - - {defaultSubplebbits.map((subplebbit, index) => ( - - {index === 0 ? null : "\u00a0"} - { - setSelectedTitle(subplebbit.title); - setSelectedAddress(subplebbit.address); - }} - >{subplebbit.title ? subplebbit.title : subplebbit.address} - {index !== defaultSubplebbits.length - 1 ? " /" : null} + ]  - ))} + {defaultSubplebbits.map((subplebbit, index) => ( + + {index === 0 ? null : "\u00a0"} + { + setSelectedTitle(subplebbit.title); + setSelectedAddress(subplebbit.address); + }} + >{subplebbit.title ? subplebbit.title : subplebbit.address} + {index !== defaultSubplebbits.length - 1 ? " /" : null} + + ))} - [ - { - window.electron && window.electron.isElectron ? ( - setIsCreateBoardOpen(true) - ) : ( - alert( - 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n' - ) - ) - } - }>Create Board - ] + [ + { + window.electron && window.electron.isElectron ? ( + setIsCreateBoardOpen(true) + ) : ( + alert( + 'You can create a board with the desktop version of plebchan, which you can download from here: https://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can also run a board (called "subplebbit") using plebbit-cli: https://github.com/plebbit/plebbit-cli\n\n' + ) + ) + } + }>Create Board + ] [ setIsSettingsOpen(true)}>Settings ] [ - handleStyleChange({target: {value: "Yotsuba"}} + handleStyleChange({ target: { value: "Yotsuba" } } )}>Home ] @@ -1216,13 +1240,13 @@ const Catalog = () => { marginTop: "5px", marginBottom: "15px", }}> - About -  •  - App + About  •  - Twitter -  •  - Telegram + App +  •  + Twitter +  •  + Telegram
diff --git a/src/components/views/Description.jsx b/src/components/views/Description.jsx index 322ac86c..f322a0dc 100644 --- a/src/components/views/Description.jsx +++ b/src/components/views/Description.jsx @@ -1,25 +1,25 @@ +import { useSubplebbit } from '@plebbit/plebbit-react-hooks'; +import { debounce } from 'lodash'; import React, { useCallback, useEffect, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; import { Helmet } from 'react-helmet-async'; import { Link, useNavigate, useParams } from 'react-router-dom'; import { Tooltip } from 'react-tooltip'; -import { useSubplebbit } from '@plebbit/plebbit-react-hooks'; -import { debounce } from 'lodash'; -import { Container, NavBar, Header, Break, PostMenu, PostForm } from '../styled/views/Board.styled'; -import { TopBar, BoardForm, Footer, ReplyFormLink} from '../styled/views/Thread.styled'; -import { PostMenuCatalog } from '../styled/views/Catalog.styled'; -import ImageBanner from '../ImageBanner'; -import Post from '../Post'; -import CreateBoardModal from '../modals/CreateBoardModal'; -import AdminListModal from '../modals/AdminListModal'; -import OfflineIndicator from '../OfflineIndicator'; -import SettingsModal from '../modals/SettingsModal'; +import packageJson from '../../../package.json'; +import useGeneralStore from '../../hooks/stores/useGeneralStore'; import getDate from '../../utils/getDate'; import handleImageClick from '../../utils/handleImageClick'; import handleStyleChange from '../../utils/handleStyleChange'; -import useGeneralStore from '../../hooks/stores/useGeneralStore'; -import packageJson from '../../../package.json' -const {version} = packageJson +import ImageBanner from '../ImageBanner'; +import OfflineIndicator from '../OfflineIndicator'; +import Post from '../Post'; +import AdminListModal from '../modals/AdminListModal'; +import CreateBoardModal from '../modals/CreateBoardModal'; +import SettingsModal from '../modals/SettingsModal'; +import { Break, Container, Header, NavBar, PostForm, PostMenu } from '../styled/views/Board.styled'; +import { PostMenuCatalog } from '../styled/views/Catalog.styled'; +import { BoardForm, Footer, ReplyFormLink, TopBar } from '../styled/views/Thread.styled'; +const { version } = packageJson const Description = () => { @@ -31,7 +31,7 @@ const Description = () => { selectedThread, setSelectedTitle, } = useGeneralStore(state => state); - + const navigate = useNavigate(); const threadMenuRefs = useRef({}); @@ -41,13 +41,13 @@ const Description = () => { const [isAdminListOpen, setIsAdminListOpen] = useState(false); const [prevScrollPos, setPrevScrollPos] = useState(0); const [visible, setVisible] = useState(true); - const [menuPosition, setMenuPosition] = useState({top: 0, left: 0}); + const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 }); const [openMenuCid, setOpenMenuCid] = useState(null); const [isCreateBoardOpen, setIsCreateBoardOpen] = useState(false); - const { subplebbitAddress } = useParams(); - const subplebbit = useSubplebbit({subplebbitAddress: selectedAddress}); - + const { subplebbitAddress, threadCid } = useParams(); + const subplebbit = useSubplebbit({ subplebbitAddress: selectedAddress }); + const handleOptionClick = () => { setOpenMenuCid(null); @@ -66,13 +66,13 @@ const Description = () => { } else { document.removeEventListener('click', handleOutsideClick); } - + return () => { document.removeEventListener('click', handleOutsideClick); }; }, [openMenuCid, handleOutsideClick]); - + useEffect(() => { window.scrollTo(0, 0); }, []); @@ -99,9 +99,9 @@ const Description = () => { setVisible(prevScrollPos > currentScrollPos || currentScrollPos < 10); setPrevScrollPos(currentScrollPos); }, 50); - + window.addEventListener('scroll', debouncedHandleScroll); - + return () => window.removeEventListener('scroll', debouncedHandleScroll); }, [prevScrollPos, visible]); @@ -127,57 +127,57 @@ const Description = () => { return ( <> - + <title> {"Board Description - " + (subplebbit.title || subplebbit.address) + " - plebchan"} - - + + setIsCreateBoardOpen(false)} /> + selectedStyle={selectedStyle} + isOpen={isCreateBoardOpen} + closeModal={() => setIsCreateBoardOpen(false)} /> setIsAdminListOpen(false)} - roles={subplebbit.roles} /> + selectedStyle={selectedStyle} + isOpen={isAdminListOpen} + closeModal={() => setIsAdminListOpen(false)} + roles={subplebbit.roles} /> setIsSettingsOpen(false)} /> + selectedStyle={selectedStyle} + isOpen={isSettingsOpen} + closeModal={() => setIsSettingsOpen(false)} /> <> - - [ + + [ window.scrollTo(0, 0)}>All -  /  + / window.scrollTo(0, 0)}>Subscriptions - ] [ - {defaultSubplebbits.map((subplebbit, index) => ( - - {index === 0 ? null : "\u00a0"} - { - setSelectedTitle(subplebbit.title); - setSelectedAddress(subplebbit.address); - }} - >{subplebbit.title ? subplebbit.title : subplebbit.address} - {index !== defaultSubplebbits.length - 1 ? " /" : null} - - ))} - ] - + ] [ + {defaultSubplebbits.map((subplebbit, index) => ( + + {index === 0 ? null : "\u00a0"} + { + setSelectedTitle(subplebbit.title); + setSelectedAddress(subplebbit.address); + }} + >{subplebbit.title ? subplebbit.title : subplebbit.address} + {index !== defaultSubplebbits.length - 1 ? " /" : null} + + ))} + ] + [ - { - window.electron && window.electron.isElectron ? ( - setIsCreateBoardOpen(true) - ) : ( - alert( - 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n' + { + window.electron && window.electron.isElectron ? ( + setIsCreateBoardOpen(true) + ) : ( + alert( + 'You can create a board with the desktop version of plebchan, which you can download from here: https://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can also run a board (called "subplebbit") using plebbit-cli: https://github.com/plebbit/plebbit-cli\n\n' + ) ) - ) - } + } }>Create Board ] [ @@ -196,20 +196,20 @@ const Description = () => { {defaultSubplebbits.map(subplebbit => ( - - ))} -   - alert( - 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n' + + ))} + + alert( + 'You can create a board with the desktop version of plebchan, which you can download from here: https://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can also run a board (called "subplebbit") using plebbit-cli: https://github.com/plebbit/plebbit-cli\n\n' ) }>Create Board
setIsSettingsOpen(true)}>Settings   - {handleStyleChange({target: {value: "Yotsuba"}}); window.scrollTo(0, 0);}}>Home + { handleStyleChange({ target: { value: "Yotsuba" } }); window.scrollTo(0, 0); }}>Home
@@ -222,33 +222,43 @@ const Description = () => {
- <> + <>
{subplebbit.title ?? null}
p/{subplebbit.address} - +
- + - -
- {window.scrollTo(0, 0)}}> + +
+ { window.scrollTo(0, 0) }}> Return
+
+ + + [ + window.location.reload()} + onMouseOver={(event) => event.target.style.cursor = 'pointer'} + onTouchStart={() => window.location.reload()}>Refresh + ] + +
- {window.scrollTo(0, 0)}}>Catalog + { window.scrollTo(0, 0) }}>Catalog
- window.scrollTo(0, document.body.scrollHeight)} onMouseOver={(event) => event.target.style.cursor='pointer'}>Bottom + window.scrollTo(0, document.body.scrollHeight)} onMouseOver={(event) => event.target.style.cursor = 'pointer'}>Bottom
@@ -256,7 +266,7 @@ const Description = () => { Style: -   + @@ -460,43 +479,43 @@ const Description = () => { marginTop: "42px", }}> <> - - [ + + [ window.scrollTo(0, 0)}>All -  /  + / window.scrollTo(0, 0)}>Subscriptions - ]  - - {defaultSubplebbits.map((subplebbit, index) => ( - - {index === 0 ? null : "\u00a0"} - { - setSelectedTitle(subplebbit.title); - setSelectedAddress(subplebbit.address); - }} - >{subplebbit.title ? subplebbit.title : subplebbit.address} - {index !== defaultSubplebbits.length - 1 ? " /" : null} + ]  - ))} - - [ - { - window.electron && window.electron.isElectron ? ( - setIsCreateBoardOpen(true) - ) : ( - alert( - 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n' - ) - ) - } - }>Create Board - ] + {defaultSubplebbits.map((subplebbit, index) => ( + + {index === 0 ? null : "\u00a0"} + { + setSelectedTitle(subplebbit.title); + setSelectedAddress(subplebbit.address); + }} + >{subplebbit.title ? subplebbit.title : subplebbit.address} + {index !== defaultSubplebbits.length - 1 ? " /" : null} + + ))} + + [ + { + window.electron && window.electron.isElectron ? ( + setIsCreateBoardOpen(true) + ) : ( + alert( + 'You can create a board with the desktop version of plebchan, which you can download from here: https://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can also run a board (called "subplebbit") using plebbit-cli: https://github.com/plebbit/plebbit-cli\n\n' + ) + ) + } + }>Create Board + ] [ setIsSettingsOpen(true)}>Settings ] [ - handleStyleChange({target: {value: "Yotsuba"}} + handleStyleChange({ target: { value: "Yotsuba" } } )}>Home ] @@ -513,13 +532,13 @@ const Description = () => { marginTop: "5px", marginBottom: "15px", }}> - About -  •  - App + About  •  - Twitter -  •  - Telegram + App +  •  + Twitter +  •  + Telegram
diff --git a/src/components/views/SubscriptionsCatalog.jsx b/src/components/views/SubscriptionsCatalog.jsx index a3d6404e..f67619dc 100755 --- a/src/components/views/SubscriptionsCatalog.jsx +++ b/src/components/views/SubscriptionsCatalog.jsx @@ -1,32 +1,32 @@ -import React, { useCallback, useEffect, useRef, useState } from 'react'; -import { createPortal } from 'react-dom'; -import { Helmet } from 'react-helmet-async'; -import { Link, useNavigate} from 'react-router-dom'; -import { confirmAlert } from 'react-confirm-alert'; -import { Tooltip } from 'react-tooltip'; -import { VirtuosoGrid } from 'react-virtuoso'; import { useAccount, useFeed, usePublishCommentEdit, useSubplebbits } from '@plebbit/plebbit-react-hooks'; import { debounce } from 'lodash'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; +import { confirmAlert } from 'react-confirm-alert'; +import { createPortal } from 'react-dom'; +import { Helmet } from 'react-helmet-async'; +import InfiniteScroll from 'react-infinite-scroller'; +import { Link, useNavigate } from 'react-router-dom'; +import { Tooltip } from 'react-tooltip'; +import packageJson from '../../../package.json'; import useGeneralStore from '../../hooks/stores/useGeneralStore'; -import { Container, NavBar, Header, Break, PostMenu, BoardForm } from '../styled/views/Board.styled'; -import { Threads, PostMenuCatalog, GridContainer } from '../styled/views/Catalog.styled'; -import { TopBar, Footer, AuthorDeleteAlert } from '../styled/views/Thread.styled'; -import CatalogLoader from '../CatalogLoader'; -import EditModal from '../modals/EditModal'; -import ImageBanner from '../ImageBanner'; -import VerifiedAuthor from '../VerifiedAuthor'; -import CreateBoardModal from '../modals/CreateBoardModal'; -import ModerationModal from '../modals/ModerationModal'; -import OfflineIndicator from '../OfflineIndicator'; -import SettingsModal from '../modals/SettingsModal'; -import countLinks from '../../utils/countLinks'; -import getCommentMediaInfo from '../../utils/getCommentMediaInfo'; -import handleStyleChange from '../../utils/handleStyleChange'; import useError from '../../hooks/useError'; import useFeedStateString from '../../hooks/useFeedStateString'; import useSuccess from '../../hooks/useSuccess'; -import packageJson from '../../../package.json' -const {version} = packageJson +import countLinks from '../../utils/countLinks'; +import getCommentMediaInfo from '../../utils/getCommentMediaInfo'; +import handleStyleChange from '../../utils/handleStyleChange'; +import CatalogLoader from '../CatalogLoader'; +import ImageBanner from '../ImageBanner'; +import OfflineIndicator from '../OfflineIndicator'; +import VerifiedAuthor from '../VerifiedAuthor'; +import CreateBoardModal from '../modals/CreateBoardModal'; +import EditModal from '../modals/EditModal'; +import ModerationModal from '../modals/ModerationModal'; +import SettingsModal from '../modals/SettingsModal'; +import { BoardForm, Break, Container, Header, NavBar, PostMenu } from '../styled/views/Board.styled'; +import { PostMenuCatalog, Threads } from '../styled/views/Catalog.styled'; +import { AuthorDeleteAlert, Footer, TopBar } from '../styled/views/Thread.styled'; +const { version } = packageJson const SubscriptionsCatalog = () => { @@ -67,27 +67,27 @@ const SubscriptionsCatalog = () => { const [deletePost, setDeletePost] = useState(false); const [isImageSearchOpen, setIsImageSearchOpen] = useState(false); const [commentCid, setCommentCid] = useState(null); - const [menuPosition, setMenuPosition] = useState({top: 0, left: 0}); + const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 }); const [openMenuCid, setOpenMenuCid] = useState(null); const [moderatorPermissions, setModeratorPermissions] = useState({}); const [isCreateBoardOpen, setIsCreateBoardOpen] = useState(false); - const { feed, loadMore } = useFeed({subplebbitAddresses: account?.subscriptions, sortType: 'active'}); + const { feed, hasMore, loadMore } = useFeed({ subplebbitAddresses: account?.subscriptions, sortType: 'active' }); const [selectedFeed, setSelectedFeed] = useState(feed.sort((a, b) => b.timestamp - a.timestamp)); - const {subplebbits} = useSubplebbits({subplebbitAddresses: account?.subscriptions, sortType: 'active'}); + const { subplebbits } = useSubplebbits({ subplebbitAddresses: account?.subscriptions, sortType: 'active' }); const stateString = useFeedStateString(subplebbits); useEffect(() => { let permissions = {}; - + selectedFeed.forEach(thread => { const subplebbit = subplebbits.find(s => s && s.address === thread.subplebbitAddress); - - if (subplebbit && subplebbit.roles) { + + if (subplebbit && subplebbit.roles) { const role = subplebbit.roles[account?.author.address]?.role; - + if (role === 'moderator' || role === 'admin' || role === 'owner') { permissions[thread.subplebbitAddress] = true; } else { @@ -95,9 +95,9 @@ const SubscriptionsCatalog = () => { } } }); - + setModeratorPermissions(permissions); - }, [account?.author.address, selectedFeed, subplebbits]); + }, [account?.author.address, selectedFeed, subplebbits]); const handleOptionClick = () => { @@ -118,7 +118,7 @@ const SubscriptionsCatalog = () => { } else { document.removeEventListener('click', handleOutsideClick); } - + return () => { document.removeEventListener('click', handleOutsideClick); }; @@ -131,24 +131,23 @@ const SubscriptionsCatalog = () => { setVisible(prevScrollPos > currentScrollPos || currentScrollPos < 10); setPrevScrollPos(currentScrollPos); }, 50); - + window.addEventListener('scroll', debouncedHandleScroll); - + return () => window.removeEventListener('scroll', debouncedHandleScroll); }, [prevScrollPos, visible]); const tryLoadMore = async () => { - try {loadMore()} - catch (e) - {await new Promise(resolve => setTimeout(resolve, 1000))} + try { loadMore() } + catch (e) { await new Promise(resolve => setTimeout(resolve, 1000)) } }; const onChallengeVerification = (challengeVerification) => { if (challengeVerification.challengeSuccess === true) { - setNewSuccessMessage('Challenge Success'); - } + setNewSuccessMessage('Challenge Success'); + } else if (challengeVerification.challengeSuccess === false) { setNewErrorMessage(`Challenge Failed, reason: ${challengeVerification.reason}. Errors: ${challengeVerification.errors}`); console.log('challenge failed', challengeVerification); @@ -172,16 +171,16 @@ const SubscriptionsCatalog = () => { const getChallengeAnswersFromUser = async (challenges) => { setChallengesArray(challenges); - + return new Promise((resolve, reject) => { const imageString = challenges?.challenges[0].challenge; const imageSource = `data:image/png;base64,${imageString}`; const challengeImg = new Image(); challengeImg.src = imageSource; - + challengeImg.onload = () => { setIsCaptchaOpen(true); - + const handleKeyDown = async (event) => { if (event.key === 'Enter') { const currentCaptchaResponse = useGeneralStore.getState().captchaResponse; @@ -197,7 +196,7 @@ const SubscriptionsCatalog = () => { setResolveCaptchaPromise(resolve); }; - + challengeImg.onerror = () => { reject(setNewErrorMessage('Could not load challenges')); }; @@ -214,8 +213,8 @@ const SubscriptionsCatalog = () => { setNewErrorMessage(error.message); console.log(error); }, }); - - + + const { publishCommentEdit } = usePublishCommentEdit(publishCommentEditOptions); @@ -262,8 +261,8 @@ const SubscriptionsCatalog = () => { setOriginalCommentContent(comment.content); setIsEditModalOpen(true); } - - + + useEffect(() => { setPublishCommentEditOptions((prevOptions) => ({ ...prevOptions, @@ -279,7 +278,7 @@ const SubscriptionsCatalog = () => { } }, [editedComment, setIsAuthorEdit]); - + useEffect(() => { let isActive = true; if (publishCommentEditOptions && triggerPublishCommentEdit) { @@ -325,60 +324,60 @@ const SubscriptionsCatalog = () => { return ( <> - Subscriptions - Catalog - plebchan + Subscriptions - Catalog - plebchan setIsCreateBoardOpen(false)} /> + selectedStyle={selectedStyle} + isOpen={isCreateBoardOpen} + closeModal={() => setIsCreateBoardOpen(false)} /> setIsSettingsOpen(false)} /> - {setIsModerationOpen(false); setDeletePost(false)}} - deletePost={deletePost} /> + selectedStyle={selectedStyle} + isOpen={isSettingsOpen} + closeModal={() => setIsSettingsOpen(false)} /> + { setIsModerationOpen(false); setDeletePost(false) }} + deletePost={deletePost} /> setIsEditModalOpen(false)} - originalCommentContent={originalCommentContent} /> + selectedStyle={selectedStyle} + isOpen={isEditModalOpen} + closeModal={() => setIsEditModalOpen(false)} + originalCommentContent={originalCommentContent} /> <> - - [ + + [ window.scrollTo(0, 0)}>All -  /  + / window.scrollTo(0, 0)}>Subscriptions - ] [ - {defaultSubplebbits.map((subplebbit, index) => ( - - {index === 0 ? null : "\u00a0"} - { - setSelectedTitle(subplebbit.title); - setSelectedAddress(subplebbit.address); - }} - >{subplebbit.title ? subplebbit.title : subplebbit.address} - {index !== defaultSubplebbits.length - 1 ? " /" : null} - - ))} - ] - + ] [ + {defaultSubplebbits.map((subplebbit, index) => ( + + {index === 0 ? null : "\u00a0"} + { + setSelectedTitle(subplebbit.title); + setSelectedAddress(subplebbit.address); + }} + >{subplebbit.title ? subplebbit.title : subplebbit.address} + {index !== defaultSubplebbits.length - 1 ? " /" : null} + + ))} + ] + [ - { - window.electron && window.electron.isElectron ? ( - setIsCreateBoardOpen(true) - ) : ( - alert( - 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n' + { + window.electron && window.electron.isElectron ? ( + setIsCreateBoardOpen(true) + ) : ( + alert( + 'You can create a board with the desktop version of plebchan, which you can download from here: https://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can also run a board (called "subplebbit") using plebbit-cli: https://github.com/plebbit/plebbit-cli\n\n' + ) ) - ) - } + } }>Create Board ] [ @@ -397,20 +396,20 @@ const SubscriptionsCatalog = () => { {defaultSubplebbits.map(subplebbit => ( - - ))} -   - alert( - 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n' + + ))} + + alert( + 'You can create a board with the desktop version of plebchan, which you can download from here: https://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can also run a board (called "subplebbit") using plebbit-cli: https://github.com/plebbit/plebbit-cli\n\n' ) }>Create Board
setIsSettingsOpen(true)}>Settings   - {handleStyleChange({target: {value: "Yotsuba"}}); window.scrollTo(0, 0);}}>Home + { handleStyleChange({ target: { value: "Yotsuba" } }); window.scrollTo(0, 0); }}>Home
@@ -423,7 +422,7 @@ const SubscriptionsCatalog = () => {
- <> + <>
Subscriptions
{account?.subscriptions.length < 1 ? (
You haven't subscribed to any board yet.
@@ -432,7 +431,7 @@ const SubscriptionsCatalog = () => { You have subscribed to {account?.subscriptions.length} board{account?.subscriptions.length > 1 ? "s" : null}. )} - + @@ -440,7 +439,7 @@ const SubscriptionsCatalog = () => {
Style: -   + @@ -700,40 +715,40 @@ const SubscriptionsCatalog = () => { - <> - - [ + <> + + [ window.scrollTo(0, 0)}>Subscriptions - ] [ - {defaultSubplebbits.map((subplebbit, index) => ( - - {index === 0 ? null : "\u00a0"} - handleClickTitle(subplebbit.title, subplebbit.address)} - >{subplebbit.title ? subplebbit.title : subplebbit.address} - {index !== defaultSubplebbits.length - 1 ? " /" : null} - - ))} - ] - + ] [ + {defaultSubplebbits.map((subplebbit, index) => ( + + {index === 0 ? null : "\u00a0"} + handleClickTitle(subplebbit.title, subplebbit.address)} + >{subplebbit.title ? subplebbit.title : subplebbit.address} + {index !== defaultSubplebbits.length - 1 ? " /" : null} + + ))} + ] + - [ - { - window.electron && window.electron.isElectron ? ( - setIsCreateBoardOpen(true) - ) : ( - alert( - 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n' - ) - ) - } - }>Create Board - ] + [ + { + window.electron && window.electron.isElectron ? ( + setIsCreateBoardOpen(true) + ) : ( + alert( + 'You can create a board with the desktop version of plebchan, which you can download from here: https://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can also run a board (called "subplebbit") using plebbit-cli: https://github.com/plebbit/plebbit-cli\n\n' + ) + ) + } + }>Create Board + ] [ setIsSettingsOpen(true)}>Settings ] [ - handleStyleChange({target: {value: "Yotsuba"}} + handleStyleChange({ target: { value: "Yotsuba" } } )}>Home ] @@ -750,13 +765,13 @@ const SubscriptionsCatalog = () => { marginTop: "5px", marginBottom: "15px", }}> - About -  •  - App + About  •  - Twitter -  •  - Telegram + App +  •  + Twitter +  •  + Telegram
diff --git a/src/components/views/Thread.jsx b/src/components/views/Thread.jsx index a3988d30..c4e1d53a 100755 --- a/src/components/views/Thread.jsx +++ b/src/components/views/Thread.jsx @@ -41,7 +41,7 @@ import useSuccess from '../../hooks/useSuccess'; import useAnonModeStore from '../../hooks/stores/useAnonModeStore'; import useGeneralStore from '../../hooks/stores/useGeneralStore'; import packageJson from '../../../package.json' -const {version} = packageJson +const { version } = packageJson const Thread = () => { @@ -73,7 +73,7 @@ const Thread = () => { } = useGeneralStore(state => state); const { anonymousMode } = useAnonModeStore(); - + const account = useAccount(); const navigate = useNavigate(); const handleClickForm = useClickForm(); @@ -106,10 +106,10 @@ const Thread = () => { const [isImageSearchOpen, setIsImageSearchOpen] = useState(false); const [isModerator, setIsModerator] = useState(false); const [commentCid, setCommentCid] = useState(null); - const [menuPosition, setMenuPosition] = useState({top: 0, left: 0}); + const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 }); const [openMenuCid, setOpenMenuCid] = useState(null); const [outOfViewCid, setOutOfViewCid] = useState(null); - const [outOfViewPosition, setOutOfViewPosition] = useState({top: 0, left: 0}); + const [outOfViewPosition, setOutOfViewPosition] = useState({ top: 0, left: 0 }); const [postOnHoverHeight, setPostOnHoverHeight] = useState(0); const [executeAnonMode, setExecuteAnonMode] = useState(false); const [cidTracker, setCidTracker] = useState({}); @@ -121,9 +121,9 @@ const Thread = () => { useAnonMode(selectedThread, anonymousMode && executeAnonMode); - const comment = useComment({commentCid: selectedThread}); + const comment = useComment({ commentCid: selectedThread }); const { subplebbitAddress, threadCid } = useParams(); - const subplebbit = useSubplebbit({subplebbitAddress: comment.subplebbitAddress}); + const subplebbit = useSubplebbit({ subplebbitAddress: comment.subplebbitAddress }); const selectedAddress = subplebbit.address; const stateString = useStateString(comment); @@ -159,17 +159,17 @@ const Thread = () => { useEffect(() => { - if (subplebbit.roles !== undefined) { + if (subplebbit.roles !== undefined) { const role = subplebbit.roles[account?.author?.address]?.role; - + if (role === 'moderator' || role === 'admin' || role === 'owner') { setIsModerator(true); } else { setIsModerator(false); } } - }, [account?.author.address, subplebbit.roles]); - + }, [account?.author.address, subplebbit.roles]); + const handleOptionClick = () => { setOpenMenuCid(null); @@ -187,7 +187,7 @@ const Thread = () => { } else { document.removeEventListener('click', handleOutsideClick); } - + return () => { document.removeEventListener('click', handleOutsideClick); }; @@ -201,14 +201,14 @@ const Thread = () => { } }, [outOfViewCid]); - + useEffect(() => { window.scrollTo(0, 0); }, []); useEffect(() => { - if ( comment.state === "failed" && selectedAddress === undefined) { + if (comment.state === "failed" && selectedAddress === undefined) { navigate('/404'); } }, [selectedAddress, navigate, comment.state]); @@ -232,7 +232,7 @@ const Thread = () => { }, [errorString, setNewErrorMessage]); - const flattenedReplies = useMemo(() => + const flattenedReplies = useMemo(() => flattenCommentsPages(comment.replies), [comment.replies] ); @@ -244,7 +244,7 @@ const Thread = () => { }), [flattenedReplies, selectedThread]); - const { accountComments } = useAccountComments({filter}); + const { accountComments } = useAccountComments({ filter }); const accountRepliesNotYetInCommentReplies = useMemo(() => { @@ -255,7 +255,7 @@ const Thread = () => { const sortedReplies = useMemo(() => [ ...accountRepliesNotYetInCommentReplies, ...flattenedReplies - ].sort((a, b) => a.timestamp - b.timestamp + ].sort((a, b) => a.timestamp - b.timestamp ), [accountRepliesNotYetInCommentReplies, flattenedReplies]); // let post.jsx access full cid of user-typed short cid @@ -292,13 +292,13 @@ const Thread = () => { setVisible(prevScrollPos > currentScrollPos || currentScrollPos < 10); setPrevScrollPos(currentScrollPos); }, 50); - + window.addEventListener('scroll', debouncedHandleScroll); - + return () => window.removeEventListener('scroll', debouncedHandleScroll); }, [prevScrollPos, visible]); - + const onChallengeVerification = (challengeVerification) => { if (challengeVerification.challengeSuccess === true) { if (challengeVerification.publication?.cid !== undefined) { @@ -316,7 +316,7 @@ const Thread = () => { const onChallenge = async (challenges, comment) => { setPendingComment(comment); let challengeAnswers = []; - + try { challengeAnswers = await getChallengeAnswersFromUser(challenges) } @@ -328,7 +328,7 @@ const Thread = () => { } }; - + useEffect(() => { setPublishCommentOptions((prevPublishCommentOptions) => ({ ...prevPublishCommentOptions, @@ -336,7 +336,7 @@ const Thread = () => { })); }, [comment.subplebbitAddress]); - + const [publishCommentOptions, setPublishCommentOptions] = useState({ subplebbitAddress: comment.subplebbitAddress, onChallenge, @@ -356,7 +356,7 @@ const Thread = () => { } }, [index, setPendingCommentIndex]); - + const resetFields = useCallback(() => { if (nameRef.current) { nameRef.current.value = ''; @@ -380,8 +380,8 @@ const Thread = () => { setNewErrorMessage("Please enter a comment or link."); return; } - - + + setPublishCommentOptions((prevPublishCommentOptions) => ({ ...prevPublishCommentOptions, author: { @@ -395,28 +395,28 @@ const Thread = () => { setTriggerPublishComment(true); }; - + const updateSigner = useCallback(async () => { if (anonymousMode) { setExecuteAnonMode(true); - + let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {}; let signer; - + if (!storedSigners[selectedThread]) { signer = await account?.plebbit.createSigner(); storedSigners[selectedThread] = { privateKey: signer?.privateKey, address: signer?.address }; localStorage.setItem('storedSigners', JSON.stringify(storedSigners)); } else { const signerPrivateKey = storedSigners[selectedThread].privateKey; - + try { - signer = await account?.plebbit.createSigner({type: 'ed25519', privateKey: signerPrivateKey}); + signer = await account?.plebbit.createSigner({ type: 'ed25519', privateKey: signerPrivateKey }); } catch (error) { console.log(error); } } - + setPublishCommentOptions(prevPublishCommentOptions => { const newPublishCommentOptions = { ...prevPublishCommentOptions, @@ -426,23 +426,23 @@ const Thread = () => { address: signer?.address }, }; - + if (JSON.stringify(prevPublishCommentOptions) !== JSON.stringify(newPublishCommentOptions)) { return newPublishCommentOptions; } - + return prevPublishCommentOptions; }); } }, [selectedThread, anonymousMode, account]); - + useEffect(() => { if (anonymousMode) { updateSigner(); } }, [updateSigner, anonymousMode]); - - + + useEffect(() => { if (publishCommentOptions && triggerPublishComment) { (async () => { @@ -457,16 +457,16 @@ const Thread = () => { const getChallengeAnswersFromUser = async (challenges) => { setChallengesArray(challenges); - + return new Promise((resolve, reject) => { const imageString = challenges?.challenges[0].challenge; const imageSource = `data:image/png;base64,${imageString}`; const challengeImg = new Image(); challengeImg.src = imageSource; - + challengeImg.onload = () => { setIsCaptchaOpen(true); - + const handleKeyDown = async (event) => { if (event.key === 'Enter') { const currentCaptchaResponse = captchaResponse; @@ -482,7 +482,7 @@ const Thread = () => { setResolveCaptchaPromise(resolve); }; - + challengeImg.onerror = () => { reject(setNewErrorMessage('Could not load challenges')); }; @@ -500,8 +500,8 @@ const Thread = () => { setNewErrorMessage(error.message); console.log(error); }, }); - - + + const { publishCommentEdit } = usePublishCommentEdit(publishCommentEditOptions); @@ -548,8 +548,8 @@ const Thread = () => { setOriginalCommentContent(comment.content); setIsEditModalOpen(true); } - - + + useEffect(() => { setPublishCommentEditOptions((prevOptions) => ({ ...prevOptions, @@ -565,7 +565,7 @@ const Thread = () => { } }, [editedComment]); - + useEffect(() => { let isActive = true; if (publishCommentEditOptions && triggerPublishCommentEdit) { @@ -604,70 +604,70 @@ const Thread = () => { return ( <> - - {( - (comment.content?.slice(0, 40) ?? comment.title?.slice(0, 40) ?? "Thread") + " - " - + (selectedTitle ? selectedTitle : selectedAddress) - + " - plebchan" - )} - - + + {( + (comment.content?.slice(0, 40) ?? comment.title?.slice(0, 40) ?? "Thread") + " - " + + (selectedTitle ? selectedTitle : selectedAddress) + + " - plebchan" + )} + + setIsCreateBoardOpen(false)} /> - setIsReplyOpen(false)} /> + selectedStyle={selectedStyle} + isOpen={isCreateBoardOpen} + closeModal={() => setIsCreateBoardOpen(false)} /> + setIsReplyOpen(false)} /> setIsSettingsOpen(false)} /> - {setIsModerationOpen(false); setDeletePost(false)}} - deletePost={deletePost} /> + selectedStyle={selectedStyle} + isOpen={isSettingsOpen} + closeModal={() => setIsSettingsOpen(false)} /> + { setIsModerationOpen(false); setDeletePost(false) }} + deletePost={deletePost} /> setIsEditModalOpen(false)} - originalCommentContent={originalCommentContent} /> + selectedStyle={selectedStyle} + isOpen={isEditModalOpen} + closeModal={() => setIsEditModalOpen(false)} + originalCommentContent={originalCommentContent} /> <> - - [ + + [ window.scrollTo(0, 0)}>All -  /  + / window.scrollTo(0, 0)}>Subscriptions - ] [ - {defaultSubplebbits.map((subplebbit, index) => ( - - {index === 0 ? null : "\u00a0"} - { - setSelectedTitle(subplebbit.title); - setSelectedAddress(subplebbit.address); - }} - >{subplebbit.title ? subplebbit.title : subplebbit.address} - {index !== defaultSubplebbits.length - 1 ? " /" : null} - - ))} - ] - + ] [ + {defaultSubplebbits.map((subplebbit, index) => ( + + {index === 0 ? null : "\u00a0"} + { + setSelectedTitle(subplebbit.title); + setSelectedAddress(subplebbit.address); + }} + >{subplebbit.title ? subplebbit.title : subplebbit.address} + {index !== defaultSubplebbits.length - 1 ? " /" : null} + + ))} + ] + [ - { - window.electron && window.electron.isElectron ? ( - setIsCreateBoardOpen(true) - ) : ( - alert( - 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n' + { + window.electron && window.electron.isElectron ? ( + setIsCreateBoardOpen(true) + ) : ( + alert( + 'You can create a board with the desktop version of plebchan, which you can download from here: https://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can also run a board (called "subplebbit") using plebbit-cli: https://github.com/plebbit/plebbit-cli\n\n' + ) ) - ) - } + } }>Create Board ] [ @@ -686,20 +686,20 @@ const Thread = () => { {defaultSubplebbits.map(subplebbit => ( - - ))} -   - alert( - 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n' + + ))} + + alert( + 'You can create a board with the desktop version of plebchan, which you can download from here: https://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can also run a board (called "subplebbit") using plebbit-cli: https://github.com/plebbit/plebbit-cli\n\n' ) }>Create Board
setIsSettingsOpen(true)}>Settings   - {handleStyleChange({target: {value: "Yotsuba"}}); window.scrollTo(0, 0);}}>Home + { handleStyleChange({ target: { value: "Yotsuba" } }); window.scrollTo(0, 0); }}>Home
@@ -712,43 +712,43 @@ const Thread = () => {
- <> + <>
{subplebbit.title ?? null}
p/{subplebbit.address} - +
- +
- {window.scrollTo(0, 0)}}> + { window.scrollTo(0, 0) }}> Return
- {window.scrollTo(0, 0)}}>Catalog + { window.scrollTo(0, 0) }}>Catalog
- window.scrollTo(0, document.body.scrollHeight)} onMouseOver={(event) => event.target.style.cursor='pointer'}>Bottom + window.scrollTo(0, document.body.scrollHeight)} onMouseOver={(event) => event.target.style.cursor = 'pointer'}>Bottom
[ - {handleClickForm(); setSelectedShortCid(comment.shortCid)}} onMouseOver={(event) => event.target.style.cursor='pointer'}>Post a Reply + { handleClickForm(); setSelectedShortCid(comment.shortCid) }} onMouseOver={(event) => event.target.style.cursor = 'pointer'}>Post a Reply ]
- {handleClickForm(); setSelectedShortCid(comment.shortCid)}} onMouseOver={(event) => event.target.style.cursor='pointer'}>Post a Reply + { handleClickForm(); setSelectedShortCid(comment.shortCid) }} onMouseOver={(event) => event.target.style.cursor = 'pointer'}>Post a Reply
@@ -762,8 +762,8 @@ const Thread = () => { ) : ( )} - + @@ -789,7 +789,7 @@ const Thread = () => {
Style: -   + @@ -2197,7 +2239,7 @@ const Thread = () => {
- {setIsReplyOpen(true); setSelectedParentCid(comment.cid); setSelectedShortCid(comment.shortCid);}} onMouseOver={(event) => event.target.style.cursor='pointer'}>Post a Reply + { setIsReplyOpen(true); setSelectedParentCid(comment.cid); setSelectedShortCid(comment.shortCid); }} onMouseOver={(event) => event.target.style.cursor = 'pointer'}>Post a Reply
@@ -2206,17 +2248,17 @@ const Thread = () => { Return
-
+
Catalog
- window.scrollTo(0, 0)} - onMouseOver={(event) => event.target.style.cursor='pointer'} - onTouchStart={() => window.scrollTo(0, 0)} - style={{cursor: 'pointer', marginRight: "10px", marginLeft: "10px"}} + window.scrollTo(0, 0)} + onMouseOver={(event) => event.target.style.cursor = 'pointer'} + onTouchStart={() => window.scrollTo(0, 0)} + style={{ cursor: 'pointer', marginRight: "10px", marginLeft: "10px" }} >Top @@ -2224,8 +2266,8 @@ const Thread = () => {
) : (null)} - - )) : null} + + )) : null} {outOfViewCid && outOfViewPosition && createPortal(
{ feed={comment} />
- , document.body)} + , document.body)}