mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
feat(home): redesigned home to be more similar to 4chan, with boards box listing all boards and thread box showing recent threads
This commit is contained in:
+27
-2
@@ -28,8 +28,18 @@ import packageJson from '../package.json';
|
|||||||
const commitRef = process?.env?.REACT_APP_COMMIT_REF || '';
|
const commitRef = process?.env?.REACT_APP_COMMIT_REF || '';
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const { bodyStyle, setBodyStyle, setDefaultSubplebbits, isCaptchaOpen, setIsCaptchaOpen, setIsSettingsOpen, selectedStyle, setShowPostForm, setShowPostFormLink } =
|
const {
|
||||||
useGeneralStore((state) => state);
|
bodyStyle,
|
||||||
|
setBodyStyle,
|
||||||
|
setDefaultSubplebbits,
|
||||||
|
setDefaultNsfwSubplebbits,
|
||||||
|
isCaptchaOpen,
|
||||||
|
setIsCaptchaOpen,
|
||||||
|
setIsSettingsOpen,
|
||||||
|
selectedStyle,
|
||||||
|
setShowPostForm,
|
||||||
|
setShowPostFormLink,
|
||||||
|
} = useGeneralStore((state) => state);
|
||||||
|
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const isElectron = window.electron && window.electron.isElectron;
|
const isElectron = window.electron && window.electron.isElectron;
|
||||||
@@ -116,6 +126,21 @@ export default function App() {
|
|||||||
};
|
};
|
||||||
}, [setDefaultSubplebbits]);
|
}, [setDefaultSubplebbits]);
|
||||||
|
|
||||||
|
// fetch default NSFW subplebbits
|
||||||
|
useEffect(() => {
|
||||||
|
let didCancel = false;
|
||||||
|
fetch('https://raw.githubusercontent.com/plebbit/temporary-default-subplebbits/master/subplebbits-nsfw.json', { cache: 'no-cache' })
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((res) => {
|
||||||
|
if (!didCancel) {
|
||||||
|
setDefaultNsfwSubplebbits(res);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return () => {
|
||||||
|
didCancel = true;
|
||||||
|
};
|
||||||
|
}, [setDefaultNsfwSubplebbits]);
|
||||||
|
|
||||||
// handle nested routes
|
// handle nested routes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const path = location.pathname;
|
const path = location.pathname;
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export const Search = styled.div`
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
|
||||||
input[type="text"] {
|
input[type='text'] {
|
||||||
width: 400px;
|
width: 400px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
@@ -60,27 +60,27 @@ export const Search = styled.div`
|
|||||||
font-family: arial, helvetica, sans-serif;
|
font-family: arial, helvetica, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="submit"] {
|
input[type='submit'] {
|
||||||
width: 60px;
|
width: 70px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@-moz-document url-prefix() {
|
@-moz-document url-prefix() {
|
||||||
input[type="submit"] {
|
input[type='submit'] {
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
@media screen and (-webkit-min-device-pixel-ratio: 0) {
|
||||||
input[type="submit"] {
|
input[type='submit'] {
|
||||||
vertical-align: center;
|
vertical-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media not all and (min-resolution:.001dpcm) {
|
@media not all and (min-resolution: 0.001dpcm) {
|
||||||
input[type="submit"] {
|
input[type='submit'] {
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,7 +88,7 @@ export const Search = styled.div`
|
|||||||
@media only screen and (max-width: 480px) {
|
@media only screen and (max-width: 480px) {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
input[type="text"] {
|
input[type='text'] {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
@@ -96,8 +96,8 @@ export const Search = styled.div`
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="submit"] {
|
input[type='submit'] {
|
||||||
height: 35px;
|
height: 35px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
@@ -107,7 +107,6 @@ export const Search = styled.div`
|
|||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Page = styled.div`
|
export const Page = styled.div`
|
||||||
@@ -119,15 +118,15 @@ export const About = styled.div`
|
|||||||
background: #fff;
|
background: #fff;
|
||||||
color: #000;
|
color: #000;
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
margin-bottom: .5em;
|
margin-bottom: 0.5em;
|
||||||
padding-bottom: .5em;
|
padding-bottom: 0.5em;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const AboutTitle = styled.div`
|
export const AboutTitle = styled.div`
|
||||||
background: #800;
|
background: #800;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-left: .5em;
|
padding-left: 0.5em;
|
||||||
line-height: 2em;
|
line-height: 2em;
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
@@ -141,8 +140,8 @@ export const AboutTitle = styled.div`
|
|||||||
export const AboutContent = styled.div`
|
export const AboutContent = styled.div`
|
||||||
line-height: 1.5em;
|
line-height: 1.5em;
|
||||||
font-size: 93%;
|
font-size: 93%;
|
||||||
padding: .5em;
|
padding: 0.5em;
|
||||||
padding-top: .25em;
|
padding-top: 0.25em;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
min-height: 91px;
|
min-height: 91px;
|
||||||
|
|
||||||
@@ -165,39 +164,92 @@ export const AboutContent = styled.div`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Boards = styled.div`
|
export const BoardsBox = styled.div`
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
margin: 0;
|
padding-bottom: 0.5em;
|
||||||
padding: 0;
|
|
||||||
padding-bottom: .5em;
|
|
||||||
background: #fff;
|
background: #fff;
|
||||||
word-wrap: break-word;
|
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
|
|
||||||
#subscriptions {
|
&:after {
|
||||||
text-align: left;
|
content: '';
|
||||||
|
display: table;
|
||||||
|
clear: both;
|
||||||
}
|
}
|
||||||
`;
|
|
||||||
|
|
||||||
export const BoardsTitle = styled.div`
|
.boxbar {
|
||||||
background: #fca;
|
background: #fca;
|
||||||
color: #800;
|
color: #800;
|
||||||
position: relative;
|
padding-left: 0.5em;
|
||||||
padding-left: .5em;
|
line-height: 2em;
|
||||||
line-height: 2em;
|
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
font-size: 131%;
|
font-size: 131%;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.boxcontent {
|
||||||
|
font-size: 93%;
|
||||||
|
padding: 0.5em;
|
||||||
|
padding-top: 0.25em;
|
||||||
|
padding-bottom: 0;
|
||||||
|
line-height: 130%;
|
||||||
|
|
||||||
|
.column {
|
||||||
|
float: left;
|
||||||
|
width: 163px;
|
||||||
|
margin-right: 20px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 100%;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
li {
|
||||||
|
list-style: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #800;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: #e00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.disconnected {
|
||||||
|
width: 13px;
|
||||||
|
margin: 0 2px -3px 0;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#button {
|
||||||
|
color: #800;
|
||||||
|
font-weight: 700;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
:hover {
|
||||||
|
color: #e00;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const BoardsContent = styled.div`
|
export const BoardsContent = styled.div`
|
||||||
font-size: 93%;
|
font-size: 93%;
|
||||||
padding: .5em;
|
padding: 0.5em;
|
||||||
padding-top: .25em;
|
padding-top: 0.25em;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
line-height: 130%;
|
line-height: 130%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -233,7 +285,6 @@ export const BoardsContent = styled.div`
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.board-avatar-container img.board-avatar {
|
.board-avatar-container img.board-avatar {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -265,7 +316,7 @@ export const BoardsContent = styled.div`
|
|||||||
|
|
||||||
:hover {
|
:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
color: #e00
|
color: #e00;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,7 +331,8 @@ export const BoardsContent = styled.div`
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 480px) {
|
@media (max-width: 480px) {
|
||||||
.boardlink, #view-all {
|
.boardlink,
|
||||||
|
#view-all {
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,15 +354,13 @@ export const BoardsContent = styled.div`
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Footer = styled.div`
|
export const Footer = styled.div`
|
||||||
font-size: 93%;
|
font-size: 93%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
clear: both;
|
clear: both;
|
||||||
padding-top: .5em;
|
padding-top: 0.5em;
|
||||||
padding-bottom: 2em;
|
padding-bottom: 2em;
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
@@ -320,7 +370,7 @@ export const Footer = styled.div`
|
|||||||
width: 750px;
|
width: 750px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
background: #fed;
|
background: #fed;
|
||||||
display: block;
|
display: block;
|
||||||
@@ -331,7 +381,7 @@ export const Footer = styled.div`
|
|||||||
margin-top: -1px;
|
margin-top: -1px;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fill {
|
.fill {
|
||||||
border-top: 1x solid;
|
border-top: 1x solid;
|
||||||
border-right: 0;
|
border-right: 0;
|
||||||
@@ -340,16 +390,16 @@ export const Footer = styled.div`
|
|||||||
background: #ffe;
|
background: #ffe;
|
||||||
width: 10.5%;
|
width: 10.5%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.first {
|
.first {
|
||||||
border-left: 1px solid;
|
border-left: 1px solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: #800;
|
color: #800;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-device-width: 640px) {
|
@media (max-device-width: 640px) {
|
||||||
padding-top: 2em;
|
padding-top: 2em;
|
||||||
padding-bottom: 3em;
|
padding-bottom: 3em;
|
||||||
@@ -386,4 +436,4 @@ export const Footer = styled.div`
|
|||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
+202
-93
@@ -1,13 +1,14 @@
|
|||||||
import React, { Fragment, useEffect, useRef, useState } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import { Helmet } from 'react-helmet-async';
|
import { Helmet } from 'react-helmet-async';
|
||||||
import { useAccount, useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
import { useAccount, useComment, useSubplebbit, useSubplebbits } from '@plebbit/plebbit-react-hooks';
|
||||||
import { Link, useNavigate } from 'react-router-dom';
|
import { Link, useNavigate } from 'react-router-dom';
|
||||||
import { Container, Header, Logo, Page, Search, About, AboutTitle, AboutContent, Boards, BoardsTitle, BoardsContent, Footer } from '../styled/views/Home.styled';
|
import { Container, Header, Logo, Page, Search, About, AboutTitle, AboutContent, BoardsBox, BoardsContent, Footer } from '../styled/views/Home.styled';
|
||||||
import BoardAvatar from '../BoardAvatar';
|
import BoardAvatar from '../BoardAvatar';
|
||||||
import OfflineIndicator from '../OfflineIndicator';
|
import OfflineIndicator from '../OfflineIndicator';
|
||||||
import CreateBoardModal from '../modals/CreateBoardModal';
|
import CreateBoardModal from '../modals/CreateBoardModal';
|
||||||
import useGeneralStore from '../../hooks/stores/useGeneralStore';
|
import useGeneralStore from '../../hooks/stores/useGeneralStore';
|
||||||
import packageJson from '../../../package.json';
|
import packageJson from '../../../package.json';
|
||||||
|
import getCommentMediaInfo from '../../utils/getCommentMediaInfo';
|
||||||
import { Tooltip } from 'react-tooltip';
|
import { Tooltip } from 'react-tooltip';
|
||||||
const { version } = packageJson;
|
const { version } = packageJson;
|
||||||
const commitRef = process?.env?.REACT_APP_COMMIT_REF ? ` ${process.env.REACT_APP_COMMIT_REF.slice(0, 7)}` : '';
|
const commitRef = process?.env?.REACT_APP_COMMIT_REF ? ` ${process.env.REACT_APP_COMMIT_REF.slice(0, 7)}` : '';
|
||||||
@@ -20,17 +21,64 @@ const SubplebbitTitle = ({ address }) => {
|
|||||||
return <>{title ? <span>{title}</span> : <span style={{ userSelect: 'none' }}> </span>}</>;
|
return <>{title ? <span>{title}</span> : <span style={{ userSelect: 'none' }}> </span>}</>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const RecentThread = ({ commentCid }) => {
|
||||||
|
const comment = useComment({ commentCid });
|
||||||
|
const subplebbit = useSubplebbit({ subplebbitAddress: comment?.subplebbitAddress });
|
||||||
|
const { setSelectedAddress, setSelectedTitle } = useGeneralStore((state) => state);
|
||||||
|
const commentMediaInfo = getCommentMediaInfo(comment);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='board'>
|
||||||
|
<div className='board-title' key='board-title'>
|
||||||
|
<SubplebbitTitle address={comment?.subplebbitAddress} />
|
||||||
|
</div>
|
||||||
|
<div className='board-avatar-container' key='board-avatar-container'>
|
||||||
|
<Link
|
||||||
|
to={`/p/${comment?.subplebbitAddress}/c/${comment?.cid}`}
|
||||||
|
key='link'
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedTitle(subplebbit?.title);
|
||||||
|
setSelectedAddress(comment?.subplebbitAddress);
|
||||||
|
window.scrollTo(0, 0);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{commentMediaInfo?.type === 'webpage' && comment.thumbnailUrl ? (
|
||||||
|
<img className='board-avatar' src={commentMediaInfo?.thumbnail} alt='post' />
|
||||||
|
) : commentMediaInfo?.type === 'image' ? (
|
||||||
|
<img className='board-avatar' src={commentMediaInfo?.url} alt='post' />
|
||||||
|
) : (
|
||||||
|
<BoardAvatar address={comment.subplebbitAddress} />
|
||||||
|
)}
|
||||||
|
</Link>
|
||||||
|
<OfflineIndicator address={comment?.subplebbitAddress} className='offline-indicator' tooltipPlace='top' key='oi2' />
|
||||||
|
</div>
|
||||||
|
<div className='board-text' key='bt'>
|
||||||
|
{comment?.title ? <b>{comment?.title}</b> : null}
|
||||||
|
{comment?.content ? `: ${comment.content}` : null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const Home = () => {
|
const Home = () => {
|
||||||
const { bodyStyle, setBodyStyle, defaultSubplebbits, setSelectedAddress, selectedStyle, setSelectedStyle, setSelectedTitle } = useGeneralStore((state) => state);
|
const { bodyStyle, setBodyStyle, defaultSubplebbits, defaultNsfwSubplebbits, setSelectedAddress, selectedStyle, setSelectedStyle } = useGeneralStore((state) => state);
|
||||||
|
|
||||||
|
const sfwAddresses = defaultSubplebbits.map((subplebbit) => subplebbit.address);
|
||||||
|
const sfwSubs = useSubplebbits({ subplebbitAddresses: sfwAddresses });
|
||||||
|
const sfwList = sfwSubs.subplebbits.map((subplebbit) => subplebbit?.address);
|
||||||
|
const sfwListCids = sfwSubs.subplebbits.map((s) => s?.lastPostCid);
|
||||||
|
|
||||||
const account = useAccount();
|
const account = useAccount();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const isElectron = window.electron && window.electron.isElectron;
|
||||||
|
|
||||||
const inputRef = useRef(null);
|
const inputRef = useRef(null);
|
||||||
const prevStyle = useRef(selectedStyle);
|
const prevStyle = useRef(selectedStyle);
|
||||||
const prevBodyStyle = useRef(bodyStyle);
|
const prevBodyStyle = useRef(bodyStyle);
|
||||||
|
|
||||||
const [isCreateBoardOpen, setIsCreateBoardOpen] = useState(false);
|
const [isCreateBoardOpen, setIsCreateBoardOpen] = useState(false);
|
||||||
|
const [showAllSFWBoards, setShowAllSFWBoards] = useState(false);
|
||||||
|
const [showAllSubscriptions, setShowAllSubscriptions] = useState(false);
|
||||||
|
|
||||||
// prevent dark mode
|
// prevent dark mode
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -84,7 +132,7 @@ const Home = () => {
|
|||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
type='submit'
|
type='submit'
|
||||||
value='Search'
|
value='Connect'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const address = inputRef.current.value;
|
const address = inputRef.current.value;
|
||||||
if (address) {
|
if (address) {
|
||||||
@@ -101,58 +149,112 @@ const Home = () => {
|
|||||||
<AboutContent>
|
<AboutContent>
|
||||||
<div id='content'>
|
<div id='content'>
|
||||||
<p>
|
<p>
|
||||||
Plebchan is the only serverless, adminless, fully decentralized 4chan alternative where any pleb can create and own unlimited boards, and nobody can
|
Plebchan is a serverless, adminless, decentralized 4chan alternative where any pleb can create and own unlimited boards. All data comes from the
|
||||||
take them down. Boards can always find competition, and board owners can monetize freely, so janitors aren't needed. Plebchan is a client for{' '}
|
|
||||||
<a href='https://plebbit.com' target='_blank' rel='noreferrer'>
|
<a href='https://plebbit.com' target='_blank' rel='noreferrer'>
|
||||||
plebbit
|
plebbit
|
||||||
</a>
|
</a>{' '}
|
||||||
, a pure P2P protocol and tooling for creating decentralized forum applications. All data is just text, and plebchan's speed depends on how many users
|
protocol, it's all text including links from which media is embedded, shared peer-to-peer. Users do not need to register an account before participating
|
||||||
are{' '}
|
in the community. Feel free to click on a board below that interests you and jump right in!{' '}
|
||||||
<button
|
|
||||||
style={{ all: 'unset', cursor: 'pointer' }}
|
|
||||||
onClick={() => {
|
|
||||||
alert(
|
|
||||||
'You can seed automatically simply by using the plebchan desktop app, which is a plebbit full node. Download it here:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can use plebbit-cli with the --seed flag:\nhttps://github.com/plebbit/plebbit-cli\n\n',
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
seeding
|
|
||||||
</button>
|
|
||||||
. Search for any board address above, or feel free to click on a popular board below that interests you and jump right in!{' '}
|
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
<p>There are no global rules, each board is completely independent and its owner decides how/if it should be moderated.</p>
|
<p>There are no global rules, each board is completely independent and its owner decides how/if it should be moderated.</p>
|
||||||
<br />
|
|
||||||
<p>
|
|
||||||
{' '}
|
|
||||||
HOW TO RUN A BOARD (currently via CLI only): <strong>(1)</strong> have a computer you can use as server, because users will connect to your board
|
|
||||||
peer-to-peer; <strong>(2)</strong> go to{' '}
|
|
||||||
<a href='https://github.com/plebbit/plebbit-cli#install' target='_blank' rel='noreferrer'>
|
|
||||||
https://github.com/plebbit/plebbit-cli#install
|
|
||||||
</a>{' '}
|
|
||||||
and follow the instructions to run your daemon, create a subplebbit (board) and edit its settings; <strong>(3)</strong> users can always connect to your
|
|
||||||
board via its address, but it can be added below by submitting a pull request here:{' '}
|
|
||||||
<a href='https://github.com/plebbit/temporary-default-subplebbits' target='_blank' rel='noreferrer'>
|
|
||||||
https://github.com/plebbit/temporary-default-subplebbits
|
|
||||||
</a>{' '}
|
|
||||||
this will be automated with a plebbit DAO using the plebbit token.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</AboutContent>
|
</AboutContent>
|
||||||
</About>
|
</About>
|
||||||
{account?.subscriptions?.length > 0 ? (
|
<BoardsBox>
|
||||||
<Boards>
|
<div className='boxbar'>
|
||||||
<BoardsTitle>
|
<h2>Boards</h2>
|
||||||
<h2>Subscriptions</h2>
|
</div>
|
||||||
</BoardsTitle>
|
<div class='boxcontent'>
|
||||||
<BoardsContent id='subscriptions'>
|
<div class='column'>
|
||||||
<h3 style={{ textDecoration: 'underline', display: 'inline' }}>
|
<h3 style={{ textDecoration: 'underline', display: 'inline' }}>
|
||||||
You have subscribed to {account?.subscriptions?.length} board{account?.subscriptions?.length > 1 ? 's' : null}
|
<a
|
||||||
|
href='https://github.com/plebbit/temporary-default-subplebbits'
|
||||||
|
target='_blank'
|
||||||
|
rel='noopener noreferrer'
|
||||||
|
style={{ all: 'unset', cursor: 'pointer' }}
|
||||||
|
>
|
||||||
|
Default SFW
|
||||||
|
</a>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
|
<Link
|
||||||
|
to='/p/all'
|
||||||
|
id='button'
|
||||||
|
onClick={() => {
|
||||||
|
window.scrollTo(0, 0);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
[view all]
|
||||||
|
</Link>
|
||||||
|
<ul>
|
||||||
|
{sfwList.slice(0, showAllSFWBoards ? undefined : 18).map((address, index) => (
|
||||||
|
<li key={`default-${index}`}>
|
||||||
|
<OfflineIndicator address={address} className='disconnected' isText={true} />
|
||||||
|
<Link
|
||||||
|
key={`default-link-${index}`}
|
||||||
|
className='boardlink'
|
||||||
|
onClick={() => {
|
||||||
|
window.scrollTo(0, 0);
|
||||||
|
}}
|
||||||
|
to={`/p/${address}`}
|
||||||
|
>
|
||||||
|
{address}
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
{sfwList.length > 17 && (
|
||||||
|
<li onClick={() => setShowAllSFWBoards(!showAllSFWBoards)}>
|
||||||
|
{!showAllSFWBoards ? '... ' : null}
|
||||||
|
<span id='button'>{showAllSFWBoards ? '[show less]' : '[show more]'}</span>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class='column'>
|
||||||
|
<h3 style={{ textDecoration: 'underline', display: 'inline' }}>
|
||||||
|
<a
|
||||||
|
href='https://github.com/plebbit/temporary-default-subplebbits'
|
||||||
|
target='_blank'
|
||||||
|
rel='noopener noreferrer'
|
||||||
|
style={{ all: 'unset', cursor: 'pointer' }}
|
||||||
|
>
|
||||||
|
Default NSFW
|
||||||
|
</a>
|
||||||
|
</h3>
|
||||||
|
<ul>
|
||||||
|
{defaultNsfwSubplebbits.length === 0 && <li style={{ color: 'black' }}>No boards yet in this list.</li>}
|
||||||
|
{defaultNsfwSubplebbits.slice(0, showAllSFWBoards ? undefined : 18).map((subplebbit, index) => (
|
||||||
|
<li key={`default-${index}`}>
|
||||||
|
<OfflineIndicator address={subplebbit.address} className='disconnected' isText={true} />
|
||||||
|
<Link
|
||||||
|
key={`default-link-${index}`}
|
||||||
|
className='boardlink'
|
||||||
|
onClick={() => {
|
||||||
|
window.scrollTo(0, 0);
|
||||||
|
}}
|
||||||
|
to={`/p/${subplebbit.address}`}
|
||||||
|
>
|
||||||
|
{subplebbit.address}
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
{defaultNsfwSubplebbits.length > 17 && (
|
||||||
|
<li onClick={() => setShowAllSFWBoards(!showAllSFWBoards)}>
|
||||||
|
{!showAllSFWBoards ? '... ' : null}
|
||||||
|
<span id='button'>{showAllSFWBoards ? '[show less]' : '[show more]'}</span>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class='column'>
|
||||||
|
<h3 style={{ textDecoration: 'underline', display: 'inline' }}>Subscriptions</h3>
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
to='/p/subscriptions'
|
to='/p/subscriptions'
|
||||||
id='view-all'
|
id='button'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
}}
|
}}
|
||||||
@@ -160,58 +262,65 @@ const Home = () => {
|
|||||||
[view all]
|
[view all]
|
||||||
</Link>
|
</Link>
|
||||||
<br />
|
<br />
|
||||||
{account?.subscriptions?.map((subscription, index) => (
|
<ul>
|
||||||
<Fragment key={`frag-${index}`}>
|
{account?.subscriptions?.length === 0 && <li style={{ color: 'black' }}>Not subscribed to any board.</li>}
|
||||||
<Link
|
{account?.subscriptions?.slice(0, showAllSubscriptions ? undefined : 18).map((subscription, index) => (
|
||||||
key={`sub-${index}`}
|
<li key={`sub-${index}`}>
|
||||||
className='boardlink'
|
<OfflineIndicator address={subscription} className='disconnected' isText={true} />
|
||||||
onClick={() => {
|
<Link
|
||||||
window.scrollTo(0, 0);
|
key={`sub-link-${index}`}
|
||||||
}}
|
className='boardlink'
|
||||||
to={`/p/${subscription}`}
|
onClick={() => {
|
||||||
>
|
window.scrollTo(0, 0);
|
||||||
<br id='mobile-br' />
|
}}
|
||||||
{subscription}
|
to={`/p/${subscription}`}
|
||||||
</Link>
|
>
|
||||||
<OfflineIndicator key={`offline-${index}`} address={subscription} className='disconnected' isText={true} />
|
{subscription}
|
||||||
<br key={`br-${index}`} />
|
</Link>
|
||||||
</Fragment>
|
|
||||||
))}
|
</li>
|
||||||
<br id='mobile-br' />
|
))}
|
||||||
</BoardsContent>
|
{account?.subscriptions?.length > 17 && (
|
||||||
</Boards>
|
<li onClick={() => setShowAllSubscriptions(!showAllSubscriptions)}>
|
||||||
) : null}
|
{!showAllSubscriptions ? '... ' : null}
|
||||||
<Boards>
|
<span id='button'>{showAllSubscriptions ? '[show less]' : '[show more]'}</span>
|
||||||
<BoardsTitle>
|
</li>
|
||||||
<h2>Default Boards</h2>
|
)}
|
||||||
</BoardsTitle>
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class='column'>
|
||||||
|
<h3 style={{ textDecoration: 'underline', display: 'inline' }}>Moderating</h3>
|
||||||
|
<ul>
|
||||||
|
{!isElectron ? (
|
||||||
|
<li style={{ color: 'black' }}>
|
||||||
|
Visible on{' '}
|
||||||
|
<a
|
||||||
|
style={{ color: 'blue', textDecoration: 'underline' }}
|
||||||
|
href='https://github.com/plebbit/plebchan/releases/latest'
|
||||||
|
target='_blank'
|
||||||
|
rel='noopener noreferrer'
|
||||||
|
>
|
||||||
|
full node (desktop)
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
</li>
|
||||||
|
) : (
|
||||||
|
<div>WIP</div>
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</BoardsBox>
|
||||||
|
<BoardsBox>
|
||||||
|
<div className='boxbar'>
|
||||||
|
<h2>Recent Threads</h2>
|
||||||
|
</div>
|
||||||
<BoardsContent>
|
<BoardsContent>
|
||||||
{defaultSubplebbits.map((subplebbit, index) => (
|
{sfwListCids.slice(0, 8).map((cid) => (
|
||||||
<div className='board' key={`board-${index}`}>
|
<RecentThread commentCid={cid} />
|
||||||
<div className='board-title' key='board-title'>
|
|
||||||
{subplebbit.title ?? <SubplebbitTitle address={subplebbit.address} />}
|
|
||||||
</div>
|
|
||||||
<div className='board-avatar-container' key='board-avatar-container'>
|
|
||||||
<Link
|
|
||||||
to={`/p/${subplebbit.address}`}
|
|
||||||
key='link'
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedTitle(subplebbit.title);
|
|
||||||
setSelectedAddress(subplebbit.address);
|
|
||||||
window.scrollTo(0, 0);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<BoardAvatar key='baordavatar' address={subplebbit.address} />
|
|
||||||
</Link>
|
|
||||||
<OfflineIndicator address={subplebbit.address} className='offline-indicator' tooltipPlace='top' key='oi2' />
|
|
||||||
</div>
|
|
||||||
<div className='board-text' key='bt'>
|
|
||||||
<b key='b'>{subplebbit.address}</b>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
))}
|
||||||
</BoardsContent>
|
</BoardsContent>
|
||||||
</Boards>
|
</BoardsBox>
|
||||||
</Page>
|
</Page>
|
||||||
<Footer>
|
<Footer>
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
@@ -1,23 +1,22 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { Helmet } from 'react-helmet-async';
|
import { Helmet } from 'react-helmet-async';
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from 'react-router-dom';
|
||||||
import { Container, Header, Logo, Page, Boards, BoardsTitle } from '../styled/views/Home.styled';
|
import { Container, Header, Logo, Page, BoardsBox } from '../styled/views/Home.styled';
|
||||||
import packageJson from '../../../package.json';
|
import packageJson from '../../../package.json';
|
||||||
const {version} = packageJson;
|
const { version } = packageJson;
|
||||||
const commitRef = process?.env?.REACT_APP_COMMIT_REF ? ` ${process.env.REACT_APP_COMMIT_REF.slice(0, 7)}` : '';
|
const commitRef = process?.env?.REACT_APP_COMMIT_REF ? ` ${process.env.REACT_APP_COMMIT_REF.slice(0, 7)}` : '';
|
||||||
|
|
||||||
|
|
||||||
const NotFound = () => {
|
const NotFound = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const yotsubaBodyStyle = {
|
const yotsubaBodyStyle = {
|
||||||
background: "#ffe url(assets/fade.png) top repeat-x",
|
background: '#ffe url(assets/fade.png) top repeat-x',
|
||||||
color: "maroon",
|
color: 'maroon',
|
||||||
fontFamily: "Arial, Helvetica, sans-serif"
|
fontFamily: 'Arial, Helvetica, sans-serif',
|
||||||
};
|
};
|
||||||
const originalBodyStyles = {
|
const originalBodyStyles = {
|
||||||
background: document.body.style.background,
|
background: document.body.style.background,
|
||||||
color: document.body.style.color,
|
color: document.body.style.color,
|
||||||
fontFamily: document.body.style.fontFamily
|
fontFamily: document.body.style.fontFamily,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(yotsubaBodyStyle)) {
|
for (const [key, value] of Object.entries(yotsubaBodyStyle)) {
|
||||||
@@ -39,34 +38,41 @@ const NotFound = () => {
|
|||||||
<Container>
|
<Container>
|
||||||
<Header>
|
<Header>
|
||||||
<Logo>
|
<Logo>
|
||||||
<Link to="/">
|
<Link to='/'>
|
||||||
<img alt="plebchan" src="assets/logo/logo-transparent.png" />
|
<img alt='plebchan' src='assets/logo/logo-transparent.png' />
|
||||||
</Link>
|
</Link>
|
||||||
</Logo>
|
</Logo>
|
||||||
</Header>
|
</Header>
|
||||||
<Page>
|
<Page>
|
||||||
<Boards>
|
<BoardsBox>
|
||||||
<BoardsTitle>
|
<div className='boxbar'>
|
||||||
<h2 style={{textAlign: 'center'}}>404 Not Found</h2>
|
<h2 style={{ textAlign: 'center' }}>404 Not Found</h2>
|
||||||
</BoardsTitle>
|
</div>
|
||||||
<img src="assets/plebchan-husbando.jpg" alt="plebchan" style={{
|
<img
|
||||||
display: "block",
|
src='assets/plebchan-husbando.jpg'
|
||||||
margin: "auto",
|
alt='plebchan'
|
||||||
padding: "15px",
|
style={{
|
||||||
width: "50%"
|
display: 'block',
|
||||||
}}></img>
|
margin: 'auto',
|
||||||
</Boards>
|
padding: '15px',
|
||||||
|
width: '50%',
|
||||||
|
}}
|
||||||
|
></img>
|
||||||
|
</BoardsBox>
|
||||||
</Page>
|
</Page>
|
||||||
<div style={{
|
<div
|
||||||
textAlign: "center",
|
style={{
|
||||||
fontSize: "11px",
|
textAlign: 'center',
|
||||||
marginTop: "2em",
|
fontSize: '11px',
|
||||||
}}>
|
marginTop: '2em',
|
||||||
plebchan v{version}{commitRef}. GPL-2.0
|
}}
|
||||||
|
>
|
||||||
|
plebchan v{version}
|
||||||
|
{commitRef}. GPL-2.0
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default NotFound;
|
export default NotFound;
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ const useGeneralStore = create((set) => ({
|
|||||||
defaultSubplebbits: [],
|
defaultSubplebbits: [],
|
||||||
setDefaultSubplebbits: (subplebbits) => set({ defaultSubplebbits: subplebbits }),
|
setDefaultSubplebbits: (subplebbits) => set({ defaultSubplebbits: subplebbits }),
|
||||||
|
|
||||||
|
defaultNsfwSubplebbits: [],
|
||||||
|
setDefaultNsfwSubplebbits: (subplebbits) => set({ defaultNsfwSubplebbits: subplebbits }),
|
||||||
|
|
||||||
deletePost: false,
|
deletePost: false,
|
||||||
setDeletePost: (deletePost) => set({ deletePost }),
|
setDeletePost: (deletePost) => set({ deletePost }),
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user