+ {subplebbit.rules ? (
+
setIsHoveringOnThread('rules')}
onMouseLeave={() => setIsHoveringOnThread('')}>
-
-
- R:
0 / L:
0
-
-
+
+ R:
0 / L:
0
+
+
-
+
-
-
{
- threadMenuRefs.current["rules"] = el;
- postMenuRef.current = el;
- }}
- className='post-menu-button'
- id='post-menu-button-catalog'
- rotated={openMenuCid === "rules"}
- onClick={(event) => {
- event.stopPropagation();
- const rect = threadMenuRefs.current["rules"].getBoundingClientRect();
- setMenuPosition({top: rect.top + window.scrollY, left: rect.left});
- setOpenMenuCid(prevCid => (prevCid === "rules" ? null : "rules"));
- }}
- >
- ▶
-
+ imageRendering: "pixelated",
+ }} />
- {createPortal(
- {postMenuCatalogRef.current = el}}
- onClick={(event) => event.stopPropagation()}
- style={{position: "absolute",
- top: menuPosition.top + 7,
- left: menuPosition.left}}>
- {
+ threadMenuRefs.current["rules"] = el;
+ postMenuRef.current = el;
+ }}
+ className='post-menu-button'
+ id='post-menu-button-catalog'
+ rotated={openMenuCid === "rules"}
+ onClick={(event) => {
+ event.stopPropagation();
+ const rect = threadMenuRefs.current["rules"].getBoundingClientRect();
+ setMenuPosition({ top: rect.top + window.scrollY, left: rect.left });
+ setOpenMenuCid(prevCid => (prevCid === "rules" ? null : "rules"));
+ }}
+ >
+ ▶
+
+
+ {createPortal(
+ { postMenuCatalogRef.current = el }}
+ onClick={(event) => event.stopPropagation()}
+ style={{
+ position: "absolute",
+ top: menuPosition.top + 7,
+ left: menuPosition.left
+ }}>
+
-
- handleOptionClick("rules")}>Hide thread
- {/* {isModerator ? (
+ >
+
+ handleOptionClick("rules")}>Hide thread
+ {/* {isModerator ? (
<>
change rules
>
) : null} */}
-
-
- , document.body
- )}
-
-
-
- Rules
- {": " + subplebbit.rules.map((rule, index) => `${index + 1}. ${rule}`).join(' ')}
+
-
-
- )
- } else if (item?.type === 'description') {
- return (
- <>
-
setIsHoveringOnThread('description')}
- onMouseLeave={() => setIsHoveringOnThread('')}>
-
- {subplebbit.suggested?.avatarUrl ? (
-
- ) : null}
-
- {subplebbit.suggested?.avatarUrl ? (
-
-
-
-
- ) : null}
-
-
- R:
0 / L:
0
- {subplebbit.suggested?.avatarUrl ? null : (
-
-
-
-
- )}
-
{
- threadMenuRefs.current["description"] = el;
- postMenuRef.current = el;
- }}
- className='post-menu-button'
- id='post-menu-button-catalog'
- rotated={openMenuCid === "description"}
- onClick={(event) => {
- event.stopPropagation();
- const rect = threadMenuRefs.current["description"].getBoundingClientRect();
- setMenuPosition({top: rect.top + window.scrollY, left: rect.left});
- setOpenMenuCid(prevCid => (prevCid === "description" ? null : "description"));
- }}
- >
- ▶
-
-
- {createPortal(
- {postMenuCatalogRef.current = el}}
- onClick={(event) => event.stopPropagation()}
- style={{position: "absolute",
- top: menuPosition.top + 7,
- left: menuPosition.left}}>
-
-
- handleOptionClick("description")}>Hide thread
- {/* {isModerator ? (
- <>
- change description
- >
- ) : null} */}
- {subplebbit.suggested?.avatarUrl ? (
- {setIsImageSearchOpen(true)}}
- onMouseLeave={() => {setIsImageSearchOpen(false)}}>
- Image search »
-
- handleOptionClick("description")}>
- Google
-
- handleOptionClick("description")}>
- Yandex
-
- handleOptionClick("description")}>
- SauceNAO
-
-
-
- ) : null}
-
-
- , document.body
- )}
-
-
setSelectedThread("description")}>
-
- Welcome to {subplebbit.title || subplebbit.address}
- {": " + subplebbit.description}
-
-
+ , document.body
+ )}
+
+
+
+ Rules
+ {": " + subplebbit.rules.map((rule, index) => `${index + 1}. ${rule}`).join(' ')}
- >
- )
- } else {
+
+
+ ) : null}
+ {subplebbit.description ? (
+
setIsHoveringOnThread('description')}
+ onMouseLeave={() => setIsHoveringOnThread('')}>
+
+ {subplebbit.suggested?.avatarUrl ? (
+
+ ) : null}
+
+ {subplebbit.suggested?.avatarUrl ? (
+
+
+
+
+ ) : null}
+
+
+ R:
0 / L:
0
+ {subplebbit.suggested?.avatarUrl ? null : (
+
+
+
+
+ )}
+
{
+ threadMenuRefs.current["description"] = el;
+ postMenuRef.current = el;
+ }}
+ className='post-menu-button'
+ id='post-menu-button-catalog'
+ rotated={openMenuCid === "description"}
+ onClick={(event) => {
+ event.stopPropagation();
+ const rect = threadMenuRefs.current["description"].getBoundingClientRect();
+ setMenuPosition({ top: rect.top + window.scrollY, left: rect.left });
+ setOpenMenuCid(prevCid => (prevCid === "description" ? null : "description"));
+ }}
+ >
+ ▶
+
+
+ {createPortal(
+ { postMenuCatalogRef.current = el }}
+ onClick={(event) => event.stopPropagation()}
+ style={{
+ position: "absolute",
+ top: menuPosition.top + 7,
+ left: menuPosition.left
+ }}>
+
+
+ handleOptionClick("description")}>Hide thread
+ {/* {isModerator ? (
+ <>
+ change description
+ >
+ ) : null} */}
+ {subplebbit.suggested?.avatarUrl ? (
+ { setIsImageSearchOpen(true) }}
+ onMouseLeave={() => { setIsImageSearchOpen(false) }}>
+ Image search »
+
+ handleOptionClick("description")}>
+ Google
+
+ handleOptionClick("description")}>
+ Yandex
+
+ handleOptionClick("description")}>
+ SauceNAO
+
+
+
+ ) : null}
+
+
+ , document.body
+ )}
+
+
setSelectedThread("description")}>
+
+ Welcome to {subplebbit.title || subplebbit.address}
+ {": " + subplebbit.description}
+
+
+
+ ) : null}
+ {feed.map((thread, index) => {
+ const commentMediaInfo = getCommentMediaInfo(thread);
+ const fallbackImgUrl = "assets/filedeleted-res.gif";
+ const linkCount = countLinks(thread);
return (
-
{setIsHoveringOnThread(thread.cid)}}
- onMouseLeave={() => {setIsHoveringOnThread('')}}>
+
{ setIsHoveringOnThread(thread.cid) }}
+ onMouseLeave={() => { setIsHoveringOnThread('') }}>
{commentMediaInfo?.url ? (
-
setSelectedThread(thread.cid)}>
+
setSelectedThread(thread.cid)}>
{commentMediaInfo?.type === "webpage" ? (
thread.thumbnailUrl ? (
-
{
- e.target.src = fallbackImgUrl
- e.target.onerror = null;
- }} />
+
{
+ e.target.src = fallbackImgUrl
+ e.target.onerror = null;
+ }} />
) : null
) : null}
{commentMediaInfo?.type === "image" ? (
{
- e.target.src = fallbackImgUrl
- e.target.onerror = null;}} />
+ src={commentMediaInfo.url} alt={commentMediaInfo.type}
+ onError={(e) => {
+ e.target.src = fallbackImgUrl
+ e.target.onerror = null;
+ }} />
) : null}
{commentMediaInfo?.type === "video" ? (
-
e.target.src = fallbackImgUrl} />
+ e.target.src = fallbackImgUrl} />
) : null}
{commentMediaInfo?.type === "audio" ? (
- e.target.src = fallbackImgUrl} />
) : null}
) : null}
{(commentMediaInfo && (
- commentMediaInfo.type === 'image' ||
- commentMediaInfo.type === 'video' ||
- (commentMediaInfo.type === 'webpage' &&
- commentMediaInfo.thumbnail))) ? (
-
- {thread.pinned ? (
-
- ) : null}
- {thread.locked ? (
-
- ) : null}
-
+ commentMediaInfo.type === 'image' ||
+ commentMediaInfo.type === 'video' ||
+ (commentMediaInfo.type === 'webpage' &&
+ commentMediaInfo.thumbnail))) ? (
+
+ {thread.pinned ? (
+
+ ) : null}
+ {thread.locked ? (
+
+ ) : null}
+
) : null}
-
+
R:
{thread.replyCount}
{linkCount > 0 ? (
@@ -993,63 +1014,69 @@ const Catalog = () => {
>
) : null}
{(commentMediaInfo && (
- commentMediaInfo.type === 'image' ||
- commentMediaInfo.type === 'video' ||
- (commentMediaInfo.type === 'webpage' &&
- commentMediaInfo.thumbnail))) ? null : (
-
+ commentMediaInfo.type === 'image' ||
+ commentMediaInfo.type === 'video' ||
+ (commentMediaInfo.type === 'webpage' &&
+ commentMediaInfo.thumbnail))) ? null : (
+
{thread.pinned ? (
+ style={{
+ imageRendering: "pixelated",
+ }} />
) : null}
{thread.locked ? (
+ style={{
+ imageRendering: "pixelated",
+ }} />
) : null}
)}
-
{
- threadMenuRefs.current[thread.cid] = el;
- postMenuRef.current = el;
- }}
- className='post-menu-button'
- id='post-menu-button-catalog'
- rotated={openMenuCid === thread.cid}
- onClick={(event) => {
- event.stopPropagation();
- const rect = threadMenuRefs.current[thread.cid].getBoundingClientRect();
- setMenuPosition({top: rect.top + window.scrollY, left: rect.left});
- setOpenMenuCid(prevCid => (prevCid === thread.cid ? null : thread.cid));
- }}
- >
- ▶
-
+
{
+ threadMenuRefs.current[thread.cid] = el;
+ postMenuRef.current = el;
+ }}
+ className='post-menu-button'
+ id='post-menu-button-catalog'
+ rotated={openMenuCid === thread.cid}
+ onClick={(event) => {
+ event.stopPropagation();
+ const rect = threadMenuRefs.current[thread.cid].getBoundingClientRect();
+ setMenuPosition({ top: rect.top + window.scrollY, left: rect.left });
+ setOpenMenuCid(prevCid => (prevCid === thread.cid ? null : thread.cid));
+ }}
+ >
+ ▶
+
{createPortal(
-
{postMenuCatalogRef.current = el}}
+ { postMenuCatalogRef.current = el }}
onClick={(event) => event.stopPropagation()}
- style={{position: "absolute",
- top: menuPosition.top + 7,
- left: menuPosition.left}}>
+ style={{
+ position: "absolute",
+ top: menuPosition.top + 7,
+ left: menuPosition.left
+ }}>
handleOptionClick(thread.cid)}>Hide thread
{({ authorAddress }) => (
<>
- {authorAddress === account?.author.address ||
- authorAddress === account?.signer.address ? (
+ {authorAddress === account?.author.address ||
+ authorAddress === account?.signer.address ? (
<>
handleAuthorEditClick(thread)}>Edit post
handleAuthorDeleteClick(thread)}>Delete post
@@ -1058,24 +1085,24 @@ const Catalog = () => {
{isModerator ? (
<>
{authorAddress === account?.author.address ||
- authorAddress === account?.signer.address ? (
+ authorAddress === account?.signer.address ? (
null
) : (
{
setModeratingCommentCid(thread.cid)
- setIsModerationOpen(true);
+ setIsModerationOpen(true);
handleOptionClick(thread.cid);
setDeletePost(true);
}}>
- Delete post
+ Delete post
)}
{
- setModeratingCommentCid(thread.cid)
- setIsModerationOpen(true);
- handleOptionClick(thread.cid);
- }}>
+ onClick={() => {
+ setModeratingCommentCid(thread.cid)
+ setIsModerationOpen(true);
+ handleOptionClick(thread.cid);
+ }}>
Mod tools
>
@@ -1083,44 +1110,44 @@ const Catalog = () => {
>
)}
{(commentMediaInfo && (
- commentMediaInfo.type === 'image' ||
- (commentMediaInfo.type === 'webpage' &&
- commentMediaInfo.thumbnail))) ? (
- {setIsImageSearchOpen(true)}}
- onMouseLeave={() => {setIsImageSearchOpen(false)}}>
- Image search »
-
+
+
+ ) : null
}
, document.body
)}
- setSelectedThread(thread.cid)}>
+ setSelectedThread(thread.cid)}>
{thread.title ? `${thread.title}` : null}
{thread.content ? `: ${thread.content}` : null}
@@ -1128,13 +1155,10 @@ const Catalog = () => {
)
- }
- }}
- endReached={tryLoadMore}
- useWindowScroll={true}
- components={{List: GridContainer}}
- />
- ) : ( )}
+ })}
+
+ ) : ( )
+ )}
{
marginTop: "2px",
}}>
Style:
-
+
Yotsuba
Yotsuba B
@@ -1163,43 +1187,43 @@ const Catalog = () => {
marginTop: "42px",
}}>
<>
-
- [
+
+ [
window.scrollTo(0, 0)}>All
- /
+ /
window.scrollTo(0, 0)}>Subscriptions
- ]
-
- {defaultSubplebbits.map((subplebbit, index) => (
-
- {index === 0 ? null : "\u00a0"}
- {
- setSelectedTitle(subplebbit.title);
- setSelectedAddress(subplebbit.address);
- }}
- >{subplebbit.title ? subplebbit.title : subplebbit.address}
- {index !== defaultSubplebbits.length - 1 ? " /" : null}
+ ]
- ))}
+ {defaultSubplebbits.map((subplebbit, index) => (
+
+ {index === 0 ? null : "\u00a0"}
+ {
+ setSelectedTitle(subplebbit.title);
+ setSelectedAddress(subplebbit.address);
+ }}
+ >{subplebbit.title ? subplebbit.title : subplebbit.address}
+ {index !== defaultSubplebbits.length - 1 ? " /" : null}
+
+ ))}
- [
- {
- window.electron && window.electron.isElectron ? (
- setIsCreateBoardOpen(true)
- ) : (
- alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n'
- )
- )
- }
- }>Create Board
- ]
+ [
+ {
+ window.electron && window.electron.isElectron ? (
+ setIsCreateBoardOpen(true)
+ ) : (
+ alert(
+ 'You can create a board with the desktop version of plebchan, which you can download from here: https://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can also run a board (called "subplebbit") using plebbit-cli: https://github.com/plebbit/plebbit-cli\n\n'
+ )
+ )
+ }
+ }>Create Board
+ ]
[
setIsSettingsOpen(true)}>Settings
]
[
- handleStyleChange({target: {value: "Yotsuba"}}
+ handleStyleChange({ target: { value: "Yotsuba" } }
)}>Home
]
@@ -1216,13 +1240,13 @@ const Catalog = () => {
marginTop: "5px",
marginBottom: "15px",
}}>
- About
- •
- App
+ About
•
- Twitter
- •
- Telegram
+ App
+ •
+ Twitter
+ •
+ Telegram
diff --git a/src/components/views/Description.jsx b/src/components/views/Description.jsx
index 322ac86c..f322a0dc 100644
--- a/src/components/views/Description.jsx
+++ b/src/components/views/Description.jsx
@@ -1,25 +1,25 @@
+import { useSubplebbit } from '@plebbit/plebbit-react-hooks';
+import { debounce } from 'lodash';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { Helmet } from 'react-helmet-async';
import { Link, useNavigate, useParams } from 'react-router-dom';
import { Tooltip } from 'react-tooltip';
-import { useSubplebbit } from '@plebbit/plebbit-react-hooks';
-import { debounce } from 'lodash';
-import { Container, NavBar, Header, Break, PostMenu, PostForm } from '../styled/views/Board.styled';
-import { TopBar, BoardForm, Footer, ReplyFormLink} from '../styled/views/Thread.styled';
-import { PostMenuCatalog } from '../styled/views/Catalog.styled';
-import ImageBanner from '../ImageBanner';
-import Post from '../Post';
-import CreateBoardModal from '../modals/CreateBoardModal';
-import AdminListModal from '../modals/AdminListModal';
-import OfflineIndicator from '../OfflineIndicator';
-import SettingsModal from '../modals/SettingsModal';
+import packageJson from '../../../package.json';
+import useGeneralStore from '../../hooks/stores/useGeneralStore';
import getDate from '../../utils/getDate';
import handleImageClick from '../../utils/handleImageClick';
import handleStyleChange from '../../utils/handleStyleChange';
-import useGeneralStore from '../../hooks/stores/useGeneralStore';
-import packageJson from '../../../package.json'
-const {version} = packageJson
+import ImageBanner from '../ImageBanner';
+import OfflineIndicator from '../OfflineIndicator';
+import Post from '../Post';
+import AdminListModal from '../modals/AdminListModal';
+import CreateBoardModal from '../modals/CreateBoardModal';
+import SettingsModal from '../modals/SettingsModal';
+import { Break, Container, Header, NavBar, PostForm, PostMenu } from '../styled/views/Board.styled';
+import { PostMenuCatalog } from '../styled/views/Catalog.styled';
+import { BoardForm, Footer, ReplyFormLink, TopBar } from '../styled/views/Thread.styled';
+const { version } = packageJson
const Description = () => {
@@ -31,7 +31,7 @@ const Description = () => {
selectedThread,
setSelectedTitle,
} = useGeneralStore(state => state);
-
+
const navigate = useNavigate();
const threadMenuRefs = useRef({});
@@ -41,13 +41,13 @@ const Description = () => {
const [isAdminListOpen, setIsAdminListOpen] = useState(false);
const [prevScrollPos, setPrevScrollPos] = useState(0);
const [visible, setVisible] = useState(true);
- const [menuPosition, setMenuPosition] = useState({top: 0, left: 0});
+ const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 });
const [openMenuCid, setOpenMenuCid] = useState(null);
const [isCreateBoardOpen, setIsCreateBoardOpen] = useState(false);
- const { subplebbitAddress } = useParams();
- const subplebbit = useSubplebbit({subplebbitAddress: selectedAddress});
-
+ const { subplebbitAddress, threadCid } = useParams();
+ const subplebbit = useSubplebbit({ subplebbitAddress: selectedAddress });
+
const handleOptionClick = () => {
setOpenMenuCid(null);
@@ -66,13 +66,13 @@ const Description = () => {
} else {
document.removeEventListener('click', handleOutsideClick);
}
-
+
return () => {
document.removeEventListener('click', handleOutsideClick);
};
}, [openMenuCid, handleOutsideClick]);
-
+
useEffect(() => {
window.scrollTo(0, 0);
}, []);
@@ -99,9 +99,9 @@ const Description = () => {
setVisible(prevScrollPos > currentScrollPos || currentScrollPos < 10);
setPrevScrollPos(currentScrollPos);
}, 50);
-
+
window.addEventListener('scroll', debouncedHandleScroll);
-
+
return () => window.removeEventListener('scroll', debouncedHandleScroll);
}, [prevScrollPos, visible]);
@@ -127,57 +127,57 @@ const Description = () => {
return (
<>
-
+
{"Board Description - " + (subplebbit.title || subplebbit.address) + " - plebchan"}
-
-
+
+
setIsCreateBoardOpen(false)} />
+ selectedStyle={selectedStyle}
+ isOpen={isCreateBoardOpen}
+ closeModal={() => setIsCreateBoardOpen(false)} />
setIsAdminListOpen(false)}
- roles={subplebbit.roles} />
+ selectedStyle={selectedStyle}
+ isOpen={isAdminListOpen}
+ closeModal={() => setIsAdminListOpen(false)}
+ roles={subplebbit.roles} />
setIsSettingsOpen(false)} />
+ selectedStyle={selectedStyle}
+ isOpen={isSettingsOpen}
+ closeModal={() => setIsSettingsOpen(false)} />
<>
-
- [
+
+ [
window.scrollTo(0, 0)}>All
- /
+ /
window.scrollTo(0, 0)}>Subscriptions
- ] [
- {defaultSubplebbits.map((subplebbit, index) => (
-
- {index === 0 ? null : "\u00a0"}
- {
- setSelectedTitle(subplebbit.title);
- setSelectedAddress(subplebbit.address);
- }}
- >{subplebbit.title ? subplebbit.title : subplebbit.address}
- {index !== defaultSubplebbits.length - 1 ? " /" : null}
-
- ))}
- ]
-
+ ] [
+ {defaultSubplebbits.map((subplebbit, index) => (
+
+ {index === 0 ? null : "\u00a0"}
+ {
+ setSelectedTitle(subplebbit.title);
+ setSelectedAddress(subplebbit.address);
+ }}
+ >{subplebbit.title ? subplebbit.title : subplebbit.address}
+ {index !== defaultSubplebbits.length - 1 ? " /" : null}
+
+ ))}
+ ]
+
[
- {
- window.electron && window.electron.isElectron ? (
- setIsCreateBoardOpen(true)
- ) : (
- alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n'
+ {
+ window.electron && window.electron.isElectron ? (
+ setIsCreateBoardOpen(true)
+ ) : (
+ alert(
+ 'You can create a board with the desktop version of plebchan, which you can download from here: https://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can also run a board (called "subplebbit") using plebbit-cli: https://github.com/plebbit/plebbit-cli\n\n'
+ )
)
- )
- }
+ }
}>Create Board
]
[
@@ -196,20 +196,20 @@ const Description = () => {
All
Subscriptions
{defaultSubplebbits.map(subplebbit => (
- {subplebbit.title ? subplebbit.title : subplebbit.address}
- ))}
-
- alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n'
+ {subplebbit.title ? subplebbit.title : subplebbit.address}
+ ))}
+
+ alert(
+ 'You can create a board with the desktop version of plebchan, which you can download from here: https://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can also run a board (called "subplebbit") using plebbit-cli: https://github.com/plebbit/plebbit-cli\n\n'
)
}>Create Board
setIsSettingsOpen(true)}>Settings
- {handleStyleChange({target: {value: "Yotsuba"}}); window.scrollTo(0, 0);}}>Home
+ { handleStyleChange({ target: { value: "Yotsuba" } }); window.scrollTo(0, 0); }}>Home
@@ -222,33 +222,43 @@ const Description = () => {
- <>
+ <>
{subplebbit.title ?? null}
p/{subplebbit.address}
-
+
- >
+ >
>
-
-
)}
- >
+ >
>
@@ -440,7 +439,7 @@ const SubscriptionsCatalog = () => {
Style:
-
+
Yotsuba
Yotsuba B
@@ -455,15 +454,27 @@ const SubscriptionsCatalog = () => {
Return
]
+
+ [
+ window.location.reload()}
+ onMouseOver={(event) => event.target.style.cursor = 'pointer'}
+ onTouchStart={() => window.location.reload()}>Refresh
+ ]
+
Return
+
+
+ Refresh
+
+
{subplebbits.state === "succeeded" ? (
null
) : (
-
+
{stateString}
)}
@@ -471,75 +482,76 @@ const SubscriptionsCatalog = () => {
- {feed.length > 1 ? (
- {
- const thread = feed[index];
+ {feed ? (
+
+ {feed.map((thread, index) => {
const commentMediaInfo = getCommentMediaInfo(thread);
const fallbackImgUrl = "assets/filedeleted-res.gif";
const isModerator = moderatorPermissions[thread.subplebbitAddress];
const linkCount = countLinks(thread);
return (
- {setIsHoveringOnThread(thread.cid)}}
- onMouseLeave={() => {setIsHoveringOnThread('')}}>
+
{ setIsHoveringOnThread(thread.cid) }}
+ onMouseLeave={() => { setIsHoveringOnThread('') }}>
{commentMediaInfo?.url ? (
-
setSelectedThread(thread.cid)}>
+
setSelectedThread(thread.cid)}>
{commentMediaInfo?.type === "webpage" ? (
thread.thumbnailUrl ? (
-
{
- e.target.src = fallbackImgUrl
- e.target.onerror = null;
- }} />
+
{
+ e.target.src = fallbackImgUrl
+ e.target.onerror = null;
+ }} />
) : null
) : null}
{commentMediaInfo?.type === "image" ? (
{
- e.target.src = fallbackImgUrl
- e.target.onerror = null;}} />
+ src={commentMediaInfo.url} alt={commentMediaInfo.type}
+ onError={(e) => {
+ e.target.src = fallbackImgUrl
+ e.target.onerror = null;
+ }} />
) : null}
{commentMediaInfo?.type === "video" ? (
-
e.target.src = fallbackImgUrl} />
+ e.target.src = fallbackImgUrl} />
) : null}
{commentMediaInfo?.type === "audio" ? (
- e.target.src = fallbackImgUrl} />
) : null}
) : null}
- {(commentMediaInfo && (
- commentMediaInfo.type === 'image' ||
- commentMediaInfo.type === 'video' ||
- (commentMediaInfo.type === 'webpage' &&
- commentMediaInfo.thumbnail))) ? (
-
+ {(commentMediaInfo && (
+ commentMediaInfo.type === 'image' ||
+ commentMediaInfo.type === 'video' ||
+ (commentMediaInfo.type === 'webpage' &&
+ commentMediaInfo.thumbnail))) ? (
+
) : (
-
- )}
+
+ )}
-
+
R:
{thread.replyCount}
{linkCount > 0 ? (
@@ -548,45 +560,49 @@ const SubscriptionsCatalog = () => {
L:
{linkCount}
>
) : null}
-
{
- threadMenuRefs.current[thread.cid] = el;
- postMenuRef.current = el;
- }}
- className='post-menu-button'
- id='post-menu-button-catalog'
- rotated={openMenuCid === thread.cid}
- onClick={(event) => {
- event.stopPropagation();
- const rect = threadMenuRefs.current[thread.cid].getBoundingClientRect();
- setMenuPosition({top: rect.top + window.scrollY, left: rect.left});
- setOpenMenuCid(prevCid => (prevCid === thread.cid ? null : thread.cid));
- }}
- >
- ▶
-
+
{
+ threadMenuRefs.current[thread.cid] = el;
+ postMenuRef.current = el;
+ }}
+ className='post-menu-button'
+ id='post-menu-button-catalog'
+ rotated={openMenuCid === thread.cid}
+ onClick={(event) => {
+ event.stopPropagation();
+ const rect = threadMenuRefs.current[thread.cid].getBoundingClientRect();
+ setMenuPosition({ top: rect.top + window.scrollY, left: rect.left });
+ setOpenMenuCid(prevCid => (prevCid === thread.cid ? null : thread.cid));
+ }}
+ >
+ ▶
+
{createPortal(
- {postMenuCatalogRef.current = el}}
+ { postMenuCatalogRef.current = el }}
onClick={(event) => event.stopPropagation()}
- style={{position: "absolute",
- top: menuPosition.top + 7,
- left: menuPosition.left}}>
+ style={{
+ position: "absolute",
+ top: menuPosition.top + 7,
+ left: menuPosition.left
+ }}>
handleOptionClick(thread.cid)}>Hide thread
{({ authorAddress }) => (
<>
- {authorAddress === account?.author.address ||
- authorAddress === account?.signer.address ? (
+ {authorAddress === account?.author.address ||
+ authorAddress === account?.signer.address ? (
<>
handleAuthorEditClick(thread)}>Edit post
handleAuthorDeleteClick(thread)}>Delete post
@@ -595,26 +611,26 @@ const SubscriptionsCatalog = () => {
{isModerator ? (
<>
{authorAddress === account?.author.address ||
- authorAddress === account?.signer.address ? (
+ authorAddress === account?.signer.address ? (
null
) : (
{
setSelectedAddress(thread.subplebbitAddress);
setModeratingCommentCid(thread.cid)
- setIsModerationOpen(true);
+ setIsModerationOpen(true);
handleOptionClick(thread.cid);
setDeletePost(true);
}}>
- Delete post
+ Delete post
)}
{
- setSelectedAddress(thread.subplebbitAddress);
- setModeratingCommentCid(thread.cid)
- setIsModerationOpen(true);
- handleOptionClick(thread.cid);
- }}>
+ onClick={() => {
+ setSelectedAddress(thread.subplebbitAddress);
+ setModeratingCommentCid(thread.cid)
+ setIsModerationOpen(true);
+ handleOptionClick(thread.cid);
+ }}>
Mod tools
>
@@ -622,57 +638,56 @@ const SubscriptionsCatalog = () => {
>
)}
{(commentMediaInfo && (
- commentMediaInfo.type === 'image' ||
- (commentMediaInfo.type === 'webpage' &&
- commentMediaInfo.thumbnail))) ? (
- {setIsImageSearchOpen(true)}}
- onMouseLeave={() => {setIsImageSearchOpen(false)}}>
- Image search »
-
+
+
+ ) : null
}
, document.body
)}
- setSelectedThread(thread.cid)}>
+ setSelectedThread(thread.cid)}>
{thread.title ? `${thread.title}` : null}
{thread.content ? `: ${thread.content}` : null}
-
+
)
- }}
- endReached={tryLoadMore}
- useWindowScroll={true}
- components={{List: GridContainer}}
- />
- ) : ( )}
+ })}
+
+ ) : (
+
+ )}
{
marginTop: "2px",
}}>
Style:
-
+
Yotsuba
Yotsuba B
@@ -700,40 +715,40 @@ const SubscriptionsCatalog = () => {
- <>
-
- [
+ <>
+
+ [
window.scrollTo(0, 0)}>Subscriptions
- ] [
- {defaultSubplebbits.map((subplebbit, index) => (
-
- {index === 0 ? null : "\u00a0"}
- handleClickTitle(subplebbit.title, subplebbit.address)}
- >{subplebbit.title ? subplebbit.title : subplebbit.address}
- {index !== defaultSubplebbits.length - 1 ? " /" : null}
-
- ))}
- ]
-
+ ] [
+ {defaultSubplebbits.map((subplebbit, index) => (
+
+ {index === 0 ? null : "\u00a0"}
+ handleClickTitle(subplebbit.title, subplebbit.address)}
+ >{subplebbit.title ? subplebbit.title : subplebbit.address}
+ {index !== defaultSubplebbits.length - 1 ? " /" : null}
+
+ ))}
+ ]
+
- [
- {
- window.electron && window.electron.isElectron ? (
- setIsCreateBoardOpen(true)
- ) : (
- alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n'
- )
- )
- }
- }>Create Board
- ]
+ [
+ {
+ window.electron && window.electron.isElectron ? (
+ setIsCreateBoardOpen(true)
+ ) : (
+ alert(
+ 'You can create a board with the desktop version of plebchan, which you can download from here: https://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can also run a board (called "subplebbit") using plebbit-cli: https://github.com/plebbit/plebbit-cli\n\n'
+ )
+ )
+ }
+ }>Create Board
+ ]
[
setIsSettingsOpen(true)}>Settings
]
[
- handleStyleChange({target: {value: "Yotsuba"}}
+ handleStyleChange({ target: { value: "Yotsuba" } }
)}>Home
]
@@ -750,13 +765,13 @@ const SubscriptionsCatalog = () => {
marginTop: "5px",
marginBottom: "15px",
}}>
- About
- •
- App
+ About
•
- Twitter
- •
- Telegram
+ App
+ •
+ Twitter
+ •
+ Telegram
diff --git a/src/components/views/Thread.jsx b/src/components/views/Thread.jsx
index a3988d30..c4e1d53a 100755
--- a/src/components/views/Thread.jsx
+++ b/src/components/views/Thread.jsx
@@ -41,7 +41,7 @@ import useSuccess from '../../hooks/useSuccess';
import useAnonModeStore from '../../hooks/stores/useAnonModeStore';
import useGeneralStore from '../../hooks/stores/useGeneralStore';
import packageJson from '../../../package.json'
-const {version} = packageJson
+const { version } = packageJson
const Thread = () => {
@@ -73,7 +73,7 @@ const Thread = () => {
} = useGeneralStore(state => state);
const { anonymousMode } = useAnonModeStore();
-
+
const account = useAccount();
const navigate = useNavigate();
const handleClickForm = useClickForm();
@@ -106,10 +106,10 @@ const Thread = () => {
const [isImageSearchOpen, setIsImageSearchOpen] = useState(false);
const [isModerator, setIsModerator] = useState(false);
const [commentCid, setCommentCid] = useState(null);
- const [menuPosition, setMenuPosition] = useState({top: 0, left: 0});
+ const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 });
const [openMenuCid, setOpenMenuCid] = useState(null);
const [outOfViewCid, setOutOfViewCid] = useState(null);
- const [outOfViewPosition, setOutOfViewPosition] = useState({top: 0, left: 0});
+ const [outOfViewPosition, setOutOfViewPosition] = useState({ top: 0, left: 0 });
const [postOnHoverHeight, setPostOnHoverHeight] = useState(0);
const [executeAnonMode, setExecuteAnonMode] = useState(false);
const [cidTracker, setCidTracker] = useState({});
@@ -121,9 +121,9 @@ const Thread = () => {
useAnonMode(selectedThread, anonymousMode && executeAnonMode);
- const comment = useComment({commentCid: selectedThread});
+ const comment = useComment({ commentCid: selectedThread });
const { subplebbitAddress, threadCid } = useParams();
- const subplebbit = useSubplebbit({subplebbitAddress: comment.subplebbitAddress});
+ const subplebbit = useSubplebbit({ subplebbitAddress: comment.subplebbitAddress });
const selectedAddress = subplebbit.address;
const stateString = useStateString(comment);
@@ -159,17 +159,17 @@ const Thread = () => {
useEffect(() => {
- if (subplebbit.roles !== undefined) {
+ if (subplebbit.roles !== undefined) {
const role = subplebbit.roles[account?.author?.address]?.role;
-
+
if (role === 'moderator' || role === 'admin' || role === 'owner') {
setIsModerator(true);
} else {
setIsModerator(false);
}
}
- }, [account?.author.address, subplebbit.roles]);
-
+ }, [account?.author.address, subplebbit.roles]);
+
const handleOptionClick = () => {
setOpenMenuCid(null);
@@ -187,7 +187,7 @@ const Thread = () => {
} else {
document.removeEventListener('click', handleOutsideClick);
}
-
+
return () => {
document.removeEventListener('click', handleOutsideClick);
};
@@ -201,14 +201,14 @@ const Thread = () => {
}
}, [outOfViewCid]);
-
+
useEffect(() => {
window.scrollTo(0, 0);
}, []);
useEffect(() => {
- if ( comment.state === "failed" && selectedAddress === undefined) {
+ if (comment.state === "failed" && selectedAddress === undefined) {
navigate('/404');
}
}, [selectedAddress, navigate, comment.state]);
@@ -232,7 +232,7 @@ const Thread = () => {
}, [errorString, setNewErrorMessage]);
- const flattenedReplies = useMemo(() =>
+ const flattenedReplies = useMemo(() =>
flattenCommentsPages(comment.replies), [comment.replies]
);
@@ -244,7 +244,7 @@ const Thread = () => {
}), [flattenedReplies, selectedThread]);
- const { accountComments } = useAccountComments({filter});
+ const { accountComments } = useAccountComments({ filter });
const accountRepliesNotYetInCommentReplies = useMemo(() => {
@@ -255,7 +255,7 @@ const Thread = () => {
const sortedReplies = useMemo(() => [
...accountRepliesNotYetInCommentReplies, ...flattenedReplies
- ].sort((a, b) => a.timestamp - b.timestamp
+ ].sort((a, b) => a.timestamp - b.timestamp
), [accountRepliesNotYetInCommentReplies, flattenedReplies]);
// let post.jsx access full cid of user-typed short cid
@@ -292,13 +292,13 @@ const Thread = () => {
setVisible(prevScrollPos > currentScrollPos || currentScrollPos < 10);
setPrevScrollPos(currentScrollPos);
}, 50);
-
+
window.addEventListener('scroll', debouncedHandleScroll);
-
+
return () => window.removeEventListener('scroll', debouncedHandleScroll);
}, [prevScrollPos, visible]);
-
+
const onChallengeVerification = (challengeVerification) => {
if (challengeVerification.challengeSuccess === true) {
if (challengeVerification.publication?.cid !== undefined) {
@@ -316,7 +316,7 @@ const Thread = () => {
const onChallenge = async (challenges, comment) => {
setPendingComment(comment);
let challengeAnswers = [];
-
+
try {
challengeAnswers = await getChallengeAnswersFromUser(challenges)
}
@@ -328,7 +328,7 @@ const Thread = () => {
}
};
-
+
useEffect(() => {
setPublishCommentOptions((prevPublishCommentOptions) => ({
...prevPublishCommentOptions,
@@ -336,7 +336,7 @@ const Thread = () => {
}));
}, [comment.subplebbitAddress]);
-
+
const [publishCommentOptions, setPublishCommentOptions] = useState({
subplebbitAddress: comment.subplebbitAddress,
onChallenge,
@@ -356,7 +356,7 @@ const Thread = () => {
}
}, [index, setPendingCommentIndex]);
-
+
const resetFields = useCallback(() => {
if (nameRef.current) {
nameRef.current.value = '';
@@ -380,8 +380,8 @@ const Thread = () => {
setNewErrorMessage("Please enter a comment or link.");
return;
}
-
-
+
+
setPublishCommentOptions((prevPublishCommentOptions) => ({
...prevPublishCommentOptions,
author: {
@@ -395,28 +395,28 @@ const Thread = () => {
setTriggerPublishComment(true);
};
-
+
const updateSigner = useCallback(async () => {
if (anonymousMode) {
setExecuteAnonMode(true);
-
+
let storedSigners = JSON.parse(localStorage.getItem('storedSigners')) || {};
let signer;
-
+
if (!storedSigners[selectedThread]) {
signer = await account?.plebbit.createSigner();
storedSigners[selectedThread] = { privateKey: signer?.privateKey, address: signer?.address };
localStorage.setItem('storedSigners', JSON.stringify(storedSigners));
} else {
const signerPrivateKey = storedSigners[selectedThread].privateKey;
-
+
try {
- signer = await account?.plebbit.createSigner({type: 'ed25519', privateKey: signerPrivateKey});
+ signer = await account?.plebbit.createSigner({ type: 'ed25519', privateKey: signerPrivateKey });
} catch (error) {
console.log(error);
}
}
-
+
setPublishCommentOptions(prevPublishCommentOptions => {
const newPublishCommentOptions = {
...prevPublishCommentOptions,
@@ -426,23 +426,23 @@ const Thread = () => {
address: signer?.address
},
};
-
+
if (JSON.stringify(prevPublishCommentOptions) !== JSON.stringify(newPublishCommentOptions)) {
return newPublishCommentOptions;
}
-
+
return prevPublishCommentOptions;
});
}
}, [selectedThread, anonymousMode, account]);
-
+
useEffect(() => {
if (anonymousMode) {
updateSigner();
}
}, [updateSigner, anonymousMode]);
-
-
+
+
useEffect(() => {
if (publishCommentOptions && triggerPublishComment) {
(async () => {
@@ -457,16 +457,16 @@ const Thread = () => {
const getChallengeAnswersFromUser = async (challenges) => {
setChallengesArray(challenges);
-
+
return new Promise((resolve, reject) => {
const imageString = challenges?.challenges[0].challenge;
const imageSource = `data:image/png;base64,${imageString}`;
const challengeImg = new Image();
challengeImg.src = imageSource;
-
+
challengeImg.onload = () => {
setIsCaptchaOpen(true);
-
+
const handleKeyDown = async (event) => {
if (event.key === 'Enter') {
const currentCaptchaResponse = captchaResponse;
@@ -482,7 +482,7 @@ const Thread = () => {
setResolveCaptchaPromise(resolve);
};
-
+
challengeImg.onerror = () => {
reject(setNewErrorMessage('Could not load challenges'));
};
@@ -500,8 +500,8 @@ const Thread = () => {
setNewErrorMessage(error.message); console.log(error);
},
});
-
-
+
+
const { publishCommentEdit } = usePublishCommentEdit(publishCommentEditOptions);
@@ -548,8 +548,8 @@ const Thread = () => {
setOriginalCommentContent(comment.content);
setIsEditModalOpen(true);
}
-
-
+
+
useEffect(() => {
setPublishCommentEditOptions((prevOptions) => ({
...prevOptions,
@@ -565,7 +565,7 @@ const Thread = () => {
}
}, [editedComment]);
-
+
useEffect(() => {
let isActive = true;
if (publishCommentEditOptions && triggerPublishCommentEdit) {
@@ -604,70 +604,70 @@ const Thread = () => {
return (
<>
-
- {(
- (comment.content?.slice(0, 40) ?? comment.title?.slice(0, 40) ?? "Thread") + " - "
- + (selectedTitle ? selectedTitle : selectedAddress)
- + " - plebchan"
- )}
-
-
+
+ {(
+ (comment.content?.slice(0, 40) ?? comment.title?.slice(0, 40) ?? "Thread") + " - "
+ + (selectedTitle ? selectedTitle : selectedAddress)
+ + " - plebchan"
+ )}
+
+
setIsCreateBoardOpen(false)} />
- setIsReplyOpen(false)} />
+ selectedStyle={selectedStyle}
+ isOpen={isCreateBoardOpen}
+ closeModal={() => setIsCreateBoardOpen(false)} />
+ setIsReplyOpen(false)} />
setIsSettingsOpen(false)} />
- {setIsModerationOpen(false); setDeletePost(false)}}
- deletePost={deletePost} />
+ selectedStyle={selectedStyle}
+ isOpen={isSettingsOpen}
+ closeModal={() => setIsSettingsOpen(false)} />
+ { setIsModerationOpen(false); setDeletePost(false) }}
+ deletePost={deletePost} />
setIsEditModalOpen(false)}
- originalCommentContent={originalCommentContent} />
+ selectedStyle={selectedStyle}
+ isOpen={isEditModalOpen}
+ closeModal={() => setIsEditModalOpen(false)}
+ originalCommentContent={originalCommentContent} />
<>
-
- [
+
+ [
window.scrollTo(0, 0)}>All
- /
+ /
window.scrollTo(0, 0)}>Subscriptions
- ] [
- {defaultSubplebbits.map((subplebbit, index) => (
-
- {index === 0 ? null : "\u00a0"}
- {
- setSelectedTitle(subplebbit.title);
- setSelectedAddress(subplebbit.address);
- }}
- >{subplebbit.title ? subplebbit.title : subplebbit.address}
- {index !== defaultSubplebbits.length - 1 ? " /" : null}
-
- ))}
- ]
-
+ ] [
+ {defaultSubplebbits.map((subplebbit, index) => (
+
+ {index === 0 ? null : "\u00a0"}
+ {
+ setSelectedTitle(subplebbit.title);
+ setSelectedAddress(subplebbit.address);
+ }}
+ >{subplebbit.title ? subplebbit.title : subplebbit.address}
+ {index !== defaultSubplebbits.length - 1 ? " /" : null}
+
+ ))}
+ ]
+
[
- {
- window.electron && window.electron.isElectron ? (
- setIsCreateBoardOpen(true)
- ) : (
- alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n'
+ {
+ window.electron && window.electron.isElectron ? (
+ setIsCreateBoardOpen(true)
+ ) : (
+ alert(
+ 'You can create a board with the desktop version of plebchan, which you can download from here: https://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can also run a board (called "subplebbit") using plebbit-cli: https://github.com/plebbit/plebbit-cli\n\n'
+ )
)
- )
- }
+ }
}>Create Board
]
[
@@ -686,20 +686,20 @@ const Thread = () => {
All
Subscriptions
{defaultSubplebbits.map(subplebbit => (
- {subplebbit.title ? subplebbit.title : subplebbit.address}
- ))}
-
- alert(
- 'You can create a board with the desktop version of plebchan:\nhttps://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, use plebbit-cli:\nhttps://github.com/plebbit/plebbit-cli\n\n'
+ {subplebbit.title ? subplebbit.title : subplebbit.address}
+ ))}
+
+ alert(
+ 'You can create a board with the desktop version of plebchan, which you can download from here: https://github.com/plebbit/plebchan/releases/latest\n\nIf you are comfortable with the command line, you can also run a board (called "subplebbit") using plebbit-cli: https://github.com/plebbit/plebbit-cli\n\n'
)
}>Create Board