mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
add fully styled author edits ui and tested logic
This commit is contained in:
@@ -7,6 +7,7 @@ import Draggable from 'react-draggable';
|
|||||||
|
|
||||||
const EditModal = ({ isOpen, closeModal, originalCommentContent }) => {
|
const EditModal = ({ isOpen, closeModal, originalCommentContent }) => {
|
||||||
const {
|
const {
|
||||||
|
setEditedComment,
|
||||||
selectedStyle,
|
selectedStyle,
|
||||||
} = useGeneralStore(state => state);
|
} = useGeneralStore(state => state);
|
||||||
|
|
||||||
@@ -27,6 +28,10 @@ const EditModal = ({ isOpen, closeModal, originalCommentContent }) => {
|
|||||||
}, [setIsMobile]);
|
}, [setIsMobile]);
|
||||||
|
|
||||||
|
|
||||||
|
const handleSaveEdit = () => {
|
||||||
|
setEditedComment(commentRef.current.value);
|
||||||
|
closeModal();
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledModal
|
<StyledModal
|
||||||
@@ -47,13 +52,14 @@ const EditModal = ({ isOpen, closeModal, originalCommentContent }) => {
|
|||||||
<div className="textarea-wrapper">
|
<div className="textarea-wrapper">
|
||||||
<textarea className="textarea"
|
<textarea className="textarea"
|
||||||
rows="4"
|
rows="4"
|
||||||
|
style={{paddingTop: '0'}}
|
||||||
placeholder="Comment"
|
placeholder="Comment"
|
||||||
defaultValue={originalCommentContent}
|
defaultValue={originalCommentContent}
|
||||||
wrap="soft"
|
wrap="soft"
|
||||||
ref={commentRef} />
|
ref={commentRef} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<button id="next">Save</button>
|
<button id="next" onClick={handleSaveEdit}>Save</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3208,17 +3208,76 @@ export const Footer = styled.div`
|
|||||||
|
|
||||||
export const AuthorDeleteAlert = styled.div`
|
export const AuthorDeleteAlert = styled.div`
|
||||||
.author-delete-alert {
|
.author-delete-alert {
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
background: #fff;
|
border: 1px solid #ccc;
|
||||||
border-radius: 5px;
|
|
||||||
box-shadow: 0 0 10px 0 rgba(0,0,0,.25);
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 40%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
|
.author-delete-buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
& > button {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > button:first-child {
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
${({ selectedStyle }) => {
|
||||||
|
switch (selectedStyle) {
|
||||||
|
case 'Yotsuba':
|
||||||
|
return `
|
||||||
|
.author-delete-alert {
|
||||||
|
background-color: #f0e0d6;
|
||||||
|
border: 1px solid #d9bfb7;
|
||||||
|
}`;
|
||||||
|
|
||||||
|
case 'Yotsuba-B':
|
||||||
|
return `
|
||||||
|
.author-delete-alert {
|
||||||
|
background-color: #d6daf0;
|
||||||
|
border: 1px solid #b7c5d9;
|
||||||
|
}`;
|
||||||
|
|
||||||
|
case 'Futaba':
|
||||||
|
return `
|
||||||
|
.author-delete-alert {
|
||||||
|
background-color: #f0e0d6;
|
||||||
|
border: 1px solid #d9bfb7;
|
||||||
|
}`;
|
||||||
|
|
||||||
|
case 'Burichan':
|
||||||
|
return `
|
||||||
|
.author-delete-alert {
|
||||||
|
background-color: #d6daf0;
|
||||||
|
border: 1px solid #b7c5d9;
|
||||||
|
}`;
|
||||||
|
|
||||||
|
case 'Tomorrow':
|
||||||
|
return `
|
||||||
|
.author-delete-alert {
|
||||||
|
background-color: #282a2e;
|
||||||
|
border: 1px solid #111;
|
||||||
|
}`;
|
||||||
|
|
||||||
|
case 'Photon':
|
||||||
|
return `
|
||||||
|
.author-delete-alert {
|
||||||
|
background-color: #ddd;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}`;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}}
|
||||||
`;
|
`;
|
||||||
+111
-100
@@ -37,6 +37,7 @@ const Thread = () => {
|
|||||||
captchaResponse, setCaptchaResponse,
|
captchaResponse, setCaptchaResponse,
|
||||||
setChallengesArray,
|
setChallengesArray,
|
||||||
defaultSubplebbits,
|
defaultSubplebbits,
|
||||||
|
editedComment,
|
||||||
setIsCaptchaOpen,
|
setIsCaptchaOpen,
|
||||||
isModerationOpen, setIsModerationOpen,
|
isModerationOpen, setIsModerationOpen,
|
||||||
isSettingsOpen, setIsSettingsOpen,
|
isSettingsOpen, setIsSettingsOpen,
|
||||||
@@ -78,7 +79,6 @@ const Thread = () => {
|
|||||||
const [isImageSearchOpen, setIsImageSearchOpen] = useState(false);
|
const [isImageSearchOpen, setIsImageSearchOpen] = useState(false);
|
||||||
const [isModerator, setIsModerator] = useState(false);
|
const [isModerator, setIsModerator] = useState(false);
|
||||||
const [commentCid, setCommentCid] = useState(null);
|
const [commentCid, setCommentCid] = useState(null);
|
||||||
const [editedComment, setEditedComment] = useState(null);
|
|
||||||
|
|
||||||
useError(errorMessage, [errorMessage]);
|
useError(errorMessage, [errorMessage]);
|
||||||
useSuccess(successMessage, [successMessage]);
|
useSuccess(successMessage, [successMessage]);
|
||||||
@@ -339,6 +339,7 @@ const Thread = () => {
|
|||||||
|
|
||||||
const [publishCommentEditOptions, setPublishCommentEditOptions] = useState({
|
const [publishCommentEditOptions, setPublishCommentEditOptions] = useState({
|
||||||
commentCid: commentCid,
|
commentCid: commentCid,
|
||||||
|
content: editedComment || undefined,
|
||||||
subplebbitAddress: selectedAddress,
|
subplebbitAddress: selectedAddress,
|
||||||
onChallenge,
|
onChallenge,
|
||||||
onChallengeVerification,
|
onChallengeVerification,
|
||||||
@@ -366,20 +367,22 @@ const Thread = () => {
|
|||||||
<AuthorDeleteAlert selectedStyle={selectedStyle}>
|
<AuthorDeleteAlert selectedStyle={selectedStyle}>
|
||||||
<div className='author-delete-alert'>
|
<div className='author-delete-alert'>
|
||||||
<p>Are you sure you want to delete this post?</p>
|
<p>Are you sure you want to delete this post?</p>
|
||||||
<button onClick={onClose}>No</button>
|
<div className="author-delete-buttons">
|
||||||
<button
|
<button onClick={onClose}>No</button>
|
||||||
onClick={() => {
|
<button
|
||||||
setCommentCid(commentCid);
|
onClick={() => {
|
||||||
setPublishCommentEditOptions(prevOptions => ({
|
setCommentCid(commentCid);
|
||||||
...prevOptions,
|
setPublishCommentEditOptions(prevOptions => ({
|
||||||
deleted: true,
|
...prevOptions,
|
||||||
}));
|
deleted: true,
|
||||||
setTriggerPublishCommentEdit(true);
|
}));
|
||||||
onClose();
|
setTriggerPublishCommentEdit(true);
|
||||||
}}
|
onClose();
|
||||||
>
|
}}
|
||||||
Yes
|
>
|
||||||
</button>
|
Yes
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</AuthorDeleteAlert>
|
</AuthorDeleteAlert>
|
||||||
);
|
);
|
||||||
@@ -399,8 +402,16 @@ const Thread = () => {
|
|||||||
setPublishCommentEditOptions((prevOptions) => ({
|
setPublishCommentEditOptions((prevOptions) => ({
|
||||||
...prevOptions,
|
...prevOptions,
|
||||||
commentCid: commentCid,
|
commentCid: commentCid,
|
||||||
|
content: editedComment || undefined,
|
||||||
}));
|
}));
|
||||||
}, [commentCid]);
|
}, [commentCid, editedComment]);
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (editedComment !== '') {
|
||||||
|
setTriggerPublishCommentEdit(true);
|
||||||
|
}
|
||||||
|
}, [editedComment]);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -777,93 +788,93 @@ const Thread = () => {
|
|||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
<PostMenu
|
<PostMenu
|
||||||
key={`pmb-${index}`}
|
key={`pmb-${index}`}
|
||||||
title="Post menu"
|
title="Post menu"
|
||||||
ref={el => threadMenuRefs.current[comment.cid] = el}
|
ref={el => threadMenuRefs.current[comment.cid] = el}
|
||||||
className='post-menu-button'
|
className='post-menu-button'
|
||||||
rotated={rotatedStates[comment.cid]}
|
rotated={rotatedStates[comment.cid]}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const rect = threadMenuRefs.current[comment.cid].getBoundingClientRect();
|
const rect = threadMenuRefs.current[comment.cid].getBoundingClientRect();
|
||||||
const menu = document.querySelector(`.post-menu-thread-${comment.cid}`);
|
const menu = document.querySelector(`.post-menu-thread-${comment.cid}`);
|
||||||
menu.style.top = `calc(${rect.top}px + 17px)`;
|
menu.style.top = `calc(${rect.top}px + 17px)`;
|
||||||
menu.style.left = `${rect.left}px`;
|
menu.style.left = `${rect.left}px`;
|
||||||
|
|
||||||
setRotatedStates(prevState => ({
|
setRotatedStates(prevState => ({
|
||||||
...prevState,
|
...prevState,
|
||||||
[comment.cid]: !prevState[comment.cid]
|
[comment.cid]: !prevState[comment.cid]
|
||||||
}));
|
}));
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
▶
|
▶
|
||||||
</PostMenu>
|
</PostMenu>
|
||||||
<div id="post-menu" className={`post-menu-thread post-menu-thread-${comment.cid}`}
|
<div id="post-menu" className={`post-menu-thread post-menu-thread-${comment.cid}`}
|
||||||
style={{ display: rotatedStates[comment.cid] ? 'block' : 'none' }}>
|
style={{ display: rotatedStates[comment.cid] ? 'block' : 'none' }}>
|
||||||
<ul>
|
<ul>
|
||||||
<li onClick={() => handleOptionClick(comment.cid)}>Hide thread</li>
|
<li onClick={() => handleOptionClick(comment.cid)}>Hide thread</li>
|
||||||
|
{comment?.author?.shortAddress === account?.author?.shortAddress ? (
|
||||||
|
<>
|
||||||
|
<li onClick={() => handleAuthorEditClick(comment)}>Edit post</li>
|
||||||
|
<li onClick={() => handleAuthorDeleteClick(comment.cid, selectedStyle)}>Delete post</li>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
{isModerator ? (
|
||||||
|
<>
|
||||||
{comment?.author?.shortAddress === account?.author?.shortAddress ? (
|
{comment?.author?.shortAddress === account?.author?.shortAddress ? (
|
||||||
<>
|
null
|
||||||
<li onClick={() => handleAuthorEditClick(comment)}>Edit post</li>
|
) : (
|
||||||
<li onClick={() => handleAuthorDeleteClick(comment.cid)}>Delete post</li>
|
<li onClick={() => {
|
||||||
</>
|
setModeratingCommentCid(comment.cid)
|
||||||
) : null}
|
setIsModerationOpen(true);
|
||||||
{isModerator ? (
|
handleOptionClick(comment.cid);
|
||||||
<>
|
setDeletePost(true);
|
||||||
{comment?.author?.shortAddress === account?.author?.shortAddress ? (
|
}}>
|
||||||
null
|
Delete post
|
||||||
) : (
|
</li>
|
||||||
<li onClick={() => {
|
)}
|
||||||
setModeratingCommentCid(comment.cid)
|
<li
|
||||||
setIsModerationOpen(true);
|
onClick={() => {
|
||||||
handleOptionClick(comment.cid);
|
setModeratingCommentCid(comment.cid)
|
||||||
setDeletePost(true);
|
setIsModerationOpen(true);
|
||||||
}}>
|
handleOptionClick(comment.cid);
|
||||||
Delete post
|
}}>
|
||||||
</li>
|
Mod tools
|
||||||
)}
|
</li>
|
||||||
<li
|
</>
|
||||||
onClick={() => {
|
) : null}
|
||||||
setModeratingCommentCid(comment.cid)
|
{(commentMediaInfo && (
|
||||||
setIsModerationOpen(true);
|
commentMediaInfo.type === 'image' ||
|
||||||
handleOptionClick(comment.cid);
|
(commentMediaInfo.type === 'webpage' &&
|
||||||
}}>
|
commentMediaInfo.thumbnail))) ? (
|
||||||
Mod tools
|
<li
|
||||||
|
onMouseOver={() => {setIsImageSearchOpen(true)}}
|
||||||
|
onMouseLeave={() => {setIsImageSearchOpen(false)}}>
|
||||||
|
Image search »
|
||||||
|
<ul className="dropdown-menu"
|
||||||
|
style={{display: isImageSearchOpen ? 'block': 'none'}}>
|
||||||
|
<li onClick={() => handleOptionClick(comment.cid)}>
|
||||||
|
<a
|
||||||
|
href={`https://lens.google.com/uploadbyurl?url=${commentMediaInfo.url}`}
|
||||||
|
target="_blank" rel="noreferrer"
|
||||||
|
>Google</a>
|
||||||
</li>
|
</li>
|
||||||
</>
|
<li onClick={() => handleOptionClick(comment.cid)}>
|
||||||
) : null}
|
<a
|
||||||
{(commentMediaInfo && (
|
href={`https://yandex.com/images/search?url=${commentMediaInfo.url}`}
|
||||||
commentMediaInfo.type === 'image' ||
|
target="_blank" rel="noreferrer"
|
||||||
(commentMediaInfo.type === 'webpage' &&
|
>Yandex</a>
|
||||||
commentMediaInfo.thumbnail))) ? (
|
|
||||||
<li
|
|
||||||
onMouseOver={() => {setIsImageSearchOpen(true)}}
|
|
||||||
onMouseLeave={() => {setIsImageSearchOpen(false)}}>
|
|
||||||
Image search »
|
|
||||||
<ul className="dropdown-menu"
|
|
||||||
style={{display: isImageSearchOpen ? 'block': 'none'}}>
|
|
||||||
<li onClick={() => handleOptionClick(comment.cid)}>
|
|
||||||
<a
|
|
||||||
href={`https://lens.google.com/uploadbyurl?url=${commentMediaInfo.url}`}
|
|
||||||
target="_blank" rel="noreferrer"
|
|
||||||
>Google</a>
|
|
||||||
</li>
|
|
||||||
<li onClick={() => handleOptionClick(comment.cid)}>
|
|
||||||
<a
|
|
||||||
href={`https://yandex.com/images/search?url=${commentMediaInfo.url}`}
|
|
||||||
target="_blank" rel="noreferrer"
|
|
||||||
>Yandex</a>
|
|
||||||
</li>
|
|
||||||
<li onClick={() => handleOptionClick(comment.cid)}>
|
|
||||||
<a
|
|
||||||
href={`https://saucenao.com/search.php?url=${commentMediaInfo.url}`}
|
|
||||||
target="_blank" rel="noreferrer"
|
|
||||||
>SauceNAO</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
</li>
|
||||||
) : null
|
<li onClick={() => handleOptionClick(comment.cid)}>
|
||||||
}
|
<a
|
||||||
</ul>
|
href={`https://saucenao.com/search.php?url=${commentMediaInfo.url}`}
|
||||||
</div>
|
target="_blank" rel="noreferrer"
|
||||||
|
>SauceNAO</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
<div id="backlink-id" className="backlink">
|
<div id="backlink-id" className="backlink">
|
||||||
{comment?.replies?.pages?.topAll.comments
|
{comment?.replies?.pages?.topAll.comments
|
||||||
.sort((a, b) => a.timestamp - b.timestamp)
|
.sort((a, b) => a.timestamp - b.timestamp)
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ const useGeneralStore = create((set) => ({
|
|||||||
defaultSubplebbits: [],
|
defaultSubplebbits: [],
|
||||||
setDefaultSubplebbits: (subplebbits) => set({ defaultSubplebbits: subplebbits }),
|
setDefaultSubplebbits: (subplebbits) => set({ defaultSubplebbits: subplebbits }),
|
||||||
|
|
||||||
|
editedComment: '',
|
||||||
|
setEditedComment: (comment) => set({ editedComment: comment }),
|
||||||
|
|
||||||
isCaptchaOpen: false,
|
isCaptchaOpen: false,
|
||||||
setIsCaptchaOpen: (isOpen) => set({ isCaptchaOpen: isOpen }),
|
setIsCaptchaOpen: (isOpen) => set({ isCaptchaOpen: isOpen }),
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user