mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
+142
-189
@@ -28,209 +28,162 @@ import packageJson from '../package.json';
|
||||
const commitRef = process?.env?.REACT_APP_COMMIT_REF || '';
|
||||
|
||||
export default function App() {
|
||||
const {
|
||||
bodyStyle,
|
||||
setBodyStyle,
|
||||
setDefaultSubplebbits,
|
||||
isCaptchaOpen,
|
||||
setIsCaptchaOpen,
|
||||
setIsSettingsOpen,
|
||||
selectedStyle,
|
||||
setSelectedStyle,
|
||||
setShowPostForm,
|
||||
setShowPostFormLink,
|
||||
} = useGeneralStore((state) => state);
|
||||
const { bodyStyle, setBodyStyle, setDefaultSubplebbits, isCaptchaOpen, setIsCaptchaOpen, setIsSettingsOpen, selectedStyle, setShowPostForm, setShowPostFormLink } =
|
||||
useGeneralStore((state) => state);
|
||||
|
||||
const location = useLocation();
|
||||
const isHomeRoute = location.pathname === '/';
|
||||
const isElectron = window.electron && window.electron.isElectron;
|
||||
const location = useLocation();
|
||||
const isElectron = window.electron && window.electron.isElectron;
|
||||
|
||||
const [, setNewErrorMessage] = useError();
|
||||
const [, setNewSuccessMessage] = useSuccess();
|
||||
const [, setNewInfoMessage] = useInfo();
|
||||
const [, setNewErrorMessage] = useError();
|
||||
const [, setNewSuccessMessage] = useSuccess();
|
||||
const [, setNewInfoMessage] = useInfo();
|
||||
|
||||
const [infoMessageShown, setInfoMessageShown] = useState(false);
|
||||
const [infoMessageShown, setInfoMessageShown] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const successToast = localStorage.getItem('successToast');
|
||||
const errorToast = localStorage.getItem('errorToast');
|
||||
if (successToast) {
|
||||
setNewSuccessMessage(successToast);
|
||||
localStorage.removeItem('successToast');
|
||||
} else if (errorToast) {
|
||||
setNewErrorMessage(errorToast);
|
||||
localStorage.removeItem('errorToast');
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}, [setNewErrorMessage, setNewSuccessMessage]);
|
||||
useEffect(() => {
|
||||
const successToast = localStorage.getItem('successToast');
|
||||
const errorToast = localStorage.getItem('errorToast');
|
||||
if (successToast) {
|
||||
setNewSuccessMessage(successToast);
|
||||
localStorage.removeItem('successToast');
|
||||
} else if (errorToast) {
|
||||
setNewErrorMessage(errorToast);
|
||||
localStorage.removeItem('errorToast');
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}, [setNewErrorMessage, setNewSuccessMessage]);
|
||||
|
||||
// check for new version
|
||||
// TODO: delete this code and toast when v1.0.0 is released
|
||||
useEffect(() => {
|
||||
const fetchVersionInfo = async () => {
|
||||
try {
|
||||
const packageRes = await fetch('https://raw.githubusercontent.com/plebbit/plebchan/master/package.json', { cache: 'no-cache' });
|
||||
const packageData = await packageRes.json();
|
||||
// check for new version
|
||||
// TODO: delete this code and toast when v1.0.0 is released
|
||||
useEffect(() => {
|
||||
const fetchVersionInfo = async () => {
|
||||
try {
|
||||
const packageRes = await fetch('https://raw.githubusercontent.com/plebbit/plebchan/master/package.json', { cache: 'no-cache' });
|
||||
const packageData = await packageRes.json();
|
||||
|
||||
if (packageJson.version !== packageData.version && !infoMessageShown) {
|
||||
const newVersionInfo = isElectron
|
||||
? `New version available, plebchan v${packageData.version}. You are using v${packageJson.version}. Download the latest version here: https://github.com/plebbit/plebchan/releases/latest`
|
||||
: `New version available, plebchan v${packageData.version}. You are using v${packageJson.version}. Refresh to update.`;
|
||||
setNewInfoMessage(newVersionInfo);
|
||||
setInfoMessageShown(true);
|
||||
}
|
||||
if (packageJson.version !== packageData.version && !infoMessageShown) {
|
||||
const newVersionInfo = isElectron
|
||||
? `New version available, plebchan v${packageData.version}. You are using v${packageJson.version}. Download the latest version here: https://github.com/plebbit/plebchan/releases/latest`
|
||||
: `New version available, plebchan v${packageData.version}. You are using v${packageJson.version}. Refresh to update.`;
|
||||
setNewInfoMessage(newVersionInfo);
|
||||
setInfoMessageShown(true);
|
||||
}
|
||||
|
||||
if (commitRef.length > 0) {
|
||||
const commitRes = await fetch('https://api.github.com/repos/plebbit/plebchan/commits?per_page=1&sha=development', { cache: 'no-cache' });
|
||||
const commitData = await commitRes.json();
|
||||
if (commitRef.length > 0) {
|
||||
const commitRes = await fetch('https://api.github.com/repos/plebbit/plebchan/commits?per_page=1&sha=development', { cache: 'no-cache' });
|
||||
const commitData = await commitRes.json();
|
||||
|
||||
const latestCommitHash = commitData[0].sha;
|
||||
const latestCommitHash = commitData[0].sha;
|
||||
|
||||
if (latestCommitHash.trim() !== commitRef.trim() && !infoMessageShown) {
|
||||
const newVersionInfo = `New dev version available, commit ${latestCommitHash.slice(0, 7)}. You are using commit ${commitRef.slice(0, 7)}. Refresh to update.`;
|
||||
setNewInfoMessage(newVersionInfo);
|
||||
setInfoMessageShown(true);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch latest version info:', error);
|
||||
}
|
||||
};
|
||||
if (latestCommitHash.trim() !== commitRef.trim() && !infoMessageShown) {
|
||||
const newVersionInfo = `New dev version available, commit ${latestCommitHash.slice(0, 7)}. You are using commit ${commitRef.slice(0, 7)}. Refresh to update.`;
|
||||
setNewInfoMessage(newVersionInfo);
|
||||
setInfoMessageShown(true);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch latest version info:', error);
|
||||
}
|
||||
};
|
||||
|
||||
fetchVersionInfo();
|
||||
}, [setNewInfoMessage, isElectron, infoMessageShown]);
|
||||
fetchVersionInfo();
|
||||
}, [setNewInfoMessage, isElectron, infoMessageShown]);
|
||||
|
||||
// preload banners
|
||||
useEffect(() => {
|
||||
const loadImages = async () => {
|
||||
const images = await importAll(require.context('../public/assets', true, /\.(png|jpe?g|svg)$/));
|
||||
const imageUrls = images.map((image) => image.default);
|
||||
preloadImages(imageUrls);
|
||||
};
|
||||
// preload banners
|
||||
useEffect(() => {
|
||||
const loadImages = async () => {
|
||||
const images = await importAll(require.context('../public/assets', true, /\.(png|jpe?g|svg)$/));
|
||||
const imageUrls = images.map((image) => image.default);
|
||||
preloadImages(imageUrls);
|
||||
};
|
||||
|
||||
loadImages();
|
||||
}, []);
|
||||
loadImages();
|
||||
}, []);
|
||||
|
||||
// automatic dark mode without interefering with user's selected style
|
||||
useEffect(() => {
|
||||
if (isHomeRoute) return;
|
||||
// fetch default subplebbits
|
||||
useEffect(() => {
|
||||
let didCancel = false;
|
||||
fetch('https://raw.githubusercontent.com/plebbit/temporary-default-subplebbits/master/subplebbits.json', { cache: 'no-cache' })
|
||||
.then((res) => res.json())
|
||||
.then((res) => {
|
||||
if (!didCancel) {
|
||||
setDefaultSubplebbits(res);
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
didCancel = true;
|
||||
};
|
||||
}, [setDefaultSubplebbits]);
|
||||
|
||||
const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
const isDarkMode = darkModeMediaQuery.matches;
|
||||
// handle nested routes
|
||||
useEffect(() => {
|
||||
const path = location.pathname;
|
||||
if (path.endsWith('/post')) {
|
||||
setShowPostFormLink(false);
|
||||
setShowPostForm(true);
|
||||
} else {
|
||||
setShowPostFormLink(true);
|
||||
setShowPostForm(false);
|
||||
}
|
||||
|
||||
if (isDarkMode && !isHomeRoute) {
|
||||
setSelectedStyle('Tomorrow');
|
||||
setBodyStyle({
|
||||
background: '#1d1f21 none',
|
||||
color: '#c5c8c6',
|
||||
fontFamily: 'Arial, Helvetica, sans-serif',
|
||||
});
|
||||
localStorage.setItem('selectedStyle', 'Tomorrow');
|
||||
}
|
||||
if (path.endsWith('/settings')) {
|
||||
setIsSettingsOpen(true);
|
||||
} else {
|
||||
setIsSettingsOpen(false);
|
||||
}
|
||||
}, [location.pathname, setIsSettingsOpen, setShowPostForm, setShowPostFormLink]);
|
||||
|
||||
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
|
||||
useEffect(() => {
|
||||
let didCancel = false;
|
||||
fetch('https://raw.githubusercontent.com/plebbit/temporary-default-subplebbits/master/subplebbits.json', { cache: 'no-cache' })
|
||||
.then((res) => res.json())
|
||||
.then((res) => {
|
||||
if (!didCancel) {
|
||||
setDefaultSubplebbits(res);
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
didCancel = true;
|
||||
};
|
||||
}, [setDefaultSubplebbits]);
|
||||
|
||||
// handle nested routes
|
||||
useEffect(() => {
|
||||
const path = location.pathname;
|
||||
if (path.endsWith('/post')) {
|
||||
setShowPostFormLink(false);
|
||||
setShowPostForm(true);
|
||||
} else {
|
||||
setShowPostFormLink(true);
|
||||
setShowPostForm(false);
|
||||
}
|
||||
|
||||
if (path.endsWith('/settings')) {
|
||||
setIsSettingsOpen(true);
|
||||
} else {
|
||||
setIsSettingsOpen(false);
|
||||
}
|
||||
}, [location.pathname, setIsSettingsOpen, setShowPostForm, setShowPostFormLink]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Helmet>
|
||||
<link rel='apple-touch-icon' sizes='180x180' href='assets/logo/apple-touch-icon.png' />
|
||||
<link rel='icon' type='image/png' sizes='32x32' href='assets/logo/favicon-32x32.png' />
|
||||
<link rel='icon' type='image/png' sizes='16x16' href='assets/logo/favicon-16x16.png' />
|
||||
<link rel='manifest' href='site.webmanifest' />
|
||||
<meta name='msapplication-TileColor' content='#fee9cd' />
|
||||
<meta name='theme-color' content='#ffffff' />
|
||||
</Helmet>
|
||||
<GlobalStyle background={bodyStyle.background} color={bodyStyle.color} fontFamily={bodyStyle.fontFamily} />
|
||||
<Routes>
|
||||
<Route exact path='/' element={<Home setBodyStyle={setBodyStyle} />} />
|
||||
<Route path={`/p/:subplebbitAddress`} element={<Board setBodyStyle={setBodyStyle} />}>
|
||||
<Route path='post' element={<Board />} />
|
||||
<Route path='settings' element={<Board />} />
|
||||
</Route>
|
||||
<Route path={`/p/:subplebbitAddress/c/:threadCid`} element={<Thread setBodyStyle={setBodyStyle} />}>
|
||||
<Route path='post' element={<Thread />} />
|
||||
<Route path='settings' element={<Thread />} />
|
||||
</Route>
|
||||
<Route path={`/p/:subplebbitAddress/catalog`} element={<Catalog setBodyStyle={setBodyStyle} />}>
|
||||
<Route path='post' element={<Catalog />} />
|
||||
<Route path='settings' element={<Catalog />} />
|
||||
</Route>
|
||||
<Route path={`/p/:subplebbitAddress/description`} element={<Description setBodyStyle={setBodyStyle} />}>
|
||||
<Route path='settings' element={<Description />} />
|
||||
</Route>
|
||||
<Route path={`/p/:subplebbitAddress/rules`} element={<Rules setBodyStyle={setBodyStyle} />}>
|
||||
<Route path='settings' element={<Rules />} />
|
||||
</Route>
|
||||
<Route path={`/profile/c/:index`} element={<Pending setBodyStyle={setBodyStyle} />}>
|
||||
<Route path='settings' element={<Pending />} />
|
||||
</Route>
|
||||
<Route path={`/p/subscriptions`} element={<Subscriptions setBodyStyle={setBodyStyle} />}>
|
||||
<Route path='settings' element={<Subscriptions />} />
|
||||
</Route>
|
||||
<Route path={`p/subscriptions/catalog`} element={<SubscriptionsCatalog setBodyStyle={setBodyStyle} />}>
|
||||
<Route path='settings' element={<SubscriptionsCatalog />} />
|
||||
</Route>
|
||||
<Route path={`p/all`} element={<All setBodyStyle={setBodyStyle} />}>
|
||||
<Route path='settings' element={<All />} />
|
||||
</Route>
|
||||
<Route path={`p/all/catalog`} element={<AllCatalog setBodyStyle={setBodyStyle} />}>
|
||||
<Route path='settings' element={<AllCatalog />} />
|
||||
</Route>
|
||||
<Route path='*' element={<NotFound setBodyStyle={setBodyStyle} />} />
|
||||
</Routes>
|
||||
<Toast />
|
||||
<CaptchaModal selectedStyle={selectedStyle} isOpen={isCaptchaOpen} closeModal={() => setIsCaptchaOpen(false)} />
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
<Helmet>
|
||||
<link rel='apple-touch-icon' sizes='180x180' href='assets/logo/apple-touch-icon.png' />
|
||||
<link rel='icon' type='image/png' sizes='32x32' href='assets/logo/favicon-32x32.png' />
|
||||
<link rel='icon' type='image/png' sizes='16x16' href='assets/logo/favicon-16x16.png' />
|
||||
<link rel='manifest' href='site.webmanifest' />
|
||||
<meta name='msapplication-TileColor' content='#fee9cd' />
|
||||
<meta name='theme-color' content='#ffffff' />
|
||||
</Helmet>
|
||||
<GlobalStyle background={bodyStyle.background} color={bodyStyle.color} fontFamily={bodyStyle.fontFamily} />
|
||||
<Routes>
|
||||
<Route exact path='/' element={<Home setBodyStyle={setBodyStyle} />} />
|
||||
<Route path={`/p/:subplebbitAddress`} element={<Board setBodyStyle={setBodyStyle} />}>
|
||||
<Route path='post' element={<Board />} />
|
||||
<Route path='settings' element={<Board />} />
|
||||
</Route>
|
||||
<Route path={`/p/:subplebbitAddress/c/:threadCid`} element={<Thread setBodyStyle={setBodyStyle} />}>
|
||||
<Route path='post' element={<Thread />} />
|
||||
<Route path='settings' element={<Thread />} />
|
||||
</Route>
|
||||
<Route path={`/p/:subplebbitAddress/catalog`} element={<Catalog setBodyStyle={setBodyStyle} />}>
|
||||
<Route path='post' element={<Catalog />} />
|
||||
<Route path='settings' element={<Catalog />} />
|
||||
</Route>
|
||||
<Route path={`/p/:subplebbitAddress/description`} element={<Description setBodyStyle={setBodyStyle} />}>
|
||||
<Route path='settings' element={<Description />} />
|
||||
</Route>
|
||||
<Route path={`/p/:subplebbitAddress/rules`} element={<Rules setBodyStyle={setBodyStyle} />}>
|
||||
<Route path='settings' element={<Rules />} />
|
||||
</Route>
|
||||
<Route path={`/profile/c/:index`} element={<Pending setBodyStyle={setBodyStyle} />}>
|
||||
<Route path='settings' element={<Pending />} />
|
||||
</Route>
|
||||
<Route path={`/p/subscriptions`} element={<Subscriptions setBodyStyle={setBodyStyle} />}>
|
||||
<Route path='settings' element={<Subscriptions />} />
|
||||
</Route>
|
||||
<Route path={`p/subscriptions/catalog`} element={<SubscriptionsCatalog setBodyStyle={setBodyStyle} />}>
|
||||
<Route path='settings' element={<SubscriptionsCatalog />} />
|
||||
</Route>
|
||||
<Route path={`p/all`} element={<All setBodyStyle={setBodyStyle} />}>
|
||||
<Route path='settings' element={<All />} />
|
||||
</Route>
|
||||
<Route path={`p/all/catalog`} element={<AllCatalog setBodyStyle={setBodyStyle} />}>
|
||||
<Route path='settings' element={<AllCatalog />} />
|
||||
</Route>
|
||||
<Route path='*' element={<NotFound setBodyStyle={setBodyStyle} />} />
|
||||
</Routes>
|
||||
<Toast />
|
||||
<CaptchaModal selectedStyle={selectedStyle} isOpen={isCaptchaOpen} closeModal={() => setIsCaptchaOpen(false)} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -81,7 +81,6 @@ const Post = ({ content, postQuoteOnClick, postQuoteOnOver, postQuoteOnLeave, po
|
||||
|
||||
parts.push(
|
||||
<ForwardRefLink
|
||||
key={`link-${i}-${matchedText}`}
|
||||
className='quotelink'
|
||||
to={linkTo}
|
||||
target={linkTarget}
|
||||
|
||||
@@ -43,10 +43,8 @@ const AdminListModal = ({ isOpen, closeModal, roles }) => {
|
||||
maxHeight: '250px',
|
||||
}}
|
||||
>
|
||||
<button className='icon' onClick={() => closeModal()} title='close' />
|
||||
<div className='modal-header' style={{ margin: '10px 10px 0px 10px' }}>
|
||||
Moderators
|
||||
</div>
|
||||
<button className='icon' style={{ imageRendering: 'pixelated', margin: '1px 1px 0 0' }} onClick={() => closeModal()} title='close' />
|
||||
<div className='modal-header'> Moderators</div>
|
||||
<div
|
||||
className='list'
|
||||
style={{
|
||||
@@ -60,15 +58,19 @@ const AdminListModal = ({ isOpen, closeModal, roles }) => {
|
||||
}}
|
||||
>
|
||||
<BoardForm selectedStyle={selectedStyle} style={{ all: 'unset' }}>
|
||||
{rolesList.map(({ address, role }, index) => (
|
||||
<p key={index}>
|
||||
•{' '}
|
||||
<Link to={() => {}} className='quote-link'>
|
||||
u/{address}
|
||||
</Link>
|
||||
: {role}
|
||||
</p>
|
||||
))}
|
||||
{roles ? (
|
||||
rolesList.map(({ address, role }, index) => (
|
||||
<p key={index}>
|
||||
•{' '}
|
||||
<Link to={() => {}} className='quote-link'>
|
||||
u/{address}
|
||||
</Link>
|
||||
: {role}
|
||||
</p>
|
||||
))
|
||||
) : (
|
||||
<p>This board doesn't have moderators yet.</p>
|
||||
)}
|
||||
</BoardForm>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,94 +2,95 @@ import styled from 'styled-components';
|
||||
import Modal from 'react-modal';
|
||||
|
||||
export const StyledModal = styled(Modal)`
|
||||
.hide-modal-overlay {
|
||||
display: none;
|
||||
}
|
||||
.hide-modal-overlay {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
position: fixed;
|
||||
top: calc(50% - 150px);
|
||||
left: calc(50% - 150px);
|
||||
display: block;
|
||||
padding: 2px;
|
||||
font-size: 10pt;
|
||||
border-left: none;
|
||||
border-top: none;
|
||||
}
|
||||
.modal-content {
|
||||
position: fixed;
|
||||
top: calc(50% - 150px);
|
||||
left: calc(50% - 150px);
|
||||
display: block;
|
||||
padding: 2px;
|
||||
font-size: 10pt;
|
||||
border-left: none;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
font-size: 10pt;
|
||||
text-align: center;
|
||||
margin-bottom: 1px;
|
||||
padding: 0;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
cursor: move;
|
||||
font-weight: 700;
|
||||
}
|
||||
.modal-header {
|
||||
font-size: 10pt;
|
||||
text-align: center;
|
||||
margin-bottom: 1px;
|
||||
padding: 0;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
cursor: move;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.icon {
|
||||
all: unset;
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
margin-bottom: -4px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: none;
|
||||
}
|
||||
.icon {
|
||||
all: unset;
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
margin-bottom: -4px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: none;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
#field {
|
||||
border: 1px solid #aaa;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
font-size: 10pt;
|
||||
outline: medium none;
|
||||
width: 298px;
|
||||
padding: 2px;
|
||||
}
|
||||
#field {
|
||||
border: 1px solid #aaa;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
font-size: 10pt;
|
||||
outline: medium none;
|
||||
width: 298px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
min-width: 296px;
|
||||
float: left;
|
||||
font-size: 10pt;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
textarea {
|
||||
min-width: 296px;
|
||||
float: left;
|
||||
font-size: 10pt;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
#captcha-container {
|
||||
position: relative;
|
||||
width: 302px;
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 17px;
|
||||
}
|
||||
#captcha-container {
|
||||
position: relative;
|
||||
width: 302px;
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 17px;
|
||||
}
|
||||
|
||||
#response {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
font-size: 11px;
|
||||
height: 18px;
|
||||
margin: 0px;
|
||||
padding: 0px 2px;
|
||||
font-family: monospace;
|
||||
vertical-align: middle;
|
||||
}
|
||||
#response {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
font-size: 11px;
|
||||
height: 18px;
|
||||
margin: 0px;
|
||||
padding: 0px 2px;
|
||||
font-family: monospace;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
img {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
display: block;
|
||||
}
|
||||
img {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#nav {
|
||||
float: right;
|
||||
margin: 0;
|
||||
width: auto;
|
||||
}
|
||||
#nav {
|
||||
float: right;
|
||||
margin: 0;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
${({ selectedStyle }) => {
|
||||
switch (selectedStyle) {
|
||||
case 'Yotsuba':
|
||||
return `
|
||||
${({ selectedStyle }) => {
|
||||
switch (selectedStyle) {
|
||||
case 'Yotsuba':
|
||||
return `
|
||||
.modal-content {
|
||||
background-color: #f0e0d6;
|
||||
border: 1px solid #d9bfb7;
|
||||
@@ -109,8 +110,8 @@ export const StyledModal = styled(Modal)`
|
||||
color: maroon;
|
||||
}`;
|
||||
|
||||
case 'Yotsuba-B':
|
||||
return `
|
||||
case 'Yotsuba-B':
|
||||
return `
|
||||
.modal-content {
|
||||
background-color: #d6daf0;
|
||||
border: 1px solid #b7c5d9;
|
||||
@@ -130,8 +131,8 @@ export const StyledModal = styled(Modal)`
|
||||
color: #000;
|
||||
}`;
|
||||
|
||||
case 'Futaba':
|
||||
return `
|
||||
case 'Futaba':
|
||||
return `
|
||||
.modal-content {
|
||||
background-color: #f0e0d6;
|
||||
border: 1px solid #d9bfb7;
|
||||
@@ -151,8 +152,8 @@ export const StyledModal = styled(Modal)`
|
||||
color: maroon;
|
||||
}`;
|
||||
|
||||
case 'Burichan':
|
||||
return `
|
||||
case 'Burichan':
|
||||
return `
|
||||
.modal-content {
|
||||
background-color: #d6daf0;
|
||||
border: 1px solid #b7c5d9;
|
||||
@@ -172,8 +173,8 @@ export const StyledModal = styled(Modal)`
|
||||
color: #000;
|
||||
}`;
|
||||
|
||||
case 'Tomorrow':
|
||||
return `
|
||||
case 'Tomorrow':
|
||||
return `
|
||||
.modal-content {
|
||||
background-color: #282a2e;
|
||||
border: 1px solid #111;
|
||||
@@ -216,8 +217,8 @@ export const StyledModal = styled(Modal)`
|
||||
filter: brightness(80%);
|
||||
}`;
|
||||
|
||||
case 'Photon':
|
||||
return `
|
||||
case 'Photon':
|
||||
return `
|
||||
.modal-content {
|
||||
background-color: #ddd;
|
||||
border: 1px solid #ccc;
|
||||
@@ -236,8 +237,8 @@ export const StyledModal = styled(Modal)`
|
||||
color: #333;
|
||||
}`;
|
||||
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}}
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}}
|
||||
`;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import styled from "styled-components";
|
||||
import Modal from "react-modal";
|
||||
import styled from 'styled-components';
|
||||
import Modal from 'react-modal';
|
||||
|
||||
export const StyledModal = styled(Modal)`
|
||||
.modal-content {
|
||||
@@ -9,10 +9,10 @@ export const StyledModal = styled(Modal)`
|
||||
transform: translate(-50%, -50%);
|
||||
width: 450px;
|
||||
height: auto;
|
||||
max-height: calc(100vh - 2*50px);
|
||||
max-height: calc(100vh - 2 * 50px);
|
||||
overflow-y: auto;
|
||||
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 {
|
||||
@@ -33,9 +33,12 @@ export const StyledModal = styled(Modal)`
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: none;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
#name, #description, #rule {
|
||||
#name,
|
||||
#description,
|
||||
#rule {
|
||||
border: 1px solid #aaa;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
font-size: 10pt;
|
||||
@@ -73,7 +76,6 @@ export const StyledModal = styled(Modal)`
|
||||
}
|
||||
|
||||
#rule {
|
||||
|
||||
}
|
||||
|
||||
#rule-btn {
|
||||
@@ -324,10 +326,10 @@ export const StyledModal = styled(Modal)`
|
||||
|
||||
span {
|
||||
color: #000;
|
||||
}`;
|
||||
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}`;
|
||||
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}}
|
||||
`;
|
||||
`;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import styled from "styled-components";
|
||||
import styled from 'styled-components';
|
||||
import Modal from 'react-modal';
|
||||
|
||||
export const StyledModal = styled(Modal)`
|
||||
@@ -13,7 +13,7 @@ export const StyledModal = styled(Modal)`
|
||||
position: absolute;
|
||||
padding: 2px 5px 5px;
|
||||
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) {
|
||||
width: 320px !important;
|
||||
@@ -27,12 +27,12 @@ export const StyledModal = styled(Modal)`
|
||||
width: 700px;
|
||||
height: auto;
|
||||
max-height: 80%;
|
||||
left: calc(50% - 350px);
|
||||
left: calc(50% - 350px);
|
||||
overflow-y: auto;
|
||||
position: absolute;
|
||||
padding: 2px 5px 5px;
|
||||
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) {
|
||||
width: 80%;
|
||||
@@ -66,6 +66,7 @@ export const StyledModal = styled(Modal)`
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
h4 {
|
||||
@@ -171,7 +172,8 @@ export const StyledModal = styled(Modal)`
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#save-board-settings, #reset-board-settings {
|
||||
#save-board-settings,
|
||||
#reset-board-settings {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -184,7 +186,7 @@ export const StyledModal = styled(Modal)`
|
||||
}
|
||||
|
||||
.settings-info strong {
|
||||
margin-bottom: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
${({ selectedStyle }) => {
|
||||
@@ -378,9 +380,9 @@ export const StyledModal = styled(Modal)`
|
||||
color: #f30 !important;
|
||||
}
|
||||
}`;
|
||||
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}}
|
||||
`;
|
||||
`;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import styled from "styled-components";
|
||||
import Modal from "react-modal";
|
||||
import styled from 'styled-components';
|
||||
import Modal from 'react-modal';
|
||||
|
||||
export const StyledModal = styled(Modal)`
|
||||
.modal-content {
|
||||
@@ -32,6 +32,7 @@ export const StyledModal = styled(Modal)`
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: none;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
#name {
|
||||
@@ -249,10 +250,10 @@ export const StyledModal = styled(Modal)`
|
||||
|
||||
span {
|
||||
color: #000;
|
||||
}`;
|
||||
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}`;
|
||||
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}}
|
||||
`;
|
||||
`;
|
||||
|
||||
@@ -50,6 +50,7 @@ export const StyledModal = styled(Modal)`
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
h4 {
|
||||
@@ -80,6 +81,7 @@ export const StyledModal = styled(Modal)`
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
display: inline-block;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
.settings-cat {
|
||||
|
||||
@@ -1698,10 +1698,6 @@ export const BoardForm = styled.div`
|
||||
margin-right: 14px;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: red !important;
|
||||
}
|
||||
|
||||
.ellipsis:after {
|
||||
content: '\\2026';
|
||||
position: absolute;
|
||||
@@ -1811,6 +1807,12 @@ export const BoardForm = styled.div`
|
||||
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: red !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#post-menu {
|
||||
@@ -1838,6 +1840,12 @@ export const BoardForm = styled.div`
|
||||
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: red !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#post-menu {
|
||||
@@ -1862,6 +1870,12 @@ export const BoardForm = styled.div`
|
||||
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: red !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#post-menu {
|
||||
@@ -1886,6 +1900,12 @@ export const BoardForm = styled.div`
|
||||
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: red !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#post-menu {
|
||||
@@ -1911,6 +1931,12 @@ export const BoardForm = styled.div`
|
||||
|
||||
.capcode {
|
||||
color: #81a2be !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: #81a2be !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#post-menu {
|
||||
@@ -1935,6 +1961,12 @@ export const BoardForm = styled.div`
|
||||
|
||||
.capcode {
|
||||
color: #f60 !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: #f60 !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#post-menu {
|
||||
@@ -3367,6 +3399,12 @@ export const BoardForm = styled.div`
|
||||
return `
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: red !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
.op-container {
|
||||
background-color: #f5e9e1;
|
||||
@@ -3487,6 +3525,12 @@ export const BoardForm = styled.div`
|
||||
return `
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: red !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
.op-container {
|
||||
background-color: #d6daf0;
|
||||
@@ -3603,6 +3647,12 @@ export const BoardForm = styled.div`
|
||||
return `
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: red !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
.op-container {
|
||||
background-color: #f5e9e1;
|
||||
@@ -3722,6 +3772,12 @@ export const BoardForm = styled.div`
|
||||
return `
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: red !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
.op-container {
|
||||
background-color: #d6daf0;
|
||||
@@ -3837,6 +3893,12 @@ export const BoardForm = styled.div`
|
||||
return `
|
||||
.capcode {
|
||||
color: #81a2be !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: #81a2be !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.op-container {
|
||||
@@ -3963,6 +4025,12 @@ export const BoardForm = styled.div`
|
||||
return `
|
||||
.capcode {
|
||||
color: #f60 !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: #f60 !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
.op-container {
|
||||
background-color: #eee;
|
||||
|
||||
@@ -17,12 +17,14 @@ export const Threads = styled.div`
|
||||
padding: 5px 0 3px;
|
||||
}
|
||||
|
||||
video, audio, img {
|
||||
video,
|
||||
audio,
|
||||
img {
|
||||
max-width: 150px;
|
||||
max-height: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
.file-thumb {
|
||||
.file-thumb {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
@@ -31,8 +33,8 @@ export const Threads = styled.div`
|
||||
}
|
||||
|
||||
.card {
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, .25);
|
||||
border: 0;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.25);
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.thread-icons {
|
||||
@@ -64,7 +66,7 @@ export const Threads = styled.div`
|
||||
}
|
||||
|
||||
.offline-icon-no-link-hovered {
|
||||
transform: translate(16px,0);
|
||||
transform: translate(16px, 0);
|
||||
}
|
||||
.sticky-icon {
|
||||
background-image: url(assets/sticky.gif);
|
||||
@@ -94,7 +96,6 @@ export const Threads = styled.div`
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
|
||||
${({ selectedStyle }) => {
|
||||
switch (selectedStyle) {
|
||||
case 'Yotsuba':
|
||||
@@ -155,7 +156,6 @@ export const PostPreview = styled.div`
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
|
||||
${({ selectedStyle }) => {
|
||||
switch (selectedStyle) {
|
||||
case 'Yotsuba':
|
||||
@@ -284,9 +284,27 @@ export const PostMenuCatalog = styled.div`
|
||||
${({ selectedStyle }) => {
|
||||
switch (selectedStyle) {
|
||||
case 'Yotsuba':
|
||||
return `.post-subject{
|
||||
color:red;
|
||||
}`;
|
||||
return `.highlighted, .highlighted-click, .highlighted-address {
|
||||
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':
|
||||
return `.highlighted, .highlighted-click, .highlighted-address {
|
||||
@@ -395,9 +413,8 @@ export const PostMenuCatalog = styled.div`
|
||||
}
|
||||
}`;
|
||||
|
||||
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}}
|
||||
`;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}}
|
||||
`;
|
||||
|
||||
@@ -906,10 +906,6 @@ export const BoardForm = styled.div`
|
||||
margin-right: 14px;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: red !important;
|
||||
}
|
||||
|
||||
.ellipsis:after {
|
||||
content: '\\2026';
|
||||
position: absolute;
|
||||
@@ -1001,6 +997,16 @@ export const BoardForm = styled.div`
|
||||
border-left: none !important;
|
||||
border-top: none !important;
|
||||
}
|
||||
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: red !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#post-menu {
|
||||
ul {
|
||||
@@ -1026,6 +1032,16 @@ export const BoardForm = styled.div`
|
||||
border-left: none !important;
|
||||
border-top: none !important;
|
||||
}
|
||||
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: red !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#post-menu {
|
||||
ul {
|
||||
@@ -1047,6 +1063,16 @@ export const BoardForm = styled.div`
|
||||
return `.highlighted, .highlighted-click, .highlighted-address {
|
||||
background-color: #f0c0b0 !important;
|
||||
}
|
||||
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: red !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#post-menu {
|
||||
font-size: 13px !important;
|
||||
@@ -1070,6 +1096,16 @@ export const BoardForm = styled.div`
|
||||
return `.highlighted, .highlighted-click, .highlighted-address {
|
||||
background-color: #d6bad0 !important;
|
||||
}
|
||||
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: red !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#post-menu {
|
||||
font-size: 13px !important;
|
||||
@@ -1094,6 +1130,16 @@ export const BoardForm = styled.div`
|
||||
background-color: #1d1d21 !important;
|
||||
outline: 1px solid #111 !important;
|
||||
}
|
||||
|
||||
.capcode {
|
||||
color: #81a2be !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: #81a2be !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#post-menu {
|
||||
ul {
|
||||
@@ -1116,6 +1162,16 @@ export const BoardForm = styled.div`
|
||||
background-color: #ccc !important;
|
||||
outline: 1px solid #ccc !important;
|
||||
}
|
||||
|
||||
.capcode {
|
||||
color: #f60 !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: #f60 !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#post-menu {
|
||||
ul {
|
||||
@@ -2506,6 +2562,12 @@ export const BoardForm = styled.div`
|
||||
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: red !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.subject-mobile {
|
||||
@@ -2627,6 +2689,12 @@ export const BoardForm = styled.div`
|
||||
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: red !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.subject-mobile {
|
||||
@@ -2744,11 +2812,12 @@ export const BoardForm = styled.div`
|
||||
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.subject-mobile {
|
||||
color: #cc1105;
|
||||
font-weight: 700;
|
||||
|
||||
.capcode-admin {
|
||||
color: red !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.date-time-mobile {
|
||||
@@ -2864,6 +2933,12 @@ export const BoardForm = styled.div`
|
||||
|
||||
.capcode {
|
||||
color: purple !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: red !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.subject-mobile {
|
||||
@@ -2980,6 +3055,12 @@ export const BoardForm = styled.div`
|
||||
|
||||
.capcode {
|
||||
color: #81a2be !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: #81a2be !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.poster-address-mobile {
|
||||
@@ -3106,7 +3187,13 @@ export const BoardForm = styled.div`
|
||||
|
||||
.capcode {
|
||||
color: #f60 !important;
|
||||
}
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capcode-admin {
|
||||
color: #f60 !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.subject-mobile {
|
||||
color: #111;
|
||||
|
||||
@@ -119,6 +119,7 @@ const All = () => {
|
||||
const [postOnHoverHeight, setPostOnHoverHeight] = useState(0);
|
||||
const [deletePost, setDeletePost] = useState(false);
|
||||
const [moderatorPermissions, setModeratorPermissions] = useState({});
|
||||
const [moderatorRole, setModeratorRole] = useState({});
|
||||
const [executeAnonMode, setExecuteAnonMode] = useState(false);
|
||||
const [cidTracker, setCidTracker] = useState({});
|
||||
const [isThreadThumbnailClicked, setIsThreadThumbnailClicked] = useState({});
|
||||
@@ -180,6 +181,7 @@ const All = () => {
|
||||
|
||||
useEffect(() => {
|
||||
let permissions = {};
|
||||
let roles = {};
|
||||
|
||||
selectedFeed.forEach((thread) => {
|
||||
const subplebbit = subplebbits.find((s) => s && s.address === thread.subplebbitAddress);
|
||||
@@ -192,10 +194,16 @@ const All = () => {
|
||||
} else {
|
||||
permissions[thread.subplebbitAddress] = false;
|
||||
}
|
||||
|
||||
if (!roles[thread.subplebbitAddress]) {
|
||||
roles[thread.subplebbitAddress] = {};
|
||||
}
|
||||
roles[thread.subplebbitAddress][account?.author.address] = role;
|
||||
}
|
||||
});
|
||||
|
||||
setModeratorPermissions(permissions);
|
||||
setModeratorRole(roles);
|
||||
}, [account?.author.address, selectedFeed, subplebbits]);
|
||||
|
||||
const handleOptionClick = () => {
|
||||
@@ -717,7 +725,11 @@ const All = () => {
|
||||
const { displayedReplies, omittedCount } = filteredRepliesByThread[thread.cid] || {};
|
||||
const commentMediaInfo = getCommentMediaInfo(thread);
|
||||
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;
|
||||
if (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}`}>
|
||||
<span
|
||||
key={`n-${index}`}
|
||||
className='name'
|
||||
className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
|
||||
data-tooltip-id='tooltip'
|
||||
data-tooltip-content={thread.author.displayName}
|
||||
data-tooltip-place='top'
|
||||
@@ -906,15 +918,22 @@ const All = () => {
|
||||
</span>
|
||||
</Fragment>
|
||||
) : (
|
||||
<span key={`n-${index}`} className='name'>
|
||||
<span key={`n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
{thread.author.displayName}
|
||||
</span>
|
||||
)
|
||||
) : (
|
||||
<span key={`n-${index}`} className='name'>
|
||||
<span key={`n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
Anonymous
|
||||
</span>
|
||||
)}
|
||||
{isOwner ? (
|
||||
<span className='name capcode-admin'> ## Board Owner</span>
|
||||
) : isAdmin ? (
|
||||
<span className='name capcode-admin'> ## Board Admin</span>
|
||||
) : isModerator ? (
|
||||
<span className='name capcode'> ## Board Mod</span>
|
||||
) : null}
|
||||
(u/
|
||||
<span
|
||||
key={`pa-${index}`}
|
||||
@@ -1037,7 +1056,7 @@ const All = () => {
|
||||
<li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
{canModerate ? (
|
||||
<>
|
||||
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
|
||||
<li
|
||||
@@ -1255,6 +1274,10 @@ const All = () => {
|
||||
}
|
||||
const replyMediaInfo = getCommentMediaInfo(reply);
|
||||
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);
|
||||
let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {};
|
||||
let signerAddress;
|
||||
@@ -1283,7 +1306,7 @@ const All = () => {
|
||||
<Fragment key={`fragment6-${index}`}>
|
||||
<span
|
||||
key={`mob-n-${index}`}
|
||||
className='name'
|
||||
className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
|
||||
data-tooltip-id='tooltip'
|
||||
data-tooltip-content={reply.author.displayName}
|
||||
data-tooltip-place='top'
|
||||
@@ -1292,15 +1315,22 @@ const All = () => {
|
||||
</span>
|
||||
</Fragment>
|
||||
) : (
|
||||
<span key={`mob-n-${index}`} className='name'>
|
||||
<span key={`mob-n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
{reply.author.displayName}
|
||||
</span>
|
||||
)
|
||||
) : (
|
||||
<span key={`mob-n-${index}`} className='name'>
|
||||
<span key={`mob-n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
Anonymous
|
||||
</span>
|
||||
)}
|
||||
{isOwner ? (
|
||||
<span className='name capcode-admin'> ## Board Owner</span>
|
||||
) : isAdmin ? (
|
||||
<span className='name capcode-admin'> ## Board Admin</span>
|
||||
) : isModerator ? (
|
||||
<span className='name capcode'> ## Board Mod</span>
|
||||
) : null}
|
||||
(u/
|
||||
<span
|
||||
key={`pa-${index}`}
|
||||
@@ -1434,7 +1464,7 @@ const All = () => {
|
||||
<li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
{canModerate ? (
|
||||
<>
|
||||
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
|
||||
<li
|
||||
@@ -2019,7 +2049,7 @@ const All = () => {
|
||||
<li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
{canModerate ? (
|
||||
<>
|
||||
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
|
||||
<li
|
||||
@@ -2085,7 +2115,7 @@ const All = () => {
|
||||
<Fragment key={`fragment9-${index}`}>
|
||||
<span
|
||||
key={`mob-n-${index}`}
|
||||
className='name-mobile'
|
||||
className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
|
||||
data-tooltip-id='tooltip'
|
||||
data-tooltip-content={thread.author.displayName}
|
||||
data-tooltip-place='top'
|
||||
@@ -2094,15 +2124,22 @@ const All = () => {
|
||||
</span>
|
||||
</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}
|
||||
</span>
|
||||
)
|
||||
) : (
|
||||
<span key={`mob-n-${index}`} className='name-mobile'>
|
||||
<span key={`mob-n-${index}`} className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
Anonymous
|
||||
</span>
|
||||
)}
|
||||
{isOwner ? (
|
||||
<span className='name capcode-admin'> ## Board Owner</span>
|
||||
) : isAdmin ? (
|
||||
<span className='name capcode-admin'> ## Board Admin</span>
|
||||
) : isModerator ? (
|
||||
<span className='name capcode'> ## Board Mod</span>
|
||||
) : null}
|
||||
|
||||
<span
|
||||
key={`mob-pa-${index}`}
|
||||
@@ -2454,6 +2491,10 @@ const All = () => {
|
||||
}
|
||||
const replyMediaInfo = getCommentMediaInfo(reply);
|
||||
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 signerAddress;
|
||||
if (storedSigners[selectedThreadCidRef]) {
|
||||
@@ -2512,7 +2553,7 @@ const All = () => {
|
||||
<li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
{canModerate ? (
|
||||
<>
|
||||
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
|
||||
<li
|
||||
@@ -2578,7 +2619,7 @@ const All = () => {
|
||||
<Fragment key={`fragment13-${index}`}>
|
||||
<span
|
||||
key={`mob-n-${index}`}
|
||||
className='name-mobile'
|
||||
className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
|
||||
data-tooltip-id='tooltip'
|
||||
data-tooltip-content={reply.author.displayName}
|
||||
data-tooltip-place='top'
|
||||
@@ -2587,15 +2628,22 @@ const All = () => {
|
||||
</span>
|
||||
</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}
|
||||
</span>
|
||||
)
|
||||
) : (
|
||||
<span key={`mob-n-${index}`} className='name-mobile'>
|
||||
<span key={`mob-n-${index}`} className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
Anonymous
|
||||
</span>
|
||||
)}
|
||||
{isOwner ? (
|
||||
<span className='name capcode-admin'> ## Board Owner</span>
|
||||
) : isAdmin ? (
|
||||
<span className='name capcode-admin'> ## Board Admin</span>
|
||||
) : isModerator ? (
|
||||
<span className='name capcode'> ## Board Mod</span>
|
||||
) : null}
|
||||
|
||||
<span
|
||||
key={`mob-pa-${index}`}
|
||||
|
||||
@@ -69,7 +69,7 @@ const CatalogPost = ({ post }) => {
|
||||
const [isImageSearchOpen, setIsImageSearchOpen] = useState(false);
|
||||
const [isClientRedirectMenuOpen, setIsClientRedirectMenuOpen] = useState(false);
|
||||
const [commentCid, setCommentCid] = useState(null);
|
||||
const [isModerator, setIsModerator] = useState(false);
|
||||
const [canModerate, setCanModerate] = useState(false);
|
||||
|
||||
const [, setNewErrorMessage] = useError();
|
||||
const [, setNewSuccessMessage] = useSuccess();
|
||||
@@ -161,9 +161,9 @@ const CatalogPost = ({ post }) => {
|
||||
const role = subplebbit.roles[account?.author.address]?.role;
|
||||
|
||||
if (role === 'moderator' || role === 'admin' || role === 'owner') {
|
||||
setIsModerator(true);
|
||||
setCanModerate(true);
|
||||
} else {
|
||||
setIsModerator(false);
|
||||
setCanModerate(false);
|
||||
}
|
||||
}
|
||||
}, [account?.author.address, subplebbit.roles]);
|
||||
@@ -573,7 +573,7 @@ const CatalogPost = ({ post }) => {
|
||||
<li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
{canModerate ? (
|
||||
<>
|
||||
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
|
||||
<li
|
||||
|
||||
@@ -145,7 +145,7 @@ const Board = () => {
|
||||
const [deletePost, setDeletePost] = useState(false);
|
||||
const [isImageSearchOpen, setIsImageSearchOpen] = useState(false);
|
||||
const [isClientRedirectMenuOpen, setIsClientRedirectMenuOpen] = useState(false);
|
||||
const [isModerator, setIsModerator] = useState(false);
|
||||
const [canModerate, setCanModerate] = useState(false);
|
||||
const [commentCid, setCommentCid] = useState(null);
|
||||
const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 });
|
||||
const [mobileMenuPosition, setMobileMenuPosition] = useState({ top: 0, left: 0 });
|
||||
@@ -177,12 +177,12 @@ const Board = () => {
|
||||
|
||||
useEffect(() => {
|
||||
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') {
|
||||
setIsModerator(true);
|
||||
setCanModerate(true);
|
||||
} else {
|
||||
setIsModerator(false);
|
||||
setCanModerate(false);
|
||||
}
|
||||
}
|
||||
}, [account?.author.address, subplebbit?.roles]);
|
||||
@@ -463,11 +463,6 @@ const Board = () => {
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
if (subjectRef.current.value === '') {
|
||||
setNewErrorMessage('Subject field is mandatory');
|
||||
return;
|
||||
}
|
||||
|
||||
setPublishCommentOptions((prevPublishCommentOptions) => ({
|
||||
...prevPublishCommentOptions,
|
||||
author: {
|
||||
@@ -933,7 +928,7 @@ const Board = () => {
|
||||
>
|
||||
Catalog
|
||||
</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>
|
||||
{subplebbit?.state === 'succeeded' ? (
|
||||
<>
|
||||
@@ -1039,7 +1034,7 @@ const Board = () => {
|
||||
>
|
||||
<div className={`post-menu-thread post-menu-thread-${'rules'}`} style={{ display: openMenuCid === 'rules' ? 'block' : 'none' }}>
|
||||
<ul className='post-menu-catalog'>
|
||||
{/* {isModerator ? (
|
||||
{/* {canModerate ? (
|
||||
<>
|
||||
change rules
|
||||
</>
|
||||
@@ -1264,7 +1259,7 @@ const Board = () => {
|
||||
>
|
||||
<div className={`post-menu-thread post-menu-thread-${'rules'}`} style={{ display: openMenuCid === 'rules' ? 'block' : 'none' }}>
|
||||
<ul className='post-menu-catalog'>
|
||||
{/* {isModerator ? (
|
||||
{/* {canModerate ? (
|
||||
<>
|
||||
change rules
|
||||
</>
|
||||
@@ -1509,7 +1504,7 @@ const Board = () => {
|
||||
style={{ display: openMenuCid === subplebbit.pubsubTopic ? 'block' : 'none' }}
|
||||
>
|
||||
<ul className='post-menu-catalog'>
|
||||
{/* {isModerator ? (
|
||||
{/* {canModerate ? (
|
||||
<>
|
||||
change description
|
||||
</>
|
||||
@@ -1744,6 +1739,9 @@ const Board = () => {
|
||||
const { displayedReplies, omittedCount } = filteredRepliesByThread[thread.cid] || {};
|
||||
const commentMediaInfo = getCommentMediaInfo(thread);
|
||||
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;
|
||||
if (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}`}>
|
||||
<span
|
||||
key={`n-${index}`}
|
||||
className='name'
|
||||
className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
|
||||
data-tooltip-id='tooltip'
|
||||
data-tooltip-content={thread.author.displayName}
|
||||
data-tooltip-place='top'
|
||||
@@ -1932,15 +1930,28 @@ const Board = () => {
|
||||
</span>
|
||||
</Fragment>
|
||||
) : (
|
||||
<span key={`n-${index}`} className='name'>
|
||||
<span key={`n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
{thread.author.displayName}
|
||||
</span>
|
||||
)
|
||||
) : (
|
||||
<span key={`n-${index}`} className='name'>
|
||||
<span key={`n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
Anonymous
|
||||
</span>
|
||||
)}
|
||||
{isOwner ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
|
||||
## Board Owner
|
||||
</span>
|
||||
) : isAdmin ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
|
||||
## Board Admin
|
||||
</span>
|
||||
) : isModerator ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode'>
|
||||
## Board Mod
|
||||
</span>
|
||||
) : null}
|
||||
(u/
|
||||
<span
|
||||
key={`pa-${index}`}
|
||||
@@ -2080,7 +2091,7 @@ const Board = () => {
|
||||
<li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
{canModerate ? (
|
||||
<>
|
||||
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
|
||||
<li
|
||||
@@ -2299,6 +2310,9 @@ const Board = () => {
|
||||
}
|
||||
const replyMediaInfo = getCommentMediaInfo(reply);
|
||||
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);
|
||||
let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {};
|
||||
let signerAddress;
|
||||
@@ -2328,7 +2342,7 @@ const Board = () => {
|
||||
<Fragment key={`fragment6-${index}`}>
|
||||
<span
|
||||
key={`mob-n-${index}`}
|
||||
className='name'
|
||||
className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
|
||||
data-tooltip-id='tooltip'
|
||||
data-tooltip-content={reply.author.displayName}
|
||||
data-tooltip-place='top'
|
||||
@@ -2337,15 +2351,28 @@ const Board = () => {
|
||||
</span>
|
||||
</Fragment>
|
||||
) : (
|
||||
<span key={`mob-n-${index}`} className='name'>
|
||||
<span key={`mob-n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
{reply.author.displayName}
|
||||
</span>
|
||||
)
|
||||
) : (
|
||||
<span key={`mob-n-${index}`} className='name'>
|
||||
<span key={`mob-n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
Anonymous
|
||||
</span>
|
||||
)}
|
||||
{isOwner ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
|
||||
## Board Owner
|
||||
</span>
|
||||
) : isAdmin ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
|
||||
## Board Admin
|
||||
</span>
|
||||
) : isModerator ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode'>
|
||||
## Board Mod
|
||||
</span>
|
||||
) : null}
|
||||
(u/
|
||||
<span
|
||||
key={`pa-${index}`}
|
||||
@@ -2465,7 +2492,7 @@ const Board = () => {
|
||||
<li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
{canModerate ? (
|
||||
<>
|
||||
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
|
||||
<li
|
||||
@@ -3057,7 +3084,7 @@ const Board = () => {
|
||||
<li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
{canModerate ? (
|
||||
<>
|
||||
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
|
||||
<li
|
||||
@@ -3139,7 +3166,7 @@ const Board = () => {
|
||||
<Fragment key={`fragment9-${index}`}>
|
||||
<span
|
||||
key={`mob-n-${index}`}
|
||||
className='name-mobile'
|
||||
className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
|
||||
data-tooltip-id='tooltip'
|
||||
data-tooltip-content={thread.author.displayName}
|
||||
data-tooltip-place='top'
|
||||
@@ -3148,15 +3175,28 @@ const Board = () => {
|
||||
</span>
|
||||
</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}
|
||||
</span>
|
||||
)
|
||||
) : (
|
||||
<span key={`mob-n-${index}`} className='name-mobile'>
|
||||
<span key={`mob-n-${index}`} className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
Anonymous
|
||||
</span>
|
||||
)}
|
||||
{isOwner ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
|
||||
## Board Owner
|
||||
</span>
|
||||
) : isAdmin ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
|
||||
## Board Admin
|
||||
</span>
|
||||
) : isModerator ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode'>
|
||||
## Board Mod
|
||||
</span>
|
||||
) : null}
|
||||
|
||||
<span
|
||||
key={`mob-pa-${index}`}
|
||||
@@ -3504,6 +3544,9 @@ const Board = () => {
|
||||
{displayedReplies?.map((reply, index) => {
|
||||
const replyMediaInfo = getCommentMediaInfo(reply);
|
||||
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 signerAddress;
|
||||
if (storedSigners[selectedThreadCidRef]) {
|
||||
@@ -3562,7 +3605,7 @@ const Board = () => {
|
||||
<li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
{canModerate ? (
|
||||
<>
|
||||
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
|
||||
<li
|
||||
@@ -3644,7 +3687,7 @@ const Board = () => {
|
||||
<Fragment key={`fragment13-${index}`}>
|
||||
<span
|
||||
key={`mob-n-${index}`}
|
||||
className='name-mobile'
|
||||
className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
|
||||
data-tooltip-id='tooltip'
|
||||
data-tooltip-content={reply.author.displayName}
|
||||
data-tooltip-place='top'
|
||||
@@ -3653,15 +3696,28 @@ const Board = () => {
|
||||
</span>
|
||||
</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}
|
||||
</span>
|
||||
)
|
||||
) : (
|
||||
<span key={`mob-n-${index}`} className='name-mobile'>
|
||||
<span key={`mob-n-${index}`} className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
Anonymous
|
||||
</span>
|
||||
)}
|
||||
{isOwner ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
|
||||
## Board Owner
|
||||
</span>
|
||||
) : isAdmin ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
|
||||
## Board Admin
|
||||
</span>
|
||||
) : isModerator ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode'>
|
||||
## Board Mod
|
||||
</span>
|
||||
) : null}
|
||||
|
||||
<span
|
||||
key={`mob-pa-${index}`}
|
||||
|
||||
@@ -52,7 +52,7 @@ const CatalogPost = ({ post }) => {
|
||||
setIsAuthorEdit,
|
||||
setIsCaptchaOpen,
|
||||
setIsEditModalOpen,
|
||||
isModerator,
|
||||
canModerate,
|
||||
setModeratingCommentCid,
|
||||
setOriginalCommentContent,
|
||||
setPendingComment,
|
||||
@@ -443,7 +443,7 @@ const CatalogPost = ({ post }) => {
|
||||
>
|
||||
<div className={`post-menu-thread post-menu-thread-${'rules'}`} style={{ display: openMenuCid === 'rules' ? 'block' : 'none' }}>
|
||||
<ul className='post-menu-catalog'>
|
||||
{/* {isModerator ? (
|
||||
{/* {canModerate ? (
|
||||
<>
|
||||
change rules
|
||||
</>
|
||||
@@ -647,7 +647,7 @@ const CatalogPost = ({ post }) => {
|
||||
>
|
||||
<div className={`post-menu-thread post-menu-thread-${'description'}`} style={{ display: openMenuCid === 'description' ? 'block' : 'none' }}>
|
||||
<ul className='post-menu-catalog'>
|
||||
{/* {isModerator ? (
|
||||
{/* {canModerate ? (
|
||||
<>
|
||||
change description
|
||||
</>
|
||||
@@ -999,7 +999,7 @@ const CatalogPost = ({ post }) => {
|
||||
<li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
{canModerate ? (
|
||||
<>
|
||||
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
|
||||
<li
|
||||
@@ -1133,7 +1133,7 @@ const Catalog = () => {
|
||||
setIsCaptchaOpen,
|
||||
isModerationOpen,
|
||||
setIsModerationOpen,
|
||||
setIsModerator,
|
||||
setCanModerate,
|
||||
isSettingsOpen,
|
||||
setIsSettingsOpen,
|
||||
originalCommentContent,
|
||||
@@ -1198,12 +1198,12 @@ const Catalog = () => {
|
||||
const role = subplebbit.roles[account?.author.address]?.role;
|
||||
|
||||
if (role === 'moderator' || role === 'admin' || role === 'owner') {
|
||||
setIsModerator(true);
|
||||
setCanModerate(true);
|
||||
} else {
|
||||
setIsModerator(false);
|
||||
setCanModerate(false);
|
||||
}
|
||||
}
|
||||
}, [account?.author.address, subplebbit.roles, setIsModerator]);
|
||||
}, [account?.author.address, subplebbit.roles, setCanModerate]);
|
||||
|
||||
useEffect(() => {
|
||||
setSelectedAddress(subplebbitAddress);
|
||||
@@ -1328,11 +1328,6 @@ const Catalog = () => {
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
if (subjectRef.current.value === '') {
|
||||
setNewErrorMessage('Subject field is mandatory');
|
||||
return;
|
||||
}
|
||||
|
||||
setPublishCommentOptions((prevPublishCommentOptions) => ({
|
||||
...prevPublishCommentOptions,
|
||||
author: {
|
||||
|
||||
@@ -427,7 +427,7 @@ const Description = () => {
|
||||
style={{ display: openMenuCid === subplebbit.pubsubTopic ? 'block' : 'none' }}
|
||||
>
|
||||
<ul className='post-menu-catalog'>
|
||||
{/* {isModerator ? (
|
||||
{/* {canModerate ? (
|
||||
<>
|
||||
change description
|
||||
</>
|
||||
|
||||
@@ -412,7 +412,7 @@ const Rules = () => {
|
||||
>
|
||||
<div className={`post-menu-thread post-menu-thread-${'rules'}`} style={{ display: openMenuCid === 'rules' ? 'block' : 'none' }}>
|
||||
<ul className='post-menu-catalog'>
|
||||
{/* {isModerator ? (
|
||||
{/* {canModerate ? (
|
||||
<>
|
||||
change rules
|
||||
</>
|
||||
|
||||
@@ -119,6 +119,7 @@ const Subscriptions = () => {
|
||||
const [postOnHoverHeight, setPostOnHoverHeight] = useState(0);
|
||||
const [deletePost, setDeletePost] = useState(false);
|
||||
const [moderatorPermissions, setModeratorPermissions] = useState({});
|
||||
const [moderatorRole, setModeratorRole] = useState({});
|
||||
const [executeAnonMode, setExecuteAnonMode] = useState(false);
|
||||
const [cidTracker, setCidTracker] = useState({});
|
||||
const [isThreadThumbnailClicked, setIsThreadThumbnailClicked] = useState({});
|
||||
@@ -179,6 +180,7 @@ const Subscriptions = () => {
|
||||
|
||||
useEffect(() => {
|
||||
let permissions = {};
|
||||
let roles = {};
|
||||
|
||||
selectedFeed.forEach((thread) => {
|
||||
const subplebbit = subplebbits.find((s) => s && s.address === thread.subplebbitAddress);
|
||||
@@ -191,10 +193,16 @@ const Subscriptions = () => {
|
||||
} else {
|
||||
permissions[thread.subplebbitAddress] = false;
|
||||
}
|
||||
|
||||
if (!roles[thread.subplebbitAddress]) {
|
||||
roles[thread.subplebbitAddress] = {};
|
||||
}
|
||||
roles[thread.subplebbitAddress][account?.author.address] = role;
|
||||
}
|
||||
});
|
||||
|
||||
setModeratorPermissions(permissions);
|
||||
setModeratorRole(roles);
|
||||
}, [account?.author.address, selectedFeed, subplebbits]);
|
||||
|
||||
const handleOptionClick = () => {
|
||||
@@ -721,7 +729,11 @@ const Subscriptions = () => {
|
||||
const { displayedReplies, omittedCount } = filteredRepliesByThread[thread.cid] || {};
|
||||
const commentMediaInfo = getCommentMediaInfo(thread);
|
||||
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;
|
||||
if (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}`}>
|
||||
<span
|
||||
key={`n-${index}`}
|
||||
className='name'
|
||||
className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
|
||||
data-tooltip-id='tooltip'
|
||||
data-tooltip-content={thread.author.displayName}
|
||||
data-tooltip-place='top'
|
||||
@@ -910,15 +922,22 @@ const Subscriptions = () => {
|
||||
</span>
|
||||
</Fragment>
|
||||
) : (
|
||||
<span key={`n-${index}`} className='name'>
|
||||
<span key={`n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
{thread.author.displayName}
|
||||
</span>
|
||||
)
|
||||
) : (
|
||||
<span key={`n-${index}`} className='name'>
|
||||
<span key={`n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
Anonymous
|
||||
</span>
|
||||
)}
|
||||
{isOwner ? (
|
||||
<span className='name capcode-admin'> ## Board Owner</span>
|
||||
) : isAdmin ? (
|
||||
<span className='name capcode-admin'> ## Board Admin</span>
|
||||
) : isModerator ? (
|
||||
<span className='name capcode'> ## Board Mod</span>
|
||||
) : null}
|
||||
(u/
|
||||
<span
|
||||
key={`pa-${index}`}
|
||||
@@ -1047,7 +1066,7 @@ const Subscriptions = () => {
|
||||
<li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
{canModerate ? (
|
||||
<>
|
||||
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
|
||||
<li
|
||||
@@ -1265,6 +1284,10 @@ const Subscriptions = () => {
|
||||
}
|
||||
const replyMediaInfo = getCommentMediaInfo(reply);
|
||||
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);
|
||||
let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {};
|
||||
let signerAddress;
|
||||
@@ -1293,7 +1316,7 @@ const Subscriptions = () => {
|
||||
<Fragment key={`fragment6-${index}`}>
|
||||
<span
|
||||
key={`mob-n-${index}`}
|
||||
className='name'
|
||||
className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
|
||||
data-tooltip-id='tooltip'
|
||||
data-tooltip-content={reply.author.displayName}
|
||||
data-tooltip-place='top'
|
||||
@@ -1302,15 +1325,22 @@ const Subscriptions = () => {
|
||||
</span>
|
||||
</Fragment>
|
||||
) : (
|
||||
<span key={`mob-n-${index}`} className='name'>
|
||||
<span key={`mob-n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
{reply.author.displayName}
|
||||
</span>
|
||||
)
|
||||
) : (
|
||||
<span key={`mob-n-${index}`} className='name'>
|
||||
<span key={`mob-n-${index}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
Anonymous
|
||||
</span>
|
||||
)}
|
||||
{isOwner ? (
|
||||
<span className='name capcode-admin'> ## Board Owner</span>
|
||||
) : isAdmin ? (
|
||||
<span className='name capcode-admin'> ## Board Admin</span>
|
||||
) : isModerator ? (
|
||||
<span className='name capcode'> ## Board Mod</span>
|
||||
) : null}
|
||||
(u/
|
||||
<span
|
||||
key={`pa-${index}`}
|
||||
@@ -1444,7 +1474,7 @@ const Subscriptions = () => {
|
||||
<li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
{canModerate ? (
|
||||
<>
|
||||
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
|
||||
<li
|
||||
@@ -2029,7 +2059,7 @@ const Subscriptions = () => {
|
||||
<li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
{canModerate ? (
|
||||
<>
|
||||
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
|
||||
<li
|
||||
@@ -2095,7 +2125,7 @@ const Subscriptions = () => {
|
||||
<Fragment key={`fragment9-${index}`}>
|
||||
<span
|
||||
key={`mob-n-${index}`}
|
||||
className='name-mobile'
|
||||
className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
|
||||
data-tooltip-id='tooltip'
|
||||
data-tooltip-content={thread.author.displayName}
|
||||
data-tooltip-place='top'
|
||||
@@ -2104,15 +2134,22 @@ const Subscriptions = () => {
|
||||
</span>
|
||||
</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}
|
||||
</span>
|
||||
)
|
||||
) : (
|
||||
<span key={`mob-n-${index}`} className='name-mobile'>
|
||||
<span key={`mob-n-${index}`} className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
Anonymous
|
||||
</span>
|
||||
)}
|
||||
{isOwner ? (
|
||||
<span className='name capcode-admin'> ## Board Owner</span>
|
||||
) : isAdmin ? (
|
||||
<span className='name capcode-admin'> ## Board Admin</span>
|
||||
) : isModerator ? (
|
||||
<span className='name capcode'> ## Board Mod</span>
|
||||
) : null}
|
||||
|
||||
<span
|
||||
key={`mob-pa-${index}`}
|
||||
@@ -2464,6 +2501,10 @@ const Subscriptions = () => {
|
||||
}
|
||||
const replyMediaInfo = getCommentMediaInfo(reply);
|
||||
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 signerAddress;
|
||||
if (storedSigners[selectedThreadCidRef]) {
|
||||
@@ -2522,7 +2563,7 @@ const Subscriptions = () => {
|
||||
<li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
{canModerate ? (
|
||||
<>
|
||||
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
|
||||
<li
|
||||
@@ -2588,7 +2629,7 @@ const Subscriptions = () => {
|
||||
<Fragment key={`fragment13-${index}`}>
|
||||
<span
|
||||
key={`mob-n-${index}`}
|
||||
className='name-mobile'
|
||||
className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
|
||||
data-tooltip-id='tooltip'
|
||||
data-tooltip-content={reply.author.displayName}
|
||||
data-tooltip-place='top'
|
||||
@@ -2597,15 +2638,22 @@ const Subscriptions = () => {
|
||||
</span>
|
||||
</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}
|
||||
</span>
|
||||
)
|
||||
) : (
|
||||
<span key={`mob-n-${index}`} className='name-mobile'>
|
||||
<span key={`mob-n-${index}`} className={`name-mobile ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
Anonymous
|
||||
</span>
|
||||
)}
|
||||
{isOwner ? (
|
||||
<span className='name capcode-admin'> ## Board Owner</span>
|
||||
) : isAdmin ? (
|
||||
<span className='name capcode-admin'> ## Board Admin</span>
|
||||
) : isModerator ? (
|
||||
<span className='name capcode'> ## Board Mod</span>
|
||||
) : null}
|
||||
|
||||
<span
|
||||
key={`mob-pa-${index}`}
|
||||
|
||||
@@ -69,7 +69,7 @@ const CatalogPost = ({ post }) => {
|
||||
const [isImageSearchOpen, setIsImageSearchOpen] = useState(false);
|
||||
const [isClientRedirectMenuOpen, setIsClientRedirectMenuOpen] = useState(false);
|
||||
const [commentCid, setCommentCid] = useState(null);
|
||||
const [isModerator, setIsModerator] = useState(false);
|
||||
const [canModerate, setCanModerate] = useState(false);
|
||||
|
||||
const [, setNewErrorMessage] = useError();
|
||||
const [, setNewSuccessMessage] = useSuccess();
|
||||
@@ -161,9 +161,9 @@ const CatalogPost = ({ post }) => {
|
||||
const role = subplebbit.roles[account?.author.address]?.role;
|
||||
|
||||
if (role === 'moderator' || role === 'admin' || role === 'owner') {
|
||||
setIsModerator(true);
|
||||
setCanModerate(true);
|
||||
} else {
|
||||
setIsModerator(false);
|
||||
setCanModerate(false);
|
||||
}
|
||||
}
|
||||
}, [account?.author.address, subplebbit.roles]);
|
||||
@@ -573,7 +573,7 @@ const CatalogPost = ({ post }) => {
|
||||
<li onClick={() => handleAuthorDeleteClick(thread)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
{canModerate ? (
|
||||
<>
|
||||
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
|
||||
<li
|
||||
|
||||
@@ -23,6 +23,7 @@ import PostOnHover from '../PostOnHover';
|
||||
import StateLabel from '../StateLabel';
|
||||
import VerifiedAuthor from '../VerifiedAuthor';
|
||||
import CreateBoardModal from '../modals/CreateBoardModal';
|
||||
import AdminListModal from '../modals/AdminListModal';
|
||||
import EditModal from '../modals/EditModal';
|
||||
import ModerationModal from '../modals/ModerationModal';
|
||||
import ReplyModal from '../modals/ReplyModal';
|
||||
@@ -119,7 +120,7 @@ const Thread = () => {
|
||||
const [visible, setVisible] = useState(true);
|
||||
const [isImageSearchOpen, setIsImageSearchOpen] = useState(false);
|
||||
const [isClientRedirectMenuOpen, setIsClientRedirectMenuOpen] = useState(false);
|
||||
const [isModerator, setIsModerator] = useState(false);
|
||||
const [canModerate, setCanModerate] = useState(false);
|
||||
const [commentCid, setCommentCid] = useState(null);
|
||||
const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 });
|
||||
const [mobileMenuPosition, setMobileMenuPosition] = useState({ top: 0, left: 0 });
|
||||
@@ -138,11 +139,15 @@ const Thread = () => {
|
||||
|
||||
useAnonMode(selectedThread, anonymousMode && executeAnonMode);
|
||||
|
||||
const [isAdminListOpen, setIsAdminListOpen] = useState(false);
|
||||
const originalComment = useComment({ commentCid: selectedThread });
|
||||
const [comment, setComment] = useState(originalComment);
|
||||
const { subplebbitAddress, threadCid } = useParams();
|
||||
const subplebbit = useSubplebbit({ subplebbitAddress: originalComment.subplebbitAddress });
|
||||
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);
|
||||
|
||||
@@ -200,9 +205,9 @@ const Thread = () => {
|
||||
const role = subplebbit.roles[account?.author?.address]?.role;
|
||||
|
||||
if (role === 'moderator' || role === 'admin' || role === 'owner') {
|
||||
setIsModerator(true);
|
||||
setCanModerate(true);
|
||||
} else {
|
||||
setIsModerator(false);
|
||||
setCanModerate(false);
|
||||
}
|
||||
}
|
||||
}, [account?.author.address, subplebbit.roles]);
|
||||
@@ -642,6 +647,7 @@ const Thread = () => {
|
||||
</title>
|
||||
</Helmet>
|
||||
<Container>
|
||||
<AdminListModal selectedStyle={selectedStyle} isOpen={isAdminListOpen} closeModal={() => setIsAdminListOpen(false)} roles={subplebbit?.roles} />
|
||||
<CreateBoardModal selectedStyle={selectedStyle} isOpen={isCreateBoardOpen} closeModal={() => setIsCreateBoardOpen(false)} />
|
||||
<ReplyModal selectedStyle={selectedStyle} isOpen={isReplyOpen} closeModal={() => setIsReplyOpen(false)} />
|
||||
<SettingsModal selectedStyle={selectedStyle} isOpen={isSettingsOpen} closeModal={() => setIsSettingsOpen(false)} />
|
||||
@@ -1078,7 +1084,7 @@ const Thread = () => {
|
||||
<>
|
||||
<span
|
||||
key={`n-${comment.cid}`}
|
||||
className='name'
|
||||
className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
|
||||
data-tooltip-id='tooltip'
|
||||
data-tooltip-content={comment?.author?.displayName}
|
||||
data-tooltip-place='top'
|
||||
@@ -1087,15 +1093,28 @@ const Thread = () => {
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<span key={`n-${comment.cid}`} className='name'>
|
||||
<span key={`n-${comment.cid}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
{comment?.author?.displayName}
|
||||
</span>
|
||||
)
|
||||
) : (
|
||||
<span key={`n-${comment.cid}`} className='name'>
|
||||
<span key={`n-${comment.cid}`} className={`name ${isAdmin || isOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
Anonymous
|
||||
</span>
|
||||
)}
|
||||
{isOwner ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
|
||||
## Board Owner
|
||||
</span>
|
||||
) : isAdmin ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
|
||||
## Board Admin
|
||||
</span>
|
||||
) : isModerator ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode'>
|
||||
## Board Mod
|
||||
</span>
|
||||
) : null}
|
||||
|
||||
<span
|
||||
className='poster-address address-desktop'
|
||||
@@ -1205,7 +1224,7 @@ const Thread = () => {
|
||||
<li onClick={() => handleAuthorDeleteClick(comment)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
{canModerate ? (
|
||||
<>
|
||||
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
|
||||
<li
|
||||
@@ -1375,6 +1394,9 @@ const Thread = () => {
|
||||
}
|
||||
const replyMediaInfo = getCommentMediaInfo(reply);
|
||||
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);
|
||||
let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {};
|
||||
let signerAddress;
|
||||
@@ -1404,7 +1426,7 @@ const Thread = () => {
|
||||
<>
|
||||
<span
|
||||
key={`mob-n-${index}`}
|
||||
className='name'
|
||||
className={`name ${isReplyAdmin || isReplyOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}
|
||||
data-tooltip-id='tooltip'
|
||||
data-tooltip-content={reply.author?.displayName}
|
||||
data-tooltip-place='top'
|
||||
@@ -1413,15 +1435,28 @@ const Thread = () => {
|
||||
</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}
|
||||
</span>
|
||||
)
|
||||
) : (
|
||||
<span key={`mob-n-${index}`} className='name'>
|
||||
<span key={`mob-n-${index}`} className={`name ${isReplyAdmin || isReplyOwner ? 'capcode-admin' : isModerator ? 'capcode' : ''}`}>
|
||||
Anonymous
|
||||
</span>
|
||||
)}
|
||||
{isReplyOwner ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
|
||||
## Board Owner
|
||||
</span>
|
||||
) : isReplyAdmin ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
|
||||
## Board Admin
|
||||
</span>
|
||||
) : isReplyModerator ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode'>
|
||||
## Board Mod
|
||||
</span>
|
||||
) : null}
|
||||
(u/
|
||||
<span
|
||||
key={`pa-${index}`}
|
||||
@@ -1531,7 +1566,7 @@ const Thread = () => {
|
||||
<li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
{canModerate ? (
|
||||
<>
|
||||
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
|
||||
<li
|
||||
@@ -1986,7 +2021,7 @@ const Thread = () => {
|
||||
<li onClick={() => handleAuthorDeleteClick(comment)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
{canModerate ? (
|
||||
<>
|
||||
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
|
||||
<li
|
||||
@@ -2086,6 +2121,19 @@ const Thread = () => {
|
||||
Anonymous
|
||||
</span>
|
||||
)}
|
||||
{isOwner ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
|
||||
## Board Owner
|
||||
</span>
|
||||
) : isAdmin ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
|
||||
## Board Admin
|
||||
</span>
|
||||
) : isModerator ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode'>
|
||||
## Board Mod
|
||||
</span>
|
||||
) : null}
|
||||
|
||||
<span
|
||||
key={`mob-pa-${comment.cid}`}
|
||||
@@ -2340,6 +2388,9 @@ const Thread = () => {
|
||||
{sortedReplies.map((reply, index) => {
|
||||
const replyMediaInfo = getCommentMediaInfo(reply);
|
||||
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 signerAddress;
|
||||
if (storedSigners[selectedThread]) {
|
||||
@@ -2398,7 +2449,7 @@ const Thread = () => {
|
||||
<li onClick={() => handleAuthorDeleteClick(reply)}>Delete post</li>
|
||||
</>
|
||||
) : null}
|
||||
{isModerator ? (
|
||||
{canModerate ? (
|
||||
<>
|
||||
{authorAddress === account?.author.address || authorAddress === account?.signer.address ? null : (
|
||||
<li
|
||||
@@ -2498,6 +2549,19 @@ const Thread = () => {
|
||||
Anonymous
|
||||
</span>
|
||||
)}
|
||||
{isReplyOwner ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
|
||||
## Board Owner
|
||||
</span>
|
||||
) : isReplyAdmin ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode-admin'>
|
||||
## Board Admin
|
||||
</span>
|
||||
) : isReplyModerator ? (
|
||||
<span onClick={() => setIsAdminListOpen(true)} className='name capcode'>
|
||||
## Board Mod
|
||||
</span>
|
||||
) : null}
|
||||
<span key={`fix1-ha-${index}`} className='poster-address-mobile'>
|
||||
(u/
|
||||
</span>
|
||||
|
||||
@@ -30,12 +30,13 @@ const useGeneralStore = create((set) => ({
|
||||
setEditedComments: (comments) => set({ editedComments: comments }),
|
||||
|
||||
feedCacheStates: {},
|
||||
setFeedCacheState: (address, isCached) => set((prev) => ({
|
||||
feedCacheStates: {
|
||||
...prev.feedCacheStates,
|
||||
[address]: isCached,
|
||||
}
|
||||
})),
|
||||
setFeedCacheState: (address, isCached) =>
|
||||
set((prev) => ({
|
||||
feedCacheStates: {
|
||||
...prev.feedCacheStates,
|
||||
[address]: isCached,
|
||||
},
|
||||
})),
|
||||
|
||||
isAuthorDelete: false,
|
||||
setIsAuthorDelete: (isAuthorDelete) => set({ isAuthorDelete }),
|
||||
@@ -49,8 +50,8 @@ const useGeneralStore = create((set) => ({
|
||||
isEditModalOpen: false,
|
||||
setIsEditModalOpen: (isOpen) => set({ isEditModalOpen: isOpen }),
|
||||
|
||||
isModerator: false,
|
||||
setIsModerator: (isModerator) => set({ isModerator }),
|
||||
canModerate: false,
|
||||
setCanModerate: (canModerate) => set({ canModerate }),
|
||||
|
||||
isModerationOpen: false,
|
||||
setIsModerationOpen: (isOpen) => set({ isModerationOpen: isOpen }),
|
||||
@@ -81,7 +82,7 @@ const useGeneralStore = create((set) => ({
|
||||
|
||||
resolveCaptchaPromise: null,
|
||||
setResolveCaptchaPromise: (resolve) => set({ resolveCaptchaPromise: resolve }),
|
||||
|
||||
|
||||
selectedAddress: '',
|
||||
setSelectedAddress: (address) => set({ selectedAddress: address }),
|
||||
|
||||
@@ -90,7 +91,7 @@ const useGeneralStore = create((set) => ({
|
||||
|
||||
selectedShortCid: '',
|
||||
setSelectedShortCid: (shortCid) => set({ selectedShortCid: shortCid }),
|
||||
|
||||
|
||||
selectedStyle: localStorage.getItem('selectedStyle') || 'Yotsuba',
|
||||
setSelectedStyle: (style) => {
|
||||
localStorage.setItem('selectedStyle', style);
|
||||
@@ -99,7 +100,7 @@ const useGeneralStore = create((set) => ({
|
||||
|
||||
selectedText: '',
|
||||
setSelectedText: (text) => set({ selectedText: text }),
|
||||
|
||||
|
||||
selectedThread: '',
|
||||
setSelectedThread: (thread) => set({ selectedThread: thread }),
|
||||
|
||||
@@ -114,7 +115,6 @@ const useGeneralStore = create((set) => ({
|
||||
|
||||
triggerInsertion: 0,
|
||||
setTriggerInsertion: (trigger) => set({ triggerInsertion: trigger }),
|
||||
|
||||
}));
|
||||
|
||||
export default useGeneralStore;
|
||||
export default useGeneralStore;
|
||||
|
||||
Reference in New Issue
Block a user