mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
Merge branch 'master' of github.com:plebbit/plebchan
This commit is contained in:
@@ -1,17 +1,19 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React
|
||||
// , { useState, useEffect }
|
||||
from "react";
|
||||
import { useAccountComment } from "@plebbit/plebbit-react-hooks";
|
||||
import useStateString from "../hooks/useStateString";
|
||||
// import useStateString from "../hooks/useStateString";
|
||||
|
||||
const PendingLabel = ({ commentIndex }) => {
|
||||
const comment = useAccountComment({commentIndex: commentIndex});
|
||||
const stateString = useStateString(comment);
|
||||
// const stateString = useStateString(comment);
|
||||
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
// const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => setIsLoading(false), 2000);
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
// useEffect(() => {
|
||||
// const timer = setTimeout(() => setIsLoading(false), 2000);
|
||||
// return () => clearTimeout(timer);
|
||||
// }, []);
|
||||
|
||||
if (commentIndex === undefined) return null;
|
||||
|
||||
@@ -19,7 +21,9 @@ const PendingLabel = ({ commentIndex }) => {
|
||||
comment.cid ? (
|
||||
<span>{comment.cid.slice(2, 14)}</span>
|
||||
) : (
|
||||
(comment.state === "failed" || (stateString === undefined && !isLoading)) ? (
|
||||
(comment.state === "failed"
|
||||
// || (stateString === undefined && !isLoading)
|
||||
) ? (
|
||||
<span style={{color: 'red', fontWeight: '700'}}>
|
||||
Failed
|
||||
</span>
|
||||
|
||||
+54
-25
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
// import { Link } from 'react-router-dom';
|
||||
import { Link } from 'react-router-dom';
|
||||
import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';
|
||||
import breaks from 'remark-breaks';
|
||||
|
||||
@@ -39,31 +39,60 @@ const blockquoteToGreentext = () => (tree) => {
|
||||
};
|
||||
|
||||
|
||||
// const createQuotelink = (handlequoteclick, comment, children) => {
|
||||
// const text = children.map((child) => (typeof child === 'string' ? child : child.props.children)).join('');
|
||||
// const regex = /(\s|^)(c\/[A-Za-z0-9]{12}|c\/[A-Za-z0-9]{45})(?=\s|$)/g;
|
||||
// const parts = text.split(regex);
|
||||
const createQuotelink = (children) => {
|
||||
const regexC = /(c\/[A-Za-z0-9]{46}|c\/[A-Za-z0-9]{12})/g;
|
||||
const regexP = /(p\/([A-Za-z0-9]{52}|[A-Za-z0-9-.]*\.eth))/g;
|
||||
const regexU = /(u\/([A-Za-z0-9]{52}|[A-Za-z0-9-.]*\.eth))/g;
|
||||
const regexPC = /(p\/([A-Za-z0-9]{52}|[A-Za-z0-9-.]*\.eth)\/c\/[A-Za-z0-9]{46})/g;
|
||||
|
||||
// return parts.flatMap((part, i) => {
|
||||
// if (regex.test(part)) {
|
||||
// return [
|
||||
// <Link
|
||||
// key={`link-${i}`}
|
||||
// className="quotelink"
|
||||
// to=""
|
||||
// onClick={handlequoteclick}
|
||||
// >
|
||||
// {part.trim()}
|
||||
// </Link>,
|
||||
// ];
|
||||
// } else {
|
||||
// return [part];
|
||||
// }
|
||||
// });
|
||||
// };
|
||||
const regexArray = [regexU, regexPC, regexP, regexC];
|
||||
let parts = [children];
|
||||
|
||||
regexArray.forEach(regex => {
|
||||
parts = parts.flatMap((child, i) => {
|
||||
if (typeof child === 'string') {
|
||||
const newParts = [];
|
||||
let match;
|
||||
let lastIndex = 0;
|
||||
|
||||
while ((match = regex.exec(child)) !== null) {
|
||||
const matchedText = match[0];
|
||||
const index = match.index;
|
||||
|
||||
if (index > lastIndex) {
|
||||
newParts.push(child.substring(lastIndex, index));
|
||||
}
|
||||
|
||||
newParts.push(
|
||||
<Link
|
||||
key={`link-${i}-${matchedText}`}
|
||||
className="quotelink"
|
||||
to={() => {}}
|
||||
>
|
||||
{matchedText}
|
||||
</Link>
|
||||
);
|
||||
|
||||
lastIndex = index + matchedText.length;
|
||||
}
|
||||
|
||||
if (lastIndex < child.length) {
|
||||
newParts.push(child.substring(lastIndex));
|
||||
}
|
||||
|
||||
return newParts;
|
||||
} else {
|
||||
return child;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return parts;
|
||||
};
|
||||
|
||||
|
||||
const Post = ({ content, handlequoteclick, comment }) => {
|
||||
|
||||
const Post = ({ content }) => {
|
||||
const doubleNewlineContent = content?.replaceAll(/\n(?!\n)/g, '\n\n');
|
||||
|
||||
return (
|
||||
@@ -76,10 +105,10 @@ const Post = ({ content, handlequoteclick, comment }) => {
|
||||
video: ({ src }) => <span>{src}</span>,
|
||||
source: ({ src }) => <span>{src}</span>,
|
||||
gif: ({ src }) => <span>{src}</span>,
|
||||
p: ({ children }) => <div className="custom-paragraph">{children}</div>,
|
||||
p: ({ children }) => <div className='custom-paragraph'>{createQuotelink(children)}</div>,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default Post;
|
||||
export default React.memo(Post);
|
||||
@@ -190,15 +190,15 @@ const PostOnHover = ({ cid, feed }) => {
|
||||
<div className="post-reply post-reply-mobile">
|
||||
<div className="post-info-mobile">
|
||||
<span className="name-block-mobile">
|
||||
{reply.author.displayName
|
||||
? reply.author.displayName.length > 20
|
||||
{reply.author?.displayName
|
||||
? reply.author?.displayName.length > 20
|
||||
? <Fragment>
|
||||
<span className="name-mobile">
|
||||
{reply.author.displayName.slice(0, 20) + " (...)"}
|
||||
{reply.author?.displayName.slice(0, 20) + " (...)"}
|
||||
</span>
|
||||
</Fragment>
|
||||
: <span className="name-mobile">
|
||||
{reply.author.displayName}</span>
|
||||
{reply.author?.displayName}</span>
|
||||
: <span className="name-mobile">
|
||||
Anonymous</span>}
|
||||
|
||||
|
||||
@@ -17,16 +17,18 @@ const StateLabel = ({ commentIndex, className }) => {
|
||||
|
||||
return (
|
||||
commentIndex && stateString !== "Succeeded" ? (
|
||||
(comment.state === "failed" || (stateString === undefined && !isLoading && comment.cid === undefined)) ? (
|
||||
<span className="ttl">
|
||||
<br />
|
||||
(
|
||||
<span className="ttl">
|
||||
Failed
|
||||
</span>
|
||||
)
|
||||
</span>
|
||||
(comment.state === "failed") ? (
|
||||
null
|
||||
) : (
|
||||
stateString === undefined && !isLoading && comment.cid === undefined ? (
|
||||
<span className="ttl">
|
||||
<br />
|
||||
(
|
||||
<span className={className}>
|
||||
</span>
|
||||
)
|
||||
</span>
|
||||
) : (
|
||||
<span className="ttl">
|
||||
<br />
|
||||
(
|
||||
@@ -35,7 +37,7 @@ const StateLabel = ({ commentIndex, className }) => {
|
||||
</span>
|
||||
)
|
||||
</span>
|
||||
)
|
||||
))
|
||||
) : null
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import { Link, useLocation, useNavigate } from "react-router-dom";
|
||||
import { confirmAlert } from "react-confirm-alert";
|
||||
import Modal from "react-modal";
|
||||
import { deleteCaches, exportAccount, importAccount, setAccount, setActiveAccount, useAccount, useAccounts } from "@plebbit/plebbit-react-hooks";
|
||||
import { StyledModal } from "../styled/modals/SettingsModal.styled";
|
||||
import { AuthorDeleteAlert } from '../styled/views/Thread.styled';
|
||||
import useGeneralStore from "../../hooks/stores/useGeneralStore";
|
||||
import useError from "../../hooks/useError";
|
||||
import useSuccess from "../../hooks/useSuccess";
|
||||
import useAnonModeStore from '../../hooks/stores/useAnonModeStore';
|
||||
import useGeneralStore from '../../hooks/stores/useGeneralStore';
|
||||
import packageJson from '../../../package.json'
|
||||
const {version} = packageJson
|
||||
|
||||
|
||||
const SettingsModal = ({ isOpen, closeModal }) => {
|
||||
const {
|
||||
anonymousMode, setAnonymousMode,
|
||||
selectedStyle,
|
||||
} = useGeneralStore(state => state);
|
||||
|
||||
const { anonymousMode, setAnonymousMode } = useAnonModeStore();
|
||||
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
@@ -194,38 +194,6 @@ const SettingsModal = ({ isOpen, closeModal }) => {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const handleAnonymousMode = () => {
|
||||
confirmAlert({
|
||||
customUI: ({ onClose }) => {
|
||||
return (
|
||||
<AuthorDeleteAlert selectedStyle={selectedStyle}>
|
||||
<div className='author-delete-alert'>
|
||||
<p>
|
||||
{ !anonymousMode ?
|
||||
"Enabling anonymous mode will turn off all account-based features, such as subscribing to boards." :
|
||||
"Disabling anonymous mode will turn on all account-based features, such as subscribing to boards."
|
||||
}
|
||||
</p>
|
||||
<div className="author-delete-buttons">
|
||||
<button onClick={onClose}>Cancel</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
setAnonymousMode(!anonymousMode);
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
{ !anonymousMode ? "Enable" : "Disable" }
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</AuthorDeleteAlert>
|
||||
)
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<StyledModal
|
||||
@@ -254,20 +222,6 @@ const SettingsModal = ({ isOpen, closeModal }) => {
|
||||
</button>
|
||||
]
|
||||
</div>
|
||||
{/* <ul>
|
||||
<li className="settings-cat-lbl">
|
||||
<span className={`${expanded.includes(0) ? 'minus' : 'plus'}`}
|
||||
onClick={() => toggleExpanded(0)}
|
||||
/>
|
||||
<span className="settings-pointer" style={{cursor: "pointer"}}
|
||||
onClick={() => toggleExpanded(0)}
|
||||
>Account</span>
|
||||
</li>
|
||||
<ul className="settings-cat" style={{ display: expanded.includes(0) ? 'block' : 'none' }}>
|
||||
<li>
|
||||
</li>
|
||||
</ul>
|
||||
</ul>*/}
|
||||
<ul>
|
||||
<li className="settings-cat-lbl">
|
||||
<span className={`${expanded.includes(1) ? 'minus' : 'plus'}`}
|
||||
@@ -282,6 +236,22 @@ const SettingsModal = ({ isOpen, closeModal }) => {
|
||||
</div>
|
||||
</li>
|
||||
<ul className="settings-cat" style={{ display: expanded.includes(1) ? 'block' : 'none' }}>
|
||||
<li className="anon-off">
|
||||
<label title={ !anonymousMode ?
|
||||
"Enable anon mode" :
|
||||
"Disable anon mode"
|
||||
}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={anonymousMode}
|
||||
onChange={() => {setAnonymousMode(!anonymousMode)}}
|
||||
/>
|
||||
Anon mode
|
||||
</label>
|
||||
</li>
|
||||
<li className="settings-tip anon-tip">
|
||||
Automatically uses a different account (u/address) per thread.
|
||||
</li>
|
||||
<li className="settings-option disc">
|
||||
Account Data
|
||||
</li>
|
||||
@@ -414,21 +384,6 @@ const SettingsModal = ({ isOpen, closeModal }) => {
|
||||
</ul>
|
||||
</ul> */}
|
||||
</ul>
|
||||
<ul>
|
||||
<li className="anon-off">
|
||||
<label title={ !anonymousMode ?
|
||||
"Enable anonymous mode (turns off all account-based features)" :
|
||||
"Disable anonymous mode (turns on all account-based features)"
|
||||
}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={!anonymousMode}
|
||||
onChange={handleAnonymousMode}
|
||||
/>
|
||||
Disable anonymous mode
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
<div>
|
||||
<button
|
||||
className="cache-button"
|
||||
|
||||
@@ -191,8 +191,33 @@ export const StyledModal = styled(Modal)`
|
||||
}
|
||||
|
||||
.anon-off {
|
||||
padding-left: 3px;
|
||||
padding-top: 15px;
|
||||
margin: 10px 0 5px -2px
|
||||
}
|
||||
|
||||
.anon-tip {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.anon-tip::before {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 10px;
|
||||
height: 1px;
|
||||
background-color: currentColor;
|
||||
position: absolute;
|
||||
left: 18px;
|
||||
top: 120px;
|
||||
}
|
||||
|
||||
.anon-tip::after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 1px;
|
||||
height: 12px;
|
||||
background-color: currentColor;
|
||||
position: absolute;
|
||||
left: 18px;
|
||||
top: 108px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1740,6 +1740,10 @@ export const BoardForm = styled.div`
|
||||
border-left: none !important;
|
||||
border-top: none !important;
|
||||
}
|
||||
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
}
|
||||
|
||||
#post-menu {
|
||||
border-right: 1px solid #d9bfb7;
|
||||
@@ -1763,6 +1767,10 @@ export const BoardForm = styled.div`
|
||||
border-left: none !important;
|
||||
border-top: none !important;
|
||||
}
|
||||
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
}
|
||||
|
||||
#post-menu {
|
||||
border-right: 1px solid #b7c5d9;
|
||||
@@ -1783,6 +1791,10 @@ export const BoardForm = styled.div`
|
||||
return `.highlighted {
|
||||
background-color: #f0c0b0 !important;
|
||||
}
|
||||
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
}
|
||||
|
||||
#post-menu {
|
||||
font-size: 13px !important;
|
||||
@@ -1803,6 +1815,10 @@ export const BoardForm = styled.div`
|
||||
return `.highlighted {
|
||||
background-color: #d6bad0 !important;
|
||||
}
|
||||
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
}
|
||||
|
||||
#post-menu {
|
||||
font-size: 13px !important;
|
||||
@@ -1824,6 +1840,10 @@ export const BoardForm = styled.div`
|
||||
background-color: #1d1d21 !important;
|
||||
outline: 1px solid #111 !important;
|
||||
}
|
||||
|
||||
.capcode {
|
||||
color: #81a2be !important;
|
||||
}
|
||||
|
||||
#post-menu {
|
||||
border: 1px solid #000;
|
||||
@@ -1844,6 +1864,10 @@ export const BoardForm = styled.div`
|
||||
background-color: #ccc !important;
|
||||
outline: 1px solid #ccc !important;
|
||||
}
|
||||
|
||||
.capcode {
|
||||
color: #f60 !important;
|
||||
}
|
||||
|
||||
#post-menu {
|
||||
border: 1px solid #ccc;
|
||||
@@ -3242,6 +3266,9 @@ export const BoardForm = styled.div`
|
||||
switch (selectedStyle) {
|
||||
case 'Yotsuba':
|
||||
return `
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
}
|
||||
.op-container {
|
||||
background-color: #f5e9e1;
|
||||
border: 1px solid #d9bfb7 !important;
|
||||
@@ -3359,6 +3386,9 @@ export const BoardForm = styled.div`
|
||||
|
||||
case 'Yotsuba-B':
|
||||
return `
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
}
|
||||
.op-container {
|
||||
background-color: #d6daf0;
|
||||
border: 1px solid #b7c5d9 !important;
|
||||
@@ -3472,6 +3502,9 @@ export const BoardForm = styled.div`
|
||||
|
||||
case 'Futaba':
|
||||
return `
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
}
|
||||
.op-container {
|
||||
background-color: #f5e9e1;
|
||||
border: 1px solid #d9bfb7 !important;
|
||||
@@ -3588,6 +3621,9 @@ export const BoardForm = styled.div`
|
||||
|
||||
case 'Burichan':
|
||||
return `
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
}
|
||||
.op-container {
|
||||
background-color: #d6daf0;
|
||||
border: 1px solid #b7c5d9 !important;
|
||||
@@ -3700,6 +3736,10 @@ export const BoardForm = styled.div`
|
||||
|
||||
case 'Tomorrow':
|
||||
return `
|
||||
.capcode {
|
||||
color: #81a2be !important;
|
||||
}
|
||||
|
||||
.op-container {
|
||||
background-color: #282A2E;
|
||||
border: 1px solid #2D2F33 !important;
|
||||
@@ -3822,6 +3862,9 @@ export const BoardForm = styled.div`
|
||||
|
||||
case 'Photon':
|
||||
return `
|
||||
.capcode {
|
||||
color: #f60 !important;
|
||||
}
|
||||
.op-container {
|
||||
background-color: #eee;
|
||||
border: 1px solid #ccc !important;
|
||||
|
||||
@@ -8,7 +8,6 @@ import { Virtuoso } from 'react-virtuoso';
|
||||
import { useAccount, useAccountComments, useFeed, usePublishCommentEdit, useSubplebbits } from '@plebbit/plebbit-react-hooks';
|
||||
import { flattenCommentsPages } from '@plebbit/plebbit-react-hooks/dist/lib/utils'
|
||||
import { debounce } from 'lodash';
|
||||
import useGeneralStore from '../../hooks/stores/useGeneralStore';
|
||||
import { Container, NavBar, Header, Break, TopBar, BoardForm, PostMenu } from '../styled/views/Board.styled';
|
||||
import { AuthorDeleteAlert, Footer } from '../styled/views/Thread.styled';
|
||||
import { PostMenuCatalog } from '../styled/views/Catalog.styled';
|
||||
@@ -33,9 +32,12 @@ import handleQuoteClick from '../../utils/handleQuoteClick';
|
||||
import handleQuoteHover from '../../utils/handleQuoteHover';
|
||||
import handleStyleChange from '../../utils/handleStyleChange';
|
||||
import removeHighlight from '../../utils/removeHighlight';
|
||||
import useAnonModeRef from '../../hooks/useAnonModeRef';
|
||||
import useError from '../../hooks/useError';
|
||||
import useFeedStateString from '../../hooks/useFeedStateString';
|
||||
import useSuccess from '../../hooks/useSuccess';
|
||||
import useAnonModeStore from '../../hooks/stores/useAnonModeStore';
|
||||
import useGeneralStore from '../../hooks/stores/useGeneralStore';
|
||||
import packageJson from '../../../package.json'
|
||||
const {version} = packageJson
|
||||
|
||||
@@ -61,6 +63,8 @@ const All = () => {
|
||||
setSelectedThread,
|
||||
setSelectedTitle,
|
||||
} = useGeneralStore(state => state);
|
||||
|
||||
const { anonymousMode } = useAnonModeStore();
|
||||
|
||||
const account = useAccount();
|
||||
const navigate = useNavigate();
|
||||
@@ -75,6 +79,7 @@ const All = () => {
|
||||
const backlinkRefsMobile = useRef({});
|
||||
const quoteRefsMobile = useRef({});
|
||||
const postOnHoverRef = useRef(null);
|
||||
const selectedThreadCidRef = useRef(null);
|
||||
|
||||
const [isReplyOpen, setIsReplyOpen] = useState(false);
|
||||
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
|
||||
@@ -91,6 +96,13 @@ const All = () => {
|
||||
const [postOnHoverHeight, setPostOnHoverHeight] = useState(0);
|
||||
const [deletePost, setDeletePost] = useState(false);
|
||||
const [moderatorPermissions, setModeratorPermissions] = useState({});
|
||||
const [executeAnonMode, setExecuteAnonMode] = useState(false);
|
||||
|
||||
const setSelectedThreadCid = (cid) => {
|
||||
selectedThreadCidRef.current = cid;
|
||||
}
|
||||
|
||||
useAnonModeRef(selectedThreadCidRef, anonymousMode && executeAnonMode);
|
||||
|
||||
const addresses = defaultSubplebbits.map(subplebbit => subplebbit.address);
|
||||
const { feed, hasMore, loadMore } = useFeed({subplebbitAddresses: addresses, sortType: 'active'});
|
||||
@@ -302,6 +314,14 @@ const All = () => {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (anonymousMode) {
|
||||
setExecuteAnonMode(true);
|
||||
}
|
||||
}, [anonymousMode, selectedThreadCidRef]);
|
||||
|
||||
|
||||
const [publishCommentEditOptions, setPublishCommentEditOptions] = useState({
|
||||
commentCid: commentCid,
|
||||
content: editedComment || undefined,
|
||||
@@ -317,8 +337,8 @@ const All = () => {
|
||||
const { publishCommentEdit } = usePublishCommentEdit(publishCommentEditOptions);
|
||||
|
||||
|
||||
const handleAuthorDeleteClick = (comment) => {
|
||||
handleOptionClick(comment.cid);
|
||||
const handleAuthorDeleteClick = (cid) => {
|
||||
handleOptionClick(cid);
|
||||
|
||||
confirmAlert({
|
||||
customUI: ({ onClose }) => {
|
||||
@@ -332,7 +352,7 @@ const All = () => {
|
||||
onClick={() => {
|
||||
setIsAuthorDelete(true);
|
||||
setIsAuthorEdit(false);
|
||||
setCommentCid(comment.cid);
|
||||
setCommentCid(cid);
|
||||
setPublishCommentEditOptions(prevOptions => ({
|
||||
...prevOptions,
|
||||
deleted: true,
|
||||
@@ -667,7 +687,8 @@ const All = () => {
|
||||
onClick={(e) => {
|
||||
if (e.button === 2) return;
|
||||
e.preventDefault();
|
||||
setIsReplyOpen(true);
|
||||
setSelectedThreadCid(thread.cid);
|
||||
setIsReplyOpen(true);
|
||||
setSelectedShortCid(thread.shortCid);
|
||||
setSelectedParentCid(thread.cid);
|
||||
setSelectedAddress(thread.subplebbitAddress);
|
||||
@@ -725,7 +746,7 @@ const All = () => {
|
||||
{thread.author.shortAddress === account?.author.shortAddress ? (
|
||||
<>
|
||||
<li onClick={() => {handleAuthorEditClick(thread); setSelectedAddress(thread.subplebbitAddress);}}>Edit post</li>
|
||||
<li onClick={() => {handleAuthorDeleteClick(thread); setSelectedAddress(thread.subplebbitAddress);}}>Delete post</li>
|
||||
<li onClick={() => {handleAuthorDeleteClick(thread.cid); setSelectedAddress(thread.subplebbitAddress);}}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
@@ -946,7 +967,8 @@ const All = () => {
|
||||
onClick={(e) => {
|
||||
if (e.button === 2) return;
|
||||
e.preventDefault();
|
||||
setIsReplyOpen(true);
|
||||
setSelectedThreadCid(thread.cid);
|
||||
setIsReplyOpen(true);
|
||||
setSelectedShortCid(reply.shortCid);
|
||||
setSelectedParentCid(reply.cid);
|
||||
setSelectedAddress(thread.subplebbitAddress);
|
||||
@@ -1004,7 +1026,7 @@ const All = () => {
|
||||
{reply.author.shortAddress === account?.author.shortAddress ? (
|
||||
<>
|
||||
<li onClick={() => {handleAuthorEditClick(reply); setSelectedAddress(thread.subplebbitAddress);}}>Edit post</li>
|
||||
<li onClick={() => {handleAuthorDeleteClick(reply); setSelectedAddress(thread.subplebbitAddress);}}>Delete post</li>
|
||||
<li onClick={() => {handleAuthorDeleteClick(reply.cid); setSelectedAddress(thread.subplebbitAddress);}}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
@@ -1379,7 +1401,8 @@ const All = () => {
|
||||
onClick={(e) => {
|
||||
if (e.button === 2) return;
|
||||
e.preventDefault();
|
||||
setIsReplyOpen(true);
|
||||
setSelectedThreadCid(thread.cid);
|
||||
setIsReplyOpen(true);
|
||||
setSelectedShortCid(thread.shortCid);
|
||||
setSelectedParentCid(thread.cid);
|
||||
setSelectedAddress(thread.subplebbitAddress);
|
||||
@@ -1551,7 +1574,8 @@ const All = () => {
|
||||
onClick={(e) => {
|
||||
if (e.button === 2) return;
|
||||
e.preventDefault();
|
||||
setIsReplyOpen(true);
|
||||
setSelectedThreadCid(thread.cid);
|
||||
setIsReplyOpen(true);
|
||||
setSelectedShortCid(reply.shortCid);
|
||||
setSelectedParentCid(reply.cid);
|
||||
setSelectedAddress(thread.subplebbitAddress);
|
||||
@@ -1842,10 +1866,10 @@ const All = () => {
|
||||
}}>
|
||||
<>
|
||||
<span className="boardList">
|
||||
[
|
||||
<Link to={`/p/all`}>All</Link>
|
||||
/
|
||||
<Link to={`/p/subscriptions`}>Subscriptions</Link>
|
||||
[
|
||||
<Link to={`/p/all`}>All</Link>
|
||||
/
|
||||
<Link to={`/p/subscriptions`}>Subscriptions</Link>
|
||||
] [
|
||||
</span>
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
|
||||
@@ -7,7 +7,6 @@ import { confirmAlert } from 'react-confirm-alert';
|
||||
import { Tooltip } from 'react-tooltip';
|
||||
import { useAccount, useFeed, usePublishCommentEdit, useSubplebbits } from '@plebbit/plebbit-react-hooks';
|
||||
import { debounce } from 'lodash';
|
||||
import useGeneralStore from '../../hooks/stores/useGeneralStore';
|
||||
import { Container, NavBar, Header, Break, PostMenu, BoardForm } from '../styled/views/Board.styled';
|
||||
import { Threads, PostMenuCatalog } from '../styled/views/Catalog.styled';
|
||||
import { TopBar, Footer, AuthorDeleteAlert } from '../styled/views/Thread.styled';
|
||||
@@ -22,6 +21,7 @@ import handleStyleChange from '../../utils/handleStyleChange';
|
||||
import useError from '../../hooks/useError';
|
||||
import useFeedStateString from '../../hooks/useFeedStateString';
|
||||
import useSuccess from '../../hooks/useSuccess';
|
||||
import useGeneralStore from '../../hooks/stores/useGeneralStore';
|
||||
import packageJson from '../../../package.json'
|
||||
const {version} = packageJson
|
||||
|
||||
@@ -44,6 +44,7 @@ const AllCatalog = () => {
|
||||
setSelectedThread,
|
||||
setSelectedTitle,
|
||||
} = useGeneralStore(state => state);
|
||||
|
||||
|
||||
const threadMenuRefs = useRef({});
|
||||
const postMenuRef = useRef(null);
|
||||
@@ -337,7 +338,7 @@ const AllCatalog = () => {
|
||||
<span className="boardList">
|
||||
[
|
||||
<Link to={`/p/all`}>All</Link>
|
||||
/
|
||||
/
|
||||
<Link to={`/p/subscriptions`}>Subscriptions</Link>
|
||||
] [
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
|
||||
+1310
-1024
File diff suppressed because it is too large
Load Diff
+353
-160
@@ -7,7 +7,6 @@ import { confirmAlert } from 'react-confirm-alert';
|
||||
import { Tooltip } from 'react-tooltip';
|
||||
import { useAccount, useFeed, usePublishComment, usePublishCommentEdit, useSubplebbit, useSubscribe } from '@plebbit/plebbit-react-hooks';
|
||||
import { debounce } from 'lodash';
|
||||
import useGeneralStore from '../../hooks/stores/useGeneralStore';
|
||||
import { Container, NavBar, Header, Break, PostForm, PostFormLink, PostFormTable, PostMenu, BoardForm } from '../styled/views/Board.styled';
|
||||
import { Threads, PostMenuCatalog } from '../styled/views/Catalog.styled';
|
||||
import { TopBar, Footer, AuthorDeleteAlert } from '../styled/views/Thread.styled';
|
||||
@@ -23,6 +22,7 @@ import useClickForm from '../../hooks/useClickForm';
|
||||
import useError from '../../hooks/useError';
|
||||
import useStateString from '../../hooks/useStateString';
|
||||
import useSuccess from '../../hooks/useSuccess';
|
||||
import useGeneralStore from '../../hooks/stores/useGeneralStore';
|
||||
import packageJson from '../../../package.json'
|
||||
const {version} = packageJson
|
||||
|
||||
@@ -49,6 +49,7 @@ const Catalog = () => {
|
||||
showPostForm,
|
||||
showPostFormLink,
|
||||
} = useGeneralStore(state => state);
|
||||
|
||||
|
||||
const nameRef = useRef();
|
||||
const subjectRef = useRef();
|
||||
@@ -77,7 +78,6 @@ const Catalog = () => {
|
||||
const [menuPosition, setMenuPosition] = useState({top: 0, left: 0});
|
||||
const [openMenuCid, setOpenMenuCid] = useState(null);
|
||||
|
||||
|
||||
const { feed, hasMore, loadMore } = useFeed({subplebbitAddresses: [`${selectedAddress}`], sortType: 'active'});
|
||||
const { subplebbitAddress } = useParams();
|
||||
const subplebbit = useSubplebbit({subplebbitAddress: selectedAddress});
|
||||
@@ -273,8 +273,8 @@ const Catalog = () => {
|
||||
|
||||
setTriggerPublishComment(true);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (publishCommentOptions && triggerPublishComment) {
|
||||
(async () => {
|
||||
@@ -462,7 +462,7 @@ const Catalog = () => {
|
||||
<span className="boardList">
|
||||
[
|
||||
<Link to={`/p/all`}>All</Link>
|
||||
/
|
||||
/
|
||||
<Link to={`/p/subscriptions`}>Subscriptions</Link>
|
||||
] [
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
@@ -612,7 +612,7 @@ const Catalog = () => {
|
||||
</div>
|
||||
{feed.length > 0 ? (
|
||||
<>
|
||||
<span className="subscribe-button-desktop">
|
||||
<span className="subscribe-button-desktop">
|
||||
[
|
||||
<span id="subscribe" style={{cursor: 'pointer'}}>
|
||||
<span onClick={() => handleSubscribe()}>
|
||||
@@ -645,88 +645,44 @@ const Catalog = () => {
|
||||
null
|
||||
) : (
|
||||
feed.length > 0 ? (
|
||||
<InfiniteScroll
|
||||
pageStart={0}
|
||||
loadMore={tryLoadMore}
|
||||
hasMore={hasMore}
|
||||
>
|
||||
{feed.map((thread, index) => {
|
||||
const commentMediaInfo = getCommentMediaInfo(thread);
|
||||
const fallbackImgUrl = "assets/filedeleted-res.gif";
|
||||
return (
|
||||
<div key={`thread-${index}`} className="thread"
|
||||
onMouseOver={() => {setIsHoveringOnThread(thread.cid)}}
|
||||
onMouseLeave={() => {setIsHoveringOnThread('')}}>
|
||||
{commentMediaInfo?.url ? (
|
||||
<Link style={{all: "unset", cursor: "pointer"}} key={`link-${index}`} to={`/p/${selectedAddress}/c/${thread.cid}`}
|
||||
onClick={() => setSelectedThread(thread.cid)}>
|
||||
{commentMediaInfo?.type === "webpage" ? (
|
||||
thread.thumbnailUrl ? (
|
||||
<img className="card" key={`img-${index}`}
|
||||
src={commentMediaInfo.thumbnail} alt={commentMediaInfo.type}
|
||||
onError={(e) => {
|
||||
e.target.src = fallbackImgUrl
|
||||
e.target.onerror = null;
|
||||
}} />
|
||||
) : null
|
||||
) : null}
|
||||
{commentMediaInfo?.type === "image" ? (
|
||||
<img className="card" key={`img-${index}`}
|
||||
src={commentMediaInfo.url} alt={commentMediaInfo.type}
|
||||
onError={(e) => {
|
||||
e.target.src = fallbackImgUrl
|
||||
e.target.onerror = null;}} />
|
||||
) : null}
|
||||
{commentMediaInfo?.type === "video" ? (
|
||||
<video className="card" key={`fti-${index}`}
|
||||
src={commentMediaInfo.url}
|
||||
alt={commentMediaInfo.type}
|
||||
onError={(e) => e.target.src = fallbackImgUrl} />
|
||||
) : null}
|
||||
{commentMediaInfo?.type === "audio" ? (
|
||||
<audio className="card" controls
|
||||
key={`fti-${index}`}
|
||||
src={commentMediaInfo.url}
|
||||
alt={commentMediaInfo.type}
|
||||
onError={(e) => e.target.src = fallbackImgUrl} />
|
||||
) : null}
|
||||
</Link>
|
||||
) : null}
|
||||
<div key={`ti-${index}`} className="thread-icons" >
|
||||
{thread.pinned ? (
|
||||
<span key={`si-${index}`} className="thread-icon sticky-icon" title="Sticky" />
|
||||
) : null}
|
||||
{thread.locked ? (
|
||||
<span key={`li-${index}`} className="thread-icon closed-icon" title="Closed" />
|
||||
) : null}
|
||||
</div>
|
||||
<BoardForm selectedStyle={selectedStyle}
|
||||
style={{ all: "unset"}}>
|
||||
<div key={`meta-${index}`} className="meta" title="(R)eplies / (I)mage Replies" >
|
||||
R:
|
||||
<b key={`b-${index}`}>{thread.replyCount}</b>
|
||||
<PostMenu
|
||||
style={{ display: isHoveringOnThread === thread.cid ? 'inline-block' : 'none',
|
||||
position: 'absolute', lineHeight: '1em', marginTop: '-1px', outline: 'none',
|
||||
zIndex: '999'}}
|
||||
key={`pmb-${index}`}
|
||||
title="Post menu"
|
||||
ref={el => {
|
||||
threadMenuRefs.current[thread.cid] = el;
|
||||
postMenuRef.current = el;
|
||||
}}
|
||||
className='post-menu-button'
|
||||
id='post-menu-button-catalog'
|
||||
rotated={openMenuCid === thread.cid}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
const rect = threadMenuRefs.current[thread.cid].getBoundingClientRect();
|
||||
setMenuPosition({top: rect.top + window.scrollY, left: rect.left});
|
||||
setOpenMenuCid(prevCid => (prevCid === thread.cid ? null : thread.cid));
|
||||
}}
|
||||
>
|
||||
▶
|
||||
</PostMenu>
|
||||
<InfiniteScroll
|
||||
pageStart={0}
|
||||
loadMore={tryLoadMore}
|
||||
hasMore={hasMore}
|
||||
>
|
||||
{subplebbit.rules ? (
|
||||
<div className='thread'
|
||||
onMouseOver={() => setIsHoveringOnThread('rules')}
|
||||
onMouseLeave={() => setIsHoveringOnThread('')}>
|
||||
<BoardForm selectedStyle={selectedStyle} style={{all: 'unset'}}>
|
||||
<div className='meta' title="(R)eplies / (I)mage Replies">
|
||||
R:<b>0</b>
|
||||
<div className='thread-icons'
|
||||
style={{position: 'absolute', top: '-2px', right: '15px'}}>
|
||||
<span className="thread-icon sticky-icon" title="Sticky" />
|
||||
<span className="thread-icon closed-icon" title="Closed" />
|
||||
</div>
|
||||
<PostMenu
|
||||
style={{ display: isHoveringOnThread === "rules" ? 'inline-block' : 'none',
|
||||
position: 'absolute', lineHeight: '1em', marginTop: '-1px', outline: 'none',
|
||||
zIndex: '999'}}
|
||||
title="Post menu"
|
||||
ref={el => {
|
||||
threadMenuRefs.current["rules"] = el;
|
||||
postMenuRef.current = el;
|
||||
}}
|
||||
className='post-menu-button'
|
||||
id='post-menu-button-catalog'
|
||||
rotated={openMenuCid === "rules"}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
const rect = threadMenuRefs.current["rules"].getBoundingClientRect();
|
||||
setMenuPosition({top: rect.top + window.scrollY, left: rect.left});
|
||||
setOpenMenuCid(prevCid => (prevCid === "rules" ? null : "rules"));
|
||||
}}
|
||||
>
|
||||
▶
|
||||
</PostMenu>
|
||||
</div>
|
||||
{createPortal(
|
||||
<PostMenuCatalog selectedStyle={selectedStyle}
|
||||
@@ -735,88 +691,325 @@ const Catalog = () => {
|
||||
style={{position: "absolute",
|
||||
top: menuPosition.top + 7,
|
||||
left: menuPosition.left}}>
|
||||
<div className={`post-menu-thread post-menu-thread-${thread.cid}`}
|
||||
style={{ display: openMenuCid === thread.cid ? 'block' : 'none' }}
|
||||
<div className={`post-menu-thread post-menu-thread-${"rules"}`}
|
||||
style={{ display: openMenuCid === "rules" ? 'block' : 'none' }}
|
||||
>
|
||||
<ul className="post-menu-catalog">
|
||||
<li onClick={() => handleOptionClick(thread.cid)}>Hide thread</li>
|
||||
{thread.author.shortAddress === account?.author.shortAddress ? (
|
||||
<li onClick={() => handleOptionClick("rules")}>Hide thread</li>
|
||||
{/* {isModerator ? (
|
||||
<>
|
||||
<li onClick={() => handleAuthorEditClick(thread)}>Edit post</li>
|
||||
<li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li>
|
||||
change rules
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
<>
|
||||
{thread.author.shortAddress === account?.author.shortAddress ? (
|
||||
null
|
||||
) : (
|
||||
<li onClick={() => {
|
||||
setModeratingCommentCid(thread.cid)
|
||||
setIsModerationOpen(true);
|
||||
handleOptionClick(thread.cid);
|
||||
setDeletePost(true);
|
||||
}}>
|
||||
Delete post
|
||||
</li>
|
||||
)}
|
||||
<li
|
||||
onClick={() => {
|
||||
setModeratingCommentCid(thread.cid)
|
||||
setIsModerationOpen(true);
|
||||
handleOptionClick(thread.cid);
|
||||
}}>
|
||||
Mod tools
|
||||
</li>
|
||||
</>
|
||||
) : null}
|
||||
{(commentMediaInfo && (
|
||||
commentMediaInfo.type === 'image' ||
|
||||
(commentMediaInfo.type === 'webpage' &&
|
||||
commentMediaInfo.thumbnail))) ? (
|
||||
<li
|
||||
onMouseOver={() => {setIsImageSearchOpen(true)}}
|
||||
onMouseLeave={() => {setIsImageSearchOpen(false)}}>
|
||||
Image search »
|
||||
<ul className="dropdown-menu post-menu-catalog"
|
||||
style={{display: isImageSearchOpen ? 'block': 'none'}}>
|
||||
<li onClick={() => handleOptionClick(thread.cid)}>
|
||||
<a
|
||||
href={`https://lens.google.com/uploadbyurl?url=${commentMediaInfo.url}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>Google</a>
|
||||
</li>
|
||||
<li onClick={() => handleOptionClick(thread.cid)}>
|
||||
<a
|
||||
href={`https://yandex.com/images/search?url=${commentMediaInfo.url}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>Yandex</a>
|
||||
</li>
|
||||
<li onClick={() => handleOptionClick(thread.cid)}>
|
||||
<a
|
||||
href={`https://saucenao.com/search.php?url=${commentMediaInfo.url}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>SauceNAO</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
) : null
|
||||
}
|
||||
) : null} */}
|
||||
</ul>
|
||||
</div>
|
||||
</PostMenuCatalog>, document.body
|
||||
)}
|
||||
</BoardForm>
|
||||
<Link style={{all: "unset", cursor: "pointer"}} key={`link2-${index}`} to={`/p/${selectedAddress}/c/${thread.cid}`}
|
||||
onClick={() => setSelectedThread(thread.cid)}>
|
||||
<div key={`t-${index}`} className="teaser">
|
||||
<b key={`b2-${index}`}>{thread.title ? `${thread.title}` : null}</b>
|
||||
{thread.content ? `: ${thread.content}` : null}
|
||||
</div>
|
||||
</Link>
|
||||
<Link style={{all: "unset", cursor: "pointer"}} to={() => {}}
|
||||
onClick={() => setSelectedThread("rules")}>
|
||||
<div className="teaser">
|
||||
<b>Rules</b>
|
||||
{": " + subplebbit.rules.map((rule, index) => `${index + 1}. ${rule}`).join(' ')}
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
)})}
|
||||
</InfiniteScroll>
|
||||
) : null}
|
||||
{subplebbit.description ? (
|
||||
<div className='thread'
|
||||
onMouseOver={() => setIsHoveringOnThread('description')}
|
||||
onMouseLeave={() => setIsHoveringOnThread('')}>
|
||||
<Link style={{all: 'unset', cursor: 'pointer'}} to={() => {}}>
|
||||
{subplebbit.suggested?.avatarUrl ? (
|
||||
<img className='card'
|
||||
src={subplebbit.suggested.avatarUrl} alt="board avatar" />
|
||||
) : null}
|
||||
</Link>
|
||||
{subplebbit.suggested?.avatarUrl ? (
|
||||
<div className='thread-icons'>
|
||||
<span className="thread-icon sticky-icon" title="Sticky" />
|
||||
<span className="thread-icon closed-icon" title="Closed" />
|
||||
</div>
|
||||
) : null}
|
||||
<BoardForm selectedStyle={selectedStyle} style={{all: 'unset'}}>
|
||||
<div className='meta' title="(R)eplies / (I)mage Replies">
|
||||
R:<b>0</b>
|
||||
{subplebbit.suggested?.avatarUrl ? null : (
|
||||
<div className='thread-icons'
|
||||
style={{position: 'absolute', top: '-2px', right: '15px'}}>
|
||||
<span className="thread-icon sticky-icon" title="Sticky" />
|
||||
<span className="thread-icon closed-icon" title="Closed" />
|
||||
</div>
|
||||
)}
|
||||
<PostMenu
|
||||
style={{ display: isHoveringOnThread === "description" ? 'inline-block' : 'none',
|
||||
position: 'absolute', lineHeight: '1em', marginTop: '-1px', outline: 'none',
|
||||
zIndex: '999'}}
|
||||
title="Post menu"
|
||||
ref={el => {
|
||||
threadMenuRefs.current["description"] = el;
|
||||
postMenuRef.current = el;
|
||||
}}
|
||||
className='post-menu-button'
|
||||
id='post-menu-button-catalog'
|
||||
rotated={openMenuCid === "description"}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
const rect = threadMenuRefs.current["description"].getBoundingClientRect();
|
||||
setMenuPosition({top: rect.top + window.scrollY, left: rect.left});
|
||||
setOpenMenuCid(prevCid => (prevCid === "description" ? null : "description"));
|
||||
}}
|
||||
>
|
||||
▶
|
||||
</PostMenu>
|
||||
</div>
|
||||
{createPortal(
|
||||
<PostMenuCatalog selectedStyle={selectedStyle}
|
||||
ref={el => {postMenuCatalogRef.current = el}}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
style={{position: "absolute",
|
||||
top: menuPosition.top + 7,
|
||||
left: menuPosition.left}}>
|
||||
<div className={`post-menu-thread post-menu-thread-${"description"}`}
|
||||
style={{ display: openMenuCid === "description" ? 'block' : 'none' }}
|
||||
>
|
||||
<ul className="post-menu-catalog">
|
||||
<li onClick={() => handleOptionClick("description")}>Hide thread</li>
|
||||
{/* {isModerator ? (
|
||||
<>
|
||||
change description
|
||||
</>
|
||||
) : null} */}
|
||||
{subplebbit.suggested?.avatarUrl ? (
|
||||
<li
|
||||
onMouseOver={() => {setIsImageSearchOpen(true)}}
|
||||
onMouseLeave={() => {setIsImageSearchOpen(false)}}>
|
||||
Image search »
|
||||
<ul className="dropdown-menu post-menu-catalog"
|
||||
style={{display: isImageSearchOpen ? 'block': 'none'}}>
|
||||
<li onClick={() => handleOptionClick("description")}>
|
||||
<a
|
||||
href={`https://lens.google.com/uploadbyurl?url=${subplebbit.suggested.avatarUrl}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>Google</a>
|
||||
</li>
|
||||
<li onClick={() => handleOptionClick("description")}>
|
||||
<a
|
||||
href={`https://yandex.com/images/search?url=${subplebbit.suggested.avatarUrl}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>Yandex</a>
|
||||
</li>
|
||||
<li onClick={() => handleOptionClick("description")}>
|
||||
<a
|
||||
href={`https://saucenao.com/search.php?url=${subplebbit.suggested.avatarUrl}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>SauceNAO</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
) : null}
|
||||
</ul>
|
||||
</div>
|
||||
</PostMenuCatalog>, document.body
|
||||
)}
|
||||
</BoardForm>
|
||||
<Link style={{all: "unset", cursor: "pointer"}} to={() => {}}
|
||||
onClick={() => setSelectedThread("description")}>
|
||||
<div className="teaser">
|
||||
<b>Welcome to {subplebbit.title || subplebbit.address}</b>
|
||||
{": " + subplebbit.description}
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
) : null}
|
||||
{feed.map((thread, index) => {
|
||||
const commentMediaInfo = getCommentMediaInfo(thread);
|
||||
const fallbackImgUrl = "assets/filedeleted-res.gif";
|
||||
return (
|
||||
<div key={`thread-${index}`} className="thread"
|
||||
onMouseOver={() => {setIsHoveringOnThread(thread.cid)}}
|
||||
onMouseLeave={() => {setIsHoveringOnThread('')}}>
|
||||
{commentMediaInfo?.url ? (
|
||||
<Link style={{all: "unset", cursor: "pointer"}} key={`link-${index}`} to={`/p/${selectedAddress}/c/${thread.cid}`}
|
||||
onClick={() => setSelectedThread(thread.cid)}>
|
||||
{commentMediaInfo?.type === "webpage" ? (
|
||||
thread.thumbnailUrl ? (
|
||||
<img className="card" key={`img-${index}`}
|
||||
src={commentMediaInfo.thumbnail} alt={commentMediaInfo.type}
|
||||
onError={(e) => {
|
||||
e.target.src = fallbackImgUrl
|
||||
e.target.onerror = null;
|
||||
}} />
|
||||
) : null
|
||||
) : null}
|
||||
{commentMediaInfo?.type === "image" ? (
|
||||
<img className="card" key={`img-${index}`}
|
||||
src={commentMediaInfo.url} alt={commentMediaInfo.type}
|
||||
onError={(e) => {
|
||||
e.target.src = fallbackImgUrl
|
||||
e.target.onerror = null;}} />
|
||||
) : null}
|
||||
{commentMediaInfo?.type === "video" ? (
|
||||
<video className="card" key={`fti-${index}`}
|
||||
src={commentMediaInfo.url}
|
||||
alt={commentMediaInfo.type}
|
||||
onError={(e) => e.target.src = fallbackImgUrl} />
|
||||
) : null}
|
||||
{commentMediaInfo?.type === "audio" ? (
|
||||
<audio className="card" controls
|
||||
key={`fti-${index}`}
|
||||
src={commentMediaInfo.url}
|
||||
alt={commentMediaInfo.type}
|
||||
onError={(e) => e.target.src = fallbackImgUrl} />
|
||||
) : null}
|
||||
</Link>
|
||||
) : null}
|
||||
{(commentMediaInfo && (
|
||||
commentMediaInfo.type === 'image' ||
|
||||
commentMediaInfo.type === 'video' ||
|
||||
(commentMediaInfo.type === 'webpage' &&
|
||||
commentMediaInfo.thumbnail))) ? (
|
||||
<div key={`ti-${index}`} className="thread-icons" >
|
||||
{thread.pinned ? (
|
||||
<span key={`si-${index}`} className="thread-icon sticky-icon" title="Sticky" />
|
||||
) : null}
|
||||
{thread.locked ? (
|
||||
<span key={`li-${index}`} className="thread-icon closed-icon" title="Closed" />
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
<BoardForm selectedStyle={selectedStyle}
|
||||
style={{ all: "unset"}}>
|
||||
<div key={`meta-${index}`} className="meta" title="(R)eplies / (I)mage Replies" >
|
||||
R:
|
||||
<b key={`b-${index}`}>{thread.replyCount}</b>
|
||||
{(commentMediaInfo && (
|
||||
commentMediaInfo.type === 'image' ||
|
||||
commentMediaInfo.type === 'video' ||
|
||||
(commentMediaInfo.type === 'webpage' &&
|
||||
commentMediaInfo.thumbnail))) ? null : (
|
||||
<div className='thread-icons'
|
||||
style={{position: 'absolute', top: '-2px', right: '15px'}}>
|
||||
{thread.pinned ? (
|
||||
<span key={`si-${index}`} className="thread-icon sticky-icon" title="Sticky" />
|
||||
) : null}
|
||||
{thread.locked ? (
|
||||
<span key={`li-${index}`} className="thread-icon closed-icon" title="Closed" />
|
||||
) : null}
|
||||
</div>
|
||||
)}
|
||||
<PostMenu
|
||||
style={{ display: isHoveringOnThread === thread.cid ? 'inline-block' : 'none',
|
||||
position: 'absolute', lineHeight: '1em', marginTop: '-1px', outline: 'none',
|
||||
zIndex: '999'}}
|
||||
key={`pmb-${index}`}
|
||||
title="Post menu"
|
||||
ref={el => {
|
||||
threadMenuRefs.current[thread.cid] = el;
|
||||
postMenuRef.current = el;
|
||||
}}
|
||||
className='post-menu-button'
|
||||
id='post-menu-button-catalog'
|
||||
rotated={openMenuCid === thread.cid}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
const rect = threadMenuRefs.current[thread.cid].getBoundingClientRect();
|
||||
setMenuPosition({top: rect.top + window.scrollY, left: rect.left});
|
||||
setOpenMenuCid(prevCid => (prevCid === thread.cid ? null : thread.cid));
|
||||
}}
|
||||
>
|
||||
▶
|
||||
</PostMenu>
|
||||
</div>
|
||||
{createPortal(
|
||||
<PostMenuCatalog selectedStyle={selectedStyle}
|
||||
ref={el => {postMenuCatalogRef.current = el}}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
style={{position: "absolute",
|
||||
top: menuPosition.top + 7,
|
||||
left: menuPosition.left}}>
|
||||
<div className={`post-menu-thread post-menu-thread-${thread.cid}`}
|
||||
style={{ display: openMenuCid === thread.cid ? 'block' : 'none' }}
|
||||
>
|
||||
<ul className="post-menu-catalog">
|
||||
<li onClick={() => handleOptionClick(thread.cid)}>Hide thread</li>
|
||||
{thread.author.shortAddress === account?.author.shortAddress ? (
|
||||
<>
|
||||
<li onClick={() => handleAuthorEditClick(thread)}>Edit post</li>
|
||||
<li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
<>
|
||||
{thread.author.shortAddress === account?.author.shortAddress ? (
|
||||
null
|
||||
) : (
|
||||
<li onClick={() => {
|
||||
setModeratingCommentCid(thread.cid)
|
||||
setIsModerationOpen(true);
|
||||
handleOptionClick(thread.cid);
|
||||
setDeletePost(true);
|
||||
}}>
|
||||
Delete post
|
||||
</li>
|
||||
)}
|
||||
<li
|
||||
onClick={() => {
|
||||
setModeratingCommentCid(thread.cid)
|
||||
setIsModerationOpen(true);
|
||||
handleOptionClick(thread.cid);
|
||||
}}>
|
||||
Mod tools
|
||||
</li>
|
||||
</>
|
||||
) : null}
|
||||
{(commentMediaInfo && (
|
||||
commentMediaInfo.type === 'image' ||
|
||||
(commentMediaInfo.type === 'webpage' &&
|
||||
commentMediaInfo.thumbnail))) ? (
|
||||
<li
|
||||
onMouseOver={() => {setIsImageSearchOpen(true)}}
|
||||
onMouseLeave={() => {setIsImageSearchOpen(false)}}>
|
||||
Image search »
|
||||
<ul className="dropdown-menu post-menu-catalog"
|
||||
style={{display: isImageSearchOpen ? 'block': 'none'}}>
|
||||
<li onClick={() => handleOptionClick(thread.cid)}>
|
||||
<a
|
||||
href={`https://lens.google.com/uploadbyurl?url=${commentMediaInfo.url}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>Google</a>
|
||||
</li>
|
||||
<li onClick={() => handleOptionClick(thread.cid)}>
|
||||
<a
|
||||
href={`https://yandex.com/images/search?url=${commentMediaInfo.url}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>Yandex</a>
|
||||
</li>
|
||||
<li onClick={() => handleOptionClick(thread.cid)}>
|
||||
<a
|
||||
href={`https://saucenao.com/search.php?url=${commentMediaInfo.url}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>SauceNAO</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
) : null
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</PostMenuCatalog>, document.body
|
||||
)}
|
||||
</BoardForm>
|
||||
<Link style={{all: "unset", cursor: "pointer"}} key={`link2-${index}`} to={`/p/${selectedAddress}/c/${thread.cid}`}
|
||||
onClick={() => setSelectedThread(thread.cid)}>
|
||||
<div key={`t-${index}`} className="teaser">
|
||||
<b key={`b2-${index}`}>{thread.title ? `${thread.title}` : null}</b>
|
||||
{thread.content ? `: ${thread.content}` : null}
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
)})}
|
||||
</InfiniteScroll>
|
||||
) : (<CatalogLoader />)
|
||||
)}
|
||||
</Threads>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import React, { Fragment, useEffect, useRef } from 'react';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
import { useAccount } from '@plebbit/plebbit-react-hooks';
|
||||
import useGeneralStore from '../../hooks/stores/useGeneralStore';
|
||||
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 BoardAvatar from '../BoardAvatar';
|
||||
import OfflineIndicator from '../OfflineIndicator';
|
||||
import useGeneralStore from '../../hooks/stores/useGeneralStore';
|
||||
import packageJson from '../../../package.json'
|
||||
import { Tooltip } from 'react-tooltip';
|
||||
const {version} = packageJson
|
||||
@@ -14,7 +14,7 @@ const commitRef = process?.env?.REACT_APP_COMMIT_REF ? ` ${process.env.REACT_APP
|
||||
|
||||
|
||||
const Home = () => {
|
||||
const {
|
||||
const {
|
||||
bodyStyle, setBodyStyle,
|
||||
defaultSubplebbits,
|
||||
setSelectedAddress,
|
||||
|
||||
@@ -33,9 +33,11 @@ import handleQuoteClick from '../../utils/handleQuoteClick';
|
||||
import handleQuoteHover from '../../utils/handleQuoteHover';
|
||||
import handleStyleChange from '../../utils/handleStyleChange';
|
||||
import removeHighlight from '../../utils/removeHighlight';
|
||||
import useAnonModeRef from '../../hooks/useAnonModeRef';
|
||||
import useError from '../../hooks/useError';
|
||||
import useFeedStateString from '../../hooks/useFeedStateString';
|
||||
import useSuccess from '../../hooks/useSuccess';
|
||||
import useAnonModeStore from '../../hooks/stores/useAnonModeStore';
|
||||
import packageJson from '../../../package.json'
|
||||
const {version} = packageJson
|
||||
|
||||
@@ -62,6 +64,8 @@ const Subscriptions = () => {
|
||||
setSelectedTitle,
|
||||
} = useGeneralStore(state => state);
|
||||
|
||||
const { anonymousMode } = useAnonModeStore();
|
||||
|
||||
const account = useAccount();
|
||||
const navigate = useNavigate();
|
||||
const [, setNewErrorMessage] = useError();
|
||||
@@ -75,6 +79,7 @@ const Subscriptions = () => {
|
||||
const backlinkRefsMobile = useRef({});
|
||||
const quoteRefsMobile = useRef({});
|
||||
const postOnHoverRef = useRef(null);
|
||||
const selectedThreadCidRef = useRef(null);
|
||||
|
||||
const [isReplyOpen, setIsReplyOpen] = useState(false);
|
||||
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
|
||||
@@ -91,6 +96,13 @@ const Subscriptions = () => {
|
||||
const [postOnHoverHeight, setPostOnHoverHeight] = useState(0);
|
||||
const [deletePost, setDeletePost] = useState(false);
|
||||
const [moderatorPermissions, setModeratorPermissions] = useState({});
|
||||
const [executeAnonMode, setExecuteAnonMode] = useState(false);
|
||||
|
||||
const setSelectedThreadCid = (cid) => {
|
||||
selectedThreadCidRef.current = cid;
|
||||
}
|
||||
|
||||
useAnonModeRef(selectedThreadCidRef, anonymousMode && executeAnonMode);
|
||||
|
||||
const { feed, hasMore, loadMore } = useFeed({subplebbitAddresses: account?.subscriptions, sortType: 'active'});
|
||||
const [selectedFeed, setSelectedFeed] = useState(feed.sort((a, b) => b.timestamp - a.timestamp));
|
||||
@@ -316,11 +328,18 @@ const Subscriptions = () => {
|
||||
});
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (anonymousMode) {
|
||||
setExecuteAnonMode(true);
|
||||
}
|
||||
}, [anonymousMode, selectedThreadCidRef]);
|
||||
|
||||
|
||||
const { publishCommentEdit } = usePublishCommentEdit(publishCommentEditOptions);
|
||||
|
||||
|
||||
const handleAuthorDeleteClick = (comment) => {
|
||||
handleOptionClick(comment.cid);
|
||||
const handleAuthorDeleteClick = (cid) => {
|
||||
handleOptionClick(cid);
|
||||
|
||||
confirmAlert({
|
||||
customUI: ({ onClose }) => {
|
||||
@@ -334,7 +353,7 @@ const Subscriptions = () => {
|
||||
onClick={() => {
|
||||
setIsAuthorDelete(true);
|
||||
setIsAuthorEdit(false);
|
||||
setCommentCid(comment.cid);
|
||||
setCommentCid(cid);
|
||||
setPublishCommentEditOptions(prevOptions => ({
|
||||
...prevOptions,
|
||||
deleted: true,
|
||||
@@ -678,7 +697,8 @@ const Subscriptions = () => {
|
||||
onClick={(e) => {
|
||||
if (e.button === 2) return;
|
||||
e.preventDefault();
|
||||
setIsReplyOpen(true);
|
||||
setSelectedThreadCid(thread.cid);
|
||||
setIsReplyOpen(true);
|
||||
setSelectedShortCid(thread.shortCid);
|
||||
setSelectedParentCid(thread.cid);
|
||||
setSelectedAddress(thread.subplebbitAddress);
|
||||
@@ -736,7 +756,7 @@ const Subscriptions = () => {
|
||||
{thread.author.shortAddress === account?.author.shortAddress ? (
|
||||
<>
|
||||
<li onClick={() => {handleAuthorEditClick(thread); setSelectedAddress(thread.subplebbitAddress);}}>Edit post</li>
|
||||
<li onClick={() => {handleAuthorDeleteClick(thread); setSelectedAddress(thread.subplebbitAddress);}}>Delete post</li>
|
||||
<li onClick={() => {handleAuthorDeleteClick(thread.cid); setSelectedAddress(thread.subplebbitAddress);}}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
@@ -957,7 +977,8 @@ const Subscriptions = () => {
|
||||
onClick={(e) => {
|
||||
if (e.button === 2) return;
|
||||
e.preventDefault();
|
||||
setIsReplyOpen(true);
|
||||
setSelectedThreadCid(thread.cid);
|
||||
setIsReplyOpen(true);
|
||||
setSelectedShortCid(reply.shortCid);
|
||||
setSelectedParentCid(reply.cid);
|
||||
setSelectedAddress(thread.subplebbitAddress);
|
||||
@@ -1015,7 +1036,7 @@ const Subscriptions = () => {
|
||||
{reply.author.shortAddress === account?.author.shortAddress ? (
|
||||
<>
|
||||
<li onClick={() => {handleAuthorEditClick(reply); setSelectedAddress(thread.subplebbitAddress);}}>Edit post</li>
|
||||
<li onClick={() => {handleAuthorDeleteClick(reply); setSelectedAddress(thread.subplebbitAddress);}}>Delete post</li>
|
||||
<li onClick={() => {handleAuthorDeleteClick(reply.cid); setSelectedAddress(thread.subplebbitAddress);}}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
@@ -1390,7 +1411,8 @@ const Subscriptions = () => {
|
||||
onClick={(e) => {
|
||||
if (e.button === 2) return;
|
||||
e.preventDefault();
|
||||
setIsReplyOpen(true);
|
||||
setSelectedThreadCid(thread.cid);
|
||||
setIsReplyOpen(true);
|
||||
setSelectedShortCid(thread.shortCid);
|
||||
setSelectedParentCid(thread.cid);
|
||||
setSelectedAddress(thread.subplebbitAddress);
|
||||
@@ -1562,7 +1584,8 @@ const Subscriptions = () => {
|
||||
onClick={(e) => {
|
||||
if (e.button === 2) return;
|
||||
e.preventDefault();
|
||||
setIsReplyOpen(true);
|
||||
setSelectedThreadCid(thread.cid);
|
||||
setIsReplyOpen(true);
|
||||
setSelectedShortCid(reply.shortCid);
|
||||
setSelectedParentCid(reply.cid);
|
||||
setSelectedAddress(thread.subplebbitAddress);
|
||||
|
||||
@@ -7,7 +7,6 @@ import { Tooltip } from 'react-tooltip';
|
||||
import { useAccount, useAccountComments, useComment, usePublishComment, usePublishCommentEdit, useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
||||
import { flattenCommentsPages } from '@plebbit/plebbit-react-hooks/dist/lib/utils'
|
||||
import { debounce } from 'lodash';
|
||||
import useGeneralStore from '../../hooks/stores/useGeneralStore';
|
||||
import { Container, NavBar, Header, Break, PostForm, PostFormTable, PostMenu } from '../styled/views/Board.styled';
|
||||
import { ReplyFormLink, TopBar, BottomBar, BoardForm, Footer, AuthorDeleteAlert } from '../styled/views/Thread.styled';
|
||||
import { PostMenuCatalog } from '../styled/views/Catalog.styled';
|
||||
@@ -32,11 +31,14 @@ import handleQuoteClick from '../../utils/handleQuoteClick';
|
||||
import handleQuoteHover from '../../utils/handleQuoteHover';
|
||||
import handleStyleChange from '../../utils/handleStyleChange';
|
||||
import removeHighlight from '../../utils/removeHighlight';
|
||||
import useAnonMode from '../../hooks/useAnonMode';
|
||||
import useClickForm from '../../hooks/useClickForm';
|
||||
import useError from '../../hooks/useError';
|
||||
import useStateString from '../../hooks/useStateString';
|
||||
import packageJson from '../../../package.json'
|
||||
import useSuccess from '../../hooks/useSuccess';
|
||||
import useAnonModeStore from '../../hooks/stores/useAnonModeStore';
|
||||
import useGeneralStore from '../../hooks/stores/useGeneralStore';
|
||||
import packageJson from '../../../package.json'
|
||||
const {version} = packageJson
|
||||
|
||||
|
||||
@@ -65,6 +67,8 @@ const Thread = () => {
|
||||
showPostFormLink,
|
||||
} = useGeneralStore(state => state);
|
||||
|
||||
const { anonymousMode } = useAnonModeStore();
|
||||
|
||||
const account = useAccount();
|
||||
const navigate = useNavigate();
|
||||
const handleClickForm = useClickForm();
|
||||
@@ -82,6 +86,8 @@ const Thread = () => {
|
||||
const backlinkRefs = useRef({});
|
||||
const quoteRefs = useRef({});
|
||||
const postOnHoverRef = useRef(null);
|
||||
const backlinkRefsMobile = useRef({});
|
||||
const quoteRefsMobile = useRef({});
|
||||
|
||||
const [triggerPublishComment, setTriggerPublishComment] = useState(false);
|
||||
const [triggerPublishCommentEdit, setTriggerPublishCommentEdit] = useState(false);
|
||||
@@ -99,9 +105,9 @@ const Thread = () => {
|
||||
const [outOfViewCid, setOutOfViewCid] = useState(null);
|
||||
const [outOfViewPosition, setOutOfViewPosition] = useState({top: 0, left: 0});
|
||||
const [postOnHoverHeight, setPostOnHoverHeight] = useState(0);
|
||||
const backlinkRefsMobile = useRef({});
|
||||
const quoteRefsMobile = useRef({});
|
||||
|
||||
const [executeAnonMode, setExecuteAnonMode] = useState(false);
|
||||
|
||||
useAnonMode(selectedThread, anonymousMode && executeAnonMode);
|
||||
|
||||
const comment = useComment({commentCid: selectedThread});
|
||||
const { subplebbitAddress, threadCid } = useParams();
|
||||
@@ -323,7 +329,15 @@ const Thread = () => {
|
||||
}));
|
||||
|
||||
setTriggerPublishComment(true);
|
||||
setExecuteAnonMode(false);
|
||||
};
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (anonymousMode) {
|
||||
setExecuteAnonMode(true);
|
||||
}
|
||||
}, [anonymousMode, selectedThread]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
@@ -387,8 +401,8 @@ const Thread = () => {
|
||||
const { publishCommentEdit } = usePublishCommentEdit(publishCommentEditOptions);
|
||||
|
||||
|
||||
const handleAuthorDeleteClick = (comment) => {
|
||||
handleOptionClick(comment.cid);
|
||||
const handleAuthorDeleteClick = (cid) => {
|
||||
handleOptionClick(cid);
|
||||
|
||||
confirmAlert({
|
||||
customUI: ({ onClose }) => {
|
||||
@@ -402,7 +416,7 @@ const Thread = () => {
|
||||
onClick={() => {
|
||||
setIsAuthorDelete(true);
|
||||
setIsAuthorEdit(false);
|
||||
setCommentCid(comment.cid);
|
||||
setCommentCid(cid);
|
||||
setPublishCommentEditOptions(prevOptions => ({
|
||||
...prevOptions,
|
||||
deleted: true,
|
||||
@@ -518,7 +532,7 @@ const Thread = () => {
|
||||
<span className="boardList">
|
||||
[
|
||||
<Link to={`/p/all`}>All</Link>
|
||||
/
|
||||
/
|
||||
<Link to={`/p/subscriptions`}>Subscriptions</Link>
|
||||
] [
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
@@ -865,7 +879,7 @@ const Thread = () => {
|
||||
{comment.author?.shortAddress === account?.author.shortAddress ? (
|
||||
<>
|
||||
<li onClick={() => handleAuthorEditClick(comment)}>Edit post</li>
|
||||
<li onClick={() => handleAuthorDeleteClick(comment)}>Delete post</li>
|
||||
<li onClick={() => handleAuthorDeleteClick(comment.cid)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
@@ -1088,7 +1102,7 @@ const Thread = () => {
|
||||
{reply.author.shortAddress === account?.author.shortAddress ? (
|
||||
<>
|
||||
<li onClick={() => handleAuthorEditClick(reply)}>Edit post</li>
|
||||
<li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li>
|
||||
<li onClick={() => handleAuthorDeleteClick(reply.cid)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
|
||||
const useAnonModeStore = create(persist(
|
||||
(set) => ({
|
||||
anonymousMode: true,
|
||||
setAnonymousMode: (mode) => set({ anonymousMode: mode }),
|
||||
}),
|
||||
{
|
||||
name: "anonmode_store",
|
||||
getStorage: () => localStorage,
|
||||
}
|
||||
));
|
||||
|
||||
export default useAnonModeStore;
|
||||
@@ -1,9 +1,6 @@
|
||||
import { create } from 'zustand';
|
||||
|
||||
const useGeneralStore = create((set) => ({
|
||||
anonymousMode: true,
|
||||
setAnonymousMode: (mode) => set({ anonymousMode: mode }),
|
||||
|
||||
bodyStyle: JSON.parse(localStorage.getItem('bodyStyle')) || {
|
||||
background: '#ffe url(assets/fade.png) top repeat-x',
|
||||
color: 'maroon',
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import { useEffect } from "react";
|
||||
import { createAccount, setActiveAccount, useAccounts } from "@plebbit/plebbit-react-hooks";
|
||||
import useAnonModeStore from "./stores/useAnonModeStore";
|
||||
|
||||
const useAnonMode = (threadCid, execute) => {
|
||||
const {accounts} = useAccounts();
|
||||
const { anonymousMode } = useAnonModeStore();
|
||||
|
||||
useEffect(() => {
|
||||
const handleAnonMode = async () => {
|
||||
let storedAccounts = JSON.parse(localStorage.getItem('storedAccounts')) || {};
|
||||
|
||||
if (!anonymousMode) return;
|
||||
|
||||
if (!storedAccounts[threadCid] && execute) {
|
||||
await createAccount();
|
||||
const lastAccount = accounts[accounts.length - 1];
|
||||
await setActiveAccount(lastAccount.name);
|
||||
storedAccounts[threadCid] = lastAccount.name;
|
||||
|
||||
localStorage.setItem('storedAccounts', JSON.stringify(storedAccounts));
|
||||
} else {
|
||||
await setActiveAccount(storedAccounts[threadCid]);
|
||||
}
|
||||
}
|
||||
|
||||
handleAnonMode();
|
||||
}, [threadCid, execute, accounts, anonymousMode]);
|
||||
|
||||
return;
|
||||
}
|
||||
export default useAnonMode;
|
||||
@@ -0,0 +1,32 @@
|
||||
import { useEffect } from "react";
|
||||
import { createAccount, setActiveAccount, useAccounts } from "@plebbit/plebbit-react-hooks";
|
||||
import useAnonModeStore from "./stores/useAnonModeStore";
|
||||
|
||||
const useAnonModeRef = (threadCidRef, execute) => {
|
||||
const {accounts} = useAccounts();
|
||||
const { anonymousMode } = useAnonModeStore();
|
||||
|
||||
useEffect(() => {
|
||||
const handleAnonMode = async () => {
|
||||
let storedAccounts = JSON.parse(localStorage.getItem('storedAccounts')) || {};
|
||||
|
||||
if (!anonymousMode) return;
|
||||
|
||||
if (!storedAccounts[threadCidRef.current] && execute) {
|
||||
await createAccount();
|
||||
const lastAccount = accounts[accounts.length - 1];
|
||||
await setActiveAccount(lastAccount.name);
|
||||
storedAccounts[threadCidRef.current] = lastAccount.name;
|
||||
|
||||
localStorage.setItem('storedAccounts', JSON.stringify(storedAccounts));
|
||||
} else {
|
||||
await setActiveAccount(storedAccounts[threadCidRef.current]);
|
||||
}
|
||||
}
|
||||
|
||||
handleAnonMode();
|
||||
}, [threadCidRef, execute, accounts, anonymousMode]);
|
||||
|
||||
return;
|
||||
}
|
||||
export default useAnonModeRef;
|
||||
@@ -7,6 +7,7 @@
|
||||
resolved "https://registry.yarnpkg.com/7zip-bin/-/7zip-bin-5.1.1.tgz#9274ec7460652f9c632c59addf24efb1684ef876"
|
||||
integrity sha512-sAP4LldeWNz0lNzmTird3uWfFDWWTeg6V/MsmyyLR9X1idwKBWIgt/ZvinqQldJm3LecKEs1emkbquO6PCiLVQ==
|
||||
|
||||
|
||||
"@adraffy/ens-normalize@1.8.3", "@adraffy/ens-normalize@1.9.0", "@adraffy/ens-normalize@1.9.2":
|
||||
version "1.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.8.3.tgz#6084dd00eac37a99bcf91a3a3249cc737cbcb005"
|
||||
@@ -2591,11 +2592,12 @@
|
||||
resolved "https://registry.yarnpkg.com/@noble/ed25519/-/ed25519-1.7.3.tgz#57e1677bf6885354b466c38e2b620c62f45a7123"
|
||||
integrity sha512-iR8GBkDt0Q3GyaVcIu7mSsVIqnFbkbRzGLWlvhwunacoLwt4J3swfKhfaM6rN6WY+TBGoYT1GtT1mIh2/jGbRQ==
|
||||
|
||||
|
||||
"@noble/hashes@1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183"
|
||||
integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==
|
||||
|
||||
|
||||
"@noble/hashes@1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.0.tgz#085fd70f6d7d9d109671090ccae1d3bec62554a1"
|
||||
@@ -2606,6 +2608,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9"
|
||||
integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==
|
||||
|
||||
|
||||
"@noble/secp256k1@1.7.1", "@noble/secp256k1@^1.3.0":
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c"
|
||||
@@ -2648,7 +2651,53 @@
|
||||
mkdirp "^1.0.4"
|
||||
rimraf "^3.0.2"
|
||||
|
||||
|
||||
"@plebbit/plebbit-js@https://github.com/plebbit/plebbit-js.git#574d1730da725a6266da6d69f2fa01f027dadb96":
|
||||
version "0.0.3"
|
||||
resolved "https://github.com/plebbit/plebbit-js.git#220c709566d8b680e7dc13722f4e81c8d0f13b3b"
|
||||
dependencies:
|
||||
"@adraffy/ens-normalize" "1.9.2"
|
||||
"@keyv/sqlite" "3.6.2"
|
||||
"@plebbit/plebbit-logger" "github:plebbit/plebbit-logger"
|
||||
"@types/node-fetch" "2.6.2"
|
||||
"@types/proper-lockfile" "4.1.2"
|
||||
"@types/uuid" "8.3.4"
|
||||
assert "2.0.0"
|
||||
async-wait-until "2.0.12"
|
||||
buffer "6.0.3"
|
||||
captcha-canvas "3.2.1"
|
||||
err-code "3.0.1"
|
||||
file-type "16.5.4"
|
||||
form-data "4.0.0"
|
||||
hpagent "1.2.0"
|
||||
ipfs-http-client "56.0.3"
|
||||
ipfs-only-hash "4.0.0"
|
||||
is-ipfs "6.0.2"
|
||||
jose "4.11.0"
|
||||
js-sha256 "0.9.0"
|
||||
keyv "4.5.2"
|
||||
knex "2.4.2"
|
||||
libp2p-crypto "0.21.2"
|
||||
limiter "2.1.0"
|
||||
localforage "1.10.0"
|
||||
lodash-es "4.17.21"
|
||||
lru-cache "7.18.3"
|
||||
open-graph-scraper "5.2.3"
|
||||
p-limit "3.1.0"
|
||||
peer-id "0.16.0"
|
||||
proper-lockfile "github:plebbit/node-proper-lockfile"
|
||||
retry "0.13.1"
|
||||
safe-stable-stringify "2.4.1"
|
||||
sha1-uint8array "0.10.3"
|
||||
skia-canvas "1.0.0"
|
||||
sqlite3 "5.1.6"
|
||||
tiny-typed-emitter "2.1.0"
|
||||
tinycache "1.1.2"
|
||||
ts-custom-error "3.3.1"
|
||||
uuid "9.0.0"
|
||||
viem "1.0.7"
|
||||
|
||||
"@plebbit/plebbit-js@https://github.com/plebbit/plebbit-js.git#27df54b8c591c9245deb91e131d15de2bc8bf4d3":
|
||||
version "0.0.3"
|
||||
resolved "https://github.com/plebbit/plebbit-js.git#574d1730da725a6266da6d69f2fa01f027dadb96"
|
||||
dependencies:
|
||||
@@ -2722,6 +2771,22 @@
|
||||
uuid "8.3.2"
|
||||
zustand "4.0.0"
|
||||
|
||||
"@plebbit/plebbit-react-hooks@https://github.com/plebbit/plebbit-react-hooks.git#338324289dffa20ecde429fa5f428a2894851512":
|
||||
version "0.0.1"
|
||||
resolved "https://github.com/plebbit/plebbit-react-hooks.git#338324289dffa20ecde429fa5f428a2894851512"
|
||||
dependencies:
|
||||
"@adraffy/ens-normalize" "1.9.2"
|
||||
"@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#220c709566d8b680e7dc13722f4e81c8d0f13b3b"
|
||||
"@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"
|
||||
|
||||
"@pmmmwh/react-refresh-webpack-plugin@^0.5.3":
|
||||
version "0.5.10"
|
||||
resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.10.tgz#2eba163b8e7dbabb4ce3609ab5e32ab63dda3ef8"
|
||||
@@ -2859,6 +2924,28 @@
|
||||
"@noble/hashes" "~1.3.0"
|
||||
"@scure/base" "~1.1.0"
|
||||
|
||||
"@scure/base@~1.1.0":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938"
|
||||
integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==
|
||||
|
||||
"@scure/bip32@1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.0.tgz#6c8d980ef3f290987736acd0ee2e0f0d50068d87"
|
||||
integrity sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q==
|
||||
dependencies:
|
||||
"@noble/curves" "~1.0.0"
|
||||
"@noble/hashes" "~1.3.0"
|
||||
"@scure/base" "~1.1.0"
|
||||
|
||||
"@scure/bip39@1.2.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.0.tgz#a207e2ef96de354de7d0002292ba1503538fc77b"
|
||||
integrity sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg==
|
||||
dependencies:
|
||||
"@noble/hashes" "~1.3.0"
|
||||
"@scure/base" "~1.1.0"
|
||||
|
||||
"@sideway/address@^4.1.3":
|
||||
version "4.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0"
|
||||
@@ -3716,6 +3803,7 @@
|
||||
dependencies:
|
||||
"@webassemblyjs/floating-point-hex-parser" "1.11.6"
|
||||
"@webassemblyjs/helper-api-error" "1.11.6"
|
||||
|
||||
"@xtuc/long" "4.2.2"
|
||||
|
||||
"@webassemblyjs/helper-wasm-bytecode@1.11.6":
|
||||
|
||||
Reference in New Issue
Block a user