Merge pull request #280 from plebbit/development

Development
This commit is contained in:
plebeius.eth
2023-09-30 21:57:59 +02:00
committed by GitHub
21 changed files with 813 additions and 468 deletions
+2 -49
View File
@@ -28,21 +28,10 @@ import packageJson from '../package.json';
const commitRef = process?.env?.REACT_APP_COMMIT_REF || ''; const commitRef = process?.env?.REACT_APP_COMMIT_REF || '';
export default function App() { export default function App() {
const { const { bodyStyle, setBodyStyle, setDefaultSubplebbits, isCaptchaOpen, setIsCaptchaOpen, setIsSettingsOpen, selectedStyle, setShowPostForm, setShowPostFormLink } =
bodyStyle, useGeneralStore((state) => state);
setBodyStyle,
setDefaultSubplebbits,
isCaptchaOpen,
setIsCaptchaOpen,
setIsSettingsOpen,
selectedStyle,
setSelectedStyle,
setShowPostForm,
setShowPostFormLink,
} = useGeneralStore((state) => state);
const location = useLocation(); const location = useLocation();
const isHomeRoute = location.pathname === '/';
const isElectron = window.electron && window.electron.isElectron; const isElectron = window.electron && window.electron.isElectron;
const [, setNewErrorMessage] = useError(); const [, setNewErrorMessage] = useError();
@@ -112,42 +101,6 @@ export default function App() {
loadImages(); loadImages();
}, []); }, []);
// automatic dark mode without interefering with user's selected style
useEffect(() => {
if (isHomeRoute) return;
const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const isDarkMode = darkModeMediaQuery.matches;
if (isDarkMode && !isHomeRoute) {
setSelectedStyle('Tomorrow');
setBodyStyle({
background: '#1d1f21 none',
color: '#c5c8c6',
fontFamily: 'Arial, Helvetica, sans-serif',
});
localStorage.setItem('selectedStyle', 'Tomorrow');
}
const darkModeListener = (e) => {
if (e.matches && !isHomeRoute) {
setSelectedStyle('Tomorrow');
setBodyStyle({
background: '#1d1f21 none',
color: '#c5c8c6',
fontFamily: 'Arial, Helvetica, sans-serif',
});
localStorage.setItem('selectedStyle', 'Tomorrow');
}
};
darkModeMediaQuery.addEventListener('change', darkModeListener);
return () => {
darkModeMediaQuery.removeEventListener('change', darkModeListener);
};
}, [isHomeRoute, setBodyStyle, setSelectedStyle]);
// fetch default subplebbits // fetch default subplebbits
useEffect(() => { useEffect(() => {
let didCancel = false; let didCancel = false;
-1
View File
@@ -81,7 +81,6 @@ const Post = ({ content, postQuoteOnClick, postQuoteOnOver, postQuoteOnLeave, po
parts.push( parts.push(
<ForwardRefLink <ForwardRefLink
key={`link-${i}-${matchedText}`}
className='quotelink' className='quotelink'
to={linkTo} to={linkTo}
target={linkTarget} target={linkTarget}
+8 -6
View File
@@ -43,10 +43,8 @@ const AdminListModal = ({ isOpen, closeModal, roles }) => {
maxHeight: '250px', maxHeight: '250px',
}} }}
> >
<button className='icon' onClick={() => closeModal()} title='close' /> <button className='icon' style={{ imageRendering: 'pixelated', margin: '1px 1px 0 0' }} onClick={() => closeModal()} title='close' />
<div className='modal-header' style={{ margin: '10px 10px 0px 10px' }}> <div className='modal-header'>   Moderators</div>
Moderators
</div>
<div <div
className='list' className='list'
style={{ style={{
@@ -60,7 +58,8 @@ const AdminListModal = ({ isOpen, closeModal, roles }) => {
}} }}
> >
<BoardForm selectedStyle={selectedStyle} style={{ all: 'unset' }}> <BoardForm selectedStyle={selectedStyle} style={{ all: 'unset' }}>
{rolesList.map(({ address, role }, index) => ( {roles ? (
rolesList.map(({ address, role }, index) => (
<p key={index}> <p key={index}>
{' '} {' '}
<Link to={() => {}} className='quote-link'> <Link to={() => {}} className='quote-link'>
@@ -68,7 +67,10 @@ const AdminListModal = ({ isOpen, closeModal, roles }) => {
</Link> </Link>
: {role} : {role}
</p> </p>
))} ))
) : (
<p>This board doesn't have moderators yet.</p>
)}
</BoardForm> </BoardForm>
</div> </div>
</div> </div>
@@ -36,6 +36,7 @@ export const StyledModal = styled(Modal)`
width: 18px; width: 18px;
height: 18px; height: 18px;
border: none; border: none;
image-rendering: pixelated;
} }
#field { #field {
@@ -1,5 +1,5 @@
import styled from "styled-components"; import styled from 'styled-components';
import Modal from "react-modal"; import Modal from 'react-modal';
export const StyledModal = styled(Modal)` export const StyledModal = styled(Modal)`
.modal-content { .modal-content {
@@ -12,7 +12,7 @@ export const StyledModal = styled(Modal)`
max-height: calc(100vh - 2 * 50px); max-height: calc(100vh - 2 * 50px);
overflow-y: auto; overflow-y: auto;
padding: 5px; padding: 5px;
box-shadow: 0 0 5px rgba(0, 0, 0, .25); box-shadow: 0 0 5px rgba(0, 0, 0, 0.25);
} }
.modal-header { .modal-header {
@@ -33,9 +33,12 @@ export const StyledModal = styled(Modal)`
width: 18px; width: 18px;
height: 18px; height: 18px;
border: none; border: none;
image-rendering: pixelated;
} }
#name, #description, #rule { #name,
#description,
#rule {
border: 1px solid #aaa; border: 1px solid #aaa;
font-family: Arial, Helvetica, sans-serif; font-family: Arial, Helvetica, sans-serif;
font-size: 10pt; font-size: 10pt;
@@ -73,7 +76,6 @@ export const StyledModal = styled(Modal)`
} }
#rule { #rule {
} }
#rule-btn { #rule-btn {
@@ -1,4 +1,4 @@
import styled from "styled-components"; import styled from 'styled-components';
import Modal from 'react-modal'; import Modal from 'react-modal';
export const StyledModal = styled(Modal)` export const StyledModal = styled(Modal)`
@@ -13,7 +13,7 @@ export const StyledModal = styled(Modal)`
position: absolute; position: absolute;
padding: 2px 5px 5px; padding: 2px 5px 5px;
font-size: 14px; font-size: 14px;
box-shadow: 0 0 5px rgba(0, 0, 0, .25); box-shadow: 0 0 5px rgba(0, 0, 0, 0.25);
@media (max-width: 480px) { @media (max-width: 480px) {
width: 320px !important; width: 320px !important;
@@ -32,7 +32,7 @@ export const StyledModal = styled(Modal)`
position: absolute; position: absolute;
padding: 2px 5px 5px; padding: 2px 5px 5px;
font-size: 14px; font-size: 14px;
box-shadow: 0 0 5px rgba(0, 0, 0, .25); box-shadow: 0 0 5px rgba(0, 0, 0, 0.25);
@media (max-width: 800px) { @media (max-width: 800px) {
width: 80%; width: 80%;
@@ -66,6 +66,7 @@ export const StyledModal = styled(Modal)`
cursor: pointer; cursor: pointer;
position: absolute; position: absolute;
top: 5px; top: 5px;
image-rendering: pixelated;
} }
h4 { h4 {
@@ -171,7 +172,8 @@ export const StyledModal = styled(Modal)`
margin-bottom: 10px; margin-bottom: 10px;
} }
#save-board-settings, #reset-board-settings { #save-board-settings,
#reset-board-settings {
text-align: center; text-align: center;
} }
@@ -1,5 +1,5 @@
import styled from "styled-components"; import styled from 'styled-components';
import Modal from "react-modal"; import Modal from 'react-modal';
export const StyledModal = styled(Modal)` export const StyledModal = styled(Modal)`
.modal-content { .modal-content {
@@ -32,6 +32,7 @@ export const StyledModal = styled(Modal)`
width: 18px; width: 18px;
height: 18px; height: 18px;
border: none; border: none;
image-rendering: pixelated;
} }
#name { #name {
@@ -50,6 +50,7 @@ export const StyledModal = styled(Modal)`
cursor: pointer; cursor: pointer;
position: absolute; position: absolute;
top: 5px; top: 5px;
image-rendering: pixelated;
} }
h4 { h4 {
@@ -80,6 +81,7 @@ export const StyledModal = styled(Modal)`
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center; background-position: center;
display: inline-block; display: inline-block;
image-rendering: pixelated;
} }
.settings-cat { .settings-cat {
+72 -4
View File
@@ -1698,10 +1698,6 @@ export const BoardForm = styled.div`
margin-right: 14px; margin-right: 14px;
} }
.capcode-admin {
color: red !important;
}
.ellipsis:after { .ellipsis:after {
content: '\\2026'; content: '\\2026';
position: absolute; position: absolute;
@@ -1811,6 +1807,12 @@ export const BoardForm = styled.div`
.capcode { .capcode {
color: purple !important; color: purple !important;
cursor: pointer;
}
.capcode-admin {
color: red !important;
cursor: pointer;
} }
#post-menu { #post-menu {
@@ -1838,6 +1840,12 @@ export const BoardForm = styled.div`
.capcode { .capcode {
color: purple !important; color: purple !important;
cursor: pointer;
}
.capcode-admin {
color: red !important;
cursor: pointer;
} }
#post-menu { #post-menu {
@@ -1862,6 +1870,12 @@ export const BoardForm = styled.div`
.capcode { .capcode {
color: purple !important; color: purple !important;
cursor: pointer;
}
.capcode-admin {
color: red !important;
cursor: pointer;
} }
#post-menu { #post-menu {
@@ -1886,6 +1900,12 @@ export const BoardForm = styled.div`
.capcode { .capcode {
color: purple !important; color: purple !important;
cursor: pointer;
}
.capcode-admin {
color: red !important;
cursor: pointer;
} }
#post-menu { #post-menu {
@@ -1911,6 +1931,12 @@ export const BoardForm = styled.div`
.capcode { .capcode {
color: #81a2be !important; color: #81a2be !important;
cursor: pointer;
}
.capcode-admin {
color: #81a2be !important;
cursor: pointer;
} }
#post-menu { #post-menu {
@@ -1935,6 +1961,12 @@ export const BoardForm = styled.div`
.capcode { .capcode {
color: #f60 !important; color: #f60 !important;
cursor: pointer;
}
.capcode-admin {
color: #f60 !important;
cursor: pointer;
} }
#post-menu { #post-menu {
@@ -3367,6 +3399,12 @@ export const BoardForm = styled.div`
return ` return `
.capcode { .capcode {
color: purple !important; color: purple !important;
cursor: pointer;
}
.capcode-admin {
color: red !important;
cursor: pointer;
} }
.op-container { .op-container {
background-color: #f5e9e1; background-color: #f5e9e1;
@@ -3487,6 +3525,12 @@ export const BoardForm = styled.div`
return ` return `
.capcode { .capcode {
color: purple !important; color: purple !important;
cursor: pointer;
}
.capcode-admin {
color: red !important;
cursor: pointer;
} }
.op-container { .op-container {
background-color: #d6daf0; background-color: #d6daf0;
@@ -3603,6 +3647,12 @@ export const BoardForm = styled.div`
return ` return `
.capcode { .capcode {
color: purple !important; color: purple !important;
cursor: pointer;
}
.capcode-admin {
color: red !important;
cursor: pointer;
} }
.op-container { .op-container {
background-color: #f5e9e1; background-color: #f5e9e1;
@@ -3722,6 +3772,12 @@ export const BoardForm = styled.div`
return ` return `
.capcode { .capcode {
color: purple !important; color: purple !important;
cursor: pointer;
}
.capcode-admin {
color: red !important;
cursor: pointer;
} }
.op-container { .op-container {
background-color: #d6daf0; background-color: #d6daf0;
@@ -3837,6 +3893,12 @@ export const BoardForm = styled.div`
return ` return `
.capcode { .capcode {
color: #81a2be !important; color: #81a2be !important;
cursor: pointer;
}
.capcode-admin {
color: #81a2be !important;
cursor: pointer;
} }
.op-container { .op-container {
@@ -3963,6 +4025,12 @@ export const BoardForm = styled.div`
return ` return `
.capcode { .capcode {
color: #f60 !important; color: #f60 !important;
cursor: pointer;
}
.capcode-admin {
color: #f60 !important;
cursor: pointer;
} }
.op-container { .op-container {
background-color: #eee; background-color: #eee;
+24 -7
View File
@@ -17,7 +17,9 @@ export const Threads = styled.div`
padding: 5px 0 3px; padding: 5px 0 3px;
} }
video, audio, img { video,
audio,
img {
max-width: 150px; max-width: 150px;
max-height: 150px; max-height: 150px;
} }
@@ -31,7 +33,7 @@ export const Threads = styled.div`
} }
.card { .card {
box-shadow: 0 0 5px rgba(0, 0, 0, .25); box-shadow: 0 0 5px rgba(0, 0, 0, 0.25);
border: 0; border: 0;
} }
@@ -94,7 +96,6 @@ export const Threads = styled.div`
word-wrap: break-word; word-wrap: break-word;
} }
${({ selectedStyle }) => { ${({ selectedStyle }) => {
switch (selectedStyle) { switch (selectedStyle) {
case 'Yotsuba': case 'Yotsuba':
@@ -155,7 +156,6 @@ export const PostPreview = styled.div`
font-weight: 700; font-weight: 700;
} }
${({ selectedStyle }) => { ${({ selectedStyle }) => {
switch (selectedStyle) { switch (selectedStyle) {
case 'Yotsuba': case 'Yotsuba':
@@ -284,8 +284,26 @@ export const PostMenuCatalog = styled.div`
${({ selectedStyle }) => { ${({ selectedStyle }) => {
switch (selectedStyle) { switch (selectedStyle) {
case 'Yotsuba': case 'Yotsuba':
return `.post-subject{ return `.highlighted, .highlighted-click, .highlighted-address {
color:red; background-color: #f0c0b0 !important;
border: 1px solid #d9bfb7 !important;
border-left: none !important;
border-top: none !important;
}
.post-menu-catalog {
border-right: 1px solid #d9bfb7;
border-bottom: 2px solid #d9bfb7;
li {
border: 1px solid #d9bfb7;
background-color: #f0e0d6;
border-bottom: none;
:hover {
background-color: #ffe;
}
}
}`; }`;
case 'Yotsuba-B': case 'Yotsuba-B':
@@ -395,7 +413,6 @@ export const PostMenuCatalog = styled.div`
} }
}`; }`;
default: default:
return ''; return '';
} }
+94 -7
View File
@@ -906,10 +906,6 @@ export const BoardForm = styled.div`
margin-right: 14px; margin-right: 14px;
} }
.capcode-admin {
color: red !important;
}
.ellipsis:after { .ellipsis:after {
content: '\\2026'; content: '\\2026';
position: absolute; position: absolute;
@@ -1002,6 +998,16 @@ export const BoardForm = styled.div`
border-top: none !important; border-top: none !important;
} }
.capcode {
color: purple !important;
cursor: pointer;
}
.capcode-admin {
color: red !important;
cursor: pointer;
}
#post-menu { #post-menu {
ul { ul {
background-color: #f0e0d6; background-color: #f0e0d6;
@@ -1027,6 +1033,16 @@ export const BoardForm = styled.div`
border-top: none !important; border-top: none !important;
} }
.capcode {
color: purple !important;
cursor: pointer;
}
.capcode-admin {
color: red !important;
cursor: pointer;
}
#post-menu { #post-menu {
ul { ul {
background-color: #d6daf0; background-color: #d6daf0;
@@ -1048,6 +1064,16 @@ export const BoardForm = styled.div`
background-color: #f0c0b0 !important; background-color: #f0c0b0 !important;
} }
.capcode {
color: purple !important;
cursor: pointer;
}
.capcode-admin {
color: red !important;
cursor: pointer;
}
#post-menu { #post-menu {
font-size: 13px !important; font-size: 13px !important;
@@ -1071,6 +1097,16 @@ export const BoardForm = styled.div`
background-color: #d6bad0 !important; background-color: #d6bad0 !important;
} }
.capcode {
color: purple !important;
cursor: pointer;
}
.capcode-admin {
color: red !important;
cursor: pointer;
}
#post-menu { #post-menu {
font-size: 13px !important; font-size: 13px !important;
@@ -1095,6 +1131,16 @@ export const BoardForm = styled.div`
outline: 1px solid #111 !important; outline: 1px solid #111 !important;
} }
.capcode {
color: #81a2be !important;
cursor: pointer;
}
.capcode-admin {
color: #81a2be !important;
cursor: pointer;
}
#post-menu { #post-menu {
ul { ul {
background-color: #282a2e; background-color: #282a2e;
@@ -1117,6 +1163,16 @@ export const BoardForm = styled.div`
outline: 1px solid #ccc !important; outline: 1px solid #ccc !important;
} }
.capcode {
color: #f60 !important;
cursor: pointer;
}
.capcode-admin {
color: #f60 !important;
cursor: pointer;
}
#post-menu { #post-menu {
ul { ul {
background-color: #ddd; background-color: #ddd;
@@ -2506,6 +2562,12 @@ export const BoardForm = styled.div`
.capcode { .capcode {
color: purple !important; color: purple !important;
cursor: pointer;
}
.capcode-admin {
color: red !important;
cursor: pointer;
} }
.subject-mobile { .subject-mobile {
@@ -2627,6 +2689,12 @@ export const BoardForm = styled.div`
.capcode { .capcode {
color: purple !important; color: purple !important;
cursor: pointer;
}
.capcode-admin {
color: red !important;
cursor: pointer;
} }
.subject-mobile { .subject-mobile {
@@ -2744,11 +2812,12 @@ export const BoardForm = styled.div`
.capcode { .capcode {
color: purple !important; color: purple !important;
cursor: pointer;
} }
.subject-mobile { .capcode-admin {
color: #cc1105; color: red !important;
font-weight: 700; cursor: pointer;
} }
.date-time-mobile { .date-time-mobile {
@@ -2864,6 +2933,12 @@ export const BoardForm = styled.div`
.capcode { .capcode {
color: purple !important; color: purple !important;
cursor: pointer;
}
.capcode-admin {
color: red !important;
cursor: pointer;
} }
.subject-mobile { .subject-mobile {
@@ -2980,6 +3055,12 @@ export const BoardForm = styled.div`
.capcode { .capcode {
color: #81a2be !important; color: #81a2be !important;
cursor: pointer;
}
.capcode-admin {
color: #81a2be !important;
cursor: pointer;
} }
.poster-address-mobile { .poster-address-mobile {
@@ -3106,6 +3187,12 @@ export const BoardForm = styled.div`
.capcode { .capcode {
color: #f60 !important; color: #f60 !important;
cursor: pointer;
}
.capcode-admin {
color: #f60 !important;
cursor: pointer;
} }
.subject-mobile { .subject-mobile {
+65 -17
View File
@@ -119,6 +119,7 @@ const All = () => {
const [postOnHoverHeight, setPostOnHoverHeight] = useState(0); const [postOnHoverHeight, setPostOnHoverHeight] = useState(0);
const [deletePost, setDeletePost] = useState(false); const [deletePost, setDeletePost] = useState(false);
const [moderatorPermissions, setModeratorPermissions] = useState({}); const [moderatorPermissions, setModeratorPermissions] = useState({});
const [moderatorRole, setModeratorRole] = useState({});
const [executeAnonMode, setExecuteAnonMode] = useState(false); const [executeAnonMode, setExecuteAnonMode] = useState(false);
const [cidTracker, setCidTracker] = useState({}); const [cidTracker, setCidTracker] = useState({});
const [isThreadThumbnailClicked, setIsThreadThumbnailClicked] = useState({}); const [isThreadThumbnailClicked, setIsThreadThumbnailClicked] = useState({});
@@ -180,6 +181,7 @@ const All = () => {
useEffect(() => { useEffect(() => {
let permissions = {}; let permissions = {};
let roles = {};
selectedFeed.forEach((thread) => { selectedFeed.forEach((thread) => {
const subplebbit = subplebbits.find((s) => s && s.address === thread.subplebbitAddress); const subplebbit = subplebbits.find((s) => s && s.address === thread.subplebbitAddress);
@@ -192,10 +194,16 @@ const All = () => {
} else { } else {
permissions[thread.subplebbitAddress] = false; permissions[thread.subplebbitAddress] = false;
} }
if (!roles[thread.subplebbitAddress]) {
roles[thread.subplebbitAddress] = {};
}
roles[thread.subplebbitAddress][account?.author.address] = role;
} }
}); });
setModeratorPermissions(permissions); setModeratorPermissions(permissions);
setModeratorRole(roles);
}, [account?.author.address, selectedFeed, subplebbits]); }, [account?.author.address, selectedFeed, subplebbits]);
const handleOptionClick = () => { const handleOptionClick = () => {
@@ -717,7 +725,11 @@ const All = () => {
const { displayedReplies, omittedCount } = filteredRepliesByThread[thread.cid] || {}; const { displayedReplies, omittedCount } = filteredRepliesByThread[thread.cid] || {};
const commentMediaInfo = getCommentMediaInfo(thread); const commentMediaInfo = getCommentMediaInfo(thread);
const fallbackImgUrl = 'assets/filedeleted-res.gif'; const fallbackImgUrl = 'assets/filedeleted-res.gif';
const isModerator = moderatorPermissions[thread.subplebbitAddress]; const canModerate = moderatorPermissions[thread.subplebbitAddress];
const userRole = moderatorRole[thread.subplebbitAddress]?.[thread?.author.address] || 'user';
const isOwner = userRole === 'owner';
const isAdmin = userRole === 'admin';
const isModerator = userRole === 'moderator';
let displayWidth, displayHeight, displayWidthMobile, displayHeightMobile; let displayWidth, displayHeight, displayWidthMobile, displayHeightMobile;
if (thread.linkWidth && thread.linkHeight) { if (thread.linkWidth && thread.linkHeight) {
let scale = Math.min(1, 250 / Math.max(thread.linkWidth, thread.linkHeight)); let scale = Math.min(1, 250 / Math.max(thread.linkWidth, thread.linkHeight));
@@ -897,7 +909,7 @@ const All = () => {
<Fragment key={`fragment3-${index}`}> <Fragment key={`fragment3-${index}`}>
<span <span
key={`n-${index}`} key={`n-${index}`}
className='name' className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
data-tooltip-id='tooltip' data-tooltip-id='tooltip'
data-tooltip-content={thread.author.displayName} data-tooltip-content={thread.author.displayName}
data-tooltip-place='top' data-tooltip-place='top'
@@ -906,15 +918,22 @@ const All = () => {
</span> </span>
</Fragment> </Fragment>
) : ( ) : (
<span key={`n-${index}`} className='name'> <span key={`n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
{thread.author.displayName} {thread.author.displayName}
</span> </span>
) )
) : ( ) : (
<span key={`n-${index}`} className='name'> <span key={`n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
Anonymous Anonymous
</span> </span>
)} )}
{isOwner ? (
<span className='name capcode-admin'>&nbsp;## Board Owner</span>
) : isAdmin ? (
<span className='name capcode-admin'>&nbsp;## Board Admin</span>
) : isModerator ? (
<span className='name capcode'>&nbsp;## Board Mod</span>
) : null}
&nbsp;(u/ &nbsp;(u/
<span <span
key={`pa-${index}`} key={`pa-${index}`}
@@ -1037,7 +1056,7 @@ const All = () => {
<li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li> <li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li>
</> </>
) : null} ) : null}
{isModerator ? ( {canModerate ? (
<> <>
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : ( {authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
<li <li
@@ -1255,6 +1274,10 @@ const All = () => {
} }
const replyMediaInfo = getCommentMediaInfo(reply); const replyMediaInfo = getCommentMediaInfo(reply);
const fallbackImgUrl = 'assets/filedeleted-res.gif'; const fallbackImgUrl = 'assets/filedeleted-res.gif';
const userRole = moderatorRole[reply.subplebbitAddress]?.[reply?.author.address] || 'user';
const isOwner = userRole === 'owner';
const isAdmin = userRole === 'admin';
const isModerator = userRole === 'moderator';
const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed); const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed);
let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {}; let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {};
let signerAddress; let signerAddress;
@@ -1283,7 +1306,7 @@ const All = () => {
<Fragment key={`fragment6-${index}`}> <Fragment key={`fragment6-${index}`}>
<span <span
key={`mob-n-${index}`} key={`mob-n-${index}`}
className='name' className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
data-tooltip-id='tooltip' data-tooltip-id='tooltip'
data-tooltip-content={reply.author.displayName} data-tooltip-content={reply.author.displayName}
data-tooltip-place='top' data-tooltip-place='top'
@@ -1292,15 +1315,22 @@ const All = () => {
</span> </span>
</Fragment> </Fragment>
) : ( ) : (
<span key={`mob-n-${index}`} className='name'> <span key={`mob-n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
{reply.author.displayName} {reply.author.displayName}
</span> </span>
) )
) : ( ) : (
<span key={`mob-n-${index}`} className='name'> <span key={`mob-n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
Anonymous Anonymous
</span> </span>
)} )}
{isOwner ? (
<span className='name capcode-admin'>&nbsp;## Board Owner</span>
) : isAdmin ? (
<span className='name capcode-admin'>&nbsp;## Board Admin</span>
) : isModerator ? (
<span className='name capcode'>&nbsp;## Board Mod</span>
) : null}
&nbsp;(u/ &nbsp;(u/
<span <span
key={`pa-${index}`} key={`pa-${index}`}
@@ -1434,7 +1464,7 @@ const All = () => {
<li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li> <li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li>
</> </>
) : null} ) : null}
{isModerator ? ( {canModerate ? (
<> <>
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : ( {authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
<li <li
@@ -2019,7 +2049,7 @@ const All = () => {
<li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li> <li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li>
</> </>
) : null} ) : null}
{isModerator ? ( {canModerate ? (
<> <>
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : ( {authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
<li <li
@@ -2085,7 +2115,7 @@ const All = () => {
<Fragment key={`fragment9-${index}`}> <Fragment key={`fragment9-${index}`}>
<span <span
key={`mob-n-${index}`} key={`mob-n-${index}`}
className='name-mobile' className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
data-tooltip-id='tooltip' data-tooltip-id='tooltip'
data-tooltip-content={thread.author.displayName} data-tooltip-content={thread.author.displayName}
data-tooltip-place='top' data-tooltip-place='top'
@@ -2094,15 +2124,22 @@ const All = () => {
</span> </span>
</Fragment> </Fragment>
) : ( ) : (
<span key={`mob-n-${index}`} className='name-mobile'> <span key={`mob-n-${index}`} className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
{thread.author.displayName} {thread.author.displayName}
</span> </span>
) )
) : ( ) : (
<span key={`mob-n-${index}`} className='name-mobile'> <span key={`mob-n-${index}`} className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
Anonymous Anonymous
</span> </span>
)} )}
{isOwner ? (
<span className='name capcode-admin'>&nbsp;## Board Owner</span>
) : isAdmin ? (
<span className='name capcode-admin'>&nbsp;## Board Admin</span>
) : isModerator ? (
<span className='name capcode'>&nbsp;## Board Mod</span>
) : null}
&nbsp; &nbsp;
<span <span
key={`mob-pa-${index}`} key={`mob-pa-${index}`}
@@ -2454,6 +2491,10 @@ const All = () => {
} }
const replyMediaInfo = getCommentMediaInfo(reply); const replyMediaInfo = getCommentMediaInfo(reply);
const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed); const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed);
const userRole = moderatorRole[reply.subplebbitAddress]?.[reply?.author.address] || 'user';
const isOwner = userRole === 'owner';
const isAdmin = userRole === 'admin';
const isModerator = userRole === 'moderator';
let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {}; let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {};
let signerAddress; let signerAddress;
if (storedSigners[selectedThreadCidRef]) { if (storedSigners[selectedThreadCidRef]) {
@@ -2512,7 +2553,7 @@ const All = () => {
<li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li> <li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li>
</> </>
) : null} ) : null}
{isModerator ? ( {canModerate ? (
<> <>
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : ( {authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
<li <li
@@ -2578,7 +2619,7 @@ const All = () => {
<Fragment key={`fragment13-${index}`}> <Fragment key={`fragment13-${index}`}>
<span <span
key={`mob-n-${index}`} key={`mob-n-${index}`}
className='name-mobile' className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
data-tooltip-id='tooltip' data-tooltip-id='tooltip'
data-tooltip-content={reply.author.displayName} data-tooltip-content={reply.author.displayName}
data-tooltip-place='top' data-tooltip-place='top'
@@ -2587,15 +2628,22 @@ const All = () => {
</span> </span>
</Fragment> </Fragment>
) : ( ) : (
<span key={`mob-n-${index}`} className='name-mobile'> <span key={`mob-n-${index}`} className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
{reply.author.displayName} {reply.author.displayName}
</span> </span>
) )
) : ( ) : (
<span key={`mob-n-${index}`} className='name-mobile'> <span key={`mob-n-${index}`} className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
Anonymous Anonymous
</span> </span>
)} )}
{isOwner ? (
<span className='name capcode-admin'>&nbsp;## Board Owner</span>
) : isAdmin ? (
<span className='name capcode-admin'>&nbsp;## Board Admin</span>
) : isModerator ? (
<span className='name capcode'>&nbsp;## Board Mod</span>
) : null}
&nbsp; &nbsp;
<span <span
key={`mob-pa-${index}`} key={`mob-pa-${index}`}
+4 -4
View File
@@ -69,7 +69,7 @@ const CatalogPost = ({ post }) => {
const [isImageSearchOpen, setIsImageSearchOpen] = useState(false); const [isImageSearchOpen, setIsImageSearchOpen] = useState(false);
const [isClientRedirectMenuOpen, setIsClientRedirectMenuOpen] = useState(false); const [isClientRedirectMenuOpen, setIsClientRedirectMenuOpen] = useState(false);
const [commentCid, setCommentCid] = useState(null); const [commentCid, setCommentCid] = useState(null);
const [isModerator, setIsModerator] = useState(false); const [canModerate, setCanModerate] = useState(false);
const [, setNewErrorMessage] = useError(); const [, setNewErrorMessage] = useError();
const [, setNewSuccessMessage] = useSuccess(); const [, setNewSuccessMessage] = useSuccess();
@@ -161,9 +161,9 @@ const CatalogPost = ({ post }) => {
const role = subplebbit.roles[account?.author.address]?.role; const role = subplebbit.roles[account?.author.address]?.role;
if (role === 'moderator' || role === 'admin' || role === 'owner') { if (role === 'moderator' || role === 'admin' || role === 'owner') {
setIsModerator(true); setCanModerate(true);
} else { } else {
setIsModerator(false); setCanModerate(false);
} }
} }
}, [account?.author.address, subplebbit.roles]); }, [account?.author.address, subplebbit.roles]);
@@ -573,7 +573,7 @@ const CatalogPost = ({ post }) => {
<li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li> <li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li>
</> </>
) : null} ) : null}
{isModerator ? ( {canModerate ? (
<> <>
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : ( {authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
<li <li
+85 -29
View File
@@ -145,7 +145,7 @@ const Board = () => {
const [deletePost, setDeletePost] = useState(false); const [deletePost, setDeletePost] = useState(false);
const [isImageSearchOpen, setIsImageSearchOpen] = useState(false); const [isImageSearchOpen, setIsImageSearchOpen] = useState(false);
const [isClientRedirectMenuOpen, setIsClientRedirectMenuOpen] = useState(false); const [isClientRedirectMenuOpen, setIsClientRedirectMenuOpen] = useState(false);
const [isModerator, setIsModerator] = useState(false); const [canModerate, setCanModerate] = useState(false);
const [commentCid, setCommentCid] = useState(null); const [commentCid, setCommentCid] = useState(null);
const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 }); const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 });
const [mobileMenuPosition, setMobileMenuPosition] = useState({ top: 0, left: 0 }); const [mobileMenuPosition, setMobileMenuPosition] = useState({ top: 0, left: 0 });
@@ -177,12 +177,12 @@ const Board = () => {
useEffect(() => { useEffect(() => {
if (subplebbit?.roles !== undefined) { if (subplebbit?.roles !== undefined) {
const role = subplebbit?.roles[account?.author.address]?.role; const role = subplebbit?.roles?.[account?.author.address]?.role;
if (role === 'moderator' || role === 'admin' || role === 'owner') { if (role === 'moderator' || role === 'admin' || role === 'owner') {
setIsModerator(true); setCanModerate(true);
} else { } else {
setIsModerator(false); setCanModerate(false);
} }
} }
}, [account?.author.address, subplebbit?.roles]); }, [account?.author.address, subplebbit?.roles]);
@@ -463,11 +463,6 @@ const Board = () => {
const handleSubmit = async (event) => { const handleSubmit = async (event) => {
event.preventDefault(); event.preventDefault();
if (subjectRef.current.value === '') {
setNewErrorMessage('Subject field is mandatory');
return;
}
setPublishCommentOptions((prevPublishCommentOptions) => ({ setPublishCommentOptions((prevPublishCommentOptions) => ({
...prevPublishCommentOptions, ...prevPublishCommentOptions,
author: { author: {
@@ -933,7 +928,7 @@ const Board = () => {
> >
Catalog Catalog
</Link> </Link>
]{subplebbit.roles && subplebbit?.roles[account?.author?.address]?.role === 'admin' ? <BoardSettings subplebbit={subplebbit} /> : null} ]{subplebbit.roles && subplebbit?.roles?.[account?.author?.address]?.role === 'admin' ? <BoardSettings subplebbit={subplebbit} /> : null}
</div> </div>
{subplebbit?.state === 'succeeded' ? ( {subplebbit?.state === 'succeeded' ? (
<> <>
@@ -1039,7 +1034,7 @@ const Board = () => {
> >
<div className={`post-menu-thread post-menu-thread-${'rules'}`} style={{ display: openMenuCid === 'rules' ? 'block' : 'none' }}> <div className={`post-menu-thread post-menu-thread-${'rules'}`} style={{ display: openMenuCid === 'rules' ? 'block' : 'none' }}>
<ul className='post-menu-catalog'> <ul className='post-menu-catalog'>
{/* {isModerator ? ( {/* {canModerate ? (
<> <>
change rules change rules
</> </>
@@ -1264,7 +1259,7 @@ const Board = () => {
> >
<div className={`post-menu-thread post-menu-thread-${'rules'}`} style={{ display: openMenuCid === 'rules' ? 'block' : 'none' }}> <div className={`post-menu-thread post-menu-thread-${'rules'}`} style={{ display: openMenuCid === 'rules' ? 'block' : 'none' }}>
<ul className='post-menu-catalog'> <ul className='post-menu-catalog'>
{/* {isModerator ? ( {/* {canModerate ? (
<> <>
change rules change rules
</> </>
@@ -1509,7 +1504,7 @@ const Board = () => {
style={{ display: openMenuCid === subplebbit.pubsubTopic ? 'block' : 'none' }} style={{ display: openMenuCid === subplebbit.pubsubTopic ? 'block' : 'none' }}
> >
<ul className='post-menu-catalog'> <ul className='post-menu-catalog'>
{/* {isModerator ? ( {/* {canModerate ? (
<> <>
change description change description
</> </>
@@ -1744,6 +1739,9 @@ const Board = () => {
const { displayedReplies, omittedCount } = filteredRepliesByThread[thread.cid] || {}; const { displayedReplies, omittedCount } = filteredRepliesByThread[thread.cid] || {};
const commentMediaInfo = getCommentMediaInfo(thread); const commentMediaInfo = getCommentMediaInfo(thread);
const fallbackImgUrl = 'assets/filedeleted-res.gif'; const fallbackImgUrl = 'assets/filedeleted-res.gif';
const isOwner = subplebbit?.roles?.[thread.author.address]?.role === 'owner';
const isAdmin = subplebbit?.roles?.[thread.author.address]?.role === 'admin';
const isModerator = subplebbit?.roles?.[thread.author.address]?.role === 'moderator';
let displayWidth, displayHeight, displayWidthMobile, displayHeightMobile; let displayWidth, displayHeight, displayWidthMobile, displayHeightMobile;
if (thread.linkWidth && thread.linkHeight) { if (thread.linkWidth && thread.linkHeight) {
let scale = Math.min(1, 250 / Math.max(thread.linkWidth, thread.linkHeight)); let scale = Math.min(1, 250 / Math.max(thread.linkWidth, thread.linkHeight));
@@ -1923,7 +1921,7 @@ const Board = () => {
<Fragment key={`fragment3-${index}`}> <Fragment key={`fragment3-${index}`}>
<span <span
key={`n-${index}`} key={`n-${index}`}
className='name' className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
data-tooltip-id='tooltip' data-tooltip-id='tooltip'
data-tooltip-content={thread.author.displayName} data-tooltip-content={thread.author.displayName}
data-tooltip-place='top' data-tooltip-place='top'
@@ -1932,15 +1930,28 @@ const Board = () => {
</span> </span>
</Fragment> </Fragment>
) : ( ) : (
<span key={`n-${index}`} className='name'> <span key={`n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
{thread.author.displayName} {thread.author.displayName}
</span> </span>
) )
) : ( ) : (
<span key={`n-${index}`} className='name'> <span key={`n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
Anonymous Anonymous
</span> </span>
)} )}
{isOwner ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
&nbsp;## Board Owner
</span>
) : isAdmin ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
&nbsp;## Board Admin
</span>
) : isModerator ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode'>
&nbsp;## Board Mod
</span>
) : null}
&nbsp;(u/ &nbsp;(u/
<span <span
key={`pa-${index}`} key={`pa-${index}`}
@@ -2080,7 +2091,7 @@ const Board = () => {
<li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li> <li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li>
</> </>
) : null} ) : null}
{isModerator ? ( {canModerate ? (
<> <>
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : ( {authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
<li <li
@@ -2299,6 +2310,9 @@ const Board = () => {
} }
const replyMediaInfo = getCommentMediaInfo(reply); const replyMediaInfo = getCommentMediaInfo(reply);
const fallbackImgUrl = 'assets/filedeleted-res.gif'; const fallbackImgUrl = 'assets/filedeleted-res.gif';
const isOwner = subplebbit?.roles?.[reply.author.address]?.role === 'owner';
const isAdmin = subplebbit?.roles?.[reply.author.address]?.role === 'admin';
const isModerator = subplebbit?.roles?.[reply.author.address]?.role === 'moderator';
const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed); const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed);
let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {}; let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {};
let signerAddress; let signerAddress;
@@ -2328,7 +2342,7 @@ const Board = () => {
<Fragment key={`fragment6-${index}`}> <Fragment key={`fragment6-${index}`}>
<span <span
key={`mob-n-${index}`} key={`mob-n-${index}`}
className='name' className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
data-tooltip-id='tooltip' data-tooltip-id='tooltip'
data-tooltip-content={reply.author.displayName} data-tooltip-content={reply.author.displayName}
data-tooltip-place='top' data-tooltip-place='top'
@@ -2337,15 +2351,28 @@ const Board = () => {
</span> </span>
</Fragment> </Fragment>
) : ( ) : (
<span key={`mob-n-${index}`} className='name'> <span key={`mob-n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
{reply.author.displayName} {reply.author.displayName}
</span> </span>
) )
) : ( ) : (
<span key={`mob-n-${index}`} className='name'> <span key={`mob-n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
Anonymous Anonymous
</span> </span>
)} )}
{isOwner ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
&nbsp;## Board Owner
</span>
) : isAdmin ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
&nbsp;## Board Admin
</span>
) : isModerator ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode'>
&nbsp;## Board Mod
</span>
) : null}
&nbsp;(u/ &nbsp;(u/
<span <span
key={`pa-${index}`} key={`pa-${index}`}
@@ -2465,7 +2492,7 @@ const Board = () => {
<li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li> <li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li>
</> </>
) : null} ) : null}
{isModerator ? ( {canModerate ? (
<> <>
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : ( {authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
<li <li
@@ -3057,7 +3084,7 @@ const Board = () => {
<li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li> <li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li>
</> </>
) : null} ) : null}
{isModerator ? ( {canModerate ? (
<> <>
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : ( {authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
<li <li
@@ -3139,7 +3166,7 @@ const Board = () => {
<Fragment key={`fragment9-${index}`}> <Fragment key={`fragment9-${index}`}>
<span <span
key={`mob-n-${index}`} key={`mob-n-${index}`}
className='name-mobile' className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
data-tooltip-id='tooltip' data-tooltip-id='tooltip'
data-tooltip-content={thread.author.displayName} data-tooltip-content={thread.author.displayName}
data-tooltip-place='top' data-tooltip-place='top'
@@ -3148,15 +3175,28 @@ const Board = () => {
</span> </span>
</Fragment> </Fragment>
) : ( ) : (
<span key={`mob-n-${index}`} className='name-mobile'> <span key={`mob-n-${index}`} className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
{thread.author.displayName} {thread.author.displayName}
</span> </span>
) )
) : ( ) : (
<span key={`mob-n-${index}`} className='name-mobile'> <span key={`mob-n-${index}`} className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
Anonymous Anonymous
</span> </span>
)} )}
{isOwner ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
&nbsp;## Board Owner
</span>
) : isAdmin ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
&nbsp;## Board Admin
</span>
) : isModerator ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode'>
&nbsp;## Board Mod
</span>
) : null}
&nbsp; &nbsp;
<span <span
key={`mob-pa-${index}`} key={`mob-pa-${index}`}
@@ -3504,6 +3544,9 @@ const Board = () => {
{displayedReplies?.map((reply, index) => { {displayedReplies?.map((reply, index) => {
const replyMediaInfo = getCommentMediaInfo(reply); const replyMediaInfo = getCommentMediaInfo(reply);
const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed); const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed);
const isOwner = subplebbit?.roles?.[reply.author.address]?.role === 'owner';
const isAdmin = subplebbit?.roles?.[reply.author.address]?.role === 'admin';
const isModerator = subplebbit?.roles?.[reply.author.address]?.role === 'moderator';
let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {}; let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {};
let signerAddress; let signerAddress;
if (storedSigners[selectedThreadCidRef]) { if (storedSigners[selectedThreadCidRef]) {
@@ -3562,7 +3605,7 @@ const Board = () => {
<li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li> <li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li>
</> </>
) : null} ) : null}
{isModerator ? ( {canModerate ? (
<> <>
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : ( {authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
<li <li
@@ -3644,7 +3687,7 @@ const Board = () => {
<Fragment key={`fragment13-${index}`}> <Fragment key={`fragment13-${index}`}>
<span <span
key={`mob-n-${index}`} key={`mob-n-${index}`}
className='name-mobile' className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
data-tooltip-id='tooltip' data-tooltip-id='tooltip'
data-tooltip-content={reply.author.displayName} data-tooltip-content={reply.author.displayName}
data-tooltip-place='top' data-tooltip-place='top'
@@ -3653,15 +3696,28 @@ const Board = () => {
</span> </span>
</Fragment> </Fragment>
) : ( ) : (
<span key={`mob-n-${index}`} className='name-mobile'> <span key={`mob-n-${index}`} className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
{reply.author.displayName} {reply.author.displayName}
</span> </span>
) )
) : ( ) : (
<span key={`mob-n-${index}`} className='name-mobile'> <span key={`mob-n-${index}`} className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
Anonymous Anonymous
</span> </span>
)} )}
{isOwner ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
&nbsp;## Board Owner
</span>
) : isAdmin ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
&nbsp;## Board Admin
</span>
) : isModerator ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode'>
&nbsp;## Board Mod
</span>
) : null}
&nbsp; &nbsp;
<span <span
key={`mob-pa-${index}`} key={`mob-pa-${index}`}
+8 -13
View File
@@ -52,7 +52,7 @@ const CatalogPost = ({ post }) => {
setIsAuthorEdit, setIsAuthorEdit,
setIsCaptchaOpen, setIsCaptchaOpen,
setIsEditModalOpen, setIsEditModalOpen,
isModerator, canModerate,
setModeratingCommentCid, setModeratingCommentCid,
setOriginalCommentContent, setOriginalCommentContent,
setPendingComment, setPendingComment,
@@ -443,7 +443,7 @@ const CatalogPost = ({ post }) => {
> >
<div className={`post-menu-thread post-menu-thread-${'rules'}`} style={{ display: openMenuCid === 'rules' ? 'block' : 'none' }}> <div className={`post-menu-thread post-menu-thread-${'rules'}`} style={{ display: openMenuCid === 'rules' ? 'block' : 'none' }}>
<ul className='post-menu-catalog'> <ul className='post-menu-catalog'>
{/* {isModerator ? ( {/* {canModerate ? (
<> <>
change rules change rules
</> </>
@@ -647,7 +647,7 @@ const CatalogPost = ({ post }) => {
> >
<div className={`post-menu-thread post-menu-thread-${'description'}`} style={{ display: openMenuCid === 'description' ? 'block' : 'none' }}> <div className={`post-menu-thread post-menu-thread-${'description'}`} style={{ display: openMenuCid === 'description' ? 'block' : 'none' }}>
<ul className='post-menu-catalog'> <ul className='post-menu-catalog'>
{/* {isModerator ? ( {/* {canModerate ? (
<> <>
change description change description
</> </>
@@ -999,7 +999,7 @@ const CatalogPost = ({ post }) => {
<li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li> <li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li>
</> </>
) : null} ) : null}
{isModerator ? ( {canModerate ? (
<> <>
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : ( {authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
<li <li
@@ -1133,7 +1133,7 @@ const Catalog = () => {
setIsCaptchaOpen, setIsCaptchaOpen,
isModerationOpen, isModerationOpen,
setIsModerationOpen, setIsModerationOpen,
setIsModerator, setCanModerate,
isSettingsOpen, isSettingsOpen,
setIsSettingsOpen, setIsSettingsOpen,
originalCommentContent, originalCommentContent,
@@ -1198,12 +1198,12 @@ const Catalog = () => {
const role = subplebbit.roles[account?.author.address]?.role; const role = subplebbit.roles[account?.author.address]?.role;
if (role === 'moderator' || role === 'admin' || role === 'owner') { if (role === 'moderator' || role === 'admin' || role === 'owner') {
setIsModerator(true); setCanModerate(true);
} else { } else {
setIsModerator(false); setCanModerate(false);
} }
} }
}, [account?.author.address, subplebbit.roles, setIsModerator]); }, [account?.author.address, subplebbit.roles, setCanModerate]);
useEffect(() => { useEffect(() => {
setSelectedAddress(subplebbitAddress); setSelectedAddress(subplebbitAddress);
@@ -1328,11 +1328,6 @@ const Catalog = () => {
const handleSubmit = async (event) => { const handleSubmit = async (event) => {
event.preventDefault(); event.preventDefault();
if (subjectRef.current.value === '') {
setNewErrorMessage('Subject field is mandatory');
return;
}
setPublishCommentOptions((prevPublishCommentOptions) => ({ setPublishCommentOptions((prevPublishCommentOptions) => ({
...prevPublishCommentOptions, ...prevPublishCommentOptions,
author: { author: {
+1 -1
View File
@@ -427,7 +427,7 @@ const Description = () => {
style={{ display: openMenuCid === subplebbit.pubsubTopic ? 'block' : 'none' }} style={{ display: openMenuCid === subplebbit.pubsubTopic ? 'block' : 'none' }}
> >
<ul className='post-menu-catalog'> <ul className='post-menu-catalog'>
{/* {isModerator ? ( {/* {canModerate ? (
<> <>
change description change description
</> </>
+1 -1
View File
@@ -412,7 +412,7 @@ const Rules = () => {
> >
<div className={`post-menu-thread post-menu-thread-${'rules'}`} style={{ display: openMenuCid === 'rules' ? 'block' : 'none' }}> <div className={`post-menu-thread post-menu-thread-${'rules'}`} style={{ display: openMenuCid === 'rules' ? 'block' : 'none' }}>
<ul className='post-menu-catalog'> <ul className='post-menu-catalog'>
{/* {isModerator ? ( {/* {canModerate ? (
<> <>
change rules change rules
</> </>
+65 -17
View File
@@ -119,6 +119,7 @@ const Subscriptions = () => {
const [postOnHoverHeight, setPostOnHoverHeight] = useState(0); const [postOnHoverHeight, setPostOnHoverHeight] = useState(0);
const [deletePost, setDeletePost] = useState(false); const [deletePost, setDeletePost] = useState(false);
const [moderatorPermissions, setModeratorPermissions] = useState({}); const [moderatorPermissions, setModeratorPermissions] = useState({});
const [moderatorRole, setModeratorRole] = useState({});
const [executeAnonMode, setExecuteAnonMode] = useState(false); const [executeAnonMode, setExecuteAnonMode] = useState(false);
const [cidTracker, setCidTracker] = useState({}); const [cidTracker, setCidTracker] = useState({});
const [isThreadThumbnailClicked, setIsThreadThumbnailClicked] = useState({}); const [isThreadThumbnailClicked, setIsThreadThumbnailClicked] = useState({});
@@ -179,6 +180,7 @@ const Subscriptions = () => {
useEffect(() => { useEffect(() => {
let permissions = {}; let permissions = {};
let roles = {};
selectedFeed.forEach((thread) => { selectedFeed.forEach((thread) => {
const subplebbit = subplebbits.find((s) => s && s.address === thread.subplebbitAddress); const subplebbit = subplebbits.find((s) => s && s.address === thread.subplebbitAddress);
@@ -191,10 +193,16 @@ const Subscriptions = () => {
} else { } else {
permissions[thread.subplebbitAddress] = false; permissions[thread.subplebbitAddress] = false;
} }
if (!roles[thread.subplebbitAddress]) {
roles[thread.subplebbitAddress] = {};
}
roles[thread.subplebbitAddress][account?.author.address] = role;
} }
}); });
setModeratorPermissions(permissions); setModeratorPermissions(permissions);
setModeratorRole(roles);
}, [account?.author.address, selectedFeed, subplebbits]); }, [account?.author.address, selectedFeed, subplebbits]);
const handleOptionClick = () => { const handleOptionClick = () => {
@@ -721,7 +729,11 @@ const Subscriptions = () => {
const { displayedReplies, omittedCount } = filteredRepliesByThread[thread.cid] || {}; const { displayedReplies, omittedCount } = filteredRepliesByThread[thread.cid] || {};
const commentMediaInfo = getCommentMediaInfo(thread); const commentMediaInfo = getCommentMediaInfo(thread);
const fallbackImgUrl = 'assets/filedeleted-res.gif'; const fallbackImgUrl = 'assets/filedeleted-res.gif';
const isModerator = moderatorPermissions[thread.subplebbitAddress]; const canModerate = moderatorPermissions[thread.subplebbitAddress];
const userRole = moderatorRole[thread.subplebbitAddress]?.[thread?.author.address] || 'user';
const isOwner = userRole === 'owner';
const isAdmin = userRole === 'admin';
const isModerator = userRole === 'moderator';
let displayWidth, displayHeight, displayWidthMobile, displayHeightMobile; let displayWidth, displayHeight, displayWidthMobile, displayHeightMobile;
if (thread.linkWidth && thread.linkHeight) { if (thread.linkWidth && thread.linkHeight) {
let scale = Math.min(1, 250 / Math.max(thread.linkWidth, thread.linkHeight)); let scale = Math.min(1, 250 / Math.max(thread.linkWidth, thread.linkHeight));
@@ -901,7 +913,7 @@ const Subscriptions = () => {
<Fragment key={`fragment3-${index}`}> <Fragment key={`fragment3-${index}`}>
<span <span
key={`n-${index}`} key={`n-${index}`}
className='name' className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
data-tooltip-id='tooltip' data-tooltip-id='tooltip'
data-tooltip-content={thread.author.displayName} data-tooltip-content={thread.author.displayName}
data-tooltip-place='top' data-tooltip-place='top'
@@ -910,15 +922,22 @@ const Subscriptions = () => {
</span> </span>
</Fragment> </Fragment>
) : ( ) : (
<span key={`n-${index}`} className='name'> <span key={`n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
{thread.author.displayName} {thread.author.displayName}
</span> </span>
) )
) : ( ) : (
<span key={`n-${index}`} className='name'> <span key={`n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
Anonymous Anonymous
</span> </span>
)} )}
{isOwner ? (
<span className='name capcode-admin'>&nbsp;## Board Owner</span>
) : isAdmin ? (
<span className='name capcode-admin'>&nbsp;## Board Admin</span>
) : isModerator ? (
<span className='name capcode'>&nbsp;## Board Mod</span>
) : null}
&nbsp;(u/ &nbsp;(u/
<span <span
key={`pa-${index}`} key={`pa-${index}`}
@@ -1047,7 +1066,7 @@ const Subscriptions = () => {
<li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li> <li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li>
</> </>
) : null} ) : null}
{isModerator ? ( {canModerate ? (
<> <>
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : ( {authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
<li <li
@@ -1265,6 +1284,10 @@ const Subscriptions = () => {
} }
const replyMediaInfo = getCommentMediaInfo(reply); const replyMediaInfo = getCommentMediaInfo(reply);
const fallbackImgUrl = 'assets/filedeleted-res.gif'; const fallbackImgUrl = 'assets/filedeleted-res.gif';
const userRole = moderatorRole[reply.subplebbitAddress]?.[reply?.author.address] || 'user';
const isOwner = userRole === 'owner';
const isAdmin = userRole === 'admin';
const isModerator = userRole === 'moderator';
const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed); const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed);
let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {}; let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {};
let signerAddress; let signerAddress;
@@ -1293,7 +1316,7 @@ const Subscriptions = () => {
<Fragment key={`fragment6-${index}`}> <Fragment key={`fragment6-${index}`}>
<span <span
key={`mob-n-${index}`} key={`mob-n-${index}`}
className='name' className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
data-tooltip-id='tooltip' data-tooltip-id='tooltip'
data-tooltip-content={reply.author.displayName} data-tooltip-content={reply.author.displayName}
data-tooltip-place='top' data-tooltip-place='top'
@@ -1302,15 +1325,22 @@ const Subscriptions = () => {
</span> </span>
</Fragment> </Fragment>
) : ( ) : (
<span key={`mob-n-${index}`} className='name'> <span key={`mob-n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
{reply.author.displayName} {reply.author.displayName}
</span> </span>
) )
) : ( ) : (
<span key={`mob-n-${index}`} className='name'> <span key={`mob-n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
Anonymous Anonymous
</span> </span>
)} )}
{isOwner ? (
<span className='name capcode-admin'>&nbsp;## Board Owner</span>
) : isAdmin ? (
<span className='name capcode-admin'>&nbsp;## Board Admin</span>
) : isModerator ? (
<span className='name capcode'>&nbsp;## Board Mod</span>
) : null}
&nbsp;(u/ &nbsp;(u/
<span <span
key={`pa-${index}`} key={`pa-${index}`}
@@ -1444,7 +1474,7 @@ const Subscriptions = () => {
<li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li> <li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li>
</> </>
) : null} ) : null}
{isModerator ? ( {canModerate ? (
<> <>
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : ( {authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
<li <li
@@ -2029,7 +2059,7 @@ const Subscriptions = () => {
<li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li> <li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li>
</> </>
) : null} ) : null}
{isModerator ? ( {canModerate ? (
<> <>
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : ( {authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
<li <li
@@ -2095,7 +2125,7 @@ const Subscriptions = () => {
<Fragment key={`fragment9-${index}`}> <Fragment key={`fragment9-${index}`}>
<span <span
key={`mob-n-${index}`} key={`mob-n-${index}`}
className='name-mobile' className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
data-tooltip-id='tooltip' data-tooltip-id='tooltip'
data-tooltip-content={thread.author.displayName} data-tooltip-content={thread.author.displayName}
data-tooltip-place='top' data-tooltip-place='top'
@@ -2104,15 +2134,22 @@ const Subscriptions = () => {
</span> </span>
</Fragment> </Fragment>
) : ( ) : (
<span key={`mob-n-${index}`} className='name-mobile'> <span key={`mob-n-${index}`} className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
{thread.author.displayName} {thread.author.displayName}
</span> </span>
) )
) : ( ) : (
<span key={`mob-n-${index}`} className='name-mobile'> <span key={`mob-n-${index}`} className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
Anonymous Anonymous
</span> </span>
)} )}
{isOwner ? (
<span className='name capcode-admin'>&nbsp;## Board Owner</span>
) : isAdmin ? (
<span className='name capcode-admin'>&nbsp;## Board Admin</span>
) : isModerator ? (
<span className='name capcode'>&nbsp;## Board Mod</span>
) : null}
&nbsp; &nbsp;
<span <span
key={`mob-pa-${index}`} key={`mob-pa-${index}`}
@@ -2464,6 +2501,10 @@ const Subscriptions = () => {
} }
const replyMediaInfo = getCommentMediaInfo(reply); const replyMediaInfo = getCommentMediaInfo(reply);
const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed); const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed);
const userRole = moderatorRole[reply.subplebbitAddress]?.[reply?.author.address] || 'user';
const isOwner = userRole === 'owner';
const isAdmin = userRole === 'admin';
const isModerator = userRole === 'moderator';
let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {}; let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {};
let signerAddress; let signerAddress;
if (storedSigners[selectedThreadCidRef]) { if (storedSigners[selectedThreadCidRef]) {
@@ -2522,7 +2563,7 @@ const Subscriptions = () => {
<li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li> <li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li>
</> </>
) : null} ) : null}
{isModerator ? ( {canModerate ? (
<> <>
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : ( {authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
<li <li
@@ -2588,7 +2629,7 @@ const Subscriptions = () => {
<Fragment key={`fragment13-${index}`}> <Fragment key={`fragment13-${index}`}>
<span <span
key={`mob-n-${index}`} key={`mob-n-${index}`}
className='name-mobile' className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
data-tooltip-id='tooltip' data-tooltip-id='tooltip'
data-tooltip-content={reply.author.displayName} data-tooltip-content={reply.author.displayName}
data-tooltip-place='top' data-tooltip-place='top'
@@ -2597,15 +2638,22 @@ const Subscriptions = () => {
</span> </span>
</Fragment> </Fragment>
) : ( ) : (
<span key={`mob-n-${index}`} className='name-mobile'> <span key={`mob-n-${index}`} className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
{reply.author.displayName} {reply.author.displayName}
</span> </span>
) )
) : ( ) : (
<span key={`mob-n-${index}`} className='name-mobile'> <span key={`mob-n-${index}`} className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
Anonymous Anonymous
</span> </span>
)} )}
{isOwner ? (
<span className='name capcode-admin'>&nbsp;## Board Owner</span>
) : isAdmin ? (
<span className='name capcode-admin'>&nbsp;## Board Admin</span>
) : isModerator ? (
<span className='name capcode'>&nbsp;## Board Mod</span>
) : null}
&nbsp; &nbsp;
<span <span
key={`mob-pa-${index}`} key={`mob-pa-${index}`}
@@ -69,7 +69,7 @@ const CatalogPost = ({ post }) => {
const [isImageSearchOpen, setIsImageSearchOpen] = useState(false); const [isImageSearchOpen, setIsImageSearchOpen] = useState(false);
const [isClientRedirectMenuOpen, setIsClientRedirectMenuOpen] = useState(false); const [isClientRedirectMenuOpen, setIsClientRedirectMenuOpen] = useState(false);
const [commentCid, setCommentCid] = useState(null); const [commentCid, setCommentCid] = useState(null);
const [isModerator, setIsModerator] = useState(false); const [canModerate, setCanModerate] = useState(false);
const [, setNewErrorMessage] = useError(); const [, setNewErrorMessage] = useError();
const [, setNewSuccessMessage] = useSuccess(); const [, setNewSuccessMessage] = useSuccess();
@@ -161,9 +161,9 @@ const CatalogPost = ({ post }) => {
const role = subplebbit.roles[account?.author.address]?.role; const role = subplebbit.roles[account?.author.address]?.role;
if (role === 'moderator' || role === 'admin' || role === 'owner') { if (role === 'moderator' || role === 'admin' || role === 'owner') {
setIsModerator(true); setCanModerate(true);
} else { } else {
setIsModerator(false); setCanModerate(false);
} }
} }
}, [account?.author.address, subplebbit.roles]); }, [account?.author.address, subplebbit.roles]);
@@ -573,7 +573,7 @@ const CatalogPost = ({ post }) => {
<li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li> <li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li>
</> </>
) : null} ) : null}
{isModerator ? ( {canModerate ? (
<> <>
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : ( {authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
<li <li
+77 -13
View File
@@ -23,6 +23,7 @@ import PostOnHover from '../PostOnHover';
import StateLabel from '../StateLabel'; import StateLabel from '../StateLabel';
import VerifiedAuthor from '../VerifiedAuthor'; import VerifiedAuthor from '../VerifiedAuthor';
import CreateBoardModal from '../modals/CreateBoardModal'; import CreateBoardModal from '../modals/CreateBoardModal';
import AdminListModal from '../modals/AdminListModal';
import EditModal from '../modals/EditModal'; import EditModal from '../modals/EditModal';
import ModerationModal from '../modals/ModerationModal'; import ModerationModal from '../modals/ModerationModal';
import ReplyModal from '../modals/ReplyModal'; import ReplyModal from '../modals/ReplyModal';
@@ -119,7 +120,7 @@ const Thread = () => {
const [visible, setVisible] = useState(true); const [visible, setVisible] = useState(true);
const [isImageSearchOpen, setIsImageSearchOpen] = useState(false); const [isImageSearchOpen, setIsImageSearchOpen] = useState(false);
const [isClientRedirectMenuOpen, setIsClientRedirectMenuOpen] = useState(false); const [isClientRedirectMenuOpen, setIsClientRedirectMenuOpen] = useState(false);
const [isModerator, setIsModerator] = useState(false); const [canModerate, setCanModerate] = useState(false);
const [commentCid, setCommentCid] = useState(null); const [commentCid, setCommentCid] = useState(null);
const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 }); const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 });
const [mobileMenuPosition, setMobileMenuPosition] = useState({ top: 0, left: 0 }); const [mobileMenuPosition, setMobileMenuPosition] = useState({ top: 0, left: 0 });
@@ -138,11 +139,15 @@ const Thread = () => {
useAnonMode(selectedThread, anonymousMode && executeAnonMode); useAnonMode(selectedThread, anonymousMode && executeAnonMode);
const [isAdminListOpen, setIsAdminListOpen] = useState(false);
const originalComment = useComment({ commentCid: selectedThread }); const originalComment = useComment({ commentCid: selectedThread });
const [comment, setComment] = useState(originalComment); const [comment, setComment] = useState(originalComment);
const { subplebbitAddress, threadCid } = useParams(); const { subplebbitAddress, threadCid } = useParams();
const subplebbit = useSubplebbit({ subplebbitAddress: originalComment.subplebbitAddress }); const subplebbit = useSubplebbit({ subplebbitAddress: originalComment.subplebbitAddress });
const selectedAddress = subplebbit.address; const selectedAddress = subplebbit.address;
const isOwner = subplebbit?.roles?.[comment.author?.address]?.role === 'owner';
const isAdmin = subplebbit?.roles?.[comment.author?.address]?.role === 'admin';
const isModerator = subplebbit?.roles?.[comment.author?.address]?.role === 'moderator';
const stateString = useStateString(comment); const stateString = useStateString(comment);
@@ -200,9 +205,9 @@ const Thread = () => {
const role = subplebbit.roles[account?.author?.address]?.role; const role = subplebbit.roles[account?.author?.address]?.role;
if (role === 'moderator' || role === 'admin' || role === 'owner') { if (role === 'moderator' || role === 'admin' || role === 'owner') {
setIsModerator(true); setCanModerate(true);
} else { } else {
setIsModerator(false); setCanModerate(false);
} }
} }
}, [account?.author.address, subplebbit.roles]); }, [account?.author.address, subplebbit.roles]);
@@ -642,6 +647,7 @@ const Thread = () => {
</title> </title>
</Helmet> </Helmet>
<Container> <Container>
<AdminListModal selectedStyle={selectedStyle} isOpen={isAdminListOpen} closeModal={() => setIsAdminListOpen(false)} roles={subplebbit?.roles} />
<CreateBoardModal selectedStyle={selectedStyle} isOpen={isCreateBoardOpen} closeModal={() => setIsCreateBoardOpen(false)} /> <CreateBoardModal selectedStyle={selectedStyle} isOpen={isCreateBoardOpen} closeModal={() => setIsCreateBoardOpen(false)} />
<ReplyModal selectedStyle={selectedStyle} isOpen={isReplyOpen} closeModal={() => setIsReplyOpen(false)} /> <ReplyModal selectedStyle={selectedStyle} isOpen={isReplyOpen} closeModal={() => setIsReplyOpen(false)} />
<SettingsModal selectedStyle={selectedStyle} isOpen={isSettingsOpen} closeModal={() => setIsSettingsOpen(false)} /> <SettingsModal selectedStyle={selectedStyle} isOpen={isSettingsOpen} closeModal={() => setIsSettingsOpen(false)} />
@@ -1078,7 +1084,7 @@ const Thread = () => {
<> <>
<span <span
key={`n-${comment.cid}`} key={`n-${comment.cid}`}
className='name' className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
data-tooltip-id='tooltip' data-tooltip-id='tooltip'
data-tooltip-content={comment?.author?.displayName} data-tooltip-content={comment?.author?.displayName}
data-tooltip-place='top' data-tooltip-place='top'
@@ -1087,15 +1093,28 @@ const Thread = () => {
</span> </span>
</> </>
) : ( ) : (
<span key={`n-${comment.cid}`} className='name'> <span key={`n-${comment.cid}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
{comment?.author?.displayName} {comment?.author?.displayName}
</span> </span>
) )
) : ( ) : (
<span key={`n-${comment.cid}`} className='name'> <span key={`n-${comment.cid}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
Anonymous Anonymous
</span> </span>
)} )}
{isOwner ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
&nbsp;## Board Owner
</span>
) : isAdmin ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
&nbsp;## Board Admin
</span>
) : isModerator ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode'>
&nbsp;## Board Mod
</span>
) : null}
&nbsp; &nbsp;
<span <span
className='poster-address address-desktop' className='poster-address address-desktop'
@@ -1205,7 +1224,7 @@ const Thread = () => {
<li onClick={() => handleAuthorDeleteClick(comment)}>Delete post</li> <li onClick={() => handleAuthorDeleteClick(comment)}>Delete post</li>
</> </>
) : null} ) : null}
{isModerator ? ( {canModerate ? (
<> <>
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : ( {authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
<li <li
@@ -1375,6 +1394,9 @@ const Thread = () => {
} }
const replyMediaInfo = getCommentMediaInfo(reply); const replyMediaInfo = getCommentMediaInfo(reply);
const fallbackImgUrl = 'assets/filedeleted-res.gif'; const fallbackImgUrl = 'assets/filedeleted-res.gif';
const isReplyOwner = subplebbit?.roles?.[reply.author.address]?.role === 'owner';
const isReplyAdmin = subplebbit?.roles?.[reply.author.address]?.role === 'admin';
const isReplyModerator = subplebbit?.roles?.[reply.author.address]?.role === 'moderator';
const shortParentCid = findShortParentCid(reply.parentCid, comment); const shortParentCid = findShortParentCid(reply.parentCid, comment);
let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {}; let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {};
let signerAddress; let signerAddress;
@@ -1404,7 +1426,7 @@ const Thread = () => {
<> <>
<span <span
key={`mob-n-${index}`} key={`mob-n-${index}`}
className='name' className={`name ${isReplyAdmin || isReplyOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
data-tooltip-id='tooltip' data-tooltip-id='tooltip'
data-tooltip-content={reply.author?.displayName} data-tooltip-content={reply.author?.displayName}
data-tooltip-place='top' data-tooltip-place='top'
@@ -1413,15 +1435,28 @@ const Thread = () => {
</span> </span>
</> </>
) : ( ) : (
<span key={`mob-n-${index}`} className='name'> <span key={`mob-n-${index}`} className={`name ${isReplyAdmin || isReplyOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
{reply.author?.displayName ?? reply.displayName} {reply.author?.displayName ?? reply.displayName}
</span> </span>
) )
) : ( ) : (
<span key={`mob-n-${index}`} className='name'> <span key={`mob-n-${index}`} className={`name ${isReplyAdmin || isReplyOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
Anonymous Anonymous
</span> </span>
)} )}
{isReplyOwner ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
&nbsp;## Board Owner
</span>
) : isReplyAdmin ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
&nbsp;## Board Admin
</span>
) : isReplyModerator ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode'>
&nbsp;## Board Mod
</span>
) : null}
&nbsp;(u/ &nbsp;(u/
<span <span
key={`pa-${index}`} key={`pa-${index}`}
@@ -1531,7 +1566,7 @@ const Thread = () => {
<li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li> <li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li>
</> </>
) : null} ) : null}
{isModerator ? ( {canModerate ? (
<> <>
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : ( {authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
<li <li
@@ -1986,7 +2021,7 @@ const Thread = () => {
<li onClick={() => handleAuthorDeleteClick(comment)}>Delete post</li> <li onClick={() => handleAuthorDeleteClick(comment)}>Delete post</li>
</> </>
) : null} ) : null}
{isModerator ? ( {canModerate ? (
<> <>
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : ( {authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
<li <li
@@ -2086,6 +2121,19 @@ const Thread = () => {
Anonymous Anonymous
</span> </span>
)} )}
{isOwner ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
&nbsp;## Board Owner
</span>
) : isAdmin ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
&nbsp;## Board Admin
</span>
) : isModerator ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode'>
&nbsp;## Board Mod
</span>
) : null}
&nbsp; &nbsp;
<span <span
key={`mob-pa-${comment.cid}`} key={`mob-pa-${comment.cid}`}
@@ -2340,6 +2388,9 @@ const Thread = () => {
{sortedReplies.map((reply, index) => { {sortedReplies.map((reply, index) => {
const replyMediaInfo = getCommentMediaInfo(reply); const replyMediaInfo = getCommentMediaInfo(reply);
const shortParentCid = findShortParentCid(reply.parentCid, comment); const shortParentCid = findShortParentCid(reply.parentCid, comment);
const isReplyOwner = subplebbit?.roles?.[reply.author.address]?.role === 'owner';
const isReplyAdmin = subplebbit?.roles?.[reply.author.address]?.role === 'admin';
const isReplyModerator = subplebbit?.roles?.[reply.author.address]?.role === 'moderator';
let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {}; let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {};
let signerAddress; let signerAddress;
if (storedSigners[selectedThread]) { if (storedSigners[selectedThread]) {
@@ -2398,7 +2449,7 @@ const Thread = () => {
<li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li> <li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li>
</> </>
) : null} ) : null}
{isModerator ? ( {canModerate ? (
<> <>
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : ( {authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
<li <li
@@ -2498,6 +2549,19 @@ const Thread = () => {
Anonymous Anonymous
</span> </span>
)} )}
{isReplyOwner ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
&nbsp;## Board Owner
</span>
) : isReplyAdmin ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
&nbsp;## Board Admin
</span>
) : isReplyModerator ? (
<span onClick={() => setIsAdminListOpen(true)} className='name capcode'>
&nbsp;## Board Mod
</span>
) : null}
<span key={`fix1-ha-${index}`} className='poster-address-mobile'> <span key={`fix1-ha-${index}`} className='poster-address-mobile'>
&nbsp;(u/ &nbsp;(u/
</span> </span>
+5 -5
View File
@@ -30,11 +30,12 @@ const useGeneralStore = create((set) => ({
setEditedComments: (comments) => set({ editedComments: comments }), setEditedComments: (comments) => set({ editedComments: comments }),
feedCacheStates: {}, feedCacheStates: {},
setFeedCacheState: (address, isCached) => set((prev) => ({ setFeedCacheState: (address, isCached) =>
set((prev) => ({
feedCacheStates: { feedCacheStates: {
...prev.feedCacheStates, ...prev.feedCacheStates,
[address]: isCached, [address]: isCached,
} },
})), })),
isAuthorDelete: false, isAuthorDelete: false,
@@ -49,8 +50,8 @@ const useGeneralStore = create((set) => ({
isEditModalOpen: false, isEditModalOpen: false,
setIsEditModalOpen: (isOpen) => set({ isEditModalOpen: isOpen }), setIsEditModalOpen: (isOpen) => set({ isEditModalOpen: isOpen }),
isModerator: false, canModerate: false,
setIsModerator: (isModerator) => set({ isModerator }), setCanModerate: (canModerate) => set({ canModerate }),
isModerationOpen: false, isModerationOpen: false,
setIsModerationOpen: (isOpen) => set({ isModerationOpen: isOpen }), setIsModerationOpen: (isOpen) => set({ isModerationOpen: isOpen }),
@@ -114,7 +115,6 @@ const useGeneralStore = create((set) => ({
triggerInsertion: 0, triggerInsertion: 0,
setTriggerInsertion: (trigger) => set({ triggerInsertion: trigger }), setTriggerInsertion: (trigger) => set({ triggerInsertion: trigger }),
})); }));
export default useGeneralStore; export default useGeneralStore;