From 9e198fb32a33267a524a19b61343dff17f0421d3 Mon Sep 17 00:00:00 2001 From: "plebeius.eth" Date: Fri, 15 Sep 2023 14:18:01 +0200 Subject: [PATCH 01/13] add support for non-direct imgur links --- src/utils/getCommentMediaInfo.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/utils/getCommentMediaInfo.js b/src/utils/getCommentMediaInfo.js index ae263a34..3de39170 100644 --- a/src/utils/getCommentMediaInfo.js +++ b/src/utils/getCommentMediaInfo.js @@ -23,6 +23,31 @@ const getCommentMediaInfo = (comment) => { } else if (host.includes('streamable.com')) { const videoId = url.pathname.split('/')[1]; scrapedThumbnailUrl = `https://cdn-cf-east.streamable.com/image/${videoId}.jpg`; + + } else if (host.includes('imgur.com') && !host.startsWith('i.imgur')) { + const imgId = url.pathname.split('/')[1]; + const formats = ['jpeg', 'jpg', 'png', 'mp4']; + + for (const format of formats) { + const directUrl = `https://i.imgur.com/${imgId}.${format}`; + const imgurUrl = new URL(directUrl); + const mime = extName(imgurUrl.pathname.toLowerCase().replace('/', ''))[0]?.mime; + + if (mime?.startsWith('image')) { + return { + url: directUrl, + type: 'image', + }; + } + + if (mime?.startsWith('video')) { + return { + url: directUrl, + type: 'video', + thumbnail: comment.thumbnailUrl, + }; + } + } } if (canEmbed(url)) { From 2cfe99bba43905c8ffa80e610dfd0b46c182eb52 Mon Sep 17 00:00:00 2001 From: "plebeius.eth" Date: Fri, 15 Sep 2023 17:10:59 +0200 Subject: [PATCH 02/13] fix account replies pushed to thread view --- src/components/views/Thread.jsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/views/Thread.jsx b/src/components/views/Thread.jsx index eb0e8232..45f60aec 100755 --- a/src/components/views/Thread.jsx +++ b/src/components/views/Thread.jsx @@ -281,6 +281,7 @@ const Thread = () => { const threadAndRepliesCids = useMemo(() => new Set([(selectedThread || 'n/a'), ...flattenedReplies.map(reply => reply.cid)]), [selectedThread, flattenedReplies]); + const filter = useCallback((accountComment) => threadAndRepliesCids.has(accountComment.parentCid), [threadAndRepliesCids]); @@ -289,8 +290,10 @@ const Thread = () => { const accountRepliesNotYetInCommentReplies = useMemo(() => { const commentReplyCids = new Set(flattenedReplies.map(reply => reply.cid)) - return accountComments.filter(accountReply => !commentReplyCids.has(accountReply.cid)) - }, [flattenedReplies, accountComments]); + return accountComments.filter(accountReply => { + return !commentReplyCids.has(accountReply.cid) && accountReply.parentCid === selectedThread; + }); + }, [flattenedReplies, accountComments, selectedThread]); const sortedReplies = useMemo(() => [ From be8932343184a96d719cf5fd4a5032ce5162d12a Mon Sep 17 00:00:00 2001 From: "plebeius.eth" Date: Fri, 15 Sep 2023 17:38:16 +0200 Subject: [PATCH 03/13] Revert "add support for non-direct imgur links" This reverts commit 9e198fb32a33267a524a19b61343dff17f0421d3. --- src/utils/getCommentMediaInfo.js | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/src/utils/getCommentMediaInfo.js b/src/utils/getCommentMediaInfo.js index 3de39170..ae263a34 100644 --- a/src/utils/getCommentMediaInfo.js +++ b/src/utils/getCommentMediaInfo.js @@ -23,31 +23,6 @@ const getCommentMediaInfo = (comment) => { } else if (host.includes('streamable.com')) { const videoId = url.pathname.split('/')[1]; scrapedThumbnailUrl = `https://cdn-cf-east.streamable.com/image/${videoId}.jpg`; - - } else if (host.includes('imgur.com') && !host.startsWith('i.imgur')) { - const imgId = url.pathname.split('/')[1]; - const formats = ['jpeg', 'jpg', 'png', 'mp4']; - - for (const format of formats) { - const directUrl = `https://i.imgur.com/${imgId}.${format}`; - const imgurUrl = new URL(directUrl); - const mime = extName(imgurUrl.pathname.toLowerCase().replace('/', ''))[0]?.mime; - - if (mime?.startsWith('image')) { - return { - url: directUrl, - type: 'image', - }; - } - - if (mime?.startsWith('video')) { - return { - url: directUrl, - type: 'video', - thumbnail: comment.thumbnailUrl, - }; - } - } } if (canEmbed(url)) { From ed8968704a9cecaa3fec6a08d28647881a5b7b24 Mon Sep 17 00:00:00 2001 From: "plebeius.eth" Date: Fri, 15 Sep 2023 21:26:55 +0200 Subject: [PATCH 04/13] fix whitespace --- src/components/views/All.jsx | 4 ++-- src/components/views/Board.jsx | 4 ++-- src/components/views/Subscriptions.jsx | 4 ++-- src/components/views/Thread.jsx | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/views/All.jsx b/src/components/views/All.jsx index c60f510b..00a605ec 100755 --- a/src/components/views/All.jsx +++ b/src/components/views/All.jsx @@ -750,7 +750,7 @@ const All = () => { commentMediaInfo?.url.length > 30 ? commentMediaInfo?.url.slice(0, 30) + "(...)" : commentMediaInfo?.url - }{commentMediaInfo?.type === "iframe" ? null : `(${commentMediaInfo?.type})`} + }{commentMediaInfo?.type === "iframe" ? null : ` (${commentMediaInfo?.type})`} {((isThreadThumbnailClicked[index] && (commentMediaInfo.type === 'iframe' || commentMediaInfo.type === 'video')) || (commentMediaInfo.type === 'iframe' && !commentMediaInfo.thumbnail)) && (  [ @@ -1457,7 +1457,7 @@ const All = () => { replyMediaInfo?.url.length > 30 ? replyMediaInfo?.url.slice(0, 30) + "(...)" : replyMediaInfo?.url - }{replyMediaInfo?.type === "iframe" ? null : `(${replyMediaInfo?.type})`} + }{replyMediaInfo?.type === "iframe" ? null : ` (${replyMediaInfo?.type})`} { ((isReplyThumbnailClicked[index] && (replyMediaInfo.type === 'iframe' || replyMediaInfo.type === 'video')) || (replyMediaInfo.type === 'iframe' && !replyMediaInfo.thumbnail)) && (  [ diff --git a/src/components/views/Board.jsx b/src/components/views/Board.jsx index e6644b1d..7abefaff 100755 --- a/src/components/views/Board.jsx +++ b/src/components/views/Board.jsx @@ -1664,7 +1664,7 @@ const Board = () => { commentMediaInfo?.url.length > 30 ? commentMediaInfo?.url.slice(0, 30) + "(...)" : commentMediaInfo?.url - }{commentMediaInfo?.type === "iframe" ? null : `(${commentMediaInfo?.type})`} + }{commentMediaInfo?.type === "iframe" ? null : ` (${commentMediaInfo?.type})`} {((isThreadThumbnailClicked[index] && (commentMediaInfo.type === 'iframe' || commentMediaInfo.type === 'video')) || (commentMediaInfo.type === 'iframe' && !commentMediaInfo.thumbnail)) && (  [ @@ -2368,7 +2368,7 @@ const Board = () => { replyMediaInfo?.url.length > 30 ? replyMediaInfo?.url.slice(0, 30) + "(...)" : replyMediaInfo?.url - }{replyMediaInfo?.type === "iframe" ? null : `(${replyMediaInfo?.type})`} + }{replyMediaInfo?.type === "iframe" ? null : ` (${replyMediaInfo?.type})`} { ((isReplyThumbnailClicked[index] && (replyMediaInfo.type === 'iframe' || replyMediaInfo.type === 'video')) || (replyMediaInfo.type === 'iframe' && !replyMediaInfo.thumbnail)) && (  [ diff --git a/src/components/views/Subscriptions.jsx b/src/components/views/Subscriptions.jsx index 4e1e46fe..3184702e 100755 --- a/src/components/views/Subscriptions.jsx +++ b/src/components/views/Subscriptions.jsx @@ -758,7 +758,7 @@ const Subscriptions = () => { commentMediaInfo?.url.length > 30 ? commentMediaInfo?.url.slice(0, 30) + "(...)" : commentMediaInfo?.url - }{commentMediaInfo?.type === "iframe" ? null : `(${commentMediaInfo?.type})`} + }{commentMediaInfo?.type === "iframe" ? null : ` (${commentMediaInfo?.type})`} {((isThreadThumbnailClicked[index] && (commentMediaInfo.type === 'iframe' || commentMediaInfo.type === 'video')) || (commentMediaInfo.type === 'iframe' && !commentMediaInfo.thumbnail)) && (  [ @@ -1465,7 +1465,7 @@ const Subscriptions = () => { replyMediaInfo?.url.length > 30 ? replyMediaInfo?.url.slice(0, 30) + "(...)" : replyMediaInfo?.url - }{replyMediaInfo?.type === "iframe" ? null : `(${replyMediaInfo?.type})`} + }{replyMediaInfo?.type === "iframe" ? null : ` (${replyMediaInfo?.type})`} { ((isReplyThumbnailClicked[index] && (replyMediaInfo.type === 'iframe' || replyMediaInfo.type === 'video')) || (replyMediaInfo.type === 'iframe' && !replyMediaInfo.thumbnail)) && (  [ diff --git a/src/components/views/Thread.jsx b/src/components/views/Thread.jsx index 45f60aec..e1f9fa8b 100755 --- a/src/components/views/Thread.jsx +++ b/src/components/views/Thread.jsx @@ -903,7 +903,7 @@ const Thread = () => { commentMediaInfo?.url.length > 30 ? commentMediaInfo?.url.slice(0, 30) + "(...)" : commentMediaInfo?.url - }{commentMediaInfo?.type === "iframe" ? null : `(${commentMediaInfo?.type})`} + }{commentMediaInfo?.type === "iframe" ? null : ` (${commentMediaInfo?.type})`} {((isThreadThumbnailClicked[index] && (commentMediaInfo.type === 'iframe' || commentMediaInfo.type === 'video')) || (commentMediaInfo.type === 'iframe' && !commentMediaInfo.thumbnail)) && (  [ @@ -1563,7 +1563,7 @@ const Thread = () => { replyMediaInfo?.url.length > 30 ? replyMediaInfo?.url.slice(0, 30) + "(...)" : replyMediaInfo?.url - }{replyMediaInfo?.type === "iframe" ? null : `(${replyMediaInfo?.type})`} + }{replyMediaInfo?.type === "iframe" ? null : ` (${replyMediaInfo?.type})`} { ((isReplyThumbnailClicked[index] && (replyMediaInfo.type === 'iframe' || replyMediaInfo.type === 'video')) || (replyMediaInfo.type === 'iframe' && !replyMediaInfo.thumbnail)) && (  [ From 3fb50b30f7386781f7d7fd7f947801686dd6cceb Mon Sep 17 00:00:00 2001 From: "plebeius.eth" Date: Sat, 16 Sep 2023 10:36:27 +0200 Subject: [PATCH 05/13] fix state of admin board settings --- src/components/BoardSettings.jsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/BoardSettings.jsx b/src/components/BoardSettings.jsx index 811d360c..846d9cff 100644 --- a/src/components/BoardSettings.jsx +++ b/src/components/BoardSettings.jsx @@ -262,6 +262,12 @@ const BoardSettings = ({ subplebbit }) => { const handleCloseModal = () => { setIsModalOpen(false); + setBoardSettingsJson(JSON.stringify(initialSettings, null, 2)); + }; + + const openModal = () => { + setIsModalOpen(true); + setBoardSettingsJson(JSON.stringify(generateSettingsFromSubplebbit(subplebbit), null, 2)); }; @@ -309,7 +315,7 @@ const BoardSettings = ({ subplebbit }) => { { window.electron && window.electron.isElectron - ? setIsModalOpen(true) + ? openModal() : alert( 'To edit this board you must be using the plebchan desktop app, which is a plebbit full node that seeds the board automatically.\n\nDownload plebchan here:\n\nhttps://github.com/plebbit/plebchan/releases/latest' ); From 4c5198f40e63aa5eeec63f98ae990e2c8e03c7fa Mon Sep 17 00:00:00 2001 From: "plebeius.eth" Date: Sat, 16 Sep 2023 16:41:51 +0200 Subject: [PATCH 06/13] fix challenge promise leak --- src/components/modals/CaptchaModal.jsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/components/modals/CaptchaModal.jsx b/src/components/modals/CaptchaModal.jsx index 7ac7cb79..a654b69f 100644 --- a/src/components/modals/CaptchaModal.jsx +++ b/src/components/modals/CaptchaModal.jsx @@ -86,16 +86,24 @@ const CaptchaModal = () => { }; + let isPromiseResolved = false; + const submitCaptcha = (callback) => { - setCaptchaResponse(responseRef.current.value); + if (!isPromiseResolved) { + setCaptchaResponse(responseRef.current.value); + resolveCaptchaPromise(responseRef.current.value); + isPromiseResolved = true; + } + setImageSources([]); setChallengesArray([]); setIsCaptchaOpen(false); - + if (callback) { callback(responseRef.current.value); } }; + const handleCloseModal = () => { setImageSources([]); From 6f2e8dcaa871187d0dcb4cd23fc847d2de7c7440 Mon Sep 17 00:00:00 2001 From: "plebeius.eth" Date: Sat, 16 Sep 2023 17:07:31 +0200 Subject: [PATCH 07/13] Update CaptchaModal.jsx --- src/components/modals/CaptchaModal.jsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/modals/CaptchaModal.jsx b/src/components/modals/CaptchaModal.jsx index a654b69f..3abd06e4 100644 --- a/src/components/modals/CaptchaModal.jsx +++ b/src/components/modals/CaptchaModal.jsx @@ -26,6 +26,7 @@ const CaptchaModal = () => { const [isMobile, setIsMobile] = useState(window.innerWidth <= 480); const responseRef = useRef(); const nodeRef = useRef(null); + const [isPromiseResolved, setIsPromiseResolved] = useState(false); useEffect(() => { @@ -86,24 +87,27 @@ const CaptchaModal = () => { }; - let isPromiseResolved = false; - const submitCaptcha = (callback) => { if (!isPromiseResolved) { setCaptchaResponse(responseRef.current.value); resolveCaptchaPromise(responseRef.current.value); - isPromiseResolved = true; + setIsPromiseResolved(true); } setImageSources([]); setChallengesArray([]); setIsCaptchaOpen(false); - + if (callback) { callback(responseRef.current.value); } }; + useEffect(() => { + if (!isCaptchaOpen) { + setIsPromiseResolved(false); + } + }, [isCaptchaOpen]); const handleCloseModal = () => { setImageSources([]); From e8b42786e1efff0611fbd047048b0a04ad969225 Mon Sep 17 00:00:00 2001 From: "plebeius.eth" Date: Sat, 16 Sep 2023 17:29:14 +0200 Subject: [PATCH 08/13] add instant mod edits --- src/components/BoardSettings.jsx | 2 +- src/components/EditLabel.jsx | 5 ++++ src/components/modals/ModerationModal.jsx | 2 +- src/components/views/All.jsx | 29 +++++++++++++++++-- src/components/views/AllCatalog.jsx | 2 +- src/components/views/Board.jsx | 24 +++++++++++++-- src/components/views/Catalog.jsx | 4 +-- src/components/views/Subscriptions.jsx | 29 +++++++++++++++++-- src/components/views/SubscriptionsCatalog.jsx | 2 +- src/components/views/Thread.jsx | 2 +- src/hooks/stores/useGeneralStore.js | 3 ++ 11 files changed, 90 insertions(+), 14 deletions(-) diff --git a/src/components/BoardSettings.jsx b/src/components/BoardSettings.jsx index 846d9cff..a183737b 100644 --- a/src/components/BoardSettings.jsx +++ b/src/components/BoardSettings.jsx @@ -138,7 +138,7 @@ const BoardSettings = ({ subplebbit }) => { const onChallengeVerification = (challengeVerification) => { if (challengeVerification.challengeSuccess === true) { - setNewSuccessMessage('Challenge Success'); + setNewSuccessMessage('Challenge Success'); console.log('challenge success', challengeVerification); } else if (challengeVerification.challengeSuccess === false) { setNewErrorMessage(`Challenge Failed, reason: ${challengeVerification.reason}. Errors: ${challengeVerification.errors}`); console.log('challenge failed', challengeVerification); diff --git a/src/components/EditLabel.jsx b/src/components/EditLabel.jsx index 0ccd2f3b..aa3e3b76 100644 --- a/src/components/EditLabel.jsx +++ b/src/components/EditLabel.jsx @@ -3,14 +3,19 @@ import { useComment, useEditedComment } from "@plebbit/plebbit-react-hooks"; import { Link } from "react-router-dom"; import OriginalCommentModal from "./modals/OriginalCommentModal"; import getDate from "../utils/getDate"; +import useGeneralStore from "../hooks/stores/useGeneralStore"; const EditLabel = ({ commentCid, className }) => { + const { editedComments, setEditedComments } = useGeneralStore(state => state); const [isOriginalCommentModalOpen, setIsOriginalCommentModalOpen] = useState(false); const comment = useComment({commentCid}); const timestamp = getDate(comment.edit?.timestamp); const {state: editedCommentState, editedComment} = useEditedComment({comment}); + if (editedCommentState === 'pending' && !(commentCid in editedComments)) { + setEditedComments({...editedComments, [commentCid]: editedComment}) + } const conditionsCheck = () => { let conditions = []; diff --git a/src/components/modals/ModerationModal.jsx b/src/components/modals/ModerationModal.jsx index 1d03b46c..e50dc005 100755 --- a/src/components/modals/ModerationModal.jsx +++ b/src/components/modals/ModerationModal.jsx @@ -58,7 +58,7 @@ const ModerationModal = ({ isOpen, closeModal, deletePost }) => { const onChallengeVerification = (challengeVerification) => { if (challengeVerification.challengeSuccess === true) { - setNewSuccessMessage('Challenge Success'); + setNewSuccessMessage('Challenge Success'); console.log('challenge success', challengeVerification); } else if (challengeVerification.challengeSuccess === false) { setNewErrorMessage(`Challenge Failed, reason: ${challengeVerification.reason}. Errors: ${challengeVerification.errors}`); console.log('challenge failed', challengeVerification); diff --git a/src/components/views/All.jsx b/src/components/views/All.jsx index 00a605ec..f578aaa4 100755 --- a/src/components/views/All.jsx +++ b/src/components/views/All.jsx @@ -54,6 +54,7 @@ const All = () => { const { defaultSubplebbits, editedComment, + editedComments, feedCacheStates, setFeedCacheState, isSettingsOpen, setIsSettingsOpen, @@ -331,6 +332,13 @@ const All = () => { return selectedFeed.flatMap(thread => filteredRepliesByThread[thread.cid]?.displayedReplies || []); }, [selectedFeed, filteredRepliesByThread]); + const filteredFeed = useMemo(() => { + return selectedFeed.filter(thread => { + const editedThread = editedComments[thread.cid]; + return !(editedThread && editedThread.removed); + }); + }, [selectedFeed, editedComments]); + // let post.jsx access full cid of user-typed short cid useEffect(() => { const newCidTracker = {}; @@ -364,7 +372,7 @@ const All = () => { const onChallengeVerification = (challengeVerification) => { if (challengeVerification.challengeSuccess === true) { - setNewSuccessMessage('Challenge Success'); + setNewSuccessMessage('Challenge Success'); console.log('challenge success', challengeVerification); } else if (challengeVerification.challengeSuccess === false) { setNewErrorMessage(`Challenge Failed, reason: ${challengeVerification.reason}. Errors: ${challengeVerification.errors}`); @@ -713,8 +721,11 @@ const All = () => { {feed ? ( { + if (editedComments[thread.cid]) { + thread = editedComments[thread.cid]; + }; const { displayedReplies, omittedCount } = filteredRepliesByThread[thread.cid] || {}; const commentMediaInfo = getCommentMediaInfo(thread); const fallbackImgUrl = "assets/filedeleted-res.gif"; @@ -1157,6 +1168,13 @@ const All = () => { ) : null} {displayedReplies?.map((reply, index) => { + if (editedComments[reply.cid]) { + reply = editedComments[reply.cid]; + if (reply.removed) { + reply.content = "[removed]"; + reply.link = undefined; + } + } const replyMediaInfo = getCommentMediaInfo(reply); const fallbackImgUrl = "assets/filedeleted-res.gif"; const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed); @@ -2099,6 +2117,13 @@ const All = () => { {displayedReplies?.map((reply, index) => { + if (editedComments[reply.cid]) { + reply = editedComments[reply.cid]; + if (reply.removed) { + reply.content = "[removed]"; + reply.link = undefined; + } + } const replyMediaInfo = getCommentMediaInfo(reply); const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed); return ( diff --git a/src/components/views/AllCatalog.jsx b/src/components/views/AllCatalog.jsx index 49640a77..5bc17307 100755 --- a/src/components/views/AllCatalog.jsx +++ b/src/components/views/AllCatalog.jsx @@ -241,7 +241,7 @@ const CatalogPost = ({post}) => { const onChallengeVerification = (challengeVerification) => { if (challengeVerification.challengeSuccess === true) { - setNewSuccessMessage('Challenge Success'); + setNewSuccessMessage('Challenge Success'); console.log('challenge success', challengeVerification); } else if (challengeVerification.challengeSuccess === false) { setNewErrorMessage(`Challenge Failed, reason: ${challengeVerification.reason}. Errors: ${challengeVerification.errors}`); diff --git a/src/components/views/Board.jsx b/src/components/views/Board.jsx index 7abefaff..3e40909f 100755 --- a/src/components/views/Board.jsx +++ b/src/components/views/Board.jsx @@ -60,6 +60,7 @@ const Board = () => { setChallengesArray, defaultSubplebbits, editedComment, + editedComments, feedCacheStates, setFeedCacheState, setIsAuthorDelete, @@ -339,6 +340,13 @@ const Board = () => { return selectedFeed.flatMap(thread => filteredRepliesByThread[thread.cid]?.displayedReplies || []); }, [selectedFeed, filteredRepliesByThread]); + const filteredFeed = useMemo(() => { + return selectedFeed.filter(thread => { + const editedThread = editedComments[thread.cid]; + return !(editedThread && editedThread.removed); + }); + }, [selectedFeed, editedComments]); + // let post.jsx access full cid of user-typed short cid useEffect(() => { const newCidTracker = {}; @@ -397,7 +405,7 @@ const Board = () => { navigate(`/p/${subplebbitAddress}/c/${challengeVerification.publication?.cid}`); console.log('challenge success'); } else { - setNewSuccessMessage('Challenge Success'); + setNewSuccessMessage('Challenge Success'); console.log('challenge success', challengeVerification); } } else if (challengeVerification.challengeSuccess === false) { @@ -587,7 +595,7 @@ const Board = () => { const [publishCommentEditOptions, setPublishCommentEditOptions] = useState({ commentCid: commentCid, content: editedComment || undefined, - subplebbitAddress: selectedAddress, + subplebbitAddress, onChallenge, onChallengeVerification, onError: (error) => { @@ -1628,8 +1636,11 @@ const Board = () => { : null} { + if (editedComments[thread.cid]) { + thread = editedComments[thread.cid]; + }; const { displayedReplies, omittedCount } = filteredRepliesByThread[thread.cid] || {}; const commentMediaInfo = getCommentMediaInfo(thread); const fallbackImgUrl = "assets/filedeleted-res.gif"; @@ -2079,6 +2090,13 @@ const Board = () => { ) : null} {displayedReplies?.map((reply, index) => { + if (editedComments[reply.cid]) { + reply = editedComments[reply.cid]; + if (reply.removed) { + reply.content = "[removed]"; + reply.link = undefined; + } + } const replyMediaInfo = getCommentMediaInfo(reply); const fallbackImgUrl = "assets/filedeleted-res.gif"; const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed); diff --git a/src/components/views/Catalog.jsx b/src/components/views/Catalog.jsx index 1053f280..47af8353 100755 --- a/src/components/views/Catalog.jsx +++ b/src/components/views/Catalog.jsx @@ -235,7 +235,7 @@ const CatalogPost = ({post}) => { const onChallengeVerification = (challengeVerification) => { if (challengeVerification.challengeSuccess === true) { - setNewSuccessMessage('Challenge Success'); + setNewSuccessMessage('Challenge Success'); console.log('challenge success', challengeVerification); } else if (challengeVerification.challengeSuccess === false) { setNewErrorMessage(`Challenge Failed, reason: ${challengeVerification.reason}. Errors: ${challengeVerification.errors}`); @@ -1093,7 +1093,7 @@ const Catalog = () => { navigate(`/p/${subplebbitAddress}/c/${challengeVerification.publication?.cid}`); console.log('challenge success'); } else { - setNewSuccessMessage('Challenge Success'); + setNewSuccessMessage('Challenge Success'); console.log('challenge success', challengeVerification); } } else if (challengeVerification.challengeSuccess === false) { diff --git a/src/components/views/Subscriptions.jsx b/src/components/views/Subscriptions.jsx index 3184702e..4c2f93ef 100755 --- a/src/components/views/Subscriptions.jsx +++ b/src/components/views/Subscriptions.jsx @@ -54,6 +54,7 @@ const Subscriptions = () => { const { defaultSubplebbits, editedComment, + editedComments, feedCacheStates, setFeedCacheState, isSettingsOpen, setIsSettingsOpen, @@ -332,6 +333,13 @@ const Subscriptions = () => { return selectedFeed.flatMap(thread => filteredRepliesByThread[thread.cid]?.displayedReplies || []); }, [selectedFeed, filteredRepliesByThread]); + const filteredFeed = useMemo(() => { + return selectedFeed.filter(thread => { + const editedThread = editedComments[thread.cid]; + return !(editedThread && editedThread.removed); + }); + }, [selectedFeed, editedComments]); + // let post.jsx access full cid of user-typed short cid useEffect(() => { const newCidTracker = {}; @@ -366,7 +374,7 @@ const Subscriptions = () => { const onChallengeVerification = (challengeVerification) => { if (challengeVerification.challengeSuccess === true) { - setNewSuccessMessage('Challenge Success'); + setNewSuccessMessage('Challenge Success'); console.log('challenge success', challengeVerification); } else if (challengeVerification.challengeSuccess === false) { setNewErrorMessage(`Challenge Failed, reason: ${challengeVerification.reason}. Errors: ${challengeVerification.errors}`); @@ -721,8 +729,11 @@ const Subscriptions = () => { ) : ( { + if (editedComments[thread.cid]) { + thread = editedComments[thread.cid]; + }; const { displayedReplies, omittedCount } = filteredRepliesByThread[thread.cid] || {}; const commentMediaInfo = getCommentMediaInfo(thread); const fallbackImgUrl = "assets/filedeleted-res.gif"; @@ -1165,6 +1176,13 @@ const Subscriptions = () => { ) : null} {displayedReplies?.map((reply, index) => { + if (editedComments[reply.cid]) { + reply = editedComments[reply.cid]; + if (reply.removed) { + reply.content = "[removed]"; + reply.link = undefined; + } + } const replyMediaInfo = getCommentMediaInfo(reply); const fallbackImgUrl = "assets/filedeleted-res.gif"; const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed); @@ -2107,6 +2125,13 @@ const Subscriptions = () => { {displayedReplies?.map((reply, index) => { + if (editedComments[reply.cid]) { + reply = editedComments[reply.cid]; + if (reply.removed) { + reply.content = "[removed]"; + reply.link = undefined; + } + } const replyMediaInfo = getCommentMediaInfo(reply); const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed); return ( diff --git a/src/components/views/SubscriptionsCatalog.jsx b/src/components/views/SubscriptionsCatalog.jsx index 1e4babea..36709181 100755 --- a/src/components/views/SubscriptionsCatalog.jsx +++ b/src/components/views/SubscriptionsCatalog.jsx @@ -241,7 +241,7 @@ const CatalogPost = ({post}) => { const onChallengeVerification = (challengeVerification) => { if (challengeVerification.challengeSuccess === true) { - setNewSuccessMessage('Challenge Success'); + setNewSuccessMessage('Challenge Success'); console.log('challenge success', challengeVerification); } else if (challengeVerification.challengeSuccess === false) { setNewErrorMessage(`Challenge Failed, reason: ${challengeVerification.reason}. Errors: ${challengeVerification.errors}`); diff --git a/src/components/views/Thread.jsx b/src/components/views/Thread.jsx index e1f9fa8b..5204cda9 100755 --- a/src/components/views/Thread.jsx +++ b/src/components/views/Thread.jsx @@ -347,7 +347,7 @@ const Thread = () => { if (challengeVerification.publication?.cid !== undefined) { return; } else { - setNewSuccessMessage('Challenge Success'); + setNewSuccessMessage('Challenge Success'); console.log('challenge success', challengeVerification); } } else if (challengeVerification.challengeSuccess === false) { setNewErrorMessage(`Challenge Failed, reason: ${challengeVerification.reason}. Errors: ${challengeVerification.errors}`); diff --git a/src/hooks/stores/useGeneralStore.js b/src/hooks/stores/useGeneralStore.js index 1fabcd4a..926446c2 100644 --- a/src/hooks/stores/useGeneralStore.js +++ b/src/hooks/stores/useGeneralStore.js @@ -26,6 +26,9 @@ const useGeneralStore = create((set) => ({ editedComment: '', setEditedComment: (comment) => set({ editedComment: comment }), + editedComments: {}, + setEditedComments: (comments) => set({ editedComments: comments }), + feedCacheStates: {}, setFeedCacheState: (address, isCached) => set((prev) => ({ feedCacheStates: { From b6f21f0034cf728c92e2f9ea86153f6831831f0e Mon Sep 17 00:00:00 2001 From: "plebeius.eth" Date: Sat, 16 Sep 2023 18:18:37 +0200 Subject: [PATCH 09/13] remove feed filter for edits --- src/components/views/All.jsx | 14 ++++++-------- src/components/views/Board.jsx | 14 ++++++-------- src/components/views/Subscriptions.jsx | 14 ++++++-------- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/components/views/All.jsx b/src/components/views/All.jsx index f578aaa4..23d4a236 100755 --- a/src/components/views/All.jsx +++ b/src/components/views/All.jsx @@ -332,13 +332,6 @@ const All = () => { return selectedFeed.flatMap(thread => filteredRepliesByThread[thread.cid]?.displayedReplies || []); }, [selectedFeed, filteredRepliesByThread]); - const filteredFeed = useMemo(() => { - return selectedFeed.filter(thread => { - const editedThread = editedComments[thread.cid]; - return !(editedThread && editedThread.removed); - }); - }, [selectedFeed, editedComments]); - // let post.jsx access full cid of user-typed short cid useEffect(() => { const newCidTracker = {}; @@ -721,10 +714,15 @@ const All = () => { {feed ? ( { if (editedComments[thread.cid]) { thread = editedComments[thread.cid]; + if (thread.removed) { + thread.content = "[removed]"; + thread.link = undefined; + thread.title = "[removed]"; + } }; const { displayedReplies, omittedCount } = filteredRepliesByThread[thread.cid] || {}; const commentMediaInfo = getCommentMediaInfo(thread); diff --git a/src/components/views/Board.jsx b/src/components/views/Board.jsx index 3e40909f..183e78f3 100755 --- a/src/components/views/Board.jsx +++ b/src/components/views/Board.jsx @@ -340,13 +340,6 @@ const Board = () => { return selectedFeed.flatMap(thread => filteredRepliesByThread[thread.cid]?.displayedReplies || []); }, [selectedFeed, filteredRepliesByThread]); - const filteredFeed = useMemo(() => { - return selectedFeed.filter(thread => { - const editedThread = editedComments[thread.cid]; - return !(editedThread && editedThread.removed); - }); - }, [selectedFeed, editedComments]); - // let post.jsx access full cid of user-typed short cid useEffect(() => { const newCidTracker = {}; @@ -1636,10 +1629,15 @@ const Board = () => { : null} { if (editedComments[thread.cid]) { thread = editedComments[thread.cid]; + if (thread.removed) { + thread.content = "[removed]"; + thread.link = undefined; + thread.title = "[removed]"; + } }; const { displayedReplies, omittedCount } = filteredRepliesByThread[thread.cid] || {}; const commentMediaInfo = getCommentMediaInfo(thread); diff --git a/src/components/views/Subscriptions.jsx b/src/components/views/Subscriptions.jsx index 4c2f93ef..9beb6009 100755 --- a/src/components/views/Subscriptions.jsx +++ b/src/components/views/Subscriptions.jsx @@ -333,13 +333,6 @@ const Subscriptions = () => { return selectedFeed.flatMap(thread => filteredRepliesByThread[thread.cid]?.displayedReplies || []); }, [selectedFeed, filteredRepliesByThread]); - const filteredFeed = useMemo(() => { - return selectedFeed.filter(thread => { - const editedThread = editedComments[thread.cid]; - return !(editedThread && editedThread.removed); - }); - }, [selectedFeed, editedComments]); - // let post.jsx access full cid of user-typed short cid useEffect(() => { const newCidTracker = {}; @@ -729,10 +722,15 @@ const Subscriptions = () => { ) : ( { if (editedComments[thread.cid]) { thread = editedComments[thread.cid]; + if (thread.removed) { + thread.content = "[removed]"; + thread.link = undefined; + thread.title = "[removed]"; + } }; const { displayedReplies, omittedCount } = filteredRepliesByThread[thread.cid] || {}; const commentMediaInfo = getCommentMediaInfo(thread); From 43f63aa341d2f861087a7c4ed95dd04bf9674d44 Mon Sep 17 00:00:00 2001 From: "plebeius.eth" Date: Sat, 16 Sep 2023 21:10:38 +0200 Subject: [PATCH 10/13] update mod edit --- src/components/views/All.jsx | 1 - src/components/views/Board.jsx | 1 - src/components/views/Subscriptions.jsx | 1 - src/components/views/Thread.jsx | 29 ++++++++++++++++++++++++-- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/components/views/All.jsx b/src/components/views/All.jsx index 23d4a236..13ef8e2b 100755 --- a/src/components/views/All.jsx +++ b/src/components/views/All.jsx @@ -721,7 +721,6 @@ const All = () => { if (thread.removed) { thread.content = "[removed]"; thread.link = undefined; - thread.title = "[removed]"; } }; const { displayedReplies, omittedCount } = filteredRepliesByThread[thread.cid] || {}; diff --git a/src/components/views/Board.jsx b/src/components/views/Board.jsx index 183e78f3..c6cde796 100755 --- a/src/components/views/Board.jsx +++ b/src/components/views/Board.jsx @@ -1636,7 +1636,6 @@ const Board = () => { if (thread.removed) { thread.content = "[removed]"; thread.link = undefined; - thread.title = "[removed]"; } }; const { displayedReplies, omittedCount } = filteredRepliesByThread[thread.cid] || {}; diff --git a/src/components/views/Subscriptions.jsx b/src/components/views/Subscriptions.jsx index 9beb6009..eaab82e5 100755 --- a/src/components/views/Subscriptions.jsx +++ b/src/components/views/Subscriptions.jsx @@ -729,7 +729,6 @@ const Subscriptions = () => { if (thread.removed) { thread.content = "[removed]"; thread.link = undefined; - thread.title = "[removed]"; } }; const { displayedReplies, omittedCount } = filteredRepliesByThread[thread.cid] || {}; diff --git a/src/components/views/Thread.jsx b/src/components/views/Thread.jsx index 5204cda9..4c805107 100755 --- a/src/components/views/Thread.jsx +++ b/src/components/views/Thread.jsx @@ -56,6 +56,7 @@ const Thread = () => { setChallengesArray, defaultSubplebbits, editedComment, + editedComments, setIsAuthorDelete, setIsAuthorEdit, setIsCaptchaOpen, @@ -134,9 +135,10 @@ const Thread = () => { useAnonMode(selectedThread, anonymousMode && executeAnonMode); - const comment = useComment({commentCid: selectedThread}); + const originalComment = useComment({commentCid: selectedThread}); + const [comment, setComment] = useState(originalComment); const { subplebbitAddress, threadCid } = useParams(); - const subplebbit = useSubplebbit({subplebbitAddress: comment.subplebbitAddress}); + const subplebbit = useSubplebbit({subplebbitAddress: originalComment.subplebbitAddress}); const selectedAddress = subplebbit.address; const stateString = useStateString(comment); @@ -144,6 +146,22 @@ const Thread = () => { const commentMediaInfo = getCommentMediaInfo(comment); const fallbackImgUrl = "assets/filedeleted-res.gif"; + + useEffect(() => { + let updatedComment = { ...originalComment }; + + if (editedComments[originalComment.cid]) { + updatedComment = { ...originalComment, ...editedComments[originalComment.cid] }; + + if (updatedComment.removed) { + updatedComment.content = "[removed]"; + updatedComment.link = undefined; + } + } + + setComment(updatedComment); + }, [originalComment, editedComments]); + const handleThumbnailClick = (index, type) => { switch(type) { @@ -1272,6 +1290,13 @@ const Thread = () => { {comment.replyCount === undefined ? : null} {sortedReplies.map((reply, index) => { + if (editedComments[reply.cid]) { + reply = editedComments[reply.cid]; + if (reply.removed) { + reply.content = "[removed]"; + reply.link = undefined; + } + } const replyMediaInfo = getCommentMediaInfo(reply); const fallbackImgUrl = "assets/filedeleted-res.gif"; const shortParentCid = findShortParentCid(reply.parentCid, comment); From 0aa105a4b92badd55076c1db70b4711eec08793b Mon Sep 17 00:00:00 2001 From: "plebeius.eth" Date: Sat, 16 Sep 2023 21:19:56 +0200 Subject: [PATCH 11/13] add prettier --- package.json | 4 +++- prettier.config.js | 6 ++++++ yarn.lock | 5 +++++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 prettier.config.js diff --git a/package.json b/package.json index 34216ba0..7ba97964 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,8 @@ "electron:before": "yarn electron:before:download-ipfs && yarn electron:before:delete-data", "electron:before:download-ipfs": "node electron/downloadIpfs", "electron:before:delete-data": "rimraf .plebbit", - "android:build:icons": "cordova-res android --skip-config --copy --resources /tmp/plebbit-react-android-icons --icon-source ./android/icons/icon.png --splash-source ./android/icons/splash.png --icon-foreground-source ./android/icons/icon-foreground.png --icon-background-source '#ffffee'" + "android:build:icons": "cordova-res android --skip-config --copy --resources /tmp/plebbit-react-android-icons --icon-source ./android/icons/icon.png --splash-source ./android/icons/splash.png --icon-foreground-source ./android/icons/icon-foreground.png --icon-background-source '#ffffee'", + "prettier": "prettier src/**/*.{js,jsx} --write" }, "eslintConfig": { "extends": [ @@ -131,6 +132,7 @@ "decompress": "4.2.1", "electron": "19.1.8", "electron-builder": "23.0.9", + "prettier": "2.3.2", "source-map-explorer": "2.5.3", "typescript": "5.0.2", "wait-on": "7.0.1" diff --git a/prettier.config.js b/prettier.config.js new file mode 100644 index 00000000..c7f18629 --- /dev/null +++ b/prettier.config.js @@ -0,0 +1,6 @@ +module.exports = { + semi: false, + singleQuote: true, + printWidth: 170, + bracketSpacing: false, +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index ce0deb66..1f18405b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12094,6 +12094,11 @@ prepend-http@^2.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== +prettier@2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.2.tgz#ef280a05ec253712e486233db5c6f23441e7342d" + integrity sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ== + pretty-bytes@^5.3.0, pretty-bytes@^5.4.1: version "5.6.0" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" From d963c90d26144c7b2bae39866c0b7fe83c9142f2 Mon Sep 17 00:00:00 2001 From: "plebeius.eth" Date: Sat, 16 Sep 2023 21:39:25 +0200 Subject: [PATCH 12/13] Update prettier.config.js --- prettier.config.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/prettier.config.js b/prettier.config.js index c7f18629..31549966 100644 --- a/prettier.config.js +++ b/prettier.config.js @@ -1,6 +1,11 @@ module.exports = { - semi: false, + semi: true, singleQuote: true, printWidth: 170, - bracketSpacing: false, + bracketSpacing: true, + tabWidth: 2, + trailingComma: 'all', + jsxSingleQuote: true, + arrowParens: 'always', + useTabs: true, } \ No newline at end of file From 020e509b71048b39a62b0a663d371a8ce1dcc525 Mon Sep 17 00:00:00 2001 From: "plebeius.eth" Date: Sat, 16 Sep 2023 21:40:23 +0200 Subject: [PATCH 13/13] prettify --- src/components/BoardAvatar.jsx | 29 +- src/components/BoardSettings.jsx | 565 +++++++++++++------------- src/components/BoardStats.jsx | 118 +++--- src/components/CatalogLoader.jsx | 80 ++-- src/components/EditLabel.jsx | 118 +++--- src/components/Embed.jsx | 395 +++++++++--------- src/components/ForwardRefLink.jsx | 50 +-- src/components/ImageBanner.jsx | 54 ++- src/components/OfflineIndicator.jsx | 46 +-- src/components/PendingLabel.jsx | 36 +- src/components/Post.jsx | 240 ++++++----- src/components/PostLoader.jsx | 61 ++- src/components/PostOnHover.jsx | 609 +++++++++++++--------------- src/components/StateLabel.jsx | 45 +- src/components/VerifiedAuthor.jsx | 10 +- src/hooks/useAnonMode.js | 45 +- src/hooks/useAnonModeRef.js | 44 +- src/hooks/useClickForm.js | 16 +- src/hooks/useError.js | 85 ++-- src/hooks/useFeedRows.js | 33 +- src/hooks/useFeedStateString.js | 175 ++++---- src/hooks/useInfo.js | 68 ++-- src/hooks/useStateString.js | 190 +++++---- src/hooks/useSuccess.js | 68 ++-- src/hooks/useWindowWidth.js | 22 +- src/utils/countLinks.js | 27 +- src/utils/findShortParentCid.js | 28 +- src/utils/getCommentMediaInfo.js | 128 +++--- src/utils/getDate.js | 69 ++-- src/utils/getFormattedTime.js | 73 ++-- src/utils/handleAddressClick.js | 58 +-- src/utils/handleImageClick.js | 14 +- src/utils/handleQuoteClick.js | 88 ++-- src/utils/handleQuoteHover.js | 69 ++-- src/utils/handleShareClick.js | 47 ++- src/utils/handleStyleChange.js | 166 ++++---- src/utils/isValidUrl.js | 14 +- src/utils/preloadImages.js | 10 +- src/utils/removeHighlight.js | 12 +- 39 files changed, 1970 insertions(+), 2035 deletions(-) diff --git a/src/components/BoardAvatar.jsx b/src/components/BoardAvatar.jsx index 3499cf93..f94359d6 100644 --- a/src/components/BoardAvatar.jsx +++ b/src/components/BoardAvatar.jsx @@ -1,24 +1,17 @@ -import React, { useEffect, useState } from "react"; -import { useSubplebbit } from "@plebbit/plebbit-react-hooks"; - +import React, { useEffect, useState } from 'react'; +import { useSubplebbit } from '@plebbit/plebbit-react-hooks'; const BoardAvatar = ({ address }) => { - const [avatarUrl, setAvatarUrl] = useState("assets/plebchan.png"); - const subplebbit = useSubplebbit({ subplebbitAddress: address }); + const [avatarUrl, setAvatarUrl] = useState('assets/plebchan.png'); + const subplebbit = useSubplebbit({ subplebbitAddress: address }); - useEffect(() => { - if (subplebbit.suggested?.avatarUrl) { - setAvatarUrl(subplebbit.suggested?.avatarUrl); - } - }, [subplebbit.suggested?.avatarUrl, subplebbit]); + useEffect(() => { + if (subplebbit.suggested?.avatarUrl) { + setAvatarUrl(subplebbit.suggested?.avatarUrl); + } + }, [subplebbit.suggested?.avatarUrl, subplebbit]); - return ( - board avatar - ); + return board avatar; }; -export default BoardAvatar; \ No newline at end of file +export default BoardAvatar; diff --git a/src/components/BoardSettings.jsx b/src/components/BoardSettings.jsx index a183737b..113d0449 100644 --- a/src/components/BoardSettings.jsx +++ b/src/components/BoardSettings.jsx @@ -1,332 +1,315 @@ -import React, { useEffect, useRef, useState } from "react"; -import { Link } from "react-router-dom"; -import { usePublishSubplebbitEdit } from "@plebbit/plebbit-react-hooks"; +import React, { useEffect, useRef, useState } from 'react'; +import { Link } from 'react-router-dom'; +import { usePublishSubplebbitEdit } from '@plebbit/plebbit-react-hooks'; import { StyledModal } from './styled/modals/ModerationModal.styled'; -import useError from "../hooks/useError"; -import useSuccess from "../hooks/useSuccess"; +import useError from '../hooks/useError'; +import useSuccess from '../hooks/useSuccess'; import useGeneralStore from '../hooks/stores/useGeneralStore'; const BoardSettings = ({ subplebbit }) => { - const { - setCaptchaResponse, - setChallengesArray, - setIsCaptchaOpen, - setResolveCaptchaPromise, - selectedAddress, - selectedStyle, - } = useGeneralStore(state => state); + const { setCaptchaResponse, setChallengesArray, setIsCaptchaOpen, setResolveCaptchaPromise, selectedAddress, selectedStyle } = useGeneralStore((state) => state); - const allowedSettings = { - address: subplebbit.address, - apiUrl: subplebbit.apiUrl, - description: subplebbit.description, - pubsubTopic: subplebbit.pubsubTopic, - settings: { - fetchThumbnailUrls: subplebbit.settings?.fetchThumbnailUrls, - fetchThumbnailUrlsProxyUrl: subplebbit.settings?.fetchThumbnailUrlsProxyUrl, - }, - roles: subplebbit.roles, - rules: subplebbit.rules, - suggested: { - avatarUrl: subplebbit.suggested?.avatarUrl, - backgroundUrl: subplebbit.suggested?.backgroundUrl, - bannerUrl: subplebbit.suggested?.bannerUrl, - language: subplebbit.suggested?.language, - primaryColor: subplebbit.suggested?.primaryColor, - secondaryColor: subplebbit.suggested?.secondaryColor, - }, - title: subplebbit.title, - }; + const allowedSettings = { + address: subplebbit.address, + apiUrl: subplebbit.apiUrl, + description: subplebbit.description, + pubsubTopic: subplebbit.pubsubTopic, + settings: { + fetchThumbnailUrls: subplebbit.settings?.fetchThumbnailUrls, + fetchThumbnailUrlsProxyUrl: subplebbit.settings?.fetchThumbnailUrlsProxyUrl, + }, + roles: subplebbit.roles, + rules: subplebbit.rules, + suggested: { + avatarUrl: subplebbit.suggested?.avatarUrl, + backgroundUrl: subplebbit.suggested?.backgroundUrl, + bannerUrl: subplebbit.suggested?.bannerUrl, + language: subplebbit.suggested?.language, + primaryColor: subplebbit.suggested?.primaryColor, + secondaryColor: subplebbit.suggested?.secondaryColor, + }, + title: subplebbit.title, + }; - const generateSettingsFromSubplebbit = (subplebbitData) => ({ - address: subplebbitData.address, - apiUrl: subplebbitData.apiUrl, - description: subplebbitData.description, - pubsubTopic: subplebbitData.pubsubTopic, - settings: { - fetchThumbnailUrls: subplebbitData.settings?.fetchThumbnailUrls, - fetchThumbnailUrlsProxyUrl: subplebbitData.settings?.fetchThumbnailUrlsProxyUrl, - }, - roles: subplebbitData.roles, - rules: subplebbitData.rules, - suggested: { - avatarUrl: subplebbitData.suggested?.avatarUrl, - backgroundUrl: subplebbitData.suggested?.backgroundUrl, - bannerUrl: subplebbitData.suggested?.bannerUrl, - language: subplebbitData.suggested?.language, - primaryColor: subplebbitData.suggested?.primaryColor, - secondaryColor: subplebbitData.suggested?.secondaryColor, - }, - title: subplebbitData.title, - }); + const generateSettingsFromSubplebbit = (subplebbitData) => ({ + address: subplebbitData.address, + apiUrl: subplebbitData.apiUrl, + description: subplebbitData.description, + pubsubTopic: subplebbitData.pubsubTopic, + settings: { + fetchThumbnailUrls: subplebbitData.settings?.fetchThumbnailUrls, + fetchThumbnailUrlsProxyUrl: subplebbitData.settings?.fetchThumbnailUrlsProxyUrl, + }, + roles: subplebbitData.roles, + rules: subplebbitData.rules, + suggested: { + avatarUrl: subplebbitData.suggested?.avatarUrl, + backgroundUrl: subplebbitData.suggested?.backgroundUrl, + bannerUrl: subplebbitData.suggested?.bannerUrl, + language: subplebbitData.suggested?.language, + primaryColor: subplebbitData.suggested?.primaryColor, + secondaryColor: subplebbitData.suggested?.secondaryColor, + }, + title: subplebbitData.title, + }); - const initialSettings = generateSettingsFromSubplebbit(subplebbit); - const [isModalOpen, setIsModalOpen] = useState(false); - const [boardSettingsJson, setBoardSettingsJson] = useState(JSON.stringify(initialSettings, null, 2)); - const [triggerPublilshSubplebbitEdit, setTriggerPublishCommentEdit] = useState(false); + const initialSettings = generateSettingsFromSubplebbit(subplebbit); + const [isModalOpen, setIsModalOpen] = useState(false); + const [boardSettingsJson, setBoardSettingsJson] = useState(JSON.stringify(initialSettings, null, 2)); + const [triggerPublilshSubplebbitEdit, setTriggerPublishCommentEdit] = useState(false); - const [, setNewErrorMessage] = useError(); - const [, setNewSuccessMessage] = useSuccess(); - + const [, setNewErrorMessage] = useError(); + const [, setNewSuccessMessage] = useSuccess(); - const getDifferences = (oldObj, newObj) => { - let differences = {}; - - for (let key in oldObj) { - if (typeof oldObj[key] === 'object' && oldObj[key] !== null) { - const nestedDifferences = getDifferences(oldObj[key], newObj[key] || {}); - if (Object.keys(nestedDifferences).length > 0) { - differences[key] = nestedDifferences; - } - } else if (oldObj[key] !== newObj[key]) { - differences[key] = newObj[key]; - } - } - - for (let key in newObj) { - if (!oldObj.hasOwnProperty(key)) { - differences[key] = newObj[key]; - } - } - - return differences; - }; + const getDifferences = (oldObj, newObj) => { + let differences = {}; + for (let key in oldObj) { + if (typeof oldObj[key] === 'object' && oldObj[key] !== null) { + const nestedDifferences = getDifferences(oldObj[key], newObj[key] || {}); + if (Object.keys(nestedDifferences).length > 0) { + differences[key] = nestedDifferences; + } + } else if (oldObj[key] !== newObj[key]) { + differences[key] = newObj[key]; + } + } - const isInitialMount = useRef(true); + for (let key in newObj) { + if (!oldObj.hasOwnProperty(key)) { + differences[key] = newObj[key]; + } + } - useEffect(() => { - if (isInitialMount.current) { - setBoardSettingsJson(JSON.stringify(generateSettingsFromSubplebbit(subplebbit), null, 2)); - isInitialMount.current = false; - } - }, [subplebbit]); + return differences; + }; + const isInitialMount = useRef(true); - function validateSettings(updatedSettings, allowedSettings) { - for (let key in updatedSettings) { - if (!allowedSettings.hasOwnProperty(key) && !initialSettings.hasOwnProperty(key)) { - throw new Error(`Unexpected setting: ${key}`); - } + useEffect(() => { + if (isInitialMount.current) { + setBoardSettingsJson(JSON.stringify(generateSettingsFromSubplebbit(subplebbit), null, 2)); + isInitialMount.current = false; + } + }, [subplebbit]); - if (typeof updatedSettings[key] === 'object' && updatedSettings[key] !== null - && !Array.isArray(updatedSettings[key])) { - if (typeof allowedSettings[key] !== 'object' || allowedSettings[key] === null - || Array.isArray(allowedSettings[key])) { - throw new Error(`Expected ${key} to be an object in allowedSettings`); - } - validateSettings(updatedSettings[key], allowedSettings[key]); - } - } - } + function validateSettings(updatedSettings, allowedSettings) { + for (let key in updatedSettings) { + if (!allowedSettings.hasOwnProperty(key) && !initialSettings.hasOwnProperty(key)) { + throw new Error(`Unexpected setting: ${key}`); + } + if (typeof updatedSettings[key] === 'object' && updatedSettings[key] !== null && !Array.isArray(updatedSettings[key])) { + if (typeof allowedSettings[key] !== 'object' || allowedSettings[key] === null || Array.isArray(allowedSettings[key])) { + throw new Error(`Expected ${key} to be an object in allowedSettings`); + } + validateSettings(updatedSettings[key], allowedSettings[key]); + } + } + } - const onChallenge = async (challenges, subplebbitEdit) => { - let challengeAnswers = []; - - try { - challengeAnswers = await getChallengeAnswersFromUser(challenges) - } - catch (error) { - setNewErrorMessage(error.message); console.log(error); - } - if (challengeAnswers) { - await subplebbitEdit.publishChallengeAnswers(challengeAnswers) - } - }; + const onChallenge = async (challenges, subplebbitEdit) => { + let challengeAnswers = []; + try { + challengeAnswers = await getChallengeAnswersFromUser(challenges); + } catch (error) { + setNewErrorMessage(error.message); + console.log(error); + } + if (challengeAnswers) { + await subplebbitEdit.publishChallengeAnswers(challengeAnswers); + } + }; - const onChallengeVerification = (challengeVerification) => { - if (challengeVerification.challengeSuccess === true) { - setNewSuccessMessage('Challenge Success'); console.log('challenge success', challengeVerification); - } else if (challengeVerification.challengeSuccess === false) { - setNewErrorMessage(`Challenge Failed, reason: ${challengeVerification.reason}. Errors: ${challengeVerification.errors}`); - console.log('challenge failed', challengeVerification); - } - }; + const onChallengeVerification = (challengeVerification) => { + if (challengeVerification.challengeSuccess === true) { + setNewSuccessMessage('Challenge Success'); + console.log('challenge success', challengeVerification); + } else if (challengeVerification.challengeSuccess === false) { + setNewErrorMessage(`Challenge Failed, reason: ${challengeVerification.reason}. Errors: ${challengeVerification.errors}`); + console.log('challenge failed', challengeVerification); + } + }; + const getChallengeAnswersFromUser = async (challenges) => { + setChallengesArray(challenges); - 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 = useGeneralStore.getState().captchaResponse; - resolve(currentCaptchaResponse); - setIsCaptchaOpen(false); - document.removeEventListener('keydown', handleKeyDown); - event.preventDefault(); - } - }; + 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; - setCaptchaResponse(''); - document.addEventListener('keydown', handleKeyDown); + challengeImg.onload = () => { + setIsCaptchaOpen(true); - setResolveCaptchaPromise(resolve); - }; - - challengeImg.onerror = () => { - reject(setNewErrorMessage('Could not load challenges')); - }; - }); - }; + const handleKeyDown = async (event) => { + if (event.key === 'Enter') { + const currentCaptchaResponse = useGeneralStore.getState().captchaResponse; + resolve(currentCaptchaResponse); + setIsCaptchaOpen(false); + document.removeEventListener('keydown', handleKeyDown); + event.preventDefault(); + } + }; + setCaptchaResponse(''); + document.addEventListener('keydown', handleKeyDown); - const [editSubplebbitOptions, setEditSubplebbitOptions] = useState({ - subplebbitAddress: selectedAddress, - onChallenge, - onChallengeVerification, - onError: (error) => { - setNewErrorMessage(error.message); console.log(error); - } - }); + setResolveCaptchaPromise(resolve); + }; + challengeImg.onerror = () => { + reject(setNewErrorMessage('Could not load challenges')); + }; + }); + }; - const { publishSubplebbitEdit } = usePublishSubplebbitEdit(editSubplebbitOptions); + const [editSubplebbitOptions, setEditSubplebbitOptions] = useState({ + subplebbitAddress: selectedAddress, + onChallenge, + onChallengeVerification, + onError: (error) => { + setNewErrorMessage(error.message); + console.log(error); + }, + }); + const { publishSubplebbitEdit } = usePublishSubplebbitEdit(editSubplebbitOptions); - useEffect(() => { - let isActive = true; - if (editSubplebbitOptions && triggerPublilshSubplebbitEdit) { - (async () => { - await publishSubplebbitEdit(editSubplebbitOptions); - if (isActive) { - setTriggerPublishCommentEdit(false); - } - })(); - } + useEffect(() => { + let isActive = true; + if (editSubplebbitOptions && triggerPublilshSubplebbitEdit) { + (async () => { + await publishSubplebbitEdit(editSubplebbitOptions); + if (isActive) { + setTriggerPublishCommentEdit(false); + } + })(); + } - return () => { - isActive = false; - }; - }, [editSubplebbitOptions, publishSubplebbitEdit, triggerPublilshSubplebbitEdit]); + return () => { + isActive = false; + }; + }, [editSubplebbitOptions, publishSubplebbitEdit, triggerPublilshSubplebbitEdit]); - - const handleSaveChanges = async () => { - try { - const updatedSettings = JSON.parse(boardSettingsJson); - validateSettings(updatedSettings, allowedSettings); - const changes = getDifferences(initialSettings, updatedSettings); - if (Object.keys(changes).length > 0) { - setEditSubplebbitOptions(prevOptions => ({ - ...prevOptions, - ...changes - })); - setTriggerPublishCommentEdit(true); - } else { - setNewErrorMessage("No changes detected"); - } - } catch (error) { - setNewErrorMessage(`Error saving changes: ${error}`); - console.log(error); - } - }; + const handleSaveChanges = async () => { + try { + const updatedSettings = JSON.parse(boardSettingsJson); + validateSettings(updatedSettings, allowedSettings); + const changes = getDifferences(initialSettings, updatedSettings); + if (Object.keys(changes).length > 0) { + setEditSubplebbitOptions((prevOptions) => ({ + ...prevOptions, + ...changes, + })); + setTriggerPublishCommentEdit(true); + } else { + setNewErrorMessage('No changes detected'); + } + } catch (error) { + setNewErrorMessage(`Error saving changes: ${error}`); + console.log(error); + } + }; + const handleResetChanges = () => { + setBoardSettingsJson(JSON.stringify(initialSettings, null, 2)); + }; - const handleResetChanges = () => { - setBoardSettingsJson(JSON.stringify(initialSettings, null, 2)); - }; - + function generateSettingsList(settingsObj, parentKey = '') { + let result = []; - function generateSettingsList(settingsObj, parentKey = '') { - let result = []; - - for (let key in settingsObj) { - if (typeof settingsObj[key] === 'object' && settingsObj[key] !== null) { - const nestedItems = generateSettingsList(settingsObj[key], `${parentKey}${key}.`); - if (nestedItems.length > 1) { - result.push(`${parentKey}${key}: { ${nestedItems.join(', ')} }`); - } else { - result.push(...nestedItems); - } - } else { - result.push(`${parentKey}${key}`); - } - } - - return result; - } - + for (let key in settingsObj) { + if (typeof settingsObj[key] === 'object' && settingsObj[key] !== null) { + const nestedItems = generateSettingsList(settingsObj[key], `${parentKey}${key}.`); + if (nestedItems.length > 1) { + result.push(`${parentKey}${key}: { ${nestedItems.join(', ')} }`); + } else { + result.push(...nestedItems); + } + } else { + result.push(`${parentKey}${key}`); + } + } - const possibleSettingsList = generateSettingsList(initialSettings); + return result; + } + const possibleSettingsList = generateSettingsList(initialSettings); - const handleCloseModal = () => { - setIsModalOpen(false); - setBoardSettingsJson(JSON.stringify(initialSettings, null, 2)); - }; + const handleCloseModal = () => { + setIsModalOpen(false); + setBoardSettingsJson(JSON.stringify(initialSettings, null, 2)); + }; - const openModal = () => { - setIsModalOpen(true); - setBoardSettingsJson(JSON.stringify(generateSettingsFromSubplebbit(subplebbit), null, 2)); - }; + const openModal = () => { + setIsModalOpen(true); + setBoardSettingsJson(JSON.stringify(generateSettingsFromSubplebbit(subplebbit), null, 2)); + }; - - return ( - <> - -
-
- Board Settings - - - -
-
-
- Allowed settings: - - {`{ ${possibleSettingsList.join(', ')} }`} - -
- API docs: https://github.com/plebbit/plebbit-js#readme -
-