diff --git a/public/assets/buttons/cross_blue.png b/public/assets/buttons/cross_blue.png new file mode 100644 index 00000000..1b139c5e Binary files /dev/null and b/public/assets/buttons/cross_blue.png differ diff --git a/public/assets/buttons/cross_dark.png b/public/assets/buttons/cross_dark.png new file mode 100644 index 00000000..6cb9e23e Binary files /dev/null and b/public/assets/buttons/cross_dark.png differ diff --git a/public/assets/buttons/cross_photon.png b/public/assets/buttons/cross_photon.png new file mode 100644 index 00000000..66e02efc Binary files /dev/null and b/public/assets/buttons/cross_photon.png differ diff --git a/public/assets/buttons/cross_red.png b/public/assets/buttons/cross_red.png new file mode 100644 index 00000000..b1d80a6e Binary files /dev/null and b/public/assets/buttons/cross_red.png differ diff --git a/public/assets/buttons/post_expand_plus_blue.png b/public/assets/buttons/post_expand_plus_blue.png new file mode 100644 index 00000000..30e32068 Binary files /dev/null and b/public/assets/buttons/post_expand_plus_blue.png differ diff --git a/public/assets/buttons/post_expand_plus_dark.png b/public/assets/buttons/post_expand_plus_dark.png new file mode 100644 index 00000000..4c7122ef Binary files /dev/null and b/public/assets/buttons/post_expand_plus_dark.png differ diff --git a/public/assets/buttons/post_expand_plus_photon.png b/public/assets/buttons/post_expand_plus_photon.png new file mode 100644 index 00000000..a995bc76 Binary files /dev/null and b/public/assets/buttons/post_expand_plus_photon.png differ diff --git a/public/assets/buttons/post_expand_plus_red.png b/public/assets/buttons/post_expand_plus_red.png new file mode 100644 index 00000000..f97153fb Binary files /dev/null and b/public/assets/buttons/post_expand_plus_red.png differ diff --git a/public/assets/filedeleted-res.gif b/public/assets/filedeleted-res.gif new file mode 100644 index 00000000..9f687c9f Binary files /dev/null and b/public/assets/filedeleted-res.gif differ diff --git a/src/App.js b/src/App.js index 457b49ff..1a349efa 100644 --- a/src/App.js +++ b/src/App.js @@ -71,12 +71,15 @@ export default function App() { } /> }> } /> + } /> }> } /> + } /> }> } /> + } /> } /> diff --git a/src/components/Board.jsx b/src/components/Board.jsx index 91935474..4fd958c1 100644 --- a/src/components/Board.jsx +++ b/src/components/Board.jsx @@ -10,6 +10,7 @@ import { Tooltip } from 'react-tooltip'; import onError from '../utils/onError'; import getDate from '../utils/getDate'; import renderComments from '../utils/renderComments'; +import SettingsModal from './SettingsModal'; const Board = ({ setBodyStyle }) => { @@ -34,6 +35,7 @@ const Board = ({ setBodyStyle }) => { const [comment, setComment] = useState(''); const { publishComment } = useAccountsActions(); const [isCaptchaOpen, setIsCaptchaOpen] = useState(false); + const [isSettingsOpen, setIsSettingsOpen] = useState(false); const [captchaImage, setCaptchaImage] = useState(''); const navigate = useNavigate(); const location = useLocation(); @@ -97,9 +99,10 @@ const Board = ({ setBodyStyle }) => { setEndIndex(2); }, [selectedAddress]); - // post route handling + // nested routes handling useEffect(() => { const path = location.pathname; + if (path.endsWith('/post')) { setShowPostFormLink(false); setShowPostForm(true); @@ -107,6 +110,13 @@ const Board = ({ setBodyStyle }) => { setShowPostFormLink(true); setShowPostForm(false); } + + if (path.endsWith('/settings')) { + setIsSettingsOpen(true); + } else { + setIsSettingsOpen(false); + } + }, [location.pathname]); // automatic dark mode without interefering with user's selected style @@ -292,6 +302,14 @@ const Board = ({ setBodyStyle }) => { setIsCaptchaOpen(false); }; + const handleSettingsClose = () => { + setIsSettingsOpen(false); + } + + const handleSettingsOpen = () => { + setIsSettingsOpen(true); + } + const handleStyleChange = (event) => { switch (event.target.value) { @@ -385,9 +403,14 @@ const Board = ({ setBodyStyle }) => { return ( + <> {defaultSubplebbits.map(subplebbit => ( @@ -400,7 +423,7 @@ const Board = ({ setBodyStyle }) => { ))} [ - Settings + Settings ] [ handleStyleChange({target: {value: "Yotsuba"}} @@ -419,7 +442,7 @@ const Board = ({ setBodyStyle }) => {
- Settings + Settings   handleStyleChange({target: {value: "Yotsuba"}} )}>Home diff --git a/src/components/CaptchaModal.jsx b/src/components/CaptchaModal.jsx index 98dd1c48..7d288a71 100644 --- a/src/components/CaptchaModal.jsx +++ b/src/components/CaptchaModal.jsx @@ -4,7 +4,6 @@ import Modal from 'react-modal'; import styled from 'styled-components'; const StyledModal = styled(Modal)` - .modal-content { width: 400px; height: 300px; @@ -51,6 +50,29 @@ const StyledModal = styled(Modal)` border: 1px solid #777; outline: none; } + + ${({ selectedStyle }) => { + switch (selectedStyle) { + case 'Yotsuba': + return ``; + + case 'Yotsuba B': + return ``; + + case 'Futaba': + return ``; + + case 'Burichan': + return ``; + + case 'Tomorrow': + return ``; + + case 'Photon': + return ``; + + } + }} `; const customOverlayStyles = { diff --git a/src/components/SettingsModal.jsx b/src/components/SettingsModal.jsx new file mode 100644 index 00000000..db3c0bf1 --- /dev/null +++ b/src/components/SettingsModal.jsx @@ -0,0 +1,193 @@ +import React from "react"; +import { Link, useLocation, useNavigate } from "react-router-dom"; +import Modal from "react-modal"; +import styled from "styled-components"; +import useBoardStore from "../useBoardStore"; + +const StyledModal = styled(Modal)` + .modal-content { + width: 400px; + height: 800px; + display: flex; + align-self: center; + flex-direction: column; + align-items: center; + justify-content: center; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: rgba(0, 0, 0, 0.85); + padding: 0; + z-index: 9999; + border: 1px solid #aaa; + } + + .panel { + top: 60px; + width: 330px; + left: 50%; + margin-left: -178px; + position: absolute; + padding: 2px 5px 5px; + font-size: 14px; + box-shadow: 0 0 5px rgba(0, 0, 0, .25); + } + + .panel-header { + font-size: 16px; + font-weight: 700; + margin-bottom: 5px; + margin-top: 5px; + padding-bottom: 5px; + text-align: center; + line-height: 14px; + } + + .icon { + right: 5px; + width: 18px; + height: 18px; + display: block; + background-size: 100%; + cursor: pointer; + position: absolute; + top: 5px; + } + + h4 { + font-size: 14px; + padding: 0; + margin: 10px 0 5px; + } + + ${({ selectedStyle }) => { + switch (selectedStyle) { + case 'Yotsuba': + return `.panel { + background-color: #f0e0d6; + } + + .panel-header { + border-bottom: 1px solid #d9bfb7; + } + + .icon { + background-image: url(/assets/buttons/cross_red.png); + }`; + + case 'Yotsuba-B': + return `.panel { + background-color: #d6daf0; + } + + .panel-header { + border-bottom: 1px solid #b7c5d9; + } + + .icon { + background-image: url(/assets/buttons/cross_blue.png); + }`; + + case 'Futaba': + return `.panel { + background-color: #f0e0d6; + } + + .panel-header { + border-bottom: 1px solid rgba(0,0,0,.2); + } + + .icon { + background-image: url(/assets/buttons/cross_red.png); + }`; + + case 'Burichan': + return `.panel { + background-color: #d6daf0; + } + + .panel-header { + border-bottom: 1px solid rgba(0,0,0,.2); + } + + .icon { + background-image: url(/assets/buttons/cross_blue.png); + }`; + + case 'Tomorrow': + return `.panel { + background-color: #282a2e; + } + + .panel-header { + border-bottom: 1px solid #111; + } + + .icon { + background-image: url(/assets/buttons/cross_dark.png); + }`; + + case 'Photon': + return `.panel { + background-color: #ddd; + } + + .panel-header { + border-bottom: 1px solid rgba(0, 0, 0, 0.20); + } + + .icon { + background-image: url(/assets/buttons/cross_photon.png); + }`; + + } + }} +`; + +const customOverlayStyles = { + overlay: { + backgroundColor: 'rgba(0,0,0,.25)' + } +}; + +const SettingsModal = ({ isOpen, closeModal }) => { + const selectedStyle = useBoardStore(state => state.selectedStyle); + const navigate = useNavigate(); + const location = useLocation(); + + const handleCloseModal = () => { + closeModal(); + + if (location.pathname === "/settings") { + navigate(-1, { replace: true }); + } else { + navigate("/settings", { state: { from: location } }); + } + }; + + return ( + +
+
+ Settings + + + +
+

Plebbit Options

+

Coming soon...

+
+
+ ); +} + +Modal.setAppElement("#root"); + +export default SettingsModal; \ No newline at end of file