2023-05-16 13:26:05 +02:00
|
|
|
import React, { useEffect, useState } from 'react';
|
2023-03-20 17:08:05 +01:00
|
|
|
import { Route, Routes, useLocation } from 'react-router-dom';
|
2023-02-01 13:30:32 +01:00
|
|
|
import { Helmet } from 'react-helmet-async';
|
2023-04-29 14:39:57 +02:00
|
|
|
import { useAccount, useBufferedFeeds } from '@plebbit/plebbit-react-hooks';
|
2023-04-09 20:55:55 +02:00
|
|
|
import 'react-tooltip/dist/react-tooltip.css';
|
|
|
|
|
import 'react-toastify/dist/ReactToastify.css';
|
2023-04-08 13:27:17 +02:00
|
|
|
import useGeneralStore from './hooks/stores/useGeneralStore';
|
2023-04-29 18:01:19 +02:00
|
|
|
import { GlobalStyle } from './components/styled/GlobalStyle.styled';
|
|
|
|
|
import { Toast } from './components/styled/Toast.styled';
|
2023-03-19 11:49:05 +01:00
|
|
|
import Board from './components/views/Board';
|
|
|
|
|
import Catalog from './components/views/Catalog';
|
2023-05-03 11:01:41 +02:00
|
|
|
import Home from './components/views/Home';
|
2023-03-19 11:49:05 +01:00
|
|
|
import NotFound from './components/views/NotFound';
|
2023-04-10 10:51:16 +02:00
|
|
|
import Pending from './components/views/Pending';
|
2023-05-03 11:01:41 +02:00
|
|
|
import Subscriptions from './components/views/Subscriptions';
|
2023-05-07 17:48:38 +02:00
|
|
|
import SubscriptionsCatalog from './components/views/SubscriptionsCatalog';
|
2023-05-03 11:01:41 +02:00
|
|
|
import Thread from './components/views/Thread';
|
2023-04-09 20:55:55 +02:00
|
|
|
import CaptchaModal from './components/CaptchaModal';
|
2023-03-22 16:23:32 +01:00
|
|
|
import { importAll } from './components/ImageBanner';
|
2023-04-09 20:55:55 +02:00
|
|
|
import preloadImages from './utils/preloadImages';
|
2023-05-16 13:26:05 +02:00
|
|
|
import useError from "./hooks/useError";
|
|
|
|
|
import useSuccess from "./hooks/useSuccess";
|
2023-02-08 21:49:36 +01:00
|
|
|
|
|
|
|
|
|
2023-03-13 14:29:34 +01:00
|
|
|
export default function App() {
|
2023-03-20 17:08:05 +01:00
|
|
|
const {
|
|
|
|
|
bodyStyle, setBodyStyle,
|
2023-04-29 14:39:57 +02:00
|
|
|
defaultSubplebbits, setDefaultSubplebbits,
|
2023-04-09 20:55:55 +02:00
|
|
|
isCaptchaOpen, setIsCaptchaOpen,
|
2023-03-20 17:08:05 +01:00
|
|
|
setIsSettingsOpen,
|
2023-04-09 20:55:55 +02:00
|
|
|
selectedStyle, setSelectedStyle,
|
2023-03-20 17:08:05 +01:00
|
|
|
setShowPostForm,
|
|
|
|
|
setShowPostFormLink,
|
2023-04-08 13:27:17 +02:00
|
|
|
} = useGeneralStore(state => state);
|
2023-03-20 17:08:05 +01:00
|
|
|
|
|
|
|
|
const location = useLocation();
|
2023-03-21 11:17:54 +01:00
|
|
|
const isHomeRoute = location.pathname === "/";
|
2023-04-29 14:39:57 +02:00
|
|
|
|
|
|
|
|
const account = useAccount();
|
|
|
|
|
|
2023-05-16 13:26:05 +02:00
|
|
|
const [errorMessage, setErrorMessage] = useState(null);
|
|
|
|
|
const [successMessage, setSuccessMessage] = useState(null);
|
|
|
|
|
useError(errorMessage, [errorMessage]);
|
|
|
|
|
useSuccess(successMessage, [successMessage]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const successToast = localStorage.getItem("successToast");
|
|
|
|
|
const errorToast = localStorage.getItem("errorToast");
|
|
|
|
|
if (successToast) {
|
|
|
|
|
setSuccessMessage(successToast);
|
|
|
|
|
localStorage.removeItem("successToast");
|
|
|
|
|
} else if (errorToast) {
|
|
|
|
|
setErrorMessage(errorToast);
|
|
|
|
|
localStorage.removeItem("errorToast");
|
|
|
|
|
} else {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}, [setErrorMessage, setSuccessMessage]);
|
|
|
|
|
|
2023-04-29 14:39:57 +02:00
|
|
|
// preload default subs and subscriptions
|
|
|
|
|
useBufferedFeeds({
|
|
|
|
|
feedsOptions: [
|
|
|
|
|
{subplebbitAddresses: defaultSubplebbits.map(
|
|
|
|
|
(subplebbit) => subplebbit.address
|
|
|
|
|
), sortType: 'new'},
|
2023-04-29 16:12:56 +02:00
|
|
|
{subplebbitAddresses: account?.subscriptions, sortType: 'new'}
|
2023-04-29 14:39:57 +02:00
|
|
|
]
|
|
|
|
|
});
|
2023-03-13 14:29:34 +01:00
|
|
|
|
2023-03-22 16:23:32 +01:00
|
|
|
// preload banners
|
2023-03-05 14:26:40 +01:00
|
|
|
useEffect(() => {
|
2023-03-22 16:23:32 +01:00
|
|
|
const loadImages = async () => {
|
2023-04-19 14:12:06 +02:00
|
|
|
const images = await importAll(require.context('../public/assets', true, /\.(png|jpe?g|svg)$/));
|
2023-03-22 16:23:32 +01:00
|
|
|
const imageUrls = images.map((image) => image.default);
|
|
|
|
|
preloadImages(imageUrls);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
loadImages();
|
2023-03-05 14:26:40 +01:00
|
|
|
}, []);
|
|
|
|
|
|
2023-03-11 17:27:46 +01:00
|
|
|
|
2023-03-20 17:08:05 +01:00
|
|
|
// automatic dark mode without interefering with user's selected style
|
|
|
|
|
useEffect(() => {
|
2023-03-21 11:17:54 +01:00
|
|
|
if (isHomeRoute) return;
|
|
|
|
|
|
2023-03-20 17:08:05 +01:00
|
|
|
const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
|
|
|
const isDarkMode = darkModeMediaQuery.matches;
|
|
|
|
|
|
2023-03-21 11:17:54 +01:00
|
|
|
if (isDarkMode && !isHomeRoute) {
|
2023-03-20 17:08:05 +01:00
|
|
|
setSelectedStyle('Tomorrow');
|
|
|
|
|
setBodyStyle({
|
|
|
|
|
background: '#1d1f21 none',
|
|
|
|
|
color: '#c5c8c6',
|
|
|
|
|
fontFamily: 'Arial, Helvetica, sans-serif'
|
|
|
|
|
});
|
|
|
|
|
localStorage.setItem('selectedStyle', 'Tomorrow');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const darkModeListener = (e) => {
|
2023-03-21 11:17:54 +01:00
|
|
|
if (e.matches && !isHomeRoute) {
|
2023-03-20 17:08:05 +01:00
|
|
|
setSelectedStyle('Tomorrow');
|
|
|
|
|
setBodyStyle({
|
|
|
|
|
background: '#1d1f21 none',
|
|
|
|
|
color: '#c5c8c6',
|
|
|
|
|
fontFamily: 'Arial, Helvetica, sans-serif'
|
|
|
|
|
});
|
|
|
|
|
localStorage.setItem('selectedStyle', 'Tomorrow');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
darkModeMediaQuery.addEventListener('change', darkModeListener);
|
|
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
|
darkModeMediaQuery.removeEventListener('change', darkModeListener);
|
|
|
|
|
};
|
2023-04-25 21:30:10 +02:00
|
|
|
}, [isHomeRoute, setBodyStyle, setSelectedStyle]);
|
2023-03-21 11:17:54 +01:00
|
|
|
|
2023-03-20 17:08:05 +01:00
|
|
|
// fetch default subplebbits
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
let didCancel = false;
|
|
|
|
|
fetch(
|
|
|
|
|
"https://raw.githubusercontent.com/plebbit/temporary-default-subplebbits/master/subplebbits.json",
|
|
|
|
|
{ cache: "no-cache" }
|
|
|
|
|
)
|
|
|
|
|
.then((res) => res.json())
|
|
|
|
|
.then(res => {
|
|
|
|
|
if (!didCancel) {
|
|
|
|
|
setDefaultSubplebbits(res);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return () => {
|
|
|
|
|
didCancel = true;
|
|
|
|
|
};
|
2023-04-25 21:30:10 +02:00
|
|
|
}, [setDefaultSubplebbits]);
|
2023-03-20 17:08:05 +01:00
|
|
|
|
|
|
|
|
// handle nested routes
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const path = location.pathname;
|
|
|
|
|
if (path.endsWith('/post')) {
|
|
|
|
|
setShowPostFormLink(false);
|
|
|
|
|
setShowPostForm(true);
|
|
|
|
|
} else {
|
|
|
|
|
setShowPostFormLink(true);
|
|
|
|
|
setShowPostForm(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (path.endsWith('/settings')) {
|
|
|
|
|
setIsSettingsOpen(true);
|
|
|
|
|
} else {
|
|
|
|
|
setIsSettingsOpen(false);
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-25 21:30:10 +02:00
|
|
|
}, [location.pathname, setIsSettingsOpen, setShowPostForm, setShowPostFormLink]);
|
2023-03-20 17:08:05 +01:00
|
|
|
|
2023-02-01 13:30:32 +01:00
|
|
|
return (
|
|
|
|
|
<div>
|
|
|
|
|
<Helmet>
|
2023-04-29 12:47:30 +02:00
|
|
|
<link rel="apple-touch-icon" sizes="180x180" href="assets/logo/apple-touch-icon.png" />
|
|
|
|
|
<link rel="icon" type="image/png" sizes="32x32" href="assets/logo/favicon-32x32.png" />
|
|
|
|
|
<link rel="icon" type="image/png" sizes="16x16" href="assets/logo/favicon-16x16.png" />
|
|
|
|
|
<link rel="manifest" href="site.webmanifest" />
|
2023-02-01 13:30:32 +01:00
|
|
|
<meta name="msapplication-TileColor" content="#fee9cd" />
|
|
|
|
|
<meta name="theme-color" content="#ffffff" />
|
|
|
|
|
</Helmet>
|
2023-02-08 21:49:36 +01:00
|
|
|
<GlobalStyle
|
2023-04-09 20:55:55 +02:00
|
|
|
background={bodyStyle.background}
|
|
|
|
|
color={bodyStyle.color}
|
|
|
|
|
fontFamily={bodyStyle.fontFamily}
|
2023-02-08 21:49:36 +01:00
|
|
|
/>
|
2023-02-09 19:08:15 +01:00
|
|
|
<Routes>
|
2023-02-13 12:05:10 +01:00
|
|
|
<Route exact path='/' element={<Home setBodyStyle={setBodyStyle} />} />
|
2023-04-08 22:30:44 +02:00
|
|
|
<Route path={`/p/:subplebbitAddress`} element={<Board setBodyStyle={setBodyStyle} />}>
|
2023-02-19 22:08:18 +01:00
|
|
|
<Route path='post' element={<Board />} />
|
2023-03-15 15:25:09 +01:00
|
|
|
<Route path='settings' element={<Board />} />
|
2023-02-12 21:20:08 +01:00
|
|
|
</Route>
|
2023-04-08 22:30:44 +02:00
|
|
|
<Route path={`/p/:subplebbitAddress/c/:threadCid`} element={<Thread setBodyStyle={setBodyStyle} />}>
|
2023-02-19 22:08:18 +01:00
|
|
|
<Route path='post' element={<Thread />} />
|
2023-03-15 15:25:09 +01:00
|
|
|
<Route path='settings' element={<Thread />} />
|
2023-02-11 22:00:13 +01:00
|
|
|
</Route>
|
2023-04-08 22:30:44 +02:00
|
|
|
<Route path={`/p/:subplebbitAddress/catalog`} element={<Catalog setBodyStyle={setBodyStyle} /> }>
|
2023-02-19 22:08:18 +01:00
|
|
|
<Route path='post' element={<Catalog />} />
|
2023-03-15 15:25:09 +01:00
|
|
|
<Route path='settings' element={<Catalog />} />
|
2023-02-19 16:48:46 +01:00
|
|
|
</Route>
|
2023-04-23 08:43:53 +02:00
|
|
|
<Route path={`/profile/c/:index`} element={<Pending setBodyStyle={setBodyStyle} /> }>
|
|
|
|
|
<Route path='settings' element={<Pending />} />
|
|
|
|
|
</Route>
|
2023-05-07 17:22:55 +02:00
|
|
|
<Route path={`/p/subscriptions`} element={<Subscriptions setBodyStyle={setBodyStyle} /> }>
|
2023-05-03 11:01:41 +02:00
|
|
|
<Route path='settings' element={<Subscriptions />} />
|
|
|
|
|
</Route>
|
2023-05-07 17:48:38 +02:00
|
|
|
<Route path={`p/subscriptions/catalog`} element={<SubscriptionsCatalog setBodyStyle={setBodyStyle} /> }>
|
2023-05-07 17:22:55 +02:00
|
|
|
<Route path='settings' element={<SubscriptionsCatalog />} />
|
2023-05-07 17:48:38 +02:00
|
|
|
</Route>
|
2023-03-17 17:49:30 +01:00
|
|
|
<Route path='*' element={<NotFound setBodyStyle={setBodyStyle} />} />
|
2023-02-09 19:08:15 +01:00
|
|
|
</Routes>
|
2023-04-29 18:01:19 +02:00
|
|
|
<Toast />
|
2023-04-09 20:55:55 +02:00
|
|
|
<CaptchaModal
|
|
|
|
|
selectedStyle={selectedStyle}
|
|
|
|
|
isOpen={isCaptchaOpen}
|
|
|
|
|
closeModal={() => setIsCaptchaOpen(false)}
|
|
|
|
|
/>
|
2023-02-01 13:30:32 +01:00
|
|
|
</div>
|
2023-03-11 17:27:46 +01:00
|
|
|
)}
|