diff --git a/src/App.js b/src/App.js index 2438af07..8f6a090a 100644 --- a/src/App.js +++ b/src/App.js @@ -13,6 +13,7 @@ import Home from './components/views/Home'; import NotFound from './components/views/NotFound'; import Pending from './components/views/Pending'; import Subscriptions from './components/views/Subscriptions'; +import SubscriptionsCatalog from './components/views/SubscriptionsCatalog'; import Thread from './components/views/Thread'; import CaptchaModal from './components/CaptchaModal'; import { importAll } from './components/ImageBanner'; @@ -165,9 +166,9 @@ export default function App() { }> } /> - {/* }> + }> } /> - */} + } /> diff --git a/src/components/views/Subscriptions.jsx b/src/components/views/Subscriptions.jsx index 1097ed6d..5587b56c 100644 --- a/src/components/views/Subscriptions.jsx +++ b/src/components/views/Subscriptions.jsx @@ -1,6 +1,6 @@ import React, { Fragment, useEffect, useMemo, useState } from 'react'; import { Helmet } from 'react-helmet-async'; -import { Link, useNavigate, useParams } from 'react-router-dom'; +import { Link, useNavigate } from 'react-router-dom'; import { Tooltip } from 'react-tooltip'; import { Virtuoso } from 'react-virtuoso'; import { useAccount, useAccountComments, useFeed } from '@plebbit/plebbit-react-hooks'; @@ -52,8 +52,6 @@ const Subscriptions = () => { setSelectedFeed(feed.sort((a, b) => b.timestamp - a.timestamp)); }, [feed]); - const { subplebbitAddress } = useParams(); - const [errorMessage] = useState(null); useError(errorMessage, [errorMessage]); @@ -137,10 +135,6 @@ const Subscriptions = () => { setSelectedTitle(title); setSelectedAddress(address); setSelectedFeed(feed.filter(feed => feed.title === title)); - - if (subplebbitAddress === address) { - window.location.reload(); - } }; // mobile navbar board select functionality diff --git a/src/components/views/SubscriptionsCatalog.jsx b/src/components/views/SubscriptionsCatalog.jsx new file mode 100644 index 00000000..ac299979 --- /dev/null +++ b/src/components/views/SubscriptionsCatalog.jsx @@ -0,0 +1,363 @@ +import React, { Fragment, useEffect, useState } from 'react'; +import { Helmet } from 'react-helmet-async'; +import InfiniteScroll from 'react-infinite-scroller'; +import { Link, useNavigate } from 'react-router-dom'; +import { useAccount, useFeed } from '@plebbit/plebbit-react-hooks'; +import { debounce } from 'lodash'; +import useGeneralStore from '../../hooks/stores/useGeneralStore'; +import { Container, NavBar, Header, Break} from '../styled/Board.styled'; +import { Threads } from '../styled/Catalog.styled'; +import { TopBar, Footer } from '../styled/Thread.styled'; +import CatalogLoader from '../CatalogLoader'; +import ImageBanner from '../ImageBanner'; +import OfflineIndicator from '../OfflineIndicator'; +import SettingsModal from '../SettingsModal'; +import formatState from '../../utils/formatState'; +import getCommentMediaInfo from '../../utils/getCommentMediaInfo'; +import handleStyleChange from '../../utils/handleStyleChange'; +import useError from '../../hooks/useError'; +import packageJson from '../../../package.json' +const {version} = packageJson + + +const SubscriptionsCatalog = () => { + const { + defaultSubplebbits, + isSettingsOpen, setIsSettingsOpen, + selectedAddress, setSelectedAddress, + selectedStyle, + setSelectedThread, + setSelectedTitle, + } = useGeneralStore(state => state); + + const account = useAccount(); + + const navigate = useNavigate(); + const [prevScrollPos, setPrevScrollPos] = useState(0); + const [visible, setVisible] = useState(true); + const { feed, hasMore, loadMore } = useFeed({subplebbitAddresses: account?.subscriptions, sortType: 'new'}); + const [selectedFeed, setSelectedFeed] = useState(feed.sort((a, b) => b.timestamp - a.timestamp)); + + const [errorMessage, setErrorMessage] = useState(null); + useError(errorMessage, [errorMessage]); + + // mobile navbar scroll effect + useEffect(() => { + const debouncedHandleScroll = debounce(() => { + const currentScrollPos = window.pageYOffset; + 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))} + }; + + // desktop navbar board select functionality + const handleClickTitle = (title, address) => { + setSelectedTitle(title); + setSelectedAddress(address); + setSelectedFeed(feed.filter(feed => feed.title === title)); + }; + + // mobile navbar board select functionality + const handleSelectChange = (event) => { + const selected = event.target.value; + + if (selected === 'subscriptions') { + return; + } + + const selectedTitle = defaultSubplebbits.find((subplebbit) => subplebbit.address === selected).title; + setSelectedTitle(selectedTitle); + setSelectedAddress(selected); + navigate(`/p/${selected}`); + }; + + + return ( + <> + + Subscriptions - Catalog - plebchan + + + setIsSettingsOpen(false)} /> + + <> + + [ + 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} + + ))} + ] + + + [ + + ] + [ + setIsSettingsOpen(true)}>Settings + ] + [ + handleStyleChange({target: {value: "Yotsuba"}} + )}>Home + ] + +
+
+ Board +   +   + +
+
+ setIsSettingsOpen(true)}>Settings +   + handleStyleChange({target: {value: "Yotsuba"}} + )}>Home +
+
+
 
+
 
+ +
+
+ <> +
+ +
+ <> +
Subscriptions
+ {feed.length < 1 ? ( +
You haven't subscribed to any board yet.
+ ) : ( +
+ You have subscribed to {account.subscriptions.length} board{account.subscriptions.length > 1 ? "s" : null}. +
+ )} + + +
+ + +
+ + Style: +   + + +
+ [ + Return + ] +
+
+ + Return + +
+
+
+ + {selectedFeed.length < 1 ? ( + + ) : ( + + {feed.map((thread, index) => { + const commentMediaInfo = getCommentMediaInfo(thread); + const fallbackImgUrl = "assets/filedeleted-res.gif"; + return ( + setSelectedThread(thread.cid)}> +
+ {commentMediaInfo?.url ? ( + + {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" ? ( + + ) : null} + {/*
+ +
*/} +
+ R: + {thread.replyCount} +
+
+ {thread.title ? `${thread.title}` : null} + {thread.content ? `: ${thread.content}` : null} +
+
+ + )})} +
+ )} +
+ +
+ + ); +} + +export default SubscriptionsCatalog; \ No newline at end of file