mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
+27
-2
@@ -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;
|
||||
|
||||
@@ -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 (
|
||||
<StyledModal
|
||||
isOpen={isOpen}
|
||||
onAfterOpen={onModalOpen}
|
||||
onRequestClose={closeModal}
|
||||
contentLabel='Reply Modal'
|
||||
shouldCloseOnEsc={true}
|
||||
shouldCloseOnOverlayClick={isMobile}
|
||||
selectedStyle={selectedStyle}
|
||||
overlayClassName='overlay'
|
||||
style={isMobile ? { overlay: { backgroundColor: 'rgba(0,0,0,.25)' } } : { overlay: { backgroundColor: 'rgba(0,0,0,0)' } }}
|
||||
>
|
||||
<Draggable handle='.modal-header' nodeRef={nodeRef} disabled={isMobile}>
|
||||
<div className='modal-content' ref={nodeRef}>
|
||||
<div className='modal-header'>
|
||||
Reply to c/{selectedShortCid}
|
||||
<button className='icon' onClick={() => closeModal()} title='close' />
|
||||
</div>
|
||||
<div id='form'>
|
||||
<div>
|
||||
{account?.author.displayName ? (
|
||||
<input id='name' type='text' defaultValue={account?.author?.displayName} ref={nameRef} />
|
||||
) : (
|
||||
<input id='name' type='text' placeholder='Anonymous' ref={nameRef} />
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<input id='name' type='text' placeholder='Embed link' ref={linkRef} />
|
||||
</div>
|
||||
<div className='textarea-wrapper'>
|
||||
<span className='fixed-text'>{`c/${selectedShortCid}`}</span>
|
||||
<textarea className='textarea' rows='4' placeholder='Comment' defaultValue={selectedText} wrap='soft' ref={commentRef} />
|
||||
</div>
|
||||
<div>
|
||||
<button id='next' onClick={handleSubmit}>
|
||||
Post
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Draggable>
|
||||
</StyledModal>
|
||||
);
|
||||
return (
|
||||
<StyledModal
|
||||
isOpen={isOpen}
|
||||
onAfterOpen={onModalOpen}
|
||||
onRequestClose={closeModal}
|
||||
contentLabel='Reply Modal'
|
||||
shouldCloseOnEsc={true}
|
||||
shouldCloseOnOverlayClick={isMobile}
|
||||
selectedStyle={selectedStyle}
|
||||
overlayClassName='overlay'
|
||||
style={isMobile ? { overlay: { backgroundColor: 'rgba(0,0,0,.25)' } } : { overlay: { backgroundColor: 'rgba(0,0,0,0)' } }}
|
||||
>
|
||||
<Draggable handle='.modal-header' nodeRef={nodeRef} disabled={isMobile}>
|
||||
<div className='modal-content' ref={nodeRef}>
|
||||
<div className='modal-header'>
|
||||
Reply to c/{selectedShortCid}
|
||||
<button className='icon' onClick={() => closeModal()} title='close' />
|
||||
</div>
|
||||
<div id='form'>
|
||||
<div>
|
||||
{account?.author.displayName ? (
|
||||
<input id='name' type='text' defaultValue={account?.author?.displayName} ref={nameRef} />
|
||||
) : (
|
||||
<input id='name' type='text' placeholder='Anonymous' ref={nameRef} />
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<input id='name' type='text' placeholder='Link' ref={linkRef} />
|
||||
</div>
|
||||
<div className='textarea-wrapper'>
|
||||
<span className='fixed-text'>{`c/${selectedShortCid}`}</span>
|
||||
<textarea className='textarea' rows='4' placeholder='Comment' defaultValue={selectedText} wrap='soft' ref={commentRef} />
|
||||
</div>
|
||||
<div>
|
||||
<button id='next' onClick={handleSubmit}>
|
||||
Post
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Draggable>
|
||||
</StyledModal>
|
||||
);
|
||||
};
|
||||
|
||||
Modal.setAppElement('#root');
|
||||
|
||||
@@ -44,7 +44,6 @@ export const GlobalStyle = createGlobalStyle`
|
||||
|
||||
.poster-address {
|
||||
display: inline-block;
|
||||
overflow: clip;
|
||||
}
|
||||
|
||||
.author-address-hidden {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
`;
|
||||
`;
|
||||
|
||||
@@ -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 ? (
|
||||
<Fragment key={`fragment5-${index}`}>
|
||||
<blockquote key={`bq-${index}`}>
|
||||
<Post content={thread.content?.slice(0, 1000)} key={`post-${index}`} />
|
||||
<Post
|
||||
key={`post-${thread.cid}`}
|
||||
content={thread.content?.slice(0, 1000)}
|
||||
postQuoteRef={(quoteShortParentCid, ref) => {
|
||||
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);
|
||||
}}
|
||||
/>
|
||||
<span key={`ttl-s-${index}`} className='ttl'>
|
||||
{' '}
|
||||
(...)
|
||||
@@ -1237,7 +1286,56 @@ const All = () => {
|
||||
</Fragment>
|
||||
) : (
|
||||
<blockquote key={`bq-${index}`}>
|
||||
<Post content={thread.content} key={`post-${index}`} />
|
||||
<Post
|
||||
key={`post-${thread.cid}`}
|
||||
content={thread.content}
|
||||
postQuoteRef={(quoteShortParentCid, ref) => {
|
||||
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);
|
||||
}}
|
||||
/>
|
||||
<EditLabel key={`edit-label-thread-${index}`} commentCid={thread.cid} className='ttl' />
|
||||
<StateLabel key={`state-label-thread-${index}`} commentIndex={thread.index} className='ttl ellipsis' />
|
||||
</blockquote>
|
||||
@@ -2431,7 +2529,56 @@ const All = () => {
|
||||
thread.content?.length > 500 ? (
|
||||
<Fragment key={`fragment12-${index}`}>
|
||||
<blockquote key={`mob-bq-${index}`} className='post-message-mobile'>
|
||||
<Post content={thread.content?.slice(0, 500)} key={`post-mobile-${index}`} />
|
||||
<Post
|
||||
key={`post-mobile-${thread.cid}`}
|
||||
content={thread.content?.slice(0, 500)}
|
||||
postQuoteRef={(quoteShortParentCid, ref) => {
|
||||
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);
|
||||
}}
|
||||
/>
|
||||
<span key={`mob-ttl-s-${index}`} className='ttl'>
|
||||
{' '}
|
||||
(...)
|
||||
@@ -2454,7 +2601,56 @@ const All = () => {
|
||||
</Fragment>
|
||||
) : (
|
||||
<blockquote key={`mob-bq-${index}`} className='post-message-mobile'>
|
||||
<Post content={thread.content} key={`post-mobile-${index}`} />
|
||||
<Post
|
||||
key={`post-mobile-${thread.cid}`}
|
||||
content={thread.content}
|
||||
postQuoteRef={(quoteShortParentCid, ref) => {
|
||||
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);
|
||||
}}
|
||||
/>
|
||||
<EditLabel key={`edit-label-thread-mob-${index}`} commentCid={thread.cid} className='ttl' />
|
||||
<StateLabel key={`state-label-thread-mob-${index}`} commentIndex={thread.index} className='ttl ellipsis' />
|
||||
</blockquote>
|
||||
@@ -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.',
|
||||
);
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -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.',
|
||||
);
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -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 = () => {
|
||||
</td>
|
||||
</tr>
|
||||
<tr data-type='File'>
|
||||
<td>Embed File</td>
|
||||
<td>Link</td>
|
||||
<td>
|
||||
<input name='embed' type='text' tabIndex={7} placeholder='Paste link' ref={linkRef} />
|
||||
<button
|
||||
@@ -2247,7 +2247,56 @@ const Board = () => {
|
||||
thread.content?.length > 1000 ? (
|
||||
<Fragment key={`fragment5-${index}`}>
|
||||
<blockquote key={`bq-${index}`}>
|
||||
<Post content={thread.content?.slice(0, 1000)} key={`post-${index}`} />
|
||||
<Post
|
||||
key={`post-${thread.cid}`}
|
||||
content={thread.content?.slice(0, 1000)}
|
||||
postQuoteRef={(quoteShortParentCid, ref) => {
|
||||
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);
|
||||
}}
|
||||
/>
|
||||
<span key={`ttl-s-${index}`} className='ttl'>
|
||||
{' '}
|
||||
(...)
|
||||
@@ -2270,7 +2319,56 @@ const Board = () => {
|
||||
</Fragment>
|
||||
) : (
|
||||
<blockquote key={`bq-${index}`}>
|
||||
<Post content={thread.content} key={`post-${index}`} />
|
||||
<Post
|
||||
key={`post-${thread.cid}`}
|
||||
content={thread.content}
|
||||
postQuoteRef={(quoteShortParentCid, ref) => {
|
||||
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);
|
||||
}}
|
||||
/>
|
||||
<EditLabel key={`edit-label-thread-${index}`} commentCid={thread.cid} className='ttl' />
|
||||
<StateLabel key={`state-label-thread-${index}`} commentIndex={thread.index} className='ttl ellipsis' />
|
||||
</blockquote>
|
||||
@@ -3488,7 +3586,56 @@ const Board = () => {
|
||||
thread.content?.length > 500 ? (
|
||||
<Fragment key={`fragment12-${index}`}>
|
||||
<blockquote key={`mob-bq-${index}`} className='post-message-mobile'>
|
||||
<Post content={thread.content?.slice(0, 500)} key={`post-mobile-${index}`} />
|
||||
<Post
|
||||
key={`post-mobile-${thread.cid}`}
|
||||
content={thread.content?.slice(0, 500)}
|
||||
postQuoteRef={(quoteShortParentCid, ref) => {
|
||||
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);
|
||||
}}
|
||||
/>
|
||||
<span key={`mob-ttl-s-${index}`} className='ttl'>
|
||||
{' '}
|
||||
(...)
|
||||
@@ -3511,7 +3658,56 @@ const Board = () => {
|
||||
</Fragment>
|
||||
) : (
|
||||
<blockquote key={`mob-bq-${index}`} className='post-message-mobile'>
|
||||
<Post content={thread.content} key={`post-mobile-${index}`} />
|
||||
<Post
|
||||
key={`post-mobile-${thread.cid}`}
|
||||
content={thread.content?.slice(0, 1000)}
|
||||
postQuoteRef={(quoteShortParentCid, ref) => {
|
||||
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);
|
||||
}}
|
||||
/>
|
||||
<EditLabel key={`edit-label-thread-mob-${index}`} commentCid={thread.cid} className='ttl' />
|
||||
<StateLabel key={`state-label-thread-mob-${index}`} commentIndex={thread.index} className='ttl ellipsis' />
|
||||
</blockquote>
|
||||
@@ -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.',
|
||||
);
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -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 = () => {
|
||||
</td>
|
||||
</tr>
|
||||
<tr data-type='File'>
|
||||
<td>Embed File</td>
|
||||
<td>Link</td>
|
||||
<td>
|
||||
<input name='embed' type='text' tabIndex={7} placeholder='Paste link' ref={linkRef} />
|
||||
<button
|
||||
@@ -1828,7 +1828,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.',
|
||||
);
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -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.',
|
||||
);
|
||||
}}
|
||||
>
|
||||
|
||||
+216
-98
@@ -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 ? <span>{title}</span> : <span style={{ userSelect: 'none' }}> </span>}</>;
|
||||
return (
|
||||
<>
|
||||
{isMediaShowed && comment.replyCount > 0 && !comment.removed ? (
|
||||
<div className='board'>
|
||||
<div className='board-title' key='board-title'>
|
||||
<span>{subplebbit.title || subplebbit.address}</span>
|
||||
</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' />
|
||||
) : commentMediaInfo?.type === 'video' ? (
|
||||
<video className='board-avatar' src={commentMediaInfo?.url} alt='post' />
|
||||
) : commentMediaInfo?.type === 'iframe' ? (
|
||||
<img className='board-avatar' src={commentMediaInfo?.thumbnail} 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.length > 99 ? `: ${comment.content.substring(0, 99)}...` : `: ${comment.content}`) : null}
|
||||
</div>
|
||||
</div>
|
||||
) : 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 = () => {
|
||||
/>
|
||||
<input
|
||||
type='submit'
|
||||
value='Search'
|
||||
value='Connect'
|
||||
onClick={() => {
|
||||
const address = inputRef.current.value;
|
||||
if (address) {
|
||||
@@ -101,58 +158,112 @@ const Home = () => {
|
||||
<AboutContent>
|
||||
<div id='content'>
|
||||
<p>
|
||||
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
|
||||
<a href='https://plebbit.com' target='_blank' rel='noreferrer'>
|
||||
plebbit
|
||||
</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
|
||||
are{' '}
|
||||
<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!{' '}
|
||||
</a>{' '}
|
||||
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!{' '}
|
||||
</p>
|
||||
<br />
|
||||
<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>
|
||||
</AboutContent>
|
||||
</About>
|
||||
{account?.subscriptions?.length > 0 ? (
|
||||
<Boards>
|
||||
<BoardsTitle>
|
||||
<h2>Subscriptions</h2>
|
||||
</BoardsTitle>
|
||||
<BoardsContent id='subscriptions'>
|
||||
<BoardsBox>
|
||||
<div className='boxbar'>
|
||||
<h2>Boards</h2>
|
||||
</div>
|
||||
<div class='boxcontent'>
|
||||
<div class='column'>
|
||||
<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>
|
||||
|
||||
<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
|
||||
to='/p/subscriptions'
|
||||
id='view-all'
|
||||
id='button'
|
||||
onClick={() => {
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
@@ -160,58 +271,65 @@ const Home = () => {
|
||||
[view all]
|
||||
</Link>
|
||||
<br />
|
||||
{account?.subscriptions?.map((subscription, index) => (
|
||||
<Fragment key={`frag-${index}`}>
|
||||
<Link
|
||||
key={`sub-${index}`}
|
||||
className='boardlink'
|
||||
onClick={() => {
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
to={`/p/${subscription}`}
|
||||
>
|
||||
<br id='mobile-br' />
|
||||
{subscription}
|
||||
</Link>
|
||||
<OfflineIndicator key={`offline-${index}`} address={subscription} className='disconnected' isText={true} />
|
||||
<br key={`br-${index}`} />
|
||||
</Fragment>
|
||||
))}
|
||||
<br id='mobile-br' />
|
||||
</BoardsContent>
|
||||
</Boards>
|
||||
) : null}
|
||||
<Boards>
|
||||
<BoardsTitle>
|
||||
<h2>Default Boards</h2>
|
||||
</BoardsTitle>
|
||||
<ul>
|
||||
{account?.subscriptions?.length === 0 && <li style={{ color: 'black' }}>Not subscribed to any board.</li>}
|
||||
{account?.subscriptions?.slice(0, showAllSubscriptions ? undefined : 18).map((subscription, index) => (
|
||||
<li key={`sub-${index}`}>
|
||||
<OfflineIndicator address={subscription} className='disconnected' isText={true} />
|
||||
<Link
|
||||
key={`sub-link-${index}`}
|
||||
className='boardlink'
|
||||
onClick={() => {
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
to={`/p/${subscription}`}
|
||||
>
|
||||
{subscription}
|
||||
</Link>
|
||||
|
||||
</li>
|
||||
))}
|
||||
{account?.subscriptions?.length > 17 && (
|
||||
<li onClick={() => setShowAllSubscriptions(!showAllSubscriptions)}>
|
||||
{!showAllSubscriptions ? '... ' : null}
|
||||
<span id='button'>{showAllSubscriptions ? '[show less]' : '[show more]'}</span>
|
||||
</li>
|
||||
)}
|
||||
</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>Popular Threads</h2>
|
||||
</div>
|
||||
<BoardsContent>
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
<div className='board' key={`board-${index}`}>
|
||||
<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>
|
||||
{sfwListCids.map((cid) => (
|
||||
<RecentThread commentCid={cid} />
|
||||
))}
|
||||
</BoardsContent>
|
||||
</Boards>
|
||||
</BoardsBox>
|
||||
</Page>
|
||||
<Footer>
|
||||
<ul>
|
||||
|
||||
@@ -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 = () => {
|
||||
<Container>
|
||||
<Header>
|
||||
<Logo>
|
||||
<Link to="/">
|
||||
<img alt="plebchan" src="assets/logo/logo-transparent.png" />
|
||||
<Link to='/'>
|
||||
<img alt='plebchan' src='assets/logo/logo-transparent.png' />
|
||||
</Link>
|
||||
</Logo>
|
||||
</Header>
|
||||
<Page>
|
||||
<Boards>
|
||||
<BoardsTitle>
|
||||
<h2 style={{textAlign: 'center'}}>404 Not Found</h2>
|
||||
</BoardsTitle>
|
||||
<img src="assets/plebchan-husbando.jpg" alt="plebchan" style={{
|
||||
display: "block",
|
||||
margin: "auto",
|
||||
padding: "15px",
|
||||
width: "50%"
|
||||
}}></img>
|
||||
</Boards>
|
||||
<BoardsBox>
|
||||
<div className='boxbar'>
|
||||
<h2 style={{ textAlign: 'center' }}>404 Not Found</h2>
|
||||
</div>
|
||||
<img
|
||||
src='assets/plebchan-husbando.jpg'
|
||||
alt='plebchan'
|
||||
style={{
|
||||
display: 'block',
|
||||
margin: 'auto',
|
||||
padding: '15px',
|
||||
width: '50%',
|
||||
}}
|
||||
></img>
|
||||
</BoardsBox>
|
||||
</Page>
|
||||
<div style={{
|
||||
textAlign: "center",
|
||||
fontSize: "11px",
|
||||
marginTop: "2em",
|
||||
}}>
|
||||
plebchan v{version}{commitRef}. GPL-2.0
|
||||
<div
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
fontSize: '11px',
|
||||
marginTop: '2em',
|
||||
}}
|
||||
>
|
||||
plebchan v{version}
|
||||
{commitRef}. GPL-2.0
|
||||
</div>
|
||||
</Container>
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default NotFound;
|
||||
export default NotFound;
|
||||
|
||||
+540
-400
File diff suppressed because it is too large
Load Diff
@@ -206,7 +206,7 @@ const Rules = () => {
|
||||
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.',
|
||||
);
|
||||
}}
|
||||
>
|
||||
@@ -239,7 +239,7 @@ const Rules = () => {
|
||||
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.',
|
||||
)
|
||||
}
|
||||
>
|
||||
@@ -655,7 +655,7 @@ const Rules = () => {
|
||||
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.',
|
||||
);
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -606,7 +606,7 @@ const Subscriptions = () => {
|
||||
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.',
|
||||
);
|
||||
}}
|
||||
>
|
||||
@@ -638,7 +638,7 @@ const Subscriptions = () => {
|
||||
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.',
|
||||
)
|
||||
}
|
||||
>
|
||||
@@ -1224,7 +1224,56 @@ const Subscriptions = () => {
|
||||
thread.content?.length > 1000 ? (
|
||||
<Fragment key={`fragment5-${index}`}>
|
||||
<blockquote key={`bq-${index}`}>
|
||||
<Post content={thread.content?.slice(0, 1000)} key={`post-${index}`} />
|
||||
<Post
|
||||
key={`post-${thread.cid}`}
|
||||
content={thread.content?.slice(0, 1000)}
|
||||
postQuoteRef={(quoteShortParentCid, ref) => {
|
||||
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);
|
||||
}}
|
||||
/>
|
||||
<span key={`ttl-s-${index}`} className='ttl'>
|
||||
{' '}
|
||||
(...)
|
||||
@@ -1247,7 +1296,56 @@ const Subscriptions = () => {
|
||||
</Fragment>
|
||||
) : (
|
||||
<blockquote key={`bq-${index}`}>
|
||||
<Post content={thread.content} key={`post-${index}`} />
|
||||
<Post
|
||||
key={`post-${thread.cid}`}
|
||||
content={thread.content}
|
||||
postQuoteRef={(quoteShortParentCid, ref) => {
|
||||
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);
|
||||
}}
|
||||
/>
|
||||
<EditLabel key={`edit-label-thread-${index}`} commentCid={thread.cid} className='ttl' />
|
||||
<StateLabel key={`state-label-thread-${index}`} commentIndex={thread.index} className='ttl ellipsis' />
|
||||
</blockquote>
|
||||
@@ -2441,7 +2539,56 @@ const Subscriptions = () => {
|
||||
thread.content?.length > 500 ? (
|
||||
<Fragment key={`fragment12-${index}`}>
|
||||
<blockquote key={`mob-bq-${index}`} className='post-message-mobile'>
|
||||
<Post content={thread.content?.slice(0, 500)} key={`post-mobile-${index}`} />
|
||||
<Post
|
||||
key={`post-mobile-${thread.cid}`}
|
||||
content={thread.content?.slice(0, 500)}
|
||||
postQuoteRef={(quoteShortParentCid, ref) => {
|
||||
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);
|
||||
}}
|
||||
/>
|
||||
<span key={`mob-ttl-s-${index}`} className='ttl'>
|
||||
{' '}
|
||||
(...)
|
||||
@@ -2464,7 +2611,56 @@ const Subscriptions = () => {
|
||||
</Fragment>
|
||||
) : (
|
||||
<blockquote key={`mob-bq-${index}`} className='post-message-mobile'>
|
||||
<Post content={thread.content} key={`post-mobile-${index}`} />
|
||||
<Post
|
||||
key={`post-mobile-${thread.cid}`}
|
||||
content={thread.content}
|
||||
postQuoteRef={(quoteShortParentCid, ref) => {
|
||||
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);
|
||||
}}
|
||||
/>
|
||||
<EditLabel key={`edit-label-thread-mob-${index}`} commentCid={thread.cid} className='ttl' />
|
||||
<StateLabel key={`state-label-thread-mob-${index}`} commentIndex={thread.index} className='ttl ellipsis' />
|
||||
</blockquote>
|
||||
@@ -3322,7 +3518,7 @@ const Subscriptions = () => {
|
||||
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.',
|
||||
);
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -849,7 +849,7 @@ const SubscriptionsCatalog = () => {
|
||||
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 SubscriptionsCatalog = () => {
|
||||
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.',
|
||||
)
|
||||
}
|
||||
>
|
||||
@@ -1040,7 +1040,7 @@ const SubscriptionsCatalog = () => {
|
||||
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.',
|
||||
);
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -700,7 +700,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.',
|
||||
);
|
||||
}}
|
||||
>
|
||||
@@ -733,7 +733,7 @@ const Thread = () => {
|
||||
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.',
|
||||
)
|
||||
}
|
||||
>
|
||||
@@ -860,7 +860,7 @@ const Thread = () => {
|
||||
</td>
|
||||
</tr>
|
||||
<tr data-type='File'>
|
||||
<td>Embed File</td>
|
||||
<td>Link</td>
|
||||
<td>
|
||||
<input name='embed' type='text' tabIndex={7} placeholder='Paste link' ref={linkRef} />
|
||||
<button
|
||||
@@ -1376,7 +1376,56 @@ const Thread = () => {
|
||||
</div>
|
||||
</span>
|
||||
<blockquote key={`blockquote-${comment.cid}`}>
|
||||
<Post content={comment.content} comment={comment} key={`post-${comment.cid}`} />
|
||||
<Post
|
||||
key={`post-${comment.cid}`}
|
||||
content={comment.content}
|
||||
postQuoteRef={(quoteShortParentCid, ref) => {
|
||||
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);
|
||||
}}
|
||||
/>
|
||||
<EditLabel key={`edit-label-thread-${index}`} commentCid={comment.cid} className='ttl' />
|
||||
<StateLabel key={`state-label-thread-${index}`} commentIndex={comment.index} className='ttl ellipsis' />
|
||||
</blockquote>
|
||||
@@ -2376,7 +2425,56 @@ const Thread = () => {
|
||||
<blockquote key={`mob-bq-${comment.cid}`} className='post-message-mobile'>
|
||||
{comment.content ? (
|
||||
<>
|
||||
<Post content={comment.content} comment={comment} key={`post-mobile-${comment.cid}`} />
|
||||
<Post
|
||||
key={`post-${comment.cid}`}
|
||||
content={comment.content}
|
||||
postQuoteRef={(quoteShortParentCid, ref) => {
|
||||
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);
|
||||
}}
|
||||
/>
|
||||
<EditLabel key={`edit-label-thread-mob-${index}`} commentCid={comment.cid} className='ttl' />
|
||||
<StateLabel key={`state-label-thread-mob-${index}`} commentIndex={comment.index} className='ttl ellipsis' />
|
||||
</>
|
||||
@@ -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.',
|
||||
);
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -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 }),
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user