import React, { useEffect } from 'react'; import { Route, Routes, useLocation } from 'react-router-dom'; import { Helmet } from 'react-helmet-async'; import useAppStore from './useAppStore'; import Home from './components/views/Home'; import Board from './components/views/Board'; import Thread from './components/views/Thread'; import Catalog from './components/views/Catalog'; import NotFound from './components/views/NotFound'; import styled, { createGlobalStyle } from 'styled-components'; import 'react-tooltip/dist/react-tooltip.css'; import 'react-toastify/dist/ReactToastify.css'; import preloadImages from './utils/preloadImages'; import { ToastContainer } from 'react-toastify'; import { importAll } from './components/ImageBanner'; const GlobalStyle = createGlobalStyle` *:focus { outline: none; } body { margin: 0; padding: 0; background: ${props => props.background}; color: ${props => props.color}; font-family: ${props => props.fontFamily}; } .tooltip { border-radius: 0; max-width: 40%; font-size: 11px; padding: 3px; opacity: 100%; } `; const StyledContainer = styled(ToastContainer)` .Toastify__toast { border-radius: 0px; font-size: 11pt; animation-duration: 0s; border: 1px solid #fee9cd; color: #c5c8c6; } `; export default function App() { const { bodyStyle, setBodyStyle, setDefaultSubplebbits, setIsSettingsOpen, setSelectedStyle, setShowPostForm, setShowPostFormLink, } = useAppStore(state => state); const location = useLocation(); const isHomeRoute = location.pathname === "/"; // preload banners useEffect(() => { const loadImages = async () => { const images = await importAll(require.context('../public/assets/banners', false, /\.(png|jpe?g|svg)$/)); const imageUrls = images.map((image) => image.default); preloadImages(imageUrls); }; loadImages(); }, []); // automatic dark mode without interefering with user's selected style useEffect(() => { if (isHomeRoute) return; const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); const isDarkMode = darkModeMediaQuery.matches; if (isDarkMode && !isHomeRoute) { setSelectedStyle('Tomorrow'); setBodyStyle({ background: '#1d1f21 none', color: '#c5c8c6', fontFamily: 'Arial, Helvetica, sans-serif' }); localStorage.setItem('selectedStyle', 'Tomorrow'); } const darkModeListener = (e) => { if (e.matches && !isHomeRoute) { 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); }; }, [isHomeRoute]); // 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; }; }, []); // 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); } }, [location.pathname]); return (
} /> }> } /> } /> }> } /> } /> }> } /> } /> } />
)}