diff --git a/src/App.js b/src/App.js
index 40a8b936..c9b59773 100755
--- a/src/App.js
+++ b/src/App.js
@@ -28,8 +28,18 @@ import packageJson from '../package.json';
const commitRef = process?.env?.REACT_APP_COMMIT_REF || '';
export default function App() {
- const { bodyStyle, setBodyStyle, setDefaultSubplebbits, isCaptchaOpen, setIsCaptchaOpen, setIsSettingsOpen, selectedStyle, setShowPostForm, setShowPostFormLink } =
- useGeneralStore((state) => state);
+ const {
+ bodyStyle,
+ setBodyStyle,
+ setDefaultSubplebbits,
+ setDefaultNsfwSubplebbits,
+ isCaptchaOpen,
+ setIsCaptchaOpen,
+ setIsSettingsOpen,
+ selectedStyle,
+ setShowPostForm,
+ setShowPostFormLink,
+ } = useGeneralStore((state) => state);
const location = useLocation();
const isElectron = window.electron && window.electron.isElectron;
@@ -116,6 +126,21 @@ export default function App() {
};
}, [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
useEffect(() => {
const path = location.pathname;
diff --git a/src/components/modals/ReplyModal.jsx b/src/components/modals/ReplyModal.jsx
index 34a79580..eefef3dd 100755
--- a/src/components/modals/ReplyModal.jsx
+++ b/src/components/modals/ReplyModal.jsx
@@ -9,307 +9,307 @@ import useAnonModeStore from '../../hooks/stores/useAnonModeStore';
import useGeneralStore from '../../hooks/stores/useGeneralStore';
const ReplyModal = ({ isOpen, closeModal }) => {
- const {
- captchaResponse,
- setCaptchaResponse,
- setChallengesArray,
- setIsCaptchaOpen,
- setPendingComment,
- setPendingCommentIndex,
- replyQuoteCid,
- setResolveCaptchaPromise,
- selectedAddress,
- selectedParentCid,
- selectedShortCid,
- selectedStyle,
- selectedText,
- setSelectedText,
- triggerInsertion,
- } = useGeneralStore((state) => state);
+ const {
+ captchaResponse,
+ setCaptchaResponse,
+ setChallengesArray,
+ setIsCaptchaOpen,
+ setPendingComment,
+ setPendingCommentIndex,
+ replyQuoteCid,
+ setResolveCaptchaPromise,
+ selectedAddress,
+ selectedParentCid,
+ selectedShortCid,
+ selectedStyle,
+ selectedText,
+ setSelectedText,
+ triggerInsertion,
+ } = useGeneralStore((state) => state);
- const { anonymousMode } = useAnonModeStore();
+ const { anonymousMode } = useAnonModeStore();
- const account = useAccount();
+ const account = useAccount();
- const [, setNewErrorMessage] = useError();
+ const [, setNewErrorMessage] = useError();
- const nodeRef = useRef(null);
- const nameRef = useRef();
- const commentRef = useRef();
- const linkRef = useRef();
+ const nodeRef = useRef(null);
+ const nameRef = useRef();
+ const commentRef = useRef();
+ const linkRef = useRef();
- const [triggerPublishComment, setTriggerPublishComment] = useState(false);
- const [isMobile, setIsMobile] = useState(window.innerWidth <= 480);
- const [executeAnonMode, setExecuteAnonMode] = useState(false);
+ const [triggerPublishComment, setTriggerPublishComment] = useState(false);
+ const [isMobile, setIsMobile] = useState(window.innerWidth <= 480);
+ const [executeAnonMode, setExecuteAnonMode] = useState(false);
- useAnonMode(selectedParentCid, anonymousMode && executeAnonMode);
+ useAnonMode(selectedParentCid, anonymousMode && executeAnonMode);
- useEffect(() => {
- const handleResize = () => setIsMobile(window.innerWidth <= 480);
- window.addEventListener('resize', handleResize);
+ useEffect(() => {
+ const handleResize = () => setIsMobile(window.innerWidth <= 480);
+ window.addEventListener('resize', handleResize);
- // Cleanup function
- return () => {
- window.removeEventListener('resize', handleResize);
- };
- }, [setIsMobile]);
+ // Cleanup function
+ return () => {
+ window.removeEventListener('resize', handleResize);
+ };
+ }, [setIsMobile]);
- const onModalOpen = () => {
- if (commentRef.current) {
- if (selectedText) {
- commentRef.current.value += '\n';
- }
- commentRef.current.focus();
- const len = commentRef.current.value.length;
- commentRef.current.setSelectionRange(len, len);
- }
- };
+ const onModalOpen = () => {
+ if (commentRef.current) {
+ if (selectedText) {
+ commentRef.current.value += '\n';
+ }
+ commentRef.current.focus();
+ const len = commentRef.current.value.length;
+ commentRef.current.setSelectionRange(len, len);
+ }
+ };
- const insertAtCursor = (inputElement, valueToInsert) => {
- const startPos = inputElement.selectionStart || inputElement.value.length;
- const endPos = startPos + valueToInsert.length;
- inputElement.setRangeText(valueToInsert, startPos, startPos, 'end');
- inputElement.setSelectionRange(endPos, endPos);
- };
+ const insertAtCursor = (inputElement, valueToInsert) => {
+ const startPos = inputElement.selectionStart || inputElement.value.length;
+ const endPos = startPos + valueToInsert.length;
+ inputElement.setRangeText(valueToInsert, startPos, startPos, 'end');
+ inputElement.setSelectionRange(endPos, endPos);
+ };
- useEffect(() => {
- if (replyQuoteCid && commentRef.current) {
- const prefixedReplyQuoteCid = `c/${replyQuoteCid}\n`;
- insertAtCursor(commentRef.current, prefixedReplyQuoteCid);
- }
- }, [triggerInsertion, replyQuoteCid]);
+ useEffect(() => {
+ if (replyQuoteCid && commentRef.current) {
+ const prefixedReplyQuoteCid = `c/${replyQuoteCid}\n`;
+ insertAtCursor(commentRef.current, prefixedReplyQuoteCid);
+ }
+ }, [triggerInsertion, replyQuoteCid]);
- const getSelectedText = useCallback(() => {
- const text = document.getSelection().toString();
- setSelectedText(text ? `>${text}\n` : '');
- }, [setSelectedText]);
+ const getSelectedText = useCallback(() => {
+ const text = document.getSelection().toString();
+ setSelectedText(text ? `>${text}\n` : '');
+ }, [setSelectedText]);
- useEffect(() => {
- if (isOpen) {
- setTimeout(getSelectedText, 0);
- } else {
- setSelectedText('');
- }
- }, [isOpen, getSelectedText, setSelectedText]);
+ useEffect(() => {
+ if (isOpen) {
+ setTimeout(getSelectedText, 0);
+ } else {
+ setSelectedText('');
+ }
+ }, [isOpen, getSelectedText, setSelectedText]);
- const onChallengeVerification = (challengeVerification) => {
- if (challengeVerification.challengeSuccess === true) {
- return;
- } else if (challengeVerification.challengeSuccess === false) {
- setNewErrorMessage(`Challenge Failed, reason: ${challengeVerification.reason}. Errors: ${challengeVerification.errors}`);
- console.log('challenge failed', challengeVerification);
- }
- };
+ const onChallengeVerification = (challengeVerification) => {
+ if (challengeVerification.challengeSuccess === true) {
+ return;
+ } else if (challengeVerification.challengeSuccess === false) {
+ setNewErrorMessage(`Challenge Failed, reason: ${challengeVerification.reason}. Errors: ${challengeVerification.errors}`);
+ console.log('challenge failed', challengeVerification);
+ }
+ };
- const onChallenge = async (challenges, comment) => {
- setPendingComment(comment);
- let challengeAnswers = [];
+ const onChallenge = async (challenges, comment) => {
+ setPendingComment(comment);
+ let challengeAnswers = [];
- try {
- challengeAnswers = await getChallengeAnswersFromUser(challenges);
- } catch (error) {
- setNewErrorMessage(error.message);
- console.log(error);
- }
- if (challengeAnswers) {
- await comment.publishChallengeAnswers(challengeAnswers);
- }
- };
+ try {
+ challengeAnswers = await getChallengeAnswersFromUser(challenges);
+ } catch (error) {
+ setNewErrorMessage(error.message);
+ console.log(error);
+ }
+ if (challengeAnswers) {
+ await comment.publishChallengeAnswers(challengeAnswers);
+ }
+ };
- useEffect(() => {
- setPublishCommentOptions((prevPublishCommentOptions) => ({
- ...prevPublishCommentOptions,
- subplebbitAddress: selectedAddress,
- }));
- }, [selectedAddress]);
+ useEffect(() => {
+ setPublishCommentOptions((prevPublishCommentOptions) => ({
+ ...prevPublishCommentOptions,
+ subplebbitAddress: selectedAddress,
+ }));
+ }, [selectedAddress]);
- const [publishCommentOptions, setPublishCommentOptions] = useState({
- subplebbitAddress: selectedAddress,
- onChallenge,
- onChallengeVerification,
- onError: (error) => {
- setNewErrorMessage(error.message);
- console.log(error);
- },
- });
+ const [publishCommentOptions, setPublishCommentOptions] = useState({
+ subplebbitAddress: selectedAddress,
+ onChallenge,
+ onChallengeVerification,
+ onError: (error) => {
+ setNewErrorMessage(error.message);
+ console.log(error);
+ },
+ });
- const { publishComment, index } = usePublishComment(publishCommentOptions);
+ const { publishComment, index } = usePublishComment(publishCommentOptions);
- useEffect(() => {
- if (index !== undefined) {
- setPendingCommentIndex(index);
- }
- }, [index, setPendingCommentIndex]);
+ useEffect(() => {
+ if (index !== undefined) {
+ setPendingCommentIndex(index);
+ }
+ }, [index, setPendingCommentIndex]);
- const resetFields = useCallback(() => {
- if (nameRef.current) {
- nameRef.current.value = '';
- }
- if (commentRef.current) {
- commentRef.current.value = '';
- }
- if (linkRef.current) {
- linkRef.current.value = '';
- }
- }, []);
+ const resetFields = useCallback(() => {
+ if (nameRef.current) {
+ nameRef.current.value = '';
+ }
+ if (commentRef.current) {
+ commentRef.current.value = '';
+ }
+ if (linkRef.current) {
+ linkRef.current.value = '';
+ }
+ }, []);
- const handleSubmit = async (event) => {
- event.preventDefault();
+ const handleSubmit = async (event) => {
+ event.preventDefault();
- if (commentRef.current.value === '' && linkRef.current.value === '') {
- setNewErrorMessage('Please enter a comment or link.');
- return;
- }
+ if (commentRef.current.value === '' && linkRef.current.value === '') {
+ setNewErrorMessage('Please enter a comment or link.');
+ return;
+ }
- setPublishCommentOptions((prevPublishCommentOptions) => ({
- ...prevPublishCommentOptions,
- author: {
- displayName: nameRef.current.value || undefined,
- ...(anonymousMode ? {} : { address: account?.author.address }),
- },
- content: commentRef.current.value || undefined,
- link: linkRef.current.value || undefined,
- parentCid: selectedParentCid,
- }));
+ setPublishCommentOptions((prevPublishCommentOptions) => ({
+ ...prevPublishCommentOptions,
+ author: {
+ displayName: nameRef.current.value || undefined,
+ ...(anonymousMode ? {} : { address: account?.author.address }),
+ },
+ content: commentRef.current.value || undefined,
+ link: linkRef.current.value || undefined,
+ parentCid: selectedParentCid,
+ }));
- setTriggerPublishComment(true);
- };
+ setTriggerPublishComment(true);
+ };
- const updateSigner = useCallback(async () => {
- if (anonymousMode) {
- setExecuteAnonMode(true);
+ const updateSigner = useCallback(async () => {
+ if (anonymousMode) {
+ setExecuteAnonMode(true);
- let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {};
- let signer;
+ let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {};
+ let signer;
- if (!storedSigners[selectedParentCid]) {
- signer = await account?.plebbit.createSigner();
- storedSigners[selectedParentCid] = { privateKey: signer?.privateKey, address: signer?.address };
- localStorage.setItem('storedSigners', JSON.stringify(storedSigners));
- } else {
- const signerPrivateKey = storedSigners[selectedParentCid].privateKey;
+ if (!storedSigners[selectedParentCid]) {
+ signer = await account?.plebbit.createSigner();
+ storedSigners[selectedParentCid] = { privateKey: signer?.privateKey, address: signer?.address };
+ localStorage.setItem('storedSigners', JSON.stringify(storedSigners));
+ } else {
+ const signerPrivateKey = storedSigners[selectedParentCid].privateKey;
- try {
- signer = await account?.plebbit.createSigner({ type: 'ed25519', privateKey: signerPrivateKey });
- } catch (error) {
- console.log(error);
- }
- }
+ try {
+ signer = await account?.plebbit.createSigner({ type: 'ed25519', privateKey: signerPrivateKey });
+ } catch (error) {
+ console.log(error);
+ }
+ }
- setPublishCommentOptions((prevPublishCommentOptions) => {
- const newPublishCommentOptions = {
- ...prevPublishCommentOptions,
- signer,
- author: {
- ...prevPublishCommentOptions.author,
- address: signer?.address,
- },
- };
+ setPublishCommentOptions((prevPublishCommentOptions) => {
+ const newPublishCommentOptions = {
+ ...prevPublishCommentOptions,
+ signer,
+ author: {
+ ...prevPublishCommentOptions.author,
+ address: signer?.address,
+ },
+ };
- if (JSON.stringify(prevPublishCommentOptions) !== JSON.stringify(newPublishCommentOptions)) {
- return newPublishCommentOptions;
- }
+ if (JSON.stringify(prevPublishCommentOptions) !== JSON.stringify(newPublishCommentOptions)) {
+ return newPublishCommentOptions;
+ }
- return prevPublishCommentOptions;
- });
- }
- }, [selectedParentCid, anonymousMode, account]);
+ return prevPublishCommentOptions;
+ });
+ }
+ }, [selectedParentCid, anonymousMode, account]);
- useEffect(() => {
- if (anonymousMode) {
- updateSigner();
- }
- }, [updateSigner, anonymousMode]);
+ useEffect(() => {
+ if (anonymousMode) {
+ updateSigner();
+ }
+ }, [updateSigner, anonymousMode]);
- useEffect(() => {
- if (publishCommentOptions && triggerPublishComment) {
- (async () => {
- await publishComment();
- resetFields();
- closeModal();
- })();
- setTriggerPublishComment(false);
- setExecuteAnonMode(false);
- }
- }, [publishCommentOptions, triggerPublishComment, publishComment, resetFields, closeModal]);
+ useEffect(() => {
+ if (publishCommentOptions && triggerPublishComment) {
+ (async () => {
+ await publishComment();
+ resetFields();
+ closeModal();
+ })();
+ setTriggerPublishComment(false);
+ setExecuteAnonMode(false);
+ }
+ }, [publishCommentOptions, triggerPublishComment, publishComment, resetFields, closeModal]);
- const getChallengeAnswersFromUser = async (challenges) => {
- setChallengesArray(challenges);
+ const getChallengeAnswersFromUser = async (challenges) => {
+ setChallengesArray(challenges);
- return new Promise((resolve, reject) => {
- const imageString = challenges?.challenges[0].challenge;
- const imageSource = `data:image/png;base64,${imageString}`;
- const challengeImg = new Image();
- challengeImg.src = imageSource;
+ return new Promise((resolve, reject) => {
+ const imageString = challenges?.challenges[0].challenge;
+ const imageSource = `data:image/png;base64,${imageString}`;
+ const challengeImg = new Image();
+ challengeImg.src = imageSource;
- challengeImg.onload = () => {
- setIsCaptchaOpen(true);
+ challengeImg.onload = () => {
+ setIsCaptchaOpen(true);
- const handleKeyDown = async (event) => {
- if (event.key === 'Enter') {
- const currentCaptchaResponse = captchaResponse;
- resolve(currentCaptchaResponse);
- setIsCaptchaOpen(false);
- document.removeEventListener('keydown', handleKeyDown);
- event.preventDefault();
- }
- };
+ const handleKeyDown = async (event) => {
+ if (event.key === 'Enter') {
+ const currentCaptchaResponse = captchaResponse;
+ resolve(currentCaptchaResponse);
+ setIsCaptchaOpen(false);
+ document.removeEventListener('keydown', handleKeyDown);
+ event.preventDefault();
+ }
+ };
- setCaptchaResponse('');
- document.addEventListener('keydown', handleKeyDown);
+ setCaptchaResponse('');
+ document.addEventListener('keydown', handleKeyDown);
- setResolveCaptchaPromise(resolve);
- };
+ setResolveCaptchaPromise(resolve);
+ };
- challengeImg.onerror = () => {
- reject(setNewErrorMessage('Could not load challenges'));
- };
- });
- };
+ challengeImg.onerror = () => {
+ reject(setNewErrorMessage('Could not load challenges'));
+ };
+ });
+ };
- return (
-
-
-
-
- Reply to c/{selectedShortCid}
- closeModal()} title='close' />
-
-
-
-
-
- );
+ return (
+
+
+
+
+ Reply to c/{selectedShortCid}
+ closeModal()} title='close' />
+
+
+
+
+
+ );
};
Modal.setAppElement('#root');
diff --git a/src/components/styled/GlobalStyle.styled.jsx b/src/components/styled/GlobalStyle.styled.jsx
index 05c647a5..ed8cd666 100644
--- a/src/components/styled/GlobalStyle.styled.jsx
+++ b/src/components/styled/GlobalStyle.styled.jsx
@@ -44,7 +44,6 @@ export const GlobalStyle = createGlobalStyle`
.poster-address {
display: inline-block;
- overflow: clip;
}
.author-address-hidden {
diff --git a/src/components/styled/views/Home.styled.jsx b/src/components/styled/views/Home.styled.jsx
index 8c263c07..b93ebf55 100644
--- a/src/components/styled/views/Home.styled.jsx
+++ b/src/components/styled/views/Home.styled.jsx
@@ -44,7 +44,7 @@ export const Search = styled.div`
text-align: center;
margin-bottom: 20px;
- input[type="text"] {
+ input[type='text'] {
width: 400px;
height: 30px;
font-size: 18px;
@@ -60,27 +60,27 @@ export const Search = styled.div`
font-family: arial, helvetica, sans-serif;
}
- input[type="submit"] {
- width: 60px;
+ input[type='submit'] {
+ width: 70px;
height: 30px;
font-size: 14px;
margin-left: 5px;
}
-
+
@-moz-document url-prefix() {
- input[type="submit"] {
+ input[type='submit'] {
vertical-align: top;
}
}
- @media screen and (-webkit-min-device-pixel-ratio:0) {
- input[type="submit"] {
+ @media screen and (-webkit-min-device-pixel-ratio: 0) {
+ input[type='submit'] {
vertical-align: center;
}
}
- @media not all and (min-resolution:.001dpcm) {
- input[type="submit"] {
+ @media not all and (min-resolution: 0.001dpcm) {
+ input[type='submit'] {
vertical-align: top;
}
}
@@ -88,7 +88,7 @@ export const Search = styled.div`
@media only screen and (max-width: 480px) {
text-align: center;
- input[type="text"] {
+ input[type='text'] {
width: 80%;
height: 35px;
font-size: 20px;
@@ -96,18 +96,17 @@ export const Search = styled.div`
box-sizing: border-box;
border-radius: 0;
}
-
- input[type="submit"] {
+
+ input[type='submit'] {
height: 35px;
font-size: 14px;
padding: 5px;
box-sizing: border-box;
vertical-align: top;
- width: 60px;
+ width: 70px;
-webkit-appearance: none;
}
}
-
`;
export const Page = styled.div`
@@ -119,15 +118,15 @@ export const About = styled.div`
background: #fff;
color: #000;
border: 1px solid;
- margin-bottom: .5em;
- padding-bottom: .5em;
+ margin-bottom: 0.5em;
+ padding-bottom: 0.5em;
`;
export const AboutTitle = styled.div`
background: #800;
color: #fff;
position: relative;
- padding-left: .5em;
+ padding-left: 0.5em;
line-height: 2em;
h2 {
@@ -141,8 +140,8 @@ export const AboutTitle = styled.div`
export const AboutContent = styled.div`
line-height: 1.5em;
font-size: 93%;
- padding: .5em;
- padding-top: .25em;
+ padding: 0.5em;
+ padding-top: 0.25em;
padding-bottom: 0;
min-height: 91px;
@@ -165,39 +164,110 @@ export const AboutContent = styled.div`
}
`;
-export const Boards = styled.div`
+export const BoardsBox = styled.div`
border: 1px solid;
- margin: 0;
- padding: 0;
- padding-bottom: .5em;
+ padding-bottom: 0.5em;
background: #fff;
- word-wrap: break-word;
margin-bottom: 6px;
- #subscriptions {
- text-align: left;
+ &:after {
+ content: '';
+ display: table;
+ clear: both;
}
-`;
-export const BoardsTitle = styled.div`
- background: #fca;
- color: #800;
- position: relative;
- padding-left: .5em;
- line-height: 2em;
+ .boxbar {
+ background: #fca;
+ color: #800;
+ padding-left: 0.5em;
+ line-height: 2em;
- h2 {
- font-size: 131%;
- font-weight: 700;
- margin: 0;
- padding: 0;
+ h2 {
+ font-size: 131%;
+ font-weight: 700;
+ margin: 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;
+ }
+ }
+ }
+
+ @media (max-width: 480px) {
+ .boxbar {
+ padding-left: 0.25em;
+ }
+
+ .boxcontent {
+ font-size: 1.05em;
+ padding: 0.25em;
+ line-height: 2em;
+
+ .column {
+ width: 44%;
+ margin-bottom: 10px;
+ margin-right: 20px;
+ }
+ }
}
`;
export const BoardsContent = styled.div`
font-size: 93%;
- padding: .5em;
- padding-top: .25em;
+ padding: 0.5em;
+ padding-top: 0.25em;
padding-bottom: 0;
line-height: 130%;
text-align: center;
@@ -225,19 +295,19 @@ export const BoardsContent = styled.div`
}
.board-avatar-container {
- width: 150px;
- height: 150px;
+ width: auto;
+ height: auto;
border: 1px solid #800;
display: inline-block;
overflow: hidden;
position: relative;
+ line-height: 0;
}
-
- .board-avatar-container img.board-avatar {
- width: 100%;
- height: 100%;
- object-fit: cover;
+ img,
+ video {
+ max-width: 150px;
+ max-height: 150px;
}
.offline-indicator {
@@ -265,7 +335,7 @@ export const BoardsContent = styled.div`
:hover {
text-decoration: underline;
- color: #e00
+ color: #e00;
}
}
@@ -280,7 +350,8 @@ export const BoardsContent = styled.div`
}
@media (max-width: 480px) {
- .boardlink, #view-all {
+ .boardlink,
+ #view-all {
font-size: 1.2em;
}
@@ -302,15 +373,13 @@ export const BoardsContent = styled.div`
position: absolute;
}
}
-
-
`;
export const Footer = styled.div`
font-size: 93%;
text-align: center;
clear: both;
- padding-top: .5em;
+ padding-top: 0.5em;
padding-bottom: 2em;
ul {
@@ -320,7 +389,7 @@ export const Footer = styled.div`
width: 750px;
padding: 0;
}
-
+
li {
background: #fed;
display: block;
@@ -331,7 +400,7 @@ export const Footer = styled.div`
margin-top: -1px;
list-style: none;
}
-
+
.fill {
border-top: 1x solid;
border-right: 0;
@@ -340,16 +409,16 @@ export const Footer = styled.div`
background: #ffe;
width: 10.5%;
}
-
+
.first {
border-left: 1px solid;
}
-
+
a {
color: #800;
text-decoration: none;
}
-
+
@media (max-device-width: 640px) {
padding-top: 2em;
padding-bottom: 3em;
@@ -386,4 +455,4 @@ export const Footer = styled.div`
text-decoration: underline;
}
}
-`;
\ No newline at end of file
+`;
diff --git a/src/components/views/All.jsx b/src/components/views/All.jsx
index 6d759ee2..78ba0ff9 100755
--- a/src/components/views/All.jsx
+++ b/src/components/views/All.jsx
@@ -607,7 +607,7 @@ const All = () => {
window.electron && window.electron.isElectron
? setIsCreateBoardOpen(true)
: alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n',
+ 'HOW TO CREATE A BOARD (currently via CLI only):\n\n(1) have a computer you can use as server, because users will connect to your board peer-to-peer;\n\n(2) go to https://github.com/plebbit/plebbit-cli#install and follow the instructions to run your daemon, create a subplebbit (board) and edit its settings;\n\n(3) users can always connect to your board via its address, but it can be added below by submitting a pull request here: https://github.com/plebbit/temporary-default-subplebbits. This will be automated with a plebbit DAO using the plebbit token.',
);
}}
>
@@ -639,7 +639,7 @@ const All = () => {
style={{ cursor: 'pointer' }}
onClick={() =>
alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n',
+ 'HOW TO CREATE A BOARD (currently via CLI only):\n\n(1) have a computer you can use as server, because users will connect to your board peer-to-peer;\n\n(2) go to https://github.com/plebbit/plebbit-cli#install and follow the instructions to run your daemon, create a subplebbit (board) and edit its settings;\n\n(3) users can always connect to your board via its address, but it can be added below by submitting a pull request here: https://github.com/plebbit/temporary-default-subplebbits. This will be automated with a plebbit DAO using the plebbit token.',
)
}
>
@@ -1214,7 +1214,56 @@ const All = () => {
thread.content?.length > 1000 ? (
-
+ {
+ postRefs.current[quoteShortParentCid] = ref;
+ }}
+ postQuoteOnClick={(quoteShortParentCid) => {
+ handleQuoteClick(thread, quoteShortParentCid, null);
+ }}
+ postQuoteOnOver={(quoteShortParentCid) => {
+ const quoteParentCid = cidTracker[quoteShortParentCid];
+ if (outOfViewCid !== quoteParentCid) {
+ handleQuoteHover(thread, quoteShortParentCid, () => {
+ setOutOfViewCid(quoteParentCid);
+
+ const rect = postRefs.current[quoteShortParentCid].getBoundingClientRect();
+ const distanceToRight = window.innerWidth - rect.right;
+ const distanceToTop = rect.top;
+ const distanceToBottom = window.innerHeight - rect.bottom;
+ let top;
+
+ if (distanceToTop < postOnHoverHeight / 2) {
+ top = window.scrollY - 5;
+ } else if (distanceToBottom < postOnHoverHeight / 2) {
+ top = window.scrollY - postOnHoverHeight + window.innerHeight - 10;
+ } else {
+ top = rect.top + window.scrollY - postOnHoverHeight / 2;
+ }
+
+ if (distanceToRight < 200) {
+ setOutOfViewPosition({
+ top,
+ right: window.innerWidth - rect.left - 10,
+ maxWidth: rect.left - 5,
+ });
+ } else {
+ setOutOfViewPosition({
+ top,
+ left: rect.left + rect.width + 5,
+ maxWidth: window.innerWidth - rect.left - rect.width - 5,
+ });
+ }
+ });
+ }
+ }}
+ postQuoteOnLeave={() => {
+ removeHighlight();
+ setOutOfViewCid(null);
+ }}
+ />
{' '}
(...)
@@ -1237,7 +1286,56 @@ const All = () => {
) : (
-
+ {
+ postRefs.current[quoteShortParentCid] = ref;
+ }}
+ postQuoteOnClick={(quoteShortParentCid) => {
+ handleQuoteClick(thread, quoteShortParentCid, null);
+ }}
+ postQuoteOnOver={(quoteShortParentCid) => {
+ const quoteParentCid = cidTracker[quoteShortParentCid];
+ if (outOfViewCid !== quoteParentCid) {
+ handleQuoteHover(thread, quoteShortParentCid, () => {
+ setOutOfViewCid(quoteParentCid);
+
+ const rect = postRefs.current[quoteShortParentCid].getBoundingClientRect();
+ const distanceToRight = window.innerWidth - rect.right;
+ const distanceToTop = rect.top;
+ const distanceToBottom = window.innerHeight - rect.bottom;
+ let top;
+
+ if (distanceToTop < postOnHoverHeight / 2) {
+ top = window.scrollY - 5;
+ } else if (distanceToBottom < postOnHoverHeight / 2) {
+ top = window.scrollY - postOnHoverHeight + window.innerHeight - 10;
+ } else {
+ top = rect.top + window.scrollY - postOnHoverHeight / 2;
+ }
+
+ if (distanceToRight < 200) {
+ setOutOfViewPosition({
+ top,
+ right: window.innerWidth - rect.left - 10,
+ maxWidth: rect.left - 5,
+ });
+ } else {
+ setOutOfViewPosition({
+ top,
+ left: rect.left + rect.width + 5,
+ maxWidth: window.innerWidth - rect.left - rect.width - 5,
+ });
+ }
+ });
+ }
+ }}
+ postQuoteOnLeave={() => {
+ removeHighlight();
+ setOutOfViewCid(null);
+ }}
+ />
@@ -2431,7 +2529,56 @@ const All = () => {
thread.content?.length > 500 ? (
-
+ {
+ postRefs.current[quoteShortParentCid] = ref;
+ }}
+ postQuoteOnClick={(quoteShortParentCid) => {
+ handleQuoteClick(thread, quoteShortParentCid, null);
+ }}
+ postQuoteOnOver={(quoteShortParentCid) => {
+ const quoteParentCid = cidTracker[quoteShortParentCid];
+ if (outOfViewCid !== quoteParentCid) {
+ handleQuoteHover(thread, quoteShortParentCid, () => {
+ setOutOfViewCid(quoteParentCid);
+
+ const rect = postRefs.current[quoteShortParentCid].getBoundingClientRect();
+ const distanceToRight = window.innerWidth - rect.right;
+ const distanceToTop = rect.top;
+ const distanceToBottom = window.innerHeight - rect.bottom;
+ let top;
+
+ if (distanceToTop < postOnHoverHeight / 2) {
+ top = window.scrollY - 5;
+ } else if (distanceToBottom < postOnHoverHeight / 2) {
+ top = window.scrollY - postOnHoverHeight + window.innerHeight - 10;
+ } else {
+ top = rect.top + window.scrollY - postOnHoverHeight / 2;
+ }
+
+ if (distanceToRight < 200) {
+ setOutOfViewPosition({
+ top,
+ right: window.innerWidth - rect.left - 10,
+ maxWidth: rect.left - 5,
+ });
+ } else {
+ setOutOfViewPosition({
+ top,
+ left: rect.left + rect.width + 5,
+ maxWidth: window.innerWidth - rect.left - rect.width - 5,
+ });
+ }
+ });
+ }
+ }}
+ postQuoteOnLeave={() => {
+ removeHighlight();
+ setOutOfViewCid(null);
+ }}
+ />
{' '}
(...)
@@ -2454,7 +2601,56 @@ const All = () => {
) : (
-
+ {
+ postRefs.current[quoteShortParentCid] = ref;
+ }}
+ postQuoteOnClick={(quoteShortParentCid) => {
+ handleQuoteClick(thread, quoteShortParentCid, null);
+ }}
+ postQuoteOnOver={(quoteShortParentCid) => {
+ const quoteParentCid = cidTracker[quoteShortParentCid];
+ if (outOfViewCid !== quoteParentCid) {
+ handleQuoteHover(thread, quoteShortParentCid, () => {
+ setOutOfViewCid(quoteParentCid);
+
+ const rect = postRefs.current[quoteShortParentCid].getBoundingClientRect();
+ const distanceToRight = window.innerWidth - rect.right;
+ const distanceToTop = rect.top;
+ const distanceToBottom = window.innerHeight - rect.bottom;
+ let top;
+
+ if (distanceToTop < postOnHoverHeight / 2) {
+ top = window.scrollY - 5;
+ } else if (distanceToBottom < postOnHoverHeight / 2) {
+ top = window.scrollY - postOnHoverHeight + window.innerHeight - 10;
+ } else {
+ top = rect.top + window.scrollY - postOnHoverHeight / 2;
+ }
+
+ if (distanceToRight < 200) {
+ setOutOfViewPosition({
+ top,
+ right: window.innerWidth - rect.left - 10,
+ maxWidth: rect.left - 5,
+ });
+ } else {
+ setOutOfViewPosition({
+ top,
+ left: rect.left + rect.width + 5,
+ maxWidth: window.innerWidth - rect.left - rect.width - 5,
+ });
+ }
+ });
+ }
+ }}
+ postQuoteOnLeave={() => {
+ removeHighlight();
+ setOutOfViewCid(null);
+ }}
+ />
@@ -3318,7 +3514,7 @@ const All = () => {
window.electron && window.electron.isElectron
? setIsCreateBoardOpen(true)
: alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n',
+ 'HOW TO CREATE A BOARD (currently via CLI only):\n\n(1) have a computer you can use as server, because users will connect to your board peer-to-peer;\n\n(2) go to https://github.com/plebbit/plebbit-cli#install and follow the instructions to run your daemon, create a subplebbit (board) and edit its settings;\n\n(3) users can always connect to your board via its address, but it can be added below by submitting a pull request here: https://github.com/plebbit/temporary-default-subplebbits. This will be automated with a plebbit DAO using the plebbit token.',
);
}}
>
diff --git a/src/components/views/AllCatalog.jsx b/src/components/views/AllCatalog.jsx
index ac43a393..f5fa5d1b 100755
--- a/src/components/views/AllCatalog.jsx
+++ b/src/components/views/AllCatalog.jsx
@@ -849,7 +849,7 @@ const AllCatalog = () => {
window.electron && window.electron.isElectron
? setIsCreateBoardOpen(true)
: alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n',
+ 'HOW TO CREATE A BOARD (currently via CLI only):\n\n(1) have a computer you can use as server, because users will connect to your board peer-to-peer;\n\n(2) go to https://github.com/plebbit/plebbit-cli#install and follow the instructions to run your daemon, create a subplebbit (board) and edit its settings;\n\n(3) users can always connect to your board via its address, but it can be added below by submitting a pull request here: https://github.com/plebbit/temporary-default-subplebbits. This will be automated with a plebbit DAO using the plebbit token.',
);
}}
>
@@ -881,7 +881,7 @@ const AllCatalog = () => {
style={{ cursor: 'pointer' }}
onClick={() =>
alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n',
+ 'HOW TO CREATE A BOARD (currently via CLI only):\n\n(1) have a computer you can use as server, because users will connect to your board peer-to-peer;\n\n(2) go to https://github.com/plebbit/plebbit-cli#install and follow the instructions to run your daemon, create a subplebbit (board) and edit its settings;\n\n(3) users can always connect to your board via its address, but it can be added below by submitting a pull request here: https://github.com/plebbit/temporary-default-subplebbits. This will be automated with a plebbit DAO using the plebbit token.',
)
}
>
@@ -1037,7 +1037,7 @@ const AllCatalog = () => {
window.electron && window.electron.isElectron
? setIsCreateBoardOpen(true)
: alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n',
+ 'HOW TO CREATE A BOARD (currently via CLI only):\n\n(1) have a computer you can use as server, because users will connect to your board peer-to-peer;\n\n(2) go to https://github.com/plebbit/plebbit-cli#install and follow the instructions to run your daemon, create a subplebbit (board) and edit its settings;\n\n(3) users can always connect to your board via its address, but it can be added below by submitting a pull request here: https://github.com/plebbit/temporary-default-subplebbits. This will be automated with a plebbit DAO using the plebbit token.',
);
}}
>
diff --git a/src/components/views/Board.jsx b/src/components/views/Board.jsx
index 695b7583..795e8767 100755
--- a/src/components/views/Board.jsx
+++ b/src/components/views/Board.jsx
@@ -765,7 +765,7 @@ const Board = () => {
window.electron && window.electron.isElectron
? setIsCreateBoardOpen(true)
: alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n',
+ 'HOW TO CREATE A BOARD (currently via CLI only):\n\n(1) have a computer you can use as server, because users will connect to your board peer-to-peer;\n\n(2) go to https://github.com/plebbit/plebbit-cli#install and follow the instructions to run your daemon, create a subplebbit (board) and edit its settings;\n\n(3) users can always connect to your board via its address, but it can be added below by submitting a pull request here: https://github.com/plebbit/temporary-default-subplebbits. This will be automated with a plebbit DAO using the plebbit token.',
);
}}
>
@@ -800,7 +800,7 @@ const Board = () => {
window.electron && window.electron.isElectron
? setIsCreateBoardOpen(true)
: alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n',
+ 'HOW TO CREATE A BOARD (currently via CLI only):\n\n(1) have a computer you can use as server, because users will connect to your board peer-to-peer;\n\n(2) go to https://github.com/plebbit/plebbit-cli#install and follow the instructions to run your daemon, create a subplebbit (board) and edit its settings;\n\n(3) users can always connect to your board via its address, but it can be added below by submitting a pull request here: https://github.com/plebbit/temporary-default-subplebbits. This will be automated with a plebbit DAO using the plebbit token.',
);
}}
>
@@ -884,7 +884,7 @@ const Board = () => {
- Embed File
+ Link
{
thread.content?.length > 1000 ? (
-
+ {
+ postRefs.current[quoteShortParentCid] = ref;
+ }}
+ postQuoteOnClick={(quoteShortParentCid) => {
+ handleQuoteClick(thread, quoteShortParentCid, null);
+ }}
+ postQuoteOnOver={(quoteShortParentCid) => {
+ const quoteParentCid = cidTracker[quoteShortParentCid];
+ if (outOfViewCid !== quoteParentCid) {
+ handleQuoteHover(thread, quoteShortParentCid, () => {
+ setOutOfViewCid(quoteParentCid);
+
+ const rect = postRefs.current[quoteShortParentCid].getBoundingClientRect();
+ const distanceToRight = window.innerWidth - rect.right;
+ const distanceToTop = rect.top;
+ const distanceToBottom = window.innerHeight - rect.bottom;
+ let top;
+
+ if (distanceToTop < postOnHoverHeight / 2) {
+ top = window.scrollY - 5;
+ } else if (distanceToBottom < postOnHoverHeight / 2) {
+ top = window.scrollY - postOnHoverHeight + window.innerHeight - 10;
+ } else {
+ top = rect.top + window.scrollY - postOnHoverHeight / 2;
+ }
+
+ if (distanceToRight < 200) {
+ setOutOfViewPosition({
+ top,
+ right: window.innerWidth - rect.left - 10,
+ maxWidth: rect.left - 5,
+ });
+ } else {
+ setOutOfViewPosition({
+ top,
+ left: rect.left + rect.width + 5,
+ maxWidth: window.innerWidth - rect.left - rect.width - 5,
+ });
+ }
+ });
+ }
+ }}
+ postQuoteOnLeave={() => {
+ removeHighlight();
+ setOutOfViewCid(null);
+ }}
+ />
{' '}
(...)
@@ -2270,7 +2319,56 @@ const Board = () => {
) : (
-
+ {
+ postRefs.current[quoteShortParentCid] = ref;
+ }}
+ postQuoteOnClick={(quoteShortParentCid) => {
+ handleQuoteClick(thread, quoteShortParentCid, null);
+ }}
+ postQuoteOnOver={(quoteShortParentCid) => {
+ const quoteParentCid = cidTracker[quoteShortParentCid];
+ if (outOfViewCid !== quoteParentCid) {
+ handleQuoteHover(thread, quoteShortParentCid, () => {
+ setOutOfViewCid(quoteParentCid);
+
+ const rect = postRefs.current[quoteShortParentCid].getBoundingClientRect();
+ const distanceToRight = window.innerWidth - rect.right;
+ const distanceToTop = rect.top;
+ const distanceToBottom = window.innerHeight - rect.bottom;
+ let top;
+
+ if (distanceToTop < postOnHoverHeight / 2) {
+ top = window.scrollY - 5;
+ } else if (distanceToBottom < postOnHoverHeight / 2) {
+ top = window.scrollY - postOnHoverHeight + window.innerHeight - 10;
+ } else {
+ top = rect.top + window.scrollY - postOnHoverHeight / 2;
+ }
+
+ if (distanceToRight < 200) {
+ setOutOfViewPosition({
+ top,
+ right: window.innerWidth - rect.left - 10,
+ maxWidth: rect.left - 5,
+ });
+ } else {
+ setOutOfViewPosition({
+ top,
+ left: rect.left + rect.width + 5,
+ maxWidth: window.innerWidth - rect.left - rect.width - 5,
+ });
+ }
+ });
+ }
+ }}
+ postQuoteOnLeave={() => {
+ removeHighlight();
+ setOutOfViewCid(null);
+ }}
+ />
@@ -3488,7 +3586,56 @@ const Board = () => {
thread.content?.length > 500 ? (
-
+ {
+ postRefs.current[quoteShortParentCid] = ref;
+ }}
+ postQuoteOnClick={(quoteShortParentCid) => {
+ handleQuoteClick(thread, quoteShortParentCid, null);
+ }}
+ postQuoteOnOver={(quoteShortParentCid) => {
+ const quoteParentCid = cidTracker[quoteShortParentCid];
+ if (outOfViewCid !== quoteParentCid) {
+ handleQuoteHover(thread, quoteShortParentCid, () => {
+ setOutOfViewCid(quoteParentCid);
+
+ const rect = postRefs.current[quoteShortParentCid].getBoundingClientRect();
+ const distanceToRight = window.innerWidth - rect.right;
+ const distanceToTop = rect.top;
+ const distanceToBottom = window.innerHeight - rect.bottom;
+ let top;
+
+ if (distanceToTop < postOnHoverHeight / 2) {
+ top = window.scrollY - 5;
+ } else if (distanceToBottom < postOnHoverHeight / 2) {
+ top = window.scrollY - postOnHoverHeight + window.innerHeight - 10;
+ } else {
+ top = rect.top + window.scrollY - postOnHoverHeight / 2;
+ }
+
+ if (distanceToRight < 200) {
+ setOutOfViewPosition({
+ top,
+ right: window.innerWidth - rect.left - 10,
+ maxWidth: rect.left - 5,
+ });
+ } else {
+ setOutOfViewPosition({
+ top,
+ left: rect.left + rect.width + 5,
+ maxWidth: window.innerWidth - rect.left - rect.width - 5,
+ });
+ }
+ });
+ }
+ }}
+ postQuoteOnLeave={() => {
+ removeHighlight();
+ setOutOfViewCid(null);
+ }}
+ />
{' '}
(...)
@@ -3511,7 +3658,56 @@ const Board = () => {
) : (
-
+ {
+ postRefs.current[quoteShortParentCid] = ref;
+ }}
+ postQuoteOnClick={(quoteShortParentCid) => {
+ handleQuoteClick(thread, quoteShortParentCid, null);
+ }}
+ postQuoteOnOver={(quoteShortParentCid) => {
+ const quoteParentCid = cidTracker[quoteShortParentCid];
+ if (outOfViewCid !== quoteParentCid) {
+ handleQuoteHover(thread, quoteShortParentCid, () => {
+ setOutOfViewCid(quoteParentCid);
+
+ const rect = postRefs.current[quoteShortParentCid].getBoundingClientRect();
+ const distanceToRight = window.innerWidth - rect.right;
+ const distanceToTop = rect.top;
+ const distanceToBottom = window.innerHeight - rect.bottom;
+ let top;
+
+ if (distanceToTop < postOnHoverHeight / 2) {
+ top = window.scrollY - 5;
+ } else if (distanceToBottom < postOnHoverHeight / 2) {
+ top = window.scrollY - postOnHoverHeight + window.innerHeight - 10;
+ } else {
+ top = rect.top + window.scrollY - postOnHoverHeight / 2;
+ }
+
+ if (distanceToRight < 200) {
+ setOutOfViewPosition({
+ top,
+ right: window.innerWidth - rect.left - 10,
+ maxWidth: rect.left - 5,
+ });
+ } else {
+ setOutOfViewPosition({
+ top,
+ left: rect.left + rect.width + 5,
+ maxWidth: window.innerWidth - rect.left - rect.width - 5,
+ });
+ }
+ });
+ }
+ }}
+ postQuoteOnLeave={() => {
+ removeHighlight();
+ setOutOfViewCid(null);
+ }}
+ />
@@ -4370,7 +4566,7 @@ const Board = () => {
window.electron && window.electron.isElectron
? setIsCreateBoardOpen(true)
: alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n',
+ 'HOW TO CREATE A BOARD (currently via CLI only):\n\n(1) have a computer you can use as server, because users will connect to your board peer-to-peer;\n\n(2) go to https://github.com/plebbit/plebbit-cli#install and follow the instructions to run your daemon, create a subplebbit (board) and edit its settings;\n\n(3) users can always connect to your board via its address, but it can be added below by submitting a pull request here: https://github.com/plebbit/temporary-default-subplebbits. This will be automated with a plebbit DAO using the plebbit token.',
);
}}
>
diff --git a/src/components/views/Catalog.jsx b/src/components/views/Catalog.jsx
index 0c49c6bf..c6afb37c 100755
--- a/src/components/views/Catalog.jsx
+++ b/src/components/views/Catalog.jsx
@@ -1534,7 +1534,7 @@ const Catalog = () => {
window.electron && window.electron.isElectron
? setIsCreateBoardOpen(true)
: alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n',
+ 'HOW TO CREATE A BOARD (currently via CLI only):\n\n(1) have a computer you can use as server, because users will connect to your board peer-to-peer;\n\n(2) go to https://github.com/plebbit/plebbit-cli#install and follow the instructions to run your daemon, create a subplebbit (board) and edit its settings;\n\n(3) users can always connect to your board via its address, but it can be added below by submitting a pull request here: https://github.com/plebbit/temporary-default-subplebbits. This will be automated with a plebbit DAO using the plebbit token.',
);
}}
>
@@ -1567,7 +1567,7 @@ const Catalog = () => {
style={{ cursor: 'pointer' }}
onClick={() =>
alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n',
+ 'HOW TO CREATE A BOARD (currently via CLI only):\n\n(1) have a computer you can use as server, because users will connect to your board peer-to-peer;\n\n(2) go to https://github.com/plebbit/plebbit-cli#install and follow the instructions to run your daemon, create a subplebbit (board) and edit its settings;\n\n(3) users can always connect to your board via its address, but it can be added below by submitting a pull request here: https://github.com/plebbit/temporary-default-subplebbits. This will be automated with a plebbit DAO using the plebbit token.',
)
}
>
@@ -1653,7 +1653,7 @@ const Catalog = () => {
- Embed File
+ Link
{
window.electron && window.electron.isElectron
? setIsCreateBoardOpen(true)
: alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n',
+ 'HOW TO CREATE A BOARD (currently via CLI only):\n\n(1) have a computer you can use as server, because users will connect to your board peer-to-peer;\n\n(2) go to https://github.com/plebbit/plebbit-cli#install and follow the instructions to run your daemon, create a subplebbit (board) and edit its settings;\n\n(3) users can always connect to your board via its address, but it can be added below by submitting a pull request here: https://github.com/plebbit/temporary-default-subplebbits. This will be automated with a plebbit DAO using the plebbit token.',
);
}}
>
diff --git a/src/components/views/Description.jsx b/src/components/views/Description.jsx
index 130647a3..8da9376e 100644
--- a/src/components/views/Description.jsx
+++ b/src/components/views/Description.jsx
@@ -196,7 +196,7 @@ const Description = () => {
window.electron && window.electron.isElectron
? setIsCreateBoardOpen(true)
: alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n',
+ 'HOW TO CREATE A BOARD (currently via CLI only):\n\n(1) have a computer you can use as server, because users will connect to your board peer-to-peer;\n\n(2) go to https://github.com/plebbit/plebbit-cli#install and follow the instructions to run your daemon, create a subplebbit (board) and edit its settings;\n\n(3) users can always connect to your board via its address, but it can be added below by submitting a pull request here: https://github.com/plebbit/temporary-default-subplebbits. This will be automated with a plebbit DAO using the plebbit token.',
);
}}
>
@@ -229,7 +229,7 @@ const Description = () => {
style={{ cursor: 'pointer' }}
onClick={() =>
alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n',
+ 'HOW TO CREATE A BOARD (currently via CLI only):\n\n(1) have a computer you can use as server, because users will connect to your board peer-to-peer;\n\n(2) go to https://github.com/plebbit/plebbit-cli#install and follow the instructions to run your daemon, create a subplebbit (board) and edit its settings;\n\n(3) users can always connect to your board via its address, but it can be added below by submitting a pull request here: https://github.com/plebbit/temporary-default-subplebbits. This will be automated with a plebbit DAO using the plebbit token.',
)
}
>
@@ -719,7 +719,7 @@ const Description = () => {
window.electron && window.electron.isElectron
? setIsCreateBoardOpen(true)
: alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n',
+ 'HOW TO CREATE A BOARD (currently via CLI only):\n\n(1) have a computer you can use as server, because users will connect to your board peer-to-peer;\n\n(2) go to https://github.com/plebbit/plebbit-cli#install and follow the instructions to run your daemon, create a subplebbit (board) and edit its settings;\n\n(3) users can always connect to your board via its address, but it can be added below by submitting a pull request here: https://github.com/plebbit/temporary-default-subplebbits. This will be automated with a plebbit DAO using the plebbit token.',
);
}}
>
diff --git a/src/components/views/Home.jsx b/src/components/views/Home.jsx
index 9da3cdba..dcd6b7a9 100644
--- a/src/components/views/Home.jsx
+++ b/src/components/views/Home.jsx
@@ -1,36 +1,93 @@
-import React, { Fragment, useEffect, useRef, useState } from 'react';
+import React, { useEffect, useRef, useState } from 'react';
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 { 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 OfflineIndicator from '../OfflineIndicator';
import CreateBoardModal from '../modals/CreateBoardModal';
import useGeneralStore from '../../hooks/stores/useGeneralStore';
import packageJson from '../../../package.json';
+import getCommentMediaInfo from '../../utils/getCommentMediaInfo';
import { Tooltip } from 'react-tooltip';
const { version } = packageJson;
const commitRef = process?.env?.REACT_APP_COMMIT_REF ? ` ${process.env.REACT_APP_COMMIT_REF.slice(0, 7)}` : '';
-const SubplebbitTitle = ({ address }) => {
- const subplebbitAddress = address;
- const subplebbit = useSubplebbit({ subplebbitAddress });
- const title = subplebbit.title ?? null;
+const RecentThread = ({ commentCid }) => {
+ const comment = useComment({ commentCid });
+ const subplebbit = useSubplebbit({ subplebbitAddress: comment?.subplebbitAddress });
+ const { setSelectedAddress, setSelectedTitle } = useGeneralStore((state) => state);
+ const commentMediaInfo = getCommentMediaInfo(comment);
+ const isMediaShowed =
+ comment.link &&
+ commentMediaInfo &&
+ (commentMediaInfo.type === 'image' ||
+ commentMediaInfo.type === 'video' ||
+ (commentMediaInfo.type === 'webpage' && commentMediaInfo.thumbnail) ||
+ (commentMediaInfo.type === 'iframe' && commentMediaInfo.thumbnail))
+ ? true
+ : false;
- return <>{title ? {title} : }>;
+ return (
+ <>
+ {isMediaShowed && comment.replyCount > 0 && !comment.removed ? (
+
+
+ {subplebbit.title || subplebbit.address}
+
+
+
{
+ setSelectedTitle(subplebbit?.title);
+ setSelectedAddress(comment?.subplebbitAddress);
+ window.scrollTo(0, 0);
+ }}
+ >
+ {commentMediaInfo?.type === 'webpage' && comment.thumbnailUrl ? (
+
+ ) : commentMediaInfo?.type === 'image' ? (
+
+ ) : commentMediaInfo?.type === 'video' ? (
+
+ ) : commentMediaInfo?.type === 'iframe' ? (
+
+ ) : (
+
+ )}
+
+
+
+
+ {comment?.title ? {comment?.title} : null}
+ {comment?.content ? (comment.content.length > 99 ? `: ${comment.content.substring(0, 99)}...` : `: ${comment.content}`) : null}
+
+
+ ) : null}
+ >
+ );
};
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 navigate = useNavigate();
+ const isElectron = window.electron && window.electron.isElectron;
const inputRef = useRef(null);
const prevStyle = useRef(selectedStyle);
const prevBodyStyle = useRef(bodyStyle);
const [isCreateBoardOpen, setIsCreateBoardOpen] = useState(false);
+ const [showAllSFWBoards, setShowAllSFWBoards] = useState(false);
+ const [showAllSubscriptions, setShowAllSubscriptions] = useState(false);
// prevent dark mode
useEffect(() => {
@@ -84,7 +141,7 @@ const Home = () => {
/>
{
const address = inputRef.current.value;
if (address) {
@@ -101,58 +158,112 @@ const Home = () => {
- Plebchan is the only serverless, adminless, fully decentralized 4chan alternative where any pleb can create and own unlimited boards, and nobody can
- take them down. Boards can always find competition, and board owners can monetize freely, so janitors aren't needed. Plebchan is a client for{' '}
+ Plebchan is a serverless, adminless, decentralized 4chan alternative where any pleb can create and own unlimited boards. All data comes from the
plebbit
-
- , 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
- are{' '}
- {
- 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
-
- . Search for any board address above, or feel free to click on a popular board below that interests you and jump right in!{' '}
+ {' '}
+ 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
+ in the community. Feel free to click on a board below that interests you and jump right in!{' '}
There are no global rules, each board is completely independent and its owner decides how/if it should be moderated.
-
-
- {' '}
- HOW TO RUN A BOARD (currently via CLI only): (1) have a computer you can use as server, because users will connect to your board
- peer-to-peer; (2) go to{' '}
-
- https://github.com/plebbit/plebbit-cli#install
- {' '}
- and follow the instructions to run your daemon, create a subplebbit (board) and edit its settings; (3) users can always connect to your
- board via its address, but it can be added below by submitting a pull request here:{' '}
-
- https://github.com/plebbit/temporary-default-subplebbits
- {' '}
- this will be automated with a plebbit DAO using the plebbit token.
-
- {account?.subscriptions?.length > 0 ? (
-
-
- Subscriptions
-
-
+
+
+
Boards
+
+
+
- You have subscribed to {account?.subscriptions?.length} board{account?.subscriptions?.length > 1 ? 's' : null}
+
+ Default SFW
+
+
{
+ window.scrollTo(0, 0);
+ }}
+ >
+ [view all]
+
+
+ {sfwList.slice(0, showAllSFWBoards ? undefined : 18).map((address, index) => (
+
+
+ {
+ window.scrollTo(0, 0);
+ }}
+ to={`/p/${address}`}
+ >
+ {address}
+
+
+
+ ))}
+ {sfwList.length > 17 && (
+ setShowAllSFWBoards(!showAllSFWBoards)}>
+ {!showAllSFWBoards ? '... ' : null}
+ {showAllSFWBoards ? '[show less]' : '[show more]'}
+
+ )}
+
+
+
+
+
+ {defaultNsfwSubplebbits.length === 0 && No boards yet in this list. }
+ {defaultNsfwSubplebbits.slice(0, showAllSFWBoards ? undefined : 18).map((subplebbit, index) => (
+
+
+ {
+ window.scrollTo(0, 0);
+ }}
+ to={`/p/${subplebbit.address}`}
+ >
+ {subplebbit.address}
+
+
+
+ ))}
+ {defaultNsfwSubplebbits.length > 17 && (
+ setShowAllSFWBoards(!showAllSFWBoards)}>
+ {!showAllSFWBoards ? '... ' : null}
+ {showAllSFWBoards ? '[show less]' : '[show more]'}
+
+ )}
+
+
+
+
Subscriptions
+
{
window.scrollTo(0, 0);
}}
@@ -160,58 +271,65 @@ const Home = () => {
[view all]
- {account?.subscriptions?.map((subscription, index) => (
-
- {
- window.scrollTo(0, 0);
- }}
- to={`/p/${subscription}`}
- >
-
- {subscription}
-
-
-
-
- ))}
-
-
-
- ) : null}
-
-
- Default Boards
-
+
+ {account?.subscriptions?.length === 0 && Not subscribed to any board. }
+ {account?.subscriptions?.slice(0, showAllSubscriptions ? undefined : 18).map((subscription, index) => (
+
+
+ {
+ window.scrollTo(0, 0);
+ }}
+ to={`/p/${subscription}`}
+ >
+ {subscription}
+
+
+
+ ))}
+ {account?.subscriptions?.length > 17 && (
+ setShowAllSubscriptions(!showAllSubscriptions)}>
+ {!showAllSubscriptions ? '... ' : null}
+ {showAllSubscriptions ? '[show less]' : '[show more]'}
+
+ )}
+
+
+
+
+
+
+
+
Popular Threads
+
- {defaultSubplebbits.map((subplebbit, index) => (
-
-
- {subplebbit.title ?? }
-
-
- {
- setSelectedTitle(subplebbit.title);
- setSelectedAddress(subplebbit.address);
- window.scrollTo(0, 0);
- }}
- >
-
-
-
-
-
- {subplebbit.address}
-
-
+ {sfwListCids.map((cid) => (
+
))}
-
+
diff --git a/src/components/views/NotFound.jsx b/src/components/views/NotFound.jsx
index e6815d21..da2b851e 100644
--- a/src/components/views/NotFound.jsx
+++ b/src/components/views/NotFound.jsx
@@ -1,23 +1,22 @@
import React, { useEffect } from 'react';
import { Helmet } from 'react-helmet-async';
-import { Link } from "react-router-dom";
-import { Container, Header, Logo, Page, Boards, BoardsTitle } from '../styled/views/Home.styled';
+import { Link } from 'react-router-dom';
+import { Container, Header, Logo, Page, BoardsBox } from '../styled/views/Home.styled';
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 NotFound = () => {
useEffect(() => {
const yotsubaBodyStyle = {
- background: "#ffe url(assets/fade.png) top repeat-x",
- color: "maroon",
- fontFamily: "Arial, Helvetica, sans-serif"
+ background: '#ffe url(assets/fade.png) top repeat-x',
+ color: 'maroon',
+ fontFamily: 'Arial, Helvetica, sans-serif',
};
const originalBodyStyles = {
background: document.body.style.background,
color: document.body.style.color,
- fontFamily: document.body.style.fontFamily
+ fontFamily: document.body.style.fontFamily,
};
for (const [key, value] of Object.entries(yotsubaBodyStyle)) {
@@ -39,34 +38,41 @@ const NotFound = () => {
-
-
+
+
-
-
- 404 Not Found
-
-
-
+
+
+
404 Not Found
+
+
+
-
- plebchan v{version}{commitRef}. GPL-2.0
+
+ plebchan v{version}
+ {commitRef}. GPL-2.0
>
);
-}
+};
-export default NotFound;
\ No newline at end of file
+export default NotFound;
diff --git a/src/components/views/Pending.jsx b/src/components/views/Pending.jsx
index d1e10ded..8d7022af 100755
--- a/src/components/views/Pending.jsx
+++ b/src/components/views/Pending.jsx
@@ -20,24 +20,17 @@ import handleStyleChange from '../../utils/handleStyleChange';
import useError from '../../hooks/useError';
import useStateString from '../../hooks/useStateString';
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 Pending = () => {
- const {
- defaultSubplebbits,
- isSettingsOpen, setIsSettingsOpen,
- selectedAddress, setSelectedAddress,
- selectedStyle,
- setSelectedTitle,
- showPostFormLink
- } = useGeneralStore(state => state);
+ const { defaultSubplebbits, isSettingsOpen, setIsSettingsOpen, selectedAddress, setSelectedAddress, selectedStyle, setSelectedTitle, showPostFormLink } =
+ useGeneralStore((state) => state);
const { index } = useParams();
const account = useAccount();
- const comment = useAccountComment({commentIndex: index});
+ const comment = useAccountComment({ commentIndex: index });
const [, setNewErrorMessage] = useError();
const [isThumbnailClicked, setIsThumbnailClicked] = useState({});
const [isMobileThumbnailClicked, setIsMobileThumbnailClicked] = useState({});
@@ -45,17 +38,17 @@ const Pending = () => {
const subplebbitAddress = comment?.subplebbitAddress;
- const subplebbit = useSubplebbit({subplebbitAddress})
+ const subplebbit = useSubplebbit({ subplebbitAddress });
const selectedTitle = subplebbit?.title;
- const handleThumbnailClick = (index, isMobile=false) => {
+ const handleThumbnailClick = (index, isMobile = false) => {
if (isMobile) {
- setIsMobileThumbnailClicked(prevState => ({
+ setIsMobileThumbnailClicked((prevState) => ({
...prevState,
[index]: !prevState[index],
}));
} else {
- setIsThumbnailClicked(prevState => ({
+ setIsThumbnailClicked((prevState) => ({
...prevState,
[index]: !prevState[index],
}));
@@ -66,17 +59,17 @@ const Pending = () => {
setSelectedAddress(comment?.subplebbitAddress);
}, [comment, setSelectedAddress]);
- const stateString = useStateString(comment)
+ const stateString = useStateString(comment);
const errorString = useMemo(() => {
if (comment?.state === 'failed') {
let errorString = 'Failed fetching pending thread. Pending index: ' + index;
if (comment.error) {
- errorString += `: ${comment.error.toString().slice(0, 300)}`
+ errorString += `: ${comment.error.toString().slice(0, 300)}`;
}
- return errorString
+ return errorString;
}
- }, [comment?.state, comment?.error, index])
+ }, [comment?.state, comment?.error, index]);
useEffect(() => {
if (errorString) {
@@ -88,7 +81,7 @@ const Pending = () => {
const navigate = useNavigate();
const [commentMediaInfo, setCommentMediaInfo] = useState(null);
- const fallbackImgUrl = "assets/filedeleted-res.gif";
+ const fallbackImgUrl = 'assets/filedeleted-res.gif';
// mobile navbar board select functionality
const handleSelectChange = (event) => {
@@ -115,7 +108,6 @@ const Pending = () => {
setCommentMediaInfo(mediaInfo);
}
}, [comment]);
-
return (
<>
@@ -123,111 +115,144 @@ const Pending = () => {
{`plebchan - Pending Thread #${parseInt(index) + 1}`}
- setIsCreateBoardOpen(false)} />
- setIsSettingsOpen(false)} />
+ setIsCreateBoardOpen(false)} />
+ setIsSettingsOpen(false)} />
<>
-
- [
- window.scrollTo(0, 0)}>All
- /
- window.scrollTo(0, 0)}>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}
-
- ))}
- ]
-
-
+
[
- {
- window.electron && window.electron.isElectron ? (
- setIsCreateBoardOpen(true)
- ) : (
- alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n'
- )
- )
- }
- }>Create Board
- ]
- [
- setIsSettingsOpen(true)}>Settings
- ]
- [
- Home
+ window.scrollTo(0, 0)}>
+ All
+
+ /
+ window.scrollTo(0, 0)}>
+ 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}
+
+ ))}
]
-
-
-
+
+ [
+ {
+ window.electron && window.electron.isElectron
+ ? setIsCreateBoardOpen(true)
+ : alert(
+ 'HOW TO CREATE A BOARD (currently via CLI only):\n\n(1) have a computer you can use as server, because users will connect to your board peer-to-peer;\n\n(2) go to https://github.com/plebbit/plebbit-cli#install and follow the instructions to run your daemon, create a subplebbit (board) and edit its settings;\n\n(3) users can always connect to your board via its address, but it can be added below by submitting a pull request here: https://github.com/plebbit/temporary-default-subplebbits. This will be automated with a plebbit DAO using the plebbit token.',
+ );
+ }}
+ >
+ Create Board
+
+ ] [
+ setIsSettingsOpen(true)}>
+ Settings
+
+ ] [ Home]
+
+
+
+
Board
-
- All
- Subscriptions
- {!defaultSubplebbits.some(subplebbit => subplebbit.address === selectedAddress) && (
- {selectedAddress}
- )}
- {defaultSubplebbits.map(subplebbit => (
- {subplebbit.title ? subplebbit.title : subplebbit.address}
- ))}
-
- alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n'
- )
- }>Create Board
+
+ All
+ Subscriptions
+ {!defaultSubplebbits.some((subplebbit) => subplebbit.address === selectedAddress) && {selectedAddress} }
+ {defaultSubplebbits.map((subplebbit) => (
+
+ {subplebbit.title ? subplebbit.title : subplebbit.address}
+
+ ))}
+
+
+
+ alert(
+ 'HOW TO CREATE A BOARD (currently via CLI only):\n\n(1) have a computer you can use as server, because users will connect to your board peer-to-peer;\n\n(2) go to https://github.com/plebbit/plebbit-cli#install and follow the instructions to run your daemon, create a subplebbit (board) and edit its settings;\n\n(3) users can always connect to your board via its address, but it can be added below by submitting a pull request here: https://github.com/plebbit/temporary-default-subplebbits. This will be automated with a plebbit DAO using the plebbit token.',
+ )
+ }
+ >
+ Create Board
+
-
-
setIsSettingsOpen(true)}>Settings
+
+ setIsSettingsOpen(true)}>
+ Settings
+
- {handleStyleChange({target: {value: "Yotsuba"}}); window.scrollTo(0, 0);}}>Home
+ {
+ handleStyleChange({ target: { value: 'Yotsuba' } });
+ window.scrollTo(0, 0);
+ }}
+ >
+ Home
+
-
-
+
+
>
- Embed File
+ Link
{
-
+ {
+ postRefs.current[quoteShortParentCid] = ref;
+ }}
+ postQuoteOnClick={(quoteShortParentCid) => {
+ handleQuoteClick(comment, quoteShortParentCid, null);
+ }}
+ postQuoteOnOver={(quoteShortParentCid) => {
+ const quoteParentCid = cidTracker[quoteShortParentCid];
+ if (outOfViewCid !== quoteParentCid) {
+ handleQuoteHover(comment, quoteShortParentCid, () => {
+ setOutOfViewCid(quoteParentCid);
+
+ const rect = postRefs.current[quoteShortParentCid].getBoundingClientRect();
+ const distanceToRight = window.innerWidth - rect.right;
+ const distanceToTop = rect.top;
+ const distanceToBottom = window.innerHeight - rect.bottom;
+ let top;
+
+ if (distanceToTop < postOnHoverHeight / 2) {
+ top = window.scrollY - 5;
+ } else if (distanceToBottom < postOnHoverHeight / 2) {
+ top = window.scrollY - postOnHoverHeight + window.innerHeight - 10;
+ } else {
+ top = rect.top + window.scrollY - postOnHoverHeight / 2;
+ }
+
+ if (distanceToRight < 200) {
+ setOutOfViewPosition({
+ top,
+ right: window.innerWidth - rect.left - 10,
+ maxWidth: rect.left - 5,
+ });
+ } else {
+ setOutOfViewPosition({
+ top,
+ left: rect.left + rect.width + 5,
+ maxWidth: window.innerWidth - rect.left - rect.width - 5,
+ });
+ }
+ });
+ }
+ }}
+ postQuoteOnLeave={() => {
+ removeHighlight();
+ setOutOfViewCid(null);
+ }}
+ />
@@ -2376,7 +2425,56 @@ const Thread = () => {
{comment.content ? (
<>
-
+ {
+ postRefs.current[quoteShortParentCid] = ref;
+ }}
+ postQuoteOnClick={(quoteShortParentCid) => {
+ handleQuoteClick(comment, quoteShortParentCid, null);
+ }}
+ postQuoteOnOver={(quoteShortParentCid) => {
+ const quoteParentCid = cidTracker[quoteShortParentCid];
+ if (outOfViewCid !== quoteParentCid) {
+ handleQuoteHover(comment, quoteShortParentCid, () => {
+ setOutOfViewCid(quoteParentCid);
+
+ const rect = postRefs.current[quoteShortParentCid].getBoundingClientRect();
+ const distanceToRight = window.innerWidth - rect.right;
+ const distanceToTop = rect.top;
+ const distanceToBottom = window.innerHeight - rect.bottom;
+ let top;
+
+ if (distanceToTop < postOnHoverHeight / 2) {
+ top = window.scrollY - 5;
+ } else if (distanceToBottom < postOnHoverHeight / 2) {
+ top = window.scrollY - postOnHoverHeight + window.innerHeight - 10;
+ } else {
+ top = rect.top + window.scrollY - postOnHoverHeight / 2;
+ }
+
+ if (distanceToRight < 200) {
+ setOutOfViewPosition({
+ top,
+ right: window.innerWidth - rect.left - 10,
+ maxWidth: rect.left - 5,
+ });
+ } else {
+ setOutOfViewPosition({
+ top,
+ left: rect.left + rect.width + 5,
+ maxWidth: window.innerWidth - rect.left - rect.width - 5,
+ });
+ }
+ });
+ }
+ }}
+ postQuoteOnLeave={() => {
+ removeHighlight();
+ setOutOfViewCid(null);
+ }}
+ />
>
@@ -3159,7 +3257,7 @@ const Thread = () => {
window.electron && window.electron.isElectron
? setIsCreateBoardOpen(true)
: alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n',
+ 'HOW TO CREATE A BOARD (currently via CLI only):\n\n(1) have a computer you can use as server, because users will connect to your board peer-to-peer;\n\n(2) go to https://github.com/plebbit/plebbit-cli#install and follow the instructions to run your daemon, create a subplebbit (board) and edit its settings;\n\n(3) users can always connect to your board via its address, but it can be added below by submitting a pull request here: https://github.com/plebbit/temporary-default-subplebbits. This will be automated with a plebbit DAO using the plebbit token.',
);
}}
>
diff --git a/src/hooks/stores/useGeneralStore.js b/src/hooks/stores/useGeneralStore.js
index 83b3b378..116a6ec2 100644
--- a/src/hooks/stores/useGeneralStore.js
+++ b/src/hooks/stores/useGeneralStore.js
@@ -20,6 +20,9 @@ const useGeneralStore = create((set) => ({
defaultSubplebbits: [],
setDefaultSubplebbits: (subplebbits) => set({ defaultSubplebbits: subplebbits }),
+ defaultNsfwSubplebbits: [],
+ setDefaultNsfwSubplebbits: (subplebbits) => set({ defaultNsfwSubplebbits: subplebbits }),
+
deletePost: false,
setDeletePost: (deletePost) => set({ deletePost }),
diff --git a/yarn.lock b/yarn.lock
index fa8ff152..3949ab5a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2817,21 +2817,6 @@
dependencies:
debug "4.3.3"
-"@plebbit/plebbit-react-hooks@https://github.com/plebbit/plebbit-react-hooks.git#0024401c390929e47b44331a8dadd61ba212b871":
- version "0.0.1"
- resolved "https://github.com/plebbit/plebbit-react-hooks.git#0024401c390929e47b44331a8dadd61ba212b871"
- dependencies:
- "@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#6985b2a4194328752c6d76e80470c8079c562869"
- "@plebbit/plebbit-logger" "https://github.com/plebbit/plebbit-logger.git"
- assert "2.0.0"
- ethers "5.6.9"
- localforage "1.10.0"
- lodash.isequal "4.5.0"
- memoizee "0.4.15"
- quick-lru "5.1.1"
- uuid "8.3.2"
- zustand "4.0.0"
-
"@plebbit/plebbit-react-hooks@https://github.com/plebbit/plebbit-react-hooks.git#b6477148191a501aa0b0c11acfc4761aca0dcc1e":
version "0.0.1"
resolved "https://github.com/plebbit/plebbit-react-hooks.git#b6477148191a501aa0b0c11acfc4761aca0dcc1e"