From 828e066d3dd2898d5fee22339a5573de682fd5a5 Mon Sep 17 00:00:00 2001 From: "Tom (plebeius.eth)" Date: Fri, 9 Aug 2024 12:08:22 +0200 Subject: [PATCH 01/11] fix replymodal autofocus --- src/components/reply-modal/reply-modal.tsx | 35 ++++++++++++---------- src/views/board/board.tsx | 2 +- src/views/post/post.tsx | 2 +- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/components/reply-modal/reply-modal.tsx b/src/components/reply-modal/reply-modal.tsx index 6a7455bc..28a41b8d 100644 --- a/src/components/reply-modal/reply-modal.tsx +++ b/src/components/reply-modal/reply-modal.tsx @@ -17,12 +17,13 @@ import useAnonMode from '../../hooks/use-anon-mode'; interface ReplyModalProps { closeModal: () => void; + showReplyModal: boolean; parentCid: string; postCid: string; scrollY: number; } -const ReplyModal = ({ closeModal, parentCid, postCid, scrollY }: ReplyModalProps) => { +const ReplyModal = ({ closeModal, showReplyModal, parentCid, postCid, scrollY }: ReplyModalProps) => { const { t } = useTranslation(); const { subplebbitAddress } = useParams() as { subplebbitAddress: string }; const { setPublishReplyOptions, publishReply } = usePublishReply({ cid: parentCid, subplebbitAddress }); @@ -122,14 +123,15 @@ const ReplyModal = ({ closeModal, parentCid, postCid, scrollY }: ReplyModalProps ) : `The subplebbit might be offline and publishing might fail.`; - const setTextRef = (ref: HTMLTextAreaElement | null) => { - if (ref) { - textRef.current = ref; - // if (!isMobile && !urlRef.current?.value) { - // ref.focus(); - // } + useEffect(() => { + if (showReplyModal && !isMobile) { + setTimeout(() => { + if (textRef.current) { + textRef.current.focus(); + } + }, 0); } - }; + }, [showReplyModal, isMobile]); useEffect(() => { if (textRef.current) { @@ -196,7 +198,7 @@ const ReplyModal = ({ closeModal, parentCid, postCid, scrollY }: ReplyModalProps cols={48} rows={4} wrap='soft' - ref={setTextRef} + ref={textRef} spellCheck={false} defaultValue={contentPrefix + selectedText} onInput={handleContentInput} @@ -227,12 +229,15 @@ const ReplyModal = ({ closeModal, parentCid, postCid, scrollY }: ReplyModalProps ); - return isMobile ? ( - modalContent - ) : ( - - {modalContent} - + return ( + showReplyModal && + (isMobile ? ( + modalContent + ) : ( + + {modalContent} + + )) ); }; diff --git a/src/views/board/board.tsx b/src/views/board/board.tsx index cd42dea4..64036b43 100644 --- a/src/views/board/board.tsx +++ b/src/views/board/board.tsx @@ -158,7 +158,7 @@ const Board = () => { return (
{location.pathname.endsWith('/settings') && } - {showReplyModal && activeCid && threadCid && } + {activeCid && threadCid && } {feed.length !== 0 ? ( <> {rules && rules.length > 0 && } diff --git a/src/views/post/post.tsx b/src/views/post/post.tsx index b3c94dff..0f4cf02a 100644 --- a/src/views/post/post.tsx +++ b/src/views/post/post.tsx @@ -91,7 +91,7 @@ const PostPage = () => { return (
{isInSettigsView && } - {showReplyModal && activeCid && threadCid && } + {activeCid && threadCid && } {/* TODO: remove this replyCount error once api supports scrolling replies pages */} {replyCount > 60 && Error: this thread has too many replies, some of them cannot be displayed right now.} {error && Error: {error.message}} From cfe8686d94c6ad0df05fe6a240ef25b1840429be Mon Sep 17 00:00:00 2001 From: "Tom (plebeius.eth)" Date: Mon, 12 Aug 2024 13:13:42 +0200 Subject: [PATCH 02/11] fix(popular threads box): in each post content, one return would appear as two returns (empty lines) --- src/views/home/popular-threads-box/popular-threads-box.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/views/home/popular-threads-box/popular-threads-box.tsx b/src/views/home/popular-threads-box/popular-threads-box.tsx index 6e6a58ae..f06e73de 100644 --- a/src/views/home/popular-threads-box/popular-threads-box.tsx +++ b/src/views/home/popular-threads-box/popular-threads-box.tsx @@ -18,9 +18,11 @@ interface PopularThreadProps { } const PopularThreadCard = ({ post, boardTitle, boardShortAddress }: PopularThreadProps) => { - const { cid, content, subplebbitAddress, title } = post || {}; + const { cid, subplebbitAddress, title } = post || {}; const commentMediaInfo = getCommentMediaInfo(post); + let content = post?.content?.replace(/\n\n/g, '\n'); + return (
{boardTitle || boardShortAddress}
From 99a219733c65138616976fd3f3f71a6b90199909 Mon Sep 17 00:00:00 2001 From: "Tom (plebeius.eth)" Date: Mon, 12 Aug 2024 18:11:18 +0200 Subject: [PATCH 03/11] feat(post): add button to show full comment when it's too long --- src/components/post-desktop/post-desktop.tsx | 14 +++++--------- src/components/post-mobile/post-mobile.tsx | 14 +++++--------- src/views/post/post.module.css | 10 ++++++---- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/components/post-desktop/post-desktop.tsx b/src/components/post-desktop/post-desktop.tsx index 556c9860..96bdff11 100644 --- a/src/components/post-desktop/post-desktop.tsx +++ b/src/components/post-desktop/post-desktop.tsx @@ -239,8 +239,7 @@ const PostMedia = ({ post }: PostProps) => { }; const PostMessage = ({ post }: PostProps) => { - const { cid, content, deleted, edit, original, parentCid, postCid, reason, removed, state, subplebbitAddress } = post || {}; - const { isDescription, isRules } = post || {}; // custom properties, not from api + const { cid, content, deleted, edit, original, parentCid, postCid, reason, removed, state } = post || {}; // TODO: commentAuthor is not available outside of editedComment, update when available // const banned = !!post?.commentAuthor?.banExpiresAt; const { t } = useTranslation(); @@ -249,7 +248,8 @@ const PostMessage = ({ post }: PostProps) => { const isInPostView = isPostPageView(location.pathname, params); const [showOriginal, setShowOriginal] = useState(false); - const displayContent = content && !isInPostView && content.length > 1000 ? content?.slice(0, 1000) + '(...)' : content; + const [showFullComment, setShowFullComment] = useState(false); + const displayContent = content && !isInPostView && content.length > 1000 && !showFullComment ? content.slice(0, 1000) : content; const quotelinkReply = useComment({ commentCid: parentCid }); const isReply = parentCid; @@ -318,14 +318,10 @@ const PostMessage = ({ post }: PostProps) => { /> )} */} - {!isReply && content.length > 1000 && !isInPostView && ( + {content?.length > 1000 && !isInPostView && !showFullComment && (
- }} - /> + setShowFullComment(true)} /> }} />
)} {!cid && state === 'pending' && stateString !== 'Failed' && ( diff --git a/src/components/post-mobile/post-mobile.tsx b/src/components/post-mobile/post-mobile.tsx index 025b65e5..81f07724 100644 --- a/src/components/post-mobile/post-mobile.tsx +++ b/src/components/post-mobile/post-mobile.tsx @@ -163,8 +163,7 @@ const ReplyBacklinks = ({ post }: PostProps) => { const PostMessageMobile = ({ post }: PostProps) => { const { t } = useTranslation(); - const { cid, content, deleted, edit, original, parentCid, postCid, reason, removed, state, subplebbitAddress } = post || {}; - const { isDescription, isRules } = post || {}; // custom properties, not from api + const { cid, content, deleted, edit, original, parentCid, postCid, reason, removed, state } = post || {}; // TODO: commentAuthor is not available outside of editedComment, update when available // const banned = !!post?.commentAuthor?.banExpiresAt; const [showOriginal, setShowOriginal] = useState(false); @@ -173,7 +172,8 @@ const PostMessageMobile = ({ post }: PostProps) => { const location = useLocation(); const isInPostView = isPostPageView(location.pathname, params); - const displayContent = content && !isInPostView && content.length > 1000 ? content?.slice(0, 1000) : content; + const [showFullComment, setShowFullComment] = useState(false); + const displayContent = content && !isInPostView && content.length > 1000 && !showFullComment ? content.slice(0, 1000) : content; const quotelinkReply = useComment({ commentCid: parentCid }); const isReply = parentCid; @@ -242,14 +242,10 @@ const PostMessageMobile = ({ post }: PostProps) => { /> )} */} - {!isReply && content.length > 1000 && !isInPostView && ( + {content?.length > 1000 && !isInPostView && !showFullComment && (
- }} - /> + setShowFullComment(true)} /> }} />
)} {!cid && state === 'pending' && stateString !== 'Failed' && ( diff --git a/src/views/post/post.module.css b/src/views/post/post.module.css index 5c9e6bb0..14e78581 100644 --- a/src/views/post/post.module.css +++ b/src/views/post/post.module.css @@ -164,12 +164,13 @@ font-size: var(--post-mobile-abbr-font-size); } -.postDesktop .abbr a { +.postDesktop .abbr a, .postDesktop .abbr span { color: var(--post-link-text-color); text-decoration: var(--post-content-link-text-decoration); } -.postDesktop .abbr a:hover { +.postDesktop .abbr a:hover, .postDesktop .abbr span:hover { + cursor: pointer; color: var(--post-link-text-color-hover); text-decoration: var(--post-content-link-text-decoration-hover); } @@ -344,13 +345,14 @@ font-size: var(--post-mobile-abbr-font-size); } -.postMobile .abbr a { +.postMobile .abbr a, .postMobile .abbr span { color: var(--post-link-text-color); text-decoration: var(--post-content-link-text-decoration); } -.postMobile .abbr a:hover { +.postMobile .abbr a:hover, .postMobile .abbr span:hover { + cursor: pointer; color: var(--post-link-text-color-hover); text-decoration: var(--post-content-link-text-decoration-hover); } From 43561e9077a744b4b0d00a30ff800578fd694463 Mon Sep 17 00:00:00 2001 From: "Tom (plebeius.eth)" Date: Mon, 12 Aug 2024 21:55:52 +0200 Subject: [PATCH 04/11] fix couldn't change displayName more than once on anon mode --- src/components/post-form/post-form.tsx | 21 ++++++++++++++------ src/components/reply-modal/reply-modal.tsx | 14 ++++++++----- src/hooks/use-publish-reply.ts | 23 +++++++++++++++------- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/components/post-form/post-form.tsx b/src/components/post-form/post-form.tsx index edd9c5ac..ab38d5d0 100644 --- a/src/components/post-form/post-form.tsx +++ b/src/components/post-form/post-form.tsx @@ -160,12 +160,11 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid: setSubmitStore({ signer: newSigner, author: { - displayName, address: newSigner.address, }, }); } - }, [anonMode, getNewSigner, setSubmitStore, displayName]); + }, [anonMode, getNewSigner, setSubmitStore]); const onPublishPost = async () => { if (!title && !content && !link) { @@ -212,7 +211,6 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid: setPublishReplyOptions({ signer: existingSigner, author: { - displayName, address: existingSigner.address, }, }); @@ -221,13 +219,12 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid: setPublishReplyOptions({ signer: newSigner, author: { - displayName, address: newSigner.address, }, }); } } - }, [address, getExistingSigner, getNewSigner, setPublishReplyOptions, displayName, anonMode]); + }, [address, getExistingSigner, getNewSigner, setPublishReplyOptions, anonMode]); const onPublishReply = () => { const currentContent = textRef.current?.value || ''; @@ -246,6 +243,14 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid: publishReply(); }; + const hasSetInitialDisplayName = useRef(false); + useEffect(() => { + if (!hasSetInitialDisplayName.current && displayName) { + setPublishReplyOptions({ displayName }); + hasSetInitialDisplayName.current = true; + } + }, [displayName, setPublishReplyOptions]); + useEffect(() => { if (typeof replyIndex === 'number') { resetPublishReplyOptions(); @@ -276,7 +281,11 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid: defaultValue={displayName || undefined} onChange={(e) => { setAccount({ ...account, author: { ...account?.author, displayName: e.target.value } }); - setSubmitStore({ displayName: e.target.value }); + if (isInPostView) { + setPublishReplyOptions({ displayName: e.target.value }); + } else { + setSubmitStore({ displayName: e.target.value }); + } }} /> {isInPostView && } diff --git a/src/components/reply-modal/reply-modal.tsx b/src/components/reply-modal/reply-modal.tsx index 28a41b8d..efdc50e3 100644 --- a/src/components/reply-modal/reply-modal.tsx +++ b/src/components/reply-modal/reply-modal.tsx @@ -48,7 +48,6 @@ const ReplyModal = ({ closeModal, showReplyModal, parentCid, postCid, scrollY }: setPublishReplyOptions({ signer: existingSigner, author: { - displayName, address: existingSigner.address, }, }); @@ -57,13 +56,12 @@ const ReplyModal = ({ closeModal, showReplyModal, parentCid, postCid, scrollY }: setPublishReplyOptions({ signer: newSigner, author: { - displayName, address: newSigner.address, }, }); } } - }, [anonMode, address, getExistingSigner, getNewSigner, displayName, setPublishReplyOptions]); + }, [anonMode, address, getExistingSigner, getNewSigner, setPublishReplyOptions]); useEffect(() => { if (anonMode) { @@ -89,10 +87,17 @@ const ReplyModal = ({ closeModal, showReplyModal, parentCid, postCid, scrollY }: closeModal(); }; + const hasSetInitialDisplayName = useRef(false); + useEffect(() => { + if (!hasSetInitialDisplayName.current && displayName) { + setPublishReplyOptions({ displayName }); + hasSetInitialDisplayName.current = true; + } + }, [displayName, setPublishReplyOptions]); + const nodeRef = useRef(null); const isMobile = useIsMobile(); - // on mobile, the position is absolute instead of fixed, so we need to calculate the top position useEffect(() => { if (nodeRef.current && isMobile) { const viewportHeight = window.innerHeight; @@ -150,7 +155,6 @@ const ReplyModal = ({ closeModal, showReplyModal, parentCid, postCid, scrollY }: }; const handleContentChange = (e: React.ChangeEvent) => { - // remove the prefix from the content to publish, and also add newlines for markdown const contentWithoutPrefix = e.target.value.slice(contentPrefix.length).replace(/\n/g, '\n\n'); if (textRef.current && textRef.current.value !== contentWithoutPrefix) { setPublishReplyOptions({ content: contentWithoutPrefix }); diff --git a/src/hooks/use-publish-reply.ts b/src/hooks/use-publish-reply.ts index 92ed28f3..783469d5 100644 --- a/src/hooks/use-publish-reply.ts +++ b/src/hooks/use-publish-reply.ts @@ -36,15 +36,21 @@ const useReplyStore = create((set) => ({ signer: {}, spoiler: {}, publishCommentOptions: {}, + setReplyStore: (data: SetReplyStoreData) => set((state) => { const { subplebbitAddress, parentCid, author, displayName, content, link, signer, spoiler } = data; - const updatedAuthor = displayName ? { ...author, displayName } : author; + + const updatedAuthor = { + ...(state.author[parentCid] || author), + ...(displayName ? { displayName } : {}), + }; + const publishCommentOptions = { subplebbitAddress, parentCid, - ...(data.author ? { author: updatedAuthor } : {}), - ...(data.signer ? { signer: data.signer } : {}), + ...(updatedAuthor ? { author: updatedAuthor } : {}), + ...(signer ? { signer } : {}), content, link, spoiler, @@ -57,11 +63,12 @@ const useReplyStore = create((set) => ({ alert(error.message); }, }; + return { author: { ...state.author, [parentCid]: updatedAuthor }, - signer: { ...state.signer, [parentCid]: signer }, content: { ...state.content, [parentCid]: content }, link: { ...state.link, [parentCid]: link }, + signer: { ...state.signer, [parentCid]: signer }, spoiler: { ...state.spoiler, [parentCid]: spoiler }, publishCommentOptions: { ...state.publishCommentOptions, [parentCid]: publishCommentOptions }, }; @@ -70,9 +77,9 @@ const useReplyStore = create((set) => ({ resetReplyStore: (parentCid) => set((state) => ({ author: { ...state.author, [parentCid]: undefined }, - signer: { ...state.signer, [parentCid]: undefined }, content: { ...state.content, [parentCid]: undefined }, link: { ...state.link, [parentCid]: undefined }, + signer: { ...state.signer, [parentCid]: undefined }, spoiler: { ...state.spoiler, [parentCid]: undefined }, publishCommentOptions: { ...state.publishCommentOptions, [parentCid]: undefined }, })), @@ -80,8 +87,9 @@ const useReplyStore = create((set) => ({ const useReply = ({ cid, subplebbitAddress }: { cid: string; subplebbitAddress: string }) => { const parentCid = cid; - const { author, signer, content, link, spoiler, publishCommentOptions } = useReplyStore((state) => ({ + const { author, displayName, signer, content, link, spoiler, publishCommentOptions } = useReplyStore((state) => ({ author: state.author[parentCid], + displayName: state.author[parentCid]?.displayName, signer: state.signer[parentCid], content: state.content[parentCid], link: state.link[parentCid], @@ -99,6 +107,7 @@ const useReply = ({ cid, subplebbitAddress }: { cid: string; subplebbitAddress: setReplyStore({ subplebbitAddress, parentCid, + ...(anonMode ? { displayName } : {}), ...(anonMode ? { author } : {}), content, link, @@ -107,7 +116,7 @@ const useReply = ({ cid, subplebbitAddress }: { cid: string; subplebbitAddress: ...options, }); }, - [subplebbitAddress, parentCid, author, signer, content, link, spoiler, setReplyStore, anonMode], + [subplebbitAddress, parentCid, author, displayName, signer, content, link, spoiler, setReplyStore, anonMode], ); const resetPublishReplyOptions = useCallback(() => resetReplyStore(parentCid), [parentCid, resetReplyStore]); From 25722d74a3e048c03d69d924a644886fdb70310f Mon Sep 17 00:00:00 2001 From: "Tom (plebeius.eth)" Date: Tue, 13 Aug 2024 15:59:17 +0200 Subject: [PATCH 05/11] fix(post menu): 'view on (client)' link was broken on multisubs --- .../post-menu-desktop/post-menu-desktop.tsx | 19 +++++++++++++--- .../post-menu-mobile/post-menu-mobile.tsx | 22 +++++++++++++++++-- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/components/post-desktop/post-menu-desktop/post-menu-desktop.tsx b/src/components/post-desktop/post-menu-desktop/post-menu-desktop.tsx index 11c65f83..025441f4 100644 --- a/src/components/post-desktop/post-menu-desktop/post-menu-desktop.tsx +++ b/src/components/post-desktop/post-menu-desktop/post-menu-desktop.tsx @@ -73,7 +73,20 @@ const ImageSearchButton = ({ url, onClose }: { url: string; onClose: () => void const ViewOnButton = ({ cid, isDescription, isInAllView, isInSubscriptionsView, isRules, subplebbitAddress, onClose }: PostMenuDesktopProps) => { const { t } = useTranslation(); const [isClientRedirectMenuOpen, setIsClientRedirectMenuOpen] = useState(false); - const viewOnOtherClientLink = `p/${isInAllView ? 'all' : isInSubscriptionsView ? 'subscriptions' : subplebbitAddress}${isDescription || isRules ? '' : `/c/${cid}`}`; + + const getViewOnOtherClientLink = () => { + if (isDescription || isRules) { + if (isInAllView || isInSubscriptionsView) { + return `${isInAllView ? 'all' : isInSubscriptionsView && 'subscriptions'}`; + } else { + return `${subplebbitAddress}/${isDescription ? 'description' : isRules && 'rules'}`; + } + } else { + return `${subplebbitAddress}/c/${cid}`; + } + }; + + const viewOnOtherClientLink = getViewOnOtherClientLink(); const { refs, floatingStyles } = useFloating({ placement: 'right-start', @@ -91,10 +104,10 @@ const ViewOnButton = ({ cid, isDescription, isInAllView, isInSubscriptionsView, {_.capitalize(t('view_on'))} ยป {isClientRedirectMenuOpen && ( diff --git a/src/components/post-mobile/post-menu-mobile/post-menu-mobile.tsx b/src/components/post-mobile/post-menu-mobile/post-menu-mobile.tsx index e64315ff..5756654f 100644 --- a/src/components/post-mobile/post-menu-mobile/post-menu-mobile.tsx +++ b/src/components/post-mobile/post-menu-mobile/post-menu-mobile.tsx @@ -9,7 +9,7 @@ import { copyShareLinkToClipboard, isValidURL } from '../../../lib/utils/url-uti import useEditCommentPrivileges from '../../../hooks/use-author-privileges'; import useHide from '../../../hooks/use-hide'; import EditMenu from '../../edit-menu/edit-menu'; -import { isBoardView, isPostPageView } from '../../../lib/utils/view-utils'; +import { isAllView, isBoardView, isPostPageView, isSubscriptionsView } from '../../../lib/utils/view-utils'; import { useLocation, useParams } from 'react-router-dom'; interface PostMenuMobileProps { @@ -57,7 +57,25 @@ const ImageSearchButtons = ({ url, onClose }: { url: string; onClose: () => void const ViewOnButtons = ({ cid, isDescription, isRules, subplebbitAddress, onClose }: PostMenuMobileProps) => { const { t } = useTranslation(); - const viewOnOtherClientLink = `p/${subplebbitAddress}${isDescription || isRules ? '' : `/c/${cid}`}`; + const location = useLocation(); + const params = useParams(); + const isInAllView = isAllView(location.pathname, params); + const isInSubscriptionsView = isSubscriptionsView(location.pathname, params); + + const getViewOnOtherClientLink = () => { + if (isDescription || isRules) { + if (isInAllView || isInSubscriptionsView) { + return `${isInAllView ? 'all' : isInSubscriptionsView && 'subscriptions'}`; + } else { + return `${subplebbitAddress}/${isDescription ? 'description' : isRules && 'rules'}`; + } + } else { + return `${subplebbitAddress}/c/${cid}`; + } + }; + + const viewOnOtherClientLink = getViewOnOtherClientLink(); + return (
From 8dfe2098ce14e77898805093b5ce28c610f1b098 Mon Sep 17 00:00:00 2001 From: "Tom (plebeius.eth)" Date: Tue, 13 Aug 2024 18:27:56 +0200 Subject: [PATCH 06/11] feat(post): add user ID with color specific to user address --- src/components/post-desktop/post-desktop.tsx | 13 +++++++++++-- src/components/post-mobile/post-mobile.tsx | 13 +++++++++++-- src/lib/utils/post-utils.ts | 18 ++++++++++++++++++ src/views/post/post.module.css | 7 +++++-- 4 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 src/lib/utils/post-utils.ts diff --git a/src/components/post-desktop/post-desktop.tsx b/src/components/post-desktop/post-desktop.tsx index 96bdff11..be9a752b 100644 --- a/src/components/post-desktop/post-desktop.tsx +++ b/src/components/post-desktop/post-desktop.tsx @@ -5,6 +5,7 @@ import { Comment, useAccount, useAccountComments, useAuthorAvatar, useComment, u import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js'; import styles from '../../views/post/post.module.css'; import { getCommentMediaInfo, getDisplayMediaInfoType, getHasThumbnail } from '../../lib/utils/media-utils'; +import { hashStringToColor, getTextColorForBackground } from '../../lib/utils/post-utils'; import { getFormattedDate, getFormattedTimeAgo } from '../../lib/utils/time-utils'; import { isValidURL } from '../../lib/utils/url-utils'; import { isAllView, isPendingPostView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils'; @@ -71,6 +72,9 @@ const PostInfo = ({ openReplyModal, post, postReplyCount = 0, roles, isHidden }: const handleUserAddressClick = useAuthorAddressClick(); const numberOfPostsByAuthor = document.querySelectorAll(`[data-author-address="${shortAddress}"][data-post-cid="${postCid}"]`).length; + const userIDBackgroundColor = hashStringToColor(shortAddress || accountShortAddress); + const userIDTextColor = getTextColorForBackground(userIDBackgroundColor); + return (
{!isHidden && } @@ -106,10 +110,15 @@ const PostInfo = ({ openReplyModal, post, postReplyCount = 0, roles, isHidden }: )} - (u/ + (ID: {''} handleUserAddressClick(shortAddress || accountShortAddress, postCid)}> + handleUserAddressClick(shortAddress || accountShortAddress, postCid)} + style={{ backgroundColor: userIDBackgroundColor, color: userIDTextColor }} + > {shortAddress || accountShortAddress} } diff --git a/src/components/post-mobile/post-mobile.tsx b/src/components/post-mobile/post-mobile.tsx index 81f07724..0854ac03 100644 --- a/src/components/post-mobile/post-mobile.tsx +++ b/src/components/post-mobile/post-mobile.tsx @@ -5,6 +5,7 @@ import { Comment, useAccount, useAuthorAvatar, useComment, useEditedComment } fr import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js'; import styles from '../../views/post/post.module.css'; import { getCommentMediaInfo, getHasThumbnail } from '../../lib/utils/media-utils'; +import { getTextColorForBackground, hashStringToColor } from '../../lib/utils/post-utils'; import { getFormattedDate, getFormattedTimeAgo } from '../../lib/utils/time-utils'; import { isAllView, isPendingPostView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils'; import useAuthorAddressClick from '../../hooks/use-author-address-click'; @@ -52,6 +53,9 @@ const PostInfoAndMedia = ({ openReplyModal, post, postReplyCount = 0, roles }: P const handleUserAddressClick = useAuthorAddressClick(); const numberOfPostsByAuthor = document.querySelectorAll(`[data-author-address="${shortAddress}"][data-post-cid="${postCid}"]`).length; + const userIDBackgroundColor = hashStringToColor(shortAddress || accountShortAddress); + const userIDTextColor = getTextColorForBackground(userIDBackgroundColor); + return ( <>
@@ -79,10 +83,15 @@ const PostInfoAndMedia = ({ openReplyModal, post, postReplyCount = 0, roles }: P )} - (u/ + (ID: {''} handleUserAddressClick(shortAddress || accountShortAddress, postCid)}> + handleUserAddressClick(shortAddress || accountShortAddress, postCid)} + style={{ backgroundColor: userIDBackgroundColor, color: userIDTextColor }} + > {shortAddress || accountShortAddress} } diff --git a/src/lib/utils/post-utils.ts b/src/lib/utils/post-utils.ts new file mode 100644 index 00000000..63a4188d --- /dev/null +++ b/src/lib/utils/post-utils.ts @@ -0,0 +1,18 @@ +export function hashStringToColor(str: string): string { + let hash = 0; + for (let i = 0; i < str.length; i++) { + hash = str.charCodeAt(i) + ((hash << 5) - hash); + } + + const r = (hash >> 24) & 0xff; + const g = (hash >> 16) & 0xff; + const b = (hash >> 8) & 0xff; + + return `rgb(${r}, ${g}, ${b})`; +} + +export function getTextColorForBackground(rgb: string): string { + const [r, g, b] = rgb.match(/\d+/g)?.map(Number) || [0, 0, 0]; + const brightness = r * 0.299 + g * 0.587 + b * 0.114; + return brightness > 125 ? 'black' : 'white'; +} diff --git a/src/views/post/post.module.css b/src/views/post/post.module.css index 14e78581..60bc1f02 100644 --- a/src/views/post/post.module.css +++ b/src/views/post/post.module.css @@ -73,11 +73,14 @@ } .userAddress { + padding: 0 5px; + border-radius: 6px; + font-size: 0.8em; cursor: pointer; } -.postDesktop .userAddress:hover { - color: var(--button-desktop-text-color-hover); +.userAddress:hover { + color: var(--post-quotelink-text-color-hover) !important; } .postDesktop .subject { From 2f4c087e8e55cb9a999b23cf5fc4451ab5020fd5 Mon Sep 17 00:00:00 2001 From: "Tom (plebeius.eth)" Date: Tue, 13 Aug 2024 18:31:51 +0200 Subject: [PATCH 07/11] Update themes.css --- src/themes.css | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/themes.css b/src/themes.css index 5a40cf46..b494fa6d 100644 --- a/src/themes.css +++ b/src/themes.css @@ -23,7 +23,7 @@ --body-background-pattern-image: url("/public/assets/background-fade.png"); --body-font-color: maroon; --body-font-family: arial, helvetica, sans-serif; - --body-font-size: 13px; + --body-font-size: 10pt; /* catalog post */ --catalog-post-menu-desktop-btn-color: navy; @@ -232,7 +232,7 @@ --body-background-pattern-image: url("/public/assets/background-fade-blue.png"); --body-font-color: #000; --body-font-family: arial, helvetica, sans-serif; - --body-font-size: 13px; + --body-font-size: 10pt; /* catalog post */ --catalog-post-menu-desktop-btn-color: navy; @@ -434,7 +434,7 @@ --body-background-pattern-image: none; --body-font-color: maroon; --body-font-family: times new roman, serif; - --body-font-size: 16px; + --body-font-size: 12pt; /* board banner */ --banner-image-border: none; @@ -616,7 +616,7 @@ --body-background-pattern-image: none; --body-font-color: #000; --body-font-family: times new roman, serif; - --body-font-size: 16px; + --body-font-size: 12pt; /* catalog post */ --catalog-post-menu-desktop-btn-color: navy; @@ -795,7 +795,7 @@ --body-background-pattern-image: none; --body-font-color: #c5c8c6; --body-font-family: arial, helvetica, sans-serif; - --body-font-size: 13px; + --body-font-size: 10pt; /* board banner */ --banner-image-border: none; @@ -1008,7 +1008,7 @@ --body-background-pattern-image: none; --body-font-color: #333; --body-font-family: arial, helvetica, sans-serif; - --body-font-size: 13px; + --body-font-size: 10pt; /* board banner */ --banner-image-border: none; From c354d72e0ac561291a44822ad9f84e7d8c02059b Mon Sep 17 00:00:00 2001 From: "Tom (plebeius.eth)" Date: Tue, 13 Aug 2024 18:41:04 +0200 Subject: [PATCH 08/11] fix(edit menu): checkbox would appear dark in floating post from quote --- src/components/edit-menu/edit-menu.module.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/edit-menu/edit-menu.module.css b/src/components/edit-menu/edit-menu.module.css index 2c7acfdc..d16a825f 100644 --- a/src/components/edit-menu/edit-menu.module.css +++ b/src/components/edit-menu/edit-menu.module.css @@ -2,6 +2,7 @@ display: inline-block; padding: 3px 7px 3px 4px; filter: var(--filter80); + color-scheme: var(--color-scheme, revert) !important; } .modal { From 77980ee0c64a413f7582863487c23e7fc6b5ac9d Mon Sep 17 00:00:00 2001 From: "Tom (plebeius.eth)" Date: Tue, 13 Aug 2024 21:40:34 +0200 Subject: [PATCH 09/11] fix undefined --- src/lib/utils/post-utils.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lib/utils/post-utils.ts b/src/lib/utils/post-utils.ts index 63a4188d..a9d0f01f 100644 --- a/src/lib/utils/post-utils.ts +++ b/src/lib/utils/post-utils.ts @@ -1,4 +1,8 @@ export function hashStringToColor(str: string): string { + if (!str) { + return ''; + } + let hash = 0; for (let i = 0; i < str.length; i++) { hash = str.charCodeAt(i) + ((hash << 5) - hash); From f7bab7c83e92b24220c8244f4e1f7d0754ebb1a7 Mon Sep 17 00:00:00 2001 From: "Tom (plebeius.eth)" Date: Tue, 13 Aug 2024 21:41:04 +0200 Subject: [PATCH 10/11] fix(post menu): 'hide post' button wasn't appearing in thread page on desktop --- .../post-desktop/post-menu-desktop/post-menu-desktop.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/post-desktop/post-menu-desktop/post-menu-desktop.tsx b/src/components/post-desktop/post-menu-desktop/post-menu-desktop.tsx index 025441f4..c943afec 100644 --- a/src/components/post-desktop/post-menu-desktop/post-menu-desktop.tsx +++ b/src/components/post-desktop/post-menu-desktop/post-menu-desktop.tsx @@ -184,7 +184,7 @@ const PostMenuDesktop = ({ post }: { post: Comment }) => {
{cid && subplebbitAddress && } - {!isInPostPageView && !isDescription && !isRules && ( + {!(isInPostPageView && postCid === cid) && !isDescription && !isRules && (
{ From f6548cc2b826ba4b80d9d7511df17891408e016a Mon Sep 17 00:00:00 2001 From: "Tom (plebeius.eth)" Date: Wed, 14 Aug 2024 10:23:47 +0200 Subject: [PATCH 11/11] fix(replymodal): replying didn't work from multiboard feeds (p/all, p/subscriptions) --- src/components/post-desktop/post-desktop.tsx | 2 +- src/components/post-mobile/post-mobile.tsx | 2 +- src/components/reply-modal/reply-modal.tsx | 4 ++-- src/hooks/use-reply-modal.ts | 6 ++++-- src/views/board/board.tsx | 13 +++++++++++-- src/views/post/post.tsx | 15 ++++++++++++--- 6 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/components/post-desktop/post-desktop.tsx b/src/components/post-desktop/post-desktop.tsx index be9a752b..adb59a5b 100644 --- a/src/components/post-desktop/post-desktop.tsx +++ b/src/components/post-desktop/post-desktop.tsx @@ -147,7 +147,7 @@ const PostInfo = ({ openReplyModal, post, postReplyCount = 0, roles, isHidden }: !cid && e.preventDefault()}> c/ - openReplyModal && openReplyModal(cid, postCid)}> + openReplyModal && openReplyModal(cid, postCid, subplebbitAddress)}> {shortCid} diff --git a/src/components/post-mobile/post-mobile.tsx b/src/components/post-mobile/post-mobile.tsx index 0854ac03..a77f9b2c 100644 --- a/src/components/post-mobile/post-mobile.tsx +++ b/src/components/post-mobile/post-mobile.tsx @@ -136,7 +136,7 @@ const PostInfoAndMedia = ({ openReplyModal, post, postReplyCount = 0, roles }: P !cid && e.preventDefault()}> c/ - openReplyModal && openReplyModal(cid, postCid)}> + openReplyModal && openReplyModal(cid, postCid, subplebbitAddress)}> {shortCid} diff --git a/src/components/reply-modal/reply-modal.tsx b/src/components/reply-modal/reply-modal.tsx index efdc50e3..fb047814 100644 --- a/src/components/reply-modal/reply-modal.tsx +++ b/src/components/reply-modal/reply-modal.tsx @@ -21,11 +21,11 @@ interface ReplyModalProps { parentCid: string; postCid: string; scrollY: number; + subplebbitAddress: string; } -const ReplyModal = ({ closeModal, showReplyModal, parentCid, postCid, scrollY }: ReplyModalProps) => { +const ReplyModal = ({ closeModal, showReplyModal, parentCid, postCid, scrollY, subplebbitAddress }: ReplyModalProps) => { const { t } = useTranslation(); - const { subplebbitAddress } = useParams() as { subplebbitAddress: string }; const { setPublishReplyOptions, publishReply } = usePublishReply({ cid: parentCid, subplebbitAddress }); const account = useAccount(); const { displayName } = account?.author || {}; diff --git a/src/hooks/use-reply-modal.ts b/src/hooks/use-reply-modal.ts index 861bc416..e4f56301 100644 --- a/src/hooks/use-reply-modal.ts +++ b/src/hooks/use-reply-modal.ts @@ -6,6 +6,7 @@ const useReplyModal = () => { const [showReplyModal, setShowReplyModal] = useState(false); const [activeCid, setActiveCid] = useState(null); const [threadCid, setThreadCid] = useState(null); + const [subplebbitAddress, setSubplebbitAddress] = useState(null); const { resetSelectedText, setSelectedText } = useSelectedTextStore(); // on mobile, the css position is absolute instead of fixed, so we need to calculate the top position @@ -23,7 +24,7 @@ const useReplyModal = () => { text && setSelectedText(`>${text}\n`); }; - const openReplyModal = (parentCid: string, postCid: string) => { + const openReplyModal = (parentCid: string, postCid: string, subplebbitAddress: string) => { getSelectedText(); if (isMobile) { @@ -37,9 +38,10 @@ const useReplyModal = () => { setActiveCid(parentCid); setThreadCid(postCid); setShowReplyModal(true); + setSubplebbitAddress(subplebbitAddress); }; - return { activeCid, threadCid, closeModal, openReplyModal, scrollY, showReplyModal }; + return { activeCid, threadCid, closeModal, openReplyModal, scrollY, showReplyModal, subplebbitAddress }; }; export default useReplyModal; diff --git a/src/views/board/board.tsx b/src/views/board/board.tsx index 64036b43..290a5730 100644 --- a/src/views/board/board.tsx +++ b/src/views/board/board.tsx @@ -104,7 +104,7 @@ const Board = () => { const { createdAt, description, error, rules, shortAddress, state, suggested } = subplebbit || {}; const title = isInAllView ? t('all') : isInSubscriptionsView ? t('subscriptions') : subplebbit?.title; - const { activeCid, threadCid, closeModal, openReplyModal, showReplyModal, scrollY } = useReplyModal(); + const { activeCid, threadCid, closeModal, openReplyModal, showReplyModal, scrollY, subplebbitAddress: postSubplebbitAddress } = useReplyModal(); const { blocked, unblock } = useBlock({ address: subplebbitAddress }); const loadingStateString = useFeedStateString(subplebbitAddresses) || t('loading'); @@ -158,7 +158,16 @@ const Board = () => { return (
{location.pathname.endsWith('/settings') && } - {activeCid && threadCid && } + {activeCid && threadCid && postSubplebbitAddress && ( + + )} {feed.length !== 0 ? ( <> {rules && rules.length > 0 && } diff --git a/src/views/post/post.tsx b/src/views/post/post.tsx index 0f4cf02a..f62a4a85 100644 --- a/src/views/post/post.tsx +++ b/src/views/post/post.tsx @@ -22,7 +22,7 @@ export interface PostProps { roles?: Role[]; showAllReplies?: boolean; showReplies?: boolean; - openReplyModal?: (parentCid: string, postCid: string) => void; + openReplyModal?: (parentCid: string, postCid: string, subplebbitAddress: string) => void; } export const Post = ({ post, showAllReplies = false, showReplies = true, openReplyModal }: PostProps) => { @@ -62,7 +62,7 @@ const PostPage = () => { const subplebbit = useSubplebbit({ subplebbitAddress }); const { createdAt, description, rules, shortAddress, suggested, title } = subplebbit; - const { activeCid, threadCid, closeModal, openReplyModal, showReplyModal, scrollY } = useReplyModal(); + const { activeCid, threadCid, closeModal, openReplyModal, showReplyModal, scrollY, subplebbitAddress: postSubplebbitAddress } = useReplyModal(); const comment = useComment({ commentCid }); @@ -91,7 +91,16 @@ const PostPage = () => { return (
{isInSettigsView && } - {activeCid && threadCid && } + {activeCid && threadCid && postSubplebbitAddress && ( + + )} {/* TODO: remove this replyCount error once api supports scrolling replies pages */} {replyCount > 60 && Error: this thread has too many replies, some of them cannot be displayed right now.} {error && Error: {error.message}}